sibujs 3.4.0 → 4.0.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/LICENSE +21 -21
- package/README.md +118 -15
- package/dist/browser.cjs +410 -101
- package/dist/browser.d.cts +50 -5
- package/dist/browser.d.ts +50 -5
- package/dist/browser.js +8 -6
- package/dist/build.cjs +777 -385
- package/dist/build.js +15 -15
- package/dist/cdn.global.js +11 -7
- package/dist/{chunk-JCO7AHNU.js → chunk-3EKJK5FZ.js} +73 -34
- package/dist/chunk-4MFZMLUU.js +147 -0
- package/dist/chunk-52XFPGSN.js +123 -0
- package/dist/chunk-5INI7D2L.js +194 -0
- package/dist/{chunk-OAVXAFAY.js → chunk-6LG2T7LO.js} +5 -5
- package/dist/{chunk-OOUQUCNN.js → chunk-ACBT6UZS.js} +57 -22
- package/dist/{chunk-F7HW2NI5.js → chunk-AW6HPJ3L.js} +1 -1
- package/dist/chunk-DHDZ7IVN.js +109 -0
- package/dist/{chunk-JNGGM2XE.js → chunk-DQVUBVNX.js} +16 -25
- package/dist/{chunk-AXFWGY32.js → chunk-DR7H6UGM.js} +232 -67
- package/dist/{chunk-WSGLJYFI.js → chunk-E62UADKL.js} +9 -3
- package/dist/{chunk-3Z2NGWQI.js → chunk-ES2GERY2.js} +1 -1
- package/dist/{chunk-S3V6ZXPI.js → chunk-EWEE7NBF.js} +115 -41
- package/dist/{chunk-3DVGCW7O.js → chunk-F64ZPCFE.js} +8 -8
- package/dist/{chunk-APFRCIRI.js → chunk-GCSGGA3Q.js} +295 -198
- package/dist/{chunk-EX77FXTT.js → chunk-HYCCIYNS.js} +228 -51
- package/dist/{chunk-ELXMRSVN.js → chunk-NF3LYCQH.js} +259 -124
- package/dist/chunk-O3QQ3XOL.js +61 -0
- package/dist/{chunk-BUKYCWHX.js → chunk-PBQEW5VW.js} +14 -10
- package/dist/{chunk-H5FI5WDP.js → chunk-RRIDJQ5C.js} +3 -3
- package/dist/{chunk-S3NFJO6L.js → chunk-TIRZCERI.js} +36 -5
- package/dist/{chunk-ODXVQ3CS.js → chunk-VFHIVEPF.js} +309 -188
- package/dist/chunk-VPP2FONR.js +142 -0
- package/dist/{chunk-KZBEVFXZ.js → chunk-W55YHPEP.js} +5 -3
- package/dist/{chunk-FKQG7FTY.js → chunk-WN6WDFCB.js} +4 -4
- package/dist/{chunk-CEBWDD63.js → chunk-WOOMUJFT.js} +228 -86
- package/dist/{chunk-ITWCTZYH.js → chunk-Z2CE42DB.js} +19 -25
- package/dist/{contracts-ey_Qh8ef.d.cts → contracts-Hg6ITAEF.d.cts} +6 -6
- package/dist/{contracts-ey_Qh8ef.d.ts → contracts-Hg6ITAEF.d.ts} +6 -6
- package/dist/{customElement-CPfIrbvg.d.ts → customElement-CKLoO63w.d.cts} +73 -11
- package/dist/{customElement-CPfIrbvg.d.cts → customElement-CKLoO63w.d.ts} +73 -11
- package/dist/data.cjs +483 -205
- package/dist/data.d.cts +139 -7
- package/dist/data.d.ts +139 -7
- package/dist/data.js +9 -9
- package/dist/devtools.cjs +222 -87
- package/dist/devtools.js +8 -8
- package/dist/dispose-4FZ6OFXR.js +19 -0
- package/dist/ecosystem.cjs +419 -175
- package/dist/ecosystem.js +11 -11
- package/dist/extras.cjs +1981 -765
- package/dist/extras.d.cts +7 -7
- package/dist/extras.d.ts +7 -7
- package/dist/extras.js +29 -26
- package/dist/index.cjs +784 -385
- package/dist/index.d.cts +299 -28
- package/dist/index.d.ts +299 -28
- package/dist/index.js +33 -18
- package/dist/motion.cjs +180 -50
- package/dist/motion.d.cts +26 -0
- package/dist/motion.d.ts +26 -0
- package/dist/motion.js +5 -5
- package/dist/patterns.cjs +437 -170
- package/dist/patterns.d.cts +60 -13
- package/dist/patterns.d.ts +60 -13
- package/dist/patterns.js +7 -7
- package/dist/performance.cjs +333 -148
- package/dist/performance.d.cts +55 -7
- package/dist/performance.d.ts +55 -7
- package/dist/performance.js +9 -9
- package/dist/plugins.cjs +1374 -576
- package/dist/plugins.d.cts +227 -9
- package/dist/plugins.d.ts +227 -9
- package/dist/plugins.js +613 -321
- package/dist/{ssr-D62yFwuw.d.cts → ssr-BiPRdZ6n.d.cts} +44 -15
- package/dist/{ssr-D62yFwuw.d.ts → ssr-BiPRdZ6n.d.ts} +44 -15
- package/dist/{ssr-2PPULEK2.js → ssr-JFP5535P.js} +5 -4
- package/dist/ssr.cjs +1104 -443
- package/dist/ssr.d.cts +230 -20
- package/dist/ssr.d.ts +230 -20
- package/dist/ssr.js +15 -12
- package/dist/{startup-0Qv6aosO.d.cts → startup-BMpaiMhP.d.cts} +1 -1
- package/dist/{startup-0Qv6aosO.d.ts → startup-BMpaiMhP.d.ts} +1 -1
- package/dist/testing.cjs +205 -63
- package/dist/testing.d.cts +1 -1
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +8 -10
- package/dist/ui.cjs +640 -199
- package/dist/ui.d.cts +2 -2
- package/dist/ui.d.ts +2 -2
- package/dist/ui.js +10 -10
- package/dist/widgets.cjs +207 -82
- package/dist/widgets.js +9 -9
- package/package.json +12 -7
- package/dist/chunk-5VGSK6D2.js +0 -80
- package/dist/chunk-COY6PUD2.js +0 -34
- package/dist/chunk-K35BAR4P.js +0 -96
- package/dist/chunk-L3GAGWCC.js +0 -111
- package/dist/chunk-RT3IYFN2.js +0 -38
package/dist/index.d.cts
CHANGED
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { N as NodeChild, a as NodeChildren, T as TagProps } from './tagFactory-Bzupt4Pj.cjs';
|
|
2
2
|
export { D as Dispose, S as SVG_NS, t as tagFactory } from './tagFactory-Bzupt4Pj.cjs';
|
|
3
|
-
export { T as TrustedHTML, t as trustHTML } from './ssr-
|
|
3
|
+
export { T as TrustedHTML, t as trustHTML } from './ssr-BiPRdZ6n.cjs';
|
|
4
4
|
import { R as ReactiveSignal } from './signal-BnWpq6WB.cjs';
|
|
5
5
|
|
|
6
6
|
interface ErrorBoundaryOptions {
|
|
7
7
|
/**
|
|
8
|
-
* Fallback renderer
|
|
9
|
-
*
|
|
8
|
+
* Fallback renderer, called with this boundary's Error and its own `retry`.
|
|
9
|
+
*
|
|
10
|
+
* Safe to share one fallback function across many boundaries: the Error and
|
|
11
|
+
* the retry callback always belong to the boundary that invoked it, even when
|
|
12
|
+
* two boundaries fail with identical messages. It is re-invoked whenever the
|
|
13
|
+
* boundary re-renders its error state; do not rely on it running only once.
|
|
10
14
|
*/
|
|
11
15
|
fallback?: (error: Error, retry: () => void) => Element;
|
|
12
16
|
/**
|
|
@@ -14,11 +18,27 @@ interface ErrorBoundaryOptions {
|
|
|
14
18
|
*/
|
|
15
19
|
onError?: (error: Error) => void;
|
|
16
20
|
/**
|
|
17
|
-
* A list of reactive getters. Whenever any of these
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
21
|
+
* A list of reactive getters. Whenever any of these VALUES changes AFTER an
|
|
22
|
+
* error has been caught, the boundary automatically resets (clears the error
|
|
23
|
+
* and re-renders). Useful for recovering from a failed render after the user
|
|
24
|
+
* navigates, changes filters, or otherwise picks a new input that might not
|
|
25
|
+
* fail this time.
|
|
26
|
+
*
|
|
27
|
+
* Getters are selectors, compared by `Object.is` against the values captured
|
|
28
|
+
* when the error was caught. Replacing the source object without changing the
|
|
29
|
+
* selected result does not reset the boundary:
|
|
30
|
+
*
|
|
31
|
+
* ```ts
|
|
32
|
+
* resetKeys: [() => route().pathname] // only the pathname matters
|
|
33
|
+
* ```
|
|
34
|
+
*
|
|
35
|
+
* "After" is literal: a key change that is itself the reason the children
|
|
36
|
+
* threw belongs to that failure and will not undo it. Only a change observed
|
|
37
|
+
* once the boundary is already showing its fallback triggers recovery.
|
|
38
|
+
*
|
|
39
|
+
* The getters are evaluated only while the boundary is failed, so a getter
|
|
40
|
+
* that throws is reported through the runtime error pipeline at that point
|
|
41
|
+
* rather than at construction.
|
|
22
42
|
*
|
|
23
43
|
* @example
|
|
24
44
|
* ```ts
|
|
@@ -44,7 +64,8 @@ type ErrorBoundaryProps = ErrorBoundaryOptions;
|
|
|
44
64
|
* `unhandledrejection` events instead.
|
|
45
65
|
* - Supports nested ErrorBoundaries (inner catches first, outer catches propagation)
|
|
46
66
|
* - Retry functionality to clear error and re-render children
|
|
47
|
-
* -
|
|
67
|
+
* - Fallback state is per-boundary: a shared fallback function never leaks one
|
|
68
|
+
* boundary's Error or retry callback into another
|
|
48
69
|
* - onError callback for logging/telemetry
|
|
49
70
|
* - Improved CSS styling
|
|
50
71
|
*/
|
|
@@ -122,6 +143,77 @@ interface LoadingProps {
|
|
|
122
143
|
*/
|
|
123
144
|
declare function Loading(props?: LoadingProps): HTMLElement;
|
|
124
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Central runtime error pipeline.
|
|
148
|
+
*
|
|
149
|
+
* WHY THIS EXISTS
|
|
150
|
+
* ---------------
|
|
151
|
+
* The reactive runtime has to *contain* application exceptions: a subscriber
|
|
152
|
+
* that throws must not abort the notification drain, or one broken component
|
|
153
|
+
* would freeze every unrelated binding on the page. Containment, however, was
|
|
154
|
+
* previously implemented as a bare `catch` that only warned when a dev-mode
|
|
155
|
+
* flag was on — so in a production build an application exception thrown from
|
|
156
|
+
* an effect re-run became literally nothing: no log, no handler, no signal that
|
|
157
|
+
* anything had happened.
|
|
158
|
+
*
|
|
159
|
+
* Containment is not silence. This module keeps the containment and makes the
|
|
160
|
+
* failure observable, with ONE resolution order for every phase of the runtime:
|
|
161
|
+
*
|
|
162
|
+
* 1. the nearest `ErrorBoundary`, but only if it EXPLICITLY claims the error
|
|
163
|
+
* 2. the application's configured runtime error handler
|
|
164
|
+
* 3. `console.error` — in production builds too, never gated on dev mode
|
|
165
|
+
*
|
|
166
|
+
* Every `catch` in the runtime that is not re-thrown routes here, so
|
|
167
|
+
* applications have exactly one place to install reporting/telemetry.
|
|
168
|
+
*/
|
|
169
|
+
/** The runtime activity that was executing when the error escaped. */
|
|
170
|
+
type RuntimeErrorPhase = "effect" | "binding" | "derived" | "cleanup" | "event" | "async" | "render" | "scheduler";
|
|
171
|
+
interface RuntimeErrorContext {
|
|
172
|
+
/** Which part of the runtime was executing. */
|
|
173
|
+
phase: RuntimeErrorPhase;
|
|
174
|
+
/** Debug label of the failing effect/computed/binding, when it has one. */
|
|
175
|
+
name?: string;
|
|
176
|
+
/**
|
|
177
|
+
* DOM node the failure is associated with, when one is known. Given a node,
|
|
178
|
+
* an enclosing `ErrorBoundary` gets first refusal — but only a boundary that
|
|
179
|
+
* explicitly claims the error stops the fallback chain. See `reportError`.
|
|
180
|
+
*/
|
|
181
|
+
node?: unknown;
|
|
182
|
+
}
|
|
183
|
+
type RuntimeErrorHandler = (error: unknown, context: RuntimeErrorContext) => void;
|
|
184
|
+
/**
|
|
185
|
+
* Install an application-wide handler for errors the runtime caught and
|
|
186
|
+
* contained. Returns the previously installed handler so callers can restore
|
|
187
|
+
* it (tests, nested frameworks). Pass `null` to clear.
|
|
188
|
+
*
|
|
189
|
+
* The handler replaces the default `console.error` reporting. Throwing from
|
|
190
|
+
* inside the handler falls back to the default, so a broken reporter cannot
|
|
191
|
+
* itself silence the runtime.
|
|
192
|
+
*
|
|
193
|
+
* This is application/runtime-global state, NOT request-scoped: under SSR it is
|
|
194
|
+
* shared by every concurrent request in the process. Install it once at startup
|
|
195
|
+
* and derive any request-specific detail from the error/context instead.
|
|
196
|
+
*/
|
|
197
|
+
declare function setRuntimeErrorHandler(handler: RuntimeErrorHandler | null): RuntimeErrorHandler | null;
|
|
198
|
+
/** The currently installed runtime error handler, if any. */
|
|
199
|
+
declare function getRuntimeErrorHandler(): RuntimeErrorHandler | null;
|
|
200
|
+
/**
|
|
201
|
+
* Report an error the runtime caught and contained.
|
|
202
|
+
*
|
|
203
|
+
* Resolution order: nearest claiming `ErrorBoundary` → configured runtime
|
|
204
|
+
* handler → `console.error`. Exactly one of those runs for a given report.
|
|
205
|
+
*
|
|
206
|
+
* Never throws — callers are inside `catch`/`finally` blocks where a secondary
|
|
207
|
+
* failure would corrupt teardown or abort a drain.
|
|
208
|
+
*
|
|
209
|
+
* @public Framework primitive, also usable by plugin/integration code that
|
|
210
|
+
* catches an application exception on SibuJS's behalf (custom rendering
|
|
211
|
+
* primitives, adapters) and wants it to follow the same boundary/handler
|
|
212
|
+
* resolution as a built-in one. Ordinary application code should prefer
|
|
213
|
+
* `ErrorBoundary` or `setRuntimeErrorHandler`.
|
|
214
|
+
*/
|
|
215
|
+
declare function reportError(error: unknown, context: RuntimeErrorContext): void;
|
|
216
|
+
|
|
125
217
|
/**
|
|
126
218
|
* An action is a reusable element-level behavior.
|
|
127
219
|
* It receives the element and an optional parameter, and may return
|
|
@@ -163,6 +255,7 @@ declare function getAction<T = unknown>(name: string): ActionFn<T> | undefined;
|
|
|
163
255
|
* ```
|
|
164
256
|
*/
|
|
165
257
|
declare function action<T>(element: HTMLElement, action: ActionFn<T> | string, param: T): void;
|
|
258
|
+
declare function action<T>(element: HTMLElement, action: ActionFn<T | undefined> | string): void;
|
|
166
259
|
declare function action(element: HTMLElement, action: ActionFn<void> | string): void;
|
|
167
260
|
/**
|
|
168
261
|
* Fires a callback when the user clicks outside the element.
|
|
@@ -414,11 +507,50 @@ declare function when<T>(condition: () => T, thenBranch: () => NodeChild, elseBr
|
|
|
414
507
|
*/
|
|
415
508
|
declare function match<T extends string | number>(value: () => T, cases: Record<string, () => NodeChild>, fallback?: () => NodeChild): Comment;
|
|
416
509
|
|
|
510
|
+
/**
|
|
511
|
+
* Safety ceiling on the **total number of teardowns a single drain may execute**.
|
|
512
|
+
*
|
|
513
|
+
* A cleanup registering another cleanup is legitimate — a parent teardown
|
|
514
|
+
* releasing a child, a lifecycle hook re-arming — so a drain keeps going until
|
|
515
|
+
* the queue is stable, and ordinary finite chains of practical depth complete.
|
|
516
|
+
*
|
|
517
|
+
* The ceiling counts total teardown executions, not iterations over the queue.
|
|
518
|
+
* Capping iterations abandons finite work purely for crossing the boundary,
|
|
519
|
+
* which is indistinguishable from a leak; capping total work distinguishes
|
|
520
|
+
* ordinary reentrant chains from typical runaway behaviour far better.
|
|
521
|
+
*
|
|
522
|
+
* It is nonetheless an **absolute work bound**, not a recursion detector. It
|
|
523
|
+
* primarily protects against cleanup production that does not terminate — most
|
|
524
|
+
* often recursive self-registration — but an exceptionally large *finite* chain
|
|
525
|
+
* needing more than this many executions reaches it just the same. Either way
|
|
526
|
+
* the condition is reported rather than silently swallowed, so bounded
|
|
527
|
+
* protection never passes as completed cleanup — see {@link reportDrainRunaway}.
|
|
528
|
+
*/
|
|
529
|
+
declare const MAX_DRAIN_TEARDOWNS = 10000;
|
|
530
|
+
/**
|
|
531
|
+
* Report a cleanup queue that did not stabilise within {@link MAX_DRAIN_TEARDOWNS}.
|
|
532
|
+
*
|
|
533
|
+
* Uses the existing console-based lifecycle convention; deliberately not a new
|
|
534
|
+
* public error API. Reported unconditionally (not dev-gated) because it means
|
|
535
|
+
* the framework stopped doing teardown work it was asked to do.
|
|
536
|
+
*/
|
|
537
|
+
declare function reportDrainRunaway(label: string, executed: number, remaining: number): void;
|
|
417
538
|
/**
|
|
418
539
|
* Register a teardown function for a DOM node.
|
|
419
540
|
* When dispose(node) is called, all registered teardowns run.
|
|
420
541
|
*/
|
|
421
542
|
declare function registerDisposer(node: Node, teardown: () => void): void;
|
|
543
|
+
/**
|
|
544
|
+
* Drop a previously registered teardown for a node without running it.
|
|
545
|
+
*
|
|
546
|
+
* For owners that can be released independently of their node — an enhancement
|
|
547
|
+
* disposed while its server markup stays on the page, and possibly re-enhanced
|
|
548
|
+
* afterwards — the node-level entry would otherwise accumulate one dead closure
|
|
549
|
+
* per generation, since `dispose()` is the only thing that clears the map.
|
|
550
|
+
* The teardown is assumed to have already run (or to be deliberately abandoned);
|
|
551
|
+
* this only releases the reference.
|
|
552
|
+
*/
|
|
553
|
+
declare function unregisterDisposer(node: Node, teardown: () => void): void;
|
|
422
554
|
/**
|
|
423
555
|
* Run all registered teardowns for a node and its descendants,
|
|
424
556
|
* cleaning up reactive subscriptions to prevent memory leaks.
|
|
@@ -428,6 +560,25 @@ declare function registerDisposer(node: Node, teardown: () => void): void;
|
|
|
428
560
|
* on deeply nested DOM trees.
|
|
429
561
|
*/
|
|
430
562
|
declare function dispose(node: Node): void;
|
|
563
|
+
/**
|
|
564
|
+
* Replace every child of `parent` with `next`, disposing the outgoing children
|
|
565
|
+
* first.
|
|
566
|
+
*
|
|
567
|
+
* Native `replaceChildren()` detaches nodes without running SibuJS teardown, so
|
|
568
|
+
* any reactive binding, lifecycle hook, or listener inside the removed subtree
|
|
569
|
+
* survives as an unreachable zombie: it keeps firing against detached DOM and
|
|
570
|
+
* is never collected. This helper enforces the disposal invariant — a
|
|
571
|
+
* SibuJS-owned node removed permanently from the DOM is disposed exactly once.
|
|
572
|
+
*
|
|
573
|
+
* **A node in `next` is never disposed, even when it currently sits somewhere
|
|
574
|
+
* inside an outgoing subtree.** Native `replaceChildren()` would move such a
|
|
575
|
+
* node out of the content being replaced and keep it alive, and this helper
|
|
576
|
+
* preserves those semantics: incoming nodes are detached *before* the outgoing
|
|
577
|
+
* roots are disposed, so the dispose-walk cannot reach them. Everything else in
|
|
578
|
+
* those outgoing subtrees is still torn down, so preserving one descendant does
|
|
579
|
+
* not leak its former siblings or ancestors.
|
|
580
|
+
*/
|
|
581
|
+
declare function replaceChildrenSafely(parent: ParentNode, ...next: Node[]): void;
|
|
431
582
|
/**
|
|
432
583
|
* Check for potential binding leaks. Returns the number of active DOM bindings.
|
|
433
584
|
* In dev mode, logs a warning if the count exceeds the threshold.
|
|
@@ -499,9 +650,19 @@ declare function DynamicComponent(is: () => string | Component$1): HTMLElement;
|
|
|
499
650
|
* skipping DOM operations for nodes that are part of the LIS.
|
|
500
651
|
*
|
|
501
652
|
* The render callback receives reactive getters `() => T` and `() => number`
|
|
502
|
-
* instead of plain values.
|
|
503
|
-
*
|
|
504
|
-
* is
|
|
653
|
+
* instead of plain values. Each keyed row owns its own item and index cells,
|
|
654
|
+
* written by reconciliation when the row is reused. `render` therefore runs
|
|
655
|
+
* exactly ONCE per key — identity is preserved across updates — while anything
|
|
656
|
+
* inside the row that reads `item()` or `index()` re-runs when reconciliation
|
|
657
|
+
* assigns that row a new item or position.
|
|
658
|
+
*
|
|
659
|
+
* Identity is not value freshness: a row keeps its DOM node when its key is
|
|
660
|
+
* unchanged, and still updates its contents when the item behind that key is
|
|
661
|
+
* replaced.
|
|
662
|
+
*
|
|
663
|
+
* Reading `item()` subscribes to the ROW's cell, not to the whole-array signal,
|
|
664
|
+
* so a row only re-renders when its own item/index actually changes — mutating
|
|
665
|
+
* an unrelated row does not disturb it.
|
|
505
666
|
*
|
|
506
667
|
* @param getArray A reactive getter returning an array.
|
|
507
668
|
* @param render A function that receives reactive item and index getters and returns a NodeChild.
|
|
@@ -1105,8 +1266,26 @@ interface AsyncDerivedState<T> {
|
|
|
1105
1266
|
loading: () => boolean;
|
|
1106
1267
|
/** The last caught error, or `null`. */
|
|
1107
1268
|
error: () => unknown | null;
|
|
1108
|
-
/** Manually re-run the async computation. */
|
|
1269
|
+
/** Manually re-run the async computation. No-op after `dispose()`. */
|
|
1109
1270
|
refresh: () => void;
|
|
1271
|
+
/**
|
|
1272
|
+
* Stop the derivation permanently: unsubscribe from every tracked source,
|
|
1273
|
+
* abort the in-flight run, and ignore any promise that resolves afterwards.
|
|
1274
|
+
*
|
|
1275
|
+
* Idempotent. An `asyncDerived` created inside a component or route must be
|
|
1276
|
+
* disposed when that scope tears down — otherwise it stays subscribed to its
|
|
1277
|
+
* sources for the lifetime of the page and keeps re-running.
|
|
1278
|
+
*/
|
|
1279
|
+
dispose: () => void;
|
|
1280
|
+
}
|
|
1281
|
+
/** Per-run context handed to the factory. */
|
|
1282
|
+
interface AsyncDerivedContext {
|
|
1283
|
+
/**
|
|
1284
|
+
* Aborted when a newer run supersedes this one, or when the derivation is
|
|
1285
|
+
* disposed. Forward it to `fetch` (or any abortable API) to cancel work that
|
|
1286
|
+
* can no longer affect the result.
|
|
1287
|
+
*/
|
|
1288
|
+
signal: AbortSignal;
|
|
1110
1289
|
}
|
|
1111
1290
|
/**
|
|
1112
1291
|
* `asyncDerived` is the async counterpart of `derived`: it takes a factory
|
|
@@ -1116,7 +1295,35 @@ interface AsyncDerivedState<T> {
|
|
|
1116
1295
|
*
|
|
1117
1296
|
* Stale responses are dropped: if a new run starts before an older one
|
|
1118
1297
|
* resolves, the older one's result is ignored. This prevents flicker when
|
|
1119
|
-
* dependencies change rapidly (e.g. typing in a search box).
|
|
1298
|
+
* dependencies change rapidly (e.g. typing in a search box). The superseded
|
|
1299
|
+
* run's `AbortSignal` is also aborted, so abortable work (e.g. `fetch`) is
|
|
1300
|
+
* cancelled rather than merely ignored. The run-id guard is retained
|
|
1301
|
+
* regardless, because not every async API honours `AbortSignal` — aborting
|
|
1302
|
+
* alone does not close the stale-completion race.
|
|
1303
|
+
*
|
|
1304
|
+
* ## Dependency tracking and `await`
|
|
1305
|
+
*
|
|
1306
|
+
* Reactive reads are tracked **synchronously**, so only the reads that happen
|
|
1307
|
+
* BEFORE the factory's first `await` become dependencies:
|
|
1308
|
+
*
|
|
1309
|
+
* ```ts
|
|
1310
|
+
* asyncDerived(async () => {
|
|
1311
|
+
* const a = sourceA(); // tracked — runs synchronously
|
|
1312
|
+
* await something();
|
|
1313
|
+
* const b = sourceB(); // NOT tracked — the tracking context is gone
|
|
1314
|
+
* });
|
|
1315
|
+
* ```
|
|
1316
|
+
*
|
|
1317
|
+
* This is a property of synchronous tracking, not a bug: SibuJS does not
|
|
1318
|
+
* install async-context machinery to follow reads across suspension points.
|
|
1319
|
+
* Read every dependency up front (before the first `await`) if the derivation
|
|
1320
|
+
* must react to it, or call `refresh()` explicitly.
|
|
1321
|
+
*
|
|
1322
|
+
* ## Ownership
|
|
1323
|
+
*
|
|
1324
|
+
* `asyncDerived` subscribes to its sources until `dispose()` is called. It is
|
|
1325
|
+
* not attached to an enclosing scope automatically — dispose it from the
|
|
1326
|
+
* owning component's cleanup.
|
|
1120
1327
|
*
|
|
1121
1328
|
* Unlike `query()` or `resource()`, `asyncDerived` has no caching or retry
|
|
1122
1329
|
* logic — it's a minimal async-reactivity primitive suited for ad-hoc
|
|
@@ -1136,7 +1343,7 @@ interface AsyncDerivedState<T> {
|
|
|
1136
1343
|
* }, []);
|
|
1137
1344
|
* ```
|
|
1138
1345
|
*/
|
|
1139
|
-
declare function asyncDerived<T>(factory: () => Promise<T>, initial: T): AsyncDerivedState<T>;
|
|
1346
|
+
declare function asyncDerived<T>(factory: (context: AsyncDerivedContext) => Promise<T>, initial: T): AsyncDerivedState<T>;
|
|
1140
1347
|
|
|
1141
1348
|
/**
|
|
1142
1349
|
* Deep equality comparison for objects and arrays.
|
|
@@ -1179,13 +1386,23 @@ declare function deepSignal<T>(initial: T): [Accessor<T>, (next: T | ((prev: T)
|
|
|
1179
1386
|
* derived-of-derived chains propagate correctly without paying the full
|
|
1180
1387
|
* Set-delete + re-add cost of track()'s cleanup phase.
|
|
1181
1388
|
*
|
|
1182
|
-
*
|
|
1183
|
-
*
|
|
1184
|
-
*
|
|
1185
|
-
*
|
|
1186
|
-
*
|
|
1187
|
-
*
|
|
1188
|
-
*
|
|
1389
|
+
* STABILIZATION — why a dirty flag is enough:
|
|
1390
|
+
*
|
|
1391
|
+
* A dirty computed does NOT imply a changed value. Downstream effects are
|
|
1392
|
+
* enqueued by `propagateDirty` at write time, before this computed has had a
|
|
1393
|
+
* chance to recompute and compare. Rather than adding a three-color
|
|
1394
|
+
* (CLEAN/CHECK/DIRTY) propagation pass — which an earlier revision measured as
|
|
1395
|
+
* a regression on every benchmark, because the extra state has nothing to skip
|
|
1396
|
+
* when values genuinely change — the engine settles the question lazily at
|
|
1397
|
+
* DRAIN time: `cs._validate` recomputes a dirty computed and `cs.__v` is bumped
|
|
1398
|
+
* ONLY when the new value differs under this computed's comparator. The
|
|
1399
|
+
* scheduler compares that version against what each subscriber last observed
|
|
1400
|
+
* and suppresses the run when nothing changed (see `depsChanged` in
|
|
1401
|
+
* ../../reactivity/track-core.ts).
|
|
1402
|
+
*
|
|
1403
|
+
* That keeps the cheap boolean dirty flag AND makes `equals` actually stop
|
|
1404
|
+
* propagation, with recomputation still fully lazy: `_validate` only ever runs
|
|
1405
|
+
* when an effect is genuinely about to observe the value.
|
|
1189
1406
|
*/
|
|
1190
1407
|
declare function derived<T>(getter: () => T, options?: {
|
|
1191
1408
|
name?: string;
|
|
@@ -1373,10 +1590,6 @@ declare function writable<T>(get: () => T, set: (value: T) => void, options?: {
|
|
|
1373
1590
|
* withSSR(() => renderToString(...));
|
|
1374
1591
|
* runInSSRContext(() => renderToString(...));
|
|
1375
1592
|
*/
|
|
1376
|
-
/**
|
|
1377
|
-
* Per-request SSR store. Currently holds the SSR flag plus a
|
|
1378
|
-
* suspense-id counter so concurrent streaming renders never collide.
|
|
1379
|
-
*/
|
|
1380
1593
|
interface SSRStore {
|
|
1381
1594
|
ssr: boolean;
|
|
1382
1595
|
suspenseIdCounter: number;
|
|
@@ -1386,6 +1599,17 @@ interface SSRStore {
|
|
|
1386
1599
|
* server renders. Typed loosely to avoid a dependency cycle with data/.
|
|
1387
1600
|
*/
|
|
1388
1601
|
caches?: Map<string, Map<string, unknown>>;
|
|
1602
|
+
/**
|
|
1603
|
+
* The locale this request has selected, or `undefined` when it has not
|
|
1604
|
+
* chosen one and should follow the application default.
|
|
1605
|
+
*
|
|
1606
|
+
* A plain string rather than a signal: reactive locale switching is a client
|
|
1607
|
+
* concern (one page, one active locale, subscribers to notify), while a
|
|
1608
|
+
* server render reads the value once per request and never re-renders. Giving
|
|
1609
|
+
* every request its own signal would allocate subscriber machinery nothing
|
|
1610
|
+
* will ever use. See `plugins/i18n.ts`.
|
|
1611
|
+
*/
|
|
1612
|
+
locale?: string;
|
|
1389
1613
|
}
|
|
1390
1614
|
/** Returns the active store (ALS or fallback). */
|
|
1391
1615
|
declare function getSSRStore(): SSRStore;
|
|
@@ -1503,9 +1727,26 @@ type EnhanceSetup = (ctx: EnhanceContext) => void | (() => void);
|
|
|
1503
1727
|
* replacing it. Returns a dispose function; disposal is also wired to the
|
|
1504
1728
|
* element, so removing its subtree cleans everything up.
|
|
1505
1729
|
*
|
|
1730
|
+
* **Setup is a transaction.** If `setup` throws, every binding, listener and
|
|
1731
|
+
* cleanup it registered through the {@link EnhanceContext} is torn down and the
|
|
1732
|
+
* original error is rethrown unchanged — the element is left exactly as
|
|
1733
|
+
* unenhanced as it started, so a retry is legal. The rollback covers
|
|
1734
|
+
* framework-owned resources only (`ctx.on`, `ctx.text`, `ctx.attr`,
|
|
1735
|
+
* `ctx.classed`, `ctx.show`, `ctx.model`, `ctx.cleanup`, and a cleanup returned
|
|
1736
|
+
* from setup); work the setup performed outside those helpers — `innerHTML`
|
|
1737
|
+
* writes, network calls, global mutation — cannot be reversed generically, so
|
|
1738
|
+
* register its undo with `ctx.cleanup()` as you go.
|
|
1739
|
+
*
|
|
1740
|
+
* **Ownership.** A successfully enhanced root is marked
|
|
1741
|
+
* `data-sibu-enhanced="true"`; disposal removes it. The marker tracks *current*
|
|
1742
|
+
* ownership rather than history, so a **disposed root can be enhanced again**,
|
|
1743
|
+
* while enhancing a root that is still active is refused (dev-warns) to prevent
|
|
1744
|
+
* two competing sets of bindings. See `docs/architecture/enhancement-lifecycle.md`.
|
|
1745
|
+
*
|
|
1506
1746
|
* @param target An `Element` or a CSS selector resolved against `document`
|
|
1507
1747
|
* (the first match is used; see {@link enhanceAll} for many).
|
|
1508
1748
|
* @param setup Wires reactivity via the {@link EnhanceContext}.
|
|
1749
|
+
* @throws Whatever `setup` throws, after rolling its resources back.
|
|
1509
1750
|
*
|
|
1510
1751
|
* @example
|
|
1511
1752
|
* ```ts
|
|
@@ -1521,6 +1762,19 @@ declare function enhance(target: Element | string, setup: EnhanceSetup): () => v
|
|
|
1521
1762
|
/**
|
|
1522
1763
|
* Enhance every element matching a selector. Returns a single dispose that
|
|
1523
1764
|
* tears down all of them.
|
|
1765
|
+
*
|
|
1766
|
+
* The whole collection is one transaction: if any element's setup throws, the
|
|
1767
|
+
* elements already enhanced are rolled back (newest first, mirroring stack
|
|
1768
|
+
* unwinding) and the original error is rethrown. A caller that never received
|
|
1769
|
+
* the aggregate disposer is therefore never left holding live enhancements it
|
|
1770
|
+
* has no way to release. A teardown that fails during that rollback is reported
|
|
1771
|
+
* and skipped — it neither aborts the remaining rollback nor replaces the
|
|
1772
|
+
* original setup error.
|
|
1773
|
+
*
|
|
1774
|
+
* The returned disposer is idempotent, and the collection may be enhanced again
|
|
1775
|
+
* afterwards (see {@link enhance} on marker lifetime).
|
|
1776
|
+
*
|
|
1777
|
+
* @throws Whatever the failing element's setup threw, after rolling back.
|
|
1524
1778
|
*/
|
|
1525
1779
|
declare function enhanceAll(selector: string, setup: EnhanceSetup): () => void;
|
|
1526
1780
|
|
|
@@ -1575,6 +1829,23 @@ interface MountIslandsOptions {
|
|
|
1575
1829
|
* - `visible` — when the element scrolls into view (IntersectionObserver).
|
|
1576
1830
|
* - `interaction` — on first pointer/focus/key/touch interaction.
|
|
1577
1831
|
* - `media` — when `data-sibu-media` (a media query) matches.
|
|
1832
|
+
*
|
|
1833
|
+
* **Error isolation is lifecycle isolation.** Each island is one `enhance()`
|
|
1834
|
+
* transaction, so an island whose setup throws is reported and leaves zero live
|
|
1835
|
+
* bindings and zero live listeners; siblings activate normally, and the failed
|
|
1836
|
+
* island can be mounted again once its setup is fixed.
|
|
1837
|
+
*
|
|
1838
|
+
* **Remounting is supported.** Cleanup disposes each island and releases its
|
|
1839
|
+
* `data-sibu-enhanced` marker, so the same server markup can be mounted again
|
|
1840
|
+
* with a fresh generation. Mounting twice *without* cleanup is also safe:
|
|
1841
|
+
* islands that currently own an enhancement are skipped, never double-wired.
|
|
1842
|
+
*
|
|
1843
|
+
* Activation can never outlive its owner. Cleanup landing before a lazy chunk
|
|
1844
|
+
* resolves prevents activation entirely, and cleanup landing *during* a setup
|
|
1845
|
+
* disposes the island rather than stranding it — DISPOSED never becomes ACTIVE.
|
|
1846
|
+
* `data-sibu-hydrated` is hydration provenance rather than ownership, and is
|
|
1847
|
+
* therefore not cleared on disposal; see
|
|
1848
|
+
* `docs/architecture/enhancement-lifecycle.md`.
|
|
1578
1849
|
*/
|
|
1579
1850
|
declare function mountIslands(root?: ParentNode | null, options?: MountIslandsOptions): () => void;
|
|
1580
1851
|
|
|
@@ -1710,7 +1981,7 @@ declare function isTrackingSuspended(): boolean;
|
|
|
1710
1981
|
declare function untracked$1<T>(fn: () => T): T;
|
|
1711
1982
|
declare function retrack$1(effectFn: () => void, subscriber: Subscriber): void;
|
|
1712
1983
|
declare function track(effectFn: () => void, subscriber?: Subscriber): () => void;
|
|
1713
|
-
declare function reactiveBinding(commit: () => void): () => void;
|
|
1984
|
+
declare function reactiveBinding(commit: () => void, ownerNode?: unknown): () => void;
|
|
1714
1985
|
declare function recordDependency(signal: ReactiveSignal): void;
|
|
1715
1986
|
declare function cleanup(subscriber: Subscriber): void;
|
|
1716
1987
|
declare function setMaxSubscriberRepeats(n: number): number;
|
|
@@ -1750,4 +2021,4 @@ declare const untracked: ReactiveApi["untracked"];
|
|
|
1750
2021
|
declare const retrack: ReactiveApi["retrack"];
|
|
1751
2022
|
declare const setMaxDrainIterations: ReactiveApi["setMaxDrainIterations"];
|
|
1752
2023
|
|
|
1753
|
-
export { type Accessor, type ActionFn, type AnchorProps, type ArrayActions, type AsyncDerivedState, type AudioProps, type ButtonProps, type Context, DynamicComponent, type EffectBody, type EffectOptions, type EnhanceContext, type EnhanceSetup, ErrorBoundary, type ErrorBoundaryOptions, type ErrorBoundaryProps, ErrorDisplay, type ErrorDisplayProps, type ErrorSeverity, type FormProps, Fragment, type ImgProps, type InputProps, type InputType, type IslandLoader, type IslandRegistration, type IslandStrategy, KeepAlive, type KeepAliveOptions, type LabelProps, Loading, type LoadingProps, type LongPressOptions, type MediaProps, type MountIslandsOptions, NodeChild, NodeChildren, type OnCleanup, type OptionProps, Portal, type Ref, type SSRStore, type SelectProps, type SignalOptions, type SlotFn, type Slots, type StoreActions, Suspense, type SuspenseProps, TagProps, type TextareaProps, type TypedTagFunction, type VideoProps, __resetIdCounter, a, abbr, action, address, area, array, article, aside, asyncDerived, audio, autoResize, b, base, batch, bdi, bdo, bindDynamic, blockquote, body, br, button, canvas, caption, catchError, catchErrorAsync, center, checkLeaks, circle, cite, clickOutside, clipPath, code, col, colgroup, context, copyOnClick, createId, customElement, data, datalist, dd, deepEqual, deepSignal, defer, defs, del, derived, details, dfn, dialog, disableSSR, dispose, div, dl, dt, each, effect, ellipse, em, embed, enableSSR, enhance, enhanceAll, enqueueBatchedSignal, fieldset, figcaption, figure, font, footer, form, g, getAction, getRequestScopedCache, getSSRStore, getSlot, h1, h2, h3, h4, h5, h6, head, header, hr, html, i, iframe, img, input, ins, isBatching, isSSR, kbd, label, lazy, lazyIsland, legend, li, line, linearGradient, link, longPress, main, map, mark, marker, marquee, mask, match, math, menu, meta, meter, mount, mountIslands, nav, nextTick, noscript, object, ol, on, onCleanup, onMount, onUnmount, optgroup, option, output, p, param, path, pattern, picture, polygon, polyline, portal, pre, progress, q, radialGradient, reactiveArray, rect, ref, registerAction, registerComponent, registerDisposer, registerIsland, resolveComponent, retrack, rp, rt, ruby, runInSSRContext, s, samp, script, section, select, setGlobalErrorHandler, setMaxDrainIterations, show, signal, slot, small, source, span, stop, store, strict, strictEffect, strong, style, sub, summary, sup, svg, symbol, table, takePendingError, tbody, td, template, text, textarea, tfoot, th, thead, time, title, tr, track$1 as track, transition, trapFocus, tspan, u, ul, unregisterComponent, unregisterIsland, untracked, use, var_, video, watch, when, withSSR, writable };
|
|
2024
|
+
export { type Accessor, type ActionFn, type AnchorProps, type ArrayActions, type AsyncDerivedContext, type AsyncDerivedState, type AudioProps, type ButtonProps, type Context, DynamicComponent, type EffectBody, type EffectOptions, type EnhanceContext, type EnhanceSetup, ErrorBoundary, type ErrorBoundaryOptions, type ErrorBoundaryProps, ErrorDisplay, type ErrorDisplayProps, type ErrorSeverity, type FormProps, Fragment, type ImgProps, type InputProps, type InputType, type IslandLoader, type IslandRegistration, type IslandStrategy, KeepAlive, type KeepAliveOptions, type LabelProps, Loading, type LoadingProps, type LongPressOptions, MAX_DRAIN_TEARDOWNS, type MediaProps, type MountIslandsOptions, NodeChild, NodeChildren, type OnCleanup, type OptionProps, Portal, type Ref, type RuntimeErrorContext, type RuntimeErrorHandler, type RuntimeErrorPhase, type SSRStore, type SelectProps, type SignalOptions, type SlotFn, type Slots, type StoreActions, Suspense, type SuspenseProps, TagProps, type TextareaProps, type TypedTagFunction, type VideoProps, __resetIdCounter, a, abbr, action, address, area, array, article, aside, asyncDerived, audio, autoResize, b, base, batch, bdi, bdo, bindDynamic, blockquote, body, br, button, canvas, caption, catchError, catchErrorAsync, center, checkLeaks, circle, cite, clickOutside, clipPath, code, col, colgroup, context, copyOnClick, createId, customElement, data, datalist, dd, deepEqual, deepSignal, defer, defs, del, derived, details, dfn, dialog, disableSSR, dispose, div, dl, dt, each, effect, ellipse, em, embed, enableSSR, enhance, enhanceAll, enqueueBatchedSignal, fieldset, figcaption, figure, font, footer, form, g, getAction, getRequestScopedCache, getRuntimeErrorHandler, getSSRStore, getSlot, h1, h2, h3, h4, h5, h6, head, header, hr, html, i, iframe, img, input, ins, isBatching, isSSR, kbd, label, lazy, lazyIsland, legend, li, line, linearGradient, link, longPress, main, map, mark, marker, marquee, mask, match, math, menu, meta, meter, mount, mountIslands, nav, nextTick, noscript, object, ol, on, onCleanup, onMount, onUnmount, optgroup, option, output, p, param, path, pattern, picture, polygon, polyline, portal, pre, progress, q, radialGradient, reactiveArray, rect, ref, registerAction, registerComponent, registerDisposer, registerIsland, replaceChildrenSafely, reportDrainRunaway, reportError, resolveComponent, retrack, rp, rt, ruby, runInSSRContext, s, samp, script, section, select, setGlobalErrorHandler, setMaxDrainIterations, setRuntimeErrorHandler, show, signal, slot, small, source, span, stop, store, strict, strictEffect, strong, style, sub, summary, sup, svg, symbol, table, takePendingError, tbody, td, template, text, textarea, tfoot, th, thead, time, title, tr, track$1 as track, transition, trapFocus, tspan, u, ul, unregisterComponent, unregisterDisposer, unregisterIsland, untracked, use, var_, video, watch, when, withSSR, writable };
|