@toyz/loom 0.17.3 → 0.17.4

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,25 @@
1
+ /**
2
+ * Loom — @clipboard decorator
3
+ *
4
+ * Method decorator for declarative clipboard read/write.
5
+ *
6
+ * ```ts
7
+ * // Write: method returns the text to copy
8
+ * @clipboard("write")
9
+ * copyLink() { return this.shareUrl; }
10
+ *
11
+ * // Read: method receives pasted text as argument
12
+ * @clipboard("read")
13
+ * onPaste(text: string) { this.content = text; }
14
+ * ```
15
+ */
16
+ type ClipboardMode = "read" | "write";
17
+ /**
18
+ * @clipboard(mode) — Method decorator
19
+ *
20
+ * - `"write"`: Calling the method copies its return value to the clipboard.
21
+ * - `"read"`: Binds a `paste` event listener; the method receives the pasted text.
22
+ */
23
+ export declare function clipboard(mode: ClipboardMode): (method: Function, context: ClassMethodDecoratorContext) => ((this: any, ...args: unknown[]) => any) | undefined;
24
+ export {};
25
+ //# sourceMappingURL=clipboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clipboard.d.ts","sourceRoot":"","sources":["../../src/element/clipboard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,KAAK,aAAa,GAAG,MAAM,GAAG,OAAO,CAAC;AAEtC;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,aAAa,IAC1B,QAAQ,QAAQ,EAAE,SAAS,2BAA2B,aAG5C,GAAG,WAAW,OAAO,EAAE,sBAkCnD"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Loom — @clipboard decorator
3
+ *
4
+ * Method decorator for declarative clipboard read/write.
5
+ *
6
+ * ```ts
7
+ * // Write: method returns the text to copy
8
+ * @clipboard("write")
9
+ * copyLink() { return this.shareUrl; }
10
+ *
11
+ * // Read: method receives pasted text as argument
12
+ * @clipboard("read")
13
+ * onPaste(text: string) { this.content = text; }
14
+ * ```
15
+ */
16
+ import { CONNECT_HOOKS } from "../decorators/symbols";
17
+ /**
18
+ * @clipboard(mode) — Method decorator
19
+ *
20
+ * - `"write"`: Calling the method copies its return value to the clipboard.
21
+ * - `"read"`: Binds a `paste` event listener; the method receives the pasted text.
22
+ */
23
+ export function clipboard(mode) {
24
+ return function (method, context) {
25
+ if (mode === "write") {
26
+ // Wrap the method — calling it copies its return value
27
+ return function (...args) {
28
+ const text = method.call(this, ...args);
29
+ if (text != null && navigator.clipboard) {
30
+ navigator.clipboard.writeText(String(text)).catch(() => {
31
+ // Fallback: legacy execCommand
32
+ const ta = document.createElement("textarea");
33
+ ta.value = String(text);
34
+ ta.style.position = "fixed";
35
+ ta.style.opacity = "0";
36
+ document.body.appendChild(ta);
37
+ ta.select();
38
+ document.execCommand("copy");
39
+ ta.remove();
40
+ });
41
+ }
42
+ return text;
43
+ };
44
+ }
45
+ // mode === "read" — listen for paste events on the element
46
+ context.addInitializer(function () {
47
+ if (!this[CONNECT_HOOKS.key])
48
+ this[CONNECT_HOOKS.key] = [];
49
+ this[CONNECT_HOOKS.key].push((el) => {
50
+ const handler = (e) => {
51
+ const text = e.clipboardData?.getData("text/plain") ?? "";
52
+ method.call(el, text, e);
53
+ };
54
+ el.addEventListener("paste", handler);
55
+ return () => el.removeEventListener("paste", handler);
56
+ });
57
+ });
58
+ };
59
+ }
60
+ //# sourceMappingURL=clipboard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../src/element/clipboard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAItD;;;;;GAKG;AACH,MAAM,UAAU,SAAS,CAAC,IAAmB;IAC3C,OAAO,UAAU,MAAgB,EAAE,OAAoC;QACrE,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YACrB,uDAAuD;YACvD,OAAO,UAAqB,GAAG,IAAe;gBAC5C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC;gBACxC,IAAI,IAAI,IAAI,IAAI,IAAI,SAAS,CAAC,SAAS,EAAE,CAAC;oBACxC,SAAS,CAAC,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;wBACrD,+BAA+B;wBAC/B,MAAM,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC;wBAC9C,EAAE,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;wBACxB,EAAE,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC;wBAC5B,EAAE,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC;wBACvB,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;wBAC9B,EAAE,CAAC,MAAM,EAAE,CAAC;wBACZ,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;wBAC7B,EAAE,CAAC,MAAM,EAAE,CAAC;oBACd,CAAC,CAAC,CAAC;gBACL,CAAC;gBACD,OAAO,IAAI,CAAC;YACd,CAAC,CAAC;QACJ,CAAC;QAED,2DAA2D;QAC3D,OAAO,CAAC,cAAc,CAAC;YACrB,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC;gBAAE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;YAE3D,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,EAAe,EAAE,EAAE;gBAC/C,MAAM,OAAO,GAAG,CAAC,CAAiB,EAAE,EAAE;oBACpC,MAAM,IAAI,GAAG,CAAC,CAAC,aAAa,EAAE,OAAO,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC;oBAC1D,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;gBAC3B,CAAC,CAAC;gBAEF,EAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;gBACtC,OAAO,GAAG,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACxD,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Loom — @draggable / @dropzone decorators
3
+ *
4
+ * Declarative HTML5 Drag and Drop API wrappers.
5
+ *
6
+ * ```ts
7
+ * // Make the component draggable — serializes data for transfer
8
+ * @draggable({ type: "card" })
9
+ * getDragData() { return JSON.stringify({ id: this.cardId }); }
10
+ *
11
+ * // Accept drops — receives transferred data
12
+ * @dropzone({ accept: "card" })
13
+ * onDrop(data: string) { this.items.push(JSON.parse(data)); }
14
+ *
15
+ * // With JSX overlay during drag-over
16
+ * @dropzone({ accept: "card", over: () => <div class="drop-hint">Drop here!</div> })
17
+ * onDrop(data: string) { ... }
18
+ * ```
19
+ */
20
+ export interface DraggableOptions {
21
+ /** MIME-like type key for dataTransfer, default "text/plain" */
22
+ type?: string;
23
+ /** Drag effect, default "move" */
24
+ effect?: DataTransfer["effectAllowed"];
25
+ }
26
+ export interface DropzoneOptions {
27
+ /** MIME-like type key to accept, default "text/plain" */
28
+ accept?: string;
29
+ /** Drop effect, default "move" */
30
+ effect?: DataTransfer["dropEffect"];
31
+ /** CSS class to add when dragging over, default "drag-over" */
32
+ overClass?: string;
33
+ /**
34
+ * Optional JSX overlay rendered into the element's shadow DOM (or light DOM)
35
+ * during dragover. Removed on dragleave/drop. Accepts a function that returns
36
+ * a DOM node (JSX), or a string that creates a simple text overlay.
37
+ */
38
+ over?: (() => Node | string) | string;
39
+ }
40
+ /**
41
+ * @draggable(opts?) — Method decorator
42
+ *
43
+ * Makes the host element draggable. The decorated method returns the drag
44
+ * data string. Sets `draggable="true"`, wires `dragstart`/`dragend` events.
45
+ */
46
+ export declare function draggable(opts?: DraggableOptions): (method: Function, context: ClassMethodDecoratorContext) => void;
47
+ /**
48
+ * @dropzone(opts?) — Method decorator
49
+ *
50
+ * Makes the host element a drop target. The decorated method receives
51
+ * the transferred data string and the DragEvent. Wires `dragover`,
52
+ * `dragleave`, `drop` events with proper `preventDefault()`.
53
+ *
54
+ * When `opts.over` is provided, a JSX overlay is rendered into the
55
+ * element during dragover and removed on dragleave/drop.
56
+ */
57
+ export declare function dropzone(opts?: DropzoneOptions): (method: Function, context: ClassMethodDecoratorContext) => void;
58
+ //# sourceMappingURL=dnd.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dnd.d.ts","sourceRoot":"","sources":["../../src/element/dnd.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,MAAM,WAAW,gBAAgB;IAC/B,gEAAgE;IAChE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,kCAAkC;IAClC,MAAM,CAAC,EAAE,YAAY,CAAC,eAAe,CAAC,CAAC;CACxC;AAED,MAAM,WAAW,eAAe;IAC9B,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,MAAM,CAAC,EAAE,YAAY,CAAC,YAAY,CAAC,CAAC;IACpC,+DAA+D;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,IAAI,CAAC,EAAE,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,MAAM,CAAC;CACvC;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,IAAI,CAAC,EAAE,gBAAgB,IAI9B,QAAQ,QAAQ,EAAE,SAAS,2BAA2B,UA6BxE;AAED;;;;;;;;;GASG;AACH,wBAAgB,QAAQ,CAAC,IAAI,CAAC,EAAE,eAAe,IAM5B,QAAQ,QAAQ,EAAE,SAAS,2BAA2B,UA+DxE"}
@@ -0,0 +1,132 @@
1
+ /**
2
+ * Loom — @draggable / @dropzone decorators
3
+ *
4
+ * Declarative HTML5 Drag and Drop API wrappers.
5
+ *
6
+ * ```ts
7
+ * // Make the component draggable — serializes data for transfer
8
+ * @draggable({ type: "card" })
9
+ * getDragData() { return JSON.stringify({ id: this.cardId }); }
10
+ *
11
+ * // Accept drops — receives transferred data
12
+ * @dropzone({ accept: "card" })
13
+ * onDrop(data: string) { this.items.push(JSON.parse(data)); }
14
+ *
15
+ * // With JSX overlay during drag-over
16
+ * @dropzone({ accept: "card", over: () => <div class="drop-hint">Drop here!</div> })
17
+ * onDrop(data: string) { ... }
18
+ * ```
19
+ */
20
+ import { CONNECT_HOOKS } from "../decorators/symbols";
21
+ /**
22
+ * @draggable(opts?) — Method decorator
23
+ *
24
+ * Makes the host element draggable. The decorated method returns the drag
25
+ * data string. Sets `draggable="true"`, wires `dragstart`/`dragend` events.
26
+ */
27
+ export function draggable(opts) {
28
+ const mimeType = opts?.type ?? "text/plain";
29
+ const effect = opts?.effect ?? "move";
30
+ return function (method, context) {
31
+ context.addInitializer(function () {
32
+ if (!this[CONNECT_HOOKS.key])
33
+ this[CONNECT_HOOKS.key] = [];
34
+ this[CONNECT_HOOKS.key].push((el) => {
35
+ el.draggable = true;
36
+ const onStart = (e) => {
37
+ const data = method.call(el);
38
+ e.dataTransfer?.setData(mimeType, String(data ?? ""));
39
+ if (e.dataTransfer)
40
+ e.dataTransfer.effectAllowed = effect;
41
+ el.classList.add("dragging");
42
+ };
43
+ const onEnd = () => {
44
+ el.classList.remove("dragging");
45
+ };
46
+ el.addEventListener("dragstart", onStart);
47
+ el.addEventListener("dragend", onEnd);
48
+ return () => {
49
+ el.removeEventListener("dragstart", onStart);
50
+ el.removeEventListener("dragend", onEnd);
51
+ el.draggable = false;
52
+ };
53
+ });
54
+ });
55
+ };
56
+ }
57
+ /**
58
+ * @dropzone(opts?) — Method decorator
59
+ *
60
+ * Makes the host element a drop target. The decorated method receives
61
+ * the transferred data string and the DragEvent. Wires `dragover`,
62
+ * `dragleave`, `drop` events with proper `preventDefault()`.
63
+ *
64
+ * When `opts.over` is provided, a JSX overlay is rendered into the
65
+ * element during dragover and removed on dragleave/drop.
66
+ */
67
+ export function dropzone(opts) {
68
+ const mimeType = opts?.accept ?? "text/plain";
69
+ const dropEffect = opts?.effect ?? "move";
70
+ const overClass = opts?.overClass ?? "drag-over";
71
+ const overFn = opts?.over;
72
+ return function (method, context) {
73
+ context.addInitializer(function () {
74
+ if (!this[CONNECT_HOOKS.key])
75
+ this[CONNECT_HOOKS.key] = [];
76
+ this[CONNECT_HOOKS.key].push((el) => {
77
+ let overlayEl = null;
78
+ const showOverlay = () => {
79
+ if (!overFn || overlayEl)
80
+ return;
81
+ const content = typeof overFn === "function" ? overFn() : overFn;
82
+ if (content instanceof Node) {
83
+ overlayEl = content;
84
+ }
85
+ else {
86
+ const div = document.createElement("div");
87
+ div.setAttribute("data-loom-dropzone-overlay", "");
88
+ div.textContent = String(content);
89
+ overlayEl = div;
90
+ }
91
+ // Append to shadow root if available, otherwise light DOM
92
+ const root = el.shadowRoot ?? el;
93
+ root.appendChild(overlayEl);
94
+ };
95
+ const hideOverlay = () => {
96
+ if (overlayEl) {
97
+ overlayEl.parentNode?.removeChild(overlayEl);
98
+ overlayEl = null;
99
+ }
100
+ };
101
+ const onOver = (e) => {
102
+ e.preventDefault();
103
+ if (e.dataTransfer)
104
+ e.dataTransfer.dropEffect = dropEffect;
105
+ el.classList.add(overClass);
106
+ showOverlay();
107
+ };
108
+ const onLeave = () => {
109
+ el.classList.remove(overClass);
110
+ hideOverlay();
111
+ };
112
+ const onDrop = (e) => {
113
+ e.preventDefault();
114
+ el.classList.remove(overClass);
115
+ hideOverlay();
116
+ const data = e.dataTransfer?.getData(mimeType) ?? "";
117
+ method.call(el, data, e);
118
+ };
119
+ el.addEventListener("dragover", onOver);
120
+ el.addEventListener("dragleave", onLeave);
121
+ el.addEventListener("drop", onDrop);
122
+ return () => {
123
+ el.removeEventListener("dragover", onOver);
124
+ el.removeEventListener("dragleave", onLeave);
125
+ el.removeEventListener("drop", onDrop);
126
+ hideOverlay();
127
+ };
128
+ });
129
+ });
130
+ };
131
+ }
132
+ //# sourceMappingURL=dnd.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dnd.js","sourceRoot":"","sources":["../../src/element/dnd.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Loom — @fullscreen decorator
3
+ *
4
+ * Accessor decorator that binds a boolean field to the Fullscreen API.
5
+ * Setting to `true` calls `requestFullscreen()`, `false` calls `exitFullscreen()`.
6
+ * Listens for `fullscreenchange` events to keep the field in sync.
7
+ *
8
+ * ```ts
9
+ * @fullscreen()
10
+ * accessor isFullscreen = false;
11
+ *
12
+ * // With options
13
+ * @fullscreen({ navigationUI: "hide" })
14
+ * accessor isFullscreen = false;
15
+ * ```
16
+ */
17
+ export interface FullscreenOptions {
18
+ /** Navigation UI preference for requestFullscreen */
19
+ navigationUI?: "auto" | "hide" | "show";
20
+ }
21
+ /**
22
+ * @fullscreen(opts?) — Accessor decorator
23
+ *
24
+ * Binds a boolean accessor to the Fullscreen API.
25
+ * Toggling the field enters/exits fullscreen. The field stays in sync
26
+ * with external fullscreen changes (e.g., user presses Escape).
27
+ */
28
+ export declare function fullscreen(opts?: FullscreenOptions): (_target: ClassAccessorDecoratorTarget<any, boolean>, context: ClassAccessorDecoratorContext) => ClassAccessorDecoratorResult<any, boolean>;
29
+ //# sourceMappingURL=fullscreen.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fullscreen.d.ts","sourceRoot":"","sources":["../../src/element/fullscreen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,MAAM,WAAW,iBAAiB;IAChC,qDAAqD;IACrD,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;CACzC;AAED;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,CAAC,EAAE,iBAAiB,IAE/C,SAAS,4BAA4B,CAAC,GAAG,EAAE,OAAO,CAAC,EACnD,SAAS,6BAA6B,KACrC,4BAA4B,CAAC,GAAG,EAAE,OAAO,CAAC,CAoD9C"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Loom — @fullscreen decorator
3
+ *
4
+ * Accessor decorator that binds a boolean field to the Fullscreen API.
5
+ * Setting to `true` calls `requestFullscreen()`, `false` calls `exitFullscreen()`.
6
+ * Listens for `fullscreenchange` events to keep the field in sync.
7
+ *
8
+ * ```ts
9
+ * @fullscreen()
10
+ * accessor isFullscreen = false;
11
+ *
12
+ * // With options
13
+ * @fullscreen({ navigationUI: "hide" })
14
+ * accessor isFullscreen = false;
15
+ * ```
16
+ */
17
+ import { CONNECT_HOOKS } from "../decorators/symbols";
18
+ /**
19
+ * @fullscreen(opts?) — Accessor decorator
20
+ *
21
+ * Binds a boolean accessor to the Fullscreen API.
22
+ * Toggling the field enters/exits fullscreen. The field stays in sync
23
+ * with external fullscreen changes (e.g., user presses Escape).
24
+ */
25
+ export function fullscreen(opts) {
26
+ return function (_target, context) {
27
+ const fieldName = context.name;
28
+ const storageKey = `__fs_${fieldName}`;
29
+ context.addInitializer(function () {
30
+ if (!this[CONNECT_HOOKS.key])
31
+ this[CONNECT_HOOKS.key] = [];
32
+ this[CONNECT_HOOKS.key].push((el) => {
33
+ // Sync field when fullscreen changes externally (e.g., Escape key)
34
+ const handler = () => {
35
+ const isFs = document.fullscreenElement === el;
36
+ this[storageKey] = isFs;
37
+ this.scheduleUpdate?.();
38
+ };
39
+ document.addEventListener("fullscreenchange", handler);
40
+ return () => {
41
+ document.removeEventListener("fullscreenchange", handler);
42
+ // Exit fullscreen if component disconnects while fullscreen
43
+ if (document.fullscreenElement === el) {
44
+ document.exitFullscreen?.();
45
+ }
46
+ };
47
+ });
48
+ });
49
+ return {
50
+ init(_value) {
51
+ return false;
52
+ },
53
+ set(value) {
54
+ const prev = this[storageKey];
55
+ this[storageKey] = value;
56
+ if (value && !prev) {
57
+ // Entering fullscreen
58
+ this.requestFullscreen?.(opts);
59
+ }
60
+ else if (!value && prev) {
61
+ // Exiting fullscreen
62
+ if (document.fullscreenElement === this) {
63
+ document.exitFullscreen?.();
64
+ }
65
+ }
66
+ },
67
+ get() {
68
+ return this[storageKey] ?? false;
69
+ },
70
+ };
71
+ };
72
+ }
73
+ //# sourceMappingURL=fullscreen.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fullscreen.js","sourceRoot":"","sources":["../../src/element/fullscreen.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAOtD;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,IAAwB;IACjD,OAAO,UACL,OAAmD,EACnD,OAAsC;QAEtC,MAAM,SAAS,GAAG,OAAO,CAAC,IAAc,CAAC;QACzC,MAAM,UAAU,GAAG,QAAQ,SAAS,EAAE,CAAC;QAEvC,OAAO,CAAC,cAAc,CAAC;YACrB,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC;gBAAE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;YAE3D,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,EAAe,EAAE,EAAE;gBAC/C,mEAAmE;gBACnE,MAAM,OAAO,GAAG,GAAG,EAAE;oBACnB,MAAM,IAAI,GAAG,QAAQ,CAAC,iBAAiB,KAAK,EAAE,CAAC;oBAC/C,IAAI,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;oBACxB,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;gBAC1B,CAAC,CAAC;gBAEF,QAAQ,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC;gBAEvD,OAAO,GAAG,EAAE;oBACV,QAAQ,CAAC,mBAAmB,CAAC,kBAAkB,EAAE,OAAO,CAAC,CAAC;oBAC1D,4DAA4D;oBAC5D,IAAI,QAAQ,CAAC,iBAAiB,KAAK,EAAE,EAAE,CAAC;wBACtC,QAAQ,CAAC,cAAc,EAAE,EAAE,CAAC;oBAC9B,CAAC;gBACH,CAAC,CAAC;YACJ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,OAAO;YACL,IAAI,CAAC,MAAe;gBAClB,OAAO,KAAK,CAAC;YACf,CAAC;YAED,GAAG,CAAY,KAAc;gBAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;gBAC9B,IAAI,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC;gBAEzB,IAAI,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;oBACnB,sBAAsB;oBACrB,IAAoB,CAAC,iBAAiB,EAAE,CAAC,IAAI,CAAC,CAAC;gBAClD,CAAC;qBAAM,IAAI,CAAC,KAAK,IAAI,IAAI,EAAE,CAAC;oBAC1B,qBAAqB;oBACrB,IAAI,QAAQ,CAAC,iBAAiB,KAAK,IAAI,EAAE,CAAC;wBACxC,QAAQ,CAAC,cAAc,EAAE,EAAE,CAAC;oBAC9B,CAAC;gBACH,CAAC;YACH,CAAC;YAED,GAAG;gBACD,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC;YACnC,CAAC;SACF,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
@@ -25,4 +25,10 @@ export { provide, consume, ContextRequestEvent } from "./context";
25
25
  export type { ContextCallback } from "./context";
