@hyperfixi/behaviors 2.5.1 → 2.7.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.
Files changed (182) hide show
  1. package/README.md +100 -0
  2. package/dist/all.browser.global.js +43 -40
  3. package/dist/all.browser.global.js.map +1 -1
  4. package/dist/autodismiss.browser.global.js +2 -2
  5. package/dist/autodismiss.browser.global.js.map +1 -1
  6. package/dist/behaviors/autodismiss.cjs +5 -54
  7. package/dist/behaviors/autodismiss.cjs.map +1 -1
  8. package/dist/behaviors/autodismiss.d.cts +3 -2
  9. package/dist/behaviors/autodismiss.d.ts +3 -2
  10. package/dist/behaviors/autodismiss.js +1 -1
  11. package/dist/behaviors/clickoutside.cjs +6 -28
  12. package/dist/behaviors/clickoutside.cjs.map +1 -1
  13. package/dist/behaviors/clickoutside.d.cts +3 -2
  14. package/dist/behaviors/clickoutside.d.ts +3 -2
  15. package/dist/behaviors/clickoutside.js +2 -2
  16. package/dist/behaviors/clipboard.cjs +30 -86
  17. package/dist/behaviors/clipboard.cjs.map +1 -1
  18. package/dist/behaviors/clipboard.d.cts +3 -2
  19. package/dist/behaviors/clipboard.d.ts +3 -2
  20. package/dist/behaviors/clipboard.js +2 -2
  21. package/dist/behaviors/draggable.cjs +6 -41
  22. package/dist/behaviors/draggable.cjs.map +1 -1
  23. package/dist/behaviors/draggable.d.cts +3 -3
  24. package/dist/behaviors/draggable.d.ts +3 -3
  25. package/dist/behaviors/draggable.js +2 -2
  26. package/dist/behaviors/focustrap.cjs +5 -81
  27. package/dist/behaviors/focustrap.cjs.map +1 -1
  28. package/dist/behaviors/focustrap.d.cts +3 -2
  29. package/dist/behaviors/focustrap.d.ts +3 -2
  30. package/dist/behaviors/focustrap.js +1 -1
  31. package/dist/behaviors/removable.d.cts +1 -1
  32. package/dist/behaviors/removable.d.ts +1 -1
  33. package/dist/behaviors/resizable.cjs +9 -49
  34. package/dist/behaviors/resizable.cjs.map +1 -1
  35. package/dist/behaviors/resizable.d.cts +3 -2
  36. package/dist/behaviors/resizable.d.ts +3 -2
  37. package/dist/behaviors/resizable.js +2 -2
  38. package/dist/behaviors/scrollreveal.cjs +5 -32
  39. package/dist/behaviors/scrollreveal.cjs.map +1 -1
  40. package/dist/behaviors/scrollreveal.d.cts +3 -2
  41. package/dist/behaviors/scrollreveal.d.ts +3 -2
  42. package/dist/behaviors/scrollreveal.js +1 -1
  43. package/dist/behaviors/sortable.cjs +8 -43
  44. package/dist/behaviors/sortable.cjs.map +1 -1
  45. package/dist/behaviors/sortable.d.cts +3 -2
  46. package/dist/behaviors/sortable.d.ts +3 -2
  47. package/dist/behaviors/sortable.js +2 -2
  48. package/dist/behaviors/tabs.cjs +5 -120
  49. package/dist/behaviors/tabs.cjs.map +1 -1
  50. package/dist/behaviors/tabs.d.cts +3 -2
  51. package/dist/behaviors/tabs.d.ts +3 -2
  52. package/dist/behaviors/tabs.js +1 -1
  53. package/dist/behaviors/toggleable.cjs +5 -27
  54. package/dist/behaviors/toggleable.cjs.map +1 -1
  55. package/dist/behaviors/toggleable.d.cts +3 -3
  56. package/dist/behaviors/toggleable.d.ts +3 -3
  57. package/dist/behaviors/toggleable.js +1 -1
  58. package/dist/{chunk-SLOXO6IY.js → chunk-26IX7QU7.js} +2 -2
  59. package/dist/{chunk-SLOXO6IY.js.map → chunk-26IX7QU7.js.map} +1 -1
  60. package/dist/chunk-2HUF6RMI.js +40 -0
  61. package/dist/chunk-2HUF6RMI.js.map +1 -0
  62. package/dist/{chunk-ZBSWTV6I.js → chunk-5LFOFVZ3.js} +5 -5
  63. package/dist/chunk-5LFOFVZ3.js.map +1 -0
  64. package/dist/{chunk-BBIIOGMF.js → chunk-6EG2MNC7.js} +6 -6
  65. package/dist/chunk-7NGOA3T5.js +40 -0
  66. package/dist/chunk-7NGOA3T5.js.map +1 -0
  67. package/dist/{chunk-ZZ2WSAX3.js → chunk-7TPDLB7W.js} +7 -29
  68. package/dist/chunk-7TPDLB7W.js.map +1 -0
  69. package/dist/chunk-CR3J7VV6.js +40 -0
  70. package/dist/chunk-CR3J7VV6.js.map +1 -0
  71. package/dist/chunk-EDBG2F57.js +40 -0
  72. package/dist/chunk-EDBG2F57.js.map +1 -0
  73. package/dist/{chunk-G6WR2AYR.js → chunk-FBQ3X3UY.js} +2 -2
  74. package/dist/chunk-FBQ3X3UY.js.map +1 -0
  75. package/dist/chunk-HX663BJ4.js +40 -0
  76. package/dist/chunk-HX663BJ4.js.map +1 -0
  77. package/dist/chunk-KROW43CG.js +40 -0
  78. package/dist/chunk-KROW43CG.js.map +1 -0
  79. package/dist/chunk-ORBJ7MRW.js +40 -0
  80. package/dist/chunk-ORBJ7MRW.js.map +1 -0
  81. package/dist/{chunk-V2M4W3LO.js → chunk-PDMOOWFW.js} +4 -4
  82. package/dist/chunk-PDMOOWFW.js.map +1 -0
  83. package/dist/chunk-SLSCZV4A.js +40 -0
  84. package/dist/chunk-SLSCZV4A.js.map +1 -0
  85. package/dist/chunk-WKBRZGGL.js +40 -0
  86. package/dist/chunk-WKBRZGGL.js.map +1 -0
  87. package/dist/{chunk-WOTZO7K4.js → chunk-YXS27XM6.js} +26 -23
  88. package/dist/chunk-YXS27XM6.js.map +1 -0
  89. package/dist/clickoutside.browser.global.js +3 -3
  90. package/dist/clickoutside.browser.global.js.map +1 -1
  91. package/dist/clipboard.browser.global.js +27 -24
  92. package/dist/clipboard.browser.global.js.map +1 -1
  93. package/dist/core.browser.global.js +3 -3
  94. package/dist/core.browser.global.js.map +1 -1
  95. package/dist/draggable.browser.global.js +2 -2
  96. package/dist/draggable.browser.global.js.map +1 -1
  97. package/dist/focustrap.browser.global.js +2 -2
  98. package/dist/focustrap.browser.global.js.map +1 -1
  99. package/dist/index.cjs +120 -563
  100. package/dist/index.cjs.map +1 -1
  101. package/dist/index.d.cts +41 -3
  102. package/dist/index.d.ts +41 -3
  103. package/dist/index.js +44 -16
  104. package/dist/index.js.map +1 -1
  105. package/dist/loaders.cjs +86 -563
  106. package/dist/loaders.cjs.map +1 -1
  107. package/dist/loaders.js +6 -6
  108. package/dist/registry.d.cts +1 -1
  109. package/dist/registry.d.ts +1 -1
  110. package/dist/resizable.browser.global.js +5 -5
  111. package/dist/resizable.browser.global.js.map +1 -1
  112. package/dist/resolver.browser.global.js +34 -31
  113. package/dist/resolver.browser.global.js.map +1 -1
  114. package/dist/schemas/index.cjs +34 -31
  115. package/dist/schemas/index.cjs.map +1 -1
  116. package/dist/schemas/index.d.cts +2 -2
  117. package/dist/schemas/index.d.ts +2 -2
  118. package/dist/schemas/index.js +5 -5
  119. package/dist/scrollreveal.browser.global.js +2 -2
  120. package/dist/scrollreveal.browser.global.js.map +1 -1
  121. package/dist/sortable.browser.global.js +4 -4
  122. package/dist/sortable.browser.global.js.map +1 -1
  123. package/dist/tabs.browser.global.js +2 -2
  124. package/dist/tabs.browser.global.js.map +1 -1
  125. package/dist/toggleable.browser.global.js +2 -2
  126. package/dist/toggleable.browser.global.js.map +1 -1
  127. package/dist/{types-BY-jB5FV.d.ts → types-DCCtVQS5.d.cts} +1 -1
  128. package/dist/{types-BY-jB5FV.d.cts → types-DCCtVQS5.d.ts} +1 -1
  129. package/package.json +4 -4
  130. package/src/behaviors/autodismiss.test.ts +15 -9
  131. package/src/behaviors/autodismiss.ts +15 -70
  132. package/src/behaviors/clickoutside.test.ts +17 -9
  133. package/src/behaviors/clickoutside.ts +13 -39
  134. package/src/behaviors/clipboard.test.ts +16 -10
  135. package/src/behaviors/clipboard.ts +15 -93
  136. package/src/behaviors/curated-runtime.test.ts +158 -0
  137. package/src/behaviors/draggable.ts +15 -59
  138. package/src/behaviors/experimental-runtime.test.ts +136 -0
  139. package/src/behaviors/focustrap.test.ts +15 -9
  140. package/src/behaviors/focustrap.ts +17 -121
  141. package/src/behaviors/integration.test.ts +9 -64
  142. package/src/behaviors/optional-runtime.test.ts +251 -0
  143. package/src/behaviors/resizable.ts +14 -61
  144. package/src/behaviors/scrollreveal.test.ts +17 -9
  145. package/src/behaviors/scrollreveal.ts +17 -41
  146. package/src/behaviors/sortable.ts +15 -58
  147. package/src/behaviors/tabs.test.ts +16 -10
  148. package/src/behaviors/tabs.ts +18 -160
  149. package/src/behaviors/toggleable.ts +14 -41
  150. package/src/curation.test.ts +45 -0
  151. package/src/curation.ts +58 -0
  152. package/src/index.ts +14 -0
  153. package/src/registry.test.ts +6 -11
  154. package/src/schemas/clickoutside.schema.ts +1 -1
  155. package/src/schemas/clipboard.schema.ts +25 -22
  156. package/src/schemas/draggable.schema.ts +2 -1
  157. package/src/schemas/resizable.schema.ts +5 -4
  158. package/src/schemas/sortable.schema.ts +4 -3
  159. package/dist/chunk-7O7UOSBH.js +0 -99
  160. package/dist/chunk-7O7UOSBH.js.map +0 -1
  161. package/dist/chunk-EKKJVXDZ.js +0 -67
  162. package/dist/chunk-EKKJVXDZ.js.map +0 -1
  163. package/dist/chunk-F3CASJ7Q.js +0 -116
  164. package/dist/chunk-F3CASJ7Q.js.map +0 -1
  165. package/dist/chunk-G6WR2AYR.js.map +0 -1
  166. package/dist/chunk-GALKOMJ5.js +0 -62
  167. package/dist/chunk-GALKOMJ5.js.map +0 -1
  168. package/dist/chunk-IMDFEGIT.js +0 -75
  169. package/dist/chunk-IMDFEGIT.js.map +0 -1
  170. package/dist/chunk-IT6TYVMW.js +0 -80
  171. package/dist/chunk-IT6TYVMW.js.map +0 -1
  172. package/dist/chunk-LQJOQTBZ.js +0 -89
  173. package/dist/chunk-LQJOQTBZ.js.map +0 -1
  174. package/dist/chunk-S4QDV2MH.js +0 -75
  175. package/dist/chunk-S4QDV2MH.js.map +0 -1
  176. package/dist/chunk-V2M4W3LO.js.map +0 -1
  177. package/dist/chunk-WOTZO7K4.js.map +0 -1
  178. package/dist/chunk-WPOQIMCC.js +0 -155
  179. package/dist/chunk-WPOQIMCC.js.map +0 -1
  180. package/dist/chunk-ZBSWTV6I.js.map +0 -1
  181. package/dist/chunk-ZZ2WSAX3.js.map +0 -1
  182. /package/dist/{chunk-BBIIOGMF.js.map → chunk-6EG2MNC7.js.map} +0 -0
