streetui 1.6.1 → 1.7.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.d.cts CHANGED
@@ -1,9 +1,9 @@
1
- import { a as Signal, b as Subscriber, U as Unsubscribe, R as ReadonlySignal, A as ApplicationId, D as DiagnosticCollector, c as ApplicationGraph, G as GraphNode, C as CompiledApplication, d as SemanticNodeType, P as PageDSL, e as ContainerDSL, f as SignalKind } from './compile-CEom4hkp.cjs';
2
- export { g as A11yOptions, h as AppBuilder, i as AppDSL, j as AppOptions, k as ApplicationGraphOptions, B as BaseNode, l as Bindable, m as BindableText, n as BoundInputOptions, o as ButtonOptions, p as CompileOptions, q as ContainerBuilder, r as ContainerBuilderImpl, s as ContainerOptions, t as ContentDSL, u as ControlledInputOptions, v as DerivedSignal, w as Diagnostic, x as DiagnosticError, y as DiagnosticLocation, z as DiagnosticSeverity, E as ErrorBoundaryOptions, F as ErrorFallbackBuilder, H as ErrorSource, I as EventDescriptor, J as FormBuilder, K as FormBuilderImpl, L as FormDSL, M as FormOptions, N as GraphNodeData, O as HandlerFn, Q as HeadingOptions, T as ImageOptions, W as InputOptions, X as InputOptionsBase, Y as LinkOptions, Z as ListBuilder, _ as ListBuilderImpl, $ as ListDSL, a0 as ListOptions, a1 as ListPlanEntry, a2 as NodeId, a3 as NodeMetadata, a4 as PageBuilder, a5 as PageBuilderImpl, a6 as PropValue, a7 as Props, a8 as ReactiveConsumer, a9 as ReactiveSource, aa as SectionBuilder, ab as SectionBuilderImpl, ac as SectionDSL, ad as SectionOptions, ae as SerializedGraph, af as SerializedNode, ag as StateRef, S as StreetApp, ah as StreetUI, ai as TextOptions, aj as TextValue, V as VERSION, ak as batch, al as compile, am as compileGraph, an as createNodeId, ao as derived, ap as effect, aq as formatDiagnostic, ar as generateApplicationId, as as generateNodeId, at as isBatching, au as nextId, av as nodeIdPrefix, aw as observerCount, ax as reactiveListItemKey, ay as reactiveListItemSignature, az as resetIdCounter, aA as signal, aB as signalKind, aC as streetui } from './compile-CEom4hkp.cjs';
3
- import { R as RenderHandle, S as StreetRenderer, a as HydrationDiagnosticSink } from './hydration-diagnostics-D286jpZZ.cjs';
4
- export { H as HydrationDiagnostic, b as HydrationMismatchType, c as consoleHydrationDiagnosticSink, d as createHydrationDiagnosticCollector, f as formatHydrationDiagnostic } from './hydration-diagnostics-D286jpZZ.cjs';
5
- import { D as DOMAdapter } from './server-ZBh5DO-z.cjs';
6
- export { R as RenderToStringOptions, S as STATE_MARKER_ATTR, a as ServerDOMAdapter, r as readState, b as renderToString, s as serializeState, c as serverDOMAdapter } from './server-ZBh5DO-z.cjs';
1
+ import { a as Signal, b as Subscriber, U as Unsubscribe, R as ReadonlySignal, A as ApplicationId, D as DiagnosticCollector, c as ApplicationGraph, G as GraphNode, C as CompiledApplication, d as SemanticNodeType, P as PageDSL, e as ContainerDSL, f as SignalKind } from './compile-Cte0nf06.cjs';
2
+ export { g as A11yOptions, h as AppBuilder, i as AppDSL, j as AppOptions, k as ApplicationGraphOptions, B as BaseNode, l as Bindable, m as BindableText, n as BoundInputOptions, o as ButtonOptions, p as CompileOptions, q as ContainerBuilder, r as ContainerBuilderImpl, s as ContainerOptions, t as ContentDSL, u as ControlledInputOptions, v as DerivedSignal, w as Diagnostic, x as DiagnosticError, y as DiagnosticLocation, z as DiagnosticSeverity, E as ErrorBoundaryOptions, F as ErrorFallbackBuilder, H as ErrorSource, I as EventDescriptor, J as FormBuilder, K as FormBuilderImpl, L as FormDSL, M as FormOptions, N as GraphNodeData, O as HandlerFn, Q as HeadingOptions, T as ImageOptions, W as InputOptions, X as InputOptionsBase, Y as LinkOptions, Z as ListBuilder, _ as ListBuilderImpl, $ as ListDSL, a0 as ListOptions, a1 as ListPlanEntry, a2 as NodeId, a3 as NodeMetadata, a4 as OverlayOptions, a5 as PageBuilder, a6 as PageBuilderImpl, a7 as PortalOptions, a8 as PropValue, a9 as Props, aa as ReactiveConsumer, ab as ReactiveSource, ac as SectionBuilder, ad as SectionBuilderImpl, ae as SectionDSL, af as SectionOptions, ag as SerializedGraph, ah as SerializedNode, ai as StateRef, S as StreetApp, aj as StreetUI, ak as TextOptions, al as TextValue, V as VERSION, am as batch, an as compile, ao as compileGraph, ap as createNodeId, aq as derived, ar as effect, as as formatDiagnostic, at as generateApplicationId, au as generateNodeId, av as isBatching, aw as nextId, ax as nodeIdPrefix, ay as observerCount, az as reactiveListItemKey, aA as reactiveListItemSignature, aB as resetIdCounter, aC as signal, aD as signalKind, aE as streetui } from './compile-Cte0nf06.cjs';
3
+ import { R as RenderHandle, S as StreetRenderer, a as HydrationDiagnosticSink } from './hydration-diagnostics-zK-fihvd.cjs';
4
+ export { H as HydrationDiagnostic, b as HydrationMismatchType, c as consoleHydrationDiagnosticSink, d as createHydrationDiagnosticCollector, f as formatHydrationDiagnostic } from './hydration-diagnostics-zK-fihvd.cjs';
5
+ import { D as DOMAdapter } from './server-D4A8eunr.cjs';
6
+ export { R as RenderToStringOptions, S as STATE_MARKER_ATTR, a as ServerDOMAdapter, r as readState, b as renderToString, s as serializeState, c as serverDOMAdapter } from './server-D4A8eunr.cjs';
7
7
 
8
8
  /**
9
9
  * A simple reactive store built on top of signals.
@@ -557,6 +557,10 @@ declare class BrowserDOMAdapter implements DOMAdapter {
557
557
  querySelectorAll(root: Element | Document, selector: string): NodeListOf<Element>;
558
558
  getElementById(id: string): Element | null;
559
559
  focus(element: Element): void;
560
+ body(): Element | null;
561
+ activeElement(): Element | null;
562
+ contains(ancestor: Element, node: Node): boolean;
563
+ matches(element: Element, selector: string): boolean;
560
564
  isElement(node: Node): node is Element;
561
565
  isTextNode(node: Node): node is Text;
562
566
  tagName(element: Element): string;
@@ -674,6 +678,42 @@ declare function focusById(dom: DOMAdapter, root: Element | Document, id: string
674
678
  * Returns true if a focusable element was found and focused.
675
679
  */
