streetui 1.6.0 → 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/bin.cjs +1 -1
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/bin.js.map +1 -1
- package/dist/{compile-CEom4hkp.d.cts → compile-Cte0nf06.d.cts} +80 -3
- package/dist/{compile-CEom4hkp.d.ts → compile-Cte0nf06.d.ts} +80 -3
- package/dist/create-bin.cjs +1 -1
- package/dist/create-bin.cjs.map +1 -1
- package/dist/create-bin.js +1 -1
- package/dist/create-bin.js.map +1 -1
- package/dist/{hydration-diagnostics-YrG-OJJe.d.ts → hydration-diagnostics-Ddgs3Puu.d.ts} +1 -1
- package/dist/{hydration-diagnostics-D286jpZZ.d.cts → hydration-diagnostics-zK-fihvd.d.cts} +1 -1
- package/dist/index.cjs +439 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +93 -10
- package/dist/index.d.ts +93 -10
- package/dist/index.js +430 -5
- package/dist/index.js.map +1 -1
- package/dist/{server-C2xovHHb.d.cts → server-D4A8eunr.d.cts} +43 -1
- package/dist/{server-xU-BEwAj.d.ts → server-cgmCiPsz.d.ts} +43 -1
- package/dist/server.cjs +1126 -839
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js +1126 -839
- package/dist/server.js.map +1 -1
- package/dist/testing.cjs +375 -111
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +3 -3
- package/dist/testing.d.ts +3 -3
- package/dist/testing.js +375 -111
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/version.ts
|
|
2
|
-
var VERSION = "1.
|
|
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
|
}
|
|
@@ -1877,6 +2002,14 @@ var ServerFragment = class {
|
|
|
1877
2002
|
parent = null;
|
|
1878
2003
|
children = [];
|
|
1879
2004
|
};
|
|
2005
|
+
var ServerRawHTML = class {
|
|
2006
|
+
kind = "raw";
|
|
2007
|
+
parent = null;
|
|
2008
|
+
html;
|
|
2009
|
+
constructor(html) {
|
|
2010
|
+
this.html = html;
|
|
2011
|
+
}
|
|
2012
|
+
};
|
|
1880
2013
|
var ServerElement = class {
|
|
1881
2014
|
kind = "element";
|
|
1882
2015
|
parent = null;
|
|
@@ -2027,6 +2160,8 @@ function serializeServerNode(node) {
|
|
|
2027
2160
|
return `<!--${node.data}-->`;
|
|
2028
2161
|
case "fragment":
|
|
2029
2162
|
return serializeChildren(node);
|
|
2163
|
+
case "raw":
|
|
2164
|
+
return node.html;
|
|
2030
2165
|
case "element": {
|
|
2031
2166
|
const el = node;
|
|
2032
2167
|
const tag = el.tagName;
|
|
@@ -2066,6 +2201,15 @@ var ServerDOMAdapter = class {
|
|
|
2066
2201
|
createFragment() {
|
|
2067
2202
|
return new ServerFragment();
|
|
2068
2203
|
}
|
|
2204
|
+
/**
|
|
2205
|
+
* Create a verbatim pre-serialized HTML node (v1.7 static SSR plan, §6).
|
|
2206
|
+
* Server-only: the browser adapter does not implement this, and the renderer
|
|
2207
|
+
* fast path only invokes it when a static SSR plan is present (SSR). The
|
|
2208
|
+
* stored HTML was produced by this same serializer, so it is emitted as-is.
|
|
2209
|
+
*/
|
|
2210
|
+
createRawHTML(html) {
|
|
2211
|
+
return new ServerRawHTML(html);
|
|
2212
|
+
}
|
|
2069
2213
|
appendChild(parent, child) {
|
|
2070
2214
|
const p = asParent(parent);
|
|
2071
2215
|
const c = asServer(child);
|
|
@@ -2167,6 +2311,18 @@ var ServerDOMAdapter = class {
|
|
|
2167
2311
|
}
|
|
2168
2312
|
focus() {
|
|
2169
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
|
+
}
|
|
2170
2326
|
isElement(node) {
|
|
2171
2327
|
return asServer(node).kind === "element";
|
|
2172
2328
|
}
|
|
@@ -2232,15 +2388,76 @@ function focusFirst(dom, container, selector = FOCUSABLE_SELECTOR) {
|
|
|
2232
2388
|
dom.focus(el);
|
|
2233
2389
|
return true;
|
|
2234
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
|
+
}
|
|
2235
2451
|
|
|
2236
2452
|
// ../renderer/src/render-context.ts
|
|
2237
|
-
function createRenderContext(dom, graph, container, hydrationDiagnostics) {
|
|
2453
|
+
function createRenderContext(dom, graph, container, hydrationDiagnostics, staticHTML) {
|
|
2238
2454
|
return {
|
|
2239
2455
|
dom,
|
|
2240
2456
|
graph,
|
|
2241
2457
|
instances: /* @__PURE__ */ new Map(),
|
|
2242
2458
|
container,
|
|
2243
|
-
...hydrationDiagnostics !== void 0 ? { hydrationDiagnostics } : {}
|
|
2459
|
+
...hydrationDiagnostics !== void 0 ? { hydrationDiagnostics } : {},
|
|
2460
|
+
...staticHTML !== void 0 ? { staticHTML } : {}
|
|
2244
2461
|
};
|
|
2245
2462
|
}
|
|
2246
2463
|
|
|
@@ -2389,7 +2606,12 @@ var TAG_MAP = {
|
|
|
2389
2606
|
component: "div",
|
|
2390
2607
|
slot: "div",
|
|
2391
2608
|
fragment: "div",
|
|
2392
|
-
"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"
|
|
2393
2615
|
};
|
|
2394
2616
|
function resolveTag(type) {
|
|
2395
2617
|
return TAG_MAP[type] ?? "div";
|
|
@@ -2668,6 +2890,17 @@ function mountGraph(ctx) {
|
|
|
2668
2890
|
}
|
|
2669
2891
|
function mountNode(ctx, graphNode, parentDom) {
|
|
2670
2892
|
const { dom, graph } = ctx;
|
|
2893
|
+
const staticHTML = ctx.staticHTML;
|
|
2894
|
+
if (staticHTML !== void 0 && dom.createRawHTML !== void 0) {
|
|
2895
|
+
const precomputed = staticHTML.get(graphNode.id);
|
|
2896
|
+
if (precomputed !== void 0) {
|
|
2897
|
+
const raw = dom.createRawHTML(precomputed);
|
|
2898
|
+
dom.appendChild(parentDom, raw);
|
|
2899
|
+
const instance2 = new NodeInstance(graphNode, raw);
|
|
2900
|
+
ctx.instances.set(graphNode.id, instance2);
|
|
2901
|
+
return instance2;
|
|
2902
|
+
}
|
|
2903
|
+
}
|
|
2671
2904
|
if (graphNode.type === "application") {
|
|
2672
2905
|
const instance2 = new NodeInstance(graphNode, parentDom);
|
|
2673
2906
|
ctx.instances.set(graphNode.id, instance2);
|
|
@@ -2790,6 +3023,28 @@ function mountNode(ctx, graphNode, parentDom) {
|
|
|
2790
3023
|
wireReactiveList(ctx, graphNode, instance2, el2);
|
|
2791
3024
|
return instance2;
|
|
2792
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
|
+
}
|
|
2793
3048
|
const tag = resolveTag(graphNode.type);
|
|
2794
3049
|
const el = dom.createElement(tag);
|
|
2795
3050
|
applyNodeProps(ctx, graphNode, el);
|
|
@@ -2939,6 +3194,44 @@ function forgetInstance(ctx, instance) {
|
|
|
2939
3194
|
ctx.instances.delete(instance.graphNode.id);
|
|
2940
3195
|
for (const child of instance.children) forgetInstance(ctx, child);
|
|
2941
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
|
+
}
|
|
2942
3235
|
|
|
2943
3236
|
// ../renderer/src/hydration-diagnostics.ts
|
|
2944
3237
|
function formatHydrationDiagnostic(d) {
|
|
@@ -3041,6 +3334,25 @@ function hydrateNode(ctx, graphNode, domNode, path) {
|
|
|
3041
3334
|
wireReactiveList(ctx, graphNode, instance, domNode);
|
|
3042
3335
|
return instance;
|
|
3043
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
|
+
}
|
|
3044
3356
|
default: {
|
|
3045
3357
|
const instance = new NodeInstance(graphNode, domNode);
|
|
3046
3358
|
ctx.instances.set(graphNode.id, instance);
|
|
@@ -3255,11 +3567,115 @@ function readState(dom, root) {
|
|
|
3255
3567
|
}
|
|
3256
3568
|
}
|
|
3257
3569
|
|
|
3570
|
+
// ../compiler/dist/diagnostics.js
|
|
3571
|
+
var TEXT_PROP_KEYS = /* @__PURE__ */ new Set(["text", "label", "value"]);
|
|
3572
|
+
function analyzeGraph(graph) {
|
|
3573
|
+
const nodes = /* @__PURE__ */ new Map();
|
|
3574
|
+
const summary = {
|
|
3575
|
+
totalNodes: 0,
|
|
3576
|
+
staticNodes: 0,
|
|
3577
|
+
staticSubtrees: 0,
|
|
3578
|
+
dynamicTextNodes: 0,
|
|
3579
|
+
dynamicAttrNodes: 0,
|
|
3580
|
+
eventNodes: 0,
|
|
3581
|
+
lists: 0,
|
|
3582
|
+
conditionals: 0
|
|
3583
|
+
};
|
|
3584
|
+
const visit = (node) => {
|
|
3585
|
+
let allChildrenStatic = true;
|
|
3586
|
+
for (const child of node.children) {
|
|
3587
|
+
const childSubtreeStatic = visit(child);
|
|
3588
|
+
if (!childSubtreeStatic) allChildrenStatic = false;
|
|
3589
|
+
}
|
|
3590
|
+
let hasDynamicText = false;
|
|
3591
|
+
let hasDynamicAttr = false;
|
|
3592
|
+
for (const ref of node.stateRefs) {
|
|
3593
|
+
if (TEXT_PROP_KEYS.has(ref.propKey)) hasDynamicText = true;
|
|
3594
|
+
else hasDynamicAttr = true;
|
|
3595
|
+
}
|
|
3596
|
+
const hasEvents = node.events.length > 0;
|
|
3597
|
+
const isList = node.type === "reactive-list";
|
|
3598
|
+
const isConditional = node.type === "conditional";
|
|
3599
|
+
const isPortal = node.type === "portal";
|
|
3600
|
+
const isStatic = node.stateRefs.length === 0 && !hasEvents && !isList && !isConditional && !isPortal;
|
|
3601
|
+
const isStaticSubtree = isStatic && allChildrenStatic;
|
|
3602
|
+
nodes.set(node.id, {
|
|
3603
|
+
isStatic,
|
|
3604
|
+
isStaticSubtree,
|
|
3605
|
+
hasDynamicText,
|
|
3606
|
+
hasDynamicAttr,
|
|
3607
|
+
hasEvents,
|
|
3608
|
+
isList,
|
|
3609
|
+
isConditional
|
|
3610
|
+
});
|
|
3611
|
+
summary.totalNodes += 1;
|
|
3612
|
+
if (isStatic) summary.staticNodes += 1;
|
|
3613
|
+
if (isStaticSubtree) summary.staticSubtrees += 1;
|
|
3614
|
+
if (hasDynamicText) summary.dynamicTextNodes += 1;
|
|
3615
|
+
if (hasDynamicAttr) summary.dynamicAttrNodes += 1;
|
|
3616
|
+
if (hasEvents) summary.eventNodes += 1;
|
|
3617
|
+
if (isList) summary.lists += 1;
|
|
3618
|
+
if (isConditional) summary.conditionals += 1;
|
|
3619
|
+
return isStaticSubtree;
|
|
3620
|
+
};
|
|
3621
|
+
visit(graph.root);
|
|
3622
|
+
return { nodes, summary };
|
|
3623
|
+
}
|
|
3624
|
+
|
|
3625
|
+
// ../renderer/src/static-ssr-plan.ts
|
|
3626
|
+
function collectMaximalStaticRoots(graph) {
|
|
3627
|
+
const analysis = analyzeGraph(graph);
|
|
3628
|
+
const roots = [];
|
|
3629
|
+
const walk = (node) => {
|
|
3630
|
+
if (node.type !== "application") {
|
|
3631
|
+
const a = analysis.nodes.get(node.id);
|
|
3632
|
+
if (a !== void 0 && a.isStaticSubtree) {
|
|
3633
|
+
roots.push(node);
|
|
3634
|
+
return;
|
|
3635
|
+
}
|
|
3636
|
+
}
|
|
3637
|
+
for (const child of node.children) walk(child);
|
|
3638
|
+
};
|
|
3639
|
+
walk(graph.root);
|
|
3640
|
+
return roots;
|
|
3641
|
+
}
|
|
3642
|
+
function serializeStaticSubtree(dom, graph, root) {
|
|
3643
|
+
const container = dom.createElement("div");
|
|
3644
|
+
const ctx = createRenderContext(dom, graph, container);
|
|
3645
|
+
const instance = mountNode(ctx, root, container);
|
|
3646
|
+
const html = dom.serializeInner(container);
|
|
3647
|
+
instance.dispose();
|
|
3648
|
+
ctx.instances.clear();
|
|
3649
|
+
return html;
|
|
3650
|
+
}
|
|
3651
|
+
function buildStaticSSRPlan(compiled) {
|
|
3652
|
+
const graph = compiled.graph;
|
|
3653
|
+
const roots = collectMaximalStaticRoots(graph);
|
|
3654
|
+
const plan = /* @__PURE__ */ new Map();
|
|
3655
|
+
if (roots.length === 0) return plan;
|
|
3656
|
+
const dom = new ServerDOMAdapter();
|
|
3657
|
+
for (const root of roots) {
|
|
3658
|
+
plan.set(root.id, serializeStaticSubtree(dom, graph, root));
|
|
3659
|
+
}
|
|
3660
|
+
return plan;
|
|
3661
|
+
}
|
|
3662
|
+
var PLAN_CACHE = /* @__PURE__ */ new WeakMap();
|
|
3663
|
+
function getStaticSSRPlan(compiled) {
|
|
3664
|
+
let plan = PLAN_CACHE.get(compiled);
|
|
3665
|
+
if (plan === void 0) {
|
|
3666
|
+
plan = buildStaticSSRPlan(compiled);
|
|
3667
|
+
PLAN_CACHE.set(compiled, plan);
|
|
3668
|
+
}
|
|
3669
|
+
return plan;
|
|
3670
|
+
}
|
|
3671
|
+
|
|
3258
3672
|
// ../renderer/src/ssr.ts
|
|
3259
3673
|
function renderToString(compiled, options = {}) {
|
|
3260
3674
|
const dom = options.domAdapter ?? new ServerDOMAdapter();
|
|
3675
|
+
const plan = options.staticPlan === null ? void 0 : options.staticPlan ?? getStaticSSRPlan(compiled);
|
|
3676
|
+
const staticHTML = plan !== void 0 && plan.size > 0 ? plan : void 0;
|
|
3261
3677
|
const container = dom.createElement("div");
|
|
3262
|
-
const ctx = createRenderContext(dom, compiled.graph, container);
|
|
3678
|
+
const ctx = createRenderContext(dom, compiled.graph, container, void 0, staticHTML);
|
|
3263
3679
|
const rootInstance = mountGraph(ctx);
|
|
3264
3680
|
const html = dom.serializeInner(container);
|
|
3265
3681
|
rootInstance.dispose();
|
|
@@ -4252,6 +4668,7 @@ export {
|
|
|
4252
4668
|
ServerDOMAdapter,
|
|
4253
4669
|
ServerElement,
|
|
4254
4670
|
ServerFragment,
|
|
4671
|
+
ServerRawHTML,
|
|
4255
4672
|
ServerStyle,
|
|
4256
4673
|
ServerText,
|
|
4257
4674
|
Signal,
|
|
@@ -4272,6 +4689,7 @@ export {
|
|
|
4272
4689
|
compileGraph,
|
|
4273
4690
|
consoleDiagnosticSink,
|
|
4274
4691
|
consoleHydrationDiagnosticSink,
|
|
4692
|
+
containFocus,
|
|
4275
4693
|
createApplication,
|
|
4276
4694
|
createBrowserHistory,
|
|
4277
4695
|
createContext,
|
|
@@ -4298,12 +4716,14 @@ export {
|
|
|
4298
4716
|
flushSync,
|
|
4299
4717
|
focusById,
|
|
4300
4718
|
focusFirst,
|
|
4719
|
+
focusInitial,
|
|
4301
4720
|
formatDiagnostic,
|
|
4302
4721
|
formatDiagnosticContext,
|
|
4303
4722
|
formatHydrationDiagnostic,
|
|
4304
4723
|
frameworkError,
|
|
4305
4724
|
generateApplicationId,
|
|
4306
4725
|
generateNodeId,
|
|
4726
|
+
getFocusable,
|
|
4307
4727
|
globalEventBus,
|
|
4308
4728
|
headingUpdate,
|
|
4309
4729
|
hydrateGraph,
|
|
@@ -4330,6 +4750,7 @@ export {
|
|
|
4330
4750
|
nodeTypeStats,
|
|
4331
4751
|
normalizePath,
|
|
4332
4752
|
observerCount,
|
|
4753
|
+
onEscape,
|
|
4333
4754
|
patchNode,
|
|
4334
4755
|
patchProp,
|
|
4335
4756
|
pattern,
|
|
@@ -4346,8 +4767,10 @@ export {
|
|
|
4346
4767
|
resetIdCounter,
|
|
4347
4768
|
resolveTag,
|
|
4348
4769
|
resource,
|
|
4770
|
+
restoreFocus,
|
|
4349
4771
|
routerOutlet,
|
|
4350
4772
|
runValidators,
|
|
4773
|
+
saveFocus,
|
|
4351
4774
|
scheduleImmediate,
|
|
4352
4775
|
scheduleUpdate,
|
|
4353
4776
|
scheduler,
|
|
@@ -4362,8 +4785,10 @@ export {
|
|
|
4362
4785
|
textUpdate,
|
|
4363
4786
|
toIdToken,
|
|
4364
4787
|
transformGraph,
|
|
4788
|
+
trapFocus,
|
|
4365
4789
|
validateGraph,
|
|
4366
4790
|
wireEvents,
|
|
4791
|
+
wireOverlayBehavior,
|
|
4367
4792
|
wireReactiveList,
|
|
4368
4793
|
wireSignalBindings
|
|
4369
4794
|
};
|