@hyperfixi/behaviors 2.2.0 → 2.3.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 (131) hide show
  1. package/dist/all.browser.global.js +316 -54
  2. package/dist/all.browser.global.js.map +1 -1
  3. package/dist/autodismiss.browser.global.js +54 -2
  4. package/dist/autodismiss.browser.global.js.map +1 -1
  5. package/dist/behaviors/autodismiss.cjs +54 -18
  6. package/dist/behaviors/autodismiss.cjs.map +1 -1
  7. package/dist/behaviors/autodismiss.js +2 -2
  8. package/dist/behaviors/clickoutside.cjs +23 -4
  9. package/dist/behaviors/clickoutside.cjs.map +1 -1
  10. package/dist/behaviors/clickoutside.js +2 -2
  11. package/dist/behaviors/clipboard.cjs +43 -21
  12. package/dist/behaviors/clipboard.cjs.map +1 -1
  13. package/dist/behaviors/clipboard.js +2 -2
  14. package/dist/behaviors/focustrap.cjs +44 -3
  15. package/dist/behaviors/focustrap.cjs.map +1 -1
  16. package/dist/behaviors/focustrap.js +2 -2
  17. package/dist/behaviors/removable.cjs +7 -4
  18. package/dist/behaviors/removable.cjs.map +1 -1
  19. package/dist/behaviors/removable.js +2 -2
  20. package/dist/behaviors/resizable.cjs +22 -14
  21. package/dist/behaviors/resizable.cjs.map +1 -1
  22. package/dist/behaviors/resizable.js +2 -2
  23. package/dist/behaviors/scrollreveal.cjs +25 -13
  24. package/dist/behaviors/scrollreveal.cjs.map +1 -1
  25. package/dist/behaviors/scrollreveal.js +2 -2
  26. package/dist/behaviors/sortable.cjs +18 -12
  27. package/dist/behaviors/sortable.cjs.map +1 -1
  28. package/dist/behaviors/sortable.js +2 -2
  29. package/dist/behaviors/tabs.cjs +80 -11
  30. package/dist/behaviors/tabs.cjs.map +1 -1
  31. package/dist/behaviors/tabs.js +2 -2
  32. package/dist/behaviors/toggleable.cjs +5 -2
  33. package/dist/behaviors/toggleable.cjs.map +1 -1
  34. package/dist/behaviors/toggleable.js +2 -2
  35. package/dist/chunk-66U2RSYJ.js +100 -0
  36. package/dist/chunk-66U2RSYJ.js.map +1 -0
  37. package/dist/{chunk-2NSKQMNM.js → chunk-7O7UOSBH.js} +2 -2
  38. package/dist/{chunk-244WSZOL.js → chunk-EKKJVXDZ.js} +2 -2
  39. package/dist/{chunk-AFGA54SA.js → chunk-F3CASJ7Q.js} +2 -2
  40. package/dist/{chunk-YHQRFUWV.js → chunk-GALKOMJ5.js} +2 -2
  41. package/dist/{chunk-272NKUJ3.js → chunk-HMU342XE.js} +8 -5
  42. package/dist/chunk-HMU342XE.js.map +1 -0
  43. package/dist/chunk-HQDYH45I.js +137 -0
  44. package/dist/chunk-HQDYH45I.js.map +1 -0
  45. package/dist/{chunk-WTUVPVSD.js → chunk-IQM32TEY.js} +2 -2
  46. package/dist/{chunk-H5Y5ARYG.js → chunk-L52AGCMP.js} +2 -2
  47. package/dist/{chunk-H2MCHR5A.js → chunk-LQJOQTBZ.js} +2 -2
  48. package/dist/{chunk-7JDV2THA.js → chunk-MVNHMYIK.js} +11 -11
  49. package/dist/{chunk-BWZ6EGII.js → chunk-NC6I6T7T.js} +19 -13
  50. package/dist/{chunk-BWZ6EGII.js.map → chunk-NC6I6T7T.js.map} +1 -1
  51. package/dist/chunk-OJ3YWO3W.js +92 -0
  52. package/dist/chunk-OJ3YWO3W.js.map +1 -0
  53. package/dist/{chunk-64DIQGQI.js → chunk-SLOXO6IY.js} +24 -5
  54. package/dist/chunk-SLOXO6IY.js.map +1 -0
  55. package/dist/{chunk-RPERQTFU.js → chunk-TLLGH5KX.js} +2 -2
  56. package/dist/{chunk-V5IWDPDP.js → chunk-U5GNXZUF.js} +23 -15
  57. package/dist/{chunk-V5IWDPDP.js.map → chunk-U5GNXZUF.js.map} +1 -1
  58. package/dist/{chunk-GPTHAUWN.js → chunk-URZGNPTQ.js} +26 -14
  59. package/dist/chunk-URZGNPTQ.js.map +1 -0
  60. package/dist/chunk-WOTZO7K4.js +92 -0
  61. package/dist/chunk-WOTZO7K4.js.map +1 -0
  62. package/dist/{chunk-JKBWIJFI.js → chunk-WPOQIMCC.js} +2 -2
  63. package/dist/{chunk-WUHHMDAA.js → chunk-XYZ7FOXJ.js} +6 -3
  64. package/dist/{chunk-WUHHMDAA.js.map → chunk-XYZ7FOXJ.js.map} +1 -1
  65. package/dist/{chunk-DYHBKDKB.js → chunk-ZZ2WSAX3.js} +2 -2
  66. package/dist/clickoutside.browser.global.js +16 -5
  67. package/dist/clickoutside.browser.global.js.map +1 -1
  68. package/dist/clipboard.browser.global.js +43 -2
  69. package/dist/clipboard.browser.global.js.map +1 -1
  70. package/dist/core.browser.global.js +5 -2
  71. package/dist/core.browser.global.js.map +1 -1
  72. package/dist/focustrap.browser.global.js +46 -5
  73. package/dist/focustrap.browser.global.js.map +1 -1
  74. package/dist/index.cjs +321 -102
  75. package/dist/index.cjs.map +1 -1
  76. package/dist/index.js +21 -21
  77. package/dist/loaders.cjs +321 -102
  78. package/dist/loaders.cjs.map +1 -1
  79. package/dist/loaders.js +11 -11
  80. package/dist/removable.browser.global.js +8 -5
  81. package/dist/removable.browser.global.js.map +1 -1
  82. package/dist/resizable.browser.global.js +24 -16
  83. package/dist/resizable.browser.global.js.map +1 -1
  84. package/dist/resolver.browser.global.js +407 -0
  85. package/dist/resolver.browser.global.js.map +1 -0
  86. package/dist/schemas/index.cjs +321 -102
  87. package/dist/schemas/index.cjs.map +1 -1
  88. package/dist/schemas/index.js +10 -10
  89. package/dist/scrollreveal.browser.global.js +27 -8
  90. package/dist/scrollreveal.browser.global.js.map +1 -1
  91. package/dist/sortable.browser.global.js +19 -13
  92. package/dist/sortable.browser.global.js.map +1 -1
  93. package/dist/tabs.browser.global.js +80 -2
  94. package/dist/tabs.browser.global.js.map +1 -1
  95. package/dist/toggleable.browser.global.js +6 -3
  96. package/dist/toggleable.browser.global.js.map +1 -1
  97. package/package.json +1 -1
  98. package/src/behavior-resolver.ts +91 -0
  99. package/src/browser-resolver-bundle.ts +42 -0
  100. package/src/schemas/autodismiss.schema.ts +54 -18
  101. package/src/schemas/clickoutside.schema.ts +22 -3
  102. package/src/schemas/clipboard.schema.ts +43 -21
  103. package/src/schemas/focustrap.schema.ts +44 -3
  104. package/src/schemas/removable.schema.ts +7 -4
  105. package/src/schemas/resizable.schema.ts +22 -14
  106. package/src/schemas/scrollreveal.schema.ts +25 -13
  107. package/src/schemas/sortable.schema.ts +18 -12
  108. package/src/schemas/tabs.schema.ts +80 -11
  109. package/src/schemas/toggleable.schema.ts +5 -2
  110. package/dist/chunk-272NKUJ3.js.map +0 -1
  111. package/dist/chunk-64DIQGQI.js.map +0 -1
  112. package/dist/chunk-GPTHAUWN.js.map +0 -1
  113. package/dist/chunk-GVJPA2EK.js +0 -68
  114. package/dist/chunk-GVJPA2EK.js.map +0 -1
  115. package/dist/chunk-QKDYW4VM.js +0 -70
  116. package/dist/chunk-QKDYW4VM.js.map +0 -1
  117. package/dist/chunk-RB7OB6OD.js +0 -51
  118. package/dist/chunk-RB7OB6OD.js.map +0 -1
  119. package/dist/chunk-ZQQZTMCJ.js +0 -64
  120. package/dist/chunk-ZQQZTMCJ.js.map +0 -1
  121. /package/dist/{chunk-2NSKQMNM.js.map → chunk-7O7UOSBH.js.map} +0 -0
  122. /package/dist/{chunk-244WSZOL.js.map → chunk-EKKJVXDZ.js.map} +0 -0
  123. /package/dist/{chunk-AFGA54SA.js.map → chunk-F3CASJ7Q.js.map} +0 -0
  124. /package/dist/{chunk-YHQRFUWV.js.map → chunk-GALKOMJ5.js.map} +0 -0
  125. /package/dist/{chunk-WTUVPVSD.js.map → chunk-IQM32TEY.js.map} +0 -0
  126. /package/dist/{chunk-H5Y5ARYG.js.map → chunk-L52AGCMP.js.map} +0 -0
  127. /package/dist/{chunk-H2MCHR5A.js.map → chunk-LQJOQTBZ.js.map} +0 -0
  128. /package/dist/{chunk-7JDV2THA.js.map → chunk-MVNHMYIK.js.map} +0 -0
  129. /package/dist/{chunk-RPERQTFU.js.map → chunk-TLLGH5KX.js.map} +0 -0
  130. /package/dist/{chunk-JKBWIJFI.js.map → chunk-WPOQIMCC.js.map} +0 -0
  131. /package/dist/{chunk-DYHBKDKB.js.map → chunk-ZZ2WSAX3.js.map} +0 -0
