@toyz/loom 0.11.1 → 0.12.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.
@@ -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"}