676
680
  declare function focusFirst(dom: DOMAdapter, container: Element | Document, selector?: string): boolean;
681
+ /**
682
+ * Ordered list of focusable/tabbable descendants of `container`.
683
+ * Re-checks each candidate against the selector so elements disabled after the
684
+ * initial query (e.g. a button toggled to `disabled`) are excluded.
685
+ */
686
+ declare function getFocusable(dom: DOMAdapter, container: Element, selector?: string): Element[];
687
+ /**
688
+ * Capture the currently-focused element so it can be restored later (e.g. when
689
+ * a dialog closes). Returns null on the server or when nothing is focused.
690
+ */
691
+ declare function saveFocus(dom: DOMAdapter): Element | null;
692
+ /** Restore focus to a previously {@link saveFocus}-d element. No-op if null. */
693
+ declare function restoreFocus(dom: DOMAdapter, saved: Element | null): void;
694
+ /**
695
+ * Move focus into `container` on open: the element with id `initialFocusId` if
696
+ * given and present, otherwise the first focusable element. Server-safe no-op.
697
+ */
698
+ declare function focusInitial(dom: DOMAdapter, container: Element, initialFocusId?: string): void;
699
+ /**
700
+ * Trap Tab / Shift+Tab focus within `container` (wrap-around at both ends).
701
+ * Attaches a keydown listener to the container and returns a cleanup function
702
+ * that detaches it. Server-safe: `addEventListener` is a no-op, and the returned
703
+ * cleanup is still callable.
704
+ */
705
+ declare function trapFocus(dom: DOMAdapter, container: Element): () => void;
706
+ /**
707
+ * Modal containment: if focus moves to an element outside `container`, redirect
708
+ * it back inside. Listens on the document body (focusin bubbles there) and
709
+ * returns a cleanup function. Server-safe no-op (body() is null).
710
+ */
711
+ declare function containFocus(dom: DOMAdapter, container: Element): () => void;
712
+ /**
713
+ * Invoke `handler` when Escape is pressed while focus is within `target`.
714
+ * Returns a cleanup function. Server-safe no-op.
715
+ */
716
+ declare function onEscape(dom: DOMAdapter, target: Element, handler: () => void): () => void;
677
717
 
678
718
  /**
679
719
  * NodeInstance — the renderer's live counterpart to a GraphNode.
@@ -785,6 +825,20 @@ declare function wireSignalBindings(ctx: RenderContext, graphNode: GraphNode, in
785
825
  * eager build factory (it only ever renders 0..1 branch, so eager is fine).
786
826
  */
787
827
  declare function wireReactiveList(ctx: RenderContext, graphNode: GraphNode, instance: NodeInstance, el: Element): void;
828
+ /**
829
+ * Attach overlay focus/keyboard behavior to a mounted portal. Server-safe: on
830
+ * the server `dom.body()` is null so this returns immediately (SSR emits inert
831
+ * markup, no focus concept). A plain portal has no `__overlay__` descriptor, so
832
+ * this also returns immediately — the behavior is purely additive.
833
+ *
834
+ * The panel is mounted/unmounted by the portal's inner `when(open, …)`, whose
835
+ * signal subscription is registered *before* this one (the conditional child is
836
+ * mounted earlier in the portal branch). Signal subscribers fire synchronously
837
+ * in subscription order, so on open→true the panel DOM exists before we move
838
+ * focus into it, and on open→false the panel is torn down before we restore
839
+ * focus. All listeners are tracked on the instance and torn down on unmount.
840
+ */
841
+ declare function wireOverlayBehavior(ctx: RenderContext, graphNode: GraphNode, instance: NodeInstance, target: Element): void;
788
842
 
789
843
  /**
790
844
  * Patch — targeted DOM updates driven by signal changes.
@@ -1836,4 +1890,4 @@ interface ResolvedConfig {
1836
1890
  /** Identity helper that gives `streetui.config.ts` full type-checking + inference. */
1837
1891
  declare function defineConfig(config: StreetUIConfig): StreetUIConfig;
1838
1892
 