package/dist/loaders.cjs CHANGED
@@ -19,7 +19,7 @@ var init_draggable_schema = __esm({
19
19
  category: "ui",
20
20
  tier: "core",
21
21
  version: "1.0.0",
22
- description: "Makes elements draggable with pointer events",
22
+ description: "Makes elements draggable with pointer events (EXPERIMENTAL \u2014 stateful async component, beyond the inline-scripting boundary; not part of the curated set)",
23
23
  parameters: [
24
24
  {
25
25
  name: "dragHandle",
@@ -73,7 +73,7 @@ var init_sortable_schema = __esm({
73
73
  category: "ui",
74
74
  tier: "common",
75
75
  version: "1.0.0",
76
- description: "Makes child elements reorderable via drag-and-drop",
76
+ description: "Makes child elements reorderable via drag-and-drop (EXPERIMENTAL \u2014 stateful async component, beyond the inline-scripting boundary; not part of the curated set)",
77
77
  parameters: [
78
78
  {
79
79
  name: "dragClass",
@@ -100,7 +100,7 @@ behavior Sortable(dragClass)
100
100
  end
101
101
  end
102
102
  on pointerdown(clientY) from me
103
- set item to the closest <li/> to the target
103
+ set item to the target.closest("li")
104
104
  if item is null
105
105
  exit
106
106
  end
@@ -108,7 +108,7 @@ behavior Sortable(dragClass)
108
108
  add .{dragClass} to item
109
109
  trigger sortable:start on me
110
110
  repeat until event pointerup from document
111
- wait for pointermove(clientY) from document
111
+ wait for pointermove(clientY) or pointerup(clientY) from document
112
112
  trigger sortable:move on me
113
113
  end
114
114
  remove .{dragClass} from item
@@ -129,7 +129,7 @@ var init_resizable_schema = __esm({
129
129
  category: "ui",
130
130
  tier: "optional",
131
131
  version: "1.0.0",
132
- description: "Makes elements resizable by dragging",
132
+ description: "Makes elements resizable by dragging (EXPERIMENTAL \u2014 stateful async component, beyond the inline-scripting boundary; not part of the curated set)",
133
133
  parameters: [
134
134
  {
135
135
  name: "minWidth",
@@ -177,15 +177,15 @@ behavior Resizable(minWidth, minHeight, maxWidth, maxHeight)
177
177
  set startX to clientX
178
178
  set startY to clientY
179
179
  repeat until event pointerup from document
180
- wait for pointermove(clientX, clientY) from document
180
+ wait for pointermove(clientX, clientY) or pointerup(clientX, clientY) from document
181
181
  set newWidth to startWidth + clientX - startX
182
182
  set newHeight to startHeight + clientY - startY
183
183
  if newWidth < minWidth then set newWidth to minWidth end
184
184
  if newWidth > maxWidth then set newWidth to maxWidth end
185
185
  if newHeight < minHeight then set newHeight to minHeight end
186
186
  if newHeight > maxHeight then set newHeight to maxHeight end
187
- set my style.width to newWidth + "px"
188
- set my style.height to newHeight + "px"
187
+ set my *width to newWidth + "px"
188
+ set my *height to newHeight + "px"
189
189
  trigger resizable:resize
190
190
  end
191
191
  trigger resizable:end
@@ -381,29 +381,32 @@ behavior Clipboard(text, source, feedback, feedbackDuration)
381
381
  set copyText to source's textContent
382
382
  end
383
383
  js(me, copyText, feedback, feedbackDuration)
384
- async function copyToClipboard(t) {
385
- if (navigator.clipboard && navigator.clipboard.writeText) {
386
- await navigator.clipboard.writeText(t);
387
- return;
384
+ // Wrapped in an async IIFE: hyperscript's js() block has no top-level await.
385
+ (async function() {
386
+ async function copyToClipboard(t) {
387
+ if (navigator.clipboard && navigator.clipboard.writeText) {
388
+ await navigator.clipboard.writeText(t);
389
+ return;
390
+ }
391
+ var ta = document.createElement('textarea');
392
+ ta.value = t;
393
+ ta.style.position = 'fixed';
394
+ ta.style.opacity = '0';
395
+ document.body.appendChild(ta);
396
+ ta.select();
397
+ try { document.execCommand('copy'); } finally { document.body.removeChild(ta); }
388
398
  }
389
- var ta = document.createElement('textarea');
390
- ta.value = t;
391
- ta.style.position = 'fixed';
392
- ta.style.opacity = '0';
393
- document.body.appendChild(ta);
394
- ta.select();
395
- try { document.execCommand('copy'); } finally { document.body.removeChild(ta); }
396
- }
397
- try {
398
- await copyToClipboard(copyText);
399
- var feedbackEl = feedback ? (typeof feedback === 'string' ? document.querySelector(feedback) : feedback) : me;
400
- if (!feedbackEl) feedbackEl = me;
401
- feedbackEl.classList.add('copied');
402
- me.dispatchEvent(new CustomEvent('clipboard:copied', { bubbles: true, detail: { text: copyText } }));
403
- setTimeout(function() { feedbackEl.classList.remove('copied'); }, feedbackDuration);
404
- } catch(err) {
405
- me.dispatchEvent(new CustomEvent('clipboard:error', { bubbles: true, detail: { error: err } }));
406
- }
399
+ try {
400
+ await copyToClipboard(copyText);
401
+ var feedbackEl = feedback ? (typeof feedback === 'string' ? document.querySelector(feedback) : feedback) : me;
402
+ if (!feedbackEl) feedbackEl = me;
403
+ feedbackEl.classList.add('copied');
404
+ me.dispatchEvent(new CustomEvent('clipboard:copied', { bubbles: true, detail: { text: copyText } }));
405
+ setTimeout(function() { feedbackEl.classList.remove('copied'); }, feedbackDuration);
406
+ } catch(err) {
407
+ me.dispatchEvent(new CustomEvent('clipboard:error', { bubbles: true, detail: { error: err } }));
408
+ }
409
+ })();
407
410
  end
408
411
  end
409
412
  end`.trim()
@@ -553,7 +556,7 @@ behavior ClickOutside(active)
553
556
  end
554
557
  end
555
558
  on pointerdown from document
556
- js(me, active)
559
+ js(me, active, event)
557
560
  if (!me.isConnected) return;
558
561
  if (active && !me.contains(event.target)) {
559
562
  me.dispatchEvent(new CustomEvent('clickoutside', { bubbles: true }));
@@ -896,38 +899,6 @@ __export(draggable_exports, {
896
899
  draggableSource: () => draggableSource,
897
900
  registerDraggable: () => registerDraggable
898
901
  });
899
- function installDraggable(element, params) {
900
- let dragHandle = element;
901
- if (params.dragHandle && params.dragHandle !== "me") {
902
- if (typeof params.dragHandle === "string") {
903
- const found = element.querySelector(params.dragHandle);
904
- if (found instanceof HTMLElement) dragHandle = found;
905
- } else if (params.dragHandle instanceof HTMLElement) {
906
- dragHandle = params.dragHandle;
907
- }
908
- }
909
- dragHandle.addEventListener("pointerdown", (e) => {
910
- e.preventDefault();
911
- e.stopPropagation();
912
- element.dispatchEvent(new CustomEvent("draggable:start", { bubbles: true }));
913
- const startX = element.offsetLeft;
914
- const startY = element.offsetTop;
915
- const xoff = e.clientX - startX;
916
- const yoff = e.clientY - startY;
917
- function onMove(ev) {
918
- element.style.left = `${ev.clientX - xoff}px`;
919
- element.style.top = `${ev.clientY - yoff}px`;
920
- element.dispatchEvent(new CustomEvent("draggable:move", { bubbles: true }));
921
- }
922
- function onUp() {
923
- document.removeEventListener("pointermove", onMove);
924
- document.removeEventListener("pointerup", onUp);
925
- element.dispatchEvent(new CustomEvent("draggable:end", { bubbles: true }));
926
- }
927
- document.addEventListener("pointermove", onMove);
928
- document.addEventListener("pointerup", onUp);
929
- });
930
- }
931
902
  async function registerDraggable(hyperfixi) {
932
903
  const hf = hyperfixi || resolveRuntime();
933
904
  if (!hf) {
@@ -935,15 +906,12 @@ async function registerDraggable(hyperfixi) {
935
906
  "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
936
907
  );
937
908
  }
938
- const syntheticNode = {
939
- type: "behavior",
940
- name: "Draggable",
941
- parameters: ["dragHandle"],
942
- eventHandlers: [],
943
- imperativeInstaller: installDraggable
944
- };
909
+ const result = hf.compileSync(draggableSchema.source, { traditional: true });
910
+ if (!result.ok) {
911
+ throw new Error(`Failed to compile Draggable behavior: ${JSON.stringify(result.errors)}`);
912
+ }
945
913
  const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
946
- await hf.execute(syntheticNode, ctx);
914
+ await hf.execute(result.ast, ctx);
947
915
  }
948
916
  var draggableSource, draggableMetadata, draggable_default;
949
917
  var init_draggable = __esm({
@@ -972,38 +940,6 @@ __export(sortable_exports, {
972
940
  sortableMetadata: () => sortableMetadata,
973
941
  sortableSource: () => sortableSource
974
942
  });
975
- function installSortable(element, params) {
976
- const dragClass = params.dragClass || "sorting";
977
- const handleSelector = params.handle || null;
978
- element.addEventListener("pointerdown", (e) => {
979
- const target = e.target;
980
- const item = target.closest("li");
981
- if (!item || !element.contains(item)) return;
982
- if (handleSelector) {
983
- const handleEl = target.closest(handleSelector);
984
- if (!handleEl) return;
985
- }
986
- e.preventDefault();
987
- item.classList.add(dragClass);
988
- element.dispatchEvent(new CustomEvent("sortable:start", { bubbles: true, detail: { item } }));
989
- function onMove(ev) {
990
- element.dispatchEvent(
991
- new CustomEvent("sortable:move", {
992
- bubbles: true,
993
- detail: { clientY: ev.clientY, item }
994
- })
995
- );
996
- }
997
- function onUp() {
998
- document.removeEventListener("pointermove", onMove);
999
- document.removeEventListener("pointerup", onUp);
1000
- item.classList.remove(dragClass);
1001
- element.dispatchEvent(new CustomEvent("sortable:end", { bubbles: true, detail: { item } }));
1002
- }
1003
- document.addEventListener("pointermove", onMove);
1004
- document.addEventListener("pointerup", onUp);
1005
- });
1006
- }
1007
943
  async function registerSortable(hyperfixi) {
1008
944
  const hf = hyperfixi || resolveRuntime();
1009
945
  if (!hf) {
@@ -1011,15 +947,12 @@ async function registerSortable(hyperfixi) {
1011
947
  "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
1012
948
  );
1013
949
  }
1014
- const syntheticNode = {
1015
- type: "behavior",
1016
- name: "Sortable",
1017
- parameters: ["dragClass"],
1018
- eventHandlers: [],
1019
- imperativeInstaller: installSortable
1020
- };
950
+ const result = hf.compileSync(sortableSchema.source, { traditional: true });
951
+ if (!result.ok) {
952
+ throw new Error(`Failed to compile Sortable behavior: ${JSON.stringify(result.errors)}`);
953
+ }
1021
954
  const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
1022
- await hf.execute(syntheticNode, ctx);
955
+ await hf.execute(result.ast, ctx);
1023
956
  }
1024
957
  var sortableSource, sortableMetadata, sortable_default;
1025
958
  var init_sortable = __esm({
@@ -1048,43 +981,6 @@ __export(resizable_exports, {
1048
981
  resizableMetadata: () => resizableMetadata,
1049
982
  resizableSource: () => resizableSource
1050
983
  });
1051
- function installResizable(element, params) {
1052
- let handleEl = element;
1053
- if (params.handle && params.handle !== "me") {
1054
- if (typeof params.handle === "string") {
1055
- const found = element.querySelector(params.handle);
1056
- if (found instanceof HTMLElement) handleEl = found;
1057
- } else if (params.handle instanceof HTMLElement) {
1058
- handleEl = params.handle;
1059
- }
1060
- }
1061
- const minW = params.minWidth ?? 50;
1062
- const minH = params.minHeight ?? 50;
1063
- const maxW = params.maxWidth ?? 9999;
1064
- const maxH = params.maxHeight ?? 9999;
1065
- handleEl.addEventListener("pointerdown", (e) => {
1066
- e.preventDefault();
1067
- element.dispatchEvent(new CustomEvent("resizable:start", { bubbles: true }));
1068
- const startWidth = element.offsetWidth;
1069
- const startHeight = element.offsetHeight;
1070
- const startX = e.clientX;
1071
- const startY = e.clientY;
1072
- function onMove(ev) {
1073
- const newWidth = Math.max(minW, Math.min(maxW, startWidth + (ev.clientX - startX)));
1074
- const newHeight = Math.max(minH, Math.min(maxH, startHeight + (ev.clientY - startY)));
1075
- element.style.width = `${newWidth}px`;
1076
- element.style.height = `${newHeight}px`;
1077
- element.dispatchEvent(new CustomEvent("resizable:resize", { bubbles: true }));
1078
- }
1079
- function onUp() {
1080
- document.removeEventListener("pointermove", onMove);
1081
- document.removeEventListener("pointerup", onUp);
1082
- element.dispatchEvent(new CustomEvent("resizable:end", { bubbles: true }));
1083
- }
1084
- document.addEventListener("pointermove", onMove);
1085
- document.addEventListener("pointerup", onUp);
1086
- });
1087
- }
1088
984
  async function registerResizable(hyperfixi) {
1089
985
  const hf = hyperfixi || resolveRuntime();
1090
986
  if (!hf) {
@@ -1092,15 +988,12 @@ async function registerResizable(hyperfixi) {
1092
988
  "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
1093
989
  );
1094
990
  }
1095
- const syntheticNode = {
1096
- type: "behavior",
1097
- name: "Resizable",
1098
- parameters: [],
1099
- eventHandlers: [],
1100
- imperativeInstaller: installResizable
1101
- };
991
+ const result = hf.compileSync(resizableSchema.source, { traditional: true });
992
+ if (!result.ok) {
993
+ throw new Error(`Failed to compile Resizable behavior: ${JSON.stringify(result.errors)}`);
994
+ }
1102
995
  const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
1103
- await hf.execute(syntheticNode, ctx);
996
+ await hf.execute(result.ast, ctx);
1104
997
  }
1105
998
  var resizableSource, resizableMetadata, resizable_default;
1106
999
  var init_resizable = __esm({
@@ -1170,25 +1063,6 @@ __export(toggleable_exports, {
1170
1063
  toggleableMetadata: () => toggleableMetadata,
1171
1064
  toggleableSource: () => toggleableSource
1172
1065
  });
1173
- function installToggleable(element, params) {
1174
- const cls = params.cls || "active";
1175
- let targetEl = element;
1176
- if (params.target && params.target !== "me") {
1177
- if (typeof params.target === "string") {
1178
- const found = document.querySelector(params.target);
1179
- if (found instanceof HTMLElement) targetEl = found;
1180
- } else if (params.target instanceof HTMLElement) {
1181
- targetEl = params.target;
1182
- }
1183
- }
1184
- element.addEventListener("click", () => {
1185
- const wasOn = targetEl.classList.contains(cls);
1186
- targetEl.classList.toggle(cls);
1187
- targetEl.dispatchEvent(
1188
- new CustomEvent(wasOn ? "toggleable:off" : "toggleable:on", { bubbles: true })
1189
- );
1190
- });
1191
- }
1192
1066
  async function registerToggleable(hyperfixi) {
1193
1067
  const hf = hyperfixi || resolveRuntime();
1194
1068
  if (!hf) {
@@ -1196,15 +1070,12 @@ async function registerToggleable(hyperfixi) {
1196
1070
  "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
1197
1071
  );
1198
1072
  }
1199
- const syntheticNode = {
1200
- type: "behavior",
1201
- name: "Toggleable",
1202
- parameters: ["cls", "target"],
1203
- eventHandlers: [],
1204
- imperativeInstaller: installToggleable
1205
- };
1073
+ const result = hf.compileSync(toggleableSchema.source, { traditional: true });
1074
+ if (!result.ok) {
1075
+ throw new Error(`Failed to compile Toggleable behavior: ${JSON.stringify(result.errors)}`);
1076
+ }
1206
1077
  const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
1207
- await hf.execute(syntheticNode, ctx);
1078
+ await hf.execute(result.ast, ctx);
1208
1079
  }
1209
1080
  var toggleableSource, toggleableMetadata, toggleable_default;
1210
1081
  var init_toggleable = __esm({
@@ -1233,62 +1104,6 @@ __export(clipboard_exports, {
1233
1104
  default: () => clipboard_default,
1234
1105
  registerClipboard: () => registerClipboard
1235
1106
  });
1236
- async function copyToClipboard(text) {
1237
- if (navigator.clipboard?.writeText) {
1238
- await navigator.clipboard.writeText(text);
1239
- return;
1240
- }
1241
- const textarea = document.createElement("textarea");
1242
- textarea.value = text;
1243
- textarea.style.position = "fixed";
1244
- textarea.style.opacity = "0";
1245
- document.body.appendChild(textarea);
1246
- textarea.select();
1247
- try {
1248
- document.execCommand("copy");
1249
- } finally {
1250
- document.body.removeChild(textarea);
1251
- }
1252
- }
1253
- function resolveElement(element, param) {
1254
- if (!param || param === "me") return element;
1255
- if (param instanceof HTMLElement) return param;
1256
- if (typeof param === "string") {
1257
- return element.querySelector(param) || document.querySelector(param) || null;
1258
- }
1259
- return null;
1260
- }
1261
- function installClipboard(element, params) {
1262
- const feedbackDuration = typeof params.feedbackDuration === "number" ? params.feedbackDuration : 2e3;
1263
- element.addEventListener("click", async () => {
1264
- let copyText;
1265
- if (params.text != null) {
1266
- copyText = String(params.text);
1267
- } else {
1268
- const sourceEl = resolveElement(element, params.source) || element;
1269
- copyText = sourceEl.value ?? sourceEl.textContent ?? "";
1270
- }
1271
- try {
1272
- await copyToClipboard(copyText);
1273
- const feedbackEl = resolveElement(element, params.feedback) || element;
1274
- feedbackEl.classList.add("copied");
1275
- setTimeout(() => feedbackEl.classList.remove("copied"), feedbackDuration);
1276
- element.dispatchEvent(
1277
- new CustomEvent("clipboard:copied", {
1278
- bubbles: true,
1279
- detail: { text: copyText }
1280
- })
1281
- );
1282
- } catch (error) {
1283
- element.dispatchEvent(
1284
- new CustomEvent("clipboard:error", {
1285
- bubbles: true,
1286
- detail: { error }
1287
- })
1288
- );
1289
- }
1290
- });
1291
- }
1292
1107
  async function registerClipboard(hyperfixi) {
1293
1108
  const hf = hyperfixi || resolveRuntime();
1294
1109
  if (!hf) {
@@ -1296,15 +1111,12 @@ async function registerClipboard(hyperfixi) {
1296
1111
  "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
1297
1112
  );
1298
1113
  }
1299
- const syntheticNode = {
1300
- type: "behavior",
1301
- name: "Clipboard",
1302
- parameters: ["text", "source", "feedback", "feedbackDuration"],
1303
- eventHandlers: [],
1304
- imperativeInstaller: installClipboard
1305
- };
1114
+ const result = hf.compileSync(clipboardSchema.source, { traditional: true });
1115
+ if (!result.ok) {
1116
+ throw new Error(`Failed to compile Clipboard behavior: ${JSON.stringify(result.errors)}`);
1117
+ }
1306
1118
  const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
1307
- await hf.execute(syntheticNode, ctx);
1119
+ await hf.execute(result.ast, ctx);
1308
1120
  }
1309
1121
  var clipboardSource, clipboardMetadata, clipboard_default;
1310
1122
  var init_clipboard = __esm({
@@ -1333,52 +1145,6 @@ __export(autodismiss_exports, {
1333
1145
  default: () => autodismiss_default,
1334
1146
  registerAutoDismiss: () => registerAutoDismiss
1335
1147
  });
1336
- function installAutoDismiss(element, params) {
1337
- const delay = typeof params.delay === "number" ? params.delay : 5e3;
1338
- const pauseOnHover = params.pauseOnHover !== false;
1339
- const effect = params.effect === "fade" ? "fade" : "none";
1340
- let timerId = null;
1341
- let remaining = delay;
1342
- let startedAt = Date.now();
1343
- function dismiss() {
1344
- const event = new CustomEvent("autodismiss:dismissed", {
1345
- bubbles: true,
1346
- cancelable: true
1347
- });
1348
- element.dispatchEvent(event);
1349
- if (event.defaultPrevented) return;
1350
- if (effect === "fade") {
1351
- element.style.transition = "opacity 300ms";
1352
- element.style.opacity = "0";
1353
- setTimeout(() => element.remove(), 300);
1354
- } else {
1355
- element.remove();
1356
- }
1357
- }
1358
- function start() {
1359
- startedAt = Date.now();
1360
- timerId = setTimeout(dismiss, remaining);
1361
- }
1362
- element.dispatchEvent(new CustomEvent("autodismiss:start", { bubbles: true }));
1363
- start();
1364
- if (pauseOnHover) {
1365
- element.addEventListener("mouseenter", () => {
1366
- if (timerId != null) {
1367
- clearTimeout(timerId);
1368
- timerId = null;
1369
- remaining -= Date.now() - startedAt;
1370
- if (remaining < 0) remaining = 0;
1371
- element.dispatchEvent(new CustomEvent("autodismiss:paused", { bubbles: true }));
1372
- }
1373
- });
1374
- element.addEventListener("mouseleave", () => {
1375
- if (timerId == null && element.isConnected) {
1376
- element.dispatchEvent(new CustomEvent("autodismiss:resumed", { bubbles: true }));
1377
- start();
1378
- }
1379
- });
1380
- }
1381
- }
1382
1148
  async function registerAutoDismiss(hyperfixi) {
1383
1149
  const hf = hyperfixi || resolveRuntime();
1384
1150
  if (!hf) {
@@ -1386,15 +1152,12 @@ async function registerAutoDismiss(hyperfixi) {
1386
1152
  "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
1387
1153
  );
1388
1154
  }
1389
- const syntheticNode = {
1390
- type: "behavior",
1391
- name: "AutoDismiss",
1392
- parameters: ["delay", "pauseOnHover", "effect"],
1393
- eventHandlers: [],
1394
- imperativeInstaller: installAutoDismiss
1395
- };
1155
+ const result = hf.compileSync(autoDismissSchema.source, { traditional: true });
1156
+ if (!result.ok) {
1157
+ throw new Error(`Failed to compile AutoDismiss behavior: ${JSON.stringify(result.errors)}`);
1158
+ }
1396
1159
  const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
1397
- await hf.execute(syntheticNode, ctx);
1160
+ await hf.execute(result.ast, ctx);
1398
1161
  }
1399
1162
  var autoDismissSource, autoDismissMetadata, autodismiss_default;
1400
1163
  var init_autodismiss = __esm({
@@ -1423,25 +1186,6 @@ __export(clickoutside_exports, {
1423
1186
  default: () => clickoutside_default,
1424
1187
  registerClickOutside: () => registerClickOutside
1425
1188
  });
1426
- function installClickOutside(element, params) {
1427
- let active = params.active !== false;
1428
- function onPointerDown(e) {
1429
- if (!element.isConnected) {
1430
- document.removeEventListener("pointerdown", onPointerDown);
1431
- return;
1432
- }
1433
- if (active && !element.contains(e.target)) {
1434
- element.dispatchEvent(new CustomEvent("clickoutside", { bubbles: true }));
1435
- }
1436
- }
1437
- document.addEventListener("pointerdown", onPointerDown);
1438
- element.addEventListener("clickoutside:activate", () => {
1439
- active = true;
1440
- });
1441
- element.addEventListener("clickoutside:deactivate", () => {
1442
- active = false;
1443
- });
1444
- }
1445
1189
  async function registerClickOutside(hyperfixi) {
1446
1190
  const hf = hyperfixi || resolveRuntime();
1447
1191
  if (!hf) {
@@ -1449,15 +1193,12 @@ async function registerClickOutside(hyperfixi) {
1449
1193
  "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
1450
1194
  );
1451
1195
  }
1452
- const syntheticNode = {
1453
- type: "behavior",
1454
- name: "ClickOutside",
1455
- parameters: ["active"],
1456
- eventHandlers: [],
1457
- imperativeInstaller: installClickOutside
1458
- };
1196
+ const result = hf.compileSync(clickOutsideSchema.source, { traditional: true });
1197
+ if (!result.ok) {
1198
+ throw new Error(`Failed to compile ClickOutside behavior: ${JSON.stringify(result.errors)}`);
1199
+ }
1459
1200
  const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
1460
- await hf.execute(syntheticNode, ctx);
1201
+ await hf.execute(result.ast, ctx);
1461
1202
  }
1462
1203
  var clickOutsideSource, clickOutsideMetadata, clickoutside_default;
1463
1204
  var init_clickoutside = __esm({
@@ -1486,71 +1227,6 @@ __export(focustrap_exports, {
1486
1227
  focusTrapSource: () => focusTrapSource,
1487
1228
  registerFocusTrap: () => registerFocusTrap
1488
1229
  });
1489
- function resolveElement2(container, param) {
1490
- if (!param) return null;
1491
- if (param instanceof HTMLElement) return param;
1492
- if (typeof param === "string") {
1493
- return container.querySelector(param) || document.querySelector(param) || null;
1494
- }
1495
- return null;
1496
- }
1497
- function installFocusTrap(element, params) {
1498
- const returnFocus = params.returnFocus !== false;
1499
- let isActive = false;
1500
- let previouslyFocused = null;
1501
- function getFocusableElements() {
1502
- return Array.from(element.querySelectorAll(FOCUSABLE_SELECTOR));
1503
- }
1504
- function onKeyDown(e) {
1505
- if (!isActive || e.key !== "Tab") return;
1506
- const focusable = getFocusableElements();
1507
- if (focusable.length === 0) {
1508
- e.preventDefault();
1509
- return;
1510
- }
1511
- e.preventDefault();
1512
- const currentIndex = focusable.indexOf(document.activeElement);
1513
- if (e.shiftKey) {
1514
- const prevIndex = currentIndex <= 0 ? focusable.length - 1 : currentIndex - 1;
1515
- focusable[prevIndex].focus();
1516
- } else {
1517
- const nextIndex = currentIndex >= focusable.length - 1 ? 0 : currentIndex + 1;
1518
- focusable[nextIndex].focus();
1519
- }
1520
- }
1521
- function activate() {
1522
- if (isActive) return;
1523
- isActive = true;
1524
- previouslyFocused = document.activeElement;
1525
- element.setAttribute("aria-modal", "true");
1526
- const initialEl = resolveElement2(element, params.initialFocus);
1527
- if (initialEl) {
1528
- initialEl.focus();
1529
- } else {
1530
- const focusable = getFocusableElements();
1531
- if (focusable.length > 0) {
1532
- focusable[0].focus();
1533
- }
1534
- }
1535
- element.dispatchEvent(new CustomEvent("focustrap:activated", { bubbles: true }));
1536
- }
1537
- function deactivate() {
1538
- if (!isActive) return;
1539
- isActive = false;
1540
- element.removeAttribute("aria-modal");
1541
- if (returnFocus && previouslyFocused instanceof HTMLElement) {
1542
- previouslyFocused.focus();
1543
- }
1544
- previouslyFocused = null;
1545
- element.dispatchEvent(new CustomEvent("focustrap:deactivated", { bubbles: true }));
1546
- }
1547
- element.addEventListener("keydown", onKeyDown);
1548
- element.addEventListener("focustrap:activate", () => activate());
1549
- element.addEventListener("focustrap:deactivate", () => deactivate());
1550
- if (params.active !== false) {
1551
- activate();
1552
- }
1553
- }
1554
1230
  async function registerFocusTrap(hyperfixi) {
1555
1231
  const hf = hyperfixi || resolveRuntime();
1556
1232
  if (!hf) {
@@ -1558,17 +1234,14 @@ async function registerFocusTrap(hyperfixi) {
1558
1234
  "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
1559
1235
  );
1560
1236
  }
1561
- const syntheticNode = {
1562
- type: "behavior",
1563
- name: "FocusTrap",
1564
- parameters: ["active", "initialFocus", "returnFocus"],
1565
- eventHandlers: [],
1566
- imperativeInstaller: installFocusTrap
1567
- };
1237
+ const result = hf.compileSync(focusTrapSchema.source, { traditional: true });
1238
+ if (!result.ok) {
1239
+ throw new Error(`Failed to compile FocusTrap behavior: ${JSON.stringify(result.errors)}`);
1240
+ }
1568
1241
  const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
1569
- await hf.execute(syntheticNode, ctx);
1242
+ await hf.execute(result.ast, ctx);
1570
1243
  }
1571
- var focusTrapSource, focusTrapMetadata, FOCUSABLE_SELECTOR, focustrap_default;
1244
+ var focusTrapSource, focusTrapMetadata, focustrap_default;
1572
1245
  var init_focustrap = __esm({
1573
1246
  "src/behaviors/focustrap.ts"() {
1574
1247
  "use strict";
@@ -1576,14 +1249,6 @@ var init_focustrap = __esm({
1576
1249
  init_types();
1577
1250
  focusTrapSource = focusTrapSchema.source;
1578
1251
  focusTrapMetadata = focusTrapSchema;
1579
- FOCUSABLE_SELECTOR = [
1580
- "a[href]",
1581
- "button:not(:disabled)",
1582
- "input:not(:disabled)",
1583
- "select:not(:disabled)",
1584
- "textarea:not(:disabled)",
1585
- '[tabindex]:not([tabindex="-1"])'
1586
- ].join(", ");
1587
1252
  if (resolveRuntime()) {
1588
1253
  registerFocusTrap().catch(console.error);
1589
1254
  }
@@ -1603,30 +1268,6 @@ __export(scrollreveal_exports, {
1603
1268
  scrollRevealMetadata: () => scrollRevealMetadata,
1604
1269
  scrollRevealSource: () => scrollRevealSource
1605
1270
  });
1606
- function installScrollReveal(element, params) {
1607
- const cls = typeof params.cls === "string" ? params.cls : "revealed";
1608
- const threshold = typeof params.threshold === "number" ? params.threshold : 0.1;
1609
- const once = params.once !== false;
1610
- const rootMargin = typeof params.rootMargin === "string" ? params.rootMargin : "0px";
1611
- const observer = new IntersectionObserver(
1612
- (entries) => {
1613
- for (const entry of entries) {
1614
- if (entry.isIntersecting) {
1615
- element.classList.add(cls);
1616
- element.dispatchEvent(new CustomEvent("scrollreveal:enter", { bubbles: true }));
1617
- if (once) {
1618
- observer.disconnect();
1619
- }
1620
- } else if (!once) {
1621
- element.classList.remove(cls);
1622
- element.dispatchEvent(new CustomEvent("scrollreveal:exit", { bubbles: true }));
1623
- }
1624
- }
1625
- },
1626
- { threshold, rootMargin }
1627
- );
1628
- observer.observe(element);
1629
- }
1630
1271
  async function registerScrollReveal(hyperfixi) {
1631
1272
  const hf = hyperfixi || resolveRuntime();
1632
1273
  if (!hf) {
@@ -1634,15 +1275,12 @@ async function registerScrollReveal(hyperfixi) {
1634
1275
  "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
1635
1276
  );
1636
1277
  }
1637
- const syntheticNode = {
1638
- type: "behavior",
1639
- name: "ScrollReveal",
1640
- parameters: ["cls", "threshold", "once", "rootMargin"],
1641
- eventHandlers: [],
1642
- imperativeInstaller: installScrollReveal
1643
- };
1278
+ const result = hf.compileSync(scrollRevealSchema.source, { traditional: true });
1279
+ if (!result.ok) {
1280
+ throw new Error(`Failed to compile ScrollReveal behavior: ${JSON.stringify(result.errors)}`);
1281
+ }
1644
1282
  const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
1645
- await hf.execute(syntheticNode, ctx);
1283
+ await hf.execute(result.ast, ctx);
1646
1284
  }
1647
1285
  var scrollRevealSource, scrollRevealMetadata, scrollreveal_default;
1648
1286
  var init_scrollreveal = __esm({
@@ -1671,117 +1309,6 @@ __export(tabs_exports, {
1671
1309
  tabsMetadata: () => tabsMetadata,
1672
1310
  tabsSource: () => tabsSource
1673
1311
  });
1674
- function ensureId(el, prefix) {
1675
- if (!el.id) {
1676
- el.id = `${prefix}-${++idCounter}`;
1677
- }
1678
- return el.id;
1679
- }
1680
- function installTabs(element, params) {
1681
- const orientation = params.orientation === "vertical" ? "vertical" : "horizontal";
1682
- const wrap = params.wrap !== false;
1683
- const activeClass = params.activeClass || "active";
1684
- const initialIndex = typeof params.activeTab === "number" ? params.activeTab : 0;
1685
- const tabs = Array.from(element.querySelectorAll('[role="tab"]'));
1686
- const panels = Array.from(element.querySelectorAll('[role="tabpanel"]'));
1687
- if (tabs.length === 0 || panels.length === 0) return;
1688
- const tablist = element.querySelector('[role="tablist"]') || tabs[0].parentElement;
1689
- if (tablist && !tablist.getAttribute("role")) {
1690
- tablist.setAttribute("role", "tablist");
1691
- }
1692
- if (tablist) {
1693
- tablist.setAttribute("aria-orientation", orientation);
1694
- }
1695
- const count = Math.min(tabs.length, panels.length);
1696
- for (let i = 0; i < count; i++) {
1697
- const tabId = ensureId(tabs[i], "tab");
1698
- const panelId = ensureId(panels[i], "tabpanel");
1699
- tabs[i].setAttribute("aria-controls", panelId);
1700
- panels[i].setAttribute("aria-labelledby", tabId);
1701
- }
1702
- let currentIndex = -1;
1703
- function selectTab(index, previousIndex) {
1704
- if (index === previousIndex || index < 0 || index >= count) return false;
1705
- const detail = {
1706
- tab: tabs[index],
1707
- panel: panels[index],
1708
- index,
1709
- previousIndex
1710
- };
1711
- const changeEvent = new CustomEvent("tabs:change", {
1712
- bubbles: true,
1713
- cancelable: true,
1714
- detail
1715
- });
1716
- element.dispatchEvent(changeEvent);
1717
- if (changeEvent.defaultPrevented) return false;
1718
- if (previousIndex >= 0 && previousIndex < count) {
1719
- tabs[previousIndex].setAttribute("aria-selected", "false");
1720
- tabs[previousIndex].setAttribute("tabindex", "-1");
1721
- tabs[previousIndex].classList.remove(activeClass);
1722
- panels[previousIndex].setAttribute("aria-hidden", "true");
1723
- panels[previousIndex].classList.remove(activeClass);
1724
- }
1725
- tabs[index].setAttribute("aria-selected", "true");
1726
- tabs[index].setAttribute("tabindex", "0");
1727
- tabs[index].classList.add(activeClass);
1728
- panels[index].setAttribute("aria-hidden", "false");
1729
- panels[index].classList.add(activeClass);
1730
- currentIndex = index;
1731
- element.dispatchEvent(new CustomEvent("tabs:changed", { bubbles: true, detail }));
1732
- return true;
1733
- }
1734
- for (let i = 0; i < count; i++) {
1735
- tabs[i].setAttribute("aria-selected", "false");
1736
- tabs[i].setAttribute("tabindex", "-1");
1737
- tabs[i].classList.remove(activeClass);
1738
- panels[i].setAttribute("aria-hidden", "true");
1739
- panels[i].classList.remove(activeClass);
1740
- }
1741
- const clamped = Math.max(0, Math.min(initialIndex, count - 1));
1742
- tabs[clamped].setAttribute("aria-selected", "true");
1743
- tabs[clamped].setAttribute("tabindex", "0");
1744
- tabs[clamped].classList.add(activeClass);
1745
- panels[clamped].setAttribute("aria-hidden", "false");
1746
- panels[clamped].classList.add(activeClass);
1747
- currentIndex = clamped;
1748
- for (let i = 0; i < count; i++) {
1749
- tabs[i].addEventListener("click", () => {
1750
- selectTab(i, currentIndex);
1751
- tabs[i].focus();
1752
- });
1753
- }
1754
- const keyTarget = tablist || element;
1755
- keyTarget.addEventListener("keydown", (e) => {
1756
- const isHorizontal = orientation === "horizontal";
1757
- const nextKey = isHorizontal ? "ArrowRight" : "ArrowDown";
1758
- const prevKey = isHorizontal ? "ArrowLeft" : "ArrowUp";
1759
- let nextIndex = null;
1760
- if (e.key === nextKey) {
1761
- nextIndex = currentIndex + 1;
1762
- if (nextIndex >= count) nextIndex = wrap ? 0 : null;
1763
- } else if (e.key === prevKey) {
1764
- nextIndex = currentIndex - 1;
1765
- if (nextIndex < 0) nextIndex = wrap ? count - 1 : null;
1766
- } else if (e.key === "Home") {
1767
- nextIndex = 0;
1768
- } else if (e.key === "End") {
1769
- nextIndex = count - 1;
1770
- }
1771
- if (nextIndex !== null) {
1772
- e.preventDefault();
1773
- if (selectTab(nextIndex, currentIndex)) {
1774
- tabs[nextIndex].focus();
1775
- }
1776
- }
1777
- });
1778
- element.addEventListener("tabs:select", ((e) => {
1779
- const index = e.detail?.index;
1780
- if (typeof index === "number") {
1781
- selectTab(index, currentIndex);
1782
- }
1783
- }));
1784
- }
1785
1312
  async function registerTabs(hyperfixi) {
1786
1313
  const hf = hyperfixi || resolveRuntime();
1787
1314
  if (!hf) {
@@ -1789,17 +1316,14 @@ async function registerTabs(hyperfixi) {
1789
1316
  "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
1790
1317
  );
1791
1318
  }
1792
- const syntheticNode = {
1793
- type: "behavior",
1794
- name: "Tabs",
1795
- parameters: ["orientation", "activeTab", "wrap", "activeClass"],
1796
- eventHandlers: [],
1797
- imperativeInstaller: installTabs
1798
- };
1319
+ const result = hf.compileSync(tabsSchema.source, { traditional: true });
1320
+ if (!result.ok) {
1321
+ throw new Error(`Failed to compile Tabs behavior: ${JSON.stringify(result.errors)}`);
1322
+ }
1799
1323
  const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
1800
- await hf.execute(syntheticNode, ctx);
1324
+ await hf.execute(result.ast, ctx);
1801
1325
  }
1802
- var tabsSource, tabsMetadata, idCounter, tabs_default;
1326
+ var tabsSource, tabsMetadata, tabs_default;
1803
1327
  var init_tabs = __esm({
1804
1328
  "src/behaviors/tabs.ts"() {
1805
1329
  "use strict";
@@ -1807,7 +1331,6 @@ var init_tabs = __esm({
1807
1331
  init_types();
1808
1332
  tabsSource = tabsSchema.source;
1809
1333
  tabsMetadata = tabsSchema;
1810
- idCounter = 0;
1811
1334
  if (resolveRuntime()) {
1812
1335
  registerTabs().catch(console.error);
1813
1336
  }