@zag-js/slider 2.0.0-next.0 → 2.0.0-next.2

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.
package/dist/index.d.mts CHANGED
@@ -2,7 +2,7 @@ export { anatomy } from './slider.anatomy.mjs';
2
2
  export { connect } from './slider.connect.mjs';
3
3
  export { machine } from './slider.machine.mjs';
4
4
  export { markerProps, props, splitMarkerProps, splitProps, splitThumbProps, thumbProps } from './slider.props.mjs';
5
- export { SliderApi as Api, DraggingIndicatorProps, ElementIds, FocusChangeDetails, SliderMachine as Machine, MarkerProps, SliderProps as Props, SliderService as Service, ThumbAlignment, ThumbCollisionBehavior, ThumbProps, ValueChangeDetails, ValueTextDetails } from './slider.types.mjs';
5
+ export { SliderApi as Api, DraggingIndicatorProps, ElementIds, FocusChangeDetails, SliderMachine as Machine, MarkerProps, MarkerState, SliderProps as Props, RootState, SliderService as Service, SliderOrigin, ThumbAlignment, ThumbCollisionBehavior, ThumbProps, ThumbState, ValueChangeDetails, ValueTextDetails } from './slider.types.mjs';
6
6
  import '@zag-js/anatomy';
7
7
  import '@zag-js/types';
8
8
  import '@zag-js/core';
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ export { anatomy } from './slider.anatomy.js';
2
2
  export { connect } from './slider.connect.js';
3
3
  export { machine } from './slider.machine.js';
4
4
  export { markerProps, props, splitMarkerProps, splitProps, splitThumbProps, thumbProps } from './slider.props.js';
5
- export { SliderApi as Api, DraggingIndicatorProps, ElementIds, FocusChangeDetails, SliderMachine as Machine, MarkerProps, SliderProps as Props, SliderService as Service, ThumbAlignment, ThumbCollisionBehavior, ThumbProps, ValueChangeDetails, ValueTextDetails } from './slider.types.js';
5
+ export { SliderApi as Api, DraggingIndicatorProps, ElementIds, FocusChangeDetails, SliderMachine as Machine, MarkerProps, MarkerState, SliderProps as Props, RootState, SliderService as Service, SliderOrigin, ThumbAlignment, ThumbCollisionBehavior, ThumbProps, ThumbState, ValueChangeDetails, ValueTextDetails } from './slider.types.js';
6
6
  import '@zag-js/anatomy';
7
7
  import '@zag-js/types';
8
8
  import '@zag-js/core';
