foldkit 0.111.1 → 0.112.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 (222) hide show
  1. package/README.md +2 -2
  2. package/dist/devTools/host.d.ts +6 -0
  3. package/dist/devTools/host.d.ts.map +1 -0
  4. package/dist/devTools/host.js +4 -0
  5. package/dist/dom/dom.d.ts +6 -1
  6. package/dist/dom/dom.d.ts.map +1 -1
  7. package/dist/dom/dom.js +24 -1
  8. package/dist/html/index.d.ts +4 -3
  9. package/dist/html/index.d.ts.map +1 -1
  10. package/dist/html/index.js +4 -3
  11. package/dist/html/submodel.d.ts +2 -2
  12. package/dist/html/submodel.d.ts.map +1 -1
  13. package/dist/index.d.ts +0 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +0 -1
  16. package/dist/runtime/public.d.ts +1 -1
  17. package/dist/runtime/public.d.ts.map +1 -1
  18. package/dist/runtime/runtime.d.ts +14 -1
  19. package/dist/runtime/runtime.d.ts.map +1 -1
  20. package/dist/runtime/runtime.js +7 -4
  21. package/dist/runtime/subscription.d.ts +1 -1
  22. package/dist/subscription/public.d.ts +1 -1
  23. package/dist/subscription/public.d.ts.map +1 -1
  24. package/package.json +12 -93
  25. package/dist/devTools/overlay-styles.d.ts +0 -3
  26. package/dist/devTools/overlay-styles.d.ts.map +0 -1
  27. package/dist/devTools/overlay-styles.js +0 -706
  28. package/dist/devTools/overlay.d.ts +0 -63
  29. package/dist/devTools/overlay.d.ts.map +0 -1
  30. package/dist/devTools/overlay.js +0 -1244
  31. package/dist/test/apps/disabledButton.d.ts +0 -38
  32. package/dist/test/apps/disabledButton.d.ts.map +0 -1
  33. package/dist/test/apps/disabledButton.js +0 -71
  34. package/dist/ui/anchor.d.ts +0 -38
  35. package/dist/ui/anchor.d.ts.map +0 -1
  36. package/dist/ui/anchor.js +0 -142
  37. package/dist/ui/animation/index.d.ts +0 -49
  38. package/dist/ui/animation/index.d.ts.map +0 -1
  39. package/dist/ui/animation/index.js +0 -74
  40. package/dist/ui/animation/public.d.ts +0 -3
  41. package/dist/ui/animation/public.d.ts.map +0 -1
  42. package/dist/ui/animation/public.js +0 -1
  43. package/dist/ui/animation/schema.d.ts +0 -43
  44. package/dist/ui/animation/schema.d.ts.map +0 -1
  45. package/dist/ui/animation/schema.js +0 -41
  46. package/dist/ui/animation/update.d.ts +0 -24
  47. package/dist/ui/animation/update.d.ts.map +0 -1
  48. package/dist/ui/animation/update.js +0 -67
  49. package/dist/ui/button/index.d.ts +0 -17
  50. package/dist/ui/button/index.d.ts.map +0 -1
  51. package/dist/ui/button/index.js +0 -22
  52. package/dist/ui/button/public.d.ts +0 -3
  53. package/dist/ui/button/public.d.ts.map +0 -1
  54. package/dist/ui/button/public.js +0 -1
  55. package/dist/ui/calendar/index.d.ts +0 -462
  56. package/dist/ui/calendar/index.d.ts.map +0 -1
  57. package/dist/ui/calendar/index.js +0 -824
  58. package/dist/ui/calendar/public.d.ts +0 -3
  59. package/dist/ui/calendar/public.d.ts.map +0 -1
  60. package/dist/ui/calendar/public.js +0 -1
  61. package/dist/ui/checkbox/index.d.ts +0 -119
  62. package/dist/ui/checkbox/index.d.ts.map +0 -1
  63. package/dist/ui/checkbox/index.js +0 -110
  64. package/dist/ui/checkbox/public.d.ts +0 -3
  65. package/dist/ui/checkbox/public.d.ts.map +0 -1
  66. package/dist/ui/checkbox/public.js +0 -1
  67. package/dist/ui/combobox/multi.d.ts +0 -184
  68. package/dist/ui/combobox/multi.d.ts.map +0 -1
  69. package/dist/ui/combobox/multi.js +0 -81
  70. package/dist/ui/combobox/multiPublic.d.ts +0 -3
  71. package/dist/ui/combobox/multiPublic.d.ts.map +0 -1
  72. package/dist/ui/combobox/multiPublic.js +0 -1
  73. package/dist/ui/combobox/public.d.ts +0 -7
  74. package/dist/ui/combobox/public.d.ts.map +0 -1
  75. package/dist/ui/combobox/public.js +0 -3
  76. package/dist/ui/combobox/shared.d.ts +0 -422
  77. package/dist/ui/combobox/shared.d.ts.map +0 -1
  78. package/dist/ui/combobox/shared.js +0 -707
  79. package/dist/ui/combobox/single.d.ts +0 -199
  80. package/dist/ui/combobox/single.d.ts.map +0 -1
  81. package/dist/ui/combobox/single.js +0 -106
  82. package/dist/ui/datePicker/index.d.ts +0 -457
  83. package/dist/ui/datePicker/index.d.ts.map +0 -1
  84. package/dist/ui/datePicker/index.js +0 -317
  85. package/dist/ui/datePicker/public.d.ts +0 -3
  86. package/dist/ui/datePicker/public.d.ts.map +0 -1
  87. package/dist/ui/datePicker/public.js +0 -1
  88. package/dist/ui/dialog/index.d.ts +0 -155
  89. package/dist/ui/dialog/index.d.ts.map +0 -1
  90. package/dist/ui/dialog/index.js +0 -208
  91. package/dist/ui/dialog/public.d.ts +0 -3
  92. package/dist/ui/dialog/public.d.ts.map +0 -1
  93. package/dist/ui/dialog/public.js +0 -1
  94. package/dist/ui/disclosure/index.d.ts +0 -110
  95. package/dist/ui/disclosure/index.d.ts.map +0 -1
  96. package/dist/ui/disclosure/index.js +0 -110
  97. package/dist/ui/disclosure/public.d.ts +0 -3
  98. package/dist/ui/disclosure/public.d.ts.map +0 -1
  99. package/dist/ui/disclosure/public.js +0 -1
  100. package/dist/ui/dragAndDrop/index.d.ts +0 -540
  101. package/dist/ui/dragAndDrop/index.d.ts.map +0 -1
  102. package/dist/ui/dragAndDrop/index.js +0 -535
  103. package/dist/ui/dragAndDrop/public.d.ts +0 -3
  104. package/dist/ui/dragAndDrop/public.d.ts.map +0 -1
  105. package/dist/ui/dragAndDrop/public.js +0 -1
  106. package/dist/ui/fieldset/index.d.ts +0 -21
  107. package/dist/ui/fieldset/index.d.ts.map +0 -1
  108. package/dist/ui/fieldset/index.js +0 -25
  109. package/dist/ui/fieldset/public.d.ts +0 -3
  110. package/dist/ui/fieldset/public.d.ts.map +0 -1
  111. package/dist/ui/fieldset/public.js +0 -1
  112. package/dist/ui/fileDrop/index.d.ts +0 -109
  113. package/dist/ui/fileDrop/index.d.ts.map +0 -1
  114. package/dist/ui/fileDrop/index.js +0 -126
  115. package/dist/ui/fileDrop/public.d.ts +0 -3
  116. package/dist/ui/fileDrop/public.d.ts.map +0 -1
  117. package/dist/ui/fileDrop/public.js +0 -1
  118. package/dist/ui/group.d.ts +0 -8
  119. package/dist/ui/group.d.ts.map +0 -1
  120. package/dist/ui/group.js +0 -13
  121. package/dist/ui/index.d.ts +0 -25
  122. package/dist/ui/index.d.ts.map +0 -1
  123. package/dist/ui/index.js +0 -24
  124. package/dist/ui/input/index.d.ts +0 -26
  125. package/dist/ui/input/index.d.ts.map +0 -1
  126. package/dist/ui/input/index.js +0 -43
  127. package/dist/ui/input/public.d.ts +0 -3
  128. package/dist/ui/input/public.d.ts.map +0 -1
  129. package/dist/ui/input/public.js +0 -1
  130. package/dist/ui/keyboard.d.ts +0 -6
  131. package/dist/ui/keyboard.d.ts.map +0 -1
  132. package/dist/ui/keyboard.js +0 -9
  133. package/dist/ui/listbox/multi.d.ts +0 -190
  134. package/dist/ui/listbox/multi.d.ts.map +0 -1
  135. package/dist/ui/listbox/multi.js +0 -65
  136. package/dist/ui/listbox/multiPublic.d.ts +0 -3
  137. package/dist/ui/listbox/multiPublic.d.ts.map +0 -1
  138. package/dist/ui/listbox/multiPublic.js +0 -1
  139. package/dist/ui/listbox/public.d.ts +0 -7
  140. package/dist/ui/listbox/public.d.ts.map +0 -1
  141. package/dist/ui/listbox/public.js +0 -3
  142. package/dist/ui/listbox/shared.d.ts +0 -431
  143. package/dist/ui/listbox/shared.d.ts.map +0 -1
  144. package/dist/ui/listbox/shared.js +0 -669
  145. package/dist/ui/listbox/single.d.ts +0 -208
  146. package/dist/ui/listbox/single.d.ts.map +0 -1
  147. package/dist/ui/listbox/single.js +0 -73
  148. package/dist/ui/menu/index.d.ts +0 -367
  149. package/dist/ui/menu/index.d.ts.map +0 -1
  150. package/dist/ui/menu/index.js +0 -681
  151. package/dist/ui/menu/public.d.ts +0 -4
  152. package/dist/ui/menu/public.d.ts.map +0 -1
  153. package/dist/ui/menu/public.js +0 -1
  154. package/dist/ui/popover/index.d.ts +0 -267
  155. package/dist/ui/popover/index.d.ts.map +0 -1
  156. package/dist/ui/popover/index.js +0 -345
  157. package/dist/ui/popover/public.d.ts +0 -4
  158. package/dist/ui/popover/public.d.ts.map +0 -1
  159. package/dist/ui/popover/public.js +0 -1
  160. package/dist/ui/radioGroup/index.d.ts +0 -169
  161. package/dist/ui/radioGroup/index.d.ts.map +0 -1
  162. package/dist/ui/radioGroup/index.js +0 -196
  163. package/dist/ui/radioGroup/public.d.ts +0 -3
  164. package/dist/ui/radioGroup/public.d.ts.map +0 -1
  165. package/dist/ui/radioGroup/public.js +0 -1
  166. package/dist/ui/select/index.d.ts +0 -24
  167. package/dist/ui/select/index.d.ts.map +0 -1
  168. package/dist/ui/select/index.js +0 -40
  169. package/dist/ui/select/public.d.ts +0 -3
  170. package/dist/ui/select/public.d.ts.map +0 -1
  171. package/dist/ui/select/public.js +0 -1
  172. package/dist/ui/slider/index.d.ts +0 -318
  173. package/dist/ui/slider/index.d.ts.map +0 -1
  174. package/dist/ui/slider/index.js +0 -336
  175. package/dist/ui/slider/public.d.ts +0 -3
  176. package/dist/ui/slider/public.d.ts.map +0 -1
  177. package/dist/ui/slider/public.js +0 -1
  178. package/dist/ui/switch/index.d.ts +0 -99
  179. package/dist/ui/switch/index.d.ts.map +0 -1
  180. package/dist/ui/switch/index.js +0 -106
  181. package/dist/ui/switch/public.d.ts +0 -3
  182. package/dist/ui/switch/public.d.ts.map +0 -1
  183. package/dist/ui/switch/public.js +0 -1
  184. package/dist/ui/tabs/index.d.ts +0 -155
  185. package/dist/ui/tabs/index.d.ts.map +0 -1
  186. package/dist/ui/tabs/index.js +0 -184
  187. package/dist/ui/tabs/public.d.ts +0 -3
  188. package/dist/ui/tabs/public.d.ts.map +0 -1
  189. package/dist/ui/tabs/public.js +0 -1
  190. package/dist/ui/textarea/index.d.ts +0 -26
  191. package/dist/ui/textarea/index.d.ts.map +0 -1
  192. package/dist/ui/textarea/index.js +0 -44
  193. package/dist/ui/textarea/public.d.ts +0 -3
  194. package/dist/ui/textarea/public.d.ts.map +0 -1
  195. package/dist/ui/textarea/public.js +0 -1
  196. package/dist/ui/toast/index.d.ts +0 -608
  197. package/dist/ui/toast/index.d.ts.map +0 -1
  198. package/dist/ui/toast/index.js +0 -145
  199. package/dist/ui/toast/public.d.ts +0 -4
  200. package/dist/ui/toast/public.d.ts.map +0 -1
  201. package/dist/ui/toast/public.js +0 -1
  202. package/dist/ui/toast/schema.d.ts +0 -154
  203. package/dist/ui/toast/schema.d.ts.map +0 -1
  204. package/dist/ui/toast/schema.js +0 -93
  205. package/dist/ui/toast/update.d.ts +0 -510
  206. package/dist/ui/toast/update.d.ts.map +0 -1
  207. package/dist/ui/toast/update.js +0 -225
  208. package/dist/ui/tooltip/index.d.ts +0 -170
  209. package/dist/ui/tooltip/index.d.ts.map +0 -1
  210. package/dist/ui/tooltip/index.js +0 -252
  211. package/dist/ui/tooltip/public.d.ts +0 -4
  212. package/dist/ui/tooltip/public.d.ts.map +0 -1
  213. package/dist/ui/tooltip/public.js +0 -1
  214. package/dist/ui/typeahead.d.ts +0 -4
  215. package/dist/ui/typeahead.d.ts.map +0 -1
  216. package/dist/ui/typeahead.js +0 -14
  217. package/dist/ui/virtualList/index.d.ts +0 -202
  218. package/dist/ui/virtualList/index.d.ts.map +0 -1
  219. package/dist/ui/virtualList/index.js +0 -391
  220. package/dist/ui/virtualList/public.d.ts +0 -3
  221. package/dist/ui/virtualList/public.d.ts.map +0 -1
  222. package/dist/ui/virtualList/public.js +0 -1
