@hyperfixi/behaviors 3.3.0 → 4.0.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 (232) hide show
  1. package/CHANGELOG.md +162 -0
  2. package/README.md +29 -9
  3. package/dist/all.browser.global.js +45 -100
  4. package/dist/all.browser.global.js.map +1 -1
  5. package/dist/autodismiss.browser.global.js +5 -11
  6. package/dist/autodismiss.browser.global.js.map +1 -1
  7. package/dist/behaviors/autodismiss.cjs +19 -22
  8. package/dist/behaviors/autodismiss.cjs.map +1 -1
  9. package/dist/behaviors/autodismiss.d.cts +4 -4
  10. package/dist/behaviors/autodismiss.d.ts +4 -4
  11. package/dist/behaviors/autodismiss.js +3 -3
  12. package/dist/behaviors/clickoutside.cjs +19 -18
  13. package/dist/behaviors/clickoutside.cjs.map +1 -1
  14. package/dist/behaviors/clickoutside.d.cts +4 -4
  15. package/dist/behaviors/clickoutside.d.ts +4 -4
  16. package/dist/behaviors/clickoutside.js +3 -3
  17. package/dist/behaviors/clipboard.cjs +18 -19
  18. package/dist/behaviors/clipboard.cjs.map +1 -1
  19. package/dist/behaviors/clipboard.d.cts +4 -4
  20. package/dist/behaviors/clipboard.d.ts +4 -4
  21. package/dist/behaviors/clipboard.js +3 -3
  22. package/dist/behaviors/draggable.cjs +20 -25
  23. package/dist/behaviors/draggable.cjs.map +1 -1
  24. package/dist/behaviors/draggable.d.cts +4 -4
  25. package/dist/behaviors/draggable.d.ts +4 -4
  26. package/dist/behaviors/draggable.js +3 -3
  27. package/dist/behaviors/focustrap.cjs +18 -19
  28. package/dist/behaviors/focustrap.cjs.map +1 -1
  29. package/dist/behaviors/focustrap.d.cts +4 -4
  30. package/dist/behaviors/focustrap.d.ts +4 -4
  31. package/dist/behaviors/focustrap.js +3 -3
  32. package/dist/behaviors/removable.cjs +18 -21
  33. package/dist/behaviors/removable.cjs.map +1 -1
  34. package/dist/behaviors/removable.d.cts +4 -3
  35. package/dist/behaviors/removable.d.ts +4 -3
  36. package/dist/behaviors/removable.js +3 -3
  37. package/dist/behaviors/resizable.cjs +19 -19
  38. package/dist/behaviors/resizable.cjs.map +1 -1
  39. package/dist/behaviors/resizable.d.cts +4 -4
  40. package/dist/behaviors/resizable.d.ts +4 -4
  41. package/dist/behaviors/resizable.js +3 -3
  42. package/dist/behaviors/scrollreveal.cjs +19 -22
  43. package/dist/behaviors/scrollreveal.cjs.map +1 -1
  44. package/dist/behaviors/scrollreveal.d.cts +4 -4
  45. package/dist/behaviors/scrollreveal.d.ts +4 -4
  46. package/dist/behaviors/scrollreveal.js +3 -3
  47. package/dist/behaviors/sortable.cjs +19 -20
  48. package/dist/behaviors/sortable.cjs.map +1 -1
  49. package/dist/behaviors/sortable.d.cts +4 -4
  50. package/dist/behaviors/sortable.d.ts +4 -4
  51. package/dist/behaviors/sortable.js +3 -3
  52. package/dist/behaviors/tabs.cjs +20 -25
  53. package/dist/behaviors/tabs.cjs.map +1 -1
  54. package/dist/behaviors/tabs.d.cts +4 -4
  55. package/dist/behaviors/tabs.d.ts +4 -4
  56. package/dist/behaviors/tabs.js +3 -3
  57. package/dist/behaviors/toggleable.cjs +25 -26
  58. package/dist/behaviors/toggleable.cjs.map +1 -1
  59. package/dist/behaviors/toggleable.d.cts +4 -4
  60. package/dist/behaviors/toggleable.d.ts +4 -4
  61. package/dist/behaviors/toggleable.js +3 -3
  62. package/dist/chunk-2GIS4DCY.js +30 -0
  63. package/dist/chunk-2GIS4DCY.js.map +1 -0
  64. package/dist/chunk-3BCBZR6R.js +30 -0
  65. package/dist/chunk-3BCBZR6R.js.map +1 -0
  66. package/dist/chunk-4YUIDZAO.js +30 -0
  67. package/dist/chunk-4YUIDZAO.js.map +1 -0
  68. package/dist/{chunk-XYZ7FOXJ.js → chunk-AQCOK5J5.js} +10 -14
  69. package/dist/chunk-AQCOK5J5.js.map +1 -0
  70. package/dist/chunk-ATGHQQC7.js +30 -0
  71. package/dist/chunk-ATGHQQC7.js.map +1 -0
  72. package/dist/{chunk-HQDYH45I.js → chunk-CWLAXLWR.js} +5 -13
  73. package/dist/chunk-CWLAXLWR.js.map +1 -0
  74. package/dist/chunk-DMWN52SV.js +30 -0
  75. package/dist/chunk-DMWN52SV.js.map +1 -0
  76. package/dist/{chunk-PDMOOWFW.js → chunk-EIVPVTUI.js} +4 -8
  77. package/dist/{chunk-PDMOOWFW.js.map → chunk-EIVPVTUI.js.map} +1 -1
  78. package/dist/chunk-HHTEMPIT.js +30 -0
  79. package/dist/chunk-HHTEMPIT.js.map +1 -0
  80. package/dist/{chunk-26IX7QU7.js → chunk-HJESSMKB.js} +4 -6
  81. package/dist/{chunk-26IX7QU7.js.map → chunk-HJESSMKB.js.map} +1 -1
  82. package/dist/{chunk-5S7WN3ZQ.js → chunk-IFAH652L.js} +4 -7
  83. package/dist/chunk-IFAH652L.js.map +1 -0
  84. package/dist/chunk-IUGJG4RA.js +30 -0
  85. package/dist/chunk-IUGJG4RA.js.map +1 -0
  86. package/dist/{chunk-ZR66E3T6.js → chunk-JNLVXPHR.js} +13 -13
  87. package/dist/chunk-KEZEGPEX.js +30 -0
  88. package/dist/chunk-KEZEGPEX.js.map +1 -0
  89. package/dist/{chunk-66U2RSYJ.js → chunk-KP4GNXYS.js} +4 -10
  90. package/dist/chunk-KP4GNXYS.js.map +1 -0
  91. package/dist/chunk-KXQMCN4O.js +30 -0
  92. package/dist/chunk-KXQMCN4O.js.map +1 -0
  93. package/dist/{chunk-YXS27XM6.js → chunk-KYBOZ7C4.js} +3 -7
  94. package/dist/chunk-KYBOZ7C4.js.map +1 -0
  95. package/dist/chunk-LBWM6TTU.js +30 -0
  96. package/dist/chunk-LBWM6TTU.js.map +1 -0
  97. package/dist/{chunk-3DVDS7CT.js → chunk-LCDONZBX.js} +5 -5
  98. package/dist/chunk-LCDONZBX.js.map +1 -0
  99. package/dist/{chunk-OJ3YWO3W.js → chunk-NE76IBV2.js} +3 -7
  100. package/dist/chunk-NE76IBV2.js.map +1 -0
  101. package/dist/{chunk-HMU342XE.js → chunk-PVO6TZCZ.js} +3 -9
  102. package/dist/{chunk-HMU342XE.js.map → chunk-PVO6TZCZ.js.map} +1 -1
  103. package/dist/{chunk-URZGNPTQ.js → chunk-RILYRQ72.js} +4 -10
  104. package/dist/chunk-RILYRQ72.js.map +1 -0
  105. package/dist/{chunk-FBQ3X3UY.js → chunk-U4QMFVAM.js} +5 -13
  106. package/dist/chunk-U4QMFVAM.js.map +1 -0
  107. package/dist/chunk-VWDTOSE3.js +26 -0
  108. package/dist/chunk-VWDTOSE3.js.map +1 -0
  109. package/dist/chunk-YRQBU2OW.js +30 -0
  110. package/dist/chunk-YRQBU2OW.js.map +1 -0
  111. package/dist/clickoutside.browser.global.js +5 -7
  112. package/dist/clickoutside.browser.global.js.map +1 -1
  113. package/dist/clipboard.browser.global.js +4 -8
  114. package/dist/clipboard.browser.global.js.map +1 -1
  115. package/dist/core.browser.global.js +13 -25
  116. package/dist/core.browser.global.js.map +1 -1
  117. package/dist/draggable.browser.global.js +5 -13
  118. package/dist/draggable.browser.global.js.map +1 -1
  119. package/dist/focustrap.browser.global.js +4 -8
  120. package/dist/focustrap.browser.global.js.map +1 -1
  121. package/dist/index.cjs +96 -271
  122. package/dist/index.cjs.map +1 -1
  123. package/dist/index.d.cts +10 -10
  124. package/dist/index.d.ts +10 -10
  125. package/dist/index.js +42 -55
  126. package/dist/index.js.map +1 -1
  127. package/dist/loaders.cjs +75 -237
  128. package/dist/loaders.cjs.map +1 -1
  129. package/dist/loaders.js +13 -13
  130. package/dist/registry.cjs +4 -4
  131. package/dist/registry.cjs.map +1 -1
  132. package/dist/registry.d.cts +5 -6
  133. package/dist/registry.d.ts +5 -6
  134. package/dist/registry.js +1 -1
  135. package/dist/removable.browser.global.js +3 -9
  136. package/dist/removable.browser.global.js.map +1 -1
  137. package/dist/resizable.browser.global.js +4 -7
  138. package/dist/resizable.browser.global.js.map +1 -1
  139. package/dist/resolver.browser.global.js +45 -100
  140. package/dist/resolver.browser.global.js.map +1 -1
  141. package/dist/schemas/index.cjs +38 -93
  142. package/dist/schemas/index.cjs.map +1 -1
  143. package/dist/schemas/index.d.cts +2 -2
  144. package/dist/schemas/index.d.ts +2 -2
  145. package/dist/schemas/index.js +11 -11
  146. package/dist/schemas/index.js.map +1 -1
  147. package/dist/scrollreveal.browser.global.js +5 -11
  148. package/dist/scrollreveal.browser.global.js.map +1 -1
  149. package/dist/sortable.browser.global.js +5 -9
  150. package/dist/sortable.browser.global.js.map +1 -1
  151. package/dist/tabs.browser.global.js +6 -14
  152. package/dist/tabs.browser.global.js.map +1 -1
  153. package/dist/toggleable.browser.global.js +9 -13
  154. package/dist/toggleable.browser.global.js.map +1 -1
  155. package/dist/{types-DCCtVQS5.d.cts → types-CbA4L8XJ.d.cts} +16 -23
  156. package/dist/{types-DCCtVQS5.d.ts → types-CbA4L8XJ.d.ts} +16 -23
  157. package/package.json +5 -5
  158. package/src/behavior-resolver.ts +24 -56
  159. package/src/behaviors/autodismiss.test.ts +12 -20
  160. package/src/behaviors/autodismiss.ts +8 -23
  161. package/src/behaviors/clickoutside.test.ts +13 -21
  162. package/src/behaviors/clickoutside.ts +8 -23
  163. package/src/behaviors/clipboard.test.ts +12 -34
  164. package/src/behaviors/clipboard.ts +8 -23
  165. package/src/behaviors/curated-runtime.test.ts +22 -24
  166. package/src/behaviors/draggable.ts +10 -24
  167. package/src/behaviors/experimental-runtime.test.ts +19 -18
  168. package/src/behaviors/focustrap.test.ts +12 -20
  169. package/src/behaviors/focustrap.ts +8 -23
  170. package/src/behaviors/integration.test.ts +19 -54
  171. package/src/behaviors/optional-runtime.test.ts +17 -22
  172. package/src/behaviors/removable.ts +6 -20
  173. package/src/behaviors/resizable.ts +9 -24
  174. package/src/behaviors/scrollreveal.test.ts +13 -21
  175. package/src/behaviors/scrollreveal.ts +8 -23
  176. package/src/behaviors/sortable.ts +7 -22
  177. package/src/behaviors/tabs.test.ts +12 -34
  178. package/src/behaviors/tabs.ts +8 -23
  179. package/src/behaviors/toggleable.ts +10 -26
  180. package/src/browser-resolver-bundle.ts +20 -30
  181. package/src/core-bundle.ts +11 -11
  182. package/src/index.test.ts +2 -2
  183. package/src/index.ts +30 -47
  184. package/src/registry.test.ts +9 -34
  185. package/src/registry.ts +7 -11
  186. package/src/schemas/autodismiss.schema.ts +3 -9
  187. package/src/schemas/clickoutside.schema.ts +3 -5
  188. package/src/schemas/clipboard.schema.ts +2 -6
  189. package/src/schemas/draggable.schema.ts +4 -12
  190. package/src/schemas/focustrap.schema.ts +2 -6
  191. package/src/schemas/index.ts +2 -1
  192. package/src/schemas/removable.schema.ts +2 -8
  193. package/src/schemas/resizable.schema.ts +3 -6
  194. package/src/schemas/scrollreveal.schema.ts +3 -9
  195. package/src/schemas/sortable.schema.ts +3 -7
  196. package/src/schemas/tabs.schema.ts +4 -12
  197. package/src/schemas/toggleable.schema.ts +10 -13
  198. package/src/schemas/types.ts +37 -30
  199. package/dist/chunk-2HUF6RMI.js +0 -40
  200. package/dist/chunk-2HUF6RMI.js.map +0 -1
  201. package/dist/chunk-3DVDS7CT.js.map +0 -1
  202. package/dist/chunk-5S7WN3ZQ.js.map +0 -1
  203. package/dist/chunk-66U2RSYJ.js.map +0 -1
  204. package/dist/chunk-6TJXDCAQ.js +0 -11
  205. package/dist/chunk-6TJXDCAQ.js.map +0 -1
  206. package/dist/chunk-7TPDLB7W.js +0 -40
  207. package/dist/chunk-7TPDLB7W.js.map +0 -1
  208. package/dist/chunk-CR3J7VV6.js +0 -40
  209. package/dist/chunk-CR3J7VV6.js.map +0 -1
  210. package/dist/chunk-EDBG2F57.js +0 -40
  211. package/dist/chunk-EDBG2F57.js.map +0 -1
  212. package/dist/chunk-FBQ3X3UY.js.map +0 -1
  213. package/dist/chunk-HQDYH45I.js.map +0 -1
  214. package/dist/chunk-HX663BJ4.js +0 -40
  215. package/dist/chunk-HX663BJ4.js.map +0 -1
  216. package/dist/chunk-KROW43CG.js +0 -40
  217. package/dist/chunk-KROW43CG.js.map +0 -1
  218. package/dist/chunk-L52AGCMP.js +0 -40
  219. package/dist/chunk-L52AGCMP.js.map +0 -1
  220. package/dist/chunk-MTI5PSRH.js +0 -40
  221. package/dist/chunk-MTI5PSRH.js.map +0 -1
  222. package/dist/chunk-OJ3YWO3W.js.map +0 -1
  223. package/dist/chunk-ORBJ7MRW.js +0 -40
  224. package/dist/chunk-ORBJ7MRW.js.map +0 -1
  225. package/dist/chunk-SLSCZV4A.js +0 -40
  226. package/dist/chunk-SLSCZV4A.js.map +0 -1
  227. package/dist/chunk-URZGNPTQ.js.map +0 -1
  228. package/dist/chunk-WKBRZGGL.js +0 -40
  229. package/dist/chunk-WKBRZGGL.js.map +0 -1
  230. package/dist/chunk-XYZ7FOXJ.js.map +0 -1
  231. package/dist/chunk-YXS27XM6.js.map +0 -1
  232. /package/dist/{chunk-ZR66E3T6.js.map → chunk-JNLVXPHR.js.map} +0 -0
