@hozu/runtime-client 0.6.0 → 0.8.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.
@@ -44,59 +44,6 @@ var init_uploads = __esm({
44
44
  }
45
45
  });
46
46
 
47
- // packages/runtime-client/dist/dev.js
48
- var dev_exports = {};
49
- __export(dev_exports, {
50
- expose: () => expose,
51
- restore: () => restore
52
- });
53
- function restore(doc) {
54
- const store2 = storage(doc);
55
- let saved = {};
56
- try {
57
- saved = JSON.parse(store2?.getItem(KEY) ?? "{}");
58
- } catch {
59
- }
60
- store2?.removeItem(KEY);
61
- return (id, machine) => {
62
- const entry = saved[id];
63
- if (!entry || !machine || entry.machine !== JSON.stringify(machine))
64
- return void 0;
65
- return machine.states[entry.snapshot.state]?.invoke ? void 0 : entry.snapshot;
66
- };
67
- }
68
- function expose(doc, apps, machines) {
69
- const win = doc.defaultView;
70
- if (!win)
71
- return;
72
- win.__hozu = {
73
- save() {
74
- const saved = {};
75
- for (const [id, app] of apps) {
76
- const snapshot = app.snapshot();
77
- const machine = machines.get(id);
78
- if (snapshot && machine)
79
- saved[id] = { machine: JSON.stringify(machine), snapshot };
80
- }
81
- storage(doc)?.setItem(KEY, JSON.stringify(saved));
82
- }
83
- };
84
- }
85
- var KEY, storage;
86
- var init_dev = __esm({
87
- "packages/runtime-client/dist/dev.js"() {
88
- "use strict";
89
- KEY = "hozu:snapshots";
90
- storage = (doc) => {
91
- try {
92
- return doc.defaultView?.sessionStorage ?? null;
93
- } catch {
94
- return null;
95
- }
96
- };
97
- }
98
- });
99
-
100
47
  // packages/runtime-client/dist/motion.js
101
48
  var motion_exports = {};
