@zag-js/number-input 0.20.0 → 0.22.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.
package/dist/index.js CHANGED
@@ -40,9 +40,9 @@ var anatomy = (0, import_anatomy.createAnatomy)("numberInput").parts(
40
40
  var parts = anatomy.build();
41
41
 
42
42
  // src/number-input.connect.ts
43
- var import_dom_event2 = require("@zag-js/dom-event");
43
+ var import_dom_event = require("@zag-js/dom-event");
44
44
  var import_dom_query2 = require("@zag-js/dom-query");
45
- var import_number_utils3 = require("@zag-js/number-utils");
45
+ var import_number_utils2 = require("@zag-js/number-utils");
46
46
 
47
47
  // src/number-input.dom.ts
48
48
  var import_dom_query = require("@zag-js/dom-query");
@@ -142,54 +142,15 @@ var dom = (0, import_dom_query.createScope)({
142
142
  }
143
143
  });
144
144
 
145
- // src/number-input.utils.ts
146
- var import_dom_event = require("@zag-js/dom-event");
147
- var import_number_utils2 = require("@zag-js/number-utils");
148
- var utils = {
149
- isValidNumericEvent: (ctx, event) => {
150
- if (event.key == null)
151
- return true;
152
- const isModifier = (0, import_dom_event.isModifiedEvent)(event);
153
- const isSingleKey = event.key.length === 1;
154
- if (isModifier || !isSingleKey)
155
- return true;
156
- return ctx.validateCharacter?.(event.key) ?? utils.isFloatingPoint(event.key);
157
- },
158
- isFloatingPoint: (v) => /^[0-9+\-.]$/.test(v),
159
- sanitize: (ctx, value) => {
160
- return value.split("").filter(ctx.validateCharacter ?? utils.isFloatingPoint).join("");
161
- },
162
- increment: (ctx, step) => {
163
- const value = (0, import_number_utils2.increment)(ctx.value, step ?? ctx.step);
164
- return (0, import_number_utils2.formatDecimal)((0, import_number_utils2.clamp)(value, ctx), ctx);
165
- },
166
- decrement: (ctx, step) => {
167
- const value = (0, import_number_utils2.decrement)(ctx.value, step ?? ctx.step);
168
- return (0, import_number_utils2.formatDecimal)((0, import_number_utils2.clamp)(value, ctx), ctx);
169
- },
170
- clamp: (ctx) => {
171
- return (0, import_number_utils2.formatDecimal)((0, import_number_utils2.clamp)(ctx.value, ctx), ctx);
172
- },
173
- parse: (ctx, value) => {
174
- return ctx.parse?.(value) ?? value;
175
- },
176
- format: (ctx, value) => {
177
- const _val = value.toString();
178
- return ctx.format?.(_val) ?? _val;
179
- },
180
- round: (ctx) => {
181
- return (0, import_number_utils2.formatDecimal)(ctx.value, ctx);
182
- }
183
- };
184
-
185
145
  // src/number-input.connect.ts