@@ -48,7 +48,7 @@ function connect(service, normalize) {
48
48
  const focused = state.matches("focus");
49
49
  const dragging = state.matches("dragging");
50
50
  const disabled = computed("isDisabled");
51
- const invalid = prop("invalid");
51
+ const invalid = !!prop("invalid");
52
52
  const interactive = computed("isInteractive");
53
53
  const isHorizontal = prop("orientation") === "horizontal";
54
54
  const isVertical = prop("orientation") === "vertical";
@@ -58,6 +58,31 @@ function connect(service, normalize) {
58
58
  function getPercentValueFn(percent) {
59
59
  return (0, import_utils.getPercentValue)(percent, prop("min"), prop("max"), prop("step"));
60
60
  }
61
+ function getRootState() {
62
+ return { disabled, invalid, dragging, focused, orientation: prop("orientation") };
63
+ }
64
+ function getThumbState(props) {
65
+ const { index } = props;
66
+ return {
67
+ index,
68
+ value: sliderValue[index],
69
+ disabled,
70
+ focused: focused && focusedIndex === index,
71
+ dragging: dragging && focusedIndex === index
72
+ };
73
+ }
74
+ function getMarkerState(props) {
75
+ const { value } = props;
76
+ let markerState;
77
+ if (value < (0, import_utils.first)(sliderValue)) {
78
+ markerState = "under-value";
79
+ } else if (value > (0, import_utils.last)(sliderValue)) {
80
+ markerState = "over-value";
81
+ } else {
82
+ markerState = "at-value";
83
+ }
84
+ return { value, disabled, state: markerState };
85
+ }
61
86
  return {
62
87
  value: sliderValue,
63
88
  dragging,
@@ -96,15 +121,17 @@ function connect(service, normalize) {
96
121
  if (!interactive) return;
97
122
  send({ type: "FOCUS", index: 0 });
98
123
  },
124
+ getRootState,
99
125
  getLabelProps() {
126
+ const rootState = getRootState();
100
127
  return normalize.label({
101
128
  ...import_slider.parts.label.attrs(scope.id),
102
129
  dir: prop("dir"),
103
- "data-disabled": (0, import_dom_query.dataAttr)(disabled),
104
- "data-orientation": prop("orientation"),
105
- "data-invalid": (0, import_dom_query.dataAttr)(invalid),
106
- "data-dragging": (0, import_dom_query.dataAttr)(dragging),
107
- "data-focus": (0, import_dom_query.dataAttr)(focused),
130
+ "data-disabled": (0, import_dom_query.dataAttr)(rootState.disabled),
131
+ "data-orientation": rootState.orientation,
132
+ "data-invalid": (0, import_dom_query.dataAttr)(rootState.invalid),
133
+ "data-dragging": (0, import_dom_query.dataAttr)(rootState.dragging),
134
+ "data-focus": (0, import_dom_query.dataAttr)(rootState.focused),
108
135
  id: dom.getLabelId(scope),
109
136
  htmlFor: dom.getHiddenInputId(scope, 0),
110
137
  onClick(event) {
@@ -119,44 +146,48 @@ function connect(service, normalize) {
119
146
  });
120
147
  },
121
148
  getRootProps() {
149
+ const rootState = getRootState();
122
150
  return normalize.element({
123
151
  ...import_slider.parts.root.attrs(scope.id),
124
- "data-disabled": (0, import_dom_query.dataAttr)(disabled),
125
- "data-orientation": prop("orientation"),
126
- "data-dragging": (0, import_dom_query.dataAttr)(dragging),
127
- "data-invalid": (0, import_dom_query.dataAttr)(invalid),
128
- "data-focus": (0, import_dom_query.dataAttr)(focused),
152
+ "data-disabled": (0, import_dom_query.dataAttr)(rootState.disabled),
153
+ "data-orientation": rootState.orientation,
154
+ "data-dragging": (0, import_dom_query.dataAttr)(rootState.dragging),
155
+ "data-invalid": (0, import_dom_query.dataAttr)(rootState.invalid),
156
+ "data-focus": (0, import_dom_query.dataAttr)(rootState.focused),
129
157
  dir: prop("dir"),
130
158
  style: (0, import_slider2.getRootStyle)(service)
131
159
  });
132
160
  },
133
161
  getValueTextProps() {
162
+ const rootState = getRootState();
134
163
  return normalize.element({
135
164
  ...import_slider.parts.valueText.attrs(scope.id),
136
165
  dir: prop("dir"),
137
- "data-disabled": (0, import_dom_query.dataAttr)(disabled),
138
- "data-orientation": prop("orientation"),
139
- "data-invalid": (0, import_dom_query.dataAttr)(invalid),
140
- "data-focus": (0, import_dom_query.dataAttr)(focused)
166
+ "data-disabled": (0, import_dom_query.dataAttr)(rootState.disabled),
167
+ "data-orientation": rootState.orientation,
168
+ "data-invalid": (0, import_dom_query.dataAttr)(rootState.invalid),
169
+ "data-focus": (0, import_dom_query.dataAttr)(rootState.focused)
141
170
  });
142
171
  },
143
172
  getTrackProps() {
173
+ const rootState = getRootState();
144
174
  return normalize.element({
145
175
  ...import_slider.parts.track.attrs(scope.id),
146
176
  dir: prop("dir"),
147
- "data-disabled": (0, import_dom_query.dataAttr)(disabled),
148
- "data-invalid": (0, import_dom_query.dataAttr)(invalid),
149
- "data-dragging": (0, import_dom_query.dataAttr)(dragging),
150
- "data-orientation": prop("orientation"),
151
- "data-focus": (0, import_dom_query.dataAttr)(focused),
177
+ "data-disabled": (0, import_dom_query.dataAttr)(rootState.disabled),
178
+ "data-invalid": (0, import_dom_query.dataAttr)(rootState.invalid),
179
+ "data-dragging": (0, import_dom_query.dataAttr)(rootState.dragging),
180
+ "data-orientation": rootState.orientation,
181
+ "data-focus": (0, import_dom_query.dataAttr)(rootState.focused),
152
182
  style: { position: "relative" }
153
183
  });
154
184
  },
185
+ getThumbState,
155
186
  getThumbProps(props) {
156
187
  const { index = 0, name } = props;
157
- const value = sliderValue[index];
188
+ const thumbState = getThumbState({ index, name });
158
189
  const range = (0, import_slider3.getRangeAtIndex)(service, index);
159
- const valueText = prop("getAriaValueText")?.({ value, index });
190
+ const valueText = prop("getAriaValueText")?.({ value: thumbState.value, index });
160
191
  const _ariaLabel = Array.isArray(ariaLabel) ? ariaLabel[index] : ariaLabel;
161
192
  const _ariaLabelledBy = Array.isArray(ariaLabelledBy) ? ariaLabelledBy[index] : ariaLabelledBy;
162
193
  return normalize.element({
@@ -164,21 +195,21 @@ function connect(service, normalize) {
164
195
  dir: prop("dir"),
165
196
  "data-index": index,
166
197
  "data-name": name,
167
- "data-disabled": (0, import_dom_query.dataAttr)(disabled),
198
+ "data-disabled": (0, import_dom_query.dataAttr)(thumbState.disabled),
168
199
  "data-orientation": prop("orientation"),
169
- "data-focus": (0, import_dom_query.dataAttr)(focused && focusedIndex === index),
170
- "data-dragging": (0, import_dom_query.dataAttr)(dragging && focusedIndex === index),
200
+ "data-focus": (0, import_dom_query.dataAttr)(thumbState.focused),
201
+ "data-dragging": (0, import_dom_query.dataAttr)(thumbState.dragging),
171
202
  draggable: false,
172
- "aria-disabled": (0, import_dom_query.ariaAttr)(disabled),
203
+ "aria-disabled": (0, import_dom_query.ariaAttr)(thumbState.disabled),
173
204
  "aria-label": _ariaLabel,
174
205
  "aria-labelledby": _ariaLabelledBy ?? dom.getLabelId(scope),
175
206
  "aria-orientation": prop("orientation"),
176
207
  "aria-valuemax": range.max,
177
208
  "aria-valuemin": range.min,
178
- "aria-valuenow": sliderValue[index],
209
+ "aria-valuenow": thumbState.value,
179
210
  "aria-valuetext": valueText,
180
211
  role: "slider",
181
- tabIndex: disabled ? void 0 : 0,
212
+ tabIndex: thumbState.disabled ? void 0 : 0,
182
213
  style: (0, import_slider2.getThumbStyle)(service, index),
183
214
  onPointerDown(event) {
184
215
  if (!interactive) return;
@@ -207,7 +238,7 @@ function connect(service, normalize) {
207
238
  onKeyDown(event) {
208
239
  if (event.defaultPrevented) return;
209
240
  if (!interactive) return;
210
- const step = (0, import_dom_query.getEventStep)(event) * prop("step");
241
+ const step = (0, import_dom_query.getEventStepValue)(event, { step: prop("step"), largeStep: prop("largeStep") });
211
242
  const keyMap = {
212
243
  ArrowUp() {
213
244
  if (isHorizontal) return;
@@ -253,36 +284,39 @@ function connect(service, normalize) {
253
284
  },
254
285
  getHiddenInputProps(props) {
255
286
  const { index = 0, name } = props;
287
+ const thumbState = getThumbState({ index, name });
256
288
  return normalize.input({
257
289
  name: name ?? (prop("name") ? prop("name") + (sliderValue.length > 1 ? "[]" : "") : void 0),
258
290
  form: prop("form"),
259
291
  type: "text",
260
292
  hidden: true,
261
- defaultValue: sliderValue[index],
293
+ defaultValue: thumbState.value,
262
294
  id: dom.getHiddenInputId(scope, index)
263
295
  });
264
296
  },
265
297
  getRangeProps() {
298
+ const rootState = getRootState();
266
299
  return normalize.element({
267
300
  ...import_slider.parts.range.attrs(scope.id),
268
301
  dir: prop("dir"),
269
- "data-dragging": (0, import_dom_query.dataAttr)(dragging),
270
- "data-focus": (0, import_dom_query.dataAttr)(focused),
271
- "data-invalid": (0, import_dom_query.dataAttr)(invalid),
272
- "data-disabled": (0, import_dom_query.dataAttr)(disabled),
273
- "data-orientation": prop("orientation"),
302
+ "data-dragging": (0, import_dom_query.dataAttr)(rootState.dragging),
303
+ "data-focus": (0, import_dom_query.dataAttr)(rootState.focused),
304
+ "data-invalid": (0, import_dom_query.dataAttr)(rootState.invalid),
305
+ "data-disabled": (0, import_dom_query.dataAttr)(rootState.disabled),
306
+ "data-orientation": rootState.orientation,
274
307
  style: (0, import_slider2.getRangeStyle)(service)
275
308
  });
276
309
  },
277
310
  getControlProps() {
311
+ const rootState = getRootState();
278
312
  return normalize.element({
279
313
  ...import_slider.parts.control.attrs(scope.id),
280
314
  dir: prop("dir"),
281
- "data-dragging": (0, import_dom_query.dataAttr)(dragging),
282
- "data-disabled": (0, import_dom_query.dataAttr)(disabled),
283
- "data-orientation": prop("orientation"),
284
- "data-invalid": (0, import_dom_query.dataAttr)(invalid),
285
- "data-focus": (0, import_dom_query.dataAttr)(focused),
315
+ "data-dragging": (0, import_dom_query.dataAttr)(rootState.dragging),
316
+ "data-disabled": (0, import_dom_query.dataAttr)(rootState.disabled),
317
+ "data-orientation": rootState.orientation,
318
+ "data-invalid": (0, import_dom_query.dataAttr)(rootState.invalid),
319
+ "data-focus": (0, import_dom_query.dataAttr)(rootState.focused),
286
320
  style: (0, import_slider2.getControlStyle)(),
287
321
  onPointerDown(event) {
288
322
  if (!interactive) return;
@@ -305,37 +339,31 @@ function connect(service, normalize) {
305
339
  style: (0, import_slider2.getMarkerGroupStyle)()
306
340
  });
307
341
  },
342
+ getMarkerState,
308
343
  getMarkerProps(props) {
309
344
  const style = (0, import_slider2.getMarkerStyle)(service, props.value);
310
- let markerState;
311
- if (props.value < (0, import_utils.first)(sliderValue)) {
312
- markerState = "under-value";
313
- } else if (props.value > (0, import_utils.last)(sliderValue)) {
314
- markerState = "over-value";
315
- } else {
316
- markerState = "at-value";
317
- }
345
+ const markerState = getMarkerState(props);
318
346
  return normalize.element({
319
347
  ...import_slider.parts.marker.attrs(scope.id),
320
348
  role: "presentation",
321
349
  dir: prop("dir"),
322
350
  "data-orientation": prop("orientation"),
323
- "data-value": props.value,
324
- "data-disabled": (0, import_dom_query.dataAttr)(disabled),
325
- "data-state": markerState,
351
+ "data-value": markerState.value,
352
+ "data-disabled": (0, import_dom_query.dataAttr)(markerState.disabled),
353
+ "data-state": markerState.state,
326
354
  style
327
355
  });
328
356
  },
329
357
  getDraggingIndicatorProps(props) {
330
358
  const { index = 0 } = props;
331
- const isDragging = index === focusedIndex && dragging;
359
+ const thumbState = getThumbState({ index });
332
360
  return normalize.element({
333
361
  ...import_slider.parts.draggingIndicator.attrs(scope.id),
334
362
  role: "presentation",
335
363
  dir: prop("dir"),
336
- hidden: !isDragging,
364
+ hidden: !thumbState.dragging,
337
365
  "data-orientation": prop("orientation"),
338
- "data-state": isDragging ? "open" : "closed",
366
+ "data-state": thumbState.dragging ? "open" : "closed",
339
367
  style: (0, import_slider2.getThumbStyle)(service, index)
340
368
  });
341
369
  }
@@ -4,7 +4,7 @@ import {
4
4
  dataAttr,
5
5
  getEventKey,
6
6
  getEventPoint,
7
- getEventStep,
7
+ getEventStepValue,
8
8
  isLeftClick,
9
9
  isModifierKey
10
10
  } from "@zag-js/dom-query";
@@ -29,7 +29,7 @@ function connect(service, normalize) {
29
29
  const focused = state.matches("focus");
30
30
  const dragging = state.matches("dragging");
31
31
  const disabled = computed("isDisabled");
32
- const invalid = prop("invalid");
32
+ const invalid = !!prop("invalid");
33
33
  const interactive = computed("isInteractive");
34
34
  const isHorizontal = prop("orientation") === "horizontal";
35
35
  const isVertical = prop("orientation") === "vertical";
@@ -39,6 +39,31 @@ function connect(service, normalize) {
39
39
  function getPercentValueFn(percent) {
40
40
  return getPercentValue(percent, prop("min"), prop("max"), prop("step"));
41
41
  }
42
+ function getRootState() {
43
+ return { disabled, invalid, dragging, focused, orientation: prop("orientation") };
44
+ }
45
+ function getThumbState(props) {
46
+ const { index } = props;
47
+ return {
48
+ index,
49
+ value: sliderValue[index],
50
+ disabled,
51
+ focused: focused && focusedIndex === index,
52
+ dragging: dragging && focusedIndex === index
53
+ };
54
+ }
55
+ function getMarkerState(props) {
56
+ const { value } = props;
57
+ let markerState;
58
+ if (value < first(sliderValue)) {
59
+ markerState = "under-value";
60
+ } else if (value > last(sliderValue)) {
61
+ markerState = "over-value";
62
+ } else {
63
+ markerState = "at-value";
64
+ }
65
+ return { value, disabled, state: markerState };
66
+ }
42
67
  return {
43
68
  value: sliderValue,
44
69
  dragging,
@@ -77,15 +102,17 @@ function connect(service, normalize) {
77
102
  if (!interactive) return;
78
103
  send({ type: "FOCUS", index: 0 });
79
104
  },
105
+ getRootState,
80
106
  getLabelProps() {
107
+ const rootState = getRootState();
81
108
  return normalize.label({
82
109
  ...parts.label.attrs(scope.id),
83
110
  dir: prop("dir"),
84
- "data-disabled": dataAttr(disabled),
85
- "data-orientation": prop("orientation"),
86
- "data-invalid": dataAttr(invalid),
87
- "data-dragging": dataAttr(dragging),
88
- "data-focus": dataAttr(focused),
111
+ "data-disabled": dataAttr(rootState.disabled),
112
+ "data-orientation": rootState.orientation,
113
+ "data-invalid": dataAttr(rootState.invalid),
114
+ "data-dragging": dataAttr(rootState.dragging),
115
+ "data-focus": dataAttr(rootState.focused),
89
116
  id: dom.getLabelId(scope),
90
117
  htmlFor: dom.getHiddenInputId(scope, 0),
91
118
  onClick(event) {
@@ -100,44 +127,48 @@ function connect(service, normalize) {
100
127
  });
101
128
  },
102
129
  getRootProps() {
130
+ const rootState = getRootState();
103
131
  return normalize.element({
104
132
  ...parts.root.attrs(scope.id),
105
- "data-disabled": dataAttr(disabled),
106
- "data-orientation": prop("orientation"),
107
- "data-dragging": dataAttr(dragging),
108
- "data-invalid": dataAttr(invalid),
109
- "data-focus": dataAttr(focused),
133
+ "data-disabled": dataAttr(rootState.disabled),
134
+ "data-orientation": rootState.orientation,
135
+ "data-dragging": dataAttr(rootState.dragging),
136
+ "data-invalid": dataAttr(rootState.invalid),
137
+ "data-focus": dataAttr(rootState.focused),
110
138
  dir: prop("dir"),
111
139
  style: getRootStyle(service)
112
140
  });
113
141
  },
114
142
  getValueTextProps() {
143
+ const rootState = getRootState();
115
144
  return normalize.element({
116
145
  ...parts.valueText.attrs(scope.id),
117
146
  dir: prop("dir"),
118
- "data-disabled": dataAttr(disabled),
119
- "data-orientation": prop("orientation"),
120
- "data-invalid": dataAttr(invalid),
121
- "data-focus": dataAttr(focused)
147
+ "data-disabled": dataAttr(rootState.disabled),
148
+ "data-orientation": rootState.orientation,
149
+ "data-invalid": dataAttr(rootState.invalid),
150
+ "data-focus": dataAttr(rootState.focused)
122
151
  });
123
152
  },
124
153
  getTrackProps() {
154
+ const rootState = getRootState();
125
155
  return normalize.element({
126
156
  ...parts.track.attrs(scope.id),
127
157
  dir: prop("dir"),
128
- "data-disabled": dataAttr(disabled),
129
- "data-invalid": dataAttr(invalid),
130
- "data-dragging": dataAttr(dragging),
131
- "data-orientation": prop("orientation"),
132
- "data-focus": dataAttr(focused),
158
+ "data-disabled": dataAttr(rootState.disabled),
159
+ "data-invalid": dataAttr(rootState.invalid),
160
+ "data-dragging": dataAttr(rootState.dragging),
161
+ "data-orientation": rootState.orientation,
162
+ "data-focus": dataAttr(rootState.focused),
133
163
  style: { position: "relative" }
134
164
  });
135
165
  },
166
+ getThumbState,
136
167
  getThumbProps(props) {
137
168
  const { index = 0, name } = props;
138
- const value = sliderValue[index];
169
+ const thumbState = getThumbState({ index, name });
139
170
  const range = getRangeAtIndex(service, index);
140
- const valueText = prop("getAriaValueText")?.({ value, index });
171
+ const valueText = prop("getAriaValueText")?.({ value: thumbState.value, index });
141
172
  const _ariaLabel = Array.isArray(ariaLabel) ? ariaLabel[index] : ariaLabel;
142
173
  const _ariaLabelledBy = Array.isArray(ariaLabelledBy) ? ariaLabelledBy[index] : ariaLabelledBy;
143
174
  return normalize.element({
@@ -145,21 +176,21 @@ function connect(service, normalize) {
145
176
  dir: prop("dir"),
146
177
  "data-index": index,
147
178
  "data-name": name,
148
- "data-disabled": dataAttr(disabled),
179
+ "data-disabled": dataAttr(thumbState.disabled),
149
180
  "data-orientation": prop("orientation"),
150
- "data-focus": dataAttr(focused && focusedIndex === index),
151
- "data-dragging": dataAttr(dragging && focusedIndex === index),
181
+ "data-focus": dataAttr(thumbState.focused),
182
+ "data-dragging": dataAttr(thumbState.dragging),
152
183
  draggable: false,
153
- "aria-disabled": ariaAttr(disabled),
184
+ "aria-disabled": ariaAttr(thumbState.disabled),
154
185
  "aria-label": _ariaLabel,
155
186
  "aria-labelledby": _ariaLabelledBy ?? dom.getLabelId(scope),
156
187
  "aria-orientation": prop("orientation"),
157
188
  "aria-valuemax": range.max,
158
189
  "aria-valuemin": range.min,
159
- "aria-valuenow": sliderValue[index],
190
+ "aria-valuenow": thumbState.value,
160
191
  "aria-valuetext": valueText,
161
192
  role: "slider",
162
- tabIndex: disabled ? void 0 : 0,
193
+ tabIndex: thumbState.disabled ? void 0 : 0,
163
194
  style: getThumbStyle(service, index),
164
195
  onPointerDown(event) {
165
196
  if (!interactive) return;
@@ -188,7 +219,7 @@ function connect(service, normalize) {
188
219
  onKeyDown(event) {
189
220
  if (event.defaultPrevented) return;
190
221
  if (!interactive) return;
191
- const step = getEventStep(event) * prop("step");
222
+ const step = getEventStepValue(event, { step: prop("step"), largeStep: prop("largeStep") });
192
223
  const keyMap = {
193
224
  ArrowUp() {
194
225
  if (isHorizontal) return;
@@ -234,36 +265,39 @@ function connect(service, normalize) {
234
265
  },
235
266
  getHiddenInputProps(props) {
236
267
  const { index = 0, name } = props;
268
+ const thumbState = getThumbState({ index, name });
237
269
  return normalize.input({
238
270
  name: name ?? (prop("name") ? prop("name") + (sliderValue.length > 1 ? "[]" : "") : void 0),
239
271
  form: prop("form"),
240
272
  type: "text",
241
273
  hidden: true,
242
- defaultValue: sliderValue[index],
274
+ defaultValue: thumbState.value,
243
275
  id: dom.getHiddenInputId(scope, index)
244
276
  });
245
277
  },
246
278
  getRangeProps() {
279
+ const rootState = getRootState();
247
280
  return normalize.element({
248
281
  ...parts.range.attrs(scope.id),
249
282
  dir: prop("dir"),
250
- "data-dragging": dataAttr(dragging),
251
- "data-focus": dataAttr(focused),
252
- "data-invalid": dataAttr(invalid),
253
- "data-disabled": dataAttr(disabled),
254
- "data-orientation": prop("orientation"),
283
+ "data-dragging": dataAttr(rootState.dragging),
284
+ "data-focus": dataAttr(rootState.focused),
285
+ "data-invalid": dataAttr(rootState.invalid),
286
+ "data-disabled": dataAttr(rootState.disabled),
287
+ "data-orientation": rootState.orientation,
255
288
  style: getRangeStyle(service)
256
289
  });
257
290
  },
258
291
  getControlProps() {
292
+ const rootState = getRootState();
259
293
  return normalize.element({
260
294
  ...parts.control.attrs(scope.id),
261
295
  dir: prop("dir"),
262
- "data-dragging": dataAttr(dragging),
263
- "data-disabled": dataAttr(disabled),
264
- "data-orientation": prop("orientation"),
265
- "data-invalid": dataAttr(invalid),
266
- "data-focus": dataAttr(focused),
296
+ "data-dragging": dataAttr(rootState.dragging),
297
+ "data-disabled": dataAttr(rootState.disabled),
298
+ "data-orientation": rootState.orientation,
299
+ "data-invalid": dataAttr(rootState.invalid),
300
+ "data-focus": dataAttr(rootState.focused),
267
301
  style: getControlStyle(),
268
302
  onPointerDown(event) {
269
303
  if (!interactive) return;
@@ -286,37 +320,31 @@ function connect(service, normalize) {
286
320
  style: getMarkerGroupStyle()
287
321
  });
288
322
  },
323
+ getMarkerState,
289
324
  getMarkerProps(props) {
290
325
  const style = getMarkerStyle(service, props.value);
291
- let markerState;
292
- if (props.value < first(sliderValue)) {
293
- markerState = "under-value";
294
- } else if (props.value > last(sliderValue)) {
295
- markerState = "over-value";
296
- } else {
297
- markerState = "at-value";
298
- }
326
+ const markerState = getMarkerState(props);
299
327
  return normalize.element({
300
328
  ...parts.marker.attrs(scope.id),
301
329
  role: "presentation",
302
330
  dir: prop("dir"),
303
331
  "data-orientation": prop("orientation"),
304
- "data-value": props.value,
305
- "data-disabled": dataAttr(disabled),
306
- "data-state": markerState,
332
+ "data-value": markerState.value,
333
+ "data-disabled": dataAttr(markerState.disabled),
334
+ "data-state": markerState.state,
307
335
  style
308
336
  });
309
337
  },
310
338
  getDraggingIndicatorProps(props) {
311
339
  const { index = 0 } = props;
312
- const isDragging = index === focusedIndex && dragging;
340
+ const thumbState = getThumbState({ index });
313
341
  return normalize.element({
314
342
  ...parts.draggingIndicator.attrs(scope.id),
315
343
  role: "presentation",
316
344
  dir: prop("dir"),
317
- hidden: !isDragging,
345
+ hidden: !thumbState.dragging,
318
346
  "data-orientation": prop("orientation"),
319
- "data-state": isDragging ? "open" : "closed",
347
+ "data-state": thumbState.dragging ? "open" : "closed",
320
348
  style: getThumbStyle(service, index)
321
349
  });
322
350
  }
@@ -69,6 +69,7 @@ var machine = (0, import_core.createMachine)({
69
69
  thumbCollisionBehavior: "none",
70
70
  minStepsBetweenThumbs,
71
71
  ...props,
72
+ largeStep: props.largeStep ?? 10 * step,
72
73
  defaultValue: normalize(defaultValue, min, max, step, minStepsBetweenThumbs),
73
74
  value: props.value ? normalize(props.value, min, max, step, minStepsBetweenThumbs) : void 0,
74
75
  max,
@@ -54,6 +54,7 @@ var machine = createMachine({
54
54
  thumbCollisionBehavior: "none",
55
55
  minStepsBetweenThumbs,
56
56
  ...props,
57
+ largeStep: props.largeStep ?? 10 * step,
57
58
  defaultValue: normalize(defaultValue, min, max, step, minStepsBetweenThumbs),
58
59
  value: props.value ? normalize(props.value, min, max, step, minStepsBetweenThumbs) : void 0,
59
60
  max,
@@ -41,6 +41,7 @@ var props = (0, import_types.createProps)()([
41
41
  "id",
42
42
  "ids",
43
43
  "invalid",
44
+ "largeStep",
44
45
  "max",
45
46
  "min",
46
47
  "minStepsBetweenThumbs",
@@ -12,6 +12,7 @@ var props = createProps()([
12
12
  "id",
13
13
  "ids",
14
14
  "invalid",
15
+ "largeStep",
15
16
  "max",
16
17
  "min",
17
18
  "minStepsBetweenThumbs",
@@ -32,6 +32,7 @@ __export(slider_style_exports, {
32
32
  });
33
33
  module.exports = __toCommonJS(slider_style_exports);
34
34
  var import_utils = require("@zag-js/utils");
35
+ var import_slider = require("./slider.utils.js");
35
36
  function getBounds(value) {
36
37
  const firstValue = value[0];
37
38
  const lastThumb = value[value.length - 1];
@@ -42,16 +43,9 @@ function getRangeOffsets(params) {
42
43
  const valuePercent = computed("valuePercent");
43
44
  const [firstPercent, lastPercent] = getBounds(valuePercent);
44
45
  if (valuePercent.length === 1) {
45
- if (prop("origin") === "center") {
46
- const isNegative = valuePercent[0] < 50;
47
- const start = isNegative ? `${valuePercent[0]}%` : "50%";
48
- const end = isNegative ? "50%" : `${100 - valuePercent[0]}%`;
49
- return { start, end };
50
- }
51
- if (prop("origin") === "end") {
52
- return { start: `${lastPercent}%`, end: "0%" };
53
- }
54
- return { start: "0%", end: `${100 - lastPercent}%` };
46
+ const originPercent = (0, import_slider.getOriginPercent)(prop("origin"), prop("min"), prop("max"));
47
+ const { start, end } = (0, import_slider.getFillRange)(valuePercent[0], originPercent);
48
+ return { start: `${start}%`, end: `${end}%` };
55
49
  }
56
50
  return { start: `${firstPercent}%`, end: `${100 - lastPercent}%` };
57
51
  }
@@ -1,5 +1,6 @@
1
1
  // src/slider.style.ts
2
2
  import { getValuePercent, getValueTransformer, toPx } from "@zag-js/utils";
3
+ import { getFillRange, getOriginPercent } from "./slider.utils.mjs";
3
4
  function getBounds(value) {
4
5
  const firstValue = value[0];
5
6
  const lastThumb = value[value.length - 1];
@@ -10,16 +11,9 @@ function getRangeOffsets(params) {
10
11
  const valuePercent = computed("valuePercent");
11
12
  const [firstPercent, lastPercent] = getBounds(valuePercent);
12
13
  if (valuePercent.length === 1) {
13
- if (prop("origin") === "center") {
14
- const isNegative = valuePercent[0] < 50;
15
- const start = isNegative ? `${valuePercent[0]}%` : "50%";
16
- const end = isNegative ? "50%" : `${100 - valuePercent[0]}%`;
17
- return { start, end };
18
- }
19
- if (prop("origin") === "end") {
20
- return { start: `${lastPercent}%`, end: "0%" };
21
- }
22
- return { start: "0%", end: `${100 - lastPercent}%` };
14
+ const originPercent = getOriginPercent(prop("origin"), prop("min"), prop("max"));
15
+ const { start, end } = getFillRange(valuePercent[0], originPercent);
16
+ return { start: `${start}%`, end: `${end}%` };
23
17
  }
24
18
  return { start: `${firstPercent}%`, end: `${100 - lastPercent}%` };
25
19
  }
@@ -1,8 +1,9 @@
1
1
  import { Machine, EventObject, Service } from '@zag-js/core';
2
- import { PropTypes, RequiredBy, DirectionProperty, CommonProperties } from '@zag-js/types';
2
+ import { PropTypes, DirectionProperty, CommonProperties } from '@zag-js/types';
3
3
 
4
4
  type ThumbCollisionBehavior = "none" | "push" | "swap";
5
5
  type ThumbAlignment = "contain" | "center";
6
+ type SliderOrigin = "start" | "center" | "end" | number;
6
7
  interface ValueChangeDetails {
7
8
  value: number[];
8
9
  }
@@ -14,17 +15,17 @@ interface ValueTextDetails {
14
15
  value: number;
15
16
  index: number;
16
17
  }
17
- type ElementIds = Partial<{
18
- root: string;
19
- thumb: (index: number) => string;
20
- hiddenInput: (index: number) => string;
21
- control: string;
22
- track: string;
23
- range: string;
24
- label: string;
25
- valueText: string;
26
- marker: (index: number) => string;
27
- }>;
18
+ interface ElementIds {
19
+ root?: string | undefined;
20
+ thumb?: ((index: number) => string) | undefined;
21
+ hiddenInput?: ((index: number) => string) | undefined;
22
+ control?: string | undefined;
23
+ track?: string | undefined;
24
+ range?: string | undefined;
25
+ label?: string | undefined;
26
+ valueText?: string | undefined;
27
+ marker?: ((index: number) => string) | undefined;
28
+ }
28
29
  interface SliderProps extends DirectionProperty, CommonProperties {
29
30
  /**
30
31
  * The ids of the elements in the slider. Useful for composition.
@@ -98,6 +99,12 @@ interface SliderProps extends DirectionProperty, CommonProperties {
98
99
  * @default 1
99
100
  */
100
101
  step?: number | undefined;
102
+ /**
103
+ * The step value of the slider when the `Shift` key is held, or the
104
+ * `PageUp`/`PageDown` keys are used.
105
+ * @default 10 * step
106
+ */
107
+ largeStep?: number | undefined;
101
108
  /**
102
109
  * The minimum permitted steps between multiple thumbs.
103
110
  *
@@ -115,15 +122,14 @@ interface SliderProps extends DirectionProperty, CommonProperties {
115
122
  */
116
123
  orientation?: "vertical" | "horizontal" | undefined;
117
124
  /**
118
- * The origin of the slider range. The track is filled from the origin
119
- * to the thumb for single values.
120
- * - "start": Useful when the value represents an absolute value
121
- * - "center": Useful when the value represents an offset (relative)
122
- * - "end": Useful when the value represents an offset from the end
125
+ * The origin of the slider range. The track is filled from the origin to the thumb.
126
+ * - `"start"` / `"end"`: fill from `min` / `max`
127
+ * - `"center"`: fill from the midpoint of `min`/`max`
128
+ * - a `number`: fill from that value instead, for when the neutral point isn't the midpoint
123
129
  *
124
130
  * @default "start"
125
131
  */
126
- origin?: "start" | "center" | "end" | undefined;
132
+ origin?: SliderOrigin | undefined;
127
133
  /**
128
134
  * The alignment of the slider thumb relative to the track
129
135
  * - `center`: the thumb will extend beyond the bounds of the slider track.
@@ -149,7 +155,7 @@ interface SliderProps extends DirectionProperty, CommonProperties {
149
155
  */
150
156
  thumbCollisionBehavior?: "none" | "push" | "swap" | undefined;
151
157
  }
152
- type PropsWithDefault = "dir" | "min" | "max" | "step" | "orientation" | "defaultValue" | "origin" | "thumbAlignment" | "minStepsBetweenThumbs" | "thumbCollisionBehavior";
158
+ type PropsWithDefault = "dir" | "min" | "max" | "step" | "largeStep" | "orientation" | "defaultValue" | "origin" | "thumbAlignment" | "minStepsBetweenThumbs" | "thumbCollisionBehavior";
153
159
  type Computed = Readonly<{
154
160
  /**
155
161
  * @computed
@@ -204,7 +210,8 @@ interface Context {
204
210
  }
205
211
  interface SliderSchema {
206
212
  state: "idle" | "dragging" | "focus";
207
- props: RequiredBy<SliderProps, PropsWithDefault>;
213
+ props: SliderProps;
214
+ defaultPropKey: PropsWithDefault;
208
215
  context: Context;
209
216
  refs: {
210
217
  /**
@@ -236,13 +243,71 @@ interface Size {
236
243
  interface MarkerProps {
237
244
  value: number;
238
245
  }
246
+ interface MarkerState {
247
+ /**
248
+ * The value of the marker
249
+ */
250
+ value: number;
251
+ /**
252
+ * Whether the marker is disabled
253
+ */
254
+ disabled: boolean;
255
+ /**
256
+ * The state of the marker relative to the slider value
257
+ */
258
+ state: "under-value" | "over-value" | "at-value";
259
+ }
239
260
  interface ThumbProps {
240
261
  index: number;
241
262
  name?: string | undefined;
242
263
  }
264
+ interface ThumbState {
265
+ /**
266
+ * The index of the thumb
267
+ */
268
+ index: number;
269
+ /**
270
+ * The value of the thumb
271
+ */
272
+ value: number;
273
+ /**
274
+ * Whether the thumb is disabled
275
+ */
276
+ disabled: boolean;
277
+ /**
278
+ * Whether the thumb is focused
279
+ */
280
+ focused: boolean;
281
+ /**
282
+ * Whether the thumb is being dragged
283
+ */
284
+ dragging: boolean;
285
+ }
243
286
  interface DraggingIndicatorProps {
244
287
  index: number;
245
288
  }
289
+ interface RootState {
290
+ /**
291
+ * Whether the slider is disabled
292
+ */
293
+ disabled: boolean;
294
+ /**
295
+ * Whether the slider is invalid
296
+ */
297
+ invalid: boolean;
298
+ /**
299
+ * Whether the slider is being dragged
300
+ */
301
+ dragging: boolean;
302
+ /**
303
+ * Whether the slider is focused
304
+ */
305
+ focused: boolean;
306
+ /**
307
+ * The orientation of the slider
308
+ */
309
+ orientation: "vertical" | "horizontal";
310
+ }
246
311
  interface SliderApi<T extends PropTypes = PropTypes> {
247
312
  /**
248
313
  * The value of the slider.
@@ -304,17 +369,29 @@ interface SliderApi<T extends PropTypes = PropTypes> {
304
369
  * Function to focus the slider. This focuses the first thumb.
305
370
  */
306
371
  focus: VoidFunction;
372
+ /**
373
+ * Returns the state of the slider
374
+ */
375
+ getRootState: () => RootState;
307
376
  getLabelProps: () => T["label"];
308
377
  getRootProps: () => T["element"];
309
378
  getValueTextProps: () => T["element"];
310
379
  getTrackProps: () => T["element"];
380
+ /**
381
+ * Returns the state of a specific thumb
382
+ */
383
+ getThumbState: (props: ThumbProps) => ThumbState;
311
384
  getThumbProps: (props: ThumbProps) => T["element"];
312
385
  getHiddenInputProps: (props: ThumbProps) => T["input"];
313
386
  getRangeProps: () => T["element"];
314
387
  getControlProps: () => T["element"];
315
388
  getMarkerGroupProps: () => T["element"];
389
+ /**
390
+ * Returns the state of a specific marker
391
+ */
392
+ getMarkerState: (props: MarkerProps) => MarkerState;
316
393
  getMarkerProps: (props: MarkerProps) => T["element"];
317
394
  getDraggingIndicatorProps: (props: DraggingIndicatorProps) => T["element"];
318
395
  }
319
396
 
320
- export type { DraggingIndicatorProps, ElementIds, FocusChangeDetails, MarkerProps, SliderApi, SliderMachine, SliderProps, SliderSchema, SliderService, ThumbAlignment, ThumbCollisionBehavior, ThumbProps, ValueChangeDetails, ValueTextDetails };
397
+ export type { DraggingIndicatorProps, ElementIds, FocusChangeDetails, MarkerProps, MarkerState, RootState, SliderApi, SliderMachine, SliderOrigin, SliderProps, SliderSchema, SliderService, ThumbAlignment, ThumbCollisionBehavior, ThumbProps, ThumbState, ValueChangeDetails, ValueTextDetails };
@@ -1,8 +1,9 @@
1
1
  import { Machine, EventObject, Service } from '@zag-js/core';
2
- import { PropTypes, RequiredBy, DirectionProperty, CommonProperties } from '@zag-js/types';
2
+ import { PropTypes, DirectionProperty, CommonProperties } from '@zag-js/types';
3
3
 
4
4
  type ThumbCollisionBehavior = "none" | "push" | "swap";
5
5
  type ThumbAlignment = "contain" | "center";
6
+ type SliderOrigin = "start" | "center" | "end" | number;
6
7
  interface ValueChangeDetails {
7
8
  value: number[];
8
9
  }
@@ -14,17 +15,17 @@ interface ValueTextDetails {
14
15
  value: number;
15
16
  index: number;
16
17
  }
17
- type ElementIds = Partial<{
18
- root: string;
19
- thumb: (index: number) => string;
20
- hiddenInput: (index: number) => string;
21
- control: string;
22
- track: string;
23
- range: string;
24
- label: string;
25
- valueText: string;
26
- marker: (index: number) => string;
27
- }>;
18
+ interface ElementIds {
19
+ root?: string | undefined;
20
+ thumb?: ((index: number) => string) | undefined;
21
+ hiddenInput?: ((index: number) => string) | undefined;
22
+ control?: string | undefined;
23
+ track?: string | undefined;
24
+ range?: string | undefined;
25
+ label?: string | undefined;
26
+ valueText?: string | undefined;
27
+ marker?: ((index: number) => string) | undefined;
28
+ }
28
29
  interface SliderProps extends DirectionProperty, CommonProperties {
29
30
  /**
30
31
  * The ids of the elements in the slider. Useful for composition.
@@ -98,6 +99,12 @@ interface SliderProps extends DirectionProperty, CommonProperties {
98
99
  * @default 1
99
100
  */
100
101
  step?: number | undefined;
102
+ /**
103
+ * The step value of the slider when the `Shift` key is held, or the
104
+ * `PageUp`/`PageDown` keys are used.
105
+ * @default 10 * step
106
+ */
107
+ largeStep?: number | undefined;
101
108
  /**
102
109
  * The minimum permitted steps between multiple thumbs.
103
110
  *
@@ -115,15 +122,14 @@ interface SliderProps extends DirectionProperty, CommonProperties {
115
122
  */
116
123
  orientation?: "vertical" | "horizontal" | undefined;
117
124
  /**
118
- * The origin of the slider range. The track is filled from the origin
119
- * to the thumb for single values.
120
- * - "start": Useful when the value represents an absolute value
121
- * - "center": Useful when the value represents an offset (relative)
122
- * - "end": Useful when the value represents an offset from the end
125
+ * The origin of the slider range. The track is filled from the origin to the thumb.
126
+ * - `"start"` / `"end"`: fill from `min` / `max`
127
+ * - `"center"`: fill from the midpoint of `min`/`max`
128
+ * - a `number`: fill from that value instead, for when the neutral point isn't the midpoint
123
129
  *
124
130
  * @default "start"
125
131
  */
126
- origin?: "start" | "center" | "end" | undefined;
132
+ origin?: SliderOrigin | undefined;
127
133
  /**
128
134
  * The alignment of the slider thumb relative to the track
129
135
  * - `center`: the thumb will extend beyond the bounds of the slider track.
@@ -149,7 +155,7 @@ interface SliderProps extends DirectionProperty, CommonProperties {
149
155
  */
150
156
  thumbCollisionBehavior?: "none" | "push" | "swap" | undefined;
151
157
  }
152
- type PropsWithDefault = "dir" | "min" | "max" | "step" | "orientation" | "defaultValue" | "origin" | "thumbAlignment" | "minStepsBetweenThumbs" | "thumbCollisionBehavior";
158
+ type PropsWithDefault = "dir" | "min" | "max" | "step" | "largeStep" | "orientation" | "defaultValue" | "origin" | "thumbAlignment" | "minStepsBetweenThumbs" | "thumbCollisionBehavior";
153
159
  type Computed = Readonly<{
154
160
  /**
155
161
  * @computed
@@ -204,7 +210,8 @@ interface Context {
204
210
  }
205
211
  interface SliderSchema {
206
212
  state: "idle" | "dragging" | "focus";
207
- props: RequiredBy<SliderProps, PropsWithDefault>;
213
+ props: SliderProps;
214
+ defaultPropKey: PropsWithDefault;
208
215
  context: Context;
209
216
  refs: {
210
217
  /**
@@ -236,13 +243,71 @@ interface Size {
236
243
  interface MarkerProps {
237
244
  value: number;
238
245
  }
246
+ interface MarkerState {
247
+ /**
248
+ * The value of the marker
249
+ */
250
+ value: number;
251
+ /**
252
+ * Whether the marker is disabled
253
+ */
254
+ disabled: boolean;
255
+ /**
256
+ * The state of the marker relative to the slider value
257
+ */
258
+ state: "under-value" | "over-value" | "at-value";
259
+ }
239
260
  interface ThumbProps {
240
261
  index: number;
241
262
  name?: string | undefined;
242
263
  }
264
+ interface ThumbState {
265
+ /**
266
+ * The index of the thumb
267
+ */
268
+ index: number;
269
+ /**
270
+ * The value of the thumb
271
+ */
272
+ value: number;
273
+ /**
274
+ * Whether the thumb is disabled
275
+ */
276
+ disabled: boolean;
277
+ /**
278
+ * Whether the thumb is focused
279
+ */
280
+ focused: boolean;
281
+ /**
282
+ * Whether the thumb is being dragged
283
+ */
284
+ dragging: boolean;
285
+ }
243
286
  interface DraggingIndicatorProps {
244
287
  index: number;
245
288
  }
289
+ interface RootState {
290
+ /**
291
+ * Whether the slider is disabled
292
+ */
293
+ disabled: boolean;
294
+ /**
295
+ * Whether the slider is invalid
296
+ */
297
+ invalid: boolean;
298
+ /**
299
+ * Whether the slider is being dragged
300
+ */
301
+ dragging: boolean;
302
+ /**
303
+ * Whether the slider is focused
304
+ */
305
+ focused: boolean;
306
+ /**
307
+ * The orientation of the slider
308
+ */
309
+ orientation: "vertical" | "horizontal";
310
+ }
246
311
  interface SliderApi<T extends PropTypes = PropTypes> {
247
312
  /**
248
313
  * The value of the slider.
@@ -304,17 +369,29 @@ interface SliderApi<T extends PropTypes = PropTypes> {
304
369
  * Function to focus the slider. This focuses the first thumb.
305
370
  */
306
371
  focus: VoidFunction;
372
+ /**
373
+ * Returns the state of the slider
374
+ */
375
+ getRootState: () => RootState;
307
376
  getLabelProps: () => T["label"];
308
377
  getRootProps: () => T["element"];
309
378
  getValueTextProps: () => T["element"];
310
379
  getTrackProps: () => T["element"];
380
+ /**
381
+ * Returns the state of a specific thumb
382
+ */
383
+ getThumbState: (props: ThumbProps) => ThumbState;
311
384
  getThumbProps: (props: ThumbProps) => T["element"];
312
385
  getHiddenInputProps: (props: ThumbProps) => T["input"];
313
386
  getRangeProps: () => T["element"];
314
387
  getControlProps: () => T["element"];
315
388
  getMarkerGroupProps: () => T["element"];
389
+ /**
390
+ * Returns the state of a specific marker
391
+ */
392
+ getMarkerState: (props: MarkerProps) => MarkerState;
316
393
  getMarkerProps: (props: MarkerProps) => T["element"];
317
394
  getDraggingIndicatorProps: (props: DraggingIndicatorProps) => T["element"];
318
395
  }
319
396
 
320
- export type { DraggingIndicatorProps, ElementIds, FocusChangeDetails, MarkerProps, SliderApi, SliderMachine, SliderProps, SliderSchema, SliderService, ThumbAlignment, ThumbCollisionBehavior, ThumbProps, ValueChangeDetails, ValueTextDetails };
397
+ export type { DraggingIndicatorProps, ElementIds, FocusChangeDetails, MarkerProps, MarkerState, RootState, SliderApi, SliderMachine, SliderOrigin, SliderProps, SliderSchema, SliderService, ThumbAlignment, ThumbCollisionBehavior, ThumbProps, ThumbState, ValueChangeDetails, ValueTextDetails };
@@ -1,5 +1,5 @@
1
1
  import { Params } from '@zag-js/core';
2
- import { SliderSchema, ThumbCollisionBehavior } from './slider.types.mjs';
2
+ import { SliderSchema, SliderOrigin, ThumbCollisionBehavior } from './slider.types.mjs';
3
3
  import '@zag-js/types';
4
4
 
5
5
  type Ctx = Params<SliderSchema>;
@@ -21,5 +21,12 @@ declare function increment(params: Pick<Ctx, "context" | "prop">, index?: number
21
21
  declare function getClosestIndex(params: Pick<Ctx, "context" | "prop">, pointValue: number): number;
22
22
  declare function selectMovableThumb(params: Pick<Ctx, "context" | "prop">, index: number): number;
23
23
  declare function assignArray(current: number[], next: number[]): void;
24
+ /** Resolves the `origin` prop to a percent position (0-100) within `min`-`max`. */
25
+ declare function getOriginPercent(origin: SliderOrigin, min: number, max: number): number;
26
+ /** Track-fill insets (from the left/right edges) needed to fill between origin and value. */
27
+ declare function getFillRange(valuePercent: number, originPercent: number): {
28
+ start: number;
29
+ end: number;
30
+ };
24
31
 
25
- export { assignArray, constrainValue, decrement, getClosestIndex, getRangeAtIndex, increment, normalizeValues, resolveThumbCollision, selectMovableThumb };
32
+ export { assignArray, constrainValue, decrement, getClosestIndex, getFillRange, getOriginPercent, getRangeAtIndex, increment, normalizeValues, resolveThumbCollision, selectMovableThumb };
@@ -1,5 +1,5 @@
1
1
  import { Params } from '@zag-js/core';
2
- import { SliderSchema, ThumbCollisionBehavior } from './slider.types.js';
2
+ import { SliderSchema, SliderOrigin, ThumbCollisionBehavior } from './slider.types.js';
3
3
  import '@zag-js/types';
4
4
 
5
5
  type Ctx = Params<SliderSchema>;
@@ -21,5 +21,12 @@ declare function increment(params: Pick<Ctx, "context" | "prop">, index?: number
21
21
  declare function getClosestIndex(params: Pick<Ctx, "context" | "prop">, pointValue: number): number;
22
22
  declare function selectMovableThumb(params: Pick<Ctx, "context" | "prop">, index: number): number;
23
23
  declare function assignArray(current: number[], next: number[]): void;
24
+ /** Resolves the `origin` prop to a percent position (0-100) within `min`-`max`. */
25
+ declare function getOriginPercent(origin: SliderOrigin, min: number, max: number): number;
26
+ /** Track-fill insets (from the left/right edges) needed to fill between origin and value. */
27
+ declare function getFillRange(valuePercent: number, originPercent: number): {
28
+ start: number;
29
+ end: number;
30
+ };
24
31
 
25
- export { assignArray, constrainValue, decrement, getClosestIndex, getRangeAtIndex, increment, normalizeValues, resolveThumbCollision, selectMovableThumb };
32
+ export { assignArray, constrainValue, decrement, getClosestIndex, getFillRange, getOriginPercent, getRangeAtIndex, increment, normalizeValues, resolveThumbCollision, selectMovableThumb };
@@ -24,6 +24,8 @@ __export(slider_utils_exports, {
24
24
  constrainValue: () => constrainValue,
25
25
  decrement: () => decrement,
26
26
  getClosestIndex: () => getClosestIndex,
27
+ getFillRange: () => getFillRange,
28
+ getOriginPercent: () => getOriginPercent,
27
29
  getRangeAtIndex: () => getRangeAtIndex,
28
30
  increment: () => increment,
29
31
  normalizeValues: () => normalizeValues,
@@ -183,12 +185,35 @@ function assignArray(current, next) {
183
185
  current[i] = value;
184
186
  }
185
187
  }
188
+ function getOriginPercent(origin, min, max) {
189
+ if (typeof origin === "number") {
190
+ return (0, import_utils.clampValue)(100 * (0, import_utils.getValuePercent)(origin, min, max), 0, 100);
191
+ }
192
+ switch (origin) {
193
+ case "end":
194
+ return 100;
195
+ case "center":
196
+ return 50;
197
+ case "start":
198
+ default:
199
+ return 0;
200
+ }
201
+ }
202
+ function getFillRange(valuePercent, originPercent) {
203
+ const isBeforeOrigin = valuePercent < originPercent;
204
+ return {
205
+ start: isBeforeOrigin ? valuePercent : originPercent,
206
+ end: isBeforeOrigin ? 100 - originPercent : 100 - valuePercent
207
+ };
208
+ }
186
209
  // Annotate the CommonJS export names for ESM import in node:
187
210
  0 && (module.exports = {
188
211
  assignArray,
189
212
  constrainValue,
190
213
  decrement,
191
214
  getClosestIndex,
215
+ getFillRange,
216
+ getOriginPercent,
192
217
  getRangeAtIndex,
193
218
  increment,
194
219
  normalizeValues,
@@ -1,5 +1,12 @@
1
1
  // src/slider.utils.ts
2
- import { clampValue, getNextStepValue, getPreviousStepValue, getValueRanges, snapValueToStep } from "@zag-js/utils";
2
+ import {
3
+ clampValue,
4
+ getNextStepValue,
5
+ getPreviousStepValue,
6
+ getValuePercent,
7
+ getValueRanges,
8
+ snapValueToStep
9
+ } from "@zag-js/utils";
3
10
  function getThumbBounds(ctx) {
4
11
  const { index, values, min, max, gap } = ctx;
5
12
  const prevThumb = values[index - 1];
@@ -151,11 +158,34 @@ function assignArray(current, next) {
151
158
  current[i] = value;
152
159
  }
153
160
  }
161
+ function getOriginPercent(origin, min, max) {
162
+ if (typeof origin === "number") {
163
+ return clampValue(100 * getValuePercent(origin, min, max), 0, 100);
164
+ }
165
+ switch (origin) {
166
+ case "end":
167
+ return 100;
168
+ case "center":
169
+ return 50;
170
+ case "start":
171
+ default:
172
+ return 0;
173
+ }
174
+ }
175
+ function getFillRange(valuePercent, originPercent) {
176
+ const isBeforeOrigin = valuePercent < originPercent;
177
+ return {
178
+ start: isBeforeOrigin ? valuePercent : originPercent,
179
+ end: isBeforeOrigin ? 100 - originPercent : 100 - valuePercent
180
+ };
181
+ }
154
182
  export {
155
183
  assignArray,
156
184
  constrainValue,
157
185
  decrement,
158
186
  getClosestIndex,
187
+ getFillRange,
188
+ getOriginPercent,
159
189
  getRangeAtIndex,
160
190
  increment,
161
191
  normalizeValues,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zag-js/slider",
3
- "version": "2.0.0-next.0",
3
+ "version": "2.0.0-next.2",
4
4
  "description": "Core logic for the slider widget implemented as a state machine",
5
5
  "keywords": [
6
6
  "js",
@@ -15,7 +15,10 @@
15
15
  "author": "Segun Adebayo <sage@adebayosegun.com>",
16
16
  "homepage": "https://github.com/chakra-ui/zag#readme",
17
17
  "license": "MIT",
18
- "repository": "https://github.com/chakra-ui/zag/tree/main/packages/slider",
18
+ "repository": {
19
+ "type": "git",
20
+ "url": "https://github.com/chakra-ui/zag/tree/main/packages/slider"
21
+ },
19
22
  "sideEffects": false,
20
23
  "files": [
21
24
  "dist"
@@ -27,11 +30,11 @@
27
30
  "url": "https://github.com/chakra-ui/zag/issues"
28
31
  },
29
32
  "dependencies": {
30
- "@zag-js/anatomy": "2.0.0-next.0",
31
- "@zag-js/core": "2.0.0-next.0",
32
- "@zag-js/dom-query": "2.0.0-next.0",
33
- "@zag-js/utils": "2.0.0-next.0",
34
- "@zag-js/types": "2.0.0-next.0"
33
+ "@zag-js/anatomy": "2.0.0-next.2",
34
+ "@zag-js/core": "2.0.0-next.2",
35
+ "@zag-js/dom-query": "2.0.0-next.2",
36
+ "@zag-js/utils": "2.0.0-next.2",
37
+ "@zag-js/types": "2.0.0-next.2"
35
38
  },
36
39
  "devDependencies": {
37
40
  "clean-package": "2.2.0"
@@ -65,7 +68,7 @@
65
68
  },
66
69
  "scripts": {
67
70
  "build": "tsup",
68
- "lint": "eslint src",
71
+ "lint": "oxlint src",
69
72
  "typecheck": "tsc --noEmit"
70
73
  }
71
74
  }