@toyz/loom 0.11.2 → 0.12.1

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/README.md CHANGED
@@ -23,6 +23,16 @@ Loom was born out of pure spite for boilerplate. What began as an ironic "what i
23
23
 
24
24
  It powers [placing.space](https://placing.space) in production — a real-time collaborative pixel canvas — so it's been battle-tested with WebSocket streams, thousands of DOM nodes, and zero framework overhead.
25
25
 
26
+ ## Why Loom?
27
+
28
+ Most frameworks make you choose: **lightweight or batteries-included.** Loom doesn't.
29
+
30
+ - **~20KB gzipped baseline** — smaller than React + ReactDOM alone, but includes a router, DI container, reactivity system, and lifecycle management out of the box.
31
+ - **No virtual DOM** — JSX compiles to real DOM nodes. The morpher diffs the live DOM directly and patches in-place. No throwaway object trees, no GC pressure, no overhead on top of the work you were going to do anyway.
32
+ - **Zero dependencies** — the entire framework is one `package.json` entry. No version conflicts, no transitive supply chain risk, no "which router do we pick" debates.
33
+ - **Pay-as-you-go** — built-in components (`<loom-virtual>`, `<loom-canvas>`, `<loom-icon>`, `<loom-image>`) and systems (`@form`, `@api`, `CollectionStore`) are tree-shaken if you don't import them. You only ship what you use.
34
+ - **Web standards** — built on custom elements, Shadow DOM, and TC39 Stage 3 decorators. When browsers ship native decorator support, your code gets faster for free.
35
+
26
36
  ## Features
27
37
 
28
38
  - **`@component` / `@styles`** — register custom elements and scoped styles in one line
@@ -101,11 +111,12 @@ class ClickCounter extends LoomElement {
101
111
 
102
112
  ## TSConfig
103
113
 
104
- Loom ships its own JSX runtime. Point your config at it:
114
+ Loom uses TC39 decorators, which require `es2022` or later. Point your config at the Loom JSX runtime:
105
115
 
106
116
  ```json
107
117
  {
108
118
  "compilerOptions": {
119
+ "target": "es2022",
109
120
  "jsx": "react-jsx",
110
121
  "jsxImportSource": "@toyz/loom"
111
122
  }
@@ -118,6 +129,7 @@ For Vite:
118
129
  // vite.config.ts
119
130
  export default defineConfig({
120
131
  esbuild: {
132
+ target: "es2022",
121
133
  jsx: "automatic",
122
134
  jsxImportSource: "@toyz/loom",
123
135
  },
@@ -20,9 +20,16 @@ import { type Constructor } from "../bus";
20
20
  * @on(window, "resize")
21
21
  * onResize(e: Event) { ... }
22
22
  * ```
23
+ *
24
+ * Resolver — lazily resolve target at connect time (shadow DOM, @query, etc.):
25
+ * ```ts
26
+ * @on(el => el.shadow, "scroll")
27
+ * onShadowScroll(e: Event) { ... }
28
+ * ```
23
29
  */
24
30
  export declare function on<T extends LoomEvent>(type: Constructor<T>): (method: Function, context: ClassMethodDecoratorContext) => void;
25
31
  export declare function on(target: EventTarget, event: string): (method: Function, context: ClassMethodDecoratorContext) => void;
32
+ export declare function on(resolver: (el: any) => EventTarget, event: string): (method: Function, context: ClassMethodDecoratorContext) => void;
26
33
  /**
27
34
  * Auto-broadcast to the bus.
28
35
  *
@@ -1 +1 @@
1
- {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/decorators/events.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAO,KAAK,WAAW,EAAE,MAAM,QAAQ,CAAC;AAE/C;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,EAAE,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC;AAChI,wBAAgB,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC;AA6BzH;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,IAAI,CAAC,CAAC,SAAS,SAAS,EACtC,KAAK,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,EACtB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,CAAC,IAwBrB,OAAO,QAAQ,GAAG,4BAA4B,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,SAAS,2BAA2B,GAAG,6BAA6B,oBApB7G,OAAO,WAAW,OAAO,EAAE,cA0BrD"}
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/decorators/events.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACrC,OAAO,EAAO,KAAK,WAAW,EAAE,MAAM,QAAQ,CAAC;AAE/C;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,EAAE,CAAC,CAAC,SAAS,SAAS,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC;AAChI,wBAAgB,EAAE,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC;AACzH,wBAAgB,EAAE,CAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,GAAG,KAAK,WAAW,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC;AAiCxI;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,IAAI,CAAC,CAAC,SAAS,SAAS,EACtC,KAAK,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,EACtB,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,CAAC,IAwBrB,OAAO,QAAQ,GAAG,4BAA4B,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,SAAS,2BAA2B,GAAG,6BAA6B,oBApB7G,OAAO,WAAW,OAAO,EAAE,cA0BrD"}
@@ -25,9 +25,13 @@ export function on(typeOrTarget, event) {
25
25
  this[CONNECT_HOOKS] = [];
26
26
  this[CONNECT_HOOKS].push((el) => {
27
27
  if (event !== undefined) {
28
+ // Resolve target: arrow/function resolver has no .prototype, class constructors do
29
+ const target = typeof typeOrTarget === "function" && !typeOrTarget.prototype
30
+ ? typeOrTarget(el)
31
+ : typeOrTarget;
28
32
  const fn = (e) => method.call(el, e);
29
- typeOrTarget.addEventListener(event, fn);
30
- return () => typeOrTarget.removeEventListener(event, fn);
33
+ target.addEventListener(event, fn);
34
+ return () => target.removeEventListener(event, fn);
31
35
  }
32
36
  else {
33
37
  return bus.on(typeOrTarget, (e) => method.call(el, e));
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/decorators/events.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/decorators/events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Loom — Canvas Element
3
+ *
4
+ * Built-in `<loom-canvas>` web component that wraps a `<canvas>`
5
+ * with loom-keep, auto-resize via @observer, and per-frame
6
+ * draw callbacks through Loom's centralized RenderLoop.
7
+ *
8
+ * Usage:
9
+ * <loom-canvas draw={(ctx, dt, t) => {
10
+ * ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
11
+ * ctx.fillRect(x, y, 20, 20);
12
+ * }} />
13
+ *
14
+ * The draw callback receives (CanvasRenderingContext2D, deltaTime, timestamp).
15
+ * Set autoResize={false} and width/height props for fixed-size canvases.
16
+ */
17
+ import { LoomElement } from "./element";
18
+ export type DrawCallback = (ctx: CanvasRenderingContext2D, dt: number, t: number) => void;
19
+ export declare class LoomCanvas extends LoomElement {
20
+ /** Fixed width in CSS pixels (ignored when autoResize is true) */
21
+ accessor width: number;
22
+ /** Fixed height in CSS pixels (ignored when autoResize is true) */
23
+ accessor height: number;
24
+ /** When true, canvas auto-sizes to match host element bounds */
25
+ accessor autoResize: boolean;
26
+ /** Per-frame draw callback: (ctx, deltaTime, timestamp) => void */
27
+ accessor draw: DrawCallback | null;
28
+ accessor canvasEl: HTMLCanvasElement;
29
+ private _ctx;
30
+ /** Cached 2D rendering context */
31
+ get ctx(): CanvasRenderingContext2D;
32
+ /** Reference to the raw <canvas> element */
33
+ get canvas(): HTMLCanvasElement;
34
+ update(): Node;
35
+ private onResize;
36
+ /** Clear the full canvas */
37
+ clear(): void;
38
+ private tick;
39
+ /** Block morph after initial skeleton */
40
+ shouldUpdate(): boolean;
41
+ }
42
+ //# sourceMappingURL=canvas.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas.d.ts","sourceRoot":"","sources":["../../src/element/canvas.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAoBxC,MAAM,MAAM,YAAY,GAAG,CACzB,GAAG,EAAE,wBAAwB,EAC7B,EAAE,EAAE,MAAM,EACV,CAAC,EAAE,MAAM,KACN,IAAI,CAAC;AAEV,qBAEa,UAAW,SAAQ,WAAW;IAIzC,kEAAkE;IAC5D,QAAQ,CAAC,KAAK,SAAK;IAEzB,mEAAmE;IAC7D,QAAQ,CAAC,MAAM,SAAK;IAE1B,gEAAgE;IAC1D,QAAQ,CAAC,UAAU,UAAQ;IAEjC,mEAAmE;IAC5C,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CAAQ;IAKjE,QAAQ,CAAC,QAAQ,EAAG,iBAAiB,CAAC;IAItC,OAAO,CAAC,IAAI,CAAyC;IAErD,kCAAkC;IAClC,IAAI,GAAG,IAAI,wBAAwB,CAKlC;IAED,4CAA4C;IAC5C,IAAI,MAAM,IAAI,iBAAiB,CAE9B;IAID,MAAM,IAAI,IAAI;IAad,OAAO,CAAC,QAAQ;IAShB,4BAA4B;IAC5B,KAAK;IAOL,OAAO,CAAC,IAAI;IAMZ,yCAAyC;IACzC,YAAY,IAAI,OAAO;CAGxB"}
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Loom — Canvas Element
3
+ *
4
+ * Built-in `<loom-canvas>` web component that wraps a `<canvas>`
5
+ * with loom-keep, auto-resize via @observer, and per-frame
6
+ * draw callbacks through Loom's centralized RenderLoop.
7
+ *
8
+ * Usage:
9
+ * <loom-canvas draw={(ctx, dt, t) => {
10
+ * ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
11
+ * ctx.fillRect(x, y, 20, 20);
12
+ * }} />
13
+ *
14
+ * The draw callback receives (CanvasRenderingContext2D, deltaTime, timestamp).
15
+ * Set autoResize={false} and width/height props for fixed-size canvases.
16
+ */
17
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
18
+ var useValue = arguments.length > 2;
19
+ for (var i = 0; i < initializers.length; i++) {
20
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
21
+ }
22
+ return useValue ? value : void 0;
23
+ };
24
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
25
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
26
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
27
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
28
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
29
+ var _, done = false;
30
+ for (var i = decorators.length - 1; i >= 0; i--) {
31
+ var context = {};
32
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
33
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
34
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
35
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
36
+ if (kind === "accessor") {
37
+ if (result === void 0) continue;
38
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
39
+ if (_ = accept(result.get)) descriptor.get = _;
40
+ if (_ = accept(result.set)) descriptor.set = _;
41
+ if (_ = accept(result.init)) initializers.unshift(_);
42
+ }
43
+ else if (_ = accept(result)) {
44
+ if (kind === "field") initializers.unshift(_);
45
+ else descriptor[key] = _;
46
+ }
47
+ }
48
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
49
+ done = true;
50
+ };
51
+ import { LoomElement } from "./element";
52
+ import { component, query, styles } from "./decorators";
53
+ import { prop } from "../store/decorators";
54
+ import { css } from "../css";
55
+ import { animationFrame } from "./timing";
56
+ import { event } from "./events";
57
+ import { observer } from "./observers";
58
+ const canvasStyles = css `
59
+ :host {
60
+ display: block;
61
+ position: relative;
62
+ }
63
+ canvas {
64
+ display: block;
65
+ width: 100%;
66
+ height: 100%;
67
+ }
68
+ `;
69
+ let LoomCanvas = (() => {
70
+ let _classDecorators = [component("loom-canvas"), styles(canvasStyles)];
71
+ let _classDescriptor;
72
+ let _classExtraInitializers = [];
73
+ let _classThis;
74
+ let _classSuper = LoomElement;
75
+ let _instanceExtraInitializers = [];
76
+ let _width_decorators;
77
+ let _width_initializers = [];
78
+ let _width_extraInitializers = [];
79
+ let _height_decorators;
80
+ let _height_initializers = [];
81
+ let _height_extraInitializers = [];
82
+ let _autoResize_decorators;
83
+ let _autoResize_initializers = [];
84
+ let _autoResize_extraInitializers = [];
85
+ let _draw_decorators;
86
+ let _draw_initializers = [];
87
+ let _draw_extraInitializers = [];
88
+ let _canvasEl_decorators;
89
+ let _canvasEl_initializers = [];
90
+ let _canvasEl_extraInitializers = [];
91
+ let _onResize_decorators;
92
+ let _tick_decorators;
93
+ var LoomCanvas = class extends _classSuper {
94
+ static { _classThis = this; }
95
+ static {
96
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
97
+ _width_decorators = [prop];
98
+ _height_decorators = [prop];
99
+ _autoResize_decorators = [prop];
100
+ _draw_decorators = [event()];
101
+ _canvasEl_decorators = [query("canvas")];
102
+ _onResize_decorators = [observer("resize")];
103
+ _tick_decorators = [animationFrame];
104
+ __esDecorate(this, null, _width_decorators, { kind: "accessor", name: "width", static: false, private: false, access: { has: obj => "width" in obj, get: obj => obj.width, set: (obj, value) => { obj.width = value; } }, metadata: _metadata }, _width_initializers, _width_extraInitializers);
105
+ __esDecorate(this, null, _height_decorators, { kind: "accessor", name: "height", static: false, private: false, access: { has: obj => "height" in obj, get: obj => obj.height, set: (obj, value) => { obj.height = value; } }, metadata: _metadata }, _height_initializers, _height_extraInitializers);
106
+ __esDecorate(this, null, _autoResize_decorators, { kind: "accessor", name: "autoResize", static: false, private: false, access: { has: obj => "autoResize" in obj, get: obj => obj.autoResize, set: (obj, value) => { obj.autoResize = value; } }, metadata: _metadata }, _autoResize_initializers, _autoResize_extraInitializers);
107
+ __esDecorate(this, null, _draw_decorators, { kind: "accessor", name: "draw", static: false, private: false, access: { has: obj => "draw" in obj, get: obj => obj.draw, set: (obj, value) => { obj.draw = value; } }, metadata: _metadata }, _draw_initializers, _draw_extraInitializers);
108
+ __esDecorate(this, null, _canvasEl_decorators, { kind: "accessor", name: "canvasEl", static: false, private: false, access: { has: obj => "canvasEl" in obj, get: obj => obj.canvasEl, set: (obj, value) => { obj.canvasEl = value; } }, metadata: _metadata }, _canvasEl_initializers, _canvasEl_extraInitializers);
109
+ __esDecorate(this, null, _onResize_decorators, { kind: "method", name: "onResize", static: false, private: false, access: { has: obj => "onResize" in obj, get: obj => obj.onResize }, metadata: _metadata }, null, _instanceExtraInitializers);
110
+ __esDecorate(this, null, _tick_decorators, { kind: "method", name: "tick", static: false, private: false, access: { has: obj => "tick" in obj, get: obj => obj.tick }, metadata: _metadata }, null, _instanceExtraInitializers);
111
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
112
+ LoomCanvas = _classThis = _classDescriptor.value;
113
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
114
+ __runInitializers(_classThis, _classExtraInitializers);
115
+ }
116
+ #width_accessor_storage = (__runInitializers(this, _instanceExtraInitializers), __runInitializers(this, _width_initializers, 0));
117
+ // ── Public props ──
118
+ /** Fixed width in CSS pixels (ignored when autoResize is true) */
119
+ get width() { return this.#width_accessor_storage; }
120
+ set width(value) { this.#width_accessor_storage = value; }
121
+ #height_accessor_storage = (__runInitializers(this, _width_extraInitializers), __runInitializers(this, _height_initializers, 0));
122
+ /** Fixed height in CSS pixels (ignored when autoResize is true) */
123
+ get height() { return this.#height_accessor_storage; }
124
+ set height(value) { this.#height_accessor_storage = value; }
125
+ #autoResize_accessor_storage = (__runInitializers(this, _height_extraInitializers), __runInitializers(this, _autoResize_initializers, true));
126
+ /** When true, canvas auto-sizes to match host element bounds */
127
+ get autoResize() { return this.#autoResize_accessor_storage; }
128
+ set autoResize(value) { this.#autoResize_accessor_storage = value; }
129
+ #draw_accessor_storage = (__runInitializers(this, _autoResize_extraInitializers), __runInitializers(this, _draw_initializers, null));
130
+ /** Per-frame draw callback: (ctx, deltaTime, timestamp) => void */
131
+ get draw() { return this.#draw_accessor_storage; }
132
+ set draw(value) { this.#draw_accessor_storage = value; }
133
+ #canvasEl_accessor_storage = (__runInitializers(this, _draw_extraInitializers), __runInitializers(this, _canvasEl_initializers, void 0));
134
+ // ── DOM refs ──
135
+ get canvasEl() { return this.#canvasEl_accessor_storage; }
136
+ set canvasEl(value) { this.#canvasEl_accessor_storage = value; }
137
+ // ── Internal ──
138
+ _ctx = (__runInitializers(this, _canvasEl_extraInitializers), null);
139
+ /** Cached 2D rendering context */
140
+ get ctx() {
141
+ if (!this._ctx) {
142
+ this._ctx = this.canvasEl.getContext("2d");
143
+ }
144
+ return this._ctx;
145
+ }
146
+ /** Reference to the raw <canvas> element */
147
+ get canvas() {
148
+ return this.canvasEl;
149
+ }
150
+ // ── Lifecycle ──
151
+ update() {
152
+ const c = document.createElement("canvas");
153
+ c.setAttribute("loom-keep", "");
154
+ if (!this.autoResize && this.width && this.height) {
155
+ c.width = this.width;
156
+ c.height = this.height;
157
+ }
158
+ return c;
159
+ }
160
+ onResize(entry) {
161
+ if (!this.autoResize)
162
+ return;
163
+ const { width, height } = entry.contentRect;
164
+ const dpr = window.devicePixelRatio || 1;
165
+ this.canvasEl.width = Math.round(width * dpr);
166
+ this.canvasEl.height = Math.round(height * dpr);
167
+ this.ctx.scale(dpr, dpr);
168
+ }
169
+ /** Clear the full canvas */
170
+ clear() {
171
+ this.ctx.clearRect(0, 0, this.canvasEl.width, this.canvasEl.height);
172
+ }
173
+ // ── Render loop ──
174
+ tick(dt, t) {
175
+ if (this.draw) {
176
+ this.draw(this.ctx, dt, t);
177
+ }
178
+ }
179
+ /** Block morph after initial skeleton */
180
+ shouldUpdate() {
181
+ return !this.canvasEl;
182
+ }
183
+ };
184
+ return LoomCanvas = _classThis;
185
+ })();
186
+ export { LoomCanvas };
187
+ //# sourceMappingURL=canvas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canvas.js","sourceRoot":"","sources":["../../src/element/canvas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Loom — @event<T> decorator
3
+ *
4
+ * Marks an auto-accessor as an event callback prop.
5
+ * When assigned, stores the callback AND dispatches a composed
6
+ * CustomEvent so external listeners work across shadow DOM.
7
+ *
8
+ * ```ts
9
+ * @event<DrawCallback>() accessor draw: DrawCallback | null;
10
+ *
11
+ * // Invoke in your render loop:
12
+ * this.draw?.(ctx, dt, t);
13
+ * ```
14
+ *
15
+ * Consumers use it naturally in JSX:
16
+ * ```tsx
17
+ * <loom-canvas draw={(ctx, dt, t) => { ... }} />
18
+ * ```
19
+ *
20
+ * External listeners also work:
21
+ * ```ts
22
+ * el.addEventListener("draw", (e: CustomEvent) => ...);
23
+ * ```
24
+ */
25
+ /**
26
+ * Decorator for typed event callback props.
27
+ *
28
+ * - Stores the callback as a JS property (JSX sets it via property assignment)
29
+ * - Dispatches a composed CustomEvent on invocation for cross-shadow-DOM listening
30
+ */
31
+ export declare function event<T extends (...args: any[]) => void>(): <This extends HTMLElement>(_target: ClassAccessorDecoratorTarget<This, T | null>, context: ClassAccessorDecoratorContext<This, T | null>) => ClassAccessorDecoratorResult<This, T | null>;
32
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/element/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH;;;;;GAKG;AACH,wBAAgB,KAAK,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,MAC9C,IAAI,SAAS,WAAW,EAC9B,SAAS,4BAA4B,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,EACrD,SAAS,6BAA6B,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,KACrD,4BAA4B,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,CAgBhD"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Loom — @event<T> decorator
3
+ *
4
+ * Marks an auto-accessor as an event callback prop.
5
+ * When assigned, stores the callback AND dispatches a composed
6
+ * CustomEvent so external listeners work across shadow DOM.
7
+ *
8
+ * ```ts
9
+ * @event<DrawCallback>() accessor draw: DrawCallback | null;
10
+ *
11
+ * // Invoke in your render loop:
12
+ * this.draw?.(ctx, dt, t);
13
+ * ```
14
+ *
15
+ * Consumers use it naturally in JSX:
16
+ * ```tsx
17
+ * <loom-canvas draw={(ctx, dt, t) => { ... }} />
18
+ * ```
19
+ *
20
+ * External listeners also work:
21
+ * ```ts
22
+ * el.addEventListener("draw", (e: CustomEvent) => ...);
23
+ * ```
24
+ */
25
+ /**
26
+ * Decorator for typed event callback props.
27
+ *
28
+ * - Stores the callback as a JS property (JSX sets it via property assignment)
29
+ * - Dispatches a composed CustomEvent on invocation for cross-shadow-DOM listening
30
+ */
31
+ export function event() {
32
+ return (_target, context) => {
33
+ const eventName = String(context.name);
34
+ const storage = new WeakMap();
35
+ return {
36
+ init() {
37
+ return null;
38
+ },
39
+ get() {
40
+ return storage.get(this) ?? null;
41
+ },
42
+ set(value) {
43
+ storage.set(this, value);
44
+ },
45
+ };
46
+ };
47
+ }
48
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/element/events.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAIH;;;;;GAKG;AACH,MAAM,UAAU,KAAK;IACnB,OAAO,CACL,OAAqD,EACrD,OAAsD,EACR,EAAE;QAChD,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAkB,CAAC;QAE9C,OAAO;YACL,IAAI;gBACF,OAAO,IAAI,CAAC;YACd,CAAC;YACD,GAAG;gBACD,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;YACnC,CAAC;YACD,GAAG,CAAa,KAAe;gBAC7B,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;YAC3B,CAAC;SACF,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Loom — Image Element
3
+ *
4
+ * Built-in `<loom-image>` web component with:
5
+ * - Lazy loading via @observer("intersection")
6
+ * - In-memory image cache (static Map) — repeated URLs are instant
7
+ * - Smooth fade-in on load
8
+ * - Customizable placeholder (slot or default shimmer)
9
+ *
10
+ * Usage:
11
+ * <loom-image src="/photo.jpg" alt="Description" />
12
+ * <loom-image src="/hero.png" width={800} height={400} />
13
+ *
14
+ * Custom placeholder:
15
+ * <loom-image src="/photo.jpg">
16
+ * <div slot="placeholder" class="my-skeleton">Loading...</div>
17
+ * </loom-image>
18
+ */
19
+ import { LoomElement } from "./element";
20
+ export declare class LoomImage extends LoomElement {
21
+ /** Image source URL */
22
+ accessor src: string;
23
+ /** Alt text for accessibility */
24
+ accessor alt: string;
25
+ /** Fixed width in CSS pixels (optional) */
26
+ accessor width: number;
27
+ /** Fixed height in CSS pixels (optional) */
28
+ accessor height: number;
29
+ /** Object-fit mode for the image */
30
+ accessor fit: string;
31
+ private _loaded;
32
+ private _visible;
33
+ accessor imgEl: HTMLImageElement;
34
+ accessor placeholderEl: HTMLDivElement;
35
+ private onIntersect;
36
+ private loadImage;
37
+ private applyImage;
38
+ /** Preload images into the cache */
39
+ static preload(...urls: string[]): Promise<void[]>;
40
+ /** Clear the image cache (all or specific URL) */
41
+ static clearCache(url?: string): void;
42
+ /** Check if a URL is cached */
43
+ static isCached(url: string): boolean;
44
+ update(): Node[];
45
+ shouldUpdate(): boolean;
46
+ }
47
+ //# sourceMappingURL=image.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image.d.ts","sourceRoot":"","sources":["../../src/element/image.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AA+DxC,qBAEa,SAAU,SAAQ,WAAW;IAIxC,uBAAuB;IACjB,QAAQ,CAAC,GAAG,SAAM;IAExB,iCAAiC;IAC3B,QAAQ,CAAC,GAAG,SAAM;IAExB,2CAA2C;IACrC,QAAQ,CAAC,KAAK,SAAK;IAEzB,4CAA4C;IACtC,QAAQ,CAAC,MAAM,SAAK;IAE1B,oCAAoC;IAC9B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAW;IAIrC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,QAAQ,CAAS;IAKzB,QAAQ,CAAC,KAAK,EAAG,gBAAgB,CAAC;IAGlC,QAAQ,CAAC,aAAa,EAAG,cAAc,CAAC;IAKxC,OAAO,CAAC,WAAW;IASnB,OAAO,CAAC,SAAS;IAuBjB,OAAO,CAAC,UAAU;IAkBlB,oCAAoC;IACpC,MAAM,CAAC,OAAO,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAYlD,kDAAkD;IAClD,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM;IAK9B,+BAA+B;IAC/B,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAMrC,MAAM,IAAI,IAAI,EAAE;IAgChB,YAAY,IAAI,OAAO;CAGxB"}
@@ -0,0 +1,310 @@
1
+ /**
2
+ * Loom — Image Element
3
+ *
4
+ * Built-in `<loom-image>` web component with:
5
+ * - Lazy loading via @observer("intersection")
6
+ * - In-memory image cache (static Map) — repeated URLs are instant
7
+ * - Smooth fade-in on load
8
+ * - Customizable placeholder (slot or default shimmer)
9
+ *
10
+ * Usage:
11
+ * <loom-image src="/photo.jpg" alt="Description" />
12
+ * <loom-image src="/hero.png" width={800} height={400} />
13
+ *
14
+ * Custom placeholder:
15
+ * <loom-image src="/photo.jpg">
16
+ * <div slot="placeholder" class="my-skeleton">Loading...</div>
17
+ * </loom-image>
18
+ */
19
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
20
+ var useValue = arguments.length > 2;
21
+ for (var i = 0; i < initializers.length; i++) {
22
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
23
+ }
24
+ return useValue ? value : void 0;
25
+ };
26
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
27
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
28
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
29
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
30
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
31
+ var _, done = false;
32
+ for (var i = decorators.length - 1; i >= 0; i--) {
33
+ var context = {};
34
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
35
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
36
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
37
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
38
+ if (kind === "accessor") {
39
+ if (result === void 0) continue;
40
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
41
+ if (_ = accept(result.get)) descriptor.get = _;
42
+ if (_ = accept(result.set)) descriptor.set = _;
43
+ if (_ = accept(result.init)) initializers.unshift(_);
44
+ }
45
+ else if (_ = accept(result)) {
46
+ if (kind === "field") initializers.unshift(_);
47
+ else descriptor[key] = _;
48
+ }
49
+ }
50
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
51
+ done = true;
52
+ };
53
+ import { LoomElement } from "./element";
54
+ import { component, query, styles } from "./decorators";
55
+ import { prop } from "../store/decorators";
56
+ import { css } from "../css";
57
+ import { observer } from "./observers";
58
+ // ── Static image cache ──
59
+ const imageCache = new Map();
60
+ const imageStyles = css `
61
+ :host {
62
+ display: inline-block;
63
+ position: relative;
64
+ overflow: hidden;
65
+ line-height: 0;
66
+ }
67
+
68
+ .placeholder {
69
+ position: absolute;
70
+ inset: 0;
71
+ border-radius: inherit;
72
+ z-index: 1;
73
+ transition: opacity 0.3s ease;
74
+ }
75
+
76
+ .placeholder.hidden {
77
+ opacity: 0;
78
+ pointer-events: none;
79
+ }
80
+
81
+ .default-skeleton {
82
+ position: absolute;
83
+ inset: 0;
84
+ background: linear-gradient(
85
+ 90deg,
86
+ rgba(255,255,255,0.04) 25%,
87
+ rgba(255,255,255,0.08) 50%,
88
+ rgba(255,255,255,0.04) 75%
89
+ );
90
+ background-size: 200% 100%;
91
+ animation: shimmer 1.5s ease-in-out infinite;
92
+ border-radius: inherit;
93
+ }
94
+
95
+ @keyframes shimmer {
96
+ 0% { background-position: 200% 0; }
97
+ 100% { background-position: -200% 0; }
98
+ }
99
+
100
+ img {
101
+ display: block;
102
+ width: 100%;
103
+ height: 100%;
104
+ object-fit: cover;
105
+ opacity: 0;
106
+ transition: opacity 0.3s ease;
107
+ }
108
+
109
+ img.loaded {
110
+ opacity: 1;
111
+ }
112
+ `;
113
+ let LoomImage = (() => {
114
+ let _classDecorators = [component("loom-image"), styles(imageStyles)];
115
+ let _classDescriptor;
116
+ let _classExtraInitializers = [];
117
+ let _classThis;
118
+ let _classSuper = LoomElement;
119
+ let _instanceExtraInitializers = [];
120
+ let _src_decorators;
121
+ let _src_initializers = [];
122
+ let _src_extraInitializers = [];
123
+ let _alt_decorators;
124
+ let _alt_initializers = [];
125
+ let _alt_extraInitializers = [];
126
+ let _width_decorators;
127
+ let _width_initializers = [];
128
+ let _width_extraInitializers = [];
129
+ let _height_decorators;
130
+ let _height_initializers = [];
131
+ let _height_extraInitializers = [];
132
+ let _fit_decorators;
133
+ let _fit_initializers = [];
134
+ let _fit_extraInitializers = [];
135
+ let _imgEl_decorators;
136
+ let _imgEl_initializers = [];
137
+ let _imgEl_extraInitializers = [];
138
+ let _placeholderEl_decorators;
139
+ let _placeholderEl_initializers = [];
140
+ let _placeholderEl_extraInitializers = [];
141
+ let _onIntersect_decorators;
142
+ var LoomImage = class extends _classSuper {
143
+ static { _classThis = this; }
144
+ static {
145
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
146
+ _src_decorators = [prop];
147
+ _alt_decorators = [prop];
148
+ _width_decorators = [prop];
149
+ _height_decorators = [prop];
150
+ _fit_decorators = [prop];
151
+ _imgEl_decorators = [query("img")];
152
+ _placeholderEl_decorators = [query(".placeholder")];
153
+ _onIntersect_decorators = [observer("intersection", { threshold: 0.01, rootMargin: "200px" })];
154
+ __esDecorate(this, null, _src_decorators, { kind: "accessor", name: "src", static: false, private: false, access: { has: obj => "src" in obj, get: obj => obj.src, set: (obj, value) => { obj.src = value; } }, metadata: _metadata }, _src_initializers, _src_extraInitializers);
155
+ __esDecorate(this, null, _alt_decorators, { kind: "accessor", name: "alt", static: false, private: false, access: { has: obj => "alt" in obj, get: obj => obj.alt, set: (obj, value) => { obj.alt = value; } }, metadata: _metadata }, _alt_initializers, _alt_extraInitializers);
156
+ __esDecorate(this, null, _width_decorators, { kind: "accessor", name: "width", static: false, private: false, access: { has: obj => "width" in obj, get: obj => obj.width, set: (obj, value) => { obj.width = value; } }, metadata: _metadata }, _width_initializers, _width_extraInitializers);
157
+ __esDecorate(this, null, _height_decorators, { kind: "accessor", name: "height", static: false, private: false, access: { has: obj => "height" in obj, get: obj => obj.height, set: (obj, value) => { obj.height = value; } }, metadata: _metadata }, _height_initializers, _height_extraInitializers);
158
+ __esDecorate(this, null, _fit_decorators, { kind: "accessor", name: "fit", static: false, private: false, access: { has: obj => "fit" in obj, get: obj => obj.fit, set: (obj, value) => { obj.fit = value; } }, metadata: _metadata }, _fit_initializers, _fit_extraInitializers);
159
+ __esDecorate(this, null, _imgEl_decorators, { kind: "accessor", name: "imgEl", static: false, private: false, access: { has: obj => "imgEl" in obj, get: obj => obj.imgEl, set: (obj, value) => { obj.imgEl = value; } }, metadata: _metadata }, _imgEl_initializers, _imgEl_extraInitializers);
160
+ __esDecorate(this, null, _placeholderEl_decorators, { kind: "accessor", name: "placeholderEl", static: false, private: false, access: { has: obj => "placeholderEl" in obj, get: obj => obj.placeholderEl, set: (obj, value) => { obj.placeholderEl = value; } }, metadata: _metadata }, _placeholderEl_initializers, _placeholderEl_extraInitializers);
161
+ __esDecorate(this, null, _onIntersect_decorators, { kind: "method", name: "onIntersect", static: false, private: false, access: { has: obj => "onIntersect" in obj, get: obj => obj.onIntersect }, metadata: _metadata }, null, _instanceExtraInitializers);
162
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
163
+ LoomImage = _classThis = _classDescriptor.value;
164
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
165
+ __runInitializers(_classThis, _classExtraInitializers);
166
+ }
167
+ #src_accessor_storage = (__runInitializers(this, _instanceExtraInitializers), __runInitializers(this, _src_initializers, ""));
168
+ // ── Public props ──
169
+ /** Image source URL */
170
+ get src() { return this.#src_accessor_storage; }
171
+ set src(value) { this.#src_accessor_storage = value; }
172
+ #alt_accessor_storage = (__runInitializers(this, _src_extraInitializers), __runInitializers(this, _alt_initializers, ""));
173
+ /** Alt text for accessibility */
174
+ get alt() { return this.#alt_accessor_storage; }
175
+ set alt(value) { this.#alt_accessor_storage = value; }
176
+ #width_accessor_storage = (__runInitializers(this, _alt_extraInitializers), __runInitializers(this, _width_initializers, 0));
177
+ /** Fixed width in CSS pixels (optional) */
178
+ get width() { return this.#width_accessor_storage; }
179
+ set width(value) { this.#width_accessor_storage = value; }
180
+ #height_accessor_storage = (__runInitializers(this, _width_extraInitializers), __runInitializers(this, _height_initializers, 0));
181
+ /** Fixed height in CSS pixels (optional) */
182
+ get height() { return this.#height_accessor_storage; }
183
+ set height(value) { this.#height_accessor_storage = value; }
184
+ #fit_accessor_storage = (__runInitializers(this, _height_extraInitializers), __runInitializers(this, _fit_initializers, "cover"));
185
+ /** Object-fit mode for the image */
186
+ get fit() { return this.#fit_accessor_storage; }
187
+ set fit(value) { this.#fit_accessor_storage = value; }
188
+ // ── Internal state ──
189
+ _loaded = (__runInitializers(this, _fit_extraInitializers), false);
190
+ _visible = false;
191
+ #imgEl_accessor_storage = __runInitializers(this, _imgEl_initializers, void 0);
192
+ // ── DOM refs ──
193
+ get imgEl() { return this.#imgEl_accessor_storage; }
194
+ set imgEl(value) { this.#imgEl_accessor_storage = value; }
195
+ #placeholderEl_accessor_storage = (__runInitializers(this, _imgEl_extraInitializers), __runInitializers(this, _placeholderEl_initializers, void 0));
196
+ get placeholderEl() { return this.#placeholderEl_accessor_storage; }
197
+ set placeholderEl(value) { this.#placeholderEl_accessor_storage = value; }
198
+ // ── Lazy loading via @observer ──
199
+ onIntersect(entry) {
200
+ if (entry.isIntersecting && !this._visible) {
201
+ this._visible = true;
202
+ this.loadImage();
203
+ }
204
+ }
205
+ // ── Image loading with cache ──
206
+ loadImage() {
207
+ if (!this.src)
208
+ return;
209
+ // Check cache first
210
+ const cached = imageCache.get(this.src);
211
+ if (cached) {
212
+ this.applyImage(cached.src);
213
+ return;
214
+ }
215
+ // Load and cache
216
+ const img = new Image();
217
+ img.onload = () => {
218
+ imageCache.set(this.src, img);
219
+ this.applyImage(img.src);
220
+ };
221
+ img.onerror = () => {
222
+ // Still hide placeholder on error
223
+ if (this.placeholderEl)
224
+ this.placeholderEl.classList.add("hidden");
225
+ };
226
+ img.src = this.src;
227
+ }
228
+ applyImage(src) {
229
+ if (!this.imgEl)
230
+ return;
231
+ this.imgEl.src = src;
232
+ this.imgEl.onload = () => {
233
+ this._loaded = true;
234
+ this.imgEl.classList.add("loaded");
235
+ if (this.placeholderEl)
236
+ this.placeholderEl.classList.add("hidden");
237
+ };
238
+ // If cached, image may already be complete
239
+ if (this.imgEl.complete) {
240
+ this._loaded = true;
241
+ this.imgEl.classList.add("loaded");
242
+ if (this.placeholderEl)
243
+ this.placeholderEl.classList.add("hidden");
244
+ }
245
+ }
246
+ // ── Static cache API ──
247
+ /** Preload images into the cache */
248
+ static preload(...urls) {
249
+ return Promise.all(urls.map(url => {
250
+ if (imageCache.has(url))
251
+ return Promise.resolve();
252
+ return new Promise((resolve, reject) => {
253
+ const img = new Image();
254
+ img.onload = () => { imageCache.set(url, img); resolve(); };
255
+ img.onerror = reject;
256
+ img.src = url;
257
+ });
258
+ }));
259
+ }
260
+ /** Clear the image cache (all or specific URL) */
261
+ static clearCache(url) {
262
+ if (url)
263
+ imageCache.delete(url);
264
+ else
265
+ imageCache.clear();
266
+ }
267
+ /** Check if a URL is cached */
268
+ static isCached(url) {
269
+ return imageCache.has(url);
270
+ }
271
+ // ── Render ──
272
+ update() {
273
+ const hostStyle = {};
274
+ if (this.width)
275
+ hostStyle.width = `${this.width}px`;
276
+ if (this.height)
277
+ hostStyle.height = `${this.height}px`;
278
+ if (Object.keys(hostStyle).length) {
279
+ Object.assign(this.style, hostStyle);
280
+ }
281
+ const img = document.createElement("img");
282
+ img.setAttribute("loom-keep", "");
283
+ img.alt = this.alt;
284
+ if (this.fit)
285
+ img.style.objectFit = this.fit;
286
+ // Placeholder wrapper: user-slotted content or default shimmer
287
+ const placeholder = document.createElement("div");
288
+ placeholder.className = "placeholder";
289
+ placeholder.setAttribute("loom-keep", "");
290
+ const slot = document.createElement("slot");
291
+ slot.name = "placeholder";
292
+ // Default skeleton shown when no slotted content
293
+ const defaultSkeleton = document.createElement("div");
294
+ defaultSkeleton.className = "default-skeleton";
295
+ slot.appendChild(defaultSkeleton);
296
+ placeholder.appendChild(slot);
297
+ return [placeholder, img];
298
+ }
299
+ shouldUpdate() {
300
+ return !this.imgEl;
301
+ }
302
+ constructor() {
303
+ super(...arguments);
304
+ __runInitializers(this, _placeholderEl_extraInitializers);
305
+ }
306
+ };
307
+ return LoomImage = _classThis;
308
+ })();
309
+ export { LoomImage };
310
+ //# sourceMappingURL=image.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"image.js","sourceRoot":"","sources":["../../src/element/image.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,8 @@
6
6
  export { LoomElement } from "./element";
7
7
  export { component, query, queryAll, styles } from "./decorators";
8
8
  export { catch_, suspend, mount, unmount } from "./lifecycle";
9
+ export { event } from "./events";
10
+ export { observer } from "./observers";
9
11
  export { interval, timeout, debounce, throttle, animationFrame } from "./timing";
10
12
  export { form } from "./form";
11
13
  export type { FormState, FormSchema, FieldSchema } from "./form";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/element/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAOxC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAGlE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAG9D,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAGjF,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAGjE,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,YAAY,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAG1C,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG/B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/element/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AASxC,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAGlE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAG9D,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAGjC,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAGvC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAGjF,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAGjE,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAC9B,YAAY,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAC;AAG1C,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG/B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
@@ -8,10 +8,16 @@ export { LoomElement } from "./element";
8
8
  // Built-in elements — import explicitly to opt-in to side effects
9
9
  // e.g. import { LoomVirtual } from "@toyz/loom/element/virtual"
10
10
  // e.g. import { LoomIcon } from "@toyz/loom/element/icon"
11
+ // e.g. import { LoomCanvas } from "@toyz/loom/element/canvas"
12
+ // e.g. import { LoomImage } from "@toyz/loom/element/image"
11
13
  // Element decorators
12
14
  export { component, query, queryAll, styles } from "./decorators";
13
15
  // Lifecycle decorators
14
16
  export { catch_, suspend, mount, unmount } from "./lifecycle";
17
+ // Event decorator
18
+ export { event } from "./events";
19
+ // Observer decorator
20
+ export { observer } from "./observers";
15
21
  // Timing decorators
16
22
  export { interval, timeout, debounce, throttle, animationFrame } from "./timing";
17
23
  // Form decorator
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/element/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAe;AACf,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,kEAAkE;AAClE,gEAAgE;AAChE,0DAA0D;AAE1D,qBAAqB;AACrB,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAElE,uBAAuB;AACvB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE9D,oBAAoB;AACpB,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAEjF,iBAAiB;AACjB,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAG9B,yBAAyB;AACzB,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAG9B,iBAAiB;AACjB,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B,uBAAuB;AACvB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/element/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,eAAe;AACf,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,kEAAkE;AAClE,gEAAgE;AAChE,0DAA0D;AAC1D,8DAA8D;AAC9D,4DAA4D;AAE5D,qBAAqB;AACrB,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAElE,uBAAuB;AACvB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE9D,kBAAkB;AAClB,OAAO,EAAE,KAAK,EAAE,MAAM,UAAU,CAAC;AAEjC,qBAAqB;AACrB,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,oBAAoB;AACpB,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAEjF,iBAAiB;AACjB,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAG9B,yBAAyB;AACzB,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAG9B,iBAAiB;AACjB,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B,uBAAuB;AACvB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Loom — @observer decorator
3
+ *
4
+ * Auto-managed DOM observers with lifecycle cleanup.
5
+ * Creates the observer on connect, observes `this`, disconnects on unmount.
6
+ *
7
+ * ```ts
8
+ * @observer("resize")
9
+ * onResize(entry: ResizeObserverEntry) {
10
+ * const { width, height } = entry.contentRect;
11
+ * // ...
12
+ * }
13
+ *
14
+ * @observer("intersection", { threshold: 0.5 })
15
+ * onVisible(entry: IntersectionObserverEntry) {
16
+ * if (entry.isIntersecting) this.load();
17
+ * }
18
+ *
19
+ * @observer("mutation", { childList: true, subtree: true })
20
+ * onChildChange(record: MutationRecord) {
21
+ * this.recount();
22
+ * }
23
+ * ```
24
+ */
25
+ export declare function observer(type: "resize", options?: ResizeObserverOptions): (method: Function, context: ClassMethodDecoratorContext) => void;
26
+ export declare function observer(type: "intersection", options?: IntersectionObserverInit): (method: Function, context: ClassMethodDecoratorContext) => void;
27
+ export declare function observer(type: "mutation", options: MutationObserverInit): (method: Function, context: ClassMethodDecoratorContext) => void;
28
+ //# sourceMappingURL=observers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observers.d.ts","sourceRoot":"","sources":["../../src/element/observers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAMH,wBAAgB,QAAQ,CACtB,IAAI,EAAE,QAAQ,EACd,OAAO,CAAC,EAAE,qBAAqB,GAC9B,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC;AAEpE,wBAAgB,QAAQ,CACtB,IAAI,EAAE,cAAc,EACpB,OAAO,CAAC,EAAE,wBAAwB,GACjC,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC;AAEpE,wBAAgB,QAAQ,CACtB,IAAI,EAAE,UAAU,EAChB,OAAO,EAAE,oBAAoB,GAC5B,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,2BAA2B,KAAK,IAAI,CAAC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Loom — @observer decorator
3
+ *
4
+ * Auto-managed DOM observers with lifecycle cleanup.
5
+ * Creates the observer on connect, observes `this`, disconnects on unmount.
6
+ *
7
+ * ```ts
8
+ * @observer("resize")
9
+ * onResize(entry: ResizeObserverEntry) {
10
+ * const { width, height } = entry.contentRect;
11
+ * // ...
12
+ * }
13
+ *
14
+ * @observer("intersection", { threshold: 0.5 })
15
+ * onVisible(entry: IntersectionObserverEntry) {
16
+ * if (entry.isIntersecting) this.load();
17
+ * }
18
+ *
19
+ * @observer("mutation", { childList: true, subtree: true })
20
+ * onChildChange(record: MutationRecord) {
21
+ * this.recount();
22
+ * }
23
+ * ```
24
+ */
25
+ import { CONNECT_HOOKS } from "../decorators/symbols";
26
+ // ── Implementation ──
27
+ export function observer(type, options) {
28
+ return (method, context) => {
29
+ context.addInitializer(function () {
30
+ if (!this[CONNECT_HOOKS])
31
+ this[CONNECT_HOOKS] = [];
32
+ this[CONNECT_HOOKS].push((el) => {
33
+ const callback = (entries) => {
34
+ for (const entry of entries) {
35
+ method.call(el, entry);
36
+ }
37
+ };
38
+ let obs;
39
+ switch (type) {
40
+ case "resize": {
41
+ const ro = new ResizeObserver(callback);
42
+ ro.observe(el, options);
43
+ obs = ro;
44
+ break;
45
+ }
46
+ case "intersection": {
47
+ const io = new IntersectionObserver(callback, options);
48
+ io.observe(el);
49
+ obs = io;
50
+ break;
51
+ }
52
+ case "mutation": {
53
+ const mo = new MutationObserver(callback);
54
+ mo.observe(el, options);
55
+ obs = mo;
56
+ break;
57
+ }
58
+ }
59
+ // Return cleanup — runs on disconnectedCallback
60
+ return () => obs.disconnect();
61
+ });
62
+ });
63
+ };
64
+ }
65
+ //# sourceMappingURL=observers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observers.js","sourceRoot":"","sources":["../../src/element/observers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAmBtD,uBAAuB;AAEvB,MAAM,UAAU,QAAQ,CACtB,IAA4C,EAC5C,OAAa;IAEb,OAAO,CAAC,MAAgB,EAAE,OAAoC,EAAE,EAAE;QAChE,OAAO,CAAC,cAAc,CAAC;YACrB,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC;gBAAE,IAAI,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC;YAEnD,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,EAAe,EAAE,EAAE;gBAC3C,MAAM,QAAQ,GAAG,CAAC,OAAc,EAAE,EAAE;oBAClC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;wBAC5B,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;oBACzB,CAAC;gBACH,CAAC,CAAC;gBAEF,IAAI,GAA2B,CAAC;gBAEhC,QAAQ,IAAI,EAAE,CAAC;oBACb,KAAK,QAAQ,CAAC,CAAC,CAAC;wBACd,MAAM,EAAE,GAAG,IAAI,cAAc,CAAC,QAAQ,CAAC,CAAC;wBACxC,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;wBACxB,GAAG,GAAG,EAAE,CAAC;wBACT,MAAM;oBACR,CAAC;oBACD,KAAK,cAAc,CAAC,CAAC,CAAC;wBACpB,MAAM,EAAE,GAAG,IAAI,oBAAoB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;wBACvD,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;wBACf,GAAG,GAAG,EAAE,CAAC;wBACT,MAAM;oBACR,CAAC;oBACD,KAAK,UAAU,CAAC,CAAC,CAAC;wBAChB,MAAM,EAAE,GAAG,IAAI,gBAAgB,CAAC,QAAQ,CAAC,CAAC;wBAC1C,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;wBACxB,GAAG,GAAG,EAAE,CAAC;wBACT,MAAM;oBACR,CAAC;gBACH,CAAC;gBAED,gDAAgD;gBAChD,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,UAAU,EAAE,CAAC;YAChC,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
package/dist/index.d.ts CHANGED
@@ -20,7 +20,7 @@ export type { Subscriber, Updater, Identifiable, StorageAdapter, StorageMedium,
20
20
  export { service, inject, factory } from "./di";
21
21
  /** @deprecated Use `@watch(Service)` or `@watch(Service, "prop")` instead. Will be removed in v1.0. */
22
22
  export { watch as watchService } from "./di";
23
- export { LoomElement, component, query, queryAll, styles, catch_, suspend, mount, unmount, interval, timeout, debounce, throttle, animationFrame, form, lazy, slot, transition, } from "./element";
23
+ export { LoomElement, component, query, queryAll, styles, catch_, suspend, mount, unmount, event, observer, interval, timeout, debounce, throttle, animationFrame, form, lazy, slot, transition, } from "./element";
24
24
  export type { FormState, FormSchema, FieldSchema, LazyOptions, TransitionOptions } from "./element";
25
25
  export { transform, createTransform, typed, typedTransformer, toNumber, toBoolean, toDate, toJSON, toTrimmed, toInt, toFloat, } from "./transform";
26
26
  export type { TransformSchema } from "./transform";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,YAAY,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAGrC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAGlD,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,YAAY,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGtC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGpD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAKhD,OAAO,EACL,QAAQ,EAAE,eAAe,EACzB,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,aAAa,EACvE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAC5C,KAAK,EACL,KAAK,GACN,MAAM,SAAS,CAAC;AACjB,YAAY,EACV,UAAU,EAAE,OAAO,EAAE,YAAY,EACjC,cAAc,EAAE,aAAa,EAAE,cAAc,GAC9C,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAChD,uGAAuG;AACvG,OAAO,EAAE,KAAK,IAAI,YAAY,EAAE,MAAM,MAAM,CAAC;AAG7C,OAAO,EACL,WAAW,EACX,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAClC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAC/B,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EACrD,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,GAC7B,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAGpG,OAAO,EACL,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,gBAAgB,EACvB,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,GAC/D,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGnD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGzD,OAAO,EACL,UAAU,EACV,YAAY,EACZ,KAAK,EACL,KAAK,EACL,KAAK,EACL,UAAU,EACV,MAAM,EACN,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,YAAY,GACb,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAG5F,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzD,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAG9E,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,YAAY,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAGrC,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAC9C,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAGlD,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,YAAY,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAGtC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGpD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,YAAY,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAKhD,OAAO,EACL,QAAQ,EAAE,eAAe,EACzB,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,aAAa,EACvE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAC5C,KAAK,EACL,KAAK,GACN,MAAM,SAAS,CAAC;AACjB,YAAY,EACV,UAAU,EAAE,OAAO,EAAE,YAAY,EACjC,cAAc,EAAE,aAAa,EAAE,cAAc,GAC9C,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAChD,uGAAuG;AACvG,OAAO,EAAE,KAAK,IAAI,YAAY,EAAE,MAAM,MAAM,CAAC;AAG7C,OAAO,EACL,WAAW,EACX,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAClC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAC/B,KAAK,EAAE,QAAQ,EACf,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EACrD,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,GAC7B,MAAM,WAAW,CAAC;AACnB,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAGpG,OAAO,EACL,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,gBAAgB,EACvB,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,GAC/D,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAGnD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGzD,OAAO,EACL,UAAU,EACV,YAAY,EACZ,KAAK,EACL,KAAK,EACL,KAAK,EACL,UAAU,EACV,MAAM,EACN,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,YAAY,GACb,MAAM,UAAU,CAAC;AAClB,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAG5F,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACzD,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAG9E,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC"}
package/dist/index.js CHANGED
@@ -25,7 +25,7 @@ export { service, inject, factory } from "./di";
25
25
  /** @deprecated Use `@watch(Service)` or `@watch(Service, "prop")` instead. Will be removed in v1.0. */
26
26
  export { watch as watchService } from "./di";
27
27
  // Element: base class, element decorators
28
- export { LoomElement, component, query, queryAll, styles, catch_, suspend, mount, unmount, interval, timeout, debounce, throttle, animationFrame, form, lazy, slot, transition, } from "./element";
28
+ export { LoomElement, component, query, queryAll, styles, catch_, suspend, mount, unmount, event, observer, interval, timeout, debounce, throttle, animationFrame, form, lazy, slot, transition, } from "./element";
29
29
  // Transform: value transforms
30
30
  export { transform, createTransform, typed, typedTransformer, toNumber, toBoolean, toDate, toJSON, toTrimmed, toInt, toFloat, } from "./transform";
31
31
  // Decorators: event decorators + factory
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,kBAAkB;AAClB,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAG5B,eAAe;AACf,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAG9C,MAAM;AACN,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAG5B,eAAe;AACf,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,wDAAwD;AACxD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEpD,cAAc;AACd,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,0BAA0B;AAE1B,qCAAqC;AACrC,OAAO,EACL,QAAQ,EAAE,eAAe,EACzB,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,aAAa,EACvE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAC5C,KAAK,EACL,KAAK,GACN,MAAM,SAAS,CAAC;AAMjB,mCAAmC;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAChD,uGAAuG;AACvG,OAAO,EAAE,KAAK,IAAI,YAAY,EAAE,MAAM,MAAM,CAAC;AAE7C,0CAA0C;AAC1C,OAAO,EACL,WAAW,EACX,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAClC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAC/B,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EACrD,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,GAC7B,MAAM,WAAW,CAAC;AAGnB,8BAA8B;AAC9B,OAAO,EACL,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,gBAAgB,EACvB,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,GAC/D,MAAM,aAAa,CAAC;AAGrB,yCAAyC;AACzC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEzD,SAAS;AACT,OAAO,EACL,UAAU,EACV,YAAY,EACZ,KAAK,EACL,KAAK,EACL,KAAK,EACL,UAAU,EACV,MAAM,EACN,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,YAAY,GACb,MAAM,UAAU,CAAC;AAGlB,oDAAoD;AACpD,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGzD,cAAc;AACd,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,kBAAkB;AAClB,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAG5B,eAAe;AACf,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAG9C,MAAM;AACN,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAG5B,eAAe;AACf,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,wDAAwD;AACxD,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEpD,cAAc;AACd,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAG3C,0BAA0B;AAE1B,qCAAqC;AACrC,OAAO,EACL,QAAQ,EAAE,eAAe,EACzB,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,aAAa,EACvE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAC5C,KAAK,EACL,KAAK,GACN,MAAM,SAAS,CAAC;AAMjB,mCAAmC;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAChD,uGAAuG;AACvG,OAAO,EAAE,KAAK,IAAI,YAAY,EAAE,MAAM,MAAM,CAAC;AAE7C,0CAA0C;AAC1C,OAAO,EACL,WAAW,EACX,SAAS,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAClC,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAC/B,KAAK,EAAE,QAAQ,EACf,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,cAAc,EACrD,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,GAC7B,MAAM,WAAW,CAAC;AAGnB,8BAA8B;AAC9B,OAAO,EACL,SAAS,EAAE,eAAe,EAC1B,KAAK,EAAE,gBAAgB,EACvB,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,GAC/D,MAAM,aAAa,CAAC;AAGrB,yCAAyC;AACzC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEzD,SAAS;AACT,OAAO,EACL,UAAU,EACV,YAAY,EACZ,KAAK,EACL,KAAK,EACL,KAAK,EACL,UAAU,EACV,MAAM,EACN,UAAU,EACV,QAAQ,EACR,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,YAAY,GACb,MAAM,UAAU,CAAC;AAGlB,oDAAoD;AACpD,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGzD,cAAc;AACd,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toyz/loom",
3
- "version": "0.11.2",
3
+ "version": "0.12.1",
4
4
  "type": "module",
5
5
  "description": "Decorator-driven web component framework with reactive state, DOM morphing, DI, and JSX",
6
6
  "license": "MIT",
@@ -59,6 +59,14 @@
59
59
  "types": "./dist/element/virtual.d.ts",
60
60
  "import": "./dist/element/virtual.js"
61
61
  },
62
+ "./element/canvas": {
63
+ "types": "./dist/element/canvas.d.ts",
64
+ "import": "./dist/element/canvas.js"
65
+ },
66
+ "./element/image": {
67
+ "types": "./dist/element/image.d.ts",
68
+ "import": "./dist/element/image.js"
69
+ },
62
70
  "./decorators": {
63
71
  "types": "./dist/decorators/index.d.ts",
64
72
  "import": "./dist/decorators/index.js"