1839
- export { type A11yIds, Application, ApplicationGraph, ApplicationId, type ApplicationIdentity, type ApplicationInspection, type ApplicationOptions, type ApplicationPanel, BrowserDOMAdapter, CleanupRegistry, CompiledApplication, ContainerDSL, type Context, type ContextInspection, type ContextLike, DEFAULT_PERF_THRESHOLDS, DOMAdapter, type DevToolsOptions, type DevToolsSession, type DevToolsSnapshot, type DevToolsSources, DiagnosticCollector, type DiagnosticContext, type DiagnosticSink, type DiagnosticsSummary, type DomBinding, DomEventRegistry, Environment, type EnvironmentCapabilities, type EnvironmentKind, EventBus, type EventHandler, FOCUSABLE_SELECTOR, type Field, type Form, type FormConfig, type FormInspection, type FormLike, type FormValidators, type FormValues, GraphNode, HydrationDiagnosticSink, type I18n, type I18nConfig, type I18nInspection, type I18nLike, type InspectFormOptions, type InspectI18nOptions, type InspectResourceOptions, type InspectSignalOptions, type InspectedNode, type InspectedPage, type InterpolationParams, type IsActiveOptions, type Job, Lifecycle, type LifecycleHook, type LifecyclePhase, type MatchResult, type MessageMap, type MountFn, type MountRouterOptions, type MountedApplication, type MountedRouter, type NavigateOptions, NodeInstance, type NodeInstanceOptions, PageDSL, type PerfDiagnostic, type PerfDiagnosticCode, type PerfSnapshot, type PerfThresholds, type PerformancePanel, type PlanEntry, type Priority, ROUTER_OUTLET_ID, ReadonlySignal, type ReconcileResult, type RenderContext, RenderHandle, type ResolvedConfig, type Resource, type ResourceInspection, type ResourceLike, type ResourceLoader, type ResourceLoaderContext, type ResourceOptions, type ResourceStatus, type RouteBuilder, type RouteContext, type RouteDefinition, type RouteMatch, type RouteMatchLike, type Router, type RouterHistory, type RouterInspection, type RouterLike, type RouterLocation, type RouterOptions, Runtime, RuntimeNodeInstance, type RuntimeOptions, Scheduler, type SchedulerDiagnostics, SemanticNodeType, ServerComment, ServerElement, ServerFragment, type ServerNode, type ServerNodeKind, type ServerParent, ServerRawHTML, ServerStyle, ServerText, type ShellBuilder, Signal, type SignalInspection, SignalKind, type SignalsPanel, Store, type StoreState, type StreetEvent, type StreetEventType, StreetFrameworkError, StreetRenderHandle, StreetRenderer, StreetRendererImpl, type StreetRendererOptions, type StreetUIConfig, type SubmitStatus, Subscriber, Unsubscribe, type Validator, a11yIds, applyNodeProps, applyProp, bindDomEvent, browserDOMAdapter, buttonUpdate, consoleDiagnosticSink, createApplication, createBrowserHistory, createContext, createDevTools, createForm, createI18n, createMemoryHistory, createRenderContext, createRenderer, createRouter, createRuntime, createStore, createStreetEvent, defineConfig, diagnosePerformance, email, environment, escapeHtmlAttr, escapeHtmlText, flushSync, focusById, focusFirst, formatDiagnosticContext, frameworkError, globalEventBus, headingUpdate, hydrateGraph, inputUpdate, inspectApplication, inspectContext, inspectForm, inspectGraph, inspectI18n, inspectResource, inspectRouter, inspectSignal, interpolate, matchPattern, matchRoutes, maxLength, minLength, mountGraph, mountNode, mountRouter, nodeTypeStats, normalizePath, patchNode, patchProp, pattern, printDiagnostics, printGraph, reconcileChildren, reconcileChildrenByPlan, reportDiagnostic, required, resolveTag, resource, routerOutlet, runValidators, scheduleImmediate, scheduleUpdate, scheduler, serializeChildren, serializeServerNode, splitTarget, textUpdate, toIdToken, transformGraph, validateGraph, wireEvents, wireReactiveList, wireSignalBindings };
1893
+ export { type A11yIds, Application, ApplicationGraph, ApplicationId, type ApplicationIdentity, type ApplicationInspection, type ApplicationOptions, type ApplicationPanel, BrowserDOMAdapter, CleanupRegistry, CompiledApplication, ContainerDSL, type Context, type ContextInspection, type ContextLike, DEFAULT_PERF_THRESHOLDS, DOMAdapter, type DevToolsOptions, type DevToolsSession, type DevToolsSnapshot, type DevToolsSources, DiagnosticCollector, type DiagnosticContext, type DiagnosticSink, type DiagnosticsSummary, type DomBinding, DomEventRegistry, Environment, type EnvironmentCapabilities, type EnvironmentKind, EventBus, type EventHandler, FOCUSABLE_SELECTOR, type Field, type Form, type FormConfig, type FormInspection, type FormLike, type FormValidators, type FormValues, GraphNode, HydrationDiagnosticSink, type I18n, type I18nConfig, type I18nInspection, type I18nLike, type InspectFormOptions, type InspectI18nOptions, type InspectResourceOptions, type InspectSignalOptions, type InspectedNode, type InspectedPage, type InterpolationParams, type IsActiveOptions, type Job, Lifecycle, type LifecycleHook, type LifecyclePhase, type MatchResult, type MessageMap, type MountFn, type MountRouterOptions, type MountedApplication, type MountedRouter, type NavigateOptions, NodeInstance, type NodeInstanceOptions, PageDSL, type PerfDiagnostic, type PerfDiagnosticCode, type PerfSnapshot, type PerfThresholds, type PerformancePanel, type PlanEntry, type Priority, ROUTER_OUTLET_ID, ReadonlySignal, type ReconcileResult, type RenderContext, RenderHandle, type ResolvedConfig, type Resource, type ResourceInspection, type ResourceLike, type ResourceLoader, type ResourceLoaderContext, type ResourceOptions, type ResourceStatus, type RouteBuilder, type RouteContext, type RouteDefinition, type RouteMatch, type RouteMatchLike, type Router, type RouterHistory, type RouterInspection, type RouterLike, type RouterLocation, type RouterOptions, Runtime, RuntimeNodeInstance, type RuntimeOptions, Scheduler, type SchedulerDiagnostics, SemanticNodeType, ServerComment, ServerElement, ServerFragment, type ServerNode, type ServerNodeKind, type ServerParent, ServerRawHTML, ServerStyle, ServerText, type ShellBuilder, Signal, type SignalInspection, SignalKind, type SignalsPanel, Store, type StoreState, type StreetEvent, type StreetEventType, StreetFrameworkError, StreetRenderHandle, StreetRenderer, StreetRendererImpl, type StreetRendererOptions, type StreetUIConfig, type SubmitStatus, Subscriber, Unsubscribe, type Validator, a11yIds, applyNodeProps, applyProp, bindDomEvent, browserDOMAdapter, buttonUpdate, consoleDiagnosticSink, containFocus, createApplication, createBrowserHistory, createContext, createDevTools, createForm, createI18n, createMemoryHistory, createRenderContext, createRenderer, createRouter, createRuntime, createStore, createStreetEvent, defineConfig, diagnosePerformance, email, environment, escapeHtmlAttr, escapeHtmlText, flushSync, focusById, focusFirst, focusInitial, formatDiagnosticContext, frameworkError, getFocusable, globalEventBus, headingUpdate, hydrateGraph, inputUpdate, inspectApplication, inspectContext, inspectForm, inspectGraph, inspectI18n, inspectResource, inspectRouter, inspectSignal, interpolate, matchPattern, matchRoutes, maxLength, minLength, mountGraph, mountNode, mountRouter, nodeTypeStats, normalizePath, onEscape, patchNode, patchProp, pattern, printDiagnostics, printGraph, reconcileChildren, reconcileChildrenByPlan, reportDiagnostic, required, resolveTag, resource, restoreFocus, routerOutlet, runValidators, saveFocus, scheduleImmediate, scheduleUpdate, scheduler, serializeChildren, serializeServerNode, splitTarget, textUpdate, toIdToken, transformGraph, trapFocus, validateGraph, wireEvents, wireOverlayBehavior, wireReactiveList, wireSignalBindings };
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
- import { a as Signal, b as Subscriber, U as Unsubscribe, R as ReadonlySignal, A as ApplicationId, D as DiagnosticCollector, c as ApplicationGraph, G as GraphNode, C as CompiledApplication, d as SemanticNodeType, P as PageDSL, e as ContainerDSL, f as SignalKind } from './compile-CEom4hkp.js';
2
- export { g as A11yOptions, h as AppBuilder, i as AppDSL, j as AppOptions, k as ApplicationGraphOptions, B as BaseNode, l as Bindable, m as BindableText, n as BoundInputOptions, o as ButtonOptions, p as CompileOptions, q as ContainerBuilder, r as ContainerBuilderImpl, s as ContainerOptions, t as ContentDSL, u as ControlledInputOptions, v as DerivedSignal, w as Diagnostic, x as DiagnosticError, y as DiagnosticLocation, z as DiagnosticSeverity, E as ErrorBoundaryOptions, F as ErrorFallbackBuilder, H as ErrorSource, I as EventDescriptor, J as FormBuilder, K as FormBuilderImpl, L as FormDSL, M as FormOptions, N as GraphNodeData, O as HandlerFn, Q as HeadingOptions, T as ImageOptions, W as InputOptions, X as InputOptionsBase, Y as LinkOptions, Z as ListBuilder, _ as ListBuilderImpl, $ as ListDSL, a0 as ListOptions, a1 as ListPlanEntry, a2 as NodeId, a3 as NodeMetadata, a4 as PageBuilder, a5 as PageBuilderImpl, a6 as PropValue, a7 as Props, a8 as ReactiveConsumer, a9 as ReactiveSource, aa as SectionBuilder, ab as SectionBuilderImpl, ac as SectionDSL, ad as SectionOptions, ae as SerializedGraph, af as SerializedNode, ag as StateRef, S as StreetApp, ah as StreetUI, ai as TextOptions, aj as TextValue, V as VERSION, ak as batch, al as compile, am as compileGraph, an as createNodeId, ao as derived, ap as effect, aq as formatDiagnostic, ar as generateApplicationId, as as generateNodeId, at as isBatching, au as nextId, av as nodeIdPrefix, aw as observerCount, ax as reactiveListItemKey, ay as reactiveListItemSignature, az as resetIdCounter, aA as signal, aB as signalKind, aC as streetui } from './compile-CEom4hkp.js';
3
- import { R as RenderHandle, S as StreetRenderer, a as HydrationDiagnosticSink } from './hydration-diagnostics-YrG-OJJe.js';
4
- export { H as HydrationDiagnostic, b as HydrationMismatchType, c as consoleHydrationDiagnosticSink, d as createHydrationDiagnosticCollector, f as formatHydrationDiagnostic } from './hydration-diagnostics-YrG-OJJe.js';
5
- import { D as DOMAdapter } from './server-jbB-7oN-.js';
6
- export { R as RenderToStringOptions, S as STATE_MARKER_ATTR, a as ServerDOMAdapter, r as readState, b as renderToString, s as serializeState, c as serverDOMAdapter } from './server-jbB-7oN-.js';
1
+ import { a as Signal, b as Subscriber, U as Unsubscribe, R as ReadonlySignal, A as ApplicationId, D as DiagnosticCollector, c as ApplicationGraph, G as GraphNode, C as CompiledApplication, d as SemanticNodeType, P as PageDSL, e as ContainerDSL, f as SignalKind } from './compile-Cte0nf06.js';
2
+ export { g as A11yOptions, h as AppBuilder, i as AppDSL, j as AppOptions, k as ApplicationGraphOptions, B as BaseNode, l as Bindable, m as BindableText, n as BoundInputOptions, o as ButtonOptions, p as CompileOptions, q as ContainerBuilder, r as ContainerBuilderImpl, s as ContainerOptions, t as ContentDSL, u as ControlledInputOptions, v as DerivedSignal, w as Diagnostic, x as DiagnosticError, y as DiagnosticLocation, z as DiagnosticSeverity, E as ErrorBoundaryOptions, F as ErrorFallbackBuilder, H as ErrorSource, I as EventDescriptor, J as FormBuilder, K as FormBuilderImpl, L as FormDSL, M as FormOptions, N as GraphNodeData, O as HandlerFn, Q as HeadingOptions, T as ImageOptions, W as InputOptions, X as InputOptionsBase, Y as LinkOptions, Z as ListBuilder, _ as ListBuilderImpl, $ as ListDSL, a0 as ListOptions, a1 as ListPlanEntry, a2 as NodeId, a3 as NodeMetadata, a4 as OverlayOptions, a5 as PageBuilder, a6 as PageBuilderImpl, a7 as PortalOptions, a8 as PropValue, a9 as Props, aa as ReactiveConsumer, ab as ReactiveSource, ac as SectionBuilder, ad as SectionBuilderImpl, ae as SectionDSL, af as SectionOptions, ag as SerializedGraph, ah as SerializedNode, ai as StateRef, S as StreetApp, aj as StreetUI, ak as TextOptions, al as TextValue, V as VERSION, am as batch, an as compile, ao as compileGraph, ap as createNodeId, aq as derived, ar as effect, as as formatDiagnostic, at as generateApplicationId, au as generateNodeId, av as isBatching, aw as nextId, ax as nodeIdPrefix, ay as observerCount, az as reactiveListItemKey, aA as reactiveListItemSignature, aB as resetIdCounter, aC as signal, aD as signalKind, aE as streetui } from './compile-Cte0nf06.js';
3
+ import { R as RenderHandle, S as StreetRenderer, a as HydrationDiagnosticSink } from './hydration-diagnostics-Ddgs3Puu.js';
4
+ export { H as HydrationDiagnostic, b as HydrationMismatchType, c as consoleHydrationDiagnosticSink, d as createHydrationDiagnosticCollector, f as formatHydrationDiagnostic } from './hydration-diagnostics-Ddgs3Puu.js';
5
+ import { D as DOMAdapter } from './server-cgmCiPsz.js';
6
+ export { R as RenderToStringOptions, S as STATE_MARKER_ATTR, a as ServerDOMAdapter, r as readState, b as renderToString, s as serializeState, c as serverDOMAdapter } from './server-cgmCiPsz.js';
7
7
 