@@ -175,49 +175,24 @@ describe('registry', () => {
175
175
  });
176
176
 
177
177
  describe('registerWithRuntime', () => {
178
- it('should load and call module.register (Draggable — now source-compiled)', async () => {
179
- const mockInstance = {
180
- compileSync: vi.fn().mockReturnValue({ ok: true, ast: {} }),
181
- execute: vi.fn().mockResolvedValue(undefined),
182
- createContext: vi.fn().mockReturnValue({ locals: new Map(), globals: new Map() }),
183
- };
178
+ it('should load the behavior and define its source on the host', async () => {
179
+ const host = { evaluate: vi.fn() };
184
180
 
185
181
  await loadBehavior('Draggable');
186
- await registerWithRuntime('Draggable', mockInstance);
182
+ await registerWithRuntime('Draggable', host);
187
183
 
188
- // Draggable used to install imperatively; it now compiles its hyperscript
189
- // `source` like every other behavior (no imperative installer).
190
- expect(mockInstance.compileSync).toHaveBeenCalled();
191
- expect(mockInstance.execute).toHaveBeenCalled();
192
- });
193
-
194
- it('should load and call module.register (compiled behavior)', async () => {
195
- const mockInstance = {
196
- compileSync: vi.fn().mockReturnValue({ ok: true, ast: {} }),
197
- execute: vi.fn().mockResolvedValue(undefined),
198
- createContext: vi.fn().mockReturnValue({ locals: new Map(), globals: new Map() }),
199
- };
200
-
201
- await loadBehavior('Removable');
202
- await registerWithRuntime('Removable', mockInstance);
203
-
204
- // Source-compiled behaviors use compileSync
205
- expect(mockInstance.compileSync).toHaveBeenCalled();
184
+ expect(host.evaluate).toHaveBeenCalledTimes(1);
185
+ expect(host.evaluate.mock.calls[0][0]).toContain('behavior Draggable');
206
186
  });
207
187
  });
208
188
 
209
189
  describe('registerAllWithRuntime', () => {
210
- it('should register all loaded behaviors', async () => {
211
- const mockInstance = {
212
- compileSync: vi.fn().mockReturnValue({ ok: true, ast: {} }),
213
- execute: vi.fn().mockResolvedValue(undefined),
214
- createContext: vi.fn().mockReturnValue({ locals: new Map(), globals: new Map() }),
215
- };
190
+ it('should define every loaded behavior', async () => {
191
+ const host = { evaluate: vi.fn() };
216
192
 
217
193
  await loadAll();
218
- await registerAllWithRuntime(mockInstance);
219
- // execute called for each behavior (all source-compiled now)
220
- expect(mockInstance.execute.mock.calls.length).toBeGreaterThanOrEqual(10);
194
+ await registerAllWithRuntime(host);
195
+ expect(host.evaluate.mock.calls.length).toBeGreaterThanOrEqual(10);
221
196
  });
222
197
  });
223
198
  });
package/src/registry.ts CHANGED
@@ -23,7 +23,7 @@ import type {
23
23
  BehaviorSchema,
24
24
  BehaviorCategory,
25
25
  BehaviorTier,
26
- LokaScriptInstance,
26
+ HyperscriptHost,
27
27
  } from './schemas/types';
28
28
 
29
29
  // =============================================================================
@@ -284,21 +284,17 @@ export async function loadAll(): Promise<void> {
284
284
  // =============================================================================
285
285
 
286
286
  /**
287
- * Register a behavior with HyperFixi runtime.
288
- * Compiles and executes the behavior source.
287
+ * Load a behavior and define it on a hyperscript host (`window.hyperfixi` when none is given).
289
288
  */
290
- export async function registerWithRuntime(
291
- name: string,
292
- hyperfixi?: LokaScriptInstance
293
- ): Promise<void> {
289
+ export async function registerWithRuntime(name: string, host?: HyperscriptHost): Promise<void> {
294
290
  const module = await loadBehavior(name);
295
- await module.register(hyperfixi);
291
+ await module.register(host);
296
292
  }
297
293
 
298
294
  /**
299
- * Register all loaded behaviors with HyperFixi runtime.
295
+ * Define every loaded behavior on a hyperscript host.
300
296
  */
301
- export async function registerAllWithRuntime(hyperfixi?: LokaScriptInstance): Promise<void> {
302
- const registrations = Array.from(behaviors.values()).map(module => module.register(hyperfixi));
297
+ export async function registerAllWithRuntime(host?: HyperscriptHost): Promise<void> {
298
+ const registrations = Array.from(behaviors.values()).map(module => module.register(host));
303
299
  await Promise.all(registrations);
304
300
  }
@@ -48,15 +48,9 @@ export const autoDismissSchema: BehaviorSchema = {
48
48
  source: `
49
49
  behavior AutoDismiss(delay, pauseOnHover, effect)
50
50
  init
51
- if delay is undefined
52
- set delay to 5000
53
- end
54
- if pauseOnHover is undefined
55
- set pauseOnHover to true
56
- end
57
- if effect is undefined
58
- set effect to "none"
59
- end
51
+ if delay is undefined set element's delay to 5000 end
52
+ if pauseOnHover is undefined set element's pauseOnHover to true end
53
+ if effect is undefined set element's effect to "none" end
60
54
  js(me, delay, effect, pauseOnHover)
61
55
  me.dispatchEvent(new CustomEvent('autodismiss:start', { bubbles: true }));
62
56
  var remaining = delay;
@@ -36,9 +36,7 @@ export const clickOutsideSchema: BehaviorSchema = {
36
36
  source: `
37
37
  behavior ClickOutside(active)
38
38
  init
39
- if active is undefined
40
- set active to true
41
- end
39
+ if active is undefined set element's active to true end
42
40
  end
43
41
  on pointerdown from document
44
42
  js(me, active, event)
@@ -49,10 +47,10 @@ behavior ClickOutside(active)
49
47
  end
50
48
  end
51
49
  on clickoutside:activate
52
- set active to true
50
+ set element's active to true
53
51
  end
54
52
  on clickoutside:deactivate
55
- set active to false
53
+ set element's active to false
56
54
  end
57
55
  end`.trim(),
58
56
  };
@@ -51,12 +51,8 @@ export const clipboardSchema: BehaviorSchema = {
51
51
  source: `
52
52
  behavior Clipboard(text, source, feedback, feedbackDuration)
53
53
  init
54
- if feedbackDuration is undefined
55
- set feedbackDuration to 2000
56
- end
57
- if source is undefined
58
- set source to me
59
- end
54
+ if feedbackDuration is undefined set element's feedbackDuration to 2000 end
55
+ if source is undefined set element's source to me end
60
56
  end
61
57
  on click
62
58
  if text is not undefined
@@ -30,18 +30,11 @@ export const draggableSchema: BehaviorSchema = {
30
30
  requirements: ['position: absolute or position: fixed on the element'],
31
31
  source: `
32
32
  behavior Draggable(dragHandle)
33
- init
34
- if no dragHandle set dragHandle to me
35
- end
36
- on pointerdown(clientX, clientY) from dragHandle
33
+ on pointerdown(clientX, clientY) from (dragHandle or me)
37
34
  halt the event
38
35
  trigger draggable:start
39
- measure x
40
- set startX to it
41
- measure y
42
- set startY to it
43
- set xoff to clientX - startX
44
- set yoff to clientY - startY
36
+ set xoff to clientX - my offsetLeft
37
+ set yoff to clientY - my offsetTop
45
38
  repeat until event pointerup from document
46
39
  wait for pointermove(clientX, clientY) or
47
40
  pointerup(clientX, clientY) from document
@@ -50,6 +43,5 @@ behavior Draggable(dragHandle)
50
43
  end
51
44
  trigger draggable:end
52
45
  end
53
- end
54
- `.trim(),
46
+ end`.trim(),
55
47
  };
@@ -45,12 +45,8 @@ export const focusTrapSchema: BehaviorSchema = {
45
45
  source: `
46
46
  behavior FocusTrap(active, initialFocus, returnFocus)
47
47
  init
48
- if active is undefined
49
- set active to true
50
- end
51
- if returnFocus is undefined
52
- set returnFocus to true
53
- end
48
+ if active is undefined set element's active to true end
49
+ if returnFocus is undefined set element's returnFocus to true end
54
50
  js(me, active, initialFocus, returnFocus)
55
51
  var FOCUSABLE = 'a[href],button:not(:disabled),input:not(:disabled),select:not(:disabled),textarea:not(:disabled),[tabindex]:not([tabindex="-1"])';
56
52
  var isActive = false;
@@ -13,7 +13,8 @@ export type {
13
13
  ParameterSchema,
14
14
  EventSchema,
15
15
  BehaviorModule,
16
- LokaScriptInstance,
16
+ HyperscriptHost,
17
+ HyperscriptWindow,
17
18
  } from './types';
18
19
 
19
20
  // Individual schemas
@@ -46,12 +46,7 @@ export const removableSchema: BehaviorSchema = {
46
46
  ],
47
47
  source: `
48
48
  behavior Removable(triggerEl, confirmRemoval, effect)
49
- init
50
- if triggerEl is undefined
51
- set triggerEl to me
52
- end
53
- end
54
- on click from triggerEl
49
+ on click from (triggerEl or me)
55
50
  if confirmRemoval
56
51
  js(me)
57
52
  if (!window.confirm("Are you sure?")) return "cancel";
@@ -67,6 +62,5 @@ behavior Removable(triggerEl, confirmRemoval, effect)
67
62
  trigger removable:removed
68
63
  remove me
69
64
  end
70
- end
71
- `.trim(),
65
+ end`.trim(),
72
66
  };
@@ -53,10 +53,8 @@ behavior Resizable(minWidth, minHeight, maxWidth, maxHeight)
53
53
  on pointerdown(clientX, clientY) from me
54
54
  halt the event
55
55
  trigger resizable:start
56
- measure width
57
- set startWidth to it
58
- measure height
59
- set startHeight to it
56
+ set startWidth to my offsetWidth
57
+ set startHeight to my offsetHeight
60
58
  set startX to clientX
61
59
  set startY to clientY
62
60
  repeat until event pointerup from document
@@ -73,6 +71,5 @@ behavior Resizable(minWidth, minHeight, maxWidth, maxHeight)
73
71
  end
74
72
  trigger resizable:end
75
73
  end
76
- end
77
- `.trim(),
74
+ end`.trim(),
78
75
  };
@@ -43,15 +43,9 @@ export const scrollRevealSchema: BehaviorSchema = {
43
43
  source: `
44
44
  behavior ScrollReveal(cls, threshold, once)
45
45
  init
46
- if cls is undefined
47
- set cls to "revealed"
48
- end
49
- if threshold is undefined
50
- set threshold to 0.1
51
- end
52
- if once is undefined
53
- set once to true
54
- end
46
+ if cls is undefined set element's cls to "revealed" end
47
+ if threshold is undefined set element's threshold to 0.1 end
48
+ if once is undefined set element's once to true end
55
49
  js(me, cls, threshold, once)
56
50
  var obs = new IntersectionObserver(function(entries) {
57
51
  for (var i = 0; i < entries.length; i++) {
@@ -37,24 +37,20 @@ export const sortableSchema: BehaviorSchema = {
37
37
  requirements: ['Users must handle DOM reordering in sortable:move event handlers'],
38
38
  source: `
39
39
  behavior Sortable(dragClass)
40
- init
41
- if dragClass is undefined
42
- set dragClass to "sorting"
43
- end
44
- end
45
40
  on pointerdown(clientY) from me
46
41
  set item to the target.closest("li")
47
42
  if item is null
48
43
  exit
49
44
  end
50
45
  halt the event
51
- add .{dragClass} to item
46
+ set cls to dragClass or "sorting"
47
+ add .{cls} to item
52
48
  trigger sortable:start on me
53
49
  repeat until event pointerup from document
54
50
  wait for pointermove(clientY) or pointerup(clientY) from document
55
51
  trigger sortable:move on me
56
52
  end
57
- remove .{dragClass} from item
53
+ remove .{cls} from item
58
54
  trigger sortable:end on me
59
55
  end
60
56
  end`.trim(),
@@ -55,18 +55,10 @@ export const tabsSchema: BehaviorSchema = {
55
55
  source: `
56
56
  behavior Tabs(orientation, activeTab, wrap, activeClass)
57
57
  init
58
- if orientation is undefined
59
- set orientation to "horizontal"
60
- end
61
- if activeTab is undefined
62
- set activeTab to 0
63
- end
64
- if wrap is undefined
65
- set wrap to true
66
- end
67
- if activeClass is undefined
68
- set activeClass to "active"
69
- end
58
+ if orientation is undefined set element's orientation to "horizontal" end
59
+ if activeTab is undefined set element's activeTab to 0 end
60
+ if wrap is undefined set element's wrap to true end
61
+ if activeClass is undefined set element's activeClass to "active" end
70
62
  js(me, orientation, activeTab, wrap, activeClass)
71
63
  var tabs = Array.from(me.querySelectorAll('[role="tab"]'));
72
64
  var panels = Array.from(me.querySelectorAll('[role="tabpanel"]'));
@@ -21,11 +21,12 @@ export const toggleableSchema: BehaviorSchema = {
21
21
  description: 'CSS class to toggle',
22
22
  },
23
23
  {
24
- name: 'target',
24
+ name: 'targetEl',
25
25
  type: 'selector',
26
26
  optional: true,
27
27
  default: 'me',
28
- description: 'Element to toggle the class on',
28
+ description:
29
+ "Element to toggle the class on (not `target`: that is hyperscript's name for the event target)",
29
30
  },
30
31
  ],
31
32
  events: [
@@ -33,20 +34,16 @@ export const toggleableSchema: BehaviorSchema = {
33
34
  { name: 'toggleable:off', description: 'Fired when class is removed' },
34
35
  ],
35
36
  source: `
36
- behavior Toggleable(cls, target)
37
+ behavior Toggleable(cls, targetEl)
37
38
  init
38
- if cls is undefined
39
- set cls to "active"
40
- end
41
- if target is undefined
42
- set target to me
43
- end
39
+ if cls is undefined set element's cls to "active" end
40
+ if targetEl is undefined set element's targetEl to me end
44
41
  end
45
42
  on click
46
- toggle .{cls} on target
47
- js(target, cls)
48
- var eventName = target.classList.contains(cls) ? 'toggleable:on' : 'toggleable:off';
49
- target.dispatchEvent(new CustomEvent(eventName, { bubbles: true }));
43
+ toggle .{cls} on targetEl
44
+ js(targetEl, cls)
45
+ var eventName = targetEl.classList.contains(cls) ? 'toggleable:on' : 'toggleable:off';
46
+ targetEl.dispatchEvent(new CustomEvent(eventName, { bubbles: true }));
50
47
  end
51
48
  end
52
49
  end`.trim(),
@@ -72,48 +72,55 @@ export interface BehaviorSchema {
72
72
  }
73
73
 
74
74
  /**
75
- * Runtime behavior module interface.
76
- * This is what gets registered with the hyperfixi runtime.
75
+ * Runtime behavior module interface: a behavior's source, its schema, and the function that
76
+ * defines it on a hyperscript host.
77
77
  */
78
78
  export interface BehaviorModule {
79
79
  source: string;
80
80
  metadata: BehaviorSchema;
81
- register: (hyperfixi?: LokaScriptInstance) => Promise<void>;
81
+ register: (host?: HyperscriptHost) => Promise<void>;
82
82
  }
83
83
 
84
84
  /**
85
- * Minimal LokaScript instance interface for behavior registration.
85
+ * A hyperscript host, in upstream `_hyperscript`'s shape: `@hyperfixi/engine` (the
86
+ * `hyperfixi-hs.js` bundle, `window.hyperfixi` / `window._hyperscript`) or upstream itself.
87
+ * `evaluate(source)` of a `behavior … end` program defines the behavior; `processNode`
88
+ * initialises the scripted elements under a node.
86
89
  */
87
- export interface LokaScriptInstance {
88
- compileSync: (
89
- code: string,
90
- options?: { traditional?: boolean; language?: string }
91
- ) => {
92
- ok: boolean;
93
- ast?: unknown;
94
- errors?: Array<{ message: string; line?: number; column?: number }>;
95
- };
96
- execute: (ast: unknown, ctx: unknown) => Promise<unknown>;
97
- createContext?: () => { locals: Map<string, unknown>; globals: Map<string, unknown> };
90
+ export interface HyperscriptHost {
91
+ evaluate: (source: string) => unknown;
92
+ processNode?: (node: Node) => void;
98
93
  }
99
94
 
100
- /**
101
- * Typed window interface for behavior auto-registration.
102
- * Avoids `(window as any)` casts throughout the codebase.
103
- * Checks both `window.lokascript` and `window.hyperfixi` for the runtime instance.
104
- */
105
- export interface LokaScriptWindow {
106
- lokascript?: LokaScriptInstance;
107
- hyperfixi?: LokaScriptInstance;
108
- __hyperfixi_behaviors_ready?: Promise<void> | undefined;
95
+ /** The window globals a host installs itself as. */
96
+ export interface HyperscriptWindow {
97
+ hyperfixi?: HyperscriptHost;
98
+ _hyperscript?: HyperscriptHost;
99
+ }
100
+
101
+ /** The host on `window`: `hyperfixi` (the engine's bundle) or `_hyperscript` (upstream's name). */
102
+ export function resolveRuntime(): HyperscriptHost | null {
103
+ if (typeof window === 'undefined') return null;
104
+ const win = window as unknown as HyperscriptWindow;
105
+ const host = win.hyperfixi ?? win._hyperscript;
106
+ return host && typeof host.evaluate === 'function' ? host : null;
109
107
  }
110
108
 
111
109
  /**
112
- * Resolve the LokaScript runtime from window globals.
113
- * Checks both `window.lokascript` and `window.hyperfixi`.
110
+ * Define a behavior on a host from its schema's source, as a page's
111
+ * `<script type="text/hyperscript">` would. Throws when there is no host or the source
112
+ * does not parse.
114
113
  */
115
- export function resolveRuntime(): LokaScriptInstance | null {
116
- if (typeof window === 'undefined') return null;
117
- const win = window as unknown as LokaScriptWindow;
118
- return win.lokascript || win.hyperfixi || null;
114
+ export function defineBehavior(schema: BehaviorSchema, host?: HyperscriptHost): void {
115
+ const hf = host ?? resolveRuntime();
116
+ if (!hf) {
117
+ throw new Error(
118
+ `No hyperscript host found: load @hyperfixi/engine (hyperfixi-hs.js) before defining ${schema.name}.`
119
+ );
120
+ }
121
+ try {
122
+ hf.evaluate(schema.source);
123
+ } catch (e) {
124
+ throw new Error(`Failed to define ${schema.name} behavior: ${(e as Error).message}`);
125
+ }
119
126
  }
@@ -1,40 +0,0 @@
1
- import {
2
- autoDismissSchema
3
- } from "./chunk-66U2RSYJ.js";
4
- import {
5
- resolveRuntime
6
- } from "./chunk-6TJXDCAQ.js";
7
-
8
- // src/behaviors/autodismiss.ts
9
- var autoDismissSource = autoDismissSchema.source;
10
- var autoDismissMetadata = autoDismissSchema;
11
- async function registerAutoDismiss(hyperfixi) {
12
- const hf = hyperfixi || resolveRuntime();
13
- if (!hf) {
14
- throw new Error(
15
- "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
16
- );
17
- }
18
- const result = hf.compileSync(autoDismissSchema.source, { traditional: true });
19
- if (!result.ok) {
20
- throw new Error(`Failed to compile AutoDismiss behavior: ${JSON.stringify(result.errors)}`);
21
- }
22
- const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
23
- await hf.execute(result.ast, ctx);
24
- }
25
- if (resolveRuntime()) {
26
- registerAutoDismiss().catch(console.error);
27
- }
28
- var autodismiss_default = {
29
- source: autoDismissSchema.source,
30
- metadata: autoDismissSchema,
31
- register: registerAutoDismiss
32
- };
33
-
34
- export {
35
- autoDismissSource,
36
- autoDismissMetadata,
37
- registerAutoDismiss,
38
- autodismiss_default
39
- };
40
- //# sourceMappingURL=chunk-2HUF6RMI.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/behaviors/autodismiss.ts"],"sourcesContent":["/**\n * AutoDismiss Behavior\n *\n * Auto-removes elements after a configurable delay.\n * Supports pause-on-hover and fade effect using standard setTimeout/clearTimeout\n * (in its hyperscript `source`'s js() body).\n *\n * Compiled from its hyperscript `source` (the single source of truth shared with\n * the CDN resolver bundle and patterns-reference).\n */\n\nimport { autoDismissSchema } from '../schemas/autodismiss.schema';\nimport type { LokaScriptInstance } from '../schemas/types';\nimport { resolveRuntime } from '../schemas/types';\n\n// Re-export schema-derived values\nexport const autoDismissSource = autoDismissSchema.source;\nexport const autoDismissMetadata = autoDismissSchema;\n\n/**\n * Register the AutoDismiss behavior with LokaScript by compiling its\n * hyperscript source and executing the resulting behavior definition.\n */\nexport async function registerAutoDismiss(hyperfixi?: LokaScriptInstance): Promise<void> {\n const hf = hyperfixi || resolveRuntime();\n\n if (!hf) {\n throw new Error(\n 'LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors.'\n );\n }\n\n const result = hf.compileSync(autoDismissSchema.source, { traditional: true });\n\n if (!result.ok) {\n throw new Error(`Failed to compile AutoDismiss behavior: ${JSON.stringify(result.errors)}`);\n }\n\n const ctx = hf.createContext ? hf.createContext() : { locals: new Map(), globals: new Map() };\n await hf.execute(result.ast, ctx);\n}\n\n// Auto-register when loaded as a script tag\nif (resolveRuntime()) {\n registerAutoDismiss().catch(console.error);\n}\n\nexport default {\n source: autoDismissSchema.source,\n metadata: autoDismissSchema,\n register: registerAutoDismiss,\n};\n"],"mappings":";;;;;;;;AAgBO,IAAM,oBAAoB,kBAAkB;AAC5C,IAAM,sBAAsB;AAMnC,eAAsB,oBAAoB,WAA+C;AACvF,QAAM,KAAK,aAAa,eAAe;AAEvC,MAAI,CAAC,IAAI;AACP,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,GAAG,YAAY,kBAAkB,QAAQ,EAAE,aAAa,KAAK,CAAC;AAE7E,MAAI,CAAC,OAAO,IAAI;AACd,UAAM,IAAI,MAAM,2CAA2C,KAAK,UAAU,OAAO,MAAM,CAAC,EAAE;AAAA,EAC5F;AAEA,QAAM,MAAM,GAAG,gBAAgB,GAAG,cAAc,IAAI,EAAE,QAAQ,oBAAI,IAAI,GAAG,SAAS,oBAAI,IAAI,EAAE;AAC5F,QAAM,GAAG,QAAQ,OAAO,KAAK,GAAG;AAClC;AAGA,IAAI,eAAe,GAAG;AACpB,sBAAoB,EAAE,MAAM,QAAQ,KAAK;AAC3C;AAEA,IAAO,sBAAQ;AAAA,EACb,QAAQ,kBAAkB;AAAA,EAC1B,UAAU;AAAA,EACV,UAAU;AACZ;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/registry.ts"],"sourcesContent":["/**\n * Behavior Registry\n *\n * Central registration point for behaviors. Modeled on semantic/registry.ts.\n * Supports lazy loading, category/tier queries, and tree-shaking.\n *\n * @example\n * ```typescript\n * // Register a behavior\n * registerBehavior('Draggable', DraggableModule);\n *\n * // Query behaviors\n * const uiBehaviors = getBehaviorsByCategory('ui');\n * const coreBehaviors = getBehaviorsByTier('core');\n *\n * // Lazy load on demand\n * const module = await loadBehavior('Resizable');\n * ```\n */\n\nimport type {\n BehaviorModule,\n BehaviorSchema,\n BehaviorCategory,\n BehaviorTier,\n LokaScriptInstance,\n} from './schemas/types';\n\n// =============================================================================\n// Registry State\n// =============================================================================\n\nconst behaviors = new Map<string, BehaviorModule>();\nconst schemas = new Map<string, BehaviorSchema>();\nconst loaders = new Map<string, () => Promise<{ default: BehaviorModule }>>();\nconst loadingPromises = new Map<string, Promise<BehaviorModule>>();\n\n// =============================================================================\n// Registration Functions\n// =============================================================================\n\n/**\n * Register a behavior module.\n */\nexport function registerBehavior(name: string, module: BehaviorModule): void {\n behaviors.set(name, module);\n if (module.metadata) {\n schemas.set(name, module.metadata);\n }\n}\n\n/**\n * Register a behavior schema (without the module).\n */\nexport function registerSchema(schema: BehaviorSchema): void {\n schemas.set(schema.name, schema);\n}\n\n/**\n * Register a lazy loader for a behavior.\n * The loader should return a module with a default export.\n */\nexport function registerLoader(\n name: string,\n loader: () => Promise<{ default: BehaviorModule }>\n): void {\n loaders.set(name, loader);\n}\n\n// =============================================================================\n// Query Functions (Sync)\n// =============================================================================\n\n/**\n * Get a behavior module by name.\n * @throws Error if behavior is not registered\n */\nexport function getBehavior(name: string): BehaviorModule {\n const behavior = behaviors.get(name);\n if (!behavior) {\n const registered = Array.from(behaviors.keys()).join(', ');\n throw new Error(\n `Behavior '${name}' is not registered. ` +\n `Registered behaviors: ${registered || 'none'}. ` +\n `Use loadBehavior('${name}') to lazy load it.`\n );\n }\n return behavior;\n}\n\n/**\n * Try to get a behavior, returning undefined if not registered.\n */\nexport function tryGetBehavior(name: string): BehaviorModule | undefined {\n return behaviors.get(name);\n}\n\n/**\n * Get a behavior schema by name.\n * @throws Error if schema is not registered\n */\nexport function getSchema(name: string): BehaviorSchema {\n const schema = schemas.get(name);\n if (!schema) {\n throw new Error(\n `Schema for behavior '${name}' is not registered. ` +\n `Use tryGetSchema('${name}') for a non-throwing alternative.`\n );\n }\n return schema;\n}\n\n/**\n * Try to get a schema, returning undefined if not registered.\n */\nexport function tryGetSchema(name: string): BehaviorSchema | undefined {\n return schemas.get(name);\n}\n\n/**\n * Check if a behavior is registered.\n */\nexport function isRegistered(name: string): boolean {\n return behaviors.has(name);\n}\n\n/**\n * Check if a loader is registered for a behavior.\n */\nexport function hasLoader(name: string): boolean {\n return loaders.has(name);\n}\n\n/**\n * Get all registered behavior names.\n */\nexport function getRegisteredBehaviors(): string[] {\n return Array.from(behaviors.keys());\n}\n\n/**\n * Get all behavior names that have loaders (including unloaded).\n */\nexport function getAvailableBehaviors(): string[] {\n const names = new Set([...behaviors.keys(), ...loaders.keys()]);\n return Array.from(names);\n}\n\n// =============================================================================\n// Query by Metadata\n// =============================================================================\n\n/**\n * Get behavior names by category.\n */\nexport function getBehaviorsByCategory(category: BehaviorCategory): string[] {\n const result: string[] = [];\n for (const [name, schema] of schemas) {\n if (schema.category === category) {\n result.push(name);\n }\n }\n return result;\n}\n\n/**\n * Get behavior names by tier.\n */\nexport function getBehaviorsByTier(tier: BehaviorTier): string[] {\n const result: string[] = [];\n for (const [name, schema] of schemas) {\n if (schema.tier === tier) {\n result.push(name);\n }\n }\n return result;\n}\n\n/**\n * Get all schemas.\n */\nexport function getAllSchemas(): BehaviorSchema[] {\n return Array.from(schemas.values());\n}\n\n/**\n * Get all schemas as a record.\n */\nexport function getAllSchemasRecord(): Record<string, BehaviorSchema> {\n const result: Record<string, BehaviorSchema> = {};\n for (const [name, schema] of schemas) {\n result[name] = schema;\n }\n return result;\n}\n\n// =============================================================================\n// Lazy Loading (Async)\n// =============================================================================\n\n/**\n * Load a behavior by name.\n * If already loaded, returns the cached module.\n * If a loader is registered, loads and caches the module.\n */\nexport async function loadBehavior(name: string): Promise<BehaviorModule> {\n // Return cached if available\n const cached = behaviors.get(name);\n if (cached) {\n return cached;\n }\n\n // Check for in-flight load\n const inFlight = loadingPromises.get(name);\n if (inFlight) {\n return inFlight;\n }\n\n // Check for loader\n const loader = loaders.get(name);\n if (!loader) {\n throw new Error(\n `No loader registered for behavior '${name}'. ` +\n `Available loaders: ${Array.from(loaders.keys()).join(', ') || 'none'}`\n );\n }\n\n // Load and cache\n const promise = loader().then(mod => {\n const module = mod.default;\n registerBehavior(name, module);\n loadingPromises.delete(name);\n return module;\n });\n\n loadingPromises.set(name, promise);\n return promise;\n}\n\n/**\n * Preload all behaviors in a tier.\n */\nexport async function preloadTier(tier: BehaviorTier): Promise<void> {\n const names = getBehaviorsByTier(tier);\n await Promise.all(\n names.map(name =>\n loadBehavior(name).catch(err => {\n console.warn(`[behaviors] Failed to preload '${name}' (tier: ${tier}):`, err);\n })\n )\n );\n}\n\n/**\n * Preload all behaviors in a category.\n */\nexport async function preloadCategory(category: BehaviorCategory): Promise<void> {\n const names = getBehaviorsByCategory(category);\n await Promise.all(\n names.map(name =>\n loadBehavior(name).catch(err => {\n console.warn(`[behaviors] Failed to preload '${name}' (category: ${category}):`, err);\n })\n )\n );\n}\n\n/**\n * Load and register all available behaviors.\n */\nexport async function loadAll(): Promise<void> {\n const names = getAvailableBehaviors();\n await Promise.all(\n names.map(name =>\n loadBehavior(name).catch(err => {\n console.warn(`[behaviors] Failed to load '${name}':`, err);\n })\n )\n );\n}\n\n// =============================================================================\n// Runtime Registration\n// =============================================================================\n\n/**\n * Register a behavior with HyperFixi runtime.\n * Compiles and executes the behavior source.\n */\nexport async function registerWithRuntime(\n name: string,\n hyperfixi?: LokaScriptInstance\n): Promise<void> {\n const module = await loadBehavior(name);\n await module.register(hyperfixi);\n}\n\n/**\n * Register all loaded behaviors with HyperFixi runtime.\n */\nexport async function registerAllWithRuntime(hyperfixi?: LokaScriptInstance): Promise<void> {\n const registrations = Array.from(behaviors.values()).map(module => module.register(hyperfixi));\n await Promise.all(registrations);\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/schemas/resizable.schema.ts"],"sourcesContent":["import type { BehaviorSchema } from './types';\n\n/**\n * Resizable Behavior Schema\n *\n * Makes elements resizable by dragging edges or corners.\n * Supports minimum/maximum dimensions and resize handles.\n */\nexport const resizableSchema: BehaviorSchema = {\n name: 'Resizable',\n category: 'ui',\n tier: 'optional',\n version: '1.0.0',\n description:\n 'Makes elements resizable by dragging (EXPERIMENTAL — stateful async component, beyond the inline-scripting boundary; not part of the curated set)',\n parameters: [\n {\n name: 'minWidth',\n type: 'number',\n optional: true,\n default: 50,\n description: 'Minimum width in pixels',\n },\n {\n name: 'minHeight',\n type: 'number',\n optional: true,\n default: 50,\n description: 'Minimum height in pixels',\n },\n {\n name: 'maxWidth',\n type: 'number',\n optional: true,\n default: 9999,\n description: 'Maximum width in pixels',\n },\n {\n name: 'maxHeight',\n type: 'number',\n optional: true,\n default: 9999,\n description: 'Maximum height in pixels',\n },\n ],\n events: [\n { name: 'resizable:start', description: 'Fired when resize begins' },\n { name: 'resizable:resize', description: 'Fired during resize' },\n { name: 'resizable:end', description: 'Fired when resize completes' },\n ],\n source: `\nbehavior Resizable(minWidth, minHeight, maxWidth, maxHeight)\n on pointerdown(clientX, clientY) from me\n halt the event\n trigger resizable:start\n measure width\n set startWidth to it\n measure height\n set startHeight to it\n set startX to clientX\n set startY to clientY\n repeat until event pointerup from document\n wait for pointermove(clientX, clientY) or pointerup(clientX, clientY) from document\n set newWidth to (startWidth + clientX) - startX\n set newHeight to (startHeight + clientY) - startY\n if newWidth < minWidth then set newWidth to minWidth end\n if newWidth > maxWidth then set newWidth to maxWidth end\n if newHeight < minHeight then set newHeight to minHeight end\n if newHeight > maxHeight then set newHeight to maxHeight end\n set my *width to newWidth + \"px\"\n set my *height to newHeight + \"px\"\n trigger resizable:resize\n end\n trigger resizable:end\n end\nend\n`.trim(),\n};\n"],"mappings":";AAQO,IAAM,kBAAkC;AAAA,EAC7C,MAAM;AAAA,EACN,UAAU;AAAA,EACV,MAAM;AAAA,EACN,SAAS;AAAA,EACT,aACE;AAAA,EACF,YAAY;AAAA,IACV;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN,EAAE,MAAM,mBAAmB,aAAa,2BAA2B;AAAA,IACnE,EAAE,MAAM,oBAAoB,aAAa,sBAAsB;AAAA,IAC/D,EAAE,MAAM,iBAAiB,aAAa,8BAA8B;AAAA,EACtE;AAAA,EACA,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0BR,KAAK;AACP;","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/schemas/autodismiss.schema.ts"],"sourcesContent":["import type { BehaviorSchema } from './types';\n\n/**\n * AutoDismiss Behavior Schema\n *\n * Auto-removes flash messages and toasts after a configurable delay.\n * Supports pause-on-hover and fade effect.\n */\nexport const autoDismissSchema: BehaviorSchema = {\n name: 'AutoDismiss',\n category: 'ui',\n tier: 'core',\n version: '1.0.0',\n description: 'Auto-removes elements after a delay with optional pause-on-hover',\n parameters: [\n {\n name: 'delay',\n type: 'number',\n optional: true,\n default: 5000,\n description: 'Time in ms before the element is removed',\n },\n {\n name: 'pauseOnHover',\n type: 'boolean',\n optional: true,\n default: true,\n description: 'Pause the countdown when the mouse hovers over the element',\n },\n {\n name: 'effect',\n type: 'string',\n optional: true,\n default: 'none',\n enum: ['fade', 'none'],\n description: 'Transition effect before removal: \"fade\" or \"none\"',\n },\n ],\n events: [\n { name: 'autodismiss:start', description: 'Fired when the countdown timer starts' },\n {\n name: 'autodismiss:dismissed',\n description: 'Fired before removal (cancelable via preventDefault)',\n },\n { name: 'autodismiss:paused', description: 'Fired when the timer is paused on hover' },\n { name: 'autodismiss:resumed', description: 'Fired when the timer resumes on mouseleave' },\n ],\n source: `\nbehavior AutoDismiss(delay, pauseOnHover, effect)\n init\n if delay is undefined\n set delay to 5000\n end\n if pauseOnHover is undefined\n set pauseOnHover to true\n end\n if effect is undefined\n set effect to \"none\"\n end\n js(me, delay, effect, pauseOnHover)\n me.dispatchEvent(new CustomEvent('autodismiss:start', { bubbles: true }));\n var remaining = delay;\n var startedAt = Date.now();\n var timerId = null;\n function dismiss() {\n var ev = new CustomEvent('autodismiss:dismissed', { bubbles: true, cancelable: true });\n me.dispatchEvent(ev);\n if (ev.defaultPrevented) return;\n if (effect === 'fade') {\n me.style.transition = 'opacity 300ms';\n me.style.opacity = '0';\n setTimeout(function() { me.remove(); }, 300);\n } else {\n me.remove();\n }\n }\n function start() {\n startedAt = Date.now();\n timerId = setTimeout(dismiss, remaining);\n }\n start();\n if (pauseOnHover) {\n me.addEventListener('mouseenter', function() {\n if (timerId != null) {\n clearTimeout(timerId);\n timerId = null;\n remaining -= Date.now() - startedAt;\n if (remaining < 0) remaining = 0;\n me.dispatchEvent(new CustomEvent('autodismiss:paused', { bubbles: true }));\n }\n });\n me.addEventListener('mouseleave', function() {\n if (timerId == null && me.isConnected) {\n me.dispatchEvent(new CustomEvent('autodismiss:resumed', { bubbles: true }));\n start();\n }\n });\n }\n end\n end\nend`.trim(),\n};\n"],"mappings":";AAQO,IAAM,oBAAoC;AAAA,EAC/C,MAAM;AAAA,EACN,UAAU;AAAA,EACV,MAAM;AAAA,EACN,SAAS;AAAA,EACT,aAAa;AAAA,EACb,YAAY;AAAA,IACV;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,MACT,aAAa;AAAA,IACf;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,MACT,MAAM,CAAC,QAAQ,MAAM;AAAA,MACrB,aAAa;AAAA,IACf;AAAA,EACF;AAAA,EACA,QAAQ;AAAA,IACN,EAAE,MAAM,qBAAqB,aAAa,wCAAwC;AAAA,IAClF;AAAA,MACE,MAAM;AAAA,MACN,aAAa;AAAA,IACf;AAAA,IACA,EAAE,MAAM,sBAAsB,aAAa,0CAA0C;AAAA,IACrF,EAAE,MAAM,uBAAuB,aAAa,6CAA6C;AAAA,EAC3F;AAAA,EACA,QAAQ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,KAqDL,KAAK;AACV;","names":[]}
@@ -1,11 +0,0 @@
1
- // src/schemas/types.ts
2
- function resolveRuntime() {
3
- if (typeof window === "undefined") return null;
4
- const win = window;
5
- return win.lokascript || win.hyperfixi || null;
6
- }
7
-
8
- export {
9
- resolveRuntime
10
- };
11
- //# sourceMappingURL=chunk-6TJXDCAQ.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/schemas/types.ts"],"sourcesContent":["/**\n * Behavior Schema Types\n *\n * Defines the structure for behavior metadata used for:\n * - Code generation (TypeScript types, documentation)\n * - Runtime categorization and lazy loading\n * - Tooling and IDE integration\n */\n\n/**\n * Behavior categories for organization.\n * - ui: Visual interaction behaviors (drag, resize, sort)\n * - data: Data manipulation behaviors (remove, transform)\n * - animation: Animation and transition behaviors\n * - form: Form-related behaviors (validation, toggle states)\n * - layout: Layout behaviors (sticky, scrollspy)\n */\nexport type BehaviorCategory = 'ui' | 'data' | 'animation' | 'form' | 'layout';\n\n/**\n * Loading tiers for lazy loading optimization.\n * - core: Always loaded (essential behaviors)\n * - common: High usage (loaded for typical apps)\n * - optional: Low usage (loaded on demand)\n */\nexport type BehaviorTier = 'core' | 'common' | 'optional';\n\n/**\n * Schema for a behavior parameter.\n */\nexport interface ParameterSchema {\n name: string;\n type: 'string' | 'number' | 'boolean' | 'selector' | 'element';\n optional?: boolean;\n default?: string | number | boolean;\n /** Allowed values for constrained parameters */\n enum?: string[];\n description: string;\n}\n\n/**\n * Schema for a behavior event.\n */\nexport interface EventSchema {\n name: string;\n description: string;\n}\n\n/**\n * Complete schema for a behavior.\n * This is the source of truth for all behavior metadata.\n */\nexport interface BehaviorSchema {\n /** Behavior name (PascalCase) */\n name: string;\n /** Category for organization */\n category: BehaviorCategory;\n /** Loading tier for lazy loading */\n tier: BehaviorTier;\n /** Semantic version */\n version: string;\n /** Human-readable description */\n description: string;\n /** Parameter definitions */\n parameters: ParameterSchema[];\n /** Event definitions */\n events: EventSchema[];\n /** The hyperscript behavior source code */\n source: string;\n /** Optional requirements or notes */\n requirements?: string[];\n}\n\n/**\n * Runtime behavior module interface.\n * This is what gets registered with the hyperfixi runtime.\n */\nexport interface BehaviorModule {\n source: string;\n metadata: BehaviorSchema;\n register: (hyperfixi?: LokaScriptInstance) => Promise<void>;\n}\n\n/**\n * Minimal LokaScript instance interface for behavior registration.\n */\nexport interface LokaScriptInstance {\n compileSync: (\n code: string,\n options?: { traditional?: boolean; language?: string }\n ) => {\n ok: boolean;\n ast?: unknown;\n errors?: Array<{ message: string; line?: number; column?: number }>;\n };\n execute: (ast: unknown, ctx: unknown) => Promise<unknown>;\n createContext?: () => { locals: Map<string, unknown>; globals: Map<string, unknown> };\n}\n\n/**\n * Typed window interface for behavior auto-registration.\n * Avoids `(window as any)` casts throughout the codebase.\n * Checks both `window.lokascript` and `window.hyperfixi` for the runtime instance.\n */\nexport interface LokaScriptWindow {\n lokascript?: LokaScriptInstance;\n hyperfixi?: LokaScriptInstance;\n __hyperfixi_behaviors_ready?: Promise<void> | undefined;\n}\n\n/**\n * Resolve the LokaScript runtime from window globals.\n * Checks both `window.lokascript` and `window.hyperfixi`.\n */\nexport function resolveRuntime(): LokaScriptInstance | null {\n if (typeof window === 'undefined') return null;\n const win = window as unknown as LokaScriptWindow;\n return win.lokascript || win.hyperfixi || null;\n}\n"],"mappings":";AAkHO,SAAS,iBAA4C;AAC1D,MAAI,OAAO,WAAW,YAAa,QAAO;AAC1C,QAAM,MAAM;AACZ,SAAO,IAAI,cAAc,IAAI,aAAa;AAC5C;","names":[]}
@@ -1,40 +0,0 @@
1
- import {
2
- clickOutsideSchema
3
- } from "./chunk-26IX7QU7.js";
4
- import {
5
- resolveRuntime
6
- } from "./chunk-6TJXDCAQ.js";
7
-
8
- // src/behaviors/clickoutside.ts
9
- var clickOutsideSource = clickOutsideSchema.source;
10
- var clickOutsideMetadata = clickOutsideSchema;
11
- async function registerClickOutside(hyperfixi) {
12
- const hf = hyperfixi || resolveRuntime();
13
- if (!hf) {
14
- throw new Error(
15
- "LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors."
16
- );
17
- }
18
- const result = hf.compileSync(clickOutsideSchema.source, { traditional: true });
19
- if (!result.ok) {
20
- throw new Error(`Failed to compile ClickOutside behavior: ${JSON.stringify(result.errors)}`);
21
- }
22
- const ctx = hf.createContext ? hf.createContext() : { locals: /* @__PURE__ */ new Map(), globals: /* @__PURE__ */ new Map() };
23
- await hf.execute(result.ast, ctx);
24
- }
25
- if (resolveRuntime()) {
26
- registerClickOutside().catch(console.error);
27
- }
28
- var clickoutside_default = {
29
- source: clickOutsideSchema.source,
30
- metadata: clickOutsideSchema,
31
- register: registerClickOutside
32
- };
33
-
34
- export {
35
- clickOutsideSource,
36
- clickOutsideMetadata,
37
- registerClickOutside,
38
- clickoutside_default
39
- };
40
- //# sourceMappingURL=chunk-7TPDLB7W.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/behaviors/clickoutside.ts"],"sourcesContent":["/**\n * ClickOutside Behavior\n *\n * Fires a clickoutside event when the user clicks outside the element.\n * Uses pointerdown instead of click to avoid timing issues.\n *\n * Compiled from its hyperscript `source` (the single source of truth shared with\n * the CDN resolver bundle and patterns-reference).\n */\n\nimport { clickOutsideSchema } from '../schemas/clickoutside.schema';\nimport type { LokaScriptInstance } from '../schemas/types';\nimport { resolveRuntime } from '../schemas/types';\n\n// Re-export schema-derived values\nexport const clickOutsideSource = clickOutsideSchema.source;\nexport const clickOutsideMetadata = clickOutsideSchema;\n\n/**\n * Register the ClickOutside behavior with LokaScript by compiling its\n * hyperscript source and executing the resulting behavior definition.\n */\nexport async function registerClickOutside(hyperfixi?: LokaScriptInstance): Promise<void> {\n const hf = hyperfixi || resolveRuntime();\n\n if (!hf) {\n throw new Error(\n 'LokaScript not found. Make sure @hyperfixi/core is loaded before registering behaviors.'\n );\n }\n\n const result = hf.compileSync(clickOutsideSchema.source, { traditional: true });\n\n if (!result.ok) {\n throw new Error(`Failed to compile ClickOutside behavior: ${JSON.stringify(result.errors)}`);\n }\n\n const ctx = hf.createContext ? hf.createContext() : { locals: new Map(), globals: new Map() };\n await hf.execute(result.ast, ctx);\n}\n\n// Auto-register when loaded as a script tag\nif (resolveRuntime()) {\n registerClickOutside().catch(console.error);\n}\n\nexport default {\n source: clickOutsideSchema.source,\n metadata: clickOutsideSchema,\n register: registerClickOutside,\n};\n"],"mappings":";;;;;;;;AAeO,IAAM,qBAAqB,mBAAmB;AAC9C,IAAM,uBAAuB;AAMpC,eAAsB,qBAAqB,WAA+C;AACxF,QAAM,KAAK,aAAa,eAAe;AAEvC,MAAI,CAAC,IAAI;AACP,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,SAAS,GAAG,YAAY,mBAAmB,QAAQ,EAAE,aAAa,KAAK,CAAC;AAE9E,MAAI,CAAC,OAAO,IAAI;AACd,UAAM,IAAI,MAAM,4CAA4C,KAAK,UAAU,OAAO,MAAM,CAAC,EAAE;AAAA,EAC7F;AAEA,QAAM,MAAM,GAAG,gBAAgB,GAAG,cAAc,IAAI,EAAE,QAAQ,oBAAI,IAAI,GAAG,SAAS,oBAAI,IAAI,EAAE;AAC5F,QAAM,GAAG,QAAQ,OAAO,KAAK,GAAG;AAClC;AAGA,IAAI,eAAe,GAAG;AACpB,uBAAqB,EAAE,MAAM,QAAQ,KAAK;AAC5C;AAEA,IAAO,uBAAQ;AAAA,EACb,QAAQ,mBAAmB;AAAA,EAC3B,UAAU;AAAA,EACV,UAAU;AACZ;","names":[]}