streetui 1.0.0 → 1.3.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/dist/bin.cjs +1 -1
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/bin.js.map +1 -1
- package/dist/{compile-B0q07Hzq.d.cts → compile-CTA4MLX6.d.cts} +17 -2
- package/dist/{compile-B0q07Hzq.d.ts → compile-CTA4MLX6.d.ts} +17 -2
- package/dist/create-bin.cjs +1 -1
- package/dist/create-bin.cjs.map +1 -1
- package/dist/create-bin.js +1 -1
- package/dist/create-bin.js.map +1 -1
- package/dist/{hydration-diagnostics-BE6xVWD1.d.cts → hydration-diagnostics-Cu2ZRxL1.d.cts} +1 -1
- package/dist/{hydration-diagnostics-Bck5dMbz.d.ts → hydration-diagnostics-DqkNk4EU.d.ts} +1 -1
- package/dist/index.cjs +204 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +57 -9
- package/dist/index.d.ts +57 -9
- package/dist/index.js +203 -23
- package/dist/index.js.map +1 -1
- package/dist/{server-84Rz4g8W.d.cts → server-BeFSjxkL.d.cts} +1 -1
- package/dist/{server-D9GPmB49.d.ts → server-CtHBgrxf.d.ts} +1 -1
- package/dist/server.cjs +155 -13
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js +155 -13
- package/dist/server.js.map +1 -1
- package/dist/testing.cjs +281 -18
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +4 -3
- package/dist/testing.d.ts +4 -3
- package/dist/testing.js +278 -18
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { a as Signal, b as Subscriber, U as Unsubscribe, R as ReadonlySignal, A as ApplicationId, D as DiagnosticCollector, c as ApplicationGraph, G as GraphNode, C as CompiledApplication, d as SemanticNodeType, P as PageDSL, e as ContainerDSL, f as SignalKind } from './compile-
|
|
2
|
-
export { g as A11yOptions, h as AppBuilder, i as AppDSL, j as AppOptions, k as ApplicationGraphOptions, B as BaseNode, l as Bindable, m as BindableText, n as BoundInputOptions, o as ButtonOptions, p as CompileOptions, q as ContainerBuilder, r as ContainerBuilderImpl, s as ContainerOptions, t as ContentDSL, u as ControlledInputOptions, v as DerivedSignal, w as Diagnostic, x as DiagnosticError, y as DiagnosticLocation, z as DiagnosticSeverity, E as ErrorBoundaryOptions, F as ErrorFallbackBuilder, H as ErrorSource, I as EventDescriptor, J as FormBuilder, K as FormBuilderImpl, L as FormDSL, M as FormOptions, N as GraphNodeData, O as HandlerFn, Q as HeadingOptions, T as ImageOptions, W as InputOptions, X as InputOptionsBase, Y as LinkOptions, Z as ListBuilder, _ as ListBuilderImpl, $ as ListDSL, a0 as ListOptions, a1 as
|
|
3
|
-
import { R as RenderHandle, S as StreetRenderer, a as HydrationDiagnosticSink } from './hydration-diagnostics-
|
|
4
|
-
export { H as HydrationDiagnostic, b as HydrationMismatchType, c as consoleHydrationDiagnosticSink, d as createHydrationDiagnosticCollector, f as formatHydrationDiagnostic } from './hydration-diagnostics-
|
|
5
|
-
import { D as DOMAdapter } from './server-
|
|
6
|
-
export { R as RenderToStringOptions, S as STATE_MARKER_ATTR, a as ServerDOMAdapter, r as readState, b as renderToString, s as serializeState, c as serverDOMAdapter } from './server-
|
|
1
|
+
import { a as Signal, b as Subscriber, U as Unsubscribe, R as ReadonlySignal, A as ApplicationId, D as DiagnosticCollector, c as ApplicationGraph, G as GraphNode, C as CompiledApplication, d as SemanticNodeType, P as PageDSL, e as ContainerDSL, f as SignalKind } from './compile-CTA4MLX6.cjs';
|
|
2
|
+
export { g as A11yOptions, h as AppBuilder, i as AppDSL, j as AppOptions, k as ApplicationGraphOptions, B as BaseNode, l as Bindable, m as BindableText, n as BoundInputOptions, o as ButtonOptions, p as CompileOptions, q as ContainerBuilder, r as ContainerBuilderImpl, s as ContainerOptions, t as ContentDSL, u as ControlledInputOptions, v as DerivedSignal, w as Diagnostic, x as DiagnosticError, y as DiagnosticLocation, z as DiagnosticSeverity, E as ErrorBoundaryOptions, F as ErrorFallbackBuilder, H as ErrorSource, I as EventDescriptor, J as FormBuilder, K as FormBuilderImpl, L as FormDSL, M as FormOptions, N as GraphNodeData, O as HandlerFn, Q as HeadingOptions, T as ImageOptions, W as InputOptions, X as InputOptionsBase, Y as LinkOptions, Z as ListBuilder, _ as ListBuilderImpl, $ as ListDSL, a0 as ListOptions, a1 as ListPlanEntry, a2 as NodeId, a3 as NodeMetadata, a4 as PageBuilder, a5 as PageBuilderImpl, a6 as PropValue, a7 as Props, a8 as ReactiveConsumer, a9 as ReactiveSource, aa as SectionBuilder, ab as SectionBuilderImpl, ac as SectionDSL, ad as SectionOptions, ae as SerializedGraph, af as SerializedNode, ag as StateRef, S as StreetApp, ah as StreetUI, ai as TextOptions, aj as TextValue, V as VERSION, ak as batch, al as compile, am as compileGraph, an as createNodeId, ao as derived, ap as effect, aq as formatDiagnostic, ar as generateApplicationId, as as generateNodeId, at as isBatching, au as nextId, av as nodeIdPrefix, aw as observerCount, ax as reactiveListItemKey, ay as reactiveListItemSignature, az as resetIdCounter, aA as signal, aB as signalKind, aC as streetui } from './compile-CTA4MLX6.cjs';
|
|
3
|
+
import { R as RenderHandle, S as StreetRenderer, a as HydrationDiagnosticSink } from './hydration-diagnostics-Cu2ZRxL1.cjs';
|
|
4
|
+
export { H as HydrationDiagnostic, b as HydrationMismatchType, c as consoleHydrationDiagnosticSink, d as createHydrationDiagnosticCollector, f as formatHydrationDiagnostic } from './hydration-diagnostics-Cu2ZRxL1.cjs';
|
|
5
|
+
import { D as DOMAdapter } from './server-BeFSjxkL.cjs';
|
|
6
|
+
export { R as RenderToStringOptions, S as STATE_MARKER_ATTR, a as ServerDOMAdapter, r as readState, b as renderToString, s as serializeState, c as serverDOMAdapter } from './server-BeFSjxkL.cjs';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* A simple reactive store built on top of signals.
|
|
@@ -747,8 +747,10 @@ declare function applyNodeProps(ctx: RenderContext, graphNode: GraphNode, el: El
|
|
|
747
747
|
declare function wireSignalBindings(ctx: RenderContext, graphNode: GraphNode, instance: NodeInstance, onUpdate: (propKey: string, value: unknown) => void): void;
|
|
748
748
|
/**
|
|
749
749
|
* Subscribe a reactive-list instance to its driving signal. On each change the
|
|
750
|
-
* DSL-registered
|
|
751
|
-
* are reconciled against the live DOM with the keyed reconciler
|
|
750
|
+
* DSL-registered plan factory produces lightweight per-row descriptors, which
|
|
751
|
+
* are reconciled against the live DOM with the keyed, minimal-move reconciler
|
|
752
|
+
* (spec §15). A `conditional` node has no plan handler and falls back to the
|
|
753
|
+
* eager build factory (it only ever renders 0..1 branch, so eager is fine).
|
|
752
754
|
*/
|
|
753
755
|
declare function wireReactiveList(ctx: RenderContext, graphNode: GraphNode, instance: NodeInstance, el: Element): void;
|
|
754
756
|
|
|
@@ -785,6 +787,24 @@ interface ReconcileResult {
|
|
|
785
787
|
instances: NodeInstance[];
|
|
786
788
|
/** Instances that were removed and must be disposed. */
|
|
787
789
|
removed: NodeInstance[];
|
|
790
|
+
/**
|
|
791
|
+
* GraphNodes freshly materialised during this reconcile (new rows + rebuilt
|
|
792
|
+
* changed rows). The caller detaches any of these that were not adopted as a
|
|
793
|
+
* live instance's graph node, so no orphan subtree lingers in the graph index.
|
|
794
|
+
*/
|
|
795
|
+
built?: GraphNode[];
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* A lazy reconciliation descriptor for one reactive-list row (mirrors the DSL's
|
|
799
|
+
* `ListPlanEntry`). `sig()` and `build()` are only invoked for rows that are
|
|
800
|
+
* genuinely new or whose source reference changed — the whole point of the
|
|
801
|
+
* plan path (spec §15).
|
|
802
|
+
*/
|
|
803
|
+
interface PlanEntry {
|
|
804
|
+
readonly key: string;
|
|
805
|
+
readonly item: unknown;
|
|
806
|
+
readonly sig: () => string;
|
|
807
|
+
readonly build: () => GraphNode;
|
|
788
808
|
}
|
|
789
809
|
/**
|
|
790
810
|
* Reconcile children of a container element against a new list of graph nodes.
|
|
@@ -796,6 +816,25 @@ interface ReconcileResult {
|
|
|
796
816
|
* @param mountFn Factory to create a new NodeInstance for a graph node
|
|
797
817
|
*/
|
|
798
818
|
declare function reconcileChildren(ctx: RenderContext, parentDom: Element, oldInstances: NodeInstance[], newNodes: readonly GraphNode[], mountFn: MountFn): ReconcileResult;
|
|
819
|
+
/**
|
|
820
|
+
* Plan-based keyed reconciliation (spec §15 — the optimised reactive-list path).
|
|
821
|
+
*
|
|
822
|
+
* Identical observable result to {@link reconcileChildren}, but driven by lazy
|
|
823
|
+
* {@link PlanEntry} descriptors instead of a pre-built array of GraphNodes:
|
|
824
|
+
*
|
|
825
|
+
* - a reused row whose `item` reference is unchanged does **zero** work — no
|
|
826
|
+
* signature hash, no subtree build, no prop patch (the common case for
|
|
827
|
+
* append / prepend / remove / reorder / reverse, where existing item objects
|
|
828
|
+
* keep their identity);
|
|
829
|
+
* - a reused row whose reference changed hashes lazily and, only on a real
|
|
830
|
+
* signature change, materialises a fresh subtree for a targeted in-place
|
|
831
|
+
* content update;
|
|
832
|
+
* - a genuinely new key builds + mounts exactly one subtree.
|
|
833
|
+
*
|
|
834
|
+
* DOM reordering uses a longest-increasing-subsequence pass so the number of
|
|
835
|
+
* moves is minimal (e.g. a prepend into a 10k list moves 1 node, not 10k).
|
|
836
|
+
*/
|
|
837
|
+
declare function reconcileChildrenByPlan(ctx: RenderContext, parentDom: Element, oldInstances: NodeInstance[], plan: readonly PlanEntry[], mountFn: MountFn): ReconcileResult;
|
|
799
838
|
|
|
800
839
|
/**
|
|
801
840
|
* StreetUI Renderer — framework-owned DOM renderer.
|
|
@@ -1382,6 +1421,15 @@ interface PerfSnapshot {
|
|
|
1382
1421
|
readonly distinctSignals: number;
|
|
1383
1422
|
/** Largest single-node child count (a proxy for the biggest list/section). */
|
|
1384
1423
|
readonly largestChildCount: number;
|
|
1424
|
+
/**
|
|
1425
|
+
* Number of reactive keyed-list sites driven by the optimised lazy-plan
|
|
1426
|
+
* reconciler (v1.1 §15/§25). Counted from the graph's `__listplan__<id>`
|
|
1427
|
+
* handler registrations — one per `listOf(...)` bound to a signal. These are
|
|
1428
|
+
* the nodes whose updates take the identity-short-circuit + LIS minimal-move
|
|
1429
|
+
* path, so surfacing the count lets a panel or CI check see how much of an app
|
|
1430
|
+
* benefits from the keyed-list engine without measuring anything at runtime.
|
|
1431
|
+
*/
|
|
1432
|
+
readonly reactiveLists: number;
|
|
1385
1433
|
}
|
|
1386
1434
|
/**
|
|
1387
1435
|
* The complete read-only snapshot of a compiled application. Everything here is
|
|
@@ -1756,4 +1804,4 @@ interface ResolvedConfig {
|
|
|
1756
1804
|
/** Identity helper that gives `streetui.config.ts` full type-checking + inference. */
|
|
1757
1805
|
declare function defineConfig(config: StreetUIConfig): StreetUIConfig;
|
|
1758
1806
|
|
|
1759
|
-
export { type A11yIds, Application, ApplicationGraph, ApplicationId, type ApplicationIdentity, type ApplicationInspection, type ApplicationOptions, type ApplicationPanel, BrowserDOMAdapter, CleanupRegistry, CompiledApplication, ContainerDSL, type Context, type ContextInspection, type ContextLike, DEFAULT_PERF_THRESHOLDS, DOMAdapter, type DevToolsOptions, type DevToolsSession, type DevToolsSnapshot, type DevToolsSources, DiagnosticCollector, type DiagnosticContext, type DiagnosticSink, type DiagnosticsSummary, type DomBinding, DomEventRegistry, Environment, type EnvironmentCapabilities, type EnvironmentKind, EventBus, type EventHandler, FOCUSABLE_SELECTOR, type Field, type Form, type FormConfig, type FormInspection, type FormLike, type FormValidators, type FormValues, GraphNode, HydrationDiagnosticSink, type I18n, type I18nConfig, type I18nInspection, type I18nLike, type InspectFormOptions, type InspectI18nOptions, type InspectResourceOptions, type InspectSignalOptions, type InspectedNode, type InspectedPage, type InterpolationParams, type IsActiveOptions, type Job, Lifecycle, type LifecycleHook, type LifecyclePhase, type MatchResult, type MessageMap, type MountFn, type MountRouterOptions, type MountedApplication, type MountedRouter, type NavigateOptions, NodeInstance, type NodeInstanceOptions, PageDSL, type PerfDiagnostic, type PerfDiagnosticCode, type PerfSnapshot, type PerfThresholds, type PerformancePanel, type Priority, ROUTER_OUTLET_ID, ReadonlySignal, type ReconcileResult, type RenderContext, RenderHandle, type ResolvedConfig, type Resource, type ResourceInspection, type ResourceLike, type ResourceLoader, type ResourceLoaderContext, type ResourceOptions, type ResourceStatus, type RouteBuilder, type RouteContext, type RouteDefinition, type RouteMatch, type RouteMatchLike, type Router, type RouterHistory, type RouterInspection, type RouterLike, type RouterLocation, type RouterOptions, Runtime, RuntimeNodeInstance, type RuntimeOptions, Scheduler, type SchedulerDiagnostics, SemanticNodeType, ServerComment, ServerElement, ServerFragment, type ServerNode, type ServerNodeKind, type ServerParent, ServerStyle, ServerText, type ShellBuilder, Signal, type SignalInspection, SignalKind, type SignalsPanel, Store, type StoreState, type StreetEvent, type StreetEventType, StreetFrameworkError, StreetRenderHandle, StreetRenderer, StreetRendererImpl, type StreetRendererOptions, type StreetUIConfig, type SubmitStatus, Subscriber, Unsubscribe, type Validator, a11yIds, applyNodeProps, applyProp, bindDomEvent, browserDOMAdapter, buttonUpdate, consoleDiagnosticSink, createApplication, createBrowserHistory, createContext, createDevTools, createForm, createI18n, createMemoryHistory, createRenderContext, createRenderer, createRouter, createRuntime, createStore, createStreetEvent, defineConfig, diagnosePerformance, email, environment, escapeHtmlAttr, escapeHtmlText, flushSync, focusById, focusFirst, formatDiagnosticContext, frameworkError, globalEventBus, headingUpdate, hydrateGraph, inputUpdate, inspectApplication, inspectContext, inspectForm, inspectGraph, inspectI18n, inspectResource, inspectRouter, inspectSignal, interpolate, matchPattern, matchRoutes, maxLength, minLength, mountGraph, mountNode, mountRouter, nodeTypeStats, normalizePath, patchNode, patchProp, pattern, printDiagnostics, printGraph, reconcileChildren, reportDiagnostic, required, resolveTag, resource, routerOutlet, runValidators, scheduleImmediate, scheduleUpdate, scheduler, serializeChildren, serializeServerNode, splitTarget, textUpdate, toIdToken, transformGraph, validateGraph, wireEvents, wireReactiveList, wireSignalBindings };
|
|
1807
|
+
export { type A11yIds, Application, ApplicationGraph, ApplicationId, type ApplicationIdentity, type ApplicationInspection, type ApplicationOptions, type ApplicationPanel, BrowserDOMAdapter, CleanupRegistry, CompiledApplication, ContainerDSL, type Context, type ContextInspection, type ContextLike, DEFAULT_PERF_THRESHOLDS, DOMAdapter, type DevToolsOptions, type DevToolsSession, type DevToolsSnapshot, type DevToolsSources, DiagnosticCollector, type DiagnosticContext, type DiagnosticSink, type DiagnosticsSummary, type DomBinding, DomEventRegistry, Environment, type EnvironmentCapabilities, type EnvironmentKind, EventBus, type EventHandler, FOCUSABLE_SELECTOR, type Field, type Form, type FormConfig, type FormInspection, type FormLike, type FormValidators, type FormValues, GraphNode, HydrationDiagnosticSink, type I18n, type I18nConfig, type I18nInspection, type I18nLike, type InspectFormOptions, type InspectI18nOptions, type InspectResourceOptions, type InspectSignalOptions, type InspectedNode, type InspectedPage, type InterpolationParams, type IsActiveOptions, type Job, Lifecycle, type LifecycleHook, type LifecyclePhase, type MatchResult, type MessageMap, type MountFn, type MountRouterOptions, type MountedApplication, type MountedRouter, type NavigateOptions, NodeInstance, type NodeInstanceOptions, PageDSL, type PerfDiagnostic, type PerfDiagnosticCode, type PerfSnapshot, type PerfThresholds, type PerformancePanel, type PlanEntry, type Priority, ROUTER_OUTLET_ID, ReadonlySignal, type ReconcileResult, type RenderContext, RenderHandle, type ResolvedConfig, type Resource, type ResourceInspection, type ResourceLike, type ResourceLoader, type ResourceLoaderContext, type ResourceOptions, type ResourceStatus, type RouteBuilder, type RouteContext, type RouteDefinition, type RouteMatch, type RouteMatchLike, type Router, type RouterHistory, type RouterInspection, type RouterLike, type RouterLocation, type RouterOptions, Runtime, RuntimeNodeInstance, type RuntimeOptions, Scheduler, type SchedulerDiagnostics, SemanticNodeType, ServerComment, ServerElement, ServerFragment, type ServerNode, type ServerNodeKind, type ServerParent, ServerStyle, ServerText, type ShellBuilder, Signal, type SignalInspection, SignalKind, type SignalsPanel, Store, type StoreState, type StreetEvent, type StreetEventType, StreetFrameworkError, StreetRenderHandle, StreetRenderer, StreetRendererImpl, type StreetRendererOptions, type StreetUIConfig, type SubmitStatus, Subscriber, Unsubscribe, type Validator, a11yIds, applyNodeProps, applyProp, bindDomEvent, browserDOMAdapter, buttonUpdate, consoleDiagnosticSink, createApplication, createBrowserHistory, createContext, createDevTools, createForm, createI18n, createMemoryHistory, createRenderContext, createRenderer, createRouter, createRuntime, createStore, createStreetEvent, defineConfig, diagnosePerformance, email, environment, escapeHtmlAttr, escapeHtmlText, flushSync, focusById, focusFirst, formatDiagnosticContext, frameworkError, globalEventBus, headingUpdate, hydrateGraph, inputUpdate, inspectApplication, inspectContext, inspectForm, inspectGraph, inspectI18n, inspectResource, inspectRouter, inspectSignal, interpolate, matchPattern, matchRoutes, maxLength, minLength, mountGraph, mountNode, mountRouter, nodeTypeStats, normalizePath, patchNode, patchProp, pattern, printDiagnostics, printGraph, reconcileChildren, reconcileChildrenByPlan, reportDiagnostic, required, resolveTag, resource, routerOutlet, runValidators, scheduleImmediate, scheduleUpdate, scheduler, serializeChildren, serializeServerNode, splitTarget, textUpdate, toIdToken, transformGraph, validateGraph, wireEvents, wireReactiveList, wireSignalBindings };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { a as Signal, b as Subscriber, U as Unsubscribe, R as ReadonlySignal, A as ApplicationId, D as DiagnosticCollector, c as ApplicationGraph, G as GraphNode, C as CompiledApplication, d as SemanticNodeType, P as PageDSL, e as ContainerDSL, f as SignalKind } from './compile-
|
|
2
|
-
export { g as A11yOptions, h as AppBuilder, i as AppDSL, j as AppOptions, k as ApplicationGraphOptions, B as BaseNode, l as Bindable, m as BindableText, n as BoundInputOptions, o as ButtonOptions, p as CompileOptions, q as ContainerBuilder, r as ContainerBuilderImpl, s as ContainerOptions, t as ContentDSL, u as ControlledInputOptions, v as DerivedSignal, w as Diagnostic, x as DiagnosticError, y as DiagnosticLocation, z as DiagnosticSeverity, E as ErrorBoundaryOptions, F as ErrorFallbackBuilder, H as ErrorSource, I as EventDescriptor, J as FormBuilder, K as FormBuilderImpl, L as FormDSL, M as FormOptions, N as GraphNodeData, O as HandlerFn, Q as HeadingOptions, T as ImageOptions, W as InputOptions, X as InputOptionsBase, Y as LinkOptions, Z as ListBuilder, _ as ListBuilderImpl, $ as ListDSL, a0 as ListOptions, a1 as
|
|
3
|
-
import { R as RenderHandle, S as StreetRenderer, a as HydrationDiagnosticSink } from './hydration-diagnostics-
|
|
4
|
-
export { H as HydrationDiagnostic, b as HydrationMismatchType, c as consoleHydrationDiagnosticSink, d as createHydrationDiagnosticCollector, f as formatHydrationDiagnostic } from './hydration-diagnostics-
|
|
5
|
-
import { D as DOMAdapter } from './server-
|
|
6
|
-
export { R as RenderToStringOptions, S as STATE_MARKER_ATTR, a as ServerDOMAdapter, r as readState, b as renderToString, s as serializeState, c as serverDOMAdapter } from './server-
|
|
1
|
+
import { a as Signal, b as Subscriber, U as Unsubscribe, R as ReadonlySignal, A as ApplicationId, D as DiagnosticCollector, c as ApplicationGraph, G as GraphNode, C as CompiledApplication, d as SemanticNodeType, P as PageDSL, e as ContainerDSL, f as SignalKind } from './compile-CTA4MLX6.js';
|
|
2
|
+
export { g as A11yOptions, h as AppBuilder, i as AppDSL, j as AppOptions, k as ApplicationGraphOptions, B as BaseNode, l as Bindable, m as BindableText, n as BoundInputOptions, o as ButtonOptions, p as CompileOptions, q as ContainerBuilder, r as ContainerBuilderImpl, s as ContainerOptions, t as ContentDSL, u as ControlledInputOptions, v as DerivedSignal, w as Diagnostic, x as DiagnosticError, y as DiagnosticLocation, z as DiagnosticSeverity, E as ErrorBoundaryOptions, F as ErrorFallbackBuilder, H as ErrorSource, I as EventDescriptor, J as FormBuilder, K as FormBuilderImpl, L as FormDSL, M as FormOptions, N as GraphNodeData, O as HandlerFn, Q as HeadingOptions, T as ImageOptions, W as InputOptions, X as InputOptionsBase, Y as LinkOptions, Z as ListBuilder, _ as ListBuilderImpl, $ as ListDSL, a0 as ListOptions, a1 as ListPlanEntry, a2 as NodeId, a3 as NodeMetadata, a4 as PageBuilder, a5 as PageBuilderImpl, a6 as PropValue, a7 as Props, a8 as ReactiveConsumer, a9 as ReactiveSource, aa as SectionBuilder, ab as SectionBuilderImpl, ac as SectionDSL, ad as SectionOptions, ae as SerializedGraph, af as SerializedNode, ag as StateRef, S as StreetApp, ah as StreetUI, ai as TextOptions, aj as TextValue, V as VERSION, ak as batch, al as compile, am as compileGraph, an as createNodeId, ao as derived, ap as effect, aq as formatDiagnostic, ar as generateApplicationId, as as generateNodeId, at as isBatching, au as nextId, av as nodeIdPrefix, aw as observerCount, ax as reactiveListItemKey, ay as reactiveListItemSignature, az as resetIdCounter, aA as signal, aB as signalKind, aC as streetui } from './compile-CTA4MLX6.js';
|
|
3
|
+
import { R as RenderHandle, S as StreetRenderer, a as HydrationDiagnosticSink } from './hydration-diagnostics-DqkNk4EU.js';
|
|
4
|
+
export { H as HydrationDiagnostic, b as HydrationMismatchType, c as consoleHydrationDiagnosticSink, d as createHydrationDiagnosticCollector, f as formatHydrationDiagnostic } from './hydration-diagnostics-DqkNk4EU.js';
|
|
5
|
+
import { D as DOMAdapter } from './server-CtHBgrxf.js';
|
|
6
|
+
export { R as RenderToStringOptions, S as STATE_MARKER_ATTR, a as ServerDOMAdapter, r as readState, b as renderToString, s as serializeState, c as serverDOMAdapter } from './server-CtHBgrxf.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* A simple reactive store built on top of signals.
|
|
@@ -747,8 +747,10 @@ declare function applyNodeProps(ctx: RenderContext, graphNode: GraphNode, el: El
|
|
|
747
747
|
declare function wireSignalBindings(ctx: RenderContext, graphNode: GraphNode, instance: NodeInstance, onUpdate: (propKey: string, value: unknown) => void): void;
|
|
748
748
|
/**
|
|
749
749
|
* Subscribe a reactive-list instance to its driving signal. On each change the
|
|
750
|
-
* DSL-registered
|
|
751
|
-
* are reconciled against the live DOM with the keyed reconciler
|
|
750
|
+
* DSL-registered plan factory produces lightweight per-row descriptors, which
|
|
751
|
+
* are reconciled against the live DOM with the keyed, minimal-move reconciler
|
|
752
|
+
* (spec §15). A `conditional` node has no plan handler and falls back to the
|
|
753
|
+
* eager build factory (it only ever renders 0..1 branch, so eager is fine).
|
|
752
754
|
*/
|
|
753
755
|
declare function wireReactiveList(ctx: RenderContext, graphNode: GraphNode, instance: NodeInstance, el: Element): void;
|
|
754
756
|
|
|
@@ -785,6 +787,24 @@ interface ReconcileResult {
|
|
|
785
787
|
instances: NodeInstance[];
|
|
786
788
|
/** Instances that were removed and must be disposed. */
|
|
787
789
|
removed: NodeInstance[];
|
|
790
|
+
/**
|
|
791
|
+
* GraphNodes freshly materialised during this reconcile (new rows + rebuilt
|
|
792
|
+
* changed rows). The caller detaches any of these that were not adopted as a
|
|
793
|
+
* live instance's graph node, so no orphan subtree lingers in the graph index.
|
|
794
|
+
*/
|
|
795
|
+
built?: GraphNode[];
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* A lazy reconciliation descriptor for one reactive-list row (mirrors the DSL's
|
|
799
|
+
* `ListPlanEntry`). `sig()` and `build()` are only invoked for rows that are
|
|
800
|
+
* genuinely new or whose source reference changed — the whole point of the
|
|
801
|
+
* plan path (spec §15).
|
|
802
|
+
*/
|
|
803
|
+
interface PlanEntry {
|
|
804
|
+
readonly key: string;
|
|
805
|
+
readonly item: unknown;
|
|
806
|
+
readonly sig: () => string;
|
|
807
|
+
readonly build: () => GraphNode;
|
|
788
808
|
}
|
|
789
809
|
/**
|
|
790
810
|
* Reconcile children of a container element against a new list of graph nodes.
|
|
@@ -796,6 +816,25 @@ interface ReconcileResult {
|
|
|
796
816
|
* @param mountFn Factory to create a new NodeInstance for a graph node
|
|
797
817
|
*/
|
|
798
818
|
declare function reconcileChildren(ctx: RenderContext, parentDom: Element, oldInstances: NodeInstance[], newNodes: readonly GraphNode[], mountFn: MountFn): ReconcileResult;
|
|
819
|
+
/**
|
|
820
|
+
* Plan-based keyed reconciliation (spec §15 — the optimised reactive-list path).
|
|
821
|
+
*
|
|
822
|
+
* Identical observable result to {@link reconcileChildren}, but driven by lazy
|
|
823
|
+
* {@link PlanEntry} descriptors instead of a pre-built array of GraphNodes:
|
|
824
|
+
*
|
|
825
|
+
* - a reused row whose `item` reference is unchanged does **zero** work — no
|
|
826
|
+
* signature hash, no subtree build, no prop patch (the common case for
|
|
827
|
+
* append / prepend / remove / reorder / reverse, where existing item objects
|
|
828
|
+
* keep their identity);
|
|
829
|
+
* - a reused row whose reference changed hashes lazily and, only on a real
|
|
830
|
+
* signature change, materialises a fresh subtree for a targeted in-place
|
|
831
|
+
* content update;
|
|
832
|
+
* - a genuinely new key builds + mounts exactly one subtree.
|
|
833
|
+
*
|
|
834
|
+
* DOM reordering uses a longest-increasing-subsequence pass so the number of
|
|
835
|
+
* moves is minimal (e.g. a prepend into a 10k list moves 1 node, not 10k).
|
|
836
|
+
*/
|
|
837
|
+
declare function reconcileChildrenByPlan(ctx: RenderContext, parentDom: Element, oldInstances: NodeInstance[], plan: readonly PlanEntry[], mountFn: MountFn): ReconcileResult;
|
|
799
838
|
|
|
800
839
|
/**
|
|
801
840
|
* StreetUI Renderer — framework-owned DOM renderer.
|
|
@@ -1382,6 +1421,15 @@ interface PerfSnapshot {
|
|
|
1382
1421
|
readonly distinctSignals: number;
|
|
1383
1422
|
/** Largest single-node child count (a proxy for the biggest list/section). */
|
|
1384
1423
|
readonly largestChildCount: number;
|
|
1424
|
+
/**
|
|
1425
|
+
* Number of reactive keyed-list sites driven by the optimised lazy-plan
|
|
1426
|
+
* reconciler (v1.1 §15/§25). Counted from the graph's `__listplan__<id>`
|
|
1427
|
+
* handler registrations — one per `listOf(...)` bound to a signal. These are
|
|
1428
|
+
* the nodes whose updates take the identity-short-circuit + LIS minimal-move
|
|
1429
|
+
* path, so surfacing the count lets a panel or CI check see how much of an app
|
|
1430
|
+
* benefits from the keyed-list engine without measuring anything at runtime.
|
|
1431
|
+
*/
|
|
1432
|
+
readonly reactiveLists: number;
|
|
1385
1433
|
}
|
|
1386
1434
|
/**
|
|
1387
1435
|
* The complete read-only snapshot of a compiled application. Everything here is
|
|
@@ -1756,4 +1804,4 @@ interface ResolvedConfig {
|
|
|
1756
1804
|
/** Identity helper that gives `streetui.config.ts` full type-checking + inference. */
|
|
1757
1805
|
declare function defineConfig(config: StreetUIConfig): StreetUIConfig;
|
|
1758
1806
|
|
|
1759
|
-
export { type A11yIds, Application, ApplicationGraph, ApplicationId, type ApplicationIdentity, type ApplicationInspection, type ApplicationOptions, type ApplicationPanel, BrowserDOMAdapter, CleanupRegistry, CompiledApplication, ContainerDSL, type Context, type ContextInspection, type ContextLike, DEFAULT_PERF_THRESHOLDS, DOMAdapter, type DevToolsOptions, type DevToolsSession, type DevToolsSnapshot, type DevToolsSources, DiagnosticCollector, type DiagnosticContext, type DiagnosticSink, type DiagnosticsSummary, type DomBinding, DomEventRegistry, Environment, type EnvironmentCapabilities, type EnvironmentKind, EventBus, type EventHandler, FOCUSABLE_SELECTOR, type Field, type Form, type FormConfig, type FormInspection, type FormLike, type FormValidators, type FormValues, GraphNode, HydrationDiagnosticSink, type I18n, type I18nConfig, type I18nInspection, type I18nLike, type InspectFormOptions, type InspectI18nOptions, type InspectResourceOptions, type InspectSignalOptions, type InspectedNode, type InspectedPage, type InterpolationParams, type IsActiveOptions, type Job, Lifecycle, type LifecycleHook, type LifecyclePhase, type MatchResult, type MessageMap, type MountFn, type MountRouterOptions, type MountedApplication, type MountedRouter, type NavigateOptions, NodeInstance, type NodeInstanceOptions, PageDSL, type PerfDiagnostic, type PerfDiagnosticCode, type PerfSnapshot, type PerfThresholds, type PerformancePanel, type Priority, ROUTER_OUTLET_ID, ReadonlySignal, type ReconcileResult, type RenderContext, RenderHandle, type ResolvedConfig, type Resource, type ResourceInspection, type ResourceLike, type ResourceLoader, type ResourceLoaderContext, type ResourceOptions, type ResourceStatus, type RouteBuilder, type RouteContext, type RouteDefinition, type RouteMatch, type RouteMatchLike, type Router, type RouterHistory, type RouterInspection, type RouterLike, type RouterLocation, type RouterOptions, Runtime, RuntimeNodeInstance, type RuntimeOptions, Scheduler, type SchedulerDiagnostics, SemanticNodeType, ServerComment, ServerElement, ServerFragment, type ServerNode, type ServerNodeKind, type ServerParent, ServerStyle, ServerText, type ShellBuilder, Signal, type SignalInspection, SignalKind, type SignalsPanel, Store, type StoreState, type StreetEvent, type StreetEventType, StreetFrameworkError, StreetRenderHandle, StreetRenderer, StreetRendererImpl, type StreetRendererOptions, type StreetUIConfig, type SubmitStatus, Subscriber, Unsubscribe, type Validator, a11yIds, applyNodeProps, applyProp, bindDomEvent, browserDOMAdapter, buttonUpdate, consoleDiagnosticSink, createApplication, createBrowserHistory, createContext, createDevTools, createForm, createI18n, createMemoryHistory, createRenderContext, createRenderer, createRouter, createRuntime, createStore, createStreetEvent, defineConfig, diagnosePerformance, email, environment, escapeHtmlAttr, escapeHtmlText, flushSync, focusById, focusFirst, formatDiagnosticContext, frameworkError, globalEventBus, headingUpdate, hydrateGraph, inputUpdate, inspectApplication, inspectContext, inspectForm, inspectGraph, inspectI18n, inspectResource, inspectRouter, inspectSignal, interpolate, matchPattern, matchRoutes, maxLength, minLength, mountGraph, mountNode, mountRouter, nodeTypeStats, normalizePath, patchNode, patchProp, pattern, printDiagnostics, printGraph, reconcileChildren, reportDiagnostic, required, resolveTag, resource, routerOutlet, runValidators, scheduleImmediate, scheduleUpdate, scheduler, serializeChildren, serializeServerNode, splitTarget, textUpdate, toIdToken, transformGraph, validateGraph, wireEvents, wireReactiveList, wireSignalBindings };
|
|
1807
|
+
export { type A11yIds, Application, ApplicationGraph, ApplicationId, type ApplicationIdentity, type ApplicationInspection, type ApplicationOptions, type ApplicationPanel, BrowserDOMAdapter, CleanupRegistry, CompiledApplication, ContainerDSL, type Context, type ContextInspection, type ContextLike, DEFAULT_PERF_THRESHOLDS, DOMAdapter, type DevToolsOptions, type DevToolsSession, type DevToolsSnapshot, type DevToolsSources, DiagnosticCollector, type DiagnosticContext, type DiagnosticSink, type DiagnosticsSummary, type DomBinding, DomEventRegistry, Environment, type EnvironmentCapabilities, type EnvironmentKind, EventBus, type EventHandler, FOCUSABLE_SELECTOR, type Field, type Form, type FormConfig, type FormInspection, type FormLike, type FormValidators, type FormValues, GraphNode, HydrationDiagnosticSink, type I18n, type I18nConfig, type I18nInspection, type I18nLike, type InspectFormOptions, type InspectI18nOptions, type InspectResourceOptions, type InspectSignalOptions, type InspectedNode, type InspectedPage, type InterpolationParams, type IsActiveOptions, type Job, Lifecycle, type LifecycleHook, type LifecyclePhase, type MatchResult, type MessageMap, type MountFn, type MountRouterOptions, type MountedApplication, type MountedRouter, type NavigateOptions, NodeInstance, type NodeInstanceOptions, PageDSL, type PerfDiagnostic, type PerfDiagnosticCode, type PerfSnapshot, type PerfThresholds, type PerformancePanel, type PlanEntry, type Priority, ROUTER_OUTLET_ID, ReadonlySignal, type ReconcileResult, type RenderContext, RenderHandle, type ResolvedConfig, type Resource, type ResourceInspection, type ResourceLike, type ResourceLoader, type ResourceLoaderContext, type ResourceOptions, type ResourceStatus, type RouteBuilder, type RouteContext, type RouteDefinition, type RouteMatch, type RouteMatchLike, type Router, type RouterHistory, type RouterInspection, type RouterLike, type RouterLocation, type RouterOptions, Runtime, RuntimeNodeInstance, type RuntimeOptions, Scheduler, type SchedulerDiagnostics, SemanticNodeType, ServerComment, ServerElement, ServerFragment, type ServerNode, type ServerNodeKind, type ServerParent, ServerStyle, ServerText, type ShellBuilder, Signal, type SignalInspection, SignalKind, type SignalsPanel, Store, type StoreState, type StreetEvent, type StreetEventType, StreetFrameworkError, StreetRenderHandle, StreetRenderer, StreetRendererImpl, type StreetRendererOptions, type StreetUIConfig, type SubmitStatus, Subscriber, Unsubscribe, type Validator, a11yIds, applyNodeProps, applyProp, bindDomEvent, browserDOMAdapter, buttonUpdate, consoleDiagnosticSink, createApplication, createBrowserHistory, createContext, createDevTools, createForm, createI18n, createMemoryHistory, createRenderContext, createRenderer, createRouter, createRuntime, createStore, createStreetEvent, defineConfig, diagnosePerformance, email, environment, escapeHtmlAttr, escapeHtmlText, flushSync, focusById, focusFirst, formatDiagnosticContext, frameworkError, globalEventBus, headingUpdate, hydrateGraph, inputUpdate, inspectApplication, inspectContext, inspectForm, inspectGraph, inspectI18n, inspectResource, inspectRouter, inspectSignal, interpolate, matchPattern, matchRoutes, maxLength, minLength, mountGraph, mountNode, mountRouter, nodeTypeStats, normalizePath, patchNode, patchProp, pattern, printDiagnostics, printGraph, reconcileChildren, reconcileChildrenByPlan, reportDiagnostic, required, resolveTag, resource, routerOutlet, runValidators, scheduleImmediate, scheduleUpdate, scheduler, serializeChildren, serializeServerNode, splitTarget, textUpdate, toIdToken, transformGraph, validateGraph, wireEvents, wireReactiveList, wireSignalBindings };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/version.ts
|
|
2
|
-
var VERSION = "1.
|
|
2
|
+
var VERSION = "1.3.0";
|
|
3
3
|
|
|
4
4
|
// ../state/src/signal.ts
|
|
5
5
|
var _activeConsumer = null;
|
|
@@ -801,6 +801,7 @@ var ApplicationGraph = class {
|
|
|
801
801
|
this.handlers.delete(`__signal__${ref.signalId}`);
|
|
802
802
|
}
|
|
803
803
|
this.handlers.delete(`__listbuild__${node.id}`);
|
|
804
|
+
this.handlers.delete(`__listplan__${node.id}`);
|
|
804
805
|
}
|
|
805
806
|
// ── Handler registry ──────────────────────────────────────────────────────
|
|
806
807
|
registerHandler(key, fn) {
|
|
@@ -1096,16 +1097,38 @@ var ContainerBuilderBase = class extends ContentBuilderBase {
|
|
|
1096
1097
|
const itemKey = reactiveListItemKey(item, index);
|
|
1097
1098
|
const itemNode = graph.createNode("list-item", {
|
|
1098
1099
|
key: itemKey,
|
|
1099
|
-
|
|
1100
|
+
// `_item` records the source item *reference* so the reconciler can
|
|
1101
|
+
// short-circuit unchanged rows by identity (no signature hashing); `_sig`
|
|
1102
|
+
// is the content signature used to detect an in-place data change when the
|
|
1103
|
+
// reference differs. Both are internal metadata (leading `_`) and never
|
|
1104
|
+
// reach the DOM.
|
|
1105
|
+
props: {
|
|
1106
|
+
key: itemKey,
|
|
1107
|
+
_sig: reactiveListItemSignature(item),
|
|
1108
|
+
// The item reference is stored as opaque internal metadata (never
|
|
1109
|
+
// rendered); cast through `unknown` since `T` is not a `PropValue`.
|
|
1110
|
+
_item: item
|
|
1111
|
+
}
|
|
1100
1112
|
});
|
|
1101
1113
|
renderItem(item, index, new ContainerBuilderImpl(itemNode, graph));
|
|
1102
1114
|
return itemNode;
|
|
1103
1115
|
};
|
|
1104
|
-
const
|
|
1116
|
+
const buildPlan = (raw) => {
|
|
1105
1117
|
const arr = Array.isArray(raw) ? raw : [];
|
|
1106
|
-
|
|
1118
|
+
const plan = new Array(arr.length);
|
|
1119
|
+
for (let i = 0; i < arr.length; i++) {
|
|
1120
|
+
const item = arr[i];
|
|
1121
|
+
const index = i;
|
|
1122
|
+
plan[i] = {
|
|
1123
|
+
key: reactiveListItemKey(item, index),
|
|
1124
|
+
item,
|
|
1125
|
+
sig: () => reactiveListItemSignature(item),
|
|
1126
|
+
build: () => buildItem(item, index)
|
|
1127
|
+
};
|
|
1128
|
+
}
|
|
1129
|
+
return plan;
|
|
1107
1130
|
};
|
|
1108
|
-
graph.registerHandler(`
|
|
1131
|
+
graph.registerHandler(`__listplan__${node.id}`, buildPlan);
|
|
1109
1132
|
const current = isSignal(items) ? items.peek() : items;
|
|
1110
1133
|
const initial = Array.isArray(current) ? current : [];
|
|
1111
1134
|
initial.forEach((item, i) => {
|
|
@@ -2250,6 +2273,7 @@ function patchProp(dom, element, name, oldValue, newValue) {
|
|
|
2250
2273
|
|
|
2251
2274
|
// ../renderer/src/events.ts
|
|
2252
2275
|
function wireEvents(dom, graph, node, element, instance) {
|
|
2276
|
+
if (node.events.length === 0) return;
|
|
2253
2277
|
for (const eventDesc of node.events) {
|
|
2254
2278
|
const handler = graph.getHandler(eventDesc.handlerKey);
|
|
2255
2279
|
if (handler === void 0) continue;
|
|
@@ -2379,6 +2403,109 @@ function reconcileChildren(ctx, parentDom, oldInstances, newNodes, mountFn) {
|
|
|
2379
2403
|
reorderDom(ctx, parentDom, newInstances);
|
|
2380
2404
|
return { instances: newInstances, removed };
|
|
2381
2405
|
}
|
|
2406
|
+
function reconcileChildrenByPlan(ctx, parentDom, oldInstances, plan, mountFn) {
|
|
2407
|
+
const oldByKey = /* @__PURE__ */ new Map();
|
|
2408
|
+
for (const inst of oldInstances) {
|
|
2409
|
+
oldByKey.set(inst.graphNode.key ?? inst.graphNode.id, inst);
|
|
2410
|
+
}
|
|
2411
|
+
const newInstances = [];
|
|
2412
|
+
const usedKeys = /* @__PURE__ */ new Set();
|
|
2413
|
+
const built = [];
|
|
2414
|
+
for (const entry of plan) {
|
|
2415
|
+
const existing = oldByKey.get(entry.key);
|
|
2416
|
+
if (existing !== void 0) {
|
|
2417
|
+
usedKeys.add(entry.key);
|
|
2418
|
+
const oldItem = existing.graphNode.getProp("_item");
|
|
2419
|
+
if (!Object.is(oldItem, entry.item)) {
|
|
2420
|
+
const newSig = entry.sig();
|
|
2421
|
+
const oldSig = existing.graphNode.getProp("_sig");
|
|
2422
|
+
if (!Object.is(oldSig, newSig)) {
|
|
2423
|
+
const freshNode = entry.build();
|
|
2424
|
+
built.push(freshNode);
|
|
2425
|
+
patchExistingInstance(ctx, existing, freshNode);
|
|
2426
|
+
reconcileItemChildren(ctx, existing, freshNode, mountFn);
|
|
2427
|
+
existing.graphNode.setProp("_sig", newSig);
|
|
2428
|
+
}
|
|
2429
|
+
existing.graphNode.setProp("_item", entry.item);
|
|
2430
|
+
}
|
|
2431
|
+
newInstances.push(existing);
|
|
2432
|
+
} else {
|
|
2433
|
+
const freshNode = entry.build();
|
|
2434
|
+
built.push(freshNode);
|
|
2435
|
+
const inst = mountFn(freshNode, parentDom);
|
|
2436
|
+
newInstances.push(inst);
|
|
2437
|
+
}
|
|
2438
|
+
}
|
|
2439
|
+
const removed = [];
|
|
2440
|
+
for (const inst of oldInstances) {
|
|
2441
|
+
const key = inst.graphNode.key ?? inst.graphNode.id;
|
|
2442
|
+
if (!usedKeys.has(key)) removed.push(inst);
|
|
2443
|
+
}
|
|
2444
|
+
for (const inst of removed) {
|
|
2445
|
+
const parent = ctx.dom.parentNode(inst.domNode);
|
|
2446
|
+
if (parent !== null) ctx.dom.removeChild(parent, inst.domNode);
|
|
2447
|
+
inst.dispose();
|
|
2448
|
+
}
|
|
2449
|
+
reorderDomMinimal(ctx, parentDom, oldInstances, newInstances);
|
|
2450
|
+
return { instances: newInstances, removed, built };
|
|
2451
|
+
}
|
|
2452
|
+
function reorderDomMinimal(ctx, parentDom, oldInstances, newInstances) {
|
|
2453
|
+
const n = newInstances.length;
|
|
2454
|
+
if (n === 0) return;
|
|
2455
|
+
const oldIndexOf = /* @__PURE__ */ new Map();
|
|
2456
|
+
for (let i = 0; i < oldInstances.length; i++) oldIndexOf.set(oldInstances[i], i);
|
|
2457
|
+
const source = new Array(n);
|
|
2458
|
+
let moved = false;
|
|
2459
|
+
let lastSeen = -1;
|
|
2460
|
+
for (let i = 0; i < n; i++) {
|
|
2461
|
+
const oi = oldIndexOf.get(newInstances[i]);
|
|
2462
|
+
if (oi === void 0) {
|
|
2463
|
+
source[i] = -1;
|
|
2464
|
+
moved = true;
|
|
2465
|
+
} else {
|
|
2466
|
+
source[i] = oi;
|
|
2467
|
+
if (oi < lastSeen) moved = true;
|
|
2468
|
+
else lastSeen = oi;
|
|
2469
|
+
}
|
|
2470
|
+
}
|
|
2471
|
+
if (!moved) return;
|
|
2472
|
+
const keep = longestIncreasingSubsequence(source);
|
|
2473
|
+
let refNode = null;
|
|
2474
|
+
for (let i = n - 1; i >= 0; i--) {
|
|
2475
|
+
const domNode = newInstances[i].domNode;
|
|
2476
|
+
if (source[i] === -1 || !keep.has(i)) {
|
|
2477
|
+
if (ctx.dom.nextSibling(domNode) !== refNode) {
|
|
2478
|
+
ctx.dom.insertBefore(parentDom, domNode, refNode);
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2481
|
+
refNode = domNode;
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
function longestIncreasingSubsequence(source) {
|
|
2485
|
+
const keep = /* @__PURE__ */ new Set();
|
|
2486
|
+
const n = source.length;
|
|
2487
|
+
const tails = [];
|
|
2488
|
+
const prev = new Array(n).fill(-1);
|
|
2489
|
+
for (let i = 0; i < n; i++) {
|
|
2490
|
+
const v = source[i];
|
|
2491
|
+
if (v < 0) continue;
|
|
2492
|
+
let lo = 0;
|
|
2493
|
+
let hi = tails.length;
|
|
2494
|
+
while (lo < hi) {
|
|
2495
|
+
const mid = lo + hi >> 1;
|
|
2496
|
+
if (source[tails[mid]] < v) lo = mid + 1;
|
|
2497
|
+
else hi = mid;
|
|
2498
|
+
}
|
|
2499
|
+
if (lo > 0) prev[i] = tails[lo - 1];
|
|
2500
|
+
tails[lo] = i;
|
|
2501
|
+
}
|
|
2502
|
+
let idx = tails.length > 0 ? tails[tails.length - 1] : -1;
|
|
2503
|
+
while (idx >= 0) {
|
|
2504
|
+
keep.add(idx);
|
|
2505
|
+
idx = prev[idx];
|
|
2506
|
+
}
|
|
2507
|
+
return keep;
|
|
2508
|
+
}
|
|
2382
2509
|
function reconcileItemChildren(ctx, itemInstance, newItemNode, mountFn) {
|
|
2383
2510
|
const el = itemInstance.domNode;
|
|
2384
2511
|
if (!ctx.dom.isElement(el)) return;
|
|
@@ -2480,10 +2607,12 @@ function mountNode(ctx, graphNode, parentDom) {
|
|
|
2480
2607
|
const textNode = dom.createTextNode(text);
|
|
2481
2608
|
dom.appendChild(el2, textNode);
|
|
2482
2609
|
applyNodeProps(ctx, graphNode, el2);
|
|
2483
|
-
wireEvents(dom, graph, graphNode, el2, new NodeInstance(graphNode, el2));
|
|
2484
2610
|
const instance2 = new NodeInstance(graphNode, el2);
|
|
2485
2611
|
ctx.instances.set(graphNode.id, instance2);
|
|
2486
|
-
|
|
2612
|
+
wireEvents(dom, graph, graphNode, el2, instance2);
|
|
2613
|
+
if (graphNode.stateRefs.length !== 0) {
|
|
2614
|
+
wireSignalBindings(ctx, graphNode, instance2, textUpdate(dom, el2, textNode));
|
|
2615
|
+
}
|
|
2487
2616
|
dom.appendChild(parentDom, el2);
|
|
2488
2617
|
return instance2;
|
|
2489
2618
|
}
|
|
@@ -2497,7 +2626,9 @@ function mountNode(ctx, graphNode, parentDom) {
|
|
|
2497
2626
|
const instance2 = new NodeInstance(graphNode, el2);
|
|
2498
2627
|
ctx.instances.set(graphNode.id, instance2);
|
|
2499
2628
|
wireEvents(dom, graph, graphNode, el2, instance2);
|
|
2500
|
-
|
|
2629
|
+
if (graphNode.stateRefs.length !== 0) {
|
|
2630
|
+
wireSignalBindings(ctx, graphNode, instance2, headingUpdate(dom, el2));
|
|
2631
|
+
}
|
|
2501
2632
|
dom.appendChild(parentDom, el2);
|
|
2502
2633
|
return instance2;
|
|
2503
2634
|
}
|
|
@@ -2513,7 +2644,9 @@ function mountNode(ctx, graphNode, parentDom) {
|
|
|
2513
2644
|
const instance2 = new NodeInstance(graphNode, el2);
|
|
2514
2645
|
ctx.instances.set(graphNode.id, instance2);
|
|
2515
2646
|
wireEvents(dom, graph, graphNode, el2, instance2);
|
|
2516
|
-
|
|
2647
|
+
if (graphNode.stateRefs.length !== 0) {
|
|
2648
|
+
wireSignalBindings(ctx, graphNode, instance2, inputUpdate(dom, el2));
|
|
2649
|
+
}
|
|
2517
2650
|
dom.appendChild(parentDom, el2);
|
|
2518
2651
|
return instance2;
|
|
2519
2652
|
}
|
|
@@ -2561,7 +2694,9 @@ function mountNode(ctx, graphNode, parentDom) {
|
|
|
2561
2694
|
const instance2 = new NodeInstance(graphNode, el2);
|
|
2562
2695
|
ctx.instances.set(graphNode.id, instance2);
|
|
2563
2696
|
wireEvents(dom, graph, graphNode, el2, instance2);
|
|
2564
|
-
|
|
2697
|
+
if (graphNode.stateRefs.length !== 0) {
|
|
2698
|
+
wireSignalBindings(ctx, graphNode, instance2, buttonUpdate(dom, el2));
|
|
2699
|
+
}
|
|
2565
2700
|
dom.appendChild(parentDom, el2);
|
|
2566
2701
|
return instance2;
|
|
2567
2702
|
}
|
|
@@ -2588,11 +2723,11 @@ function mountNode(ctx, graphNode, parentDom) {
|
|
|
2588
2723
|
dom.setAttribute(el, "data-streetui-key", String(itemKey));
|
|
2589
2724
|
}
|
|
2590
2725
|
}
|
|
2591
|
-
if (graphNode.type === "form") {
|
|
2592
|
-
wireEvents(dom, graph, graphNode, el, new NodeInstance(graphNode, el));
|
|
2593
|
-
}
|
|
2594
2726
|
const instance = new NodeInstance(graphNode, el);
|
|
2595
2727
|
ctx.instances.set(graphNode.id, instance);
|
|
2728
|
+
if (graphNode.type === "form") {
|
|
2729
|
+
wireEvents(dom, graph, graphNode, el, instance);
|
|
2730
|
+
}
|
|
2596
2731
|
for (const child of graphNode.children) {
|
|
2597
2732
|
const childInstance = mountNode(ctx, child, el);
|
|
2598
2733
|
instance.addChild(childInstance);
|
|
@@ -2643,12 +2778,15 @@ function buttonUpdate(dom, el) {
|
|
|
2643
2778
|
};
|
|
2644
2779
|
}
|
|
2645
2780
|
function applyNodeProps(ctx, graphNode, el) {
|
|
2646
|
-
|
|
2781
|
+
const props = graphNode.props;
|
|
2782
|
+
for (const key in props) {
|
|
2783
|
+
if (!Object.hasOwn(props, key)) continue;
|
|
2647
2784
|
if (SKIP_PROP_KEYS.has(key)) continue;
|
|
2648
|
-
applyProp(ctx.dom, el, key,
|
|
2785
|
+
applyProp(ctx.dom, el, key, props[key]);
|
|
2649
2786
|
}
|
|
2650
2787
|
}
|
|
2651
2788
|
function wireSignalBindings(ctx, graphNode, instance, onUpdate) {
|
|
2789
|
+
if (graphNode.stateRefs.length === 0) return;
|
|
2652
2790
|
for (const stateRef of graphNode.stateRefs) {
|
|
2653
2791
|
const signalKey = `__signal__${stateRef.signalId}`;
|
|
2654
2792
|
const maybeSig = ctx.graph.getHandler(signalKey);
|
|
@@ -2660,18 +2798,45 @@ function wireSignalBindings(ctx, graphNode, instance, onUpdate) {
|
|
|
2660
2798
|
}
|
|
2661
2799
|
}
|
|
2662
2800
|
function wireReactiveList(ctx, graphNode, instance, el) {
|
|
2801
|
+
const plan = ctx.graph.getHandler(`__listplan__${graphNode.id}`);
|
|
2663
2802
|
const build = ctx.graph.getHandler(`__listbuild__${graphNode.id}`);
|
|
2664
|
-
if (build === void 0) return;
|
|
2803
|
+
if (plan === void 0 && build === void 0) return;
|
|
2665
2804
|
for (const stateRef of graphNode.stateRefs) {
|
|
2666
2805
|
if (stateRef.propKey !== "items") continue;
|
|
2667
2806
|
const sig = ctx.graph.getHandler(`__signal__${stateRef.signalId}`);
|
|
2668
2807
|
if (sig === void 0 || typeof sig.subscribe !== "function") continue;
|
|
2669
2808
|
const unsub = sig.subscribe((value) => {
|
|
2670
|
-
|
|
2809
|
+
if (plan !== void 0) {
|
|
2810
|
+
reconcileReactiveListByPlan(ctx, graphNode, instance, el, plan(value));
|
|
2811
|
+
} else {
|
|
2812
|
+
reconcileReactiveList(ctx, graphNode, instance, el, build(value));
|
|
2813
|
+
}
|
|
2671
2814
|
});
|
|
2672
2815
|
instance.trackCleanup(unsub);
|
|
2673
2816
|
}
|
|
2674
2817
|
}
|
|
2818
|
+
function reconcileReactiveListByPlan(ctx, listNode, listInstance, listEl, plan) {
|
|
2819
|
+
const oldInstances = [...listInstance.children];
|
|
2820
|
+
const result = reconcileChildrenByPlan(
|
|
2821
|
+
ctx,
|
|
2822
|
+
listEl,
|
|
2823
|
+
oldInstances,
|
|
2824
|
+
plan,
|
|
2825
|
+
(node, parent) => mountNode(ctx, node, parent)
|
|
2826
|
+
);
|
|
2827
|
+
listInstance.children.length = 0;
|
|
2828
|
+
for (const inst of result.instances) listInstance.children.push(inst);
|
|
2829
|
+
for (const removed of result.removed) {
|
|
2830
|
+
forgetInstance(ctx, removed);
|
|
2831
|
+
ctx.graph.detachNode(removed.graphNode);
|
|
2832
|
+
}
|
|
2833
|
+
const adopted = new Set(result.instances.map((i) => i.graphNode));
|
|
2834
|
+
for (const node of result.built ?? []) {
|
|
2835
|
+
if (!adopted.has(node)) ctx.graph.detachNode(node);
|
|
2836
|
+
}
|
|
2837
|
+
for (const child of [...listNode.children]) listNode.removeChild(child);
|
|
2838
|
+
for (const inst of result.instances) listNode.appendChild(inst.graphNode);
|
|
2839
|
+
}
|
|
2675
2840
|
function reconcileReactiveList(ctx, listNode, listInstance, listEl, newNodes) {
|
|
2676
2841
|
const oldInstances = [...listInstance.children];
|
|
2677
2842
|
const result = reconcileChildren(
|
|
@@ -2751,14 +2916,18 @@ function hydrateNode(ctx, graphNode, domNode, path) {
|
|
|
2751
2916
|
const instance = new NodeInstance(graphNode, domNode);
|
|
2752
2917
|
ctx.instances.set(graphNode.id, instance);
|
|
2753
2918
|
wireEvents(dom, graph, graphNode, domNode, instance);
|
|
2754
|
-
|
|
2919
|
+
if (graphNode.stateRefs.length !== 0) {
|
|
2920
|
+
wireSignalBindings(ctx, graphNode, instance, textUpdate(dom, domNode, textNode));
|
|
2921
|
+
}
|
|
2755
2922
|
return instance;
|
|
2756
2923
|
}
|
|
2757
2924
|
case "heading": {
|
|
2758
2925
|
const instance = new NodeInstance(graphNode, domNode);
|
|
2759
2926
|
ctx.instances.set(graphNode.id, instance);
|
|
2760
2927
|
wireEvents(dom, graph, graphNode, domNode, instance);
|
|
2761
|
-
|
|
2928
|
+
if (graphNode.stateRefs.length !== 0) {
|
|
2929
|
+
wireSignalBindings(ctx, graphNode, instance, headingUpdate(dom, domNode));
|
|
2930
|
+
}
|
|
2762
2931
|
return instance;
|
|
2763
2932
|
}
|
|
2764
2933
|
case "input": {
|
|
@@ -2767,14 +2936,18 @@ function hydrateNode(ctx, graphNode, domNode, path) {
|
|
|
2767
2936
|
const value = graphNode.getProp("value");
|
|
2768
2937
|
if (value !== void 0) dom.setProperty(domNode, "value", String(value));
|
|
2769
2938
|
wireEvents(dom, graph, graphNode, domNode, instance);
|
|
2770
|
-
|
|
2939
|
+
if (graphNode.stateRefs.length !== 0) {
|
|
2940
|
+
wireSignalBindings(ctx, graphNode, instance, inputUpdate(dom, domNode));
|
|
2941
|
+
}
|
|
2771
2942
|
return instance;
|
|
2772
2943
|
}
|
|
2773
2944
|
case "button": {
|
|
2774
2945
|
const instance = new NodeInstance(graphNode, domNode);
|
|
2775
2946
|
ctx.instances.set(graphNode.id, instance);
|
|
2776
2947
|
wireEvents(dom, graph, graphNode, domNode, instance);
|
|
2777
|
-
|
|
2948
|
+
if (graphNode.stateRefs.length !== 0) {
|
|
2949
|
+
wireSignalBindings(ctx, graphNode, instance, buttonUpdate(dom, domNode));
|
|
2950
|
+
}
|
|
2778
2951
|
return instance;
|
|
2779
2952
|
}
|
|
2780
2953
|
case "image":
|
|
@@ -2810,10 +2983,11 @@ function hydrateChildren(ctx, parentGraphNode, parentInstance, parentDom, parent
|
|
|
2810
2983
|
const expected = parentGraphNode.children;
|
|
2811
2984
|
const actual = elementChildren(ctx, parentDom);
|
|
2812
2985
|
let cursor = 0;
|
|
2986
|
+
const diag = ctx.hydrationDiagnostics !== void 0;
|
|
2813
2987
|
for (let i = 0; i < expected.length; i++) {
|
|
2814
2988
|
const childNode = expected[i];
|
|
2815
2989
|
const want = expectedTag(ctx, childNode);
|
|
2816
|
-
const childPath = `${parentPath} / ${childNode.type}[${i}]
|
|
2990
|
+
const childPath = diag ? `${parentPath} / ${childNode.type}[${i}]` : parentPath;
|
|
2817
2991
|
const actualEl = actual[cursor];
|
|
2818
2992
|
if (actualEl !== void 0 && ctx.dom.isElement(actualEl) && ctx.dom.tagName(actualEl) === want) {
|
|
2819
2993
|
const inst = hydrateNode(ctx, childNode, actualEl, childPath);
|
|
@@ -3665,6 +3839,10 @@ function inspectApplication(compiled) {
|
|
|
3665
3839
|
const errors = diags.filter((d) => d.severity === "error").length;
|
|
3666
3840
|
const perfAcc = { totalNodes: 0, maxDepth: 0, eventHandlers: 0, stateBindings: 0, largestChildCount: 0 };
|
|
3667
3841
|
collectPerf(graph, signals.size, perfAcc);
|
|
3842
|
+
let reactiveLists = 0;
|
|
3843
|
+
for (const key of compiled.graph.handlers.keys()) {
|
|
3844
|
+
if (key.startsWith("__listplan__")) reactiveLists += 1;
|
|
3845
|
+
}
|
|
3668
3846
|
return {
|
|
3669
3847
|
identity: {
|
|
3670
3848
|
name: compiled.name,
|
|
@@ -3686,7 +3864,8 @@ function inspectApplication(compiled) {
|
|
|
3686
3864
|
eventHandlers: perfAcc.eventHandlers,
|
|
3687
3865
|
stateBindings: perfAcc.stateBindings,
|
|
3688
3866
|
distinctSignals: signals.size,
|
|
3689
|
-
largestChildCount: perfAcc.largestChildCount
|
|
3867
|
+
largestChildCount: perfAcc.largestChildCount,
|
|
3868
|
+
reactiveLists
|
|
3690
3869
|
}
|
|
3691
3870
|
};
|
|
3692
3871
|
}
|
|
@@ -4084,6 +4263,7 @@ export {
|
|
|
4084
4263
|
reactiveListItemSignature,
|
|
4085
4264
|
readState,
|
|
4086
4265
|
reconcileChildren,
|
|
4266
|
+
reconcileChildrenByPlan,
|
|
4087
4267
|
renderToString,
|
|
4088
4268
|
reportDiagnostic,
|
|
4089
4269
|
required,
|