foldkit 0.100.1 → 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 (217) hide show
  1. package/README.md +3 -2
  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 +156 -149
  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 +11 -11
  56. package/dist/runtime/runtime.d.ts.map +1 -1
  57. package/dist/runtime/runtime.js +118 -63
  58. package/dist/runtime/subscription.d.ts +139 -19
  59. package/dist/runtime/subscription.d.ts.map +1 -1
  60. package/dist/runtime/subscription.js +90 -9
  61. package/dist/submodel/public.d.ts +4 -0
  62. package/dist/submodel/public.d.ts.map +1 -0
  63. package/dist/submodel/public.js +1 -0
  64. package/dist/submodel/submodel.d.ts +32 -0
  65. package/dist/submodel/submodel.d.ts.map +1 -0
  66. package/dist/submodel/submodel.js +1 -0
  67. package/dist/subscription/animationFrame.d.ts +23 -26
  68. package/dist/subscription/animationFrame.d.ts.map +1 -1
  69. package/dist/subscription/animationFrame.js +17 -18
  70. package/dist/subscription/public.d.ts +2 -2
  71. package/dist/subscription/public.d.ts.map +1 -1
  72. package/dist/subscription/public.js +1 -1
  73. package/dist/test/apps/disabledButton.d.ts +4 -5
  74. package/dist/test/apps/disabledButton.d.ts.map +1 -1
  75. package/dist/test/apps/disabledButton.js +16 -16
  76. package/dist/test/scene.d.ts +8 -8
  77. package/dist/test/scene.d.ts.map +1 -1
  78. package/dist/test/scene.js +25 -13
  79. package/dist/test/story.d.ts +15 -8
  80. package/dist/test/story.d.ts.map +1 -1
  81. package/dist/test/story.js +21 -9
  82. package/dist/ui/animation/index.d.ts +30 -14
  83. package/dist/ui/animation/index.d.ts.map +1 -1
  84. package/dist/ui/animation/index.js +9 -19
  85. package/dist/ui/animation/public.d.ts +2 -2
  86. package/dist/ui/animation/public.d.ts.map +1 -1
  87. package/dist/ui/animation/public.js +1 -1
  88. package/dist/ui/calendar/index.d.ts +199 -84
  89. package/dist/ui/calendar/index.d.ts.map +1 -1
  90. package/dist/ui/calendar/index.js +129 -140
  91. package/dist/ui/calendar/public.d.ts +2 -2
  92. package/dist/ui/calendar/public.d.ts.map +1 -1
  93. package/dist/ui/calendar/public.js +1 -1
  94. package/dist/ui/checkbox/index.d.ts +93 -21
  95. package/dist/ui/checkbox/index.d.ts.map +1 -1
  96. package/dist/ui/checkbox/index.js +62 -33
  97. package/dist/ui/checkbox/public.d.ts +2 -2
  98. package/dist/ui/checkbox/public.d.ts.map +1 -1
  99. package/dist/ui/checkbox/public.js +1 -1
  100. package/dist/ui/combobox/multi.d.ts +35 -91
  101. package/dist/ui/combobox/multi.d.ts.map +1 -1
  102. package/dist/ui/combobox/multi.js +34 -17
  103. package/dist/ui/combobox/multiPublic.d.ts +2 -2
  104. package/dist/ui/combobox/multiPublic.d.ts.map +1 -1
  105. package/dist/ui/combobox/multiPublic.js +1 -1
  106. package/dist/ui/combobox/public.d.ts +3 -3
  107. package/dist/ui/combobox/public.d.ts.map +1 -1
  108. package/dist/ui/combobox/public.js +2 -2
  109. package/dist/ui/combobox/shared.d.ts +56 -31
  110. package/dist/ui/combobox/shared.d.ts.map +1 -1
  111. package/dist/ui/combobox/shared.js +333 -322
  112. package/dist/ui/combobox/single.d.ts +46 -93
  113. package/dist/ui/combobox/single.d.ts.map +1 -1
  114. package/dist/ui/combobox/single.js +44 -17
  115. package/dist/ui/datePicker/index.d.ts +256 -48
  116. package/dist/ui/datePicker/index.d.ts.map +1 -1
  117. package/dist/ui/datePicker/index.js +149 -104
  118. package/dist/ui/datePicker/public.d.ts +2 -2
  119. package/dist/ui/datePicker/public.d.ts.map +1 -1
  120. package/dist/ui/datePicker/public.js +1 -1
  121. package/dist/ui/dialog/index.d.ts +95 -39
  122. package/dist/ui/dialog/index.d.ts.map +1 -1
  123. package/dist/ui/dialog/index.js +71 -62
  124. package/dist/ui/dialog/public.d.ts +2 -2
  125. package/dist/ui/dialog/public.d.ts.map +1 -1
  126. package/dist/ui/dialog/public.js +1 -1
  127. package/dist/ui/disclosure/index.d.ts +71 -31
  128. package/dist/ui/disclosure/index.d.ts.map +1 -1
  129. package/dist/ui/disclosure/index.js +57 -62
  130. package/dist/ui/disclosure/public.d.ts +2 -2
  131. package/dist/ui/disclosure/public.d.ts.map +1 -1
  132. package/dist/ui/disclosure/public.js +1 -1
  133. package/dist/ui/dragAndDrop/index.d.ts +385 -103
  134. package/dist/ui/dragAndDrop/index.d.ts.map +1 -1
  135. package/dist/ui/dragAndDrop/index.js +26 -31
  136. package/dist/ui/dragAndDrop/public.d.ts +1 -1
  137. package/dist/ui/dragAndDrop/public.d.ts.map +1 -1
  138. package/dist/ui/dragAndDrop/public.js +1 -1
  139. package/dist/ui/fileDrop/index.d.ts +42 -46
  140. package/dist/ui/fileDrop/index.d.ts.map +1 -1
  141. package/dist/ui/fileDrop/index.js +30 -46
  142. package/dist/ui/fileDrop/public.d.ts +2 -2
  143. package/dist/ui/fileDrop/public.d.ts.map +1 -1
  144. package/dist/ui/fileDrop/public.js +1 -1
  145. package/dist/ui/listbox/multi.d.ts +39 -84
  146. package/dist/ui/listbox/multi.d.ts.map +1 -1
  147. package/dist/ui/listbox/multi.js +38 -20
  148. package/dist/ui/listbox/multiPublic.d.ts +2 -2
  149. package/dist/ui/listbox/multiPublic.d.ts.map +1 -1
  150. package/dist/ui/listbox/multiPublic.js +1 -1
  151. package/dist/ui/listbox/public.d.ts +3 -3
  152. package/dist/ui/listbox/public.d.ts.map +1 -1
  153. package/dist/ui/listbox/public.js +2 -2
  154. package/dist/ui/listbox/shared.d.ts +71 -30
  155. package/dist/ui/listbox/shared.d.ts.map +1 -1
  156. package/dist/ui/listbox/shared.js +319 -296
  157. package/dist/ui/listbox/single.d.ts +57 -85
  158. package/dist/ui/listbox/single.d.ts.map +1 -1
  159. package/dist/ui/listbox/single.js +48 -24
  160. package/dist/ui/menu/index.d.ts +80 -36
  161. package/dist/ui/menu/index.d.ts.map +1 -1
  162. package/dist/ui/menu/index.js +117 -86
  163. package/dist/ui/menu/public.d.ts +2 -2
  164. package/dist/ui/menu/public.d.ts.map +1 -1
  165. package/dist/ui/menu/public.js +1 -1
  166. package/dist/ui/popover/index.d.ts +117 -44
  167. package/dist/ui/popover/index.d.ts.map +1 -1
  168. package/dist/ui/popover/index.js +88 -101
  169. package/dist/ui/popover/public.d.ts +2 -2
  170. package/dist/ui/popover/public.d.ts.map +1 -1
  171. package/dist/ui/popover/public.js +1 -1
  172. package/dist/ui/radioGroup/index.d.ts +122 -45
  173. package/dist/ui/radioGroup/index.d.ts.map +1 -1
  174. package/dist/ui/radioGroup/index.js +111 -72
  175. package/dist/ui/radioGroup/public.d.ts +2 -2
  176. package/dist/ui/radioGroup/public.d.ts.map +1 -1
  177. package/dist/ui/radioGroup/public.js +1 -1
  178. package/dist/ui/slider/index.d.ts +247 -103
  179. package/dist/ui/slider/index.d.ts.map +1 -1
  180. package/dist/ui/slider/index.js +52 -68
  181. package/dist/ui/slider/public.d.ts +2 -2
  182. package/dist/ui/slider/public.d.ts.map +1 -1
  183. package/dist/ui/slider/public.js +1 -1
  184. package/dist/ui/switch/index.d.ts +74 -21
  185. package/dist/ui/switch/index.d.ts.map +1 -1
  186. package/dist/ui/switch/index.js +62 -33
  187. package/dist/ui/switch/public.d.ts +2 -2
  188. package/dist/ui/switch/public.d.ts.map +1 -1
  189. package/dist/ui/switch/public.js +1 -1
  190. package/dist/ui/tabs/index.d.ts +107 -45
  191. package/dist/ui/tabs/index.d.ts.map +1 -1
  192. package/dist/ui/tabs/index.js +99 -81
  193. package/dist/ui/tabs/public.d.ts +2 -2
  194. package/dist/ui/tabs/public.d.ts.map +1 -1
  195. package/dist/ui/tabs/public.js +1 -1
  196. package/dist/ui/toast/index.d.ts +93 -109
  197. package/dist/ui/toast/index.d.ts.map +1 -1
  198. package/dist/ui/toast/index.js +16 -29
  199. package/dist/ui/toast/schema.d.ts +15 -4
  200. package/dist/ui/toast/schema.d.ts.map +1 -1
  201. package/dist/ui/toast/schema.js +11 -4
  202. package/dist/ui/toast/update.d.ts +36 -18
  203. package/dist/ui/toast/update.d.ts.map +1 -1
  204. package/dist/ui/toast/update.js +33 -14
  205. package/dist/ui/tooltip/index.d.ts +94 -42
  206. package/dist/ui/tooltip/index.d.ts.map +1 -1
  207. package/dist/ui/tooltip/index.js +64 -73
  208. package/dist/ui/tooltip/public.d.ts +2 -2
  209. package/dist/ui/tooltip/public.d.ts.map +1 -1
  210. package/dist/ui/tooltip/public.js +1 -1
  211. package/dist/ui/virtualList/index.d.ts +63 -80
  212. package/dist/ui/virtualList/index.d.ts.map +1 -1
  213. package/dist/ui/virtualList/index.js +22 -49
  214. package/dist/ui/virtualList/public.d.ts +2 -2
  215. package/dist/ui/virtualList/public.d.ts.map +1 -1
  216. package/dist/ui/virtualList/public.js +1 -1
  217. package/package.json +1 -1
