@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 { Option, Schema as S } from 'effect';
2
+ import type { Command } from 'foldkit/command';
3
+ import { type ChildAttribute, type Html } from 'foldkit/html';
4
+ import { type Reflect } from 'foldkit/submodel';
5
+ import * as Subscription from 'foldkit/subscription';
6
+ /** Schema for the slider component's state. Tracks the current value, the
7
+ * range (min/max/step), and the active drag phase. */
8
+ export declare const Model: S.Struct<{
9
+ readonly id: S.String;
10
+ readonly value: S.Number;
11
+ readonly min: S.Number;
12
+ readonly max: S.Number;
13
+ readonly step: S.Number;
14
+ readonly dragState: S.Union<readonly [import("foldkit/schema").CallableTaggedStruct<"Idle", {}>, import("foldkit/schema").CallableTaggedStruct<"Dragging", {
15
+ originValue: S.Number;
16
+ }>]>;
17
+ }>;
18
+ export type Model = typeof Model.Type;
19
+ /** The user pressed the thumb. Starts a drag without changing the value. */
20
+ export declare const PressedThumb: import("foldkit/schema").CallableTaggedStruct<"PressedThumb", {}>;
21
+ /** The user pressed the track. Starts a drag and snaps the value to the
22
+ * cursor position. Ignored while already dragging, which absorbs the bubble
23
+ * from a thumb press so the value is not shifted. */
24
+ export declare const PressedPointer: import("foldkit/schema").CallableTaggedStruct<"PressedPointer", {
25
+ value: S.Number;
26
+ }>;
27
+ /** The pointer moved during a drag, producing a new snapped value from the
28
+ * cursor position within the track. */
29
+ export declare const MovedDragPointer: import("foldkit/schema").CallableTaggedStruct<"MovedDragPointer", {
30
+ value: S.Number;
31
+ }>;
32
+ /** The pointer was released during a drag. Commits the current value. */
33
+ export declare const ReleasedDragPointer: import("foldkit/schema").CallableTaggedStruct<"ReleasedDragPointer", {}>;
34
+ /** Escape was pressed during a drag. Restores the value from the drag origin. */
35
+ export declare const CancelledDrag: import("foldkit/schema").CallableTaggedStruct<"CancelledDrag", {}>;
36
+ /** The user pressed a keyboard navigation key on the focused thumb. */
37
+ export declare const PressedKeyboardNavigation: import("foldkit/schema").CallableTaggedStruct<"PressedKeyboardNavigation", {
38
+ direction: S.Literals<readonly ["StepDecrement", "StepIncrement", "PageDecrement", "PageIncrement", "Min", "Max"]>;
39
+ }>;
40
+ /** Union of all messages the slider component can produce. */
41
+ export declare const Message: S.Union<[
42
+ typeof PressedThumb,
43
+ typeof PressedPointer,
44
+ typeof MovedDragPointer,
45
+ typeof ReleasedDragPointer,
46
+ typeof CancelledDrag,
47
+ typeof PressedKeyboardNavigation
48
+ ]>;
49
+ export type Message = typeof Message.Type;
50
+ export type PressedThumb = typeof PressedThumb.Type;
51
+ export type PressedPointer = typeof PressedPointer.Type;
52
+ export type MovedDragPointer = typeof MovedDragPointer.Type;
53
+ export type ReleasedDragPointer = typeof ReleasedDragPointer.Type;
54
+ export type CancelledDrag = typeof CancelledDrag.Type;
55
+ export type PressedKeyboardNavigation = typeof PressedKeyboardNavigation.Type;
56
+ /** Emitted when the slider value changes. The parent can handle this to
57
+ * update its own state or dispatch its own Commands, for example to run
58
+ * validation or trigger a downstream Command. */
59
+ export declare const ChangedValue: import("foldkit/schema").CallableTaggedStruct<"ChangedValue", {
60
+ value: S.Number;
61
+ }>;
62
+ /** Union of all out-messages the slider component can emit to its parent. */
63
+ export declare const OutMessage: S.Union<readonly [import("foldkit/schema").CallableTaggedStruct<"ChangedValue", {
64
+ value: S.Number;
65
+ }>]>;
66
+ export type OutMessage = typeof OutMessage.Type;
67
+ /** Configuration for creating a slider model with `init`. */
68
+ export type InitConfig = Readonly<{
69
+ id: string;
70
+ min: number;
71
+ max: number;
72
+ step: number;
73
+ initialValue: number;
74
+ }>;
75
+ /** Creates an initial slider model from a config. The initial value is
76
+ * snapped to the step and clamped into range. */
77
+ export declare const init: (config: InitConfig) => Model;
78
+ /** Computes the fraction (0–1) of a value between min and max. Returns 0 when
79
+ * the range has zero width. */
80
+ export declare const fractionOfValue: (model: Model) => number;
81
+ type UpdateReturn = readonly [
82
+ Model,
83
+ ReadonlyArray<Command<Message>>,
84
+ Option.Option<OutMessage>
85
+ ];
86
+ /** Processes a slider message and returns the next model, commands, and an
87
+ * optional out-message for the parent. */
88
+ export declare const update: (model: Model, message: Message) => UpdateReturn;
89
+ /** Reflects an externally-driven range onto the slider. Snaps and clamps the
90
+ * current value into the new range. Use this when min/max derive from
91
+ * external state (e.g. a bounded buffer whose first/last index shifts over
92
+ * time). Unlike `reflectValue`, this runs even while the user is Dragging: a
93
+ * structural range change cannot leave the value out of bounds. */
94
+ export declare const reflectRange: Reflect<Model, Readonly<{
95
+ min: number;
96
+ max: number;
97
+ }>>;
98
+ /** Reflects an externally-driven value onto the slider, snapped and clamped
99
+ * into range; a no-op while the user is dragging, since drag state owns the
100
+ * value. Does not emit `ChangedValue`; use when the value is being driven by
101
+ * external state rather than user input. */
102
+ export declare const reflectValue: Reflect<Model, number>;
103
+ /** Builds slider drag subscriptions, looking up the track
104
+ * element through the supplied root resolver. Use this when the slider is
105
+ * rendered inside a Shadow DOM. The root is read lazily so consumers can
106
+ * resolve it at subscription time. */
107
+ export declare const subscriptionsForRoot: (getTrackRoot: () => Document | ShadowRoot) => {
108
+ readonly dragPointer: Subscription.EntryWithoutKeepAlive<{
109
+ readonly id: string;
110
+ readonly value: number;
111
+ readonly min: number;
112
+ readonly max: number;
113
+ readonly step: number;
114
+ readonly dragState: {
115
+ readonly _tag: "Idle";
116
+ } | {
117
+ readonly _tag: "Dragging";
118
+ readonly originValue: number;
119
+ };
120
+ }, {
121
+ readonly _tag: "CancelledDrag";
122
+ } | {
123
+ readonly _tag: "PressedThumb";
124
+ } | {
125
+ readonly _tag: "PressedPointer";
126
+ readonly value: number;
127
+ } | {
128
+ readonly _tag: "MovedDragPointer";
129
+ readonly value: number;
130
+ } | {
131
+ readonly _tag: "ReleasedDragPointer";
132
+ } | {
133
+ readonly _tag: "PressedKeyboardNavigation";
134
+ readonly direction: "Max" | "Min" | "StepDecrement" | "StepIncrement" | "PageDecrement" | "PageIncrement";
135
+ }, {
136
+ readonly dragActivity: "Idle" | "Active";
137
+ readonly id: string;
138
+ readonly min: number;
139
+ readonly max: number;
140
+ }, never> & {
141
+ readonly __subscription: never;
142
+ };
143
+ readonly dragEscape: Subscription.EntryWithoutKeepAlive<{
144
+ readonly id: string;
145
+ readonly value: number;
146
+ readonly min: number;
147
+ readonly max: number;
148
+ readonly step: number;
149
+ readonly dragState: {
150
+ readonly _tag: "Idle";
151
+ } | {
152
+ readonly _tag: "Dragging";
153
+ readonly originValue: number;
154
+ };
155
+ }, {
156
+ readonly _tag: "CancelledDrag";
157
+ } | {
158
+ readonly _tag: "PressedThumb";
159
+ } | {
160
+ readonly _tag: "PressedPointer";
161
+ readonly value: number;
162
+ } | {
163
+ readonly _tag: "MovedDragPointer";
164
+ readonly value: number;
165
+ } | {
166
+ readonly _tag: "ReleasedDragPointer";
167
+ } | {
168
+ readonly _tag: "PressedKeyboardNavigation";
169
+ readonly direction: "Max" | "Min" | "StepDecrement" | "StepIncrement" | "PageDecrement" | "PageIncrement";
170
+ }, {
171
+ readonly dragActivity: "Idle" | "Active";
172
+ }, never> & {
173
+ readonly __subscription: never;
174
+ };
175
+ };
176
+ /** Default drag subscriptions, with the track looked up via `document`. */
177
+ export declare const subscriptions: {
178
+ readonly dragPointer: Subscription.EntryWithoutKeepAlive<{
179
+ readonly id: string;
180
+ readonly value: number;
181
+ readonly min: number;
182
+ readonly max: number;
183
+ readonly step: number;
184
+ readonly dragState: {
185
+ readonly _tag: "Idle";
186
+ } | {
187
+ readonly _tag: "Dragging";
188
+ readonly originValue: number;
189
+ };
190
+ }, {
191
+ readonly _tag: "CancelledDrag";
192
+ } | {
193
+ readonly _tag: "PressedThumb";
194
+ } | {
195
+ readonly _tag: "PressedPointer";
196
+ readonly value: number;
197
+ } | {
198
+ readonly _tag: "MovedDragPointer";
199
+ readonly value: number;
200
+ } | {
201
+ readonly _tag: "ReleasedDragPointer";
202
+ } | {
203
+ readonly _tag: "PressedKeyboardNavigation";
204
+ readonly direction: "Max" | "Min" | "StepDecrement" | "StepIncrement" | "PageDecrement" | "PageIncrement";
205
+ }, {
206
+ readonly dragActivity: "Idle" | "Active";
207
+ readonly id: string;
208
+ readonly min: number;
209
+ readonly max: number;
210
+ }, never> & {
211
+ readonly __subscription: never;
212
+ };
213
+ readonly dragEscape: Subscription.EntryWithoutKeepAlive<{
214
+ readonly id: string;
215
+ readonly value: number;
216
+ readonly min: number;
217
+ readonly max: number;
218
+ readonly step: number;
219
+ readonly dragState: {
220
+ readonly _tag: "Idle";
221
+ } | {
222
+ readonly _tag: "Dragging";
223
+ readonly originValue: number;
224
+ };
225
+ }, {
226
+ readonly _tag: "CancelledDrag";
227
+ } | {
228
+ readonly _tag: "PressedThumb";
229
+ } | {
230
+ readonly _tag: "PressedPointer";
231
+ readonly value: number;
232
+ } | {
233
+ readonly _tag: "MovedDragPointer";
234
+ readonly value: number;
235
+ } | {
236
+ readonly _tag: "ReleasedDragPointer";
237
+ } | {
238
+ readonly _tag: "PressedKeyboardNavigation";
239
+ readonly direction: "Max" | "Min" | "StepDecrement" | "StepIncrement" | "PageDecrement" | "PageIncrement";
240
+ }, {
241
+ readonly dragActivity: "Idle" | "Active";
242
+ }, never> & {
243
+ readonly __subscription: never;
244
+ };
245
+ };
246
+ /** Attribute groups the slider component provides to the consumer's `toView`
247
+ * callback. Each bundle carries the boundary's captured dispatch, so the
248
+ * consumer can spread it directly into element attributes without manual
249
+ * Message wrapping. */
250
+ export type SliderAttributes = Readonly<{
251
+ root: ReadonlyArray<ChildAttribute>;
252
+ track: ReadonlyArray<ChildAttribute>;
253
+ filledTrack: ReadonlyArray<ChildAttribute>;
254
+ thumb: ReadonlyArray<ChildAttribute>;
255
+ label: ReadonlyArray<ChildAttribute>;
256
+ hiddenInput: ReadonlyArray<ChildAttribute>;
257
+ }>;
258
+ /** Per-render view inputs passed to `view` via `h.submodel`'s `viewInputs` field. */
259
+ export type ViewInputs = Readonly<{
260
+ toView: (attributes: SliderAttributes) => Html;
261
+ ariaLabel?: string;
262
+ ariaLabelledBy?: string;
263
+ formatValue?: (value: number) => string;
264
+ isDisabled?: boolean;
265
+ name?: string;
266
+ /** Resolves the root that holds the slider track when looking it up by its
267
+ * `data-slider-track-id` attribute. Defaults to `document`. Provide a
268
+ * ShadowRoot when rendering the slider inside a shadow tree so pointer
269
+ * events on the track can map clientX into a value. */
270
+ getTrackRoot?: () => Document | ShadowRoot;
271
+ }>;
272
+ /** Renders an accessible slider by building ARIA attribute groups and
273
+ * delegating layout to the consumer's `toView` callback. Follows the
274
+ * WAI-ARIA slider pattern: role="slider" on the thumb, aria-valuemin /
275
+ * aria-valuemax / aria-valuenow, keyboard navigation by step / page / home /
276
+ * end. Pointer drag is handled by the component's drag subscriptions. */
277
+ export declare const view: import("foldkit/submodel").View<{
278
+ readonly id: string;
279
+ readonly value: number;
280
+ readonly min: number;
281
+ readonly max: number;
282
+ readonly step: number;
283
+ readonly dragState: {
284
+ readonly _tag: "Idle";
285
+ } | {
286
+ readonly _tag: "Dragging";
287
+ readonly originValue: number;
288
+ };
289
+ }, {
290
+ readonly _tag: "CancelledDrag";
291
+ } | {
292
+ readonly _tag: "PressedThumb";
293
+ } | {
294
+ readonly _tag: "PressedPointer";
295
+ readonly value: number;
296
+ } | {
297
+ readonly _tag: "MovedDragPointer";
298
+ readonly value: number;
299
+ } | {
300
+ readonly _tag: "ReleasedDragPointer";
301
+ } | {
302
+ readonly _tag: "PressedKeyboardNavigation";
303
+ readonly direction: "Max" | "Min" | "StepDecrement" | "StepIncrement" | "PageDecrement" | "PageIncrement";
304
+ }, Readonly<{
305
+ toView: (attributes: SliderAttributes) => Html;
306
+ ariaLabel?: string;
307
+ ariaLabelledBy?: string;
308
+ formatValue?: (value: number) => string;
309
+ isDisabled?: boolean;
310
+ name?: string;
311
+ /** Resolves the root that holds the slider track when looking it up by its
312
+ * `data-slider-track-id` attribute. Defaults to `document`. Provide a
313
+ * ShadowRoot when rendering the slider inside a shadow tree so pointer
314
+ * events on the track can map clientX into a value. */
315
+ getTrackRoot?: () => Document | ShadowRoot;
316
+ }>>;
317
+ export {};
318
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/slider/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,MAAM,EACN,MAAM,IAAI,CAAC,EAIZ,MAAM,QAAQ,CAAA;AACf,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAC9C,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,IAAI,EAGV,MAAM,cAAc,CAAA;AAIrB,OAAO,EAAE,KAAK,OAAO,EAAc,MAAM,kBAAkB,CAAA;AAC3D,OAAO,KAAK,YAAY,MAAM,sBAAsB,CAAA;AASpD;uDACuD;AACvD,eAAO,MAAM,KAAK;;;;;;;;;EAOhB,CAAA;AAEF,MAAM,MAAM,KAAK,GAAG,OAAO,KAAK,CAAC,IAAI,CAAA;AAIrC,4EAA4E;AAC5E,eAAO,MAAM,YAAY,mEAAoB,CAAA;AAC7C;;sDAEsD;AACtD,eAAO,MAAM,cAAc;;EAA2C,CAAA;AACtE;wCACwC;AACxC,eAAO,MAAM,gBAAgB;;EAA6C,CAAA;AAC1E,yEAAyE;AACzE,eAAO,MAAM,mBAAmB,0EAA2B,CAAA;AAC3D,iFAAiF;AACjF,eAAO,MAAM,aAAa,oEAAqB,CAAA;AAC/C,uEAAuE;AACvE,eAAO,MAAM,yBAAyB;;EASpC,CAAA;AAEF,8DAA8D;AAC9D,eAAO,MAAM,OAAO,EAAE,CAAC,CAAC,KAAK,CAC3B;IACE,OAAO,YAAY;IACnB,OAAO,cAAc;IACrB,OAAO,gBAAgB;IACvB,OAAO,mBAAmB;IAC1B,OAAO,aAAa;IACpB,OAAO,yBAAyB;CACjC,CAQD,CAAA;AAEF,MAAM,MAAM,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,CAAA;AAEzC,MAAM,MAAM,YAAY,GAAG,OAAO,YAAY,CAAC,IAAI,CAAA;AACnD,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC,IAAI,CAAA;AACvD,MAAM,MAAM,gBAAgB,GAAG,OAAO,gBAAgB,CAAC,IAAI,CAAA;AAC3D,MAAM,MAAM,mBAAmB,GAAG,OAAO,mBAAmB,CAAC,IAAI,CAAA;AACjE,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAA;AACrD,MAAM,MAAM,yBAAyB,GAAG,OAAO,yBAAyB,CAAC,IAAI,CAAA;AAI7E;;kDAEkD;AAClD,eAAO,MAAM,YAAY;;EAAyC,CAAA;AAElE,6EAA6E;AAC7E,eAAO,MAAM,UAAU;;IAA0B,CAAA;AACjD,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,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,CAAA;CACrB,CAAC,CAAA;AAEF;kDACkD;AAClD,eAAO,MAAM,IAAI,GAAI,QAAQ,UAAU,KAAG,KAOxC,CAAA;AAkCF;gCACgC;AAChC,eAAO,MAAM,eAAe,GAAI,OAAO,KAAK,KAAG,MAO9C,CAAA;AAuCD,KAAK,YAAY,GAAG,SAAS;IAC3B,KAAK;IACL,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/B,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC;CAC1B,CAAA;AAmBD;2CAC2C;AAC3C,eAAO,MAAM,MAAM,GAAI,OAAO,KAAK,EAAE,SAAS,OAAO,KAAG,YAwFrD,CAAA;AAEH;;;;oEAIoE;AACpE,eAAO,MAAM,YAAY,EAAE,OAAO,CAChC,KAAK,EACL,QAAQ,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CASvC,CAAA;AAED;;;6CAG6C;AAC7C,eAAO,MAAM,YAAY,EAAE,OAAO,CAAC,KAAK,EAAE,MAAM,CAY/C,CAAA;AAoCD;;;uCAGuC;AACvC,eAAO,MAAM,oBAAoB,GAC/B,cAAc,MAAM,QAAQ,GAAG,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6FtC,CAAA;AAEL,2EAA2E;AAC3E,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAuC,CAAA;AAyBjE;;;wBAGwB;AACxB,MAAM,MAAM,gBAAgB,GAAG,QAAQ,CAAC;IACtC,IAAI,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;IACnC,KAAK,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;IACpC,WAAW,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;IAC1C,KAAK,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;IACpC,KAAK,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;IACpC,WAAW,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;CAC3C,CAAC,CAAA;AAEF,qFAAqF;AACrF,MAAM,MAAM,UAAU,GAAG,QAAQ,CAAC;IAChC,MAAM,EAAE,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI,CAAA;IAC9C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAA;IACvC,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;4DAGwD;IACxD,YAAY,CAAC,EAAE,MAAM,QAAQ,GAAG,UAAU,CAAA;CAC3C,CAAC,CAAA;AAEF;;;;0EAI0E;AAC1E,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;;;;;;YAlBP,CAAC,UAAU,EAAE,gBAAgB,KAAK,IAAI;gBAClC,MAAM;qBACD,MAAM;kBACT,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM;iBAC1B,OAAO;WACb,MAAM;IACb;;;4DAGwD;mBACzC,MAAM,QAAQ,GAAG,UAAU;GAsJ3C,CAAA"}
@@ -0,0 +1,337 @@
1
+ import { Effect, Equal, Function, Match as M, Option, Schema as S, Stream, String as String_, pipe, } from 'effect';
2
+ import { childAttributes, html, } from 'foldkit/html';
3
+ import { m } from 'foldkit/message';
4
+ import { ts } from 'foldkit/schema';
5
+ import { evo } from 'foldkit/struct';
6
+ import { defineView } from 'foldkit/submodel';
7
+ import * as Subscription from 'foldkit/subscription';
8
+ // MODEL
9
+ const Idle = ts('Idle');
10
+ const Dragging = ts('Dragging', { originValue: S.Number });
11
+ const DragState = S.Union([Idle, Dragging]);
12
+ /** Schema for the slider component's state. Tracks the current value, the
13
+ * range (min/max/step), and the active drag phase. */
14
+ export const Model = S.Struct({
15
+ id: S.String,
16
+ value: S.Number,
17
+ min: S.Number,
18
+ max: S.Number,
19
+ step: S.Number,
20
+ dragState: DragState,
21
+ });
22
+ // MESSAGE
23
+ /** The user pressed the thumb. Starts a drag without changing the value. */
24
+ export const PressedThumb = m('PressedThumb');
25
+ /** The user pressed the track. Starts a drag and snaps the value to the
26
+ * cursor position. Ignored while already dragging, which absorbs the bubble
27
+ * from a thumb press so the value is not shifted. */
28
+ export const PressedPointer = m('PressedPointer', { value: S.Number });
29
+ /** The pointer moved during a drag, producing a new snapped value from the
30
+ * cursor position within the track. */
31
+ export const MovedDragPointer = m('MovedDragPointer', { value: S.Number });
32
+ /** The pointer was released during a drag. Commits the current value. */
33
+ export const ReleasedDragPointer = m('ReleasedDragPointer');
34
+ /** Escape was pressed during a drag. Restores the value from the drag origin. */
35
+ export const CancelledDrag = m('CancelledDrag');
36
+ /** The user pressed a keyboard navigation key on the focused thumb. */
37
+ export const PressedKeyboardNavigation = m('PressedKeyboardNavigation', {
38
+ direction: S.Literals([
39
+ 'StepDecrement',
40
+ 'StepIncrement',
41
+ 'PageDecrement',
42
+ 'PageIncrement',
43
+ 'Min',
44
+ 'Max',
45
+ ]),
46
+ });
47
+ /** Union of all messages the slider component can produce. */
48
+ export const Message = S.Union([
49
+ PressedThumb,
50
+ PressedPointer,
51
+ MovedDragPointer,
52
+ ReleasedDragPointer,
53
+ CancelledDrag,
54
+ PressedKeyboardNavigation,
55
+ ]);
56
+ // OUT MESSAGE
57
+ /** Emitted when the slider value changes. The parent can handle this to
58
+ * update its own state or dispatch its own Commands, for example to run
59
+ * validation or trigger a downstream Command. */
60
+ export const ChangedValue = m('ChangedValue', { value: S.Number });
61
+ /** Union of all out-messages the slider component can emit to its parent. */
62
+ export const OutMessage = S.Union([ChangedValue]);
63
+ /** Creates an initial slider model from a config. The initial value is
64
+ * snapped to the step and clamped into range. */
65
+ export const init = (config) => ({
66
+ id: config.id,
67
+ value: snapAndClamp(config.initialValue, config.min, config.max, config.step),
68
+ min: config.min,
69
+ max: config.max,
70
+ step: config.step,
71
+ dragState: Idle(),
72
+ });
73
+ // HELPERS
74
+ const stepDecimals = (step) => {
75
+ const text = step.toString();
76
+ return pipe(text, String_.indexOf('.'), Option.match({
77
+ onNone: () => 0,
78
+ onSome: dotIndex => text.length - dotIndex - 1,
79
+ }));
80
+ };
81
+ const roundToStepPrecision = (value, step) => {
82
+ const decimals = stepDecimals(step);
83
+ return Number(value.toFixed(decimals));
84
+ };
85
+ const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
86
+ const snapAndClamp = (value, min, max, step) => {
87
+ const snapped = min + Math.round((value - min) / step) * step;
88
+ return roundToStepPrecision(clamp(snapped, min, max), step);
89
+ };
90
+ /** Computes the fraction (0–1) of a value between min and max. Returns 0 when
91
+ * the range has zero width. */
92
+ export const fractionOfValue = (model) => {
93
+ const range = model.max - model.min;
94
+ if (range <= 0) {
95
+ return 0;
96
+ }
97
+ else {
98
+ return clamp((model.value - model.min) / range, 0, 1);
99
+ }
100
+ };
101
+ const PAGE_STEP_MULTIPLIER = 10;
102
+ const nextValueForDirection = (model, direction) => M.value(direction).pipe(M.withReturnType(), M.when('StepIncrement', () => snapAndClamp(model.value + model.step, model.min, model.max, model.step)), M.when('StepDecrement', () => snapAndClamp(model.value - model.step, model.min, model.max, model.step)), M.when('PageIncrement', () => snapAndClamp(model.value + model.step * PAGE_STEP_MULTIPLIER, model.min, model.max, model.step)), M.when('PageDecrement', () => snapAndClamp(model.value - model.step * PAGE_STEP_MULTIPLIER, model.min, model.max, model.step)), M.when('Min', () => model.min), M.when('Max', () => model.max), M.exhaustive);
103
+ const withUpdateReturn = M.withReturnType();
104
+ const withValue = (model, nextValue, commands) => {
105
+ if (nextValue === model.value) {
106
+ return [model, commands, Option.none()];
107
+ }
108
+ else {
109
+ return [
110
+ evo(model, { value: () => nextValue }),
111
+ commands,
112
+ Option.some(ChangedValue({ value: nextValue })),
113
+ ];
114
+ }
115
+ };
116
+ /** Processes a slider message and returns the next model, commands, and an
117
+ * optional out-message for the parent. */
118
+ export const update = (model, message) => M.value(message).pipe(withUpdateReturn, M.tagsExhaustive({
119
+ PressedThumb: () => M.value(model.dragState).pipe(withUpdateReturn, M.tag('Dragging', () => [model, [], Option.none()]), M.orElse(() => [
120
+ evo(model, {
121
+ dragState: () => Dragging({ originValue: model.value }),
122
+ }),
123
+ [],
124
+ Option.none(),
125
+ ])),
126
+ // NOTE: the pointerdown event on the thumb bubbles to the track, so a
127
+ // thumb press also dispatches PressedPointer. Short-circuit when already
128
+ // Dragging so the bubbled track handler cannot shift the value away
129
+ // from the thumb's current position. Fine-grained sliders (e.g. step
130
+ // 0.05) see a visible jump without this guard, because the cursor sits
131
+ // off-center on a non-zero-width thumb.
132
+ PressedPointer: ({ value }) => M.value(model.dragState).pipe(withUpdateReturn, M.tag('Dragging', () => [model, [], Option.none()]), M.orElse(() => {
133
+ const snapped = snapAndClamp(value, model.min, model.max, model.step);
134
+ const [modelWithValue, commands, maybeOutMessage] = withValue(model, snapped, []);
135
+ return [
136
+ evo(modelWithValue, {
137
+ dragState: () => Dragging({ originValue: model.value }),
138
+ }),
139
+ commands,
140
+ maybeOutMessage,
141
+ ];
142
+ })),
143
+ MovedDragPointer: ({ value }) => M.value(model.dragState).pipe(withUpdateReturn, M.tag('Dragging', () => withValue(model, snapAndClamp(value, model.min, model.max, model.step), [])), M.orElse(() => [model, [], Option.none()])),
144
+ ReleasedDragPointer: () => M.value(model.dragState).pipe(withUpdateReturn, M.tag('Dragging', () => [
145
+ evo(model, { dragState: () => Idle() }),
146
+ [],
147
+ Option.none(),
148
+ ]), M.orElse(() => [model, [], Option.none()])),
149
+ CancelledDrag: () => M.value(model.dragState).pipe(withUpdateReturn, M.tag('Dragging', ({ originValue }) => {
150
+ const restored = evo(model, {
151
+ dragState: () => Idle(),
152
+ });
153
+ return withValue(restored, originValue, []);
154
+ }), M.orElse(() => [model, [], Option.none()])),
155
+ PressedKeyboardNavigation: ({ direction }) => withValue(model, nextValueForDirection(model, direction), []),
156
+ }));
157
+ /** Reflects an externally-driven range onto the slider. Snaps and clamps the
158
+ * current value into the new range. Use this when min/max derive from
159
+ * external state (e.g. a bounded buffer whose first/last index shifts over
160
+ * time). Unlike `reflectValue`, this runs even while the user is Dragging: a
161
+ * structural range change cannot leave the value out of bounds. */
162
+ export const reflectRange = Function.dual(2, (model, range) => evo(model, {
163
+ min: () => range.min,
164
+ max: () => range.max,
165
+ value: current => snapAndClamp(current, range.min, range.max, model.step),
166
+ }));
167
+ /** Reflects an externally-driven value onto the slider, snapped and clamped
168
+ * into range; a no-op while the user is dragging, since drag state owns the
169
+ * value. Does not emit `ChangedValue`; use when the value is being driven by
170
+ * external state rather than user input. */
171
+ export const reflectValue = Function.dual(2, (model, value) => M.value(model.dragState).pipe(M.withReturnType(), M.tag('Dragging', () => model), M.orElse(() => evo(model, {
172
+ value: () => snapAndClamp(value, model.min, model.max, model.step),
173
+ }))));
174
+ // SUBSCRIPTION
175
+ const DragActivity = S.Literals(['Idle', 'Active']);
176
+ const dragActivityFromModel = (model) => M.value(model.dragState).pipe(M.withReturnType(), M.tag('Dragging', () => 'Active'), M.orElse(() => 'Idle'));
177
+ const trackElement = (id, root) => Option.fromNullishOr(root.querySelector(`[data-slider-track-id="${id}"]`));
178
+ const valueFromClientX = (clientX, trackElement_, min, max) => {
179
+ const rect = trackElement_.getBoundingClientRect();
180
+ if (rect.width === 0) {
181
+ return min;
182
+ }
183
+ else {
184
+ const fraction = clamp((clientX - rect.left) / rect.width, 0, 1);
185
+ return min + fraction * (max - min);
186
+ }
187
+ };
188
+ /** Builds slider drag subscriptions, looking up the track
189
+ * element through the supplied root resolver. Use this when the slider is
190
+ * rendered inside a Shadow DOM. The root is read lazily so consumers can
191
+ * resolve it at subscription time. */
192
+ export const subscriptionsForRoot = (getTrackRoot) => Subscription.make()(entry => ({
193
+ dragPointer: entry({
194
+ dragActivity: DragActivity,
195
+ id: S.String,
196
+ min: S.Number,
197
+ max: S.Number,
198
+ }, {
199
+ modelToDependencies: model => ({
200
+ dragActivity: dragActivityFromModel(model),
201
+ id: model.id,
202
+ min: model.min,
203
+ max: model.max,
204
+ }),
205
+ dependenciesToStream: ({ dragActivity, id, min, max }) => {
206
+ const pointerEvents = Stream.merge(Stream.fromEventListener(document, 'pointermove').pipe(Stream.mapEffect(event => Effect.sync(() => Option.map(trackElement(id, getTrackRoot()), element => MovedDragPointer({
207
+ value: valueFromClientX(event.clientX, element, min, max),
208
+ })))), Stream.filter(Option.isSome), Stream.map(option => option.value)), Stream.fromEventListener(document, 'pointerup').pipe(Stream.map(() => ReleasedDragPointer())));
209
+ // NOTE: prevents text selection and locks cursor to grabbing while the
210
+ // user drags the thumb. Matches the approach used in drag-and-drop.
211
+ const documentDragStyles = Stream.callback(() => Effect.acquireRelease(Effect.sync(() => {
212
+ document.documentElement.style.setProperty('user-select', 'none');
213
+ document.documentElement.style.setProperty('-webkit-user-select', 'none');
214
+ const cursorStyle = document.createElement('style');
215
+ cursorStyle.textContent = '* { cursor: grabbing !important; }';
216
+ document.head.appendChild(cursorStyle);
217
+ return cursorStyle;
218
+ }), cursorStyle => Effect.sync(() => {
219
+ document.documentElement.style.removeProperty('user-select');
220
+ document.documentElement.style.removeProperty('-webkit-user-select');
221
+ cursorStyle.remove();
222
+ })).pipe(Effect.flatMap(() => Effect.never)));
223
+ return Stream.when(Stream.merge(pointerEvents, documentDragStyles), Effect.sync(() => dragActivity === 'Active'));
224
+ },
225
+ }),
226
+ dragEscape: entry({ dragActivity: DragActivity }, {
227
+ modelToDependencies: model => ({
228
+ dragActivity: dragActivityFromModel(model),
229
+ }),
230
+ dependenciesToStream: ({ dragActivity }) => Stream.when(Stream.fromEventListener(document, 'keydown').pipe(Stream.filter(({ key }) => key === 'Escape'), Stream.map(() => CancelledDrag())), Effect.sync(() => dragActivity === 'Active')),
231
+ }),
232
+ }));
233
+ /** Default drag subscriptions, with the track looked up via `document`. */
234
+ export const subscriptions = subscriptionsForRoot(() => document);
235
+ // VIEW
236
+ const LEFT_MOUSE_BUTTON = 0;
237
+ const labelId = (id) => `${id}-label`;
238
+ const keyToDirection = (key) => M.value(key).pipe(M.withReturnType(), M.whenOr('ArrowRight', 'ArrowUp', () => 'StepIncrement'), M.whenOr('ArrowLeft', 'ArrowDown', () => 'StepDecrement'), M.when('PageUp', () => 'PageIncrement'), M.when('PageDown', () => 'PageDecrement'), M.when('Home', () => 'Min'), M.when('End', () => 'Max'), M.option);
239
+ const percentString = (fraction) => `${Math.round(fraction * 10000) / 100}%`;
240
+ /** Renders an accessible slider by building ARIA attribute groups and
241
+ * delegating layout to the consumer's `toView` callback. Follows the
242
+ * WAI-ARIA slider pattern: role="slider" on the thumb, aria-valuemin /
243
+ * aria-valuemax / aria-valuenow, keyboard navigation by step / page / home /
244
+ * end. Pointer drag is handled by the component's drag subscriptions. */
245
+ export const view = defineView((model, viewInputs) => {
246
+ const h = html();
247
+ const { formatValue, isDisabled = false, name, getTrackRoot = () => document, } = viewInputs;
248
+ const { id, value, min, max } = model;
249
+ const isDragging = model.dragState._tag === 'Dragging';
250
+ const fraction = fractionOfValue(model);
251
+ const handleKeyDown = (key) => Option.map(keyToDirection(key), direction => PressedKeyboardNavigation({ direction }));
252
+ const pointerAtClientX = (clientX) => Option.map(trackElement(id, getTrackRoot()), element => PressedPointer({
253
+ value: valueFromClientX(clientX, element, min, max),
254
+ }));
255
+ const trackPointerHandler = (_pointerType, button, _screenX, _screenY, _timeStamp, clientX) => pipe(button, Option.liftPredicate(Equal.equals(LEFT_MOUSE_BUTTON)), Option.flatMap(() => pointerAtClientX(clientX)));
256
+ const thumbPointerHandler = (_pointerType, button) => pipe(button, Option.liftPredicate(Equal.equals(LEFT_MOUSE_BUTTON)), Option.map(() => PressedThumb()));
257
+ const stateAttributes = [
258
+ ...(isDragging ? [h.DataAttribute('dragging', '')] : []),
259
+ ...(isDisabled ? [h.DataAttribute('disabled', '')] : []),
260
+ ];
261
+ const rootAttributes = [
262
+ h.DataAttribute('slider-id', id),
263
+ h.DataAttribute('orientation', 'horizontal'),
264
+ ...stateAttributes,
265
+ ];
266
+ const trackInteractionAttributes = isDisabled
267
+ ? []
268
+ : [h.OnPointerDown(trackPointerHandler)];
269
+ const trackAttributes = [
270
+ h.DataAttribute('slider-track-id', id),
271
+ h.Style({ position: 'relative', 'touch-action': 'none' }),
272
+ ...stateAttributes,
273
+ ...trackInteractionAttributes,
274
+ ];
275
+ const filledTrackAttributes = [
276
+ h.Style({
277
+ position: 'absolute',
278
+ left: '0',
279
+ top: '0',
280
+ bottom: '0',
281
+ width: percentString(fraction),
282
+ 'pointer-events': 'none',
283
+ }),
284
+ ...stateAttributes,
285
+ ];
286
+ const resolveThumbLabel = () => {
287
+ if (viewInputs.ariaLabel !== undefined) {
288
+ return [h.AriaLabel(viewInputs.ariaLabel)];
289
+ }
290
+ else if (viewInputs.ariaLabelledBy !== undefined) {
291
+ return [h.AriaLabelledBy(viewInputs.ariaLabelledBy)];
292
+ }
293
+ else {
294
+ return [h.AriaLabelledBy(labelId(id))];
295
+ }
296
+ };
297
+ const thumbLabelAttributes = resolveThumbLabel();
298
+ const maybeAriaValuetext = formatValue !== undefined ? [h.AriaValuetext(formatValue(value))] : [];
299
+ const thumbInteractionAttributes = isDisabled
300
+ ? []
301
+ : [
302
+ h.OnPointerDown(thumbPointerHandler),
303
+ h.OnKeyDownPreventDefault(handleKeyDown),
304
+ ];
305
+ const thumbAttributes = [
306
+ h.Id(`${id}-thumb`),
307
+ h.Role('slider'),
308
+ h.Tabindex(0),
309
+ h.AriaOrientation('horizontal'),
310
+ h.AriaValuemin(min),
311
+ h.AriaValuemax(max),
312
+ h.AriaValuenow(value),
313
+ ...maybeAriaValuetext,
314
+ ...thumbLabelAttributes,
315
+ ...(isDisabled ? [h.AriaDisabled(true)] : []),
316
+ h.Style({
317
+ position: 'absolute',
318
+ left: percentString(fraction),
319
+ transform: 'translateX(-50%)',
320
+ 'touch-action': 'none',
321
+ }),
322
+ ...stateAttributes,
323
+ ...thumbInteractionAttributes,
324
+ ];
325
+ const labelAttributes = [h.Id(labelId(id))];
326
+ const hiddenInputAttributes = name !== undefined
327
+ ? [h.Type('hidden'), h.Name(name), h.Value(value.toString())]
328
+ : [];
329
+ return viewInputs.toView({
330
+ root: childAttributes(rootAttributes),
331
+ track: childAttributes(trackAttributes),
332
+ filledTrack: childAttributes(filledTrackAttributes),
333
+ thumb: childAttributes(thumbAttributes),
334
+ label: childAttributes(labelAttributes),
335
+ hiddenInput: childAttributes(hiddenInputAttributes),
336
+ });
337
+ });
@@ -0,0 +1,3 @@
1
+ export { init, update, reflectRange, reflectValue, view, subscriptions, subscriptionsForRoot, fractionOfValue, Model, Message, OutMessage, } from './index.js';
2
+ export type { InitConfig, ViewInputs, SliderAttributes, PressedThumb, PressedPointer, MovedDragPointer, ReleasedDragPointer, CancelledDrag, PressedKeyboardNavigation, } from './index.js';
3
+ //# sourceMappingURL=public.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/slider/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,IAAI,EACJ,MAAM,EACN,YAAY,EACZ,YAAY,EACZ,IAAI,EACJ,aAAa,EACb,oBAAoB,EACpB,eAAe,EACf,KAAK,EACL,OAAO,EACP,UAAU,GACX,MAAM,YAAY,CAAA;AAEnB,YAAY,EACV,UAAU,EACV,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,mBAAmB,EACnB,aAAa,EACb,yBAAyB,GAC1B,MAAM,YAAY,CAAA"}
@@ -0,0 +1 @@
1
+ export { init, update, reflectRange, reflectValue, view, subscriptions, subscriptionsForRoot, fractionOfValue, Model, Message, OutMessage, } from './index.js';