8
8
  /**
9
9
  * A simple reactive store built on top of signals.
@@ -557,6 +557,10 @@ declare class BrowserDOMAdapter implements DOMAdapter {
557
557
  querySelectorAll(root: Element | Document, selector: string): NodeListOf<Element>;
558
558
  getElementById(id: string): Element | null;
559
559
  focus(element: Element): void;
560
+ body(): Element | null;
561
+ activeElement(): Element | null;
562
+ contains(ancestor: Element, node: Node): boolean;
563
+ matches(element: Element, selector: string): boolean;
560
564
  isElement(node: Node): node is Element;
561
565
  isTextNode(node: Node): node is Text;
562
566
  tagName(element: Element): string;
@@ -674,6 +678,42 @@ declare function focusById(dom: DOMAdapter, root: Element | Document, id: string
674
678
  * Returns true if a focusable element was found and focused.
675
679
  */
676
680
  declare function focusFirst(dom: DOMAdapter, container: Element | Document, selector?: string): boolean;
681
+ /**
682
+ * Ordered list of focusable/tabbable descendants of `container`.
683
+ * Re-checks each candidate against the selector so elements disabled after the
684
+ * initial query (e.g. a button toggled to `disabled`) are excluded.
685
+ */
686
+ declare function getFocusable(dom: DOMAdapter, container: Element, selector?: string): Element[];
687
+ /**
688
+ * Capture the currently-focused element so it can be restored later (e.g. when
689
+ * a dialog closes). Returns null on the server or when nothing is focused.
690
+ */
691
+ declare function saveFocus(dom: DOMAdapter): Element | null;
692
+ /** Restore focus to a previously {@link saveFocus}-d element. No-op if null. */
693
+ declare function restoreFocus(dom: DOMAdapter, saved: Element | null): void;
694
+ /**
695
+ * Move focus into `container` on open: the element with id `initialFocusId` if
696
+ * given and present, otherwise the first focusable element. Server-safe no-op.
697
+ */
698
+ declare function focusInitial(dom: DOMAdapter, container: Element, initialFocusId?: string): void;
699
+ /**
700
+ * Trap Tab / Shift+Tab focus within `container` (wrap-around at both ends).
701
+ * Attaches a keydown listener to the container and returns a cleanup function
702
+ * that detaches it. Server-safe: `addEventListener` is a no-op, and the returned
703
+ * cleanup is still callable.
704
+ */
705
+ declare function trapFocus(dom: DOMAdapter, container: Element): () => void;
706
+ /**
707
+ * Modal containment: if focus moves to an element outside `container`, redirect
708
+ * it back inside. Listens on the document body (focusin bubbles there) and
709
+ * returns a cleanup function. Server-safe no-op (body() is null).
710
+ */
711
+ declare function containFocus(dom: DOMAdapter, container: Element): () => void;
712
+ /**
713
+ * Invoke `handler` when Escape is pressed while focus is within `target`.
714
+ * Returns a cleanup function. Server-safe no-op.
715
+ */
716
+ declare function onEscape(dom: DOMAdapter, target: Element, handler: () => void): () => void;
677
717
 
678
718
  /**
679
719
  * NodeInstance — the renderer's live counterpart to a GraphNode.
@@ -785,6 +825,20 @@ declare function wireSignalBindings(ctx: RenderContext, graphNode: GraphNode, in
785
825
  * eager build factory (it only ever renders 0..1 branch, so eager is fine).
786
826
  */
