foldkit 0.56.0 → 0.57.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 (70) hide show
  1. package/dist/devtools/overlay-styles.d.ts +1 -1
  2. package/dist/devtools/overlay-styles.d.ts.map +1 -1
  3. package/dist/devtools/overlay-styles.js +5 -1
  4. package/dist/devtools/overlay.d.ts.map +1 -1
  5. package/dist/devtools/overlay.js +52 -19
  6. package/dist/html/index.d.ts +3 -3
  7. package/dist/html/index.d.ts.map +1 -1
  8. package/dist/html/lazy.d.ts +7 -5
  9. package/dist/html/lazy.d.ts.map +1 -1
  10. package/dist/html/lazy.js +12 -8
  11. package/dist/runtime/runtime.d.ts.map +1 -1
  12. package/dist/runtime/runtime.js +2 -4
  13. package/dist/test/apps/disabledButton.d.ts +11 -3
  14. package/dist/test/apps/disabledButton.d.ts.map +1 -1
  15. package/dist/ui/combobox/multi.d.ts +31 -10
  16. package/dist/ui/combobox/multi.d.ts.map +1 -1
  17. package/dist/ui/combobox/public.d.ts +1 -2
  18. package/dist/ui/combobox/public.d.ts.map +1 -1
  19. package/dist/ui/combobox/public.js +1 -2
  20. package/dist/ui/combobox/shared.d.ts +33 -33
  21. package/dist/ui/combobox/shared.d.ts.map +1 -1
  22. package/dist/ui/combobox/shared.js +89 -112
  23. package/dist/ui/combobox/single.d.ts +31 -10
  24. package/dist/ui/combobox/single.d.ts.map +1 -1
  25. package/dist/ui/combobox/single.js +1 -5
  26. package/dist/ui/dialog/index.d.ts +10 -15
  27. package/dist/ui/dialog/index.d.ts.map +1 -1
  28. package/dist/ui/dialog/index.js +68 -73
  29. package/dist/ui/dialog/public.d.ts +1 -1
  30. package/dist/ui/dialog/public.d.ts.map +1 -1
  31. package/dist/ui/dialog/public.js +1 -1
  32. package/dist/ui/listbox/multi.d.ts +30 -9
  33. package/dist/ui/listbox/multi.d.ts.map +1 -1
  34. package/dist/ui/listbox/public.d.ts +1 -2
  35. package/dist/ui/listbox/public.d.ts.map +1 -1
  36. package/dist/ui/listbox/public.js +1 -2
  37. package/dist/ui/listbox/shared.d.ts +35 -36
  38. package/dist/ui/listbox/shared.d.ts.map +1 -1
  39. package/dist/ui/listbox/shared.js +106 -104
  40. package/dist/ui/listbox/single.d.ts +30 -9
  41. package/dist/ui/listbox/single.d.ts.map +1 -1
  42. package/dist/ui/listbox/single.js +9 -12
  43. package/dist/ui/menu/index.d.ts +22 -26
  44. package/dist/ui/menu/index.d.ts.map +1 -1
  45. package/dist/ui/menu/index.js +103 -91
  46. package/dist/ui/menu/public.d.ts +1 -2
  47. package/dist/ui/menu/public.d.ts.map +1 -1
  48. package/dist/ui/menu/public.js +1 -2
  49. package/dist/ui/popover/index.d.ts +21 -22
  50. package/dist/ui/popover/index.d.ts.map +1 -1
  51. package/dist/ui/popover/index.js +92 -75
  52. package/dist/ui/popover/public.d.ts +1 -2
  53. package/dist/ui/popover/public.d.ts.map +1 -1
  54. package/dist/ui/popover/public.js +1 -2
  55. package/dist/ui/transition/index.d.ts +8 -58
  56. package/dist/ui/transition/index.d.ts.map +1 -1
  57. package/dist/ui/transition/index.js +21 -111
  58. package/dist/ui/transition/public.d.ts +1 -1
  59. package/dist/ui/transition/public.d.ts.map +1 -1
  60. package/dist/ui/transition/public.js +1 -1
  61. package/dist/ui/transition/schema.d.ts +43 -0
  62. package/dist/ui/transition/schema.d.ts.map +1 -0
  63. package/dist/ui/transition/schema.js +35 -0
  64. package/dist/ui/transition/update.d.ts +22 -0
  65. package/dist/ui/transition/update.d.ts.map +1 -0
  66. package/dist/ui/transition/update.js +68 -0
  67. package/package.json +1 -1
  68. package/dist/ui/transition.d.ts +0 -5
  69. package/dist/ui/transition.d.ts.map +0 -1
  70. package/dist/ui/transition.js +0 -3
@@ -1,4 +1,4 @@
1
- import { Array, Effect, Match as M, Option, Schema as S, pipe } from 'effect';
1
+ import { Array, Effect, Equal, Match as M, Option, Schema as S } from 'effect';
2
2
  import * as Command from '../../command';
3
3
  import { OptionExt } from '../../effectExtensions';
4
4
  import { createLazy, html } from '../../html';
@@ -6,7 +6,11 @@ import { m } from '../../message';
6
6
  import { evo } from '../../struct';
7
7
  import * as Task from '../../task';
8
8
  import { anchorHooks } from '../anchor';
9
- import { TransitionState } from '../transition';
9
+ // NOTE: Transition imports are split across schema + update to avoid a circular
10
+ // dependency: transition → html → runtime → devtools → popover → transition.
11
+ // The barrel (../transition) imports from html, which starts the cycle.
12
+ import { EndedTransition as TransitionEndedTransition, Hidden as TransitionHidden, Message as TransitionMessage, Model as TransitionModel, Showed as TransitionShowed, init as transitionInit, } from '../transition/schema';
13
+ import { update as transitionUpdate } from '../transition/update';
10
14
  // MODEL
11
15
  /** Schema for the popover component's state, tracking open/closed status and transition animation. */