@@ -1,6 +1,6 @@
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 } from '../../html/index.js';
3
+ import { type ChildAttribute, type Html } from '../../html/index.js';
4
4
  import * as Mount from '../../mount/index.js';
5
5
  import { AnchorConfig } from '../anchor.js';
6
6
  /** Schema for the popover component's state, tracking open/closed status and animation lifecycle. */
@@ -18,10 +18,10 @@ export declare const Model: S.Struct<{
18
18
  readonly maybeLastButtonPointerType: S.Option<S.String>;
19
19
  }>;
20
20
  export type Model = typeof Model.Type;
21
- /** Sent when the popover opens via button click or keyboard activation. */
22
- export declare const Opened: import("../../schema/index.js").CallableTaggedStruct<"Opened", {}>;
23
- /** Sent when the popover closes via Escape key or backdrop click. Returns focus to the button. */
24
- export declare const Closed: import("../../schema/index.js").CallableTaggedStruct<"Closed", {}>;
21
+ /** Sent when the popover should open via button click or keyboard activation. */
22
+ export declare const RequestedOpen: import("../../schema/index.js").CallableTaggedStruct<"RequestedOpen", {}>;
23
+ /** Sent when the popover should close via Escape key or backdrop click. Returns focus to the button. */
24
+ export declare const RequestedClose: import("../../schema/index.js").CallableTaggedStruct<"RequestedClose", {}>;
25
25
  /** Sent when the popover panel loses focus. Does NOT return focus to the button. */
26
26
  export declare const BlurredPanel: import("../../schema/index.js").CallableTaggedStruct<"BlurredPanel", {}>;
27
27
  /** Sent when the user presses a pointer device on the popover button. Records pointer type and toggles for mouse. */
@@ -38,9 +38,9 @@ export declare const CompletedLockScroll: import("../../schema/index.js").Callab
38
38
  /** Sent when the scroll unlock command completes. */