@@ -1,38 +0,0 @@
1
- import { Schema as S } from 'effect';
2
- import * as Command from '../../command/index.js';
3
- import { type Html } from '../../html/index.js';
4
- export declare const Model: S.Struct<{
5
- readonly isEnabled: S.Boolean;
6
- readonly dialog: S.Struct<{
7
- readonly id: S.String;
8
- readonly isOpen: S.Boolean;
9
- readonly isAnimated: S.Boolean;
10
- readonly animation: S.Struct<{
11
- readonly id: S.String;
12
- readonly isShowing: S.Boolean;
13
- readonly transitionState: S.Literals<readonly ["Idle", "EnterStart", "EnterAnimating", "LeaveStart", "LeaveAnimating"]>;
14
- }>;
15
- readonly maybeFocusSelector: S.Option<S.String>;
16
- }>;
17
- }>;
18
- export type Model = typeof Model.Type;
19
- export declare const ClickedToggle: import("../../schema/index.js").CallableTaggedStruct<"ClickedToggle", {}>;
20
- export declare const ClickedSubmit: import("../../schema/index.js").CallableTaggedStruct<"ClickedSubmit", {}>;
21
- export declare const GotDialogMessage: import("../../schema/index.js").CallableTaggedStruct<"GotDialogMessage", {
22
- message: S.Union<[import("../../schema/index.js").CallableTaggedStruct<"RequestedOpen", {}>, import("../../schema/index.js").CallableTaggedStruct<"RequestedClose", {}>, import("../../schema/index.js").CallableTaggedStruct<"CompletedShowDialog", {}>, import("../../schema/index.js").CallableTaggedStruct<"CompletedCloseDialog", {}>, import("../../schema/index.js").CallableTaggedStruct<"GotAnimationMessage", {
23
- message: S.Union<[import("../../schema/index.js").CallableTaggedStruct<"Showed", {}>, import("../../schema/index.js").CallableTaggedStruct<"Hid", {}>, import("../../schema/index.js").CallableTaggedStruct<"AdvancedAnimationFrame", {}>, import("../../schema/index.js").CallableTaggedStruct<"EndedAnimation", {}>]>;
24
- }>]>;
25
- }>;
26
- export declare const Message: S.Union<readonly [import("../../schema/index.js").CallableTaggedStruct<"ClickedToggle", {}>, import("../../schema/index.js").CallableTaggedStruct<"ClickedSubmit", {}>, import("../../schema/index.js").CallableTaggedStruct<"GotDialogMessage", {
27
- message: S.Union<[import("../../schema/index.js").CallableTaggedStruct<"RequestedOpen", {}>, import("../../schema/index.js").CallableTaggedStruct<"RequestedClose", {}>, import("../../schema/index.js").CallableTaggedStruct<"CompletedShowDialog", {}>, import("../../schema/index.js").CallableTaggedStruct<"CompletedCloseDialog", {}>, import("../../schema/index.js").CallableTaggedStruct<"GotAnimationMessage", {
28
- message: S.Union<[import("../../schema/index.js").CallableTaggedStruct<"Showed", {}>, import("../../schema/index.js").CallableTaggedStruct<"Hid", {}>, import("../../schema/index.js").CallableTaggedStruct<"AdvancedAnimationFrame", {}>, import("../../schema/index.js").CallableTaggedStruct<"EndedAnimation", {}>]>;
29
- }>]>;
30
- }>]>;
31
- export type Message = typeof Message.Type;
32
- export declare const initialModel: Model;
33
- export declare const update: (model: Model, message: Message) => readonly [Model, ReadonlyArray<Command.Command<Message>>];
34
- /** Plain view, no dialog wrapper. */
35
- export declare const view: (model: Model) => Html;
36
- /** View with submit button inside a dialog's panel. */
37
- export declare const viewWithDialog: (model: Model) => Html;
38
- //# sourceMappingURL=disabledButton.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"disabledButton.d.ts","sourceRoot":"","sources":["../../../src/test/apps/disabledButton.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAEhD,OAAO,KAAK,OAAO,MAAM,wBAAwB,CAAA;AACjD,OAAO,EAAE,KAAK,IAAI,EAAQ,MAAM,qBAAqB,CAAA;AAMrD,eAAO,MAAM,KAAK;;;;;;;;;;;;;EAGhB,CAAA;AACF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,eAAO,MAAM,aAAa,2EAAqB,CAAA;AAC/C,eAAO,MAAM,aAAa,2EAAqB,CAAA;AAC/C,eAAO,MAAM,gBAAgB;;;;EAE3B,CAAA;AAEF,eAAO,MAAM,OAAO;;;;IAA4D,CAAA;AAChF,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAIzC,eAAO,MAAM,YAAY,EAAE,KAG1B,CAAA;AAID,eAAO,MAAM,MAAM,GACjB,OAAO,KAAK,EACZ,SAAS,OAAO,KACf,SAAS,CAAC,KAAK,EAAE,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAqBxD,CAAA;AAgBH,qCAAqC;AACrC,eAAO,MAAM,IAAI,GAAI,OAAO,KAAK,KAAG,IAUnC,CAAA;AAED,uDAAuD;AACvD,eAAO,MAAM,cAAc,GAAI,OAAO,KAAK,KAAG,IA2B7C,CAAA"}
@@ -1,71 +0,0 @@
1
- import { Match as M, Schema as S } from 'effect';
2
- import * as Command from '../../command/index.js';
3
- import { html } from '../../html/index.js';
4
- import { m } from '../../message/index.js';
5
- import * as Dialog from '../../ui/dialog/index.js';
6
- // MODEL
7
- export const Model = S.Struct({
8
- isEnabled: S.Boolean,
9
- dialog: Dialog.Model,
10
- });
11
- // MESSAGE
12
- export const ClickedToggle = m('ClickedToggle');
13
- export const ClickedSubmit = m('ClickedSubmit');
14
- export const GotDialogMessage = m('GotDialogMessage', {
15
- message: Dialog.Message,
16
- });
17
- export const Message = S.Union([ClickedToggle, ClickedSubmit, GotDialogMessage]);
18
- // INIT
19
- export const initialModel = {
20
- isEnabled: false,
21
- dialog: Dialog.init({ id: 'test-dialog', isOpen: true }),
22
- };
23
- // UPDATE
24
- export const update = (model, message) => M.value(message).pipe(M.withReturnType(), M.tagsExhaustive({
25
- ClickedToggle: () => [{ ...model, isEnabled: !model.isEnabled }, []],
26
- ClickedSubmit: () => [model, []],
27
- GotDialogMessage: ({ message: dialogMessage }) => {
28
- const [nextDialog, commands] = Dialog.update(model.dialog, dialogMessage);
29
- return [
30
- { ...model, dialog: nextDialog },
31
- Command.mapMessages(commands, dialogMessage => GotDialogMessage({ message: dialogMessage })),
32
- ];
33
- },
34
- }));
35
- // VIEW
36
- const submitButton = (isEnabled) => {
37
- const h = html();
38
- return h.button([
39
- h.Class('submit'),
40
- ...(isEnabled ? [h.OnClick(ClickedSubmit())] : [h.Disabled(true)]),
41
- ], ['Submit']);
42
- };
43
- /** Plain view, no dialog wrapper. */
44
- export const view = (model) => {
45
- const h = html();
46
- return h.div([], [
47
- h.button([h.OnClick(ClickedToggle())], ['Toggle']),
48
- submitButton(model.isEnabled),
49
- ]);
50
- };
51
- /** View with submit button inside a dialog's panel. */
52
- export const viewWithDialog = (model) => {
53
- const h = html();
54
- return h.div([], [
55
- h.button([h.OnClick(ClickedToggle())], ['Toggle']),
56
- h.submodel({
57
- slotId: model.dialog.id,
58
- model: model.dialog,
59
- view: Dialog.view,
60
- viewInputs: {
61
- toView: ({ dialog, backdrop, panel, isVisible }) => h.dialog([...dialog], isVisible
62
- ? [
63
- h.div([...backdrop], []),
64
- h.div([...panel], [submitButton(model.isEnabled)]),
65
- ]
66
- : []),
67
- },
68
- toParentMessage: message => GotDialogMessage({ message }),
69
- }),
70
- ]);
71
- };
@@ -1,38 +0,0 @@
1
- import { Schema as S } from 'effect';
2
- /** Schema mirroring `@floating-ui/dom`'s `Placement` literal union: a side
3
- * (`top`/`right`/`bottom`/`left`) optionally suffixed with `-start` or `-end`. */
4
- export declare const Placement: S.Literals<readonly ["top", "right", "bottom", "left", "top-start", "top-end", "right-start", "right-end", "bottom-start", "bottom-end", "left-start", "left-end"]>;
5
- /** Static configuration for anchor-based positioning of a floating element relative to a button. */
6
- export declare const AnchorConfig: S.Struct<{
7
- readonly placement: S.optional<S.Literals<readonly ["top", "right", "bottom", "left", "top-start", "top-end", "right-start", "right-end", "bottom-start", "bottom-end", "left-start", "left-end"]>>;
8
- readonly gap: S.optional<S.Number>;
9
- readonly offset: S.optional<S.Number>;
10
- readonly padding: S.optional<S.Number>;
11
- readonly portal: S.optional<S.Boolean>;
12
- }>;
13
- export type AnchorConfig = typeof AnchorConfig.Type;
14
- /** Relocates an element into the shared `foldkit-portal-root` div appended to
15
- * `document.body`, escaping any ancestor stacking context. Returns a cleanup
16
- * function that removes the element from the portal root. Designed to be
17
- * called from inside an `OnMount` action: the consumer wraps the call in
18
- * `Effect.sync` and stashes the returned cleanup in the `Mount` result. */
19
- export declare const portalToBody: (element: Element) => (() => void);
20
- /** Positions a floating element relative to its button using Floating UI, then
21
- * returns a cleanup function. Designed to be called inside an `OnMount`
22
- * action: the consumer wraps the call in `Effect.sync` and stashes the
23
- * returned cleanup in the `Mount` result. When `interceptTab` is true
24
- * (default), Tab key in portal mode refocuses the button — set to false for
25
- * components like Popover where Tab should navigate naturally within the
26
- * panel. When `focusAfterPosition` is true, the element is focused after the
27
- * first position computation clears visibility — deferred via
28
- * requestAnimationFrame so the element is painted before focus fires.
29
- * `focusSelector` optionally targets a descendant (e.g. a calendar grid
30
- * inside a popover panel) instead of the panel itself. */
31
- export declare const anchorSetup: (config: {
32
- buttonId: string;
33
- anchor: AnchorConfig;
34
- interceptTab?: boolean;
35
- focusAfterPosition?: boolean;
36
- focusSelector?: string;
37
- }) => (element: Element) => (() => void);
38
- //# sourceMappingURL=anchor.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"anchor.d.ts","sourceRoot":"","sources":["../../src/ui/anchor.ts"],"names":[],"mappings":"AAQA,OAAO,EAAY,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAE9C;mFACmF;AACnF,eAAO,MAAM,SAAS,qKAapB,CAAA;AAEF,oGAAoG;AACpG,eAAO,MAAM,YAAY;;;;;;EAMvB,CAAA;AAEF,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,IAAI,CAAA;AAwBnD;;;;4EAI4E;AAC5E,eAAO,MAAM,YAAY,GAAI,SAAS,OAAO,KAAG,CAAC,MAAM,IAAI,CAW1D,CAAA;AAED;;;;;;;;;;2DAU2D;AAC3D,eAAO,MAAM,WAAW,GACrB,QAAQ;IACP,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,YAAY,CAAA;IACpB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,MACA,SAAS,OAAO,KAAG,CAAC,MAAM,IAAI,CAiF9B,CAAA"}
package/dist/ui/anchor.js DELETED
@@ -1,142 +0,0 @@
1
- import { autoUpdate, computePosition, flip, offset as floatingOffset, shift, size, } from '@floating-ui/dom';
2
- import { Function, Schema as S } from 'effect';
3
- /** Schema mirroring `@floating-ui/dom`'s `Placement` literal union: a side
4
- * (`top`/`right`/`bottom`/`left`) optionally suffixed with `-start` or `-end`. */
5
- export const Placement = S.Literals([
6
- 'top',
7
- 'right',
8
- 'bottom',
9
- 'left',
10
- 'top-start',
11
- 'top-end',
12
- 'right-start',
13
- 'right-end',
14
- 'bottom-start',
15
- 'bottom-end',
16
- 'left-start',
17
- 'left-end',
18
- ]);
19
- /** Static configuration for anchor-based positioning of a floating element relative to a button. */
20
- export const AnchorConfig = S.Struct({
21
- placement: S.optional(Placement),
22
- gap: S.optional(S.Number),
23
- offset: S.optional(S.Number),
24
- padding: S.optional(S.Number),
25
- portal: S.optional(S.Boolean),
26
- });
27
- const PORTAL_ROOT_ID = 'foldkit-portal-root';
28
- const getOrCreatePortalRoot = () => {
29
- const existing = document.getElementById(PORTAL_ROOT_ID);
30
- if (existing) {
31
- return existing;
32
- }
33
- const root = document.createElement('div');
34
- root.id = PORTAL_ROOT_ID;
35
- // NOTE: prepended (not appended) so portaled overlays sit BEFORE the page's
36
- // listbox/popover/menu wrappers in tree order. Those wrappers are
37
- // `position: relative; z-index: auto` and paint at CSS step 8 in tree order;
38
- // a backdrop appended after them would paint on top of every button on the
39
- // page, breaking click-outside detection. Prepending makes wrappers paint
40
- // above the backdrop, while panels (z-10) still win via step 9.
41
- document.body.insertBefore(root, document.body.firstChild);
42
- return root;
43
- };
44
- /** Relocates an element into the shared `foldkit-portal-root` div appended to
45
- * `document.body`, escaping any ancestor stacking context. Returns a cleanup
46
- * function that removes the element from the portal root. Designed to be
47
- * called from inside an `OnMount` action: the consumer wraps the call in
48
- * `Effect.sync` and stashes the returned cleanup in the `Mount` result. */
49
- export const portalToBody = (element) => {
50
- getOrCreatePortalRoot().appendChild(element);
51
- return () => {
52
- try {
53
- element.remove();
54
- }
55
- catch {
56
- // NOTE: a re-render may unmount the element before this cleanup fires,
57
- // so the remove() call can throw on a node that's already been removed.
58
- // Swallow the error.
59
- }
60
- };
61
- };
62
- /** Positions a floating element relative to its button using Floating UI, then
63
- * returns a cleanup function. Designed to be called inside an `OnMount`
64
- * action: the consumer wraps the call in `Effect.sync` and stashes the
65
- * returned cleanup in the `Mount` result. When `interceptTab` is true
66
- * (default), Tab key in portal mode refocuses the button — set to false for
67
- * components like Popover where Tab should navigate naturally within the
68
- * panel. When `focusAfterPosition` is true, the element is focused after the
69
- * first position computation clears visibility — deferred via
70
- * requestAnimationFrame so the element is painted before focus fires.
71
- * `focusSelector` optionally targets a descendant (e.g. a calendar grid
72
- * inside a popover panel) instead of the panel itself. */
73
- export const anchorSetup = (config) => (element) => {
74
- const button = document.getElementById(config.buttonId);
75
- if (!(button instanceof HTMLElement) || !(element instanceof HTMLElement)) {
76
- return Function.constVoid;
77
- }
78
- const isPortal = config.anchor.portal ?? true;
79
- const portalCleanup = isPortal ? portalToBody(element) : undefined;
80
- const { placement, gap, offset: crossAxis, padding } = config.anchor;
81
- const shouldInterceptTab = config.interceptTab ?? true;
82
- let isFirstUpdate = true;
83
- const floatingCleanup = autoUpdate(button, element, () => {
84
- computePosition(button, element, {
85
- placement: placement ?? 'bottom-start',
86
- strategy: 'absolute',
87
- middleware: [
88
- floatingOffset({
89
- mainAxis: gap ?? 0,
90
- crossAxis: crossAxis ?? 0,
91
- }),
92
- flip({ padding: padding ?? 0 }),
93
- shift({ padding: padding ?? 0 }),
94
- size({
95
- padding: padding ?? 0,
96
- apply({ rects, availableHeight }) {
97
- element.style.setProperty('--button-width', `${rects.reference.width}px`);
98
- element.style.maxHeight = `${availableHeight}px`;
99
- element.style.overflowY = 'auto';
100
- element.style.overscrollBehavior = 'none';
101
- },
102
- }),
103
- ],
104
- }).then(({ x, y }) => {
105
- element.style.left = `${x}px`;
106
- element.style.top = `${y}px`;
107
- if (isFirstUpdate) {
108
- isFirstUpdate = false;
109
- element.style.visibility = '';
110
- if (config.focusAfterPosition ?? false) {
111
- requestAnimationFrame(() => {
112
- const target = config.focusSelector
113
- ? document.querySelector(config.focusSelector)
114
- : element;
115
- if (target instanceof HTMLElement) {
116
- target.focus();
117
- }
118
- });
119
- }
120
- }
121
- });
122
- });
123
- if (isPortal && shouldInterceptTab) {
124
- const handleTabKey = (event) => {
125
- if (event instanceof KeyboardEvent && event.key === 'Tab') {
126
- button.focus();
127
- }
128
- };
129
- element.addEventListener('keydown', handleTabKey);
130
- return () => {
131
- floatingCleanup();
132
- element.removeEventListener('keydown', handleTabKey);
133
- portalCleanup?.();
134
- };
135
- }
136
- else {
137
- return () => {
138
- floatingCleanup();
139
- portalCleanup?.();
140
- };
141
- }
142
- };
@@ -1,49 +0,0 @@
1
- import { type ChildAttribute, type Html, type TagName } from '../../html/index.js';
2
- import { AdvancedAnimationFrame, EndedAnimation, Hid, Message, Model, OutMessage, Showed, StartedLeaveAnimating, TransitionState, TransitionedOut, init } from './schema.js';
3
- import { RequestFrame, WaitForAnimationSettled, defaultLeaveCommand, update } from './update.js';
4
- export type { InitConfig } from './schema.js';
5
- export { AdvancedAnimationFrame, EndedAnimation, Hid, init, Message, Model, OutMessage, Showed, StartedLeaveAnimating, TransitionState, TransitionedOut, };
6
- export { RequestFrame, WaitForAnimationSettled, defaultLeaveCommand, update };
7
- /** Per-render view inputs passed to `view` via `h.submodel`'s `viewInputs` field. */
8
- export type ViewInputs = Readonly<{
9
- content: Html;
10
- className?: string;
11
- attributes?: ReadonlyArray<ChildAttribute>;
12
- element?: TagName;
13
- /** When true, wraps content in a CSS grid container that smoothly animates
14
- * height via `grid-template-rows: 0fr → 1fr`. The element stays in the DOM
15
- * when hidden (collapsed to zero height) instead of being removed. */
16
- animateSize?: boolean;
17
- }>;
18
- /** Renders a headless animation wrapper that coordinates CSS transitions and
19
- * CSS keyframe animations via data attributes.
20
- *
21
- * Data attributes reflect the current lifecycle phase:
22
- * - `data-closed`: element is in its hidden/initial state
23
- * - `data-enter`: enter animation is active
24
- * - `data-leave`: leave animation is active
25
- * - `data-transition`: any animation is active
26
- */
27
- export declare const view: import("../../html/submodel.js").SubmodelView<{
28
- readonly id: string;
29
- readonly isShowing: boolean;
30
- readonly transitionState: "Idle" | "EnterStart" | "EnterAnimating" | "LeaveStart" | "LeaveAnimating";
31
- }, {
32
- readonly _tag: "Showed";
33
- } | {
34
- readonly _tag: "Hid";
35
- } | {
36
- readonly _tag: "AdvancedAnimationFrame";
37
- } | {
38
- readonly _tag: "EndedAnimation";
39
- }, Readonly<{
40
- content: Html;
41
- className?: string;
42
- attributes?: ReadonlyArray<ChildAttribute>;
43
- element?: TagName;
44
- /** When true, wraps content in a CSS grid container that smoothly animates
45
- * height via `grid-template-rows: 0fr → 1fr`. The element stays in the DOM
46
- * when hidden (collapsed to zero height) instead of being removed. */
47
- animateSize?: boolean;
48
- }>>;
49
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/animation/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,IAAI,EACT,KAAK,OAAO,EAGb,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,GAAG,EACH,OAAO,EACP,KAAK,EACL,UAAU,EACV,MAAM,EACN,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,IAAI,EACL,MAAM,aAAa,CAAA;AACpB,OAAO,EACL,YAAY,EACZ,uBAAuB,EACvB,mBAAmB,EACnB,MAAM,EACP,MAAM,aAAa,CAAA;AAEpB,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAC7C,OAAO,EACL,sBAAsB,EACtB,cAAc,EACd,GAAG,EACH,IAAI,EACJ,OAAO,EACP,KAAK,EACL,UAAU,EACV,MAAM,EACN,qBAAqB,EACrB,eAAe,EACf,eAAe,GAChB,CAAA;AAED,OAAO,EAAE,YAAY,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,EAAE,CAAA;AAI7E,qFAAqF;AACrF,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,OAAO,EAAE,IAAI,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;IAC1C,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;2EAEuE;IACvE,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,CAAC,CAAA;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,IAAI;;;;;;;;;;;;;aAnBN,IAAI;gBACD,MAAM;iBACL,aAAa,CAAC,cAAc,CAAC;cAChC,OAAO;IACjB;;2EAEuE;kBACzD,OAAO;GA6GtB,CAAA"}
@@ -1,74 +0,0 @@
1
- import { Match as M } from 'effect';
2
- import { defineView, html, } from '../../html/index.js';
3
- import { AdvancedAnimationFrame, EndedAnimation, Hid, Message, Model, OutMessage, Showed, StartedLeaveAnimating, TransitionState, TransitionedOut, init, } from './schema.js';
4
- import { RequestFrame, WaitForAnimationSettled, defaultLeaveCommand, update, } from './update.js';
5
- export { AdvancedAnimationFrame, EndedAnimation, Hid, init, Message, Model, OutMessage, Showed, StartedLeaveAnimating, TransitionState, TransitionedOut, };
6
- export { RequestFrame, WaitForAnimationSettled, defaultLeaveCommand, update };
7
- /** Renders a headless animation wrapper that coordinates CSS transitions and
8
- * CSS keyframe animations via data attributes.
9
- *
10
- * Data attributes reflect the current lifecycle phase:
11
- * - `data-closed`: element is in its hidden/initial state
12
- * - `data-enter`: enter animation is active
13
- * - `data-leave`: leave animation is active
14
- * - `data-transition`: any animation is active
15
- */
16
- export const view = defineView((model, viewInputs) => {
17
- const h = html();
18
- const { id, isShowing, transitionState } = model;
19
- const { content, className, attributes = [], element = 'div', animateSize = false, } = viewInputs;
20
- const isLeaving = transitionState === 'LeaveStart' || transitionState === 'LeaveAnimating';
21
- const isVisible = isShowing || isLeaving;
22
- const transitionAttributes = M.value(transitionState).pipe(M.when('EnterStart', () => [
23
- h.DataAttribute('closed', ''),
24
- h.DataAttribute('enter', ''),
25
- h.DataAttribute('transition', ''),
26
- ]), M.when('EnterAnimating', () => [
27
- h.DataAttribute('enter', ''),
28
- h.DataAttribute('transition', ''),
29
- ]), M.when('LeaveStart', () => [
30
- h.DataAttribute('leave', ''),
31
- h.DataAttribute('transition', ''),
32
- ]), M.when('LeaveAnimating', () => [
33
- h.DataAttribute('closed', ''),
34
- h.DataAttribute('leave', ''),
35
- h.DataAttribute('transition', ''),
36
- ]), M.orElse(() => []));
37
- if (animateSize) {
38
- const isClosed = transitionState === 'EnterStart' ||
39
- transitionState === 'LeaveAnimating' ||
40
- !isVisible;
41
- return h.div([
42
- h.Style({
43
- display: 'grid',
44
- gridTemplateRows: isClosed ? '0fr' : '1fr',
45
- transition: 'grid-template-rows 200ms ease-out',
46
- overflow: 'hidden',
47
- }),
48
- ], [
49
- h.div([
50
- h.Style({ minHeight: '0px', overflow: 'hidden' }),
51
- ...(!isVisible ? [h.AriaHidden(true)] : []),
52
- ], [
53
- h.keyed(element)(id, [
54
- h.Id(id),
55
- ...(isClosed && transitionState === 'Idle'
56
- ? [h.DataAttribute('closed', '')]
57
- : []),
58
- ...transitionAttributes,
59
- ...(className ? [h.Class(className)] : []),
60
- ...attributes,
61
- ], [content]),
62
- ]),
63
- ]);
64
- }
65
- if (!isVisible) {
66
- return h.empty;
67
- }
68
- return h.keyed(element)(id, [
69
- h.Id(id),
70
- ...transitionAttributes,
71
- ...(className ? [h.Class(className)] : []),
72
- ...attributes,
73
- ], [content]);
74
- });
@@ -1,3 +0,0 @@
1
- export { init, update, view, defaultLeaveCommand, Model, Message, OutMessage, Showed, Hid, AdvancedAnimationFrame, EndedAnimation, StartedLeaveAnimating, TransitionedOut, TransitionState, RequestFrame, WaitForAnimationSettled, } from './index.js';
2
- export type { InitConfig, ViewInputs } from './index.js';
3
- //# sourceMappingURL=public.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/ui/animation/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,MAAM,EACN,IAAI,EACJ,mBAAmB,EACnB,KAAK,EACL,OAAO,EACP,UAAU,EACV,MAAM,EACN,GAAG,EACH,sBAAsB,EACtB,cAAc,EACd,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,YAAY,EACZ,uBAAuB,GACxB,MAAM,YAAY,CAAA;AAEnB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA"}
@@ -1 +0,0 @@
1
- export { init, update, view, defaultLeaveCommand, Model, Message, OutMessage, Showed, Hid, AdvancedAnimationFrame, EndedAnimation, StartedLeaveAnimating, TransitionedOut, TransitionState, RequestFrame, WaitForAnimationSettled, } from './index.js';
@@ -1,43 +0,0 @@
1
- import { Schema as S } from 'effect';
2
- /** Schema for the animation lifecycle state, tracking enter/leave phases. */
3
- export declare const TransitionState: S.Literals<readonly ["Idle", "EnterStart", "EnterAnimating", "LeaveStart", "LeaveAnimating"]>;
4
- export type TransitionState = typeof TransitionState.Type;
5
- /** Schema for the animation component's state, tracking its unique ID, visibility intent, and lifecycle phase. */
6
- export declare const Model: S.Struct<{
7
- readonly id: S.String;
8
- readonly isShowing: S.Boolean;
9
- readonly transitionState: S.Literals<readonly ["Idle", "EnterStart", "EnterAnimating", "LeaveStart", "LeaveAnimating"]>;
10
- }>;
11
- export type Model = typeof Model.Type;
12
- /** Sent when the animation should enter (become visible). Starts the enter sequence. */
13
- export declare const Showed: import("../../schema/index.js").CallableTaggedStruct<"Showed", {}>;
14
- /** Sent when the animation should leave (become hidden). Starts the leave sequence. */
15
- export declare const Hid: import("../../schema/index.js").CallableTaggedStruct<"Hid", {}>;
16
- /** Sent internally when a double-rAF completes, advancing the lifecycle to its animating phase. */
17
- export declare const AdvancedAnimationFrame: import("../../schema/index.js").CallableTaggedStruct<"AdvancedAnimationFrame", {}>;
18
- /** Sent internally when all CSS animations on the element have settled. Covers both CSS transitions and CSS keyframe animations. */
19
- export declare const EndedAnimation: import("../../schema/index.js").CallableTaggedStruct<"EndedAnimation", {}>;
20
- /** Union of all messages the animation component can produce. */
21
- export declare const Message: S.Union<[
22
- typeof Showed,
23
- typeof Hid,
24
- typeof AdvancedAnimationFrame,
25
- typeof EndedAnimation
26
- ]>;
27
- export type Message = typeof Message.Type;
28
- export type Showed = typeof Showed.Type;
29
- export type Hid = typeof Hid.Type;
30
- /** Sent to the parent when the leave sequence advances to LeaveAnimating. The parent is responsible for providing the command that detects when the leave animation completes (e.g. WaitForAnimationSettled or a racing command). Use `defaultLeaveCommand` for the standard behavior. */
31
- export declare const StartedLeaveAnimating: import("../../schema/index.js").CallableTaggedStruct<"StartedLeaveAnimating", {}>;
32
- /** Sent to the parent when the leave animation completes. The parent can use this to unmount content or update its own state. */
33
- export declare const TransitionedOut: import("../../schema/index.js").CallableTaggedStruct<"TransitionedOut", {}>;
34
- export declare const OutMessage: S.Union<readonly [import("../../schema/index.js").CallableTaggedStruct<"StartedLeaveAnimating", {}>, import("../../schema/index.js").CallableTaggedStruct<"TransitionedOut", {}>]>;
35
- export type OutMessage = typeof OutMessage.Type;
36
- /** Configuration for creating an animation model with `init`. */
37
- export type InitConfig = Readonly<{
38
- id: string;
39
- isShowing?: boolean;
40
- }>;
41
- /** Creates an initial animation model from a config. Defaults to hidden. */
42
- export declare const init: (config: InitConfig) => Model;
43
- //# sourceMappingURL=schema.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/ui/animation/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAMpC,6EAA6E;AAC7E,eAAO,MAAM,eAAe,+FAM1B,CAAA;AACF,MAAM,MAAM,eAAe,GAAG,OAAO,eAAe,CAAC,IAAI,CAAA;AAIzD,kHAAkH;AAClH,eAAO,MAAM,KAAK;;;;EAIhB,CAAA;AAEF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,wFAAwF;AACxF,eAAO,MAAM,MAAM,oEAAc,CAAA;AACjC,uFAAuF;AACvF,eAAO,MAAM,GAAG,iEAAW,CAAA;AAC3B,mGAAmG;AACnG,eAAO,MAAM,sBAAsB,oFAA8B,CAAA;AACjE,oIAAoI;AACpI,eAAO,MAAM,cAAc,4EAAsB,CAAA;AAEjD,iEAAiE;AACjE,eAAO,MAAM,OAAO,EAAE,CAAC,CAAC,KAAK,CAC3B;IACE,OAAO,MAAM;IACb,OAAO,GAAG;IACV,OAAO,sBAAsB;IAC7B,OAAO,cAAc;CACtB,CAC+D,CAAA;AAClE,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAEzC,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AACvC,MAAM,MAAM,GAAG,GAAG,OAAO,GAAG,CAAC,IAAI,CAAA;AAIjC,0RAA0R;AAC1R,eAAO,MAAM,qBAAqB,mFAA6B,CAAA;AAC/D,iIAAiI;AACjI,eAAO,MAAM,eAAe,6EAAuB,CAAA;AAEnD,eAAO,MAAM,UAAU,oLAAoD,CAAA;AAC3E,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,IAAI,CAAA;AAI/C,iEAAiE;AACjE,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB,CAAC,CAAA;AAEF,4EAA4E;AAC5E,eAAO,MAAM,IAAI,GAAI,QAAQ,UAAU,KAAG,KAIxC,CAAA"}
@@ -1,41 +0,0 @@
1
- import { Schema as S } from 'effect';
2
- import { m } from '../../message/index.js';
3
- // TRANSITION STATE
4
- /** Schema for the animation lifecycle state, tracking enter/leave phases. */
5
- export const TransitionState = S.Literals([
6
- 'Idle',
7
- 'EnterStart',
8
- 'EnterAnimating',
9
- 'LeaveStart',
10
- 'LeaveAnimating',
11
- ]);
12
- // MODEL
13
- /** Schema for the animation component's state, tracking its unique ID, visibility intent, and lifecycle phase. */
14
- export const Model = S.Struct({
15
- id: S.String,
16
- isShowing: S.Boolean,
17
- transitionState: TransitionState,
18
- });
19
- // MESSAGE
20
- /** Sent when the animation should enter (become visible). Starts the enter sequence. */
21
- export const Showed = m('Showed');
22
- /** Sent when the animation should leave (become hidden). Starts the leave sequence. */
23
- export const Hid = m('Hid');
24
- /** Sent internally when a double-rAF completes, advancing the lifecycle to its animating phase. */
25
- export const AdvancedAnimationFrame = m('AdvancedAnimationFrame');
26
- /** Sent internally when all CSS animations on the element have settled. Covers both CSS transitions and CSS keyframe animations. */
27
- export const EndedAnimation = m('EndedAnimation');
28
- /** Union of all messages the animation component can produce. */
29
- export const Message = S.Union([Showed, Hid, AdvancedAnimationFrame, EndedAnimation]);
30
- // OUT MESSAGE
31
- /** Sent to the parent when the leave sequence advances to LeaveAnimating. The parent is responsible for providing the command that detects when the leave animation completes (e.g. WaitForAnimationSettled or a racing command). Use `defaultLeaveCommand` for the standard behavior. */
32
- export const StartedLeaveAnimating = m('StartedLeaveAnimating');
33
- /** Sent to the parent when the leave animation completes. The parent can use this to unmount content or update its own state. */
34
- export const TransitionedOut = m('TransitionedOut');
35
- export const OutMessage = S.Union([StartedLeaveAnimating, TransitionedOut]);
36
- /** Creates an initial animation model from a config. Defaults to hidden. */
37
- export const init = (config) => ({
38
- id: config.id,
39
- isShowing: config.isShowing ?? false,
40
- transitionState: 'Idle',
41
- });
@@ -1,24 +0,0 @@
1
- import { Effect, Option, Schema as S } from 'effect';
2
- import * as Command from '../../command/index.js';
3
- import { type Message, type Model, type OutMessage } from './schema.js';
4
- type UpdateReturn = readonly [
5
- Model,
6
- ReadonlyArray<Command.Command<Message>>,
7
- Option.Option<OutMessage>
8
- ];
9
- /** Advances the enter/leave lifecycle by waiting a double-rAF. */
10
- export declare const RequestFrame: Command.CommandDefinitionNoArgs<"RequestFrame", Effect.Effect<{
11
- readonly _tag: "AdvancedAnimationFrame";
12
- }, never, never>>;
13
- /** Waits for all CSS animations on the element to settle. Covers both CSS transitions and CSS keyframe animations. */
14
- export declare const WaitForAnimationSettled: Command.CommandDefinitionWithArgs<"WaitForAnimationSettled", {
15
- id: S.String;
16
- }, Effect.Effect<{
17
- readonly _tag: "EndedAnimation";
18
- }, never, never>>;
19
- /** Processes an animation message and returns the next model, commands, and optional OutMessage. */
20
- export declare const update: (model: Model, message: Message) => UpdateReturn;
21
- /** Creates the standard leave-phase command that waits for CSS animations on the element to settle. Use this when handling the `StartedLeaveAnimating` OutMessage for components that don't need custom leave behavior. */
22
- export declare const defaultLeaveCommand: (model: Model) => Command.Command<Message>;
23
- export {};
24
- //# sourceMappingURL=update.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../../src/ui/animation/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAc,MAAM,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAEhE,OAAO,KAAK,OAAO,MAAM,wBAAwB,CAAA;AAIjD,OAAO,EAGL,KAAK,OAAO,EACZ,KAAK,KAAK,EACV,KAAK,UAAU,EAGhB,MAAM,aAAa,CAAA;AAMpB,KAAK,YAAY,GAAG,SAAS;IAC3B,KAAK;IACL,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC;CAC1B,CAAA;AAGD,kEAAkE;AAClE,eAAO,MAAM,YAAY;;iBAGqC,CAAA;AAC9D,sHAAsH;AACtH,eAAO,MAAM,uBAAuB;;;;iBAQnC,CAAA;AAED,oGAAoG;AACpG,eAAO,MAAM,MAAM,GAAI,OAAO,KAAK,EAAE,SAAS,OAAO,KAAG,YAyEvD,CAAA;AAED,2NAA2N;AAC3N,eAAO,MAAM,mBAAmB,GAAI,OAAO,KAAK,KAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAC/B,CAAA"}
@@ -1,67 +0,0 @@
1
- import { Effect, Match as M, Option, Schema as S } from 'effect';
2
- import * as Command from '../../command/index.js';
3
- import * as Dom from '../../dom/index.js';
4
- import * as Render from '../../render/index.js';
5
- import { evo } from '../../struct/index.js';
6
- import { AdvancedAnimationFrame, EndedAnimation, StartedLeaveAnimating, TransitionedOut, } from './schema.js';
7
- // UPDATE
8
- const elementSelector = (id) => `#${id}`;
9
- const withUpdateReturn = M.withReturnType();
10
- /** Advances the enter/leave lifecycle by waiting a double-rAF. */
11
- export const RequestFrame = Command.define('RequestFrame', AdvancedAnimationFrame)(Render.afterPaint.pipe(Effect.as(AdvancedAnimationFrame())));
12
- /** Waits for all CSS animations on the element to settle. Covers both CSS transitions and CSS keyframe animations. */
13
- export const WaitForAnimationSettled = Command.define('WaitForAnimationSettled', { id: S.String }, EndedAnimation)(({ id }) => Dom.waitForAnimationSettled(elementSelector(id)).pipe(Effect.as(EndedAnimation())));
14
- /** Processes an animation message and returns the next model, commands, and optional OutMessage. */
15
- export const update = (model, message) => {
16
- const maybeNextFrame = RequestFrame();
17
- return M.value(message).pipe(withUpdateReturn, M.tagsExhaustive({
18
- Showed: () => {
19
- if (model.isShowing) {
20
- return [model, [], Option.none()];
21
- }
22
- return [
23
- evo(model, {
24
- isShowing: () => true,
25
- transitionState: () => 'EnterStart',
26
- }),
27
- [maybeNextFrame],
28
- Option.none(),
29
- ];
30
- },
31
- Hid: () => {
32
- const isLeaving = model.transitionState === 'LeaveStart' ||
33
- model.transitionState === 'LeaveAnimating';
34
- if (isLeaving || !model.isShowing) {
35
- return [model, [], Option.none()];
36
- }
37
- return [
38
- evo(model, {
39
- isShowing: () => false,
40
- transitionState: () => 'LeaveStart',
41
- }),
42
- [maybeNextFrame],
43
- Option.none(),
44
- ];
45
- },
46
- AdvancedAnimationFrame: () => M.value(model.transitionState).pipe(withUpdateReturn, M.when('EnterStart', () => [
47
- evo(model, { transitionState: () => 'EnterAnimating' }),
48
- [WaitForAnimationSettled({ id: model.id })],
49
- Option.none(),
50
- ]), M.when('LeaveStart', () => [
51
- evo(model, { transitionState: () => 'LeaveAnimating' }),
52
- [],
53
- Option.some(StartedLeaveAnimating()),
54
- ]), M.orElse(() => [model, [], Option.none()])),
55
- EndedAnimation: () => M.value(model.transitionState).pipe(withUpdateReturn, M.when('EnterAnimating', () => [
56
- evo(model, { transitionState: () => 'Idle' }),
57
- [],
58
- Option.none(),
59
- ]), M.when('LeaveAnimating', () => [
60
- evo(model, { transitionState: () => 'Idle' }),
61
- [],
62
- Option.some(TransitionedOut()),
63
- ]), M.orElse(() => [model, [], Option.none()])),
64
- }));
65
- };
66
- /** Creates the standard leave-phase command that waits for CSS animations on the element to settle. Use this when handling the `StartedLeaveAnimating` OutMessage for components that don't need custom leave behavior. */
67
- export const defaultLeaveCommand = (model) => WaitForAnimationSettled({ id: model.id });