foldkit 0.101.0 → 0.102.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 (208) hide show
  1. package/README.md +2 -1
  2. package/dist/canvas/view.d.ts +1 -1
  3. package/dist/canvas/view.d.ts.map +1 -1
  4. package/dist/canvas/view.js +5 -5
  5. package/dist/command/index.d.ts +71 -0
  6. package/dist/command/index.d.ts.map +1 -1
  7. package/dist/command/index.js +34 -1
  8. package/dist/command/public.d.ts +1 -1
  9. package/dist/command/public.d.ts.map +1 -1
  10. package/dist/command/public.js +1 -1
  11. package/dist/devTools/overlay.d.ts.map +1 -1
  12. package/dist/devTools/overlay.js +137 -110
  13. package/dist/dom/dom.d.ts +8 -11
  14. package/dist/dom/dom.d.ts.map +1 -1
  15. package/dist/dom/dom.js +8 -11
  16. package/dist/dom/elementMovement.d.ts +1 -3
  17. package/dist/dom/elementMovement.d.ts.map +1 -1
  18. package/dist/dom/elementMovement.js +1 -3
  19. package/dist/dom/inert.d.ts +2 -4
  20. package/dist/dom/inert.d.ts.map +1 -1
  21. package/dist/dom/inert.js +2 -4
  22. package/dist/dom/scrollLock.d.ts +2 -2
  23. package/dist/dom/scrollLock.js +2 -2
  24. package/dist/dom/waitForAnimation.d.ts +1 -1
  25. package/dist/dom/waitForAnimation.js +1 -1
  26. package/dist/html/boundary.d.ts +98 -0
  27. package/dist/html/boundary.d.ts.map +1 -0
  28. package/dist/html/boundary.js +176 -0
  29. package/dist/html/childAttribute.d.ts +44 -0
  30. package/dist/html/childAttribute.d.ts.map +1 -0
  31. package/dist/html/childAttribute.js +34 -0
  32. package/dist/html/index.d.ts +70 -23
  33. package/dist/html/index.d.ts.map +1 -1
  34. package/dist/html/index.js +639 -575
  35. package/dist/html/lazy.d.ts +12 -7
  36. package/dist/html/lazy.d.ts.map +1 -1
  37. package/dist/html/lazy.js +30 -11
  38. package/dist/html/public.d.ts +2 -2
  39. package/dist/html/public.d.ts.map +1 -1
  40. package/dist/html/public.js +1 -1
  41. package/dist/html/runtimeSingleton.d.ts +72 -0
  42. package/dist/html/runtimeSingleton.d.ts.map +1 -0
  43. package/dist/html/runtimeSingleton.js +112 -0
  44. package/dist/html/submodel.d.ts +98 -0
  45. package/dist/html/submodel.d.ts.map +1 -0
  46. package/dist/html/submodel.js +190 -0
  47. package/dist/index.d.ts +1 -0
  48. package/dist/index.d.ts.map +1 -1
  49. package/dist/index.js +1 -0
  50. package/dist/render/render.d.ts +1 -1
  51. package/dist/render/render.js +1 -1
  52. package/dist/runtime/messagePriority.d.ts +5 -1
  53. package/dist/runtime/messagePriority.d.ts.map +1 -1
  54. package/dist/runtime/messagePriority.js +25 -4
  55. package/dist/runtime/runtime.d.ts +1 -1
  56. package/dist/runtime/runtime.d.ts.map +1 -1
  57. package/dist/runtime/runtime.js +115 -61
  58. package/dist/submodel/public.d.ts +4 -0
  59. package/dist/submodel/public.d.ts.map +1 -0
  60. package/dist/submodel/public.js +1 -0
  61. package/dist/submodel/submodel.d.ts +32 -0
  62. package/dist/submodel/submodel.d.ts.map +1 -0
  63. package/dist/submodel/submodel.js +1 -0
  64. package/dist/test/apps/disabledButton.d.ts +4 -5
  65. package/dist/test/apps/disabledButton.d.ts.map +1 -1
  66. package/dist/test/apps/disabledButton.js +16 -16
  67. package/dist/test/scene.d.ts +8 -8
  68. package/dist/test/scene.d.ts.map +1 -1
  69. package/dist/test/scene.js +25 -13
  70. package/dist/test/story.d.ts +15 -8
  71. package/dist/test/story.d.ts.map +1 -1
  72. package/dist/test/story.js +21 -9
  73. package/dist/ui/animation/index.d.ts +30 -14
  74. package/dist/ui/animation/index.d.ts.map +1 -1
  75. package/dist/ui/animation/index.js +9 -19
  76. package/dist/ui/animation/public.d.ts +2 -2
  77. package/dist/ui/animation/public.d.ts.map +1 -1
  78. package/dist/ui/animation/public.js +1 -1
  79. package/dist/ui/calendar/index.d.ts +199 -84
  80. package/dist/ui/calendar/index.d.ts.map +1 -1
  81. package/dist/ui/calendar/index.js +129 -140
  82. package/dist/ui/calendar/public.d.ts +2 -2
  83. package/dist/ui/calendar/public.d.ts.map +1 -1
  84. package/dist/ui/calendar/public.js +1 -1
  85. package/dist/ui/checkbox/index.d.ts +93 -21
  86. package/dist/ui/checkbox/index.d.ts.map +1 -1
  87. package/dist/ui/checkbox/index.js +62 -33
  88. package/dist/ui/checkbox/public.d.ts +2 -2
  89. package/dist/ui/checkbox/public.d.ts.map +1 -1
  90. package/dist/ui/checkbox/public.js +1 -1
  91. package/dist/ui/combobox/multi.d.ts +35 -91
  92. package/dist/ui/combobox/multi.d.ts.map +1 -1
  93. package/dist/ui/combobox/multi.js +34 -17
  94. package/dist/ui/combobox/multiPublic.d.ts +2 -2
  95. package/dist/ui/combobox/multiPublic.d.ts.map +1 -1
  96. package/dist/ui/combobox/multiPublic.js +1 -1
  97. package/dist/ui/combobox/public.d.ts +3 -3
  98. package/dist/ui/combobox/public.d.ts.map +1 -1
  99. package/dist/ui/combobox/public.js +2 -2
  100. package/dist/ui/combobox/shared.d.ts +56 -31
  101. package/dist/ui/combobox/shared.d.ts.map +1 -1
  102. package/dist/ui/combobox/shared.js +333 -322
  103. package/dist/ui/combobox/single.d.ts +46 -93
  104. package/dist/ui/combobox/single.d.ts.map +1 -1
  105. package/dist/ui/combobox/single.js +44 -17
  106. package/dist/ui/datePicker/index.d.ts +256 -48
  107. package/dist/ui/datePicker/index.d.ts.map +1 -1
  108. package/dist/ui/datePicker/index.js +149 -104
  109. package/dist/ui/datePicker/public.d.ts +2 -2
  110. package/dist/ui/datePicker/public.d.ts.map +1 -1
  111. package/dist/ui/datePicker/public.js +1 -1
  112. package/dist/ui/dialog/index.d.ts +95 -39
  113. package/dist/ui/dialog/index.d.ts.map +1 -1
  114. package/dist/ui/dialog/index.js +71 -62
  115. package/dist/ui/dialog/public.d.ts +2 -2
  116. package/dist/ui/dialog/public.d.ts.map +1 -1
  117. package/dist/ui/dialog/public.js +1 -1
  118. package/dist/ui/disclosure/index.d.ts +71 -31
  119. package/dist/ui/disclosure/index.d.ts.map +1 -1
  120. package/dist/ui/disclosure/index.js +57 -62
  121. package/dist/ui/disclosure/public.d.ts +2 -2
  122. package/dist/ui/disclosure/public.d.ts.map +1 -1
  123. package/dist/ui/disclosure/public.js +1 -1
  124. package/dist/ui/dragAndDrop/index.d.ts +6 -6
  125. package/dist/ui/dragAndDrop/index.d.ts.map +1 -1
  126. package/dist/ui/dragAndDrop/index.js +7 -7
  127. package/dist/ui/dragAndDrop/public.d.ts +1 -1
  128. package/dist/ui/dragAndDrop/public.d.ts.map +1 -1
  129. package/dist/ui/dragAndDrop/public.js +1 -1
  130. package/dist/ui/fileDrop/index.d.ts +42 -46
  131. package/dist/ui/fileDrop/index.d.ts.map +1 -1
  132. package/dist/ui/fileDrop/index.js +30 -46
  133. package/dist/ui/fileDrop/public.d.ts +2 -2
  134. package/dist/ui/fileDrop/public.d.ts.map +1 -1
  135. package/dist/ui/fileDrop/public.js +1 -1
  136. package/dist/ui/listbox/multi.d.ts +39 -84
  137. package/dist/ui/listbox/multi.d.ts.map +1 -1
  138. package/dist/ui/listbox/multi.js +38 -20
  139. package/dist/ui/listbox/multiPublic.d.ts +2 -2
  140. package/dist/ui/listbox/multiPublic.d.ts.map +1 -1
  141. package/dist/ui/listbox/multiPublic.js +1 -1
  142. package/dist/ui/listbox/public.d.ts +3 -3
  143. package/dist/ui/listbox/public.d.ts.map +1 -1
  144. package/dist/ui/listbox/public.js +2 -2
  145. package/dist/ui/listbox/shared.d.ts +71 -30
  146. package/dist/ui/listbox/shared.d.ts.map +1 -1
  147. package/dist/ui/listbox/shared.js +319 -296
  148. package/dist/ui/listbox/single.d.ts +57 -85
  149. package/dist/ui/listbox/single.d.ts.map +1 -1
  150. package/dist/ui/listbox/single.js +48 -24
  151. package/dist/ui/menu/index.d.ts +80 -36
  152. package/dist/ui/menu/index.d.ts.map +1 -1
  153. package/dist/ui/menu/index.js +117 -86
  154. package/dist/ui/menu/public.d.ts +2 -2
  155. package/dist/ui/menu/public.d.ts.map +1 -1
  156. package/dist/ui/menu/public.js +1 -1
  157. package/dist/ui/popover/index.d.ts +117 -44
  158. package/dist/ui/popover/index.d.ts.map +1 -1
  159. package/dist/ui/popover/index.js +88 -101
  160. package/dist/ui/popover/public.d.ts +2 -2
  161. package/dist/ui/popover/public.d.ts.map +1 -1
  162. package/dist/ui/popover/public.js +1 -1
  163. package/dist/ui/radioGroup/index.d.ts +122 -45
  164. package/dist/ui/radioGroup/index.d.ts.map +1 -1
  165. package/dist/ui/radioGroup/index.js +111 -72
  166. package/dist/ui/radioGroup/public.d.ts +2 -2
  167. package/dist/ui/radioGroup/public.d.ts.map +1 -1
  168. package/dist/ui/radioGroup/public.js +1 -1
  169. package/dist/ui/slider/index.d.ts +72 -34
  170. package/dist/ui/slider/index.d.ts.map +1 -1
  171. package/dist/ui/slider/index.js +40 -49
  172. package/dist/ui/slider/public.d.ts +2 -2
  173. package/dist/ui/slider/public.d.ts.map +1 -1
  174. package/dist/ui/slider/public.js +1 -1
  175. package/dist/ui/switch/index.d.ts +74 -21
  176. package/dist/ui/switch/index.d.ts.map +1 -1
  177. package/dist/ui/switch/index.js +62 -33
  178. package/dist/ui/switch/public.d.ts +2 -2
  179. package/dist/ui/switch/public.d.ts.map +1 -1
  180. package/dist/ui/switch/public.js +1 -1
  181. package/dist/ui/tabs/index.d.ts +107 -45
  182. package/dist/ui/tabs/index.d.ts.map +1 -1
  183. package/dist/ui/tabs/index.js +99 -81
  184. package/dist/ui/tabs/public.d.ts +2 -2
  185. package/dist/ui/tabs/public.d.ts.map +1 -1
  186. package/dist/ui/tabs/public.js +1 -1
  187. package/dist/ui/toast/index.d.ts +93 -109
  188. package/dist/ui/toast/index.d.ts.map +1 -1
  189. package/dist/ui/toast/index.js +16 -29
  190. package/dist/ui/toast/schema.d.ts +15 -4
  191. package/dist/ui/toast/schema.d.ts.map +1 -1
  192. package/dist/ui/toast/schema.js +11 -4
  193. package/dist/ui/toast/update.d.ts +36 -18
  194. package/dist/ui/toast/update.d.ts.map +1 -1
  195. package/dist/ui/toast/update.js +33 -14
  196. package/dist/ui/tooltip/index.d.ts +94 -42
  197. package/dist/ui/tooltip/index.d.ts.map +1 -1
  198. package/dist/ui/tooltip/index.js +64 -73
  199. package/dist/ui/tooltip/public.d.ts +2 -2
  200. package/dist/ui/tooltip/public.d.ts.map +1 -1
  201. package/dist/ui/tooltip/public.js +1 -1
  202. package/dist/ui/virtualList/index.d.ts +18 -41
  203. package/dist/ui/virtualList/index.d.ts.map +1 -1
  204. package/dist/ui/virtualList/index.js +17 -37
  205. package/dist/ui/virtualList/public.d.ts +2 -2
  206. package/dist/ui/virtualList/public.d.ts.map +1 -1
  207. package/dist/ui/virtualList/public.js +1 -1
  208. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  import { Effect, Match as M, Option, Schema as S } from 'effect';