26
26
  export { portal } from "./portal";
27
27
  export type { PortalOptions } from "./portal";
28
+ export { media } from "./media";
29
+ export { fullscreen } from "./fullscreen";
30
+ export type { FullscreenOptions } from "./fullscreen";
31
+ export { clipboard } from "./clipboard";
32
+ export { draggable, dropzone } from "./dnd";
33
+ export type { DraggableOptions, DropzoneOptions } from "./dnd";
28
34
  //# sourceMappingURL=index.d.ts.map
@@ -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;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,KAAK,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAG7G,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;AAC1C,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG3D,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG/B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGtD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAG3D,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAC/E,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAG5D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAClE,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAGjD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,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,KAAK,qBAAqB,EAAE,MAAM,UAAU,CAAC;AAG7G,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;AAC1C,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAG3D,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAG/B,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGtD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAG3D,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAC/E,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAG5D,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAClE,YAAY,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAGjD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,YAAY,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAG9C,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGhC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGtD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGxC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC5C,YAAY,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,OAAO,CAAC"}
@@ -37,4 +37,12 @@ export { log, LogTransport, ConsoleTransport, resetLogTransport } from "./log";
37
37
  export { provide, consume, ContextRequestEvent } from "./context";
38
38
  // Portal: teleport content to external DOM targets
