@hyperfixi/behaviors 2.5.1 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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/index.cjs CHANGED
@@ -30,7 +30,7 @@ var init_draggable_schema = __esm({
30
30
  category: "ui",
31
31
  tier: "core",
32
32
  version: "1.0.0",
33
- description: "Makes elements draggable with pointer events",
33
+ description: "Makes elements draggable with pointer events (EXPERIMENTAL \u2014 stateful async component, beyond the inline-scripting boundary; not part of the curated set)",
34
34
  parameters: [
35
35
  {
36
36
  name: "dragHandle",
@@ -94,38 +94,6 @@ __export(draggable_exports, {
94
94
  draggableSource: () => draggableSource,
95
95
  registerDraggable: () => registerDraggable
96
96
  });
97
- function installDraggable(element, params) {
98
- let dragHandle = element;
99
- if (params.dragHandle && params.dragHandle !== "me") {
100
- if (typeof params.dragHandle === "string") {
101
- const found = element.querySelector(params.dragHandle);
102
- if (found instanceof HTMLElement) dragHandle = found;
103
- } else if (params.dragHandle instanceof HTMLElement) {
104
- dragHandle = params.dragHandle;
105
- }
106
- }
107
- dragHandle.addEventListener("pointerdown", (e) => {
108
- e.preventDefault();
109
- e.stopPropagation();
110
- element.dispatchEvent(new CustomEvent("draggable:start", { bubbles: true }));
111
- const startX = element.offsetLeft;
112
- const startY = element.offsetTop;
113
- const xoff = e.clientX - startX;
114
- const yoff = e.clientY - startY;
115
- function onMove(ev) {
116
- element.style.left = `${ev.clientX - xoff}px`;
117
- element.style.top = `${ev.clientY - yoff}px`;
118
- element.dispatchEvent(new CustomEvent("draggable:move", { bubbles: true }));
119
- }
120
- function onUp() {
121
- document.removeEventListener("pointermove", onMove);
122
- document.removeEventListener("pointerup", onUp);
123
- element.dispatchEvent(new CustomEvent("draggable:end", { bubbles: true }));
124
- }
125
- document.addEventListener("pointermove", onMove);
126
- document.addEventListener("pointerup", onUp);
127
- });
128
- }
129
97
  async function registerDraggable(hyperfixi) {
130
98
  const hf = hyperfixi || resolveRuntime();
131
99
  if (!hf) {
@@ -133,15 +101,12 @@ async function registerDraggable(hyperfixi) {
133
101
  "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
134
102
  );
135
103
  }
136
- const syntheticNode = {
137
- type: "behavior",
138
- name: "Draggable",
139
- parameters: ["dragHandle"],
140
- eventHandlers: [],
141
- imperativeInstaller: installDraggable
142
- };
104
+ const result = hf.compileSync(draggableSchema.source, { traditional: true });
105
+ if (!result.ok) {
106
+ throw new Error(`Failed to compile Draggable behavior: ${JSON.stringify(result.errors)}`);
107
+ }
143
108
  const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
144
- await hf.execute(syntheticNode, ctx);
109
+ await hf.execute(result.ast, ctx);
145
110
  }
146
111
  var draggableSource, draggableMetadata, draggable_default;
147
112
  var init_draggable = __esm({
@@ -332,25 +297,6 @@ __export(toggleable_exports, {
332
297
  toggleableMetadata: () => toggleableMetadata,
333
298
  toggleableSource: () => toggleableSource
334
299
  });
335
- function installToggleable(element, params) {
336
- const cls = params.cls || "active";
337
- let targetEl = element;
338
- if (params.target && params.target !== "me") {
339
- if (typeof params.target === "string") {
340
- const found = document.querySelector(params.target);
341
- if (found instanceof HTMLElement) targetEl = found;
342
- } else if (params.target instanceof HTMLElement) {
343
- targetEl = params.target;
344
- }
345
- }
346
- element.addEventListener("click", () => {
347
- const wasOn = targetEl.classList.contains(cls);
348
- targetEl.classList.toggle(cls);
349
- targetEl.dispatchEvent(
350
- new CustomEvent(wasOn ? "toggleable:off" : "toggleable:on", { bubbles: true })
351
- );
352
- });
353
- }
354
300
  async function registerToggleable(hyperfixi) {
355
301
  const hf = hyperfixi || resolveRuntime();
356
302
  if (!hf) {
@@ -358,15 +304,12 @@ async function registerToggleable(hyperfixi) {
358
304
  "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
359
305
  );
360
306
  }
361
- const syntheticNode = {
362
- type: "behavior",
363
- name: "Toggleable",
364
- parameters: ["cls", "target"],
365
- eventHandlers: [],
366
- imperativeInstaller: installToggleable
367
- };
307
+ const result = hf.compileSync(toggleableSchema.source, { traditional: true });
308
+ if (!result.ok) {
309
+ throw new Error(`Failed to compile Toggleable behavior: ${JSON.stringify(result.errors)}`);
310
+ }
368
311
  const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
369
- await hf.execute(syntheticNode, ctx);
312
+ await hf.execute(result.ast, ctx);
370
313
  }
371
314
  var toggleableSource, toggleableMetadata, toggleable_default;
372
315
  var init_toggleable = __esm({
@@ -397,7 +340,7 @@ var init_sortable_schema = __esm({
397
340
  category: "ui",
398
341
  tier: "common",
399
342
  version: "1.0.0",
400
- description: "Makes child elements reorderable via drag-and-drop",
343
+ 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)",
401
344
  parameters: [
402
345
  {
403
346
  name: "dragClass",
@@ -424,7 +367,7 @@ behavior Sortable(dragClass)
424
367
  end
425
368
  end
426
369
  on pointerdown(clientY) from me
427
- set item to the closest <li/> to the target
370
+ set item to the target.closest("li")
428
371
  if item is null
429
372
  exit
430
373
  end
@@ -432,7 +375,7 @@ behavior Sortable(dragClass)
432
375
  add .{dragClass} to item
433
376
  trigger sortable:start on me
434
377
  repeat until event pointerup from document
435
- wait for pointermove(clientY) from document
378
+ wait for pointermove(clientY) or pointerup(clientY) from document
436
379
  trigger sortable:move on me
437
380
  end
438
381
  remove .{dragClass} from item
@@ -451,38 +394,6 @@ __export(sortable_exports, {
451
394
  sortableMetadata: () => sortableMetadata,
452
395
  sortableSource: () => sortableSource
453
396
  });
454
- function installSortable(element, params) {
455
- const dragClass = params.dragClass || "sorting";
456
- const handleSelector = params.handle || null;
457
- element.addEventListener("pointerdown", (e) => {
458
- const target = e.target;
459
- const item = target.closest("li");
460
- if (!item || !element.contains(item)) return;
461
- if (handleSelector) {
462
- const handleEl = target.closest(handleSelector);
463
- if (!handleEl) return;
464
- }
465
- e.preventDefault();
466
- item.classList.add(dragClass);
467
- element.dispatchEvent(new CustomEvent("sortable:start", { bubbles: true, detail: { item } }));
468
- function onMove(ev) {
469
- element.dispatchEvent(
470
- new CustomEvent("sortable:move", {
471
- bubbles: true,
472
- detail: { clientY: ev.clientY, item }
473
- })
474
- );
475
- }
476
- function onUp() {
477
- document.removeEventListener("pointermove", onMove);
478
- document.removeEventListener("pointerup", onUp);
479
- item.classList.remove(dragClass);
480
- element.dispatchEvent(new CustomEvent("sortable:end", { bubbles: true, detail: { item } }));
481
- }
482
- document.addEventListener("pointermove", onMove);
483
- document.addEventListener("pointerup", onUp);
484
- });
485
- }
486
397
  async function registerSortable(hyperfixi) {
487
398
  const hf = hyperfixi || resolveRuntime();
488
399
  if (!hf) {
@@ -490,15 +401,12 @@ async function registerSortable(hyperfixi) {
490
401
  "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
491
402
  );
492
403
  }
493
- const syntheticNode = {
494
- type: "behavior",
495
- name: "Sortable",
496
- parameters: ["dragClass"],
497
- eventHandlers: [],
498
- imperativeInstaller: installSortable
499
- };
404
+ const result = hf.compileSync(sortableSchema.source, { traditional: true });
405
+ if (!result.ok) {
406
+ throw new Error(`Failed to compile Sortable behavior: ${JSON.stringify(result.errors)}`);
407
+ }
500
408
  const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
501
- await hf.execute(syntheticNode, ctx);
409
+ await hf.execute(result.ast, ctx);
502
410
  }
503
411
  var sortableSource, sortableMetadata, sortable_default;
504
412
  var init_sortable = __esm({
@@ -529,7 +437,7 @@ var init_resizable_schema = __esm({
529
437
  category: "ui",
530
438
  tier: "optional",
531
439
  version: "1.0.0",
532
- description: "Makes elements resizable by dragging",
440
+ description: "Makes elements resizable by dragging (EXPERIMENTAL \u2014 stateful async component, beyond the inline-scripting boundary; not part of the curated set)",
533
441
  parameters: [
534
442
  {
535
443
  name: "minWidth",
@@ -577,15 +485,15 @@ behavior Resizable(minWidth, minHeight, maxWidth, maxHeight)
577
485
  set startX to clientX
578
486
  set startY to clientY
579
487
  repeat until event pointerup from document
580
- wait for pointermove(clientX, clientY) from document
488
+ wait for pointermove(clientX, clientY) or pointerup(clientX, clientY) from document
581
489
  set newWidth to startWidth + clientX - startX
582
490
  set newHeight to startHeight + clientY - startY
583
491
  if newWidth < minWidth then set newWidth to minWidth end
584
492
  if newWidth > maxWidth then set newWidth to maxWidth end
585
493
  if newHeight < minHeight then set newHeight to minHeight end
586
494
  if newHeight > maxHeight then set newHeight to maxHeight end
587
- set my style.width to newWidth + "px"
588
- set my style.height to newHeight + "px"
495
+ set my *width to newWidth + "px"
496
+ set my *height to newHeight + "px"
589
497
  trigger resizable:resize
590
498
  end
591
499
  trigger resizable:end
@@ -604,43 +512,6 @@ __export(resizable_exports, {
604
512
  resizableMetadata: () => resizableMetadata,
605
513
  resizableSource: () => resizableSource
606
514
  });
607
- function installResizable(element, params) {
608
- let handleEl = element;
609
- if (params.handle && params.handle !== "me") {
610
- if (typeof params.handle === "string") {
611
- const found = element.querySelector(params.handle);
612
- if (found instanceof HTMLElement) handleEl = found;
613
- } else if (params.handle instanceof HTMLElement) {
614
- handleEl = params.handle;
615
- }
616
- }
617
- const minW = params.minWidth ?? 50;
618
- const minH = params.minHeight ?? 50;
619
- const maxW = params.maxWidth ?? 9999;
620
- const maxH = params.maxHeight ?? 9999;
621
- handleEl.addEventListener("pointerdown", (e) => {
622
- e.preventDefault();
623
- element.dispatchEvent(new CustomEvent("resizable:start", { bubbles: true }));
624
- const startWidth = element.offsetWidth;
625
- const startHeight = element.offsetHeight;
626
- const startX = e.clientX;
627
- const startY = e.clientY;
628
- function onMove(ev) {
629
- const newWidth = Math.max(minW, Math.min(maxW, startWidth + (ev.clientX - startX)));
630
- const newHeight = Math.max(minH, Math.min(maxH, startHeight + (ev.clientY - startY)));
631
- element.style.width = `${newWidth}px`;
632
- element.style.height = `${newHeight}px`;
633
- element.dispatchEvent(new CustomEvent("resizable:resize", { bubbles: true }));
634
- }
635
- function onUp() {
636
- document.removeEventListener("pointermove", onMove);
637
- document.removeEventListener("pointerup", onUp);
638
- element.dispatchEvent(new CustomEvent("resizable:end", { bubbles: true }));
639
- }
640
- document.addEventListener("pointermove", onMove);
641
- document.addEventListener("pointerup", onUp);
642
- });
643
- }
644
515
  async function registerResizable(hyperfixi) {
645
516
  const hf = hyperfixi || resolveRuntime();
646
517
  if (!hf) {
@@ -648,15 +519,12 @@ async function registerResizable(hyperfixi) {
648
519
  "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
649
520
  );
650
521
  }
651
- const syntheticNode = {
652
- type: "behavior",
653
- name: "Resizable",
654
- parameters: [],
655
- eventHandlers: [],
656
- imperativeInstaller: installResizable
657
- };
522
+ const result = hf.compileSync(resizableSchema.source, { traditional: true });
523
+ if (!result.ok) {
524
+ throw new Error(`Failed to compile Resizable behavior: ${JSON.stringify(result.errors)}`);
525
+ }
658
526
  const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
659
- await hf.execute(syntheticNode, ctx);
527
+ await hf.execute(result.ast, ctx);
660
528
  }
661
529
  var resizableSource, resizableMetadata, resizable_default;
662
530
  var init_resizable = __esm({
@@ -741,29 +609,32 @@ behavior Clipboard(text, source, feedback, feedbackDuration)
741
609
  set copyText to source's textContent
742
610
  end
743
611
  js(me, copyText, feedback, feedbackDuration)
744
- async function copyToClipboard(t) {
745
- if (navigator.clipboard && navigator.clipboard.writeText) {
746
- await navigator.clipboard.writeText(t);
747
- return;
612
+ // Wrapped in an async IIFE: hyperscript's js() block has no top-level await.
613
+ (async function() {
614
+ async function copyToClipboard(t) {
615
+ if (navigator.clipboard && navigator.clipboard.writeText) {
616
+ await navigator.clipboard.writeText(t);
617
+ return;
618
+ }
619
+ var ta = document.createElement('textarea');
620
+ ta.value = t;
621
+ ta.style.position = 'fixed';
622
+ ta.style.opacity = '0';
623
+ document.body.appendChild(ta);
624
+ ta.select();
625
+ try { document.execCommand('copy'); } finally { document.body.removeChild(ta); }
748
626
  }
749
- var ta = document.createElement('textarea');
750
- ta.value = t;
751
- ta.style.position = 'fixed';
752
- ta.style.opacity = '0';
753
- document.body.appendChild(ta);
754
- ta.select();
755
- try { document.execCommand('copy'); } finally { document.body.removeChild(ta); }
756
- }
757
- try {
758
- await copyToClipboard(copyText);
759
- var feedbackEl = feedback ? (typeof feedback === 'string' ? document.querySelector(feedback) : feedback) : me;
760
- if (!feedbackEl) feedbackEl = me;
761
- feedbackEl.classList.add('copied');
762
- me.dispatchEvent(new CustomEvent('clipboard:copied', { bubbles: true, detail: { text: copyText } }));
763
- setTimeout(function() { feedbackEl.classList.remove('copied'); }, feedbackDuration);
764
- } catch(err) {
765
- me.dispatchEvent(new CustomEvent('clipboard:error', { bubbles: true, detail: { error: err } }));
766
- }
627
+ try {
628
+ await copyToClipboard(copyText);
629
+ var feedbackEl = feedback ? (typeof feedback === 'string' ? document.querySelector(feedback) : feedback) : me;
630
+ if (!feedbackEl) feedbackEl = me;
631
+ feedbackEl.classList.add('copied');
632
+ me.dispatchEvent(new CustomEvent('clipboard:copied', { bubbles: true, detail: { text: copyText } }));
633
+ setTimeout(function() { feedbackEl.classList.remove('copied'); }, feedbackDuration);
634
+ } catch(err) {
635
+ me.dispatchEvent(new CustomEvent('clipboard:error', { bubbles: true, detail: { error: err } }));
636
+ }
637
+ })();
767
638
  end
768
639
  end
769
640
  end`.trim()
@@ -779,62 +650,6 @@ __export(clipboard_exports, {
779
650
  default: () => clipboard_default,
780
651
  registerClipboard: () => registerClipboard
781
652
  });
782
- async function copyToClipboard(text) {
783
- if (navigator.clipboard?.writeText) {
784
- await navigator.clipboard.writeText(text);
785
- return;
786
- }
787
- const textarea = document.createElement("textarea");
788
- textarea.value = text;
789
- textarea.style.position = "fixed";
790
- textarea.style.opacity = "0";
791
- document.body.appendChild(textarea);
792
- textarea.select();
793
- try {
794
- document.execCommand("copy");
795
- } finally {
796
- document.body.removeChild(textarea);
797
- }
798
- }
799
- function resolveElement(element, param) {
800
- if (!param || param === "me") return element;
801
- if (param instanceof HTMLElement) return param;
802
- if (typeof param === "string") {
803
- return element.querySelector(param) || document.querySelector(param) || null;
804
- }
805
- return null;
806
- }
807
- function installClipboard(element, params) {
808
- const feedbackDuration = typeof params.feedbackDuration === "number" ? params.feedbackDuration : 2e3;
809
- element.addEventListener("click", async () => {
810
- let copyText;
811
- if (params.text != null) {
812
- copyText = String(params.text);
813
- } else {
814
- const sourceEl = resolveElement(element, params.source) || element;
815
- copyText = sourceEl.value ?? sourceEl.textContent ?? "";
816
- }
817
- try {
818
- await copyToClipboard(copyText);
819
- const feedbackEl = resolveElement(element, params.feedback) || element;
820
- feedbackEl.classList.add("copied");
821
- setTimeout(() => feedbackEl.classList.remove("copied"), feedbackDuration);
822
- element.dispatchEvent(
823
- new CustomEvent("clipboard:copied", {
824
- bubbles: true,
825
- detail: { text: copyText }
826
- })
827
- );
828
- } catch (error) {
829
- element.dispatchEvent(
830
- new CustomEvent("clipboard:error", {
831
- bubbles: true,
832
- detail: { error }
833
- })
834
- );
835
- }
836
- });
837
- }
838
653
  async function registerClipboard(hyperfixi) {
839
654
  const hf = hyperfixi || resolveRuntime();
840
655
  if (!hf) {
@@ -842,15 +657,12 @@ async function registerClipboard(hyperfixi) {
842
657
  "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
843
658
  );
844
659
  }
845
- const syntheticNode = {
846
- type: "behavior",
847
- name: "Clipboard",
848
- parameters: ["text", "source", "feedback", "feedbackDuration"],
849
- eventHandlers: [],
850
- imperativeInstaller: installClipboard
851
- };
660
+ const result = hf.compileSync(clipboardSchema.source, { traditional: true });
661
+ if (!result.ok) {
662
+ throw new Error(`Failed to compile Clipboard behavior: ${JSON.stringify(result.errors)}`);
663
+ }
852
664
  const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
853
- await hf.execute(syntheticNode, ctx);
665
+ await hf.execute(result.ast, ctx);
854
666
  }
855
667
  var clipboardSource, clipboardMetadata, clipboard_default;
856
668
  var init_clipboard = __esm({
@@ -981,52 +793,6 @@ __export(autodismiss_exports, {
981
793
  default: () => autodismiss_default,
982
794
  registerAutoDismiss: () => registerAutoDismiss
983
795
  });
984
- function installAutoDismiss(element, params) {
985
- const delay = typeof params.delay === "number" ? params.delay : 5e3;
986
- const pauseOnHover = params.pauseOnHover !== false;
987
- const effect = params.effect === "fade" ? "fade" : "none";
988
- let timerId = null;
989
- let remaining = delay;
990
- let startedAt = Date.now();
991
- function dismiss() {
992
- const event = new CustomEvent("autodismiss:dismissed", {
993
- bubbles: true,
994
- cancelable: true
995
- });
996
- element.dispatchEvent(event);
997
- if (event.defaultPrevented) return;
998
- if (effect === "fade") {
999
- element.style.transition = "opacity 300ms";
1000
- element.style.opacity = "0";
1001
- setTimeout(() => element.remove(), 300);
1002
- } else {
1003
- element.remove();
1004
- }
1005
- }
1006
- function start() {
1007
- startedAt = Date.now();
1008
- timerId = setTimeout(dismiss, remaining);
1009
- }
1010
- element.dispatchEvent(new CustomEvent("autodismiss:start", { bubbles: true }));
1011
- start();
1012
- if (pauseOnHover) {
1013
- element.addEventListener("mouseenter", () => {
1014
- if (timerId != null) {
1015
- clearTimeout(timerId);
1016
- timerId = null;
1017
- remaining -= Date.now() - startedAt;
1018
- if (remaining < 0) remaining = 0;
1019
- element.dispatchEvent(new CustomEvent("autodismiss:paused", { bubbles: true }));
1020
- }
1021
- });
1022
- element.addEventListener("mouseleave", () => {
1023
- if (timerId == null && element.isConnected) {
1024
- element.dispatchEvent(new CustomEvent("autodismiss:resumed", { bubbles: true }));
1025
- start();
1026
- }
1027
- });
1028
- }
1029
- }
1030
796
  async function registerAutoDismiss(hyperfixi) {
1031
797
  const hf = hyperfixi || resolveRuntime();
1032
798
  if (!hf) {
@@ -1034,15 +800,12 @@ async function registerAutoDismiss(hyperfixi) {
1034
800
  "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
1035
801
  );
1036
802
  }
1037
- const syntheticNode = {
1038
- type: "behavior",
1039
- name: "AutoDismiss",
1040
- parameters: ["delay", "pauseOnHover", "effect"],
1041
- eventHandlers: [],
1042
- imperativeInstaller: installAutoDismiss
1043
- };
803
+ const result = hf.compileSync(autoDismissSchema.source, { traditional: true });
804
+ if (!result.ok) {
805
+ throw new Error(`Failed to compile AutoDismiss behavior: ${JSON.stringify(result.errors)}`);
806
+ }
1044
807
  const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
1045
- await hf.execute(syntheticNode, ctx);
808
+ await hf.execute(result.ast, ctx);
1046
809
  }
1047
810
  var autoDismissSource, autoDismissMetadata, autodismiss_default;
1048
811
  var init_autodismiss = __esm({
@@ -1103,7 +866,7 @@ behavior ClickOutside(active)
1103
866
  end
1104
867
  end
1105
868
  on pointerdown from document
1106
- js(me, active)
869
+ js(me, active, event)
1107
870
  if (!me.isConnected) return;
1108
871
  if (active && !me.contains(event.target)) {
1109
872
  me.dispatchEvent(new CustomEvent('clickoutside', { bubbles: true }));
@@ -1129,25 +892,6 @@ __export(clickoutside_exports, {
1129
892
  default: () => clickoutside_default,
1130
893
  registerClickOutside: () => registerClickOutside
1131
894
  });
1132
- function installClickOutside(element, params) {
1133
- let active = params.active !== false;
1134
- function onPointerDown(e) {
1135
- if (!element.isConnected) {
1136
- document.removeEventListener("pointerdown", onPointerDown);
1137
- return;
1138
- }
1139
- if (active && !element.contains(e.target)) {
1140
- element.dispatchEvent(new CustomEvent("clickoutside", { bubbles: true }));
1141
- }
1142
- }
1143
- document.addEventListener("pointerdown", onPointerDown);
1144
- element.addEventListener("clickoutside:activate", () => {
1145
- active = true;
1146
- });
1147
- element.addEventListener("clickoutside:deactivate", () => {
1148
- active = false;
1149
- });
1150
- }
1151
895
  async function registerClickOutside(hyperfixi) {
1152
896
  const hf = hyperfixi || resolveRuntime();
1153
897
  if (!hf) {
@@ -1155,15 +899,12 @@ async function registerClickOutside(hyperfixi) {
1155
899
  "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
1156
900
  );
1157
901
  }
1158
- const syntheticNode = {
1159
- type: "behavior",
1160
- name: "ClickOutside",
1161
- parameters: ["active"],
1162
- eventHandlers: [],
1163
- imperativeInstaller: installClickOutside
1164
- };
902
+ const result = hf.compileSync(clickOutsideSchema.source, { traditional: true });
903
+ if (!result.ok) {
904
+ throw new Error(`Failed to compile ClickOutside behavior: ${JSON.stringify(result.errors)}`);
905
+ }
1165
906
  const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
1166
- await hf.execute(syntheticNode, ctx);
907
+ await hf.execute(result.ast, ctx);
1167
908
  }
1168
909
  var clickOutsideSource, clickOutsideMetadata, clickoutside_default;
1169
910
  var init_clickoutside = __esm({
@@ -1286,71 +1027,6 @@ __export(focustrap_exports, {
1286
1027
  focusTrapSource: () => focusTrapSource,
1287
1028
  registerFocusTrap: () => registerFocusTrap
1288
1029
  });
1289
- function resolveElement2(container, param) {
1290
- if (!param) return null;
1291
- if (param instanceof HTMLElement) return param;
1292
- if (typeof param === "string") {
1293
- return container.querySelector(param) || document.querySelector(param) || null;
1294
- }
1295
- return null;
1296
- }
1297
- function installFocusTrap(element, params) {
1298
- const returnFocus = params.returnFocus !== false;
1299
- let isActive = false;
1300
- let previouslyFocused = null;
1301
- function getFocusableElements() {
1302
- return Array.from(element.querySelectorAll(FOCUSABLE_SELECTOR));
1303
- }
1304
- function onKeyDown(e) {
1305
- if (!isActive || e.key !== "Tab") return;
1306
- const focusable = getFocusableElements();
1307
- if (focusable.length === 0) {
1308
- e.preventDefault();
1309
- return;
1310
- }
1311
- e.preventDefault();
1312
- const currentIndex = focusable.indexOf(document.activeElement);
1313
- if (e.shiftKey) {
1314
- const prevIndex = currentIndex <= 0 ? focusable.length - 1 : currentIndex - 1;
1315
- focusable[prevIndex].focus();
1316
- } else {
1317
- const nextIndex = currentIndex >= focusable.length - 1 ? 0 : currentIndex + 1;
1318
- focusable[nextIndex].focus();
1319
- }
1320
- }
1321
- function activate() {
1322
- if (isActive) return;
1323
- isActive = true;
1324
- previouslyFocused = document.activeElement;
1325
- element.setAttribute("aria-modal", "true");
1326
- const initialEl = resolveElement2(element, params.initialFocus);
1327
- if (initialEl) {
1328
- initialEl.focus();
1329
- } else {
1330
- const focusable = getFocusableElements();
1331
- if (focusable.length > 0) {
1332
- focusable[0].focus();
1333
- }
1334
- }
1335
- element.dispatchEvent(new CustomEvent("focustrap:activated", { bubbles: true }));
1336
- }
1337
- function deactivate() {
1338
- if (!isActive) return;
1339
- isActive = false;
1340
- element.removeAttribute("aria-modal");
1341
- if (returnFocus && previouslyFocused instanceof HTMLElement) {
1342
- previouslyFocused.focus();
1343
- }
1344
- previouslyFocused = null;
1345
- element.dispatchEvent(new CustomEvent("focustrap:deactivated", { bubbles: true }));
1346
- }
1347
- element.addEventListener("keydown", onKeyDown);
1348
- element.addEventListener("focustrap:activate", () => activate());
1349
- element.addEventListener("focustrap:deactivate", () => deactivate());
1350
- if (params.active !== false) {
1351
- activate();
1352
- }
1353
- }
1354
1030
  async function registerFocusTrap(hyperfixi) {
1355
1031
  const hf = hyperfixi || resolveRuntime();
1356
1032
  if (!hf) {
@@ -1358,17 +1034,14 @@ async function registerFocusTrap(hyperfixi) {
1358
1034
  "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
1359
1035
  );
1360
1036
  }
1361
- const syntheticNode = {
1362
- type: "behavior",
1363
- name: "FocusTrap",
1364
- parameters: ["active", "initialFocus", "returnFocus"],
1365
- eventHandlers: [],
1366
- imperativeInstaller: installFocusTrap
1367
- };
1037
+ const result = hf.compileSync(focusTrapSchema.source, { traditional: true });
1038
+ if (!result.ok) {
1039
+ throw new Error(`Failed to compile FocusTrap behavior: ${JSON.stringify(result.errors)}`);
1040
+ }
1368
1041
  const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
1369
- await hf.execute(syntheticNode, ctx);
1042
+ await hf.execute(result.ast, ctx);
1370
1043
  }
1371
- var focusTrapSource, focusTrapMetadata, FOCUSABLE_SELECTOR, focustrap_default;
1044
+ var focusTrapSource, focusTrapMetadata, focustrap_default;
1372
1045
  var init_focustrap = __esm({
1373
1046
  "src/behaviors/focustrap.ts"() {
1374
1047
  "use strict";
@@ -1376,14 +1049,6 @@ var init_focustrap = __esm({
1376
1049
  init_types();
1377
1050
  focusTrapSource = focusTrapSchema.source;
1378
1051
  focusTrapMetadata = focusTrapSchema;
1379
- FOCUSABLE_SELECTOR = [
1380
- "a[href]",
1381
- "button:not(:disabled)",
1382
- "input:not(:disabled)",
1383
- "select:not(:disabled)",
1384
- "textarea:not(:disabled)",
1385
- '[tabindex]:not([tabindex="-1"])'
1386
- ].join(", ");
1387
1052
  if (resolveRuntime()) {
1388
1053
  registerFocusTrap().catch(console.error);
1389
1054
  }
@@ -1475,30 +1140,6 @@ __export(scrollreveal_exports, {
1475
1140
  scrollRevealMetadata: () => scrollRevealMetadata,
1476
1141
  scrollRevealSource: () => scrollRevealSource
1477
1142
  });
1478
- function installScrollReveal(element, params) {
1479
- const cls = typeof params.cls === "string" ? params.cls : "revealed";
1480
- const threshold = typeof params.threshold === "number" ? params.threshold : 0.1;
1481
- const once = params.once !== false;
1482
- const rootMargin = typeof params.rootMargin === "string" ? params.rootMargin : "0px";
1483
- const observer = new IntersectionObserver(
1484
- (entries) => {
1485
- for (const entry of entries) {
1486
- if (entry.isIntersecting) {
1487
- element.classList.add(cls);
1488
- element.dispatchEvent(new CustomEvent("scrollreveal:enter", { bubbles: true }));
1489
- if (once) {
1490
- observer.disconnect();
1491
- }
1492
- } else if (!once) {
1493
- element.classList.remove(cls);
1494
- element.dispatchEvent(new CustomEvent("scrollreveal:exit", { bubbles: true }));
1495
- }
1496
- }
1497
- },
1498
- { threshold, rootMargin }
1499
- );
1500
- observer.observe(element);
1501
- }
1502
1143
  async function registerScrollReveal(hyperfixi) {
1503
1144
  const hf = hyperfixi || resolveRuntime();
1504
1145
  if (!hf) {
@@ -1506,15 +1147,12 @@ async function registerScrollReveal(hyperfixi) {
1506
1147
  "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
1507
1148
  );
1508
1149
  }
1509
- const syntheticNode = {
1510
- type: "behavior",
1511
- name: "ScrollReveal",
1512
- parameters: ["cls", "threshold", "once", "rootMargin"],
1513
- eventHandlers: [],
1514
- imperativeInstaller: installScrollReveal
1515
- };
1150
+ const result = hf.compileSync(scrollRevealSchema.source, { traditional: true });
1151
+ if (!result.ok) {
1152
+ throw new Error(`Failed to compile ScrollReveal behavior: ${JSON.stringify(result.errors)}`);
1153
+ }
1516
1154
  const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
1517
- await hf.execute(syntheticNode, ctx);
1155
+ await hf.execute(result.ast, ctx);
1518
1156
  }
1519
1157
  var scrollRevealSource, scrollRevealMetadata, scrollreveal_default;
1520
1158
  var init_scrollreveal = __esm({
@@ -1682,117 +1320,6 @@ __export(tabs_exports, {
1682
1320
  tabsMetadata: () => tabsMetadata,
1683
1321
  tabsSource: () => tabsSource
1684
1322
  });
1685
- function ensureId(el, prefix) {
1686
- if (!el.id) {
1687
- el.id = `${prefix}-${++idCounter}`;
1688
- }
1689
- return el.id;
1690
- }
1691
- function installTabs(element, params) {
1692
- const orientation = params.orientation === "vertical" ? "vertical" : "horizontal";
1693
- const wrap = params.wrap !== false;
1694
- const activeClass = params.activeClass || "active";
1695
- const initialIndex = typeof params.activeTab === "number" ? params.activeTab : 0;
1696
- const tabs = Array.from(element.querySelectorAll('[role="tab"]'));
1697
- const panels = Array.from(element.querySelectorAll('[role="tabpanel"]'));
1698
- if (tabs.length === 0 || panels.length === 0) return;
1699
- const tablist = element.querySelector('[role="tablist"]') || tabs[0].parentElement;
1700
- if (tablist && !tablist.getAttribute("role")) {
1701
- tablist.setAttribute("role", "tablist");
1702
- }
1703
- if (tablist) {
1704
- tablist.setAttribute("aria-orientation", orientation);
1705
- }
1706
- const count = Math.min(tabs.length, panels.length);
1707
- for (let i = 0; i < count; i++) {
1708
- const tabId = ensureId(tabs[i], "tab");
1709
- const panelId = ensureId(panels[i], "tabpanel");
1710
- tabs[i].setAttribute("aria-controls", panelId);
1711
- panels[i].setAttribute("aria-labelledby", tabId);
1712
- }
1713
- let currentIndex = -1;
1714
- function selectTab(index, previousIndex) {
1715
- if (index === previousIndex || index < 0 || index >= count) return false;
1716
- const detail = {
1717
- tab: tabs[index],
1718
- panel: panels[index],
1719
- index,
1720
- previousIndex
1721
- };
1722
- const changeEvent = new CustomEvent("tabs:change", {
1723
- bubbles: true,
1724
- cancelable: true,
1725
- detail
1726
- });
1727
- element.dispatchEvent(changeEvent);
1728
- if (changeEvent.defaultPrevented) return false;
1729
- if (previousIndex >= 0 && previousIndex < count) {
1730
- tabs[previousIndex].setAttribute("aria-selected", "false");
1731
- tabs[previousIndex].setAttribute("tabindex", "-1");
1732
- tabs[previousIndex].classList.remove(activeClass);
1733
- panels[previousIndex].setAttribute("aria-hidden", "true");
1734
- panels[previousIndex].classList.remove(activeClass);
1735
- }
1736
- tabs[index].setAttribute("aria-selected", "true");
1737
- tabs[index].setAttribute("tabindex", "0");
1738
- tabs[index].classList.add(activeClass);
1739
- panels[index].setAttribute("aria-hidden", "false");
1740
- panels[index].classList.add(activeClass);
1741
- currentIndex = index;
1742
- element.dispatchEvent(new CustomEvent("tabs:changed", { bubbles: true, detail }));
1743
- return true;
1744
- }
1745
- for (let i = 0; i < count; i++) {
1746
- tabs[i].setAttribute("aria-selected", "false");
1747
- tabs[i].setAttribute("tabindex", "-1");
1748
- tabs[i].classList.remove(activeClass);
1749
- panels[i].setAttribute("aria-hidden", "true");
1750
- panels[i].classList.remove(activeClass);
1751
- }
1752
- const clamped = Math.max(0, Math.min(initialIndex, count - 1));
1753
- tabs[clamped].setAttribute("aria-selected", "true");
1754
- tabs[clamped].setAttribute("tabindex", "0");
1755
- tabs[clamped].classList.add(activeClass);
1756
- panels[clamped].setAttribute("aria-hidden", "false");
1757
- panels[clamped].classList.add(activeClass);
1758
- currentIndex = clamped;
1759
- for (let i = 0; i < count; i++) {
1760
- tabs[i].addEventListener("click", () => {
1761
- selectTab(i, currentIndex);
1762
- tabs[i].focus();
1763
- });
1764
- }
1765
- const keyTarget = tablist || element;
1766
- keyTarget.addEventListener("keydown", (e) => {
1767
- const isHorizontal = orientation === "horizontal";
1768
- const nextKey = isHorizontal ? "ArrowRight" : "ArrowDown";
1769
- const prevKey = isHorizontal ? "ArrowLeft" : "ArrowUp";
1770
- let nextIndex = null;
1771
- if (e.key === nextKey) {
1772
- nextIndex = currentIndex + 1;
1773
- if (nextIndex >= count) nextIndex = wrap ? 0 : null;
1774
- } else if (e.key === prevKey) {
1775
- nextIndex = currentIndex - 1;
1776
- if (nextIndex < 0) nextIndex = wrap ? count - 1 : null;
1777
- } else if (e.key === "Home") {
1778
- nextIndex = 0;
1779
- } else if (e.key === "End") {
1780
- nextIndex = count - 1;
1781
- }
1782
- if (nextIndex !== null) {
1783
- e.preventDefault();
1784
- if (selectTab(nextIndex, currentIndex)) {
1785
- tabs[nextIndex].focus();
1786
- }
1787
- }
1788
- });
1789
- element.addEventListener("tabs:select", ((e) => {
1790
- const index = e.detail?.index;
1791
- if (typeof index === "number") {
1792
- selectTab(index, currentIndex);
1793
- }
1794
- }));
1795
- }
1796
1323
  async function registerTabs(hyperfixi) {
1797
1324
  const hf = hyperfixi || resolveRuntime();
1798
1325
  if (!hf) {
@@ -1800,17 +1327,14 @@ async function registerTabs(hyperfixi) {
1800
1327
  "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
1801
1328
  );
1802
1329
  }
1803
- const syntheticNode = {
1804
- type: "behavior",
1805
- name: "Tabs",
1806
- parameters: ["orientation", "activeTab", "wrap", "activeClass"],
1807
- eventHandlers: [],
1808
- imperativeInstaller: installTabs
1809
- };
1330
+ const result = hf.compileSync(tabsSchema.source, { traditional: true });
1331
+ if (!result.ok) {
1332
+ throw new Error(`Failed to compile Tabs behavior: ${JSON.stringify(result.errors)}`);
1333
+ }
1810
1334
  const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
1811
- await hf.execute(syntheticNode, ctx);
1335
+ await hf.execute(result.ast, ctx);
1812
1336
  }
1813
- var tabsSource, tabsMetadata, idCounter, tabs_default;
1337
+ var tabsSource, tabsMetadata, tabs_default;
1814
1338
  var init_tabs = __esm({
1815
1339
  "src/behaviors/tabs.ts"() {
1816
1340
  "use strict";
@@ -1818,7 +1342,6 @@ var init_tabs = __esm({
1818
1342
  init_types();
1819
1343
  tabsSource = tabsSchema.source;
1820
1344
  tabsMetadata = tabsSchema;
1821
- idCounter = 0;
1822
1345
  if (resolveRuntime()) {
1823
1346
  registerTabs().catch(console.error);
1824
1347
  }
@@ -1839,10 +1362,14 @@ __export(index_exports, {
1839
1362
  BEHAVIORS_BY_TIER: () => BEHAVIORS_BY_TIER,
1840
1363
  BEHAVIOR_CATEGORIES: () => BEHAVIOR_CATEGORIES,
1841
1364
  BEHAVIOR_TIERS: () => BEHAVIOR_TIERS,
1365
+ CURATED_BEHAVIORS: () => CURATED_BEHAVIORS,
1366
+ CURATION_STATUS: () => CURATION_STATUS,
1842
1367
  ClickOutside: () => clickoutside_default,
1843
1368
  Clipboard: () => clipboard_default,
1844
1369
  Draggable: () => draggable_default,
1370
+ EXPERIMENTAL_BEHAVIORS: () => EXPERIMENTAL_BEHAVIORS,
1845
1371
  FocusTrap: () => focustrap_default,
1372
+ OPTIONAL_BEHAVIORS: () => OPTIONAL_BEHAVIORS,
1846
1373
  Removable: () => removable_default,
1847
1374
  Resizable: () => resizable_default,
1848
1375
  ScrollReveal: () => scrollreveal_default,
@@ -1855,6 +1382,7 @@ __export(index_exports, {
1855
1382
  clickOutsideSource: () => clickOutsideSource,
1856
1383
  clipboardMetadata: () => clipboardMetadata,
1857
1384
  clipboardSource: () => clipboardSource,
1385
+ curationStatusOf: () => curationStatusOf,
1858
1386
  draggableMetadata: () => draggableMetadata,
1859
1387
  draggableSource: () => draggableSource,
1860
1388
  focusTrapMetadata: () => focusTrapMetadata,
@@ -1868,6 +1396,7 @@ __export(index_exports, {
1868
1396
  getRegisteredBehaviors: () => getRegisteredBehaviors,
1869
1397
  getSchema: () => getSchema,
1870
1398
  hasLoader: () => hasLoader,
1399
+ isCurated: () => isCurated,
1871
1400
  isRegistered: () => isRegistered,
1872
1401
  loadAll: () => loadAll,
1873
1402
  loadBehavior: () => loadBehavior,
@@ -2182,6 +1711,28 @@ var BEHAVIOR_TIERS = {
2182
1711
  "Tabs": "core"
2183
1712
  };
2184
1713
 
1714
+ // src/curation.ts
1715
+ var CURATED_BEHAVIORS = [
1716
+ "Toggleable",
1717
+ "Removable",
1718
+ "ClickOutside",
1719
+ "Clipboard",
1720
+ "AutoDismiss"
1721
+ ];
1722
+ var OPTIONAL_BEHAVIORS = ["FocusTrap", "ScrollReveal", "Tabs"];
1723
+ var EXPERIMENTAL_BEHAVIORS = ["Draggable", "Sortable", "Resizable"];
1724
+ var CURATION_STATUS = {
1725
+ ...Object.fromEntries(CURATED_BEHAVIORS.map((n) => [n, "curated"])),
1726
+ ...Object.fromEntries(OPTIONAL_BEHAVIORS.map((n) => [n, "optional"])),
1727
+ ...Object.fromEntries(EXPERIMENTAL_BEHAVIORS.map((n) => [n, "experimental"]))
1728
+ };
1729
+ function curationStatusOf(name) {
1730
+ return CURATION_STATUS[name];
1731
+ }
1732
+ function isCurated(name) {
1733
+ return CURATION_STATUS[name] === "curated";
1734
+ }
1735
+
2185
1736
  // src/index.ts
2186
1737
  init_draggable();
2187
1738
  init_removable();
@@ -2240,10 +1791,14 @@ if (_runtime) {
2240
1791
  BEHAVIORS_BY_TIER,
2241
1792
  BEHAVIOR_CATEGORIES,
2242
1793
  BEHAVIOR_TIERS,
1794
+ CURATED_BEHAVIORS,
1795
+ CURATION_STATUS,
2243
1796
  ClickOutside,
2244
1797
  Clipboard,
2245
1798
  Draggable,
1799
+ EXPERIMENTAL_BEHAVIORS,
2246
1800
  FocusTrap,
1801
+ OPTIONAL_BEHAVIORS,
2247
1802
  Removable,
2248
1803
  Resizable,
2249
1804
  ScrollReveal,
@@ -2256,6 +1811,7 @@ if (_runtime) {
2256
1811
  clickOutsideSource,
2257
1812
  clipboardMetadata,
2258
1813
  clipboardSource,
1814
+ curationStatusOf,
2259
1815
  draggableMetadata,
2260
1816
  draggableSource,
2261
1817
  focusTrapMetadata,
@@ -2269,6 +1825,7 @@ if (_runtime) {
2269
1825
  getRegisteredBehaviors,
2270
1826
  getSchema,
2271
1827
  hasLoader,
1828
+ isCurated,
2272
1829
  isRegistered,
2273
1830
  loadAll,
2274
1831
  loadBehavior,