ilha 0.12.0 → 0.13.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 CHANGED
@@ -23,7 +23,7 @@ const Counter = ilha(() => {
23
23
  const count = state(0);
24
24
 
25
25
  const increment = action(() => {
26
- count((value) => value + 1);
26
+ count.update((value) => value + 1);
27
27
  });
28
28
 
29
29
  return html`
@@ -66,7 +66,7 @@ A plain function component stays transparent: its rendering, events, and cleanup
66
66
 
67
67
  ### `state(init?)`
68
68
 
69
- Island-local reactive state. Returns a signal accessor — a function that reads or writes depending on how you call it:
69
+ Island-local reactive state. Returns a signal accessor — call it to read, use `.set()` / `.update()` to write:
70
70
 
71
71
  ```tsx
72
72
  const Counter = ilha(() => {
@@ -75,11 +75,11 @@ const Counter = ilha(() => {
75
75
  });
76
76
 
77
77
  count(); // read
78
- count(5); // write
79
- count((previous) => previous + 1); // update from the latest value
78
+ count.set(5); // write
79
+ count.update((previous) => previous + 1); // update from the latest value
80
80
  ```
81
81
 
82
- A function argument is a lazy initializer. To store a function value, return it from an updater wrapper: `callback(() => nextCallback)`.
82
+ A function argument is a lazy initializer. To store a function value, pass it to `.set`: `onSave.set(nextCallback)`.
83
83
 
84
84
  A state initializer applies only when the instance is created. Later prop changes rerender the component but do not reset state:
85
85
 
@@ -264,24 +264,6 @@ mount({ Counter, Badge });
264
264
 
265
265
  Pass `{ root, lazy }` to scope discovery to a root element or defer mounting until hosts scroll into view.
266
266
 
267
- ### `signal(initial)`
268
-
269
- Create a free-standing signal for shared state. Same accessor shape as `state()` but lives outside any island:
270
-
271
- ```ts
272
- const count = signal(0);
273
- count(); // read
274
- count(5); // write
275
- ```
276
-
277
- ### `computed(fn)`
278
-
279
- Create a lazy, cached, read-only value derived from signals:
280
-
281
- ```ts
282
- const total = computed(() => price() * qty());
283
- ```
284
-
285
267
  ### `effect(fn)`
286
268
 
287
269
  Run a standalone reactive effect outside any island; returns a stop function:
@@ -308,8 +290,8 @@ const theme = context("app.theme", "light");
308
290
 
309
291
  ```ts
310
292
  batch(() => {
311
- a(1);
312
- b(2);
293
+ a.set(1);
294
+ b.set(2);
313
295
  });
314
296
 
315
297
  const value = untrack(() => secret());
@@ -86,8 +86,6 @@ interface NativeEventContext {
86
86
  readonly signal: AbortSignal;
87
87
  }
88
88
  type NativeEventHandler<E extends Event = Event> = (event: E, context: NativeEventContext) => unknown;
89
- type NonFunctionValue<T> = T extends ((...args: any[]) => any) ? never : T;
90
- type SignalSetter<T> = NonFunctionValue<T> | ((previous: T) => T);
91
89
  declare const SIGNAL_WRITER_TYPE: unique symbol;
92
90
  /** @internal Type-level write target carried by signal accessors. */
93
91
  interface SignalWriter<T> {
@@ -96,7 +94,8 @@ interface SignalWriter<T> {
96
94
  type PathValue<T, P extends readonly PathSegment[]> = P extends readonly [infer Head, ...infer Tail] ? Head extends keyof T ? Tail extends readonly PathSegment[] ? PathValue<T[Head], Tail> : never : unknown : T;
97
95
  interface MarkedSignalAccessor<T> extends SignalWriter<T> {
98
96
  (): T;
99
- (...args: [value: SignalSetter<T>]): void;
97
+ set(value: T): void;
98
+ update(fn: (previous: T) => T): void;
100
99
  select<S>(selector: (state: T) => S): MarkedSignalAccessor<S>;
101
100
  select<const P extends readonly PathSegment[]>(...path: P): MarkedSignalAccessor<PathValue<T, P>>;
102
101
  [SIGNAL_ACCESSOR]: true;
@@ -131,15 +130,33 @@ declare function json(value: unknown): RawHtml;
131
130
  * an attribute is author error.
132
131
  */
133
132
  declare function css(value: string): RawHtml;
133
+ declare const TEMPLATE_PARTS: unique symbol;
134
+ interface TemplateParts {
135
+ [TEMPLATE_PARTS]: true;
136
+ values: unknown[];
137
+ }
138
+ type TemplateNode = {
139
+ kind: "fragment";
140
+ children: TemplateNode[];
141
+ } | {
142
+ kind: "element";
143
+ tag: string;
144
+ props: Record<string, unknown>;
145
+ children: TemplateNode[];
146
+ selfClosing?: boolean;
147
+ } | {
148
+ kind: "text";
149
+ value: string;
150
+ } | {
151
+ kind: "comment";
152
+ value: string | TemplateParts;
153
+ } | {
154
+ kind: "dynamic";
155
+ value: unknown;
156
+ };
134
157
  declare function ilhaHtml(strings: TemplateStringsArray, ...values: unknown[]): RawHtml;
135
158
  type ContextSignal<T> = SignalAccessor<T>;
136
159
  declare function ilhaContextFn<T>(key: string, initial: T): ContextSignal<T>;
137
- /**
138
- * Create a free-standing reactive signal that lives outside any island.
139
- * Internal: used by state()'s slot-drift fallback. The public way to create
140
- * free-standing shared state is `context(key, initial)`.
141
- */
142
- declare function ilhaSignal<T>(initial: T): SignalAccessor<T>;
143
160
  /**
144
161
  * Run `fn` with reactive tracking suspended. Reading signals inside `fn`
145
162
  * returns their current value without subscribing the surrounding scope.
@@ -199,7 +216,8 @@ type DerivedAccessor<T> = {
199
216
  readonly value: T | undefined;
200
217
  readonly error: Error | undefined;
201
218
  (): T | undefined;
202
- (value: T): void;
219
+ set(value: T): void;
220
+ update(fn: (previous: T | undefined) => T | undefined): void;
203
221
  };
204
222
  type ExternalSignal<T = unknown> = SignalAccessor<T>;
205
223
  type SignalAccessor<T> = MarkedSignalAccessor<T>;
@@ -246,6 +264,9 @@ interface KeyedIsland<TInput> {
246
264
  }
247
265
  type AnyIsland = Island<any>;
248
266
  type ActionCall<P> = [P] extends [undefined] ? () => void : unknown extends P ? () => void : (payload: P) => void;
267
+ /** A bound action can back native events or component callback props.
268
+ * Runtime arguments are ignored when `.with()` binds a payload. */
269
+ type BoundActionHandler = (...runtimeArgs: unknown[]) => unknown;
249
270
  /**
250
271
  * Reactive operation with execution state. `pending`, `data`, and `error`
251
272
  * are reactive: reading them during render subscribes the island render.
@@ -255,10 +276,10 @@ type ActionAccessor<P = undefined, R = void> = ActionCall<P> & {
255
276
  readonly data: Awaited<R> | undefined;
256
277
  readonly error: Error | undefined;
257
278
  /** Bind an explicit serializable payload into an RPC-replayable action
258
- * reference for server-owned islands (`onclick={remove.withArgs(id)}`).
279
+ * reference for server-owned islands (`onclick={remove.with(id)}`).
259
280
  * Arguments are validated JSON-safe (≤ 8 KiB serialized) at bind time and
260
281
  * stored in the hydration manifest — never extracted by executing code. */
261
- withArgs: (...args: unknown[]) => NativeEventHandler;
282
+ with: (...args: unknown[]) => BoundActionHandler;
262
283
  };
263
284
  interface EffectContext {
264
285
  /**
@@ -302,8 +323,8 @@ interface MountResult {
302
323
  *
303
324
  * A function argument is treated as a lazy initializer:
304
325
  * const count = state(() => expensiveInitialValue());
305
- * To store a function VALUE, return it from the updater wrapper on write:
306
- * setCallback(() => nextCallback);
326
+ * To store a function VALUE, pass it to `.set`:
327
+ * onSave.set(nextCallback);
307
328
  */
308
329
  declare function state<T>(init?: T | (() => T)): StateAccessor<T>;
309
330
  /**
@@ -371,4 +392,4 @@ declare const context: typeof ilhaContextFn & {
371
392
  clear(): void;
372
393
  };
373
394
  //#endregion
374
- export { action as A, isSafeUrl as B, PersistOptions as C, SignalSetter as D, SignalAccessor as E, each as F, mount as G, isUrlAttributeName as H, effect as I, persist as J, onError as K, html as L, context as M, css as N, SignalWriter as O, derived as P, untrack as Q, ilha as R, NativeEventModifier as S, RawHtml as T, json as U, isSafeUrlAttrValue as V, morph as W, serializeStyle as X, raw as Y, state as Z, KeyedIsland as _, EachKeyedBuilder as a, NativeEventContext as b, EffectFn as c, ErrorContext as d, ErrorSource as f, IslandComponent as g, Island as h, EachBuilder as i, batch as j, StateAccessor as k, EffectOnceContext as l, HydratableOptions as m, DerivedAccessor as n, EachResult as o, ExternalSignal as p, onUncaughtError as q, DerivedValue as r, EffectContext as s, ActionAccessor as t, EffectOnceFn as u, MountOptions as v, PersistStorage as w, NativeEventHandler as x, MountResult as y, ilhaSignal as z };
395
+ export { action as A, isSafeUrlAttrValue as B, PersistOptions as C, SignalWriter as D, SignalAccessor as E, each as F, onError as G, json as H, effect as I, raw as J, onUncaughtError as K, html as L, context as M, css as N, StateAccessor as O, derived as P, ilha as R, NativeEventModifier as S, RawHtml as T, morph as U, isUrlAttributeName as V, mount as W, state as X, serializeStyle as Y, untrack as Z, KeyedIsland as _, EachKeyedBuilder as a, NativeEventContext as b, EffectFn as c, ErrorContext as d, ErrorSource as f, IslandComponent as g, Island as h, EachBuilder as i, batch as j, TemplateNode as k, EffectOnceContext as l, HydratableOptions as m, DerivedAccessor as n, EachResult as o, ExternalSignal as p, persist as q, DerivedValue as r, EffectContext as s, ActionAccessor as t, EffectOnceFn as u, MountOptions as v, PersistStorage as w, NativeEventHandler as x, MountResult as y, isSafeUrl as z };
package/dist/index.d.ts CHANGED
@@ -1,2 +1,2 @@
1
- import { A as action, B as isSafeUrl, C as PersistOptions, D as SignalSetter, E as SignalAccessor, F as each, G as mount, H as isUrlAttributeName, I as effect, J as persist, K as onError, L as html, M as context, N as css, O as SignalWriter, P as derived, Q as untrack, R as ilha, S as NativeEventModifier, T as RawHtml, U as json, V as isSafeUrlAttrValue, W as morph, X as serializeStyle, Y as raw, Z as state, _ as KeyedIsland, a as EachKeyedBuilder, b as NativeEventContext, c as EffectFn, d as ErrorContext, f as ErrorSource, g as IslandComponent, h as Island, i as EachBuilder, j as batch, k as StateAccessor, l as EffectOnceContext, m as HydratableOptions, n as DerivedAccessor, o as EachResult, p as ExternalSignal, q as onUncaughtError, r as DerivedValue, s as EffectContext, t as ActionAccessor, u as EffectOnceFn, v as MountOptions, w as PersistStorage, x as NativeEventHandler, y as MountResult, z as ilhaSignal } from "./index-DZI0fEmR.js";
2
- export { ActionAccessor, DerivedAccessor, DerivedValue, EachBuilder, EachKeyedBuilder, EachResult, EffectContext, EffectFn, EffectOnceContext, EffectOnceFn, ErrorContext, ErrorSource, ExternalSignal, HydratableOptions, Island, IslandComponent, KeyedIsland, MountOptions, MountResult, NativeEventContext, NativeEventHandler, NativeEventModifier, PersistOptions, PersistStorage, RawHtml, SignalAccessor, SignalSetter, SignalWriter, StateAccessor, action, batch, context, css, derived, each, effect, html, ilha, ilhaSignal, isSafeUrl, isSafeUrlAttrValue, isUrlAttributeName, json, morph, mount, onError, onUncaughtError, persist, raw, serializeStyle, state, untrack };
1
+ import { A as action, B as isSafeUrlAttrValue, C as PersistOptions, D as SignalWriter, E as SignalAccessor, F as each, G as onError, H as json, I as effect, J as raw, K as onUncaughtError, L as html, M as context, N as css, O as StateAccessor, P as derived, R as ilha, S as NativeEventModifier, T as RawHtml, U as morph, V as isUrlAttributeName, W as mount, X as state, Y as serializeStyle, Z as untrack, _ as KeyedIsland, a as EachKeyedBuilder, b as NativeEventContext, c as EffectFn, d as ErrorContext, f as ErrorSource, g as IslandComponent, h as Island, i as EachBuilder, j as batch, k as TemplateNode, l as EffectOnceContext, m as HydratableOptions, n as DerivedAccessor, o as EachResult, p as ExternalSignal, q as persist, r as DerivedValue, s as EffectContext, t as ActionAccessor, u as EffectOnceFn, v as MountOptions, w as PersistStorage, x as NativeEventHandler, y as MountResult, z as isSafeUrl } from "./index-CVOjC94p.js";
2
+ export { ActionAccessor, DerivedAccessor, DerivedValue, EachBuilder, EachKeyedBuilder, EachResult, EffectContext, EffectFn, EffectOnceContext, EffectOnceFn, ErrorContext, ErrorSource, ExternalSignal, HydratableOptions, Island, IslandComponent, KeyedIsland, MountOptions, MountResult, NativeEventContext, NativeEventHandler, NativeEventModifier, PersistOptions, PersistStorage, RawHtml, SignalAccessor, SignalWriter, StateAccessor, TemplateNode, action, batch, context, css, derived, each, effect, html, ilha, isSafeUrl, isSafeUrlAttrValue, isUrlAttributeName, json, morph, mount, onError, onUncaughtError, persist, raw, serializeStyle, state, untrack };