39
39
  export { portal } from "./portal";
40
+ // Media: reactive media query binding
41
+ export { media } from "./media";
42
+ // Fullscreen: toggle fullscreen API
43
+ export { fullscreen } from "./fullscreen";
44
+ // Clipboard: declarative copy/paste
45
+ export { clipboard } from "./clipboard";
46
+ // Drag & Drop: declarative DnD
47
+ export { draggable, dropzone } from "./dnd";
40
48
  //# sourceMappingURL=index.js.map
@@ -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;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,EAA8B,MAAM,UAAU,CAAC;AAE7G,iBAAiB;AACjB,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAG9B,yBAAyB;AACzB,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE3D,iBAAiB;AACjB,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B,uBAAuB;AACvB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,mBAAmB;AACnB,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGlC,4BAA4B;AAC5B,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAG/E,oDAAoD;AACpD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAGlE,mDAAmD;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,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,EAA8B,MAAM,UAAU,CAAC;AAE7G,iBAAiB;AACjB,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAG9B,yBAAyB;AACzB,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAE9B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE3D,iBAAiB;AACjB,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE/B,uBAAuB;AACvB,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,mBAAmB;AACnB,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGlC,4BAA4B;AAC5B,OAAO,EAAE,GAAG,EAAE,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAG/E,oDAAoD;AACpD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAGlE,mDAAmD;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAGlC,sCAAsC;AACtC,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEhC,oCAAoC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG1C,oCAAoC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,+BAA+B;AAC/B,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Loom — @media decorator
3
+ *
4
+ * Reactive media-query binding for accessor fields.
5
+ * Creates a `matchMedia` listener on connect, cleans up on disconnect.
6
+ * The field auto-updates when the media query match state changes.
7
+ *
8
+ * ```ts
9
+ * @media("(max-width: 768px)")
10
+ * accessor isMobile = false;
11
+ *
12
+ * @media("(prefers-color-scheme: dark)")
13
+ * accessor prefersDark = false;
14
+ *
15
+ * @media("(min-width: 1024px) and (orientation: landscape)")
16
+ * accessor isDesktop = false;
17
+ * ```
18
+ */
19
+ /**
20
+ * @media(query) — Accessor decorator
21
+ *
22
+ * Binds a boolean accessor to a CSS media query via `matchMedia`.
23
+ * The field is set to `true`/`false` on connect and updated reactively
24
+ * whenever the match state changes. Cleanup is automatic on disconnect.
25
+ */
26
+ export declare function media(query: string): (_target: ClassAccessorDecoratorTarget<any, boolean>, context: ClassAccessorDecoratorContext) => ClassAccessorDecoratorResult<any, boolean>;
27
+ //# sourceMappingURL=media.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media.d.ts","sourceRoot":"","sources":["../../src/element/media.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAIH;;;;;;GAMG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,IAE/B,SAAS,4BAA4B,CAAC,GAAG,EAAE,OAAO,CAAC,EACnD,SAAS,6BAA6B,KACrC,4BAA4B,CAAC,GAAG,EAAE,OAAO,CAAC,CAyC9C"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Loom — @media decorator
3
+ *
4
+ * Reactive media-query binding for accessor fields.
5
+ * Creates a `matchMedia` listener on connect, cleans up on disconnect.
6
+ * The field auto-updates when the media query match state changes.
7
+ *
8
+ * ```ts
9
+ * @media("(max-width: 768px)")
10
+ * accessor isMobile = false;
11
+ *
12
+ * @media("(prefers-color-scheme: dark)")
13
+ * accessor prefersDark = false;
14
+ *
15
+ * @media("(min-width: 1024px) and (orientation: landscape)")
16
+ * accessor isDesktop = false;
17
+ * ```
18
+ */
19
+ import { CONNECT_HOOKS } from "../decorators/symbols";
20
+ /**
21
+ * @media(query) — Accessor decorator
22
+ *
23
+ * Binds a boolean accessor to a CSS media query via `matchMedia`.
24
+ * The field is set to `true`/`false` on connect and updated reactively
25
+ * whenever the match state changes. Cleanup is automatic on disconnect.
26
+ */
27
+ export function media(query) {
28
+ return function (_target, context) {
29
+ const fieldName = context.name;
30
+ const storageKey = `__media_${fieldName}`;
31
+ context.addInitializer(function () {
32
+ if (!this[CONNECT_HOOKS.key])
33
+ this[CONNECT_HOOKS.key] = [];
34
+ this[CONNECT_HOOKS.key].push((_el) => {
35
+ const mql = window.matchMedia(query);
36
+ // Set initial value from current match state
37
+ this[storageKey] = mql.matches;
38
+ this.scheduleUpdate?.();
39
+ // Listen for changes
40
+ const handler = (e) => {
41
+ this[storageKey] = e.matches;
42
+ this.scheduleUpdate?.();
43
+ };
44
+ mql.addEventListener("change", handler);
45
+ // Return cleanup — runs on disconnectedCallback
46
+ return () => mql.removeEventListener("change", handler);
47
+ });
48
+ });
49
+ return {
50
+ init(_value) {
51
+ return false; // Will be set from matchMedia on connect
52
+ },
53
+ set(value) {
54
+ this[storageKey] = value;
55
+ },
56
+ get() {
57
+ return this[storageKey] ?? false;
58
+ },
59
+ };
60
+ };
61
+ }
62
+ //# sourceMappingURL=media.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"media.js","sourceRoot":"","sources":["../../src/element/media.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD;;;;;;GAMG;AACH,MAAM,UAAU,KAAK,CAAC,KAAa;IACjC,OAAO,UACL,OAAmD,EACnD,OAAsC;QAEtC,MAAM,SAAS,GAAG,OAAO,CAAC,IAAc,CAAC;QACzC,MAAM,UAAU,GAAG,WAAW,SAAS,EAAE,CAAC;QAE1C,OAAO,CAAC,cAAc,CAAC;YACrB,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC;gBAAE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;YAE3D,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,GAAgB,EAAE,EAAE;gBAChD,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;gBAErC,6CAA6C;gBAC7C,IAAI,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC;gBAC/B,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;gBAExB,qBAAqB;gBACrB,MAAM,OAAO,GAAG,CAAC,CAAsB,EAAE,EAAE;oBACzC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;oBAC7B,IAAI,CAAC,cAAc,EAAE,EAAE,CAAC;gBAC1B,CAAC,CAAC;gBAEF,GAAG,CAAC,gBAAgB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAExC,gDAAgD;gBAChD,OAAO,GAAG,EAAE,CAAC,GAAG,CAAC,mBAAmB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAC1D,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,OAAO;YACL,IAAI,CAAC,MAAe;gBAClB,OAAO,KAAK,CAAC,CAAC,yCAAyC;YACzD,CAAC;YAED,GAAG,CAAY,KAAc;gBAC3B,IAAI,CAAC,UAAU,CAAC,GAAG,KAAK,CAAC;YAC3B,CAAC;YAED,GAAG;gBACD,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC;YACnC,CAAC;SACF,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@toyz/loom",
3
- "version": "0.17.3",
3
+ "version": "0.17.4",
4
4
  "type": "module",
5
5
  "description": "Decorator-driven web component framework with reactive state, DOM morphing, DI, and JSX",
6
6
  "license": "MIT",