39
39
  export declare const CompletedUnlockScroll: import("../../schema/index.js").CallableTaggedStruct<"CompletedUnlockScroll", {}>;
40
40
  /** Sent when the inert-others command completes. */
41
- export declare const CompletedSetupInert: import("../../schema/index.js").CallableTaggedStruct<"CompletedSetupInert", {}>;
41
+ export declare const CompletedInertOthers: import("../../schema/index.js").CallableTaggedStruct<"CompletedInertOthers", {}>;
42
42
  /** Sent when the restore-inert command completes. */
43
- export declare const CompletedTeardownInert: import("../../schema/index.js").CallableTaggedStruct<"CompletedTeardownInert", {}>;
43
+ export declare const CompletedRestoreInert: import("../../schema/index.js").CallableTaggedStruct<"CompletedRestoreInert", {}>;
44
44
  /** Sent when a mouse click on the button is ignored because pointer-down already handled the toggle. */
45
45
  export declare const IgnoredMouseClick: import("../../schema/index.js").CallableTaggedStruct<"IgnoredMouseClick", {}>;
46
46
  /** Sent when a Space key-up is captured to prevent page scrolling. */
@@ -55,30 +55,39 @@ export declare const GotAnimationMessage: import("../../schema/index.js").Callab
55
55
  }>;
56
56
  /** Union of all messages the popover component can produce. */
57
57
  export declare const Message: S.Union<[
58
- typeof Opened,
59
- typeof Closed,
58
+ typeof RequestedOpen,
59
+ typeof RequestedClose,
60
60
  typeof BlurredPanel,
61
61
  typeof PressedPointerOnButton,
62
62
  typeof CompletedFocusPanel,
63
63
  typeof CompletedFocusButton,
64
64
  typeof CompletedLockScroll,
65
65
  typeof CompletedUnlockScroll,
66
- typeof CompletedSetupInert,
67
- typeof CompletedTeardownInert,
66
+ typeof CompletedInertOthers,
67
+ typeof CompletedRestoreInert,
68
68
  typeof IgnoredMouseClick,
69
69
  typeof SuppressedSpaceScroll,
70
70
  typeof CompletedAnchorPopover,
71
71
  typeof CompletedPortalPopoverBackdrop,
72
72
  typeof GotAnimationMessage
73
73
  ]>;
74
- export type Opened = typeof Opened.Type;
75
- export type Closed = typeof Closed.Type;
74
+ export type RequestedOpen = typeof RequestedOpen.Type;
75
+ export type RequestedClose = typeof RequestedClose.Type;
76
76
  export type BlurredPanel = typeof BlurredPanel.Type;
77
77
  export type PressedPointerOnButton = typeof PressedPointerOnButton.Type;
78
78
  export type IgnoredMouseClick = typeof IgnoredMouseClick.Type;
79
79
  export type SuppressedSpaceScroll = typeof SuppressedSpaceScroll.Type;
80
80
  export type Message = typeof Message.Type;