102
49
  __export(motion_exports, {
@@ -190,43 +137,6 @@ var init_motion = __esm({
190
137
  }
191
138
  });
192
139
 
193
- // packages/runtime-client/dist/visible.js
194
- var visible_exports = {};
195
- __export(visible_exports, {
196
- watch: () => watch
197
- });
198
- function watch(doc) {
199
- const win = doc.defaultView;
200
- if (!win?.IntersectionObserver || watched.has(doc))
201
- return;
202
- watched.add(doc);
203
- const seen = new IntersectionObserver((entries) => {
204
- for (const e of entries)
205
- if (e.isIntersecting)
206
- e.target.dispatchEvent(new win.Event("visible"));
207
- });
208
- const scan = (root) => {
209
- if (root instanceof win.Element && root.hasAttribute("data-hozu-visible"))
210
- seen.observe(root);
211
- for (const el of root.querySelectorAll("[data-hozu-visible]"))
212
- seen.observe(el);
213
- };
214
- scan(doc);
215
- new win.MutationObserver((records) => {
216
- for (const r of records)
217
- for (const n of r.addedNodes)
218
- if (n.nodeType === 1)
219
- scan(n);
220
- }).observe(doc.body, { childList: true, subtree: true });
221
- }
222
- var watched;
223
- var init_visible = __esm({
224
- "packages/runtime-client/dist/visible.js"() {
225
- "use strict";
226
- watched = /* @__PURE__ */ new WeakSet();
227
- }
228
- });
229
-
230
140
  // packages/runtime-client/dist/widget.js
231
141
  var widget_exports = {};
232
142
  __export(widget_exports, {
@@ -292,226 +202,113 @@ var init_widget = __esm({
292
202
  }
293
203
  });
294
204
 
295
- // packages/runtime-client/dist/live.js
296
- var live_exports = {};
297
- __export(live_exports, {
298
- liveStream: () => liveStream
205
+ // packages/runtime-client/dist/visible.js
206
+ var visible_exports = {};
207
+ __export(visible_exports, {
208
+ watch: () => watch
299
209
  });
300
- var liveStream;
301
- var init_live = __esm({
302
- "packages/runtime-client/dist/live.js"() {
210
+ function watch(doc) {
211
+ const win = doc.defaultView;
212
+ if (!win?.IntersectionObserver || watched.has(doc))
213
+ return;
214
+ watched.add(doc);
215
+ const seen = new IntersectionObserver((entries) => {
216
+ for (const e of entries)
217
+ if (e.isIntersecting)
218
+ e.target.dispatchEvent(new win.Event("visible"));
219
+ });
220
+ const scan = (root) => {
221
+ if (root instanceof win.Element && root.hasAttribute("data-hozu-visible"))
222
+ seen.observe(root);
223
+ for (const el of root.querySelectorAll("[data-hozu-visible]"))
224
+ seen.observe(el);
225
+ };
226
+ scan(doc);
227
+ new win.MutationObserver((records) => {
228
+ for (const r of records)
229
+ for (const n of r.addedNodes)
230
+ if (n.nodeType === 1)
231
+ scan(n);
232
+ }).observe(doc.body, { childList: true, subtree: true });
233
+ }
234
+ var watched;
235
+ var init_visible = __esm({
236
+ "packages/runtime-client/dist/visible.js"() {
303
237
  "use strict";
304
- liveStream = (doc) => (onTags) => {
305
- const Source = doc.defaultView?.EventSource;
306
- if (!Source)
307
- return;
308
- new Source(new URL("live", import.meta.url)).addEventListener("message", (e) => onTags(JSON.parse(e.data)));
309
- };
238
+ watched = /* @__PURE__ */ new WeakSet();
310
239
  }
311
240
  });
312
241
 
313
- // packages/runtime-client/dist/navigate.js
314
- var navigate_exports = {};
315
- __export(navigate_exports, {
316
- islandsIn: () => islandsIn,
317
- ranges: () => ranges,
318
- routeOf: () => routeOf,
319
- soft: () => soft,
320
- swap: () => swap,
321
- track: () => track
242
+ // packages/runtime-client/dist/dev.js
243
+ var dev_exports = {};
244
+ __export(dev_exports, {
245
+ expose: () => expose,
246
+ restore: () => restore
322
247
  });
323
- function routeOf(routes, pathname) {
324
- let best = null;
325
- let fewest = Infinity;
326
- for (const [id, path] of Object.entries(routes)) {
327
- const { pattern, keys } = patternOf(path);
328
- if (keys < fewest && pattern.test(pathname)) {
329
- best = id;
330
- fewest = keys;
331
- }
332
- }
333
- return best;
334
- }
335
- function islandsIn(root) {
336
- const found = [];
337
- const walker = (root.ownerDocument ?? root).createTreeWalker(root, 128);
338
- let view = null;
339
- while (walker.nextNode()) {
340
- const c = walker.currentNode;
341
- if (c.data === "i")
342
- found.push({ marker: c, view });
343
- else if (c.data.startsWith("v:"))
344
- view = c.data.slice(2);
345
- else if (c.data === "/v")
346
- view = null;
347
- }
348
- return found;
349
- }
350
- function track(state, session, payload, found) {
351
- session.islands(payload).forEach((island, i) => {
352
- const view = found[i]?.view;
353
- if (!view)
354
- return;
355
- const owners = state.views.get(view) ?? /* @__PURE__ */ new Set();
356
- owners.add(island.feature);
357
- state.views.set(view, owners);
358
- });
359
- state.soft = payload.soft ?? {};
360
- Object.assign(state.routes, payload.routes);
361
- }
362
- function ranges(body) {
363
- const out = /* @__PURE__ */ new Map();
364
- let current = null;
365
- for (const n of [...body.childNodes]) {
366
- if (n.nodeType === 8 && n.data.startsWith("v:")) {
367
- current = [n];
368
- out.set(n.data.slice(2), current);
369
- } else if (current) {
370
- current.push(n);
371
- if (n.nodeType === 8 && n.data === "/v")
372
- current = null;
373
- }
374
- }
375
- return out;
376
- }
377
- async function swap(session, state, next, kept) {
378
- const { doc, apps } = session;
379
- const { views } = state;
380
- const script = next.getElementById("hozu-payload");
381
- const fresh = ranges(next.body);
382
- const live = ranges(doc.body);
383
- if (!script?.textContent || kept.some((v) => !fresh.has(v) || !live.has(v)))
384
- return false;
385
- const payload = JSON.parse(script.textContent);
386
- const keep = new Set(kept);
387
- const found = islandsIn(next.body);
388
- const needed = /* @__PURE__ */ new Set();
389
- for (const v of keep)
390
- for (const f of views.get(v) ?? [])
391
- needed.add(f);
392
- session.islands(payload).forEach((island, i) => {
393
- const view = found[i]?.view;
394
- if (view === void 0 || view === null || !keep.has(view))
395
- needed.add(island.feature);
396
- });
397
- for (const [id, app] of apps)
398
- if (!needed.has(id)) {
399
- app.destroy();
400
- apps.delete(id);
401
- }
402
- for (const v of [...views.keys()])
403
- if (!keep.has(v))
404
- views.delete(v);
405
- const anchor = doc.getElementById("hozu-payload");
406
- let cursor = 0;
407
- const order = [...live.keys()].filter((v) => keep.has(v));
408
- for (const [ref, nodes] of fresh) {
409
- if (keep.has(ref)) {
410
- cursor++;
411
- continue;
412
- }
413
- const before = order[cursor] ? live.get(order[cursor])[0] : anchor;
414
- for (const n of nodes)
415
- doc.body.insertBefore(n, before);
248
+ function restore(doc) {
249
+ const store2 = storage(doc);
250
+ let saved = {};
251
+ try {
252
+ saved = JSON.parse(store2?.getItem(KEY) ?? "{}");
253
+ } catch {
416
254
  }
417
- for (const [ref, nodes] of live)
418
- if (!keep.has(ref))
419
- for (const n of nodes)
420
- n.remove();
421
- if (anchor)
422
- anchor.textContent = script.textContent;
423
- for (const el of doc.head.querySelectorAll(HEAD))
424
- el.remove();
425
- for (const el of next.head.querySelectorAll(HEAD))
426
- doc.head.append(el);
427
- doc.documentElement.lang = next.documentElement.lang;
428
- await session.mount(payload, found.map((f) => f.view !== null && keep.has(f.view) ? void 0 : f.marker));
429
- track(state, session, payload, found);
430
- return true;
255
+ store2?.removeItem(KEY);
256
+ return (id, machine) => {
257
+ const entry = saved[id];
258
+ if (!entry || !machine || entry.machine !== JSON.stringify(machine))
259
+ return void 0;
260
+ return machine.states[entry.snapshot.state]?.invoke ? void 0 : entry.snapshot;
261
+ };
431
262
  }
432
- function soft(session) {
433
- const { doc } = session;
263
+ function expose(doc, apps, machines) {
434
264
  const win = doc.defaultView;
435
- const script = doc.getElementById("hozu-payload");
436
- if (!win?.navigation || !script?.textContent)
265
+ if (!win)
437
266
  return;
438
- const state = { views: /* @__PURE__ */ new Map(), soft: {}, routes: {} };
439
- track(state, session, JSON.parse(script.textContent), islandsIn(doc.body));
440
- let announcer = null;
441
- let bypass = false;
442
- const announce = (title) => {
443
- if (!announcer) {
444
- announcer = doc.createElement("div");
445
- announcer.setAttribute("aria-live", "polite");
446
- announcer.style.cssText = "position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap";
447
- doc.body.append(announcer);
267
+ win.__hozu = {
268
+ save() {
269
+ const saved = {};
270
+ for (const [id, app] of apps) {
271
+ const snapshot = app.snapshot();
272
+ const machine = machines.get(id);
273
+ if (snapshot && machine)
274
+ saved[id] = { machine: JSON.stringify(machine), snapshot };
275
+ }
276
+ storage(doc)?.setItem(KEY, JSON.stringify(saved));
448
277
  }
449
- announcer.textContent = title;
450
278
  };
451
- win.navigation.addEventListener("navigate", (event) => {
452
- const e = event;
453
- if (bypass || !e.canIntercept || e.hashChange || e.downloadRequest !== null || e.formData)
454
- return;
455
- if (e.navigationType === "reload")
456
- return;
457
- const url = new URL(e.destination.url);
458
- if (url.origin !== win.location.origin)
459
- return;
460
- const target = routeOf(state.routes, url.pathname);
461
- const kept = target ? state.soft[target] : void 0;
462
- if (!kept)
463
- return;
464
- const hard = () => {
465
- bypass = true;
466
- win.location.replace(url.href);
467
- };
468
- e.intercept({
469
- handler: async () => {
470
- const root = doc.documentElement;
471
- root.setAttribute("data-hozu-navigating", "");
472
- try {
473
- const response = await win.fetch(url.href, { headers: { accept: "text/html" } });
474
- const type = response.headers.get("content-type") ?? "";
475
- if (response.status !== 200 || response.redirected || !type.includes("text/html"))
476
- return hard();
477
- const next = new win.DOMParser().parseFromString(await response.text(), "text/html");
478
- let ok = true;
479
- const run = async () => {
480
- ok = await swap(session, state, next, kept);
481
- };
482
- const transition2 = doc.startViewTransition;
483
- if (transition2)
484
- await transition2.call(doc, run).updateCallbackDone;
485
- else
486
- await run();
487
- if (!ok)
488
- return hard();
489
- announce(doc.title);
490
- } catch {
491
- hard();
492
- } finally {
493
- root.removeAttribute("data-hozu-navigating");
494
- }
495
- }
496
- });
497
- });
498
279
  }
499
- var HEAD, groups, patternOf;
500
- var init_navigate = __esm({
501
- "packages/runtime-client/dist/navigate.js"() {
280
+ var KEY, storage;
281
+ var init_dev = __esm({
282
+ "packages/runtime-client/dist/dev.js"() {
502
283
  "use strict";
503
- HEAD = 'title,meta[name=description],meta[name=robots],link[rel=canonical],meta[property],script[type="application/ld+json"]';
504
- groups = { "?": "(?:/[^/]+)?", "+": "(?:/[^/]+)+", "*": "(?:/[^/]+)*" };
505
- patternOf = (path) => {
506
- let keys = 0;
507
- const source = path.split(/(\/:[A-Za-z]\w*[?*+]?)/).map((part, i) => {
508
- if (i % 2 === 0)
509
- return part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
510
- const mod = part.at(-1);
511
- keys += mod === "+" || mod === "*" ? 1.01 : 1;
512
- return groups[mod] ?? "/[^/]+";
513
- }).join("");
514
- return { pattern: new RegExp(`^${source.replace(/\/$/, "")}/?$`), keys };
284
+ KEY = "hozu:snapshots";
285
+ storage = (doc) => {
286
+ try {
287
+ return doc.defaultView?.sessionStorage ?? null;
288
+ } catch {
289
+ return null;
290
+ }
291
+ };
292
+ }
293
+ });
294
+
295
+ // packages/runtime-client/dist/live.js
296
+ var live_exports = {};
297
+ __export(live_exports, {
298
+ liveStream: () => liveStream
299
+ });
300
+ var liveStream;
301
+ var init_live = __esm({
302
+ "packages/runtime-client/dist/live.js"() {
303
+ "use strict";
304
+ liveStream = (doc) => (onTags, tags) => {
305
+ const Source = doc.defaultView?.EventSource;
306
+ if (!Source)
307
+ return;
308
+ const url = new URL("live", import.meta.url);
309
+ for (const t of new Set(tags))
310
+ url.searchParams.append("tag", t);
311
+ new Source(url).addEventListener("message", (e) => onTags(JSON.parse(e.data)));
515
312
  };
516
313
  }
517
314
  });
@@ -520,6 +317,8 @@ var init_navigate = __esm({
520
317
  function getIn(value, path) {
521
318
  let current = value;
522
319
  for (const key of path) {
320
+ if (typeof current === "string" && key === "length")
321
+ return current.length;
523
322
  if (current === null || typeof current !== "object")
524
323
  return null;
525
324
  current = current[key];
@@ -584,8 +383,8 @@ var CompileError = class extends Error {
584
383
  name = "CompileError";
585
384
  };
586
385
  function compileValue(v, fns) {
587
- if ("literal" in v) {
588
- const literal = v.literal;
386
+ if ("literal" in v || "formRef" in v) {
387
+ const literal = "literal" in v ? v.literal : v.formRef;
589
388
  return () => literal;
590
389
  }
591
390
  if ("object" in v) {
@@ -614,16 +413,22 @@ function compileValue(v, fns) {
614
413
  const test = guard(v.test, fns);
615
414
  return (env) => test(env);
616
415
  }
617
- const { path } = v;
618
- if (v.ref === "binding") {
619
- const depth = v.depth;
416
+ if ("endpoint" in v) {
417
+ const id = v.endpoint;
418
+ const input = compileValue(v.input ?? { literal: null }, fns);
419
+ return (env) => pathOf(env.routes?.[id] ?? "", null, input(env));
420
+ }
421
+ const r = v;
422
+ const { path } = r;
423
+ if (r.ref === "binding") {
424
+ const depth = r.depth;
620
425
  return path.length ? (env) => getIn(env.bindings?.[depth], path) : (env) => env.bindings?.[depth] ?? null;
621
426
  }
622
- if (v.ref === "dom") {
427
+ if (r.ref === "dom") {
623
428
  const [field, ...rest] = path;
624
- return (env) => env.dom && field ? getIn(env.dom(field), rest) : null;
429
+ return (env) => env.dom && field ? getIn(env.dom(field), rest) ?? (field === "formAll" ? [] : null) : null;
625
430
  }
626
- const ref = v.ref;
431
+ const ref = r.ref;
627
432
  if (path.length === 0)
628
433
  return (env) => env[ref] ?? null;
629
434
  return (env) => getIn(env[ref], path);
@@ -686,7 +491,7 @@ function assign(a, fns) {
686
491
  const list = getIn(ctx, path);
687
492
  const match = v({ ...env, context: ctx });
688
493
  const items = Array.isArray(list) ? list : [];
689
- return setIn(ctx, path, items.filter((item) => !equal(item !== null && typeof item === "object" && !Array.isArray(item) ? item[key] : null, match)));
494
+ return setIn(ctx, path, items.filter((item) => !equal(key === null ? item : item !== null && typeof item === "object" && !Array.isArray(item) ? item[key] : null, match)));
690
495
  };
691
496
  }
692
497
  }
@@ -819,6 +624,27 @@ function messageOf(data, error) {
819
624
  return error;
820
625
  }
821
626
 
627
+ // packages/core/dist/ir/forms.js
628
+ function formEntries(entries, submitter) {
629
+ const first = /* @__PURE__ */ Object.create(null);
630
+ const all = /* @__PURE__ */ Object.create(null);
631
+ const add = (k, v) => {
632
+ const s = typeof v === "string" ? v : v.name;
633
+ const list = all[k];
634
+ if (list)
635
+ list.push(s);
636
+ else {
637
+ all[k] = [s];
638
+ first[k] = s;
639
+ }
640
+ };
641
+ for (const [k, v] of entries)
642
+ add(k, v);
643
+ if (submitter)
644
+ add(...submitter);
645
+ return { first, all };
646
+ }
647
+
822
648
  // packages/runtime-client/dist/dom.js
823
649
  var SVG_NS = "http://www.w3.org/2000/svg";
824
650
  var stringBooleans = /* @__PURE__ */ new Set(["contenteditable", "draggable", "spellcheck"]);
@@ -861,13 +687,12 @@ var domField = (e) => (field) => {
861
687
  return num(t?.valueAsNumber);
862
688
  case "files":
863
689
  return fileList(t?.files ?? e.dataTransfer?.files);
864
- case "form": {
865
- const out = {};
690
+ case "form":
691
+ case "formAll": {
866
692
  const form = e.target;
867
693
  const win = form.ownerDocument.defaultView;
868
- for (const [k, v] of new (win?.FormData ?? FormData)(form))
869
- out[k] = typeof v === "string" ? v : v.name;
870
- return out;
694
+ const d = formEntries(new (win?.FormData ?? FormData)(form, e.submitter));
695
+ return field === "form" ? d.first : d.all;
871
696
  }
872
697
  case "open":
873
698
  return t?.open === true;
@@ -956,7 +781,7 @@ function clear(start, end) {
956
781
  function createApp(doc, options) {
957
782
  const { machine, fns = {}, params = null, search = null, routes = {} } = options;
958
783
  const { data: payload } = store(options.payload);
959
- const ranges2 = [];
784
+ const ranges = [];
960
785
  const timers = /* @__PURE__ */ new Set();
961
786
  let first = machine ? options.snapshot ? null : init(machine) : null;
962
787
  let snapshot = options.snapshot ?? first?.snapshot ?? null;
@@ -1402,7 +1227,7 @@ function createApp(doc, options) {
1402
1227
  const block = [];
1403
1228
  const [a, b] = span(c, () => render(node, scope, c, block, ns));
1404
1229
  if (a && b)
1405
- ranges2.push([a, b]);
1230
+ ranges.push([a, b]);
1406
1231
  const connected = a?.isConnected === true;
1407
1232
  const update = () => {
1408
1233
  if (connected && !a.isConnected)
@@ -1433,10 +1258,10 @@ function createApp(doc, options) {
1433
1258
  m.stop();
1434
1259
  mounted.clear();
1435
1260
  root.length = 0;
1436
- for (const [a, b] of ranges2)
1261
+ for (const [a, b] of ranges)
1437
1262
  for (const n of range(a, b))
1438
1263
  n.remove();
1439
- ranges2.length = 0;
1264
+ ranges.length = 0;
1440
1265
  }
1441
1266
  };
1442
1267
  }
@@ -1487,12 +1312,14 @@ async function hydrate(doc, { transport = fetchTransport, query = fetchQuery, li
1487
1312
  const script = doc.getElementById("hozu-payload");
1488
1313
  if (!script?.textContent)
1489
1314
  return apps;
1490
- const shared = { data: /* @__PURE__ */ new Map(), versions: /* @__PURE__ */ new Map() };
1491
- const fns = {};
1492
- const widgets = {};
1493
- const routes = {};
1494
- const liveKeys = /* @__PURE__ */ new Map();
1495
- const loaded = {};
1315
+ const payload = JSON.parse(script.textContent);
1316
+ const shared = { data: new Map(payload.data), versions: /* @__PURE__ */ new Map() };
1317
+ const fns = payload.fns ? await loadFns(payload.fns) : {};
1318
+ const { widgets, routes } = payload;
1319
+ const motion = payload.motion ? await Promise.resolve().then(() => (init_motion(), motion_exports)) : void 0;
1320
+ const mountWidget2 = Object.keys(widgets).length ? (await Promise.resolve().then(() => (init_widget(), widget_exports))).mountWidget : void 0;
1321
+ if (payload.visible)
1322
+ void Promise.resolve().then(() => (init_visible(), visible_exports)).then((m) => m.watch(doc));
1496
1323
  const inflight = /* @__PURE__ */ new Map();
1497
1324
  const onQuery = (q, input) => {
1498
1325
  const key = q + JSON.stringify(input);
@@ -1503,106 +1330,78 @@ async function hydrate(doc, { transport = fetchTransport, query = fetchQuery, li
1503
1330
  }
1504
1331
  return pending;
1505
1332
  };
1333
+ const liveKeys = Object.entries(payload.live ?? {});
1334
+ const onTags = async (tags) => {
1335
+ if (busy)
1336
+ return void queued.push(...tags);
1337
+ const stale = liveKeys.filter(([, l]) => l.tags.some((t) => tags.includes(t)));
1338
+ for (const [key, l] of stale)
1339
+ shared.data.set(key, await query(l.query, l.input));
1340
+ if (stale.length)
1341
+ for (const app of apps.values())
1342
+ app.sync();
1343
+ };
1344
+ let busy = 0;
1345
+ let queued = [];
1506
1346
  const onInvoke = async (effect, input) => {
1507
- const { result, refreshed } = await transport(effect, input, [...shared.data.keys()]);
1347
+ busy++;
1348
+ const { result, refreshed, session } = await transport(effect, input, [...shared.data.keys()]).finally(() => busy--);
1349
+ if (session) {
1350
+ shared.data.clear();
1351
+ queued = [];
1352
+ }
1508
1353
  for (const [key, value] of refreshed) {
1509
1354
  shared.data.set(key, value);
1510
1355
  shared.versions.set(key, (shared.versions.get(key) ?? 0) + 1);
1511
1356
  }
1512
- if (refreshed.length)
1357
+ if (refreshed.length || session)
1513
1358
  for (const app of apps.values())
1514
1359
  app.sync();
1360
+ if (!busy && queued.length)
1361
+ onTags(queued.splice(0));
1515
1362
  return result;
1516
1363
  };
1517
1364
  const dev = true ? { restore: (await Promise.resolve().then(() => (init_dev(), dev_exports))).restore(doc), machines: /* @__PURE__ */ new Map() } : null;
1518
- const session = {
1519
- doc,
1520
- apps,
1521
- islands: islandsOf,
1522
- async mount(payload2, markers2) {
1523
- if (!loaded.motion && payload2.motion)
1524
- loaded.motion = await Promise.resolve().then(() => (init_motion(), motion_exports));
1525
- if (payload2.visible)
1526
- void Promise.resolve().then(() => (init_visible(), visible_exports)).then((m) => m.watch(doc));
1527
- if (!loaded.mountWidget && Object.keys(payload2.widgets).length)
1528
- loaded.mountWidget = (await Promise.resolve().then(() => (init_widget(), widget_exports))).mountWidget;
1529
- if (!loaded.fns && payload2.fns) {
1530
- Object.assign(fns, await loadFns(payload2.fns));
1531
- loaded.fns = true;
1532
- }
1533
- Object.assign(widgets, payload2.widgets);
1534
- Object.assign(routes, payload2.routes);
1535
- for (const [key, value] of payload2.data) {
1536
- if (shared.data.has(key))
1537
- shared.versions.set(key, (shared.versions.get(key) ?? 0) + 1);
1538
- shared.data.set(key, value);
1539
- }
1540
- const created = [];
1541
- for (const [id, machine] of Object.entries(payload2.features)) {
1542
- if (apps.has(id))
1543
- continue;
1544
- const snapshot = dev?.restore(id, machine) || payload2.snapshots?.[id];
1545
- if (true)
1546
- dev?.machines.set(id, machine);
1547
- const app = createApp(doc, {
1548
- machine: machine ? compileMachine({ id, machine }, fns, routes) : null,
1549
- payload: shared,
1550
- params: payload2.params,
1551
- search: payload2.search,
1552
- ...snapshot ? { snapshot } : {},
1553
- fns,
1554
- widgets,
1555
- routes,
1556
- get motion() {
1557
- return loaded.motion;
1558
- },
1559
- get mountWidget() {
1560
- return loaded.mountWidget;
1561
- },
1562
- loadWidget,
1563
- onQuery,
1564
- onInvoke,
1565
- onNavigate: (url) => doc.defaultView?.location.assign(url)
1566
- });
1567
- apps.set(id, app);
1568
- created.push(app);
1569
- }
1570
- islandsOf(payload2).forEach((island, i) => {
1571
- const at = markers2[i];
1572
- const node = payload2.nodes[island.node];
1573
- if (at?.parentNode && node)
1574
- apps.get(island.feature)?.attach(at.parentNode, at.nextSibling, node, island.scope, true);
1575
- });
1576
- for (const app of apps.values())
1577
- app.sync();
1578
- for (const app of created)
1579
- app.start();
1580
- for (const [key, l] of Object.entries(payload2.live ?? {}))
1581
- liveKeys.set(key, l);
1582
- if (liveKeys.size && !loaded.live) {
1583
- loaded.live = true;
1584
- (live ?? (await Promise.resolve().then(() => (init_live(), live_exports))).liveStream(doc))(async (tags) => {
1585
- const stale = [...liveKeys].filter(([, l]) => l.tags.some((t) => tags.includes(t)));
1586
- for (const [key, l] of stale)
1587
- shared.data.set(key, await query(l.query, l.input));
1588
- if (stale.length)
1589
- for (const app of apps.values())
1590
- app.sync();
1591
- });
1592
- }
1593
- }
1594
- };
1595
- const payload = JSON.parse(script.textContent);
1365
+ for (const [id, machine] of Object.entries(payload.features)) {
1366
+ const snapshot = dev?.restore(id, machine) || payload.snapshots?.[id];
1367
+ if (true)
1368
+ dev?.machines.set(id, machine);
1369
+ apps.set(id, createApp(doc, {
1370
+ machine: machine ? compileMachine({ id, machine }, fns, routes) : null,
1371
+ payload: shared,
1372
+ params: payload.params,
1373
+ search: payload.search,
1374
+ ...snapshot ? { snapshot } : {},
1375
+ fns,
1376
+ widgets,
1377
+ routes,
1378
+ motion,
1379
+ mountWidget: mountWidget2,
1380
+ loadWidget,
1381
+ onQuery,
1382
+ onInvoke,
1383
+ onNavigate: (url) => doc.defaultView?.location.assign(url)
1384
+ }));
1385
+ }
1596
1386
  const markers = [];
1597
1387
  const walker = doc.createTreeWalker(doc.body ?? doc, 128);
1598
1388
  while (walker.nextNode())
1599
1389
  if (walker.currentNode.data === "i")
1600
1390
  markers.push(walker.currentNode);
1601
- await session.mount(payload, markers);
1391
+ islandsOf(payload).forEach((island, i) => {
1392
+ const at = markers[i];
1393
+ const node = payload.nodes[island.node];
1394
+ if (at?.parentNode && node)
1395
+ apps.get(island.feature)?.attach(at.parentNode, at.nextSibling, node, island.scope, true);
1396
+ });
1397
+ for (const app of apps.values())
1398
+ app.sync();
1399
+ for (const app of apps.values())
1400
+ app.start();
1401
+ if (liveKeys.length)
1402
+ (live ?? (await Promise.resolve().then(() => (init_live(), live_exports))).liveStream(doc))(onTags, liveKeys.flatMap(([, l]) => l.tags));
1602
1403
  if (dev)
1603
1404
  (await Promise.resolve().then(() => (init_dev(), dev_exports))).expose(doc, apps, dev.machines);
1604
- if (payload.soft)
1605
- void Promise.resolve().then(() => (init_navigate(), navigate_exports)).then((m) => m.soft(session));
1606
1405
  doc.documentElement.setAttribute("data-hozu-ready", "");
1607
1406
  return apps;
1608
1407
  }