@hozu/runtime-client 0.1.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.
Files changed (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +15 -0
  3. package/dist/browser/chunk-7HUHKEFT.js +1 -0
  4. package/dist/browser/chunk-DRLGN2D4.js +1 -0
  5. package/dist/browser/chunk-FZY6ENWQ.js +1 -0
  6. package/dist/browser/chunk-HGZ7KQUC.js +1 -0
  7. package/dist/browser/chunk-Z7ZFHZVV.js +1 -0
  8. package/dist/browser/client.js +1 -0
  9. package/dist/browser/navigate.js +1 -0
  10. package/dist/browser-dev/client.js +1604 -0
  11. package/dist/browser.d.ts +2 -0
  12. package/dist/browser.d.ts.map +1 -0
  13. package/dist/browser.js +3 -0
  14. package/dist/browser.js.map +1 -0
  15. package/dist/dev.d.ts +6 -0
  16. package/dist/dev.d.ts.map +1 -0
  17. package/dist/dev.js +42 -0
  18. package/dist/dev.js.map +1 -0
  19. package/dist/dom.d.ts +11 -0
  20. package/dist/dom.d.ts.map +1 -0
  21. package/dist/dom.js +70 -0
  22. package/dist/dom.js.map +1 -0
  23. package/dist/files.js +1 -0
  24. package/dist/hydrate.d.ts +56 -0
  25. package/dist/hydrate.d.ts.map +1 -0
  26. package/dist/hydrate.js +163 -0
  27. package/dist/hydrate.js.map +1 -0
  28. package/dist/index.d.ts +7 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +5 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/live.d.ts +2 -0
  33. package/dist/live.d.ts.map +1 -0
  34. package/dist/live.js +7 -0
  35. package/dist/live.js.map +1 -0
  36. package/dist/motion.d.ts +5 -0
  37. package/dist/motion.d.ts.map +1 -0
  38. package/dist/motion.js +78 -0
  39. package/dist/motion.js.map +1 -0
  40. package/dist/mount.d.ts +65 -0
  41. package/dist/mount.d.ts.map +1 -0
  42. package/dist/mount.js +550 -0
  43. package/dist/mount.js.map +1 -0
  44. package/dist/navigate.d.ts +18 -0
  45. package/dist/navigate.d.ts.map +1 -0
  46. package/dist/navigate.js +197 -0
  47. package/dist/navigate.js.map +1 -0
  48. package/dist/uploads.d.ts +2 -0
  49. package/dist/uploads.d.ts.map +1 -0
  50. package/dist/uploads.js +21 -0
  51. package/dist/uploads.js.map +1 -0
  52. package/dist/visible.d.ts +2 -0
  53. package/dist/visible.d.ts.map +1 -0
  54. package/dist/visible.js +26 -0
  55. package/dist/visible.js.map +1 -0
  56. package/dist/widget.d.ts +16 -0
  57. package/dist/widget.d.ts.map +1 -0
  58. package/dist/widget.js +53 -0
  59. package/dist/widget.js.map +1 -0
  60. package/files.d.ts +1 -0
  61. package/package.json +53 -0
@@ -0,0 +1,1604 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __getOwnPropNames = Object.getOwnPropertyNames;
3
+ var __esm = (fn, res, err) => function __init() {
4
+ if (err) throw err[0];
5
+ try {
6
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
7
+ } catch (e) {
8
+ throw err = [e], e;
9
+ }
10
+ };
11
+ var __export = (target, all) => {
12
+ for (var name in all)
13
+ __defProp(target, name, { get: all[name], enumerable: true });
14
+ };
15
+
16
+ // packages/runtime-client/dist/uploads.js
17
+ var uploads_exports = {};
18
+ __export(uploads_exports, {
19
+ encode: () => encode
20
+ });
21
+ function encode(json, input, uploads2) {
22
+ const tokens = tokensIn(input, uploads2);
23
+ if (!tokens.length)
24
+ return json;
25
+ const form = new FormData();
26
+ form.append("request", json);
27
+ for (const token of tokens)
28
+ form.append(token, uploads2.get(token));
29
+ return form;
30
+ }
31
+ var tokensIn;
32
+ var init_uploads = __esm({
33
+ "packages/runtime-client/dist/uploads.js"() {
34
+ "use strict";
35
+ tokensIn = (value, uploads2, out = []) => {
36
+ if (typeof value === "string") {
37
+ if (uploads2.has(value))
38
+ out.push(value);
39
+ } else if (value && typeof value === "object")
40
+ for (const v of Object.values(value))
41
+ tokensIn(v, uploads2, out);
42
+ return out;
43
+ };
44
+ }
45
+ });
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
+ // packages/runtime-client/dist/motion.js
101
+ var motion_exports = {};
102
+ __export(motion_exports, {
103
+ enter: () => enter2,
104
+ flip: () => flip,
105
+ leave: () => leave,
106
+ reduced: () => reduced
107
+ });
108
+ function duration(el) {
109
+ const cs = el.ownerDocument.defaultView?.getComputedStyle(el);
110
+ if (!cs)
111
+ return 0;
112
+ const longest = (d, delay) => {
113
+ const a = seconds(d);
114
+ const b = seconds(delay);
115
+ return Math.max(0, ...a.map((x, i) => x + (b[i % b.length] ?? 0)));
116
+ };
117
+ return Math.max(longest(cs.transitionDuration, cs.transitionDelay), longest(cs.animationDuration, cs.animationDelay));
118
+ }
119
+ function after(el, run) {
120
+ const ms = duration(el);
121
+ if (ms === 0)
122
+ return run();
123
+ let done = false;
124
+ const finish = () => {
125
+ if (done)
126
+ return;
127
+ done = true;
128
+ el.removeEventListener("transitionend", finish);
129
+ el.removeEventListener("animationend", finish);
130
+ run();
131
+ };
132
+ el.addEventListener("transitionend", finish);
133
+ el.addEventListener("animationend", finish);
134
+ setTimeout(finish, ms + 50);
135
+ }
136
+ function phase(el, name, stage, done) {
137
+ const from = `${name}-${stage}-from`;
138
+ const active = `${name}-${stage}-active`;
139
+ const to = `${name}-${stage}-to`;
140
+ el.classList.add(from, active);
141
+ frame(el, () => {
142
+ el.classList.remove(from);
143
+ el.classList.add(to);
144
+ after(el, () => {
145
+ el.classList.remove(active, to);
146
+ done();
147
+ });
148
+ });
149
+ }
150
+ function enter2(nodes, name) {
151
+ for (const n of nodes)
152
+ if (n.nodeType === 1)
153
+ phase(n, name, "enter", () => {
154
+ });
155
+ }
156
+ function leave(nodes, name) {
157
+ for (const n of nodes)
158
+ if (n.nodeType === 1)
159
+ phase(n, name, "leave", () => n.remove());
160
+ else
161
+ n.remove();
162
+ }
163
+ function flip(el, before, name) {
164
+ const now = el.getBoundingClientRect();
165
+ const dx = before.left - now.left;
166
+ const dy = before.top - now.top;
167
+ if (!dx && !dy)
168
+ return;
169
+ const style = el.style;
170
+ style.transitionDuration = "0s";
171
+ style.transform = `translate(${dx}px, ${dy}px)`;
172
+ void el.offsetWidth;
173
+ el.classList.add(`${name}-move`);
174
+ style.transitionDuration = "";
175
+ style.transform = "";
176
+ after(el, () => el.classList.remove(`${name}-move`));
177
+ }
178
+ var seconds, frame, reduced;
179
+ var init_motion = __esm({
180
+ "packages/runtime-client/dist/motion.js"() {
181
+ "use strict";
182
+ seconds = (list) => list.split(",").map((s) => Number.parseFloat(s) * (s.trim().endsWith("ms") ? 1 : 1e3) || 0);
183
+ frame = (el, run) => {
184
+ const win = el.ownerDocument.defaultView;
185
+ if (!win?.requestAnimationFrame)
186
+ return run();
187
+ win.requestAnimationFrame(() => win.requestAnimationFrame(run));
188
+ };
189
+ reduced = (doc) => doc.defaultView?.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true;
190
+ }
191
+ });
192
+
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
+ // packages/runtime-client/dist/widget.js
231
+ var widget_exports = {};
232
+ __export(widget_exports, {
233
+ mountWidget: () => mountWidget
234
+ });
235
+ function mountWidget(h) {
236
+ const controller = new AbortController();
237
+ let props = h.props();
238
+ let instance;
239
+ const fail = (error) => {
240
+ instance = void 0;
241
+ h.doc.defaultView?.console.error(`Widget ${h.name} failed`, error);
242
+ };
243
+ const start = () => void h.load(h.ref.url).then((setup) => {
244
+ if (controller.signal.aborted)
245
+ return;
246
+ try {
247
+ instance = setup({ el: h.el, props, emit: h.emit, signal: controller.signal }) ?? void 0;
248
+ } catch (error) {
249
+ fail(error);
250
+ }
251
+ }, fail);
252
+ const win = h.doc.defaultView;
253
+ if (h.ref.load === "eager" || !win)
254
+ start();
255
+ else if (h.ref.load === "idle")
256
+ (win.requestIdleCallback ?? win.setTimeout)(start);
257
+ else if (!win.IntersectionObserver)
258
+ start();
259
+ else {
260
+ const io = new win.IntersectionObserver((entries) => {
261
+ if (!entries.some((e) => e.isIntersecting))
262
+ return;
263
+ io.disconnect();
264
+ start();
265
+ });
266
+ io.observe(h.el);
267
+ controller.signal.addEventListener("abort", () => io.disconnect());
268
+ }
269
+ h.watch(() => {
270
+ const next = h.props();
271
+ if (h.same(next, props))
272
+ return;
273
+ props = next;
274
+ try {
275
+ instance?.update?.(next);
276
+ } catch (error) {
277
+ fail(error);
278
+ }
279
+ });
280
+ h.own(() => {
281
+ controller.abort();
282
+ instance?.destroy?.();
283
+ });
284
+ }
285
+ var init_widget = __esm({
286
+ "packages/runtime-client/dist/widget.js"() {
287
+ "use strict";
288
+ }
289
+ });
290
+
291
+ // packages/runtime-client/dist/live.js
292
+ var live_exports = {};
293
+ __export(live_exports, {
294
+ liveStream: () => liveStream
295
+ });
296
+ var liveStream;
297
+ var init_live = __esm({
298
+ "packages/runtime-client/dist/live.js"() {
299
+ "use strict";
300
+ liveStream = (doc) => (onTags) => {
301
+ const Source = doc.defaultView?.EventSource;
302
+ if (!Source)
303
+ return;
304
+ new Source(new URL("live", import.meta.url)).addEventListener("message", (e) => onTags(JSON.parse(e.data)));
305
+ };
306
+ }
307
+ });
308
+
309
+ // packages/runtime-client/dist/navigate.js
310
+ var navigate_exports = {};
311
+ __export(navigate_exports, {
312
+ islandsIn: () => islandsIn,
313
+ ranges: () => ranges,
314
+ routeOf: () => routeOf,
315
+ soft: () => soft,
316
+ swap: () => swap,
317
+ track: () => track
318
+ });
319
+ function routeOf(routes, pathname) {
320
+ let best = null;
321
+ let fewest = Infinity;
322
+ for (const [id, path] of Object.entries(routes)) {
323
+ const { pattern, keys } = patternOf(path);
324
+ if (keys < fewest && pattern.test(pathname)) {
325
+ best = id;
326
+ fewest = keys;
327
+ }
328
+ }
329
+ return best;
330
+ }
331
+ function islandsIn(root) {
332
+ const found = [];
333
+ const walker = (root.ownerDocument ?? root).createTreeWalker(root, 128);
334
+ let view = null;
335
+ while (walker.nextNode()) {
336
+ const c = walker.currentNode;
337
+ if (c.data === "i")
338
+ found.push({ marker: c, view });
339
+ else if (c.data.startsWith("v:"))
340
+ view = c.data.slice(2);
341
+ else if (c.data === "/v")
342
+ view = null;
343
+ }
344
+ return found;
345
+ }
346
+ function track(state, session, payload, found) {
347
+ session.islands(payload).forEach((island, i) => {
348
+ const view = found[i]?.view;
349
+ if (!view)
350
+ return;
351
+ const owners = state.views.get(view) ?? /* @__PURE__ */ new Set();
352
+ owners.add(island.feature);
353
+ state.views.set(view, owners);
354
+ });
355
+ state.soft = payload.soft ?? {};
356
+ Object.assign(state.routes, payload.routes);
357
+ }
358
+ function ranges(body) {
359
+ const out = /* @__PURE__ */ new Map();
360
+ let current = null;
361
+ for (const n of [...body.childNodes]) {
362
+ if (n.nodeType === 8 && n.data.startsWith("v:")) {
363
+ current = [n];
364
+ out.set(n.data.slice(2), current);
365
+ } else if (current) {
366
+ current.push(n);
367
+ if (n.nodeType === 8 && n.data === "/v")
368
+ current = null;
369
+ }
370
+ }
371
+ return out;
372
+ }
373
+ async function swap(session, state, next, kept) {
374
+ const { doc, apps } = session;
375
+ const { views } = state;
376
+ const script = next.getElementById("hozu-payload");
377
+ const fresh = ranges(next.body);
378
+ const live = ranges(doc.body);
379
+ if (!script?.textContent || kept.some((v) => !fresh.has(v) || !live.has(v)))
380
+ return false;
381
+ const payload = JSON.parse(script.textContent);
382
+ const keep = new Set(kept);
383
+ const found = islandsIn(next.body);
384
+ const needed = /* @__PURE__ */ new Set();
385
+ for (const v of keep)
386
+ for (const f of views.get(v) ?? [])
387
+ needed.add(f);
388
+ session.islands(payload).forEach((island, i) => {
389
+ const view = found[i]?.view;
390
+ if (view === void 0 || view === null || !keep.has(view))
391
+ needed.add(island.feature);
392
+ });
393
+ for (const [id, app] of apps)
394
+ if (!needed.has(id)) {
395
+ app.destroy();
396
+ apps.delete(id);
397
+ }
398
+ for (const v of [...views.keys()])
399
+ if (!keep.has(v))
400
+ views.delete(v);
401
+ const anchor = doc.getElementById("hozu-payload");
402
+ let cursor = 0;
403
+ const order = [...live.keys()].filter((v) => keep.has(v));
404
+ for (const [ref, nodes] of fresh) {
405
+ if (keep.has(ref)) {
406
+ cursor++;
407
+ continue;
408
+ }
409
+ const before = order[cursor] ? live.get(order[cursor])[0] : anchor;
410
+ for (const n of nodes)
411
+ doc.body.insertBefore(n, before);
412
+ }
413
+ for (const [ref, nodes] of live)
414
+ if (!keep.has(ref))
415
+ for (const n of nodes)
416
+ n.remove();
417
+ if (anchor)
418
+ anchor.textContent = script.textContent;
419
+ for (const el of doc.head.querySelectorAll(HEAD))
420
+ el.remove();
421
+ for (const el of next.head.querySelectorAll(HEAD))
422
+ doc.head.append(el);
423
+ doc.documentElement.lang = next.documentElement.lang;
424
+ await session.mount(payload, found.map((f) => f.view !== null && keep.has(f.view) ? void 0 : f.marker));
425
+ track(state, session, payload, found);
426
+ return true;
427
+ }
428
+ function soft(session) {
429
+ const { doc } = session;
430
+ const win = doc.defaultView;
431
+ const script = doc.getElementById("hozu-payload");
432
+ if (!win?.navigation || !script?.textContent)
433
+ return;
434
+ const state = { views: /* @__PURE__ */ new Map(), soft: {}, routes: {} };
435
+ track(state, session, JSON.parse(script.textContent), islandsIn(doc.body));
436
+ let announcer = null;
437
+ let bypass = false;
438
+ const announce = (title) => {
439
+ if (!announcer) {
440
+ announcer = doc.createElement("div");
441
+ announcer.setAttribute("aria-live", "polite");
442
+ announcer.style.cssText = "position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap";
443
+ doc.body.append(announcer);
444
+ }
445
+ announcer.textContent = title;
446
+ };
447
+ win.navigation.addEventListener("navigate", (event) => {
448
+ const e = event;
449
+ if (bypass || !e.canIntercept || e.hashChange || e.downloadRequest !== null || e.formData)
450
+ return;
451
+ if (e.navigationType === "reload")
452
+ return;
453
+ const url = new URL(e.destination.url);
454
+ if (url.origin !== win.location.origin)
455
+ return;
456
+ const target = routeOf(state.routes, url.pathname);
457
+ const kept = target ? state.soft[target] : void 0;
458
+ if (!kept)
459
+ return;
460
+ const hard = () => {
461
+ bypass = true;
462
+ win.location.replace(url.href);
463
+ };
464
+ e.intercept({
465
+ handler: async () => {
466
+ const root = doc.documentElement;
467
+ root.setAttribute("data-hozu-navigating", "");
468
+ try {
469
+ const response = await win.fetch(url.href, { headers: { accept: "text/html" } });
470
+ const type = response.headers.get("content-type") ?? "";
471
+ if (response.status !== 200 || response.redirected || !type.includes("text/html"))
472
+ return hard();
473
+ const next = new win.DOMParser().parseFromString(await response.text(), "text/html");
474
+ let ok = true;
475
+ const run = async () => {
476
+ ok = await swap(session, state, next, kept);
477
+ };
478
+ const transition2 = doc.startViewTransition;
479
+ if (transition2)
480
+ await transition2.call(doc, run).updateCallbackDone;
481
+ else
482
+ await run();
483
+ if (!ok)
484
+ return hard();
485
+ announce(doc.title);
486
+ } catch {
487
+ hard();
488
+ } finally {
489
+ root.removeAttribute("data-hozu-navigating");
490
+ }
491
+ }
492
+ });
493
+ });
494
+ }
495
+ var HEAD, groups, patternOf;
496
+ var init_navigate = __esm({
497
+ "packages/runtime-client/dist/navigate.js"() {
498
+ "use strict";
499
+ HEAD = 'title,meta[name=description],meta[name=robots],link[rel=canonical],meta[property],script[type="application/ld+json"]';
500
+ groups = { "?": "(?:/[^/]+)?", "+": "(?:/[^/]+)+", "*": "(?:/[^/]+)*" };
501
+ patternOf = (path) => {
502
+ let keys = 0;
503
+ const source = path.split(/(\/:[A-Za-z]\w*[?*+]?)/).map((part, i) => {
504
+ if (i % 2 === 0)
505
+ return part.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
506
+ const mod = part.at(-1);
507
+ keys += mod === "+" || mod === "*" ? 1.01 : 1;
508
+ return groups[mod] ?? "/[^/]+";
509
+ }).join("");
510
+ return { pattern: new RegExp(`^${source.replace(/\/$/, "")}/?$`), keys };
511
+ };
512
+ }
513
+ });
514
+
515
+ // packages/machine/dist/data.js
516
+ function getIn(value, path) {
517
+ let current = value;
518
+ for (const key of path) {
519
+ if (current === null || typeof current !== "object")
520
+ return null;
521
+ current = current[key];
522
+ }
523
+ return current === void 0 ? null : current;
524
+ }
525
+ function setIn(value, path, next, i = 0) {
526
+ if (i === path.length)
527
+ return next;
528
+ const key = path[i];
529
+ if (Array.isArray(value)) {
530
+ const copy = value.slice();
531
+ copy[Number(key)] = setIn(value[Number(key)] ?? null, path, next, i + 1);
532
+ return copy;
533
+ }
534
+ const base = value !== null && typeof value === "object" ? value : {};
535
+ return { ...base, [key]: setIn(base[key] ?? null, path, next, i + 1) };
536
+ }
537
+ function equal(a, b) {
538
+ if (a === b)
539
+ return true;
540
+ if (a === null || b === null || typeof a !== "object" || typeof b !== "object")
541
+ return false;
542
+ if (Array.isArray(a)) {
543
+ if (!Array.isArray(b) || a.length !== b.length)
544
+ return false;
545
+ for (let i = 0; i < a.length; i++)
546
+ if (!equal(a[i], b[i]))
547
+ return false;
548
+ return true;
549
+ }
550
+ if (Array.isArray(b))
551
+ return false;
552
+ const ka = Object.keys(a);
553
+ if (ka.length !== Object.keys(b).length)
554
+ return false;
555
+ for (const k of ka)
556
+ if (!Object.hasOwn(b, k) || !equal(a[k], b[k]))
557
+ return false;
558
+ return true;
559
+ }
560
+ var pathOf = (pattern, params, search) => {
561
+ const [route = "", defaults = ""] = pattern.split("?");
562
+ const path = route.replace(/\/:([A-Za-z]\w*)[?*+]?/g, (_, key) => {
563
+ const x = getIn(params, [key]);
564
+ return [x ?? []].flat().map((s) => `/${encodeURIComponent(String(s))}`).join("");
565
+ }) || "/";
566
+ const skip = defaults.split("&");
567
+ let q = "";
568
+ if (search && typeof search === "object")
569
+ for (const key of Object.keys(search).sort()) {
570
+ const x = search[key];
571
+ const pair = `${encodeURIComponent(key)}=${encodeURIComponent(String(x))}`;
572
+ if (x !== null && typeof x !== "object" && !skip.includes(pair))
573
+ q += `${q && "&"}${pair}`;
574
+ }
575
+ return q ? `${path}?${q}` : path;
576
+ };
577
+
578
+ // packages/machine/dist/compile.js
579
+ var CompileError = class extends Error {
580
+ name = "CompileError";
581
+ };
582
+ function compileValue(v, fns) {
583
+ if ("literal" in v) {
584
+ const literal = v.literal;
585
+ return () => literal;
586
+ }
587
+ if ("object" in v) {
588
+ const entries = Object.entries(v.object).map(([k, x]) => [k, compileValue(x, fns)]);
589
+ return (env) => {
590
+ const out = {};
591
+ for (const [k, get] of entries)
592
+ out[k] = get(env);
593
+ return out;
594
+ };
595
+ }
596
+ if ("fn" in v) {
597
+ const impl = fns[v.fn];
598
+ if (!impl)
599
+ throw new CompileError(`No implementation bound for fn ${v.fn}`);
600
+ const arg = compileValue(v.arg, fns);
601
+ return (env) => impl(arg(env));
602
+ }
603
+ if ("link" in v) {
604
+ const id = v.link;
605
+ const params = compileValue(v.params, fns);
606
+ const search = compileValue(v.search, fns);
607
+ return (env) => pathOf(env.routes?.[id] ?? "", params(env), search(env));
608
+ }
609
+ if ("test" in v) {
610
+ const test = guard(v.test, fns);
611
+ return (env) => test(env);
612
+ }
613
+ const { path } = v;
614
+ if (v.ref === "binding") {
615
+ const depth = v.depth;
616
+ return path.length ? (env) => getIn(env.bindings?.[depth], path) : (env) => env.bindings?.[depth] ?? null;
617
+ }
618
+ if (v.ref === "dom") {
619
+ const [field, ...rest] = path;
620
+ return (env) => env.dom && field ? getIn(env.dom(field), rest) : null;
621
+ }
622
+ const ref = v.ref;
623
+ if (path.length === 0)
624
+ return (env) => env[ref] ?? null;
625
+ return (env) => getIn(env[ref], path);
626
+ }
627
+ var numeric = (x) => typeof x === "number" || typeof x === "string" ? x : Number.NaN;
628
+ function guard(g, fns) {
629
+ switch (g.op) {
630
+ case "and": {
631
+ const args = g.args.map((a) => guard(a, fns));
632
+ return (env) => args.every((t) => t(env));
633
+ }
634
+ case "or": {
635
+ const args = g.args.map((a) => guard(a, fns));
636
+ return (env) => args.some((t) => t(env));
637
+ }
638
+ case "not": {
639
+ const arg = guard(g.arg, fns);
640
+ return (env) => !arg(env);
641
+ }
642
+ case "fn": {
643
+ const call = compileValue({ fn: g.fn, arg: g.arg }, fns);
644
+ return (env) => call(env) === true;
645
+ }
646
+ default: {
647
+ const l = compileValue(g.left, fns);
648
+ const r = compileValue(g.right, fns);
649
+ switch (g.op) {
650
+ case "eq":
651
+ return (env) => equal(l(env), r(env));
652
+ case "neq":
653
+ return (env) => !equal(l(env), r(env));
654
+ case "lt":
655
+ return (env) => numeric(l(env)) < numeric(r(env));
656
+ case "lte":
657
+ return (env) => numeric(l(env)) <= numeric(r(env));
658
+ case "gt":
659
+ return (env) => numeric(l(env)) > numeric(r(env));
660
+ default:
661
+ return (env) => numeric(l(env)) >= numeric(r(env));
662
+ }
663
+ }
664
+ }
665
+ }
666
+ function assign(a, fns) {
667
+ const { path } = a;
668
+ const v = compileValue(a.value, fns);
669
+ switch (a.op) {
670
+ case "set":
671
+ return (ctx, env) => setIn(ctx, path, v({ ...env, context: ctx }));
672
+ case "append":
673
+ return (ctx, env) => {
674
+ const list = getIn(ctx, path);
675
+ return setIn(ctx, path, [...Array.isArray(list) ? list : [], v({ ...env, context: ctx })]);
676
+ };
677
+ case "inc":
678
+ return (ctx, env) => setIn(ctx, path, Number(getIn(ctx, path) ?? 0) + Number(v({ ...env, context: ctx })));
679
+ case "removeWhere": {
680
+ const key = a.key;
681
+ return (ctx, env) => {
682
+ const list = getIn(ctx, path);
683
+ const match = v({ ...env, context: ctx });
684
+ const items = Array.isArray(list) ? list : [];
685
+ return setIn(ctx, path, items.filter((item) => !equal(item !== null && typeof item === "object" && !Array.isArray(item) ? item[key] : null, match)));
686
+ };
687
+ }
688
+ }
689
+ }
690
+ var navigateTo = (url, routes) => (env) => url({ ...env, routes });
691
+ function compileMachine(feature, fns = {}, routes = {}) {
692
+ const m = feature.machine;
693
+ if (!m)
694
+ throw new CompileError(`Feature ${feature.id} has no machine`);
695
+ const names = Object.keys(m.states);
696
+ const index = new Map(names.map((n, i) => [n, i]));
697
+ const indexOf = (name) => {
698
+ const i = index.get(name);
699
+ if (i === void 0)
700
+ throw new CompileError(`Unknown state "${name}" in ${feature.id}`);
701
+ return i;
702
+ };
703
+ const transitions = [];
704
+ const compile = (t, id) => {
705
+ transitions.push(id);
706
+ return {
707
+ id,
708
+ guard: t.guard ? guard(t.guard, fns) : null,
709
+ target: indexOf(t.target),
710
+ assign: t.assign.map((a) => assign(a, fns)),
711
+ navigate: t.navigate ? navigateTo(compileValue(t.navigate, fns), routes) : null
712
+ };
713
+ };
714
+ const states = names.map((name) => {
715
+ const s = m.states[name];
716
+ const on = /* @__PURE__ */ new Map();
717
+ for (const [event, list] of Object.entries(s.on))
718
+ on.set(event, list.map((t, i) => compile(t, `${name}/on/${event}/${i}`)));
719
+ const after2 = /* @__PURE__ */ new Map();
720
+ s.after.forEach((a, i) => {
721
+ const t = compile(a.transition, `${name}/after/${i}`);
722
+ after2.set(a.ms, [...after2.get(a.ms) ?? [], t]);
723
+ });
724
+ const invoke = s.invoke;
725
+ return {
726
+ name,
727
+ final: s.final,
728
+ on,
729
+ invoke: invoke && {
730
+ effect: invoke.effect,
731
+ input: compileValue(invoke.input, fns),
732
+ done: invoke.done.map((t, i) => compile(t, `${name}/invoke/done/${i}`)),
733
+ failed: new Map(Object.entries(invoke.failed).map(([error, list]) => [
734
+ error,
735
+ list.map((t, i) => compile(t, `${name}/invoke/failed/${error}/${i}`))
736
+ ]))
737
+ },
738
+ after: after2,
739
+ timers: [...after2.keys()].sort((a, b) => a - b)
740
+ };
741
+ });
742
+ return {
743
+ feature: feature.id,
744
+ initial: indexOf(m.initial),
745
+ initialContext: m.initialContext,
746
+ states,
747
+ index,
748
+ transitions
749
+ };
750
+ }
751
+
752
+ // packages/machine/dist/transition.js
753
+ function enterEffects(machine, state, context, entry, effects) {
754
+ const s = machine.states[state];
755
+ if (s.invoke)
756
+ effects.push({ type: "invoke", entry, effect: s.invoke.effect, input: s.invoke.input({ context }) });
757
+ for (const ms of s.timers)
758
+ effects.push({ type: "timer", entry, ms });
759
+ }
760
+ function enter(machine, state, context, entry = 1) {
761
+ const index = machine.index.get(state);
762
+ if (index === void 0)
763
+ throw new Error(`Unknown state "${state}" in ${machine.feature}`);
764
+ const effects = [];
765
+ enterEffects(machine, index, context, entry, effects);
766
+ return { snapshot: { state, context, entry }, effects, taken: null };
767
+ }
768
+ var init = (machine) => enter(machine, machine.states[machine.initial].name, machine.initialContext);
769
+ var ignored = (snapshot) => ({ snapshot, effects: [], taken: null });
770
+ function fire(machine, snapshot, candidates, env) {
771
+ if (!candidates)
772
+ return ignored(snapshot);
773
+ for (const t of candidates) {
774
+ if (t.guard && !t.guard(env))
775
+ continue;
776
+ let context = snapshot.context;
777
+ for (const update of t.assign)
778
+ context = update(context, env);
779
+ const entry = snapshot.entry + 1;
780
+ const effects = t.navigate === null ? [] : [{ type: "navigate", url: String(t.navigate(env)) }];
781
+ enterEffects(machine, t.target, context, entry, effects);
782
+ return { snapshot: { state: machine.states[t.target].name, context, entry }, effects, taken: t.id };
783
+ }
784
+ return ignored(snapshot);
785
+ }
786
+ function transition(machine, snapshot, input) {
787
+ const state = machine.states[machine.index.get(snapshot.state) ?? -1];
788
+ if (!state || state.final)
789
+ return ignored(snapshot);
790
+ const context = snapshot.context;
791
+ switch (input.type) {
792
+ case "event":
793
+ return fire(machine, snapshot, state.on.get(input.event), { context, event: input.payload });
794
+ case "done":
795
+ if (input.entry !== snapshot.entry || !state.invoke)
796
+ return ignored(snapshot);
797
+ return fire(machine, snapshot, state.invoke.done, { context, result: input.result });
798
+ case "failed": {
799
+ if (input.entry !== snapshot.entry || !state.invoke)
800
+ return ignored(snapshot);
801
+ const failed = state.invoke.failed;
802
+ const declared = failed.has(input.error);
803
+ const error = declared ? input.data : { message: messageOf(input.data, input.error) };
804
+ return fire(machine, snapshot, failed.get(declared ? input.error : "Unexpected"), { context, error });
805
+ }
806
+ case "timer":
807
+ if (input.entry !== snapshot.entry)
808
+ return ignored(snapshot);
809
+ return fire(machine, snapshot, state.after.get(input.ms), { context });
810
+ }
811
+ }
812
+ function messageOf(data, error) {
813
+ if (data !== null && typeof data === "object" && !Array.isArray(data) && typeof data.message === "string")
814
+ return data.message;
815
+ return error;
816
+ }
817
+
818
+ // packages/runtime-client/dist/dom.js
819
+ var SVG_NS = "http://www.w3.org/2000/svg";
820
+ var stringBooleans = /* @__PURE__ */ new Set(["contenteditable", "draggable", "spellcheck"]);
821
+ var text = (v) => v === null || v === void 0 ? "" : typeof v === "object" ? JSON.stringify(v) : String(v);
822
+ function attrText(name, x) {
823
+ if (x === null || x === void 0)
824
+ return null;
825
+ if (typeof x === "boolean") {
826
+ if (name.startsWith("aria-") || name.startsWith("data-") || stringBooleans.has(name))
827
+ return String(x);
828
+ return x ? "" : null;
829
+ }
830
+ return text(x);
831
+ }
832
+ var properties = /* @__PURE__ */ new Set(["value", "checked", "selected", "muted"]);
833
+ var passive = /* @__PURE__ */ new Set([
834
+ "scroll",
835
+ "wheel",
836
+ "touchstart",
837
+ "touchmove",
838
+ "touchend",
839
+ "pointermove",
840
+ "mousemove"
841
+ ]);
842
+ var num = (x) => typeof x === "number" && !Number.isNaN(x) ? x : null;
843
+ var uploads = /* @__PURE__ */ new Map();
844
+ var fileList = (files) => files ? [...files].map((f) => {
845
+ const token = `u${uploads.size + 1}`;
846
+ uploads.set(token, f);
847
+ return { name: f.name, size: f.size, type: f.type, token };
848
+ }) : [];
849
+ var domField = (e) => (field) => {
850
+ const t = e.target;
851
+ switch (field) {
852
+ case "value":
853
+ return typeof t?.value === "string" ? t.value : "";
854
+ case "checked":
855
+ return t?.checked === true;
856
+ case "valueAsNumber":
857
+ return num(t?.valueAsNumber);
858
+ case "files":
859
+ return fileList(t?.files ?? e.dataTransfer?.files);
860
+ case "form": {
861
+ const out = {};
862
+ const form = e.target;
863
+ const win = form.ownerDocument.defaultView;
864
+ for (const [k, v] of new (win?.FormData ?? FormData)(form))
865
+ out[k] = typeof v === "string" ? v : v.name;
866
+ return out;
867
+ }
868
+ case "open":
869
+ return t?.open === true;
870
+ case "returnValue":
871
+ return typeof t?.returnValue === "string" ? t.returnValue : "";
872
+ default: {
873
+ const x = field in e ? e[field] : t?.[field];
874
+ return typeof x === "number" ? num(x) : typeof x === "string" || typeof x === "boolean" ? x : null;
875
+ }
876
+ }
877
+ };
878
+ var classText = (base, active) => base ? active.length ? `${base} ${active.join(" ")}` : base : active.join(" ");
879
+
880
+ // packages/core/dist/canonical/stringify.js
881
+ var quote = JSON.stringify;
882
+ function canonicalStringify(value) {
883
+ if (value === null)
884
+ return "null";
885
+ switch (typeof value) {
886
+ case "string":
887
+ return quote(value);
888
+ case "boolean":
889
+ return value ? "true" : "false";
890
+ case "number":
891
+ if (!Number.isFinite(value))
892
+ throw new TypeError(`Non-finite number ${value} is not valid JSON`);
893
+ return Object.is(value, -0) ? "0" : String(value);
894
+ case "object": {
895
+ if (Array.isArray(value))
896
+ return `[${value.map(canonicalStringify).join(",")}]`;
897
+ const obj = value;
898
+ const keys = Object.keys(obj).sort();
899
+ let out = "{";
900
+ for (let i = 0; i < keys.length; i++) {
901
+ const key = keys[i];
902
+ const v = obj[key];
903
+ if (v === void 0)
904
+ throw new TypeError(`Undefined value at key "${key}"`);
905
+ out += `${i ? "," : ""}${quote(key)}:${canonicalStringify(v)}`;
906
+ }
907
+ return `${out}}`;
908
+ }
909
+ default:
910
+ throw new TypeError(`Value of type ${typeof value} is not valid JSON`);
911
+ }
912
+ }
913
+
914
+ // packages/runtime-client/dist/mount.js
915
+ var guardReads = (g) => {
916
+ switch (g.op) {
917
+ case "and":
918
+ case "or":
919
+ return g.args.some(guardReads);
920
+ case "not":
921
+ return guardReads(g.arg);
922
+ case "fn":
923
+ return reads(g.arg);
924
+ default:
925
+ return reads(g.left) || reads(g.right);
926
+ }
927
+ };
928
+ var reads = (v) => "ref" in v ? v.ref === "context" || v.ref === "binding" : "object" in v ? Object.values(v.object).some(reads) : "fn" in v ? reads(v.arg) : "test" in v && guardReads(v.test);
929
+ var payloadKey = (query, input) => query + canonicalStringify(input);
930
+ var store = (payload) => payload instanceof Map ? { data: payload, versions: /* @__PURE__ */ new Map() } : payload;
931
+ var isComment = (n, data) => n !== null && n.nodeType === 8 && n.data === data;
932
+ function range(first, last) {
933
+ const out = [first];
934
+ let n = first;
935
+ while (n !== last) {
936
+ n = n.nextSibling;
937
+ if (!n)
938
+ break;
939
+ out.push(n);
940
+ }
941
+ return out;
942
+ }
943
+ function span(c, run) {
944
+ const prev = c.next ? c.next.previousSibling : c.parent.lastChild;
945
+ run();
946
+ return [prev ? prev.nextSibling : c.parent.firstChild, c.next ? c.next.previousSibling : c.parent.lastChild];
947
+ }
948
+ function clear(start, end) {
949
+ while (start.nextSibling && start.nextSibling !== end)
950
+ start.nextSibling.remove();
951
+ }
952
+ function createApp(doc, options) {
953
+ const { machine, fns = {}, params = null, search = null, routes = {} } = options;
954
+ const { data: payload } = store(options.payload);
955
+ const ranges2 = [];
956
+ const timers = /* @__PURE__ */ new Set();
957
+ let first = machine ? options.snapshot ? null : init(machine) : null;
958
+ let snapshot = options.snapshot ?? first?.snapshot ?? null;
959
+ const root = [];
960
+ const detached = /* @__PURE__ */ new Set();
961
+ const mounted = /* @__PURE__ */ new Set();
962
+ const getters = /* @__PURE__ */ new WeakMap();
963
+ const value = (v, scope, dom) => {
964
+ let get = getters.get(v);
965
+ if (!get) {
966
+ get = compileValue(v, fns);
967
+ getters.set(v, get);
968
+ }
969
+ return get({
970
+ context: snapshot?.context ?? null,
971
+ bindings: scope,
972
+ params,
973
+ search,
974
+ routes,
975
+ ...dom ? { dom } : {}
976
+ });
977
+ };
978
+ const bind = (block, v, scope, apply) => {
979
+ let last = value(v, scope);
980
+ apply(last);
981
+ if (reads(v))
982
+ block.push(() => {
983
+ const next = value(v, scope);
984
+ if (next === last)
985
+ return;
986
+ last = next;
987
+ apply(next);
988
+ });
989
+ };
990
+ const marker = (c, data) => {
991
+ if (c.claim && isComment(c.next, data)) {
992
+ const m = c.next;
993
+ c.next = m.nextSibling;
994
+ return m;
995
+ }
996
+ return c.parent.insertBefore(doc.createComment(data), c.next);
997
+ };
998
+ const skip = (c) => {
999
+ if (!c.claim || !isComment(c.next, "["))
1000
+ return;
1001
+ let depth = 0;
1002
+ while (c.next) {
1003
+ const n = c.next;
1004
+ c.next = n.nextSibling;
1005
+ if (isComment(n, "["))
1006
+ depth++;
1007
+ else if (isComment(n, "]") && --depth === 0)
1008
+ return;
1009
+ }
1010
+ };
1011
+ const render = (node, scope, c, block, ns) => {
1012
+ switch (node.kind) {
1013
+ case "text": {
1014
+ let t;
1015
+ if (c.claim && c.next?.nodeType === 3) {
1016
+ t = c.next;
1017
+ c.next = t.nextSibling;
1018
+ } else
1019
+ t = c.parent.insertBefore(doc.createTextNode(""), c.next);
1020
+ if (c.claim && isComment(c.next, ""))
1021
+ c.next = c.next.nextSibling;
1022
+ bind(block, node.value, scope, (x) => {
1023
+ const s = text(x);
1024
+ if (t.data !== s)
1025
+ t.data = s;
1026
+ });
1027
+ return;
1028
+ }
1029
+ case "el": {
1030
+ const tag = node.tag;
1031
+ const space = tag === "svg" ? SVG_NS : ns;
1032
+ let el;
1033
+ const claimed = c.claim && c.next?.nodeType === 1 && c.next.localName === tag;
1034
+ if (claimed) {
1035
+ el = c.next;
1036
+ c.next = el.nextSibling;
1037
+ } else {
1038
+ el = space ? doc.createElementNS(space, tag) : doc.createElement(tag);
1039
+ if (node.class)
1040
+ el.setAttribute("class", node.class);
1041
+ c.parent.insertBefore(el, c.next);
1042
+ }
1043
+ for (const name in node.attrs) {
1044
+ const v = node.attrs[name];
1045
+ const prop = properties.has(name) && name in el;
1046
+ if (claimed && !reads(v))
1047
+ continue;
1048
+ bind(block, v, scope, (x) => {
1049
+ if (prop) {
1050
+ const p = el;
1051
+ const next = name === "value" ? text(x) : x === true;
1052
+ if (p[name] !== next)
1053
+ p[name] = next;
1054
+ return;
1055
+ }
1056
+ const s = attrText(name, x);
1057
+ if (s === null)
1058
+ el.removeAttribute(name);
1059
+ else if (el.getAttribute(name) !== s)
1060
+ el.setAttribute(name, s);
1061
+ });
1062
+ }
1063
+ styling(el, node, scope, block);
1064
+ for (const event in node.on) {
1065
+ const send = node.on[event];
1066
+ el.addEventListener(event, (e) => {
1067
+ if (event === "submit")
1068
+ e.preventDefault();
1069
+ dispatch({ type: "event", event: send.event, payload: value(send.payload, scope, domField(e)) });
1070
+ }, passive.has(event) ? { passive: true } : void 0);
1071
+ }
1072
+ if (tag === "textarea")
1073
+ return;
1074
+ const inner = { parent: el, next: claimed ? el.firstChild : null, claim: claimed };
1075
+ const childNs = tag === "foreignObject" ? null : space;
1076
+ for (const child of node.children)
1077
+ render(child, scope, inner, block, childNs);
1078
+ return;
1079
+ }
1080
+ case "when": {
1081
+ const visible = () => snapshot ? node.states.includes(snapshot.state) : false;
1082
+ region(c, block, visible, (cc, inner) => {
1083
+ if (visible())
1084
+ for (const child of node.children)
1085
+ render(child, scope, cc, inner, ns);
1086
+ }, node.motion);
1087
+ return;
1088
+ }
1089
+ case "query": {
1090
+ let bound = scope;
1091
+ const key = () => {
1092
+ const k = payloadKey(node.query, value(node.input, scope));
1093
+ const r = payload.get(k);
1094
+ if (r && bound !== scope)
1095
+ bound.splice(0, bound.length, ...scope, r.ok ? r.value : r.data);
1096
+ return `${k}|${!r ? "" : r.ok ? "ready" : node.failed[r.error] ? r.error : "Unexpected"}`;
1097
+ };
1098
+ region(c, block, key, (cc, inner) => {
1099
+ const input = value(node.input, scope);
1100
+ const k = payloadKey(node.query, input);
1101
+ const result = payload.get(k);
1102
+ bound = scope;
1103
+ if (!result) {
1104
+ if (!cc.claim)
1105
+ request(k, node.query, input);
1106
+ if (node.pending)
1107
+ render(node.pending, scope, cc, inner, ns);
1108
+ return;
1109
+ }
1110
+ const branch = result.ok ? node.ready : node.failed[result.error] ?? node.failed.Unexpected;
1111
+ bound = [...scope, result.ok ? result.value : result.data];
1112
+ if (branch)
1113
+ render(branch, bound, cc, inner, ns);
1114
+ });
1115
+ return;
1116
+ }
1117
+ case "each":
1118
+ each(node, scope, c, block, ns);
1119
+ return;
1120
+ case "widget":
1121
+ widget(node, scope, c, block);
1122
+ return;
1123
+ case "if": {
1124
+ const test = () => value({ test: node.test }, scope) === true;
1125
+ region(c, block, test, (cc, inner) => {
1126
+ const branch = test() ? node.ifTrue : node.ifFalse;
1127
+ for (const child of branch)
1128
+ render(child, scope, cc, inner, ns);
1129
+ }, node.motion);
1130
+ return;
1131
+ }
1132
+ case "html": {
1133
+ const start = marker(c, "[");
1134
+ let end;
1135
+ if (c.claim) {
1136
+ while (c.next && !isComment(c.next, "]"))
1137
+ c.next = c.next.nextSibling;
1138
+ end = c.next ?? c.parent.appendChild(doc.createComment("]"));
1139
+ c.next = end.nextSibling;
1140
+ } else
1141
+ end = marker(c, "]");
1142
+ let last = c.claim ? text(value(node.value, scope)) : null;
1143
+ bind(block, node.value, scope, (x) => {
1144
+ const html = text(x);
1145
+ if (html === last)
1146
+ return;
1147
+ last = html;
1148
+ clear(start, end);
1149
+ const t = doc.createElement("template");
1150
+ t.innerHTML = html;
1151
+ end.parentNode.insertBefore(t.content, end);
1152
+ });
1153
+ return;
1154
+ }
1155
+ case "global": {
1156
+ const anchor = marker(c, "g");
1157
+ const target = node.target === "window" ? doc.defaultView : doc;
1158
+ const stops = [];
1159
+ for (const event in node.on) {
1160
+ const send = node.on[event];
1161
+ const listener = (e) => dispatch({ type: "event", event: send.event, payload: value(send.payload, scope, domField(e)) });
1162
+ const opts = passive.has(event) ? { passive: true } : void 0;
1163
+ target.addEventListener(event, listener, opts);
1164
+ stops.push(() => target.removeEventListener(event, listener));
1165
+ }
1166
+ mounted.add({ el: anchor, stop: () => stops.forEach((s) => s()) });
1167
+ return;
1168
+ }
1169
+ default:
1170
+ skip(c);
1171
+ }
1172
+ };
1173
+ const styling = (el, node, scope, block) => {
1174
+ const toggles = Object.entries(node.toggle);
1175
+ if (toggles.length) {
1176
+ const cls = () => {
1177
+ const active = [];
1178
+ for (const [c, v] of toggles)
1179
+ if (value(v, scope) === true)
1180
+ active.push(c);
1181
+ return classText(node.class, active);
1182
+ };
1183
+ let last = cls();
1184
+ if (el.getAttribute("class") !== last)
1185
+ el.setAttribute("class", last);
1186
+ if (toggles.some(([, v]) => reads(v)))
1187
+ block.push(() => {
1188
+ const next = cls();
1189
+ if (next === last)
1190
+ return;
1191
+ last = next;
1192
+ el.setAttribute("class", next);
1193
+ });
1194
+ }
1195
+ for (const name in node.vars)
1196
+ bind(block, node.vars[name], scope, (x) => {
1197
+ const style = el.style;
1198
+ if (x === null || x === "")
1199
+ style.removeProperty(name);
1200
+ else if (style.getPropertyValue(name) !== text(x))
1201
+ style.setProperty(name, text(x));
1202
+ });
1203
+ };
1204
+ const widget = (node, scope, c, block) => {
1205
+ const ref = options.widgets?.[node.widget];
1206
+ const tag = ref?.tag ?? "div";
1207
+ let el;
1208
+ const claimed = c.claim && c.next?.nodeType === 1 && c.next.localName === tag;
1209
+ if (claimed) {
1210
+ el = c.next;
1211
+ c.next = el.nextSibling;
1212
+ } else {
1213
+ el = doc.createElement(tag);
1214
+ if (node.class)
1215
+ el.setAttribute("class", node.class);
1216
+ c.parent.insertBefore(el, c.next);
1217
+ }
1218
+ styling(el, node, scope, block);
1219
+ if (!claimed || ref?.wraps) {
1220
+ const inner = { parent: el, next: claimed ? el.firstChild : null, claim: claimed };
1221
+ for (const child of node.children)
1222
+ render(child, scope, inner, block, null);
1223
+ }
1224
+ if (!ref || !options.loadWidget || !options.mountWidget)
1225
+ return;
1226
+ options.mountWidget({
1227
+ el,
1228
+ ref,
1229
+ name: node.widget,
1230
+ doc,
1231
+ props: () => value(node.props, scope),
1232
+ emit: (name, detail) => {
1233
+ const send = node.on[name];
1234
+ if (send)
1235
+ dispatch({
1236
+ type: "event",
1237
+ event: send.event,
1238
+ payload: value(send.payload, scope, (f) => f === "detail" ? detail : null)
1239
+ });
1240
+ },
1241
+ load: options.loadWidget,
1242
+ watch: (update) => block.push(update),
1243
+ own: (stop) => mounted.add({ el, stop }),
1244
+ same: equal
1245
+ });
1246
+ };
1247
+ const fetching = /* @__PURE__ */ new Set();
1248
+ const request = (key, query, input) => {
1249
+ if (!options.onQuery || fetching.has(key))
1250
+ return;
1251
+ fetching.add(key);
1252
+ void options.onQuery(query, input).then((result) => {
1253
+ fetching.delete(key);
1254
+ payload.set(key, result);
1255
+ for (const u of root)
1256
+ u();
1257
+ sweep();
1258
+ });
1259
+ };
1260
+ const sweep = () => {
1261
+ for (let i = root.length - 1; i >= 0; i--)
1262
+ if (detached.delete(root[i]))
1263
+ root.splice(i, 1);
1264
+ for (const m of mounted)
1265
+ if (!m.el.isConnected) {
1266
+ m.stop();
1267
+ mounted.delete(m);
1268
+ }
1269
+ };
1270
+ const region = (c, block, key, fill, motion = null) => {
1271
+ const start = marker(c, "[");
1272
+ let current = key();
1273
+ let inner = [];
1274
+ fill(c, inner);
1275
+ const end = marker(c, "]");
1276
+ block.push(() => {
1277
+ const next = key();
1278
+ if (next === current) {
1279
+ for (const u of inner)
1280
+ u();
1281
+ return;
1282
+ }
1283
+ current = next;
1284
+ inner = [];
1285
+ const m = options.motion;
1286
+ if (!motion || !m || m.reduced(doc)) {
1287
+ clear(start, end);
1288
+ fill({ parent: end.parentNode, next: end, claim: false }, inner);
1289
+ return;
1290
+ }
1291
+ m.leave(start.nextSibling === end ? [] : range(start.nextSibling, end.previousSibling), motion);
1292
+ const [a, b] = span({ parent: end.parentNode, next: end, claim: false }, () => fill({ parent: end.parentNode, next: end, claim: false }, inner));
1293
+ if (a && b && a !== end)
1294
+ m.enter(range(a, b), motion);
1295
+ });
1296
+ };
1297
+ const each = (node, scope, c, block, ns) => {
1298
+ const start = marker(c, "[");
1299
+ const keyOf = (x) => {
1300
+ const k = node.key === null ? x : getIn(x, [node.key]);
1301
+ return typeof k === "string" ? `s${k}` : JSON.stringify(k);
1302
+ };
1303
+ const list = () => {
1304
+ const x = value(node.source, scope);
1305
+ return Array.isArray(x) ? x : [];
1306
+ };
1307
+ const make = (x, cc) => {
1308
+ const s = [...scope, x];
1309
+ const b = [];
1310
+ const [firstNode, lastNode] = span(cc, () => render(node.item, s, cc, b, ns));
1311
+ return { key: keyOf(x), value: x, scope: s, block: b, first: firstNode, last: lastNode };
1312
+ };
1313
+ let items = list().map((x) => make(x, c));
1314
+ const end = marker(c, "]");
1315
+ block.push(() => {
1316
+ const m = options.motion;
1317
+ const motion = node.motion && m && !m.reduced(doc) ? node.motion : null;
1318
+ const rects = motion ? new Map(items.flatMap((i) => i.first.nodeType === 1 ? [[i, i.first.getBoundingClientRect()]] : [])) : null;
1319
+ const old = new Map(items.map((i) => [i.key, i]));
1320
+ const fresh = /* @__PURE__ */ new Set();
1321
+ const next = [];
1322
+ for (const x of list()) {
1323
+ const k = keyOf(x);
1324
+ const hit = old.get(k);
1325
+ if (hit) {
1326
+ old.delete(k);
1327
+ hit.value = x;
1328
+ hit.scope.splice(0, hit.scope.length, ...scope, x);
1329
+ for (const u of hit.block)
1330
+ u();
1331
+ next.push(hit);
1332
+ } else {
1333
+ const item = make(x, { parent: doc.createDocumentFragment(), next: null, claim: false });
1334
+ fresh.add(item);
1335
+ next.push(item);
1336
+ }
1337
+ }
1338
+ for (const gone of old.values())
1339
+ if (motion)
1340
+ m.leave(range(gone.first, gone.last), motion);
1341
+ else
1342
+ for (const n of range(gone.first, gone.last))
1343
+ n.remove();
1344
+ const parent = end.parentNode;
1345
+ let at = start.nextSibling ?? end;
1346
+ for (const item of next) {
1347
+ if (item.first === at)
1348
+ at = item.last.nextSibling ?? end;
1349
+ else
1350
+ for (const n of range(item.first, item.last))
1351
+ parent.insertBefore(n, at);
1352
+ }
1353
+ items = next;
1354
+ if (!motion)
1355
+ return;
1356
+ for (const item of next)
1357
+ if (fresh.has(item))
1358
+ m.enter(range(item.first, item.last), motion);
1359
+ else {
1360
+ const before = rects?.get(item);
1361
+ if (before)
1362
+ m.flip(item.first, before, motion);
1363
+ }
1364
+ });
1365
+ };
1366
+ const effects = (step) => {
1367
+ for (const e of step.effects) {
1368
+ if (e.type === "navigate")
1369
+ options.onNavigate?.(e.url);
1370
+ else if (e.type === "timer") {
1371
+ const t = setTimeout(() => {
1372
+ timers.delete(t);
1373
+ dispatch({ type: "timer", entry: e.entry, ms: e.ms });
1374
+ }, e.ms);
1375
+ timers.add(t);
1376
+ } else
1377
+ options.onInvoke?.(e.effect, e.input).then((r) => dispatch(r.ok ? { type: "done", entry: e.entry, result: r.value } : { type: "failed", entry: e.entry, error: r.error, data: r.data }));
1378
+ }
1379
+ };
1380
+ function dispatch(input) {
1381
+ if (!machine || !snapshot)
1382
+ return;
1383
+ const step = transition(machine, snapshot, input);
1384
+ if (!step.taken)
1385
+ return;
1386
+ snapshot = step.snapshot;
1387
+ for (const u of root)
1388
+ u();
1389
+ sweep();
1390
+ effects(step);
1391
+ }
1392
+ return {
1393
+ attach(parent, before, node, scope, claim) {
1394
+ const c = { parent, next: before, claim };
1395
+ const ns = parent.namespaceURI === SVG_NS ? SVG_NS : null;
1396
+ const block = [];
1397
+ const [a, b] = span(c, () => render(node, scope, c, block, ns));
1398
+ if (a && b)
1399
+ ranges2.push([a, b]);
1400
+ const connected = a?.isConnected === true;
1401
+ const update = () => {
1402
+ if (connected && !a.isConnected)
1403
+ detached.add(update);
1404
+ else
1405
+ for (const u of block)
1406
+ u();
1407
+ };
1408
+ root.push(update);
1409
+ },
1410
+ start() {
1411
+ if (first)
1412
+ effects(first);
1413
+ first = null;
1414
+ },
1415
+ sync: () => {
1416
+ for (const u of root)
1417
+ u();
1418
+ sweep();
1419
+ },
1420
+ dispatch,
1421
+ snapshot: () => snapshot,
1422
+ destroy: () => {
1423
+ for (const t of timers)
1424
+ clearTimeout(t);
1425
+ timers.clear();
1426
+ for (const m of mounted)
1427
+ m.stop();
1428
+ mounted.clear();
1429
+ root.length = 0;
1430
+ for (const [a, b] of ranges2)
1431
+ for (const n of range(a, b))
1432
+ n.remove();
1433
+ ranges2.length = 0;
1434
+ }
1435
+ };
1436
+ }
1437
+
1438
+ // packages/runtime-client/dist/hydrate.js
1439
+ var __rewriteRelativeImportExtension = function(path, preserveJsx) {
1440
+ if (typeof path === "string" && /^\.\.?\//.test(path)) {
1441
+ return path.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i, function(m, tsx, d, ext, cm) {
1442
+ return tsx ? preserveJsx ? ".jsx" : ".js" : d && (!ext || !cm) ? m : d + ext + "." + cm.toLowerCase() + "js";
1443
+ });
1444
+ }
1445
+ return path;
1446
+ };
1447
+ var islandsOf = (payload) => payload.islands.flatMap(([n, lead, ...tails]) => {
1448
+ const node = payload.ids[n];
1449
+ const feature = node.slice(0, node.indexOf("."));
1450
+ return tails.map((tail) => ({ feature, node, scope: [...Array(lead).fill(null), ...tail] }));
1451
+ });
1452
+ var endpoint = (name) => new URL(name, import.meta.url);
1453
+ var fetchTransport = async (effect, input, keys) => {
1454
+ const json = JSON.stringify({ effect, input, keys });
1455
+ const body = uploads.size ? await (await Promise.resolve().then(() => (init_uploads(), uploads_exports))).encode(json, input, uploads) : json;
1456
+ const response = await fetch(endpoint("effect"), {
1457
+ method: "POST",
1458
+ headers: typeof body === "string" ? { "content-type": "application/json" } : {},
1459
+ body
1460
+ });
1461
+ return await response.json();
1462
+ };
1463
+ var fetchQuery = async (query, input) => {
1464
+ const response = await fetch(endpoint("query"), {
1465
+ method: "POST",
1466
+ headers: { "content-type": "application/json" },
1467
+ body: JSON.stringify({ query, input })
1468
+ });
1469
+ return await response.json();
1470
+ };
1471
+ var importWidget = async (url) => (await import(__rewriteRelativeImportExtension(
1472
+ /* @vite-ignore */
1473
+ url
1474
+ ))).default;
1475
+ var importFns = async (url) => (await import(__rewriteRelativeImportExtension(
1476
+ /* @vite-ignore */
1477
+ url
1478
+ ))).fns;
1479
+ async function hydrate(doc, { transport = fetchTransport, query = fetchQuery, live, loadFns = importFns, loadWidget = importWidget } = {}) {
1480
+ const apps = /* @__PURE__ */ new Map();
1481
+ const script = doc.getElementById("hozu-payload");
1482
+ if (!script?.textContent)
1483
+ return apps;
1484
+ const shared = { data: /* @__PURE__ */ new Map(), versions: /* @__PURE__ */ new Map() };
1485
+ const fns = {};
1486
+ const widgets = {};
1487
+ const routes = {};
1488
+ const liveKeys = /* @__PURE__ */ new Map();
1489
+ const loaded = {};
1490
+ const inflight = /* @__PURE__ */ new Map();
1491
+ const onQuery = (q, input) => {
1492
+ const key = q + JSON.stringify(input);
1493
+ let pending = inflight.get(key);
1494
+ if (!pending) {
1495
+ pending = query(q, input).finally(() => inflight.delete(key));
1496
+ inflight.set(key, pending);
1497
+ }
1498
+ return pending;
1499
+ };
1500
+ const onInvoke = async (effect, input) => {
1501
+ const { result, refreshed } = await transport(effect, input, [...shared.data.keys()]);
1502
+ for (const [key, value] of refreshed) {
1503
+ shared.data.set(key, value);
1504
+ shared.versions.set(key, (shared.versions.get(key) ?? 0) + 1);
1505
+ }
1506
+ if (refreshed.length)
1507
+ for (const app of apps.values())
1508
+ app.sync();
1509
+ return result;
1510
+ };
1511
+ const dev = true ? { restore: (await Promise.resolve().then(() => (init_dev(), dev_exports))).restore(doc), machines: /* @__PURE__ */ new Map() } : null;
1512
+ const session = {
1513
+ doc,
1514
+ apps,
1515
+ islands: islandsOf,
1516
+ async mount(payload2, markers2) {
1517
+ if (!loaded.motion && payload2.motion)
1518
+ loaded.motion = await Promise.resolve().then(() => (init_motion(), motion_exports));
1519
+ if (payload2.visible)
1520
+ void Promise.resolve().then(() => (init_visible(), visible_exports)).then((m) => m.watch(doc));
1521
+ if (!loaded.mountWidget && Object.keys(payload2.widgets).length)
1522
+ loaded.mountWidget = (await Promise.resolve().then(() => (init_widget(), widget_exports))).mountWidget;
1523
+ if (!loaded.fns && payload2.fns) {
1524
+ Object.assign(fns, await loadFns(payload2.fns));
1525
+ loaded.fns = true;
1526
+ }
1527
+ Object.assign(widgets, payload2.widgets);
1528
+ Object.assign(routes, payload2.routes);
1529
+ for (const [key, value] of payload2.data) {
1530
+ if (shared.data.has(key))
1531
+ shared.versions.set(key, (shared.versions.get(key) ?? 0) + 1);
1532
+ shared.data.set(key, value);
1533
+ }
1534
+ const created = [];
1535
+ for (const [id, machine] of Object.entries(payload2.features)) {
1536
+ if (apps.has(id))
1537
+ continue;
1538
+ const snapshot = dev?.restore(id, machine) || payload2.snapshots?.[id];
1539
+ if (true)
1540
+ dev?.machines.set(id, machine);
1541
+ const app = createApp(doc, {
1542
+ machine: machine ? compileMachine({ id, machine }, fns, routes) : null,
1543
+ payload: shared,
1544
+ params: payload2.params,
1545
+ search: payload2.search,
1546
+ ...snapshot ? { snapshot } : {},
1547
+ fns,
1548
+ widgets,
1549
+ routes,
1550
+ get motion() {
1551
+ return loaded.motion;
1552
+ },
1553
+ get mountWidget() {
1554
+ return loaded.mountWidget;
1555
+ },
1556
+ loadWidget,
1557
+ onQuery,
1558
+ onInvoke,
1559
+ onNavigate: (url) => doc.defaultView?.location.assign(url)
1560
+ });
1561
+ apps.set(id, app);
1562
+ created.push(app);
1563
+ }
1564
+ islandsOf(payload2).forEach((island, i) => {
1565
+ const at = markers2[i];
1566
+ const node = payload2.nodes[island.node];
1567
+ if (at?.parentNode && node)
1568
+ apps.get(island.feature)?.attach(at.parentNode, at.nextSibling, node, island.scope, true);
1569
+ });
1570
+ for (const app of apps.values())
1571
+ app.sync();
1572
+ for (const app of created)
1573
+ app.start();
1574
+ for (const [key, l] of Object.entries(payload2.live ?? {}))
1575
+ liveKeys.set(key, l);
1576
+ if (liveKeys.size && !loaded.live) {
1577
+ loaded.live = true;
1578
+ (live ?? (await Promise.resolve().then(() => (init_live(), live_exports))).liveStream(doc))(async (tags) => {
1579
+ const stale = [...liveKeys].filter(([, l]) => l.tags.some((t) => tags.includes(t)));
1580
+ for (const [key, l] of stale)
1581
+ shared.data.set(key, await query(l.query, l.input));
1582
+ if (stale.length)
1583
+ for (const app of apps.values())
1584
+ app.sync();
1585
+ });
1586
+ }
1587
+ }
1588
+ };
1589
+ const payload = JSON.parse(script.textContent);
1590
+ const markers = [];
1591
+ const walker = doc.createTreeWalker(doc.body ?? doc, 128);
1592
+ while (walker.nextNode())
1593
+ if (walker.currentNode.data === "i")
1594
+ markers.push(walker.currentNode);
1595
+ await session.mount(payload, markers);
1596
+ if (dev)
1597
+ (await Promise.resolve().then(() => (init_dev(), dev_exports))).expose(doc, apps, dev.machines);
1598
+ if (payload.soft)
1599
+ void Promise.resolve().then(() => (init_navigate(), navigate_exports)).then((m) => m.soft(session));
1600
+ return apps;
1601
+ }
1602
+
1603
+ // packages/runtime-client/dist/browser.js
1604
+ void hydrate(document);