81
- /** Configuration for creating a popover model with `init`. `isAnimated` enables animation coordination (default `false`). `isModal` locks page scroll and inerts other elements when open (default `false`). `contentFocus` hands focus ownership to the consumer — the panel is not focusable and does not close on blur, so the consumer must focus a descendant on open and close the popover on its own blur rules (default `false`). */
81
+ /** Sent to the parent after the popover transitions to its open state. Fires once `update` has processed `RequestedOpen` and `isOpen` reflects the new state. */
82
+ export declare const Opened: import("../../schema/index.js").CallableTaggedStruct<"Opened", {}>;
83
+ /** Sent to the parent after the popover transitions to its closed state. */
84
+ export declare const Closed: import("../../schema/index.js").CallableTaggedStruct<"Closed", {}>;
85
+ /** Union of out-messages the popover component can produce. Parents reacting to open/close transitions (e.g. to reset related state, fire analytics) read this from the third element of `update`'s return tuple. */
86
+ export declare const OutMessage: S.Union<readonly [import("../../schema/index.js").CallableTaggedStruct<"Opened", {}>, import("../../schema/index.js").CallableTaggedStruct<"Closed", {}>]>;
87
+ export type OutMessage = typeof OutMessage.Type;
88
+ export type Opened = typeof Opened.Type;
89
+ export type Closed = typeof Closed.Type;
90
+ /** Configuration for creating a popover model with `init`. `isAnimated` enables animation coordination (default `false`). `isModal` locks page scroll and inerts other elements when open (default `false`). `contentFocus` hands focus ownership to the consumer. The panel is not focusable and does not close on blur, so the consumer must focus a descendant on open and close the popover on its own blur rules (default `false`). */
82
91
  export type InitConfig = Readonly<{
83
92
  id: string;
84
93
  isAnimated?: boolean;
@@ -87,7 +96,11 @@ export type InitConfig = Readonly<{
87
96
  }>;
88
97
  /** Creates an initial popover model from a config. Defaults to closed. */
89
98
  export declare const init: (config: InitConfig) => Model;
90
- type UpdateReturn = readonly [Model, ReadonlyArray<Command.Command<Message>>];
99
+ type UpdateReturn = readonly [
100
+ Model,
101
+ ReadonlyArray<Command.Command<Message>>,
102
+ Option.Option<OutMessage>
103
+ ];
91
104
  /** Prevents page scrolling while the popover is open in modal mode. */
92
105
  export declare const LockScroll: Command.CommandDefinitionNoArgs<"LockScroll", Effect.Effect<{
93
106
  readonly _tag: "CompletedLockScroll";
@@ -100,13 +113,13 @@ export declare const UnlockScroll: Command.CommandDefinitionNoArgs<"UnlockScroll
100
113
  export declare const InertOthers: Command.CommandDefinitionWithArgs<"InertOthers", {
101
114
  id: S.String;
102
115
  }, Effect.Effect<{
103
- readonly _tag: "CompletedSetupInert";
116
+ readonly _tag: "CompletedInertOthers";
104
117
  }, never, never>>;
105
118
  /** Removes the inert attribute from elements outside the popover. */
106
119
  export declare const RestoreInert: Command.CommandDefinitionWithArgs<"RestoreInert", {
107
120
  id: S.String;
108
121
  }, Effect.Effect<{
109
- readonly _tag: "CompletedTeardownInert";
122
+ readonly _tag: "CompletedRestoreInert";
110
123
  }, never, never>>;
111
124
  /** Moves focus to the popover panel after opening. */
112
125
  export declare const FocusPanel: Command.CommandDefinitionWithArgs<"FocusPanel", {
@@ -135,7 +148,7 @@ export declare const DetectMovementOrAnimationEnd: Command.CommandDefinitionWith
135
148
  readonly _tag: "EndedAnimation";
136
149
  };
137
150
  }, never, never>>;
138
- /** Processes a popover message and returns the next model and commands. */
151
+ /** Processes a popover message and returns the next model, commands, and optional OutMessage. */
139
152
  export declare const update: (model: Model, message: Message) => UpdateReturn;
140
153
  /** The anchor-positioning Mount this Popover renders on its panel. Exposed so
141
154
  * Scene tests can call `Scene.Mount.resolve(AnchorPopover, CompletedAnchorPopover())`
@@ -160,35 +173,95 @@ export declare const PortalPopoverBackdrop: Mount.MountDefinitionNoArgs<"PortalP
160
173
  readonly _tag: "CompletedPortalPopoverBackdrop";
161
174
  }>;
162
175
  /** Programmatically opens the popover, updating the model and returning
163
- * focus and modal commands. Use this in domain-event handlers when the popover uses `onOpened`. */
164
- export declare const open: (model: Model) => readonly [Model, ReadonlyArray<Command.Command<Message>>];
176
+ * focus and modal commands plus an `Opened` OutMessage. */
177
+ export declare const open: (model: Model) => UpdateReturn;
165
178
  /** Programmatically closes the popover, updating the model and returning
166
- * focus and modal commands. Use this in domain-event handlers when the popover uses `onClosed`. */
167
- export declare const close: (model: Model) => readonly [Model, ReadonlyArray<Command.Command<Message>>];
168
- /** Configuration for rendering a popover with `view`. */
169
- export type ViewConfig<ParentMessage> = Readonly<{
170
- model: Model;
171
- toParentMessage: (message: Opened | Closed | BlurredPanel | PressedPointerOnButton | IgnoredMouseClick | SuppressedSpaceScroll | typeof CompletedAnchorPopover.Type | typeof CompletedPortalPopoverBackdrop.Type) => ParentMessage;
172
- onOpened?: () => ParentMessage;
173
- onClosed?: () => ParentMessage;
179
+ * focus and modal commands plus a `Closed` OutMessage when it was open. */
180
+ export declare const close: (model: Model) => UpdateReturn;
181
+ /** Render-time payload published to the consumer's `toView`.
182
+ *
183
+ * - `button`: attribute bundle for the trigger button.
184
+ * - `panel`: attribute bundle for the floating panel. Includes the
185
+ * anchor Mount that positions the panel via Floating UI, ARIA
186
+ * linkage to the button, and panel keydown/blur handlers.
187
+ * - `backdrop`: attribute bundle for the modal backdrop. Includes the
188
+ * portal Mount that moves the backdrop to document.body. The
189
+ * backdrop's OnClick closes the popover.
190
+ * - `isVisible`: derived from `isOpen` and the Animation
191
+ * `transitionState`. The consumer renders the panel + backdrop only
192
+ * while this is true. */
193
+ export type RenderInfo = Readonly<{
194
+ button: ReadonlyArray<ChildAttribute>;
195
+ panel: ReadonlyArray<ChildAttribute>;
196
+ backdrop: ReadonlyArray<ChildAttribute>;
197
+ isVisible: boolean;
198
+ }>;
199
+ /** Per-render view inputs passed to `view` via `h.submodel`'s `viewInputs` field. */
200
+ export type ViewInputs = Readonly<{
174
201
  anchor: AnchorConfig;
175
- buttonContent: Html;
176
- buttonClassName?: string;
177
- buttonAttributes?: ReadonlyArray<Attribute<ParentMessage>>;
178
- panelContent: Html;
179
- panelClassName?: string;
180
- panelAttributes?: ReadonlyArray<Attribute<ParentMessage>>;
181
- backdropClassName?: string;
182
- backdropAttributes?: ReadonlyArray<Attribute<ParentMessage>>;
202
+ toView: (render: RenderInfo) => Html;
183
203
  isDisabled?: boolean;
184
204
  focusSelector?: string;
185
- className?: string;
186
- attributes?: ReadonlyArray<Attribute<ParentMessage>>;
187
205
  }>;
188
- /** 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
- export declare const view: <ParentMessage>(config: ViewConfig<ParentMessage>) => Html;
190
- /** Creates a memoized popover view. Static config is captured in a closure;
191
- * only `model` and `toParentMessage` are compared per render via `createLazy`. */
192
- export declare const lazy: <ParentMessage>(staticConfig: Omit<ViewConfig<ParentMessage>, "model" | "toParentMessage" | "onOpened" | "onClosed">) => ((model: Model, toParentMessage: ViewConfig<ParentMessage>["toParentMessage"]) => Html);
206
+ /** Renders a headless popover with a trigger button and a floating panel. */
207
+ export declare const view: import("../../html/submodel.js").SubmodelView<{
208
+ readonly id: string;
209
+ readonly isOpen: boolean;
210
+ readonly isAnimated: boolean;
211
+ readonly isModal: boolean;
212
+ readonly contentFocus: boolean;
213
+ readonly animation: {
214
+ readonly id: string;
215
+ readonly isShowing: boolean;
216
+ readonly transitionState: "Idle" | "EnterStart" | "EnterAnimating" | "LeaveStart" | "LeaveAnimating";
217
+ };
218
+ readonly maybeLastButtonPointerType: Option.Option<string>;
219
+ }, {
220
+ readonly _tag: "CompletedLockScroll";
221
+ } | {
222
+ readonly _tag: "CompletedUnlockScroll";
223
+ } | {
224
+ readonly _tag: "CompletedInertOthers";
225
+ } | {
226
+ readonly _tag: "CompletedRestoreInert";
227
+ } | {
228
+ readonly _tag: "CompletedFocusButton";
229
+ } | {
230
+ readonly _tag: "IgnoredMouseClick";
231
+ } | {
232
+ readonly _tag: "SuppressedSpaceScroll";
233
+ } | {
234
+ readonly _tag: "RequestedOpen";
235
+ } | {
236
+ readonly _tag: "RequestedClose";
237
+ } | {
238
+ readonly _tag: "BlurredPanel";
239
+ } | {
240
+ readonly _tag: "PressedPointerOnButton";
241
+ readonly pointerType: string;
242
+ readonly button: number;
243
+ } | {
244
+ readonly _tag: "CompletedFocusPanel";
245
+ } | {
246
+ readonly _tag: "CompletedAnchorPopover";
247
+ } | {
248
+ readonly _tag: "CompletedPortalPopoverBackdrop";
249
+ } | {
250
+ readonly _tag: "GotAnimationMessage";
251
+ readonly message: {
252
+ readonly _tag: "Showed";
253
+ } | {
254
+ readonly _tag: "Hid";
255
+ } | {
256
+ readonly _tag: "AdvancedAnimationFrame";
257
+ } | {
258
+ readonly _tag: "EndedAnimation";
259
+ };
260
+ }, Readonly<{
261
+ anchor: AnchorConfig;
262
+ toView: (render: RenderInfo) => Html;
263
+ isDisabled?: boolean;
264
+ focusSelector?: string;
265
+ }>>;
193
266
  export {};
194
267
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/popover/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/ui/popover/index.ts"],"names":[],"mappings":"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"}
@@ -2,7 +2,7 @@ import { Array, Effect, Equal, 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
4
  import { OptionExt } from '../../effectExtensions/index.js';
5
- import { createLazy, html, } from '../../html/index.js';
5
+ import { childAttributes, defineView, html, } from '../../html/index.js';
6
6
  import { m } from '../../message/index.js';
7
7
  import * as Mount from '../../mount/index.js';
8
8
  import { evo } from '../../struct/index.js';
@@ -24,10 +24,10 @@ export const Model = S.Struct({
24
24
  maybeLastButtonPointerType: S.Option(S.String),
25
25
  });
26
26
  // MESSAGE
27
- /** Sent when the popover opens via button click or keyboard activation. */
28
- export const Opened = m('Opened');
29
- /** Sent when the popover closes via Escape key or backdrop click. Returns focus to the button. */
30
- export const Closed = m('Closed');
27
+ /** Sent when the popover should open via button click or keyboard activation. */
28
+ export const RequestedOpen = m('RequestedOpen');
29
+ /** Sent when the popover should close via Escape key or backdrop click. Returns focus to the button. */
30
+ export const RequestedClose = m('RequestedClose');
31
31
  /** Sent when the popover panel loses focus. Does NOT return focus to the button. */
32
32
  export const BlurredPanel = m('BlurredPanel');
33
33
  /** Sent when the user presses a pointer device on the popover button. Records pointer type and toggles for mouse. */
@@ -44,9 +44,9 @@ export const CompletedLockScroll = m('CompletedLockScroll');
44
44
  /** Sent when the scroll unlock command completes. */
45
45
  export const CompletedUnlockScroll = m('CompletedUnlockScroll');
46
46
  /** Sent when the inert-others command completes. */
47
- export const CompletedSetupInert = m('CompletedSetupInert');
47
+ export const CompletedInertOthers = m('CompletedInertOthers');
48
48
  /** Sent when the restore-inert command completes. */
49
- export const CompletedTeardownInert = m('CompletedTeardownInert');
49
+ export const CompletedRestoreInert = m('CompletedRestoreInert');
50
50
  /** Sent when a mouse click on the button is ignored because pointer-down already handled the toggle. */
51
51
  export const IgnoredMouseClick = m('IgnoredMouseClick');
52
52
  /** Sent when a Space key-up is captured to prevent page scrolling. */
@@ -61,22 +61,29 @@ export const GotAnimationMessage = m('GotAnimationMessage', {
61
61
  });
62
62
  /** Union of all messages the popover component can produce. */
63
63
  export const Message = S.Union([
64
- Opened,
65
- Closed,
64
+ RequestedOpen,
65
+ RequestedClose,
66
66
  BlurredPanel,
67
67
  PressedPointerOnButton,
68
68
  CompletedFocusPanel,
69
69
  CompletedFocusButton,
70
70
  CompletedLockScroll,
71
71
  CompletedUnlockScroll,
72
- CompletedSetupInert,
73
- CompletedTeardownInert,
72
+ CompletedInertOthers,
73
+ CompletedRestoreInert,
74
74
  IgnoredMouseClick,
75
75
  SuppressedSpaceScroll,
76
76
  CompletedAnchorPopover,
77
77
  CompletedPortalPopoverBackdrop,
78
78
  GotAnimationMessage,
79
79
  ]);
80
+ // OUT MESSAGE
81
+ /** Sent to the parent after the popover transitions to its open state. Fires once `update` has processed `RequestedOpen` and `isOpen` reflects the new state. */
82
+ export const Opened = m('Opened');
83
+ /** Sent to the parent after the popover transitions to its closed state. */
84
+ export const Closed = m('Closed');
85
+ /** Union of out-messages the popover component can produce. Parents reacting to open/close transitions (e.g. to reset related state, fire analytics) read this from the third element of `update`'s return tuple. */
86
+ export const OutMessage = S.Union([Opened, Closed]);
80
87
  // INIT
81
88
  const LEFT_MOUSE_BUTTON = 0;
82
89
  /** Creates an initial popover model from a config. Defaults to closed. */
@@ -102,9 +109,9 @@ export const LockScroll = Command.define('LockScroll', CompletedLockScroll)(Dom.
102
109
  /** Re-enables page scrolling after the popover closes. */
103
110
  export const UnlockScroll = Command.define('UnlockScroll', CompletedUnlockScroll)(Dom.unlockScroll.pipe(Effect.as(CompletedUnlockScroll())));
104
111
  /** Marks all elements outside the popover as inert for modal behavior. */
105
- export const InertOthers = Command.define('InertOthers', { id: S.String }, CompletedSetupInert)(({ id }) => Dom.inertOthers(id, [buttonSelector(id), panelSelector(id)]).pipe(Effect.as(CompletedSetupInert())));
112
+ export const InertOthers = Command.define('InertOthers', { id: S.String }, CompletedInertOthers)(({ id }) => Dom.inertOthers(id, [buttonSelector(id), panelSelector(id)]).pipe(Effect.as(CompletedInertOthers())));
106
113
  /** Removes the inert attribute from elements outside the popover. */
107
- export const RestoreInert = Command.define('RestoreInert', { id: S.String }, CompletedTeardownInert)(({ id }) => Dom.restoreInert(id).pipe(Effect.as(CompletedTeardownInert())));
114
+ export const RestoreInert = Command.define('RestoreInert', { id: S.String }, CompletedRestoreInert)(({ id }) => Dom.restoreInert(id).pipe(Effect.as(CompletedRestoreInert())));
108
115
  /** Moves focus to the popover panel after opening. */
109
116
  export const FocusPanel = Command.define('FocusPanel', { id: S.String }, CompletedFocusPanel)(({ id }) => Dom.focus(panelSelector(id)).pipe(Effect.ignore, Effect.as(CompletedFocusPanel())));
110
117
  /** Moves focus back to the popover button after closing. */
@@ -113,7 +120,7 @@ export const FocusButton = Command.define('FocusButton', { id: S.String }, Compl
113
120
  export const DetectMovementOrAnimationEnd = Command.define('DetectMovementOrAnimationEnd', { id: S.String }, GotAnimationMessage)(({ id }) => Effect.raceFirst(Dom.detectElementMovement(buttonSelector(id)).pipe(Effect.as(GotAnimationMessage({ message: AnimationEndedAnimation() }))), Dom.waitForAnimationSettled(panelSelector(id)).pipe(Effect.as(GotAnimationMessage({ message: AnimationEndedAnimation() })))));
114
121
  const delegateToAnimation = (model, animationMessage) => {
115
122
  const [nextAnimation, animationCommands, maybeOutMessage] = animationUpdate(model.animation, animationMessage);
116
- const mappedCommands = animationCommands.map(Command.mapEffect(Effect.map(message => GotAnimationMessage({ message }))));
123
+ const mappedCommands = Command.mapMessages(animationCommands, message => GotAnimationMessage({ message }));
117
124
  const additionalCommands = Option.match(maybeOutMessage, {
118
125
  onNone: () => [],
119
126
  onSome: M.type().pipe(M.tagsExhaustive({
@@ -126,9 +133,10 @@ const delegateToAnimation = (model, animationMessage) => {
126
133
  return [
127
134
  evo(model, { animation: () => nextAnimation }),
128
135
  [...mappedCommands, ...additionalCommands],
136
+ Option.none(),
129
137
  ];
130
138
  };
131
- /** Processes a popover message and returns the next model and commands. */
139
+ /** Processes a popover message and returns the next model, commands, and optional OutMessage. */
132
140
  export const update = (model, message) => {
133
141
  const maybeLockScroll = OptionExt.when(model.isModal, LockScroll());
134
142
  const maybeUnlockScroll = OptionExt.when(model.isModal, UnlockScroll());
@@ -150,24 +158,36 @@ export const update = (model, message) => {
150
158
  return [
151
159
  evo(nextModel, { isOpen: () => true }),
152
160
  [...openCommands, ...animationCommands],
161
+ Option.some(Opened()),
153
162
  ];
154
163
  }
155
- return [evo(baseModel, { isOpen: () => true }), openCommands];
164
+ return [
165
+ evo(baseModel, { isOpen: () => true }),
166
+ openCommands,
167
+ Option.some(Opened()),
168
+ ];
156
169
  };
157
170
  const closePopover = (baseModel, commands) => {
171
+ if (!baseModel.isOpen) {
172
+ return [baseModel, commands, Option.none()];
173
+ }
158
174
  const closed = closedModel(baseModel);
159
175
  if (model.isAnimated) {
160
176
  const [nextModel, animationCommands] = delegateToAnimation(closed, AnimationHid());
161
- return [nextModel, [...commands, ...animationCommands]];
177
+ return [
178
+ nextModel,
179
+ [...commands, ...animationCommands],
180
+ Option.some(Closed()),
181
+ ];
162
182
  }
163
- return [closed, commands];
183
+ return [closed, commands, Option.some(Closed())];
164
184
  };
165
185
  return M.value(message).pipe(withUpdateReturn, M.tagsExhaustive({
166
- Opened: () => openPopover(model),
167
- Closed: () => closePopover(model, closeWithFocusCommands),
186
+ RequestedOpen: () => openPopover(model),
187
+ RequestedClose: () => closePopover(model, closeWithFocusCommands),
168
188
  BlurredPanel: () => {
169
189
  if (Option.exists(model.maybeLastButtonPointerType, Equal.equals('mouse'))) {
170
- return [model, []];
190
+ return [model, [], Option.none()];
171
191
  }
172
192
  return closePopover(model, closeWithoutFocusCommands);
173
193
  },
@@ -176,33 +196,35 @@ export const update = (model, message) => {
176
196
  maybeLastButtonPointerType: () => Option.some(pointerType),
177
197
  });
178
198
  if (pointerType !== 'mouse' || button !== LEFT_MOUSE_BUTTON) {
179
- return [withPointerType, []];
199
+ return [withPointerType, [], Option.none()];
180
200
  }
181
201
  if (model.isOpen) {
182
- const [closed, commands] = closePopover(withPointerType, closeWithFocusCommands);
202
+ const [closed, commands, maybeOutMessage] = closePopover(withPointerType, closeWithFocusCommands);
183
203
  return [
184
204
  evo(closed, {
185
205
  maybeLastButtonPointerType: () => Option.some(pointerType),
186
206
  }),
187
207
  commands,
208
+ maybeOutMessage,
188
209
  ];
189
210
  }
190
211
  return openPopover(withPointerType);
191
212
  },
192
213
  GotAnimationMessage: ({ message: animationMessage }) => delegateToAnimation(model, animationMessage),
193
- CompletedFocusPanel: () => [model, []],
194
- CompletedFocusButton: () => [model, []],
195
- CompletedLockScroll: () => [model, []],
196
- CompletedUnlockScroll: () => [model, []],
197
- CompletedSetupInert: () => [model, []],
198
- CompletedTeardownInert: () => [model, []],
214
+ CompletedFocusPanel: () => [model, [], Option.none()],
215
+ CompletedFocusButton: () => [model, [], Option.none()],
216
+ CompletedLockScroll: () => [model, [], Option.none()],
217
+ CompletedUnlockScroll: () => [model, [], Option.none()],
218
+ CompletedInertOthers: () => [model, [], Option.none()],
219
+ CompletedRestoreInert: () => [model, [], Option.none()],
199
220
  IgnoredMouseClick: () => [
200
221
  evo(model, { maybeLastButtonPointerType: () => Option.none() }),
201
222
  [],
223
+ Option.none(),
202
224
  ],
203
- SuppressedSpaceScroll: () => [model, []],
204
- CompletedAnchorPopover: () => [model, []],
205
- CompletedPortalPopoverBackdrop: () => [model, []],
225
+ SuppressedSpaceScroll: () => [model, [], Option.none()],
226
+ CompletedAnchorPopover: () => [model, [], Option.none()],
227
+ CompletedPortalPopoverBackdrop: () => [model, [], Option.none()],
206
228
  }));
207
229
  };
208
230
  /** The anchor-positioning Mount this Popover renders on its panel. Exposed so
@@ -230,17 +252,16 @@ export const PortalPopoverBackdrop = Mount.define('PortalPopoverBackdrop', Compl
230
252
  return CompletedPortalPopoverBackdrop();
231
253
  }));
232
254
  /** Programmatically opens the popover, updating the model and returning
233
- * focus and modal commands. Use this in domain-event handlers when the popover uses `onOpened`. */
234
- export const open = (model) => update(model, Opened());
255
+ * focus and modal commands plus an `Opened` OutMessage. */
256
+ export const open = (model) => update(model, RequestedOpen());
235
257
  /** Programmatically closes the popover, updating the model and returning
236
- * focus and modal commands. Use this in domain-event handlers when the popover uses `onClosed`. */
237
- export const close = (model) => update(model, Closed());
238
- /** 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. */
239
- export const view = (config) => {
258
+ * focus and modal commands plus a `Closed` OutMessage when it was open. */
259
+ export const close = (model) => update(model, RequestedClose());
260
+ /** Renders a headless popover with a trigger button and a floating panel. */
261
+ export const view = defineView((model, viewInputs) => {
240
262
  const h = html();
241
- const { model: { id, isOpen, contentFocus, animation: { transitionState }, maybeLastButtonPointerType, }, toParentMessage, onOpened, onClosed, anchor, buttonContent, buttonClassName, buttonAttributes = [], panelContent, panelClassName, panelAttributes = [], backdropClassName, backdropAttributes = [], isDisabled, focusSelector, className, attributes = [], } = config;
242
- const dispatchOpened = () => onOpened ? onOpened() : toParentMessage(Opened());
243
- const dispatchClosed = () => onClosed ? onClosed() : toParentMessage(Closed());
263
+ const { id, isOpen, contentFocus, animation: { transitionState }, maybeLastButtonPointerType, } = model;
264
+ const { anchor, toView, isDisabled, focusSelector } = viewInputs;
244
265
  const isLeaving = transitionState === 'LeaveStart' || transitionState === 'LeaveAnimating';
245
266
  const isVisible = isOpen || isLeaving;
246
267
  const animationAttributes = M.value(transitionState).pipe(M.when('EnterStart', () => [
@@ -258,26 +279,23 @@ export const view = (config) => {
258
279
  h.DataAttribute('leave', ''),
259
280
  h.DataAttribute('transition', ''),
260
281
  ]), M.orElse(() => []));
261
- const handleButtonKeyDown = (key) => M.value(key).pipe(M.whenOr('Enter', ' ', 'ArrowDown', () => Option.some(isOpen ? dispatchClosed() : dispatchOpened())), M.when('Escape', () => OptionExt.when(isOpen, dispatchClosed())), M.orElse(() => Option.none()));
262
- const handleButtonPointerDown = (pointerType, button) => Option.some(toParentMessage(PressedPointerOnButton({
263
- pointerType,
264
- button,
265
- })));
282
+ const handleButtonKeyDown = (key) => M.value(key).pipe(M.whenOr('Enter', ' ', 'ArrowDown', () => Option.some(isOpen ? RequestedClose() : RequestedOpen())), M.when('Escape', () => OptionExt.when(isOpen, RequestedClose())), M.orElse(() => Option.none()));
283
+ const handleButtonPointerDown = (pointerType, button) => Option.some(PressedPointerOnButton({ pointerType, button }));
266
284
  const handleButtonClick = () => {
267
285
  const isMouse = Option.exists(maybeLastButtonPointerType, type => type === 'mouse');
268
286
  if (isMouse) {
269
- return toParentMessage(IgnoredMouseClick());
287
+ return IgnoredMouseClick();
270
288
  }
271
289
  else if (isOpen) {
272
- return dispatchClosed();
290
+ return RequestedClose();
273
291
  }
274
292
  else {
275
- return dispatchOpened();
293
+ return RequestedOpen();
276
294
  }
277
295
  };
278
- const handleSpaceKeyUp = (key) => OptionExt.when(key === ' ', toParentMessage(SuppressedSpaceScroll()));
279
- const handlePanelKeyDown = (key) => M.value(key).pipe(M.when('Escape', () => Option.some(dispatchClosed())), M.orElse(() => Option.none()));
280
- const resolvedButtonAttributes = [
296
+ const handleSpaceKeyUp = (key) => OptionExt.when(key === ' ', SuppressedSpaceScroll());
297
+ const handlePanelKeyDown = (key) => M.value(key).pipe(M.when('Escape', () => Option.some(RequestedClose())), M.orElse(() => Option.none()));
298
+ const buttonAttributes = [
281
299
  h.Id(`${id}-button`),
282
300
  h.Type('button'),
283
301
  h.AriaExpanded(isVisible),
@@ -296,63 +314,32 @@ export const view = (config) => {
296
314
  h.Style({ position: 'relative', zIndex: '1' }),
297
315
  ]
298
316
  : []),
299
- ...(buttonClassName ? [h.Class(buttonClassName)] : []),
300
- ...buttonAttributes,
301
317
  ];
302
- const anchorPopover = Mount.mapMessage(AnchorPopover({
303
- buttonId: `${id}-button`,
304
- anchor,
305
- ...(focusSelector !== undefined && { focusSelector }),
306
- }), toParentMessage);
307
- const anchorAttributes = [
308
- h.Style({ position: 'absolute', margin: '0', visibility: 'hidden' }),
309
- h.OnMount(anchorPopover),
310
- ];
311
- const resolvedPanelAttributes = [
318
+ const panelAttributes = [
312
319
  h.Id(`${id}-panel`),
313
320
  ...(contentFocus ? [] : [h.Tabindex(0)]),
314
- ...anchorAttributes,
321
+ h.Style({ position: 'absolute', margin: '0', visibility: 'hidden' }),
322
+ h.OnMount(AnchorPopover({
323
+ buttonId: `${id}-button`,
324
+ anchor,
325
+ ...(focusSelector !== undefined && { focusSelector }),
326
+ })),
315
327
  ...animationAttributes,
316
328
  ...(isLeaving
317
329
  ? []
318
330
  : [
319
331
  h.OnKeyDownPreventDefault(handlePanelKeyDown),
320
- ...(contentFocus ? [] : [h.OnBlur(toParentMessage(BlurredPanel()))]),
332
+ ...(contentFocus ? [] : [h.OnBlur(BlurredPanel())]),
321
333
  ]),
322
- ...(panelClassName ? [h.Class(panelClassName)] : []),
323
- ...panelAttributes,
324
334
  ];
325
- const backdrop = h.keyed('div')(`${id}-backdrop`, [
326
- h.OnMount(Mount.mapMessage(PortalPopoverBackdrop(), toParentMessage)),
327
- ...(isLeaving ? [] : [h.OnClick(dispatchClosed())]),
328
- ...(backdropClassName ? [h.Class(backdropClassName)] : []),
329
- ...backdropAttributes,
330
- ], []);
331
- const visibleContent = [
332
- backdrop,
333
- h.keyed('div')(`${id}-panel-container`, resolvedPanelAttributes, [
334
- panelContent,
335
- ]),
335
+ const backdropAttributes = [
336
+ h.OnMount(PortalPopoverBackdrop()),
337
+ ...(isLeaving ? [] : [h.OnClick(RequestedClose())]),
336
338
  ];
337
- const wrapperAttributes = [
338
- ...(className ? [h.Class(className)] : []),
339
- ...attributes,
340
- ...(isVisible ? [h.DataAttribute('open', '')] : []),
341
- ];
342
- return h.div(wrapperAttributes, [
343
- h.keyed('button')(`${id}-button`, resolvedButtonAttributes, [
344
- buttonContent,
345
- ]),
346
- ...(isVisible ? visibleContent : []),
347
- ]);
348
- };
349
- /** Creates a memoized popover view. Static config is captured in a closure;
350
- * only `model` and `toParentMessage` are compared per render via `createLazy`. */
351
- export const lazy = (staticConfig) => {
352
- const lazyView = createLazy();
353
- return (model, toParentMessage) => lazyView((currentModel, currentToParentMessage) => view({
354
- ...staticConfig,
355
- model: currentModel,
356
- toParentMessage: currentToParentMessage,
357
- }), [model, toParentMessage]);
358
- };
339
+ return toView({
340
+ button: childAttributes(buttonAttributes),
341
+ panel: childAttributes(panelAttributes),
342
+ backdrop: childAttributes(backdropAttributes),
343
+ isVisible,
344
+ });
345
+ });
@@ -1,4 +1,4 @@
1
- export { init, update, open, close, view, lazy, Model, Message, Opened, Closed, CompletedFocusPanel, CompletedFocusButton, CompletedLockScroll, CompletedUnlockScroll, CompletedSetupInert, CompletedTeardownInert, CompletedAnchorPopover, CompletedPortalPopoverBackdrop, AnchorPopover, PortalPopoverBackdrop, GotAnimationMessage, LockScroll, UnlockScroll, InertOthers, RestoreInert, FocusPanel, FocusButton, DetectMovementOrAnimationEnd, } from './index.js';
2
- export type { BlurredPanel, PressedPointerOnButton, IgnoredMouseClick, SuppressedSpaceScroll, InitConfig, ViewConfig, } from './index.js';
1
+ export { init, update, open, close, view, Model, Message, OutMessage, Opened, Closed, RequestedOpen, RequestedClose, CompletedFocusPanel, CompletedFocusButton, CompletedLockScroll, CompletedUnlockScroll, CompletedInertOthers, CompletedRestoreInert, CompletedAnchorPopover, CompletedPortalPopoverBackdrop, AnchorPopover, PortalPopoverBackdrop, GotAnimationMessage, LockScroll, UnlockScroll, InertOthers, RestoreInert, FocusPanel, FocusButton, DetectMovementOrAnimationEnd, } from './index.js';
2
+ export type { BlurredPanel, PressedPointerOnButton, IgnoredMouseClick, SuppressedSpaceScroll, InitConfig, ViewInputs, RenderInfo, } from './index.js';
3
3
  export type { AnchorConfig } from '../anchor.js';
4
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,sBAAsB,EACtB,8BAA8B,EAC9B,aAAa,EACb,qBAAqB,EACrB,mBAAmB,EACnB,UAAU,EACV,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,UAAU,EACV,WAAW,EACX,4BAA4B,GAC7B,MAAM,YAAY,CAAA;AAEnB,YAAY,EACV,YAAY,EACZ,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACrB,UAAU,EACV,UAAU,GACX,MAAM,YAAY,CAAA;AAEnB,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,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,KAAK,EACL,OAAO,EACP,UAAU,EACV,MAAM,EACN,MAAM,EACN,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,oBAAoB,EACpB,qBAAqB,EACrB,sBAAsB,EACtB,8BAA8B,EAC9B,aAAa,EACb,qBAAqB,EACrB,mBAAmB,EACnB,UAAU,EACV,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,UAAU,EACV,WAAW,EACX,4BAA4B,GAC7B,MAAM,YAAY,CAAA;AAEnB,YAAY,EACV,YAAY,EACZ,sBAAsB,EACtB,iBAAiB,EACjB,qBAAqB,EACrB,UAAU,EACV,UAAU,EACV,UAAU,GACX,MAAM,YAAY,CAAA;AAEnB,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA"}
@@ -1 +1 @@
1
- export { init, update, open, close, view, lazy, Model, Message, Opened, Closed, CompletedFocusPanel, CompletedFocusButton, CompletedLockScroll, CompletedUnlockScroll, CompletedSetupInert, CompletedTeardownInert, CompletedAnchorPopover, CompletedPortalPopoverBackdrop, AnchorPopover, PortalPopoverBackdrop, GotAnimationMessage, LockScroll, UnlockScroll, InertOthers, RestoreInert, FocusPanel, FocusButton, DetectMovementOrAnimationEnd, } from './index.js';
1
+ export { init, update, open, close, view, Model, Message, OutMessage, Opened, Closed, RequestedOpen, RequestedClose, CompletedFocusPanel, CompletedFocusButton, CompletedLockScroll, CompletedUnlockScroll, CompletedInertOthers, CompletedRestoreInert, CompletedAnchorPopover, CompletedPortalPopoverBackdrop, AnchorPopover, PortalPopoverBackdrop, GotAnimationMessage, LockScroll, UnlockScroll, InertOthers, RestoreInert, FocusPanel, FocusButton, DetectMovementOrAnimationEnd, } from './index.js';