2
2
  import * as Command from '../../command/index.js';
3
3
  import * as Dom from '../../dom/index.js';
4
- import { createLazy, html, } from '../../html/index.js';
4
+ import { childAttributes, defineView, html, } from '../../html/index.js';
5
5
  import { m } from '../../message/index.js';
6
6
  import { evo } from '../../struct/index.js';
7
7
  // NOTE: Animation imports are split across schema + update to avoid a circular
@@ -20,12 +20,12 @@ export const Model = S.Struct({
20
20
  });
21
21
  // MESSAGE
22
22
  /** Sent when the dialog should open. Triggers the showModal command. */
23
- export const Opened = m('Opened');
24
- /** Sent when the dialog should close (Escape key, backdrop click, or programmatic). Triggers the closeModal command. */
25
- export const Closed = m('Closed');
26
- /** Sent when the show-dialog command completes (scroll lock + showModal). */
23
+ export const RequestedOpen = m('RequestedOpen');
24
+ /** Sent when the dialog should close (Escape key, backdrop click, or programmatic). */
25
+ export const RequestedClose = m('RequestedClose');
26
+ /** Sent when the show-dialog command completes. */
27
27
  export const CompletedShowDialog = m('CompletedShowDialog');
28
- /** Sent when the close-dialog command completes (closeModal + scroll unlock). */
28
+ /** Sent when the close-dialog command completes. */
29
29
  export const CompletedCloseDialog = m('CompletedCloseDialog');
