Skip to content

Commit d1397cf

Browse files
committed
Merge branch 'main' of https://github.com/ZtaMDev/RoundJS
2 parents 65b1398 + 665e40f commit d1397cf

1 file changed

Lines changed: 66 additions & 64 deletions

File tree

README.md

Lines changed: 66 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
<img src="https://img.shields.io/npm/v/round-core?color=brightgreen" alt="NPM Version" />
99
</p>
1010

11-
<p align="center">
12-
<em>Round is a lightweight frontend framework focused on building <b>single-page applications (SPAs)</b> with <b>fine‑grained reactivity.</b></em>
13-
</p>
11+
<h3 align="center">
12+
<em><b>Round</b> is a lightweight, DOM-first framework for building SPAs with fine-grained reactivity, and fast, predictable updates powered by signals and bindables</em>
13+
</h3>
14+
1415

1516
<div align="center">
1617

@@ -74,7 +75,7 @@ Round includes a CLI with a project initializer.
7475

7576
```bash
7677
# Install the CLI
77-
npm install round
78+
bun add round-core
7879

7980
# Create a new app
8081
round init myapp
@@ -142,6 +143,15 @@ export default function Counter() {
142143
}
143144
```
144145

146+
### Signals Internals
147+
148+
RoundJS utilizes a high-performance reactivity engine designed for efficiency and minimal memory overhead:
149+
150+
- **Doubly-Linked List Dependency Tracking**: Instead of using heavy `Set` objects, RoundJS uses a linked-list of subscription nodes. This eliminates array spreads and object allocations during signal updates, providing constant-time performance for adding/removing dependencies.
151+
- **Global Versioning (Clock)**: Every signal write increments a global version counter. Computed signals (`derive`) track the version of their dependencies and only recompute if they are "dirty" (out of date). This ensures true lazyness and avoids redundant calculations.
152+
- **Automatic Batching**: Multiple signal updates within the same execution cycle are batched. Effects and DOM updates only trigger once at the end of the batch, preventing "glitches" and unnecessary re-renders.
153+
154+
145155
### `derive(fn)`
146156

147157
Create a computed signal that updates automatically when its dependencies change.
@@ -242,6 +252,40 @@ export function Example() {
242252
}
243253
```
244254

255+
## DOM binding directives
256+
257+
Round supports two-way bindings via props:
258+
259+
- `bind:value={someBindable}` for text-like inputs, `<textarea>`, and `<select>`.
260+
- `bind:checked={someBindable}` for `<input type="checkbox">` and `<input type="radio">`.
261+
262+
Round will warn if the value is not signal-like, and will warn if you bind a plain `signal()` instead of a `bindable()`.
263+
264+
### `bindable.object(initialObject)` and deep binding
265+
266+
Round supports object-shaped state with ergonomic deep bindings via proxies.
267+
268+
```jsx
269+
import { bindable } from 'round-core';
270+
271+
export function Profile() {
272+
const user = bindable.object({
273+
profile: { bio: '' },
274+
flags: { newsletter: false }
275+
});
276+
277+
return (
278+
<div>
279+
<textarea bind:value={user.profile.bio} />
280+
<label>
281+
<input type="checkbox" bind:checked={user.flags.newsletter} />
282+
Subscribe
283+
</label>
284+
</div>
285+
);
286+
}
287+
```
288+
245289
### `createStore(initialState, actions)`
246290

247291
Create a shared global state store with actions and optional persistence.
@@ -286,26 +330,31 @@ const data = store.snapshot({ reactive: false }); // Get static JSON of state
286330
store.set('todos', []); // Direct set
287331
```
288332

289-
### `bindable.object(initialObject)` and deep binding
333+
### `.validate(validator, options)`
290334

291-
Round supports object-shaped state with ergonomic deep bindings via proxies.
335+
Attach validation to a signal/bindable.
336+
337+
- Invalid writes do not update the underlying value.
338+
- `signal.error` is itself a signal (reactive) containing the current error message or `null`.
339+
- `options.validateOn` can be `'input'` (default) or `'blur'`.
340+
- `options.validateInitial` can trigger validation on startup.
292341