186
146
  function connect(state, send, normalize) {
187
147
  const isFocused = state.hasTag("focus");
188
148
  const isInvalid = state.context.isOutOfRange || !!state.context.invalid;
189
- const isDisabled = !!state.context.disabled;
190
149
  const isValueEmpty = state.context.isValueEmpty;
191
- const isIncrementDisabled = isDisabled || !state.context.canIncrement;
192
- const isDecrementDisabled = isDisabled || !state.context.canDecrement;
150
+ const isDisabled = state.context.isDisabled;
151
+ const isReadOnly = state.context.readOnly;
152
+ const isIncrementDisabled = isDisabled || !state.context.canIncrement || isReadOnly;
153
+ const isDecrementDisabled = isDisabled || !state.context.canDecrement || isReadOnly;
193
154
  const translations = state.context.translations;
194
155
  return {
195
156
  isFocused,
@@ -198,38 +159,37 @@ function connect(state, send, normalize) {
198
159
  value: state.context.formattedValue,
199
160
  valueAsNumber: state.context.valueAsNumber,
200
161
  setValue(value) {
201
- send({ type: "SET_VALUE", value: value.toString() });
162
+ send({ type: "VALUE.SET", value: value.toString() });
202
163
  },
203
164
  clearValue() {
204
- send("CLEAR_VALUE");
165
+ send("VALUE.CLEAR");
205
166
  },
206
167
  increment() {
207
- send("INCREMENT");
168
+ send("VALUE.INCREMENT");
208
169
  },
209
170
  decrement() {
210
- send("DECREMENT");
171
+ send("VALUE.DECREMENT");
211
172
  },
212
173
  setToMax() {
213
- send({ type: "SET_VALUE", value: state.context.max });
174
+ send({ type: "VALUE.SET", value: state.context.max });
214
175
  },
215
176
  setToMin() {
216
- send({ type: "SET_VALUE", value: state.context.min });
177
+ send({ type: "VALUE.SET", value: state.context.min });
217
178
  },
218
179
  focus() {
219
180
  dom.getInputEl(state.context)?.focus();
220
181
  },
221
- blur() {
222
- dom.getInputEl(state.context)?.blur();
223
- },
224
182
  rootProps: normalize.element({
225
183
  id: dom.getRootId(state.context),
226
184
  ...parts.root.attrs,
185
+ dir: state.context.dir,
227
186
  "data-disabled": (0, import_dom_query2.dataAttr)(isDisabled),
228
187
  "data-focus": (0, import_dom_query2.dataAttr)(isFocused),
229
188
  "data-invalid": (0, import_dom_query2.dataAttr)(isInvalid)
230
189
  }),
231
190
  labelProps: normalize.label({
232
191
  ...parts.label.attrs,
192
+ dir: state.context.dir,
233
193
  "data-disabled": (0, import_dom_query2.dataAttr)(isDisabled),
234
194
  "data-focus": (0, import_dom_query2.dataAttr)(isFocused),
235
195
  "data-invalid": (0, import_dom_query2.dataAttr)(isInvalid),
@@ -238,6 +198,7 @@ function connect(state, send, normalize) {
238
198
  }),
239
199
  controlProps: normalize.element({
240
200
  ...parts.control.attrs,
201
+ dir: state.context.dir,
241
202
  role: "group",
242
203
  "aria-disabled": isDisabled,
243
204
  "data-focus": (0, import_dom_query2.dataAttr)(isFocused),
@@ -247,6 +208,7 @@ function connect(state, send, normalize) {
247
208
  }),
248
209
  inputProps: normalize.input({
249
210
  ...parts.input.attrs,
211
+ dir: state.context.dir,
250
212
  name: state.context.name,
251
213
  form: state.context.form,
252
214
  id: dom.getInputId(state.context),
@@ -266,48 +228,68 @@ function connect(state, send, normalize) {
266
228
  "aria-roledescription": "numberfield",
267
229
  "aria-valuemin": state.context.min,
268
230
  "aria-valuemax": state.context.max,
269
- "aria-valuenow": isNaN(state.context.valueAsNumber) ? void 0 : state.context.valueAsNumber,
231
+ "aria-valuenow": Number.isNaN(state.context.valueAsNumber) ? void 0 : state.context.valueAsNumber,
270
232
  "aria-valuetext": state.context.valueText,
233
+ onCompositionStart() {
234
+ send("INPUT.COMPOSITION_START");
235
+ },
236
+ onCompositionEnd() {
237
+ send("INPUT.COMPOSITION_END");
238
+ },
271
239
  onFocus() {
272
- send("FOCUS");
240
+ send("INPUT.FOCUS");
273
241
  },
274
242
  onBlur() {
275
- send("BLUR");
243
+ send({ type: "INPUT.COMMIT", src: "blur" });
276
244
  },
277
245
  onChange(event) {
278
- send({ type: "CHANGE", target: event.currentTarget, hint: "set" });
246
+ send({ type: "INPUT.CHANGE", target: event.currentTarget, hint: "set" });
247
+ },
248
+ onBeforeInput(event) {
249
+ try {
250
+ const { selectionStart, selectionEnd, value } = event.currentTarget;
251
+ const nextValue = value.slice(0, selectionStart) + event.data + value.slice(selectionEnd);
252
+ const isValid = state.context.parser.isValidPartialNumber(nextValue);
253
+ if (!isValid) {
254
+ event.preventDefault();
255
+ }
256
+ } catch {
257
+ }
279
258
  },
280
259
  onKeyDown(event) {
281
- const evt = (0, import_dom_event2.getNativeEvent)(event);
282
- if (evt.isComposing)
260
+ if (state.context.readOnly)
283
261
  return;
284
- if (!utils.isValidNumericEvent(state.context, event)) {
285
- event.preventDefault();
286
- }
287
- const step = (0, import_dom_event2.getEventStep)(event) * state.context.step;
262
+ const step = (0, import_dom_event.getEventStep)(event) * state.context.step;
288
263
  const keyMap = {
289
264
  ArrowUp() {
290
- send({ type: "ARROW_UP", step });
265
+ send({ type: "INPUT.ARROW_UP", step });
266
+ event.preventDefault();
291
267
  },
292
268
  ArrowDown() {
293
- send({ type: "ARROW_DOWN", step });
269
+ send({ type: "INPUT.ARROW_DOWN", step });
270
+ event.preventDefault();
294
271
  },
295
272
  Home() {
296
- send("HOME");
273
+ send("INPUT.HOME");
274
+ event.preventDefault();
297
275
  },
298
276
  End() {
299
- send("END");
277
+ send("INPUT.END");
278
+ event.preventDefault();
279
+ },
280
+ Enter() {
281
+ if (state.context.composing)
282
+ return;
283
+ send({ type: "INPUT.COMMIT", src: "enter" });
300
284
  }
301
285
  };
302
286
  const exec = keyMap[event.key];
303
- if (exec) {
304
- exec(event);
305
- event.preventDefault();
306
- }
287
+ exec?.(event);
307
288
  }
308
289
  }),
309
290
  decrementTriggerProps: normalize.button({
310
291
  ...parts.decrementTrigger.attrs,
292
+ dir: state.context.dir,
311
293
  id: dom.getDecrementTriggerId(state.context),
312
294
  disabled: isDecrementDisabled,
313
295
  "data-disabled": (0, import_dom_query2.dataAttr)(isDecrementDisabled),
@@ -316,22 +298,28 @@ function connect(state, send, normalize) {
316
298
  tabIndex: -1,
317
299
  "aria-controls": dom.getInputId(state.context),
318
300
  onPointerDown(event) {
319
- if (isDecrementDisabled)
301
+ if (isDecrementDisabled || !(0, import_dom_event.isLeftClick)(event))
320
302
  return;
321
- send((0, import_dom_event2.isLeftClick)(event) ? { type: "PRESS_DOWN", hint: "decrement" } : { type: "FOCUS" });
322
- event.preventDefault();
303
+ if (event.pointerType === "mouse") {
304
+ send({ type: "TRIGGER.PRESS_DOWN", hint: "decrement" });
305
+ return event.preventDefault();
306
+ }
307
+ if ((0, import_dom_query2.isHTMLElement)(event.target)) {
308
+ event.target?.focus();
309
+ }
323
310
  },
324
311
  onPointerUp() {
325
- send({ type: "PRESS_UP", hint: "decrement" });
312
+ send({ type: "TRIGGER.PRESS_UP", hint: "decrement" });
326
313
  },
327
314
  onPointerLeave() {
328
315
  if (isDecrementDisabled)
329
316
  return;
330
- send({ type: "PRESS_UP", hint: "decrement" });
317
+ send({ type: "TRIGGER.PRESS_UP", hint: "decrement" });
331
318
  }
332
319
  }),
333
320
  incrementTriggerProps: normalize.button({
334
321
  ...parts.incrementTrigger.attrs,
322
+ dir: state.context.dir,
335
323
  id: dom.getIncrementTriggerId(state.context),
336
324
  disabled: isIncrementDisabled,
337
325
  "data-disabled": (0, import_dom_query2.dataAttr)(isIncrementDisabled),
@@ -340,16 +328,21 @@ function connect(state, send, normalize) {
340
328
  tabIndex: -1,
341
329
  "aria-controls": dom.getInputId(state.context),
342
330
  onPointerDown(event) {
343
- if (isIncrementDisabled)
331
+ if (isIncrementDisabled || !(0, import_dom_event.isLeftClick)(event))
344
332
  return;
345
- send((0, import_dom_event2.isLeftClick)(event) ? { type: "PRESS_DOWN", hint: "increment" } : { type: "FOCUS" });
346
- event.preventDefault();
333
+ if (event.pointerType === "mouse") {
334
+ send({ type: "TRIGGER.PRESS_DOWN", hint: "increment" });
335
+ return event.preventDefault();
336
+ }
337
+ if ((0, import_dom_query2.isHTMLElement)(event.target)) {
338
+ event.target?.focus();
339
+ }
347
340
  },
348
341
  onPointerUp() {
349
- send({ type: "PRESS_UP", hint: "increment" });
342
+ send({ type: "TRIGGER.PRESS_UP", hint: "increment" });
350
343
  },
351
344
  onPointerLeave() {
352
- send({ type: "PRESS_UP", hint: "increment" });
345
+ send({ type: "TRIGGER.PRESS_UP", hint: "increment" });
353
346
  }
354
347
  }),
355
348
  scrubberProps: normalize.element({
@@ -360,11 +353,11 @@ function connect(state, send, normalize) {
360
353
  onMouseDown(event) {
361
354
  if (isDisabled)
362
355
  return;
363
- const evt = (0, import_dom_event2.getNativeEvent)(event);
364
- const point = (0, import_dom_event2.getEventPoint)(evt);
365
- point.x = point.x - (0, import_number_utils3.roundToDevicePixel)(7.5);
366
- point.y = point.y - (0, import_number_utils3.roundToDevicePixel)(7.5);
367
- send({ type: "PRESS_DOWN_SCRUBBER", point });
356
+ const evt = (0, import_dom_event.getNativeEvent)(event);
357
+ const point = (0, import_dom_event.getEventPoint)(evt);
358
+ point.x = point.x - (0, import_number_utils2.roundToDevicePixel)(7.5);
359
+ point.y = point.y - (0, import_number_utils2.roundToDevicePixel)(7.5);
360
+ send({ type: "SCRUBBER.PRESS_DOWN", point });
368
361
  event.preventDefault();
369
362
  },
370
363
  style: {
@@ -375,12 +368,57 @@ function connect(state, send, normalize) {
375
368
  }
376
369
 
377
370
  // src/number-input.machine.ts
371
+ var import_number = require("@internationalized/number");
378
372
  var import_core = require("@zag-js/core");
379
- var import_dom_event3 = require("@zag-js/dom-event");
373
+ var import_dom_event2 = require("@zag-js/dom-event");
380
374
  var import_dom_query3 = require("@zag-js/dom-query");
375
+ var import_form_utils = require("@zag-js/form-utils");
381
376
  var import_mutation_observer = require("@zag-js/mutation-observer");
382
- var import_number_utils4 = require("@zag-js/number-utils");
377
+ var import_number_utils3 = require("@zag-js/number-utils");
383
378
  var import_utils = require("@zag-js/utils");
379
+
380
+ // src/cursor.ts
381
+ function recordCursor(inputEl) {
382
+ if (inputEl.ownerDocument.activeElement !== inputEl)
383
+ return;
384
+ try {
385
+ const { selectionStart: start, selectionEnd: end, value } = inputEl;
386
+ const beforeTxt = value.substring(0, start);
387
+ const afterTxt = value.substring(end);
388
+ return {
389
+ start,
390
+ end,
391
+ value,
392
+ beforeTxt,
393
+ afterTxt
394
+ };
395
+ } catch {
396
+ }
397
+ }
398
+ function restoreCursor(inputEl, selection) {
399
+ if (inputEl.ownerDocument.activeElement !== inputEl || !selection)
400
+ return;
401
+ try {
402
+ const { value } = inputEl;
403
+ const { beforeTxt = "", afterTxt = "", start } = selection;
404
+ let startPos = value.length;
405
+ if (value.endsWith(afterTxt)) {
406
+ startPos = value.length - afterTxt.length;
407
+ } else if (value.startsWith(beforeTxt)) {
408
+ startPos = beforeTxt.length;
409
+ } else if (start != null) {
410
+ const beforeLastChar = beforeTxt[start - 1];
411
+ const newIndex = value.indexOf(beforeLastChar, start - 1);
412
+ if (newIndex !== -1) {
413
+ startPos = newIndex + 1;
414
+ }
415
+ }
416
+ inputEl.setSelectionRange(startPos, startPos);
417
+ } catch {
418
+ }
419
+ }
420
+
421
+ // src/number-input.machine.ts
384
422
  var { not, and } = import_core.guards;
385
423
  function machine(userContext) {
386
424
  const ctx = (0, import_utils.compact)(userContext);
@@ -390,20 +428,25 @@ function machine(userContext) {
390
428
  initial: "idle",
391
429
  context: {
392
430
  dir: "ltr",
431
+ locale: "en-US",
393
432
  focusInputOnChange: true,
394
433
  clampValueOnBlur: true,
395
434
  allowOverflow: false,
396
435
  inputMode: "decimal",
397
436
  pattern: "[0-9]*(.[0-9]+)?",
398
- hint: null,
399
437
  value: "",
400
438
  step: 1,
401
439
  min: Number.MIN_SAFE_INTEGER,
402
440
  max: Number.MAX_SAFE_INTEGER,
403
- scrubberCursorPoint: null,
404
441
  invalid: false,
405
442
  spinOnPress: true,
406
443
  ...ctx,
444
+ hint: null,
445
+ scrubberCursorPoint: null,
446
+ composing: false,
447
+ fieldsetDisabled: false,
448
+ formatter: createFormatter(ctx.locale || "en-US", ctx.formatOptions),
449
+ parser: createParser(ctx.locale || "en-US", ctx.formatOptions),
407
450
  translations: {
408
451
  incrementLabel: "increment value",
409
452
  decrementLabel: "decrease value",
@@ -412,48 +455,56 @@ function machine(userContext) {
412
455
  },
413
456
  computed: {
414
457
  isRtl: (ctx2) => ctx2.dir === "rtl",
415
- valueAsNumber: (ctx2) => (0, import_number_utils4.valueOf)(ctx2.value),
416
- isAtMin: (ctx2) => (0, import_number_utils4.isAtMin)(ctx2.value, ctx2),
417
- isAtMax: (ctx2) => (0, import_number_utils4.isAtMax)(ctx2.value, ctx2),
418
- isOutOfRange: (ctx2) => !(0, import_number_utils4.isWithinRange)(ctx2.value, ctx2),
458
+ valueAsNumber: (ctx2) => ctx2.parser.parse(String(ctx2.value)) ?? 0,
459
+ isAtMin: (ctx2) => (0, import_number_utils3.isAtMin)(ctx2.value, ctx2),
460
+ isAtMax: (ctx2) => (0, import_number_utils3.isAtMax)(ctx2.value, ctx2),
461
+ isOutOfRange: (ctx2) => !(0, import_number_utils3.isWithinRange)(ctx2.value, ctx2),
419
462
  isValueEmpty: (ctx2) => ctx2.value === "",
463
+ isDisabled: (ctx2) => !!ctx2.disabled || ctx2.fieldsetDisabled,
420
464
  canIncrement: (ctx2) => ctx2.allowOverflow || !ctx2.isAtMax,
421
465
  canDecrement: (ctx2) => ctx2.allowOverflow || !ctx2.isAtMin,
422
466
  valueText: (ctx2) => ctx2.translations.valueText?.(ctx2.value),
423
- formattedValue: (ctx2) => ctx2.format?.(ctx2.value).toString() ?? ctx2.value
467
+ formattedValue: (ctx2) => {
468
+ if (Number.isNaN(ctx2.valueAsNumber))
469
+ return ctx2.value;
470
+ return ctx2.formatter.format(ctx2.valueAsNumber);
471
+ }
424
472
  },
425
473
  watch: {
474
+ formatOptions: ["setFormatterAndParser", "syncInputElement"],
475
+ locale: ["setFormatterAndParser", "syncInputElement"],
426
476
  value: ["syncInputElement"],
427
477
  isOutOfRange: ["invokeOnInvalid"],
428
478
  scrubberCursorPoint: ["setVirtualCursorPosition"]
429
479
  },
430
480
  entry: ["syncInputValue"],
481
+ activities: ["trackFormControl"],
431
482
  on: {
432
- SET_VALUE: {
483
+ "VALUE.SET": {
433
484
  actions: ["setValue", "clampValue", "setHintToSet"]
434
485
  },
435
- CLEAR_VALUE: {
486
+ "VALUE.CLEAR": {
436
487
  actions: ["clearValue"]
437
488
  },
438
- INCREMENT: {
489
+ "VALUE.INCREMENT": {
439
490
  actions: ["increment"]
440
491
  },
441
- DECREMENT: {
492
+ "VALUE.DECREMENT": {
442
493
  actions: ["decrement"]
443
494
  }
444
495
  },
445
496
  states: {
446
497
  idle: {
447
498
  on: {
448
- PRESS_DOWN: {
499
+ "TRIGGER.PRESS_DOWN": {
449
500
  target: "before:spin",
450
501
  actions: ["focusInput", "invokeOnFocus", "setHint"]
451
502
  },
452
- PRESS_DOWN_SCRUBBER: {
503
+ "SCRUBBER.PRESS_DOWN": {
453
504
  target: "scrubbing",
454
505
  actions: ["focusInput", "invokeOnFocus", "setHint", "setCursorPoint"]
455
506
  },
456
- FOCUS: {
507
+ "INPUT.FOCUS": {
457
508
  target: "focused",
458
509
  actions: ["focusInput", "invokeOnFocus"]
459
510
  }
@@ -464,45 +515,46 @@ function machine(userContext) {
464
515
  entry: "focusInput",
465
516
  activities: "attachWheelListener",
466
517
  on: {
467
- PRESS_DOWN: {
518
+ "TRIGGER.PRESS_DOWN": {
468
519
  target: "before:spin",
469
520
  actions: ["focusInput", "setHint"]
470
521
  },
471
- PRESS_DOWN_SCRUBBER: {
522
+ "SCRUBBER.PRESS_DOWN": {
472
523
  target: "scrubbing",
473
524
  actions: ["focusInput", "setHint", "setCursorPoint"]
474
525
  },
475
- ARROW_UP: {
526
+ "INPUT.ARROW_UP": {
476
527
  actions: "increment"
477
528
  },
478
- ARROW_DOWN: {
529
+ "INPUT.ARROW_DOWN": {
479
530
  actions: "decrement"
480
531
  },
481
- HOME: {
482
- actions: "setToMin"
532
+ "INPUT.HOME": {
533
+ actions: "decrementToMin"
483
534
  },
484
- END: {
485
- actions: "setToMax"
535
+ "INPUT.END": {
536
+ actions: "incrementToMax"
486
537
  },
487
- CHANGE: {
538
+ "INPUT.CHANGE": {
488
539
  actions: ["setValue", "setHint"]
489
540
  },
490
- BLUR: [
541
+ "INPUT.COMMIT": [
491
542
  {
492
- guard: "isInvalidExponential",
543
+ guard: and("clampValueOnBlur", not("isInRange")),
493
544
  target: "idle",
494
- actions: ["clearValue", "clearHint", "invokeOnBlur"]
545
+ actions: ["clampValue", "syncInputElement", "clearHint", "invokeOnBlur"]
495
546
  },
496
547
  {
497
- guard: and("clampOnBlur", not("isInRange"), not("isEmptyValue")),
498
548
  target: "idle",
499
- actions: ["clampValue", "clearHint", "invokeOnBlur"]
500
- },
501
- {
502
- target: "idle",
503
- actions: ["roundValue", "invokeOnBlur"]
549
+ actions: ["syncInputElement", "invokeOnBlur"]
504
550
  }
505
- ]
551
+ ],
552
+ "INPUT.COMPOSITION_START": {
553
+ actions: "setComposing"
554
+ },
555
+ "INPUT.COMPOSITION_END": {
556
+ actions: "clearComposing"
557
+ }
506
558
  }
507
559
  },
508
560
  "before:spin": {
@@ -519,7 +571,7 @@ function machine(userContext) {
519
571
  }
520
572
  },
521
573
  on: {
522
- PRESS_UP: {
574
+ "TRIGGER.PRESS_UP": {
523
575
  target: "focused",
524
576
  actions: "clearHint"
525
577
  }
@@ -541,7 +593,7 @@ function machine(userContext) {
541
593
  }
542
594
  ],
543
595
  on: {
544
- PRESS_UP: {
596
+ "TRIGGER.PRESS_UP": {
545
597
  target: "focused",
546
598
  actions: "clearHint"
547
599
  }
@@ -552,8 +604,8 @@ function machine(userContext) {
552
604
  exit: "clearCursorPoint",
553
605
  activities: ["activatePointerLock", "trackMousemove", "setupVirtualCursor", "preventTextSelection"],
554
606
  on: {
555
- POINTER_UP_SCRUBBER: "focused",
556
- POINTER_MOVE_SCRUBBER: [
607
+ "SCRUBBER.POINTER_UP": "focused",
608
+ "SCRUBBER.POINTER_MOVE": [
557
609
  {
558
610
  guard: "isIncrementHint",
559
611
  actions: ["increment", "setCursorPoint"]
@@ -573,17 +625,26 @@ function machine(userContext) {
573
625
  CHANGE_DELAY: 300
574
626
  },
575
627
  guards: {
576
- clampOnBlur: (ctx2) => !!ctx2.clampValueOnBlur,
628
+ clampValueOnBlur: (ctx2) => ctx2.clampValueOnBlur,
577
629
  isAtMin: (ctx2) => ctx2.isAtMin,
578
630
  spinOnPress: (ctx2) => !!ctx2.spinOnPress,
579
631
  isAtMax: (ctx2) => ctx2.isAtMax,
580
632
  isInRange: (ctx2) => !ctx2.isOutOfRange,
581
633
  isDecrementHint: (ctx2, evt) => (evt.hint ?? ctx2.hint) === "decrement",
582
- isEmptyValue: (ctx2) => ctx2.isValueEmpty,
583
- isIncrementHint: (ctx2, evt) => (evt.hint ?? ctx2.hint) === "increment",
584
- isInvalidExponential: (ctx2) => ctx2.value.toString().startsWith("e")
634
+ isIncrementHint: (ctx2, evt) => (evt.hint ?? ctx2.hint) === "increment"
585
635
  },
586
636
  activities: {
637
+ trackFormControl(ctx2, _evt, { initialContext }) {
638
+ const inputEl = dom.getInputEl(ctx2);
639
+ return (0, import_form_utils.trackFormControl)(inputEl, {
640
+ onFieldsetDisabledChange(disabled) {
641
+ ctx2.fieldsetDisabled = disabled;
642
+ },
643
+ onFormReset() {
644
+ set.value(ctx2, initialContext.value);
645
+ }
646
+ });
647
+ },
587
648
  setupVirtualCursor(ctx2) {
588
649
  return dom.setupVirtualCursor(ctx2);
589
650
  },
@@ -593,31 +654,28 @@ function machine(userContext) {
593
654
  trackButtonDisabled(ctx2, _evt, { send }) {
594
655
  const btn = dom.getPressedTriggerEl(ctx2, ctx2.hint);
595
656
  return (0, import_mutation_observer.observeAttributes)(btn, ["disabled"], () => {
596
- send("PRESS_UP");
657
+ send({ type: "TRIGGER.PRESS_UP", src: "attr" });
597
658
  });
598
659
  },
599
660
  attachWheelListener(ctx2, _evt, { send }) {
600
- const input = dom.getInputEl(ctx2);
601
- if (!input)
661
+ const inputEl = dom.getInputEl(ctx2);
662
+ if (!inputEl || !dom.isActiveElement(ctx2, inputEl) || !ctx2.allowMouseWheel)
602
663
  return;
603
664
  function onWheel(event) {
604
- const isInputFocused = dom.getDoc(ctx2).activeElement === input;
605
- if (!ctx2.allowMouseWheel || !isInputFocused)
606
- return;
607
665
  event.preventDefault();
608
666
  const dir = Math.sign(event.deltaY) * -1;
609
667
  if (dir === 1) {
610
- send("INCREMENT");
668
+ send("VALUE.INCREMENT");
611
669
  } else if (dir === -1) {
612
- send("DECREMENT");
670
+ send("VALUE.DECREMENT");
613
671
  }
614
672
  }
615
- return (0, import_dom_event3.addDomEvent)(input, "wheel", onWheel, { passive: false });
673
+ return (0, import_dom_event2.addDomEvent)(inputEl, "wheel", onWheel, { passive: false });
616
674
  },
617
675
  activatePointerLock(ctx2) {
618
676
  if ((0, import_dom_query3.isSafari)())
619
677
  return;
620
- return (0, import_dom_event3.requestPointerLock)(dom.getDoc(ctx2));
678
+ return (0, import_dom_event2.requestPointerLock)(dom.getDoc(ctx2));
621
679
  },
622
680
  trackMousemove(ctx2, _evt, { send }) {
623
681
  const doc = dom.getDoc(ctx2);
@@ -628,17 +686,17 @@ function machine(userContext) {
628
686
  if (!value.hint)
629
687
  return;
630
688
  send({
631
- type: "POINTER_MOVE_SCRUBBER",
689
+ type: "SCRUBBER.POINTER_MOVE",
632
690
  hint: value.hint,
633
691
  point: value.point
634
692
  });
635
693
  }
636
694
  function onMouseup() {
637
- send("POINTER_UP_SCRUBBER");
695
+ send("SCRUBBER.POINTER_UP");
638
696
  }
639
697
  return (0, import_utils.callAll)(
640
- (0, import_dom_event3.addDomEvent)(doc, "mousemove", onMousemove, false),
641
- (0, import_dom_event3.addDomEvent)(doc, "mouseup", onMouseup, false)
698
+ (0, import_dom_event2.addDomEvent)(doc, "mousemove", onMousemove, false),
699
+ (0, import_dom_event2.addDomEvent)(doc, "mouseup", onMouseup, false)
642
700
  );
643
701
  }
644
702
  },
@@ -647,37 +705,34 @@ function machine(userContext) {
647
705
  if (!ctx2.focusInputOnChange)
648
706
  return;
649
707
  const inputEl = dom.getInputEl(ctx2);
650
- (0, import_dom_query3.raf)(() => {
651
- inputEl?.focus();
652
- });
708
+ if (dom.isActiveElement(ctx2, inputEl))
709
+ return;
710
+ (0, import_dom_query3.raf)(() => inputEl?.focus({ preventScroll: true }));
653
711
  },
654
712
  increment(ctx2, evt) {
655
- set.value(ctx2, utils.increment(ctx2, evt.step));
713
+ const nextValue = (0, import_number_utils3.increment)(ctx2.value, evt.step ?? ctx2.step);
714
+ set.value(ctx2, String((0, import_number_utils3.clamp)(nextValue, ctx2)));
656
715
  },
657
716
  decrement(ctx2, evt) {
658
- set.value(ctx2, utils.decrement(ctx2, evt.step));
717
+ const nextValue = (0, import_number_utils3.decrement)(ctx2.value, evt.step ?? ctx2.step);
718
+ set.value(ctx2, String((0, import_number_utils3.clamp)(nextValue, ctx2)));
659
719
  },
660
720
  clampValue(ctx2) {
661
- set.value(ctx2, utils.clamp(ctx2));
662
- },
663
- roundValue(ctx2) {
664
- if (ctx2.value === "")
665
- return;
666
- set.value(ctx2, utils.round(ctx2));
721
+ const nextValue = (0, import_number_utils3.clamp)(ctx2.value, ctx2);
722
+ set.value(ctx2, String(nextValue));
667
723
  },
668
724
  setValue(ctx2, evt) {
669
- let value = evt.target?.value ?? evt.value;
670
- value = utils.sanitize(ctx2, utils.parse(ctx2, value.toString()));
725
+ const value = evt.target?.value ?? evt.value;
671
726
  set.value(ctx2, value);
672
727
  },
673
728
  clearValue(ctx2) {
674
729
  set.value(ctx2, "");
675
730
  },
676
- setToMax(ctx2) {
677
- set.value(ctx2, ctx2.max.toString());
731
+ incrementToMax(ctx2) {
732
+ set.value(ctx2, String(ctx2.max));
678
733
  },
679
- setToMin(ctx2) {
680
- set.value(ctx2, ctx2.min.toString());
734
+ decrementToMin(ctx2) {
735
+ set.value(ctx2, String(ctx2.min));
681
736
  },
682
737
  setHint(ctx2, evt) {
683
738
  ctx2.hint = evt.hint;
@@ -688,15 +743,9 @@ function machine(userContext) {
688
743
  setHintToSet(ctx2) {
689
744
  ctx2.hint = "set";
690
745
  },
691
- invokeOnFocus(ctx2, evt) {
692
- const srcElement = (0, import_utils.match)(evt.type, {
693
- PRESS_DOWN: dom.getPressedTriggerEl(ctx2, evt.hint),
694
- FOCUS: dom.getInputEl(ctx2),
695
- PRESS_DOWN_SCRUBBER: dom.getScrubberEl(ctx2)
696
- });
746
+ invokeOnFocus(ctx2) {
697
747
  ctx2.onFocusChange?.({
698
748
  focused: true,
699
- srcElement,
700
749
  value: ctx2.formattedValue,
701
750
  valueAsNumber: ctx2.valueAsNumber
702
751
  });
@@ -718,16 +767,20 @@ function machine(userContext) {
718
767
  valueAsNumber: ctx2.valueAsNumber
719
768
  });
720
769
  },
721
- syncInputElement(ctx2) {
770
+ syncInputElement(ctx2, evt) {
722
771
  const inputEl = dom.getInputEl(ctx2);
723
- dom.setValue(inputEl, ctx2.formattedValue);
772
+ const inputValue = evt.type.endsWith("CHANGE") ? ctx2.value : ctx2.formattedValue;
773
+ const sel = recordCursor(inputEl);
774
+ dom.setValue(inputEl, inputValue);
775
+ (0, import_dom_query3.raf)(() => {
776
+ restoreCursor(inputEl, sel);
777
+ });
724
778
  },
725
779
  syncInputValue(ctx2) {
726
780
  const inputEl = dom.getInputEl(ctx2);
727
781
  if (!inputEl || inputEl.value == ctx2.value)
728
782
  return;
729
- const value = utils.parse(ctx2, inputEl.value);
730
- set.value(ctx2, utils.sanitize(ctx2, value));
783
+ set.value(ctx2, ctx2.formattedValue);
731
784
  },
732
785
  setCursorPoint(ctx2, evt) {
733
786
  ctx2.scrubberCursorPoint = evt.point;
@@ -736,19 +789,50 @@ function machine(userContext) {
736
789
  ctx2.scrubberCursorPoint = null;
737
790
  },
738
791
  setVirtualCursorPosition(ctx2) {
739
- const cursor = dom.getCursorEl(ctx2);
740
- if (!cursor || !ctx2.scrubberCursorPoint)
792
+ const cursorEl = dom.getCursorEl(ctx2);
793
+ if (!cursorEl || !ctx2.scrubberCursorPoint)
741
794
  return;
742
795
  const { x, y } = ctx2.scrubberCursorPoint;
743
- cursor.style.transform = `translate3d(${x}px, ${y}px, 0px)`;
796
+ cursorEl.style.transform = `translate3d(${x}px, ${y}px, 0px)`;
797
+ },
798
+ setComposing(ctx2) {
799
+ ctx2.composing = true;
800
+ },
801
+ clearComposing(ctx2) {
802
+ ctx2.composing = false;
803
+ },
804
+ setFormatterAndParser(ctx2) {
805
+ if (!ctx2.locale)
806
+ return;
807
+ ctx2.formatter = createFormatter(ctx2.locale, ctx2.formatOptions);
808
+ ctx2.parser = createParser(ctx2.locale, ctx2.formatOptions);
744
809
  }
810
+ },
811
+ compareFns: {
812
+ formatOptions: (a, b) => (0, import_utils.isEqual)(a, b)
745
813
  }
746
814
  }
747
815
  );
748
816
  }
817
+ var defaultFormatOptions = {
818
+ style: "decimal",
819
+ minimumFractionDigits: 0,
820
+ maximumFractionDigits: 20
821
+ };
822
+ var createFormatter = (locale, options = {}) => {
823
+ const formatOptions = Object.assign({}, defaultFormatOptions, options);
824
+ return (0, import_core.ref)(new Intl.NumberFormat(locale, formatOptions));
825
+ };
826
+ var createParser = (locale, options = {}) => {
827
+ const formatOptions = Object.assign({}, defaultFormatOptions, options);
828
+ return (0, import_core.ref)(new import_number.NumberParser(locale, formatOptions));
829
+ };
749
830
  var invoke = {
750
831
  onChange: (ctx) => {
751
- ctx.onValueChange?.({ value: ctx.value, valueAsNumber: ctx.valueAsNumber });
832
+ ctx.onValueChange?.({
833
+ value: ctx.value,
834
+ valueAsNumber: ctx.valueAsNumber
835
+ });
752
836
  }
753
837
  };
754
838
  var set = {