@foldkit/ui 0.112.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (201) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +67 -0
  3. package/dist/anchor.d.ts +38 -0
  4. package/dist/anchor.d.ts.map +1 -0
  5. package/dist/anchor.js +142 -0
  6. package/dist/animation/index.d.ts +49 -0
  7. package/dist/animation/index.d.ts.map +1 -0
  8. package/dist/animation/index.js +75 -0
  9. package/dist/animation/public.d.ts +3 -0
  10. package/dist/animation/public.d.ts.map +1 -0
  11. package/dist/animation/public.js +1 -0
  12. package/dist/animation/schema.d.ts +43 -0
  13. package/dist/animation/schema.d.ts.map +1 -0
  14. package/dist/animation/schema.js +41 -0
  15. package/dist/animation/update.d.ts +24 -0
  16. package/dist/animation/update.d.ts.map +1 -0
  17. package/dist/animation/update.js +67 -0
  18. package/dist/button/index.d.ts +17 -0
  19. package/dist/button/index.d.ts.map +1 -0
  20. package/dist/button/index.js +22 -0
  21. package/dist/button/public.d.ts +3 -0
  22. package/dist/button/public.d.ts.map +1 -0
  23. package/dist/button/public.js +1 -0
  24. package/dist/calendar/index.d.ts +462 -0
  25. package/dist/calendar/index.d.ts.map +1 -0
  26. package/dist/calendar/index.js +825 -0
  27. package/dist/calendar/public.d.ts +3 -0
  28. package/dist/calendar/public.d.ts.map +1 -0
  29. package/dist/calendar/public.js +1 -0
  30. package/dist/checkbox/index.d.ts +119 -0
  31. package/dist/checkbox/index.d.ts.map +1 -0
  32. package/dist/checkbox/index.js +111 -0
  33. package/dist/checkbox/public.d.ts +3 -0
  34. package/dist/checkbox/public.d.ts.map +1 -0
  35. package/dist/checkbox/public.js +1 -0
  36. package/dist/combobox/multi.d.ts +183 -0
  37. package/dist/combobox/multi.d.ts.map +1 -0
  38. package/dist/combobox/multi.js +81 -0
  39. package/dist/combobox/multiPublic.d.ts +3 -0
  40. package/dist/combobox/multiPublic.d.ts.map +1 -0
  41. package/dist/combobox/multiPublic.js +1 -0
  42. package/dist/combobox/public.d.ts +7 -0
  43. package/dist/combobox/public.d.ts.map +1 -0
  44. package/dist/combobox/public.js +3 -0
  45. package/dist/combobox/shared.d.ts +423 -0
  46. package/dist/combobox/shared.d.ts.map +1 -0
  47. package/dist/combobox/shared.js +708 -0
  48. package/dist/combobox/single.d.ts +198 -0
  49. package/dist/combobox/single.d.ts.map +1 -0
  50. package/dist/combobox/single.js +106 -0
  51. package/dist/datePicker/index.d.ts +457 -0
  52. package/dist/datePicker/index.d.ts.map +1 -0
  53. package/dist/datePicker/index.js +318 -0
  54. package/dist/datePicker/public.d.ts +3 -0
  55. package/dist/datePicker/public.d.ts.map +1 -0
  56. package/dist/datePicker/public.js +1 -0
  57. package/dist/dialog/index.d.ts +160 -0
  58. package/dist/dialog/index.d.ts.map +1 -0
  59. package/dist/dialog/index.js +211 -0
  60. package/dist/dialog/public.d.ts +3 -0
  61. package/dist/dialog/public.d.ts.map +1 -0
  62. package/dist/dialog/public.js +1 -0
  63. package/dist/disclosure/index.d.ts +110 -0
  64. package/dist/disclosure/index.d.ts.map +1 -0
  65. package/dist/disclosure/index.js +111 -0
  66. package/dist/disclosure/public.d.ts +3 -0
  67. package/dist/disclosure/public.d.ts.map +1 -0
  68. package/dist/disclosure/public.js +1 -0
  69. package/dist/dragAndDrop/index.d.ts +540 -0
  70. package/dist/dragAndDrop/index.d.ts.map +1 -0
  71. package/dist/dragAndDrop/index.js +535 -0
  72. package/dist/dragAndDrop/public.d.ts +3 -0
  73. package/dist/dragAndDrop/public.d.ts.map +1 -0
  74. package/dist/dragAndDrop/public.js +1 -0
  75. package/dist/fieldset/index.d.ts +21 -0
  76. package/dist/fieldset/index.d.ts.map +1 -0
  77. package/dist/fieldset/index.js +25 -0
  78. package/dist/fieldset/public.d.ts +3 -0
  79. package/dist/fieldset/public.d.ts.map +1 -0
  80. package/dist/fieldset/public.js +1 -0
  81. package/dist/fileDrop/index.d.ts +109 -0
  82. package/dist/fileDrop/index.d.ts.map +1 -0
  83. package/dist/fileDrop/index.js +127 -0
  84. package/dist/fileDrop/public.d.ts +3 -0
  85. package/dist/fileDrop/public.d.ts.map +1 -0
  86. package/dist/fileDrop/public.js +1 -0
  87. package/dist/group.d.ts +8 -0
  88. package/dist/group.d.ts.map +1 -0
  89. package/dist/group.js +13 -0
  90. package/dist/index.d.ts +25 -0
  91. package/dist/index.d.ts.map +1 -0
  92. package/dist/index.js +24 -0
  93. package/dist/input/index.d.ts +26 -0
  94. package/dist/input/index.d.ts.map +1 -0
  95. package/dist/input/index.js +43 -0
  96. package/dist/input/public.d.ts +3 -0
  97. package/dist/input/public.d.ts.map +1 -0
  98. package/dist/input/public.js +1 -0
  99. package/dist/internal/optionExtensions.d.ts +6 -0
  100. package/dist/internal/optionExtensions.d.ts.map +1 -0
  101. package/dist/internal/optionExtensions.js +2 -0
  102. package/dist/keyboard.d.ts +6 -0
  103. package/dist/keyboard.d.ts.map +1 -0
  104. package/dist/keyboard.js +9 -0
  105. package/dist/listbox/multi.d.ts +189 -0
  106. package/dist/listbox/multi.d.ts.map +1 -0
  107. package/dist/listbox/multi.js +65 -0
  108. package/dist/listbox/multiPublic.d.ts +3 -0
  109. package/dist/listbox/multiPublic.d.ts.map +1 -0
  110. package/dist/listbox/multiPublic.js +1 -0
  111. package/dist/listbox/public.d.ts +7 -0
  112. package/dist/listbox/public.d.ts.map +1 -0
  113. package/dist/listbox/public.js +3 -0
  114. package/dist/listbox/shared.d.ts +432 -0
  115. package/dist/listbox/shared.d.ts.map +1 -0
  116. package/dist/listbox/shared.js +670 -0
  117. package/dist/listbox/single.d.ts +207 -0
  118. package/dist/listbox/single.d.ts.map +1 -0
  119. package/dist/listbox/single.js +73 -0
  120. package/dist/menu/index.d.ts +368 -0
  121. package/dist/menu/index.d.ts.map +1 -0
  122. package/dist/menu/index.js +682 -0
  123. package/dist/menu/public.d.ts +4 -0
  124. package/dist/menu/public.d.ts.map +1 -0
  125. package/dist/menu/public.js +1 -0
  126. package/dist/popover/index.d.ts +267 -0
  127. package/dist/popover/index.d.ts.map +1 -0
  128. package/dist/popover/index.js +346 -0
  129. package/dist/popover/public.d.ts +4 -0
  130. package/dist/popover/public.d.ts.map +1 -0
  131. package/dist/popover/public.js +1 -0
  132. package/dist/radioGroup/index.d.ts +169 -0
  133. package/dist/radioGroup/index.d.ts.map +1 -0
  134. package/dist/radioGroup/index.js +197 -0
  135. package/dist/radioGroup/public.d.ts +3 -0
  136. package/dist/radioGroup/public.d.ts.map +1 -0
  137. package/dist/radioGroup/public.js +1 -0
  138. package/dist/select/index.d.ts +24 -0
  139. package/dist/select/index.d.ts.map +1 -0
  140. package/dist/select/index.js +40 -0
  141. package/dist/select/public.d.ts +3 -0
  142. package/dist/select/public.d.ts.map +1 -0
  143. package/dist/select/public.js +1 -0
  144. package/dist/slider/index.d.ts +318 -0
  145. package/dist/slider/index.d.ts.map +1 -0
  146. package/dist/slider/index.js +337 -0
  147. package/dist/slider/public.d.ts +3 -0
  148. package/dist/slider/public.d.ts.map +1 -0
  149. package/dist/slider/public.js +1 -0
  150. package/dist/switch/index.d.ts +99 -0
  151. package/dist/switch/index.d.ts.map +1 -0
  152. package/dist/switch/index.js +107 -0
  153. package/dist/switch/public.d.ts +3 -0
  154. package/dist/switch/public.d.ts.map +1 -0
  155. package/dist/switch/public.js +1 -0
  156. package/dist/tabs/index.d.ts +155 -0
  157. package/dist/tabs/index.d.ts.map +1 -0
  158. package/dist/tabs/index.js +185 -0
  159. package/dist/tabs/public.d.ts +3 -0
  160. package/dist/tabs/public.d.ts.map +1 -0
  161. package/dist/tabs/public.js +1 -0
  162. package/dist/test/apps/disabledButton.d.ts +38 -0
  163. package/dist/test/apps/disabledButton.d.ts.map +1 -0
  164. package/dist/test/apps/disabledButton.js +71 -0
  165. package/dist/textarea/index.d.ts +26 -0
  166. package/dist/textarea/index.d.ts.map +1 -0
  167. package/dist/textarea/index.js +44 -0
  168. package/dist/textarea/public.d.ts +3 -0
  169. package/dist/textarea/public.d.ts.map +1 -0
  170. package/dist/textarea/public.js +1 -0
  171. package/dist/toast/index.d.ts +608 -0
  172. package/dist/toast/index.d.ts.map +1 -0
  173. package/dist/toast/index.js +146 -0
  174. package/dist/toast/public.d.ts +4 -0
  175. package/dist/toast/public.d.ts.map +1 -0
  176. package/dist/toast/public.js +1 -0
  177. package/dist/toast/schema.d.ts +154 -0
  178. package/dist/toast/schema.d.ts.map +1 -0
  179. package/dist/toast/schema.js +93 -0
  180. package/dist/toast/update.d.ts +510 -0
  181. package/dist/toast/update.d.ts.map +1 -0
  182. package/dist/toast/update.js +225 -0
  183. package/dist/tooltip/index.d.ts +170 -0
  184. package/dist/tooltip/index.d.ts.map +1 -0
  185. package/dist/tooltip/index.js +253 -0
  186. package/dist/tooltip/public.d.ts +4 -0
  187. package/dist/tooltip/public.d.ts.map +1 -0
  188. package/dist/tooltip/public.js +1 -0
  189. package/dist/typeahead.d.ts +4 -0
  190. package/dist/typeahead.d.ts.map +1 -0
  191. package/dist/typeahead.js +14 -0
  192. package/dist/virtualList/index.d.ts +203 -0
  193. package/dist/virtualList/index.d.ts.map +1 -0
  194. package/dist/virtualList/index.js +392 -0
  195. package/dist/virtualList/public.d.ts +3 -0
  196. package/dist/virtualList/public.d.ts.map +1 -0
  197. package/dist/virtualList/public.js +1 -0
  198. package/dist/vitest-setup.d.ts +2 -0
  199. package/dist/vitest-setup.d.ts.map +1 -0
  200. package/dist/vitest-setup.js +2 -0
  201. package/package.json +161 -0