30
30
  /** Wraps an Animation submodel message for delegation. */
31
31
  export const GotAnimationMessage = m('GotAnimationMessage', {
@@ -33,12 +33,25 @@ export const GotAnimationMessage = m('GotAnimationMessage', {
33
33
  });
34
34
  /** Union of all messages the dialog component can produce. */
35
35
  export const Message = S.Union([
36
- Opened,
37
- Closed,
36
+ RequestedOpen,
37
+ RequestedClose,
38
38
  CompletedShowDialog,
39
39
  CompletedCloseDialog,
40
40
  GotAnimationMessage,
41
41
  ]);
42
+ // OUT MESSAGE
43
+ /** Sent once the dialog has transitioned to open. Fires after `update`
44
+ * has processed `RequestedOpen` and `isOpen` reflects the new state.
45
+ * Programmatic `Dialog.open` on an already-open model is a no-op that
46
+ * does not re-emit. */
47
+ export const Opened = m('Opened');
48
+ /** Sent once the dialog has transitioned to closed. Programmatic
49
+ * `Dialog.close` on an already-closed model is a no-op that does not
50
+ * re-emit; calling close while a leave animation is in progress is
51
+ * also a no-op. */
52
+ export const Closed = m('Closed');
53
+ /** Union of out-messages the dialog component can produce. */
54
+ export const OutMessage = S.Union([Opened, Closed]);
42
55
  /** Creates an initial dialog model from a config. Defaults to closed and non-animated. */
43
56
  export const init = (config) => ({
44
57
  id: config.id,
@@ -60,15 +73,15 @@ export const ShowDialog = Command.define('ShowDialog', { id: S.String, maybeFocu
60
73
  }))), Effect.ignore, Effect.as(CompletedShowDialog())));
61
74
  /** Calls `close()` on the native dialog element and unlocks page scroll. */
62
75
  export const CloseDialog = Command.define('CloseDialog', { id: S.String }, CompletedCloseDialog)(({ id }) => Dom.closeModal(dialogSelector(id)).pipe(Effect.andThen(() => Dom.unlockScroll), Effect.ignore, Effect.as(CompletedCloseDialog())));
