@streetui/dsl 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/index.cjs CHANGED
@@ -241,16 +241,38 @@ var ContainerBuilderBase = class extends ContentBuilderBase {
241
241
  const itemKey = reactiveListItemKey(item, index);
242
242
  const itemNode = graph.createNode("list-item", {
243
243
  key: itemKey,
244
- props: { key: itemKey, _sig: reactiveListItemSignature(item) }
244
+ // `_item` records the source item *reference* so the reconciler can
245
+ // short-circuit unchanged rows by identity (no signature hashing); `_sig`
246
+ // is the content signature used to detect an in-place data change when the
247
+ // reference differs. Both are internal metadata (leading `_`) and never
248
+ // reach the DOM.
249
+ props: {
250
+ key: itemKey,
251
+ _sig: reactiveListItemSignature(item),
252
+ // The item reference is stored as opaque internal metadata (never
253
+ // rendered); cast through `unknown` since `T` is not a `PropValue`.
254
+ _item: item
255
+ }
245
256
  });
246
257
  renderItem(item, index, new ContainerBuilderImpl(itemNode, graph));
247
258
  return itemNode;
248
259
  };
249
- const buildAll = (raw) => {
260
+ const buildPlan = (raw) => {
250
261
  const arr = Array.isArray(raw) ? raw : [];
251
- return arr.map((item, i) => buildItem(item, i));
262
+ const plan = new Array(arr.length);
263
+ for (let i = 0; i < arr.length; i++) {
264
+ const item = arr[i];
265
+ const index = i;
266
+ plan[i] = {
267
+ key: reactiveListItemKey(item, index),
268
+ item,
269
+ sig: () => reactiveListItemSignature(item),
270
+ build: () => buildItem(item, index)
271
+ };
272
+ }
273
+ return plan;
252
274
  };
253
- graph.registerHandler(`__listbuild__${node.id}`, buildAll);
275
+ graph.registerHandler(`__listplan__${node.id}`, buildPlan);
254
276
  const current = isSignal(items) ? items.peek() : items;
255
277
  const initial = Array.isArray(current) ? current : [];
256
278
  initial.forEach((item, i) => {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/builders.ts","../src/dsl.ts"],"sourcesContent":["export * from './dsl-types.js';\nexport * from './builders.js';\nexport * from './dsl.js';\n","/**\n * DSL builder implementations.\n *\n * Each builder wraps a GraphNode and provides the fluent API\n * for constructing the Semantic Application Graph via the DSL.\n *\n * Builders do NOT render anything — they only build the graph.\n */\n\nimport { ApplicationGraph, GraphNode, type Props } from '@streetui/graph';\nimport type {\n ContentDSL,\n ContainerDSL,\n SectionDSL,\n PageDSL,\n FormDSL,\n ListDSL,\n AppDSL,\n HeadingOptions,\n TextOptions,\n ButtonOptions,\n InputOptions,\n LinkOptions,\n ImageOptions,\n ContainerOptions,\n SectionOptions,\n FormOptions,\n ListOptions,\n A11yOptions,\n Bindable,\n BindableText,\n TextValue,\n ErrorBoundaryOptions,\n ErrorSource,\n PageBuilder,\n SectionBuilder,\n ContainerBuilder as ContainerBuilderFn,\n FormBuilder,\n ListBuilder,\n} from './dsl-types.js';\nimport { signal, derived, type Signal, type ReadonlySignal } from '@streetui/state';\n\n// ── Signal helpers ────────────────────────────────────────────────────────────\n\nfunction isSignal(v: unknown): v is Signal<unknown> | ReadonlySignal<unknown> {\n return (\n v !== null &&\n typeof v === 'object' &&\n typeof (v as Record<string, unknown>)['get'] === 'function' &&\n typeof (v as Record<string, unknown>)['subscribe'] === 'function'\n );\n}\n\n/** Register a signal binding on the node and return the current static value. */\nfunction bindValue<T>(\n graph: ApplicationGraph,\n node: GraphNode,\n propKey: string,\n value: Bindable<T>,\n): T {\n if (isSignal(value)) {\n const signalId = `${node.id}:${propKey}`;\n node.stateRefs.push({ signalId, propKey });\n graph.registerHandler(`__signal__${signalId}`, value as unknown as () => unknown);\n return (value as ReadonlySignal<T>).peek();\n }\n return value as T;\n}\n\n// ── Helper to build Props from ContainerOptions ───────────────────────────────\n\n/**\n * Copy accessibility options onto a props bag as their corresponding HTML/ARIA\n * attribute names. Values are written as strings (booleans become \"true\"/\"false\"\n * rather than being dropped) so ARIA state attributes render literally. These\n * flow to the DOM via the renderer's generic attribute pass — no ARIA-specific\n * renderer code is involved.\n */\nfunction applyA11yProps(props: Props, options: A11yOptions): void {\n if (options.role !== undefined) props['role'] = options.role;\n if (options.tabIndex !== undefined) props['tabindex'] = String(options.tabIndex);\n if (options.ariaLabel !== undefined) props['aria-label'] = options.ariaLabel;\n if (options.ariaLabelledBy !== undefined) props['aria-labelledby'] = options.ariaLabelledBy;\n if (options.ariaDescribedBy !== undefined) props['aria-describedby'] = options.ariaDescribedBy;\n if (options.ariaExpanded !== undefined) props['aria-expanded'] = String(options.ariaExpanded);\n if (options.ariaControls !== undefined) props['aria-controls'] = options.ariaControls;\n if (options.ariaHidden !== undefined) props['aria-hidden'] = String(options.ariaHidden);\n if (options.ariaLive !== undefined) props['aria-live'] = options.ariaLive;\n if (options.ariaCurrent !== undefined) props['aria-current'] = String(options.ariaCurrent);\n if (options.ariaInvalid !== undefined) props['aria-invalid'] = String(options.ariaInvalid);\n if (options.ariaRequired !== undefined) props['aria-required'] = String(options.ariaRequired);\n}\n\nfunction containerProps(options: ContainerOptions): Props {\n const props: Props = {};\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n if (options.key !== undefined) props['key'] = options.key;\n applyA11yProps(props, options);\n return props;\n}\n\n// ── Reactive-list item keying ──────────────────────────────────────────────────\n//\n// The `listOf` DSL signature does not take an explicit key extractor, so we\n// derive a stable reconciliation key from each item. The key combines an\n// *identity* part (so reordering the same items reuses their DOM nodes) with a\n// *value signature* (so an item whose data changed is treated as a fresh node\n// and re-rendered rather than silently kept stale by the shallow reconciler).\n\nfunction itemIdentity(item: unknown, index: number): string {\n if (item !== null && typeof item === 'object') {\n const obj = item as Record<string, unknown>;\n if ('id' in obj) return `id:${String(obj['id'])}`;\n if ('key' in obj) return `key:${String(obj['key'])}`;\n return `idx:${index}`;\n }\n return `val:${String(item)}`;\n}\n\nfunction itemValueSignature(item: unknown): string {\n try {\n return JSON.stringify(item) ?? String(item);\n } catch {\n return String(item);\n }\n}\n\n/** Content signature used to detect in-place data changes of a stable item. */\nexport function reactiveListItemSignature(item: unknown): string {\n return itemValueSignature(item);\n}\n\n/** Stable, identity-only reconciliation key for a reactive-list item. */\nexport function reactiveListItemKey(item: unknown, index: number): string {\n return itemIdentity(item, index);\n}\n\n// ── Base content builder ──────────────────────────────────────────────────────\n\nclass ContentBuilderBase implements ContentDSL {\n constructor(\n protected readonly _node: GraphNode,\n protected readonly _graph: ApplicationGraph,\n ) {}\n\n heading(text: BindableText, options: HeadingOptions = {}): void {\n const props: Props = { level: options.level ?? 1 };\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const node = this._graph.createNode('heading', { parent: this._node, props });\n const resolved = bindValue<TextValue>(this._graph, node, 'text', text);\n node.setProp('text', resolved);\n }\n\n text(content: BindableText, options: TextOptions = {}): void {\n const props: Props = {};\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const node = this._graph.createNode('text', { parent: this._node, props });\n const resolved = bindValue<TextValue>(this._graph, node, 'text', content);\n node.setProp('text', resolved);\n }\n\n button(label: BindableText, options: ButtonOptions = {}): void {\n const props: Props = {};\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const node = this._graph.createNode('button', { parent: this._node, props });\n const resolved = bindValue<TextValue>(this._graph, node, 'label', label);\n node.setProp('label', resolved);\n if (options.disabled !== undefined) {\n const resolvedDisabled = bindValue(this._graph, node, 'disabled', options.disabled);\n node.setProp('disabled', resolvedDisabled);\n }\n if (options.onClick !== undefined) {\n const handlerKey = `click:${node.id}`;\n this._graph.registerHandler(handlerKey, options.onClick as () => unknown);\n node.addEvent({ type: 'click', handlerKey });\n }\n }\n\n input(options: InputOptions = {}): void {\n const props: Props = {};\n props['inputType'] = options.type ?? 'text';\n if (options.placeholder !== undefined) props['placeholder'] = options.placeholder;\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const nodeOpts: { key?: string; props: Props; parent: GraphNode } = {\n props,\n parent: this._node,\n };\n if (options.id !== undefined) nodeOpts.key = options.id;\n const node = this._graph.createNode('input', nodeOpts);\n\n // Two-way `bind` expands to a value binding + an input write-back. The type\n // system (BoundInputOptions vs ControlledInputOptions) guarantees `bind` is\n // never combined with explicit `value`/`onInput`, so there is no ambiguity.\n const bindSignal = options.bind;\n const valueBindable: Bindable<string> | undefined =\n bindSignal !== undefined ? bindSignal : options.value;\n const inputHandler: ((value: string) => void) | undefined =\n bindSignal !== undefined ? (v: string) => bindSignal.set(v) : options.onInput;\n\n if (valueBindable !== undefined) {\n const resolved = bindValue(this._graph, node, 'value', valueBindable);\n node.setProp('value', resolved);\n }\n if (options.disabled !== undefined) {\n const resolved = bindValue(this._graph, node, 'disabled', options.disabled);\n node.setProp('disabled', resolved);\n }\n if (inputHandler !== undefined) {\n const handlerKey = `input:${node.id}`;\n this._graph.registerHandler(handlerKey, inputHandler as () => unknown);\n node.addEvent({ type: 'input', handlerKey });\n }\n if (options.onChange !== undefined) {\n const handlerKey = `change:${node.id}`;\n this._graph.registerHandler(handlerKey, options.onChange as () => unknown);\n node.addEvent({ type: 'change', handlerKey });\n }\n }\n\n image(options: ImageOptions): void {\n const props: Props = {\n src: options.src,\n alt: options.alt,\n };\n if (options.width !== undefined) props['width'] = options.width;\n if (options.height !== undefined) props['height'] = options.height;\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const nodeOpts: { key?: string; props: Props; parent: GraphNode } = {\n props,\n parent: this._node,\n };\n if (options.id !== undefined) nodeOpts.key = options.id;\n this._graph.createNode('image', nodeOpts);\n }\n\n link(label: BindableText, options: LinkOptions): void {\n const props: Props = {\n href: options.href,\n external: options.external ?? false,\n };\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const node = this._graph.createNode('link', { parent: this._node, props });\n const resolved = bindValue<TextValue>(this._graph, node, 'label', label);\n node.setProp('label', resolved);\n if (options.onClick !== undefined) {\n const handlerKey = `click:${node.id}`;\n this._graph.registerHandler(handlerKey, options.onClick as () => unknown);\n node.addEvent({ type: 'click', handlerKey });\n }\n }\n}\n\n// ── Container builder ─────────────────────────────────────────────────────────\n\nclass ContainerBuilderBase extends ContentBuilderBase implements ContainerDSL {\n section(key: string, builder: SectionBuilder, options: SectionOptions = {}): void {\n const node = this._graph.createNode('section', {\n key,\n parent: this._node,\n props: containerProps(options),\n });\n builder(new SectionBuilderImpl(node, this._graph));\n }\n\n container(key: string, builder: ContainerBuilderFn, options: ContainerOptions = {}): void {\n const node = this._graph.createNode('container', {\n key,\n parent: this._node,\n props: containerProps(options),\n });\n builder(new ContainerBuilderImpl(node, this._graph));\n }\n\n list(key: string, builder: ListBuilder, options: ListOptions = {}): void {\n const node = this._graph.createNode('list', {\n key,\n parent: this._node,\n props: containerProps(options),\n });\n builder(new ListBuilderImpl(node, this._graph));\n }\n\n listOf<T>(\n key: string,\n items: Signal<T[]> | ReadonlySignal<T[]>,\n renderItem: (item: T, index: number, content: ContentDSL) => void,\n options: ListOptions = {},\n ): void {\n const graph = this._graph;\n const node = graph.createNode('reactive-list', {\n key,\n parent: this._node,\n props: containerProps(options),\n });\n\n // Register the driving signal so the runtime/renderer can subscribe to it.\n const signalId = `${node.id}:items`;\n node.stateRefs.push({ signalId, propKey: 'items' });\n graph.registerHandler(`__signal__${signalId}`, items as unknown as () => unknown);\n\n // Build a single detached list-item subtree for one item. The item's\n // reconciliation `key` is identity-only, and its value signature is stored\n // in the internal `_sig` prop so the renderer can detect (and apply a\n // targeted update for) a data change on an item whose identity is stable.\n const buildItem = (item: T, index: number): GraphNode => {\n const itemKey = reactiveListItemKey(item, index);\n const itemNode = graph.createNode('list-item', {\n key: itemKey,\n props: { key: itemKey, _sig: reactiveListItemSignature(item) },\n });\n renderItem(item, index, new ContainerBuilderImpl(itemNode, graph));\n return itemNode;\n };\n\n // Factory the renderer invokes on every change to produce the desired,\n // freshly-rendered child nodes for the new items array.\n const buildAll = (raw: unknown): GraphNode[] => {\n const arr = Array.isArray(raw) ? (raw as T[]) : [];\n return arr.map((item, i) => buildItem(item, i));\n };\n graph.registerHandler(`__listbuild__${node.id}`, buildAll as unknown as () => unknown);\n\n // Build the initial children into the graph so the first mount renders them.\n const current = isSignal(items)\n ? (items as ReadonlySignal<T[]>).peek()\n : (items as unknown as T[]);\n const initial = Array.isArray(current) ? current : [];\n initial.forEach((item, i) => {\n node.appendChild(buildItem(item, i));\n });\n }\n\n form(key: string, builder: FormBuilder, options: FormOptions = {}): void {\n const props: Props = containerProps(options);\n const node = this._graph.createNode('form', {\n key,\n parent: this._node,\n props,\n });\n if (options.onSubmit !== undefined) {\n const handlerKey = `submit:${node.id}`;\n this._graph.registerHandler(handlerKey, options.onSubmit as () => unknown);\n node.addEvent({ type: 'submit', handlerKey });\n }\n builder(new FormBuilderImpl(node, this._graph));\n }\n\n when(\n condition: Bindable<boolean>,\n builder: ContainerBuilderFn,\n elseBuilder?: ContainerBuilderFn,\n ): void {\n const graph = this._graph;\n // A dedicated 'conditional' node reuses the reactive-list reconciliation\n // machinery (same signal subscription + keyed reconcile) but renders as a\n // neutral <div> rather than a <ul>. It holds zero or one child branch.\n const node = graph.createNode('conditional', {\n parent: this._node,\n props: containerProps({}),\n });\n\n // Build the active branch as a single keyed container. Distinct keys for the\n // then/else branches make a flip a clean swap under the keyed reconciler.\n const buildBranch = (build: ContainerBuilderFn, tag: 'then' | 'else'): GraphNode => {\n const branchKey = `when-${tag}:${node.id}`;\n const branch = graph.createNode('container', {\n key: branchKey,\n props: { key: branchKey },\n });\n build(new ContainerBuilderImpl(branch, graph));\n return branch;\n };\n\n const buildAll = (raw: unknown): GraphNode[] => {\n if (raw) return [buildBranch(builder, 'then')];\n return elseBuilder !== undefined ? [buildBranch(elseBuilder, 'else')] : [];\n };\n\n if (isSignal(condition)) {\n const signalId = `${node.id}:items`;\n node.stateRefs.push({ signalId, propKey: 'items' });\n graph.registerHandler(`__signal__${signalId}`, condition as unknown as () => unknown);\n graph.registerHandler(`__listbuild__${node.id}`, buildAll as unknown as () => unknown);\n const current = (condition as ReadonlySignal<boolean>).peek();\n for (const child of buildAll(current)) node.appendChild(child);\n } else {\n // Static condition — resolve once at build time, no reactive wiring.\n for (const child of buildAll(condition)) node.appendChild(child);\n }\n }\n\n errorBoundary(\n id: string,\n builder: ContainerBuilderFn,\n options: ErrorBoundaryOptions,\n ): void {\n // Normalise the observed error source(s) into an array.\n const sources: ErrorSource[] =\n options.source === undefined\n ? []\n : Array.isArray(options.source)\n ? [...options.source]\n : [options.source];\n\n // The boundary's own captured error (from a synchronous build throw) and a\n // retry nonce that forces a re-evaluation even when the boolean is unchanged.\n const localError = signal<unknown>(undefined);\n const retryNonce = signal<number>(0);\n\n const readError = (): unknown => {\n const local = localError.peek();\n if (local !== undefined && local !== null) return local;\n for (const s of sources) {\n const e = s.peek();\n if (e !== undefined && e !== null) return e;\n }\n return undefined;\n };\n\n // Reactive condition: true while an error is present. Reads every input so a\n // change in any source (or a retry) re-runs the conditional.\n const hasError = derived<boolean>(() => {\n retryNonce.get();\n localError.get();\n for (const s of sources) s.get();\n return readError() !== undefined;\n });\n\n const retry = (): void => {\n localError.set(undefined);\n options.onRetry?.();\n // Force the body branch to re-attempt even if no observed value changed.\n retryNonce.update((n) => n + 1);\n };\n\n // Wrap in a container so the whole boundary is addressable and disposes as a\n // unit. `when` provides the reactive body↔fallback swap (and its cleanup).\n this.container(id, (c) => {\n c.when(\n hasError,\n // Error state → fallback.\n (fb) => options.fallback(fb, readError(), retry),\n // Healthy state → body, guarded against synchronous build throws.\n (body) => {\n try {\n builder(body);\n } catch (err) {\n // Surface the throw as the boundary's error on the next microtask\n // (deferred to avoid re-entrant reconciliation during this build).\n queueMicrotask(() => localError.set(err));\n }\n },\n );\n }, { id });\n }\n}\n\n// ── Concrete builder implementations ─────────────────────────────────────────\n\nexport class SectionBuilderImpl extends ContainerBuilderBase implements SectionDSL {}\nexport class ContainerBuilderImpl extends ContainerBuilderBase implements ContainerDSL {}\nexport class FormBuilderImpl extends ContainerBuilderBase implements FormDSL {}\n\nexport class ListBuilderImpl extends ContentBuilderBase implements ListDSL {\n item(key: string, builder: ContainerBuilderFn, options: ContainerOptions = {}): void {\n const node = this._graph.createNode('list-item', {\n key,\n parent: this._node,\n props: containerProps(options),\n });\n builder(new ContainerBuilderImpl(node, this._graph));\n }\n}\n\nexport class PageBuilderImpl extends ContainerBuilderBase implements PageDSL {}\n\n// ── App builder ───────────────────────────────────────────────────────────────\n\nexport class AppBuilder implements AppDSL {\n constructor(private readonly _graph: ApplicationGraph) {}\n\n page(key: string, builder: PageBuilder): void {\n const node = this._graph.createNode('page', {\n key,\n parent: this._graph.root,\n props: { key },\n });\n builder(new PageBuilderImpl(node, this._graph));\n }\n}\n","/**\n * StreetUI DSL entry point.\n *\n * Usage:\n * import { streetui } from '@streetui/dsl';\n *\n * const app = streetui.app({ name: 'My App' });\n * app.page('home', page => {\n * page.section('hero', section => {\n * section.heading('Welcome');\n * section.button('Click me', { onClick: () => {} });\n * });\n * });\n *\n * const graph = app.build();\n */\n\nimport { ApplicationGraph } from '@streetui/graph';\nimport { AppBuilder } from './builders.js';\n\nexport interface AppOptions {\n readonly name: string;\n readonly version?: string;\n}\n\nexport class StreetApp {\n private readonly _graph: ApplicationGraph;\n private readonly _builder: AppBuilder;\n\n constructor(options: AppOptions) {\n const graphOpts: { name: string; version?: string } = { name: options.name };\n if (options.version !== undefined) graphOpts.version = options.version;\n this._graph = new ApplicationGraph(graphOpts);\n this._builder = new AppBuilder(this._graph);\n }\n\n page(key: string, builder: Parameters<AppBuilder['page']>[1]): this {\n this._builder.page(key, builder);\n return this;\n }\n\n /** Compile to ApplicationGraph — validates and returns the graph. */\n build(): ApplicationGraph {\n const dc = this._graph.validate();\n dc.throwIfErrors();\n return this._graph;\n }\n\n /** Access graph before building (useful for inspection). */\n get graph(): ApplicationGraph {\n return this._graph;\n }\n}\n\nexport interface StreetUI {\n app(options: AppOptions): StreetApp;\n}\n\nexport const streetui: StreetUI = {\n app(options: AppOptions): StreetApp {\n return new StreetApp(options);\n },\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/builders.ts","../src/dsl.ts"],"sourcesContent":["export * from './dsl-types.js';\nexport * from './builders.js';\nexport * from './dsl.js';\n","/**\n * DSL builder implementations.\n *\n * Each builder wraps a GraphNode and provides the fluent API\n * for constructing the Semantic Application Graph via the DSL.\n *\n * Builders do NOT render anything — they only build the graph.\n */\n\nimport { ApplicationGraph, GraphNode, type Props } from '@streetui/graph';\nimport type {\n ContentDSL,\n ContainerDSL,\n SectionDSL,\n PageDSL,\n FormDSL,\n ListDSL,\n AppDSL,\n HeadingOptions,\n TextOptions,\n ButtonOptions,\n InputOptions,\n LinkOptions,\n ImageOptions,\n ContainerOptions,\n SectionOptions,\n FormOptions,\n ListOptions,\n A11yOptions,\n Bindable,\n BindableText,\n TextValue,\n ErrorBoundaryOptions,\n ErrorSource,\n PageBuilder,\n SectionBuilder,\n ContainerBuilder as ContainerBuilderFn,\n FormBuilder,\n ListBuilder,\n} from './dsl-types.js';\nimport { signal, derived, type Signal, type ReadonlySignal } from '@streetui/state';\n\n/**\n * A single reactive-list reconciliation descriptor (spec §15).\n *\n * Emitted by the `__listplan__<nodeId>` handler on every list change. `key` is\n * the item's identity-only reconciliation key (cheap to compute); `item` is the\n * source value *reference* used for identity short-circuiting; `sig()` computes\n * the content signature on demand (only when the reference changed); `build()`\n * materialises the full item subtree on demand (only for new/changed rows).\n */\nexport interface ListPlanEntry {\n readonly key: string;\n readonly item: unknown;\n readonly sig: () => string;\n readonly build: () => GraphNode;\n}\n\n// ── Signal helpers ────────────────────────────────────────────────────────────\n\nfunction isSignal(v: unknown): v is Signal<unknown> | ReadonlySignal<unknown> {\n return (\n v !== null &&\n typeof v === 'object' &&\n typeof (v as Record<string, unknown>)['get'] === 'function' &&\n typeof (v as Record<string, unknown>)['subscribe'] === 'function'\n );\n}\n\n/** Register a signal binding on the node and return the current static value. */\nfunction bindValue<T>(\n graph: ApplicationGraph,\n node: GraphNode,\n propKey: string,\n value: Bindable<T>,\n): T {\n if (isSignal(value)) {\n const signalId = `${node.id}:${propKey}`;\n node.stateRefs.push({ signalId, propKey });\n graph.registerHandler(`__signal__${signalId}`, value as unknown as () => unknown);\n return (value as ReadonlySignal<T>).peek();\n }\n return value as T;\n}\n\n// ── Helper to build Props from ContainerOptions ───────────────────────────────\n\n/**\n * Copy accessibility options onto a props bag as their corresponding HTML/ARIA\n * attribute names. Values are written as strings (booleans become \"true\"/\"false\"\n * rather than being dropped) so ARIA state attributes render literally. These\n * flow to the DOM via the renderer's generic attribute pass — no ARIA-specific\n * renderer code is involved.\n */\nfunction applyA11yProps(props: Props, options: A11yOptions): void {\n if (options.role !== undefined) props['role'] = options.role;\n if (options.tabIndex !== undefined) props['tabindex'] = String(options.tabIndex);\n if (options.ariaLabel !== undefined) props['aria-label'] = options.ariaLabel;\n if (options.ariaLabelledBy !== undefined) props['aria-labelledby'] = options.ariaLabelledBy;\n if (options.ariaDescribedBy !== undefined) props['aria-describedby'] = options.ariaDescribedBy;\n if (options.ariaExpanded !== undefined) props['aria-expanded'] = String(options.ariaExpanded);\n if (options.ariaControls !== undefined) props['aria-controls'] = options.ariaControls;\n if (options.ariaHidden !== undefined) props['aria-hidden'] = String(options.ariaHidden);\n if (options.ariaLive !== undefined) props['aria-live'] = options.ariaLive;\n if (options.ariaCurrent !== undefined) props['aria-current'] = String(options.ariaCurrent);\n if (options.ariaInvalid !== undefined) props['aria-invalid'] = String(options.ariaInvalid);\n if (options.ariaRequired !== undefined) props['aria-required'] = String(options.ariaRequired);\n}\n\nfunction containerProps(options: ContainerOptions): Props {\n const props: Props = {};\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n if (options.key !== undefined) props['key'] = options.key;\n applyA11yProps(props, options);\n return props;\n}\n\n// ── Reactive-list item keying ──────────────────────────────────────────────────\n//\n// The `listOf` DSL signature does not take an explicit key extractor, so we\n// derive a stable reconciliation key from each item. The key combines an\n// *identity* part (so reordering the same items reuses their DOM nodes) with a\n// *value signature* (so an item whose data changed is treated as a fresh node\n// and re-rendered rather than silently kept stale by the shallow reconciler).\n\nfunction itemIdentity(item: unknown, index: number): string {\n if (item !== null && typeof item === 'object') {\n const obj = item as Record<string, unknown>;\n if ('id' in obj) return `id:${String(obj['id'])}`;\n if ('key' in obj) return `key:${String(obj['key'])}`;\n return `idx:${index}`;\n }\n return `val:${String(item)}`;\n}\n\nfunction itemValueSignature(item: unknown): string {\n try {\n return JSON.stringify(item) ?? String(item);\n } catch {\n return String(item);\n }\n}\n\n/** Content signature used to detect in-place data changes of a stable item. */\nexport function reactiveListItemSignature(item: unknown): string {\n return itemValueSignature(item);\n}\n\n/** Stable, identity-only reconciliation key for a reactive-list item. */\nexport function reactiveListItemKey(item: unknown, index: number): string {\n return itemIdentity(item, index);\n}\n\n// ── Base content builder ──────────────────────────────────────────────────────\n\nclass ContentBuilderBase implements ContentDSL {\n constructor(\n protected readonly _node: GraphNode,\n protected readonly _graph: ApplicationGraph,\n ) {}\n\n heading(text: BindableText, options: HeadingOptions = {}): void {\n const props: Props = { level: options.level ?? 1 };\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const node = this._graph.createNode('heading', { parent: this._node, props });\n const resolved = bindValue<TextValue>(this._graph, node, 'text', text);\n node.setProp('text', resolved);\n }\n\n text(content: BindableText, options: TextOptions = {}): void {\n const props: Props = {};\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const node = this._graph.createNode('text', { parent: this._node, props });\n const resolved = bindValue<TextValue>(this._graph, node, 'text', content);\n node.setProp('text', resolved);\n }\n\n button(label: BindableText, options: ButtonOptions = {}): void {\n const props: Props = {};\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const node = this._graph.createNode('button', { parent: this._node, props });\n const resolved = bindValue<TextValue>(this._graph, node, 'label', label);\n node.setProp('label', resolved);\n if (options.disabled !== undefined) {\n const resolvedDisabled = bindValue(this._graph, node, 'disabled', options.disabled);\n node.setProp('disabled', resolvedDisabled);\n }\n if (options.onClick !== undefined) {\n const handlerKey = `click:${node.id}`;\n this._graph.registerHandler(handlerKey, options.onClick as () => unknown);\n node.addEvent({ type: 'click', handlerKey });\n }\n }\n\n input(options: InputOptions = {}): void {\n const props: Props = {};\n props['inputType'] = options.type ?? 'text';\n if (options.placeholder !== undefined) props['placeholder'] = options.placeholder;\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const nodeOpts: { key?: string; props: Props; parent: GraphNode } = {\n props,\n parent: this._node,\n };\n if (options.id !== undefined) nodeOpts.key = options.id;\n const node = this._graph.createNode('input', nodeOpts);\n\n // Two-way `bind` expands to a value binding + an input write-back. The type\n // system (BoundInputOptions vs ControlledInputOptions) guarantees `bind` is\n // never combined with explicit `value`/`onInput`, so there is no ambiguity.\n const bindSignal = options.bind;\n const valueBindable: Bindable<string> | undefined =\n bindSignal !== undefined ? bindSignal : options.value;\n const inputHandler: ((value: string) => void) | undefined =\n bindSignal !== undefined ? (v: string) => bindSignal.set(v) : options.onInput;\n\n if (valueBindable !== undefined) {\n const resolved = bindValue(this._graph, node, 'value', valueBindable);\n node.setProp('value', resolved);\n }\n if (options.disabled !== undefined) {\n const resolved = bindValue(this._graph, node, 'disabled', options.disabled);\n node.setProp('disabled', resolved);\n }\n if (inputHandler !== undefined) {\n const handlerKey = `input:${node.id}`;\n this._graph.registerHandler(handlerKey, inputHandler as () => unknown);\n node.addEvent({ type: 'input', handlerKey });\n }\n if (options.onChange !== undefined) {\n const handlerKey = `change:${node.id}`;\n this._graph.registerHandler(handlerKey, options.onChange as () => unknown);\n node.addEvent({ type: 'change', handlerKey });\n }\n }\n\n image(options: ImageOptions): void {\n const props: Props = {\n src: options.src,\n alt: options.alt,\n };\n if (options.width !== undefined) props['width'] = options.width;\n if (options.height !== undefined) props['height'] = options.height;\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const nodeOpts: { key?: string; props: Props; parent: GraphNode } = {\n props,\n parent: this._node,\n };\n if (options.id !== undefined) nodeOpts.key = options.id;\n this._graph.createNode('image', nodeOpts);\n }\n\n link(label: BindableText, options: LinkOptions): void {\n const props: Props = {\n href: options.href,\n external: options.external ?? false,\n };\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const node = this._graph.createNode('link', { parent: this._node, props });\n const resolved = bindValue<TextValue>(this._graph, node, 'label', label);\n node.setProp('label', resolved);\n if (options.onClick !== undefined) {\n const handlerKey = `click:${node.id}`;\n this._graph.registerHandler(handlerKey, options.onClick as () => unknown);\n node.addEvent({ type: 'click', handlerKey });\n }\n }\n}\n\n// ── Container builder ─────────────────────────────────────────────────────────\n\nclass ContainerBuilderBase extends ContentBuilderBase implements ContainerDSL {\n section(key: string, builder: SectionBuilder, options: SectionOptions = {}): void {\n const node = this._graph.createNode('section', {\n key,\n parent: this._node,\n props: containerProps(options),\n });\n builder(new SectionBuilderImpl(node, this._graph));\n }\n\n container(key: string, builder: ContainerBuilderFn, options: ContainerOptions = {}): void {\n const node = this._graph.createNode('container', {\n key,\n parent: this._node,\n props: containerProps(options),\n });\n builder(new ContainerBuilderImpl(node, this._graph));\n }\n\n list(key: string, builder: ListBuilder, options: ListOptions = {}): void {\n const node = this._graph.createNode('list', {\n key,\n parent: this._node,\n props: containerProps(options),\n });\n builder(new ListBuilderImpl(node, this._graph));\n }\n\n listOf<T>(\n key: string,\n items: Signal<T[]> | ReadonlySignal<T[]>,\n renderItem: (item: T, index: number, content: ContentDSL) => void,\n options: ListOptions = {},\n ): void {\n const graph = this._graph;\n const node = graph.createNode('reactive-list', {\n key,\n parent: this._node,\n props: containerProps(options),\n });\n\n // Register the driving signal so the runtime/renderer can subscribe to it.\n const signalId = `${node.id}:items`;\n node.stateRefs.push({ signalId, propKey: 'items' });\n graph.registerHandler(`__signal__${signalId}`, items as unknown as () => unknown);\n\n // Build a single detached list-item subtree for one item. The item's\n // reconciliation `key` is identity-only, and its value signature is stored\n // in the internal `_sig` prop so the renderer can detect (and apply a\n // targeted update for) a data change on an item whose identity is stable.\n const buildItem = (item: T, index: number): GraphNode => {\n const itemKey = reactiveListItemKey(item, index);\n const itemNode = graph.createNode('list-item', {\n key: itemKey,\n // `_item` records the source item *reference* so the reconciler can\n // short-circuit unchanged rows by identity (no signature hashing); `_sig`\n // is the content signature used to detect an in-place data change when the\n // reference differs. Both are internal metadata (leading `_`) and never\n // reach the DOM.\n props: {\n key: itemKey,\n _sig: reactiveListItemSignature(item),\n // The item reference is stored as opaque internal metadata (never\n // rendered); cast through `unknown` since `T` is not a `PropValue`.\n _item: item as unknown as Props[string],\n },\n });\n renderItem(item, index, new ContainerBuilderImpl(itemNode, graph));\n return itemNode;\n };\n\n // Lazy reconciliation plan (spec §15 — the measured keyed-list hot path).\n //\n // Instead of eagerly rebuilding all N item GraphNodes (and hashing every item\n // with JSON.stringify) on *every* emission — the dominant cost of the old\n // `buildAll` path — the renderer receives lightweight descriptors and only\n // materialises a subtree for rows that are genuinely new or whose data\n // actually changed. `key` is cheap (identity only); `sig()` and `build()` are\n // thunks the reconciler calls on demand.\n const buildPlan = (raw: unknown): ListPlanEntry[] => {\n const arr = Array.isArray(raw) ? (raw as T[]) : [];\n const plan: ListPlanEntry[] = new Array(arr.length);\n for (let i = 0; i < arr.length; i++) {\n const item = arr[i]!;\n const index = i;\n plan[i] = {\n key: reactiveListItemKey(item, index),\n item,\n sig: () => reactiveListItemSignature(item),\n build: () => buildItem(item, index),\n };\n }\n return plan;\n };\n graph.registerHandler(`__listplan__${node.id}`, buildPlan as unknown as () => unknown);\n\n // Build the initial children into the graph so the first mount renders them.\n const current = isSignal(items)\n ? (items as ReadonlySignal<T[]>).peek()\n : (items as unknown as T[]);\n const initial = Array.isArray(current) ? current : [];\n initial.forEach((item, i) => {\n node.appendChild(buildItem(item, i));\n });\n }\n\n form(key: string, builder: FormBuilder, options: FormOptions = {}): void {\n const props: Props = containerProps(options);\n const node = this._graph.createNode('form', {\n key,\n parent: this._node,\n props,\n });\n if (options.onSubmit !== undefined) {\n const handlerKey = `submit:${node.id}`;\n this._graph.registerHandler(handlerKey, options.onSubmit as () => unknown);\n node.addEvent({ type: 'submit', handlerKey });\n }\n builder(new FormBuilderImpl(node, this._graph));\n }\n\n when(\n condition: Bindable<boolean>,\n builder: ContainerBuilderFn,\n elseBuilder?: ContainerBuilderFn,\n ): void {\n const graph = this._graph;\n // A dedicated 'conditional' node reuses the reactive-list reconciliation\n // machinery (same signal subscription + keyed reconcile) but renders as a\n // neutral <div> rather than a <ul>. It holds zero or one child branch.\n const node = graph.createNode('conditional', {\n parent: this._node,\n props: containerProps({}),\n });\n\n // Build the active branch as a single keyed container. Distinct keys for the\n // then/else branches make a flip a clean swap under the keyed reconciler.\n const buildBranch = (build: ContainerBuilderFn, tag: 'then' | 'else'): GraphNode => {\n const branchKey = `when-${tag}:${node.id}`;\n const branch = graph.createNode('container', {\n key: branchKey,\n props: { key: branchKey },\n });\n build(new ContainerBuilderImpl(branch, graph));\n return branch;\n };\n\n const buildAll = (raw: unknown): GraphNode[] => {\n if (raw) return [buildBranch(builder, 'then')];\n return elseBuilder !== undefined ? [buildBranch(elseBuilder, 'else')] : [];\n };\n\n if (isSignal(condition)) {\n const signalId = `${node.id}:items`;\n node.stateRefs.push({ signalId, propKey: 'items' });\n graph.registerHandler(`__signal__${signalId}`, condition as unknown as () => unknown);\n graph.registerHandler(`__listbuild__${node.id}`, buildAll as unknown as () => unknown);\n const current = (condition as ReadonlySignal<boolean>).peek();\n for (const child of buildAll(current)) node.appendChild(child);\n } else {\n // Static condition — resolve once at build time, no reactive wiring.\n for (const child of buildAll(condition)) node.appendChild(child);\n }\n }\n\n errorBoundary(\n id: string,\n builder: ContainerBuilderFn,\n options: ErrorBoundaryOptions,\n ): void {\n // Normalise the observed error source(s) into an array.\n const sources: ErrorSource[] =\n options.source === undefined\n ? []\n : Array.isArray(options.source)\n ? [...options.source]\n : [options.source];\n\n // The boundary's own captured error (from a synchronous build throw) and a\n // retry nonce that forces a re-evaluation even when the boolean is unchanged.\n const localError = signal<unknown>(undefined);\n const retryNonce = signal<number>(0);\n\n const readError = (): unknown => {\n const local = localError.peek();\n if (local !== undefined && local !== null) return local;\n for (const s of sources) {\n const e = s.peek();\n if (e !== undefined && e !== null) return e;\n }\n return undefined;\n };\n\n // Reactive condition: true while an error is present. Reads every input so a\n // change in any source (or a retry) re-runs the conditional.\n const hasError = derived<boolean>(() => {\n retryNonce.get();\n localError.get();\n for (const s of sources) s.get();\n return readError() !== undefined;\n });\n\n const retry = (): void => {\n localError.set(undefined);\n options.onRetry?.();\n // Force the body branch to re-attempt even if no observed value changed.\n retryNonce.update((n) => n + 1);\n };\n\n // Wrap in a container so the whole boundary is addressable and disposes as a\n // unit. `when` provides the reactive body↔fallback swap (and its cleanup).\n this.container(id, (c) => {\n c.when(\n hasError,\n // Error state → fallback.\n (fb) => options.fallback(fb, readError(), retry),\n // Healthy state → body, guarded against synchronous build throws.\n (body) => {\n try {\n builder(body);\n } catch (err) {\n // Surface the throw as the boundary's error on the next microtask\n // (deferred to avoid re-entrant reconciliation during this build).\n queueMicrotask(() => localError.set(err));\n }\n },\n );\n }, { id });\n }\n}\n\n// ── Concrete builder implementations ─────────────────────────────────────────\n\nexport class SectionBuilderImpl extends ContainerBuilderBase implements SectionDSL {}\nexport class ContainerBuilderImpl extends ContainerBuilderBase implements ContainerDSL {}\nexport class FormBuilderImpl extends ContainerBuilderBase implements FormDSL {}\n\nexport class ListBuilderImpl extends ContentBuilderBase implements ListDSL {\n item(key: string, builder: ContainerBuilderFn, options: ContainerOptions = {}): void {\n const node = this._graph.createNode('list-item', {\n key,\n parent: this._node,\n props: containerProps(options),\n });\n builder(new ContainerBuilderImpl(node, this._graph));\n }\n}\n\nexport class PageBuilderImpl extends ContainerBuilderBase implements PageDSL {}\n\n// ── App builder ───────────────────────────────────────────────────────────────\n\nexport class AppBuilder implements AppDSL {\n constructor(private readonly _graph: ApplicationGraph) {}\n\n page(key: string, builder: PageBuilder): void {\n const node = this._graph.createNode('page', {\n key,\n parent: this._graph.root,\n props: { key },\n });\n builder(new PageBuilderImpl(node, this._graph));\n }\n}\n","/**\n * StreetUI DSL entry point.\n *\n * Usage:\n * import { streetui } from '@streetui/dsl';\n *\n * const app = streetui.app({ name: 'My App' });\n * app.page('home', page => {\n * page.section('hero', section => {\n * section.heading('Welcome');\n * section.button('Click me', { onClick: () => {} });\n * });\n * });\n *\n * const graph = app.build();\n */\n\nimport { ApplicationGraph } from '@streetui/graph';\nimport { AppBuilder } from './builders.js';\n\nexport interface AppOptions {\n readonly name: string;\n readonly version?: string;\n}\n\nexport class StreetApp {\n private readonly _graph: ApplicationGraph;\n private readonly _builder: AppBuilder;\n\n constructor(options: AppOptions) {\n const graphOpts: { name: string; version?: string } = { name: options.name };\n if (options.version !== undefined) graphOpts.version = options.version;\n this._graph = new ApplicationGraph(graphOpts);\n this._builder = new AppBuilder(this._graph);\n }\n\n page(key: string, builder: Parameters<AppBuilder['page']>[1]): this {\n this._builder.page(key, builder);\n return this;\n }\n\n /** Compile to ApplicationGraph — validates and returns the graph. */\n build(): ApplicationGraph {\n const dc = this._graph.validate();\n dc.throwIfErrors();\n return this._graph;\n }\n\n /** Access graph before building (useful for inspection). */\n get graph(): ApplicationGraph {\n return this._graph;\n }\n}\n\nexport interface StreetUI {\n app(options: AppOptions): StreetApp;\n}\n\nexport const streetui: StreetUI = {\n app(options: AppOptions): StreetApp {\n return new StreetApp(options);\n },\n};\n"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -198,6 +198,21 @@ interface AppDSL {
198
198
  * Builders do NOT render anything — they only build the graph.
199
199
  */
200
200
 
201
+ /**
202
+ * A single reactive-list reconciliation descriptor (spec §15).
203
+ *
204
+ * Emitted by the `__listplan__<nodeId>` handler on every list change. `key` is
205
+ * the item's identity-only reconciliation key (cheap to compute); `item` is the
206
+ * source value *reference* used for identity short-circuiting; `sig()` computes
207
+ * the content signature on demand (only when the reference changed); `build()`
208
+ * materialises the full item subtree on demand (only for new/changed rows).
209
+ */
210
+ interface ListPlanEntry {
211
+ readonly key: string;
212
+ readonly item: unknown;
213
+ readonly sig: () => string;
214
+ readonly build: () => GraphNode;
215
+ }
201
216
  /** Content signature used to detect in-place data changes of a stable item. */
202
217
  declare function reactiveListItemSignature(item: unknown): string;
203
218
  /** Stable, identity-only reconciliation key for a reactive-list item. */
@@ -275,4 +290,4 @@ interface StreetUI {
275
290
  }
276
291
  declare const streetui: StreetUI;
277
292
 
278
- export { type A11yOptions, AppBuilder, type AppDSL, type AppOptions, type Bindable, type BindableText, type BoundInputOptions, type ButtonOptions, type ContainerBuilder, ContainerBuilderImpl, type ContainerDSL, type ContainerOptions, type ContentDSL, type ControlledInputOptions, type ErrorBoundaryOptions, type ErrorFallbackBuilder, type ErrorSource, type FormBuilder, FormBuilderImpl, type FormDSL, type FormOptions, type HeadingOptions, type ImageOptions, type InputOptions, type InputOptionsBase, type LinkOptions, type ListBuilder, ListBuilderImpl, type ListDSL, type ListOptions, type PageBuilder, PageBuilderImpl, type PageDSL, type SectionBuilder, SectionBuilderImpl, type SectionDSL, type SectionOptions, StreetApp, type StreetUI, type TextOptions, type TextValue, reactiveListItemKey, reactiveListItemSignature, streetui };
293
+ export { type A11yOptions, AppBuilder, type AppDSL, type AppOptions, type Bindable, type BindableText, type BoundInputOptions, type ButtonOptions, type ContainerBuilder, ContainerBuilderImpl, type ContainerDSL, type ContainerOptions, type ContentDSL, type ControlledInputOptions, type ErrorBoundaryOptions, type ErrorFallbackBuilder, type ErrorSource, type FormBuilder, FormBuilderImpl, type FormDSL, type FormOptions, type HeadingOptions, type ImageOptions, type InputOptions, type InputOptionsBase, type LinkOptions, type ListBuilder, ListBuilderImpl, type ListDSL, type ListOptions, type ListPlanEntry, type PageBuilder, PageBuilderImpl, type PageDSL, type SectionBuilder, SectionBuilderImpl, type SectionDSL, type SectionOptions, StreetApp, type StreetUI, type TextOptions, type TextValue, reactiveListItemKey, reactiveListItemSignature, streetui };
package/dist/index.d.ts CHANGED
@@ -198,6 +198,21 @@ interface AppDSL {
198
198
  * Builders do NOT render anything — they only build the graph.
199
199
  */
200
200
 
201
+ /**
202
+ * A single reactive-list reconciliation descriptor (spec §15).
203
+ *
204
+ * Emitted by the `__listplan__<nodeId>` handler on every list change. `key` is
205
+ * the item's identity-only reconciliation key (cheap to compute); `item` is the
206
+ * source value *reference* used for identity short-circuiting; `sig()` computes
207
+ * the content signature on demand (only when the reference changed); `build()`
208
+ * materialises the full item subtree on demand (only for new/changed rows).
209
+ */
210
+ interface ListPlanEntry {
211
+ readonly key: string;
212
+ readonly item: unknown;
213
+ readonly sig: () => string;
214
+ readonly build: () => GraphNode;
215
+ }
201
216
  /** Content signature used to detect in-place data changes of a stable item. */
202
217
  declare function reactiveListItemSignature(item: unknown): string;
203
218
  /** Stable, identity-only reconciliation key for a reactive-list item. */
@@ -275,4 +290,4 @@ interface StreetUI {
275
290
  }
276
291
  declare const streetui: StreetUI;
277
292
 
278
- export { type A11yOptions, AppBuilder, type AppDSL, type AppOptions, type Bindable, type BindableText, type BoundInputOptions, type ButtonOptions, type ContainerBuilder, ContainerBuilderImpl, type ContainerDSL, type ContainerOptions, type ContentDSL, type ControlledInputOptions, type ErrorBoundaryOptions, type ErrorFallbackBuilder, type ErrorSource, type FormBuilder, FormBuilderImpl, type FormDSL, type FormOptions, type HeadingOptions, type ImageOptions, type InputOptions, type InputOptionsBase, type LinkOptions, type ListBuilder, ListBuilderImpl, type ListDSL, type ListOptions, type PageBuilder, PageBuilderImpl, type PageDSL, type SectionBuilder, SectionBuilderImpl, type SectionDSL, type SectionOptions, StreetApp, type StreetUI, type TextOptions, type TextValue, reactiveListItemKey, reactiveListItemSignature, streetui };
293
+ export { type A11yOptions, AppBuilder, type AppDSL, type AppOptions, type Bindable, type BindableText, type BoundInputOptions, type ButtonOptions, type ContainerBuilder, ContainerBuilderImpl, type ContainerDSL, type ContainerOptions, type ContentDSL, type ControlledInputOptions, type ErrorBoundaryOptions, type ErrorFallbackBuilder, type ErrorSource, type FormBuilder, FormBuilderImpl, type FormDSL, type FormOptions, type HeadingOptions, type ImageOptions, type InputOptions, type InputOptionsBase, type LinkOptions, type ListBuilder, ListBuilderImpl, type ListDSL, type ListOptions, type ListPlanEntry, type PageBuilder, PageBuilderImpl, type PageDSL, type SectionBuilder, SectionBuilderImpl, type SectionDSL, type SectionOptions, StreetApp, type StreetUI, type TextOptions, type TextValue, reactiveListItemKey, reactiveListItemSignature, streetui };
package/dist/index.js CHANGED
@@ -206,16 +206,38 @@ var ContainerBuilderBase = class extends ContentBuilderBase {
206
206
  const itemKey = reactiveListItemKey(item, index);
207
207
  const itemNode = graph.createNode("list-item", {
208
208
  key: itemKey,
209
- props: { key: itemKey, _sig: reactiveListItemSignature(item) }
209
+ // `_item` records the source item *reference* so the reconciler can
210
+ // short-circuit unchanged rows by identity (no signature hashing); `_sig`
211
+ // is the content signature used to detect an in-place data change when the
212
+ // reference differs. Both are internal metadata (leading `_`) and never
213
+ // reach the DOM.
214
+ props: {
215
+ key: itemKey,
216
+ _sig: reactiveListItemSignature(item),
217
+ // The item reference is stored as opaque internal metadata (never
218
+ // rendered); cast through `unknown` since `T` is not a `PropValue`.
219
+ _item: item
220
+ }
210
221
  });
211
222
  renderItem(item, index, new ContainerBuilderImpl(itemNode, graph));
212
223
  return itemNode;
213
224
  };
214
- const buildAll = (raw) => {
225
+ const buildPlan = (raw) => {
215
226
  const arr = Array.isArray(raw) ? raw : [];
216
- return arr.map((item, i) => buildItem(item, i));
227
+ const plan = new Array(arr.length);
228
+ for (let i = 0; i < arr.length; i++) {
229
+ const item = arr[i];
230
+ const index = i;
231
+ plan[i] = {
232
+ key: reactiveListItemKey(item, index),
233
+ item,
234
+ sig: () => reactiveListItemSignature(item),
235
+ build: () => buildItem(item, index)
236
+ };
237
+ }
238
+ return plan;
217
239
  };
218
- graph.registerHandler(`__listbuild__${node.id}`, buildAll);
240
+ graph.registerHandler(`__listplan__${node.id}`, buildPlan);
219
241
  const current = isSignal(items) ? items.peek() : items;
220
242
  const initial = Array.isArray(current) ? current : [];
221
243
  initial.forEach((item, i) => {
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/builders.ts","../src/dsl.ts"],"sourcesContent":["/**\n * DSL builder implementations.\n *\n * Each builder wraps a GraphNode and provides the fluent API\n * for constructing the Semantic Application Graph via the DSL.\n *\n * Builders do NOT render anything — they only build the graph.\n */\n\nimport { ApplicationGraph, GraphNode, type Props } from '@streetui/graph';\nimport type {\n ContentDSL,\n ContainerDSL,\n SectionDSL,\n PageDSL,\n FormDSL,\n ListDSL,\n AppDSL,\n HeadingOptions,\n TextOptions,\n ButtonOptions,\n InputOptions,\n LinkOptions,\n ImageOptions,\n ContainerOptions,\n SectionOptions,\n FormOptions,\n ListOptions,\n A11yOptions,\n Bindable,\n BindableText,\n TextValue,\n ErrorBoundaryOptions,\n ErrorSource,\n PageBuilder,\n SectionBuilder,\n ContainerBuilder as ContainerBuilderFn,\n FormBuilder,\n ListBuilder,\n} from './dsl-types.js';\nimport { signal, derived, type Signal, type ReadonlySignal } from '@streetui/state';\n\n// ── Signal helpers ────────────────────────────────────────────────────────────\n\nfunction isSignal(v: unknown): v is Signal<unknown> | ReadonlySignal<unknown> {\n return (\n v !== null &&\n typeof v === 'object' &&\n typeof (v as Record<string, unknown>)['get'] === 'function' &&\n typeof (v as Record<string, unknown>)['subscribe'] === 'function'\n );\n}\n\n/** Register a signal binding on the node and return the current static value. */\nfunction bindValue<T>(\n graph: ApplicationGraph,\n node: GraphNode,\n propKey: string,\n value: Bindable<T>,\n): T {\n if (isSignal(value)) {\n const signalId = `${node.id}:${propKey}`;\n node.stateRefs.push({ signalId, propKey });\n graph.registerHandler(`__signal__${signalId}`, value as unknown as () => unknown);\n return (value as ReadonlySignal<T>).peek();\n }\n return value as T;\n}\n\n// ── Helper to build Props from ContainerOptions ───────────────────────────────\n\n/**\n * Copy accessibility options onto a props bag as their corresponding HTML/ARIA\n * attribute names. Values are written as strings (booleans become \"true\"/\"false\"\n * rather than being dropped) so ARIA state attributes render literally. These\n * flow to the DOM via the renderer's generic attribute pass — no ARIA-specific\n * renderer code is involved.\n */\nfunction applyA11yProps(props: Props, options: A11yOptions): void {\n if (options.role !== undefined) props['role'] = options.role;\n if (options.tabIndex !== undefined) props['tabindex'] = String(options.tabIndex);\n if (options.ariaLabel !== undefined) props['aria-label'] = options.ariaLabel;\n if (options.ariaLabelledBy !== undefined) props['aria-labelledby'] = options.ariaLabelledBy;\n if (options.ariaDescribedBy !== undefined) props['aria-describedby'] = options.ariaDescribedBy;\n if (options.ariaExpanded !== undefined) props['aria-expanded'] = String(options.ariaExpanded);\n if (options.ariaControls !== undefined) props['aria-controls'] = options.ariaControls;\n if (options.ariaHidden !== undefined) props['aria-hidden'] = String(options.ariaHidden);\n if (options.ariaLive !== undefined) props['aria-live'] = options.ariaLive;\n if (options.ariaCurrent !== undefined) props['aria-current'] = String(options.ariaCurrent);\n if (options.ariaInvalid !== undefined) props['aria-invalid'] = String(options.ariaInvalid);\n if (options.ariaRequired !== undefined) props['aria-required'] = String(options.ariaRequired);\n}\n\nfunction containerProps(options: ContainerOptions): Props {\n const props: Props = {};\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n if (options.key !== undefined) props['key'] = options.key;\n applyA11yProps(props, options);\n return props;\n}\n\n// ── Reactive-list item keying ──────────────────────────────────────────────────\n//\n// The `listOf` DSL signature does not take an explicit key extractor, so we\n// derive a stable reconciliation key from each item. The key combines an\n// *identity* part (so reordering the same items reuses their DOM nodes) with a\n// *value signature* (so an item whose data changed is treated as a fresh node\n// and re-rendered rather than silently kept stale by the shallow reconciler).\n\nfunction itemIdentity(item: unknown, index: number): string {\n if (item !== null && typeof item === 'object') {\n const obj = item as Record<string, unknown>;\n if ('id' in obj) return `id:${String(obj['id'])}`;\n if ('key' in obj) return `key:${String(obj['key'])}`;\n return `idx:${index}`;\n }\n return `val:${String(item)}`;\n}\n\nfunction itemValueSignature(item: unknown): string {\n try {\n return JSON.stringify(item) ?? String(item);\n } catch {\n return String(item);\n }\n}\n\n/** Content signature used to detect in-place data changes of a stable item. */\nexport function reactiveListItemSignature(item: unknown): string {\n return itemValueSignature(item);\n}\n\n/** Stable, identity-only reconciliation key for a reactive-list item. */\nexport function reactiveListItemKey(item: unknown, index: number): string {\n return itemIdentity(item, index);\n}\n\n// ── Base content builder ──────────────────────────────────────────────────────\n\nclass ContentBuilderBase implements ContentDSL {\n constructor(\n protected readonly _node: GraphNode,\n protected readonly _graph: ApplicationGraph,\n ) {}\n\n heading(text: BindableText, options: HeadingOptions = {}): void {\n const props: Props = { level: options.level ?? 1 };\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const node = this._graph.createNode('heading', { parent: this._node, props });\n const resolved = bindValue<TextValue>(this._graph, node, 'text', text);\n node.setProp('text', resolved);\n }\n\n text(content: BindableText, options: TextOptions = {}): void {\n const props: Props = {};\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const node = this._graph.createNode('text', { parent: this._node, props });\n const resolved = bindValue<TextValue>(this._graph, node, 'text', content);\n node.setProp('text', resolved);\n }\n\n button(label: BindableText, options: ButtonOptions = {}): void {\n const props: Props = {};\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const node = this._graph.createNode('button', { parent: this._node, props });\n const resolved = bindValue<TextValue>(this._graph, node, 'label', label);\n node.setProp('label', resolved);\n if (options.disabled !== undefined) {\n const resolvedDisabled = bindValue(this._graph, node, 'disabled', options.disabled);\n node.setProp('disabled', resolvedDisabled);\n }\n if (options.onClick !== undefined) {\n const handlerKey = `click:${node.id}`;\n this._graph.registerHandler(handlerKey, options.onClick as () => unknown);\n node.addEvent({ type: 'click', handlerKey });\n }\n }\n\n input(options: InputOptions = {}): void {\n const props: Props = {};\n props['inputType'] = options.type ?? 'text';\n if (options.placeholder !== undefined) props['placeholder'] = options.placeholder;\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const nodeOpts: { key?: string; props: Props; parent: GraphNode } = {\n props,\n parent: this._node,\n };\n if (options.id !== undefined) nodeOpts.key = options.id;\n const node = this._graph.createNode('input', nodeOpts);\n\n // Two-way `bind` expands to a value binding + an input write-back. The type\n // system (BoundInputOptions vs ControlledInputOptions) guarantees `bind` is\n // never combined with explicit `value`/`onInput`, so there is no ambiguity.\n const bindSignal = options.bind;\n const valueBindable: Bindable<string> | undefined =\n bindSignal !== undefined ? bindSignal : options.value;\n const inputHandler: ((value: string) => void) | undefined =\n bindSignal !== undefined ? (v: string) => bindSignal.set(v) : options.onInput;\n\n if (valueBindable !== undefined) {\n const resolved = bindValue(this._graph, node, 'value', valueBindable);\n node.setProp('value', resolved);\n }\n if (options.disabled !== undefined) {\n const resolved = bindValue(this._graph, node, 'disabled', options.disabled);\n node.setProp('disabled', resolved);\n }\n if (inputHandler !== undefined) {\n const handlerKey = `input:${node.id}`;\n this._graph.registerHandler(handlerKey, inputHandler as () => unknown);\n node.addEvent({ type: 'input', handlerKey });\n }\n if (options.onChange !== undefined) {\n const handlerKey = `change:${node.id}`;\n this._graph.registerHandler(handlerKey, options.onChange as () => unknown);\n node.addEvent({ type: 'change', handlerKey });\n }\n }\n\n image(options: ImageOptions): void {\n const props: Props = {\n src: options.src,\n alt: options.alt,\n };\n if (options.width !== undefined) props['width'] = options.width;\n if (options.height !== undefined) props['height'] = options.height;\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const nodeOpts: { key?: string; props: Props; parent: GraphNode } = {\n props,\n parent: this._node,\n };\n if (options.id !== undefined) nodeOpts.key = options.id;\n this._graph.createNode('image', nodeOpts);\n }\n\n link(label: BindableText, options: LinkOptions): void {\n const props: Props = {\n href: options.href,\n external: options.external ?? false,\n };\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const node = this._graph.createNode('link', { parent: this._node, props });\n const resolved = bindValue<TextValue>(this._graph, node, 'label', label);\n node.setProp('label', resolved);\n if (options.onClick !== undefined) {\n const handlerKey = `click:${node.id}`;\n this._graph.registerHandler(handlerKey, options.onClick as () => unknown);\n node.addEvent({ type: 'click', handlerKey });\n }\n }\n}\n\n// ── Container builder ─────────────────────────────────────────────────────────\n\nclass ContainerBuilderBase extends ContentBuilderBase implements ContainerDSL {\n section(key: string, builder: SectionBuilder, options: SectionOptions = {}): void {\n const node = this._graph.createNode('section', {\n key,\n parent: this._node,\n props: containerProps(options),\n });\n builder(new SectionBuilderImpl(node, this._graph));\n }\n\n container(key: string, builder: ContainerBuilderFn, options: ContainerOptions = {}): void {\n const node = this._graph.createNode('container', {\n key,\n parent: this._node,\n props: containerProps(options),\n });\n builder(new ContainerBuilderImpl(node, this._graph));\n }\n\n list(key: string, builder: ListBuilder, options: ListOptions = {}): void {\n const node = this._graph.createNode('list', {\n key,\n parent: this._node,\n props: containerProps(options),\n });\n builder(new ListBuilderImpl(node, this._graph));\n }\n\n listOf<T>(\n key: string,\n items: Signal<T[]> | ReadonlySignal<T[]>,\n renderItem: (item: T, index: number, content: ContentDSL) => void,\n options: ListOptions = {},\n ): void {\n const graph = this._graph;\n const node = graph.createNode('reactive-list', {\n key,\n parent: this._node,\n props: containerProps(options),\n });\n\n // Register the driving signal so the runtime/renderer can subscribe to it.\n const signalId = `${node.id}:items`;\n node.stateRefs.push({ signalId, propKey: 'items' });\n graph.registerHandler(`__signal__${signalId}`, items as unknown as () => unknown);\n\n // Build a single detached list-item subtree for one item. The item's\n // reconciliation `key` is identity-only, and its value signature is stored\n // in the internal `_sig` prop so the renderer can detect (and apply a\n // targeted update for) a data change on an item whose identity is stable.\n const buildItem = (item: T, index: number): GraphNode => {\n const itemKey = reactiveListItemKey(item, index);\n const itemNode = graph.createNode('list-item', {\n key: itemKey,\n props: { key: itemKey, _sig: reactiveListItemSignature(item) },\n });\n renderItem(item, index, new ContainerBuilderImpl(itemNode, graph));\n return itemNode;\n };\n\n // Factory the renderer invokes on every change to produce the desired,\n // freshly-rendered child nodes for the new items array.\n const buildAll = (raw: unknown): GraphNode[] => {\n const arr = Array.isArray(raw) ? (raw as T[]) : [];\n return arr.map((item, i) => buildItem(item, i));\n };\n graph.registerHandler(`__listbuild__${node.id}`, buildAll as unknown as () => unknown);\n\n // Build the initial children into the graph so the first mount renders them.\n const current = isSignal(items)\n ? (items as ReadonlySignal<T[]>).peek()\n : (items as unknown as T[]);\n const initial = Array.isArray(current) ? current : [];\n initial.forEach((item, i) => {\n node.appendChild(buildItem(item, i));\n });\n }\n\n form(key: string, builder: FormBuilder, options: FormOptions = {}): void {\n const props: Props = containerProps(options);\n const node = this._graph.createNode('form', {\n key,\n parent: this._node,\n props,\n });\n if (options.onSubmit !== undefined) {\n const handlerKey = `submit:${node.id}`;\n this._graph.registerHandler(handlerKey, options.onSubmit as () => unknown);\n node.addEvent({ type: 'submit', handlerKey });\n }\n builder(new FormBuilderImpl(node, this._graph));\n }\n\n when(\n condition: Bindable<boolean>,\n builder: ContainerBuilderFn,\n elseBuilder?: ContainerBuilderFn,\n ): void {\n const graph = this._graph;\n // A dedicated 'conditional' node reuses the reactive-list reconciliation\n // machinery (same signal subscription + keyed reconcile) but renders as a\n // neutral <div> rather than a <ul>. It holds zero or one child branch.\n const node = graph.createNode('conditional', {\n parent: this._node,\n props: containerProps({}),\n });\n\n // Build the active branch as a single keyed container. Distinct keys for the\n // then/else branches make a flip a clean swap under the keyed reconciler.\n const buildBranch = (build: ContainerBuilderFn, tag: 'then' | 'else'): GraphNode => {\n const branchKey = `when-${tag}:${node.id}`;\n const branch = graph.createNode('container', {\n key: branchKey,\n props: { key: branchKey },\n });\n build(new ContainerBuilderImpl(branch, graph));\n return branch;\n };\n\n const buildAll = (raw: unknown): GraphNode[] => {\n if (raw) return [buildBranch(builder, 'then')];\n return elseBuilder !== undefined ? [buildBranch(elseBuilder, 'else')] : [];\n };\n\n if (isSignal(condition)) {\n const signalId = `${node.id}:items`;\n node.stateRefs.push({ signalId, propKey: 'items' });\n graph.registerHandler(`__signal__${signalId}`, condition as unknown as () => unknown);\n graph.registerHandler(`__listbuild__${node.id}`, buildAll as unknown as () => unknown);\n const current = (condition as ReadonlySignal<boolean>).peek();\n for (const child of buildAll(current)) node.appendChild(child);\n } else {\n // Static condition — resolve once at build time, no reactive wiring.\n for (const child of buildAll(condition)) node.appendChild(child);\n }\n }\n\n errorBoundary(\n id: string,\n builder: ContainerBuilderFn,\n options: ErrorBoundaryOptions,\n ): void {\n // Normalise the observed error source(s) into an array.\n const sources: ErrorSource[] =\n options.source === undefined\n ? []\n : Array.isArray(options.source)\n ? [...options.source]\n : [options.source];\n\n // The boundary's own captured error (from a synchronous build throw) and a\n // retry nonce that forces a re-evaluation even when the boolean is unchanged.\n const localError = signal<unknown>(undefined);\n const retryNonce = signal<number>(0);\n\n const readError = (): unknown => {\n const local = localError.peek();\n if (local !== undefined && local !== null) return local;\n for (const s of sources) {\n const e = s.peek();\n if (e !== undefined && e !== null) return e;\n }\n return undefined;\n };\n\n // Reactive condition: true while an error is present. Reads every input so a\n // change in any source (or a retry) re-runs the conditional.\n const hasError = derived<boolean>(() => {\n retryNonce.get();\n localError.get();\n for (const s of sources) s.get();\n return readError() !== undefined;\n });\n\n const retry = (): void => {\n localError.set(undefined);\n options.onRetry?.();\n // Force the body branch to re-attempt even if no observed value changed.\n retryNonce.update((n) => n + 1);\n };\n\n // Wrap in a container so the whole boundary is addressable and disposes as a\n // unit. `when` provides the reactive body↔fallback swap (and its cleanup).\n this.container(id, (c) => {\n c.when(\n hasError,\n // Error state → fallback.\n (fb) => options.fallback(fb, readError(), retry),\n // Healthy state → body, guarded against synchronous build throws.\n (body) => {\n try {\n builder(body);\n } catch (err) {\n // Surface the throw as the boundary's error on the next microtask\n // (deferred to avoid re-entrant reconciliation during this build).\n queueMicrotask(() => localError.set(err));\n }\n },\n );\n }, { id });\n }\n}\n\n// ── Concrete builder implementations ─────────────────────────────────────────\n\nexport class SectionBuilderImpl extends ContainerBuilderBase implements SectionDSL {}\nexport class ContainerBuilderImpl extends ContainerBuilderBase implements ContainerDSL {}\nexport class FormBuilderImpl extends ContainerBuilderBase implements FormDSL {}\n\nexport class ListBuilderImpl extends ContentBuilderBase implements ListDSL {\n item(key: string, builder: ContainerBuilderFn, options: ContainerOptions = {}): void {\n const node = this._graph.createNode('list-item', {\n key,\n parent: this._node,\n props: containerProps(options),\n });\n builder(new ContainerBuilderImpl(node, this._graph));\n }\n}\n\nexport class PageBuilderImpl extends ContainerBuilderBase implements PageDSL {}\n\n// ── App builder ───────────────────────────────────────────────────────────────\n\nexport class AppBuilder implements AppDSL {\n constructor(private readonly _graph: ApplicationGraph) {}\n\n page(key: string, builder: PageBuilder): void {\n const node = this._graph.createNode('page', {\n key,\n parent: this._graph.root,\n props: { key },\n });\n builder(new PageBuilderImpl(node, this._graph));\n }\n}\n","/**\n * StreetUI DSL entry point.\n *\n * Usage:\n * import { streetui } from '@streetui/dsl';\n *\n * const app = streetui.app({ name: 'My App' });\n * app.page('home', page => {\n * page.section('hero', section => {\n * section.heading('Welcome');\n * section.button('Click me', { onClick: () => {} });\n * });\n * });\n *\n * const graph = app.build();\n */\n\nimport { ApplicationGraph } from '@streetui/graph';\nimport { AppBuilder } from './builders.js';\n\nexport interface AppOptions {\n readonly name: string;\n readonly version?: string;\n}\n\nexport class StreetApp {\n private readonly _graph: ApplicationGraph;\n private readonly _builder: AppBuilder;\n\n constructor(options: AppOptions) {\n const graphOpts: { name: string; version?: string } = { name: options.name };\n if (options.version !== undefined) graphOpts.version = options.version;\n this._graph = new ApplicationGraph(graphOpts);\n this._builder = new AppBuilder(this._graph);\n }\n\n page(key: string, builder: Parameters<AppBuilder['page']>[1]): this {\n this._builder.page(key, builder);\n return this;\n }\n\n /** Compile to ApplicationGraph — validates and returns the graph. */\n build(): ApplicationGraph {\n const dc = this._graph.validate();\n dc.throwIfErrors();\n return this._graph;\n }\n\n /** Access graph before building (useful for inspection). */\n get graph(): ApplicationGraph {\n return this._graph;\n }\n}\n\nexport interface StreetUI {\n app(options: AppOptions): StreetApp;\n}\n\nexport const streetui: StreetUI = {\n app(options: AppOptions): StreetApp {\n return new StreetApp(options);\n },\n};\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/builders.ts","../src/dsl.ts"],"sourcesContent":["/**\n * DSL builder implementations.\n *\n * Each builder wraps a GraphNode and provides the fluent API\n * for constructing the Semantic Application Graph via the DSL.\n *\n * Builders do NOT render anything — they only build the graph.\n */\n\nimport { ApplicationGraph, GraphNode, type Props } from '@streetui/graph';\nimport type {\n ContentDSL,\n ContainerDSL,\n SectionDSL,\n PageDSL,\n FormDSL,\n ListDSL,\n AppDSL,\n HeadingOptions,\n TextOptions,\n ButtonOptions,\n InputOptions,\n LinkOptions,\n ImageOptions,\n ContainerOptions,\n SectionOptions,\n FormOptions,\n ListOptions,\n A11yOptions,\n Bindable,\n BindableText,\n TextValue,\n ErrorBoundaryOptions,\n ErrorSource,\n PageBuilder,\n SectionBuilder,\n ContainerBuilder as ContainerBuilderFn,\n FormBuilder,\n ListBuilder,\n} from './dsl-types.js';\nimport { signal, derived, type Signal, type ReadonlySignal } from '@streetui/state';\n\n/**\n * A single reactive-list reconciliation descriptor (spec §15).\n *\n * Emitted by the `__listplan__<nodeId>` handler on every list change. `key` is\n * the item's identity-only reconciliation key (cheap to compute); `item` is the\n * source value *reference* used for identity short-circuiting; `sig()` computes\n * the content signature on demand (only when the reference changed); `build()`\n * materialises the full item subtree on demand (only for new/changed rows).\n */\nexport interface ListPlanEntry {\n readonly key: string;\n readonly item: unknown;\n readonly sig: () => string;\n readonly build: () => GraphNode;\n}\n\n// ── Signal helpers ────────────────────────────────────────────────────────────\n\nfunction isSignal(v: unknown): v is Signal<unknown> | ReadonlySignal<unknown> {\n return (\n v !== null &&\n typeof v === 'object' &&\n typeof (v as Record<string, unknown>)['get'] === 'function' &&\n typeof (v as Record<string, unknown>)['subscribe'] === 'function'\n );\n}\n\n/** Register a signal binding on the node and return the current static value. */\nfunction bindValue<T>(\n graph: ApplicationGraph,\n node: GraphNode,\n propKey: string,\n value: Bindable<T>,\n): T {\n if (isSignal(value)) {\n const signalId = `${node.id}:${propKey}`;\n node.stateRefs.push({ signalId, propKey });\n graph.registerHandler(`__signal__${signalId}`, value as unknown as () => unknown);\n return (value as ReadonlySignal<T>).peek();\n }\n return value as T;\n}\n\n// ── Helper to build Props from ContainerOptions ───────────────────────────────\n\n/**\n * Copy accessibility options onto a props bag as their corresponding HTML/ARIA\n * attribute names. Values are written as strings (booleans become \"true\"/\"false\"\n * rather than being dropped) so ARIA state attributes render literally. These\n * flow to the DOM via the renderer's generic attribute pass — no ARIA-specific\n * renderer code is involved.\n */\nfunction applyA11yProps(props: Props, options: A11yOptions): void {\n if (options.role !== undefined) props['role'] = options.role;\n if (options.tabIndex !== undefined) props['tabindex'] = String(options.tabIndex);\n if (options.ariaLabel !== undefined) props['aria-label'] = options.ariaLabel;\n if (options.ariaLabelledBy !== undefined) props['aria-labelledby'] = options.ariaLabelledBy;\n if (options.ariaDescribedBy !== undefined) props['aria-describedby'] = options.ariaDescribedBy;\n if (options.ariaExpanded !== undefined) props['aria-expanded'] = String(options.ariaExpanded);\n if (options.ariaControls !== undefined) props['aria-controls'] = options.ariaControls;\n if (options.ariaHidden !== undefined) props['aria-hidden'] = String(options.ariaHidden);\n if (options.ariaLive !== undefined) props['aria-live'] = options.ariaLive;\n if (options.ariaCurrent !== undefined) props['aria-current'] = String(options.ariaCurrent);\n if (options.ariaInvalid !== undefined) props['aria-invalid'] = String(options.ariaInvalid);\n if (options.ariaRequired !== undefined) props['aria-required'] = String(options.ariaRequired);\n}\n\nfunction containerProps(options: ContainerOptions): Props {\n const props: Props = {};\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n if (options.key !== undefined) props['key'] = options.key;\n applyA11yProps(props, options);\n return props;\n}\n\n// ── Reactive-list item keying ──────────────────────────────────────────────────\n//\n// The `listOf` DSL signature does not take an explicit key extractor, so we\n// derive a stable reconciliation key from each item. The key combines an\n// *identity* part (so reordering the same items reuses their DOM nodes) with a\n// *value signature* (so an item whose data changed is treated as a fresh node\n// and re-rendered rather than silently kept stale by the shallow reconciler).\n\nfunction itemIdentity(item: unknown, index: number): string {\n if (item !== null && typeof item === 'object') {\n const obj = item as Record<string, unknown>;\n if ('id' in obj) return `id:${String(obj['id'])}`;\n if ('key' in obj) return `key:${String(obj['key'])}`;\n return `idx:${index}`;\n }\n return `val:${String(item)}`;\n}\n\nfunction itemValueSignature(item: unknown): string {\n try {\n return JSON.stringify(item) ?? String(item);\n } catch {\n return String(item);\n }\n}\n\n/** Content signature used to detect in-place data changes of a stable item. */\nexport function reactiveListItemSignature(item: unknown): string {\n return itemValueSignature(item);\n}\n\n/** Stable, identity-only reconciliation key for a reactive-list item. */\nexport function reactiveListItemKey(item: unknown, index: number): string {\n return itemIdentity(item, index);\n}\n\n// ── Base content builder ──────────────────────────────────────────────────────\n\nclass ContentBuilderBase implements ContentDSL {\n constructor(\n protected readonly _node: GraphNode,\n protected readonly _graph: ApplicationGraph,\n ) {}\n\n heading(text: BindableText, options: HeadingOptions = {}): void {\n const props: Props = { level: options.level ?? 1 };\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const node = this._graph.createNode('heading', { parent: this._node, props });\n const resolved = bindValue<TextValue>(this._graph, node, 'text', text);\n node.setProp('text', resolved);\n }\n\n text(content: BindableText, options: TextOptions = {}): void {\n const props: Props = {};\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const node = this._graph.createNode('text', { parent: this._node, props });\n const resolved = bindValue<TextValue>(this._graph, node, 'text', content);\n node.setProp('text', resolved);\n }\n\n button(label: BindableText, options: ButtonOptions = {}): void {\n const props: Props = {};\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const node = this._graph.createNode('button', { parent: this._node, props });\n const resolved = bindValue<TextValue>(this._graph, node, 'label', label);\n node.setProp('label', resolved);\n if (options.disabled !== undefined) {\n const resolvedDisabled = bindValue(this._graph, node, 'disabled', options.disabled);\n node.setProp('disabled', resolvedDisabled);\n }\n if (options.onClick !== undefined) {\n const handlerKey = `click:${node.id}`;\n this._graph.registerHandler(handlerKey, options.onClick as () => unknown);\n node.addEvent({ type: 'click', handlerKey });\n }\n }\n\n input(options: InputOptions = {}): void {\n const props: Props = {};\n props['inputType'] = options.type ?? 'text';\n if (options.placeholder !== undefined) props['placeholder'] = options.placeholder;\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const nodeOpts: { key?: string; props: Props; parent: GraphNode } = {\n props,\n parent: this._node,\n };\n if (options.id !== undefined) nodeOpts.key = options.id;\n const node = this._graph.createNode('input', nodeOpts);\n\n // Two-way `bind` expands to a value binding + an input write-back. The type\n // system (BoundInputOptions vs ControlledInputOptions) guarantees `bind` is\n // never combined with explicit `value`/`onInput`, so there is no ambiguity.\n const bindSignal = options.bind;\n const valueBindable: Bindable<string> | undefined =\n bindSignal !== undefined ? bindSignal : options.value;\n const inputHandler: ((value: string) => void) | undefined =\n bindSignal !== undefined ? (v: string) => bindSignal.set(v) : options.onInput;\n\n if (valueBindable !== undefined) {\n const resolved = bindValue(this._graph, node, 'value', valueBindable);\n node.setProp('value', resolved);\n }\n if (options.disabled !== undefined) {\n const resolved = bindValue(this._graph, node, 'disabled', options.disabled);\n node.setProp('disabled', resolved);\n }\n if (inputHandler !== undefined) {\n const handlerKey = `input:${node.id}`;\n this._graph.registerHandler(handlerKey, inputHandler as () => unknown);\n node.addEvent({ type: 'input', handlerKey });\n }\n if (options.onChange !== undefined) {\n const handlerKey = `change:${node.id}`;\n this._graph.registerHandler(handlerKey, options.onChange as () => unknown);\n node.addEvent({ type: 'change', handlerKey });\n }\n }\n\n image(options: ImageOptions): void {\n const props: Props = {\n src: options.src,\n alt: options.alt,\n };\n if (options.width !== undefined) props['width'] = options.width;\n if (options.height !== undefined) props['height'] = options.height;\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const nodeOpts: { key?: string; props: Props; parent: GraphNode } = {\n props,\n parent: this._node,\n };\n if (options.id !== undefined) nodeOpts.key = options.id;\n this._graph.createNode('image', nodeOpts);\n }\n\n link(label: BindableText, options: LinkOptions): void {\n const props: Props = {\n href: options.href,\n external: options.external ?? false,\n };\n if (options.class !== undefined) props['class'] = options.class;\n if (options.id !== undefined) props['id'] = options.id;\n applyA11yProps(props, options);\n const node = this._graph.createNode('link', { parent: this._node, props });\n const resolved = bindValue<TextValue>(this._graph, node, 'label', label);\n node.setProp('label', resolved);\n if (options.onClick !== undefined) {\n const handlerKey = `click:${node.id}`;\n this._graph.registerHandler(handlerKey, options.onClick as () => unknown);\n node.addEvent({ type: 'click', handlerKey });\n }\n }\n}\n\n// ── Container builder ─────────────────────────────────────────────────────────\n\nclass ContainerBuilderBase extends ContentBuilderBase implements ContainerDSL {\n section(key: string, builder: SectionBuilder, options: SectionOptions = {}): void {\n const node = this._graph.createNode('section', {\n key,\n parent: this._node,\n props: containerProps(options),\n });\n builder(new SectionBuilderImpl(node, this._graph));\n }\n\n container(key: string, builder: ContainerBuilderFn, options: ContainerOptions = {}): void {\n const node = this._graph.createNode('container', {\n key,\n parent: this._node,\n props: containerProps(options),\n });\n builder(new ContainerBuilderImpl(node, this._graph));\n }\n\n list(key: string, builder: ListBuilder, options: ListOptions = {}): void {\n const node = this._graph.createNode('list', {\n key,\n parent: this._node,\n props: containerProps(options),\n });\n builder(new ListBuilderImpl(node, this._graph));\n }\n\n listOf<T>(\n key: string,\n items: Signal<T[]> | ReadonlySignal<T[]>,\n renderItem: (item: T, index: number, content: ContentDSL) => void,\n options: ListOptions = {},\n ): void {\n const graph = this._graph;\n const node = graph.createNode('reactive-list', {\n key,\n parent: this._node,\n props: containerProps(options),\n });\n\n // Register the driving signal so the runtime/renderer can subscribe to it.\n const signalId = `${node.id}:items`;\n node.stateRefs.push({ signalId, propKey: 'items' });\n graph.registerHandler(`__signal__${signalId}`, items as unknown as () => unknown);\n\n // Build a single detached list-item subtree for one item. The item's\n // reconciliation `key` is identity-only, and its value signature is stored\n // in the internal `_sig` prop so the renderer can detect (and apply a\n // targeted update for) a data change on an item whose identity is stable.\n const buildItem = (item: T, index: number): GraphNode => {\n const itemKey = reactiveListItemKey(item, index);\n const itemNode = graph.createNode('list-item', {\n key: itemKey,\n // `_item` records the source item *reference* so the reconciler can\n // short-circuit unchanged rows by identity (no signature hashing); `_sig`\n // is the content signature used to detect an in-place data change when the\n // reference differs. Both are internal metadata (leading `_`) and never\n // reach the DOM.\n props: {\n key: itemKey,\n _sig: reactiveListItemSignature(item),\n // The item reference is stored as opaque internal metadata (never\n // rendered); cast through `unknown` since `T` is not a `PropValue`.\n _item: item as unknown as Props[string],\n },\n });\n renderItem(item, index, new ContainerBuilderImpl(itemNode, graph));\n return itemNode;\n };\n\n // Lazy reconciliation plan (spec §15 — the measured keyed-list hot path).\n //\n // Instead of eagerly rebuilding all N item GraphNodes (and hashing every item\n // with JSON.stringify) on *every* emission — the dominant cost of the old\n // `buildAll` path — the renderer receives lightweight descriptors and only\n // materialises a subtree for rows that are genuinely new or whose data\n // actually changed. `key` is cheap (identity only); `sig()` and `build()` are\n // thunks the reconciler calls on demand.\n const buildPlan = (raw: unknown): ListPlanEntry[] => {\n const arr = Array.isArray(raw) ? (raw as T[]) : [];\n const plan: ListPlanEntry[] = new Array(arr.length);\n for (let i = 0; i < arr.length; i++) {\n const item = arr[i]!;\n const index = i;\n plan[i] = {\n key: reactiveListItemKey(item, index),\n item,\n sig: () => reactiveListItemSignature(item),\n build: () => buildItem(item, index),\n };\n }\n return plan;\n };\n graph.registerHandler(`__listplan__${node.id}`, buildPlan as unknown as () => unknown);\n\n // Build the initial children into the graph so the first mount renders them.\n const current = isSignal(items)\n ? (items as ReadonlySignal<T[]>).peek()\n : (items as unknown as T[]);\n const initial = Array.isArray(current) ? current : [];\n initial.forEach((item, i) => {\n node.appendChild(buildItem(item, i));\n });\n }\n\n form(key: string, builder: FormBuilder, options: FormOptions = {}): void {\n const props: Props = containerProps(options);\n const node = this._graph.createNode('form', {\n key,\n parent: this._node,\n props,\n });\n if (options.onSubmit !== undefined) {\n const handlerKey = `submit:${node.id}`;\n this._graph.registerHandler(handlerKey, options.onSubmit as () => unknown);\n node.addEvent({ type: 'submit', handlerKey });\n }\n builder(new FormBuilderImpl(node, this._graph));\n }\n\n when(\n condition: Bindable<boolean>,\n builder: ContainerBuilderFn,\n elseBuilder?: ContainerBuilderFn,\n ): void {\n const graph = this._graph;\n // A dedicated 'conditional' node reuses the reactive-list reconciliation\n // machinery (same signal subscription + keyed reconcile) but renders as a\n // neutral <div> rather than a <ul>. It holds zero or one child branch.\n const node = graph.createNode('conditional', {\n parent: this._node,\n props: containerProps({}),\n });\n\n // Build the active branch as a single keyed container. Distinct keys for the\n // then/else branches make a flip a clean swap under the keyed reconciler.\n const buildBranch = (build: ContainerBuilderFn, tag: 'then' | 'else'): GraphNode => {\n const branchKey = `when-${tag}:${node.id}`;\n const branch = graph.createNode('container', {\n key: branchKey,\n props: { key: branchKey },\n });\n build(new ContainerBuilderImpl(branch, graph));\n return branch;\n };\n\n const buildAll = (raw: unknown): GraphNode[] => {\n if (raw) return [buildBranch(builder, 'then')];\n return elseBuilder !== undefined ? [buildBranch(elseBuilder, 'else')] : [];\n };\n\n if (isSignal(condition)) {\n const signalId = `${node.id}:items`;\n node.stateRefs.push({ signalId, propKey: 'items' });\n graph.registerHandler(`__signal__${signalId}`, condition as unknown as () => unknown);\n graph.registerHandler(`__listbuild__${node.id}`, buildAll as unknown as () => unknown);\n const current = (condition as ReadonlySignal<boolean>).peek();\n for (const child of buildAll(current)) node.appendChild(child);\n } else {\n // Static condition — resolve once at build time, no reactive wiring.\n for (const child of buildAll(condition)) node.appendChild(child);\n }\n }\n\n errorBoundary(\n id: string,\n builder: ContainerBuilderFn,\n options: ErrorBoundaryOptions,\n ): void {\n // Normalise the observed error source(s) into an array.\n const sources: ErrorSource[] =\n options.source === undefined\n ? []\n : Array.isArray(options.source)\n ? [...options.source]\n : [options.source];\n\n // The boundary's own captured error (from a synchronous build throw) and a\n // retry nonce that forces a re-evaluation even when the boolean is unchanged.\n const localError = signal<unknown>(undefined);\n const retryNonce = signal<number>(0);\n\n const readError = (): unknown => {\n const local = localError.peek();\n if (local !== undefined && local !== null) return local;\n for (const s of sources) {\n const e = s.peek();\n if (e !== undefined && e !== null) return e;\n }\n return undefined;\n };\n\n // Reactive condition: true while an error is present. Reads every input so a\n // change in any source (or a retry) re-runs the conditional.\n const hasError = derived<boolean>(() => {\n retryNonce.get();\n localError.get();\n for (const s of sources) s.get();\n return readError() !== undefined;\n });\n\n const retry = (): void => {\n localError.set(undefined);\n options.onRetry?.();\n // Force the body branch to re-attempt even if no observed value changed.\n retryNonce.update((n) => n + 1);\n };\n\n // Wrap in a container so the whole boundary is addressable and disposes as a\n // unit. `when` provides the reactive body↔fallback swap (and its cleanup).\n this.container(id, (c) => {\n c.when(\n hasError,\n // Error state → fallback.\n (fb) => options.fallback(fb, readError(), retry),\n // Healthy state → body, guarded against synchronous build throws.\n (body) => {\n try {\n builder(body);\n } catch (err) {\n // Surface the throw as the boundary's error on the next microtask\n // (deferred to avoid re-entrant reconciliation during this build).\n queueMicrotask(() => localError.set(err));\n }\n },\n );\n }, { id });\n }\n}\n\n// ── Concrete builder implementations ─────────────────────────────────────────\n\nexport class SectionBuilderImpl extends ContainerBuilderBase implements SectionDSL {}\nexport class ContainerBuilderImpl extends ContainerBuilderBase implements ContainerDSL {}\nexport class FormBuilderImpl extends ContainerBuilderBase implements FormDSL {}\n\nexport class ListBuilderImpl extends ContentBuilderBase implements ListDSL {\n item(key: string, builder: ContainerBuilderFn, options: ContainerOptions = {}): void {\n const node = this._graph.createNode('list-item', {\n key,\n parent: this._node,\n props: containerProps(options),\n });\n builder(new ContainerBuilderImpl(node, this._graph));\n }\n}\n\nexport class PageBuilderImpl extends ContainerBuilderBase implements PageDSL {}\n\n// ── App builder ───────────────────────────────────────────────────────────────\n\nexport class AppBuilder implements AppDSL {\n constructor(private readonly _graph: ApplicationGraph) {}\n\n page(key: string, builder: PageBuilder): void {\n const node = this._graph.createNode('page', {\n key,\n parent: this._graph.root,\n props: { key },\n });\n builder(new PageBuilderImpl(node, this._graph));\n }\n}\n","/**\n * StreetUI DSL entry point.\n *\n * Usage:\n * import { streetui } from '@streetui/dsl';\n *\n * const app = streetui.app({ name: 'My App' });\n * app.page('home', page => {\n * page.section('hero', section => {\n * section.heading('Welcome');\n * section.button('Click me', { onClick: () => {} });\n * });\n * });\n *\n * const graph = app.build();\n */\n\nimport { ApplicationGraph } from '@streetui/graph';\nimport { AppBuilder } from './builders.js';\n\nexport interface AppOptions {\n readonly name: string;\n readonly version?: string;\n}\n\nexport class StreetApp {\n private readonly _graph: ApplicationGraph;\n private readonly _builder: AppBuilder;\n\n constructor(options: AppOptions) {\n const graphOpts: { name: string; version?: string } = { name: options.name };\n if (options.version !== undefined) graphOpts.version = options.version;\n this._graph = new ApplicationGraph(graphOpts);\n this._builder = new AppBuilder(this._graph);\n }\n\n page(key: string, builder: Parameters<AppBuilder['page']>[1]): this {\n this._builder.page(key, builder);\n return this;\n }\n\n /** Compile to ApplicationGraph — validates and returns the graph. */\n build(): ApplicationGraph {\n const dc = this._graph.validate();\n dc.throwIfErrors();\n return this._graph;\n }\n\n /** Access graph before building (useful for inspection). */\n get graph(): ApplicationGraph {\n return this._graph;\n }\n}\n\nexport interface StreetUI {\n app(options: AppOptions): StreetApp;\n}\n\nexport const streetui: StreetUI = {\n app(options: AppOptions): StreetApp {\n return new StreetApp(options);\n },\n};\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streetui/dsl",
3
- "version": "1.0.0",
3
+ "version": "1.3.0",
4
4
  "description": "StreetUI semantic TypeScript DSL",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -25,9 +25,9 @@
25
25
  "clean": "rm -rf dist"
26
26
  },
27
27
  "dependencies": {
28
- "@streetui/core": "1.0.0",
29
- "@streetui/graph": "1.0.0",
30
- "@streetui/state": "1.0.0"
28
+ "@streetui/core": "1.3.0",
29
+ "@streetui/graph": "1.3.0",
30
+ "@streetui/state": "1.3.0"
31
31
  },
32
32
  "devDependencies": {
33
33
  "typescript": "*",