@toyz/loom 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 (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +108 -0
  3. package/dist/app.d.ts +70 -0
  4. package/dist/app.d.ts.map +1 -0
  5. package/dist/app.js +152 -0
  6. package/dist/app.js.map +1 -0
  7. package/dist/bus.d.ts +27 -0
  8. package/dist/bus.d.ts.map +1 -0
  9. package/dist/bus.js +41 -0
  10. package/dist/bus.js.map +1 -0
  11. package/dist/css.d.ts +25 -0
  12. package/dist/css.d.ts.map +1 -0
  13. package/dist/css.js +48 -0
  14. package/dist/css.js.map +1 -0
  15. package/dist/decorators/component.d.ts +11 -0
  16. package/dist/decorators/component.d.ts.map +1 -0
  17. package/dist/decorators/component.js +38 -0
  18. package/dist/decorators/component.js.map +1 -0
  19. package/dist/decorators/di.d.ts +37 -0
  20. package/dist/decorators/di.d.ts.map +1 -0
  21. package/dist/decorators/di.js +65 -0
  22. package/dist/decorators/di.js.map +1 -0
  23. package/dist/decorators/dom.d.ts +15 -0
  24. package/dist/decorators/dom.d.ts.map +1 -0
  25. package/dist/decorators/dom.js +33 -0
  26. package/dist/decorators/dom.js.map +1 -0
  27. package/dist/decorators/events.d.ts +46 -0
  28. package/dist/decorators/events.d.ts.map +1 -0
  29. package/dist/decorators/events.js +69 -0
  30. package/dist/decorators/events.js.map +1 -0
  31. package/dist/decorators/index.d.ts +18 -0
  32. package/dist/decorators/index.d.ts.map +1 -0
  33. package/dist/decorators/index.js +27 -0
  34. package/dist/decorators/index.js.map +1 -0
  35. package/dist/decorators/lifecycle.d.ts +49 -0
  36. package/dist/decorators/lifecycle.d.ts.map +1 -0
  37. package/dist/decorators/lifecycle.js +105 -0
  38. package/dist/decorators/lifecycle.js.map +1 -0
  39. package/dist/decorators/state.d.ts +41 -0
  40. package/dist/decorators/state.d.ts.map +1 -0
  41. package/dist/decorators/state.js +125 -0
  42. package/dist/decorators/state.js.map +1 -0
  43. package/dist/decorators/symbols.d.ts +13 -0
  44. package/dist/decorators/symbols.d.ts.map +1 -0
  45. package/dist/decorators/symbols.js +15 -0
  46. package/dist/decorators/symbols.js.map +1 -0
  47. package/dist/decorators/timing.d.ts +35 -0
  48. package/dist/decorators/timing.d.ts.map +1 -0
  49. package/dist/decorators/timing.js +57 -0
  50. package/dist/decorators/timing.js.map +1 -0
  51. package/dist/decorators/transform.d.ts +45 -0
  52. package/dist/decorators/transform.d.ts.map +1 -0
  53. package/dist/decorators/transform.js +48 -0
  54. package/dist/decorators/transform.js.map +1 -0
  55. package/dist/element.d.ts +62 -0
  56. package/dist/element.d.ts.map +1 -0
  57. package/dist/element.js +150 -0
  58. package/dist/element.js.map +1 -0
  59. package/dist/event.d.ts +24 -0
  60. package/dist/event.d.ts.map +1 -0
  61. package/dist/event.js +35 -0
  62. package/dist/event.js.map +1 -0
  63. package/dist/icon.d.ts +35 -0
  64. package/dist/icon.d.ts.map +1 -0
  65. package/dist/icon.js +119 -0
  66. package/dist/icon.js.map +1 -0
  67. package/dist/index.d.ts +29 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +34 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/jsx-dev-runtime.d.ts +8 -0
  72. package/dist/jsx-dev-runtime.d.ts.map +1 -0
  73. package/dist/jsx-dev-runtime.js +8 -0
  74. package/dist/jsx-dev-runtime.js.map +1 -0
  75. package/dist/jsx-runtime.d.ts +13 -0
  76. package/dist/jsx-runtime.d.ts.map +1 -0
  77. package/dist/jsx-runtime.js +101 -0
  78. package/dist/jsx-runtime.js.map +1 -0
  79. package/dist/morph.d.ts +23 -0
  80. package/dist/morph.d.ts.map +1 -0
  81. package/dist/morph.js +212 -0
  82. package/dist/morph.js.map +1 -0
  83. package/dist/reactive.d.ts +75 -0
  84. package/dist/reactive.d.ts.map +1 -0
  85. package/dist/reactive.js +133 -0
  86. package/dist/reactive.js.map +1 -0
  87. package/dist/render-loop.d.ts +34 -0
  88. package/dist/render-loop.d.ts.map +1 -0
  89. package/dist/render-loop.js +70 -0
  90. package/dist/render-loop.js.map +1 -0
  91. package/dist/router/events.d.ts +12 -0
  92. package/dist/router/events.d.ts.map +1 -0
  93. package/dist/router/events.js +17 -0
  94. package/dist/router/events.js.map +1 -0
  95. package/dist/router/index.d.ts +14 -0
  96. package/dist/router/index.d.ts.map +1 -0
  97. package/dist/router/index.js +18 -0
  98. package/dist/router/index.js.map +1 -0
  99. package/dist/router/link.d.ts +18 -0
  100. package/dist/router/link.d.ts.map +1 -0
  101. package/dist/router/link.js +75 -0
  102. package/dist/router/link.js.map +1 -0
  103. package/dist/router/mode.d.ts +33 -0
  104. package/dist/router/mode.d.ts.map +1 -0
  105. package/dist/router/mode.js +48 -0
  106. package/dist/router/mode.js.map +1 -0
  107. package/dist/router/outlet.d.ts +40 -0
  108. package/dist/router/outlet.d.ts.map +1 -0
  109. package/dist/router/outlet.js +171 -0
  110. package/dist/router/outlet.js.map +1 -0
  111. package/dist/router/route.d.ts +76 -0
  112. package/dist/router/route.d.ts.map +1 -0
  113. package/dist/router/route.js +147 -0
  114. package/dist/router/route.js.map +1 -0
  115. package/dist/router/router.d.ts +50 -0
  116. package/dist/router/router.d.ts.map +1 -0
  117. package/dist/router/router.js +140 -0
  118. package/dist/router/router.js.map +1 -0
  119. package/dist/storage.d.ts +55 -0
  120. package/dist/storage.d.ts.map +1 -0
  121. package/dist/storage.js +90 -0
  122. package/dist/storage.js.map +1 -0
  123. package/dist/virtual.d.ts +69 -0
  124. package/dist/virtual.d.ts.map +1 -0
  125. package/dist/virtual.js +247 -0
  126. package/dist/virtual.js.map +1 -0
  127. package/package.json +58 -0
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Loom — Reactive primitives
3
+ *
4
+ * Reactive<T> — Observable value container for any shape
5
+ * CollectionStore<T> — CRUD over Reactive<T[]> for identifiable items
6
+ *
7
+ * Both support optional persistent storage via StorageMedium.
8
+ */
9
+ import type { PersistOptions } from "./storage";
10
+ export type Subscriber<T> = (value: T, prev: T) => void;
11
+ export type Updater<T> = T | ((prev: T) => T);
12
+ /**
13
+ * Observable value container. Works with any data shape.
14
+ * Optionally backs to a StorageMedium for auto-persistence.
15
+ *
16
+ * ```ts
17
+ * // In-memory (default)
18
+ * const count = new Reactive(0);
19
+ *
20
+ * // Auto-persisted to localStorage
21
+ * const count = new Reactive(0, { key: "app:count", storage: new LocalMedium() });
22
+ * ```
23
+ */
24
+ export declare class Reactive<T> {
25
+ private _value;
26
+ private subs;
27
+ private _key?;
28
+ private _storage?;
29
+ constructor(initial: T, persist?: PersistOptions);
30
+ get value(): T;
31
+ set(next: Updater<T>): void;
32
+ /** Subscribe to changes. Returns unsubscribe function. */
33
+ subscribe(fn: Subscriber<T>): () => void;
34
+ /** Subscribe and immediately call with current value */
35
+ watch(fn: Subscriber<T>): () => void;
36
+ /** Clear persisted data and reset to a value */
37
+ clear(resetTo: T): void;
38
+ /** Swap the storage medium at runtime (e.g. upgrade from local to remote) */
39
+ swapStorage(persist: PersistOptions): void;
40
+ }
41
+ /**
42
+ * Items must have an `id` field to be stored in a CollectionStore.
43
+ */
44
+ export interface Identifiable {
45
+ id: string;
46
+ }
47
+ /**
48
+ * CRUD collection backed by Reactive<T[]>.
49
+ * Supports optional persistent storage via StorageMedium.
50
+ *
51
+ * ```ts
52
+ * // In-memory
53
+ * const items = new CollectionStore<Item>();
54
+ *
55
+ * // Persisted to localStorage
56
+ * const items = new CollectionStore<Item>([], {
57
+ * key: "app:items",
58
+ * storage: new LocalMedium(),
59
+ * });
60
+ * ```
61
+ */
62
+ export declare class CollectionStore<T extends Identifiable> extends Reactive<T[]> {
63
+ constructor(initial?: T[], persist?: PersistOptions);
64
+ /** Add an item. If no `id` provided, one is auto-generated. */
65
+ add(item: Omit<T, "id"> & {
66
+ id?: string;
67
+ }): T;
68
+ /** Remove an item by id */
69
+ remove(id: string): void;
70
+ /** Patch an item by id */
71
+ update(id: string, patch: Partial<T>): T;
72
+ /** Find an item by id */
73
+ find(id: string): T | undefined;
74
+ }
75
+ //# sourceMappingURL=reactive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reactive.d.ts","sourceRoot":"","sources":["../src/reactive.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAiB,MAAM,WAAW,CAAC;AAE/D,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,KAAK,IAAI,CAAC;AACxD,MAAM,MAAM,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;AAE9C;;;;;;;;;;;GAWG;AACH,qBAAa,QAAQ,CAAC,CAAC;IACrB,OAAO,CAAC,MAAM,CAAI;IAClB,OAAO,CAAC,IAAI,CAA4B;IACxC,OAAO,CAAC,IAAI,CAAC,CAAS;IACtB,OAAO,CAAC,QAAQ,CAAC,CAAgB;gBAErB,OAAO,EAAE,CAAC,EAAE,OAAO,CAAC,EAAE,cAAc;IAqBhD,IAAI,KAAK,IAAI,CAAC,CAEb;IAED,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI;IAa3B,0DAA0D;IAC1D,SAAS,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAKxC,wDAAwD;IACxD,KAAK,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAKpC,gDAAgD;IAChD,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI;IAOvB,6EAA6E;IAC7E,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;CAM3C;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAC;CACZ;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,eAAe,CAC1B,CAAC,SAAS,YAAY,CACtB,SAAQ,QAAQ,CAAC,CAAC,EAAE,CAAC;gBACT,OAAO,GAAE,CAAC,EAAO,EAAE,OAAO,CAAC,EAAE,cAAc;IAIvD,+DAA+D;IAC/D,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,CAAC;IAM7C,2BAA2B;IAC3B,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAIxB,0BAA0B;IAC1B,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC;IAYxC,yBAAyB;IACzB,IAAI,CAAC,EAAE,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS;CAGhC"}
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Loom — Reactive primitives
3
+ *
4
+ * Reactive<T> — Observable value container for any shape
5
+ * CollectionStore<T> — CRUD over Reactive<T[]> for identifiable items
6
+ *
7
+ * Both support optional persistent storage via StorageMedium.
8
+ */
9
+ /**
10
+ * Observable value container. Works with any data shape.
11
+ * Optionally backs to a StorageMedium for auto-persistence.
12
+ *
13
+ * ```ts
14
+ * // In-memory (default)
15
+ * const count = new Reactive(0);
16
+ *
17
+ * // Auto-persisted to localStorage
18
+ * const count = new Reactive(0, { key: "app:count", storage: new LocalMedium() });
19
+ * ```
20
+ */
21
+ export class Reactive {
22
+ _value;
23
+ subs = new Set();
24
+ _key;
25
+ _storage;
26
+ constructor(initial, persist) {
27
+ this._key = persist?.key;
28
+ this._storage = persist?.storage;
29
+ // Try to hydrate from storage
30
+ if (this._key && this._storage) {
31
+ const stored = this._storage.get(this._key);
32
+ if (stored !== null) {
33
+ try {
34
+ this._value = JSON.parse(stored);
35
+ }
36
+ catch {
37
+ this._value = initial;
38
+ }
39
+ }
40
+ else {
41
+ this._value = initial;
42
+ }
43
+ }
44
+ else {
45
+ this._value = initial;
46
+ }
47
+ }
48
+ get value() {
49
+ return this._value;
50
+ }
51
+ set(next) {
52
+ const prev = this._value;
53
+ this._value =
54
+ typeof next === "function" ? next(prev) : next;
55
+ if (this._value !== prev) {
56
+ // Persist
57
+ if (this._key && this._storage) {
58
+ this._storage.set(this._key, JSON.stringify(this._value));
59
+ }
60
+ this.subs.forEach((s) => s(this._value, prev));
61
+ }
62
+ }
63
+ /** Subscribe to changes. Returns unsubscribe function. */
64
+ subscribe(fn) {
65
+ this.subs.add(fn);
66
+ return () => this.subs.delete(fn);
67
+ }
68
+ /** Subscribe and immediately call with current value */
69
+ watch(fn) {
70
+ fn(this._value, this._value);
71
+ return this.subscribe(fn);
72
+ }
73
+ /** Clear persisted data and reset to a value */
74
+ clear(resetTo) {
75
+ if (this._key && this._storage) {
76
+ this._storage.remove(this._key);
77
+ }
78
+ this.set(resetTo);
79
+ }
80
+ /** Swap the storage medium at runtime (e.g. upgrade from local to remote) */
81
+ swapStorage(persist) {
82
+ // Persist current value to new storage
83
+ this._key = persist.key;
84
+ this._storage = persist.storage;
85
+ this._storage.set(this._key, JSON.stringify(this._value));
86
+ }
87
+ }
88
+ /**
89
+ * CRUD collection backed by Reactive<T[]>.
90
+ * Supports optional persistent storage via StorageMedium.
91
+ *
92
+ * ```ts
93
+ * // In-memory
94
+ * const items = new CollectionStore<Item>();
95
+ *
96
+ * // Persisted to localStorage
97
+ * const items = new CollectionStore<Item>([], {
98
+ * key: "app:items",
99
+ * storage: new LocalMedium(),
100
+ * });
101
+ * ```
102
+ */
103
+ export class CollectionStore extends Reactive {
104
+ constructor(initial = [], persist) {
105
+ super(initial, persist);
106
+ }
107
+ /** Add an item. If no `id` provided, one is auto-generated. */
108
+ add(item) {
109
+ const full = { ...item, id: item.id ?? crypto.randomUUID() };
110
+ this.set((prev) => [...prev, full]);
111
+ return full;
112
+ }
113
+ /** Remove an item by id */
114
+ remove(id) {
115
+ this.set((prev) => prev.filter((i) => i.id !== id));
116
+ }
117
+ /** Patch an item by id */
118
+ update(id, patch) {
119
+ let updated;
120
+ this.set((prev) => prev.map((i) => {
121
+ if (i.id !== id)
122
+ return i;
123
+ updated = { ...i, ...patch, id };
124
+ return updated;
125
+ }));
126
+ return updated;
127
+ }
128
+ /** Find an item by id */
129
+ find(id) {
130
+ return this.value.find((i) => i.id === id);
131
+ }
132
+ }
133
+ //# sourceMappingURL=reactive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reactive.js","sourceRoot":"","sources":["../src/reactive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Loom — RenderLoop
3
+ *
4
+ * Centralized requestAnimationFrame dispatcher.
5
+ * One global rAF loop, callbacks sorted by layer for deterministic order.
6
+ *
7
+ * ```ts
8
+ * const unsub = renderLoop.add(10, (dt, t) => { ... });
9
+ * // later:
10
+ * unsub(); // or this.track(renderLoop.add(...))
11
+ * ```
12
+ */
13
+ declare class RenderLoop {
14
+ private callbacks;
15
+ private sorted;
16
+ private dirty;
17
+ private running;
18
+ private prevTime;
19
+ private rafId;
20
+ /**
21
+ * Register a frame callback at the given layer.
22
+ * Lower layers execute first. Returns an unsubscribe function.
23
+ */
24
+ add(layer: number, fn: (dt: number, t: number) => void): () => void;
25
+ /** Number of active callbacks */
26
+ get size(): number;
27
+ start(): void;
28
+ stop(): void;
29
+ private tick;
30
+ }
31
+ /** Module-level singleton — used by @animationFrame */
32
+ export declare const renderLoop: RenderLoop;
33
+ export type { RenderLoop };
34
+ //# sourceMappingURL=render-loop.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-loop.d.ts","sourceRoot":"","sources":["../src/render-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,cAAM,UAAU;IACd,OAAO,CAAC,SAAS,CAA4B;IAC7C,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,KAAK,CAAK;IAElB;;;OAGG;IACH,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,IAAI,GAAG,MAAM,IAAI;IAUnE,iCAAiC;IACjC,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,KAAK,IAAI,IAAI;IAOb,IAAI,IAAI,IAAI;IAMZ,OAAO,CAAC,IAAI,CAmBV;CACH;AAED,uDAAuD;AACvD,eAAO,MAAM,UAAU,YAAmB,CAAC;AAC3C,YAAY,EAAE,UAAU,EAAE,CAAC"}
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Loom — RenderLoop
3
+ *
4
+ * Centralized requestAnimationFrame dispatcher.
5
+ * One global rAF loop, callbacks sorted by layer for deterministic order.
6
+ *
7
+ * ```ts
8
+ * const unsub = renderLoop.add(10, (dt, t) => { ... });
9
+ * // later:
10
+ * unsub(); // or this.track(renderLoop.add(...))
11
+ * ```
12
+ */
13
+ class RenderLoop {
14
+ callbacks = new Set();
15
+ sorted = [];
16
+ dirty = false;
17
+ running = false;
18
+ prevTime = 0;
19
+ rafId = 0;
20
+ /**
21
+ * Register a frame callback at the given layer.
22
+ * Lower layers execute first. Returns an unsubscribe function.
23
+ */
24
+ add(layer, fn) {
25
+ const entry = { layer, fn };
26
+ this.callbacks.add(entry);
27
+ this.dirty = true;
28
+ return () => {
29
+ this.callbacks.delete(entry);
30
+ this.dirty = true;
31
+ };
32
+ }
33
+ /** Number of active callbacks */
34
+ get size() {
35
+ return this.callbacks.size;
36
+ }
37
+ start() {
38
+ if (this.running)
39
+ return;
40
+ this.running = true;
41
+ this.prevTime = 0;
42
+ this.rafId = requestAnimationFrame(this.tick);
43
+ }
44
+ stop() {
45
+ if (!this.running)
46
+ return;
47
+ this.running = false;
48
+ cancelAnimationFrame(this.rafId);
49
+ }
50
+ tick = (timestamp) => {
51
+ if (!this.running)
52
+ return;
53
+ // Compute delta (0 on first frame)
54
+ const dt = this.prevTime ? (timestamp - this.prevTime) / 1000 : 0;
55
+ this.prevTime = timestamp;
56
+ // Re-sort if callbacks changed
57
+ if (this.dirty) {
58
+ this.sorted = [...this.callbacks].sort((a, b) => a.layer - b.layer);
59
+ this.dirty = false;
60
+ }
61
+ // Dispatch in layer order
62
+ for (const entry of this.sorted) {
63
+ entry.fn(dt, timestamp);
64
+ }
65
+ this.rafId = requestAnimationFrame(this.tick);
66
+ };
67
+ }
68
+ /** Module-level singleton — used by @animationFrame */
69
+ export const renderLoop = new RenderLoop();
70
+ //# sourceMappingURL=render-loop.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-loop.js","sourceRoot":"","sources":["../src/render-loop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,MAAM,UAAU;IACN,SAAS,GAAG,IAAI,GAAG,EAAiB,CAAC;IACrC,MAAM,GAAoB,EAAE,CAAC;IAC7B,KAAK,GAAG,KAAK,CAAC;IACd,OAAO,GAAG,KAAK,CAAC;IAChB,QAAQ,GAAG,CAAC,CAAC;IACb,KAAK,GAAG,CAAC,CAAC;IAElB;;;OAGG;IACH,GAAG,CAAC,KAAa,EAAE,EAAmC;QACpD,MAAM,KAAK,GAAkB,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC;QAC3C,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QAClB,OAAO,GAAG,EAAE;YACV,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC7B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC,CAAC;IACJ,CAAC;IAED,iCAAiC;IACjC,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;IAC7B,CAAC;IAED,KAAK;QACH,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QACzB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,QAAQ,GAAG,CAAC,CAAC;QAClB,IAAI,CAAC,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChD,CAAC;IAED,IAAI;QACF,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAC1B,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IAEO,IAAI,GAAG,CAAC,SAAiB,EAAQ,EAAE;QACzC,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAE1B,mCAAmC;QACnC,MAAM,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAClE,IAAI,CAAC,QAAQ,GAAG,SAAS,CAAC;QAE1B,+BAA+B;QAC/B,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;YACpE,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACrB,CAAC;QAED,0BAA0B;QAC1B,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;YAChC,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,SAAS,CAAC,CAAC;QAC1B,CAAC;QAED,IAAI,CAAC,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChD,CAAC,CAAC;CACH;AAED,uDAAuD;AACvD,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,UAAU,EAAE,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Loom Router — Events
3
+ */
4
+ import { LoomEvent } from "../event";
5
+ /** Emitted on every navigation */
6
+ export declare class RouteChanged extends LoomEvent {
7
+ readonly path: string;
8
+ readonly params: Record<string, string>;
9
+ readonly previous: string;
10
+ constructor(path: string, params: Record<string, string>, previous: string);
11
+ }
12
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/router/events.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,kCAAkC;AAClC,qBAAa,YAAa,SAAQ,SAAS;aAEvB,IAAI,EAAE,MAAM;aACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;aAC9B,QAAQ,EAAE,MAAM;gBAFhB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC9B,QAAQ,EAAE,MAAM;CAInC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Loom Router — Events
3
+ */
4
+ import { LoomEvent } from "../event";
5
+ /** Emitted on every navigation */
6
+ export class RouteChanged extends LoomEvent {
7
+ path;
8
+ params;
9
+ previous;
10
+ constructor(path, params, previous) {
11
+ super();
12
+ this.path = path;
13
+ this.params = params;
14
+ this.previous = previous;
15
+ }
16
+ }
17
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/router/events.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,kCAAkC;AAClC,MAAM,OAAO,YAAa,SAAQ,SAAS;IAEvB;IACA;IACA;IAHlB,YACkB,IAAY,EACZ,MAA8B,EAC9B,QAAgB;QAEhC,KAAK,EAAE,CAAC;QAJQ,SAAI,GAAJ,IAAI,CAAQ;QACZ,WAAM,GAAN,MAAM,CAAwB;QAC9B,aAAQ,GAAR,QAAQ,CAAQ;IAGlC,CAAC;CACF"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Loom Router — Barrel exports
3
+ */
4
+ export { type RouterMode, HashMode, HistoryMode } from "./mode";
5
+ export { RouteChanged } from "./events";
6
+ export { route, guard, matchRoute, routes, guardRegistry } from "./route";
7
+ export type { RouteEntry, GuardRegistration } from "./route";
8
+ export { params, routeQuery } from "../decorators/state";
9
+ export { transform } from "../decorators/transform";
10
+ export { LoomRouter } from "./router";
11
+ export type { RouterOptions, RouteInfo } from "./router";
12
+ export { LoomOutlet } from "./outlet";
13
+ export { LoomLink } from "./link";
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/router/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,KAAK,UAAU,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAGhE,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGxC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC1E,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAG7D,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAGpD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAGzD,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Loom Router — Barrel exports
3
+ */
4
+ // Mode
5
+ export { HashMode, HistoryMode } from "./mode";
6
+ // Events
7
+ export { RouteChanged } from "./events";
8
+ // Route table & decorators
9
+ export { route, guard, matchRoute, routes, guardRegistry } from "./route";
10
+ // Route data sentinels (for @prop({params}) and @prop({query: routeQuery}))
11
+ export { params, routeQuery } from "../decorators/state";
12
+ export { transform } from "../decorators/transform";
13
+ // Router service
14
+ export { LoomRouter } from "./router";
15
+ // Components
16
+ export { LoomOutlet } from "./outlet";
17
+ export { LoomLink } from "./link";
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/router/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO;AACP,OAAO,EAAmB,QAAQ,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAEhE,SAAS;AACT,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAExC,2BAA2B;AAC3B,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAG1E,4EAA4E;AAC5E,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEpD,iBAAiB;AACjB,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAGtC,aAAa;AACb,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Loom Router — <loom-link>
3
+ *
4
+ * Declarative navigation link. Renders an <a> that adapts
5
+ * its href to the current router mode (hash vs history).
6
+ * Adds `.active` class when the current route matches.
7
+ */
8
+ import { LoomElement } from "../element";
9
+ declare class LoomLink extends LoomElement {
10
+ to: string;
11
+ private anchor;
12
+ private get router();
13
+ connectedCallback(): void;
14
+ private _onRouteChanged;
15
+ private _sync;
16
+ }
17
+ export { LoomLink };
18
+ //# sourceMappingURL=link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../src/router/link.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAMzC,cACM,QAAS,SAAQ,WAAW;IAC1B,EAAE,SAAO;IAEH,OAAO,CAAC,MAAM,CAAqB;IAE/C,OAAO,KAAK,MAAM,GAEjB;IAED,iBAAiB;IAgCjB,OAAO,CAAC,eAAe;IAIvB,OAAO,CAAC,KAAK;CAMd;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Loom Router — <loom-link>
3
+ *
4
+ * Declarative navigation link. Renders an <a> that adapts
5
+ * its href to the current router mode (hash vs history).
6
+ * Adds `.active` class when the current route matches.
7
+ */
8
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
9
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
10
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
11
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
12
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
13
+ };
14
+ import { LoomElement } from "../element";
15
+ import { component, prop, on, query } from "../decorators";
16
+ import { app } from "../app";
17
+ import { LoomRouter } from "./router";
18
+ import { RouteChanged } from "./events";
19
+ let LoomLink = class LoomLink extends LoomElement {
20
+ to = "/";
21
+ anchor;
22
+ get router() {
23
+ return app.get(LoomRouter);
24
+ }
25
+ connectedCallback() {
26
+ super.connectedCallback();
27
+ this.css `
28
+ :host { display: contents; }
29
+ a {
30
+ color: inherit;
31
+ text-decoration: inherit;
32
+ cursor: pointer;
33
+ display: flex;
34
+ align-items: center;
35
+ gap: inherit;
36
+ }
37
+ `;
38
+ // Build initial DOM
39
+ const a = document.createElement("a");
40
+ a.setAttribute("part", "anchor");
41
+ const slot = document.createElement("slot");
42
+ a.appendChild(slot);
43
+ this.shadow.appendChild(a);
44
+ this._sync();
45
+ // Intercept clicks — use router.go() instead of native nav
46
+ this.shadow.addEventListener("click", (e) => {
47
+ e.preventDefault();
48
+ this.router.go(this.to);
49
+ });
50
+ }
51
+ _onRouteChanged() {
52
+ this._sync();
53
+ }
54
+ _sync() {
55
+ const a = this.anchor;
56
+ if (!a)
57
+ return;
58
+ a.href = this.router.href(this.to);
59
+ a.className = this.router.current.path === this.to ? "active" : "";
60
+ }
61
+ };
62
+ __decorate([
63
+ prop
64
+ ], LoomLink.prototype, "to", void 0);
65
+ __decorate([
66
+ query("a")
67
+ ], LoomLink.prototype, "anchor", void 0);
68
+ __decorate([
69
+ on(RouteChanged)
70
+ ], LoomLink.prototype, "_onRouteChanged", null);
71
+ LoomLink = __decorate([
72
+ component("loom-link")
73
+ ], LoomLink);
74
+ export { LoomLink };
75
+ //# sourceMappingURL=link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.js","sourceRoot":"","sources":["../../src/router/link.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;;;;;;;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAC3D,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGxC,IAAM,QAAQ,GAAd,MAAM,QAAS,SAAQ,WAAW;IAC1B,EAAE,GAAG,GAAG,CAAC;IAEK,MAAM,CAAqB;IAE/C,IAAY,MAAM;QAChB,OAAO,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;IAC7B,CAAC;IAED,iBAAiB;QACf,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAE1B,IAAI,CAAC,GAAG,CAAA;;;;;;;;;;KAUP,CAAC;QAEF,oBAAoB;QACpB,MAAM,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;QACtC,CAAC,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;QAC5C,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QACpB,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QAE3B,IAAI,CAAC,KAAK,EAAE,CAAC;QAEb,2DAA2D;QAC3D,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,CAAQ,EAAE,EAAE;YACjD,CAAC,CAAC,cAAc,EAAE,CAAC;YACnB,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;IACL,CAAC;IAGO,eAAe;QACrB,IAAI,CAAC,KAAK,EAAE,CAAC;IACf,CAAC;IAEO,KAAK;QACX,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;QACtB,IAAI,CAAC,CAAC;YAAE,OAAO;QACf,CAAC,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnC,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;IACrE,CAAC;CACF,CAAA;AAlDO;IAAL,IAAI;oCAAU;AAEK;IAAnB,KAAK,CAAC,GAAG,CAAC;wCAAoC;AAsCvC;IADP,EAAE,CAAC,YAAY,CAAC;+CAGhB;AA3CG,QAAQ;IADb,SAAS,CAAC,WAAW,CAAC;GACjB,QAAQ,CAmDb;AAED,OAAO,EAAE,QAAQ,EAAE,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Loom Router — Mode abstraction
3
+ *
4
+ * Separates URL read/write/listen so the same router logic
5
+ * works with both hash and history-based navigation.
6
+ */
7
+ export interface RouterMode {
8
+ /** Read the current path */
9
+ read(): string;
10
+ /** Navigate to a path (pushes history) */
11
+ write(path: string): void;
12
+ /** Replace current path (no history entry) */
13
+ replace(path: string): void;
14
+ /** Listen for external navigation (back/forward). Returns cleanup fn. */
15
+ listen(cb: () => void): () => void;
16
+ /** Build an href string for <a> tags */
17
+ href(path: string): string;
18
+ }
19
+ export declare class HashMode implements RouterMode {
20
+ read(): string;
21
+ write(path: string): void;
22
+ replace(path: string): void;
23
+ listen(cb: () => void): () => void;
24
+ href(path: string): string;
25
+ }
26
+ export declare class HistoryMode implements RouterMode {
27
+ read(): string;
28
+ write(path: string): void;
29
+ replace(path: string): void;
30
+ listen(cb: () => void): () => void;
31
+ href(path: string): string;
32
+ }
33
+ //# sourceMappingURL=mode.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mode.d.ts","sourceRoot":"","sources":["../../src/router/mode.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,UAAU;IACzB,4BAA4B;IAC5B,IAAI,IAAI,MAAM,CAAC;IACf,0CAA0C;IAC1C,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,8CAA8C;IAC9C,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,yEAAyE;IACzE,MAAM,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC;IACnC,wCAAwC;IACxC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAC;CAC5B;AAED,qBAAa,QAAS,YAAW,UAAU;IACzC,IAAI,IAAI,MAAM;IAId,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAIzB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAM3B,MAAM,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAKlC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAG3B;AAED,qBAAa,WAAY,YAAW,UAAU;IAC5C,IAAI,IAAI,MAAM;IAId,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAMzB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAK3B,MAAM,CAAC,EAAE,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI;IAKlC,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;CAG3B"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Loom Router — Mode abstraction
3
+ *
4
+ * Separates URL read/write/listen so the same router logic
5
+ * works with both hash and history-based navigation.
6
+ */
7
+ export class HashMode {
8
+ read() {
9
+ return location.hash.slice(1) || "/";
10
+ }
11
+ write(path) {
12
+ location.hash = path;
13
+ }
14
+ replace(path) {
15
+ const url = new URL(location.href);
16
+ url.hash = path;
17
+ history.replaceState(null, "", url);
18
+ }
19
+ listen(cb) {
20
+ window.addEventListener("hashchange", cb);
21
+ return () => window.removeEventListener("hashchange", cb);
22
+ }
23
+ href(path) {
24
+ return `#${path}`;
25
+ }
26
+ }
27
+ export class HistoryMode {
28
+ read() {
29
+ return location.pathname || "/";
30
+ }
31
+ write(path) {
32
+ history.pushState(null, "", path);
33
+ // pushState doesn't fire popstate — we dispatch manually
34
+ window.dispatchEvent(new PopStateEvent("popstate"));
35
+ }
36
+ replace(path) {
37
+ history.replaceState(null, "", path);
38
+ window.dispatchEvent(new PopStateEvent("popstate"));
39
+ }
40
+ listen(cb) {
41
+ window.addEventListener("popstate", cb);
42
+ return () => window.removeEventListener("popstate", cb);
43
+ }
44
+ href(path) {
45
+ return path;
46
+ }
47
+ }
48
+ //# sourceMappingURL=mode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mode.js","sourceRoot":"","sources":["../../src/router/mode.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAeH,MAAM,OAAO,QAAQ;IACnB,IAAI;QACF,OAAO,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;IACvC,CAAC;IAED,KAAK,CAAC,IAAY;QAChB,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAC;IACvB,CAAC;IAED,OAAO,CAAC,IAAY;QAClB,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACnC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC;QAChB,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,CAAC,EAAc;QACnB,MAAM,CAAC,gBAAgB,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QAC1C,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED,IAAI,CAAC,IAAY;QACf,OAAO,IAAI,IAAI,EAAE,CAAC;IACpB,CAAC;CACF;AAED,MAAM,OAAO,WAAW;IACtB,IAAI;QACF,OAAO,QAAQ,CAAC,QAAQ,IAAI,GAAG,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,IAAY;QAChB,OAAO,CAAC,SAAS,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;QAClC,yDAAyD;QACzD,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,OAAO,CAAC,IAAY;QAClB,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,EAAE,EAAE,IAAI,CAAC,CAAC;QACrC,MAAM,CAAC,aAAa,CAAC,IAAI,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC;IACtD,CAAC;IAED,MAAM,CAAC,EAAc;QACnB,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;QACxC,OAAO,GAAG,EAAE,CAAC,MAAM,CAAC,mBAAmB,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC1D,CAAC;IAED,IAAI,CAAC,IAAY;QACf,OAAO,IAAI,CAAC;IACd,CAAC;CACF"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Loom Router — <loom-outlet>
3
+ *
4
+ * Renders the component matched by the current route.
5
+ * Supports `inherit-styles` attribute to pass parent stylesheets
6
+ * into the routed component's shadow root.
7
+ *
8
+ * Resolves the initial route on connect so pages render even if
9
+ * RouteChanged fired before the outlet entered the DOM.
10
+ */
11
+ import { LoomElement } from "../element";
12
+ import { RouteChanged } from "./events";
13
+ declare class LoomOutlet extends LoomElement {
14
+ /** Stylesheets to pass down to routed components via adoptStyles() */
15
+ styles: CSSStyleSheet[];
16
+ scrollToTop: boolean;
17
+ /** Optional callback invoked with the routed element after mount */
18
+ routeMount: ((el: HTMLElement) => void) | null;
19
+ private _currentTag;
20
+ private _currentEl;
21
+ private _initialResolved;
22
+ onRouteChanged(e: RouteChanged): void;
23
+ /** Called after the first render — resolve whatever the current URL is */
24
+ firstUpdated(): void;
25
+ private _show;
26
+ private _mount;
27
+ /**
28
+ * Inject route params and query params into the element.
29
+ * Uses ROUTE_PROPS metadata when available (typed properties),
30
+ * falls back to setAttribute for backward compat.
31
+ */
32
+ private _injectRouteData;
33
+ /** Parse query params from the URL hash */
34
+ private _parseQuery;
35
+ private _adoptParentStyles;
36
+ private _clear;
37
+ private _scrollToTop;
38
+ }
39
+ export { LoomOutlet };
40
+ //# sourceMappingURL=outlet.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outlet.d.ts","sourceRoot":"","sources":["../../src/router/outlet.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGzC,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGxC,cACM,UAAW,SAAQ,WAAW;IAClC,sEAAsE;IAChE,MAAM,EAAE,aAAa,EAAE,CAAM;IAC7B,WAAW,UAAQ;IAEzB,oEAAoE;IACpE,UAAU,EAAE,CAAC,CAAC,EAAE,EAAE,WAAW,KAAK,IAAI,CAAC,GAAG,IAAI,CAAQ;IAEtD,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,UAAU,CAA4B;IAC9C,OAAO,CAAC,gBAAgB,CAAS;IAGjC,cAAc,CAAC,CAAC,EAAE,YAAY;IAI9B,0EAA0E;IAC1E,YAAY;IAUZ,OAAO,CAAC,KAAK;IAoBb,OAAO,CAAC,MAAM;IAmBd;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IAyCxB,2CAA2C;IAC3C,OAAO,CAAC,WAAW;IAMnB,OAAO,CAAC,kBAAkB;IAM1B,OAAO,CAAC,MAAM;IAQd,OAAO,CAAC,YAAY;CAkBrB;AAED,OAAO,EAAE,UAAU,EAAE,CAAC"}