787
827
  declare function wireReactiveList(ctx: RenderContext, graphNode: GraphNode, instance: NodeInstance, el: Element): void;
828
+ /**
829
+ * Attach overlay focus/keyboard behavior to a mounted portal. Server-safe: on
830
+ * the server `dom.body()` is null so this returns immediately (SSR emits inert
831
+ * markup, no focus concept). A plain portal has no `__overlay__` descriptor, so
832
+ * this also returns immediately — the behavior is purely additive.
833
+ *
834
+ * The panel is mounted/unmounted by the portal's inner `when(open, …)`, whose
835
+ * signal subscription is registered *before* this one (the conditional child is
836
+ * mounted earlier in the portal branch). Signal subscribers fire synchronously
837
+ * in subscription order, so on open→true the panel DOM exists before we move
838
+ * focus into it, and on open→false the panel is torn down before we restore
839
+ * focus. All listeners are tracked on the instance and torn down on unmount.
840
+ */
841
+ declare function wireOverlayBehavior(ctx: RenderContext, graphNode: GraphNode, instance: NodeInstance, target: Element): void;
788
842
 
789
843
  /**
790
844
  * Patch — targeted DOM updates driven by signal changes.
@@ -1836,4 +1890,4 @@ interface ResolvedConfig {
1836
1890
  /** Identity helper that gives `streetui.config.ts` full type-checking + inference. */
1837
1891
  declare function defineConfig(config: StreetUIConfig): StreetUIConfig;
1838
1892
 
1839
- export { type A11yIds, Application, ApplicationGraph, ApplicationId, type ApplicationIdentity, type ApplicationInspection, type ApplicationOptions, type ApplicationPanel, BrowserDOMAdapter, CleanupRegistry, CompiledApplication, ContainerDSL, type Context, type ContextInspection, type ContextLike, DEFAULT_PERF_THRESHOLDS, DOMAdapter, type DevToolsOptions, type DevToolsSession, type DevToolsSnapshot, type DevToolsSources, DiagnosticCollector, type DiagnosticContext, type DiagnosticSink, type DiagnosticsSummary, type DomBinding, DomEventRegistry, Environment, type EnvironmentCapabilities, type EnvironmentKind, EventBus, type EventHandler, FOCUSABLE_SELECTOR, type Field, type Form, type FormConfig, type FormInspection, type FormLike, type FormValidators, type FormValues, GraphNode, HydrationDiagnosticSink, type I18n, type I18nConfig, type I18nInspection, type I18nLike, type InspectFormOptions, type InspectI18nOptions, type InspectResourceOptions, type InspectSignalOptions, type InspectedNode, type InspectedPage, type InterpolationParams, type IsActiveOptions, type Job, Lifecycle, type LifecycleHook, type LifecyclePhase, type MatchResult, type MessageMap, type MountFn, type MountRouterOptions, type MountedApplication, type MountedRouter, type NavigateOptions, NodeInstance, type NodeInstanceOptions, PageDSL, type PerfDiagnostic, type PerfDiagnosticCode, type PerfSnapshot, type PerfThresholds, type PerformancePanel, type PlanEntry, type Priority, ROUTER_OUTLET_ID, ReadonlySignal, type ReconcileResult, type RenderContext, RenderHandle, type ResolvedConfig, type Resource, type ResourceInspection, type ResourceLike, type ResourceLoader, type ResourceLoaderContext, type ResourceOptions, type ResourceStatus, type RouteBuilder, type RouteContext, type RouteDefinition, type RouteMatch, type RouteMatchLike, type Router, type RouterHistory, type RouterInspection, type RouterLike, type RouterLocation, type RouterOptions, Runtime, RuntimeNodeInstance, type RuntimeOptions, Scheduler, type SchedulerDiagnostics, SemanticNodeType, ServerComment, ServerElement, ServerFragment, type ServerNode, type ServerNodeKind, type ServerParent, ServerRawHTML, ServerStyle, ServerText, type ShellBuilder, Signal, type SignalInspection, SignalKind, type SignalsPanel, Store, type StoreState, type StreetEvent, type StreetEventType, StreetFrameworkError, StreetRenderHandle, StreetRenderer, StreetRendererImpl, type StreetRendererOptions, type StreetUIConfig, type SubmitStatus, Subscriber, Unsubscribe, type Validator, a11yIds, applyNodeProps, applyProp, bindDomEvent, browserDOMAdapter, buttonUpdate, consoleDiagnosticSink, createApplication, createBrowserHistory, createContext, createDevTools, createForm, createI18n, createMemoryHistory, createRenderContext, createRenderer, createRouter, createRuntime, createStore, createStreetEvent, defineConfig, diagnosePerformance, email, environment, escapeHtmlAttr, escapeHtmlText, flushSync, focusById, focusFirst, formatDiagnosticContext, frameworkError, globalEventBus, headingUpdate, hydrateGraph, inputUpdate, inspectApplication, inspectContext, inspectForm, inspectGraph, inspectI18n, inspectResource, inspectRouter, inspectSignal, interpolate, matchPattern, matchRoutes, maxLength, minLength, mountGraph, mountNode, mountRouter, nodeTypeStats, normalizePath, patchNode, patchProp, pattern, printDiagnostics, printGraph, reconcileChildren, reconcileChildrenByPlan, reportDiagnostic, required, resolveTag, resource, routerOutlet, runValidators, scheduleImmediate, scheduleUpdate, scheduler, serializeChildren, serializeServerNode, splitTarget, textUpdate, toIdToken, transformGraph, validateGraph, wireEvents, wireReactiveList, wireSignalBindings };
1893
+ export { type A11yIds, Application, ApplicationGraph, ApplicationId, type ApplicationIdentity, type ApplicationInspection, type ApplicationOptions, type ApplicationPanel, BrowserDOMAdapter, CleanupRegistry, CompiledApplication, ContainerDSL, type Context, type ContextInspection, type ContextLike, DEFAULT_PERF_THRESHOLDS, DOMAdapter, type DevToolsOptions, type DevToolsSession, type DevToolsSnapshot, type DevToolsSources, DiagnosticCollector, type DiagnosticContext, type DiagnosticSink, type DiagnosticsSummary, type DomBinding, DomEventRegistry, Environment, type EnvironmentCapabilities, type EnvironmentKind, EventBus, type EventHandler, FOCUSABLE_SELECTOR, type Field, type Form, type FormConfig, type FormInspection, type FormLike, type FormValidators, type FormValues, GraphNode, HydrationDiagnosticSink, type I18n, type I18nConfig, type I18nInspection, type I18nLike, type InspectFormOptions, type InspectI18nOptions, type InspectResourceOptions, type InspectSignalOptions, type InspectedNode, type InspectedPage, type InterpolationParams, type IsActiveOptions, type Job, Lifecycle, type LifecycleHook, type LifecyclePhase, type MatchResult, type MessageMap, type MountFn, type MountRouterOptions, type MountedApplication, type MountedRouter, type NavigateOptions, NodeInstance, type NodeInstanceOptions, PageDSL, type PerfDiagnostic, type PerfDiagnosticCode, type PerfSnapshot, type PerfThresholds, type PerformancePanel, type PlanEntry, type Priority, ROUTER_OUTLET_ID, ReadonlySignal, type ReconcileResult, type RenderContext, RenderHandle, type ResolvedConfig, type Resource, type ResourceInspection, type ResourceLike, type ResourceLoader, type ResourceLoaderContext, type ResourceOptions, type ResourceStatus, type RouteBuilder, type RouteContext, type RouteDefinition, type RouteMatch, type RouteMatchLike, type Router, type RouterHistory, type RouterInspection, type RouterLike, type RouterLocation, type RouterOptions, Runtime, RuntimeNodeInstance, type RuntimeOptions, Scheduler, type SchedulerDiagnostics, SemanticNodeType, ServerComment, ServerElement, ServerFragment, type ServerNode, type ServerNodeKind, type ServerParent, ServerRawHTML, ServerStyle, ServerText, type ShellBuilder, Signal, type SignalInspection, SignalKind, type SignalsPanel, Store, type StoreState, type StreetEvent, type StreetEventType, StreetFrameworkError, StreetRenderHandle, StreetRenderer, StreetRendererImpl, type StreetRendererOptions, type StreetUIConfig, type SubmitStatus, Subscriber, Unsubscribe, type Validator, a11yIds, applyNodeProps, applyProp, bindDomEvent, browserDOMAdapter, buttonUpdate, consoleDiagnosticSink, containFocus, createApplication, createBrowserHistory, createContext, createDevTools, createForm, createI18n, createMemoryHistory, createRenderContext, createRenderer, createRouter, createRuntime, createStore, createStreetEvent, defineConfig, diagnosePerformance, email, environment, escapeHtmlAttr, escapeHtmlText, flushSync, focusById, focusFirst, focusInitial, formatDiagnosticContext, frameworkError, getFocusable, globalEventBus, headingUpdate, hydrateGraph, inputUpdate, inspectApplication, inspectContext, inspectForm, inspectGraph, inspectI18n, inspectResource, inspectRouter, inspectSignal, interpolate, matchPattern, matchRoutes, maxLength, minLength, mountGraph, mountNode, mountRouter, nodeTypeStats, normalizePath, onEscape, patchNode, patchProp, pattern, printDiagnostics, printGraph, reconcileChildren, reconcileChildrenByPlan, reportDiagnostic, required, resolveTag, resource, restoreFocus, routerOutlet, runValidators, saveFocus, scheduleImmediate, scheduleUpdate, scheduler, serializeChildren, serializeServerNode, splitTarget, textUpdate, toIdToken, transformGraph, trapFocus, validateGraph, wireEvents, wireOverlayBehavior, wireReactiveList, wireSignalBindings };
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/version.ts
2
- var VERSION = "1.6.0";
2
+ var VERSION = "1.7.0";
3
3
 
