ilha 0.9.4 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +104 -41
- package/dist/{index-Dx_q_SGo.d.ts → index-Bi_I3qEL.d.ts} +106 -46
- package/dist/index.d.ts +2 -2
- package/dist/index.js +609 -83
- package/dist/jsx-dev-runtime.d.ts +1 -1
- package/dist/jsx-runtime-DJ2B4fvA.d.ts +633 -0
- package/dist/jsx-runtime.d.ts +1 -1
- package/dist/jsx-runtime.js +94 -16
- package/package.json +1 -1
- package/dist/jsx-runtime-DysRyz9R.d.ts +0 -37
package/README.md
CHANGED
|
@@ -21,12 +21,14 @@ import ilha, { html } from "ilha";
|
|
|
21
21
|
|
|
22
22
|
const Counter = ilha
|
|
23
23
|
.state("count", 0)
|
|
24
|
-
.
|
|
24
|
+
.action("increment", (_, { state }) => {
|
|
25
|
+
state.count((count) => count + 1);
|
|
26
|
+
})
|
|
25
27
|
.render(
|
|
26
|
-
({ state }) => html`
|
|
28
|
+
({ state, action }) => html`
|
|
27
29
|
<div>
|
|
28
30
|
<p>Count: ${state.count()}</p>
|
|
29
|
-
<button>Increment</button>
|
|
31
|
+
<button onclick=${action.increment}>Increment</button>
|
|
30
32
|
</div>
|
|
31
33
|
`,
|
|
32
34
|
);
|
|
@@ -42,15 +44,45 @@ Counter.mount(document.getElementById("app"));
|
|
|
42
44
|
|
|
43
45
|
## Core Concepts
|
|
44
46
|
|
|
45
|
-
Islands are **self-contained reactive components** that know how to render themselves to an HTML string (SSR) and mount themselves into the DOM (client).
|
|
47
|
+
Islands are **self-contained reactive components** that know how to render themselves to an HTML string (SSR) and mount themselves into the DOM (client). Create one directly with `ilha(renderFn)`, or use the fluent builder when it needs local capabilities.
|
|
46
48
|
|
|
47
49
|
State is managed with signals — when a signal changes, only the affected island re-renders using a minimal DOM morph. No virtual DOM diffing, no framework overhead.
|
|
48
50
|
|
|
51
|
+
### Choose the smallest component form
|
|
52
|
+
|
|
53
|
+
Ilha has two runtime modes with three authoring forms:
|
|
54
|
+
|
|
55
|
+
| Form | Use it when |
|
|
56
|
+
| ----------------------------------------- | -------------------------------------------------------------------------------- |
|
|
57
|
+
| `const View = () => JSX` | You need reusable markup inside another island |
|
|
58
|
+
| `const View = ilha(() => JSX)` | The component needs its own reactive scope, lifecycle, mount, or hydration |
|
|
59
|
+
| `ilha.state(...).action(...).render(...)` | The island needs local state, derived values, actions, input, or lifecycle hooks |
|
|
60
|
+
|
|
61
|
+
Start with a plain component:
|
|
62
|
+
|
|
63
|
+
```tsx
|
|
64
|
+
const Status = () => <p>Ready</p>;
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Promote it without changing its markup when it needs an island boundary:
|
|
68
|
+
|
|
69
|
+
```tsx
|
|
70
|
+
const Status = ilha(() => <p>Ready</p>);
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Expand it into the builder when it needs local capabilities:
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
const Status = ilha.state("message", "Ready").render(({ state }) => <p>{state.message()}</p>);
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Both `ilha(() => JSX)` and the builder return a complete `Island`. A plain function remains transparent: its rendering, events, and cleanup belong to the containing island.
|
|
80
|
+
|
|
49
81
|
---
|
|
50
82
|
|
|
51
83
|
## Builder API
|
|
52
84
|
|
|
53
|
-
|
|
85
|
+
Use the `ilha` builder when an island needs capabilities such as typed input, state, derived values, actions, effects, or lifecycle hooks.
|
|
54
86
|
|
|
55
87
|
### `ilha.input<T>()` / `ilha.input(schema)`
|
|
56
88
|
|
|
@@ -99,7 +131,7 @@ state.count(); // → 0 (read)
|
|
|
99
131
|
state.count(5); // → sets to 5 (write)
|
|
100
132
|
```
|
|
101
133
|
|
|
102
|
-
Inside `html\`\``, you can interpolate signal accessors directly **without calling them**
|
|
134
|
+
Inside `html\`\``, you can interpolate signal accessors directly **without calling them** —`ilha` detects signal accessors and calls them for you, also applying HTML escaping:
|
|
103
135
|
|
|
104
136
|
```ts
|
|
105
137
|
html`<p>${state.count}</p>`; // same as html`<p>${state.count()}</p>`
|
|
@@ -129,15 +161,37 @@ Read with `derived.name()` like state. Each accessor also exposes `loading`, `va
|
|
|
129
161
|
|
|
130
162
|
---
|
|
131
163
|
|
|
164
|
+
### `.action(key, fn)`
|
|
165
|
+
|
|
166
|
+
Declares a reusable synchronous or asynchronous operation. Define actions before consumers, then call them from lowercase native event handlers:
|
|
167
|
+
|
|
168
|
+
```tsx
|
|
169
|
+
const Counter = ilha
|
|
170
|
+
.state("count", 0)
|
|
171
|
+
.action("increment", (amount: number, { state }) => {
|
|
172
|
+
state.count((count) => count + amount);
|
|
173
|
+
return state.count();
|
|
174
|
+
})
|
|
175
|
+
.render(({ state, action }) => (
|
|
176
|
+
<button onclick={() => action.increment(1)}>{state.count()}</button>
|
|
177
|
+
));
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Async actions expose reactive `pending`, `data`, and `error` properties. Action callbacks receive state, derived values, input, host, and an abort signal.
|
|
181
|
+
|
|
182
|
+
---
|
|
183
|
+
|
|
132
184
|
### `.on(selector, handler)`
|
|
133
185
|
|
|
134
|
-
|
|
186
|
+
Prefer lowercase native event props for handlers owned by one rendered element. Use `.on()` when you need a CSS selector, an island-host listener, the full handler context, or combined modifiers.
|
|
187
|
+
|
|
188
|
+
The selector string uses the format `"cssSelector@eventName"`. Omit the selector part to target the island host itself.
|
|
135
189
|
|
|
136
190
|
```ts
|
|
137
191
|
ilha
|
|
138
192
|
.state("count", 0)
|
|
139
|
-
.on("@click", ({ state }) => state.count(
|
|
140
|
-
.on("button.inc@click", ({ state }) => state.count(
|
|
193
|
+
.on("@click", ({ state }) => state.count((count) => count + 1)) // host click
|
|
194
|
+
.on("button.inc@click", ({ state }) => state.count((count) => count + 1)) // child click
|
|
141
195
|
.on("input@input", ({ state, event }) => {
|
|
142
196
|
state.query((event.target as HTMLInputElement).value);
|
|
143
197
|
})
|
|
@@ -301,7 +355,7 @@ ilha
|
|
|
301
355
|
.state("count", 0)
|
|
302
356
|
.on("@click", ({ state }) => {
|
|
303
357
|
if (state.count() > 5) throw new Error("too many clicks");
|
|
304
|
-
state.count(
|
|
358
|
+
state.count((count) => count + 1);
|
|
305
359
|
})
|
|
306
360
|
.onError(({ error, source }) => {
|
|
307
361
|
console.error(`[${source}] ${error.message}`);
|
|
@@ -388,12 +442,12 @@ ilha.css(styles).render(() => `<div class="card">…</div>`);
|
|
|
388
442
|
|
|
389
443
|
### Composing Islands
|
|
390
444
|
|
|
391
|
-
Child islands are interpolated directly inside a parent's html
|
|
445
|
+
Child islands are interpolated directly inside a parent's html template. During SSR the child's HTML is rendered inline; during client mount the child is activated independently inside its own host element.
|
|
392
446
|
|
|
393
447
|
```ts
|
|
394
|
-
const Icon = ilha
|
|
448
|
+
const Icon = ilha(() => `<svg>…</svg>`);
|
|
395
449
|
|
|
396
|
-
const Card = ilha
|
|
450
|
+
const Card = ilha(
|
|
397
451
|
() => html`
|
|
398
452
|
<div class="card">
|
|
399
453
|
${Icon}
|
|
@@ -403,27 +457,27 @@ const Card = ilha.render(
|
|
|
403
457
|
);
|
|
404
458
|
```
|
|
405
459
|
|
|
406
|
-
**Passing props** —
|
|
460
|
+
**Passing props** — use JSX props when composing a child island:
|
|
407
461
|
|
|
408
|
-
```
|
|
462
|
+
```tsx
|
|
409
463
|
const Badge = ilha
|
|
410
464
|
.input(z.object({ label: z.string(), color: z.string().default("teal") }))
|
|
411
|
-
.render(({ input }) =>
|
|
465
|
+
.render(({ input }) => <span style={{ background: input.color }}>{input.label}</span>);
|
|
412
466
|
|
|
413
|
-
const Card = ilha
|
|
414
|
-
|
|
415
|
-
<
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
`,
|
|
420
|
-
);
|
|
467
|
+
const Card = ilha(() => (
|
|
468
|
+
<div>
|
|
469
|
+
<Badge label="New" color="coral" />
|
|
470
|
+
<p>Content</p>
|
|
471
|
+
</div>
|
|
472
|
+
));
|
|
421
473
|
```
|
|
422
474
|
|
|
475
|
+
Props (including JSX `children` and function callbacks) stay on the **live slot map** during parent render/mount. `data-ilha-props` only carries JSON-safe scalars for hydration hints — never rely on it for children or handlers. Nested islands under layout shells (`defineLayout` / `wrapLayout`) use the same path as page-level composition.
|
|
476
|
+
|
|
423
477
|
**Keyed children** — use `.key()` when a child may reorder or appear conditionally. Keys must be unique within a parent render:
|
|
424
478
|
|
|
425
479
|
```ts
|
|
426
|
-
const List = ilha
|
|
480
|
+
const List = ilha(
|
|
427
481
|
() =>
|
|
428
482
|
html`<ul>
|
|
429
483
|
${items.map((item) => html`<li>${Item.key(item.id)({ name: item.name })}</li>`)}
|
|
@@ -454,25 +508,32 @@ The `leave` transition is awaited before cleanup runs.
|
|
|
454
508
|
|
|
455
509
|
---
|
|
456
510
|
|
|
457
|
-
### `.render(fn)`
|
|
511
|
+
### `.render(fn)` and `ilha(fn)`
|
|
458
512
|
|
|
459
|
-
|
|
513
|
+
`.render()` finalises a configured builder and returns an `Island`. The render function receives `{ state, derived, action, input }` and returns a string or `RawHtml`.
|
|
460
514
|
|
|
461
515
|
```ts
|
|
462
|
-
const MyIsland = ilha.state("x", 1).render(({ state
|
|
516
|
+
const MyIsland = ilha.state("x", 1).render(({ state }) => html`<p>${state.x()}</p>`);
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
For an island without builder configuration, `ilha(fn)` is shorthand for `ilha.render(fn)`:
|
|
520
|
+
|
|
521
|
+
```tsx
|
|
522
|
+
const StaticIsland = ilha(() => <p>Hello</p>);
|
|
523
|
+
const Label = ilha<{ label: string }>(({ input }) => <p>{input.label}</p>);
|
|
463
524
|
```
|
|
464
525
|
|
|
465
526
|
---
|
|
466
527
|
|
|
467
528
|
## Island Interface
|
|
468
529
|
|
|
469
|
-
Every island produced by `.render()` exposes:
|
|
530
|
+
Every island produced by `.render()` or `ilha(fn)` exposes:
|
|
470
531
|
|
|
471
|
-
### `island
|
|
532
|
+
### `island.toString(props?)`
|
|
472
533
|
|
|
473
|
-
Render the island to an HTML string synchronously.
|
|
534
|
+
Render the island to an HTML string synchronously. If `.derived()` entries have async functions, they render in `loading: true` state.
|
|
474
535
|
|
|
475
|
-
|
|
536
|
+
Use `await island(props)` instead when asynchronous derived values must settle before rendering. Always include `await` when using the callable form so a possible `Promise<string>` is never mistaken for a string.
|
|
476
537
|
|
|
477
538
|
```ts
|
|
478
539
|
MyIsland.toString(); // always sync
|
|
@@ -578,8 +639,8 @@ import ilha, { signal, html } from "ilha";
|
|
|
578
639
|
|
|
579
640
|
const username = signal("anonymous");
|
|
580
641
|
|
|
581
|
-
const Header = ilha
|
|
582
|
-
const Footer = ilha
|
|
642
|
+
const Header = ilha(() => html`<header>Hi, ${username()}!</header>`);
|
|
643
|
+
const Footer = ilha(() => html`<footer>Logged in as ${username()}</footer>`);
|
|
583
644
|
|
|
584
645
|
// Both islands re-render when `username` changes from anywhere.
|
|
585
646
|
username("alice");
|
|
@@ -790,11 +851,13 @@ import ilha from "ilha";
|
|
|
790
851
|
|
|
791
852
|
const Counter = ilha
|
|
792
853
|
.state("count", 0)
|
|
793
|
-
.
|
|
794
|
-
|
|
854
|
+
.action("increment", (_, { state }) => {
|
|
855
|
+
state.count((count) => count + 1);
|
|
856
|
+
})
|
|
857
|
+
.render(({ state, action }) => (
|
|
795
858
|
<div>
|
|
796
859
|
<p>Count: {state.count}</p>
|
|
797
|
-
<button>Increment</button>
|
|
860
|
+
<button onclick={action.increment}>Increment</button>
|
|
798
861
|
</div>
|
|
799
862
|
));
|
|
800
863
|
```
|
|
@@ -812,25 +875,25 @@ Interpolated children follow the same rules as the `html` tag — strings are es
|
|
|
812
875
|
| `bind:*` | Two-way bindings, same as in `html` templates — pass a signal accessor: `<input bind:value={state.name} />` |
|
|
813
876
|
| `key` | Keys a child island for reorder-safe rendering (same as `.key()`). Keys must be non-empty and must not contain `:` |
|
|
814
877
|
|
|
815
|
-
|
|
878
|
+
Lowercase native event props such as `onclick={handler}` attach with `addEventListener` during island mount; executable handlers never become inline SSR attributes. `srcdoc` is stripped, and URL attributes (`href`, `src`, `action`, …) with unsafe schemes such as `javascript:` are dropped.
|
|
816
879
|
|
|
817
880
|
### Islands as components
|
|
818
881
|
|
|
819
|
-
Islands are
|
|
882
|
+
Islands are callable JSX components, so props and keys work as expected. Unlike transparent plain components, each island keeps its own reactive scope and lifecycle:
|
|
820
883
|
|
|
821
884
|
```tsx
|
|
822
885
|
const Badge = ilha
|
|
823
886
|
.input<{ label: string }>()
|
|
824
887
|
.render(({ input }) => <span class="badge">{input.label}</span>);
|
|
825
888
|
|
|
826
|
-
const Card = ilha
|
|
889
|
+
const Card = ilha(() => (
|
|
827
890
|
<div class="card">
|
|
828
891
|
<Badge label="New" />
|
|
829
892
|
<p>Card content</p>
|
|
830
893
|
</div>
|
|
831
894
|
));
|
|
832
895
|
|
|
833
|
-
const List = ilha
|
|
896
|
+
const List = ilha(() => (
|
|
834
897
|
<ul>
|
|
835
898
|
{items.map((item) => (
|
|
836
899
|
<li>
|
|
@@ -56,9 +56,21 @@ interface IslandCall {
|
|
|
56
56
|
props: Record<string, unknown> | undefined;
|
|
57
57
|
key: string | undefined;
|
|
58
58
|
}
|
|
59
|
-
|
|
59
|
+
type NativeEventModifier = "abortable" | "once" | "capture" | "passive";
|
|
60
|
+
interface NativeEventContext {
|
|
61
|
+
readonly signal: AbortSignal;
|
|
62
|
+
}
|
|
63
|
+
type NativeEventHandler<E extends Event = Event> = (event: E, context: NativeEventContext) => unknown;
|
|
64
|
+
type NonFunctionValue<T> = T extends ((...args: any[]) => any) ? never : T;
|
|
65
|
+
type SignalSetter<T> = NonFunctionValue<T> | ((previous: T) => T);
|
|
66
|
+
declare const SIGNAL_WRITER_TYPE: unique symbol;
|
|
67
|
+
/** @internal Type-level write target carried by signal accessors. */
|
|
68
|
+
interface SignalWriter<T> {
|
|
69
|
+
readonly [SIGNAL_WRITER_TYPE]?: (value: T) => void;
|
|
70
|
+
}
|
|
71
|
+
interface MarkedSignalAccessor<T> extends SignalWriter<T> {
|
|
60
72
|
(): T;
|
|
61
|
-
(...args: [value: T]): void;
|
|
73
|
+
(...args: [value: SignalSetter<T>]): void;
|
|
62
74
|
select<S>(selector: (state: T) => S): MarkedSignalAccessor<S>;
|
|
63
75
|
[SIGNAL_ACCESSOR]: true;
|
|
64
76
|
}
|
|
@@ -67,7 +79,7 @@ declare function ilhaCss(strings: TemplateStringsArray | string, ...values: (str
|
|
|
67
79
|
declare function ilhaHtml(strings: TemplateStringsArray, ...values: unknown[]): RawHtml;
|
|
68
80
|
type ContextSignal<T> = {
|
|
69
81
|
(): T;
|
|
70
|
-
(value: T): void;
|
|
82
|
+
(value: SignalSetter<T>): void;
|
|
71
83
|
};
|
|
72
84
|
declare function ilhaContextFn<T>(key: string, initial: T): ContextSignal<T>;
|
|
73
85
|
/**
|
|
@@ -149,11 +161,11 @@ interface DerivedEntry<TInput, TStateMap extends Record<string, unknown>> {
|
|
|
149
161
|
key: string;
|
|
150
162
|
fn: DerivedFn<TInput, TStateMap, unknown>;
|
|
151
163
|
}
|
|
152
|
-
type IslandDerived<TDerivedMap extends Record<string, unknown>> = { readonly [K in keyof TDerivedMap]: DerivedAccessor<TDerivedMap[K]
|
|
164
|
+
type IslandDerived<TDerivedMap extends Record<string, unknown>> = { readonly [K in keyof TDerivedMap]: DerivedAccessor<TDerivedMap[K]>; };
|
|
153
165
|
type ExternalSignal<T = unknown> = SignalAccessor<T>;
|
|
154
166
|
type SignalAccessor<T> = MarkedSignalAccessor<T>;
|
|
155
167
|
type MergeState<TStateMap extends Record<string, unknown>, K extends string, V> = Omit<TStateMap, K> & Record<K, V>;
|
|
156
|
-
type IslandState<TStateMap extends Record<string, unknown>> = { readonly [K in keyof TStateMap]-?: SignalAccessor<TStateMap[K]
|
|
168
|
+
type IslandState<TStateMap extends Record<string, unknown>> = { readonly [K in keyof TStateMap]-?: SignalAccessor<TStateMap[K]>; };
|
|
157
169
|
interface HydratableOptions {
|
|
158
170
|
name: string;
|
|
159
171
|
as?: string;
|
|
@@ -187,14 +199,32 @@ interface KeyedIsland<TInput> {
|
|
|
187
199
|
[ISLAND_CALL]: true;
|
|
188
200
|
}
|
|
189
201
|
type AnyIsland = Island<any, any>;
|
|
190
|
-
type
|
|
202
|
+
type AnyActionFn = (props: any, ctx: any) => unknown;
|
|
203
|
+
type ActionMap = Record<string, AnyActionFn>;
|
|
204
|
+
type ActionCall<P> = [P] extends [undefined] ? () => void : unknown extends P ? () => void : (props: P) => void;
|
|
205
|
+
type ActionAccessor<P = undefined, R = void> = ActionCall<P> & {
|
|
206
|
+
readonly pending: boolean;
|
|
207
|
+
readonly data: Awaited<R> | undefined;
|
|
208
|
+
readonly error: Error | undefined;
|
|
209
|
+
};
|
|
210
|
+
type IslandActions<TActionMap extends ActionMap> = { readonly [K in keyof TActionMap]: TActionMap[K] extends ((props: infer P, ctx: any) => infer R) ? ActionAccessor<P, R> : never; };
|
|
211
|
+
type ActionContext<TInput, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown> = Record<never, never>> = {
|
|
191
212
|
state: IslandState<TStateMap>;
|
|
192
213
|
derived: IslandDerived<TDerivedMap>;
|
|
193
214
|
input: TInput;
|
|
215
|
+
host: Element;
|
|
216
|
+
signal: AbortSignal;
|
|
194
217
|
};
|
|
195
|
-
type
|
|
218
|
+
type RenderContext<TInput, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown>, TActionMap extends ActionMap = Record<never, never>> = {
|
|
196
219
|
state: IslandState<TStateMap>;
|
|
197
220
|
derived: IslandDerived<TDerivedMap>;
|
|
221
|
+
action: IslandActions<TActionMap>;
|
|
222
|
+
input: TInput;
|
|
223
|
+
};
|
|
224
|
+
type EffectContext<TInput, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown> = Record<never, never>, TActionMap extends ActionMap = Record<never, never>> = {
|
|
225
|
+
state: IslandState<TStateMap>;
|
|
226
|
+
derived: IslandDerived<TDerivedMap>;
|
|
227
|
+
action: IslandActions<TActionMap>;
|
|
198
228
|
input: TInput;
|
|
199
229
|
host: Element;
|
|
200
230
|
/**
|
|
@@ -205,16 +235,18 @@ type EffectContext<TInput, TStateMap extends Record<string, unknown>, TDerivedMa
|
|
|
205
235
|
*/
|
|
206
236
|
signal: AbortSignal;
|
|
207
237
|
};
|
|
208
|
-
type OnMountContext<TInput, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown> = Record<never, never>> = {
|
|
238
|
+
type OnMountContext<TInput, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown> = Record<never, never>, TActionMap extends ActionMap = Record<never, never>> = {
|
|
209
239
|
state: IslandState<TStateMap>;
|
|
210
240
|
derived: IslandDerived<TDerivedMap>;
|
|
241
|
+
action: IslandActions<TActionMap>;
|
|
211
242
|
input: TInput;
|
|
212
243
|
host: Element;
|
|
213
244
|
hydrated: boolean;
|
|
214
245
|
};
|
|
215
|
-
type HandlerContext<TInput, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown> = Record<never, never>> = {
|
|
246
|
+
type HandlerContext<TInput, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown> = Record<never, never>, TActionMap extends ActionMap = Record<never, never>> = {
|
|
216
247
|
state: IslandState<TStateMap>;
|
|
217
248
|
derived: IslandDerived<TDerivedMap>;
|
|
249
|
+
action: IslandActions<TActionMap>;
|
|
218
250
|
input: TInput;
|
|
219
251
|
host: Element;
|
|
220
252
|
target: Element;
|
|
@@ -231,9 +263,10 @@ type HandlerContext<TInput, TStateMap extends Record<string, unknown>, TDerivedM
|
|
|
231
263
|
};
|
|
232
264
|
type HTMLEventFor<E extends string> = E extends keyof HTMLElementEventMap ? HTMLElementEventMap[E] : Event;
|
|
233
265
|
type HTMLTargetFor<E extends string> = E extends keyof HTMLElementEventMap ? NonNullable<HTMLElementEventMap[E]["target"]> extends Element ? NonNullable<HTMLElementEventMap[E]["target"]> : Element : Element;
|
|
234
|
-
type HandlerContextFor<TInput, TStateMap extends Record<string, unknown>, TEventName extends string, TDerivedMap extends Record<string, unknown> = Record<never, never>> = {
|
|
266
|
+
type HandlerContextFor<TInput, TStateMap extends Record<string, unknown>, TEventName extends string, TDerivedMap extends Record<string, unknown> = Record<never, never>, TActionMap extends ActionMap = Record<never, never>> = {
|
|
235
267
|
state: IslandState<TStateMap>;
|
|
236
268
|
derived: IslandDerived<TDerivedMap>;
|
|
269
|
+
action: IslandActions<TActionMap>;
|
|
237
270
|
input: TInput;
|
|
238
271
|
host: Element;
|
|
239
272
|
target: HTMLTargetFor<TEventName>;
|
|
@@ -250,20 +283,24 @@ interface StateEntry<TInput> {
|
|
|
250
283
|
key: string;
|
|
251
284
|
init: StateInit<TInput, unknown>;
|
|
252
285
|
}
|
|
253
|
-
interface
|
|
286
|
+
interface ActionEntry<TInput, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown>> {
|
|
287
|
+
key: string;
|
|
288
|
+
fn: (props: unknown, ctx: ActionContext<TInput, TStateMap, TDerivedMap>) => unknown;
|
|
289
|
+
}
|
|
290
|
+
interface OnEntry<TInput, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown> = Record<never, never>, TActionMap extends ActionMap = Record<never, never>> {
|
|
254
291
|
selector: string;
|
|
255
292
|
event: string;
|
|
256
293
|
options: AddEventListenerOptions;
|
|
257
294
|
abortable: boolean;
|
|
258
|
-
handler: (ctx: HandlerContext<TInput, TStateMap, TDerivedMap>) => void | Promise<void>;
|
|
295
|
+
handler: (ctx: HandlerContext<TInput, TStateMap, TDerivedMap, TActionMap>) => void | Promise<void>;
|
|
259
296
|
}
|
|
260
|
-
interface EffectEntry<TInput, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown>> {
|
|
261
|
-
fn: (ctx: EffectContext<TInput, TStateMap, TDerivedMap>) => (() => void) | void;
|
|
297
|
+
interface EffectEntry<TInput, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown>, TActionMap extends ActionMap = Record<never, never>> {
|
|
298
|
+
fn: (ctx: EffectContext<TInput, TStateMap, TDerivedMap, TActionMap>) => (() => void) | void;
|
|
262
299
|
}
|
|
263
300
|
/** Where the error originated. `"on"` covers sync throws and async rejections
|
|
264
301
|
* from `.on()` handlers; `"effect"` covers sync throws from `.effect()` runs
|
|
265
302
|
* (async work spawned inside an effect is not awaited by the runtime). */
|
|
266
|
-
type ErrorSource = "on" | "effect" | "mount" | "transition";
|
|
303
|
+
type ErrorSource = "on" | "effect" | "mount" | "transition" | "action";
|
|
267
304
|
/**
|
|
268
305
|
* Register a global error handler invoked when any island reports an error
|
|
269
306
|
* (from .on, .effect, .onMount, or transitions) and has no local .onError()
|
|
@@ -271,19 +308,20 @@ type ErrorSource = "on" | "effect" | "mount" | "transition";
|
|
|
271
308
|
* are handled locally and do not reach the global sink.
|
|
272
309
|
*/
|
|
273
310
|
declare function onUncaughtError(fn: (error: Error, source: ErrorSource) => void): () => void;
|
|
274
|
-
type ErrorContext<TInput, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown> = Record<never, never>> = {
|
|
311
|
+
type ErrorContext<TInput, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown> = Record<never, never>, TActionMap extends ActionMap = Record<never, never>> = {
|
|
275
312
|
error: Error;
|
|
276
313
|
source: ErrorSource;
|
|
277
314
|
state: IslandState<TStateMap>;
|
|
278
315
|
derived: IslandDerived<TDerivedMap>;
|
|
316
|
+
action: IslandActions<TActionMap>;
|
|
279
317
|
input: TInput;
|
|
280
318
|
host: Element;
|
|
281
319
|
};
|
|
282
|
-
interface OnErrorEntry<TInput, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown>> {
|
|
283
|
-
fn: (ctx: ErrorContext<TInput, TStateMap, TDerivedMap>) => void;
|
|
320
|
+
interface OnErrorEntry<TInput, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown>, TActionMap extends ActionMap = Record<never, never>> {
|
|
321
|
+
fn: (ctx: ErrorContext<TInput, TStateMap, TDerivedMap, TActionMap>) => void;
|
|
284
322
|
}
|
|
285
|
-
interface OnMountEntry<TInput, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown>> {
|
|
286
|
-
fn: (ctx: OnMountContext<TInput, TStateMap, TDerivedMap>) => (() => void) | void;
|
|
323
|
+
interface OnMountEntry<TInput, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown>, TActionMap extends ActionMap = Record<never, never>> {
|
|
324
|
+
fn: (ctx: OnMountContext<TInput, TStateMap, TDerivedMap, TActionMap>) => (() => void) | void;
|
|
287
325
|
}
|
|
288
326
|
interface TransitionOptions {
|
|
289
327
|
enter?: (host: Element) => Promise<void> | void;
|
|
@@ -296,48 +334,58 @@ interface MountOptions {
|
|
|
296
334
|
interface MountResult {
|
|
297
335
|
unmount: () => void | Promise<void>;
|
|
298
336
|
}
|
|
299
|
-
interface BuilderConfig<TInput, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown>> {
|
|
337
|
+
interface BuilderConfig<TInput, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown>, TActionMap extends ActionMap = Record<never, never>> {
|
|
300
338
|
schema: StandardSchemaV1 | null;
|
|
301
339
|
/** Shallow defaults merged before props (POJO `.input({ ... })` only). */
|
|
302
340
|
defaultInput: Record<string, unknown> | null;
|
|
303
341
|
states: StateEntry<TInput>[];
|
|
304
342
|
deriveds: DerivedEntry<TInput, TStateMap>[];
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
343
|
+
actions: ActionEntry<TInput, TStateMap, TDerivedMap>[];
|
|
344
|
+
ons: OnEntry<TInput, TStateMap, TDerivedMap, TActionMap>[];
|
|
345
|
+
effects: EffectEntry<TInput, TStateMap, TDerivedMap, TActionMap>[];
|
|
346
|
+
onMounts: OnMountEntry<TInput, TStateMap, TDerivedMap, TActionMap>[];
|
|
347
|
+
onErrors: OnErrorEntry<TInput, TStateMap, TDerivedMap, TActionMap>[];
|
|
309
348
|
transition: TransitionOptions | null;
|
|
310
349
|
css: string | null;
|
|
311
350
|
/** Slot wrapper tag when this island is embedded in a parent (default div). */
|
|
312
351
|
as: string | null;
|
|
313
352
|
}
|
|
314
|
-
declare class IlhaBuilder<TInput extends Record<string, unknown>, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown> = Record<never, never>> {
|
|
315
|
-
readonly _cfg: BuilderConfig<TInput, TStateMap, TDerivedMap>;
|
|
316
|
-
constructor(cfg: BuilderConfig<TInput, TStateMap, TDerivedMap>);
|
|
317
|
-
input<T extends Record<string, unknown>>(): IlhaBuilder<T, Record<never, never>, Record<never, never>>;
|
|
318
|
-
input<S extends StandardSchemaV1>(schema: S): IlhaBuilder<StandardSchemaV1.InferOutput<S> & Record<string, unknown>, Record<never, never>, Record<never, never>>;
|
|
319
|
-
input<T extends Record<string, unknown>>(defaults: T): IlhaBuilder<T, Record<never, never>, Record<never, never>>;
|
|
320
|
-
as<Tag extends string>(tag: Tag): IlhaBuilder<TInput, TStateMap, TDerivedMap>;
|
|
321
|
-
state<V = undefined, K extends string = string>(key: K, init?: StateInit<TInput, V> | undefined): IlhaBuilder<TInput, MergeState<TStateMap, K, V>, TDerivedMap>;
|
|
322
|
-
derived<K extends string, V>(key: K, fn: DerivedFn<TInput, TStateMap, V>): IlhaBuilder<TInput, TStateMap, TDerivedMap & Record<K, V
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
353
|
+
declare class IlhaBuilder<TInput extends Record<string, unknown>, TStateMap extends Record<string, unknown>, TDerivedMap extends Record<string, unknown> = Record<never, never>, TActionMap extends ActionMap = Record<never, never>> {
|
|
354
|
+
readonly _cfg: BuilderConfig<TInput, TStateMap, TDerivedMap, TActionMap>;
|
|
355
|
+
constructor(cfg: BuilderConfig<TInput, TStateMap, TDerivedMap, TActionMap>);
|
|
356
|
+
input<T extends Record<string, unknown>>(): IlhaBuilder<T, Record<never, never>, Record<never, never>, Record<never, never>>;
|
|
357
|
+
input<S extends StandardSchemaV1>(schema: S): IlhaBuilder<StandardSchemaV1.InferOutput<S> & Record<string, unknown>, Record<never, never>, Record<never, never>, Record<never, never>>;
|
|
358
|
+
input<T extends Record<string, unknown>>(defaults: T): IlhaBuilder<T, Record<never, never>, Record<never, never>, Record<never, never>>;
|
|
359
|
+
as<Tag extends string>(tag: Tag): IlhaBuilder<TInput, TStateMap, TDerivedMap, TActionMap>;
|
|
360
|
+
state<V = undefined, K extends string = string>(key: K, init?: StateInit<TInput, V> | undefined): IlhaBuilder<TInput, MergeState<TStateMap, K, V>, TDerivedMap, TActionMap>;
|
|
361
|
+
derived<K extends string, V>(key: K, fn: DerivedFn<TInput, TStateMap, V>): IlhaBuilder<TInput, TStateMap, TDerivedMap & Record<K, V>, TActionMap>;
|
|
362
|
+
action<K extends string, P = undefined, R = void>(key: K, fn: (props: P, ctx: ActionContext<TInput, TStateMap, TDerivedMap>) => R): IlhaBuilder<TInput, TStateMap, TDerivedMap, TActionMap & Record<K, typeof fn>>;
|
|
363
|
+
on<S extends string>(selectorOrCombined: S, handler: (ctx: S extends `${string}@${infer E}:${string}` ? HandlerContextFor<TInput, TStateMap, E, TDerivedMap, TActionMap> : S extends `${string}@${infer E}` ? HandlerContextFor<TInput, TStateMap, E, TDerivedMap, TActionMap> : HandlerContext<TInput, TStateMap, TDerivedMap, TActionMap>) => void | Promise<void>): IlhaBuilder<TInput, TStateMap, TDerivedMap, TActionMap>;
|
|
364
|
+
effect(fn: (ctx: EffectContext<TInput, TStateMap, TDerivedMap, TActionMap>) => (() => void) | void): IlhaBuilder<TInput, TStateMap, TDerivedMap, TActionMap>;
|
|
365
|
+
onMount(fn: (ctx: OnMountContext<TInput, TStateMap, TDerivedMap, TActionMap>) => (() => void) | void): IlhaBuilder<TInput, TStateMap, TDerivedMap, TActionMap>;
|
|
366
|
+
onError(fn: (ctx: ErrorContext<TInput, TStateMap, TDerivedMap, TActionMap>) => void): IlhaBuilder<TInput, TStateMap, TDerivedMap, TActionMap>;
|
|
367
|
+
transition(opts: TransitionOptions): IlhaBuilder<TInput, TStateMap, TDerivedMap, TActionMap>;
|
|
368
|
+
css(strings: TemplateStringsArray | string, ...values: (string | number)[]): IlhaBuilder<TInput, TStateMap, TDerivedMap, TActionMap>;
|
|
369
|
+
render(fn: (ctx: RenderContext<TInput, TStateMap, TDerivedMap, TActionMap>) => string | RawHtml): Island<TInput, TStateMap>;
|
|
330
370
|
}
|
|
331
371
|
declare function ilhaFrom<TInput, TStateMap extends Record<string, unknown>>(selector: string | Element, island: Island<TInput, TStateMap>, props?: Partial<TInput>): (() => void) | null;
|
|
332
372
|
type IslandRegistry = Record<string, AnyIsland>;
|
|
333
373
|
declare function mountAll(registry: IslandRegistry, options?: MountOptions): MountResult;
|
|
334
|
-
|
|
374
|
+
type RootInput = Record<string, unknown>;
|
|
375
|
+
type RootState = Record<never, never>;
|
|
376
|
+
type RootDerived = Record<never, never>;
|
|
377
|
+
type RootActions = Record<never, never>;
|
|
378
|
+
type RootBuilder = IlhaBuilder<RootInput, RootState, RootDerived, RootActions>;
|
|
379
|
+
type DirectIslandFactory = <TInput extends Record<string, unknown> = RootInput>(fn: (ctx: RenderContext<TInput, RootState, RootDerived, RootActions>) => string | RawHtml) => Island<TInput, RootState>;
|
|
380
|
+
declare const ilha: RootBuilder & DirectIslandFactory & {
|
|
335
381
|
html: typeof ilhaHtml;
|
|
336
382
|
raw: typeof ilhaRaw;
|
|
337
383
|
mount: typeof mountAll;
|
|
338
384
|
from: typeof ilhaFrom;
|
|
339
385
|
context: typeof ilhaContextFn & {
|
|
340
|
-
/** Remove a context signal from the registry. Returns true if it existed. */
|
|
386
|
+
/** Remove a context signal from the registry. Returns true if it existed. */
|
|
387
|
+
delete(key: string): boolean;
|
|
388
|
+
/** Remove all context signals from the registry (e.g. between tests). */
|
|
341
389
|
clear(): void;
|
|
342
390
|
};
|
|
343
391
|
signal: typeof ilhaSignal;
|
|
@@ -346,16 +394,28 @@ declare const ilha: IlhaBuilder<Record<string, unknown>, Record<never, never>, R
|
|
|
346
394
|
untrack: typeof untrack;
|
|
347
395
|
onUncaughtError: typeof onUncaughtError;
|
|
348
396
|
};
|
|
397
|
+
/** @internal Used by the separate JSX runtime to register a native event handler. */
|
|
398
|
+
declare function __ilhaJsxEvent({ type, handler, modifier }: {
|
|
399
|
+
type: string;
|
|
400
|
+
handler: NativeEventHandler;
|
|
401
|
+
modifier?: NativeEventModifier;
|
|
402
|
+
}): number | undefined;
|
|
349
403
|
/** @internal Used by the separate JSX runtime entry to preserve island slot composition. */
|
|
350
|
-
declare function __ilhaJsxSlot(island
|
|
404
|
+
declare function __ilhaJsxSlot({ island, props, key }: {
|
|
405
|
+
island: unknown;
|
|
406
|
+
props: Record<string, unknown> | undefined;
|
|
407
|
+
key: string | undefined;
|
|
408
|
+
}): RawHtml;
|
|
351
409
|
declare const html: typeof ilhaHtml;
|
|
352
410
|
declare const raw: typeof ilhaRaw;
|
|
353
411
|
declare const css: typeof ilhaCss;
|
|
354
412
|
declare const mount: typeof mountAll;
|
|
355
413
|
declare const from: typeof ilhaFrom;
|
|
356
414
|
declare const context: typeof ilhaContextFn & {
|
|
357
|
-
/** Remove a context signal from the registry. Returns true if it existed. */
|
|
415
|
+
/** Remove a context signal from the registry. Returns true if it existed. */
|
|
416
|
+
delete(key: string): boolean;
|
|
417
|
+
/** Remove all context signals from the registry (e.g. between tests). */
|
|
358
418
|
clear(): void;
|
|
359
419
|
};
|
|
360
420
|
//#endregion
|
|
361
|
-
export {
|
|
421
|
+
export { __ilhaJsxSlot as A, mount as B, NativeEventModifier as C, SignalSetter as D, SignalAccessor as E, html as F, raw as H, ilha as I, ilhaComputed as L, context as M, css as N, SignalWriter as O, from as P, ilhaEffect as R, NativeEventHandler as S, RawHtml as T, untrack as U, onUncaughtError as V, IslandState as _, EffectContext as a, MountResult as b, ExternalSignal as c, HydratableOptions as d, ISLAND_MOUNT_HANDLES as f, IslandDerived as g, IslandActions as h, DerivedValue as i, batch as j, __ilhaJsxEvent as k, HandlerContext as l, Island as m, ActionContext as n, ErrorContext as o, ISLAND_MOUNT_INTERNAL as p, DerivedAccessor as r, ErrorSource as s, ActionAccessor as t, HandlerContextFor as u, KeyedIsland as v, OnMountContext as w, NativeEventContext as x, MountOptions as y, ilhaSignal as z };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { A as
|
|
2
|
-
export { DerivedAccessor, DerivedValue, EffectContext, ErrorContext, ErrorSource, ExternalSignal, HandlerContext, HandlerContextFor, HydratableOptions, ISLAND_MOUNT_HANDLES, ISLAND_MOUNT_INTERNAL, Island, IslandDerived, IslandState, KeyedIsland, MountOptions, MountResult, OnMountContext, RawHtml, SignalAccessor, __ilhaJsxSlot, batch, ilhaComputed as computed, context, css, ilha as default, ilhaEffect as effect, from, html, ilhaSignal, ilhaSignal as signal, mount, onUncaughtError, raw, untrack };
|
|
1
|
+
import { A as __ilhaJsxSlot, B as mount, C as NativeEventModifier, D as SignalSetter, E as SignalAccessor, F as html, H as raw, I as ilha, L as ilhaComputed, M as context, N as css, O as SignalWriter, P as from, R as ilhaEffect, S as NativeEventHandler, T as RawHtml, U as untrack, V as onUncaughtError, _ as IslandState, a as EffectContext, b as MountResult, c as ExternalSignal, d as HydratableOptions, f as ISLAND_MOUNT_HANDLES, g as IslandDerived, h as IslandActions, i as DerivedValue, j as batch, k as __ilhaJsxEvent, l as HandlerContext, m as Island, n as ActionContext, o as ErrorContext, p as ISLAND_MOUNT_INTERNAL, r as DerivedAccessor, s as ErrorSource, t as ActionAccessor, u as HandlerContextFor, v as KeyedIsland, w as OnMountContext, x as NativeEventContext, y as MountOptions, z as ilhaSignal } from "./index-Bi_I3qEL.js";
|
|
2
|
+
export { ActionAccessor, ActionContext, DerivedAccessor, DerivedValue, EffectContext, ErrorContext, ErrorSource, ExternalSignal, HandlerContext, HandlerContextFor, HydratableOptions, ISLAND_MOUNT_HANDLES, ISLAND_MOUNT_INTERNAL, Island, IslandActions, IslandDerived, IslandState, KeyedIsland, MountOptions, MountResult, NativeEventContext, NativeEventHandler, NativeEventModifier, OnMountContext, RawHtml, SignalAccessor, SignalSetter, SignalWriter, __ilhaJsxEvent, __ilhaJsxSlot, batch, ilhaComputed as computed, context, css, ilha as default, ilhaEffect as effect, from, html, ilhaSignal, ilhaSignal as signal, mount, onUncaughtError, raw, untrack };
|