293342
```jsx
294343
import { bindable } from 'round-core';
295344

296-
export function Profile() {
297-
const user = bindable.object({
298-
profile: { bio: '' },
299-
flags: { newsletter: false }
300-
});
345+
export function EmailField() {
346+
const email = bindable('')
347+
.validate(
348+
(v) => v.includes('@') || 'Invalid email',
349+
{ validateOn: 'blur' }
350+
);
301351

302352
return (
303353
<div>
304-
<textarea bind:value={user.profile.bio} />
305-
<label>
306-
<input type="checkbox" bind:checked={user.flags.newsletter} />
307-
Subscribe
308-
</label>
354+
<input bind:value={email} placeholder="name@example.com" />
355+
<div style={() => ({ color: email.error() ? 'crimson' : '#666' })}>
356+
{email.error}
357+
</div>
309358
</div>
310359
);
311360
}
@@ -343,45 +392,6 @@ export function MyComponent() {
343392
}
344393
```
345394

346-
### `.validate(validator, options)`
347-
348-
Attach validation to a signal/bindable.
349-
350-
- Invalid writes do not update the underlying value.
351-
- `signal.error` is itself a signal (reactive) containing the current error message or `null`.
352-
- `options.validateOn` can be `'input'` (default) or `'blur'`.
353-
- `options.validateInitial` can trigger validation on startup.
354-
355-
```jsx
356-
import { bindable } from 'round-core';
357-
358-
export function EmailField() {
359-
const email = bindable('')
360-
.validate(
361-
(v) => v.includes('@') || 'Invalid email',
362-
{ validateOn: 'blur' }
363-
);
364-
365-
return (
366-
<div>
367-
<input bind:value={email} placeholder="name@example.com" />
368-
<div style={() => ({ color: email.error() ? 'crimson' : '#666' })}>
369-
{email.error}
370-
</div>
371-
</div>
372-
);
373-
}
374-
```
375-
376-
## DOM binding directives
377-
378-
Round supports two-way bindings via props:
379-
380-
- `bind:value={someBindable}` for text-like inputs, `<textarea>`, and `<select>`.
381-
- `bind:checked={someBindable}` for `<input type="checkbox">` and `<input type="radio">`.
382-
383-
Round will warn if the value is not signal-like, and will warn if you bind a plain `signal()` instead of a `bindable()`.
384-
385395
## JSX superset control flow
386396

387397
Round extends JSX inside `.round` files with a control-flow syntax that compiles to JavaScript.
@@ -418,7 +428,7 @@ This compiles to efficient **keyed reconciliation** using the `ForKeyed` runtime
418428
- **Keyed (Recommended)**: By providing `key=expr`, Round maintains the identity of DOM nodes. If the list reorders, Round moves the existing nodes instead of recreating them. This preserves local state (like input focus, cursor position, or CSS animations).
419429
- **Unkeyed**: If no key is provided, Round simply maps over the list. Reordering the list will cause nodes to be reused based on their index, which might lead to state issues in complex lists.
420430

421-
### `switch`
431+
### `switch(...)`
422432

423433
```jsx
424434
{switch(status()){
@@ -538,14 +548,6 @@ The CLI is intended for day-to-day development:
538548

539549
Run `round -h` to see available commands.
540550

541-
## Signals Internals
542-
543-
RoundJS utilizes a high-performance reactivity engine designed for efficiency and minimal memory overhead:
544-
545-
- **Doubly-Linked List Dependency Tracking**: Instead of using heavy `Set` objects, RoundJS uses a linked-list of subscription nodes. This eliminates array spreads and object allocations during signal updates, providing constant-time performance for adding/removing dependencies.
546-
- **Global Versioning (Clock)**: Every signal write increments a global version counter. Computed signals (`derive`) track the version of their dependencies and only recompute if they are "dirty" (out of date). This ensures true lazyness and avoids redundant calculations.
547-
- **Automatic Batching**: Multiple signal updates within the same execution cycle are batched. Effects and DOM updates only trigger once at the end of the batch, preventing "glitches" and unnecessary re-renders.
548-
549551
## Performance
550552

551553
RoundJS sits in a powerful "middle ground" of performance:

0 commit comments

Comments
 (0)