@hyperfixi/behaviors 2.2.1 → 2.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (131) hide show
  1. package/dist/all.browser.global.js +316 -54
  2. package/dist/all.browser.global.js.map +1 -1
  3. package/dist/autodismiss.browser.global.js +54 -2
  4. package/dist/autodismiss.browser.global.js.map +1 -1
  5. package/dist/behaviors/autodismiss.cjs +54 -18
  6. package/dist/behaviors/autodismiss.cjs.map +1 -1
  7. package/dist/behaviors/autodismiss.js +2 -2
  8. package/dist/behaviors/clickoutside.cjs +23 -4
  9. package/dist/behaviors/clickoutside.cjs.map +1 -1
  10. package/dist/behaviors/clickoutside.js +2 -2
  11. package/dist/behaviors/clipboard.cjs +43 -21
  12. package/dist/behaviors/clipboard.cjs.map +1 -1
  13. package/dist/behaviors/clipboard.js +2 -2
  14. package/dist/behaviors/focustrap.cjs +44 -3
  15. package/dist/behaviors/focustrap.cjs.map +1 -1
  16. package/dist/behaviors/focustrap.js +2 -2
  17. package/dist/behaviors/removable.cjs +7 -4
  18. package/dist/behaviors/removable.cjs.map +1 -1
  19. package/dist/behaviors/removable.js +2 -2
  20. package/dist/behaviors/resizable.cjs +22 -14
  21. package/dist/behaviors/resizable.cjs.map +1 -1
  22. package/dist/behaviors/resizable.js +2 -2
  23. package/dist/behaviors/scrollreveal.cjs +25 -13
  24. package/dist/behaviors/scrollreveal.cjs.map +1 -1
  25. package/dist/behaviors/scrollreveal.js +2 -2
  26. package/dist/behaviors/sortable.cjs +18 -12
  27. package/dist/behaviors/sortable.cjs.map +1 -1
  28. package/dist/behaviors/sortable.js +2 -2
  29. package/dist/behaviors/tabs.cjs +80 -11
  30. package/dist/behaviors/tabs.cjs.map +1 -1
  31. package/dist/behaviors/tabs.js +2 -2
  32. package/dist/behaviors/toggleable.cjs +5 -2
  33. package/dist/behaviors/toggleable.cjs.map +1 -1
  34. package/dist/behaviors/toggleable.js +2 -2
  35. package/dist/chunk-66U2RSYJ.js +100 -0
  36. package/dist/chunk-66U2RSYJ.js.map +1 -0
  37. package/dist/{chunk-2NSKQMNM.js → chunk-7O7UOSBH.js} +2 -2
  38. package/dist/{chunk-244WSZOL.js → chunk-EKKJVXDZ.js} +2 -2
  39. package/dist/{chunk-AFGA54SA.js → chunk-F3CASJ7Q.js} +2 -2
  40. package/dist/{chunk-YHQRFUWV.js → chunk-GALKOMJ5.js} +2 -2
  41. package/dist/{chunk-272NKUJ3.js → chunk-HMU342XE.js} +8 -5
  42. package/dist/chunk-HMU342XE.js.map +1 -0
  43. package/dist/chunk-HQDYH45I.js +137 -0
  44. package/dist/chunk-HQDYH45I.js.map +1 -0
  45. package/dist/{chunk-WTUVPVSD.js → chunk-IQM32TEY.js} +2 -2
  46. package/dist/{chunk-H5Y5ARYG.js → chunk-L52AGCMP.js} +2 -2
  47. package/dist/{chunk-H2MCHR5A.js → chunk-LQJOQTBZ.js} +2 -2
  48. package/dist/{chunk-7JDV2THA.js → chunk-MVNHMYIK.js} +11 -11
  49. package/dist/{chunk-BWZ6EGII.js → chunk-NC6I6T7T.js} +19 -13
  50. package/dist/{chunk-BWZ6EGII.js.map → chunk-NC6I6T7T.js.map} +1 -1
  51. package/dist/chunk-OJ3YWO3W.js +92 -0
  52. package/dist/chunk-OJ3YWO3W.js.map +1 -0
  53. package/dist/{chunk-64DIQGQI.js → chunk-SLOXO6IY.js} +24 -5
  54. package/dist/chunk-SLOXO6IY.js.map +1 -0
  55. package/dist/{chunk-RPERQTFU.js → chunk-TLLGH5KX.js} +2 -2
  56. package/dist/{chunk-V5IWDPDP.js → chunk-U5GNXZUF.js} +23 -15
  57. package/dist/{chunk-V5IWDPDP.js.map → chunk-U5GNXZUF.js.map} +1 -1
  58. package/dist/{chunk-GPTHAUWN.js → chunk-URZGNPTQ.js} +26 -14
  59. package/dist/chunk-URZGNPTQ.js.map +1 -0
  60. package/dist/chunk-WOTZO7K4.js +92 -0
  61. package/dist/chunk-WOTZO7K4.js.map +1 -0
  62. package/dist/{chunk-JKBWIJFI.js → chunk-WPOQIMCC.js} +2 -2
  63. package/dist/{chunk-WUHHMDAA.js → chunk-XYZ7FOXJ.js} +6 -3
  64. package/dist/{chunk-WUHHMDAA.js.map → chunk-XYZ7FOXJ.js.map} +1 -1
  65. package/dist/{chunk-DYHBKDKB.js → chunk-ZZ2WSAX3.js} +2 -2
  66. package/dist/clickoutside.browser.global.js +16 -5
  67. package/dist/clickoutside.browser.global.js.map +1 -1
  68. package/dist/clipboard.browser.global.js +43 -2
  69. package/dist/clipboard.browser.global.js.map +1 -1
  70. package/dist/core.browser.global.js +5 -2
  71. package/dist/core.browser.global.js.map +1 -1
  72. package/dist/focustrap.browser.global.js +46 -5
  73. package/dist/focustrap.browser.global.js.map +1 -1
  74. package/dist/index.cjs +321 -102
  75. package/dist/index.cjs.map +1 -1
  76. package/dist/index.js +21 -21
  77. package/dist/loaders.cjs +321 -102
  78. package/dist/loaders.cjs.map +1 -1
  79. package/dist/loaders.js +11 -11
  80. package/dist/removable.browser.global.js +8 -5
  81. package/dist/removable.browser.global.js.map +1 -1
  82. package/dist/resizable.browser.global.js +24 -16
  83. package/dist/resizable.browser.global.js.map +1 -1
  84. package/dist/resolver.browser.global.js +407 -0
  85. package/dist/resolver.browser.global.js.map +1 -0
  86. package/dist/schemas/index.cjs +321 -102
  87. package/dist/schemas/index.cjs.map +1 -1
  88. package/dist/schemas/index.js +10 -10
  89. package/dist/scrollreveal.browser.global.js +27 -8
  90. package/dist/scrollreveal.browser.global.js.map +1 -1
  91. package/dist/sortable.browser.global.js +19 -13
  92. package/dist/sortable.browser.global.js.map +1 -1
  93. package/dist/tabs.browser.global.js +80 -2
  94. package/dist/tabs.browser.global.js.map +1 -1
  95. package/dist/toggleable.browser.global.js +6 -3
  96. package/dist/toggleable.browser.global.js.map +1 -1
  97. package/package.json +1 -1
  98. package/src/behavior-resolver.ts +91 -0
  99. package/src/browser-resolver-bundle.ts +42 -0
  100. package/src/schemas/autodismiss.schema.ts +54 -18
  101. package/src/schemas/clickoutside.schema.ts +22 -3
  102. package/src/schemas/clipboard.schema.ts +43 -21
  103. package/src/schemas/focustrap.schema.ts +44 -3
  104. package/src/schemas/removable.schema.ts +7 -4
  105. package/src/schemas/resizable.schema.ts +22 -14
  106. package/src/schemas/scrollreveal.schema.ts +25 -13
  107. package/src/schemas/sortable.schema.ts +18 -12
  108. package/src/schemas/tabs.schema.ts +80 -11
  109. package/src/schemas/toggleable.schema.ts +5 -2
  110. package/dist/chunk-272NKUJ3.js.map +0 -1
  111. package/dist/chunk-64DIQGQI.js.map +0 -1
  112. package/dist/chunk-GPTHAUWN.js.map +0 -1
  113. package/dist/chunk-GVJPA2EK.js +0 -68
  114. package/dist/chunk-GVJPA2EK.js.map +0 -1
  115. package/dist/chunk-QKDYW4VM.js +0 -70
  116. package/dist/chunk-QKDYW4VM.js.map +0 -1
  117. package/dist/chunk-RB7OB6OD.js +0 -51
  118. package/dist/chunk-RB7OB6OD.js.map +0 -1
  119. package/dist/chunk-ZQQZTMCJ.js +0 -64
  120. package/dist/chunk-ZQQZTMCJ.js.map +0 -1
  121. /package/dist/{chunk-2NSKQMNM.js.map → chunk-7O7UOSBH.js.map} +0 -0
  122. /package/dist/{chunk-244WSZOL.js.map → chunk-EKKJVXDZ.js.map} +0 -0
  123. /package/dist/{chunk-AFGA54SA.js.map → chunk-F3CASJ7Q.js.map} +0 -0
  124. /package/dist/{chunk-YHQRFUWV.js.map → chunk-GALKOMJ5.js.map} +0 -0
  125. /package/dist/{chunk-WTUVPVSD.js.map → chunk-IQM32TEY.js.map} +0 -0
  126. /package/dist/{chunk-H5Y5ARYG.js.map → chunk-L52AGCMP.js.map} +0 -0
  127. /package/dist/{chunk-H2MCHR5A.js.map → chunk-LQJOQTBZ.js.map} +0 -0
  128. /package/dist/{chunk-7JDV2THA.js.map → chunk-MVNHMYIK.js.map} +0 -0
  129. /package/dist/{chunk-RPERQTFU.js.map → chunk-TLLGH5KX.js.map} +0 -0
  130. /package/dist/{chunk-JKBWIJFI.js.map → chunk-WPOQIMCC.js.map} +0 -0
  131. /package/dist/{chunk-DYHBKDKB.js.map → chunk-ZZ2WSAX3.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/behaviors/removable.ts","../src/schemas/removable.schema.ts","../src/schemas/types.ts"],"sourcesContent":["/**\n * Removable Behavior\n *\n * A behavior that removes an element when a trigger is clicked.\n * Supports optional confirmation and transition effects.\n *\n * @example\n * ```html\n * <div _=\"install Removable\">Click to remove</div>\n *\n * <div _=\"install Removable(confirm: true)\">With confirmation</div>\n * ```\n */\n\nimport { removableSchema } from '../schemas/removable.schema';\nimport type { LokaScriptInstance } from '../schemas/types';\nimport { resolveRuntime } from '../schemas/types';\n\n// Re-export schema-derived values for backwards compatibility\nexport const removableSource = removableSchema.source;\nexport const removableMetadata = removableSchema;\n\n/**\n * Register the Removable behavior with LokaScript.\n */\nexport async function registerRemovable(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(removableSchema.source, { traditional: true });\n\n if (!result.ok) {\n throw new Error(`Failed to compile Removable 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 registerRemovable().catch(console.error);\n}\n\nexport default {\n source: removableSchema.source,\n metadata: removableSchema,\n register: registerRemovable,\n};\n","import type { BehaviorSchema } from './types';\n\n/**\n * Removable Behavior Schema\n *\n * Removes an element when a trigger is clicked.\n * Supports optional confirmation and transition effects.\n *\n * @since 1.2.0 — `trigger` parameter renamed to `triggerEl` to avoid\n * shadowing the hyperscript `trigger` command keyword. Users migrating\n * from v1.x should update: `install Removable(triggerEl: .close-btn)`.\n */\nexport const removableSchema: BehaviorSchema = {\n name: 'Removable',\n category: 'data',\n tier: 'common',\n version: '1.2.0',\n description: 'Makes elements removable on click',\n parameters: [\n {\n name: 'triggerEl',\n type: 'selector',\n optional: true,\n default: 'me',\n description: 'Element that triggers removal (e.g., a close button)',\n },\n {\n name: 'confirm',\n type: 'boolean',\n optional: true,\n default: false,\n description: 'Show confirmation dialog before removal',\n },\n {\n name: 'effect',\n type: 'string',\n optional: true,\n default: 'none',\n enum: ['fade', 'none'],\n description: 'Transition effect: \"fade\" or \"none\"',\n },\n ],\n events: [\n { name: 'removable:before', description: 'Fired before removal (cancelable)' },\n { name: 'removable:removed', description: 'Fired after removal' },\n ],\n source: `\nbehavior Removable(triggerEl, confirm, effect)\n init\n if triggerEl is undefined\n set triggerEl to me\n end\n end\n on click from triggerEl\n if confirm\n if not window.confirm(\"Are you sure?\")\n halt\n end\n end\n trigger removable:before\n if effect is \"fade\"\n transition opacity to 0 over 300ms\n end\n trigger removable:removed\n remove me\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":"scAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,aAAAE,EAAA,sBAAAC,EAAA,sBAAAC,EAAA,oBAAAC,ICYO,IAAMC,EAAkC,CAC7C,KAAM,YACN,SAAU,OACV,KAAM,SACN,QAAS,QACT,YAAa,oCACb,WAAY,CACV,CACE,KAAM,YACN,KAAM,WACN,SAAU,GACV,QAAS,KACT,YAAa,sDACf,EACA,CACE,KAAM,UACN,KAAM,UACN,SAAU,GACV,QAAS,GACT,YAAa,yCACf,EACA,CACE,KAAM,SACN,KAAM,SACN,SAAU,GACV,QAAS,OACT,KAAM,CAAC,OAAQ,MAAM,EACrB,YAAa,qCACf,CACF,EACA,OAAQ,CACN,CAAE,KAAM,mBAAoB,YAAa,mCAAoC,EAC7E,CAAE,KAAM,oBAAqB,YAAa,qBAAsB,CAClE,EACA,OAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAqBR,KAAK,CACP,EC8CO,SAASC,GAA4C,CAC1D,GAAI,OAAO,OAAW,IAAa,OAAO,KAC1C,IAAMC,EAAM,OACZ,OAAOA,EAAI,YAAcA,EAAI,WAAa,IAC5C,CFnGO,IAAMC,EAAkBC,EAAgB,OAClCC,EAAoBD,EAKjC,eAAsBE,EAAkBC,EAA+C,CACrF,IAAMC,EAAKD,GAAaE,EAAe,EAEvC,GAAI,CAACD,EACH,MAAM,IAAI,MACR,yFACF,EAGF,IAAME,EAASF,EAAG,YAAYJ,EAAgB,OAAQ,CAAE,YAAa,EAAK,CAAC,EAE3E,GAAI,CAACM,EAAO,GACV,MAAM,IAAI,MAAM,yCAAyC,KAAK,UAAUA,EAAO,MAAM,CAAC,EAAE,EAG1F,IAAMC,EAAMH,EAAG,cAAgBA,EAAG,cAAc,EAAI,CAAE,OAAQ,IAAI,IAAO,QAAS,IAAI,GAAM,EAC5F,MAAMA,EAAG,QAAQE,EAAO,IAAKC,CAAG,CAClC,CAGIF,EAAe,GACjBH,EAAkB,EAAE,MAAM,QAAQ,KAAK,EAGzC,IAAOM,EAAQ,CACb,OAAQR,EAAgB,OACxB,SAAUA,EACV,SAAUE,CACZ","names":["removable_exports","__export","removable_default","registerRemovable","removableMetadata","removableSource","removableSchema","resolveRuntime","win","removableSource","removableSchema","removableMetadata","registerRemovable","hyperfixi","hf","resolveRuntime","result","ctx","removable_default"]}
1
+ {"version":3,"sources":["../src/behaviors/removable.ts","../src/schemas/removable.schema.ts","../src/schemas/types.ts"],"sourcesContent":["/**\n * Removable Behavior\n *\n * A behavior that removes an element when a trigger is clicked.\n * Supports optional confirmation and transition effects.\n *\n * @example\n * ```html\n * <div _=\"install Removable\">Click to remove</div>\n *\n * <div _=\"install Removable(confirm: true)\">With confirmation</div>\n * ```\n */\n\nimport { removableSchema } from '../schemas/removable.schema';\nimport type { LokaScriptInstance } from '../schemas/types';\nimport { resolveRuntime } from '../schemas/types';\n\n// Re-export schema-derived values for backwards compatibility\nexport const removableSource = removableSchema.source;\nexport const removableMetadata = removableSchema;\n\n/**\n * Register the Removable behavior with LokaScript.\n */\nexport async function registerRemovable(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(removableSchema.source, { traditional: true });\n\n if (!result.ok) {\n throw new Error(`Failed to compile Removable 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 registerRemovable().catch(console.error);\n}\n\nexport default {\n source: removableSchema.source,\n metadata: removableSchema,\n register: registerRemovable,\n};\n","import type { BehaviorSchema } from './types';\n\n/**\n * Removable Behavior Schema\n *\n * Removes an element when a trigger is clicked.\n * Supports optional confirmation and transition effects.\n *\n * @since 1.2.0 — `trigger` parameter renamed to `triggerEl` to avoid\n * shadowing the hyperscript `trigger` command keyword. Users migrating\n * from v1.x should update: `install Removable(triggerEl: .close-btn)`.\n */\nexport const removableSchema: BehaviorSchema = {\n name: 'Removable',\n category: 'data',\n tier: 'common',\n version: '1.2.0',\n description: 'Makes elements removable on click',\n parameters: [\n {\n name: 'triggerEl',\n type: 'selector',\n optional: true,\n default: 'me',\n description: 'Element that triggers removal (e.g., a close button)',\n },\n {\n name: 'confirmRemoval',\n type: 'boolean',\n optional: true,\n default: false,\n description: 'Show confirmation dialog before removal',\n },\n {\n name: 'effect',\n type: 'string',\n optional: true,\n default: 'none',\n enum: ['fade', 'none'],\n description: 'Transition effect: \"fade\" or \"none\"',\n },\n ],\n events: [\n { name: 'removable:before', description: 'Fired before removal (cancelable)' },\n { name: 'removable:removed', description: 'Fired after removal' },\n ],\n source: `\nbehavior Removable(triggerEl, confirmRemoval, effect)\n init\n if triggerEl is undefined\n set triggerEl to me\n end\n end\n on click from triggerEl\n if confirmRemoval\n js(me)\n if (!window.confirm(\"Are you sure?\")) return \"cancel\";\n end\n if it is \"cancel\"\n halt\n end\n end\n trigger removable:before\n if effect is \"fade\"\n transition opacity to 0 over 300ms\n end\n trigger removable:removed\n remove me\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":"scAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,aAAAE,EAAA,sBAAAC,EAAA,sBAAAC,EAAA,oBAAAC,ICYO,IAAMC,EAAkC,CAC7C,KAAM,YACN,SAAU,OACV,KAAM,SACN,QAAS,QACT,YAAa,oCACb,WAAY,CACV,CACE,KAAM,YACN,KAAM,WACN,SAAU,GACV,QAAS,KACT,YAAa,sDACf,EACA,CACE,KAAM,iBACN,KAAM,UACN,SAAU,GACV,QAAS,GACT,YAAa,yCACf,EACA,CACE,KAAM,SACN,KAAM,SACN,SAAU,GACV,QAAS,OACT,KAAM,CAAC,OAAQ,MAAM,EACrB,YAAa,qCACf,CACF,EACA,OAAQ,CACN,CAAE,KAAM,mBAAoB,YAAa,mCAAoC,EAC7E,CAAE,KAAM,oBAAqB,YAAa,qBAAsB,CAClE,EACA,OAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAwBR,KAAK,CACP,EC2CO,SAASC,GAA4C,CAC1D,GAAI,OAAO,OAAW,IAAa,OAAO,KAC1C,IAAMC,EAAM,OACZ,OAAOA,EAAI,YAAcA,EAAI,WAAa,IAC5C,CFnGO,IAAMC,EAAkBC,EAAgB,OAClCC,EAAoBD,EAKjC,eAAsBE,EAAkBC,EAA+C,CACrF,IAAMC,EAAKD,GAAaE,EAAe,EAEvC,GAAI,CAACD,EACH,MAAM,IAAI,MACR,yFACF,EAGF,IAAME,EAASF,EAAG,YAAYJ,EAAgB,OAAQ,CAAE,YAAa,EAAK,CAAC,EAE3E,GAAI,CAACM,EAAO,GACV,MAAM,IAAI,MAAM,yCAAyC,KAAK,UAAUA,EAAO,MAAM,CAAC,EAAE,EAG1F,IAAMC,EAAMH,EAAG,cAAgBA,EAAG,cAAc,EAAI,CAAE,OAAQ,IAAI,IAAO,QAAS,IAAI,GAAM,EAC5F,MAAMA,EAAG,QAAQE,EAAO,IAAKC,CAAG,CAClC,CAGIF,EAAe,GACjBH,EAAkB,EAAE,MAAM,QAAQ,KAAK,EAGzC,IAAOM,EAAQ,CACb,OAAQR,EAAgB,OACxB,SAAUA,EACV,SAAUE,CACZ","names":["removable_exports","__export","removable_default","registerRemovable","removableMetadata","removableSource","removableSchema","resolveRuntime","win","removableSource","removableSchema","removableMetadata","registerRemovable","hyperfixi","hf","resolveRuntime","result","ctx","removable_default"]}
@@ -1,11 +1,21 @@
1
- "use strict";var HyperFixiBehaviors=(()=>{var s=Object.defineProperty;var y=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var W=Object.prototype.hasOwnProperty;var z=(t,e)=>{for(var i in e)s(t,i,{get:e[i],enumerable:!0})},S=(t,e,i,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of H(e))!W.call(t,n)&&n!==i&&s(t,n,{get:()=>e[n],enumerable:!(r=y(e,n))||r.enumerable});return t};var k=t=>S(s({},"__esModule",{value:!0}),t);var C={};z(C,{default:()=>B,registerResizable:()=>h,resizableMetadata:()=>M,resizableSource:()=>E});var a={name:"Resizable",category:"ui",tier:"optional",version:"1.0.0",description:"Makes elements resizable by dragging",parameters:[{name:"handle",type:"selector",optional:!0,default:"me",description:"CSS selector for the resize handle (defaults to the element itself)"},{name:"minWidth",type:"number",optional:!0,default:50,description:"Minimum width in pixels"},{name:"minHeight",type:"number",optional:!0,default:50,description:"Minimum height in pixels"},{name:"maxWidth",type:"number",optional:!0,default:9999,description:"Maximum width in pixels"},{name:"maxHeight",type:"number",optional:!0,default:9999,description:"Maximum height in pixels"}],events:[{name:"resizable:start",description:"Fired when resize begins"},{name:"resizable:resize",description:"Fired during resize"},{name:"resizable:end",description:"Fired when resize completes"}],source:`
1
+ "use strict";var HyperFixiBehaviors=(()=>{var s=Object.defineProperty;var w=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var z=Object.prototype.hasOwnProperty;var W=(t,e)=>{for(var i in e)s(t,i,{get:e[i],enumerable:!0})},M=(t,e,i,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of H(e))!z.call(t,n)&&n!==i&&s(t,n,{get:()=>e[n],enumerable:!(r=w(e,n))||r.enumerable});return t};var S=t=>M(s({},"__esModule",{value:!0}),t);var Y={};W(Y,{default:()=>X,registerResizable:()=>c,resizableMetadata:()=>E,resizableSource:()=>k});var a={name:"Resizable",category:"ui",tier:"optional",version:"1.0.0",description:"Makes elements resizable by dragging",parameters:[{name:"handle",type:"selector",optional:!0,default:"me",description:"CSS selector for the resize handle (defaults to the element itself)"},{name:"minWidth",type:"number",optional:!0,default:50,description:"Minimum width in pixels"},{name:"minHeight",type:"number",optional:!0,default:50,description:"Minimum height in pixels"},{name:"maxWidth",type:"number",optional:!0,default:9999,description:"Maximum width in pixels"},{name:"maxHeight",type:"number",optional:!0,default:9999,description:"Maximum height in pixels"}],events:[{name:"resizable:start",description:"Fired when resize begins"},{name:"resizable:resize",description:"Fired during resize"},{name:"resizable:end",description:"Fired when resize completes"}],source:`
2
2
  behavior Resizable(handle, minWidth, minHeight, maxWidth, maxHeight)
3
3
  init
4
- if no handle set handle to me
5
- if no minWidth set minWidth to 50
6
- if no minHeight set minHeight to 50
7
- if no maxWidth set maxWidth to 9999
8
- if no maxHeight set maxHeight to 9999
4
+ if handle is undefined
5
+ set handle to me
6
+ end
7
+ if minWidth is undefined
8
+ set minWidth to 50
9
+ end
10
+ if minHeight is undefined
11
+ set minHeight to 50
12
+ end
13
+ if maxWidth is undefined
14
+ set maxWidth to 9999
15
+ end
16
+ if maxHeight is undefined
17
+ set maxHeight to 9999
18
+ end
9
19
  end
10
20
  on pointerdown(clientX, clientY) from handle
11
21
  halt the event
@@ -17,19 +27,17 @@ behavior Resizable(handle, minWidth, minHeight, maxWidth, maxHeight)
17
27
  set startX to clientX
18
28
  set startY to clientY
19
29
  repeat until event pointerup from document
20
- wait for pointermove(clientX, clientY) or
21
- pointerup from document
22
- set newWidth to startWidth + (clientX - startX)
23
- set newHeight to startHeight + (clientY - startY)
24
- if newWidth < minWidth set newWidth to minWidth
25
- if newWidth > maxWidth set newWidth to maxWidth
26
- if newHeight < minHeight set newHeight to minHeight
27
- if newHeight > maxHeight set newHeight to maxHeight
28
- add { width: \${newWidth}px; height: \${newHeight}px; }
30
+ wait for pointermove(clientX, clientY) or pointerup from document
31
+ js(startWidth, startHeight, clientX, clientY, startX, startY, minWidth, maxWidth, minHeight, maxHeight, me)
32
+ var nw = Math.max(minWidth, Math.min(maxWidth, startWidth + (clientX - startX)));
33
+ var nh = Math.max(minHeight, Math.min(maxHeight, startHeight + (clientY - startY)));
34
+ me.style.width = nw + 'px';
35
+ me.style.height = nh + 'px';
36
+ end
29
37
  trigger resizable:resize
30
38
  end
31
39
  trigger resizable:end
32
40
  end
33
41
  end
34
- `.trim()};function c(){if(typeof window>"u")return null;let t=window;return t.lokascript||t.hyperfixi||null}var E=a.source,M=a;function L(t,e){let i=t;if(e.handle&&e.handle!=="me")if(typeof e.handle=="string"){let o=t.querySelector(e.handle);o instanceof HTMLElement&&(i=o)}else e.handle instanceof HTMLElement&&(i=e.handle);let r=e.minWidth??50,n=e.minHeight??50,p=e.maxWidth??9999,u=e.maxHeight??9999;i.addEventListener("pointerdown",o=>{o.preventDefault(),t.dispatchEvent(new CustomEvent("resizable:start",{bubbles:!0}));let g=t.offsetWidth,f=t.offsetHeight,x=o.clientX,b=o.clientY;function m(l){let v=Math.max(r,Math.min(p,g+(l.clientX-x))),w=Math.max(n,Math.min(u,f+(l.clientY-b)));t.style.width=`${v}px`,t.style.height=`${w}px`,t.dispatchEvent(new CustomEvent("resizable:resize",{bubbles:!0}))}function d(){document.removeEventListener("pointermove",m),document.removeEventListener("pointerup",d),t.dispatchEvent(new CustomEvent("resizable:end",{bubbles:!0}))}document.addEventListener("pointermove",m),document.addEventListener("pointerup",d)})}async function h(t){let e=t||c();if(!e)throw new Error("LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors.");let i={type:"behavior",name:"Resizable",parameters:["handle","minWidth","minHeight","maxWidth","maxHeight"],eventHandlers:[],imperativeInstaller:L},r=e.createContext?e.createContext():{locals:new Map,globals:new Map};await e.execute(i,r)}c()&&h().catch(console.error);var B={source:a.source,metadata:a,register:h};return k(C);})();
42
+ `.trim()};function d(){if(typeof window>"u")return null;let t=window;return t.lokascript||t.hyperfixi||null}var k=a.source,E=a;function L(t,e){let i=t;if(e.handle&&e.handle!=="me")if(typeof e.handle=="string"){let o=t.querySelector(e.handle);o instanceof HTMLElement&&(i=o)}else e.handle instanceof HTMLElement&&(i=e.handle);let r=e.minWidth??50,n=e.minHeight??50,p=e.maxWidth??9999,u=e.maxHeight??9999;i.addEventListener("pointerdown",o=>{o.preventDefault(),t.dispatchEvent(new CustomEvent("resizable:start",{bubbles:!0}));let g=t.offsetWidth,f=t.offsetHeight,x=o.clientX,b=o.clientY;function m(l){let v=Math.max(r,Math.min(p,g+(l.clientX-x))),y=Math.max(n,Math.min(u,f+(l.clientY-b)));t.style.width=`${v}px`,t.style.height=`${y}px`,t.dispatchEvent(new CustomEvent("resizable:resize",{bubbles:!0}))}function h(){document.removeEventListener("pointermove",m),document.removeEventListener("pointerup",h),t.dispatchEvent(new CustomEvent("resizable:end",{bubbles:!0}))}document.addEventListener("pointermove",m),document.addEventListener("pointerup",h)})}async function c(t){let e=t||d();if(!e)throw new Error("LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors.");let i={type:"behavior",name:"Resizable",parameters:["handle","minWidth","minHeight","maxWidth","maxHeight"],eventHandlers:[],imperativeInstaller:L},r=e.createContext?e.createContext():{locals:new Map,globals:new Map};await e.execute(i,r)}d()&&c().catch(console.error);var X={source:a.source,metadata:a,register:c};return S(Y);})();
35
43
  //# sourceMappingURL=resizable.browser.global.js.map
@@ -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: ['handle', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight'],\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: 'handle',\n type: 'selector',\n optional: true,\n default: 'me',\n description: 'CSS selector for the resize handle (defaults to the element itself)',\n },\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(handle, minWidth, minHeight, maxWidth, maxHeight)\n init\n if no handle set handle to me\n if no minWidth set minWidth to 50\n if no minHeight set minHeight to 50\n if no maxWidth set maxWidth to 9999\n if no maxHeight set maxHeight to 9999\n end\n on pointerdown(clientX, clientY) from handle\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\n pointerup from document\n set newWidth to startWidth + (clientX - startX)\n set newHeight to startHeight + (clientY - startY)\n if newWidth < minWidth set newWidth to minWidth\n if newWidth > maxWidth set newWidth to maxWidth\n if newHeight < minHeight set newHeight to minHeight\n if newHeight > maxHeight set newHeight to maxHeight\n add { width: \\${newWidth}px; height: \\${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":["resizable_exports","__export","resizable_default","registerResizable","resizableMetadata","resizableSource","resizableSchema","resolveRuntime","win","resizableSource","resizableSchema","resizableMetadata","installResizable","element","params","handleEl","found","minW","minH","maxW","maxH","e","startWidth","startHeight","startX","startY","onMove","ev","newWidth","newHeight","onUp","registerResizable","hyperfixi","hf","resolveRuntime","syntheticNode","ctx","resizable_default"]}
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: ['handle', 'minWidth', 'minHeight', 'maxWidth', 'maxHeight'],\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: 'handle',\n type: 'selector',\n optional: true,\n default: 'me',\n description: 'CSS selector for the resize handle (defaults to the element itself)',\n },\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(handle, minWidth, minHeight, maxWidth, maxHeight)\n init\n if handle is undefined\n set handle to me\n end\n if minWidth is undefined\n set minWidth to 50\n end\n if minHeight is undefined\n set minHeight to 50\n end\n if maxWidth is undefined\n set maxWidth to 9999\n end\n if maxHeight is undefined\n set maxHeight to 9999\n end\n end\n on pointerdown(clientX, clientY) from handle\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 from document\n js(startWidth, startHeight, clientX, clientY, startX, startY, minWidth, maxWidth, minHeight, maxHeight, me)\n var nw = Math.max(minWidth, Math.min(maxWidth, startWidth + (clientX - startX)));\n var nh = Math.max(minHeight, Math.min(maxHeight, startHeight + (clientY - startY)));\n me.style.width = nw + 'px';\n me.style.height = nh + 'px';\n end\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":["resizable_exports","__export","resizable_default","registerResizable","resizableMetadata","resizableSource","resizableSchema","resolveRuntime","win","resizableSource","resizableSchema","resizableMetadata","installResizable","element","params","handleEl","found","minW","minH","maxW","maxH","e","startWidth","startHeight","startX","startY","onMove","ev","newWidth","newHeight","onUp","registerResizable","hyperfixi","hf","resolveRuntime","syntheticNode","ctx","resizable_default"]}
@@ -0,0 +1,407 @@
1
+ "use strict";var HyperFixiBehaviors=(()=>{var a={name:"Toggleable",category:"form",tier:"core",version:"1.0.0",description:"Toggles a CSS class on click",parameters:[{name:"cls",type:"string",optional:!0,default:"active",description:"CSS class to toggle"},{name:"target",type:"selector",optional:!0,default:"me",description:"Element to toggle the class on"}],events:[{name:"toggleable:on",description:"Fired when class is added"},{name:"toggleable:off",description:"Fired when class is removed"}],source:`
2
+ behavior Toggleable(cls, target)
3
+ init
4
+ if cls is undefined
5
+ set cls to "active"
6
+ end
7
+ if target is undefined
8
+ set target to me
9
+ end
10
+ end
11
+ on click
12
+ toggle .{cls} on target
13
+ js(target, cls)
14
+ var eventName = target.classList.contains(cls) ? 'toggleable:on' : 'toggleable:off';
15
+ target.dispatchEvent(new CustomEvent(eventName, { bubbles: true }));
16
+ end
17
+ end
18
+ end`.trim()};var r={name:"Removable",category:"data",tier:"common",version:"1.2.0",description:"Makes elements removable on click",parameters:[{name:"triggerEl",type:"selector",optional:!0,default:"me",description:"Element that triggers removal (e.g., a close button)"},{name:"confirmRemoval",type:"boolean",optional:!0,default:!1,description:"Show confirmation dialog before removal"},{name:"effect",type:"string",optional:!0,default:"none",enum:["fade","none"],description:'Transition effect: "fade" or "none"'}],events:[{name:"removable:before",description:"Fired before removal (cancelable)"},{name:"removable:removed",description:"Fired after removal"}],source:`
19
+ behavior Removable(triggerEl, confirmRemoval, effect)
20
+ init
21
+ if triggerEl is undefined
22
+ set triggerEl to me
23
+ end
24
+ end
25
+ on click from triggerEl
26
+ if confirmRemoval
27
+ js(me)
28
+ if (!window.confirm("Are you sure?")) return "cancel";
29
+ end
30
+ if it is "cancel"
31
+ halt
32
+ end
33
+ end
34
+ trigger removable:before
35
+ if effect is "fade"
36
+ transition opacity to 0 over 300ms
37
+ end
38
+ trigger removable:removed
39
+ remove me
40
+ end
41
+ end
42
+ `.trim()};var n={name:"AutoDismiss",category:"ui",tier:"core",version:"1.0.0",description:"Auto-removes elements after a delay with optional pause-on-hover",parameters:[{name:"delay",type:"number",optional:!0,default:5e3,description:"Time in ms before the element is removed"},{name:"pauseOnHover",type:"boolean",optional:!0,default:!0,description:"Pause the countdown when the mouse hovers over the element"},{name:"effect",type:"string",optional:!0,default:"none",enum:["fade","none"],description:'Transition effect before removal: "fade" or "none"'}],events:[{name:"autodismiss:start",description:"Fired when the countdown timer starts"},{name:"autodismiss:dismissed",description:"Fired before removal (cancelable via preventDefault)"},{name:"autodismiss:paused",description:"Fired when the timer is paused on hover"},{name:"autodismiss:resumed",description:"Fired when the timer resumes on mouseleave"}],source:`
43
+ behavior AutoDismiss(delay, pauseOnHover, effect)
44
+ init
45
+ if delay is undefined
46
+ set delay to 5000
47
+ end
48
+ if pauseOnHover is undefined
49
+ set pauseOnHover to true
50
+ end
51
+ if effect is undefined
52
+ set effect to "none"
53
+ end
54
+ js(me, delay, effect, pauseOnHover)
55
+ me.dispatchEvent(new CustomEvent('autodismiss:start', { bubbles: true }));
56
+ var remaining = delay;
57
+ var startedAt = Date.now();
58
+ var timerId = null;
59
+ function dismiss() {
60
+ var ev = new CustomEvent('autodismiss:dismissed', { bubbles: true, cancelable: true });
61
+ me.dispatchEvent(ev);
62
+ if (ev.defaultPrevented) return;
63
+ if (effect === 'fade') {
64
+ me.style.transition = 'opacity 300ms';
65
+ me.style.opacity = '0';
66
+ setTimeout(function() { me.remove(); }, 300);
67
+ } else {
68
+ me.remove();
69
+ }
70
+ }
71
+ function start() {
72
+ startedAt = Date.now();
73
+ timerId = setTimeout(dismiss, remaining);
74
+ }
75
+ start();
76
+ if (pauseOnHover) {
77
+ me.addEventListener('mouseenter', function() {
78
+ if (timerId != null) {
79
+ clearTimeout(timerId);
80
+ timerId = null;
81
+ remaining -= Date.now() - startedAt;
82
+ if (remaining < 0) remaining = 0;
83
+ me.dispatchEvent(new CustomEvent('autodismiss:paused', { bubbles: true }));
84
+ }
85
+ });
86
+ me.addEventListener('mouseleave', function() {
87
+ if (timerId == null && me.isConnected) {
88
+ me.dispatchEvent(new CustomEvent('autodismiss:resumed', { bubbles: true }));
89
+ start();
90
+ }
91
+ });
92
+ }
93
+ end
94
+ end
95
+ end`.trim()};var o={name:"Clipboard",category:"ui",tier:"core",version:"1.0.0",description:"Copies text to clipboard on click with visual feedback",parameters:[{name:"text",type:"string",optional:!0,description:"Literal text to copy (takes priority over source)"},{name:"source",type:"selector",optional:!0,default:"me",description:"Element whose textContent or value is copied"},{name:"feedback",type:"selector",optional:!0,description:"Element to show .copied feedback on (defaults to the installed element)"},{name:"feedbackDuration",type:"number",optional:!0,default:2e3,description:"Duration in ms to show .copied class feedback"}],events:[{name:"clipboard:copied",description:"Fired after text is copied successfully"},{name:"clipboard:error",description:"Fired when clipboard write fails"}],requirements:["navigator.clipboard.writeText() requires HTTPS or localhost",'Falls back to document.execCommand("copy") for older browsers'],source:`
96
+ behavior Clipboard(text, source, feedback, feedbackDuration)
97
+ init
98
+ if feedbackDuration is undefined
99
+ set feedbackDuration to 2000
100
+ end
101
+ if source is undefined
102
+ set source to me
103
+ end
104
+ end
105
+ on click
106
+ if text is not undefined
107
+ set copyText to text
108
+ else
109
+ set copyText to source's textContent
110
+ end
111
+ js(me, copyText, feedback, feedbackDuration)
112
+ async function copyToClipboard(t) {
113
+ if (navigator.clipboard && navigator.clipboard.writeText) {
114
+ await navigator.clipboard.writeText(t);
115
+ return;
116
+ }
117
+ var ta = document.createElement('textarea');
118
+ ta.value = t;
119
+ ta.style.position = 'fixed';
120
+ ta.style.opacity = '0';
121
+ document.body.appendChild(ta);
122
+ ta.select();
123
+ try { document.execCommand('copy'); } finally { document.body.removeChild(ta); }
124
+ }
125
+ try {
126
+ await copyToClipboard(copyText);
127
+ var feedbackEl = feedback ? (typeof feedback === 'string' ? document.querySelector(feedback) : feedback) : me;
128
+ if (!feedbackEl) feedbackEl = me;
129
+ feedbackEl.classList.add('copied');
130
+ me.dispatchEvent(new CustomEvent('clipboard:copied', { bubbles: true, detail: { text: copyText } }));
131
+ setTimeout(function() { feedbackEl.classList.remove('copied'); }, feedbackDuration);
132
+ } catch(err) {
133
+ me.dispatchEvent(new CustomEvent('clipboard:error', { bubbles: true, detail: { error: err } }));
134
+ }
135
+ end
136
+ end
137
+ end`.trim()};var s={name:"Draggable",category:"ui",tier:"core",version:"1.0.0",description:"Makes elements draggable with pointer events",parameters:[{name:"dragHandle",type:"selector",optional:!0,default:"me",description:"CSS selector for the drag handle element"}],events:[{name:"draggable:start",description:"Fired when drag begins"},{name:"draggable:move",description:"Fired during each movement"},{name:"draggable:end",description:"Fired when drag completes"}],requirements:["position: absolute or position: fixed on the element"],source:`
138
+ behavior Draggable(dragHandle)
139
+ init
140
+ if no dragHandle set dragHandle to me
141
+ end
142
+ on pointerdown(clientX, clientY) from dragHandle
143
+ halt the event
144
+ trigger draggable:start
145
+ measure x
146
+ set startX to it
147
+ measure y
148
+ set startY to it
149
+ set xoff to clientX - startX
150
+ set yoff to clientY - startY
151
+ repeat until event pointerup from document
152
+ wait for pointermove(clientX, clientY) or
153
+ pointerup(clientX, clientY) from document
154
+ add { left: \${clientX - xoff}px; top: \${clientY - yoff}px; }
155
+ trigger draggable:move
156
+ end
157
+ trigger draggable:end
158
+ end
159
+ end
160
+ `.trim()};var c={name:"ClickOutside",category:"ui",tier:"core",version:"1.0.0",description:"Fires an event when the user clicks outside the element",parameters:[{name:"active",type:"boolean",optional:!0,default:!0,description:"Whether the listener is active (can be toggled programmatically)"}],events:[{name:"clickoutside",description:"Fired when a pointer press occurs outside the element"},{name:"clickoutside:activate",description:"Listen for this event to programmatically activate detection"},{name:"clickoutside:deactivate",description:"Listen for this event to programmatically deactivate detection"}],requirements:["Uses pointerdown instead of click to avoid timing issues with removed elements"],source:`
161
+ behavior ClickOutside(active)
162
+ init
163
+ if active is undefined
164
+ set active to true
165
+ end
166
+ end
167
+ on pointerdown from document
168
+ js(me, active)
169
+ if (!me.isConnected) return;
170
+ if (active && !me.contains(event.target)) {
171
+ me.dispatchEvent(new CustomEvent('clickoutside', { bubbles: true }));
172
+ }
173
+ end
174
+ end
175
+ on clickoutside:activate
176
+ set active to true
177
+ end
178
+ on clickoutside:deactivate
179
+ set active to false
180
+ end
181
+ end`.trim()};var d={name:"ScrollReveal",category:"layout",tier:"common",version:"1.0.0",description:"Adds a class when the element enters the viewport via IntersectionObserver",parameters:[{name:"cls",type:"string",optional:!0,default:"revealed",description:"CSS class added when element enters viewport"},{name:"threshold",type:"number",optional:!0,default:.1,description:"Intersection ratio threshold (0-1) for triggering"},{name:"once",type:"boolean",optional:!0,default:!0,description:"If true, disconnect observer after first intersection"}],events:[{name:"scrollreveal:enter",description:"Fired when the element enters the viewport"},{name:"scrollreveal:exit",description:"Fired when the element exits the viewport"}],requirements:["Uses IntersectionObserver API (supported in all modern browsers)"],source:`
182
+ behavior ScrollReveal(cls, threshold, once)
183
+ init
184
+ if cls is undefined
185
+ set cls to "revealed"
186
+ end
187
+ if threshold is undefined
188
+ set threshold to 0.1
189
+ end
190
+ if once is undefined
191
+ set once to true
192
+ end
193
+ js(me, cls, threshold, once)
194
+ var obs = new IntersectionObserver(function(entries) {
195
+ for (var i = 0; i < entries.length; i++) {
196
+ if (entries[i].isIntersecting) {
197
+ me.classList.add(cls);
198
+ me.dispatchEvent(new CustomEvent('scrollreveal:enter', { bubbles: true }));
199
+ if (once) obs.disconnect();
200
+ } else if (!once) {
201
+ me.classList.remove(cls);
202
+ me.dispatchEvent(new CustomEvent('scrollreveal:exit', { bubbles: true }));
203
+ }
204
+ }
205
+ }, { threshold: threshold });
206
+ obs.observe(me);
207
+ end
208
+ end
209
+ end`.trim()};var l={name:"Tabs",category:"ui",tier:"core",version:"1.0.0",description:"WAI-ARIA compliant tabs with roving tabindex keyboard navigation. Auto-wires role, aria-selected, aria-controls, and aria-labelledby attributes.",parameters:[{name:"orientation",type:"string",optional:!0,default:"horizontal",enum:["horizontal","vertical"],description:"Arrow key direction: horizontal (Left/Right) or vertical (Up/Down)"},{name:"activeTab",type:"number",optional:!0,default:0,description:"Initial active tab index (zero-based)"},{name:"wrap",type:"boolean",optional:!0,default:!0,description:"Wrap to first/last tab when navigating past the end"},{name:"activeClass",type:"string",optional:!0,default:"active",description:"CSS class applied to the active tab and its panel"}],events:[{name:"tabs:change",description:"Fired before tab selection changes (cancelable via preventDefault)"},{name:"tabs:changed",description:"Fired after tab selection has changed"}],requirements:['Sets role="tablist" on the tab container','Sets role="tab" on tab buttons and role="tabpanel" on content panels',"Manages aria-selected, aria-controls, aria-labelledby, and tabindex","Keyboard: Arrow keys navigate, Home/End jump to first/last, Tab exits tablist"],source:`
210
+ behavior Tabs(orientation, activeTab, wrap, activeClass)
211
+ init
212
+ if orientation is undefined
213
+ set orientation to "horizontal"
214
+ end
215
+ if activeTab is undefined
216
+ set activeTab to 0
217
+ end
218
+ if wrap is undefined
219
+ set wrap to true
220
+ end
221
+ if activeClass is undefined
222
+ set activeClass to "active"
223
+ end
224
+ js(me, orientation, activeTab, wrap, activeClass)
225
+ var tabs = Array.from(me.querySelectorAll('[role="tab"]'));
226
+ var panels = Array.from(me.querySelectorAll('[role="tabpanel"]'));
227
+ if (tabs.length === 0 || panels.length === 0) return;
228
+ var tablist = me.querySelector('[role="tablist"]') || tabs[0].parentElement;
229
+ if (tablist) tablist.setAttribute('aria-orientation', orientation);
230
+ var count = Math.min(tabs.length, panels.length);
231
+ var idN = 0;
232
+ for (var i = 0; i < count; i++) {
233
+ if (!tabs[i].id) tabs[i].id = 'tab-' + (++idN);
234
+ if (!panels[i].id) panels[i].id = 'tabpanel-' + idN;
235
+ tabs[i].setAttribute('aria-controls', panels[i].id);
236
+ panels[i].setAttribute('aria-labelledby', tabs[i].id);
237
+ }
238
+ var cur = Math.max(0, Math.min(activeTab, count - 1));
239
+ function activate(idx, prev) {
240
+ if (idx === prev || idx < 0 || idx >= count) return false;
241
+ var ev = new CustomEvent('tabs:change', { bubbles: true, cancelable: true, detail: { index: idx, previousIndex: prev } });
242
+ me.dispatchEvent(ev);
243
+ if (ev.defaultPrevented) return false;
244
+ if (prev >= 0 && prev < count) {
245
+ tabs[prev].setAttribute('aria-selected', 'false');
246
+ tabs[prev].setAttribute('tabindex', '-1');
247
+ tabs[prev].classList.remove(activeClass);
248
+ panels[prev].setAttribute('aria-hidden', 'true');
249
+ panels[prev].classList.remove(activeClass);
250
+ }
251
+ tabs[idx].setAttribute('aria-selected', 'true');
252
+ tabs[idx].setAttribute('tabindex', '0');
253
+ tabs[idx].classList.add(activeClass);
254
+ panels[idx].setAttribute('aria-hidden', 'false');
255
+ panels[idx].classList.add(activeClass);
256
+ cur = idx;
257
+ me.dispatchEvent(new CustomEvent('tabs:changed', { bubbles: true, detail: { index: idx } }));
258
+ return true;
259
+ }
260
+ for (var j = 0; j < count; j++) {
261
+ tabs[j].setAttribute('aria-selected', 'false');
262
+ tabs[j].setAttribute('tabindex', '-1');
263
+ panels[j].setAttribute('aria-hidden', 'true');
264
+ panels[j].classList.remove(activeClass);
265
+ }
266
+ tabs[cur].setAttribute('aria-selected', 'true');
267
+ tabs[cur].setAttribute('tabindex', '0');
268
+ tabs[cur].classList.add(activeClass);
269
+ panels[cur].setAttribute('aria-hidden', 'false');
270
+ panels[cur].classList.add(activeClass);
271
+ for (var k = 0; k < count; k++) {
272
+ (function(idx) {
273
+ tabs[idx].addEventListener('click', function() { if (activate(idx, cur)) tabs[idx].focus(); });
274
+ })(k);
275
+ }
276
+ (tablist || me).addEventListener('keydown', function(e) {
277
+ var nk = orientation === 'horizontal' ? 'ArrowRight' : 'ArrowDown';
278
+ var pk = orientation === 'horizontal' ? 'ArrowLeft' : 'ArrowUp';
279
+ var next = null;
280
+ if (e.key === nk) { next = cur + 1; if (next >= count) next = wrap ? 0 : null; }
281
+ else if (e.key === pk) { next = cur - 1; if (next < 0) next = wrap ? count - 1 : null; }
282
+ else if (e.key === 'Home') next = 0;
283
+ else if (e.key === 'End') next = count - 1;
284
+ if (next !== null) { e.preventDefault(); if (activate(next, cur)) tabs[next].focus(); }
285
+ });
286
+ end
287
+ end
288
+ end`.trim()};var m={name:"FocusTrap",category:"ui",tier:"core",version:"1.0.0",description:"Confines Tab navigation inside an element with ARIA support",parameters:[{name:"active",type:"boolean",optional:!0,default:!0,description:"Whether the trap is active on install"},{name:"initialFocus",type:"selector",optional:!0,description:"Element to focus when the trap activates"},{name:"returnFocus",type:"boolean",optional:!0,default:!0,description:"Restore focus to the previously focused element on deactivation"}],events:[{name:"focustrap:activated",description:"Fired when the trap is activated"},{name:"focustrap:deactivated",description:"Fired when the trap is deactivated"}],requirements:['Sets aria-modal="true" on the element when active',"Listens for focustrap:activate and focustrap:deactivate custom events for programmatic control"],source:`
289
+ behavior FocusTrap(active, initialFocus, returnFocus)
290
+ init
291
+ if active is undefined
292
+ set active to true
293
+ end
294
+ if returnFocus is undefined
295
+ set returnFocus to true
296
+ end
297
+ js(me, active, initialFocus, returnFocus)
298
+ var FOCUSABLE = 'a[href],button:not(:disabled),input:not(:disabled),select:not(:disabled),textarea:not(:disabled),[tabindex]:not([tabindex="-1"])';
299
+ var isActive = false;
300
+ var previouslyFocused = null;
301
+ function getFocusable() { return Array.from(me.querySelectorAll(FOCUSABLE)); }
302
+ function activate() {
303
+ if (isActive) return;
304
+ isActive = true;
305
+ previouslyFocused = document.activeElement;
306
+ me.setAttribute('aria-modal', 'true');
307
+ var initEl = initialFocus ? (typeof initialFocus === 'string' ? me.querySelector(initialFocus) : initialFocus) : null;
308
+ if (initEl) { initEl.focus(); } else { var f = getFocusable(); if (f.length) f[0].focus(); }
309
+ me.dispatchEvent(new CustomEvent('focustrap:activated', { bubbles: true }));
310
+ }
311
+ function deactivate() {
312
+ if (!isActive) return;
313
+ isActive = false;
314
+ me.removeAttribute('aria-modal');
315
+ if (returnFocus && previouslyFocused instanceof HTMLElement) previouslyFocused.focus();
316
+ previouslyFocused = null;
317
+ me.dispatchEvent(new CustomEvent('focustrap:deactivated', { bubbles: true }));
318
+ }
319
+ me.addEventListener('keydown', function(e) {
320
+ if (!isActive || e.key !== 'Tab') return;
321
+ var focusable = getFocusable();
322
+ if (focusable.length === 0) { e.preventDefault(); return; }
323
+ e.preventDefault();
324
+ var idx = focusable.indexOf(document.activeElement);
325
+ if (e.shiftKey) {
326
+ focusable[idx <= 0 ? focusable.length - 1 : idx - 1].focus();
327
+ } else {
328
+ focusable[idx >= focusable.length - 1 ? 0 : idx + 1].focus();
329
+ }
330
+ });
331
+ me.addEventListener('focustrap:activate', function() { activate(); });
332
+ me.addEventListener('focustrap:deactivate', function() { deactivate(); });
333
+ if (active) activate();
334
+ end
335
+ end
336
+ end`.trim()};var u={name:"Sortable",category:"ui",tier:"common",version:"1.0.0",description:"Makes child elements reorderable via drag-and-drop",parameters:[{name:"handle",type:"selector",optional:!0,default:"none",description:"CSS selector for drag handles within items"},{name:"dragClass",type:"string",optional:!0,default:"sorting",description:"CSS class added to item during drag"}],events:[{name:"sortable:start",description:"Fired when drag begins"},{name:"sortable:move",description:"Fired during drag \u2014 handle this event to reorder DOM elements"},{name:"sortable:end",description:"Fired when drag completes"}],requirements:["Users must handle DOM reordering in sortable:move event handlers"],source:`
337
+ behavior Sortable(handle, dragClass)
338
+ init
339
+ if dragClass is undefined
340
+ set dragClass to "sorting"
341
+ end
342
+ end
343
+ on pointerdown(clientY) from me
344
+ js(me, handle, event)
345
+ var target = event.target;
346
+ var item = target.closest("li");
347
+ if (!item || !me.contains(item)) return false;
348
+ if (handle && !target.closest(handle)) return false;
349
+ event.preventDefault();
350
+ event.stopPropagation();
351
+ return true;
352
+ end
353
+ if it is false
354
+ exit
355
+ end
356
+ add .{dragClass} to me
357
+ trigger sortable:start on me
358
+ repeat until event pointerup from document
359
+ wait for pointermove(clientY) from document
360
+ trigger sortable:move on me
361
+ end
362
+ remove .{dragClass} from me
363
+ trigger sortable:end on me
364
+ end
365
+ end`.trim()};var p={name:"Resizable",category:"ui",tier:"optional",version:"1.0.0",description:"Makes elements resizable by dragging",parameters:[{name:"handle",type:"selector",optional:!0,default:"me",description:"CSS selector for the resize handle (defaults to the element itself)"},{name:"minWidth",type:"number",optional:!0,default:50,description:"Minimum width in pixels"},{name:"minHeight",type:"number",optional:!0,default:50,description:"Minimum height in pixels"},{name:"maxWidth",type:"number",optional:!0,default:9999,description:"Maximum width in pixels"},{name:"maxHeight",type:"number",optional:!0,default:9999,description:"Maximum height in pixels"}],events:[{name:"resizable:start",description:"Fired when resize begins"},{name:"resizable:resize",description:"Fired during resize"},{name:"resizable:end",description:"Fired when resize completes"}],source:`
366
+ behavior Resizable(handle, minWidth, minHeight, maxWidth, maxHeight)
367
+ init
368
+ if handle is undefined
369
+ set handle to me
370
+ end
371
+ if minWidth is undefined
372
+ set minWidth to 50
373
+ end
374
+ if minHeight is undefined
375
+ set minHeight to 50
376
+ end
377
+ if maxWidth is undefined
378
+ set maxWidth to 9999
379
+ end
380
+ if maxHeight is undefined
381
+ set maxHeight to 9999
382
+ end
383
+ end
384
+ on pointerdown(clientX, clientY) from handle
385
+ halt the event
386
+ trigger resizable:start
387
+ measure width
388
+ set startWidth to it
389
+ measure height
390
+ set startHeight to it
391
+ set startX to clientX
392
+ set startY to clientY
393
+ repeat until event pointerup from document
394
+ wait for pointermove(clientX, clientY) or pointerup from document
395
+ js(startWidth, startHeight, clientX, clientY, startX, startY, minWidth, maxWidth, minHeight, maxHeight, me)
396
+ var nw = Math.max(minWidth, Math.min(maxWidth, startWidth + (clientX - startX)));
397
+ var nh = Math.max(minHeight, Math.min(maxHeight, startHeight + (clientY - startY)));
398
+ me.style.width = nw + 'px';
399
+ me.style.height = nh + 'px';
400
+ end
401
+ trigger resizable:resize
402
+ end
403
+ trigger resizable:end
404
+ end
405
+ end
406
+ `.trim()};var f={Toggleable:a.source,Removable:r.source,AutoDismiss:n.source,Clipboard:o.source,Draggable:s.source,ClickOutside:c.source,ScrollReveal:d.source,Tabs:l.source,FocusTrap:m.source,Sortable:u.source,Resizable:p.source};function b(){let e=window.hyperfixi;if(!e?.compileSync||!e?.execute)return;for(let[h,v]of Object.entries(f)){let i=e.compileSync(v,{traditional:!0});i?.ok&&i.ast&&e.execute(i.ast).catch(()=>{})}let t=e.attributeProcessor;t&&(t.reset(),t.init())}typeof window<"u"&&b();})();
407
+ //# sourceMappingURL=resolver.browser.global.js.map