package/dist/index.js CHANGED
@@ -3,44 +3,44 @@ import {
3
3
  removableMetadata,
4
4
  removableSource,
5
5
  removable_default
6
- } from "./chunk-H5Y5ARYG.js";
6
+ } from "./chunk-L52AGCMP.js";
7
7
  import {
8
8
  registerResizable,
9
9
  resizableMetadata,
10
10
  resizableSource,
11
11
  resizable_default
12
- } from "./chunk-WTUVPVSD.js";
12
+ } from "./chunk-IQM32TEY.js";
13
13
  import {
14
14
  registerScrollReveal,
15
15
  scrollRevealMetadata,
16
16
  scrollRevealSource,
17
17
  scrollreveal_default
18
- } from "./chunk-244WSZOL.js";
18
+ } from "./chunk-EKKJVXDZ.js";
19
19
  import {
20
20
  registerSortable,
21
21
  sortableMetadata,
22
22
  sortableSource,
23
23
  sortable_default
24
- } from "./chunk-RPERQTFU.js";
24
+ } from "./chunk-TLLGH5KX.js";
25
25
  import {
26
26
  registerTabs,
27
27
  tabsMetadata,
28
28
  tabsSource,
29
29
  tabs_default
30
- } from "./chunk-JKBWIJFI.js";
30
+ } from "./chunk-WPOQIMCC.js";
31
31
  import {
32
32
  registerToggleable,
33
33
  toggleableMetadata,
34
34
  toggleableSource,
35
35
  toggleable_default
36
- } from "./chunk-YHQRFUWV.js";
37
- import "./chunk-7JDV2THA.js";
38
- import "./chunk-272NKUJ3.js";
39
- import "./chunk-V5IWDPDP.js";
40
- import "./chunk-GPTHAUWN.js";
41
- import "./chunk-BWZ6EGII.js";
42
- import "./chunk-GVJPA2EK.js";
43
- import "./chunk-WUHHMDAA.js";
36
+ } from "./chunk-GALKOMJ5.js";
37
+ import "./chunk-MVNHMYIK.js";
38
+ import "./chunk-HMU342XE.js";
39
+ import "./chunk-U5GNXZUF.js";
40
+ import "./chunk-URZGNPTQ.js";
41
+ import "./chunk-NC6I6T7T.js";
42
+ import "./chunk-HQDYH45I.js";
43
+ import "./chunk-XYZ7FOXJ.js";
44
44
  import {
45
45
  getAllSchemas,
46
46
  getAllSchemasRecord,
@@ -69,22 +69,22 @@ import {
69
69
  autoDismissSource,
70
70
  autodismiss_default,
71
71
  registerAutoDismiss
72
- } from "./chunk-H2MCHR5A.js";
73
- import "./chunk-ZQQZTMCJ.js";
72
+ } from "./chunk-LQJOQTBZ.js";
73
+ import "./chunk-66U2RSYJ.js";
74
74
  import {
75
75
  clickOutsideMetadata,
76
76
  clickOutsideSource,
77
77
  clickoutside_default,
78
78
  registerClickOutside
79
- } from "./chunk-DYHBKDKB.js";
80
- import "./chunk-64DIQGQI.js";
79
+ } from "./chunk-ZZ2WSAX3.js";
80
+ import "./chunk-SLOXO6IY.js";
81
81
  import {
82
82
  clipboardMetadata,
83
83
  clipboardSource,
84
84
  clipboard_default,
85
85
  registerClipboard
86
- } from "./chunk-2NSKQMNM.js";
87
- import "./chunk-QKDYW4VM.js";
86
+ } from "./chunk-7O7UOSBH.js";
87
+ import "./chunk-WOTZO7K4.js";
88
88
  import {
89
89
  draggableMetadata,
90
90
  draggableSource,
@@ -97,8 +97,8 @@ import {
97
97
  focusTrapSource,
98
98
  focustrap_default,
99
99
  registerFocusTrap
100
- } from "./chunk-AFGA54SA.js";
101
- import "./chunk-RB7OB6OD.js";
100
+ } from "./chunk-F3CASJ7Q.js";
101
+ import "./chunk-OJ3YWO3W.js";
102
102
  import {
103
103
  resolveRuntime
104
104
  } from "./chunk-6TJXDCAQ.js";
