@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.
- package/LICENSE +21 -0
- package/README.md +108 -0
- package/dist/app.d.ts +70 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +152 -0
- package/dist/app.js.map +1 -0
- package/dist/bus.d.ts +27 -0
- package/dist/bus.d.ts.map +1 -0
- package/dist/bus.js +41 -0
- package/dist/bus.js.map +1 -0
- package/dist/css.d.ts +25 -0
- package/dist/css.d.ts.map +1 -0
- package/dist/css.js +48 -0
- package/dist/css.js.map +1 -0
- package/dist/decorators/component.d.ts +11 -0
- package/dist/decorators/component.d.ts.map +1 -0
- package/dist/decorators/component.js +38 -0
- package/dist/decorators/component.js.map +1 -0
- package/dist/decorators/di.d.ts +37 -0
- package/dist/decorators/di.d.ts.map +1 -0
- package/dist/decorators/di.js +65 -0
- package/dist/decorators/di.js.map +1 -0
- package/dist/decorators/dom.d.ts +15 -0
- package/dist/decorators/dom.d.ts.map +1 -0
- package/dist/decorators/dom.js +33 -0
- package/dist/decorators/dom.js.map +1 -0
- package/dist/decorators/events.d.ts +46 -0
- package/dist/decorators/events.d.ts.map +1 -0
- package/dist/decorators/events.js +69 -0
- package/dist/decorators/events.js.map +1 -0
- package/dist/decorators/index.d.ts +18 -0
- package/dist/decorators/index.d.ts.map +1 -0
- package/dist/decorators/index.js +27 -0
- package/dist/decorators/index.js.map +1 -0
- package/dist/decorators/lifecycle.d.ts +49 -0
- package/dist/decorators/lifecycle.d.ts.map +1 -0
- package/dist/decorators/lifecycle.js +105 -0
- package/dist/decorators/lifecycle.js.map +1 -0
- package/dist/decorators/state.d.ts +41 -0
- package/dist/decorators/state.d.ts.map +1 -0
- package/dist/decorators/state.js +125 -0
- package/dist/decorators/state.js.map +1 -0
- package/dist/decorators/symbols.d.ts +13 -0
- package/dist/decorators/symbols.d.ts.map +1 -0
- package/dist/decorators/symbols.js +15 -0
- package/dist/decorators/symbols.js.map +1 -0
- package/dist/decorators/timing.d.ts +35 -0
- package/dist/decorators/timing.d.ts.map +1 -0
- package/dist/decorators/timing.js +57 -0
- package/dist/decorators/timing.js.map +1 -0
- package/dist/decorators/transform.d.ts +45 -0
- package/dist/decorators/transform.d.ts.map +1 -0
- package/dist/decorators/transform.js +48 -0
- package/dist/decorators/transform.js.map +1 -0
- package/dist/element.d.ts +62 -0
- package/dist/element.d.ts.map +1 -0
- package/dist/element.js +150 -0
- package/dist/element.js.map +1 -0
- package/dist/event.d.ts +24 -0
- package/dist/event.d.ts.map +1 -0
- package/dist/event.js +35 -0
- package/dist/event.js.map +1 -0
- package/dist/icon.d.ts +35 -0
- package/dist/icon.d.ts.map +1 -0
- package/dist/icon.js +119 -0
- package/dist/icon.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/jsx-dev-runtime.d.ts +8 -0
- package/dist/jsx-dev-runtime.d.ts.map +1 -0
- package/dist/jsx-dev-runtime.js +8 -0
- package/dist/jsx-dev-runtime.js.map +1 -0
- package/dist/jsx-runtime.d.ts +13 -0
- package/dist/jsx-runtime.d.ts.map +1 -0
- package/dist/jsx-runtime.js +101 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/morph.d.ts +23 -0
- package/dist/morph.d.ts.map +1 -0
- package/dist/morph.js +212 -0
- package/dist/morph.js.map +1 -0
- package/dist/reactive.d.ts +75 -0
- package/dist/reactive.d.ts.map +1 -0
- package/dist/reactive.js +133 -0
- package/dist/reactive.js.map +1 -0
- package/dist/render-loop.d.ts +34 -0
- package/dist/render-loop.d.ts.map +1 -0
- package/dist/render-loop.js +70 -0
- package/dist/render-loop.js.map +1 -0
- package/dist/router/events.d.ts +12 -0
- package/dist/router/events.d.ts.map +1 -0
- package/dist/router/events.js +17 -0
- package/dist/router/events.js.map +1 -0
- package/dist/router/index.d.ts +14 -0
- package/dist/router/index.d.ts.map +1 -0
- package/dist/router/index.js +18 -0
- package/dist/router/index.js.map +1 -0
- package/dist/router/link.d.ts +18 -0
- package/dist/router/link.d.ts.map +1 -0
- package/dist/router/link.js +75 -0
- package/dist/router/link.js.map +1 -0
- package/dist/router/mode.d.ts +33 -0
- package/dist/router/mode.d.ts.map +1 -0
- package/dist/router/mode.js +48 -0
- package/dist/router/mode.js.map +1 -0
- package/dist/router/outlet.d.ts +40 -0
- package/dist/router/outlet.d.ts.map +1 -0
- package/dist/router/outlet.js +171 -0
- package/dist/router/outlet.js.map +1 -0
- package/dist/router/route.d.ts +76 -0
- package/dist/router/route.d.ts.map +1 -0
- package/dist/router/route.js +147 -0
- package/dist/router/route.js.map +1 -0
- package/dist/router/router.d.ts +50 -0
- package/dist/router/router.d.ts.map +1 -0
- package/dist/router/router.js +140 -0
- package/dist/router/router.js.map +1 -0
- package/dist/storage.d.ts +55 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +90 -0
- package/dist/storage.js.map +1 -0
- package/dist/virtual.d.ts +69 -0
- package/dist/virtual.d.ts.map +1 -0
- package/dist/virtual.js +247 -0
- package/dist/virtual.js.map +1 -0
- package/package.json +58 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare const REACTIVES: unique symbol;
|
|
2
|
+
export declare const PROPS: unique symbol;
|
|
3
|
+
export declare const ON_HANDLERS: unique symbol;
|
|
4
|
+
export declare const WATCHERS: unique symbol;
|
|
5
|
+
export declare const EMITTERS: unique symbol;
|
|
6
|
+
export declare const COMPUTED_DIRTY: unique symbol;
|
|
7
|
+
export declare const CATCH_HANDLER: unique symbol;
|
|
8
|
+
export declare const MOUNT_HANDLERS: unique symbol;
|
|
9
|
+
export declare const UNMOUNT_HANDLERS: unique symbol;
|
|
10
|
+
export declare const INJECT_PARAMS: unique symbol;
|
|
11
|
+
export declare const ROUTE_PROPS: unique symbol;
|
|
12
|
+
export declare const TRANSFORMS: unique symbol;
|
|
13
|
+
//# sourceMappingURL=symbols.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symbols.d.ts","sourceRoot":"","sources":["../../src/decorators/symbols.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,SAAS,eAA2B,CAAC;AAClD,eAAO,MAAM,KAAK,eAAuB,CAAC;AAC1C,eAAO,MAAM,WAAW,eAAoB,CAAC;AAC7C,eAAO,MAAM,QAAQ,eAAuB,CAAC;AAC7C,eAAO,MAAM,QAAQ,eAAsB,CAAC;AAC5C,eAAO,MAAM,cAAc,eAAgC,CAAC;AAC5D,eAAO,MAAM,aAAa,eAAuB,CAAC;AAClD,eAAO,MAAM,cAAc,eAAuB,CAAC;AACnD,eAAO,MAAM,gBAAgB,eAAyB,CAAC;AACvD,eAAO,MAAM,aAAa,eAA+B,CAAC;AAC1D,eAAO,MAAM,WAAW,eAA6B,CAAC;AACtD,eAAO,MAAM,UAAU,eAA4B,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// ── Symbol keys ──
|
|
2
|
+
// Shared contract between decorators and LoomElement.
|
|
3
|
+
export const REACTIVES = Symbol("loom:reactives");
|
|
4
|
+
export const PROPS = Symbol("loom:props");
|
|
5
|
+
export const ON_HANDLERS = Symbol("loom:on");
|
|
6
|
+
export const WATCHERS = Symbol("loom:watch");
|
|
7
|
+
export const EMITTERS = Symbol("loom:emit");
|
|
8
|
+
export const COMPUTED_DIRTY = Symbol("loom:computed:dirty");
|
|
9
|
+
export const CATCH_HANDLER = Symbol("loom:catch");
|
|
10
|
+
export const MOUNT_HANDLERS = Symbol("loom:mount");
|
|
11
|
+
export const UNMOUNT_HANDLERS = Symbol("loom:unmount");
|
|
12
|
+
export const INJECT_PARAMS = Symbol("loom:inject:params");
|
|
13
|
+
export const ROUTE_PROPS = Symbol("loom:route:props");
|
|
14
|
+
export const TRANSFORMS = Symbol("loom:transforms");
|
|
15
|
+
//# sourceMappingURL=symbols.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symbols.js","sourceRoot":"","sources":["../../src/decorators/symbols.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB,sDAAsD;AAEtD,MAAM,CAAC,MAAM,SAAS,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAClD,MAAM,CAAC,MAAM,KAAK,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;AAC1C,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;AAC7C,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;AAC7C,MAAM,CAAC,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC;AAC5C,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAC5D,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;AAClD,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;AACnD,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;AACvD,MAAM,CAAC,MAAM,aAAa,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC;AAC1D,MAAM,CAAC,MAAM,WAAW,GAAG,MAAM,CAAC,kBAAkB,CAAC,CAAC;AACtD,MAAM,CAAC,MAAM,UAAU,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto-cleaned setInterval. Runs the method every `ms` milliseconds.
|
|
3
|
+
* Timer is started on connect, cleared on disconnect via track().
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* @interval(1000)
|
|
7
|
+
* tick() { this.time = new Date(); }
|
|
8
|
+
* ```
|
|
9
|
+
*/
|
|
10
|
+
export declare function interval(ms: number): (target: any, key: string) => void;
|
|
11
|
+
/**
|
|
12
|
+
* Auto-cleaned setTimeout. Runs the method once after `ms` milliseconds.
|
|
13
|
+
* Timer is started on connect, cleared on disconnect via track().
|
|
14
|
+
*
|
|
15
|
+
* ```ts
|
|
16
|
+
* @timeout(3000)
|
|
17
|
+
* hideWelcome() { this.$(".welcome")?.remove(); }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare function timeout(ms: number): (target: any, key: string) => void;
|
|
21
|
+
/**
|
|
22
|
+
* Centralized rAF loop via RenderLoop. Method receives (deltaTime, timestamp).
|
|
23
|
+
* Use layer to control execution order (lower = earlier).
|
|
24
|
+
*
|
|
25
|
+
* ```ts
|
|
26
|
+
* @animationFrame(10) // layer 10
|
|
27
|
+
* draw(dt: number, t: number) { ... }
|
|
28
|
+
*
|
|
29
|
+
* @animationFrame() // default layer 0
|
|
30
|
+
* physics(dt: number) { ... }
|
|
31
|
+
* ```
|
|
32
|
+
*/
|
|
33
|
+
export declare function animationFrame(layer?: number): (target: any, key: string) => void;
|
|
34
|
+
export declare function animationFrame(target: any, key: string): void;
|
|
35
|
+
//# sourceMappingURL=timing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timing.d.ts","sourceRoot":"","sources":["../../src/decorators/timing.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,IACzB,QAAQ,GAAG,EAAE,KAAK,MAAM,UAQjC;AAED;;;;;;;;GAQG;AACH,wBAAgB,OAAO,CAAC,EAAE,EAAE,MAAM,IACxB,QAAQ,GAAG,EAAE,KAAK,MAAM,UAQjC;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,cAAc,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;AACnF,wBAAgB,cAAc,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { renderLoop } from "../render-loop";
|
|
2
|
+
/**
|
|
3
|
+
* Auto-cleaned setInterval. Runs the method every `ms` milliseconds.
|
|
4
|
+
* Timer is started on connect, cleared on disconnect via track().
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* @interval(1000)
|
|
8
|
+
* tick() { this.time = new Date(); }
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export function interval(ms) {
|
|
12
|
+
return (target, key) => {
|
|
13
|
+
const origConnect = target.connectedCallback;
|
|
14
|
+
target.connectedCallback = function () {
|
|
15
|
+
origConnect?.call(this);
|
|
16
|
+
const id = setInterval(() => this[key](), ms);
|
|
17
|
+
this.track(() => clearInterval(id));
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Auto-cleaned setTimeout. Runs the method once after `ms` milliseconds.
|
|
23
|
+
* Timer is started on connect, cleared on disconnect via track().
|
|
24
|
+
*
|
|
25
|
+
* ```ts
|
|
26
|
+
* @timeout(3000)
|
|
27
|
+
* hideWelcome() { this.$(".welcome")?.remove(); }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export function timeout(ms) {
|
|
31
|
+
return (target, key) => {
|
|
32
|
+
const origConnect = target.connectedCallback;
|
|
33
|
+
target.connectedCallback = function () {
|
|
34
|
+
origConnect?.call(this);
|
|
35
|
+
const id = setTimeout(() => this[key](), ms);
|
|
36
|
+
this.track(() => clearTimeout(id));
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
export function animationFrame(targetOrLayer, key) {
|
|
41
|
+
// Called as @animationFrame (no parens)
|
|
42
|
+
if (typeof targetOrLayer === "object" && typeof key === "string") {
|
|
43
|
+
wireAnimationFrame(targetOrLayer, key, 0);
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
// Called as @animationFrame() or @animationFrame(layer)
|
|
47
|
+
const layer = typeof targetOrLayer === "number" ? targetOrLayer : 0;
|
|
48
|
+
return (target, key) => wireAnimationFrame(target, key, layer);
|
|
49
|
+
}
|
|
50
|
+
function wireAnimationFrame(target, key, layer) {
|
|
51
|
+
const origConnect = target.connectedCallback;
|
|
52
|
+
target.connectedCallback = function () {
|
|
53
|
+
origConnect?.call(this);
|
|
54
|
+
this.track(renderLoop.add(layer, (dt, t) => this[key](dt, t)));
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=timing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"timing.js","sourceRoot":"","sources":["../../src/decorators/timing.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CAAC,EAAU;IACjC,OAAO,CAAC,MAAW,EAAE,GAAW,EAAE,EAAE;QAClC,MAAM,WAAW,GAAG,MAAM,CAAC,iBAAiB,CAAC;QAC7C,MAAM,CAAC,iBAAiB,GAAG;YACzB,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YACxB,MAAM,EAAE,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YAC9C,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC;QACtC,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,OAAO,CAAC,EAAU;IAChC,OAAO,CAAC,MAAW,EAAE,GAAW,EAAE,EAAE;QAClC,MAAM,WAAW,GAAG,MAAM,CAAC,iBAAiB,CAAC;QAC7C,MAAM,CAAC,iBAAiB,GAAG;YACzB,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YACxB,MAAM,EAAE,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;YAC7C,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC;QACrC,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAgBD,MAAM,UAAU,cAAc,CAC5B,aAAmB,EACnB,GAAY;IAEZ,wCAAwC;IACxC,IAAI,OAAO,aAAa,KAAK,QAAQ,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACjE,kBAAkB,CAAC,aAAa,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QAC1C,OAAO;IACT,CAAC;IACD,wDAAwD;IACxD,MAAM,KAAK,GAAG,OAAO,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;IACpE,OAAO,CAAC,MAAW,EAAE,GAAW,EAAE,EAAE,CAAC,kBAAkB,CAAC,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,kBAAkB,CAAC,MAAW,EAAE,GAAW,EAAE,KAAa;IACjE,MAAM,WAAW,GAAG,MAAM,CAAC,iBAAiB,CAAC;IAC7C,MAAM,CAAC,iBAAiB,GAAG;QACzB,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACxB,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAU,EAAE,CAAS,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACjF,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @transform — Type conversion for route params/query values.
|
|
3
|
+
*
|
|
4
|
+
* Accepts any `(value: any) => T` function. Built-in constructors
|
|
5
|
+
* like `Number` and `Boolean` work natively since they match the signature.
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* @prop({ param: "id" })
|
|
9
|
+
* @transform(Number)
|
|
10
|
+
* userId!: number; // "42" → 42
|
|
11
|
+
*
|
|
12
|
+
* @prop({ param: "tags" })
|
|
13
|
+
* @transform((v) => v.split(","))
|
|
14
|
+
* tags!: string[]; // "a,b,c" → ["a", "b", "c"]
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* For full object decomposition, use `typed<T>()`:
|
|
18
|
+
*
|
|
19
|
+
* ```ts
|
|
20
|
+
* interface MyParams { id: number; slug: string }
|
|
21
|
+
*
|
|
22
|
+
* @prop({ params })
|
|
23
|
+
* @transform(typed<MyParams>({ id: Number }))
|
|
24
|
+
* routeParams!: MyParams;
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function transform(fn: (value: any) => any): (target: any, key: string) => void;
|
|
28
|
+
/**
|
|
29
|
+
* Type-safe field-level transform for object decomposition.
|
|
30
|
+
*
|
|
31
|
+
* Schema keys must match fields of `T`. Each converter must return
|
|
32
|
+
* the correct type for that field. Unlisted fields pass through as-is.
|
|
33
|
+
*
|
|
34
|
+
* ```ts
|
|
35
|
+
* interface MyParams { id: number; slug: string }
|
|
36
|
+
* typed<MyParams>({ id: Number })
|
|
37
|
+
* // → { id: 42, slug: "hello" }
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
type TransformSchema<T> = {
|
|
41
|
+
[K in keyof T]?: (raw: string) => T[K];
|
|
42
|
+
};
|
|
43
|
+
export declare function typed<T>(schema: TransformSchema<T>): (raw: Record<string, string>) => T;
|
|
44
|
+
export {};
|
|
45
|
+
//# sourceMappingURL=transform.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform.d.ts","sourceRoot":"","sources":["../../src/decorators/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,wBAAgB,SAAS,CAAC,EAAE,EAAE,CAAC,KAAK,EAAE,GAAG,KAAK,GAAG,IACvC,QAAQ,GAAG,EAAE,KAAK,MAAM,UAKjC;AAED;;;;;;;;;;;GAWG;AACH,KAAK,eAAe,CAAC,CAAC,IAAI;KACvB,CAAC,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC;CACvC,CAAC;AAEF,wBAAgB,KAAK,CAAC,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAWvF"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @transform — Type conversion for route params/query values.
|
|
3
|
+
*
|
|
4
|
+
* Accepts any `(value: any) => T` function. Built-in constructors
|
|
5
|
+
* like `Number` and `Boolean` work natively since they match the signature.
|
|
6
|
+
*
|
|
7
|
+
* ```ts
|
|
8
|
+
* @prop({ param: "id" })
|
|
9
|
+
* @transform(Number)
|
|
10
|
+
* userId!: number; // "42" → 42
|
|
11
|
+
*
|
|
12
|
+
* @prop({ param: "tags" })
|
|
13
|
+
* @transform((v) => v.split(","))
|
|
14
|
+
* tags!: string[]; // "a,b,c" → ["a", "b", "c"]
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* For full object decomposition, use `typed<T>()`:
|
|
18
|
+
*
|
|
19
|
+
* ```ts
|
|
20
|
+
* interface MyParams { id: number; slug: string }
|
|
21
|
+
*
|
|
22
|
+
* @prop({ params })
|
|
23
|
+
* @transform(typed<MyParams>({ id: Number }))
|
|
24
|
+
* routeParams!: MyParams;
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
import { TRANSFORMS } from "./symbols";
|
|
28
|
+
export function transform(fn) {
|
|
29
|
+
return (target, key) => {
|
|
30
|
+
const ctor = target.constructor;
|
|
31
|
+
if (!ctor[TRANSFORMS])
|
|
32
|
+
ctor[TRANSFORMS] = new Map();
|
|
33
|
+
ctor[TRANSFORMS].set(key, fn);
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export function typed(schema) {
|
|
37
|
+
return (raw) => {
|
|
38
|
+
const result = { ...raw };
|
|
39
|
+
for (const key of Object.keys(schema)) {
|
|
40
|
+
const fn = schema[key];
|
|
41
|
+
if (fn && key in result) {
|
|
42
|
+
result[key] = fn(result[key]);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return result;
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=transform.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transform.js","sourceRoot":"","sources":["../../src/decorators/transform.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,MAAM,UAAU,SAAS,CAAC,EAAuB;IAC/C,OAAO,CAAC,MAAW,EAAE,GAAW,EAAE,EAAE;QAClC,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC;QAChC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC;YAAE,IAAI,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,EAAoB,CAAC;QACtE,IAAI,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IAChC,CAAC,CAAC;AACJ,CAAC;AAkBD,MAAM,UAAU,KAAK,CAAI,MAA0B;IACjD,OAAO,CAAC,GAA2B,EAAK,EAAE;QACxC,MAAM,MAAM,GAAQ,EAAE,GAAG,GAAG,EAAE,CAAC;QAC/B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACtC,MAAM,EAAE,GAAI,MAAc,CAAC,GAAG,CAAC,CAAC;YAChC,IAAI,EAAE,IAAI,GAAG,IAAI,MAAM,EAAE,CAAC;gBACxB,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;QACD,OAAO,MAAW,CAAC;IACrB,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loom — LoomElement base class
|
|
3
|
+
*
|
|
4
|
+
* Web Component base with shadow DOM, css tagged templates,
|
|
5
|
+
* lifecycle hooks, and cleanup tracking.
|
|
6
|
+
*/
|
|
7
|
+
import { type Constructor, type Handler } from "./bus";
|
|
8
|
+
import { type LoomEvent } from "./event";
|
|
9
|
+
import { type CSSValue } from "./css";
|
|
10
|
+
export declare abstract class LoomElement extends HTMLElement {
|
|
11
|
+
/** Access the LoomApp instance for inline provider resolution */
|
|
12
|
+
protected get app(): import("./app").LoomApp;
|
|
13
|
+
protected shadow: ShadowRoot;
|
|
14
|
+
private cleanups;
|
|
15
|
+
constructor();
|
|
16
|
+
/** Adopt styles — supports both tagged template and string */
|
|
17
|
+
protected css(text: string): void;
|
|
18
|
+
protected css(strings: TemplateStringsArray, ...values: CSSValue[]): void;
|
|
19
|
+
/**
|
|
20
|
+
* Adopt external CSSStyleSheets into this component's shadow root.
|
|
21
|
+
* Used by the router outlet to pass inherited styles down.
|
|
22
|
+
* Deduplicates — sheets already present are skipped.
|
|
23
|
+
*/
|
|
24
|
+
adoptStyles(sheets: CSSStyleSheet[]): void;
|
|
25
|
+
/** Subscribe to a typed event — auto-cleaned on disconnect */
|
|
26
|
+
protected on<T>(type: Constructor<T>, handler: Handler<T>): () => void;
|
|
27
|
+
/** Emit a typed event */
|
|
28
|
+
protected emit<T extends LoomEvent>(event: T): void;
|
|
29
|
+
/** Track any cleanup function — runs on disconnect */
|
|
30
|
+
protected track(unsub: () => void): void;
|
|
31
|
+
/** querySelector within shadow root */
|
|
32
|
+
protected $<T extends Element = HTMLElement>(sel: string): T | null;
|
|
33
|
+
/** querySelectorAll within shadow root */
|
|
34
|
+
protected $$<T extends Element = HTMLElement>(sel: string): T[];
|
|
35
|
+
connectedCallback(): void;
|
|
36
|
+
disconnectedCallback(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Batched re-render. Fires once per microtask when any @reactive/@prop changes.
|
|
39
|
+
* Override this to render your component.
|
|
40
|
+
*/
|
|
41
|
+
update(): Node | Node[] | void;
|
|
42
|
+
/**
|
|
43
|
+
* Called after the very first update(). DOM is guaranteed to exist.
|
|
44
|
+
* Perfect for wiring up canvas, charts, third-party libs, or initial focus.
|
|
45
|
+
*/
|
|
46
|
+
firstUpdated(): void;
|
|
47
|
+
/**
|
|
48
|
+
* Return false to skip this render cycle. Called before each update().
|
|
49
|
+
* Default: always renders.
|
|
50
|
+
*/
|
|
51
|
+
shouldUpdate(): boolean;
|
|
52
|
+
private _updateScheduled;
|
|
53
|
+
private _hasUpdated;
|
|
54
|
+
/** Called by @reactive setters — batches via microtask */
|
|
55
|
+
scheduleUpdate(): void;
|
|
56
|
+
/**
|
|
57
|
+
* Re-run lifecycle from scratch (after @catch error).
|
|
58
|
+
* Cleans up, then re-connects.
|
|
59
|
+
*/
|
|
60
|
+
retry(): void;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=element.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element.d.ts","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAO,KAAK,WAAW,EAAE,KAAK,OAAO,EAAE,MAAM,OAAO,CAAC;AAC5D,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,KAAK,QAAQ,EAAY,MAAM,OAAO,CAAC;AAKhD,8BAAsB,WAAY,SAAQ,WAAW;IACnD,iEAAiE;IACjE,SAAS,KAAK,GAAG,4BAAkB;IAEnC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC;IAC7B,OAAO,CAAC,QAAQ,CAAsB;;IAStC,8DAA8D;IAC9D,SAAS,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IACjC,SAAS,CAAC,GAAG,CAAC,OAAO,EAAE,oBAAoB,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI;IAQzE;;;;OAIG;IACH,WAAW,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,IAAI;IAU1C,8DAA8D;IAC9D,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;IAMtE,yBAAyB;IACzB,SAAS,CAAC,IAAI,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI;IAMnD,sDAAsD;IACtD,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,IAAI,GAAG,IAAI;IAMxC,uCAAuC;IACvC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,OAAO,GAAG,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI;IAInE,0CAA0C;IAC1C,SAAS,CAAC,EAAE,CAAC,CAAC,SAAS,OAAO,GAAG,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,EAAE;IAM/D,iBAAiB,IAAI,IAAI;IAuBzB,oBAAoB,IAAI,IAAI;IAY5B;;;OAGG;IACH,MAAM,IAAI,IAAI,GAAG,IAAI,EAAE,GAAG,IAAI;IAE9B;;;OAGG;IACH,YAAY,IAAI,IAAI;IAEpB;;;OAGG;IACH,YAAY,IAAI,OAAO;IAMvB,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,WAAW,CAAS;IAE5B,0DAA0D;IAC1D,cAAc,IAAI,IAAI;IAsBtB;;;OAGG;IACH,KAAK,IAAI,IAAI;CAKd"}
|
package/dist/element.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loom — LoomElement base class
|
|
3
|
+
*
|
|
4
|
+
* Web Component base with shadow DOM, css tagged templates,
|
|
5
|
+
* lifecycle hooks, and cleanup tracking.
|
|
6
|
+
*/
|
|
7
|
+
import { bus } from "./bus";
|
|
8
|
+
import { adoptCSS } from "./css";
|
|
9
|
+
import { ON_HANDLERS, COMPUTED_DIRTY, MOUNT_HANDLERS, UNMOUNT_HANDLERS, REACTIVES } from "./decorators";
|
|
10
|
+
import { morph } from "./morph";
|
|
11
|
+
import { app } from "./app";
|
|
12
|
+
export class LoomElement extends HTMLElement {
|
|
13
|
+
/** Access the LoomApp instance for inline provider resolution */
|
|
14
|
+
get app() { return app; }
|
|
15
|
+
shadow;
|
|
16
|
+
cleanups = [];
|
|
17
|
+
constructor() {
|
|
18
|
+
super();
|
|
19
|
+
this.shadow = this.attachShadow({ mode: "open" });
|
|
20
|
+
}
|
|
21
|
+
css(stringsOrText, ...values) {
|
|
22
|
+
adoptCSS(this.shadow, stringsOrText, ...values);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Adopt external CSSStyleSheets into this component's shadow root.
|
|
26
|
+
* Used by the router outlet to pass inherited styles down.
|
|
27
|
+
* Deduplicates — sheets already present are skipped.
|
|
28
|
+
*/
|
|
29
|
+
adoptStyles(sheets) {
|
|
30
|
+
const existing = this.shadow.adoptedStyleSheets;
|
|
31
|
+
const newSheets = sheets.filter(s => !existing.includes(s));
|
|
32
|
+
if (newSheets.length > 0) {
|
|
33
|
+
this.shadow.adoptedStyleSheets = [...existing, ...newSheets];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// ── Event helpers ──
|
|
37
|
+
/** Subscribe to a typed event — auto-cleaned on disconnect */
|
|
38
|
+
on(type, handler) {
|
|
39
|
+
const unsub = bus.on(type, handler);
|
|
40
|
+
this.cleanups.push(unsub);
|
|
41
|
+
return unsub;
|
|
42
|
+
}
|
|
43
|
+
/** Emit a typed event */
|
|
44
|
+
emit(event) {
|
|
45
|
+
bus.emit(event);
|
|
46
|
+
}
|
|
47
|
+
// ── Cleanup tracking ──
|
|
48
|
+
/** Track any cleanup function — runs on disconnect */
|
|
49
|
+
track(unsub) {
|
|
50
|
+
this.cleanups.push(unsub);
|
|
51
|
+
}
|
|
52
|
+
// ── DOM queries ──
|
|
53
|
+
/** querySelector within shadow root */
|
|
54
|
+
$(sel) {
|
|
55
|
+
return this.shadow.querySelector(sel);
|
|
56
|
+
}
|
|
57
|
+
/** querySelectorAll within shadow root */
|
|
58
|
+
$$(sel) {
|
|
59
|
+
return Array.from(this.shadow.querySelectorAll(sel));
|
|
60
|
+
}
|
|
61
|
+
// ── Lifecycle ──
|
|
62
|
+
connectedCallback() {
|
|
63
|
+
// Wire @on handlers (bus events + DOM events)
|
|
64
|
+
for (const handler of this[ON_HANDLERS] ?? []) {
|
|
65
|
+
if (handler.domTarget) {
|
|
66
|
+
// DOM EventTarget: @on(window, "resize")
|
|
67
|
+
const fn = (e) => this[handler.key](e);
|
|
68
|
+
handler.domTarget.addEventListener(handler.event, fn);
|
|
69
|
+
this.track(() => handler.domTarget.removeEventListener(handler.event, fn));
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
// Bus event: @on(ColorSelect)
|
|
73
|
+
this.track(bus.on(handler.type, (e) => this[handler.key](e)));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// Only auto-render if component uses reactive patterns
|
|
77
|
+
const hasReactives = (this[REACTIVES]?.length ?? 0) > 0;
|
|
78
|
+
const overridesUpdate = this.update !== LoomElement.prototype.update;
|
|
79
|
+
if (hasReactives || overridesUpdate)
|
|
80
|
+
this.scheduleUpdate();
|
|
81
|
+
// Fire @mount handlers
|
|
82
|
+
for (const key of this[MOUNT_HANDLERS] ?? []) {
|
|
83
|
+
this[key]();
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
disconnectedCallback() {
|
|
87
|
+
// Fire @unmount handlers (before cleanup)
|
|
88
|
+
for (const key of this[UNMOUNT_HANDLERS] ?? []) {
|
|
89
|
+
this[key]();
|
|
90
|
+
}
|
|
91
|
+
// Run all track() cleanups
|
|
92
|
+
this.cleanups.forEach((fn) => fn());
|
|
93
|
+
this.cleanups = [];
|
|
94
|
+
}
|
|
95
|
+
// ── Lifecycle hooks (override in subclass) ──
|
|
96
|
+
/**
|
|
97
|
+
* Batched re-render. Fires once per microtask when any @reactive/@prop changes.
|
|
98
|
+
* Override this to render your component.
|
|
99
|
+
*/
|
|
100
|
+
update() { }
|
|
101
|
+
/**
|
|
102
|
+
* Called after the very first update(). DOM is guaranteed to exist.
|
|
103
|
+
* Perfect for wiring up canvas, charts, third-party libs, or initial focus.
|
|
104
|
+
*/
|
|
105
|
+
firstUpdated() { }
|
|
106
|
+
/**
|
|
107
|
+
* Return false to skip this render cycle. Called before each update().
|
|
108
|
+
* Default: always renders.
|
|
109
|
+
*/
|
|
110
|
+
shouldUpdate() {
|
|
111
|
+
return true;
|
|
112
|
+
}
|
|
113
|
+
// ── Batching internals ──
|
|
114
|
+
_updateScheduled = false;
|
|
115
|
+
_hasUpdated = false;
|
|
116
|
+
/** Called by @reactive setters — batches via microtask */
|
|
117
|
+
scheduleUpdate() {
|
|
118
|
+
if (this._updateScheduled)
|
|
119
|
+
return;
|
|
120
|
+
this._updateScheduled = true;
|
|
121
|
+
queueMicrotask(() => {
|
|
122
|
+
this._updateScheduled = false;
|
|
123
|
+
if (!this.shouldUpdate())
|
|
124
|
+
return;
|
|
125
|
+
// Dirty all @computed caches
|
|
126
|
+
for (const dirtyKey of this[COMPUTED_DIRTY] ?? []) {
|
|
127
|
+
this[dirtyKey] = true;
|
|
128
|
+
}
|
|
129
|
+
const result = this.update();
|
|
130
|
+
// Auto-morph if update() returned DOM nodes
|
|
131
|
+
if (result != null) {
|
|
132
|
+
morph(this.shadow, result);
|
|
133
|
+
}
|
|
134
|
+
if (!this._hasUpdated) {
|
|
135
|
+
this._hasUpdated = true;
|
|
136
|
+
this.firstUpdated();
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Re-run lifecycle from scratch (after @catch error).
|
|
142
|
+
* Cleans up, then re-connects.
|
|
143
|
+
*/
|
|
144
|
+
retry() {
|
|
145
|
+
this.disconnectedCallback();
|
|
146
|
+
this._hasUpdated = false;
|
|
147
|
+
this.connectedCallback();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=element.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"element.js","sourceRoot":"","sources":["../src/element.ts"],"names":[],"mappings":"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"}
|
package/dist/event.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loom — LoomEvent base class
|
|
3
|
+
*
|
|
4
|
+
* All events extend this. Gives you for free:
|
|
5
|
+
* - timestamp (auto-stamped)
|
|
6
|
+
* - clone(overrides?) — typed shallow clone
|
|
7
|
+
* - is(event) — static type guard
|
|
8
|
+
* - toJSON() — serialize to plain object
|
|
9
|
+
* - toString() — debug-friendly string
|
|
10
|
+
*/
|
|
11
|
+
import type { Constructor } from "./bus";
|
|
12
|
+
export declare abstract class LoomEvent {
|
|
13
|
+
/** Auto-stamped on creation */
|
|
14
|
+
readonly timestamp: number;
|
|
15
|
+
/** Shallow clone with optional overrides */
|
|
16
|
+
clone(overrides?: Partial<this>): this;
|
|
17
|
+
/** Type guard — `if (SomeEvent.is(event))` */
|
|
18
|
+
static is<T extends LoomEvent>(this: Constructor<T>, event: unknown): event is T;
|
|
19
|
+
/** Serialize to plain object (strips methods) */
|
|
20
|
+
toJSON(): Record<string, unknown>;
|
|
21
|
+
/** Debug-friendly string */
|
|
22
|
+
toString(): string;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=event.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../src/event.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AAEzC,8BAAsB,SAAS;IAC7B,+BAA+B;IAC/B,QAAQ,CAAC,SAAS,SAAc;IAEhC,4CAA4C;IAC5C,KAAK,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAQtC,8CAA8C;IAC9C,MAAM,CAAC,EAAE,CAAC,CAAC,SAAS,SAAS,EAC3B,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,EACpB,KAAK,EAAE,OAAO,GACb,KAAK,IAAI,CAAC;IAIb,iDAAiD;IACjD,MAAM,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAQjC,4BAA4B;IAC5B,QAAQ,IAAI,MAAM;CAGnB"}
|
package/dist/event.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loom — LoomEvent base class
|
|
3
|
+
*
|
|
4
|
+
* All events extend this. Gives you for free:
|
|
5
|
+
* - timestamp (auto-stamped)
|
|
6
|
+
* - clone(overrides?) — typed shallow clone
|
|
7
|
+
* - is(event) — static type guard
|
|
8
|
+
* - toJSON() — serialize to plain object
|
|
9
|
+
* - toString() — debug-friendly string
|
|
10
|
+
*/
|
|
11
|
+
export class LoomEvent {
|
|
12
|
+
/** Auto-stamped on creation */
|
|
13
|
+
timestamp = Date.now();
|
|
14
|
+
/** Shallow clone with optional overrides */
|
|
15
|
+
clone(overrides) {
|
|
16
|
+
return Object.assign(Object.create(Object.getPrototypeOf(this)), this, overrides);
|
|
17
|
+
}
|
|
18
|
+
/** Type guard — `if (SomeEvent.is(event))` */
|
|
19
|
+
static is(event) {
|
|
20
|
+
return event instanceof this;
|
|
21
|
+
}
|
|
22
|
+
/** Serialize to plain object (strips methods) */
|
|
23
|
+
toJSON() {
|
|
24
|
+
const out = {};
|
|
25
|
+
for (const key of Object.keys(this)) {
|
|
26
|
+
out[key] = this[key];
|
|
27
|
+
}
|
|
28
|
+
return out;
|
|
29
|
+
}
|
|
30
|
+
/** Debug-friendly string */
|
|
31
|
+
toString() {
|
|
32
|
+
return `${this.constructor.name}(${JSON.stringify(this.toJSON())})`;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=event.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event.js","sourceRoot":"","sources":["../src/event.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,MAAM,OAAgB,SAAS;IAC7B,+BAA+B;IACtB,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAEhC,4CAA4C;IAC5C,KAAK,CAAC,SAAyB;QAC7B,OAAO,MAAM,CAAC,MAAM,CAClB,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,EAC1C,IAAI,EACJ,SAAS,CACV,CAAC;IACJ,CAAC;IAED,8CAA8C;IAC9C,MAAM,CAAC,EAAE,CAEP,KAAc;QAEd,OAAO,KAAK,YAAY,IAAI,CAAC;IAC/B,CAAC;IAED,iDAAiD;IACjD,MAAM;QACJ,MAAM,GAAG,GAA4B,EAAE,CAAC;QACxC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACpC,GAAG,CAAC,GAAG,CAAC,GAAI,IAAY,CAAC,GAAG,CAAC,CAAC;QAChC,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,4BAA4B;IAC5B,QAAQ;QACN,OAAO,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC;IACtE,CAAC;CACF"}
|
package/dist/icon.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Loom — Icon Component
|
|
3
|
+
*
|
|
4
|
+
* Reusable SVG icon wrapper with a static registry.
|
|
5
|
+
* Ships with zero built-in icons — register your own.
|
|
6
|
+
*
|
|
7
|
+
* Usage:
|
|
8
|
+
* // Register icons (once, at boot)
|
|
9
|
+
* LoomIcon.register("bolt", '<path d="M13 2 3 14h9l-1 8 10-12h-9l1-8z" />');
|
|
10
|
+
*
|
|
11
|
+
* // Use anywhere in JSX
|
|
12
|
+
* <loom-icon name="bolt" size={20} color="var(--accent)" />
|
|
13
|
+
*/
|
|
14
|
+
import { LoomElement } from "./element";
|
|
15
|
+
export declare class LoomIcon extends LoomElement {
|
|
16
|
+
/** Icon name (must be registered via LoomIcon.register) */
|
|
17
|
+
name: string;
|
|
18
|
+
/** Size in pixels */
|
|
19
|
+
size: number;
|
|
20
|
+
/** Stroke color (CSS value) */
|
|
21
|
+
color: string;
|
|
22
|
+
/** Register an icon. `svgInner` is the SVG inner content (paths, circles, etc). */
|
|
23
|
+
static register(name: string, svgInner: string): void;
|
|
24
|
+
/** Register multiple icons at once. */
|
|
25
|
+
static registerAll(icons: Record<string, string>): void;
|
|
26
|
+
/** Check if an icon is registered. */
|
|
27
|
+
static has(name: string): boolean;
|
|
28
|
+
/** List all registered icon names. */
|
|
29
|
+
static get names(): string[];
|
|
30
|
+
/** Immediately apply size/color from attributes — runs before connectedCallback */
|
|
31
|
+
attributeChangedCallback(name: string, _old: string | null, val: string | null): void;
|
|
32
|
+
connectedCallback(): void;
|
|
33
|
+
update(): SVGSVGElement | HTMLSpanElement;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=icon.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"icon.d.ts","sourceRoot":"","sources":["../src/icon.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AA4BxC,qBACa,QAAS,SAAQ,WAAW;IAEvC,2DAA2D;IACrD,IAAI,SAAM;IAEhB,qBAAqB;IACf,IAAI,SAAM;IAEhB,+BAA+B;IACzB,KAAK,SAAkB;IAE7B,mFAAmF;IACnF,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI;IAIrD,uCAAuC;IACvC,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI;IAMvD,sCAAsC;IACtC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAIjC,sCAAsC;IACtC,MAAM,KAAK,KAAK,IAAI,MAAM,EAAE,CAE3B;IAED,mFAAmF;IACnF,wBAAwB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI;IAU9E,iBAAiB;IASjB,MAAM;CAiBP"}
|