4
4
  // ../state/src/signal.ts
5
5
  var _activeConsumer = null;
@@ -802,6 +802,7 @@ var ApplicationGraph = class {
802
802
  }
803
803
  this.handlers.delete(`__listbuild__${node.id}`);
804
804
  this.handlers.delete(`__listplan__${node.id}`);
805
+ this.handlers.delete(`__overlay__${node.id}`);
805
806
  }
806
807
  // ── Handler registry ──────────────────────────────────────────────────────
807
808
  registerHandler(key, fn) {
@@ -916,6 +917,7 @@ function applyA11yProps(props, options) {
916
917
  if (options.ariaCurrent !== void 0) props["aria-current"] = String(options.ariaCurrent);
917
918
  if (options.ariaInvalid !== void 0) props["aria-invalid"] = String(options.ariaInvalid);
918
919
  if (options.ariaRequired !== void 0) props["aria-required"] = String(options.ariaRequired);
920
+ if (options.ariaModal !== void 0) props["aria-modal"] = String(options.ariaModal);
919
921
  }
920
922
  function containerProps(options) {
921
923
  const props = {};
@@ -947,6 +949,49 @@ function reactiveListItemSignature(item) {
947
949
  function reactiveListItemKey(item, index) {
948
950
  return itemIdentity(item, index);
949
951
  }
952
+ var OVERLAY_KINDS = {
953
+ dialog: {
954
+ role: "dialog",
955
+ modal: true,
956
+ takesFocus: true,
957
+ ariaModal: true,
958
+ defaultCloseOnEscape: true,
959
+ defaultRestoreFocus: true
960
+ },
961
+ popover: {
962
+ role: "dialog",
963
+ modal: false,
964
+ takesFocus: true,
965
+ ariaModal: false,
966
+ defaultCloseOnEscape: true,
967
+ defaultRestoreFocus: true
968
+ },
969
+ tooltip: {
970
+ role: "tooltip",
971
+ modal: false,
972
+ takesFocus: false,
973
+ ariaModal: false,
974
+ defaultCloseOnEscape: false,
975
+ defaultRestoreFocus: false
976
+ },
977
+ dropdown: {
978
+ role: "menu",
979
+ modal: false,
980
+ takesFocus: true,
981
+ ariaModal: false,
982
+ defaultCloseOnEscape: true,
983
+ defaultRestoreFocus: true
984
+ },
985
+ toast: {
986
+ role: "status",
987
+ modal: false,
988
+ takesFocus: false,
989
+ ariaModal: false,
990
+ ariaLive: "polite",
991
+ defaultCloseOnEscape: false,
992
+ defaultRestoreFocus: false
993
+ }
994
+ };
950
995
  var ContentBuilderBase = class {
951
996
  constructor(_node, _graph) {
952
997
  this._node = _node;
@@ -1219,6 +1264,74 @@ var ContainerBuilderBase = class extends ContentBuilderBase {
1219
1264
  );
1220
1265
  }, { id });
1221
1266
  }
1267
+ // ── Portals & overlays ──────────────────────────────────────────────────────
1268
+ portal(key, builder, options = {}) {
1269
+ const node = this._graph.createNode("portal", {
1270
+ key,
1271
+ parent: this._node,
1272
+ props: containerProps(options)
1273
+ });
1274
+ builder(new ContainerBuilderImpl(node, this._graph));
1275
+ }
1276
+ /**
1277
+ * Shared assembly for every overlay kind: a `portal` node whose single child
1278
+ * is a `when(open, panel)` conditional. The panel container carries the
1279
+ * kind's ARIA semantics; `builder` fills it. An `__overlay__<portalId>`
1280
+ * descriptor is registered so the renderer wires focus/keyboard behavior to
1281
+ * the same `open` signal that drives the panel. Reuses existing primitives
1282
+ * (portal + when + container) — no new render path.
1283
+ */
1284
+ _overlay(kind, key, options, builder) {
1285
+ const graph = this._graph;
1286
+ const portalNode = graph.createNode("portal", {
1287
+ key,
1288
+ parent: this._node,
1289
+ props: { key }
1290
+ });
1291
+ const openBindable = options.open;
1292
+ const openSignal = isSignal(openBindable) ? openBindable : signal(openBindable);
1293
+ const panelOptions = {
1294
+ role: options.role ?? kind.role,
1295
+ ...kind.ariaModal ? { ariaModal: true } : {},
1296
+ ...kind.ariaLive !== void 0 ? { ariaLive: kind.ariaLive } : {},
1297
+ ...options.class !== void 0 ? { class: options.class } : {},
1298
+ ...options.ariaLabel !== void 0 ? { ariaLabel: options.ariaLabel } : {},
1299
+ ...options.ariaLabelledBy !== void 0 ? { ariaLabelledBy: options.ariaLabelledBy } : {},
1300
+ ...options.ariaDescribedBy !== void 0 ? { ariaDescribedBy: options.ariaDescribedBy } : {}
1301
+ };
1302
+ const portalBuilder = new ContainerBuilderImpl(portalNode, graph);
1303
+ portalBuilder.when(openSignal, (panelHost) => {
1304
+ panelHost.container(`${key}__panel`, builder, panelOptions);
1305
+ });
1306
+ const descriptor = {
1307
+ open: openSignal,
1308
+ modal: kind.modal,
1309
+ takesFocus: kind.takesFocus,
1310
+ closeOnEscape: options.closeOnEscape ?? kind.defaultCloseOnEscape,
1311
+ restoreFocus: options.restoreFocus ?? kind.defaultRestoreFocus,
1312
+ ...options.initialFocusId !== void 0 ? { initialFocusId: options.initialFocusId } : {},
1313
+ ...options.onClose !== void 0 ? { onClose: options.onClose } : {}
1314
+ };
1315
+ graph.registerHandler(
1316
+ `__overlay__${portalNode.id}`,
1317
+ () => descriptor
1318
+ );
1319
+ }
1320
+ dialog(key, options, builder) {
1321
+ this._overlay(OVERLAY_KINDS.dialog, key, options, builder);
1322
+ }
1323
+ popover(key, options, builder) {
1324
+ this._overlay(OVERLAY_KINDS.popover, key, options, builder);
1325
+ }
1326
+ tooltip(key, options, builder) {
1327
+ this._overlay(OVERLAY_KINDS.tooltip, key, options, builder);
1328
+ }
1329
+ dropdown(key, options, builder) {
1330
+ this._overlay(OVERLAY_KINDS.dropdown, key, options, builder);
1331
+ }
1332
+ toast(key, options, builder) {
1333
+ this._overlay(OVERLAY_KINDS.toast, key, options, builder);
1334
+ }
1222
1335
  };
1223
1336
  var SectionBuilderImpl = class extends ContainerBuilderBase {
1224
1337
  };
@@ -1819,6 +1932,18 @@ var BrowserDOMAdapter = class {
1819
1932
  focus(element) {
1820
1933
  element.focus?.();
1821
1934
  }
1935
+ body() {
1936
+ return document.body ?? null;
1937
+ }
1938
+ activeElement() {
1939
+ return document.activeElement ?? null;
1940
+ }
1941
+ contains(ancestor, node) {
1942
+ return ancestor.contains(node);
1943
+ }
1944
+ matches(element, selector) {
1945
+ return typeof element.matches === "function" && element.matches(selector);
1946
+ }
1822
1947
  isElement(node) {
1823
1948
  return node.nodeType === Node.ELEMENT_NODE;
1824
1949
  }
@@ -2186,6 +2311,18 @@ var ServerDOMAdapter = class {
2186
2311
  }
2187
2312
  focus() {
2188
2313
  }
2314
+ body() {
2315
+ return null;
2316
+ }
2317
+ activeElement() {
2318
+ return null;
2319
+ }
2320
+ contains(_ancestor, _node) {
2321
+ return false;
2322
+ }
2323
+ matches(_element, _selector) {
2324
+ return false;
2325
+ }
2189
2326
  isElement(node) {
2190
2327
  return asServer(node).kind === "element";
2191
2328
  }
@@ -2251,6 +2388,66 @@ function focusFirst(dom, container, selector = FOCUSABLE_SELECTOR) {
2251
2388
  dom.focus(el);
2252
2389
  return true;
2253
2390
  }
2391
+ function getFocusable(dom, container, selector = FOCUSABLE_SELECTOR) {
2392
+ return Array.from(dom.querySelectorAll(container, selector)).filter(
2393
+ (el) => dom.matches(el, selector)
2394
+ );
2395
+ }
2396
+ function saveFocus(dom) {
2397
+ return dom.activeElement();
2398
+ }
2399
+ function restoreFocus(dom, saved) {
2400
+ if (saved !== null) dom.focus(saved);
2401
+ }
2402
+ function focusInitial(dom, container, initialFocusId) {
2403
+ if (initialFocusId !== void 0 && focusById(dom, container, initialFocusId)) return;
2404
+ focusFirst(dom, container);
2405
+ }
2406
+ function trapFocus(dom, container) {
2407
+ const onKeydown = (event) => {
2408
+ if (event.key !== "Tab") return;
2409
+ const items = getFocusable(dom, container);
2410
+ if (items.length === 0) {
2411
+ event.preventDefault();
2412
+ return;
2413
+ }
2414
+ const first = items[0];
2415
+ const last = items[items.length - 1];
2416
+ const active = dom.activeElement();
2417
+ if (active === null || !dom.contains(container, active)) {
2418
+ event.preventDefault();
2419
+ dom.focus(first);
2420
+ } else if (event.shiftKey && active === first) {
2421
+ event.preventDefault();
2422
+ dom.focus(last);
2423
+ } else if (!event.shiftKey && active === last) {
2424
+ event.preventDefault();
2425
+ dom.focus(first);
2426
+ }
2427
+ };
2428
+ dom.addEventListener(container, "keydown", onKeydown);
2429
+ return () => dom.removeEventListener(container, "keydown", onKeydown);
2430
+ }
2431
+ function containFocus(dom, container) {
2432
+ const body = dom.body();
2433
+ if (body === null) return () => {
2434
+ };
2435
+ const onFocusIn = (event) => {
2436
+ const target = event.target;
2437
+ if (target !== null && !dom.contains(container, target)) {
2438
+ focusFirst(dom, container);
2439
+ }
2440
+ };
2441
+ dom.addEventListener(body, "focusin", onFocusIn);
2442
+ return () => dom.removeEventListener(body, "focusin", onFocusIn);
2443
+ }
2444
+ function onEscape(dom, target, handler) {
2445
+ const onKeydown = (event) => {
2446
+ if (event.key === "Escape") handler();
2447
+ };
2448
+ dom.addEventListener(target, "keydown", onKeydown);
2449
+ return () => dom.removeEventListener(target, "keydown", onKeydown);
2450
+ }
2254
2451
 
2255
2452
  // ../renderer/src/render-context.ts
2256
2453
  function createRenderContext(dom, graph, container, hydrationDiagnostics, staticHTML) {
@@ -2409,7 +2606,12 @@ var TAG_MAP = {
2409
2606
  component: "div",
2410
2607
  slot: "div",
2411
2608
  fragment: "div",
2412
- "reactive-list": "ul"
2609
+ "reactive-list": "ul",
2610
+ // A portal renders as a neutral inline anchor <div> at its declaration site;
2611
+ // its children are relocated to a document.body container on the browser
2612
+ // (see the portal branch in mount.ts). On the server (no body) it renders
2613
+ // inline, so the anchor tag is what SSR/hydration positionally match on.
2614
+ portal: "div"
2413
2615
  };
2414
2616
  function resolveTag(type) {
2415
2617
  return TAG_MAP[type] ?? "div";
@@ -2821,6 +3023,28 @@ function mountNode(ctx, graphNode, parentDom) {
2821
3023
  wireReactiveList(ctx, graphNode, instance2, el2);
2822
3024
  return instance2;
2823
3025
  }
3026
+ if (graphNode.type === "portal") {
3027
+ const anchor = dom.createElement(resolveTag("portal"));
3028
+ dom.setAttribute(anchor, "data-streetui-portal", "");
3029
+ applyNodeProps(ctx, graphNode, anchor);
3030
+ const instance2 = new NodeInstance(graphNode, anchor);
3031
+ ctx.instances.set(graphNode.id, instance2);
3032
+ const body = dom.body();
3033
+ let target = anchor;
3034
+ if (body !== null) {
3035
+ const portalContainer = dom.createElement("div");
3036
+ dom.setAttribute(portalContainer, "data-streetui-portal-container", "");
3037
+ dom.appendChild(body, portalContainer);
3038
+ instance2.trackCleanup(() => dom.removeChild(body, portalContainer));
3039
+ target = portalContainer;
3040
+ }
3041
+ for (const child of graphNode.children) {
3042
+ instance2.addChild(mountNode(ctx, child, target));
3043
+ }
3044
+ dom.appendChild(parentDom, anchor);
3045
+ wireOverlayBehavior(ctx, graphNode, instance2, target);
3046
+ return instance2;
3047
+ }
2824
3048
  const tag = resolveTag(graphNode.type);
2825
3049
  const el = dom.createElement(tag);
2826
3050
  applyNodeProps(ctx, graphNode, el);
@@ -2970,6 +3194,44 @@ function forgetInstance(ctx, instance) {
2970
3194
  ctx.instances.delete(instance.graphNode.id);
2971
3195
  for (const child of instance.children) forgetInstance(ctx, child);
2972
3196
  }
3197
+ function wireOverlayBehavior(ctx, graphNode, instance, target) {
3198
+ const { dom, graph } = ctx;
3199
+ if (dom.body() === null) return;
3200
+ const descFn = graph.getHandler(`__overlay__${graphNode.id}`);
3201
+ if (descFn === void 0) return;
3202
+ const desc = descFn();
3203
+ const openSig = desc.open;
3204
+ if (openSig === void 0 || typeof openSig.subscribe !== "function") return;
3205
+ let active = [];
3206
+ let saved = null;
3207
+ const teardown = () => {
3208
+ for (const fn of active) fn();
3209
+ active = [];
3210
+ };
3211
+ const onOpenChange = (isOpen) => {
3212
+ if (isOpen) {
3213
+ if (desc.restoreFocus) saved = saveFocus(dom);
3214
+ if (desc.takesFocus) focusInitial(dom, target, desc.initialFocusId);
3215
+ if (desc.modal) {
3216
+ active.push(trapFocus(dom, target));
3217
+ active.push(containFocus(dom, target));
3218
+ }
3219
+ if (desc.closeOnEscape && desc.onClose !== void 0) {
3220
+ active.push(onEscape(dom, target, desc.onClose));
3221
+ }
3222
+ } else {
3223
+ teardown();
3224
+ if (desc.restoreFocus && saved !== null) {
3225
+ restoreFocus(dom, saved);
3226
+ saved = null;
3227
+ }
3228
+ }
3229
+ };
3230
+ const unsub = openSig.subscribe(onOpenChange);
3231
+ instance.trackCleanup(unsub);
3232
+ instance.trackCleanup(teardown);
3233
+ if (openSig.peek() === true) onOpenChange(true);
3234
+ }
2973
3235
 
2974
3236
  // ../renderer/src/hydration-diagnostics.ts
2975
3237
  function formatHydrationDiagnostic(d) {
@@ -3072,6 +3334,25 @@ function hydrateNode(ctx, graphNode, domNode, path) {
3072
3334
  wireReactiveList(ctx, graphNode, instance, domNode);
3073
3335
  return instance;
3074
3336
  }
3337
+ case "portal": {
3338
+ const instance = new NodeInstance(graphNode, domNode);
3339
+ ctx.instances.set(graphNode.id, instance);
3340
+ const body = dom.body();
3341
+ let target = domNode;
3342
+ if (body !== null) {
3343
+ const portalContainer = dom.createElement("div");
3344
+ dom.setAttribute(portalContainer, "data-streetui-portal-container", "");
3345
+ for (const child of dom.childNodes(domNode)) {
3346
+ dom.appendChild(portalContainer, child);
3347
+ }
3348
+ dom.appendChild(body, portalContainer);
3349
+ instance.trackCleanup(() => dom.removeChild(body, portalContainer));
3350
+ target = portalContainer;
3351
+ }
3352
+ hydrateChildren(ctx, graphNode, instance, target, path);
3353
+ wireOverlayBehavior(ctx, graphNode, instance, target);
3354
+ return instance;
3355
+ }
3075
3356
  default: {
3076
3357
  const instance = new NodeInstance(graphNode, domNode);
3077
3358
  ctx.instances.set(graphNode.id, instance);
@@ -3315,7 +3596,8 @@ function analyzeGraph(graph) {
3315
3596
  const hasEvents = node.events.length > 0;
3316
3597
  const isList = node.type === "reactive-list";
3317
3598
  const isConditional = node.type === "conditional";
3318
- const isStatic = node.stateRefs.length === 0 && !hasEvents && !isList && !isConditional;
3599
+ const isPortal = node.type === "portal";
3600
+ const isStatic = node.stateRefs.length === 0 && !hasEvents && !isList && !isConditional && !isPortal;
3319
3601
  const isStaticSubtree = isStatic && allChildrenStatic;
3320
3602
  nodes.set(node.id, {
3321
3603
  isStatic,
@@ -4407,6 +4689,7 @@ export {
4407
4689
  compileGraph,
4408
4690
  consoleDiagnosticSink,
4409
4691
  consoleHydrationDiagnosticSink,
4692
+ containFocus,
4410
4693
  createApplication,
4411
4694
  createBrowserHistory,
4412
4695
  createContext,
@@ -4433,12 +4716,14 @@ export {
4433
4716
  flushSync,
4434
4717
  focusById,
4435
4718
  focusFirst,
4719
+ focusInitial,
4436
4720
  formatDiagnostic,
4437
4721
  formatDiagnosticContext,
4438
4722
  formatHydrationDiagnostic,
4439
4723
  frameworkError,
4440
4724
  generateApplicationId,
4441
4725
  generateNodeId,
4726
+ getFocusable,
4442
4727
  globalEventBus,
4443
4728
  headingUpdate,
4444
4729
  hydrateGraph,
@@ -4465,6 +4750,7 @@ export {
4465
4750
  nodeTypeStats,
4466
4751
  normalizePath,
4467
4752
  observerCount,
4753
+ onEscape,
4468
4754
  patchNode,
4469
4755
  patchProp,
4470
4756
  pattern,
@@ -4481,8 +4767,10 @@ export {
4481
4767
  resetIdCounter,
4482
4768
  resolveTag,
4483
4769
  resource,
4770
+ restoreFocus,
4484
4771
  routerOutlet,
4485
4772
  runValidators,
4773
+ saveFocus,
4486
4774
  scheduleImmediate,
4487
4775
  scheduleUpdate,
4488
4776
  scheduler,
@@ -4497,8 +4785,10 @@ export {
4497
4785
  textUpdate,
4498
4786
  toIdToken,
4499
4787
  transformGraph,
4788
+ trapFocus,
4500
4789
  validateGraph,
4501
4790
  wireEvents,
4791
+ wireOverlayBehavior,
4502
4792
  wireReactiveList,
4503
4793
  wireSignalBindings
4504
4794
  };