@@ -0,0 +1,318 @@
1
+ import { Function, Match as M, Option, Schema as S } from 'effect';
2
+ import * as Calendar from 'foldkit/calendar';
3
+ import * as Command from 'foldkit/command';
4
+ import { html } from 'foldkit/html';
5
+ import { m } from 'foldkit/message';
6
+ import { evo } from 'foldkit/struct';
7
+ import { defineView } from 'foldkit/submodel';
8
+ import * as UiCalendar from '../calendar/index.js';
9
+ import * as Popover from '../popover/index.js';
10
+ // MODEL
11
+ /** Schema for the date picker component's state. Holds the selected date,
12
+ * the embedded Calendar submodel (the visible grid), and the embedded Popover
13
+ * submodel (the open/close + transition layer). */
14
+ export const Model = S.Struct({
15
+ id: S.String,
16
+ maybeSelectedDate: S.Option(Calendar.CalendarDate),
17
+ calendar: UiCalendar.Model,
18
+ popover: Popover.Model,
19
+ });
20
+ // MESSAGE
21
+ /** Wraps a Calendar submodel message for delegation. */
22
+ export const GotCalendarMessage = m('GotCalendarMessage', {
23
+ message: UiCalendar.Message,
24
+ });
25
+ /** Wraps a Popover submodel message for delegation. */
26
+ export const GotPopoverMessage = m('GotPopoverMessage', {
27
+ message: Popover.Message,
28
+ });
29
+ /** Sent when the user commits a date via click or keyboard. Updates the
30
+ * selected date, syncs the calendar, and closes the popover. */
31
+ export const RequestedSelectDate = m('RequestedSelectDate', {
32
+ date: Calendar.CalendarDate,
33
+ });
34
+ /** Sent when the user clears the selected date. Does not close the popover. */
35
+ export const Cleared = m('Cleared');
36
+ /** Sent when the popover should open. Triggers focus-grid on the embedded
37
+ * Calendar so keyboard focus lands inside the grid instead of the panel. */
38
+ export const Opened = m('Opened');
39
+ /** Sent when the popover should close. Delegates to Popover which returns
40
+ * focus to the trigger button. */
41
+ export const Closed = m('Closed');
42
+ /** Union of all messages the date picker component can produce. */
43
+ export const Message = S.Union([
44
+ GotCalendarMessage,
45
+ GotPopoverMessage,
46
+ RequestedSelectDate,
47
+ Cleared,
48
+ Opened,
49
+ Closed,
50
+ ]);
51
+ // OUT MESSAGE
52
+ /** Emitted when the visible month changes (propagated from the embedded
53
+ * Calendar). Useful for month-scoped data loading. */
54
+ export const ChangedViewMonth = m('ChangedViewMonth', {
55
+ year: S.Int,
56
+ month: S.Int,
57
+ });
58
+ /** Emitted when the user commits a date selection (propagated from the
59
+ * embedded Calendar). The popover has already closed; the parent reads the
60
+ * committed date and lifts it into domain state. */
61
+ export const SelectedDate = m('SelectedDate', {
62
+ date: Calendar.CalendarDate,
63
+ });
64
+ /** Union of out-messages the date picker can produce. */
65
+ export const OutMessage = S.Union([ChangedViewMonth, SelectedDate]);
66
+ /** Creates an initial date picker model from a config. The calendar and
67
+ * popover submodels are created with derived ids so their DOM elements stay
68
+ * addressable. The popover is opened in `contentFocus` mode so focus lands on
69
+ * the calendar grid instead of the panel. */
70
+ export const init = (config) => ({
71
+ id: config.id,
72
+ maybeSelectedDate: Option.fromNullishOr(config.initialSelectedDate),
73
+ calendar: UiCalendar.init({
74
+ id: `${config.id}-calendar`,
75
+ today: config.today,
76
+ ...(config.initialSelectedDate !== undefined && {
77
+ initialSelectedDate: config.initialSelectedDate,
78
+ }),
79
+ ...(config.locale !== undefined && { locale: config.locale }),
80
+ ...(config.minDate !== undefined && { minDate: config.minDate }),
81
+ ...(config.maxDate !== undefined && { maxDate: config.maxDate }),
82
+ ...(config.disabledDaysOfWeek !== undefined && {
83
+ disabledDaysOfWeek: config.disabledDaysOfWeek,
84
+ }),
85
+ ...(config.disabledDates !== undefined && {
86
+ disabledDates: config.disabledDates,
87
+ }),
88
+ }),
89
+ popover: Popover.init({
90
+ id: `${config.id}-popover`,
91
+ contentFocus: true,
92
+ ...(config.isAnimated !== undefined && { isAnimated: config.isAnimated }),
93
+ }),
94
+ });
95
+ const withUpdateReturn = M.withReturnType();
96
+ const mapCalendarCommands = (commands) => Command.mapMessages(commands, message => GotCalendarMessage({ message }));
97
+ const mapPopoverCommands = (commands) => Command.mapMessages(commands, message => GotPopoverMessage({ message }));
98
+ const delegateToCalendar = (model, calendarMessage) => {
99
+ const [nextCalendar, calendarCommands, maybeCalendarOutMessage] = UiCalendar.update(model.calendar, calendarMessage);
100
+ const modelWithCalendar = evo(model, { calendar: () => nextCalendar });
101
+ return Option.match(maybeCalendarOutMessage, {
102
+ onNone: () => [
103
+ modelWithCalendar,
104
+ mapCalendarCommands(calendarCommands),
105
+ Option.none(),
106
+ ],
107
+ onSome: M.type().pipe(M.withReturnType(), M.tagsExhaustive({
108
+ ChangedViewMonth: ({ year, month }) => [
109
+ modelWithCalendar,
110
+ mapCalendarCommands(calendarCommands),
111
+ Option.some(ChangedViewMonth({ year, month })),
112
+ ],
113
+ SelectedDate: ({ date }) => {
114
+ const [nextPopover, popoverCommands] = Popover.close(model.popover);
115
+ return [
116
+ evo(modelWithCalendar, {
117
+ maybeSelectedDate: () => Option.some(date),
118
+ popover: () => nextPopover,
119
+ }),
120
+ [
121
+ ...mapCalendarCommands(calendarCommands),
122
+ ...mapPopoverCommands(popoverCommands),
123
+ ],
124
+ Option.some(SelectedDate({ date })),
125
+ ];
126
+ },
127
+ })),
128
+ });
129
+ };
130
+ const delegateToPopover = (model, popoverMessage) => {
131
+ const [nextPopover, popoverCommands, maybePopoverOutMessage] = Popover.update(model.popover, popoverMessage);
132
+ const modelWithPopover = evo(model, { popover: () => nextPopover });
133
+ return Option.match(maybePopoverOutMessage, {
134
+ onNone: () => [
135
+ modelWithPopover,
136
+ mapPopoverCommands(popoverCommands),
137
+ Option.none(),
138
+ ],
139
+ onSome: () => [
140
+ evo(modelWithPopover, {
141
+ calendar: () => UiCalendar.dropToDays(modelWithPopover.calendar),
142
+ }),
143
+ mapPopoverCommands(popoverCommands),
144
+ Option.none(),
145
+ ],
146
+ });
147
+ };
148
+ /** Processes a date picker message and returns the next model, commands, and
149
+ * optional OutMessage. */
150
+ export const update = (model, message) => M.value(message).pipe(withUpdateReturn, M.tagsExhaustive({
151
+ GotCalendarMessage: ({ message: calendarMessage }) => delegateToCalendar(model, calendarMessage),
152
+ GotPopoverMessage: ({ message: popoverMessage }) => delegateToPopover(model, popoverMessage),
153
+ Opened: () => {
154
+ const [nextPopover, popoverCommands] = Popover.open(model.popover);
155
+ return [
156
+ evo(model, {
157
+ popover: () => nextPopover,
158
+ calendar: () => UiCalendar.dropToDays(model.calendar),
159
+ }),
160
+ mapPopoverCommands(popoverCommands),
161
+ Option.none(),
162
+ ];
163
+ },
164
+ Closed: () => {
165
+ const [nextPopover, popoverCommands] = Popover.close(model.popover);
166
+ return [
167
+ evo(model, {
168
+ popover: () => nextPopover,
169
+ calendar: () => UiCalendar.dropToDays(model.calendar),
170
+ }),
171
+ mapPopoverCommands(popoverCommands),
172
+ Option.none(),
173
+ ];
174
+ },
175
+ RequestedSelectDate: ({ date }) => {
176
+ const [nextCalendar, calendarCommands] = UiCalendar.selectDate(model.calendar, date);
177
+ const [nextPopover, popoverCommands] = Popover.close(model.popover);
178
+ return [
179
+ evo(model, {
180
+ maybeSelectedDate: () => Option.some(date),
181
+ calendar: () => nextCalendar,
182
+ popover: () => nextPopover,
183
+ }),
184
+ [
185
+ ...mapCalendarCommands(calendarCommands),
186
+ ...mapPopoverCommands(popoverCommands),
187
+ ],
188
+ Option.some(SelectedDate({ date })),
189
+ ];
190
+ },
191
+ Cleared: () => [
192
+ evo(model, {
193
+ maybeSelectedDate: () => Option.none(),
194
+ calendar: UiCalendar.reflectSelectedDate(Option.none()),
195
+ }),
196
+ [],
197
+ Option.none(),
198
+ ],
199
+ }));
200
+ /** Programmatically opens the date picker, updating the model and returning
201
+ * focus and popover commands. Use this in domain-event handlers. */
202
+ export const open = (model) => update(model, Opened());
203
+ /** Programmatically closes the date picker. Use this in domain-event handlers. */
204
+ export const close = (model) => update(model, Closed());
205
+ /** Programmatically selects a date, committing it and closing the popover. Emits a `SelectedDate` OutMessage just like a user-initiated selection. */
206
+ export const selectDate = (model, date) => update(model, RequestedSelectDate({ date }));
207
+ /** Programmatically clears the selected date. */
208
+ export const clear = (model) => update(model, Cleared());
209
+ /** Reflects an externally-sourced selected date onto the date picker
210
+ * without emitting an OutMessage or touching the popover. Sets the
211
+ * picker's selection and reflects it onto the embedded calendar (moving
212
+ * the calendar's view to the date), mirroring `selectDate`'s state change
213
+ * minus the `SelectedDate` announcement and the popover close. Pass
214
+ * `Option.none()` to clear. Use this to mirror external truth (a URL
215
+ * parameter, a saved draft) onto the picker. Contrast with `selectDate`,
216
+ * a user or programmatic *choice* that emits `SelectedDate`. Returns the
217
+ * model directly because it produces no commands and no OutMessage. */
218
+ export const reflectSelectedDate = Function.dual(2, (model, maybeDate) => evo(model, {
219
+ maybeSelectedDate: () => maybeDate,
220
+ calendar: () => UiCalendar.reflectSelectedDate(model.calendar, maybeDate),
221
+ }));
222
+ /** Reflects the minimum selectable date onto the embedded calendar. Pass
223
+ * `Option.none()` to remove the minimum. Use this when the minimum derives
224
+ * from other Model state (e.g. a start date field whose current selection
225
+ * constrains an end date picker).
226
+ *
227
+ * Does NOT reconcile the current selection. If a previously-selected date
228
+ * is now below the new minimum, it remains selected. Callers should `clear`
229
+ * or reassign the selection explicitly if their domain requires it. */
230
+ export const reflectMinDate = Function.dual(2, (model, maybeMinDate) => evo(model, {
231
+ calendar: () => UiCalendar.reflectMinDate(model.calendar, maybeMinDate),
232
+ }));
233
+ /** Reflects the maximum selectable date onto the embedded calendar. Pass
234
+ * `Option.none()` to remove the maximum. Does NOT reconcile the current
235
+ * selection. */
236
+ export const reflectMaxDate = Function.dual(2, (model, maybeMaxDate) => evo(model, {
237
+ calendar: () => UiCalendar.reflectMaxDate(model.calendar, maybeMaxDate),
238
+ }));
239
+ /** Reflects the list of individually-disabled dates onto the embedded
240
+ * calendar. Pass an empty array to clear. Does NOT reconcile the current
241
+ * selection. */
242
+ export const reflectDisabledDates = Function.dual(2, (model, disabledDates) => evo(model, {
243
+ calendar: () => UiCalendar.reflectDisabledDates(model.calendar, disabledDates),
244
+ }));
245
+ /** Reflects the days of the week that are disabled onto the embedded calendar
246
+ * (e.g. weekends). Pass an empty array to clear. Does NOT reconcile the
247
+ * current selection. */
248
+ export const reflectDisabledDaysOfWeek = Function.dual(2, (model, disabledDaysOfWeek) => evo(model, {
249
+ calendar: () => UiCalendar.reflectDisabledDaysOfWeek(model.calendar, disabledDaysOfWeek),
250
+ }));
251
+ // VIEW
252
+ const encodeIsoDate = S.encodeSync(Calendar.CalendarDateFromIsoString);
253
+ /** Renders an accessible date picker: a trigger button that opens a popover
254
+ * containing an accessible calendar grid. The date picker assembles the
255
+ * embedded Calendar and Popover components into one flat API. Consumers
256
+ * provide the trigger face and the calendar grid layout, DatePicker handles
257
+ * focus choreography, open/close state, and form submission. */
258
+ export const view = defineView((model, viewInputs) => {
259
+ const h = html();
260
+ const { anchor, triggerContent, toCalendarView, isDisabled, name, className, attributes = [], triggerClassName, triggerAttributes = [], panelClassName, panelAttributes = [], backdropClassName, backdropAttributes = [], } = viewInputs;
261
+ const calendarVNode = h.submodel({
262
+ slotId: model.calendar.id,
263
+ model: model.calendar,
264
+ view: UiCalendar.view,
265
+ viewInputs: { toView: toCalendarView },
266
+ toParentMessage: message => GotCalendarMessage({ message }),
267
+ });
268
+ const popoverVNode = h.submodel({
269
+ slotId: model.popover.id,
270
+ model: model.popover,
271
+ view: Popover.view,
272
+ viewInputs: {
273
+ anchor,
274
+ ...(isDisabled !== undefined && { isDisabled }),
275
+ focusSelector: `#${model.calendar.id}-grid`,
276
+ toView: ({ button, panel, backdrop, isVisible }) => h.div([], [
277
+ h.button([
278
+ ...button,
279
+ ...(triggerClassName !== undefined
280
+ ? [h.Class(triggerClassName)]
281
+ : []),
282
+ ...triggerAttributes,
283
+ ], [triggerContent(model.maybeSelectedDate)]),
284
+ ...(isVisible
285
+ ? [
286
+ h.div([
287
+ ...backdrop,
288
+ ...(backdropClassName !== undefined
289
+ ? [h.Class(backdropClassName)]
290
+ : []),
291
+ ...backdropAttributes,
292
+ ], []),
293
+ h.div([
294
+ ...panel,
295
+ ...(panelClassName !== undefined
296
+ ? [h.Class(panelClassName)]
297
+ : []),
298
+ ...panelAttributes,
299
+ ], [calendarVNode]),
300
+ ]
301
+ : []),
302
+ ]),
303
+ },
304
+ toParentMessage: message => GotPopoverMessage({ message }),
305
+ });
306
+ const hiddenInputValue = Option.match(model.maybeSelectedDate, {
307
+ onNone: () => '',
308
+ onSome: encodeIsoDate,
309
+ });
310
+ const maybeHiddenInput = name !== undefined
311
+ ? [h.input([h.Type('hidden'), h.Name(name), h.Value(hiddenInputValue)])]
312
+ : [];
313
+ const wrapperAttributes = [
314
+ ...(className !== undefined ? [h.Class(className)] : []),
315
+ ...attributes,
316
+ ];
317
+ return h.div(wrapperAttributes, [popoverVNode, ...maybeHiddenInput]);
318
+ });
@@ -0,0 +1,3 @@
1
+ export { init, update, view, open, close, selectDate, clear, reflectSelectedDate, reflectMinDate, reflectMaxDate, reflectDisabledDates, reflectDisabledDaysOfWeek, Model, Message, OutMessage, GotCalendarMessage, GotPopoverMessage, RequestedSelectDate, SelectedDate, Cleared, Opened, Closed, ChangedViewMonth, } from './index.js';
2
+ export type { InitConfig, ViewInputs } from './index.js';
3
+ //# sourceMappingURL=public.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/datePicker/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,MAAM,EACN,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,UAAU,EACV,KAAK,EACL,mBAAmB,EACnB,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,yBAAyB,EACzB,KAAK,EACL,OAAO,EACP,UAAU,EACV,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACnB,YAAY,EACZ,OAAO,EACP,MAAM,EACN,MAAM,EACN,gBAAgB,GACjB,MAAM,YAAY,CAAA;AAEnB,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1 @@
1
+ export { init, update, view, open, close, selectDate, clear, reflectSelectedDate, reflectMinDate, reflectMaxDate, reflectDisabledDates, reflectDisabledDaysOfWeek, Model, Message, OutMessage, GotCalendarMessage, GotPopoverMessage, RequestedSelectDate, SelectedDate, Cleared, Opened, Closed, ChangedViewMonth, } from './index.js';
@@ -0,0 +1,160 @@
1
+ import { Effect, Option, Schema as S } from 'effect';
2
+ import * as Command from 'foldkit/command';
3
+ import { type ChildAttribute, type Html } from 'foldkit/html';
4
+ /** Schema for the dialog component's state, tracking its unique ID, open/closed status, animation support, and animation lifecycle phase. */
5
+ export declare const Model: S.Struct<{
6
+ readonly id: S.String;
7
+ readonly isOpen: S.Boolean;
8
+ readonly isAnimated: S.Boolean;
9
+ readonly animation: S.Struct<{
10
+ readonly id: S.String;
11
+ readonly isShowing: S.Boolean;
12
+ readonly transitionState: S.Literals<readonly ["Idle", "EnterStart", "EnterAnimating", "LeaveStart", "LeaveAnimating"]>;
13
+ }>;
14
+ readonly maybeFocusSelector: S.Option<S.String>;
15
+ }>;
16
+ export type Model = typeof Model.Type;
17
+ /** Sent when the dialog should open. Triggers the ShowDialog command. */
18
+ export declare const RequestedOpen: import("foldkit/schema").CallableTaggedStruct<"RequestedOpen", {}>;
19
+ /** Sent when the dialog should close (Escape key, backdrop click, or programmatic). */
20
+ export declare const RequestedClose: import("foldkit/schema").CallableTaggedStruct<"RequestedClose", {}>;
21
+ /** Sent when the show-dialog command completes. */
22
+ export declare const CompletedShowDialog: import("foldkit/schema").CallableTaggedStruct<"CompletedShowDialog", {}>;
23
+ /** Sent when the close-dialog command completes. */
24
+ export declare const CompletedCloseDialog: import("foldkit/schema").CallableTaggedStruct<"CompletedCloseDialog", {}>;
25
+ /** Wraps an Animation submodel message for delegation. */
26
+ export declare const GotAnimationMessage: import("foldkit/schema").CallableTaggedStruct<"GotAnimationMessage", {
27
+ message: S.Union<[import("foldkit/schema").CallableTaggedStruct<"Showed", {}>, import("foldkit/schema").CallableTaggedStruct<"Hid", {}>, import("foldkit/schema").CallableTaggedStruct<"AdvancedAnimationFrame", {}>, import("foldkit/schema").CallableTaggedStruct<"EndedAnimation", {}>]>;
28
+ }>;
29
+ /** Union of all messages the dialog component can produce. */
30
+ export declare const Message: S.Union<[
31
+ typeof RequestedOpen,
32
+ typeof RequestedClose,
33
+ typeof CompletedShowDialog,
34
+ typeof CompletedCloseDialog,
35
+ typeof GotAnimationMessage
36
+ ]>;
37
+ export type RequestedOpen = typeof RequestedOpen.Type;
38
+ export type RequestedClose = typeof RequestedClose.Type;
39
+ export type CompletedShowDialog = typeof CompletedShowDialog.Type;
40
+ export type CompletedCloseDialog = typeof CompletedCloseDialog.Type;
41
+ export type Message = typeof Message.Type;
42
+ /** Sent once the dialog has transitioned to open. Fires after `update`
43
+ * has processed `RequestedOpen` and `isOpen` reflects the new state.
44
+ * Programmatic `Dialog.open` on an already-open model is a no-op that
45
+ * does not re-emit. */
46
+ export declare const Opened: import("foldkit/schema").CallableTaggedStruct<"Opened", {}>;
47
+ /** Sent once the dialog has transitioned to closed. Programmatic
48
+ * `Dialog.close` on an already-closed model is a no-op that does not
49
+ * re-emit; calling close while a leave animation is in progress is
50
+ * also a no-op. */
51
+ export declare const Closed: import("foldkit/schema").CallableTaggedStruct<"Closed", {}>;
52
+ /** Union of out-messages the dialog component can produce. */
53
+ export declare const OutMessage: S.Union<readonly [import("foldkit/schema").CallableTaggedStruct<"Opened", {}>, import("foldkit/schema").CallableTaggedStruct<"Closed", {}>]>;
54
+ export type Opened = typeof Opened.Type;
55
+ export type Closed = typeof Closed.Type;
56
+ export type OutMessage = typeof OutMessage.Type;
57
+ /** Configuration for creating a dialog model with `init`. */
58
+ export type InitConfig = Readonly<{
59
+ id: string;
60
+ isOpen?: boolean;
61
+ isAnimated?: boolean;
62
+ focusSelector?: string;
63
+ }>;
64
+ /** Creates an initial dialog model from a config. Defaults to closed and non-animated. */
65
+ export declare const init: (config: InitConfig) => Model;
66
+ type UpdateReturn = readonly [
67
+ Model,
68
+ ReadonlyArray<Command.Command<Message>>,
69
+ Option.Option<OutMessage>
70
+ ];
71
+ /** Locks page scroll and opens the native dialog element with `show()`. */
72
+ export declare const ShowDialog: Command.CommandDefinitionWithArgs<"ShowDialog", {
73
+ id: S.String;
74
+ maybeFocusSelector: S.Option<S.String>;
75
+ }, Effect.Effect<{
76
+ readonly _tag: "CompletedShowDialog";
77
+ }, never, never>>;
78
+ /** Calls `close()` on the native dialog element and unlocks page scroll. */
79
+ export declare const CloseDialog: Command.CommandDefinitionWithArgs<"CloseDialog", {
80
+ id: S.String;
81
+ }, Effect.Effect<{
82
+ readonly _tag: "CompletedCloseDialog";
83
+ }, never, never>>;
84
+ /** Processes a dialog message and returns the next model and commands. */
85
+ export declare const update: (model: Model, message: Message) => UpdateReturn;
86
+ /** Programmatically opens the dialog. */
87
+ export declare const open: (model: Model) => UpdateReturn;
88
+ /** Programmatically closes the dialog. */
89
+ export declare const close: (model: Model) => UpdateReturn;
90
+ /** Returns the ID used for `aria-labelledby` on the dialog. Apply this to your title element. */
91
+ export declare const titleId: (model: Model) => string;
92
+ /** Returns the ID used for `aria-describedby` on the dialog. Apply this to your description element. */
93
+ export declare const descriptionId: (model: Model) => string;
94
+ /** Render-time payload published to the consumer's `toView`.
95
+ *
96
+ * - `dialog`: attributes for the native `<dialog>` element. Carries
97
+ * the id, ARIA labelling, `open` prop, positioning style, and the
98
+ * `OnCancel` handler that wires Escape to `RequestedClose`. The
99
+ * consumer MUST render an `h.dialog(...)` element so the framework can
100
+ * open and close it.
101
+ * - `backdrop`: attributes for the backdrop element. Includes the
102
+ * Animation data attributes and the `OnClick` handler that closes
103
+ * the dialog on outside-click (suppressed while a leave animation
104
+ * is in progress).
105
+ * - `panel`: attributes for the panel element. Includes the panel id
106
+ * (`${model.id}-panel`) and the Animation data attributes.
107
+ * - `closeButton`: attributes for an in-panel close control such as a Cancel
108
+ * or dismiss button. Carries the `OnClick` handler that closes the
109
+ * dialog (suppressed while a leave animation is in progress). Spread
110
+ * onto your own button so a plain close needs no parent message.
111
+ * - `isVisible`: derived from `isOpen` and the Animation
112
+ * `transitionState`. The consumer renders backdrop + panel only
113
+ * while this is true. */
114
+ export type RenderInfo = Readonly<{
115
+ dialog: ReadonlyArray<ChildAttribute>;
116
+ backdrop: ReadonlyArray<ChildAttribute>;
117
+ panel: ReadonlyArray<ChildAttribute>;
118
+ closeButton: ReadonlyArray<ChildAttribute>;
119
+ isVisible: boolean;
120
+ }>;
121
+ /** Per-render view inputs passed to `view` via `h.submodel`'s `viewInputs` field. */
122
+ export type ViewInputs = Readonly<{
123
+ toView: (render: RenderInfo) => Html;
124
+ }>;
125
+ /** Renders a headless dialog component backed by the native `<dialog>`
126
+ * element opened with `show()`. */
127
+ export declare const view: import("foldkit/submodel").View<{
128
+ readonly id: string;
129
+ readonly isOpen: boolean;
130
+ readonly isAnimated: boolean;
131
+ readonly animation: {
132
+ readonly id: string;
133
+ readonly isShowing: boolean;
134
+ readonly transitionState: "Idle" | "EnterStart" | "EnterAnimating" | "LeaveStart" | "LeaveAnimating";
135
+ };
136
+ readonly maybeFocusSelector: Option.Option<string>;
137
+ }, {
138
+ readonly _tag: "RequestedOpen";
139
+ } | {
140
+ readonly _tag: "RequestedClose";
141
+ } | {
142
+ readonly _tag: "CompletedShowDialog";
143
+ } | {
144
+ readonly _tag: "CompletedCloseDialog";
145
+ } | {
146
+ readonly _tag: "GotAnimationMessage";
147
+ readonly message: {
148
+ readonly _tag: "Showed";
149
+ } | {
150
+ readonly _tag: "Hid";
151
+ } | {
152
+ readonly _tag: "AdvancedAnimationFrame";
153
+ } | {
154
+ readonly _tag: "EndedAnimation";
155
+ };
156
+ }, Readonly<{
157
+ toView: (render: RenderInfo) => Html;
158
+ }>>;
159
+ export {};
160
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dialog/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAc,MAAM,EAAE,MAAM,IAAI,CAAC,EAAE,MAAM,QAAQ,CAAA;AAChE,OAAO,KAAK,OAAO,MAAM,iBAAiB,CAAA;AAE1C,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,IAAI,EAGV,MAAM,cAAc,CAAA;AAuBrB,6IAA6I;AAC7I,eAAO,MAAM,KAAK;;;;;;;;;;EAMhB,CAAA;AAEF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,yEAAyE;AACzE,eAAO,MAAM,aAAa,oEAAqB,CAAA;AAC/C,uFAAuF;AACvF,eAAO,MAAM,cAAc,qEAAsB,CAAA;AACjD,mDAAmD;AACnD,eAAO,MAAM,mBAAmB,0EAA2B,CAAA;AAC3D,oDAAoD;AACpD,eAAO,MAAM,oBAAoB,2EAA4B,CAAA;AAC7D,0DAA0D;AAC1D,eAAO,MAAM,mBAAmB;;EAE9B,CAAA;AAEF,8DAA8D;AAC9D,eAAO,MAAM,OAAO,EAAE,CAAC,CAAC,KAAK,CAC3B;IACE,OAAO,aAAa;IACpB,OAAO,cAAc;IACrB,OAAO,mBAAmB;IAC1B,OAAO,oBAAoB;IAC3B,OAAO,mBAAmB;CAC3B,CAOD,CAAA;AAEF,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAA;AACrD,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC,IAAI,CAAA;AACvD,MAAM,MAAM,mBAAmB,GAAG,OAAO,mBAAmB,CAAC,IAAI,CAAA;AACjE,MAAM,MAAM,oBAAoB,GAAG,OAAO,oBAAoB,CAAC,IAAI,CAAA;AAEnE,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAIzC;;;wBAGwB;AACxB,eAAO,MAAM,MAAM,6DAAc,CAAA;AAEjC;;;oBAGoB;AACpB,eAAO,MAAM,MAAM,6DAAc,CAAA;AAEjC,8DAA8D;AAC9D,eAAO,MAAM,UAAU,8IAA4B,CAAA;AAEnD,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AACvC,MAAM,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,IAAI,CAAA;AACvC,MAAM,MAAM,UAAU,GAAG,OAAO,UAAU,CAAC,IAAI,CAAA;AAI/C,6DAA6D;AAC7D,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,aAAa,CAAC,EAAE,MAAM,CAAA;CACvB,CAAC,CAAA;AAEF,0FAA0F;AAC1F,eAAO,MAAM,IAAI,GAAI,QAAQ,UAAU,KAAG,KASxC,CAAA;AAMF,KAAK,YAAY,GAAG,SAAS;IAC3B,KAAK;IACL,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC;CAC1B,CAAA;AAGD,2EAA2E;AAC3E,eAAO,MAAM,UAAU;;;;;iBAkBtB,CAAA;AAED,4EAA4E;AAC5E,eAAO,MAAM,WAAW;;;;iBAUvB,CAAA;AAyCD,0EAA0E;AAC1E,eAAO,MAAM,MAAM,GAAI,OAAO,KAAK,EAAE,SAAS,OAAO,KAAG,YA6ErD,CAAA;AAEH,yCAAyC;AACzC,eAAO,MAAM,IAAI,GAAI,OAAO,KAAK,KAAG,YACJ,CAAA;AAEhC,0CAA0C;AAC1C,eAAO,MAAM,KAAK,GAAI,OAAO,KAAK,KAAG,YACJ,CAAA;AAIjC,iGAAiG;AACjG,eAAO,MAAM,OAAO,GAAI,OAAO,KAAK,KAAG,MAA6B,CAAA;AAEpE,wGAAwG;AACxG,eAAO,MAAM,aAAa,GAAI,OAAO,KAAK,KAAG,MAAmC,CAAA;AAEhF;;;;;;;;;;;;;;;;;;;4BAmB4B;AAC5B,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,MAAM,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;IACrC,QAAQ,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;IACvC,KAAK,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;IACpC,WAAW,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;IAC1C,SAAS,EAAE,OAAO,CAAA;CACnB,CAAC,CAAA;AAEF,qFAAqF;AACrF,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,MAAM,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAA;CACrC,CAAC,CAAA;AAEF;oCACoC;AACpC,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;YALP,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI;GAiFrC,CAAA"}