package/dist/loaders.cjs CHANGED
@@ -102,27 +102,33 @@ var init_sortable_schema = __esm({
102
102
  source: `
103
103
  behavior Sortable(handle, dragClass)
104
104
  init
105
- if no dragClass set dragClass to "sorting"
105
+ if dragClass is undefined
106
+ set dragClass to "sorting"
107
+ end
106
108
  end
107
- on pointerdown(target, clientY) from me
108
- set item to closest <li/> in target
109
- if no item exit
110
- if handle
111
- set handleEl to target.closest(handle)
112
- if no handleEl exit
109
+ on pointerdown(clientY) from me
110
+ js(me, handle, event)
111
+ var target = event.target;
112
+ var item = target.closest("li");
113
+ if (!item || !me.contains(item)) return false;
114
+ if (handle && !target.closest(handle)) return false;
115
+ event.preventDefault();
116
+ event.stopPropagation();
117
+ return true;
113
118
  end
114
- halt the event
115
- add dragClass to item
119
+ if it is false
120
+ exit
121
+ end
122
+ add .{dragClass} to me
116
123
  trigger sortable:start on me
117
124
  repeat until event pointerup from document
118
125
  wait for pointermove(clientY) from document
119
126
  trigger sortable:move on me
120
127
  end
121
- remove dragClass from item
128
+ remove .{dragClass} from me
122
129
  trigger sortable:end on me
123
130
  end
124
- end
125
- `.trim()
131
+ end`.trim()
126
132
  };
127
133
  }
128
134
  });
@@ -183,11 +189,21 @@ var init_resizable_schema = __esm({
183
189
  source: `
184
190
  behavior Resizable(handle, minWidth, minHeight, maxWidth, maxHeight)
185
191
  init
186
- if no handle set handle to me
187
- if no minWidth set minWidth to 50
188
- if no minHeight set minHeight to 50
189
- if no maxWidth set maxWidth to 9999
190
- if no maxHeight set maxHeight to 9999
192
+ if handle is undefined
193
+ set handle to me
194
+ end
195
+ if minWidth is undefined
196
+ set minWidth to 50
197
+ end
198
+ if minHeight is undefined
199
+ set minHeight to 50
200
+ end
201
+ if maxWidth is undefined
202
+ set maxWidth to 9999
203
+ end
204
+ if maxHeight is undefined
205
+ set maxHeight to 9999
206
+ end
191
207
  end
192
208
  on pointerdown(clientX, clientY) from handle
193
209
  halt the event
@@ -199,15 +215,13 @@ behavior Resizable(handle, minWidth, minHeight, maxWidth, maxHeight)
199
215
  set startX to clientX
200
216
  set startY to clientY
201
217
  repeat until event pointerup from document
202
- wait for pointermove(clientX, clientY) or
203
- pointerup from document
204
- set newWidth to startWidth + (clientX - startX)
205
- set newHeight to startHeight + (clientY - startY)
206
- if newWidth < minWidth set newWidth to minWidth
207
- if newWidth > maxWidth set newWidth to maxWidth
208
- if newHeight < minHeight set newHeight to minHeight
209
- if newHeight > maxHeight set newHeight to maxHeight
210
- add { width: \${newWidth}px; height: \${newHeight}px; }
218
+ wait for pointermove(clientX, clientY) or pointerup from document
219
+ js(startWidth, startHeight, clientX, clientY, startX, startY, minWidth, maxWidth, minHeight, maxHeight, me)
220
+ var nw = Math.max(minWidth, Math.min(maxWidth, startWidth + (clientX - startX)));
221
+ var nh = Math.max(minHeight, Math.min(maxHeight, startHeight + (clientY - startY)));
222
+ me.style.width = nw + 'px';
223
+ me.style.height = nh + 'px';
224
+ end
211
225
  trigger resizable:resize
212
226
  end
213
227
  trigger resizable:end
@@ -238,7 +252,7 @@ var init_removable_schema = __esm({
238
252
  description: "Element that triggers removal (e.g., a close button)"
239
253
  },
240
254
  {
241
- name: "confirm",
255
+ name: "confirmRemoval",
242
256
  type: "boolean",
243
257
  optional: true,
244
258
  default: false,
@@ -258,15 +272,18 @@ var init_removable_schema = __esm({
258
272
  { name: "removable:removed", description: "Fired after removal" }
259
273
  ],
260
274
  source: `
261
- behavior Removable(triggerEl, confirm, effect)
275
+ behavior Removable(triggerEl, confirmRemoval, effect)
262
276
  init
263
277
  if triggerEl is undefined
264
278
  set triggerEl to me
265
279
  end
266
280
  end
267
281
  on click from triggerEl
268
- if confirm
269
- if not window.confirm("Are you sure?")
282
+ if confirmRemoval
283
+ js(me)
284
+ if (!window.confirm("Are you sure?")) return "cancel";
285
+ end
286
+ if it is "cancel"
270
287
  halt
271
288
  end
272
289
  end
@@ -326,9 +343,12 @@ behavior Toggleable(cls, target)
326
343
  end
327
344
  on click
328
345
  toggle .{cls} on target
346
+ js(target, cls)
347
+ var eventName = target.classList.contains(cls) ? 'toggleable:on' : 'toggleable:off';
348
+ target.dispatchEvent(new CustomEvent(eventName, { bubbles: true }));
349
+ end
329
350
  end
330
- end
331
- `.trim()
351
+ end`.trim()
332
352
  };
333
353
  }
334
354
  });
@@ -380,27 +400,49 @@ var init_clipboard_schema = __esm({
380
400
  "navigator.clipboard.writeText() requires HTTPS or localhost",
381
401
  'Falls back to document.execCommand("copy") for older browsers'
382
402
  ],
383
- source: [
384
- "behavior Clipboard(text, source, feedback, feedbackDuration)",
385
- " init",
386
- " if feedbackDuration is undefined set feedbackDuration to 2000",
387
- " if source is undefined set source to me",
388
- " end",
389
- " on click",
390
- " if text is not undefined",
391
- " set copyText to text",
392
- " else",
393
- " set copyText to source's value or source's textContent",
394
- " end",
395
- " js(copyText) navigator.clipboard.writeText(copyText) end",
396
- " set feedbackEl to feedback or me",
397
- " add .copied to feedbackEl",
398
- " wait feedbackDuration ms",
399
- " remove .copied from feedbackEl",
400
- " trigger clipboard:copied",
401
- " end",
402
- "end"
403
- ].join("\n")
403
+ source: `
404
+ behavior Clipboard(text, source, feedback, feedbackDuration)
405
+ init
406
+ if feedbackDuration is undefined
407
+ set feedbackDuration to 2000
408
+ end
409
+ if source is undefined
410
+ set source to me
411
+ end
412
+ end
413
+ on click
414
+ if text is not undefined
415
+ set copyText to text
416
+ else
417
+ set copyText to source's textContent
418
+ end
419
+ js(me, copyText, feedback, feedbackDuration)
420
+ async function copyToClipboard(t) {
421
+ if (navigator.clipboard && navigator.clipboard.writeText) {
422
+ await navigator.clipboard.writeText(t);
423
+ return;
424
+ }
425
+ var ta = document.createElement('textarea');
426
+ ta.value = t;
427
+ ta.style.position = 'fixed';
428
+ ta.style.opacity = '0';
429
+ document.body.appendChild(ta);
430
+ ta.select();
431
+ try { document.execCommand('copy'); } finally { document.body.removeChild(ta); }
432
+ }
433
+ try {
434
+ await copyToClipboard(copyText);
435
+ var feedbackEl = feedback ? (typeof feedback === 'string' ? document.querySelector(feedback) : feedback) : me;
436
+ if (!feedbackEl) feedbackEl = me;
437
+ feedbackEl.classList.add('copied');
438
+ me.dispatchEvent(new CustomEvent('clipboard:copied', { bubbles: true, detail: { text: copyText } }));
439
+ setTimeout(function() { feedbackEl.classList.remove('copied'); }, feedbackDuration);
440
+ } catch(err) {
441
+ me.dispatchEvent(new CustomEvent('clipboard:error', { bubbles: true, detail: { error: err } }));
442
+ }
443
+ end
444
+ end
445
+ end`.trim()
404
446
  };
405
447
  }
406
448
  });
@@ -449,24 +491,60 @@ var init_autodismiss_schema = __esm({
449
491
  { name: "autodismiss:paused", description: "Fired when the timer is paused on hover" },
450
492
  { name: "autodismiss:resumed", description: "Fired when the timer resumes on mouseleave" }
451
493
  ],
452
- source: [
453
- "behavior AutoDismiss(delay, pauseOnHover, effect)",
454
- " init",
455
- " if delay is undefined set delay to 5000",
456
- " if pauseOnHover is undefined set pauseOnHover to true",
457
- ' if effect is undefined set effect to "none"',
458
- " end",
459
- " on load",
460
- " trigger autodismiss:start",
461
- " wait delay ms",
462
- " trigger autodismiss:dismissed",
463
- ' if effect is "fade"',
464
- " transition opacity to 0 over 300ms",
465
- " end",
466
- " remove me",
467
- " end",
468
- "end"
469
- ].join("\n")
494
+ source: `
495
+ behavior AutoDismiss(delay, pauseOnHover, effect)
496
+ init
497
+ if delay is undefined
498
+ set delay to 5000
499
+ end
500
+ if pauseOnHover is undefined
501
+ set pauseOnHover to true
502
+ end
503
+ if effect is undefined
504
+ set effect to "none"
505
+ end
506
+ js(me, delay, effect, pauseOnHover)
507
+ me.dispatchEvent(new CustomEvent('autodismiss:start', { bubbles: true }));
508
+ var remaining = delay;
509
+ var startedAt = Date.now();
510
+ var timerId = null;
511
+ function dismiss() {
512
+ var ev = new CustomEvent('autodismiss:dismissed', { bubbles: true, cancelable: true });
513
+ me.dispatchEvent(ev);
514
+ if (ev.defaultPrevented) return;
515
+ if (effect === 'fade') {
516
+ me.style.transition = 'opacity 300ms';
517
+ me.style.opacity = '0';
518
+ setTimeout(function() { me.remove(); }, 300);
519
+ } else {
520
+ me.remove();
521
+ }
522
+ }
523
+ function start() {
524
+ startedAt = Date.now();
525
+ timerId = setTimeout(dismiss, remaining);
526
+ }
527
+ start();
528
+ if (pauseOnHover) {
529
+ me.addEventListener('mouseenter', function() {
530
+ if (timerId != null) {
531
+ clearTimeout(timerId);
532
+ timerId = null;
533
+ remaining -= Date.now() - startedAt;
534
+ if (remaining < 0) remaining = 0;
535
+ me.dispatchEvent(new CustomEvent('autodismiss:paused', { bubbles: true }));
536
+ }
537
+ });
538
+ me.addEventListener('mouseleave', function() {
539
+ if (timerId == null && me.isConnected) {
540
+ me.dispatchEvent(new CustomEvent('autodismiss:resumed', { bubbles: true }));
541
+ start();
542
+ }
543
+ });
544
+ }
545
+ end
546
+ end
547
+ end`.trim()
470
548
  };
471
549
  }
472
550
  });
@@ -492,19 +570,38 @@ var init_clickoutside_schema = __esm({
492
570
  }
493
571
  ],
494
572
  events: [
495
- { name: "clickoutside", description: "Fired when a pointer press occurs outside the element" }
573
+ { name: "clickoutside", description: "Fired when a pointer press occurs outside the element" },
574
+ {
575
+ name: "clickoutside:activate",
576
+ description: "Listen for this event to programmatically activate detection"
577
+ },
578
+ {
579
+ name: "clickoutside:deactivate",
580
+ description: "Listen for this event to programmatically deactivate detection"
581
+ }
496
582
  ],
497
583
  requirements: ["Uses pointerdown instead of click to avoid timing issues with removed elements"],
498
584
  source: `
499
585
  behavior ClickOutside(active)
500
586
  init
501
- if active is undefined set active to true
587
+ if active is undefined
588
+ set active to true
589
+ end
502
590
  end
503
591
  on pointerdown from document
504
- if active and not me.contains(event.target)
505
- trigger clickoutside on me
592
+ js(me, active)
593
+ if (!me.isConnected) return;
594
+ if (active && !me.contains(event.target)) {
595
+ me.dispatchEvent(new CustomEvent('clickoutside', { bubbles: true }));
596
+ }
506
597
  end
507
598
  end
599
+ on clickoutside:activate
600
+ set active to true
601
+ end
602
+ on clickoutside:deactivate
603
+ set active to false
604
+ end
508
605
  end`.trim()
509
606
  };
510
607
  }
@@ -554,10 +651,51 @@ var init_focustrap_schema = __esm({
554
651
  source: `
555
652
  behavior FocusTrap(active, initialFocus, returnFocus)
556
653
  init
557
- if active is undefined set active to true
558
- if returnFocus is undefined set returnFocus to true
654
+ if active is undefined
655
+ set active to true
656
+ end
657
+ if returnFocus is undefined
658
+ set returnFocus to true
659
+ end
660
+ js(me, active, initialFocus, returnFocus)
661
+ var FOCUSABLE = 'a[href],button:not(:disabled),input:not(:disabled),select:not(:disabled),textarea:not(:disabled),[tabindex]:not([tabindex="-1"])';
662
+ var isActive = false;
663
+ var previouslyFocused = null;
664
+ function getFocusable() { return Array.from(me.querySelectorAll(FOCUSABLE)); }
665
+ function activate() {
666
+ if (isActive) return;
667
+ isActive = true;
668
+ previouslyFocused = document.activeElement;
669
+ me.setAttribute('aria-modal', 'true');
670
+ var initEl = initialFocus ? (typeof initialFocus === 'string' ? me.querySelector(initialFocus) : initialFocus) : null;
671
+ if (initEl) { initEl.focus(); } else { var f = getFocusable(); if (f.length) f[0].focus(); }
672
+ me.dispatchEvent(new CustomEvent('focustrap:activated', { bubbles: true }));
673
+ }
674
+ function deactivate() {
675
+ if (!isActive) return;
676
+ isActive = false;
677
+ me.removeAttribute('aria-modal');
678
+ if (returnFocus && previouslyFocused instanceof HTMLElement) previouslyFocused.focus();
679
+ previouslyFocused = null;
680
+ me.dispatchEvent(new CustomEvent('focustrap:deactivated', { bubbles: true }));
681
+ }
682
+ me.addEventListener('keydown', function(e) {
683
+ if (!isActive || e.key !== 'Tab') return;
684
+ var focusable = getFocusable();
685
+ if (focusable.length === 0) { e.preventDefault(); return; }
686
+ e.preventDefault();
687
+ var idx = focusable.indexOf(document.activeElement);
688
+ if (e.shiftKey) {
689
+ focusable[idx <= 0 ? focusable.length - 1 : idx - 1].focus();
690
+ } else {
691
+ focusable[idx >= focusable.length - 1 ? 0 : idx + 1].focus();
692
+ }
693
+ });
694
+ me.addEventListener('focustrap:activate', function() { activate(); });
695
+ me.addEventListener('focustrap:deactivate', function() { deactivate(); });
696
+ if (active) activate();
697
+ end
559
698
  end
560
- -- Imperative installer handles Tab key trapping and focus management
561
699
  end`.trim()
562
700
  };
563
701
  }
@@ -595,13 +733,6 @@ var init_scrollreveal_schema = __esm({
595
733
  optional: true,
596
734
  default: true,
597
735
  description: "If true, disconnect observer after first intersection"
598
- },
599
- {
600
- name: "rootMargin",
601
- type: "string",
602
- optional: true,
603
- default: "0px",
604
- description: "CSS margin around the viewport for triggering earlier or later"
605
736
  }
606
737
  ],
607
738
  events: [
@@ -610,14 +741,33 @@ var init_scrollreveal_schema = __esm({
610
741
  ],
611
742
  requirements: ["Uses IntersectionObserver API (supported in all modern browsers)"],
612
743
  source: `
613
- behavior ScrollReveal(cls, threshold, once, rootMargin)
744
+ behavior ScrollReveal(cls, threshold, once)
614
745
  init
615
- if cls is undefined set cls to "revealed"
616
- if threshold is undefined set threshold to 0.1
617
- if once is undefined set once to true
618
- if rootMargin is undefined set rootMargin to "0px"
746
+ if cls is undefined
747
+ set cls to "revealed"
748
+ end
749
+ if threshold is undefined
750
+ set threshold to 0.1
751
+ end
752
+ if once is undefined
753
+ set once to true
754
+ end
755
+ js(me, cls, threshold, once)
756
+ var obs = new IntersectionObserver(function(entries) {
757
+ for (var i = 0; i < entries.length; i++) {
758
+ if (entries[i].isIntersecting) {
759
+ me.classList.add(cls);
760
+ me.dispatchEvent(new CustomEvent('scrollreveal:enter', { bubbles: true }));
761
+ if (once) obs.disconnect();
762
+ } else if (!once) {
763
+ me.classList.remove(cls);
764
+ me.dispatchEvent(new CustomEvent('scrollreveal:exit', { bubbles: true }));
765
+ }
766
+ }
767
+ }, { threshold: threshold });
768
+ obs.observe(me);
769
+ end
619
770
  end
620
- -- Imperative installer handles IntersectionObserver setup
621
771
  end`.trim()
622
772
  };
623
773
  }
@@ -678,17 +828,86 @@ var init_tabs_schema = __esm({
678
828
  "Manages aria-selected, aria-controls, aria-labelledby, and tabindex",
679
829
  "Keyboard: Arrow keys navigate, Home/End jump to first/last, Tab exits tablist"
680
830
  ],
681
- source: [
682
- "behavior Tabs(orientation, activeTab, wrap, activeClass)",
683
- " init",
684
- ' if orientation is undefined set orientation to "horizontal"',
685
- " if activeTab is undefined set activeTab to 0",
686
- " if wrap is undefined set wrap to true",
687
- ' if activeClass is undefined set activeClass to "active"',
688
- " end",
689
- " -- Imperative installer handles ARIA wiring and keyboard navigation",
690
- "end"
691
- ].join("\n")
831
+ source: `
832
+ behavior Tabs(orientation, activeTab, wrap, activeClass)
833
+ init
834
+ if orientation is undefined
835
+ set orientation to "horizontal"
836
+ end
837
+ if activeTab is undefined
838
+ set activeTab to 0
839
+ end
840
+ if wrap is undefined
841
+ set wrap to true
842
+ end
843
+ if activeClass is undefined
844
+ set activeClass to "active"
845
+ end
846
+ js(me, orientation, activeTab, wrap, activeClass)
847
+ var tabs = Array.from(me.querySelectorAll('[role="tab"]'));
848
+ var panels = Array.from(me.querySelectorAll('[role="tabpanel"]'));
849
+ if (tabs.length === 0 || panels.length === 0) return;
850
+ var tablist = me.querySelector('[role="tablist"]') || tabs[0].parentElement;
851
+ if (tablist) tablist.setAttribute('aria-orientation', orientation);
852
+ var count = Math.min(tabs.length, panels.length);
853
+ var idN = 0;
854
+ for (var i = 0; i < count; i++) {
855
+ if (!tabs[i].id) tabs[i].id = 'tab-' + (++idN);
856
+ if (!panels[i].id) panels[i].id = 'tabpanel-' + idN;
857
+ tabs[i].setAttribute('aria-controls', panels[i].id);
858
+ panels[i].setAttribute('aria-labelledby', tabs[i].id);
859
+ }
860
+ var cur = Math.max(0, Math.min(activeTab, count - 1));
861
+ function activate(idx, prev) {
862
+ if (idx === prev || idx < 0 || idx >= count) return false;
863
+ var ev = new CustomEvent('tabs:change', { bubbles: true, cancelable: true, detail: { index: idx, previousIndex: prev } });
864
+ me.dispatchEvent(ev);
865
+ if (ev.defaultPrevented) return false;
866
+ if (prev >= 0 && prev < count) {
867
+ tabs[prev].setAttribute('aria-selected', 'false');
868
+ tabs[prev].setAttribute('tabindex', '-1');
869
+ tabs[prev].classList.remove(activeClass);
870
+ panels[prev].setAttribute('aria-hidden', 'true');
871
+ panels[prev].classList.remove(activeClass);
872
+ }
873
+ tabs[idx].setAttribute('aria-selected', 'true');
874
+ tabs[idx].setAttribute('tabindex', '0');
875
+ tabs[idx].classList.add(activeClass);
876
+ panels[idx].setAttribute('aria-hidden', 'false');
877
+ panels[idx].classList.add(activeClass);
878
+ cur = idx;
879
+ me.dispatchEvent(new CustomEvent('tabs:changed', { bubbles: true, detail: { index: idx } }));
880
+ return true;
881
+ }
882
+ for (var j = 0; j < count; j++) {
883
+ tabs[j].setAttribute('aria-selected', 'false');
884
+ tabs[j].setAttribute('tabindex', '-1');
885
+ panels[j].setAttribute('aria-hidden', 'true');
886
+ panels[j].classList.remove(activeClass);
887
+ }
888
+ tabs[cur].setAttribute('aria-selected', 'true');
889
+ tabs[cur].setAttribute('tabindex', '0');
890
+ tabs[cur].classList.add(activeClass);
891
+ panels[cur].setAttribute('aria-hidden', 'false');
892
+ panels[cur].classList.add(activeClass);
893
+ for (var k = 0; k < count; k++) {
894
+ (function(idx) {
895
+ tabs[idx].addEventListener('click', function() { if (activate(idx, cur)) tabs[idx].focus(); });
896
+ })(k);
897
+ }
898
+ (tablist || me).addEventListener('keydown', function(e) {
899
+ var nk = orientation === 'horizontal' ? 'ArrowRight' : 'ArrowDown';
900
+ var pk = orientation === 'horizontal' ? 'ArrowLeft' : 'ArrowUp';
901
+ var next = null;
902
+ if (e.key === nk) { next = cur + 1; if (next >= count) next = wrap ? 0 : null; }
903
+ else if (e.key === pk) { next = cur - 1; if (next < 0) next = wrap ? count - 1 : null; }
904
+ else if (e.key === 'Home') next = 0;
905
+ else if (e.key === 'End') next = count - 1;
906
+ if (next !== null) { e.preventDefault(); if (activate(next, cur)) tabs[next].focus(); }
907
+ });
908
+ end
909
+ end
910
+ end`.trim()
692
911
  };
693
912
  }
694
913
  });