streetui 1.7.0 → 1.9.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-Cte0nf06.d.cts → compile-DqsMQVJk.d.cts} +255 -4
- package/dist/{compile-Cte0nf06.d.ts → compile-DqsMQVJk.d.ts} +255 -4
- 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-zK-fihvd.d.cts → hydration-diagnostics-4pwt6v7b.d.cts} +1 -1
- package/dist/{hydration-diagnostics-Ddgs3Puu.d.ts → hydration-diagnostics-B2FmY05M.d.ts} +1 -1
- package/dist/index.cjs +639 -41
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +294 -18
- package/dist/index.d.ts +294 -18
- package/dist/index.js +627 -41
- package/dist/index.js.map +1 -1
- package/dist/{server-cgmCiPsz.d.ts → server-BYnmb_hR.d.ts} +1 -1
- package/dist/{server-D4A8eunr.d.cts → server-DnwqBTfE.d.cts} +1 -1
- package/dist/server.cjs +274 -31
- 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 +274 -31
- package/dist/server.js.map +1 -1
- package/dist/testing.cjs +1470 -33
- package/dist/testing.cjs.map +1 -1
- package/dist/testing.d.cts +101 -4
- package/dist/testing.d.ts +101 -4
- package/dist/testing.js +1456 -32
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -60,6 +60,7 @@ __export(src_exports, {
|
|
|
60
60
|
StreetFrameworkError: () => StreetFrameworkError,
|
|
61
61
|
StreetRenderHandle: () => StreetRenderHandle,
|
|
62
62
|
StreetRendererImpl: () => StreetRendererImpl,
|
|
63
|
+
TransitionController: () => TransitionController,
|
|
63
64
|
VERSION: () => VERSION,
|
|
64
65
|
a11yIds: () => a11yIds,
|
|
65
66
|
applyNodeProps: () => applyNodeProps,
|
|
@@ -70,9 +71,11 @@ __export(src_exports, {
|
|
|
70
71
|
buttonUpdate: () => buttonUpdate,
|
|
71
72
|
compile: () => compile,
|
|
72
73
|
compileGraph: () => compileGraph,
|
|
74
|
+
component: () => component,
|
|
73
75
|
consoleDiagnosticSink: () => consoleDiagnosticSink,
|
|
74
76
|
consoleHydrationDiagnosticSink: () => consoleHydrationDiagnosticSink,
|
|
75
77
|
containFocus: () => containFocus,
|
|
78
|
+
createAnnouncer: () => createAnnouncer,
|
|
76
79
|
createApplication: () => createApplication,
|
|
77
80
|
createBrowserHistory: () => createBrowserHistory,
|
|
78
81
|
createContext: () => createContext,
|
|
@@ -107,20 +110,25 @@ __export(src_exports, {
|
|
|
107
110
|
generateApplicationId: () => generateApplicationId,
|
|
108
111
|
generateNodeId: () => generateNodeId,
|
|
109
112
|
getFocusable: () => getFocusable,
|
|
113
|
+
getResolvedTransition: () => getResolvedTransition,
|
|
110
114
|
globalEventBus: () => globalEventBus,
|
|
111
115
|
headingUpdate: () => headingUpdate,
|
|
112
116
|
hydrateGraph: () => hydrateGraph,
|
|
113
117
|
inputUpdate: () => inputUpdate,
|
|
114
118
|
inspectApplication: () => inspectApplication,
|
|
119
|
+
inspectComponents: () => inspectComponents,
|
|
115
120
|
inspectContext: () => inspectContext,
|
|
116
121
|
inspectForm: () => inspectForm,
|
|
117
122
|
inspectGraph: () => inspectGraph,
|
|
118
123
|
inspectI18n: () => inspectI18n,
|
|
124
|
+
inspectInteractions: () => inspectInteractions,
|
|
119
125
|
inspectResource: () => inspectResource,
|
|
120
126
|
inspectRouter: () => inspectRouter,
|
|
121
127
|
inspectSignal: () => inspectSignal,
|
|
122
128
|
interpolate: () => interpolate,
|
|
123
129
|
isBatching: () => isBatching,
|
|
130
|
+
isComponentDefinition: () => isComponentDefinition,
|
|
131
|
+
isTransitionConfig: () => isTransitionConfig,
|
|
124
132
|
matchPattern: () => matchPattern,
|
|
125
133
|
matchRoutes: () => matchRoutes,
|
|
126
134
|
maxLength: () => maxLength,
|
|
@@ -149,9 +157,12 @@ __export(src_exports, {
|
|
|
149
157
|
required: () => required,
|
|
150
158
|
resetIdCounter: () => resetIdCounter,
|
|
151
159
|
resolveTag: () => resolveTag,
|
|
160
|
+
resolveTransition: () => resolveTransition,
|
|
152
161
|
resource: () => resource,
|
|
153
162
|
restoreFocus: () => restoreFocus,
|
|
154
163
|
routerOutlet: () => routerOutlet,
|
|
164
|
+
rovingMenu: () => rovingMenu,
|
|
165
|
+
runElementTransition: () => runElementTransition,
|
|
155
166
|
runValidators: () => runValidators,
|
|
156
167
|
saveFocus: () => saveFocus,
|
|
157
168
|
scheduleImmediate: () => scheduleImmediate,
|
|
@@ -170,6 +181,7 @@ __export(src_exports, {
|
|
|
170
181
|
transformGraph: () => transformGraph,
|
|
171
182
|
trapFocus: () => trapFocus,
|
|
172
183
|
validateGraph: () => validateGraph,
|
|
184
|
+
wireComponentBehavior: () => wireComponentBehavior,
|
|
173
185
|
wireEvents: () => wireEvents,
|
|
174
186
|
wireOverlayBehavior: () => wireOverlayBehavior,
|
|
175
187
|
wireReactiveList: () => wireReactiveList,
|
|
@@ -178,7 +190,7 @@ __export(src_exports, {
|
|
|
178
190
|
module.exports = __toCommonJS(src_exports);
|
|
179
191
|
|
|
180
192
|
// src/version.ts
|
|
181
|
-
var VERSION = "1.
|
|
193
|
+
var VERSION = "1.9.0";
|
|
182
194
|
|
|
183
195
|
// ../state/src/signal.ts
|
|
184
196
|
var _activeConsumer = null;
|
|
@@ -533,6 +545,9 @@ function a11yIds(base) {
|
|
|
533
545
|
description: `${token}-description`,
|
|
534
546
|
error: `${token}-error`,
|
|
535
547
|
title: `${token}-title`,
|
|
548
|
+
trigger: `${token}-trigger`,
|
|
549
|
+
controls: `${token}-controls`,
|
|
550
|
+
owns: `${token}-owns`,
|
|
536
551
|
id: (suffix) => `${token}-${toIdToken(suffix)}`
|
|
537
552
|
};
|
|
538
553
|
}
|
|
@@ -982,6 +997,8 @@ var ApplicationGraph = class {
|
|
|
982
997
|
this.handlers.delete(`__listbuild__${node.id}`);
|
|
983
998
|
this.handlers.delete(`__listplan__${node.id}`);
|
|
984
999
|
this.handlers.delete(`__overlay__${node.id}`);
|
|
1000
|
+
this.handlers.delete(`__component__${node.id}`);
|
|
1001
|
+
this.handlers.delete(`__transition__${node.id}`);
|
|
985
1002
|
}
|
|
986
1003
|
// ── Handler registry ──────────────────────────────────────────────────────
|
|
987
1004
|
registerHandler(key, fn) {
|
|
@@ -1070,6 +1087,47 @@ var ApplicationGraph = class {
|
|
|
1070
1087
|
}
|
|
1071
1088
|
};
|
|
1072
1089
|
|
|
1090
|
+
// ../dsl/src/transition.ts
|
|
1091
|
+
function classes(value) {
|
|
1092
|
+
if (value === void 0) return [];
|
|
1093
|
+
const out = [];
|
|
1094
|
+
for (const token of value.split(/\s+/)) {
|
|
1095
|
+
if (token.length > 0 && !out.includes(token)) out.push(token);
|
|
1096
|
+
}
|
|
1097
|
+
return out;
|
|
1098
|
+
}
|
|
1099
|
+
function merge(a, b) {
|
|
1100
|
+
const out = [...a];
|
|
1101
|
+
for (const token of b) if (!out.includes(token)) out.push(token);
|
|
1102
|
+
return out;
|
|
1103
|
+
}
|
|
1104
|
+
function resolveTransition(config) {
|
|
1105
|
+
const n = config.name;
|
|
1106
|
+
const enterActive = merge(
|
|
1107
|
+
classes(config.enter),
|
|
1108
|
+
classes(config.enterActive ?? (n !== void 0 ? `${n}-enter-active` : void 0))
|
|
1109
|
+
);
|
|
1110
|
+
const leaveActive = merge(
|
|
1111
|
+
classes(config.leave),
|
|
1112
|
+
classes(config.leaveActive ?? (n !== void 0 ? `${n}-leave-active` : void 0))
|
|
1113
|
+
);
|
|
1114
|
+
return {
|
|
1115
|
+
enterActive,
|
|
1116
|
+
enterFrom: classes(config.enterFrom ?? (n !== void 0 ? `${n}-enter-from` : void 0)),
|
|
1117
|
+
enterTo: classes(config.enterTo ?? (n !== void 0 ? `${n}-enter-to` : void 0)),
|
|
1118
|
+
leaveActive,
|
|
1119
|
+
leaveFrom: classes(config.leaveFrom ?? (n !== void 0 ? `${n}-leave-from` : void 0)),
|
|
1120
|
+
leaveTo: classes(config.leaveTo ?? (n !== void 0 ? `${n}-leave-to` : void 0)),
|
|
1121
|
+
appear: config.appear ?? false,
|
|
1122
|
+
duration: config.duration ?? 1e3
|
|
1123
|
+
};
|
|
1124
|
+
}
|
|
1125
|
+
function isTransitionConfig(value) {
|
|
1126
|
+
if (value === null || typeof value !== "object") return false;
|
|
1127
|
+
const o = value;
|
|
1128
|
+
return typeof o["name"] === "string" || typeof o["enter"] === "string" || typeof o["enterActive"] === "string" || typeof o["enterFrom"] === "string" || typeof o["leave"] === "string" || typeof o["leaveActive"] === "string" || typeof o["leaveFrom"] === "string";
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1073
1131
|
// ../dsl/src/builders.ts
|
|
1074
1132
|
function isSignal(v) {
|
|
1075
1133
|
return v !== null && typeof v === "object" && typeof v["get"] === "function" && typeof v["subscribe"] === "function";
|
|
@@ -1097,6 +1155,18 @@ function applyA11yProps(props, options) {
|
|
|
1097
1155
|
if (options.ariaInvalid !== void 0) props["aria-invalid"] = String(options.ariaInvalid);
|
|
1098
1156
|
if (options.ariaRequired !== void 0) props["aria-required"] = String(options.ariaRequired);
|
|
1099
1157
|
if (options.ariaModal !== void 0) props["aria-modal"] = String(options.ariaModal);
|
|
1158
|
+
if (options.ariaOwns !== void 0) props["aria-owns"] = options.ariaOwns;
|
|
1159
|
+
if (options.ariaActiveDescendant !== void 0) props["aria-activedescendant"] = options.ariaActiveDescendant;
|
|
1160
|
+
if (options.ariaHasPopup !== void 0) props["aria-haspopup"] = String(options.ariaHasPopup);
|
|
1161
|
+
if (options.ariaSelected !== void 0) props["aria-selected"] = String(options.ariaSelected);
|
|
1162
|
+
}
|
|
1163
|
+
function registerTransition(graph, node, config) {
|
|
1164
|
+
if (config === void 0) return;
|
|
1165
|
+
const resolved = resolveTransition(config);
|
|
1166
|
+
graph.registerHandler(
|
|
1167
|
+
`__transition__${node.id}`,
|
|
1168
|
+
() => resolved
|
|
1169
|
+
);
|
|
1100
1170
|
}
|
|
1101
1171
|
function containerProps(options) {
|
|
1102
1172
|
const props = {};
|
|
@@ -1157,6 +1227,7 @@ var OVERLAY_KINDS = {
|
|
|
1157
1227
|
role: "menu",
|
|
1158
1228
|
modal: false,
|
|
1159
1229
|
takesFocus: true,
|
|
1230
|
+
menu: true,
|
|
1160
1231
|
ariaModal: false,
|
|
1161
1232
|
defaultCloseOnEscape: true,
|
|
1162
1233
|
defaultRestoreFocus: true
|
|
@@ -1289,6 +1360,7 @@ var ContainerBuilderBase = class extends ContentBuilderBase {
|
|
|
1289
1360
|
parent: this._node,
|
|
1290
1361
|
props: containerProps(options)
|
|
1291
1362
|
});
|
|
1363
|
+
registerTransition(this._graph, node, options.transition);
|
|
1292
1364
|
builder(new SectionBuilderImpl(node, this._graph));
|
|
1293
1365
|
}
|
|
1294
1366
|
container(key, builder, options = {}) {
|
|
@@ -1297,6 +1369,7 @@ var ContainerBuilderBase = class extends ContentBuilderBase {
|
|
|
1297
1369
|
parent: this._node,
|
|
1298
1370
|
props: containerProps(options)
|
|
1299
1371
|
});
|
|
1372
|
+
registerTransition(this._graph, node, options.transition);
|
|
1300
1373
|
builder(new ContainerBuilderImpl(node, this._graph));
|
|
1301
1374
|
}
|
|
1302
1375
|
list(key, builder, options = {}) {
|
|
@@ -1305,6 +1378,7 @@ var ContainerBuilderBase = class extends ContentBuilderBase {
|
|
|
1305
1378
|
parent: this._node,
|
|
1306
1379
|
props: containerProps(options)
|
|
1307
1380
|
});
|
|
1381
|
+
registerTransition(this._graph, node, options.transition);
|
|
1308
1382
|
builder(new ListBuilderImpl(node, this._graph));
|
|
1309
1383
|
}
|
|
1310
1384
|
listOf(key, items, renderItem, options = {}) {
|
|
@@ -1314,6 +1388,7 @@ var ContainerBuilderBase = class extends ContentBuilderBase {
|
|
|
1314
1388
|
parent: this._node,
|
|
1315
1389
|
props: containerProps(options)
|
|
1316
1390
|
});
|
|
1391
|
+
registerTransition(graph, node, options.transition);
|
|
1317
1392
|
const signalId = `${node.id}:items`;
|
|
1318
1393
|
node.stateRefs.push({ signalId, propKey: "items" });
|
|
1319
1394
|
graph.registerHandler(`__signal__${signalId}`, items);
|
|
@@ -1335,6 +1410,7 @@ var ContainerBuilderBase = class extends ContentBuilderBase {
|
|
|
1335
1410
|
}
|
|
1336
1411
|
});
|
|
1337
1412
|
renderItem(item, index, new ContainerBuilderImpl(itemNode, graph));
|
|
1413
|
+
registerTransition(graph, itemNode, options.itemTransition);
|
|
1338
1414
|
return itemNode;
|
|
1339
1415
|
};
|
|
1340
1416
|
const buildPlan = (raw) => {
|
|
@@ -1366,6 +1442,7 @@ var ContainerBuilderBase = class extends ContentBuilderBase {
|
|
|
1366
1442
|
parent: this._node,
|
|
1367
1443
|
props
|
|
1368
1444
|
});
|
|
1445
|
+
registerTransition(this._graph, node, options.transition);
|
|
1369
1446
|
if (options.onSubmit !== void 0) {
|
|
1370
1447
|
const handlerKey = `submit:${node.id}`;
|
|
1371
1448
|
this._graph.registerHandler(handlerKey, options.onSubmit);
|
|
@@ -1373,18 +1450,20 @@ var ContainerBuilderBase = class extends ContentBuilderBase {
|
|
|
1373
1450
|
}
|
|
1374
1451
|
builder(new FormBuilderImpl(node, this._graph));
|
|
1375
1452
|
}
|
|
1376
|
-
when(condition, builder, elseBuilder) {
|
|
1453
|
+
when(condition, builder, elseBuilder, options = {}) {
|
|
1377
1454
|
const graph = this._graph;
|
|
1378
1455
|
const node = graph.createNode("conditional", {
|
|
1379
1456
|
parent: this._node,
|
|
1380
1457
|
props: containerProps({})
|
|
1381
1458
|
});
|
|
1459
|
+
const branchTransition = options.transition !== void 0 && options.appear === true ? { ...options.transition, appear: true } : options.transition;
|
|
1382
1460
|
const buildBranch = (build, tag) => {
|
|
1383
1461
|
const branchKey = `when-${tag}:${node.id}`;
|
|
1384
1462
|
const branch = graph.createNode("container", {
|
|
1385
1463
|
key: branchKey,
|
|
1386
1464
|
props: { key: branchKey }
|
|
1387
1465
|
});
|
|
1466
|
+
registerTransition(graph, branch, branchTransition);
|
|
1388
1467
|
build(new ContainerBuilderImpl(branch, graph));
|
|
1389
1468
|
return branch;
|
|
1390
1469
|
};
|
|
@@ -1479,13 +1558,24 @@ var ContainerBuilderBase = class extends ContentBuilderBase {
|
|
|
1479
1558
|
...options.ariaDescribedBy !== void 0 ? { ariaDescribedBy: options.ariaDescribedBy } : {}
|
|
1480
1559
|
};
|
|
1481
1560
|
const portalBuilder = new ContainerBuilderImpl(portalNode, graph);
|
|
1482
|
-
portalBuilder.when(
|
|
1483
|
-
|
|
1484
|
-
|
|
1561
|
+
portalBuilder.when(
|
|
1562
|
+
openSignal,
|
|
1563
|
+
(panelHost) => {
|
|
1564
|
+
panelHost.container(`${key}__panel`, builder, panelOptions);
|
|
1565
|
+
},
|
|
1566
|
+
void 0,
|
|
1567
|
+
// Overlay open/close rides the panel's `when`; a transition animates the
|
|
1568
|
+
// panel in on open and — via the reconciler's deferred-leave — plays the
|
|
1569
|
+
// leave before the panel is removed (§10). Focus is restored at close-
|
|
1570
|
+
// request time (see wireOverlayBehavior), so it never stays trapped inside
|
|
1571
|
+
// a panel that is animating away.
|
|
1572
|
+
options.transition !== void 0 ? { transition: options.transition } : {}
|
|
1573
|
+
);
|
|
1485
1574
|
const descriptor = {
|
|
1486
1575
|
open: openSignal,
|
|
1487
1576
|
modal: kind.modal,
|
|
1488
1577
|
takesFocus: kind.takesFocus,
|
|
1578
|
+
menu: kind.menu ?? false,
|
|
1489
1579
|
closeOnEscape: options.closeOnEscape ?? kind.defaultCloseOnEscape,
|
|
1490
1580
|
restoreFocus: options.restoreFocus ?? kind.defaultRestoreFocus,
|
|
1491
1581
|
...options.initialFocusId !== void 0 ? { initialFocusId: options.initialFocusId } : {},
|
|
@@ -1511,6 +1601,63 @@ var ContainerBuilderBase = class extends ContentBuilderBase {
|
|
|
1511
1601
|
toast(key, options, builder) {
|
|
1512
1602
|
this._overlay(OVERLAY_KINDS.toast, key, options, builder);
|
|
1513
1603
|
}
|
|
1604
|
+
// ── Components ────────────────────────────────────────────────────────────
|
|
1605
|
+
/**
|
|
1606
|
+
* Instantiate a reusable component (§3–§9). Creates a `'component'` node
|
|
1607
|
+
* (rendered as a `<div>` wrapper — preserves the one-node/one-element
|
|
1608
|
+
* positional-hydration invariant), then runs `def.setup(props, ctx)`
|
|
1609
|
+
* synchronously to obtain the render function and fills the component's own
|
|
1610
|
+
* container scope with it — structurally identical to `container`/
|
|
1611
|
+
* `errorBoundary`. Cleanups the setup registers via `ctx.effect`/
|
|
1612
|
+
* `ctx.onCleanup` are collected into a closure and exposed to the renderer
|
|
1613
|
+
* through a `__component__<id>` handler (mirroring `__overlay__`); the mount/
|
|
1614
|
+
* hydrate paths read it and route each into `NodeInstance.trackCleanup`, so
|
|
1615
|
+
* teardown runs (children-first) when the component leaves the graph.
|
|
1616
|
+
*
|
|
1617
|
+
* `setup` runs once per instance here at build time. When this component sits
|
|
1618
|
+
* inside a keyed list / conditional, a rebuild disposes the old instance
|
|
1619
|
+
* (running its cleanups + pruning its `__component__` entry) and re-runs this
|
|
1620
|
+
* method for the new node — so re-invocation is safe and leak-free.
|
|
1621
|
+
*/
|
|
1622
|
+
component(key, def, props, children) {
|
|
1623
|
+
const graph = this._graph;
|
|
1624
|
+
const node = graph.createNode("component", {
|
|
1625
|
+
key,
|
|
1626
|
+
parent: this._node,
|
|
1627
|
+
// `data-streetui-component` is a non-underscore prop, so it reaches the
|
|
1628
|
+
// DOM as an attribute and is visible to DevTools (§21) — unlike the
|
|
1629
|
+
// internal `_`-prefixed metadata the renderer hides.
|
|
1630
|
+
props: { key, "data-streetui-component": def.name }
|
|
1631
|
+
});
|
|
1632
|
+
const cleanups = [];
|
|
1633
|
+
const ctx = {
|
|
1634
|
+
key,
|
|
1635
|
+
onCleanup(fn) {
|
|
1636
|
+
cleanups.push(fn);
|
|
1637
|
+
},
|
|
1638
|
+
effect(fn) {
|
|
1639
|
+
cleanups.push(effect(fn));
|
|
1640
|
+
},
|
|
1641
|
+
renderChildren(content) {
|
|
1642
|
+
if (children !== void 0) children(content);
|
|
1643
|
+
}
|
|
1644
|
+
};
|
|
1645
|
+
let render;
|
|
1646
|
+
try {
|
|
1647
|
+
render = def.setup(props, ctx);
|
|
1648
|
+
render(new ContainerBuilderImpl(node, graph));
|
|
1649
|
+
} catch (err) {
|
|
1650
|
+
queueMicrotask(() => {
|
|
1651
|
+
throw err;
|
|
1652
|
+
});
|
|
1653
|
+
}
|
|
1654
|
+
if (cleanups.length > 0) {
|
|
1655
|
+
graph.registerHandler(
|
|
1656
|
+
`__component__${node.id}`,
|
|
1657
|
+
() => cleanups
|
|
1658
|
+
);
|
|
1659
|
+
}
|
|
1660
|
+
}
|
|
1514
1661
|
};
|
|
1515
1662
|
var SectionBuilderImpl = class extends ContainerBuilderBase {
|
|
1516
1663
|
};
|
|
@@ -1525,6 +1672,7 @@ var ListBuilderImpl = class extends ContentBuilderBase {
|
|
|
1525
1672
|
parent: this._node,
|
|
1526
1673
|
props: containerProps(options)
|
|
1527
1674
|
});
|
|
1675
|
+
registerTransition(this._graph, node, options.transition);
|
|
1528
1676
|
builder(new ContainerBuilderImpl(node, this._graph));
|
|
1529
1677
|
}
|
|
1530
1678
|
};
|
|
@@ -1544,6 +1692,18 @@ var AppBuilder = class {
|
|
|
1544
1692
|
}
|
|
1545
1693
|
};
|
|
1546
1694
|
|
|
1695
|
+
// ../dsl/src/component.ts
|
|
1696
|
+
function component(setup, options = {}) {
|
|
1697
|
+
return {
|
|
1698
|
+
__streetui_component: true,
|
|
1699
|
+
name: options.name ?? setup.name ?? "Component",
|
|
1700
|
+
setup
|
|
1701
|
+
};
|
|
1702
|
+
}
|
|
1703
|
+
function isComponentDefinition(value) {
|
|
1704
|
+
return value !== null && typeof value === "object" && value.__streetui_component === true;
|
|
1705
|
+
}
|
|
1706
|
+
|
|
1547
1707
|
// ../dsl/src/dsl.ts
|
|
1548
1708
|
var StreetApp = class {
|
|
1549
1709
|
_graph;
|
|
@@ -2607,18 +2767,25 @@ function trapFocus(dom, container) {
|
|
|
2607
2767
|
dom.addEventListener(container, "keydown", onKeydown);
|
|
2608
2768
|
return () => dom.removeEventListener(container, "keydown", onKeydown);
|
|
2609
2769
|
}
|
|
2770
|
+
var containmentStack = [];
|
|
2610
2771
|
function containFocus(dom, container) {
|
|
2611
2772
|
const body = dom.body();
|
|
2612
2773
|
if (body === null) return () => {
|
|
2613
2774
|
};
|
|
2775
|
+
containmentStack.push(container);
|
|
2614
2776
|
const onFocusIn = (event) => {
|
|
2777
|
+
if (containmentStack[containmentStack.length - 1] !== container) return;
|
|
2615
2778
|
const target = event.target;
|
|
2616
2779
|
if (target !== null && !dom.contains(container, target)) {
|
|
2617
2780
|
focusFirst(dom, container);
|
|
2618
2781
|
}
|
|
2619
2782
|
};
|
|
2620
2783
|
dom.addEventListener(body, "focusin", onFocusIn);
|
|
2621
|
-
return () =>
|
|
2784
|
+
return () => {
|
|
2785
|
+
dom.removeEventListener(body, "focusin", onFocusIn);
|
|
2786
|
+
const index = containmentStack.lastIndexOf(container);
|
|
2787
|
+
if (index !== -1) containmentStack.splice(index, 1);
|
|
2788
|
+
};
|
|
2622
2789
|
}
|
|
2623
2790
|
function onEscape(dom, target, handler) {
|
|
2624
2791
|
const onKeydown = (event) => {
|
|
@@ -2627,6 +2794,84 @@ function onEscape(dom, target, handler) {
|
|
|
2627
2794
|
dom.addEventListener(target, "keydown", onKeydown);
|
|
2628
2795
|
return () => dom.removeEventListener(target, "keydown", onKeydown);
|
|
2629
2796
|
}
|
|
2797
|
+
function rovingMenu(dom, container, selector = FOCUSABLE_SELECTOR) {
|
|
2798
|
+
const onKeydown = (event) => {
|
|
2799
|
+
const key = event.key;
|
|
2800
|
+
const isActivate = key === "Enter" || key === " " || key === "Spacebar";
|
|
2801
|
+
const isMove = key === "ArrowDown" || key === "ArrowUp" || key === "Home" || key === "End";
|
|
2802
|
+
if (!isActivate && !isMove) return;
|
|
2803
|
+
const items = getFocusable(dom, container, selector);
|
|
2804
|
+
if (items.length === 0) return;
|
|
2805
|
+
const active = dom.activeElement();
|
|
2806
|
+
const index = active === null ? -1 : items.indexOf(active);
|
|
2807
|
+
if (isActivate) {
|
|
2808
|
+
if (index < 0) return;
|
|
2809
|
+
event.preventDefault();
|
|
2810
|
+
items[index].click?.();
|
|
2811
|
+
return;
|
|
2812
|
+
}
|
|
2813
|
+
event.preventDefault();
|
|
2814
|
+
let next;
|
|
2815
|
+
if (key === "Home") next = 0;
|
|
2816
|
+
else if (key === "End") next = items.length - 1;
|
|
2817
|
+
else if (key === "ArrowDown") next = index < 0 ? 0 : (index + 1) % items.length;
|
|
2818
|
+
else next = index <= 0 ? items.length - 1 : index - 1;
|
|
2819
|
+
dom.focus(items[next]);
|
|
2820
|
+
};
|
|
2821
|
+
dom.addEventListener(container, "keydown", onKeydown);
|
|
2822
|
+
return () => dom.removeEventListener(container, "keydown", onKeydown);
|
|
2823
|
+
}
|
|
2824
|
+
|
|
2825
|
+
// ../dom/src/live-region.ts
|
|
2826
|
+
var VISUALLY_HIDDEN = "position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0;";
|
|
2827
|
+
function makeRegion(dom, politeness) {
|
|
2828
|
+
const el = dom.createElement("div");
|
|
2829
|
+
dom.setAttribute(el, "aria-live", politeness);
|
|
2830
|
+
dom.setAttribute(el, "aria-atomic", "true");
|
|
2831
|
+
dom.setAttribute(el, "role", politeness === "assertive" ? "alert" : "status");
|
|
2832
|
+
dom.setAttribute(el, "data-streetui-live", politeness);
|
|
2833
|
+
dom.setAttribute(el, "style", VISUALLY_HIDDEN);
|
|
2834
|
+
return el;
|
|
2835
|
+
}
|
|
2836
|
+
function createAnnouncer(dom) {
|
|
2837
|
+
const body = dom.body();
|
|
2838
|
+
if (body === null) {
|
|
2839
|
+
return { announce() {
|
|
2840
|
+
}, clear() {
|
|
2841
|
+
}, destroy() {
|
|
2842
|
+
} };
|
|
2843
|
+
}
|
|
2844
|
+
const polite = makeRegion(dom, "polite");
|
|
2845
|
+
const assertive = makeRegion(dom, "assertive");
|
|
2846
|
+
dom.appendChild(body, polite);
|
|
2847
|
+
dom.appendChild(body, assertive);
|
|
2848
|
+
let destroyed = false;
|
|
2849
|
+
const write = (region, message) => {
|
|
2850
|
+
dom.setTextContent(region, "");
|
|
2851
|
+
void Promise.resolve().then(() => {
|
|
2852
|
+
if (!destroyed) dom.setTextContent(region, message);
|
|
2853
|
+
});
|
|
2854
|
+
};
|
|
2855
|
+
return {
|
|
2856
|
+
announce(message, options) {
|
|
2857
|
+
if (destroyed) return;
|
|
2858
|
+
write(options?.assertive === true ? assertive : polite, message);
|
|
2859
|
+
},
|
|
2860
|
+
clear() {
|
|
2861
|
+
if (destroyed) return;
|
|
2862
|
+
dom.setTextContent(polite, "");
|
|
2863
|
+
dom.setTextContent(assertive, "");
|
|
2864
|
+
},
|
|
2865
|
+
destroy() {
|
|
2866
|
+
if (destroyed) return;
|
|
2867
|
+
destroyed = true;
|
|
2868
|
+
for (const region of [polite, assertive]) {
|
|
2869
|
+
const parent = dom.parentNode(region);
|
|
2870
|
+
if (parent !== null) dom.removeChild(parent, region);
|
|
2871
|
+
}
|
|
2872
|
+
}
|
|
2873
|
+
};
|
|
2874
|
+
}
|
|
2630
2875
|
|
|
2631
2876
|
// ../renderer/src/render-context.ts
|
|
2632
2877
|
function createRenderContext(dom, graph, container, hydrationDiagnostics, staticHTML) {
|
|
@@ -2838,7 +3083,7 @@ function patchNode(ctx, graphNode, propKey, newValue) {
|
|
|
2838
3083
|
}
|
|
2839
3084
|
|
|
2840
3085
|
// ../renderer/src/reconciliation.ts
|
|
2841
|
-
function reconcileChildren(ctx, parentDom, oldInstances, newNodes, mountFn) {
|
|
3086
|
+
function reconcileChildren(ctx, parentDom, oldInstances, newNodes, mountFn, hooks) {
|
|
2842
3087
|
const oldByKey = /* @__PURE__ */ new Map();
|
|
2843
3088
|
for (const inst of oldInstances) {
|
|
2844
3089
|
const key = inst.graphNode.key ?? inst.graphNode.id;
|
|
@@ -2859,28 +3104,33 @@ function reconcileChildren(ctx, parentDom, oldInstances, newNodes, mountFn) {
|
|
|
2859
3104
|
}
|
|
2860
3105
|
newInstances.push(existing);
|
|
2861
3106
|
} else {
|
|
2862
|
-
const
|
|
2863
|
-
|
|
3107
|
+
const reclaimed = hooks?.takeLeaving(key);
|
|
3108
|
+
if (reclaimed !== void 0) {
|
|
3109
|
+
patchExistingInstance(ctx, reclaimed, newNode);
|
|
3110
|
+
reconcileItemChildren(ctx, reclaimed, newNode, mountFn);
|
|
3111
|
+
hooks?.onEnter(reclaimed);
|
|
3112
|
+
newInstances.push(reclaimed);
|
|
3113
|
+
} else {
|
|
3114
|
+
const inst = mountFn(newNode, parentDom);
|
|
3115
|
+
hooks?.onEnter(inst);
|
|
3116
|
+
newInstances.push(inst);
|
|
3117
|
+
}
|
|
2864
3118
|
}
|
|
2865
3119
|
}
|
|
2866
3120
|
const removed = [];
|
|
2867
3121
|
for (const inst of oldInstances) {
|
|
2868
3122
|
const key = inst.graphNode.key ?? inst.graphNode.id;
|
|
2869
|
-
if (
|
|
2870
|
-
|
|
2871
|
-
}
|
|
2872
|
-
}
|
|
2873
|
-
for (const inst of removed) {
|
|
3123
|
+
if (usedKeys.has(key)) continue;
|
|
3124
|
+
if (hooks !== void 0 && hooks.beginLeave(inst)) continue;
|
|
2874
3125
|
const parent = ctx.dom.parentNode(inst.domNode);
|
|
2875
|
-
if (parent !== null)
|
|
2876
|
-
ctx.dom.removeChild(parent, inst.domNode);
|
|
2877
|
-
}
|
|
3126
|
+
if (parent !== null) ctx.dom.removeChild(parent, inst.domNode);
|
|
2878
3127
|
inst.dispose();
|
|
3128
|
+
removed.push(inst);
|
|
2879
3129
|
}
|
|
2880
3130
|
reorderDom(ctx, parentDom, newInstances);
|
|
2881
3131
|
return { instances: newInstances, removed };
|
|
2882
3132
|
}
|
|
2883
|
-
function reconcileChildrenByPlan(ctx, parentDom, oldInstances, plan, mountFn) {
|
|
3133
|
+
function reconcileChildrenByPlan(ctx, parentDom, oldInstances, plan, mountFn, hooks) {
|
|
2884
3134
|
const oldByKey = /* @__PURE__ */ new Map();
|
|
2885
3135
|
for (const inst of oldInstances) {
|
|
2886
3136
|
oldByKey.set(inst.graphNode.key ?? inst.graphNode.id, inst);
|
|
@@ -2907,21 +3157,34 @@ function reconcileChildrenByPlan(ctx, parentDom, oldInstances, plan, mountFn) {
|
|
|
2907
3157
|
}
|
|
2908
3158
|
newInstances.push(existing);
|
|
2909
3159
|
} else {
|
|
2910
|
-
const
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
|
|
3160
|
+
const reclaimed = hooks?.takeLeaving(entry.key);
|
|
3161
|
+
if (reclaimed !== void 0) {
|
|
3162
|
+
const freshNode = entry.build();
|
|
3163
|
+
built.push(freshNode);
|
|
3164
|
+
patchExistingInstance(ctx, reclaimed, freshNode);
|
|
3165
|
+
reconcileItemChildren(ctx, reclaimed, freshNode, mountFn);
|
|
3166
|
+
reclaimed.graphNode.setProp("_sig", freshNode.getProp("_sig"));
|
|
3167
|
+
reclaimed.graphNode.setProp("_item", entry.item);
|
|
3168
|
+
hooks?.onEnter(reclaimed);
|
|
3169
|
+
newInstances.push(reclaimed);
|
|
3170
|
+
} else {
|
|
3171
|
+
const freshNode = entry.build();
|
|
3172
|
+
built.push(freshNode);
|
|
3173
|
+
const inst = mountFn(freshNode, parentDom);
|
|
3174
|
+
hooks?.onEnter(inst);
|
|
3175
|
+
newInstances.push(inst);
|
|
3176
|
+
}
|
|
2914
3177
|
}
|
|
2915
3178
|
}
|
|
2916
3179
|
const removed = [];
|
|
2917
3180
|
for (const inst of oldInstances) {
|
|
2918
3181
|
const key = inst.graphNode.key ?? inst.graphNode.id;
|
|
2919
|
-
if (
|
|
2920
|
-
|
|
2921
|
-
for (const inst of removed) {
|
|
3182
|
+
if (usedKeys.has(key)) continue;
|
|
3183
|
+
if (hooks !== void 0 && hooks.beginLeave(inst)) continue;
|
|
2922
3184
|
const parent = ctx.dom.parentNode(inst.domNode);
|
|
2923
3185
|
if (parent !== null) ctx.dom.removeChild(parent, inst.domNode);
|
|
2924
3186
|
inst.dispose();
|
|
3187
|
+
removed.push(inst);
|
|
2925
3188
|
}
|
|
2926
3189
|
reorderDomMinimal(ctx, parentDom, oldInstances, newInstances);
|
|
2927
3190
|
return { instances: newInstances, removed, built };
|
|
@@ -3047,6 +3310,187 @@ function patchExistingInstance(ctx, instance, newNode) {
|
|
|
3047
3310
|
}
|
|
3048
3311
|
}
|
|
3049
3312
|
|
|
3313
|
+
// ../renderer/src/transition.ts
|
|
3314
|
+
function getResolvedTransition(graph, nodeId) {
|
|
3315
|
+
const fn = graph.getHandler(`__transition__${nodeId}`);
|
|
3316
|
+
return fn === void 0 ? void 0 : fn();
|
|
3317
|
+
}
|
|
3318
|
+
function host() {
|
|
3319
|
+
return globalThis;
|
|
3320
|
+
}
|
|
3321
|
+
function nextFrame(cb) {
|
|
3322
|
+
const h = host();
|
|
3323
|
+
const raf = h.requestAnimationFrame;
|
|
3324
|
+
if (typeof raf === "function") {
|
|
3325
|
+
raf(() => raf(cb));
|
|
3326
|
+
} else {
|
|
3327
|
+
h.setTimeout(cb, 0);
|
|
3328
|
+
}
|
|
3329
|
+
}
|
|
3330
|
+
function splitClass(value) {
|
|
3331
|
+
if (value === null) return [];
|
|
3332
|
+
const out = [];
|
|
3333
|
+
for (const t of value.split(/\s+/)) if (t.length > 0) out.push(t);
|
|
3334
|
+
return out;
|
|
3335
|
+
}
|
|
3336
|
+
function addClasses(dom, el, classes2) {
|
|
3337
|
+
if (classes2.length === 0) return;
|
|
3338
|
+
const current = splitClass(dom.getAttribute(el, "class"));
|
|
3339
|
+
let changed = false;
|
|
3340
|
+
for (const c of classes2) {
|
|
3341
|
+
if (!current.includes(c)) {
|
|
3342
|
+
current.push(c);
|
|
3343
|
+
changed = true;
|
|
3344
|
+
}
|
|
3345
|
+
}
|
|
3346
|
+
if (changed) dom.setAttribute(el, "class", current.join(" "));
|
|
3347
|
+
}
|
|
3348
|
+
function removeClasses(dom, el, classes2) {
|
|
3349
|
+
if (classes2.length === 0) return;
|
|
3350
|
+
const current = splitClass(dom.getAttribute(el, "class"));
|
|
3351
|
+
const next = current.filter((c) => !classes2.includes(c));
|
|
3352
|
+
if (next.length !== current.length) {
|
|
3353
|
+
if (next.length === 0) dom.removeAttribute(el, "class");
|
|
3354
|
+
else dom.setAttribute(el, "class", next.join(" "));
|
|
3355
|
+
}
|
|
3356
|
+
}
|
|
3357
|
+
function startRun(dom, el, active, from, to, duration, onDone) {
|
|
3358
|
+
const h = host();
|
|
3359
|
+
let finished = false;
|
|
3360
|
+
let timer = null;
|
|
3361
|
+
const onEvent = (e) => {
|
|
3362
|
+
if (e.target !== el) return;
|
|
3363
|
+
finish();
|
|
3364
|
+
};
|
|
3365
|
+
const detach = () => {
|
|
3366
|
+
dom.removeEventListener(el, "transitionend", onEvent);
|
|
3367
|
+
dom.removeEventListener(el, "animationend", onEvent);
|
|
3368
|
+
if (timer !== null) {
|
|
3369
|
+
h.clearTimeout(timer);
|
|
3370
|
+
timer = null;
|
|
3371
|
+
}
|
|
3372
|
+
};
|
|
3373
|
+
const finish = () => {
|
|
3374
|
+
if (finished) return;
|
|
3375
|
+
finished = true;
|
|
3376
|
+
detach();
|
|
3377
|
+
removeClasses(dom, el, active);
|
|
3378
|
+
removeClasses(dom, el, to);
|
|
3379
|
+
removeClasses(dom, el, from);
|
|
3380
|
+
onDone();
|
|
3381
|
+
};
|
|
3382
|
+
addClasses(dom, el, from);
|
|
3383
|
+
addClasses(dom, el, active);
|
|
3384
|
+
dom.addEventListener(el, "transitionend", onEvent);
|
|
3385
|
+
dom.addEventListener(el, "animationend", onEvent);
|
|
3386
|
+
timer = h.setTimeout(finish, duration);
|
|
3387
|
+
nextFrame(() => {
|
|
3388
|
+
if (finished) return;
|
|
3389
|
+
removeClasses(dom, el, from);
|
|
3390
|
+
addClasses(dom, el, to);
|
|
3391
|
+
});
|
|
3392
|
+
return {
|
|
3393
|
+
cancel: () => {
|
|
3394
|
+
if (finished) return;
|
|
3395
|
+
finished = true;
|
|
3396
|
+
detach();
|
|
3397
|
+
removeClasses(dom, el, active);
|
|
3398
|
+
removeClasses(dom, el, to);
|
|
3399
|
+
removeClasses(dom, el, from);
|
|
3400
|
+
}
|
|
3401
|
+
};
|
|
3402
|
+
}
|
|
3403
|
+
function runElementTransition(dom, el, rt, phase, onDone) {
|
|
3404
|
+
if (dom.body() === null || !dom.isElement(el)) {
|
|
3405
|
+
onDone();
|
|
3406
|
+
return { cancel: () => {
|
|
3407
|
+
} };
|
|
3408
|
+
}
|
|
3409
|
+
const active = phase === "enter" ? rt.enterActive : rt.leaveActive;
|
|
3410
|
+
const from = phase === "enter" ? rt.enterFrom : rt.leaveFrom;
|
|
3411
|
+
const to = phase === "enter" ? rt.enterTo : rt.leaveTo;
|
|
3412
|
+
return startRun(dom, el, active, from, to, rt.duration, onDone);
|
|
3413
|
+
}
|
|
3414
|
+
var TransitionController = class {
|
|
3415
|
+
constructor(dom, graph, finalize) {
|
|
3416
|
+
this.dom = dom;
|
|
3417
|
+
this.graph = graph;
|
|
3418
|
+
this.finalize = finalize;
|
|
3419
|
+
}
|
|
3420
|
+
leaving = /* @__PURE__ */ new Map();
|
|
3421
|
+
/** True only in a real DOM environment (browser). */
|
|
3422
|
+
get browser() {
|
|
3423
|
+
return this.dom.body() !== null;
|
|
3424
|
+
}
|
|
3425
|
+
keyOf(inst) {
|
|
3426
|
+
return inst.graphNode.key ?? inst.graphNode.id;
|
|
3427
|
+
}
|
|
3428
|
+
resolved(node) {
|
|
3429
|
+
return getResolvedTransition(this.graph, node.id);
|
|
3430
|
+
}
|
|
3431
|
+
/** Run the enter animation for `inst` if it carries a transition (browser only). */
|
|
3432
|
+
enter(inst) {
|
|
3433
|
+
if (!this.browser) return;
|
|
3434
|
+
const rt = this.resolved(inst.graphNode);
|
|
3435
|
+
if (rt === void 0) return;
|
|
3436
|
+
const el = inst.domNode;
|
|
3437
|
+
if (!this.dom.isElement(el)) return;
|
|
3438
|
+
startRun(this.dom, el, rt.enterActive, rt.enterFrom, rt.enterTo, rt.duration, () => {
|
|
3439
|
+
});
|
|
3440
|
+
}
|
|
3441
|
+
/**
|
|
3442
|
+
* Play `appear` for any initial child that opted into it (fresh browser mount
|
|
3443
|
+
* only — hydration must never animate appear, §22, and this is called only on
|
|
3444
|
+
* the mount path).
|
|
3445
|
+
*/
|
|
3446
|
+
appear(children) {
|
|
3447
|
+
if (!this.browser) return;
|
|
3448
|
+
for (const child of children) {
|
|
3449
|
+
const rt = this.resolved(child.graphNode);
|
|
3450
|
+
if (rt !== void 0 && rt.appear) this.enter(child);
|
|
3451
|
+
}
|
|
3452
|
+
}
|
|
3453
|
+
hooks() {
|
|
3454
|
+
return {
|
|
3455
|
+
takeLeaving: (key) => {
|
|
3456
|
+
const entry = this.leaving.get(key);
|
|
3457
|
+
if (entry === void 0) return void 0;
|
|
3458
|
+
entry.run.cancel();
|
|
3459
|
+
this.leaving.delete(key);
|
|
3460
|
+
return entry.inst;
|
|
3461
|
+
},
|
|
3462
|
+
beginLeave: (inst) => {
|
|
3463
|
+
if (!this.browser) return false;
|
|
3464
|
+
const rt = this.resolved(inst.graphNode);
|
|
3465
|
+
if (rt === void 0) return false;
|
|
3466
|
+
const el = inst.domNode;
|
|
3467
|
+
if (!this.dom.isElement(el)) return false;
|
|
3468
|
+
const key = this.keyOf(inst);
|
|
3469
|
+
const prior = this.leaving.get(key);
|
|
3470
|
+
if (prior !== void 0) prior.run.cancel();
|
|
3471
|
+
const run = startRun(
|
|
3472
|
+
this.dom,
|
|
3473
|
+
el,
|
|
3474
|
+
rt.leaveActive,
|
|
3475
|
+
rt.leaveFrom,
|
|
3476
|
+
rt.leaveTo,
|
|
3477
|
+
rt.duration,
|
|
3478
|
+
() => {
|
|
3479
|
+
const current = this.leaving.get(key);
|
|
3480
|
+
if (current !== void 0 && current.run === run) {
|
|
3481
|
+
this.leaving.delete(key);
|
|
3482
|
+
this.finalize(inst);
|
|
3483
|
+
}
|
|
3484
|
+
}
|
|
3485
|
+
);
|
|
3486
|
+
this.leaving.set(key, { inst, run });
|
|
3487
|
+
return true;
|
|
3488
|
+
},
|
|
3489
|
+
onEnter: (inst) => this.enter(inst)
|
|
3490
|
+
};
|
|
3491
|
+
}
|
|
3492
|
+
};
|
|
3493
|
+
|
|
3050
3494
|
// ../renderer/src/mount.ts
|
|
3051
3495
|
var SKIP_PROP_KEYS = /* @__PURE__ */ new Set([
|
|
3052
3496
|
"text",
|
|
@@ -3199,7 +3643,7 @@ function mountNode(ctx, graphNode, parentDom) {
|
|
|
3199
3643
|
instance2.addChild(childInstance);
|
|
3200
3644
|
}
|
|
3201
3645
|
dom.appendChild(parentDom, el2);
|
|
3202
|
-
wireReactiveList(ctx, graphNode, instance2, el2);
|
|
3646
|
+
wireReactiveList(ctx, graphNode, instance2, el2, true);
|
|
3203
3647
|
return instance2;
|
|
3204
3648
|
}
|
|
3205
3649
|
if (graphNode.type === "portal") {
|
|
@@ -3243,6 +3687,7 @@ function mountNode(ctx, graphNode, parentDom) {
|
|
|
3243
3687
|
instance.addChild(childInstance);
|
|
3244
3688
|
}
|
|
3245
3689
|
dom.appendChild(parentDom, el);
|
|
3690
|
+
if (graphNode.type === "component") wireComponentBehavior(ctx, graphNode, instance);
|
|
3246
3691
|
return instance;
|
|
3247
3692
|
}
|
|
3248
3693
|
function textUpdate(dom, el, textNode) {
|
|
@@ -3307,32 +3752,42 @@ function wireSignalBindings(ctx, graphNode, instance, onUpdate) {
|
|
|
3307
3752
|
instance.trackCleanup(unsub);
|
|
3308
3753
|
}
|
|
3309
3754
|
}
|
|
3310
|
-
function wireReactiveList(ctx, graphNode, instance, el) {
|
|
3755
|
+
function wireReactiveList(ctx, graphNode, instance, el, runAppear = false) {
|
|
3311
3756
|
const plan = ctx.graph.getHandler(`__listplan__${graphNode.id}`);
|
|
3312
3757
|
const build = ctx.graph.getHandler(`__listbuild__${graphNode.id}`);
|
|
3313
3758
|
if (plan === void 0 && build === void 0) return;
|
|
3759
|
+
const controller = new TransitionController(ctx.dom, ctx.graph, (leaving) => {
|
|
3760
|
+
const parent = ctx.dom.parentNode(leaving.domNode);
|
|
3761
|
+
if (parent !== null) ctx.dom.removeChild(parent, leaving.domNode);
|
|
3762
|
+
leaving.dispose();
|
|
3763
|
+
forgetInstance(ctx, leaving);
|
|
3764
|
+
ctx.graph.detachNode(leaving.graphNode);
|
|
3765
|
+
});
|
|
3766
|
+
const hooks = controller.hooks();
|
|
3767
|
+
if (runAppear) controller.appear(instance.children);
|
|
3314
3768
|
for (const stateRef of graphNode.stateRefs) {
|
|
3315
3769
|
if (stateRef.propKey !== "items") continue;
|
|
3316
3770
|
const sig = ctx.graph.getHandler(`__signal__${stateRef.signalId}`);
|
|
3317
3771
|
if (sig === void 0 || typeof sig.subscribe !== "function") continue;
|
|
3318
3772
|
const unsub = sig.subscribe((value) => {
|
|
3319
3773
|
if (plan !== void 0) {
|
|
3320
|
-
reconcileReactiveListByPlan(ctx, graphNode, instance, el, plan(value));
|
|
3774
|
+
reconcileReactiveListByPlan(ctx, graphNode, instance, el, plan(value), hooks);
|
|
3321
3775
|
} else {
|
|
3322
|
-
reconcileReactiveList(ctx, graphNode, instance, el, build(value));
|
|
3776
|
+
reconcileReactiveList(ctx, graphNode, instance, el, build(value), hooks);
|
|
3323
3777
|
}
|
|
3324
3778
|
});
|
|
3325
3779
|
instance.trackCleanup(unsub);
|
|
3326
3780
|
}
|
|
3327
3781
|
}
|
|
3328
|
-
function reconcileReactiveListByPlan(ctx, listNode, listInstance, listEl, plan) {
|
|
3782
|
+
function reconcileReactiveListByPlan(ctx, listNode, listInstance, listEl, plan, hooks) {
|
|
3329
3783
|
const oldInstances = [...listInstance.children];
|
|
3330
3784
|
const result = reconcileChildrenByPlan(
|
|
3331
3785
|
ctx,
|
|
3332
3786
|
listEl,
|
|
3333
3787
|
oldInstances,
|
|
3334
3788
|
plan,
|
|
3335
|
-
(node, parent) => mountNode(ctx, node, parent)
|
|
3789
|
+
(node, parent) => mountNode(ctx, node, parent),
|
|
3790
|
+
hooks
|
|
3336
3791
|
);
|
|
3337
3792
|
listInstance.children.length = 0;
|
|
3338
3793
|
for (const inst of result.instances) listInstance.children.push(inst);
|
|
@@ -3347,14 +3802,15 @@ function reconcileReactiveListByPlan(ctx, listNode, listInstance, listEl, plan)
|
|
|
3347
3802
|
for (const child of [...listNode.children]) listNode.removeChild(child);
|
|
3348
3803
|
for (const inst of result.instances) listNode.appendChild(inst.graphNode);
|
|
3349
3804
|
}
|
|
3350
|
-
function reconcileReactiveList(ctx, listNode, listInstance, listEl, newNodes) {
|
|
3805
|
+
function reconcileReactiveList(ctx, listNode, listInstance, listEl, newNodes, hooks) {
|
|
3351
3806
|
const oldInstances = [...listInstance.children];
|
|
3352
3807
|
const result = reconcileChildren(
|
|
3353
3808
|
ctx,
|
|
3354
3809
|
listEl,
|
|
3355
3810
|
oldInstances,
|
|
3356
3811
|
newNodes,
|
|
3357
|
-
(node, parent) => mountNode(ctx, node, parent)
|
|
3812
|
+
(node, parent) => mountNode(ctx, node, parent),
|
|
3813
|
+
hooks
|
|
3358
3814
|
);
|
|
3359
3815
|
listInstance.children.length = 0;
|
|
3360
3816
|
for (const inst of result.instances) listInstance.children.push(inst);
|
|
@@ -3390,11 +3846,14 @@ function wireOverlayBehavior(ctx, graphNode, instance, target) {
|
|
|
3390
3846
|
const onOpenChange = (isOpen) => {
|
|
3391
3847
|
if (isOpen) {
|
|
3392
3848
|
if (desc.restoreFocus) saved = saveFocus(dom);
|
|
3393
|
-
if (desc.takesFocus) focusInitial(dom, target, desc.initialFocusId);
|
|
3394
3849
|
if (desc.modal) {
|
|
3395
3850
|
active.push(trapFocus(dom, target));
|
|
3396
3851
|
active.push(containFocus(dom, target));
|
|
3397
3852
|
}
|
|
3853
|
+
if (desc.menu) {
|
|
3854
|
+
active.push(rovingMenu(dom, target));
|
|
3855
|
+
}
|
|
3856
|
+
if (desc.takesFocus) focusInitial(dom, target, desc.initialFocusId);
|
|
3398
3857
|
if (desc.closeOnEscape && desc.onClose !== void 0) {
|
|
3399
3858
|
active.push(onEscape(dom, target, desc.onClose));
|
|
3400
3859
|
}
|
|
@@ -3411,6 +3870,11 @@ function wireOverlayBehavior(ctx, graphNode, instance, target) {
|
|
|
3411
3870
|
instance.trackCleanup(teardown);
|
|
3412
3871
|
if (openSig.peek() === true) onOpenChange(true);
|
|
3413
3872
|
}
|
|
3873
|
+
function wireComponentBehavior(ctx, graphNode, instance) {
|
|
3874
|
+
const fn = ctx.graph.getHandler(`__component__${graphNode.id}`);
|
|
3875
|
+
if (fn === void 0) return;
|
|
3876
|
+
for (const cleanup of fn()) instance.trackCleanup(cleanup);
|
|
3877
|
+
}
|
|
3414
3878
|
|
|
3415
3879
|
// ../renderer/src/hydration-diagnostics.ts
|
|
3416
3880
|
function formatHydrationDiagnostic(d) {
|
|
@@ -3542,6 +4006,7 @@ function hydrateNode(ctx, graphNode, domNode, path) {
|
|
|
3542
4006
|
return instance;
|
|
3543
4007
|
}
|
|
3544
4008
|
hydrateChildren(ctx, graphNode, instance, domNode, path);
|
|
4009
|
+
if (graphNode.type === "component") wireComponentBehavior(ctx, graphNode, instance);
|
|
3545
4010
|
return instance;
|
|
3546
4011
|
}
|
|
3547
4012
|
}
|
|
@@ -3776,7 +4241,8 @@ function analyzeGraph(graph) {
|
|
|
3776
4241
|
const isList = node.type === "reactive-list";
|
|
3777
4242
|
const isConditional = node.type === "conditional";
|
|
3778
4243
|
const isPortal = node.type === "portal";
|
|
3779
|
-
const
|
|
4244
|
+
const isComponent = node.type === "component";
|
|
4245
|
+
const isStatic = node.stateRefs.length === 0 && !hasEvents && !isList && !isConditional && !isPortal && !isComponent;
|
|
3780
4246
|
const isStaticSubtree = isStatic && allChildrenStatic;
|
|
3781
4247
|
nodes.set(node.id, {
|
|
3782
4248
|
isStatic,
|
|
@@ -4122,16 +4588,38 @@ function mountRouter(router, options) {
|
|
|
4122
4588
|
} else {
|
|
4123
4589
|
outlet = container;
|
|
4124
4590
|
}
|
|
4591
|
+
const routeTransition = options.transition !== void 0 ? resolveTransition(options.transition) : void 0;
|
|
4592
|
+
const txDom = routeTransition !== void 0 ? new BrowserDOMAdapter() : void 0;
|
|
4125
4593
|
let active = null;
|
|
4594
|
+
const pendingLeaves = /* @__PURE__ */ new Map();
|
|
4126
4595
|
let firstRender = hydrateMode;
|
|
4596
|
+
const teardownRoute = (route) => {
|
|
4597
|
+
route.registry.run();
|
|
4598
|
+
route.mounted.unmount();
|
|
4599
|
+
if (route.host !== null && txDom !== void 0) {
|
|
4600
|
+
const parent = txDom.parentNode(route.host);
|
|
4601
|
+
if (parent !== null) txDom.removeChild(parent, route.host);
|
|
4602
|
+
}
|
|
4603
|
+
};
|
|
4127
4604
|
const disposeActive = () => {
|
|
4128
4605
|
if (active === null) return;
|
|
4129
|
-
active
|
|
4130
|
-
active.mounted.unmount();
|
|
4606
|
+
teardownRoute(active);
|
|
4131
4607
|
active = null;
|
|
4132
4608
|
};
|
|
4133
|
-
const
|
|
4134
|
-
|
|
4609
|
+
const wrapOutletChildren = (dom) => {
|
|
4610
|
+
const host2 = dom.createElement("div");
|
|
4611
|
+
dom.setAttribute(host2, "data-streetui-route", "");
|
|
4612
|
+
const moved = [];
|
|
4613
|
+
let child = dom.firstChild(outlet);
|
|
4614
|
+
while (child !== null) {
|
|
4615
|
+
moved.push(child);
|
|
4616
|
+
child = dom.nextSibling(child);
|
|
4617
|
+
}
|
|
4618
|
+
for (const n of moved) dom.appendChild(host2, n);
|
|
4619
|
+
dom.appendChild(outlet, host2);
|
|
4620
|
+
return host2;
|
|
4621
|
+
};
|
|
4622
|
+
const buildRoute = (match, target, hydrate) => {
|
|
4135
4623
|
const registry = new CleanupRegistry();
|
|
4136
4624
|
const ctx = {
|
|
4137
4625
|
path: match.path,
|
|
@@ -4144,9 +4632,53 @@ function mountRouter(router, options) {
|
|
|
4144
4632
|
routeApp.page("route", (page) => match.route.builder(page, ctx));
|
|
4145
4633
|
const runtime = createRuntime({ renderer });
|
|
4146
4634
|
const routeCompiled = compile(routeApp);
|
|
4147
|
-
const mounted =
|
|
4635
|
+
const mounted = hydrate ? runtime.hydrate(routeCompiled, target) : runtime.mount(routeCompiled, target);
|
|
4636
|
+
return { registry, mounted, host: null, enterRun: null };
|
|
4637
|
+
};
|
|
4638
|
+
const renderRoute = (match) => {
|
|
4639
|
+
if (routeTransition === void 0 || txDom === void 0) {
|
|
4640
|
+
disposeActive();
|
|
4641
|
+
active = buildRoute(match, outlet, firstRender);
|
|
4642
|
+
firstRender = false;
|
|
4643
|
+
return;
|
|
4644
|
+
}
|
|
4645
|
+
if (active === null) {
|
|
4646
|
+
if (firstRender) {
|
|
4647
|
+
active = buildRoute(match, outlet, true);
|
|
4648
|
+
active.host = wrapOutletChildren(txDom);
|
|
4649
|
+
} else {
|
|
4650
|
+
const host2 = txDom.createElement("div");
|
|
4651
|
+
txDom.setAttribute(host2, "data-streetui-route", "");
|
|
4652
|
+
txDom.appendChild(outlet, host2);
|
|
4653
|
+
active = buildRoute(match, host2, false);
|
|
4654
|
+
active.host = host2;
|
|
4655
|
+
}
|
|
4656
|
+
firstRender = false;
|
|
4657
|
+
return;
|
|
4658
|
+
}
|
|
4148
4659
|
firstRender = false;
|
|
4149
|
-
|
|
4660
|
+
const leaving = active;
|
|
4661
|
+
leaving.enterRun?.cancel();
|
|
4662
|
+
leaving.enterRun = null;
|
|
4663
|
+
const leaveHost = leaving.host;
|
|
4664
|
+
const enterHost = txDom.createElement("div");
|
|
4665
|
+
txDom.setAttribute(enterHost, "data-streetui-route", "");
|
|
4666
|
+
txDom.appendChild(outlet, enterHost);
|
|
4667
|
+
const next = buildRoute(match, enterHost, false);
|
|
4668
|
+
next.host = enterHost;
|
|
4669
|
+
next.enterRun = runElementTransition(txDom, enterHost, routeTransition, "enter", () => {
|
|
4670
|
+
next.enterRun = null;
|
|
4671
|
+
});
|
|
4672
|
+
active = next;
|
|
4673
|
+
if (leaveHost !== null) {
|
|
4674
|
+
const run = runElementTransition(txDom, leaveHost, routeTransition, "leave", () => {
|
|
4675
|
+
pendingLeaves.delete(leaving);
|
|
4676
|
+
teardownRoute(leaving);
|
|
4677
|
+
});
|
|
4678
|
+
pendingLeaves.set(leaving, run);
|
|
4679
|
+
} else {
|
|
4680
|
+
teardownRoute(leaving);
|
|
4681
|
+
}
|
|
4150
4682
|
};
|
|
4151
4683
|
renderRoute(router.currentRoute.peek());
|
|
4152
4684
|
const stopRouteSub = router.currentRoute.subscribe((match) => renderRoute(match));
|
|
@@ -4174,6 +4706,11 @@ function mountRouter(router, options) {
|
|
|
4174
4706
|
unmount() {
|
|
4175
4707
|
if (interceptLinks) container.removeEventListener("click", onClick);
|
|
4176
4708
|
stopRouteSub();
|
|
4709
|
+
for (const [route, run] of pendingLeaves) {
|
|
4710
|
+
run.cancel();
|
|
4711
|
+
teardownRoute(route);
|
|
4712
|
+
}
|
|
4713
|
+
pendingLeaves.clear();
|
|
4177
4714
|
disposeActive();
|
|
4178
4715
|
shellMounted?.unmount();
|
|
4179
4716
|
router.destroy();
|
|
@@ -4483,6 +5020,55 @@ function nodeTypeStats(graph) {
|
|
|
4483
5020
|
});
|
|
4484
5021
|
return counts;
|
|
4485
5022
|
}
|
|
5023
|
+
function inspectComponents(graph) {
|
|
5024
|
+
const out = [];
|
|
5025
|
+
graph.walk((node, depth) => {
|
|
5026
|
+
if (node.type !== "component") return;
|
|
5027
|
+
const name = node.props["data-streetui-component"];
|
|
5028
|
+
out.push({
|
|
5029
|
+
id: node.id,
|
|
5030
|
+
key: node.key,
|
|
5031
|
+
name: typeof name === "string" ? name : "Component",
|
|
5032
|
+
depth,
|
|
5033
|
+
childCount: node.children.length
|
|
5034
|
+
});
|
|
5035
|
+
});
|
|
5036
|
+
return out;
|
|
5037
|
+
}
|
|
5038
|
+
function inspectInteractions(graph) {
|
|
5039
|
+
const overlays = [];
|
|
5040
|
+
const transitions = [];
|
|
5041
|
+
graph.walk((node, depth) => {
|
|
5042
|
+
const overlayFn = graph.getHandler(`__overlay__${node.id}`);
|
|
5043
|
+
if (overlayFn !== void 0) {
|
|
5044
|
+
const d = overlayFn();
|
|
5045
|
+
overlays.push({
|
|
5046
|
+
id: node.id,
|
|
5047
|
+
key: node.key,
|
|
5048
|
+
open: d.open.peek(),
|
|
5049
|
+
modal: d.modal,
|
|
5050
|
+
takesFocus: d.takesFocus,
|
|
5051
|
+
menu: d.menu,
|
|
5052
|
+
closeOnEscape: d.closeOnEscape,
|
|
5053
|
+
restoreFocus: d.restoreFocus,
|
|
5054
|
+
depth
|
|
5055
|
+
});
|
|
5056
|
+
}
|
|
5057
|
+
const transitionFn = graph.getHandler(`__transition__${node.id}`);
|
|
5058
|
+
if (transitionFn !== void 0) {
|
|
5059
|
+
const t = transitionFn();
|
|
5060
|
+
transitions.push({
|
|
5061
|
+
id: node.id,
|
|
5062
|
+
key: node.key,
|
|
5063
|
+
nodeType: node.type,
|
|
5064
|
+
duration: t.duration,
|
|
5065
|
+
appear: t.appear,
|
|
5066
|
+
depth
|
|
5067
|
+
});
|
|
5068
|
+
}
|
|
5069
|
+
});
|
|
5070
|
+
return { overlays, transitions };
|
|
5071
|
+
}
|
|
4486
5072
|
|
|
4487
5073
|
// ../devtools/src/application.ts
|
|
4488
5074
|
function collectPerf(node, distinctSignals, acc) {
|
|
@@ -4857,6 +5443,7 @@ function defineConfig(config) {
|
|
|
4857
5443
|
StreetFrameworkError,
|
|
4858
5444
|
StreetRenderHandle,
|
|
4859
5445
|
StreetRendererImpl,
|
|
5446
|
+
TransitionController,
|
|
4860
5447
|
VERSION,
|
|
4861
5448
|
a11yIds,
|
|
4862
5449
|
applyNodeProps,
|
|
@@ -4867,9 +5454,11 @@ function defineConfig(config) {
|
|
|
4867
5454
|
buttonUpdate,
|
|
4868
5455
|
compile,
|
|
4869
5456
|
compileGraph,
|
|
5457
|
+
component,
|
|
4870
5458
|
consoleDiagnosticSink,
|
|
4871
5459
|
consoleHydrationDiagnosticSink,
|
|
4872
5460
|
containFocus,
|
|
5461
|
+
createAnnouncer,
|
|
4873
5462
|
createApplication,
|
|
4874
5463
|
createBrowserHistory,
|
|
4875
5464
|
createContext,
|
|
@@ -4904,20 +5493,25 @@ function defineConfig(config) {
|
|
|
4904
5493
|
generateApplicationId,
|
|
4905
5494
|
generateNodeId,
|
|
4906
5495
|
getFocusable,
|
|
5496
|
+
getResolvedTransition,
|
|
4907
5497
|
globalEventBus,
|
|
4908
5498
|
headingUpdate,
|
|
4909
5499
|
hydrateGraph,
|
|
4910
5500
|
inputUpdate,
|
|
4911
5501
|
inspectApplication,
|
|
5502
|
+
inspectComponents,
|
|
4912
5503
|
inspectContext,
|
|
4913
5504
|
inspectForm,
|
|
4914
5505
|
inspectGraph,
|
|
4915
5506
|
inspectI18n,
|
|
5507
|
+
inspectInteractions,
|
|
4916
5508
|
inspectResource,
|
|
4917
5509
|
inspectRouter,
|
|
4918
5510
|
inspectSignal,
|
|
4919
5511
|
interpolate,
|
|
4920
5512
|
isBatching,
|
|
5513
|
+
isComponentDefinition,
|
|
5514
|
+
isTransitionConfig,
|
|
4921
5515
|
matchPattern,
|
|
4922
5516
|
matchRoutes,
|
|
4923
5517
|
maxLength,
|
|
@@ -4946,9 +5540,12 @@ function defineConfig(config) {
|
|
|
4946
5540
|
required,
|
|
4947
5541
|
resetIdCounter,
|
|
4948
5542
|
resolveTag,
|
|
5543
|
+
resolveTransition,
|
|
4949
5544
|
resource,
|
|
4950
5545
|
restoreFocus,
|
|
4951
5546
|
routerOutlet,
|
|
5547
|
+
rovingMenu,
|
|
5548
|
+
runElementTransition,
|
|
4952
5549
|
runValidators,
|
|
4953
5550
|
saveFocus,
|
|
4954
5551
|
scheduleImmediate,
|
|
@@ -4967,6 +5564,7 @@ function defineConfig(config) {
|
|
|
4967
5564
|
transformGraph,
|
|
4968
5565
|
trapFocus,
|
|
4969
5566
|
validateGraph,
|
|
5567
|
+
wireComponentBehavior,
|
|
4970
5568
|
wireEvents,
|
|
4971
5569
|
wireOverlayBehavior,
|
|
4972
5570
|
wireReactiveList,
|