12
16
  export const Model = S.Struct({
@@ -14,7 +18,7 @@ export const Model = S.Struct({
14
18
  isOpen: S.Boolean,
15
19
  isAnimated: S.Boolean,
16
20
  isModal: S.Boolean,
17
- transitionState: TransitionState,
21
+ transition: TransitionModel,
18
22
  maybeLastButtonPointerType: S.OptionFromSelf(S.String),
19
23
  });
20
24
  // MESSAGE
@@ -45,14 +49,12 @@ export const CompletedTeardownInert = m('CompletedTeardownInert');
45
49
  export const IgnoredMouseClick = m('IgnoredMouseClick');
46
50
  /** Sent when a Space key-up is captured to prevent page scrolling. */
47
51
  export const SuppressedSpaceScroll = m('SuppressedSpaceScroll');
48
- /** Sent internally when a double-rAF completes, advancing the transition to its animating phase. */
49
- export const AdvancedTransitionFrame = m('AdvancedTransitionFrame');
50
- /** Sent internally when all CSS transitions on the popover panel have completed. */
51
- export const EndedTransition = m('EndedTransition');
52
- /** Sent internally when the popover button moves in the viewport during a leave transition, cancelling the animation. */
53
- export const DetectedButtonMovement = m('DetectedButtonMovement');
52
+ /** Wraps a Transition submodel message for delegation. */
53
+ export const GotTransitionMessage = m('GotTransitionMessage', {
54
+ message: TransitionMessage,
55
+ });
54
56
  /** Union of all messages the popover component can produce. */
55
- export const Message = S.Union(Opened, Closed, ClosedByTab, PressedPointerOnButton, CompletedFocusPanel, CompletedFocusButton, CompletedLockScroll, CompletedUnlockScroll, CompletedSetupInert, CompletedTeardownInert, IgnoredMouseClick, SuppressedSpaceScroll, AdvancedTransitionFrame, EndedTransition, DetectedButtonMovement);
57
+ export const Message = S.Union(Opened, Closed, ClosedByTab, PressedPointerOnButton, CompletedFocusPanel, CompletedFocusButton, CompletedLockScroll, CompletedUnlockScroll, CompletedSetupInert, CompletedTeardownInert, IgnoredMouseClick, SuppressedSpaceScroll, GotTransitionMessage);
56
58
  // INIT
57
59
  const LEFT_MOUSE_BUTTON = 0;
58
60
  /** Creates an initial popover model from a config. Defaults to closed. */
@@ -61,20 +63,17 @@ export const init = (config) => ({
61
63
  isOpen: false,
62
64
  isAnimated: config.isAnimated ?? false,
63
65
  isModal: config.isModal ?? false,
64
- transitionState: 'Idle',
66
+ transition: transitionInit({ id: `${config.id}-panel` }),
65
67
  maybeLastButtonPointerType: Option.none(),
66
68
  });
67
69
  // UPDATE
68
70
  const closedModel = (model) => evo(model, {
69
71
  isOpen: () => false,
70
- transitionState: () => (model.isAnimated ? 'LeaveStart' : 'Idle'),
71
72
  maybeLastButtonPointerType: () => Option.none(),
72
73
  });
73
74
  const buttonSelector = (id) => `#${id}-button`;
74
75
  const panelSelector = (id) => `#${id}-panel`;
75
76
  const withUpdateReturn = M.withReturnType();
76
- /** Advances the popover's enter/leave transition by waiting a double-rAF. */
77
- export const RequestFrame = Command.define('RequestFrame', AdvancedTransitionFrame);
78
77
  /** Prevents page scrolling while the popover is open in modal mode. */
79
78
  export const LockScroll = Command.define('LockScroll', CompletedLockScroll);
80
79
  /** Re-enables page scrolling after the popover closes. */
@@ -87,13 +86,31 @@ export const RestoreInert = Command.define('RestoreInert', CompletedTeardownIner
87
86
  export const FocusPanel = Command.define('FocusPanel', CompletedFocusPanel);
88
87
  /** Moves focus back to the popover button after closing. */
89
88
  export const FocusButton = Command.define('FocusButton', CompletedFocusButton);
90
- /** Waits for all CSS transitions on the popover panel to complete. */
91
- export const WaitForTransitions = Command.define('WaitForTransitions', EndedTransition);
92
- /** Detects whether the popover button moved or the leave transition ended — whichever comes first. */
93
- export const DetectMovementOrTransitionEnd = Command.define('DetectMovementOrTransitionEnd', DetectedButtonMovement, EndedTransition);
89
+ /** Detects whether the popover button moved or the leave transition ended — whichever comes first. Both outcomes signal the Transition submodel that leave is complete. */
90
+ export const DetectMovementOrTransitionEnd = Command.define('DetectMovementOrTransitionEnd', GotTransitionMessage);
91
+ const delegateToTransition = (model, transitionMessage) => {
92
+ const [nextTransition, transitionCommands, maybeOutMessage] = transitionUpdate(model.transition, transitionMessage);
93
+ const mappedCommands = transitionCommands.map(Command.mapEffect(Effect.map(message => GotTransitionMessage({ message }))));
94
+ const additionalCommands = Option.match(maybeOutMessage, {
95
+ onNone: () => [],
96
+ onSome: M.type().pipe(M.tagsExhaustive({
97
+ StartedLeaveAnimating: () => [
98
+ DetectMovementOrTransitionEnd(Effect.raceFirst(Task.detectElementMovement(buttonSelector(model.id)).pipe(Effect.as(GotTransitionMessage({
99
+ message: TransitionEndedTransition(),
100
+ }))), Task.waitForTransitions(panelSelector(model.id)).pipe(Effect.as(GotTransitionMessage({
101
+ message: TransitionEndedTransition(),
102
+ }))))),
103
+ ],
104
+ TransitionedOut: () => [],
105
+ })),
106
+ });
107
+ return [
108
+ evo(model, { transition: () => nextTransition }),
109
+ [...mappedCommands, ...additionalCommands],
110
+ ];
111
+ };
94
112
  /** Processes a popover message and returns the next model and commands. */
95
113
  export const update = (model, message) => {
96
- const maybeNextFrame = OptionExt.when(model.isAnimated, RequestFrame(Task.nextFrame.pipe(Effect.as(AdvancedTransitionFrame()))));
97
114
  const maybeLockScroll = OptionExt.when(model.isModal, LockScroll(Task.lockScroll.pipe(Effect.as(CompletedLockScroll()))));
98
115
  const maybeUnlockScroll = OptionExt.when(model.isModal, UnlockScroll(Task.unlockScroll.pipe(Effect.as(CompletedUnlockScroll()))));
99
116
  const maybeInertOthers = OptionExt.when(model.isModal, InertOthers(Task.inertOthers(model.id, [
@@ -101,29 +118,47 @@ export const update = (model, message) => {
101
118
  panelSelector(model.id),
102
119
  ]).pipe(Effect.as(CompletedSetupInert()))));
103
120
  const maybeRestoreInert = OptionExt.when(model.isModal, RestoreInert(Task.restoreInert(model.id).pipe(Effect.as(CompletedTeardownInert()))));
104
- return M.value(message).pipe(withUpdateReturn, M.tagsExhaustive({
105
- Opened: () => {
106
- const nextModel = evo(model, {
107
- isOpen: () => true,
108
- transitionState: () => (model.isAnimated ? 'EnterStart' : 'Idle'),
109
- });
121
+ const focusPanel = FocusPanel(Task.focus(panelSelector(model.id)).pipe(Effect.ignore, Effect.as(CompletedFocusPanel())));
122
+ const focusButton = FocusButton(Task.focus(buttonSelector(model.id)).pipe(Effect.ignore, Effect.as(CompletedFocusButton())));
123
+ const openCommands = [
124
+ focusPanel,
125
+ ...Array.getSomes([maybeLockScroll, maybeInertOthers]),
126
+ ];
127
+ const closeWithFocusCommands = [
128
+ focusButton,
129
+ ...Array.getSomes([maybeUnlockScroll, maybeRestoreInert]),
130
+ ];
131
+ const closeWithoutFocusCommands = Array.getSomes([
132
+ maybeUnlockScroll,
133
+ maybeRestoreInert,
134
+ ]);
135
+ const openPopover = (baseModel) => {
136
+ if (model.isAnimated) {
137
+ const [nextModel, transitionCommands] = delegateToTransition(baseModel, TransitionShowed());
110
138
  return [
111
- nextModel,
112
- pipe(Array.getSomes([maybeNextFrame, maybeLockScroll, maybeInertOthers]), Array.prepend(FocusPanel(Task.focus(panelSelector(model.id)).pipe(Effect.ignore, Effect.as(CompletedFocusPanel()))))),
139
+ evo(nextModel, { isOpen: () => true }),
140
+ [...openCommands, ...transitionCommands],
113
141
  ];
142
+ }
143
+ return [evo(baseModel, { isOpen: () => true }), openCommands];
144
+ };
145
+ const closePopover = (baseModel, commands) => {
146
+ const closed = closedModel(baseModel);
147
+ if (model.isAnimated) {
148
+ const [nextModel, transitionCommands] = delegateToTransition(closed, TransitionHidden());
149
+ return [nextModel, [...commands, ...transitionCommands]];
150
+ }
151
+ return [closed, commands];
152
+ };
153
+ return M.value(message).pipe(withUpdateReturn, M.tagsExhaustive({
154
+ Opened: () => openPopover(model),
155
+ Closed: () => closePopover(model, closeWithFocusCommands),
156
+ ClosedByTab: () => {
157
+ if (Option.exists(model.maybeLastButtonPointerType, Equal.equals('mouse'))) {
158
+ return [model, []];
159
+ }
160
+ return closePopover(model, closeWithoutFocusCommands);
114
161
  },
115
- Closed: () => [
116
- closedModel(model),
117
- pipe(Array.getSomes([
118
- maybeNextFrame,
119
- maybeUnlockScroll,
120
- maybeRestoreInert,
121
- ]), Array.prepend(FocusButton(Task.focus(buttonSelector(model.id)).pipe(Effect.ignore, Effect.as(CompletedFocusButton()))))),
122
- ],
123
- ClosedByTab: () => [
124
- closedModel(model),
125
- Array.getSomes([maybeNextFrame, maybeUnlockScroll, maybeRestoreInert]),
126
- ],
127
162
  PressedPointerOnButton: ({ pointerType, button }) => {
128
163
  const withPointerType = evo(model, {
129
164
  maybeLastButtonPointerType: () => Option.some(pointerType),
@@ -132,50 +167,27 @@ export const update = (model, message) => {
132
167
  return [withPointerType, []];
133
168
  }
134
169
  if (model.isOpen) {
170
+ const [closed, commands] = closePopover(withPointerType, closeWithFocusCommands);
135
171
  return [
136
- closedModel(withPointerType),
137
- pipe(Array.getSomes([
138
- maybeNextFrame,
139
- maybeUnlockScroll,
140
- maybeRestoreInert,
141
- ]), Array.prepend(FocusButton(Task.focus(buttonSelector(model.id)).pipe(Effect.ignore, Effect.as(CompletedFocusButton()))))),
172
+ evo(closed, {
173
+ maybeLastButtonPointerType: () => Option.some(pointerType),
174
+ }),
175
+ commands,
142
176
  ];
143
177
  }
144
- const nextModel = evo(withPointerType, {
145
- isOpen: () => true,
146
- transitionState: () => (model.isAnimated ? 'EnterStart' : 'Idle'),
147
- });
148
- return [
149
- nextModel,
150
- pipe(Array.getSomes([maybeNextFrame, maybeLockScroll, maybeInertOthers]), Array.prepend(FocusPanel(Task.focus(panelSelector(model.id)).pipe(Effect.ignore, Effect.as(CompletedFocusPanel()))))),
151
- ];
178
+ return openPopover(withPointerType);
152
179
  },
153
- AdvancedTransitionFrame: () => M.value(model.transitionState).pipe(withUpdateReturn, M.when('EnterStart', () => [
154
- evo(model, { transitionState: () => 'EnterAnimating' }),
155
- [
156
- WaitForTransitions(Task.waitForTransitions(panelSelector(model.id)).pipe(Effect.as(EndedTransition()))),
157
- ],
158
- ]), M.when('LeaveStart', () => [
159
- evo(model, { transitionState: () => 'LeaveAnimating' }),
160
- [
161
- DetectMovementOrTransitionEnd(Effect.raceFirst(Task.detectElementMovement(buttonSelector(model.id)).pipe(Effect.as(DetectedButtonMovement())), Task.waitForTransitions(panelSelector(model.id)).pipe(Effect.as(EndedTransition())))),
162
- ],
163
- ]), M.orElse(() => [model, []])),
164
- EndedTransition: () => M.value(model.transitionState).pipe(withUpdateReturn, M.whenOr('EnterAnimating', 'LeaveAnimating', () => [
165
- evo(model, { transitionState: () => 'Idle' }),
166
- [],
167
- ]), M.orElse(() => [model, []])),
168
- DetectedButtonMovement: () => M.value(model.transitionState).pipe(withUpdateReturn, M.when('LeaveAnimating', () => [
169
- evo(model, { transitionState: () => 'Idle' }),
170
- [],
171
- ]), M.orElse(() => [model, []])),
180
+ GotTransitionMessage: ({ message: transitionMessage }) => delegateToTransition(model, transitionMessage),
172
181
  CompletedFocusPanel: () => [model, []],
173
182
  CompletedFocusButton: () => [model, []],
174
183
  CompletedLockScroll: () => [model, []],
175
184
  CompletedUnlockScroll: () => [model, []],
176
185
  CompletedSetupInert: () => [model, []],
177
186
  CompletedTeardownInert: () => [model, []],
178
- IgnoredMouseClick: () => [model, []],
187
+ IgnoredMouseClick: () => [
188
+ evo(model, { maybeLastButtonPointerType: () => Option.none() }),
189
+ [],
190
+ ],
179
191
  SuppressedSpaceScroll: () => [model, []],
180
192
  }));
181
193
  };
@@ -188,7 +200,7 @@ export const close = (model) => update(model, Closed());
188
200
  /** Renders a headless popover with a trigger button and a floating panel. Uses the disclosure ARIA pattern (aria-expanded + aria-controls) with no role on the panel. */
189
201
  export const view = (config) => {
190
202
  const { div, AriaControls, AriaDisabled, AriaExpanded, Class, DataAttribute, Id, OnBlur, OnClick, OnDestroy, OnInsert, OnKeyDownPreventDefault, OnKeyUpPreventDefault, OnPointerDown, Style, Tabindex, Type, keyed, } = html();
191
- const { model: { id, isOpen, transitionState, maybeLastButtonPointerType }, toParentMessage, onOpened, onClosed, anchor, buttonContent, buttonClassName, buttonAttributes = [], panelContent, panelClassName, panelAttributes = [], backdropClassName, backdropAttributes = [], isDisabled, className, attributes = [], } = config;
203
+ const { model: { id, isOpen, transition: { transitionState }, maybeLastButtonPointerType, }, toParentMessage, onOpened, onClosed, anchor, buttonContent, buttonClassName, buttonAttributes = [], panelContent, panelClassName, panelAttributes = [], backdropClassName, backdropAttributes = [], isDisabled, className, attributes = [], } = config;
192
204
  const dispatchOpened = () => onOpened ? onOpened() : toParentMessage(Opened());
193
205
  const dispatchClosed = () => onClosed ? onClosed() : toParentMessage(Closed());
194
206
  const isLeaving = transitionState === 'LeaveStart' || transitionState === 'LeaveAnimating';
@@ -240,7 +252,12 @@ export const view = (config) => {
240
252
  OnKeyUpPreventDefault(handleSpaceKeyUp),
241
253
  OnClick(handleButtonClick()),
242
254
  ]),
243
- ...(isVisible ? [DataAttribute('open', '')] : []),
255
+ ...(isVisible
256
+ ? [
257
+ DataAttribute('open', ''),
258
+ Style({ position: 'relative', zIndex: '1' }),
259
+ ]
260
+ : []),
244
261
  ...(buttonClassName ? [Class(buttonClassName)] : []),
245
262
  ...buttonAttributes,
246
263
  ];
@@ -1,5 +1,4 @@
1
- export { init, update, open, close, view, lazy, Model, Message, Opened, Closed, CompletedFocusPanel, CompletedFocusButton, CompletedLockScroll, CompletedUnlockScroll, CompletedSetupInert, CompletedTeardownInert, AdvancedTransitionFrame, EndedTransition, DetectedButtonMovement, RequestFrame, LockScroll, UnlockScroll, InertOthers, RestoreInert, FocusPanel, FocusButton, WaitForTransitions, DetectMovementOrTransitionEnd, } from './index';
2
- export { TransitionState } from '../transition';
1
+ export { init, update, open, close, view, lazy, Model, Message, Opened, Closed, CompletedFocusPanel, CompletedFocusButton, CompletedLockScroll, CompletedUnlockScroll, CompletedSetupInert, CompletedTeardownInert, GotTransitionMessage, LockScroll, UnlockScroll, InertOthers, RestoreInert, FocusPanel, FocusButton, DetectMovementOrTransitionEnd, } from './index';
3
2
  export type { ClosedByTab, PressedPointerOnButton, IgnoredMouseClick, SuppressedSpaceScroll, InitConfig, ViewConfig, } from './index';
4
3
  export type { AnchorConfig } from '../anchor';
5
4
  //# sourceMappingURL=public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/ui/popover/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,MAAM,EACN,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,OAAO,EACP,MAAM,EACN,MAAM,EACN,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,uBAAuB,EACvB,eAAe,EACf,sBAAsB,EACtB,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,UAAU,EACV,WAAW,EACX,kBAAkB,EAClB,6BAA6B,GAC9B,MAAM,SAAS,CAAA;AAEhB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAE/C,YAAY,EACV,WAAW,EACX,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACrB,UAAU,EACV,UAAU,GACX,MAAM,SAAS,CAAA;AAEhB,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/ui/popover/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,MAAM,EACN,IAAI,EACJ,KAAK,EACL,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,OAAO,EACP,MAAM,EACN,MAAM,EACN,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,mBAAmB,EACnB,sBAAsB,EACtB,oBAAoB,EACpB,UAAU,EACV,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,UAAU,EACV,WAAW,EACX,6BAA6B,GAC9B,MAAM,SAAS,CAAA;AAEhB,YAAY,EACV,WAAW,EACX,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACrB,UAAU,EACV,UAAU,GACX,MAAM,SAAS,CAAA;AAEhB,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA"}
@@ -1,2 +1 @@
1
- export { init, update, open, close, view, lazy, Model, Message, Opened, Closed, CompletedFocusPanel, CompletedFocusButton, CompletedLockScroll, CompletedUnlockScroll, CompletedSetupInert, CompletedTeardownInert, AdvancedTransitionFrame, EndedTransition, DetectedButtonMovement, RequestFrame, LockScroll, UnlockScroll, InertOthers, RestoreInert, FocusPanel, FocusButton, WaitForTransitions, DetectMovementOrTransitionEnd, } from './index';
2
- export { TransitionState } from '../transition';
1
+ export { init, update, open, close, view, lazy, Model, Message, Opened, Closed, CompletedFocusPanel, CompletedFocusButton, CompletedLockScroll, CompletedUnlockScroll, CompletedSetupInert, CompletedTeardownInert, GotTransitionMessage, LockScroll, UnlockScroll, InertOthers, RestoreInert, FocusPanel, FocusButton, DetectMovementOrTransitionEnd, } from './index';
@@ -1,61 +1,12 @@
1
- import { Option, Schema as S } from 'effect';
2
- import * as Command from '../../command';
3
1
  import { type Attribute, type Html, type TagName } from '../../html';
4
- /** Schema for the transition component's state, tracking its unique ID, visibility intent, and animation phase. */
5
- export declare const Model: S.Struct<{
6
- id: typeof S.String;
7
- isShowing: typeof S.Boolean;
8
- transitionState: S.Literal<["Idle", "EnterStart", "EnterAnimating", "LeaveStart", "LeaveAnimating"]>;
9
- }>;
10
- export type Model = typeof Model.Type;
11
- /** Sent when the transition should enter (become visible). Starts the enter animation sequence. */
12
- export declare const Showed: import("../../schema").CallableTaggedStruct<"Showed", {}>;
13
- /** Sent when the transition should leave (become hidden). Starts the leave animation sequence. */
14
- export declare const Hidden: import("../../schema").CallableTaggedStruct<"Hidden", {}>;
15
- /** Sent internally when a double-rAF completes, advancing the transition to its animating phase. */
16
- export declare const AdvancedTransitionFrame: import("../../schema").CallableTaggedStruct<"AdvancedTransitionFrame", {}>;
17
- /** Sent internally when all CSS transitions on the transition element have completed. */
18
- export declare const EndedTransition: import("../../schema").CallableTaggedStruct<"EndedTransition", {}>;
19
- /** Union of all messages the transition component can produce. */
20
- export declare const Message: S.Union<[
21
- typeof Showed,
22
- typeof Hidden,
23
- typeof AdvancedTransitionFrame,
24
- typeof EndedTransition
25
- ]>;
26
- export type Showed = typeof Showed.Type;
27
- export type Hidden = typeof Hidden.Type;
28
- export type Message = typeof Message.Type;
29
- /** Sent to the parent when the leave animation completes. The parent can use this to unmount content or update its own state. */
30
- export declare const TransitionedOut: import("../../schema").CallableTaggedStruct<"TransitionedOut", {}>;
31
- export declare const OutMessage: import("../../schema").CallableTaggedStruct<"TransitionedOut", {}>;
32
- export type OutMessage = typeof OutMessage.Type;
33
- /** Configuration for creating a transition model with `init`. */
34
- export type InitConfig = Readonly<{
35
- id: string;
36
- isShowing?: boolean;
37
- }>;
38
- /** Creates an initial transition model from a config. Defaults to hidden. */
39
- export declare const init: (config: InitConfig) => Model;
40
- type UpdateReturn = readonly [
41
- Model,
42
- ReadonlyArray<Command.Command<Message>>,
43
- Option.Option<OutMessage>
44
- ];
45
- /** Advances the transition's enter/leave animation by waiting a double-rAF. */
46
- export declare const RequestFrame: Command.CommandDefinition<"RequestFrame", {
47
- readonly _tag: "AdvancedTransitionFrame";
48
- }>;
49
- /** Waits for all CSS transitions on the transition element to complete. */
50
- export declare const WaitForTransitions: Command.CommandDefinition<"WaitForTransitions", {
51
- readonly _tag: "EndedTransition";
52
- }>;
53
- /** Processes a transition message and returns the next model, commands, and optional OutMessage. */
54
- export declare const update: (model: Model, message: Message) => UpdateReturn;
2
+ import { AdvancedTransitionFrame, EndedTransition, Hidden, Message, Model, OutMessage, Showed, StartedLeaveAnimating, TransitionState, TransitionedOut, init } from './schema';
3
+ import { RequestFrame, WaitForTransitions, defaultLeaveCommand, update } from './update';
4
+ export type { InitConfig } from './schema';
5
+ export { AdvancedTransitionFrame, EndedTransition, Hidden, init, Message, Model, OutMessage, Showed, StartedLeaveAnimating, TransitionState, TransitionedOut, };
6
+ export { RequestFrame, WaitForTransitions, defaultLeaveCommand, update };
55
7
  /** Configuration for rendering a transition with `view`. */
56
8
  export type ViewConfig<Message> = Readonly<{
57
9
  model: Model;
58
- toParentMessage: (message: Showed | Hidden) => Message;
59
10
  content: Html;
60
11
  className?: string;
61
12
  attributes?: ReadonlyArray<Attribute<Message>>;
@@ -75,8 +26,7 @@ export type ViewConfig<Message> = Readonly<{
75
26
  */
76
27
  export declare const view: <Message>(config: ViewConfig<Message>) => Html;
77
28
  /** Creates a memoized transition view. Static config (className, element, etc.)
78
- * is captured in a closure. Dynamic fields — `model`, `toParentMessage`,
79
- * and `content` — are compared by reference per render via `createLazy`. */
80
- export declare const lazy: <Message>(staticConfig: Omit<ViewConfig<Message>, "model" | "toParentMessage" | "content">) => ((model: Model, toParentMessage: ViewConfig<Message>["toParentMessage"], content: Html) => Html);
81
- export {};
29
+ * is captured in a closure. Dynamic fields — `model` and `content` — are
30
+ * compared by reference per render via `createLazy`. */
31
+ export declare const lazy: <Message>(staticConfig: Omit<ViewConfig<Message>, "model" | "content">) => ((model: Model, content: Html) => Html);
82
32
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/transition/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/transition/index.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,KAAK,SAAS,EACd,KAAK,IAAI,EACT,KAAK,OAAO,EAGb,MAAM,YAAY,CAAA;AACnB,OAAO,EACL,uBAAuB,EACvB,eAAe,EACf,MAAM,EACN,OAAO,EACP,KAAK,EACL,UAAU,EACV,MAAM,EACN,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,IAAI,EACL,MAAM,UAAU,CAAA;AACjB,OAAO,EACL,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,MAAM,EACP,MAAM,UAAU,CAAA;AAEjB,YAAY,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,EACL,uBAAuB,EACvB,eAAe,EACf,MAAM,EACN,IAAI,EACJ,OAAO,EACP,KAAK,EACL,UAAU,EACV,MAAM,EACN,qBAAqB,EACrB,eAAe,EACf,eAAe,GAChB,CAAA;AAED,OAAO,EAAE,YAAY,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,EAAE,CAAA;AAIxE,4DAA4D;AAC5D,MAAM,MAAM,UAAU,CAAC,OAAO,IAAI,QAAQ,CAAC;IACzC,KAAK,EAAE,KAAK,CAAA;IACZ,OAAO,EAAE,IAAI,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,UAAU,CAAC,EAAE,aAAa,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAA;IAC9C,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;2EAEuE;IACvE,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB,CAAC,CAAA;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,IAAI,GAAI,OAAO,EAAE,QAAQ,UAAU,CAAC,OAAO,CAAC,KAAG,IA+F3D,CAAA;AAED;;yDAEyD;AACzD,eAAO,MAAM,IAAI,GAAI,OAAO,EAC1B,cAAc,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC,KAC3D,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,KAAK,IAAI,CAaxC,CAAA"}
@@ -1,101 +1,9 @@
1
- import { Effect, Match as M, Option, Schema as S } from 'effect';
2
- import * as Command from '../../command';
1
+ import { Match as M } from 'effect';
3
2
  import { createLazy, html, } from '../../html';
4
- import { m } from '../../message';
5
- import { evo } from '../../struct';
6
- import * as Task from '../../task';
7
- import { TransitionState } from '../transition';
8
- // MODEL
9
- /** Schema for the transition component's state, tracking its unique ID, visibility intent, and animation phase. */
10
- export const Model = S.Struct({
11
- id: S.String,
12
- isShowing: S.Boolean,
13
- transitionState: TransitionState,
14
- });
15
- // MESSAGE
16
- /** Sent when the transition should enter (become visible). Starts the enter animation sequence. */
17
- export const Showed = m('Showed');
18
- /** Sent when the transition should leave (become hidden). Starts the leave animation sequence. */
19
- export const Hidden = m('Hidden');
20
- /** Sent internally when a double-rAF completes, advancing the transition to its animating phase. */
21
- export const AdvancedTransitionFrame = m('AdvancedTransitionFrame');
22
- /** Sent internally when all CSS transitions on the transition element have completed. */
23
- export const EndedTransition = m('EndedTransition');
24
- /** Union of all messages the transition component can produce. */
25
- export const Message = S.Union(Showed, Hidden, AdvancedTransitionFrame, EndedTransition);
26
- // OUT MESSAGE
27
- /** Sent to the parent when the leave animation completes. The parent can use this to unmount content or update its own state. */
28
- export const TransitionedOut = m('TransitionedOut');
29
- export const OutMessage = S.Union(TransitionedOut);
30
- /** Creates an initial transition model from a config. Defaults to hidden. */
31
- export const init = (config) => ({
32
- id: config.id,
33
- isShowing: config.isShowing ?? false,
34
- transitionState: 'Idle',
35
- });
36
- // UPDATE
37
- const elementSelector = (id) => `#${id}`;
38
- const withUpdateReturn = M.withReturnType();
39
- /** Advances the transition's enter/leave animation by waiting a double-rAF. */
40
- export const RequestFrame = Command.define('RequestFrame', AdvancedTransitionFrame);
41
- /** Waits for all CSS transitions on the transition element to complete. */
42
- export const WaitForTransitions = Command.define('WaitForTransitions', EndedTransition);
43
- /** Processes a transition message and returns the next model, commands, and optional OutMessage. */
44
- export const update = (model, message) => {
45
- const maybeNextFrame = RequestFrame(Task.nextFrame.pipe(Effect.as(AdvancedTransitionFrame())));
46
- return M.value(message).pipe(withUpdateReturn, M.tagsExhaustive({
47
- Showed: () => {
48
- if (model.isShowing) {
49
- return [model, [], Option.none()];
50
- }
51
- return [
52
- evo(model, {
53
- isShowing: () => true,
54
- transitionState: () => 'EnterStart',
55
- }),
56
- [maybeNextFrame],
57
- Option.none(),
58
- ];
59
- },
60
- Hidden: () => {
61
- const isLeaving = model.transitionState === 'LeaveStart' ||
62
- model.transitionState === 'LeaveAnimating';
63
- if (isLeaving || !model.isShowing) {
64
- return [model, [], Option.none()];
65
- }
66
- return [
67
- evo(model, {
68
- isShowing: () => false,
69
- transitionState: () => 'LeaveStart',
70
- }),
71
- [maybeNextFrame],
72
- Option.none(),
73
- ];
74
- },
75
- AdvancedTransitionFrame: () => M.value(model.transitionState).pipe(withUpdateReturn, M.when('EnterStart', () => [
76
- evo(model, { transitionState: () => 'EnterAnimating' }),
77
- [
78
- WaitForTransitions(Task.waitForTransitions(elementSelector(model.id)).pipe(Effect.as(EndedTransition()))),
79
- ],
80
- Option.none(),
81
- ]), M.when('LeaveStart', () => [
82
- evo(model, { transitionState: () => 'LeaveAnimating' }),
83
- [
84
- WaitForTransitions(Task.waitForTransitions(elementSelector(model.id)).pipe(Effect.as(EndedTransition()))),
85
- ],
86
- Option.none(),
87
- ]), M.orElse(() => [model, [], Option.none()])),
88
- EndedTransition: () => M.value(model.transitionState).pipe(withUpdateReturn, M.when('EnterAnimating', () => [
89
- evo(model, { transitionState: () => 'Idle' }),
90
- [],
91
- Option.none(),
92
- ]), M.when('LeaveAnimating', () => [
93
- evo(model, { transitionState: () => 'Idle' }),
94
- [],
95
- Option.some(TransitionedOut()),
96
- ]), M.orElse(() => [model, [], Option.none()])),
97
- }));
98
- };
3
+ import { AdvancedTransitionFrame, EndedTransition, Hidden, Message, Model, OutMessage, Showed, StartedLeaveAnimating, TransitionState, TransitionedOut, init, } from './schema';
4
+ import { RequestFrame, WaitForTransitions, defaultLeaveCommand, update, } from './update';
5
+ export { AdvancedTransitionFrame, EndedTransition, Hidden, init, Message, Model, OutMessage, Showed, StartedLeaveAnimating, TransitionState, TransitionedOut, };
6
+ export { RequestFrame, WaitForTransitions, defaultLeaveCommand, update };
99
7
  /** Renders a headless transition wrapper that coordinates CSS transitions via data attributes.
100
8
  *
101
9
  * Data attributes reflect the current transition phase:
@@ -136,17 +44,20 @@ export const view = (config) => {
136
44
  overflow: 'hidden',
137
45
  }),
138
46
  ], [
139
- keyed(element)(id, [
140
- Id(id),
47
+ div([
141
48
  Style({ minHeight: '0px', overflow: 'hidden' }),
142
- ...(isClosed && transitionState === 'Idle'
143
- ? [DataAttribute('closed', '')]
144
- : []),
145
- ...transitionAttributes,
146
- ...(className ? [Class(className)] : []),
147
49
  ...(!isVisible ? [AriaHidden(true)] : []),
148
- ...attributes,
149
- ], [content]),
50
+ ], [
51
+ keyed(element)(id, [
52
+ Id(id),
53
+ ...(isClosed && transitionState === 'Idle'
54
+ ? [DataAttribute('closed', '')]
55
+ : []),
56
+ ...transitionAttributes,
57
+ ...(className ? [Class(className)] : []),
58
+ ...attributes,
59
+ ], [content]),
60
+ ]),
150
61
  ]);
151
62
  }
152
63
  if (!isVisible) {
@@ -160,14 +71,13 @@ export const view = (config) => {
160
71
  ], [content]);
161
72
  };
162
73
  /** Creates a memoized transition view. Static config (className, element, etc.)
163
- * is captured in a closure. Dynamic fields — `model`, `toParentMessage`,
164
- * and `content` — are compared by reference per render via `createLazy`. */
74
+ * is captured in a closure. Dynamic fields — `model` and `content` — are
75
+ * compared by reference per render via `createLazy`. */
165
76
  export const lazy = (staticConfig) => {
166
77
  const lazyView = createLazy();
167
- return (model, toParentMessage, content) => lazyView((currentModel, currentToMessage, currentContent) => view({
78
+ return (model, content) => lazyView((currentModel, currentContent) => view({
168
79
  ...staticConfig,
169
80
  model: currentModel,
170
- toParentMessage: currentToMessage,
171
81
  content: currentContent,
172
- }), [model, toParentMessage, content]);
82
+ }), [model, content]);
173
83
  };
@@ -1,3 +1,3 @@
1
- export { init, update, view, lazy, Model, Message, OutMessage, Showed, Hidden, AdvancedTransitionFrame, EndedTransition, TransitionedOut, RequestFrame, WaitForTransitions, } from './index';
1
+ export { init, update, view, lazy, defaultLeaveCommand, Model, Message, OutMessage, Showed, Hidden, AdvancedTransitionFrame, EndedTransition, StartedLeaveAnimating, TransitionedOut, TransitionState, RequestFrame, WaitForTransitions, } from './index';
2
2
  export type { InitConfig, ViewConfig } from './index';
3
3
  //# sourceMappingURL=public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/ui/transition/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,MAAM,EACN,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,OAAO,EACP,UAAU,EACV,MAAM,EACN,MAAM,EACN,uBAAuB,EACvB,eAAe,EACf,eAAe,EACf,YAAY,EACZ,kBAAkB,GACnB,MAAM,SAAS,CAAA;AAEhB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../../src/ui/transition/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,MAAM,EACN,IAAI,EACJ,IAAI,EACJ,mBAAmB,EACnB,KAAK,EACL,OAAO,EACP,UAAU,EACV,MAAM,EACN,MAAM,EACN,uBAAuB,EACvB,eAAe,EACf,qBAAqB,EACrB,eAAe,EACf,eAAe,EACf,YAAY,EACZ,kBAAkB,GACnB,MAAM,SAAS,CAAA;AAEhB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,SAAS,CAAA"}
@@ -1 +1 @@
1
- export { init, update, view, lazy, Model, Message, OutMessage, Showed, Hidden, AdvancedTransitionFrame, EndedTransition, TransitionedOut, RequestFrame, WaitForTransitions, } from './index';
1
+ export { init, update, view, lazy, defaultLeaveCommand, Model, Message, OutMessage, Showed, Hidden, AdvancedTransitionFrame, EndedTransition, StartedLeaveAnimating, TransitionedOut, TransitionState, RequestFrame, WaitForTransitions, } from './index';
@@ -0,0 +1,43 @@
1
+ import { Schema as S } from 'effect';
2
+ /** Schema for the transition animation state, tracking enter/leave phases for CSS transition coordination. */
3
+ export declare const TransitionState: S.Literal<["Idle", "EnterStart", "EnterAnimating", "LeaveStart", "LeaveAnimating"]>;
4
+ export type TransitionState = typeof TransitionState.Type;
5
+ /** Schema for the transition component's state, tracking its unique ID, visibility intent, and animation phase. */
6
+ export declare const Model: S.Struct<{
7
+ id: typeof S.String;
8
+ isShowing: typeof S.Boolean;
9
+ transitionState: S.Literal<["Idle", "EnterStart", "EnterAnimating", "LeaveStart", "LeaveAnimating"]>;
10
+ }>;
11
+ export type Model = typeof Model.Type;
12
+ /** Sent when the transition should enter (become visible). Starts the enter animation sequence. */
13
+ export declare const Showed: import("../../schema").CallableTaggedStruct<"Showed", {}>;
14
+ /** Sent when the transition should leave (become hidden). Starts the leave animation sequence. */
15
+ export declare const Hidden: import("../../schema").CallableTaggedStruct<"Hidden", {}>;
16
+ /** Sent internally when a double-rAF completes, advancing the transition to its animating phase. */
17
+ export declare const AdvancedTransitionFrame: import("../../schema").CallableTaggedStruct<"AdvancedTransitionFrame", {}>;
18
+ /** Sent internally when all CSS transitions on the transition element have completed. */
19
+ export declare const EndedTransition: import("../../schema").CallableTaggedStruct<"EndedTransition", {}>;
20
+ /** Union of all messages the transition component can produce. */
21
+ export declare const Message: S.Union<[
22
+ typeof Showed,
23
+ typeof Hidden,
24
+ typeof AdvancedTransitionFrame,
25
+ typeof EndedTransition
26
+ ]>;
27
+ export type Message = typeof Message.Type;
28
+ export type Showed = typeof Showed.Type;
29
+ export type Hidden = typeof Hidden.Type;
30
+ /** Sent to the parent when the leave transition advances to LeaveAnimating. The parent is responsible for providing the command that detects when the leave animation completes (e.g. WaitForTransitions or a racing command). Use `defaultLeaveCommand` for the standard behavior. */
31
+ export declare const StartedLeaveAnimating: import("../../schema").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").CallableTaggedStruct<"TransitionedOut", {}>;
34
+ export declare const OutMessage: S.Union<[import("../../schema").CallableTaggedStruct<"StartedLeaveAnimating", {}>, import("../../schema").CallableTaggedStruct<"TransitionedOut", {}>]>;
35
+ export type OutMessage = typeof OutMessage.Type;
36
+ /** Configuration for creating a transition model with `init`. */
37
+ export type InitConfig = Readonly<{
38
+ id: string;
39
+ isShowing?: boolean;
40
+ }>;
41
+ /** Creates an initial transition model from a config. Defaults to hidden. */
42
+ export declare const init: (config: InitConfig) => Model;
43
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../../src/ui/transition/schema.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAMpC,8GAA8G;AAC9G,eAAO,MAAM,eAAe,qFAM3B,CAAA;AACD,MAAM,MAAM,eAAe,GAAG,OAAO,eAAe,CAAC,IAAI,CAAA;AAIzD,mHAAmH;AACnH,eAAO,MAAM,KAAK;;;;EAIhB,CAAA;AAEF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,mGAAmG;AACnG,eAAO,MAAM,MAAM,2DAAc,CAAA;AACjC,kGAAkG;AAClG,eAAO,MAAM,MAAM,2DAAc,CAAA;AACjC,oGAAoG;AACpG,eAAO,MAAM,uBAAuB,4EAA+B,CAAA;AACnE,yFAAyF;AACzF,eAAO,MAAM,eAAe,oEAAuB,CAAA;AAEnD,kEAAkE;AAClE,eAAO,MAAM,OAAO,EAAE,CAAC,CAAC,KAAK,CAC3B;IACE,OAAO,MAAM;IACb,OAAO,MAAM;IACb,OAAO,uBAAuB;IAC9B,OAAO,eAAe;CACvB,CACkE,CAAA;AACrE,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAEzC,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AACvC,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AAIvC,uRAAuR;AACvR,eAAO,MAAM,qBAAqB,0EAA6B,CAAA;AAC/D,iIAAiI;AACjI,eAAO,MAAM,eAAe,oEAAuB,CAAA;AAEnD,eAAO,MAAM,UAAU,yJAAkD,CAAA;AACzE,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,6EAA6E;AAC7E,eAAO,MAAM,IAAI,GAAI,QAAQ,UAAU,KAAG,KAIxC,CAAA"}
@@ -0,0 +1,35 @@
1
+ import { Schema as S } from 'effect';
2
+ import { m } from '../../message';
3
+ // TRANSITION STATE
4
+ /** Schema for the transition animation state, tracking enter/leave phases for CSS transition coordination. */
5
+ export const TransitionState = S.Literal('Idle', 'EnterStart', 'EnterAnimating', 'LeaveStart', 'LeaveAnimating');
6
+ // MODEL
7
+ /** Schema for the transition component's state, tracking its unique ID, visibility intent, and animation phase. */
8
+ export const Model = S.Struct({
9
+ id: S.String,
10
+ isShowing: S.Boolean,
11
+ transitionState: TransitionState,
12
+ });
13
+ // MESSAGE
14
+ /** Sent when the transition should enter (become visible). Starts the enter animation sequence. */
15
+ export const Showed = m('Showed');
16
+ /** Sent when the transition should leave (become hidden). Starts the leave animation sequence. */
17
+ export const Hidden = m('Hidden');
18
+ /** Sent internally when a double-rAF completes, advancing the transition to its animating phase. */
19
+ export const AdvancedTransitionFrame = m('AdvancedTransitionFrame');
20
+ /** Sent internally when all CSS transitions on the transition element have completed. */
21
+ export const EndedTransition = m('EndedTransition');
22
+ /** Union of all messages the transition component can produce. */
23
+ export const Message = S.Union(Showed, Hidden, AdvancedTransitionFrame, EndedTransition);
24
+ // OUT MESSAGE
25
+ /** Sent to the parent when the leave transition advances to LeaveAnimating. The parent is responsible for providing the command that detects when the leave animation completes (e.g. WaitForTransitions or a racing command). Use `defaultLeaveCommand` for the standard behavior. */
26
+ export const StartedLeaveAnimating = m('StartedLeaveAnimating');
27
+ /** Sent to the parent when the leave animation completes. The parent can use this to unmount content or update its own state. */
28
+ export const TransitionedOut = m('TransitionedOut');
29
+ export const OutMessage = S.Union(StartedLeaveAnimating, TransitionedOut);
30
+ /** Creates an initial transition model from a config. Defaults to hidden. */
31
+ export const init = (config) => ({
32
+ id: config.id,
33
+ isShowing: config.isShowing ?? false,
34
+ transitionState: 'Idle',
35
+ });