@hyperfixi/behaviors 2.5.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +100 -0
- package/dist/all.browser.global.js +43 -40
- package/dist/all.browser.global.js.map +1 -1
- package/dist/autodismiss.browser.global.js +2 -2
- package/dist/autodismiss.browser.global.js.map +1 -1
- package/dist/behaviors/autodismiss.cjs +5 -54
- package/dist/behaviors/autodismiss.cjs.map +1 -1
- package/dist/behaviors/autodismiss.d.cts +3 -2
- package/dist/behaviors/autodismiss.d.ts +3 -2
- package/dist/behaviors/autodismiss.js +1 -1
- package/dist/behaviors/clickoutside.cjs +6 -28
- package/dist/behaviors/clickoutside.cjs.map +1 -1
- package/dist/behaviors/clickoutside.d.cts +3 -2
- package/dist/behaviors/clickoutside.d.ts +3 -2
- package/dist/behaviors/clickoutside.js +2 -2
- package/dist/behaviors/clipboard.cjs +30 -86
- package/dist/behaviors/clipboard.cjs.map +1 -1
- package/dist/behaviors/clipboard.d.cts +3 -2
- package/dist/behaviors/clipboard.d.ts +3 -2
- package/dist/behaviors/clipboard.js +2 -2
- package/dist/behaviors/draggable.cjs +6 -41
- package/dist/behaviors/draggable.cjs.map +1 -1
- package/dist/behaviors/draggable.d.cts +3 -3
- package/dist/behaviors/draggable.d.ts +3 -3
- package/dist/behaviors/draggable.js +2 -2
- package/dist/behaviors/focustrap.cjs +5 -81
- package/dist/behaviors/focustrap.cjs.map +1 -1
- package/dist/behaviors/focustrap.d.cts +3 -2
- package/dist/behaviors/focustrap.d.ts +3 -2
- package/dist/behaviors/focustrap.js +1 -1
- package/dist/behaviors/removable.d.cts +1 -1
- package/dist/behaviors/removable.d.ts +1 -1
- package/dist/behaviors/resizable.cjs +9 -49
- package/dist/behaviors/resizable.cjs.map +1 -1
- package/dist/behaviors/resizable.d.cts +3 -2
- package/dist/behaviors/resizable.d.ts +3 -2
- package/dist/behaviors/resizable.js +2 -2
- package/dist/behaviors/scrollreveal.cjs +5 -32
- package/dist/behaviors/scrollreveal.cjs.map +1 -1
- package/dist/behaviors/scrollreveal.d.cts +3 -2
- package/dist/behaviors/scrollreveal.d.ts +3 -2
- package/dist/behaviors/scrollreveal.js +1 -1
- package/dist/behaviors/sortable.cjs +8 -43
- package/dist/behaviors/sortable.cjs.map +1 -1
- package/dist/behaviors/sortable.d.cts +3 -2
- package/dist/behaviors/sortable.d.ts +3 -2
- package/dist/behaviors/sortable.js +2 -2
- package/dist/behaviors/tabs.cjs +5 -120
- package/dist/behaviors/tabs.cjs.map +1 -1
- package/dist/behaviors/tabs.d.cts +3 -2
- package/dist/behaviors/tabs.d.ts +3 -2
- package/dist/behaviors/tabs.js +1 -1
- package/dist/behaviors/toggleable.cjs +5 -27
- package/dist/behaviors/toggleable.cjs.map +1 -1
- package/dist/behaviors/toggleable.d.cts +3 -3
- package/dist/behaviors/toggleable.d.ts +3 -3
- package/dist/behaviors/toggleable.js +1 -1
- package/dist/{chunk-SLOXO6IY.js → chunk-26IX7QU7.js} +2 -2
- package/dist/{chunk-SLOXO6IY.js.map → chunk-26IX7QU7.js.map} +1 -1
- package/dist/chunk-2HUF6RMI.js +40 -0
- package/dist/chunk-2HUF6RMI.js.map +1 -0
- package/dist/{chunk-ZBSWTV6I.js → chunk-5LFOFVZ3.js} +5 -5
- package/dist/chunk-5LFOFVZ3.js.map +1 -0
- package/dist/{chunk-BBIIOGMF.js → chunk-6EG2MNC7.js} +6 -6
- package/dist/chunk-7NGOA3T5.js +40 -0
- package/dist/chunk-7NGOA3T5.js.map +1 -0
- package/dist/{chunk-ZZ2WSAX3.js → chunk-7TPDLB7W.js} +7 -29
- package/dist/chunk-7TPDLB7W.js.map +1 -0
- package/dist/chunk-CR3J7VV6.js +40 -0
- package/dist/chunk-CR3J7VV6.js.map +1 -0
- package/dist/chunk-EDBG2F57.js +40 -0
- package/dist/chunk-EDBG2F57.js.map +1 -0
- package/dist/{chunk-G6WR2AYR.js → chunk-FBQ3X3UY.js} +2 -2
- package/dist/chunk-FBQ3X3UY.js.map +1 -0
- package/dist/chunk-HX663BJ4.js +40 -0
- package/dist/chunk-HX663BJ4.js.map +1 -0
- package/dist/chunk-KROW43CG.js +40 -0
- package/dist/chunk-KROW43CG.js.map +1 -0
- package/dist/chunk-ORBJ7MRW.js +40 -0
- package/dist/chunk-ORBJ7MRW.js.map +1 -0
- package/dist/{chunk-V2M4W3LO.js → chunk-PDMOOWFW.js} +4 -4
- package/dist/chunk-PDMOOWFW.js.map +1 -0
- package/dist/chunk-SLSCZV4A.js +40 -0
- package/dist/chunk-SLSCZV4A.js.map +1 -0
- package/dist/chunk-WKBRZGGL.js +40 -0
- package/dist/chunk-WKBRZGGL.js.map +1 -0
- package/dist/{chunk-WOTZO7K4.js → chunk-YXS27XM6.js} +26 -23
- package/dist/chunk-YXS27XM6.js.map +1 -0
- package/dist/clickoutside.browser.global.js +3 -3
- package/dist/clickoutside.browser.global.js.map +1 -1
- package/dist/clipboard.browser.global.js +27 -24
- package/dist/clipboard.browser.global.js.map +1 -1
- package/dist/core.browser.global.js +3 -3
- package/dist/core.browser.global.js.map +1 -1
- package/dist/draggable.browser.global.js +2 -2
- package/dist/draggable.browser.global.js.map +1 -1
- package/dist/focustrap.browser.global.js +2 -2
- package/dist/focustrap.browser.global.js.map +1 -1
- package/dist/index.cjs +120 -563
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +41 -3
- package/dist/index.d.ts +41 -3
- package/dist/index.js +44 -16
- package/dist/index.js.map +1 -1
- package/dist/loaders.cjs +86 -563
- package/dist/loaders.cjs.map +1 -1
- package/dist/loaders.js +6 -6
- package/dist/registry.d.cts +1 -1
- package/dist/registry.d.ts +1 -1
- package/dist/resizable.browser.global.js +5 -5
- package/dist/resizable.browser.global.js.map +1 -1
- package/dist/resolver.browser.global.js +34 -31
- package/dist/resolver.browser.global.js.map +1 -1
- package/dist/schemas/index.cjs +34 -31
- package/dist/schemas/index.cjs.map +1 -1
- package/dist/schemas/index.d.cts +2 -2
- package/dist/schemas/index.d.ts +2 -2
- package/dist/schemas/index.js +5 -5
- package/dist/scrollreveal.browser.global.js +2 -2
- package/dist/scrollreveal.browser.global.js.map +1 -1
- package/dist/sortable.browser.global.js +4 -4
- package/dist/sortable.browser.global.js.map +1 -1
- package/dist/tabs.browser.global.js +2 -2
- package/dist/tabs.browser.global.js.map +1 -1
- package/dist/toggleable.browser.global.js +2 -2
- package/dist/toggleable.browser.global.js.map +1 -1
- package/dist/{types-BY-jB5FV.d.ts → types-DCCtVQS5.d.cts} +1 -1
- package/dist/{types-BY-jB5FV.d.cts → types-DCCtVQS5.d.ts} +1 -1
- package/package.json +4 -4
- package/src/behaviors/autodismiss.test.ts +15 -9
- package/src/behaviors/autodismiss.ts +15 -70
- package/src/behaviors/clickoutside.test.ts +17 -9
- package/src/behaviors/clickoutside.ts +13 -39
- package/src/behaviors/clipboard.test.ts +16 -10
- package/src/behaviors/clipboard.ts +15 -93
- package/src/behaviors/curated-runtime.test.ts +158 -0
- package/src/behaviors/draggable.ts +15 -59
- package/src/behaviors/experimental-runtime.test.ts +136 -0
- package/src/behaviors/focustrap.test.ts +15 -9
- package/src/behaviors/focustrap.ts +17 -121
- package/src/behaviors/integration.test.ts +9 -64
- package/src/behaviors/optional-runtime.test.ts +251 -0
- package/src/behaviors/resizable.ts +14 -61
- package/src/behaviors/scrollreveal.test.ts +17 -9
- package/src/behaviors/scrollreveal.ts +17 -41
- package/src/behaviors/sortable.ts +15 -58
- package/src/behaviors/tabs.test.ts +16 -10
- package/src/behaviors/tabs.ts +18 -160
- package/src/behaviors/toggleable.ts +14 -41
- package/src/curation.test.ts +45 -0
- package/src/curation.ts +58 -0
- package/src/index.ts +14 -0
- package/src/registry.test.ts +6 -11
- package/src/schemas/clickoutside.schema.ts +1 -1
- package/src/schemas/clipboard.schema.ts +25 -22
- package/src/schemas/draggable.schema.ts +2 -1
- package/src/schemas/resizable.schema.ts +5 -4
- package/src/schemas/sortable.schema.ts +4 -3
- package/dist/chunk-7O7UOSBH.js +0 -99
- package/dist/chunk-7O7UOSBH.js.map +0 -1
- package/dist/chunk-EKKJVXDZ.js +0 -67
- package/dist/chunk-EKKJVXDZ.js.map +0 -1
- package/dist/chunk-F3CASJ7Q.js +0 -116
- package/dist/chunk-F3CASJ7Q.js.map +0 -1
- package/dist/chunk-G6WR2AYR.js.map +0 -1
- package/dist/chunk-GALKOMJ5.js +0 -62
- package/dist/chunk-GALKOMJ5.js.map +0 -1
- package/dist/chunk-IMDFEGIT.js +0 -75
- package/dist/chunk-IMDFEGIT.js.map +0 -1
- package/dist/chunk-IT6TYVMW.js +0 -80
- package/dist/chunk-IT6TYVMW.js.map +0 -1
- package/dist/chunk-LQJOQTBZ.js +0 -89
- package/dist/chunk-LQJOQTBZ.js.map +0 -1
- package/dist/chunk-S4QDV2MH.js +0 -75
- package/dist/chunk-S4QDV2MH.js.map +0 -1
- package/dist/chunk-V2M4W3LO.js.map +0 -1
- package/dist/chunk-WOTZO7K4.js.map +0 -1
- package/dist/chunk-WPOQIMCC.js +0 -155
- package/dist/chunk-WPOQIMCC.js.map +0 -1
- package/dist/chunk-ZBSWTV6I.js.map +0 -1
- package/dist/chunk-ZZ2WSAX3.js.map +0 -1
- /package/dist/{chunk-BBIIOGMF.js.map → chunk-6EG2MNC7.js.map} +0 -0
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as BehaviorSchema, L as LokaScriptInstance } from '../types-DCCtVQS5.js';
|
|
2
2
|
|
|
3
3
|
declare const clipboardSource: string;
|
|
4
4
|
declare const clipboardMetadata: BehaviorSchema;
|
|
5
5
|
/**
|
|
6
|
-
* Register the Clipboard behavior with LokaScript
|
|
6
|
+
* Register the Clipboard behavior with LokaScript by compiling its
|
|
7
|
+
* hyperscript source and executing the resulting behavior definition.
|
|
7
8
|
*/
|
|
8
9
|
declare function registerClipboard(hyperfixi?: LokaScriptInstance): Promise<void>;
|
|
9
10
|
declare const _default: {
|
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
clipboardSource,
|
|
4
4
|
clipboard_default,
|
|
5
5
|
registerClipboard
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import "../chunk-
|
|
6
|
+
} from "../chunk-EDBG2F57.js";
|
|
7
|
+
import "../chunk-YXS27XM6.js";
|
|
8
8
|
import "../chunk-6TJXDCAQ.js";
|
|
9
9
|
export {
|
|
10
10
|
clipboardMetadata,
|
|
@@ -33,7 +33,7 @@ var draggableSchema = {
|
|
|
33
33
|
category: "ui",
|
|
34
34
|
tier: "core",
|
|
35
35
|
version: "1.0.0",
|
|
36
|
-
description: "Makes elements draggable with pointer events",
|
|
36
|
+
description: "Makes elements draggable with pointer events (EXPERIMENTAL \u2014 stateful async component, beyond the inline-scripting boundary; not part of the curated set)",
|
|
37
37
|
parameters: [
|
|
38
38
|
{
|
|
39
39
|
name: "dragHandle",
|
|
@@ -85,38 +85,6 @@ function resolveRuntime() {
|
|
|
85
85
|
// src/behaviors/draggable.ts
|
|
86
86
|
var draggableSource = draggableSchema.source;
|
|
87
87
|
var draggableMetadata = draggableSchema;
|
|
88
|
-
function installDraggable(element, params) {
|
|
89
|
-
let dragHandle = element;
|
|
90
|
-
if (params.dragHandle && params.dragHandle !== "me") {
|
|
91
|
-
if (typeof params.dragHandle === "string") {
|
|
92
|
-
const found = element.querySelector(params.dragHandle);
|
|
93
|
-
if (found instanceof HTMLElement) dragHandle = found;
|
|
94
|
-
} else if (params.dragHandle instanceof HTMLElement) {
|
|
95
|
-
dragHandle = params.dragHandle;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
dragHandle.addEventListener("pointerdown", (e) => {
|
|
99
|
-
e.preventDefault();
|
|
100
|
-
e.stopPropagation();
|
|
101
|
-
element.dispatchEvent(new CustomEvent("draggable:start", { bubbles: true }));
|
|
102
|
-
const startX = element.offsetLeft;
|
|
103
|
-
const startY = element.offsetTop;
|
|
104
|
-
const xoff = e.clientX - startX;
|
|
105
|
-
const yoff = e.clientY - startY;
|
|
106
|
-
function onMove(ev) {
|
|
107
|
-
element.style.left = `${ev.clientX - xoff}px`;
|
|
108
|
-
element.style.top = `${ev.clientY - yoff}px`;
|
|
109
|
-
element.dispatchEvent(new CustomEvent("draggable:move", { bubbles: true }));
|
|
110
|
-
}
|
|
111
|
-
function onUp() {
|
|
112
|
-
document.removeEventListener("pointermove", onMove);
|
|
113
|
-
document.removeEventListener("pointerup", onUp);
|
|
114
|
-
element.dispatchEvent(new CustomEvent("draggable:end", { bubbles: true }));
|
|
115
|
-
}
|
|
116
|
-
document.addEventListener("pointermove", onMove);
|
|
117
|
-
document.addEventListener("pointerup", onUp);
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
88
|
async function registerDraggable(hyperfixi) {
|
|
121
89
|
const hf = hyperfixi || resolveRuntime();
|
|
122
90
|
if (!hf) {
|
|
@@ -124,15 +92,12 @@ async function registerDraggable(hyperfixi) {
|
|
|
124
92
|
"LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
|
|
125
93
|
);
|
|
126
94
|
}
|
|
127
|
-
const
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
eventHandlers: [],
|
|
132
|
-
imperativeInstaller: installDraggable
|
|
133
|
-
};
|
|
95
|
+
const result = hf.compileSync(draggableSchema.source, { traditional: true });
|
|
96
|
+
if (!result.ok) {
|
|
97
|
+
throw new Error(`Failed to compile Draggable behavior: ${JSON.stringify(result.errors)}`);
|
|
98
|
+
}
|
|
134
99
|
const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
|
|
135
|
-
await hf.execute(
|
|
100
|
+
await hf.execute(result.ast, ctx);
|
|
136
101
|
}
|
|
137
102
|
if (resolveRuntime()) {
|
|
138
103
|
registerDraggable().catch(console.error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/behaviors/draggable.ts","../../src/schemas/draggable.schema.ts","../../src/schemas/types.ts"],"sourcesContent":["/**\n * Draggable Behavior — Imperative Implementation\n *\n * Makes elements draggable with pointer events.\n * Uses direct DOM APIs instead of compiling hyperscript source,\n * bypassing the complex repeat-until-event + wait-for async pattern.\n *\n * @example\n * ```html\n * <!-- Basic usage -->\n * <div _=\"install Draggable\">Drag me!</div>\n *\n * <!-- With custom drag handle -->\n * <div _=\"install Draggable(dragHandle: .titlebar)\">\n * <div class=\"titlebar\">Drag here</div>\n * <div class=\"content\">Content</div>\n * </div>\n * ```\n */\n\nimport { draggableSchema } from '../schemas/draggable.schema';\nimport type { LokaScriptInstance } from '../schemas/types';\nimport { resolveRuntime } from '../schemas/types';\n\n// Re-export schema-derived values for backwards compatibility\nexport const draggableSource = draggableSchema.source;\nexport const draggableMetadata = draggableSchema;\n\n/**\n * Imperative installer for Draggable behavior.\n * Called directly by the runtime when `install Draggable` is executed.\n */\nfunction installDraggable(element: HTMLElement, params: Record<string, any>): void {\n // Resolve drag handle: parameter value, CSS selector, or the element itself\n let dragHandle: HTMLElement = element;\n if (params.dragHandle && params.dragHandle !== 'me') {\n if (typeof params.dragHandle === 'string') {\n const found = element.querySelector(params.dragHandle);\n if (found instanceof HTMLElement) dragHandle = found;\n } else if (params.dragHandle instanceof HTMLElement) {\n dragHandle = params.dragHandle;\n }\n }\n\n dragHandle.addEventListener('pointerdown', (e: PointerEvent) => {\n e.preventDefault();\n e.stopPropagation();\n element.dispatchEvent(new CustomEvent('draggable:start', { bubbles: true }));\n\n const startX = element.offsetLeft;\n const startY = element.offsetTop;\n const xoff = e.clientX - startX;\n const yoff = e.clientY - startY;\n\n function onMove(ev: PointerEvent) {\n element.style.left = `${ev.clientX - xoff}px`;\n element.style.top = `${ev.clientY - yoff}px`;\n element.dispatchEvent(new CustomEvent('draggable:move', { bubbles: true }));\n }\n\n function onUp() {\n document.removeEventListener('pointermove', onMove);\n document.removeEventListener('pointerup', onUp);\n element.dispatchEvent(new CustomEvent('draggable:end', { bubbles: true }));\n }\n\n document.addEventListener('pointermove', onMove);\n document.addEventListener('pointerup', onUp);\n });\n}\n\n/**\n * Register the Draggable behavior with LokaScript.\n * Uses imperative installer via synthetic behavior node.\n */\nexport async function registerDraggable(hyperfixi?: LokaScriptInstance): Promise<void> {\n const hf = hyperfixi || resolveRuntime();\n\n if (!hf) {\n throw new Error(\n 'LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors.'\n );\n }\n\n // Register via execute() with a synthetic behavior node containing the imperative installer.\n // The runtime detects imperativeInstaller and stores it directly in the behaviorRegistry.\n const syntheticNode = {\n type: 'behavior',\n name: 'Draggable',\n parameters: ['dragHandle'],\n eventHandlers: [],\n imperativeInstaller: installDraggable,\n };\n const ctx = hf.createContext ? hf.createContext() : { locals: new Map(), globals: new Map() };\n await hf.execute(syntheticNode, ctx);\n}\n\n// Auto-register when loaded as a script tag\nif (resolveRuntime()) {\n registerDraggable().catch(console.error);\n}\n\nexport default {\n source: draggableSchema.source,\n metadata: draggableSchema,\n register: registerDraggable,\n};\n","import type { BehaviorSchema } from './types';\n\n/**\n * Draggable Behavior Schema\n *\n * Makes elements draggable with pointer events.\n * Supports custom drag handles and lifecycle events.\n */\nexport const draggableSchema: BehaviorSchema = {\n name: 'Draggable',\n category: 'ui',\n tier: 'core',\n version: '1.0.0',\n description: 'Makes elements draggable with pointer events',\n parameters: [\n {\n name: 'dragHandle',\n type: 'selector',\n optional: true,\n default: 'me',\n description: 'CSS selector for the drag handle element',\n },\n ],\n events: [\n { name: 'draggable:start', description: 'Fired when drag begins' },\n { name: 'draggable:move', description: 'Fired during each movement' },\n { name: 'draggable:end', description: 'Fired when drag completes' },\n ],\n requirements: ['position: absolute or position: fixed on the element'],\n source: `\nbehavior Draggable(dragHandle)\n init\n if no dragHandle set dragHandle to me\n end\n on pointerdown(clientX, clientY) from dragHandle\n halt the event\n trigger draggable:start\n measure x\n set startX to it\n measure y\n set startY to it\n set xoff to clientX - startX\n set yoff to clientY - startY\n repeat until event pointerup from document\n wait for pointermove(clientX, clientY) or\n pointerup(clientX, clientY) from document\n add { left: \\${clientX - xoff}px; top: \\${clientY - yoff}px; }\n trigger draggable:move\n end\n trigger draggable:end\n end\nend\n`.trim(),\n};\n","/**\n * Behavior Schema Types\n *\n * Defines the structure for behavior metadata used for:\n * - Code generation (TypeScript types, documentation)\n * - Runtime categorization and lazy loading\n * - Tooling and IDE integration\n */\n\n/**\n * Behavior categories for organization.\n * - ui: Visual interaction behaviors (drag, resize, sort)\n * - data: Data manipulation behaviors (remove, transform)\n * - animation: Animation and transition behaviors\n * - form: Form-related behaviors (validation, toggle states)\n * - layout: Layout behaviors (sticky, scrollspy)\n */\nexport type BehaviorCategory = 'ui' | 'data' | 'animation' | 'form' | 'layout';\n\n/**\n * Loading tiers for lazy loading optimization.\n * - core: Always loaded (essential behaviors)\n * - common: High usage (loaded for typical apps)\n * - optional: Low usage (loaded on demand)\n */\nexport type BehaviorTier = 'core' | 'common' | 'optional';\n\n/**\n * Schema for a behavior parameter.\n */\nexport interface ParameterSchema {\n name: string;\n type: 'string' | 'number' | 'boolean' | 'selector' | 'element';\n optional?: boolean;\n default?: string | number | boolean;\n /** Allowed values for constrained parameters */\n enum?: string[];\n description: string;\n}\n\n/**\n * Schema for a behavior event.\n */\nexport interface EventSchema {\n name: string;\n description: string;\n}\n\n/**\n * Complete schema for a behavior.\n * This is the source of truth for all behavior metadata.\n */\nexport interface BehaviorSchema {\n /** Behavior name (PascalCase) */\n name: string;\n /** Category for organization */\n category: BehaviorCategory;\n /** Loading tier for lazy loading */\n tier: BehaviorTier;\n /** Semantic version */\n version: string;\n /** Human-readable description */\n description: string;\n /** Parameter definitions */\n parameters: ParameterSchema[];\n /** Event definitions */\n events: EventSchema[];\n /** The hyperscript behavior source code */\n source: string;\n /** Optional requirements or notes */\n requirements?: string[];\n}\n\n/**\n * Runtime behavior module interface.\n * This is what gets registered with the hyperfixi runtime.\n */\nexport interface BehaviorModule {\n source: string;\n metadata: BehaviorSchema;\n register: (hyperfixi?: LokaScriptInstance) => Promise<void>;\n}\n\n/**\n * Minimal LokaScript instance interface for behavior registration.\n */\nexport interface LokaScriptInstance {\n compileSync: (\n code: string,\n options?: { traditional?: boolean; language?: string }\n ) => {\n ok: boolean;\n ast?: unknown;\n errors?: Array<{ message: string; line?: number; column?: number }>;\n };\n execute: (ast: unknown, ctx: unknown) => Promise<unknown>;\n createContext?: () => { locals: Map<string, unknown>; globals: Map<string, unknown> };\n}\n\n/**\n * Typed window interface for behavior auto-registration.\n * Avoids `(window as any)` casts throughout the codebase.\n * Checks both `window.lokascript` and `window.hyperfixi` for the runtime instance.\n */\nexport interface LokaScriptWindow {\n lokascript?: LokaScriptInstance;\n hyperfixi?: LokaScriptInstance;\n __hyperfixi_behaviors_ready?: Promise<void> | undefined;\n}\n\n/**\n * Resolve the LokaScript runtime from window globals.\n * Checks both `window.lokascript` and `window.hyperfixi`.\n */\nexport function resolveRuntime(): LokaScriptInstance | null {\n if (typeof window === 'undefined') return null;\n const win = window as unknown as LokaScriptWindow;\n return win.lokascript || win.hyperfixi || null;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/behaviors/draggable.ts","../../src/schemas/draggable.schema.ts","../../src/schemas/types.ts"],"sourcesContent":["/**\n * Draggable Behavior\n *\n * Makes elements draggable with pointer events. Compiled from its hyperscript\n * `source` (the single source of truth shared with the CDN resolver bundle and\n * patterns-reference) — no imperative installer. The source uses\n * `repeat until event pointerup` + `wait for pointermove or pointerup` to run the\n * drag loop, `measure` for the start offset, and `add { left: ${…}px }` to move.\n *\n * @example\n * ```html\n * <!-- Basic usage -->\n * <div _=\"install Draggable\">Drag me!</div>\n *\n * <!-- With custom drag handle -->\n * <div _=\"install Draggable(dragHandle: .titlebar)\">\n * <div class=\"titlebar\">Drag here</div>\n * <div class=\"content\">Content</div>\n * </div>\n * ```\n */\n\nimport { draggableSchema } from '../schemas/draggable.schema';\nimport type { LokaScriptInstance } from '../schemas/types';\nimport { resolveRuntime } from '../schemas/types';\n\n// Re-export schema-derived values for backwards compatibility\nexport const draggableSource = draggableSchema.source;\nexport const draggableMetadata = draggableSchema;\n\n/**\n * Register the Draggable behavior with LokaScript by compiling its hyperscript\n * source and executing the resulting behavior definition.\n */\nexport async function registerDraggable(hyperfixi?: LokaScriptInstance): Promise<void> {\n const hf = hyperfixi || resolveRuntime();\n\n if (!hf) {\n throw new Error(\n 'LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors.'\n );\n }\n\n const result = hf.compileSync(draggableSchema.source, { traditional: true });\n\n if (!result.ok) {\n throw new Error(`Failed to compile Draggable behavior: ${JSON.stringify(result.errors)}`);\n }\n\n const ctx = hf.createContext ? hf.createContext() : { locals: new Map(), globals: new Map() };\n await hf.execute(result.ast, ctx);\n}\n\n// Auto-register when loaded as a script tag\nif (resolveRuntime()) {\n registerDraggable().catch(console.error);\n}\n\nexport default {\n source: draggableSchema.source,\n metadata: draggableSchema,\n register: registerDraggable,\n};\n","import type { BehaviorSchema } from './types';\n\n/**\n * Draggable Behavior Schema\n *\n * Makes elements draggable with pointer events.\n * Supports custom drag handles and lifecycle events.\n */\nexport const draggableSchema: BehaviorSchema = {\n name: 'Draggable',\n category: 'ui',\n tier: 'core',\n version: '1.0.0',\n description:\n 'Makes elements draggable with pointer events (EXPERIMENTAL — stateful async component, beyond the inline-scripting boundary; not part of the curated set)',\n parameters: [\n {\n name: 'dragHandle',\n type: 'selector',\n optional: true,\n default: 'me',\n description: 'CSS selector for the drag handle element',\n },\n ],\n events: [\n { name: 'draggable:start', description: 'Fired when drag begins' },\n { name: 'draggable:move', description: 'Fired during each movement' },\n { name: 'draggable:end', description: 'Fired when drag completes' },\n ],\n requirements: ['position: absolute or position: fixed on the element'],\n source: `\nbehavior Draggable(dragHandle)\n init\n if no dragHandle set dragHandle to me\n end\n on pointerdown(clientX, clientY) from dragHandle\n halt the event\n trigger draggable:start\n measure x\n set startX to it\n measure y\n set startY to it\n set xoff to clientX - startX\n set yoff to clientY - startY\n repeat until event pointerup from document\n wait for pointermove(clientX, clientY) or\n pointerup(clientX, clientY) from document\n add { left: \\${clientX - xoff}px; top: \\${clientY - yoff}px; }\n trigger draggable:move\n end\n trigger draggable:end\n end\nend\n`.trim(),\n};\n","/**\n * Behavior Schema Types\n *\n * Defines the structure for behavior metadata used for:\n * - Code generation (TypeScript types, documentation)\n * - Runtime categorization and lazy loading\n * - Tooling and IDE integration\n */\n\n/**\n * Behavior categories for organization.\n * - ui: Visual interaction behaviors (drag, resize, sort)\n * - data: Data manipulation behaviors (remove, transform)\n * - animation: Animation and transition behaviors\n * - form: Form-related behaviors (validation, toggle states)\n * - layout: Layout behaviors (sticky, scrollspy)\n */\nexport type BehaviorCategory = 'ui' | 'data' | 'animation' | 'form' | 'layout';\n\n/**\n * Loading tiers for lazy loading optimization.\n * - core: Always loaded (essential behaviors)\n * - common: High usage (loaded for typical apps)\n * - optional: Low usage (loaded on demand)\n */\nexport type BehaviorTier = 'core' | 'common' | 'optional';\n\n/**\n * Schema for a behavior parameter.\n */\nexport interface ParameterSchema {\n name: string;\n type: 'string' | 'number' | 'boolean' | 'selector' | 'element';\n optional?: boolean;\n default?: string | number | boolean;\n /** Allowed values for constrained parameters */\n enum?: string[];\n description: string;\n}\n\n/**\n * Schema for a behavior event.\n */\nexport interface EventSchema {\n name: string;\n description: string;\n}\n\n/**\n * Complete schema for a behavior.\n * This is the source of truth for all behavior metadata.\n */\nexport interface BehaviorSchema {\n /** Behavior name (PascalCase) */\n name: string;\n /** Category for organization */\n category: BehaviorCategory;\n /** Loading tier for lazy loading */\n tier: BehaviorTier;\n /** Semantic version */\n version: string;\n /** Human-readable description */\n description: string;\n /** Parameter definitions */\n parameters: ParameterSchema[];\n /** Event definitions */\n events: EventSchema[];\n /** The hyperscript behavior source code */\n source: string;\n /** Optional requirements or notes */\n requirements?: string[];\n}\n\n/**\n * Runtime behavior module interface.\n * This is what gets registered with the hyperfixi runtime.\n */\nexport interface BehaviorModule {\n source: string;\n metadata: BehaviorSchema;\n register: (hyperfixi?: LokaScriptInstance) => Promise<void>;\n}\n\n/**\n * Minimal LokaScript instance interface for behavior registration.\n */\nexport interface LokaScriptInstance {\n compileSync: (\n code: string,\n options?: { traditional?: boolean; language?: string }\n ) => {\n ok: boolean;\n ast?: unknown;\n errors?: Array<{ message: string; line?: number; column?: number }>;\n };\n execute: (ast: unknown, ctx: unknown) => Promise<unknown>;\n createContext?: () => { locals: Map<string, unknown>; globals: Map<string, unknown> };\n}\n\n/**\n * Typed window interface for behavior auto-registration.\n * Avoids `(window as any)` casts throughout the codebase.\n * Checks both `window.lokascript` and `window.hyperfixi` for the runtime instance.\n */\nexport interface LokaScriptWindow {\n lokascript?: LokaScriptInstance;\n hyperfixi?: LokaScriptInstance;\n __hyperfixi_behaviors_ready?: Promise<void> | undefined;\n}\n\n/**\n * Resolve the LokaScript runtime from window globals.\n * Checks both `window.lokascript` and `window.hyperfixi`.\n */\nexport function resolveRuntime(): LokaScriptInstance | null {\n if (typeof window === 'undefined') return null;\n const win = window as unknown as LokaScriptWindow;\n return win.lokascript || win.hyperfixi || null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACQO,IAAM,kBAAkC;AAAA,EAC7C,MAAM;AAAA,EACN,UAAU;AAAA,EACV,MAAM;AAAA,EACN,SAAS;AAAA,EACT,aACE;AAAA,EACF,YAAY;AAAA,IACV;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN,EAAE,MAAM,mBAAmB,aAAa,yBAAyB;AAAA,IACjE,EAAE,MAAM,kBAAkB,aAAa,6BAA6B;AAAA,IACpE,EAAE,MAAM,iBAAiB,aAAa,4BAA4B;AAAA,EACpE;AAAA,EACA,cAAc,CAAC,sDAAsD;AAAA,EACrE,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBR,KAAK;AACP;;;AC4DO,SAAS,iBAA4C;AAC1D,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,QAAM,MAAM;AACZ,SAAO,IAAI,cAAc,IAAI,aAAa;AAC5C;;;AF3FO,IAAM,kBAAkB,gBAAgB;AACxC,IAAM,oBAAoB;AAMjC,eAAsB,kBAAkB,WAA+C;AACrF,QAAM,KAAK,aAAa,eAAe;AAEvC,MAAI,CAAC,IAAI;AACP,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,GAAG,YAAY,gBAAgB,QAAQ,EAAE,aAAa,KAAK,CAAC;AAE3E,MAAI,CAAC,OAAO,IAAI;AACd,UAAM,IAAI,MAAM,yCAAyC,KAAK,UAAU,OAAO,MAAM,CAAC,EAAE;AAAA,EAC1F;AAEA,QAAM,MAAM,GAAG,gBAAgB,GAAG,cAAc,IAAI,EAAE,QAAQ,oBAAI,IAAI,GAAG,SAAS,oBAAI,IAAI,EAAE;AAC5F,QAAM,GAAG,QAAQ,OAAO,KAAK,GAAG;AAClC;AAGA,IAAI,eAAe,GAAG;AACpB,oBAAkB,EAAE,MAAM,QAAQ,KAAK;AACzC;AAEA,IAAO,oBAAQ;AAAA,EACb,QAAQ,gBAAgB;AAAA,EACxB,UAAU;AAAA,EACV,UAAU;AACZ;","names":[]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as BehaviorSchema, L as LokaScriptInstance } from '../types-DCCtVQS5.cjs';
|
|
2
2
|
|
|
3
3
|
declare const draggableSource: string;
|
|
4
4
|
declare const draggableMetadata: BehaviorSchema;
|
|
5
5
|
/**
|
|
6
|
-
* Register the Draggable behavior with LokaScript
|
|
7
|
-
*
|
|
6
|
+
* Register the Draggable behavior with LokaScript by compiling its hyperscript
|
|
7
|
+
* source and executing the resulting behavior definition.
|
|
8
8
|
*/
|
|
9
9
|
declare function registerDraggable(hyperfixi?: LokaScriptInstance): Promise<void>;
|
|
10
10
|
declare const _default: {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as BehaviorSchema, L as LokaScriptInstance } from '../types-DCCtVQS5.js';
|
|
2
2
|
|
|
3
3
|
declare const draggableSource: string;
|
|
4
4
|
declare const draggableMetadata: BehaviorSchema;
|
|
5
5
|
/**
|
|
6
|
-
* Register the Draggable behavior with LokaScript
|
|
7
|
-
*
|
|
6
|
+
* Register the Draggable behavior with LokaScript by compiling its hyperscript
|
|
7
|
+
* source and executing the resulting behavior definition.
|
|
8
8
|
*/
|
|
9
9
|
declare function registerDraggable(hyperfixi?: LokaScriptInstance): Promise<void>;
|
|
10
10
|
declare const _default: {
|
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
draggableSource,
|
|
4
4
|
draggable_default,
|
|
5
5
|
registerDraggable
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import "../chunk-
|
|
6
|
+
} from "../chunk-ORBJ7MRW.js";
|
|
7
|
+
import "../chunk-FBQ3X3UY.js";
|
|
8
8
|
import "../chunk-6TJXDCAQ.js";
|
|
9
9
|
export {
|
|
10
10
|
draggable_default as default,
|
|
@@ -125,79 +125,6 @@ function resolveRuntime() {
|
|
|
125
125
|
// src/behaviors/focustrap.ts
|
|
126
126
|
var focusTrapSource = focusTrapSchema.source;
|
|
127
127
|
var focusTrapMetadata = focusTrapSchema;
|
|
128
|
-
var FOCUSABLE_SELECTOR = [
|
|
129
|
-
"a[href]",
|
|
130
|
-
"button:not(:disabled)",
|
|
131
|
-
"input:not(:disabled)",
|
|
132
|
-
"select:not(:disabled)",
|
|
133
|
-
"textarea:not(:disabled)",
|
|
134
|
-
'[tabindex]:not([tabindex="-1"])'
|
|
135
|
-
].join(", ");
|
|
136
|
-
function resolveElement(container, param) {
|
|
137
|
-
if (!param) return null;
|
|
138
|
-
if (param instanceof HTMLElement) return param;
|
|
139
|
-
if (typeof param === "string") {
|
|
140
|
-
return container.querySelector(param) || document.querySelector(param) || null;
|
|
141
|
-
}
|
|
142
|
-
return null;
|
|
143
|
-
}
|
|
144
|
-
function installFocusTrap(element, params) {
|
|
145
|
-
const returnFocus = params.returnFocus !== false;
|
|
146
|
-
let isActive = false;
|
|
147
|
-
let previouslyFocused = null;
|
|
148
|
-
function getFocusableElements() {
|
|
149
|
-
return Array.from(element.querySelectorAll(FOCUSABLE_SELECTOR));
|
|
150
|
-
}
|
|
151
|
-
function onKeyDown(e) {
|
|
152
|
-
if (!isActive || e.key !== "Tab") return;
|
|
153
|
-
const focusable = getFocusableElements();
|
|
154
|
-
if (focusable.length === 0) {
|
|
155
|
-
e.preventDefault();
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
e.preventDefault();
|
|
159
|
-
const currentIndex = focusable.indexOf(document.activeElement);
|
|
160
|
-
if (e.shiftKey) {
|
|
161
|
-
const prevIndex = currentIndex <= 0 ? focusable.length - 1 : currentIndex - 1;
|
|
162
|
-
focusable[prevIndex].focus();
|
|
163
|
-
} else {
|
|
164
|
-
const nextIndex = currentIndex >= focusable.length - 1 ? 0 : currentIndex + 1;
|
|
165
|
-
focusable[nextIndex].focus();
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
function activate() {
|
|
169
|
-
if (isActive) return;
|
|
170
|
-
isActive = true;
|
|
171
|
-
previouslyFocused = document.activeElement;
|
|
172
|
-
element.setAttribute("aria-modal", "true");
|
|
173
|
-
const initialEl = resolveElement(element, params.initialFocus);
|
|
174
|
-
if (initialEl) {
|
|
175
|
-
initialEl.focus();
|
|
176
|
-
} else {
|
|
177
|
-
const focusable = getFocusableElements();
|
|
178
|
-
if (focusable.length > 0) {
|
|
179
|
-
focusable[0].focus();
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
element.dispatchEvent(new CustomEvent("focustrap:activated", { bubbles: true }));
|
|
183
|
-
}
|
|
184
|
-
function deactivate() {
|
|
185
|
-
if (!isActive) return;
|
|
186
|
-
isActive = false;
|
|
187
|
-
element.removeAttribute("aria-modal");
|
|
188
|
-
if (returnFocus && previouslyFocused instanceof HTMLElement) {
|
|
189
|
-
previouslyFocused.focus();
|
|
190
|
-
}
|
|
191
|
-
previouslyFocused = null;
|
|
192
|
-
element.dispatchEvent(new CustomEvent("focustrap:deactivated", { bubbles: true }));
|
|
193
|
-
}
|
|
194
|
-
element.addEventListener("keydown", onKeyDown);
|
|
195
|
-
element.addEventListener("focustrap:activate", () => activate());
|
|
196
|
-
element.addEventListener("focustrap:deactivate", () => deactivate());
|
|
197
|
-
if (params.active !== false) {
|
|
198
|
-
activate();
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
128
|
async function registerFocusTrap(hyperfixi) {
|
|
202
129
|
const hf = hyperfixi || resolveRuntime();
|
|
203
130
|
if (!hf) {
|
|
@@ -205,15 +132,12 @@ async function registerFocusTrap(hyperfixi) {
|
|
|
205
132
|
"LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
|
|
206
133
|
);
|
|
207
134
|
}
|
|
208
|
-
const
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
eventHandlers: [],
|
|
213
|
-
imperativeInstaller: installFocusTrap
|
|
214
|
-
};
|
|
135
|
+
const result = hf.compileSync(focusTrapSchema.source, { traditional: true });
|
|
136
|
+
if (!result.ok) {
|
|
137
|
+
throw new Error(`Failed to compile FocusTrap behavior: ${JSON.stringify(result.errors)}`);
|
|
138
|
+
}
|
|
215
139
|
const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
|
|
216
|
-
await hf.execute(
|
|
140
|
+
await hf.execute(result.ast, ctx);
|
|
217
141
|
}
|
|
218
142
|
if (resolveRuntime()) {
|
|
219
143
|
registerFocusTrap().catch(console.error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/behaviors/focustrap.ts","../../src/schemas/focustrap.schema.ts","../../src/schemas/types.ts"],"sourcesContent":["/**\n * FocusTrap Behavior — Imperative Implementation\n *\n * Confines Tab navigation inside an element, manages aria-modal,\n * and restores focus on deactivation.\n */\n\nimport { focusTrapSchema } from '../schemas/focustrap.schema';\nimport type { LokaScriptInstance } from '../schemas/types';\nimport { resolveRuntime } from '../schemas/types';\n\n// Re-export schema-derived values\nexport const focusTrapSource = focusTrapSchema.source;\nexport const focusTrapMetadata = focusTrapSchema;\n\nconst FOCUSABLE_SELECTOR = [\n 'a[href]',\n 'button:not(:disabled)',\n 'input:not(:disabled)',\n 'select:not(:disabled)',\n 'textarea:not(:disabled)',\n '[tabindex]:not([tabindex=\"-1\"])',\n].join(', ');\n\n/**\n * Resolve a selector parameter to an HTMLElement within the container.\n */\nfunction resolveElement(container: HTMLElement, param: unknown): HTMLElement | null {\n if (!param) return null;\n if (param instanceof HTMLElement) return param;\n if (typeof param === 'string') {\n return (\n (container.querySelector(param) as HTMLElement) ||\n (document.querySelector(param) as HTMLElement) ||\n null\n );\n }\n return null;\n}\n\n/**\n * Imperative installer for FocusTrap behavior.\n */\nfunction installFocusTrap(element: HTMLElement, params: Record<string, any>): void {\n const returnFocus = params.returnFocus !== false;\n let isActive = false;\n let previouslyFocused: Element | null = null;\n\n function getFocusableElements(): HTMLElement[] {\n return Array.from(element.querySelectorAll<HTMLElement>(FOCUSABLE_SELECTOR));\n }\n\n function onKeyDown(e: KeyboardEvent) {\n if (!isActive || e.key !== 'Tab') return;\n\n const focusable = getFocusableElements();\n if (focusable.length === 0) {\n e.preventDefault();\n return;\n }\n\n // Always prevent default Tab and manually manage focus.\n // This ensures focus never escapes to elements outside the trap,\n // even when the modal is embedded in a page with other focusable elements.\n e.preventDefault();\n\n const currentIndex = focusable.indexOf(document.activeElement as HTMLElement);\n\n if (e.shiftKey) {\n const prevIndex = currentIndex <= 0 ? focusable.length - 1 : currentIndex - 1;\n focusable[prevIndex].focus();\n } else {\n const nextIndex = currentIndex >= focusable.length - 1 ? 0 : currentIndex + 1;\n focusable[nextIndex].focus();\n }\n }\n\n function activate() {\n if (isActive) return;\n isActive = true;\n previouslyFocused = document.activeElement;\n\n element.setAttribute('aria-modal', 'true');\n\n // Focus initialFocus element or first focusable\n const initialEl = resolveElement(element, params.initialFocus);\n if (initialEl) {\n initialEl.focus();\n } else {\n const focusable = getFocusableElements();\n if (focusable.length > 0) {\n focusable[0].focus();\n }\n }\n\n element.dispatchEvent(new CustomEvent('focustrap:activated', { bubbles: true }));\n }\n\n function deactivate() {\n if (!isActive) return;\n isActive = false;\n\n element.removeAttribute('aria-modal');\n\n if (returnFocus && previouslyFocused instanceof HTMLElement) {\n previouslyFocused.focus();\n }\n previouslyFocused = null;\n\n element.dispatchEvent(new CustomEvent('focustrap:deactivated', { bubbles: true }));\n }\n\n // Keydown handler for Tab trapping\n element.addEventListener('keydown', onKeyDown);\n\n // Programmatic activation/deactivation via custom events\n element.addEventListener('focustrap:activate', () => activate());\n element.addEventListener('focustrap:deactivate', () => deactivate());\n\n // Activate immediately if requested\n if (params.active !== false) {\n activate();\n }\n}\n\n/**\n * Register the FocusTrap behavior with LokaScript.\n */\nexport async function registerFocusTrap(hyperfixi?: LokaScriptInstance): Promise<void> {\n const hf = hyperfixi || resolveRuntime();\n\n if (!hf) {\n throw new Error(\n 'LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors.'\n );\n }\n\n const syntheticNode = {\n type: 'behavior',\n name: 'FocusTrap',\n parameters: ['active', 'initialFocus', 'returnFocus'],\n eventHandlers: [],\n imperativeInstaller: installFocusTrap,\n };\n const ctx = hf.createContext ? hf.createContext() : { locals: new Map(), globals: new Map() };\n await hf.execute(syntheticNode, ctx);\n}\n\n// Auto-register when loaded as a script tag\nif (resolveRuntime()) {\n registerFocusTrap().catch(console.error);\n}\n\nexport default {\n source: focusTrapSchema.source,\n metadata: focusTrapSchema,\n register: registerFocusTrap,\n};\n","import type { BehaviorSchema } from './types';\n\n/**\n * FocusTrap Behavior Schema\n *\n * Confines Tab navigation inside an element and restores focus on release.\n * Manages aria-modal for accessibility compliance.\n */\nexport const focusTrapSchema: BehaviorSchema = {\n name: 'FocusTrap',\n category: 'ui',\n tier: 'core',\n version: '1.0.0',\n description: 'Confines Tab navigation inside an element with ARIA support',\n parameters: [\n {\n name: 'active',\n type: 'boolean',\n optional: true,\n default: true,\n description: 'Whether the trap is active on install',\n },\n {\n name: 'initialFocus',\n type: 'selector',\n optional: true,\n description: 'Element to focus when the trap activates',\n },\n {\n name: 'returnFocus',\n type: 'boolean',\n optional: true,\n default: true,\n description: 'Restore focus to the previously focused element on deactivation',\n },\n ],\n events: [\n { name: 'focustrap:activated', description: 'Fired when the trap is activated' },\n { name: 'focustrap:deactivated', description: 'Fired when the trap is deactivated' },\n ],\n requirements: [\n 'Sets aria-modal=\"true\" on the element when active',\n 'Listens for focustrap:activate and focustrap:deactivate custom events for programmatic control',\n ],\n source: `\nbehavior FocusTrap(active, initialFocus, returnFocus)\n init\n if active is undefined\n set active to true\n end\n if returnFocus is undefined\n set returnFocus to true\n end\n js(me, active, initialFocus, returnFocus)\n var FOCUSABLE = 'a[href],button:not(:disabled),input:not(:disabled),select:not(:disabled),textarea:not(:disabled),[tabindex]:not([tabindex=\"-1\"])';\n var isActive = false;\n var previouslyFocused = null;\n function getFocusable() { return Array.from(me.querySelectorAll(FOCUSABLE)); }\n function activate() {\n if (isActive) return;\n isActive = true;\n previouslyFocused = document.activeElement;\n me.setAttribute('aria-modal', 'true');\n var initEl = initialFocus ? (typeof initialFocus === 'string' ? me.querySelector(initialFocus) : initialFocus) : null;\n if (initEl) { initEl.focus(); } else { var f = getFocusable(); if (f.length) f[0].focus(); }\n me.dispatchEvent(new CustomEvent('focustrap:activated', { bubbles: true }));\n }\n function deactivate() {\n if (!isActive) return;\n isActive = false;\n me.removeAttribute('aria-modal');\n if (returnFocus && previouslyFocused instanceof HTMLElement) previouslyFocused.focus();\n previouslyFocused = null;\n me.dispatchEvent(new CustomEvent('focustrap:deactivated', { bubbles: true }));\n }\n me.addEventListener('keydown', function(e) {\n if (!isActive || e.key !== 'Tab') return;\n var focusable = getFocusable();\n if (focusable.length === 0) { e.preventDefault(); return; }\n e.preventDefault();\n var idx = focusable.indexOf(document.activeElement);\n if (e.shiftKey) {\n focusable[idx <= 0 ? focusable.length - 1 : idx - 1].focus();\n } else {\n focusable[idx >= focusable.length - 1 ? 0 : idx + 1].focus();\n }\n });\n me.addEventListener('focustrap:activate', function() { activate(); });\n me.addEventListener('focustrap:deactivate', function() { deactivate(); });\n if (active) activate();\n end\n end\nend`.trim(),\n};\n","/**\n * Behavior Schema Types\n *\n * Defines the structure for behavior metadata used for:\n * - Code generation (TypeScript types, documentation)\n * - Runtime categorization and lazy loading\n * - Tooling and IDE integration\n */\n\n/**\n * Behavior categories for organization.\n * - ui: Visual interaction behaviors (drag, resize, sort)\n * - data: Data manipulation behaviors (remove, transform)\n * - animation: Animation and transition behaviors\n * - form: Form-related behaviors (validation, toggle states)\n * - layout: Layout behaviors (sticky, scrollspy)\n */\nexport type BehaviorCategory = 'ui' | 'data' | 'animation' | 'form' | 'layout';\n\n/**\n * Loading tiers for lazy loading optimization.\n * - core: Always loaded (essential behaviors)\n * - common: High usage (loaded for typical apps)\n * - optional: Low usage (loaded on demand)\n */\nexport type BehaviorTier = 'core' | 'common' | 'optional';\n\n/**\n * Schema for a behavior parameter.\n */\nexport interface ParameterSchema {\n name: string;\n type: 'string' | 'number' | 'boolean' | 'selector' | 'element';\n optional?: boolean;\n default?: string | number | boolean;\n /** Allowed values for constrained parameters */\n enum?: string[];\n description: string;\n}\n\n/**\n * Schema for a behavior event.\n */\nexport interface EventSchema {\n name: string;\n description: string;\n}\n\n/**\n * Complete schema for a behavior.\n * This is the source of truth for all behavior metadata.\n */\nexport interface BehaviorSchema {\n /** Behavior name (PascalCase) */\n name: string;\n /** Category for organization */\n category: BehaviorCategory;\n /** Loading tier for lazy loading */\n tier: BehaviorTier;\n /** Semantic version */\n version: string;\n /** Human-readable description */\n description: string;\n /** Parameter definitions */\n parameters: ParameterSchema[];\n /** Event definitions */\n events: EventSchema[];\n /** The hyperscript behavior source code */\n source: string;\n /** Optional requirements or notes */\n requirements?: string[];\n}\n\n/**\n * Runtime behavior module interface.\n * This is what gets registered with the hyperfixi runtime.\n */\nexport interface BehaviorModule {\n source: string;\n metadata: BehaviorSchema;\n register: (hyperfixi?: LokaScriptInstance) => Promise<void>;\n}\n\n/**\n * Minimal LokaScript instance interface for behavior registration.\n */\nexport interface LokaScriptInstance {\n compileSync: (\n code: string,\n options?: { traditional?: boolean; language?: string }\n ) => {\n ok: boolean;\n ast?: unknown;\n errors?: Array<{ message: string; line?: number; column?: number }>;\n };\n execute: (ast: unknown, ctx: unknown) => Promise<unknown>;\n createContext?: () => { locals: Map<string, unknown>; globals: Map<string, unknown> };\n}\n\n/**\n * Typed window interface for behavior auto-registration.\n * Avoids `(window as any)` casts throughout the codebase.\n * Checks both `window.lokascript` and `window.hyperfixi` for the runtime instance.\n */\nexport interface LokaScriptWindow {\n lokascript?: LokaScriptInstance;\n hyperfixi?: LokaScriptInstance;\n __hyperfixi_behaviors_ready?: Promise<void> | undefined;\n}\n\n/**\n * Resolve the LokaScript runtime from window globals.\n * Checks both `window.lokascript` and `window.hyperfixi`.\n */\nexport function resolveRuntime(): LokaScriptInstance | null {\n if (typeof window === 'undefined') return null;\n const win = window as unknown as LokaScriptWindow;\n return win.lokascript || win.hyperfixi || null;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/behaviors/focustrap.ts","../../src/schemas/focustrap.schema.ts","../../src/schemas/types.ts"],"sourcesContent":["/**\n * FocusTrap Behavior\n *\n * Confines Tab navigation inside an element, manages aria-modal,\n * and restores focus on deactivation. The Tab-trapping / focus-model logic\n * lives in the schema's hyperscript `source` (an `init`-block `js()` body).\n *\n * Compiled from its hyperscript `source` — the single source of truth shared with\n * the CDN resolver bundle and patterns-reference. This collapses FocusTrap onto\n * the one runtime path (no more imperative-installer fork between CDN and npm);\n * see docs-internal/BEHAVIORS_CONSOLIDATION_PLAN.md §3d.\n */\n\nimport { focusTrapSchema } from '../schemas/focustrap.schema';\nimport type { LokaScriptInstance } from '../schemas/types';\nimport { resolveRuntime } from '../schemas/types';\n\n// Re-export schema-derived values\nexport const focusTrapSource = focusTrapSchema.source;\nexport const focusTrapMetadata = focusTrapSchema;\n\n/**\n * Register the FocusTrap behavior with LokaScript by compiling its\n * hyperscript source and executing the resulting behavior definition.\n */\nexport async function registerFocusTrap(hyperfixi?: LokaScriptInstance): Promise<void> {\n const hf = hyperfixi || resolveRuntime();\n\n if (!hf) {\n throw new Error(\n 'LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors.'\n );\n }\n\n const result = hf.compileSync(focusTrapSchema.source, { traditional: true });\n\n if (!result.ok) {\n throw new Error(`Failed to compile FocusTrap behavior: ${JSON.stringify(result.errors)}`);\n }\n\n const ctx = hf.createContext ? hf.createContext() : { locals: new Map(), globals: new Map() };\n await hf.execute(result.ast, ctx);\n}\n\n// Auto-register when loaded as a script tag\nif (resolveRuntime()) {\n registerFocusTrap().catch(console.error);\n}\n\nexport default {\n source: focusTrapSchema.source,\n metadata: focusTrapSchema,\n register: registerFocusTrap,\n};\n","import type { BehaviorSchema } from './types';\n\n/**\n * FocusTrap Behavior Schema\n *\n * Confines Tab navigation inside an element and restores focus on release.\n * Manages aria-modal for accessibility compliance.\n */\nexport const focusTrapSchema: BehaviorSchema = {\n name: 'FocusTrap',\n category: 'ui',\n tier: 'core',\n version: '1.0.0',\n description: 'Confines Tab navigation inside an element with ARIA support',\n parameters: [\n {\n name: 'active',\n type: 'boolean',\n optional: true,\n default: true,\n description: 'Whether the trap is active on install',\n },\n {\n name: 'initialFocus',\n type: 'selector',\n optional: true,\n description: 'Element to focus when the trap activates',\n },\n {\n name: 'returnFocus',\n type: 'boolean',\n optional: true,\n default: true,\n description: 'Restore focus to the previously focused element on deactivation',\n },\n ],\n events: [\n { name: 'focustrap:activated', description: 'Fired when the trap is activated' },\n { name: 'focustrap:deactivated', description: 'Fired when the trap is deactivated' },\n ],\n requirements: [\n 'Sets aria-modal=\"true\" on the element when active',\n 'Listens for focustrap:activate and focustrap:deactivate custom events for programmatic control',\n ],\n source: `\nbehavior FocusTrap(active, initialFocus, returnFocus)\n init\n if active is undefined\n set active to true\n end\n if returnFocus is undefined\n set returnFocus to true\n end\n js(me, active, initialFocus, returnFocus)\n var FOCUSABLE = 'a[href],button:not(:disabled),input:not(:disabled),select:not(:disabled),textarea:not(:disabled),[tabindex]:not([tabindex=\"-1\"])';\n var isActive = false;\n var previouslyFocused = null;\n function getFocusable() { return Array.from(me.querySelectorAll(FOCUSABLE)); }\n function activate() {\n if (isActive) return;\n isActive = true;\n previouslyFocused = document.activeElement;\n me.setAttribute('aria-modal', 'true');\n var initEl = initialFocus ? (typeof initialFocus === 'string' ? me.querySelector(initialFocus) : initialFocus) : null;\n if (initEl) { initEl.focus(); } else { var f = getFocusable(); if (f.length) f[0].focus(); }\n me.dispatchEvent(new CustomEvent('focustrap:activated', { bubbles: true }));\n }\n function deactivate() {\n if (!isActive) return;\n isActive = false;\n me.removeAttribute('aria-modal');\n if (returnFocus && previouslyFocused instanceof HTMLElement) previouslyFocused.focus();\n previouslyFocused = null;\n me.dispatchEvent(new CustomEvent('focustrap:deactivated', { bubbles: true }));\n }\n me.addEventListener('keydown', function(e) {\n if (!isActive || e.key !== 'Tab') return;\n var focusable = getFocusable();\n if (focusable.length === 0) { e.preventDefault(); return; }\n e.preventDefault();\n var idx = focusable.indexOf(document.activeElement);\n if (e.shiftKey) {\n focusable[idx <= 0 ? focusable.length - 1 : idx - 1].focus();\n } else {\n focusable[idx >= focusable.length - 1 ? 0 : idx + 1].focus();\n }\n });\n me.addEventListener('focustrap:activate', function() { activate(); });\n me.addEventListener('focustrap:deactivate', function() { deactivate(); });\n if (active) activate();\n end\n end\nend`.trim(),\n};\n","/**\n * Behavior Schema Types\n *\n * Defines the structure for behavior metadata used for:\n * - Code generation (TypeScript types, documentation)\n * - Runtime categorization and lazy loading\n * - Tooling and IDE integration\n */\n\n/**\n * Behavior categories for organization.\n * - ui: Visual interaction behaviors (drag, resize, sort)\n * - data: Data manipulation behaviors (remove, transform)\n * - animation: Animation and transition behaviors\n * - form: Form-related behaviors (validation, toggle states)\n * - layout: Layout behaviors (sticky, scrollspy)\n */\nexport type BehaviorCategory = 'ui' | 'data' | 'animation' | 'form' | 'layout';\n\n/**\n * Loading tiers for lazy loading optimization.\n * - core: Always loaded (essential behaviors)\n * - common: High usage (loaded for typical apps)\n * - optional: Low usage (loaded on demand)\n */\nexport type BehaviorTier = 'core' | 'common' | 'optional';\n\n/**\n * Schema for a behavior parameter.\n */\nexport interface ParameterSchema {\n name: string;\n type: 'string' | 'number' | 'boolean' | 'selector' | 'element';\n optional?: boolean;\n default?: string | number | boolean;\n /** Allowed values for constrained parameters */\n enum?: string[];\n description: string;\n}\n\n/**\n * Schema for a behavior event.\n */\nexport interface EventSchema {\n name: string;\n description: string;\n}\n\n/**\n * Complete schema for a behavior.\n * This is the source of truth for all behavior metadata.\n */\nexport interface BehaviorSchema {\n /** Behavior name (PascalCase) */\n name: string;\n /** Category for organization */\n category: BehaviorCategory;\n /** Loading tier for lazy loading */\n tier: BehaviorTier;\n /** Semantic version */\n version: string;\n /** Human-readable description */\n description: string;\n /** Parameter definitions */\n parameters: ParameterSchema[];\n /** Event definitions */\n events: EventSchema[];\n /** The hyperscript behavior source code */\n source: string;\n /** Optional requirements or notes */\n requirements?: string[];\n}\n\n/**\n * Runtime behavior module interface.\n * This is what gets registered with the hyperfixi runtime.\n */\nexport interface BehaviorModule {\n source: string;\n metadata: BehaviorSchema;\n register: (hyperfixi?: LokaScriptInstance) => Promise<void>;\n}\n\n/**\n * Minimal LokaScript instance interface for behavior registration.\n */\nexport interface LokaScriptInstance {\n compileSync: (\n code: string,\n options?: { traditional?: boolean; language?: string }\n ) => {\n ok: boolean;\n ast?: unknown;\n errors?: Array<{ message: string; line?: number; column?: number }>;\n };\n execute: (ast: unknown, ctx: unknown) => Promise<unknown>;\n createContext?: () => { locals: Map<string, unknown>; globals: Map<string, unknown> };\n}\n\n/**\n * Typed window interface for behavior auto-registration.\n * Avoids `(window as any)` casts throughout the codebase.\n * Checks both `window.lokascript` and `window.hyperfixi` for the runtime instance.\n */\nexport interface LokaScriptWindow {\n lokascript?: LokaScriptInstance;\n hyperfixi?: LokaScriptInstance;\n __hyperfixi_behaviors_ready?: Promise<void> | undefined;\n}\n\n/**\n * Resolve the LokaScript runtime from window globals.\n * Checks both `window.lokascript` and `window.hyperfixi`.\n */\nexport function resolveRuntime(): LokaScriptInstance | null {\n if (typeof window === 'undefined') return null;\n const win = window as unknown as LokaScriptWindow;\n return win.lokascript || win.hyperfixi || null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACQO,IAAM,kBAAkC;AAAA,EAC7C,MAAM;AAAA,EACN,UAAU;AAAA,EACV,MAAM;AAAA,EACN,SAAS;AAAA,EACT,aAAa;AAAA,EACb,YAAY;AAAA,IACV;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN,EAAE,MAAM,uBAAuB,aAAa,mCAAmC;AAAA,IAC/E,EAAE,MAAM,yBAAyB,aAAa,qCAAqC;AAAA,EACrF;AAAA,EACA,cAAc;AAAA,IACZ;AAAA,IACA;AAAA,EACF;AAAA,EACA,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAgDL,KAAK;AACV;;;ACqBO,SAAS,iBAA4C;AAC1D,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,QAAM,MAAM;AACZ,SAAO,IAAI,cAAc,IAAI,aAAa;AAC5C;;;AFpGO,IAAM,kBAAkB,gBAAgB;AACxC,IAAM,oBAAoB;AAMjC,eAAsB,kBAAkB,WAA+C;AACrF,QAAM,KAAK,aAAa,eAAe;AAEvC,MAAI,CAAC,IAAI;AACP,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,GAAG,YAAY,gBAAgB,QAAQ,EAAE,aAAa,KAAK,CAAC;AAE3E,MAAI,CAAC,OAAO,IAAI;AACd,UAAM,IAAI,MAAM,yCAAyC,KAAK,UAAU,OAAO,MAAM,CAAC,EAAE;AAAA,EAC1F;AAEA,QAAM,MAAM,GAAG,gBAAgB,GAAG,cAAc,IAAI,EAAE,QAAQ,oBAAI,IAAI,GAAG,SAAS,oBAAI,IAAI,EAAE;AAC5F,QAAM,GAAG,QAAQ,OAAO,KAAK,GAAG;AAClC;AAGA,IAAI,eAAe,GAAG;AACpB,oBAAkB,EAAE,MAAM,QAAQ,KAAK;AACzC;AAEA,IAAO,oBAAQ;AAAA,EACb,QAAQ,gBAAgB;AAAA,EACxB,UAAU;AAAA,EACV,UAAU;AACZ;","names":[]}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as BehaviorSchema, L as LokaScriptInstance } from '../types-DCCtVQS5.cjs';
|
|
2
2
|
|
|
3
3
|
declare const focusTrapSource: string;
|
|
4
4
|
declare const focusTrapMetadata: BehaviorSchema;
|
|
5
5
|
/**
|
|
6
|
-
* Register the FocusTrap behavior with LokaScript
|
|
6
|
+
* Register the FocusTrap behavior with LokaScript by compiling its
|
|
7
|
+
* hyperscript source and executing the resulting behavior definition.
|
|
7
8
|
*/
|
|
8
9
|
declare function registerFocusTrap(hyperfixi?: LokaScriptInstance): Promise<void>;
|
|
9
10
|
declare const _default: {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as BehaviorSchema, L as LokaScriptInstance } from '../types-DCCtVQS5.js';
|
|
2
2
|
|
|
3
3
|
declare const focusTrapSource: string;
|
|
4
4
|
declare const focusTrapMetadata: BehaviorSchema;
|
|
5
5
|
/**
|
|
6
|
-
* Register the FocusTrap behavior with LokaScript
|
|
6
|
+
* Register the FocusTrap behavior with LokaScript by compiling its
|
|
7
|
+
* hyperscript source and executing the resulting behavior definition.
|
|
7
8
|
*/
|
|
8
9
|
declare function registerFocusTrap(hyperfixi?: LokaScriptInstance): Promise<void>;
|
|
9
10
|
declare const _default: {
|
|
@@ -33,7 +33,7 @@ var resizableSchema = {
|
|
|
33
33
|
category: "ui",
|
|
34
34
|
tier: "optional",
|
|
35
35
|
version: "1.0.0",
|
|
36
|
-
description: "Makes elements resizable by dragging",
|
|
36
|
+
description: "Makes elements resizable by dragging (EXPERIMENTAL \u2014 stateful async component, beyond the inline-scripting boundary; not part of the curated set)",
|
|
37
37
|
parameters: [
|
|
38
38
|
{
|
|
39
39
|
name: "minWidth",
|
|
@@ -81,15 +81,15 @@ behavior Resizable(minWidth, minHeight, maxWidth, maxHeight)
|
|
|
81
81
|
set startX to clientX
|
|
82
82
|
set startY to clientY
|
|
83
83
|
repeat until event pointerup from document
|
|
84
|
-
wait for pointermove(clientX, clientY) from document
|
|
84
|
+
wait for pointermove(clientX, clientY) or pointerup(clientX, clientY) from document
|
|
85
85
|
set newWidth to startWidth + clientX - startX
|
|
86
86
|
set newHeight to startHeight + clientY - startY
|
|
87
87
|
if newWidth < minWidth then set newWidth to minWidth end
|
|
88
88
|
if newWidth > maxWidth then set newWidth to maxWidth end
|
|
89
89
|
if newHeight < minHeight then set newHeight to minHeight end
|
|
90
90
|
if newHeight > maxHeight then set newHeight to maxHeight end
|
|
91
|
-
set my
|
|
92
|
-
set my
|
|
91
|
+
set my *width to newWidth + "px"
|
|
92
|
+
set my *height to newHeight + "px"
|
|
93
93
|
trigger resizable:resize
|
|
94
94
|
end
|
|
95
95
|
trigger resizable:end
|
|
@@ -108,43 +108,6 @@ function resolveRuntime() {
|
|
|
108
108
|
// src/behaviors/resizable.ts
|
|
109
109
|
var resizableSource = resizableSchema.source;
|
|
110
110
|
var resizableMetadata = resizableSchema;
|
|
111
|
-
function installResizable(element, params) {
|
|
112
|
-
let handleEl = element;
|
|
113
|
-
if (params.handle && params.handle !== "me") {
|
|
114
|
-
if (typeof params.handle === "string") {
|
|
115
|
-
const found = element.querySelector(params.handle);
|
|
116
|
-
if (found instanceof HTMLElement) handleEl = found;
|
|
117
|
-
} else if (params.handle instanceof HTMLElement) {
|
|
118
|
-
handleEl = params.handle;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
const minW = params.minWidth ?? 50;
|
|
122
|
-
const minH = params.minHeight ?? 50;
|
|
123
|
-
const maxW = params.maxWidth ?? 9999;
|
|
124
|
-
const maxH = params.maxHeight ?? 9999;
|
|
125
|
-
handleEl.addEventListener("pointerdown", (e) => {
|
|
126
|
-
e.preventDefault();
|
|
127
|
-
element.dispatchEvent(new CustomEvent("resizable:start", { bubbles: true }));
|
|
128
|
-
const startWidth = element.offsetWidth;
|
|
129
|
-
const startHeight = element.offsetHeight;
|
|
130
|
-
const startX = e.clientX;
|
|
131
|
-
const startY = e.clientY;
|
|
132
|
-
function onMove(ev) {
|
|
133
|
-
const newWidth = Math.max(minW, Math.min(maxW, startWidth + (ev.clientX - startX)));
|
|
134
|
-
const newHeight = Math.max(minH, Math.min(maxH, startHeight + (ev.clientY - startY)));
|
|
135
|
-
element.style.width = `${newWidth}px`;
|
|
136
|
-
element.style.height = `${newHeight}px`;
|
|
137
|
-
element.dispatchEvent(new CustomEvent("resizable:resize", { bubbles: true }));
|
|
138
|
-
}
|
|
139
|
-
function onUp() {
|
|
140
|
-
document.removeEventListener("pointermove", onMove);
|
|
141
|
-
document.removeEventListener("pointerup", onUp);
|
|
142
|
-
element.dispatchEvent(new CustomEvent("resizable:end", { bubbles: true }));
|
|
143
|
-
}
|
|
144
|
-
document.addEventListener("pointermove", onMove);
|
|
145
|
-
document.addEventListener("pointerup", onUp);
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
111
|
async function registerResizable(hyperfixi) {
|
|
149
112
|
const hf = hyperfixi || resolveRuntime();
|
|
150
113
|
if (!hf) {
|
|
@@ -152,15 +115,12 @@ async function registerResizable(hyperfixi) {
|
|
|
152
115
|
"LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
|
|
153
116
|
);
|
|
154
117
|
}
|
|
155
|
-
const
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
eventHandlers: [],
|
|
160
|
-
imperativeInstaller: installResizable
|
|
161
|
-
};
|
|
118
|
+
const result = hf.compileSync(resizableSchema.source, { traditional: true });
|
|
119
|
+
if (!result.ok) {
|
|
120
|
+
throw new Error(`Failed to compile Resizable behavior: ${JSON.stringify(result.errors)}`);
|
|
121
|
+
}
|
|
162
122
|
const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
|
|
163
|
-
await hf.execute(
|
|
123
|
+
await hf.execute(result.ast, ctx);
|
|
164
124
|
}
|
|
165
125
|
if (resolveRuntime()) {
|
|
166
126
|
registerResizable().catch(console.error);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/behaviors/resizable.ts","../../src/schemas/resizable.schema.ts","../../src/schemas/types.ts"],"sourcesContent":["/**\n * Resizable Behavior — Imperative Implementation\n *\n * Makes elements resizable by dragging edges or corners.\n * Supports minimum/maximum dimensions and resize handles.\n *\n * @example\n * ```html\n * <div _=\"install Resizable\" style=\"width: 200px; height: 150px;\">\n * Resize me!\n * </div>\n * ```\n */\n\nimport { resizableSchema } from '../schemas/resizable.schema';\nimport type { LokaScriptInstance } from '../schemas/types';\nimport { resolveRuntime } from '../schemas/types';\n\n// Re-export schema-derived values for backwards compatibility\nexport const resizableSource = resizableSchema.source;\nexport const resizableMetadata = resizableSchema;\n\n/**\n * Imperative installer for Resizable behavior.\n */\nfunction installResizable(element: HTMLElement, params: Record<string, any>): void {\n // Resolve handle element\n let handleEl: HTMLElement = element;\n if (params.handle && params.handle !== 'me') {\n if (typeof params.handle === 'string') {\n const found = element.querySelector(params.handle);\n if (found instanceof HTMLElement) handleEl = found;\n } else if (params.handle instanceof HTMLElement) {\n handleEl = params.handle;\n }\n }\n\n const minW = params.minWidth ?? 50;\n const minH = params.minHeight ?? 50;\n const maxW = params.maxWidth ?? 9999;\n const maxH = params.maxHeight ?? 9999;\n\n handleEl.addEventListener('pointerdown', (e: PointerEvent) => {\n e.preventDefault();\n element.dispatchEvent(new CustomEvent('resizable:start', { bubbles: true }));\n\n const startWidth = element.offsetWidth;\n const startHeight = element.offsetHeight;\n const startX = e.clientX;\n const startY = e.clientY;\n\n function onMove(ev: PointerEvent) {\n const newWidth = Math.max(minW, Math.min(maxW, startWidth + (ev.clientX - startX)));\n const newHeight = Math.max(minH, Math.min(maxH, startHeight + (ev.clientY - startY)));\n\n element.style.width = `${newWidth}px`;\n element.style.height = `${newHeight}px`;\n element.dispatchEvent(new CustomEvent('resizable:resize', { bubbles: true }));\n }\n\n function onUp() {\n document.removeEventListener('pointermove', onMove);\n document.removeEventListener('pointerup', onUp);\n element.dispatchEvent(new CustomEvent('resizable:end', { bubbles: true }));\n }\n\n document.addEventListener('pointermove', onMove);\n document.addEventListener('pointerup', onUp);\n });\n}\n\n/**\n * Register the Resizable behavior with LokaScript.\n */\nexport async function registerResizable(hyperfixi?: LokaScriptInstance): Promise<void> {\n const hf = hyperfixi || resolveRuntime();\n\n if (!hf) {\n throw new Error(\n 'LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors.'\n );\n }\n\n const syntheticNode = {\n type: 'behavior',\n name: 'Resizable',\n parameters: [],\n eventHandlers: [],\n imperativeInstaller: installResizable,\n };\n const ctx = hf.createContext ? hf.createContext() : { locals: new Map(), globals: new Map() };\n await hf.execute(syntheticNode, ctx);\n}\n\n// Auto-register when loaded as a script tag\nif (resolveRuntime()) {\n registerResizable().catch(console.error);\n}\n\nexport default {\n source: resizableSchema.source,\n metadata: resizableSchema,\n register: registerResizable,\n};\n","import type { BehaviorSchema } from './types';\n\n/**\n * Resizable Behavior Schema\n *\n * Makes elements resizable by dragging edges or corners.\n * Supports minimum/maximum dimensions and resize handles.\n */\nexport const resizableSchema: BehaviorSchema = {\n name: 'Resizable',\n category: 'ui',\n tier: 'optional',\n version: '1.0.0',\n description: 'Makes elements resizable by dragging',\n parameters: [\n {\n name: 'minWidth',\n type: 'number',\n optional: true,\n default: 50,\n description: 'Minimum width in pixels',\n },\n {\n name: 'minHeight',\n type: 'number',\n optional: true,\n default: 50,\n description: 'Minimum height in pixels',\n },\n {\n name: 'maxWidth',\n type: 'number',\n optional: true,\n default: 9999,\n description: 'Maximum width in pixels',\n },\n {\n name: 'maxHeight',\n type: 'number',\n optional: true,\n default: 9999,\n description: 'Maximum height in pixels',\n },\n ],\n events: [\n { name: 'resizable:start', description: 'Fired when resize begins' },\n { name: 'resizable:resize', description: 'Fired during resize' },\n { name: 'resizable:end', description: 'Fired when resize completes' },\n ],\n source: `\nbehavior Resizable(minWidth, minHeight, maxWidth, maxHeight)\n on pointerdown(clientX, clientY) from me\n halt the event\n trigger resizable:start\n measure width\n set startWidth to it\n measure height\n set startHeight to it\n set startX to clientX\n set startY to clientY\n repeat until event pointerup from document\n wait for pointermove(clientX, clientY) from document\n set newWidth to startWidth + clientX - startX\n set newHeight to startHeight + clientY - startY\n if newWidth < minWidth then set newWidth to minWidth end\n if newWidth > maxWidth then set newWidth to maxWidth end\n if newHeight < minHeight then set newHeight to minHeight end\n if newHeight > maxHeight then set newHeight to maxHeight end\n set my style.width to newWidth + \"px\"\n set my style.height to newHeight + \"px\"\n trigger resizable:resize\n end\n trigger resizable:end\n end\nend\n`.trim(),\n};\n","/**\n * Behavior Schema Types\n *\n * Defines the structure for behavior metadata used for:\n * - Code generation (TypeScript types, documentation)\n * - Runtime categorization and lazy loading\n * - Tooling and IDE integration\n */\n\n/**\n * Behavior categories for organization.\n * - ui: Visual interaction behaviors (drag, resize, sort)\n * - data: Data manipulation behaviors (remove, transform)\n * - animation: Animation and transition behaviors\n * - form: Form-related behaviors (validation, toggle states)\n * - layout: Layout behaviors (sticky, scrollspy)\n */\nexport type BehaviorCategory = 'ui' | 'data' | 'animation' | 'form' | 'layout';\n\n/**\n * Loading tiers for lazy loading optimization.\n * - core: Always loaded (essential behaviors)\n * - common: High usage (loaded for typical apps)\n * - optional: Low usage (loaded on demand)\n */\nexport type BehaviorTier = 'core' | 'common' | 'optional';\n\n/**\n * Schema for a behavior parameter.\n */\nexport interface ParameterSchema {\n name: string;\n type: 'string' | 'number' | 'boolean' | 'selector' | 'element';\n optional?: boolean;\n default?: string | number | boolean;\n /** Allowed values for constrained parameters */\n enum?: string[];\n description: string;\n}\n\n/**\n * Schema for a behavior event.\n */\nexport interface EventSchema {\n name: string;\n description: string;\n}\n\n/**\n * Complete schema for a behavior.\n * This is the source of truth for all behavior metadata.\n */\nexport interface BehaviorSchema {\n /** Behavior name (PascalCase) */\n name: string;\n /** Category for organization */\n category: BehaviorCategory;\n /** Loading tier for lazy loading */\n tier: BehaviorTier;\n /** Semantic version */\n version: string;\n /** Human-readable description */\n description: string;\n /** Parameter definitions */\n parameters: ParameterSchema[];\n /** Event definitions */\n events: EventSchema[];\n /** The hyperscript behavior source code */\n source: string;\n /** Optional requirements or notes */\n requirements?: string[];\n}\n\n/**\n * Runtime behavior module interface.\n * This is what gets registered with the hyperfixi runtime.\n */\nexport interface BehaviorModule {\n source: string;\n metadata: BehaviorSchema;\n register: (hyperfixi?: LokaScriptInstance) => Promise<void>;\n}\n\n/**\n * Minimal LokaScript instance interface for behavior registration.\n */\nexport interface LokaScriptInstance {\n compileSync: (\n code: string,\n options?: { traditional?: boolean; language?: string }\n ) => {\n ok: boolean;\n ast?: unknown;\n errors?: Array<{ message: string; line?: number; column?: number }>;\n };\n execute: (ast: unknown, ctx: unknown) => Promise<unknown>;\n createContext?: () => { locals: Map<string, unknown>; globals: Map<string, unknown> };\n}\n\n/**\n * Typed window interface for behavior auto-registration.\n * Avoids `(window as any)` casts throughout the codebase.\n * Checks both `window.lokascript` and `window.hyperfixi` for the runtime instance.\n */\nexport interface LokaScriptWindow {\n lokascript?: LokaScriptInstance;\n hyperfixi?: LokaScriptInstance;\n __hyperfixi_behaviors_ready?: Promise<void> | undefined;\n}\n\n/**\n * Resolve the LokaScript runtime from window globals.\n * Checks both `window.lokascript` and `window.hyperfixi`.\n */\nexport function resolveRuntime(): LokaScriptInstance | null {\n if (typeof window === 'undefined') return null;\n const win = window as unknown as LokaScriptWindow;\n return win.lokascript || win.hyperfixi || null;\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../src/behaviors/resizable.ts","../../src/schemas/resizable.schema.ts","../../src/schemas/types.ts"],"sourcesContent":["/**\n * Resizable Behavior\n *\n * Makes elements resizable by dragging. Compiled from its hyperscript `source`\n * (single source of truth) — no imperative installer. The source measures the\n * start size, runs a `repeat until event pointerup` loop, clamps to\n * min/max dimensions, and writes `*width` / `*height` inline styles.\n *\n * @example\n * ```html\n * <div _=\"install Resizable\" style=\"width: 200px; height: 150px;\">\n * Resize me!\n * </div>\n * ```\n */\n\nimport { resizableSchema } from '../schemas/resizable.schema';\nimport type { LokaScriptInstance } from '../schemas/types';\nimport { resolveRuntime } from '../schemas/types';\n\n// Re-export schema-derived values for backwards compatibility\nexport const resizableSource = resizableSchema.source;\nexport const resizableMetadata = resizableSchema;\n\n/**\n * Register the Resizable behavior with LokaScript by compiling its hyperscript\n * source and executing the resulting behavior definition.\n */\nexport async function registerResizable(hyperfixi?: LokaScriptInstance): Promise<void> {\n const hf = hyperfixi || resolveRuntime();\n\n if (!hf) {\n throw new Error(\n 'LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors.'\n );\n }\n\n const result = hf.compileSync(resizableSchema.source, { traditional: true });\n\n if (!result.ok) {\n throw new Error(`Failed to compile Resizable behavior: ${JSON.stringify(result.errors)}`);\n }\n\n const ctx = hf.createContext ? hf.createContext() : { locals: new Map(), globals: new Map() };\n await hf.execute(result.ast, ctx);\n}\n\n// Auto-register when loaded as a script tag\nif (resolveRuntime()) {\n registerResizable().catch(console.error);\n}\n\nexport default {\n source: resizableSchema.source,\n metadata: resizableSchema,\n register: registerResizable,\n};\n","import type { BehaviorSchema } from './types';\n\n/**\n * Resizable Behavior Schema\n *\n * Makes elements resizable by dragging edges or corners.\n * Supports minimum/maximum dimensions and resize handles.\n */\nexport const resizableSchema: BehaviorSchema = {\n name: 'Resizable',\n category: 'ui',\n tier: 'optional',\n version: '1.0.0',\n description:\n 'Makes elements resizable by dragging (EXPERIMENTAL — stateful async component, beyond the inline-scripting boundary; not part of the curated set)',\n parameters: [\n {\n name: 'minWidth',\n type: 'number',\n optional: true,\n default: 50,\n description: 'Minimum width in pixels',\n },\n {\n name: 'minHeight',\n type: 'number',\n optional: true,\n default: 50,\n description: 'Minimum height in pixels',\n },\n {\n name: 'maxWidth',\n type: 'number',\n optional: true,\n default: 9999,\n description: 'Maximum width in pixels',\n },\n {\n name: 'maxHeight',\n type: 'number',\n optional: true,\n default: 9999,\n description: 'Maximum height in pixels',\n },\n ],\n events: [\n { name: 'resizable:start', description: 'Fired when resize begins' },\n { name: 'resizable:resize', description: 'Fired during resize' },\n { name: 'resizable:end', description: 'Fired when resize completes' },\n ],\n source: `\nbehavior Resizable(minWidth, minHeight, maxWidth, maxHeight)\n on pointerdown(clientX, clientY) from me\n halt the event\n trigger resizable:start\n measure width\n set startWidth to it\n measure height\n set startHeight to it\n set startX to clientX\n set startY to clientY\n repeat until event pointerup from document\n wait for pointermove(clientX, clientY) or pointerup(clientX, clientY) from document\n set newWidth to startWidth + clientX - startX\n set newHeight to startHeight + clientY - startY\n if newWidth < minWidth then set newWidth to minWidth end\n if newWidth > maxWidth then set newWidth to maxWidth end\n if newHeight < minHeight then set newHeight to minHeight end\n if newHeight > maxHeight then set newHeight to maxHeight end\n set my *width to newWidth + \"px\"\n set my *height to newHeight + \"px\"\n trigger resizable:resize\n end\n trigger resizable:end\n end\nend\n`.trim(),\n};\n","/**\n * Behavior Schema Types\n *\n * Defines the structure for behavior metadata used for:\n * - Code generation (TypeScript types, documentation)\n * - Runtime categorization and lazy loading\n * - Tooling and IDE integration\n */\n\n/**\n * Behavior categories for organization.\n * - ui: Visual interaction behaviors (drag, resize, sort)\n * - data: Data manipulation behaviors (remove, transform)\n * - animation: Animation and transition behaviors\n * - form: Form-related behaviors (validation, toggle states)\n * - layout: Layout behaviors (sticky, scrollspy)\n */\nexport type BehaviorCategory = 'ui' | 'data' | 'animation' | 'form' | 'layout';\n\n/**\n * Loading tiers for lazy loading optimization.\n * - core: Always loaded (essential behaviors)\n * - common: High usage (loaded for typical apps)\n * - optional: Low usage (loaded on demand)\n */\nexport type BehaviorTier = 'core' | 'common' | 'optional';\n\n/**\n * Schema for a behavior parameter.\n */\nexport interface ParameterSchema {\n name: string;\n type: 'string' | 'number' | 'boolean' | 'selector' | 'element';\n optional?: boolean;\n default?: string | number | boolean;\n /** Allowed values for constrained parameters */\n enum?: string[];\n description: string;\n}\n\n/**\n * Schema for a behavior event.\n */\nexport interface EventSchema {\n name: string;\n description: string;\n}\n\n/**\n * Complete schema for a behavior.\n * This is the source of truth for all behavior metadata.\n */\nexport interface BehaviorSchema {\n /** Behavior name (PascalCase) */\n name: string;\n /** Category for organization */\n category: BehaviorCategory;\n /** Loading tier for lazy loading */\n tier: BehaviorTier;\n /** Semantic version */\n version: string;\n /** Human-readable description */\n description: string;\n /** Parameter definitions */\n parameters: ParameterSchema[];\n /** Event definitions */\n events: EventSchema[];\n /** The hyperscript behavior source code */\n source: string;\n /** Optional requirements or notes */\n requirements?: string[];\n}\n\n/**\n * Runtime behavior module interface.\n * This is what gets registered with the hyperfixi runtime.\n */\nexport interface BehaviorModule {\n source: string;\n metadata: BehaviorSchema;\n register: (hyperfixi?: LokaScriptInstance) => Promise<void>;\n}\n\n/**\n * Minimal LokaScript instance interface for behavior registration.\n */\nexport interface LokaScriptInstance {\n compileSync: (\n code: string,\n options?: { traditional?: boolean; language?: string }\n ) => {\n ok: boolean;\n ast?: unknown;\n errors?: Array<{ message: string; line?: number; column?: number }>;\n };\n execute: (ast: unknown, ctx: unknown) => Promise<unknown>;\n createContext?: () => { locals: Map<string, unknown>; globals: Map<string, unknown> };\n}\n\n/**\n * Typed window interface for behavior auto-registration.\n * Avoids `(window as any)` casts throughout the codebase.\n * Checks both `window.lokascript` and `window.hyperfixi` for the runtime instance.\n */\nexport interface LokaScriptWindow {\n lokascript?: LokaScriptInstance;\n hyperfixi?: LokaScriptInstance;\n __hyperfixi_behaviors_ready?: Promise<void> | undefined;\n}\n\n/**\n * Resolve the LokaScript runtime from window globals.\n * Checks both `window.lokascript` and `window.hyperfixi`.\n */\nexport function resolveRuntime(): LokaScriptInstance | null {\n if (typeof window === 'undefined') return null;\n const win = window as unknown as LokaScriptWindow;\n return win.lokascript || win.hyperfixi || null;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACQO,IAAM,kBAAkC;AAAA,EAC7C,MAAM;AAAA,EACN,UAAU;AAAA,EACV,MAAM;AAAA,EACN,SAAS;AAAA,EACT,aACE;AAAA,EACF,YAAY;AAAA,IACV;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN,EAAE,MAAM,mBAAmB,aAAa,2BAA2B;AAAA,IACnE,EAAE,MAAM,oBAAoB,aAAa,sBAAsB;AAAA,IAC/D,EAAE,MAAM,iBAAiB,aAAa,8BAA8B;AAAA,EACtE;AAAA,EACA,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0BR,KAAK;AACP;;;ACqCO,SAAS,iBAA4C;AAC1D,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,QAAM,MAAM;AACZ,SAAO,IAAI,cAAc,IAAI,aAAa;AAC5C;;;AFjGO,IAAM,kBAAkB,gBAAgB;AACxC,IAAM,oBAAoB;AAMjC,eAAsB,kBAAkB,WAA+C;AACrF,QAAM,KAAK,aAAa,eAAe;AAEvC,MAAI,CAAC,IAAI;AACP,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,GAAG,YAAY,gBAAgB,QAAQ,EAAE,aAAa,KAAK,CAAC;AAE3E,MAAI,CAAC,OAAO,IAAI;AACd,UAAM,IAAI,MAAM,yCAAyC,KAAK,UAAU,OAAO,MAAM,CAAC,EAAE;AAAA,EAC1F;AAEA,QAAM,MAAM,GAAG,gBAAgB,GAAG,cAAc,IAAI,EAAE,QAAQ,oBAAI,IAAI,GAAG,SAAS,oBAAI,IAAI,EAAE;AAC5F,QAAM,GAAG,QAAQ,OAAO,KAAK,GAAG;AAClC;AAGA,IAAI,eAAe,GAAG;AACpB,oBAAkB,EAAE,MAAM,QAAQ,KAAK;AACzC;AAEA,IAAO,oBAAQ;AAAA,EACb,QAAQ,gBAAgB;AAAA,EACxB,UAAU;AAAA,EACV,UAAU;AACZ;","names":[]}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as BehaviorSchema, L as LokaScriptInstance } from '../types-DCCtVQS5.cjs';
|
|
2
2
|
|
|
3
3
|
declare const resizableSource: string;
|
|
4
4
|
declare const resizableMetadata: BehaviorSchema;
|
|
5
5
|
/**
|
|
6
|
-
* Register the Resizable behavior with LokaScript
|
|
6
|
+
* Register the Resizable behavior with LokaScript by compiling its hyperscript
|
|
7
|
+
* source and executing the resulting behavior definition.
|
|
7
8
|
*/
|
|
8
9
|
declare function registerResizable(hyperfixi?: LokaScriptInstance): Promise<void>;
|
|
9
10
|
declare const _default: {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { B as BehaviorSchema, L as LokaScriptInstance } from '../types-DCCtVQS5.js';
|
|
2
2
|
|
|
3
3
|
declare const resizableSource: string;
|
|
4
4
|
declare const resizableMetadata: BehaviorSchema;
|
|
5
5
|
/**
|
|
6
|
-
* Register the Resizable behavior with LokaScript
|
|
6
|
+
* Register the Resizable behavior with LokaScript by compiling its hyperscript
|
|
7
|
+
* source and executing the resulting behavior definition.
|
|
7
8
|
*/
|
|
8
9
|
declare function registerResizable(hyperfixi?: LokaScriptInstance): Promise<void>;
|
|
9
10
|
declare const _default: {
|
|
@@ -3,8 +3,8 @@ import {
|
|
|
3
3
|
resizableMetadata,
|
|
4
4
|
resizableSource,
|
|
5
5
|
resizable_default
|
|
6
|
-
} from "../chunk-
|
|
7
|
-
import "../chunk-
|
|
6
|
+
} from "../chunk-7NGOA3T5.js";
|
|
7
|
+
import "../chunk-5LFOFVZ3.js";
|
|
8
8
|
import "../chunk-6TJXDCAQ.js";
|
|
9
9
|
export {
|
|
10
10
|
resizable_default as default,
|