63
- const toParentMessage = (message) => GotAnimationMessage({ message });
76
+ const wrapAnimationMessage = (message) => GotAnimationMessage({ message });
64
77
  const delegateToAnimation = (model, animationMessage) => {
65
78
  const [nextAnimation, animationCommands, maybeOutMessage] = animationUpdate(model.animation, animationMessage);
66
- const mappedCommands = animationCommands.map(Command.mapEffect(Effect.map(toParentMessage)));
79
+ const mappedCommands = Command.mapMessages(animationCommands, wrapAnimationMessage);
67
80
  const additionalCommands = Option.match(maybeOutMessage, {
68
81
  onNone: () => [],
69
82
  onSome: M.type().pipe(M.tagsExhaustive({
70
83
  StartedLeaveAnimating: () => [
71
- Command.mapEffect(animationDefaultLeaveCommand(nextAnimation), Effect.map(toParentMessage)),
84
+ Command.mapMessage(animationDefaultLeaveCommand(nextAnimation), wrapAnimationMessage),
72
85
  ],
73
86
  TransitionedOut: () => [CloseDialog({ id: model.id })],
74
87
  })),
@@ -76,58 +89,73 @@ const delegateToAnimation = (model, animationMessage) => {
76
89
  return [
77
90
  evo(model, { animation: () => nextAnimation }),
78
91
  [...mappedCommands, ...additionalCommands],
92
+ Option.none(),
79
93
  ];
80
94
  };
81
95
  /** Processes a dialog message and returns the next model and commands. */
82
96
  export const update = (model, message) => M.value(message).pipe(withUpdateReturn, M.tagsExhaustive({
83
- Opened: () => {
97
+ RequestedOpen: () => {
98
+ const wasClosed = !model.isOpen;
84
99
  const maybeShow = Option.liftPredicate(ShowDialog({
85
100
  id: model.id,
86
101
  maybeFocusSelector: model.maybeFocusSelector,
87
- }), () => !model.isOpen);
102
+ }), () => wasClosed);
103
+ const maybeOutMessage = wasClosed
104
+ ? Option.some(Opened())
105
+ : Option.none();
88
106
  if (model.isAnimated) {
89
107
  const [nextModel, animationCommands] = delegateToAnimation(model, AnimationShowed());
90
108
  return [
91
109
  evo(nextModel, { isOpen: () => true }),
92
110
  [...Option.toArray(maybeShow), ...animationCommands],
111
+ maybeOutMessage,
93
112
  ];
94
113
  }
95
- return [evo(model, { isOpen: () => true }), Option.toArray(maybeShow)];
114
+ return [
115
+ evo(model, { isOpen: () => true }),
116
+ Option.toArray(maybeShow),
117
+ maybeOutMessage,
118
+ ];
96
119
  },
97
- Closed: () => {
120
+ RequestedClose: () => {
98
121
  const { transitionState } = model.animation;
99
122
  const isLeaving = transitionState === 'LeaveStart' ||
100
123
  transitionState === 'LeaveAnimating';
101
124
  if (isLeaving) {
102
- return [model, []];
125
+ return [model, [], Option.none()];
103
126
  }
127
+ const wasOpen = model.isOpen;
128
+ const maybeOutMessage = wasOpen ? Option.some(Closed()) : Option.none();
104
129
  if (model.isAnimated) {
105
130
  const [nextModel, animationCommands] = delegateToAnimation(evo(model, { isOpen: () => false }), AnimationHid());
106
- return [nextModel, animationCommands];
131
+ return [nextModel, animationCommands, maybeOutMessage];
107
132
  }
108
- const maybeClose = Option.liftPredicate(CloseDialog({ id: model.id }), () => model.isOpen);
109
- return [evo(model, { isOpen: () => false }), Option.toArray(maybeClose)];
133
+ const maybeClose = Option.liftPredicate(CloseDialog({ id: model.id }), () => wasOpen);
134
+ return [
135
+ evo(model, { isOpen: () => false }),
136
+ Option.toArray(maybeClose),
137
+ maybeOutMessage,
138
+ ];
110
139
  },
111
140
  GotAnimationMessage: ({ message: animationMessage }) => delegateToAnimation(model, animationMessage),
112
- CompletedShowDialog: () => [model, []],
113
- CompletedCloseDialog: () => [model, []],
141
+ CompletedShowDialog: () => [model, [], Option.none()],
142
+ CompletedCloseDialog: () => [model, [], Option.none()],
114
143
  }));
144
+ /** Programmatically opens the dialog. */
145
+ export const open = (model) => update(model, RequestedOpen());
146
+ /** Programmatically closes the dialog. */
147
+ export const close = (model) => update(model, RequestedClose());
115
148
  // VIEW
116
149
  /** Returns the ID used for `aria-labelledby` on the dialog. Apply this to your title element. */
117
150
  export const titleId = (model) => `${model.id}-title`;
118
151
  /** Returns the ID used for `aria-describedby` on the dialog. Apply this to your description element. */
119
152
  export const descriptionId = (model) => `${model.id}-description`;
120
- /** Programmatically opens the dialog, updating the model and returning
121
- * show commands. Use this in domain-event handlers to open the dialog. */
122
- export const open = (model) => update(model, Opened());
123
- /** Programmatically closes the dialog, updating the model and returning
124
- * close commands. Use this in domain-event handlers when the dialog uses `onClosed`. */
125
- export const close = (model) => update(model, Closed());
126
- /** Renders a headless dialog component backed by the native `<dialog>` element with `showModal()`. */
127
- export const view = (config) => {
153
+ /** Renders a headless dialog component backed by the native `<dialog>`
154
+ * element with `showModal()`. */
155
+ export const view = defineView((model, viewInputs) => {
128
156
  const h = html();
129
- const { model: { id, isOpen, animation: { transitionState }, }, toParentMessage, onClosed, panelContent, panelClassName, panelAttributes = [], backdropClassName, backdropAttributes = [], className, attributes = [], } = config;
130
- const dispatchClosed = () => onClosed ? onClosed() : toParentMessage(Closed());
157
+ const { id, isOpen, animation: { transitionState }, } = model;
158
+ const { toView } = viewInputs;
131
159
  const isLeaving = transitionState === 'LeaveStart' || transitionState === 'LeaveAnimating';
132
160
  const isVisible = isOpen || isLeaving;
133
161
  const animationAttributes = M.value(transitionState).pipe(M.when('EnterStart', () => [
@@ -149,7 +177,7 @@ export const view = (config) => {
149
177
  h.Id(id),
150
178
  h.AriaLabelledBy(`${id}-title`),
151
179
  h.AriaDescribedBy(`${id}-description`),
152
- h.OnCancel(dispatchClosed()),
180
+ h.OnCancel(RequestedClose()),
153
181
  h.Open(isVisible),
154
182
  h.Style({
155
183
  width: '100%',
@@ -164,36 +192,17 @@ export const view = (config) => {
164
192
  : {}),
165
193
  }),
166
194
  ...(isVisible ? [h.DataAttribute('open', '')] : []),
167
- ...(className ? [h.Class(className)] : []),
168
- ...attributes,
169
195
  ];
170
- const backdrop = h.keyed('div')(`${id}-backdrop`, [
196
+ const backdropAttributes = [
171
197
  h.Style({ minHeight: '100vh' }),
172
198
  ...animationAttributes,
173
- ...(isLeaving ? [] : [h.OnClick(dispatchClosed())]),
174
- ...(backdropClassName ? [h.Class(backdropClassName)] : []),
175
- ...backdropAttributes,
176
- ], []);
177
- const panel = h.keyed('div')(`${id}-panel`, [
178
- h.Id(`${id}-panel`),
179
- ...animationAttributes,
180
- ...(panelClassName ? [h.Class(panelClassName)] : []),
181
- ...panelAttributes,
182
- ], [panelContent]);
183
- const content = isVisible ? [backdrop, panel] : [];
184
- return h.keyed('dialog')(id, dialogAttributes, content);
185
- };
186
- /** Creates a memoized dialog view. Static config (className, panelClassName,
187
- * etc.) is captured in a closure. Dynamic fields — `model`, `toParentMessage`,
188
- * and `panelContent` — are compared by reference per render via `createLazy`.
189
- * When any of them change, the view re-renders; otherwise the cached VNode is
190
- * reused and snabbdom skips the entire subtree. */
191
- export const lazy = (staticConfig) => {
192
- const lazyView = createLazy();
193
- return (model, toParentMessage, panelContent) => lazyView((currentModel, currentToParentMessage, currentPanelContent) => view({
194
- ...staticConfig,
195
- model: currentModel,
196
- toParentMessage: currentToParentMessage,
197
- panelContent: currentPanelContent,
198
- }), [model, toParentMessage, panelContent]);
199
- };
199
+ ...(isLeaving ? [] : [h.OnClick(RequestedClose())]),
200
+ ];
201
+ const panelAttributes = [h.Id(`${id}-panel`), ...animationAttributes];
202
+ return toView({
203
+ dialog: childAttributes(dialogAttributes),
204
+ backdrop: childAttributes(backdropAttributes),
205
+ panel: childAttributes(panelAttributes),
206
+ isVisible,
207
+ });
208
+ });
@@ -1,3 +1,3 @@
1
- export { init, update, open, close, view, lazy, titleId, descriptionId, Model, Message, Opened, Closed, CompletedShowDialog, CompletedCloseDialog, GotAnimationMessage, ShowDialog, CloseDialog, } from './index.js';
2
- export type { InitConfig, ViewConfig } from './index.js';
1
+ export { init, update, open, close, view, titleId, descriptionId, Model, Message, OutMessage, Opened, Closed, RequestedOpen, RequestedClose, CompletedShowDialog, CompletedCloseDialog, GotAnimationMessage, ShowDialog, CloseDialog, } from './index.js';
2
+ export type { InitConfig, ViewInputs, RenderInfo } from './index.js';
3
3
  //# sourceMappingURL=public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/ui/dialog/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,MAAM,EACN,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,OAAO,EACP,aAAa,EACb,KAAK,EACL,OAAO,EACP,MAAM,EACN,MAAM,EACN,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,UAAU,EACV,WAAW,GACZ,MAAM,YAAY,CAAA;AAEnB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/ui/dialog/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,MAAM,EACN,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,OAAO,EACP,aAAa,EACb,KAAK,EACL,OAAO,EACP,UAAU,EACV,MAAM,EACN,MAAM,EACN,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,UAAU,EACV,WAAW,GACZ,MAAM,YAAY,CAAA;AAEnB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA"}
@@ -1 +1 @@
1
- export { init, update, open, close, view, lazy, titleId, descriptionId, Model, Message, Opened, Closed, CompletedShowDialog, CompletedCloseDialog, GotAnimationMessage, ShowDialog, CloseDialog, } from './index.js';
1
+ export { init, update, open, close, view, titleId, descriptionId, Model, Message, OutMessage, Opened, Closed, RequestedOpen, RequestedClose, CompletedShowDialog, CompletedCloseDialog, GotAnimationMessage, ShowDialog, CloseDialog, } from './index.js';
@@ -1,6 +1,7 @@
1
- import { Effect, Schema as S } from 'effect';
1
+ import { Effect, Option, Schema as S } from 'effect';
2
2
  import * as Command from '../../command/index.js';
3
- import { type Attribute, type Html, type TagName } from '../../html/index.js';
3
+ import { type ChildAttribute, type Html } from '../../html/index.js';
4
+ import type { Reflect } from '../../submodel/submodel.js';
4
5
  /** Schema for the disclosure component's state, tracking its unique ID and open/closed status. */
5
6
  export declare const Model: S.Struct<{
6
7
  readonly id: S.String;
@@ -23,6 +24,15 @@ export type Toggled = typeof Toggled.Type;
23
24
  export type Closed = typeof Closed.Type;
24
25
  export type CompletedFocusButton = typeof CompletedFocusButton.Type;
25
26
  export type Message = typeof Message.Type;
27
+ /** Sent to the parent each time the disclosure toggles. The new open state is available on the next model snapshot; this OutMessage signals only that the transition happened. Consumers typically use this for analytics, lazy content loading, or saving open/closed state to a store. */
28
+ export declare const ToggledOpenState: import("../../schema/index.js").CallableTaggedStruct<"ToggledOpenState", {
29
+ isOpen: S.Boolean;
30
+ }>;
31
+ export declare const OutMessage: S.Union<readonly [import("../../schema/index.js").CallableTaggedStruct<"ToggledOpenState", {
32
+ isOpen: S.Boolean;
33
+ }>]>;
34
+ export type OutMessage = typeof OutMessage.Type;
35
+ export type ToggledOpenState = typeof ToggledOpenState.Type;
26
36
  /** Configuration for creating a disclosure model with `init`. */
27
37
  export type InitConfig = Readonly<{
28
38
  id: string;
@@ -36,35 +46,65 @@ export declare const FocusButton: Command.CommandDefinitionWithArgs<"FocusButton
36
46
  }, Effect.Effect<{
37
47
  readonly _tag: "CompletedFocusButton";
38
48
  }, never, never>>;
39
- /** Processes a disclosure message and returns the next model and commands. */
40
- export declare const update: (model: Model, message: Message) => readonly [Model, ReadonlyArray<Command.Command<Message>>];
41
- /** Configuration for rendering a disclosure with `view`. */
42
- export type ViewConfig<ParentMessage> = Readonly<{
43
- model: Model;
44
- toParentMessage: (message: Toggled | Closed | CompletedFocusButton) => ParentMessage;
45
- onToggled?: () => ParentMessage;
46
- buttonClassName?: string;
47
- buttonAttributes?: ReadonlyArray<Attribute<ParentMessage>>;
48
- buttonContent: Html;
49
- panelClassName?: string;
50
- panelAttributes?: ReadonlyArray<Attribute<ParentMessage>>;
51
- panelContent: Html;
52
- isDisabled?: boolean;
53
- persistPanel?: boolean;
54
- buttonElement?: TagName;
55
- panelElement?: TagName;
56
- className?: string;
57
- attributes?: ReadonlyArray<Attribute<ParentMessage>>;
58
- }>;
49
+ type UpdateReturn = readonly [
50
+ Model,
51
+ ReadonlyArray<Command.Command<Message>>,
52
+ Option.Option<OutMessage>
53
+ ];
54
+ /** Processes a disclosure message and returns the next model, commands, and optional OutMessage. */
55
+ export declare const update: (model: Model, message: Message) => UpdateReturn;
59
56
  /** Programmatically toggles the disclosure, updating the model and returning
60
- * focus commands. Use this in domain-event handlers when the disclosure uses `onToggled`. */
61
- export declare const toggle: (model: Model) => readonly [Model, ReadonlyArray<Command.Command<Message>>];
57
+ * focus commands plus a `ToggledOpenState` OutMessage. */
58
+ export declare const toggle: (model: Model) => UpdateReturn;
62
59
  /** Programmatically closes the disclosure, updating the model and returning
63
- * focus commands. Use this in domain-event handlers to close the disclosure. */
64
- export declare const close: (model: Model) => readonly [Model, ReadonlyArray<Command.Command<Message>>];
65
- /** Renders a headless disclosure component with accessible ARIA attributes and keyboard support. */
66
- export declare const view: <ParentMessage>(config: ViewConfig<ParentMessage>) => Html;
67
- /** Creates a memoized disclosure view. Static config is captured in a closure;
68
- * only `model` and `toParentMessage` are compared per render via `createLazy`. */
69
- export declare const lazy: <ParentMessage>(staticConfig: Omit<ViewConfig<ParentMessage>, "model" | "toParentMessage" | "onToggled">) => ((model: Model, toParentMessage: ViewConfig<ParentMessage>["toParentMessage"]) => Html);
60
+ * focus commands plus a `ToggledOpenState` OutMessage when it was open. */
61
+ export declare const close: (model: Model) => UpdateReturn;
62
+ /** Reflects an externally-sourced open state onto the model without
63
+ * emitting an OutMessage or running the focus command. Use this to mirror
64
+ * external truth (restored storage, a deep link) onto the disclosure.
65
+ * Contrast with `toggle`/`close`, which represent user or programmatic
66
+ * *choices* and emit `ToggledOpenState`. Returns the model directly
67
+ * because it produces no commands and no OutMessage. */
68
+ export declare const reflectOpenState: Reflect<Model, boolean>;
69
+ /** Attribute groups the disclosure component provides to the consumer's
70
+ * `toView` callback. The consumer composes the button + panel layout
71
+ * themselves using these bundles. */
72
+ export type DisclosureAttributes = Readonly<{
73
+ button: ReadonlyArray<ChildAttribute>;
74
+ panel: ReadonlyArray<ChildAttribute>;
75
+ }>;
76
+ /** Per-render view inputs passed to `view` via `h.submodel`'s `viewInputs` field.
77
+ *
78
+ * - `toView`: receives the disclosure's `button` and `panel` attribute
79
+ * bundles and returns the composed layout. The consumer reads
80
+ * `isOpen` from their parent model when they need to render
81
+ * conditionally on it.
82
+ * - `isDisabled`: when true, the button is not clickable, gets
83
+ * `aria-disabled` and a `data-disabled` attribute. */
84
+ export type ViewInputs = Readonly<{
85
+ toView: (attributes: DisclosureAttributes) => Html;
86
+ isDisabled?: boolean;
87
+ }>;
88
+ /** Renders a headless disclosure component with accessible ARIA
89
+ * attributes and keyboard support. The consumer composes the layout
90
+ * through the `toView` slot, spreading the published `button` and
91
+ * `panel` attribute bundles onto their own elements.
92
+ *
93
+ * Designed to be embedded via `h.submodel`. The consumer reacts to
94
+ * toggle events by pattern-matching the `ToggledOpenState` OutMessage
95
+ * from the third element of `update`'s return tuple. */
96
+ export declare const view: import("../../html/submodel.js").SubmodelView<{
97
+ readonly id: string;
98
+ readonly isOpen: boolean;
99
+ }, {
100
+ readonly _tag: "Closed";
101
+ } | {
102
+ readonly _tag: "CompletedFocusButton";
103
+ } | {
104
+ readonly _tag: "Toggled";
105
+ }, Readonly<{
106
+ toView: (attributes: DisclosureAttributes) => Html;
107
+ isDisabled?: boolean;
108
+ }>>;
109
+ export {};
70
110
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/disclosure/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/disclosure/index.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,7 @@
1
- import { Effect, Match as M, Option, Schema as S } from 'effect';
1
+ import { Effect, Function, Match as M, Option, Schema as S } from 'effect';
2
2
  import * as Command from '../../command/index.js';
3
3
  import * as Dom from '../../dom/index.js';
4
- import { createLazy, html, } from '../../html/index.js';
4
+ import { childAttributes, defineView, html, } from '../../html/index.js';
5
5
  import { m } from '../../message/index.js';
6
6
  import { evo } from '../../struct/index.js';
7
7
  // MODEL
@@ -19,6 +19,10 @@ export const Closed = m('Closed');
19
19
  export const CompletedFocusButton = m('CompletedFocusButton');
20
20
  /** Union of all messages the disclosure component can produce. */
21
21
  export const Message = S.Union([Toggled, Closed, CompletedFocusButton]);
22
+ // OUT MESSAGE
23
+ /** Sent to the parent each time the disclosure toggles. The new open state is available on the next model snapshot; this OutMessage signals only that the transition happened. Consumers typically use this for analytics, lazy content loading, or saving open/closed state to a store. */
24
+ export const ToggledOpenState = m('ToggledOpenState', { isOpen: S.Boolean });
25
+ export const OutMessage = S.Union([ToggledOpenState]);
22
26
  /** Creates an initial disclosure model from a config. Defaults to closed. */
23
27
  export const init = (config) => ({
24
28
  id: config.id,
@@ -30,86 +34,77 @@ const buttonSelector = (id) => `#${CSS.escape(buttonId(id))}`;
30
34
  const panelId = (id) => `${id}-panel`;
31
35
  /** Moves focus to the disclosure's toggle button. */
32
36
  export const FocusButton = Command.define('FocusButton', { id: S.String }, CompletedFocusButton)(({ id }) => Dom.focus(buttonSelector(id)).pipe(Effect.ignore, Effect.as(CompletedFocusButton())));
33
- /** Processes a disclosure message and returns the next model and commands. */
34
- export const update = (model, message) => M.value(message).pipe(M.withReturnType(), M.tagsExhaustive({
37
+ const withUpdateReturn = M.withReturnType();
38
+ /** Processes a disclosure message and returns the next model, commands, and optional OutMessage. */
39
+ export const update = (model, message) => M.value(message).pipe(withUpdateReturn, M.tagsExhaustive({
35
40
  Toggled: () => {
41
+ const nextIsOpen = !model.isOpen;
36
42
  const maybeFocus = Option.liftPredicate(FocusButton({ id: model.id }), () => model.isOpen);
37
43
  return [
38
- evo(model, { isOpen: () => !model.isOpen }),
44
+ evo(model, { isOpen: () => nextIsOpen }),
39
45
  Option.toArray(maybeFocus),
46
+ Option.some(ToggledOpenState({ isOpen: nextIsOpen })),
40
47
  ];
41
48
  },
42
49
  Closed: () => {
50
+ if (!model.isOpen) {
51
+ return [model, [], Option.none()];
52
+ }
43
53
  const maybeFocus = Option.liftPredicate(FocusButton({ id: model.id }), () => model.isOpen);
44
- return [evo(model, { isOpen: () => false }), Option.toArray(maybeFocus)];
54
+ return [
55
+ evo(model, { isOpen: () => false }),
56
+ Option.toArray(maybeFocus),
57
+ Option.some(ToggledOpenState({ isOpen: false })),
58
+ ];
45
59
  },
46
- CompletedFocusButton: () => [model, []],
60
+ CompletedFocusButton: () => [model, [], Option.none()],
47
61
  }));
48
62
  /** Programmatically toggles the disclosure, updating the model and returning
49
- * focus commands. Use this in domain-event handlers when the disclosure uses `onToggled`. */
63
+ * focus commands plus a `ToggledOpenState` OutMessage. */
50
64
  export const toggle = (model) => update(model, Toggled());
51
65
  /** Programmatically closes the disclosure, updating the model and returning
52
- * focus commands. Use this in domain-event handlers to close the disclosure. */
66
+ * focus commands plus a `ToggledOpenState` OutMessage when it was open. */
53
67
  export const close = (model) => update(model, Closed());
54
- /** Renders a headless disclosure component with accessible ARIA attributes and keyboard support. */
55
- export const view = (config) => {
68
+ /** Reflects an externally-sourced open state onto the model without
69
+ * emitting an OutMessage or running the focus command. Use this to mirror
70
+ * external truth (restored storage, a deep link) onto the disclosure.
71
+ * Contrast with `toggle`/`close`, which represent user or programmatic
72
+ * *choices* and emit `ToggledOpenState`. Returns the model directly
73
+ * because it produces no commands and no OutMessage. */
74
+ export const reflectOpenState = Function.dual(2, (model, isOpen) => evo(model, { isOpen: () => isOpen }));
75
+ /** Renders a headless disclosure component with accessible ARIA
76
+ * attributes and keyboard support. The consumer composes the layout
77
+ * through the `toView` slot, spreading the published `button` and
78
+ * `panel` attribute bundles onto their own elements.
79
+ *
80
+ * Designed to be embedded via `h.submodel`. The consumer reacts to
81
+ * toggle events by pattern-matching the `ToggledOpenState` OutMessage
82
+ * from the third element of `update`'s return tuple. */
83
+ export const view = defineView((model, viewInputs) => {
56
84
  const h = html();
57
- const { model: { id, isOpen }, toParentMessage, onToggled, buttonClassName, buttonAttributes = [], buttonContent, panelClassName, panelAttributes = [], panelContent, isDisabled, persistPanel, buttonElement = 'button', panelElement = 'div', className, attributes = [], } = config;
58
- const dispatchToggled = () => onToggled ? onToggled() : toParentMessage(Toggled());
59
- const isNativeButton = buttonElement === 'button';
60
- const handleKeyDown = (key) => M.value(key).pipe(M.whenOr('Enter', ' ', () => Option.some(dispatchToggled())), M.orElse(() => Option.none()));
61
- const disabledAttributes = [
62
- h.Disabled(true),
63
- h.AriaDisabled(true),
64
- h.DataAttribute('disabled', ''),
65
- ];
66
- const interactionAttributes = isDisabled
67
- ? disabledAttributes
68
- : [
69
- h.OnClick(dispatchToggled()),
70
- ...(!isNativeButton ? [h.OnKeyDownPreventDefault(handleKeyDown)] : []),
71
- ];
72
- const resolvedButtonAttributes = [
85
+ const { id, isOpen } = model;
86
+ const { toView, isDisabled = false } = viewInputs;
87
+ const handleKeyDown = (key) => M.value(key).pipe(M.whenOr('Enter', ' ', () => Option.some(Toggled())), M.orElse(() => Option.none()));
88
+ const disabledAttributes = isDisabled
89
+ ? [h.AriaDisabled(true), h.DataAttribute('disabled', '')]
90
+ : [];
91
+ const buttonAttributes = [
73
92
  h.Id(buttonId(id)),
74
93
  h.AriaExpanded(isOpen),
75
94
  h.AriaControls(panelId(id)),
76
- ...(isNativeButton ? [h.Type('button')] : [h.Tabindex(0)]),
95
+ h.Tabindex(0),
77
96
  ...(isOpen ? [h.DataAttribute('open', '')] : []),
78
- ...interactionAttributes,
79
- ...(buttonClassName ? [h.Class(buttonClassName)] : []),
80
- ...buttonAttributes,
97
+ ...disabledAttributes,
98
+ ...(isDisabled
99
+ ? []
100
+ : [h.OnClick(Toggled()), h.OnKeyDownPreventDefault(handleKeyDown)]),
81
101
  ];
82
- const resolvedPanelAttributes = [
102
+ const panelAttributes = [
83
103
  h.Id(panelId(id)),
84
104
  ...(isOpen ? [h.DataAttribute('open', '')] : []),
85
- ...(panelClassName ? [h.Class(panelClassName)] : []),
86
- ...panelAttributes,
87
105
  ];
88
- const persistedPanel = h.keyed(panelElement)(panelId(id), [
89
- ...resolvedPanelAttributes,
90
- h.Hidden(!isOpen),
91
- ...(isOpen ? [] : [h.Style({ display: 'none' })]),
92
- ], [panelContent]);
93
- const activePanel = isOpen
94
- ? h.keyed(panelElement)(panelId(id), resolvedPanelAttributes, [
95
- panelContent,
96
- ])
97
- : h.empty;
98
- const panel = persistPanel ? persistedPanel : activePanel;
99
- return h.div([...(className ? [h.Class(className)] : []), ...attributes], [
100
- h.keyed(buttonElement)(buttonId(id), resolvedButtonAttributes, [
101
- buttonContent,
102
- ]),
103
- panel,
104
- ]);
105
- };
106
- /** Creates a memoized disclosure view. Static config is captured in a closure;
107
- * only `model` and `toParentMessage` are compared per render via `createLazy`. */
108
- export const lazy = (staticConfig) => {
109
- const lazyView = createLazy();
110
- return (model, toParentMessage) => lazyView((currentModel, currentToParentMessage) => view({
111
- ...staticConfig,
112
- model: currentModel,
113
- toParentMessage: currentToParentMessage,
114
- }), [model, toParentMessage]);
115
- };
106
+ return toView({
107
+ button: childAttributes(buttonAttributes),
108
+ panel: childAttributes(panelAttributes),
109
+ });
110
+ });
@@ -1,3 +1,3 @@
1
- export { init, update, toggle, close, view, lazy, Model, Message, Toggled, Closed, CompletedFocusButton, FocusButton, } from './index.js';
2
- export type { InitConfig, ViewConfig } from './index.js';
1
+ export { init, update, toggle, close, reflectOpenState, view, Model, Message, OutMessage, ToggledOpenState, Closed, CompletedFocusButton, FocusButton, } from './index.js';
2
+ export type { InitConfig, ViewInputs, DisclosureAttributes, Toggled, } from './index.js';
3
3
  //# sourceMappingURL=public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/ui/disclosure/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,MAAM,EACN,MAAM,EACN,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,OAAO,EACP,OAAO,EACP,MAAM,EACN,oBAAoB,EACpB,WAAW,GACZ,MAAM,YAAY,CAAA;AAEnB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/ui/disclosure/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,MAAM,EACN,MAAM,EACN,KAAK,EACL,gBAAgB,EAChB,IAAI,EACJ,KAAK,EACL,OAAO,EACP,UAAU,EACV,gBAAgB,EAChB,MAAM,EACN,oBAAoB,EACpB,WAAW,GACZ,MAAM,YAAY,CAAA;AAEnB,YAAY,EACV,UAAU,EACV,UAAU,EACV,oBAAoB,EACpB,OAAO,GACR,MAAM,YAAY,CAAA"}
@@ -1 +1 @@
1
- export { init, update, toggle, close, view, lazy, Model, Message, Toggled, Closed, CompletedFocusButton, FocusButton, } from './index.js';
1
+ export { init, update, toggle, close, reflectOpenState, view, Model, Message, OutMessage, ToggledOpenState, Closed, CompletedFocusButton, FocusButton, } from './index.js';
@@ -84,7 +84,7 @@ export declare const PressedArrowKey: import("../../schema/index.js").CallableTa
84
84
  direction: S.Literals<readonly ["Up", "Down", "Left", "Right", "NextContainer", "PreviousContainer"]>;
85
85
  }>;
86
86
  /** An animation frame fired during auto-scroll. */
87
- export declare const CompletedAutoScroll: import("../../schema/index.js").CallableTaggedStruct<"CompletedAutoScroll", {}>;
87
+ export declare const AdvancedAutoScrollFrame: import("../../schema/index.js").CallableTaggedStruct<"AdvancedAutoScrollFrame", {}>;
88
88
  /** The FocusItem Command completed. */
89
89
  export declare const CompletedFocusItem: import("../../schema/index.js").CallableTaggedStruct<"CompletedFocusItem", {}>;
90
90
  /** Union of all messages the drag-and-drop component can produce. */
@@ -97,7 +97,7 @@ export declare const Message: S.Union<[
97
97
  typeof ResolvedKeyboardMove,
98
98
  typeof ConfirmedKeyboardDrop,
99
99
  typeof PressedArrowKey,
100
- typeof CompletedAutoScroll,
100
+ typeof AdvancedAutoScrollFrame,
101
101
  typeof CompletedFocusItem
102
102
  ]>;
103
103
  export type Message = typeof Message.Type;
@@ -244,7 +244,7 @@ export declare const subscriptions: {
244
244
  readonly _tag: "PressedArrowKey";
245
245
  readonly direction: "Left" | "Right" | "Up" | "Down" | "NextContainer" | "PreviousContainer";
246
246
  } | {
247
- readonly _tag: "CompletedAutoScroll";
247
+ readonly _tag: "AdvancedAutoScrollFrame";
248
248
  } | {
249
249
  readonly _tag: "CompletedFocusItem";
250
250
  }, never, never>;
@@ -339,7 +339,7 @@ export declare const subscriptions: {
339
339
  readonly _tag: "PressedArrowKey";
340
340
  readonly direction: "Left" | "Right" | "Up" | "Down" | "NextContainer" | "PreviousContainer";
341
341
  } | {
342
- readonly _tag: "CompletedAutoScroll";
342
+ readonly _tag: "AdvancedAutoScrollFrame";
343
343
  } | {
344
344
  readonly _tag: "CompletedFocusItem";
345
345
  }, never, never>;
@@ -434,7 +434,7 @@ export declare const subscriptions: {
434
434
  readonly _tag: "PressedArrowKey";
435
435
  readonly direction: "Left" | "Right" | "Up" | "Down" | "NextContainer" | "PreviousContainer";
436
436
  } | {
437
- readonly _tag: "CompletedAutoScroll";
437
+ readonly _tag: "AdvancedAutoScrollFrame";
438
438
  } | {
439
439
  readonly _tag: "CompletedFocusItem";
440
440
  }, never, never>;
@@ -538,7 +538,7 @@ export declare const subscriptions: {
538
538
  readonly _tag: "PressedArrowKey";
539
539
  readonly direction: "Left" | "Right" | "Up" | "Down" | "NextContainer" | "PreviousContainer";
540
540
  } | {
541
- readonly _tag: "CompletedAutoScroll";
541
+ readonly _tag: "AdvancedAutoScrollFrame";
542
542
  } | {
543
543
  readonly _tag: "CompletedFocusItem";
544
544
  }, never, never>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/dragAndDrop/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/dragAndDrop/index.ts"],"names":[],"mappings":"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"}