@source-crafter/xzor-runtime 0.1.9 → 0.1.10

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/index.js CHANGED
@@ -1,979 +1,55 @@
1
- // runtime/index.ts
2
- class Route {
3
- path;
4
- tag;
5
- params;
6
- query;
7
- match;
8
- #nav;
9
- constructor(path, tag, params, query, match, nav) {
10
- this.path = path;
11
- this.tag = tag;
12
- this.params = params;
13
- this.query = query;
14
- this.match = match;
15
- this.#nav = nav;
16
- }
17
- is(tag) {
18
- return this.tag === tag;
19
- }
20
- navigate(url, opts) {
21
- if (this.#nav)
22
- this.#nav.navigate(url, opts?.replace === true);
23
- else
24
- location.href = url;
25
- }
26
- }
27
- var navigated = new Set;
28
- var observers = new Set;
29
- var EXTERNAL = /(^|\s)external(\s|$)/;
30
- function notifyNavigated() {
31
- for (const fn of [...navigated])
32
- fn();
33
- for (const fn of [...observers])
34
- fn();
35
- }
36
- var onPopState = () => notifyNavigated();
37
- function onLinkClick(e) {
38
- if (e.defaultPrevented || e.button !== 0 || e.ctrlKey || e.metaKey || e.shiftKey || e.altKey)
39
- return;
40
- const anchor = e.target?.closest?.("a");
41
- const href = anchor?.getAttribute("href");
42
- if (!anchor || href == null || href.startsWith("#"))
43
- return;
44
- const frame = anchor.getAttribute("target");
45
- if (frame !== null && frame !== "_self" || anchor.hasAttribute("download"))
46
- return;
47
- const rel = anchor.getAttribute("rel");
48
- if (rel !== null && EXTERNAL.test(rel))
49
- return;
50
- const url = new URL(href, document.baseURI);
51
- if (url.origin !== location.origin)
52
- return;
53
- if (url.hash !== "" && url.pathname === location.pathname && url.search === location.search)
54
- return;
55
- e.preventDefault();
56
- browserNavigation.navigate(url.href, false);
57
- }
58
- var currentUrl;
59
- var browserNavigation = {
60
- current: () => currentUrl?.href === location.href ? currentUrl : currentUrl = new URL(location.href),
61
- navigate(url, replace) {
62
- const href = new URL(url, document.baseURI).href;
63
- if (replace)
64
- history.replaceState(null, "", href);
65
- else
66
- history.pushState(null, "", href);
67
- notifyNavigated();
68
- },
69
- subscribe(fn) {
70
- navigated.add(fn);
71
- if (navigated.size === 1) {
72
- if (observers.size === 0)
73
- window.addEventListener("popstate", onPopState);
74
- document.addEventListener("click", onLinkClick);
75
- }
76
- return () => {
77
- navigated.delete(fn);
78
- if (navigated.size === 0) {
79
- if (observers.size === 0)
80
- window.removeEventListener("popstate", onPopState);
81
- document.removeEventListener("click", onLinkClick);
82
- }
83
- };
84
- },
85
- observe(fn) {
86
- observers.add(fn);
87
- if (observers.size === 1 && navigated.size === 0)
88
- window.addEventListener("popstate", onPopState);
89
- return () => {
90
- observers.delete(fn);
91
- if (observers.size === 0 && navigated.size === 0)
92
- window.removeEventListener("popstate", onPopState);
93
- };
94
- }
95
- };
96
- var testNavigation;
97
- function setNavigationForTests(nav) {
98
- testNavigation = nav;
99
- }
100
- var navigationOf = () => testNavigation ?? browserNavigation;
101
- var ROUTER = Symbol("xzor.router");
102
- function segmentsOf(pathname) {
103
- const rest = pathname.startsWith("/") ? pathname.slice(1) : pathname;
104
- return rest === "" ? [] : rest.split("/");
105
- }
106
- var baseFor;
107
- var base = "";
108
- function basePath() {
109
- const uri = document.baseURI;
110
- if (uri !== baseFor) {
111
- baseFor = uri;
112
- const path = document.querySelector("base[href]") ? new URL(uri).pathname : "/";
113
- base = path.slice(0, path.lastIndexOf("/"));
114
- }
115
- return base;
116
- }
117
- function routePath(pathname) {
118
- const b = basePath();
119
- return b !== "" && (pathname === b || pathname.startsWith(`${b}/`)) ? pathname.slice(b.length) || "/" : pathname;
120
- }
121
- function groupsOf(re, pathname) {
122
- re.lastIndex = 0;
123
- const m = re.exec(pathname);
124
- return m ? m.groups ?? {} : null;
125
- }
126
- function resolveRoute(router, table, sections, url) {
127
- const path = routePath(url.pathname);
128
- const segments = segmentsOf(path);
129
- let page;
130
- let params = null;
131
- for (const entry of table) {
132
- params = entry.match(segments);
133
- if (params) {
134
- page = entry;
135
- break;
136
- }
137
- }
138
- let section = -1;
139
- let match = {};
140
- for (let i = 0;i < sections.length && section < 0; i++) {
141
- const s = sections[i];
142
- if (page) {
143
- if (s.kind === "tag") {
144
- if (s.tag === page.tag)
145
- section = i;
146
- } else if (s.kind === "regex" && s.page) {
147
- const groups = groupsOf(s.re, path);
148
- if (groups) {
149
- section = i;
150
- match = groups;
151
- }
152
- } else if (s.kind === "pattern" && s.page) {
153
- const own = s.match(segments);
154
- if (own) {
155
- section = i;
156
- match = own;
157
- }
158
- }
159
- } else if (s.kind === "regex" && !s.page) {
160
- const groups = groupsOf(s.re, path);
161
- if (groups) {
162
- section = i;
163
- match = groups;
164
- }
165
- } else if (s.kind === "pattern" && !s.page) {
166
- const own = s.match(segments);
167
- if (own) {
168
- section = i;
169
- params = own;
170
- }
171
- }
172
- }
173
- if (section < 0)
174
- section = sections.findIndex((s) => s.kind === (page ? "default" : "notFound"));
175
- router.href = url.href;
176
- router.id++;
177
- router.page = page;
178
- router.params = params ?? {};
179
- router.section = section;
180
- router.route = new Route(path, page?.tag, router.params, url.searchParams, match, router.nav);
181
- }
182
- function renavigate(owner) {
183
- if (depth === 0)
184
- update(owner);
185
- else
186
- queueMicrotask(() => update(owner));
187
- }
188
- var noop = () => {};
189
- var SELECTOR = /[#.[]/;
190
- var rethrow = (err) => queueMicrotask(() => {
191
- throw err;
192
- });
193
- function surface(result) {
194
- if (result instanceof Promise)
195
- result.catch(rethrow);
196
- }
197
- var wellKnown = Symbol;
198
- function polyfillDisposeSymbols(target) {
199
- target.dispose ??= Symbol.for("Symbol.dispose");
200
- target.asyncDispose ??= Symbol.for("Symbol.asyncDispose");
201
- }
202
- polyfillDisposeSymbols(wellKnown);
203
- var ServiceProvider = () => noop;
204
- var Mount = (_component, _target) => noop;
205
- var Import = (..._providers) => noop;
206
- var Singleton = () => noop;
207
- var Scoped = () => noop;
208
- var Transient = () => noop;
209
- var SharedInstance = Symbol("xzor.sharedInstance");
210
- var mountedComponents = new WeakMap;
211
- var elementHandlers = new WeakMap;
212
- var FRAGMENT = Symbol("xzor.fragment");
213
- function isFragment(value) {
214
- return typeof value === "function" && FRAGMENT in value;
215
- }
216
-
217
- class ComponentBase {
218
- static fragment(build) {
219
- return Object.assign(build, { [FRAGMENT]: true });
220
- }
221
- static bindValue(e, current) {
222
- const input = e.target;
223
- if (typeof current === "boolean")
224
- return input.checked;
225
- if (typeof current === "number")
226
- return Number(input.value);
227
- return input.value;
228
- }
229
- slots = {};
230
- onInitialized() {}
231
- onInitializedAsync() {}
232
- onParametersSet() {}
233
- onParametersSetAsync() {}
234
- onAfterRender(_firstRender) {}
235
- onAfterRenderAsync(_firstRender) {}
236
- shouldRender() {
237
- return true;
238
- }
239
- dispose() {}
240
- stateHasChanged() {
241
- update(this);
242
- }
243
- }
244
- var hooks = (c) => c;
245
-
246
- class RenderTreeBuilder {
247
- owner;
248
- #root = [];
249
- #open = [];
250
- constructor(owner) {
251
- this.owner = owner;
252
- }
253
- get nodes() {
254
- return this.#root;
255
- }
256
- #append(node) {
257
- (this.#open.at(-1)?.children ?? this.#root).push(node);
258
- }
259
- #current() {
260
- const el = this.#open.at(-1);
261
- if (el?.kind !== "element")
262
- throw new Error("xzor: attribute outside of an element");
263
- return el;
264
- }
265
- openElement(tag) {
266
- const el = { kind: "element", tag, attrs: {}, events: {}, modifiers: {}, children: [] };
267
- this.#append(el);
268
- this.#open.push(el);
269
- }
270
- closeElement() {
271
- this.#open.pop();
272
- }
273
- openRegion() {
274
- const region = { kind: "region", children: [] };
275
- this.#append(region);
276
- this.#open.push(region);
277
- }
278
- openCascade(name, value, fixed) {
279
- const region = { kind: "region", children: [], name, value, fixed: fixed === true };
280
- this.#append(region);
281
- this.#open.push(region);
282
- }
283
- closeRegion() {
284
- this.#open.pop();
285
- }
286
- addRoutes(engine, table, sections) {
287
- const owner = this.owner;
288
- const nav = navigationOf();
289
- let router = owner[ROUTER];
290
- if (!router) {
291
- router = owner[ROUTER] = {
292
- nav: engine === "client" ? nav : undefined,
293
- off: undefined,
294
- onError: undefined,
295
- caught: sections.find((s) => s.kind === "catch"),
296
- href: "",
297
- id: 0,
298
- route: undefined,
299
- section: -1,
300
- page: undefined,
301
- params: {},
302
- error: undefined,
303
- failed: false
304
- };
305
- const failing = router;
306
- if (router.caught) {
307
- router.onError = (err, id) => {
308
- if (id !== failing.id)
309
- return;
310
- failing.error = err;
311
- failing.failed = true;
312
- queueMicrotask(() => update(owner));
313
- };
314
- }
315
- if (router.nav)
316
- router.off = router.nav.subscribe(() => renavigate(owner));
317
- }
318
- const state = router;
319
- const url = nav.current();
320
- if (url.href !== state.href || !state.route) {
321
- state.failed = false;
322
- state.error = undefined;
323
- resolveRoute(state, table, sections, url);
324
- }
325
- const route = state.route;
326
- const section = sections[state.section];
327
- const page = state.page;
328
- this.openCascade("route", route);
329
- if (state.failed) {
330
- state.caught.render(route, state.error)(this);
331
- } else if (page) {
332
- const entry = page;
333
- const fragment = ComponentBase.fragment((b) => b.#addPage(entry, state));
334
- if (section)
335
- section.render(route, fragment)(this);
336
- else
337
- fragment(this);
338
- } else if (section) {
339
- section.render(route)(this);
340
- }
341
- this.closeRegion();
342
- }
343
- #addPage(entry, router) {
344
- this.#append({
345
- kind: "component",
346
- type: entry.component,
347
- props: router.params,
348
- key: entry.family ?? entry.pattern,
349
- onError: router.onError,
350
- nav: router.id
351
- });
352
- }
353
- addAttribute(name, value) {
354
- const el = this.#current();
355
- if (value === false || value == null)
356
- delete el.attrs[name];
357
- else
358
- el.attrs[name] = value === true ? "" : String(value);
359
- }
360
- addAttributes(attrs) {
361
- for (const [name, value] of Object.entries(attrs ?? {}))
362
- this.addAttribute(name, value);
363
- }
364
- addEventModifier(event, modifier, enabled) {
365
- const el = this.#current();
366
- (el.modifiers[event] ??= {})[modifier] = enabled;
367
- }
368
- setKey(key) {
369
- this.#current().key = key;
370
- }
371
- setRef(_tag, ref) {
372
- this.#current().ref = ref;
373
- }
374
- addEventHandler(event, handler) {
375
- this.#current().events[event] = handler;
376
- }
377
- addText(text) {
378
- this.#append({ kind: "text", text });
379
- }
380
- addContent(value) {
381
- if (isFragment(value)) {
382
- this.openRegion();
383
- value(this);
384
- this.closeRegion();
385
- return;
386
- }
387
- if (value === false || value == null)
388
- value = "";
389
- this.#append({ kind: "text", text: String(value) });
390
- }
391
- addComponent(type, props, slots, extra) {
392
- this.#append({
393
- kind: "component",
394
- type,
395
- props,
396
- slots,
397
- key: extra?.key,
398
- ref: extra?.ref
399
- });
400
- }
401
- callback(handler) {
402
- const owner = this.owner;
403
- return (arg) => {
404
- const result = handler(arg);
405
- update(owner);
406
- if (result instanceof Promise)
407
- result.then(() => update(owner));
408
- return result;
409
- };
410
- }
411
- }
412
- function setAttr(el, name, value) {
413
- el.setAttribute(name, value);
414
- if (name === "value" && "value" in el)
415
- el.value = value;
416
- if (name === "checked" && "checked" in el)
417
- el.checked = true;
418
- }
419
- function removeAttr(el, name) {
420
- el.removeAttribute(name);
421
- if (name === "value" && "value" in el)
422
- el.value = "";
423
- if (name === "checked" && "checked" in el)
424
- el.checked = false;
425
- }
426
- function render(component) {
427
- const builder = new RenderTreeBuilder(component);
428
- hooks(component).buildRenderTree(builder);
429
- return builder.nodes;
430
- }
431
- var depth = 0;
432
- var pass = 0;
433
- var afterRender = [];
434
- function batch(fn) {
435
- if (depth++ === 0)
436
- pass++;
437
- try {
438
- fn();
439
- } finally {
440
- if (--depth === 0)
441
- for (const done of afterRender.splice(0))
442
- done();
443
- }
444
- }
445
- function settle(component, result, node) {
446
- if (!(result instanceof Promise))
447
- return;
448
- result.then(() => update(component), node?.onError && ((err) => fail(node, err)));
449
- }
450
- function fail(v, err) {
451
- if (v.onError)
452
- v.onError(err, v.mounted?.nav ?? v.nav ?? 0);
453
- else
454
- rethrow(err);
455
- }
456
- function parametersSet(component) {
457
- hooks(component).onParametersSet();
458
- settle(component, hooks(component).onParametersSetAsync());
459
- }
460
- var cascadesOf = (type) => type.cascades;
461
- var fields = (c) => c;
462
- function findCascade(scope, name) {
463
- for (let s = scope;s; s = s.parent)
464
- if (s.name === name)
465
- return s;
466
- return;
467
- }
468
- function resolveCascades(instance, type, scope) {
469
- const list = cascadesOf(type);
470
- if (!list)
471
- return;
472
- for (const [prop, name] of list) {
473
- const record = findCascade(scope, name);
474
- if (!record)
475
- continue;
476
- fields(instance)[prop] = record.value;
477
- if (!record.fixed)
478
- (record.consumers ??= new Set).add(instance);
479
- }
480
- }
481
- function unsubscribeCascades(instance, type, scope) {
482
- const list = cascadesOf(type);
483
- if (!list)
484
- return;
485
- for (const [, name] of list)
486
- findCascade(scope, name)?.consumers?.delete(instance);
487
- }
488
- function assignCascade(record, consumers) {
489
- for (const consumer of consumers) {
490
- for (const [prop, name] of cascadesOf(consumer.constructor)) {
491
- if (name === record.name)
492
- fields(consumer)[prop] = record.value;
493
- }
494
- }
495
- }
496
- function notifyCascade(consumers) {
497
- for (const consumer of consumers) {
498
- const m = mountedComponents.get(consumer);
499
- if (!m || m.pass === pass)
500
- continue;
501
- m.pass = pass;
502
- try {
503
- parametersSet(consumer);
504
- update(consumer);
505
- } catch (err) {
506
- rethrow(err);
507
- }
508
- }
509
- }
510
- function queueAfterRender(component, first) {
511
- afterRender.push(() => {
512
- hooks(component).onAfterRender(first);
513
- hooks(component).onAfterRenderAsync(first);
514
- });
515
- }
516
- function update(component) {
517
- batch(() => {
518
- const m = mountedComponents.get(component);
519
- const parent = m?.anchor.parentNode;
520
- if (!m || !parent || !hooks(component).shouldRender())
521
- return;
522
- const next = render(component);
523
- patchList(parent, m.tree, next, m.anchor, component, m.app, m.scope);
524
- m.tree = next;
525
- queueAfterRender(component, false);
526
- });
527
- }
528
- function mountComponent(component, app, scope, into, node) {
529
- hooks(component).onInitialized();
530
- settle(component, hooks(component).onInitializedAsync(), node);
531
- parametersSet(component);
532
- const tree = render(component);
533
- const mounted = into ?? { tree, anchor: document.createComment(""), app, scope, latest: undefined, pass };
534
- if (into)
535
- into.tree = tree;
536
- mountedComponents.set(component, mounted);
537
- const nodes = tree.flatMap((v) => create(v, component, app, scope));
538
- queueAfterRender(component, true);
539
- if (!into)
540
- nodes.push(mounted.anchor);
541
- return { nodes, mounted };
542
- }
543
- function construct(type, app) {
544
- const inject = type.inject;
545
- if (!inject?.length)
546
- return new type;
547
- const made = app?.createComponent?.(type);
548
- if (made)
549
- return made;
550
- if (app)
551
- throw new Error(`xzor: ${type.name} is not registered with the application`);
552
- throw new Error(`xzor: ${type.name} needs injected services (${inject.join(", ")}) but has no application`);
553
- }
554
- function arrive(mounted, instance) {
555
- const v = mounted.latest;
556
- const parent = mounted.anchor.parentNode;
557
- mounted.latest = undefined;
558
- if (!v || !parent) {
559
- disposeInstance(instance);
560
- return;
561
- }
562
- try {
563
- batch(() => {
564
- applyProps(instance, v);
565
- resolveCascades(instance, v.type, mounted.scope);
566
- v.ref?.(instance);
567
- for (const node of mountComponent(instance, mounted.app, mounted.scope, mounted, v).nodes)
568
- parent.insertBefore(node, mounted.anchor);
569
- v.instance = instance;
570
- });
571
- } catch (err) {
572
- fail(v, err);
573
- if (!v.instance) {
574
- mountedComponents.delete(instance);
575
- unsubscribeCascades(instance, v.type, mounted.scope);
576
- const partial = mounted.tree;
577
- mounted.tree = [];
578
- for (const node of partial) {
579
- try {
580
- dispose(node);
581
- } catch (disposeErr) {
582
- rethrow(disposeErr);
583
- }
584
- }
585
- }
586
- }
587
- }
588
- function applyProps(instance, v) {
589
- Object.assign(instance, v.props);
590
- if (v.slots)
591
- instance.slots = v.slots;
592
- }
593
- function propsChanged(o, n) {
594
- if (n.slots)
595
- return true;
596
- for (const [key, value] of Object.entries(n.props)) {
597
- if (!Object.is(o.props[key], value) || typeof value === "object" && value !== null)
598
- return true;
599
- }
600
- return false;
601
- }
602
- var eventNames = (v) => new Set([...Object.keys(v.events), ...Object.keys(v.modifiers)]);
603
- function listen(el, event) {
604
- elementHandlers.get(el).listening.add(event);
605
- el.addEventListener(event, (e) => {
606
- const record = elementHandlers.get(el);
607
- if (!record)
608
- return;
609
- const mods = record.modifiers[event];
610
- if (mods?.preventDefault)
611
- e.preventDefault();
612
- if (mods?.stopPropagation)
613
- e.stopPropagation();
614
- const handler = record.events[event];
615
- if (!handler)
616
- return;
617
- const result = handler(e);
618
- update(record.owner);
619
- if (result instanceof Promise)
620
- result.then(() => update(record.owner));
621
- });
622
- }
623
- function create(v, owner, app, scope) {
624
- switch (v.kind) {
625
- case "text":
626
- v.dom = document.createTextNode(v.text);
627
- return [v.dom];
628
- case "element": {
629
- const el = document.createElement(v.tag);
630
- for (const [name, value] of Object.entries(v.attrs))
631
- setAttr(el, name, value);
632
- elementHandlers.set(el, { owner, events: v.events, modifiers: v.modifiers, listening: new Set });
633
- for (const event of eventNames(v))
634
- listen(el, event);
635
- for (const child of v.children)
636
- el.append(...create(child, owner, app, scope));
637
- v.dom = el;
638
- v.ref?.(el);
639
- return [el];
640
- }
641
- case "region": {
642
- v.anchor = document.createComment("");
643
- const inner = v.name === undefined ? scope : v.cascade = { name: v.name, value: v.value, fixed: v.fixed === true, consumers: undefined, parent: scope };
644
- return [...v.children.flatMap((c) => create(c, owner, app, inner)), v.anchor];
645
- }
646
- case "component": {
647
- if (!v.onError)
648
- return createComponent(v, app, scope);
649
- try {
650
- return createComponent(v, app, scope);
651
- } catch (err) {
652
- return failedComponent(v, err, app, scope);
653
- }
654
- }
655
- }
656
- }
657
- function createComponent(v, app, scope) {
658
- const made = construct(v.type, app);
659
- if (made instanceof Promise) {
660
- const mounted2 = v.mounted = {
661
- tree: [],
662
- anchor: document.createComment(""),
663
- app,
664
- scope,
665
- latest: v,
666
- pass
667
- };
668
- made.then((instance) => arrive(mounted2, instance), (err) => {
669
- const latest = mounted2.latest;
670
- mounted2.latest = undefined;
671
- if (latest)
672
- fail(latest, err);
673
- else if (!v.onError)
674
- rethrow(err);
675
- });
676
- return [mounted2.anchor];
677
- }
678
- v.instance = made;
679
- applyProps(made, v);
680
- resolveCascades(made, v.type, scope);
681
- v.ref?.(made);
682
- const { nodes, mounted } = mountComponent(made, app, scope, undefined, v);
683
- v.mounted = mounted;
684
- return nodes;
685
- }
686
- function failedComponent(v, err, app, scope) {
687
- const instance = v.instance;
688
- v.instance = undefined;
689
- if (instance) {
690
- const partial = mountedComponents.get(instance);
691
- mountedComponents.delete(instance);
692
- unsubscribeCascades(instance, v.type, scope);
693
- for (const node of partial?.tree ?? []) {
694
- try {
695
- dispose(node);
696
- } catch (disposeErr) {
697
- rethrow(disposeErr);
698
- }
699
- }
700
- }
701
- v.mounted = { tree: [], anchor: document.createComment(""), app, scope, latest: undefined, pass };
702
- fail(v, err);
703
- return [v.mounted.anchor];
704
- }
705
- function nodesOf(v) {
706
- switch (v.kind) {
707
- case "text":
708
- case "element":
709
- return [v.dom];
710
- case "region":
711
- return [...v.children.flatMap(nodesOf), v.anchor];
712
- case "component":
713
- return [...v.mounted.tree.flatMap(nodesOf), v.mounted.anchor];
714
- }
715
- }
716
- function same(o, n) {
717
- if (o.kind !== n.kind)
718
- return false;
719
- if (o.kind === "element")
720
- return o.tag === n.tag && o.key === n.key;
721
- if (o.kind === "component")
722
- return o.type === n.type && o.key === n.key;
723
- if (o.kind === "region")
724
- return o.name === n.name && o.fixed === n.fixed;
725
- return true;
726
- }
727
- function dispose(v) {
728
- switch (v.kind) {
729
- case "element":
730
- v.children.forEach(dispose);
731
- return;
732
- case "region":
733
- if (v.cascade)
734
- v.cascade.consumers = undefined;
735
- v.children.forEach(dispose);
736
- return;
737
- case "component":
738
- if (!v.instance) {
739
- if (v.mounted)
740
- v.mounted.latest = undefined;
741
- return;
742
- }
743
- v.mounted?.tree.forEach(dispose);
744
- mountedComponents.delete(v.instance);
745
- unsubscribeCascades(v.instance, v.type, v.mounted?.scope);
746
- disposeInstance(v.instance);
747
- return;
748
- }
749
- }
750
- function disposeInstance(c) {
751
- c[ROUTER]?.off?.();
752
- hooks(c).dispose();
753
- const d = c;
754
- d[wellKnown.dispose]?.();
755
- surface(d[wellKnown.asyncDispose]?.());
756
- }
757
- function remove(parent, v) {
758
- for (const node of nodesOf(v))
759
- parent.removeChild(node);
760
- dispose(v);
761
- }
762
- function patch(o, n, owner, app, scope) {
763
- switch (n.kind) {
764
- case "text": {
765
- const dom = n.dom = o.dom;
766
- if (dom.data !== n.text)
767
- dom.data = n.text;
768
- return;
769
- }
770
- case "element": {
771
- const old = o;
772
- const el = n.dom = old.dom;
773
- for (const name of Object.keys(old.attrs))
774
- if (!(name in n.attrs))
775
- removeAttr(el, name);
776
- for (const [name, value] of Object.entries(n.attrs)) {
777
- const live = name === "value" ? el.value : undefined;
778
- if (old.attrs[name] !== value || live !== undefined && live !== value)
779
- setAttr(el, name, value);
780
- }
781
- const record = elementHandlers.get(el);
782
- record.events = n.events;
783
- record.modifiers = n.modifiers;
784
- for (const event of eventNames(n))
785
- if (!record.listening.has(event))
786
- listen(el, event);
787
- patchList(el, old.children, n.children, null, owner, app, scope);
788
- n.ref?.(el);
789
- return;
790
- }
791
- case "region": {
792
- const old = o;
793
- const anchor = n.anchor = old.anchor;
794
- const record = old.cascade;
795
- let subscribers;
796
- let inner = scope;
797
- if (record) {
798
- record.parent = scope;
799
- n.cascade = record;
800
- inner = record;
801
- if (!record.fixed && !Object.is(record.value, n.value)) {
802
- record.value = n.value;
803
- if (record.consumers?.size) {
804
- subscribers = [...record.consumers];
805
- assignCascade(record, subscribers);
806
- }
807
- }
808
- }
809
- patchList(anchor.parentNode, old.children, n.children, anchor, owner, app, inner);
810
- if (subscribers)
811
- notifyCascade(subscribers);
812
- return;
813
- }
814
- case "component": {
815
- const old = o;
816
- n.mounted = old.mounted;
817
- if (!old.instance) {
818
- if (n.mounted.latest)
819
- n.mounted.latest = n;
820
- return;
821
- }
822
- const instance = n.instance = old.instance;
823
- const changed = n.nav !== old.nav || propsChanged(old, n);
824
- if (n.nav !== undefined)
825
- n.mounted.nav = n.nav;
826
- applyProps(instance, n);
827
- n.ref?.(instance);
828
- if (changed) {
829
- n.mounted.pass = pass;
830
- parametersSet(instance);
831
- update(instance);
832
- }
833
- return;
834
- }
835
- }
836
- }
837
- var keyOf = (v) => v && (v.kind === "element" || v.kind === "component") ? v.key : undefined;
838
- function patchList(parent, old, next, end, owner, app, scope) {
839
- if (old.some((v) => keyOf(v) != null) || next.some((v) => keyOf(v) != null)) {
840
- patchKeyed(parent, old, next, end, owner, app, scope);
841
- return;
842
- }
843
- for (let i = 0;i < next.length; i++) {
844
- const n = next[i];
845
- const o = old[i];
846
- if (o && same(o, n)) {
847
- patch(o, n, owner, app, scope);
848
- continue;
849
- }
850
- const ref = o ? nodesOf(o)[0] : end;
851
- for (const node of create(n, owner, app, scope))
852
- parent.insertBefore(node, ref);
853
- if (o)
854
- remove(parent, o);
855
- }
856
- for (const o of old.slice(next.length))
857
- remove(parent, o);
858
- }
859
- function patchKeyed(parent, old, next, end, owner, app, scope) {
860
- const byKey = new Map;
861
- for (const o of old)
862
- if (keyOf(o) != null)
863
- byKey.set(keyOf(o), o);
864
- const used = new Set;
865
- const matches = next.map((n, i) => {
866
- const key = keyOf(n);
867
- const o = key != null ? byKey.get(key) : keyOf(old[i]) == null ? old[i] : undefined;
868
- if (o && !used.has(o) && same(o, n)) {
869
- used.add(o);
870
- return o;
871
- }
872
- return;
873
- });
874
- for (const o of old)
875
- if (!used.has(o))
876
- remove(parent, o);
877
- let ref = end;
878
- for (let i = next.length - 1;i >= 0; i--) {
879
- const n = next[i];
880
- const o = matches[i];
881
- let nodes;
882
- if (o) {
883
- patch(o, n, owner, app, scope);
884
- nodes = nodesOf(n);
885
- } else {
886
- nodes = create(n, owner, app, scope);
887
- }
888
- for (let j = nodes.length - 1;j >= 0; j--) {
889
- const node = nodes[j];
890
- if (node.parentNode !== parent || node.nextSibling !== ref)
891
- parent.insertBefore(node, ref);
892
- ref = node;
893
- }
894
- }
895
- }
896
- function resolveTarget(target) {
897
- if (typeof target !== "string")
898
- return target;
899
- const found = SELECTOR.test(target) ? document.querySelector(target) : document.getElementById(target);
900
- if (!found)
901
- throw new Error(`xzor: mount target "${target}" not found`);
902
- return found;
903
- }
904
- function mount(type, target, app) {
905
- const host = resolveTarget(target);
906
- const root = construct(type, app);
907
- if (root instanceof Promise)
908
- throw new Error(`xzor: root component ${type.name} cannot be asynchronous`);
909
- batch(() => host.replaceChildren(...mountComponent(root, app, undefined).nodes));
910
- surface(app?.onStarted?.());
911
- return root;
912
- }
913
-
914
- class NavLink extends ComponentBase {
915
- href = "";
916
- activeClass = "active";
917
- match = "prefix";
918
- #path = "";
919
- #for;
920
- #target = null;
921
- #off;
922
- onInitialized() {
923
- const nav = navigationOf();
924
- this.#path = nav.current().pathname;
925
- const fn = () => {
926
- const path = nav.current().pathname;
927
- if (path === this.#path)
928
- return;
929
- this.#path = path;
930
- this.stateHasChanged();
931
- };
932
- this.#off = nav.observe ? nav.observe(fn) : nav.subscribe(fn);
933
- }
934
- dispose() {
935
- this.#off?.();
936
- }
937
- #active() {
938
- if (this.#for !== this.href) {
939
- this.#for = this.href;
940
- const url = new URL(this.href, document.baseURI);
941
- this.#target = url.origin === location.origin ? url.pathname : null;
942
- }
943
- const target = this.#target;
944
- if (target === null)
945
- return false;
946
- const path = this.#path;
947
- if (this.match === "exact" || target === `${basePath()}/`)
948
- return path === target;
949
- return path === target || path.startsWith(target.endsWith("/") ? target : `${target}/`);
950
- }
951
- buildRenderTree(b) {
952
- b.openElement("a");
953
- b.addAttribute("href", this.href);
954
- if (this.#active())
955
- b.addAttribute("class", this.activeClass);
956
- b.addContent(this.slots.default?.() ?? null);
957
- b.closeElement();
958
- }
959
- }
1
+ import {
2
+ $inSvg,
3
+ $isFragment,
4
+ ComponentBase,
5
+ FINE,
6
+ Import,
7
+ Mount,
8
+ NavLink,
9
+ RenderTreeBuilder,
10
+ Route,
11
+ SVG,
12
+ Scoped,
13
+ ServiceProvider,
14
+ SharedInstance,
15
+ Singleton,
16
+ Transient,
17
+ basePath,
18
+ disposeIsland,
19
+ mount,
20
+ patchIsland,
21
+ polyfillDisposeSymbols,
22
+ setFineHooks,
23
+ setNavigationForTests,
24
+ setRenderObserver,
25
+ viewTransitions
26
+ } from "./index-qhyvdf2k.js";
960
27
  export {
28
+ $inSvg,
29
+ $isFragment,
961
30
  ComponentBase,
31
+ FINE,
962
32
  Import,
963
33
  Mount,
964
34
  NavLink,
965
35
  RenderTreeBuilder,
966
36
  Route,
37
+ SVG,
967
38
  Scoped,
968
39
  ServiceProvider,
969
40
  SharedInstance,
970
41
  Singleton,
971
42
  Transient,
972
43
  basePath,
44
+ disposeIsland,
973
45
  mount,
46
+ patchIsland,
974
47
  polyfillDisposeSymbols,
975
- setNavigationForTests
48
+ setFineHooks,
49
+ setNavigationForTests,
50
+ setRenderObserver,
51
+ viewTransitions
976
52
  };
977
53
 
978
- //# debugId=07155AAB187D1CBA64756E2164756E21
54
+ //# debugId=F1916F213281C3EF64756E2164756E21
979
55
  //# sourceMappingURL=index.js.map