@zag-js/number-input 0.0.0-dev-20230925133045 → 0.0.0-dev-20230926100120

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,29 +159,26 @@ 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,
@@ -270,44 +228,63 @@ function connect(state, send, normalize) {
270
228
  "aria-roledescription": "numberfield",
271
229
  "aria-valuemin": state.context.min,
272
230
  "aria-valuemax": state.context.max,
273
- "aria-valuenow": isNaN(state.context.valueAsNumber) ? void 0 : state.context.valueAsNumber,
231
+ "aria-valuenow": Number.isNaN(state.context.valueAsNumber) ? void 0 : state.context.valueAsNumber,
274
232
  "aria-valuetext": state.context.valueText,
233
+ onCompositionStart() {
234
+ send("INPUT.COMPOSITION_START");
235
+ },
236
+ onCompositionEnd() {
237
+ send("INPUT.COMPOSITION_END");
238
+ },
275
239
  onFocus() {
276
- send("FOCUS");
240
+ send("INPUT.FOCUS");
277
241
  },
278
242
  onBlur() {
279
- send("BLUR");
243
+ send({ type: "INPUT.COMMIT", src: "blur" });
280
244
  },
281
245
  onChange(event) {
282
- 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
+ }
283
258
  },
284
259
  onKeyDown(event) {
285
- const evt = (0, import_dom_event2.getNativeEvent)(event);
286
- if (evt.isComposing)
260
+ if (state.context.readOnly)
287
261
  return;
288
- if (!utils.isValidNumericEvent(state.context, event)) {
289
- event.preventDefault();
290
- }
291
- const step = (0, import_dom_event2.getEventStep)(event) * state.context.step;
262
+ const step = (0, import_dom_event.getEventStep)(event) * state.context.step;
292
263
  const keyMap = {
293
264
  ArrowUp() {
294
- send({ type: "ARROW_UP", step });
265
+ send({ type: "INPUT.ARROW_UP", step });
266
+ event.preventDefault();
295
267
  },
296
268
  ArrowDown() {
297
- send({ type: "ARROW_DOWN", step });
269
+ send({ type: "INPUT.ARROW_DOWN", step });
270
+ event.preventDefault();
298
271
  },
299
272
  Home() {
300
- send("HOME");
273
+ send("INPUT.HOME");
274
+ event.preventDefault();
301
275
  },
302
276
  End() {
303
- 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" });
304
284
  }
305
285
  };
306
286
  const exec = keyMap[event.key];
307
- if (exec) {
308
- exec(event);
309
- event.preventDefault();
310
- }
287
+ exec?.(event);
311
288
  }
312
289
  }),
313
290
  decrementTriggerProps: normalize.button({
@@ -321,18 +298,23 @@ function connect(state, send, normalize) {
321
298
  tabIndex: -1,
322
299
  "aria-controls": dom.getInputId(state.context),
323
300
  onPointerDown(event) {
324
- if (isDecrementDisabled)
301
+ if (isDecrementDisabled || !(0, import_dom_event.isLeftClick)(event))
325
302
  return;
326
- send((0, import_dom_event2.isLeftClick)(event) ? { type: "PRESS_DOWN", hint: "decrement" } : { type: "FOCUS" });
327
- 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
+ }
328
310
  },
329
311
  onPointerUp() {
330
- send({ type: "PRESS_UP", hint: "decrement" });
312
+ send({ type: "TRIGGER.PRESS_UP", hint: "decrement" });
331
313
  },
332
314
  onPointerLeave() {
333
315
  if (isDecrementDisabled)
334
316
  return;
335
- send({ type: "PRESS_UP", hint: "decrement" });
317
+ send({ type: "TRIGGER.PRESS_UP", hint: "decrement" });
336
318
  }
337
319
  }),
338
320
  incrementTriggerProps: normalize.button({
@@ -346,16 +328,21 @@ function connect(state, send, normalize) {
346
328
  tabIndex: -1,
347
329
  "aria-controls": dom.getInputId(state.context),
348
330
  onPointerDown(event) {
349
- if (isIncrementDisabled)
331
+ if (isIncrementDisabled || !(0, import_dom_event.isLeftClick)(event))
350
332
  return;
351
- send((0, import_dom_event2.isLeftClick)(event) ? { type: "PRESS_DOWN", hint: "increment" } : { type: "FOCUS" });
352
- 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
+ }
353
340
  },
354
341
  onPointerUp() {
355
- send({ type: "PRESS_UP", hint: "increment" });
342
+ send({ type: "TRIGGER.PRESS_UP", hint: "increment" });
356
343
  },
357
344
  onPointerLeave() {
358
- send({ type: "PRESS_UP", hint: "increment" });
345
+ send({ type: "TRIGGER.PRESS_UP", hint: "increment" });
359
346
  }
360
347
  }),
361
348
  scrubberProps: normalize.element({
@@ -366,11 +353,11 @@ function connect(state, send, normalize) {
366
353
  onMouseDown(event) {
367
354
  if (isDisabled)
368
355
  return;
369
- const evt = (0, import_dom_event2.getNativeEvent)(event);
370
- const point = (0, import_dom_event2.getEventPoint)(evt);
371
- point.x = point.x - (0, import_number_utils3.roundToDevicePixel)(7.5);
372
- point.y = point.y - (0, import_number_utils3.roundToDevicePixel)(7.5);
373
- 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 });
374
361
  event.preventDefault();
375
362
  },
376
363
  style: {
@@ -381,12 +368,57 @@ function connect(state, send, normalize) {
381
368
  }
382
369
 
383
370
  // src/number-input.machine.ts
371
+ var import_number = require("@internationalized/number");
384
372
  var import_core = require("@zag-js/core");
385
- var import_dom_event3 = require("@zag-js/dom-event");
373
+ var import_dom_event2 = require("@zag-js/dom-event");
386
374
  var import_dom_query3 = require("@zag-js/dom-query");
375
+ var import_form_utils = require("@zag-js/form-utils");
387
376
  var import_mutation_observer = require("@zag-js/mutation-observer");
388
- var import_number_utils4 = require("@zag-js/number-utils");
377
+ var import_number_utils3 = require("@zag-js/number-utils");
389
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
390
422
  var { not, and } = import_core.guards;
391
423
  function machine(userContext) {
392
424
  const ctx = (0, import_utils.compact)(userContext);
@@ -396,20 +428,25 @@ function machine(userContext) {
396
428
  initial: "idle",
397
429
  context: {
398
430
  dir: "ltr",
431
+ locale: "en-US",
399
432
  focusInputOnChange: true,
400
433
  clampValueOnBlur: true,
401
434
  allowOverflow: false,
402
435
  inputMode: "decimal",
403
436
  pattern: "[0-9]*(.[0-9]+)?",
404
- hint: null,
405
437
  value: "",
406
438
  step: 1,
407
439
  min: Number.MIN_SAFE_INTEGER,
408
440
  max: Number.MAX_SAFE_INTEGER,
409
- scrubberCursorPoint: null,
410
441
  invalid: false,
411
442
  spinOnPress: true,
412
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),
413
450
  translations: {
414
451
  incrementLabel: "increment value",
415
452
  decrementLabel: "decrease value",
@@ -418,48 +455,56 @@ function machine(userContext) {
418
455
  },
419
456
  computed: {
420
457
  isRtl: (ctx2) => ctx2.dir === "rtl",
421
- valueAsNumber: (ctx2) => (0, import_number_utils4.valueOf)(ctx2.value),
422
- isAtMin: (ctx2) => (0, import_number_utils4.isAtMin)(ctx2.value, ctx2),
423
- isAtMax: (ctx2) => (0, import_number_utils4.isAtMax)(ctx2.value, ctx2),
424
- 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),
425
462
  isValueEmpty: (ctx2) => ctx2.value === "",
463
+ isDisabled: (ctx2) => !!ctx2.disabled || ctx2.fieldsetDisabled,
426
464
  canIncrement: (ctx2) => ctx2.allowOverflow || !ctx2.isAtMax,
427
465
  canDecrement: (ctx2) => ctx2.allowOverflow || !ctx2.isAtMin,
428
466
  valueText: (ctx2) => ctx2.translations.valueText?.(ctx2.value),
429
- 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
+ }
430
472
  },
431
473
  watch: {
474
+ formatOptions: ["setFormatterAndParser", "syncInputElement"],
475
+ locale: ["setFormatterAndParser", "syncInputElement"],
432
476
  value: ["syncInputElement"],
433
477
  isOutOfRange: ["invokeOnInvalid"],
434
478
  scrubberCursorPoint: ["setVirtualCursorPosition"]
435
479
  },
436
480
  entry: ["syncInputValue"],
481
+ activities: ["trackFormControl"],
437
482
  on: {
438
- SET_VALUE: {
483
+ "VALUE.SET": {
439
484
  actions: ["setValue", "clampValue", "setHintToSet"]
440
485
  },
441
- CLEAR_VALUE: {
486
+ "VALUE.CLEAR": {
442
487
  actions: ["clearValue"]
443
488
  },
444
- INCREMENT: {
489
+ "VALUE.INCREMENT": {
445
490
  actions: ["increment"]
446
491
  },
447
- DECREMENT: {
492
+ "VALUE.DECREMENT": {
448
493
  actions: ["decrement"]
449
494
  }
450
495
  },
451
496
  states: {
452
497
  idle: {
453
498
  on: {
454
- PRESS_DOWN: {
499
+ "TRIGGER.PRESS_DOWN": {
455
500
  target: "before:spin",
456
501
  actions: ["focusInput", "invokeOnFocus", "setHint"]
457
502
  },
458
- PRESS_DOWN_SCRUBBER: {
503
+ "SCRUBBER.PRESS_DOWN": {
459
504
  target: "scrubbing",
460
505
  actions: ["focusInput", "invokeOnFocus", "setHint", "setCursorPoint"]
461
506
  },
462
- FOCUS: {
507
+ "INPUT.FOCUS": {
463
508
  target: "focused",
464
509
  actions: ["focusInput", "invokeOnFocus"]
465
510
  }
@@ -470,45 +515,46 @@ function machine(userContext) {
470
515
  entry: "focusInput",
471
516
  activities: "attachWheelListener",
472
517
  on: {
473
- PRESS_DOWN: {
518
+ "TRIGGER.PRESS_DOWN": {
474
519
  target: "before:spin",
475
520
  actions: ["focusInput", "setHint"]
476
521
  },
477
- PRESS_DOWN_SCRUBBER: {
522
+ "SCRUBBER.PRESS_DOWN": {
478
523
  target: "scrubbing",
479
524
  actions: ["focusInput", "setHint", "setCursorPoint"]
480
525
  },
481
- ARROW_UP: {
526
+ "INPUT.ARROW_UP": {
482
527
  actions: "increment"
483
528
  },
484
- ARROW_DOWN: {
529
+ "INPUT.ARROW_DOWN": {
485
530
  actions: "decrement"
486
531
  },
487
- HOME: {
488
- actions: "setToMin"
532
+ "INPUT.HOME": {
533
+ actions: "decrementToMin"
489
534
  },
490
- END: {
491
- actions: "setToMax"
535
+ "INPUT.END": {
536
+ actions: "incrementToMax"
492
537
  },
493
- CHANGE: {
538
+ "INPUT.CHANGE": {
494
539
  actions: ["setValue", "setHint"]
495
540
  },
496
- BLUR: [
541
+ "INPUT.COMMIT": [
497
542
  {
498
- guard: "isInvalidExponential",
543
+ guard: and("clampValueOnBlur", not("isInRange")),
499
544
  target: "idle",
500
- actions: ["clearValue", "clearHint", "invokeOnBlur"]
545
+ actions: ["clampValue", "syncInputElement", "clearHint", "invokeOnBlur"]
501
546
  },
502
547
  {
503
- guard: and("clampOnBlur", not("isInRange"), not("isEmptyValue")),
504
548
  target: "idle",
505
- actions: ["clampValue", "clearHint", "invokeOnBlur"]
506
- },
507
- {
508
- target: "idle",
509
- actions: ["roundValue", "invokeOnBlur"]
549
+ actions: ["syncInputElement", "invokeOnBlur"]
510
550
  }
511
- ]
551
+ ],
552
+ "INPUT.COMPOSITION_START": {
553
+ actions: "setComposing"
554
+ },
555
+ "INPUT.COMPOSITION_END": {
556
+ actions: "clearComposing"
557
+ }
512
558
  }
513
559
  },
514
560
  "before:spin": {
@@ -525,7 +571,7 @@ function machine(userContext) {
525
571
  }
526
572
  },
527
573
  on: {
528
- PRESS_UP: {
574
+ "TRIGGER.PRESS_UP": {
529
575
  target: "focused",
530
576
  actions: "clearHint"
531
577
  }
@@ -547,7 +593,7 @@ function machine(userContext) {
547
593
  }
548
594
  ],
549
595
  on: {
550
- PRESS_UP: {
596
+ "TRIGGER.PRESS_UP": {
551
597
  target: "focused",
552
598
  actions: "clearHint"
553
599
  }
@@ -558,8 +604,8 @@ function machine(userContext) {
558
604
  exit: "clearCursorPoint",
559
605
  activities: ["activatePointerLock", "trackMousemove", "setupVirtualCursor", "preventTextSelection"],
560
606
  on: {
561
- POINTER_UP_SCRUBBER: "focused",
562
- POINTER_MOVE_SCRUBBER: [
607
+ "SCRUBBER.POINTER_UP": "focused",
608
+ "SCRUBBER.POINTER_MOVE": [
563
609
  {
564
610
  guard: "isIncrementHint",
565
611
  actions: ["increment", "setCursorPoint"]
@@ -579,17 +625,26 @@ function machine(userContext) {
579
625
  CHANGE_DELAY: 300
580
626
  },
581
627
  guards: {
582
- clampOnBlur: (ctx2) => !!ctx2.clampValueOnBlur,
628
+ clampValueOnBlur: (ctx2) => ctx2.clampValueOnBlur,
583
629
  isAtMin: (ctx2) => ctx2.isAtMin,
584
630
  spinOnPress: (ctx2) => !!ctx2.spinOnPress,
585
631
  isAtMax: (ctx2) => ctx2.isAtMax,
586
632
  isInRange: (ctx2) => !ctx2.isOutOfRange,
587
633
  isDecrementHint: (ctx2, evt) => (evt.hint ?? ctx2.hint) === "decrement",
588
- isEmptyValue: (ctx2) => ctx2.isValueEmpty,
589
- isIncrementHint: (ctx2, evt) => (evt.hint ?? ctx2.hint) === "increment",
590
- isInvalidExponential: (ctx2) => ctx2.value.toString().startsWith("e")
634
+ isIncrementHint: (ctx2, evt) => (evt.hint ?? ctx2.hint) === "increment"
591
635
  },
592
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
+ },
593
648
  setupVirtualCursor(ctx2) {
594
649
  return dom.setupVirtualCursor(ctx2);
595
650
  },
@@ -599,31 +654,28 @@ function machine(userContext) {
599
654
  trackButtonDisabled(ctx2, _evt, { send }) {
600
655
  const btn = dom.getPressedTriggerEl(ctx2, ctx2.hint);
601
656
  return (0, import_mutation_observer.observeAttributes)(btn, ["disabled"], () => {
602
- send("PRESS_UP");
657
+ send({ type: "TRIGGER.PRESS_UP", src: "attr" });
603
658
  });
604
659
  },
605
660
  attachWheelListener(ctx2, _evt, { send }) {
606
- const input = dom.getInputEl(ctx2);
607
- if (!input)
661
+ const inputEl = dom.getInputEl(ctx2);
662
+ if (!inputEl || !dom.isActiveElement(ctx2, inputEl) || !ctx2.allowMouseWheel)
608
663
  return;
609
664
  function onWheel(event) {
610
- const isInputFocused = dom.getDoc(ctx2).activeElement === input;
611
- if (!ctx2.allowMouseWheel || !isInputFocused)
612
- return;
613
665
  event.preventDefault();
614
666
  const dir = Math.sign(event.deltaY) * -1;
615
667
  if (dir === 1) {
616
- send("INCREMENT");
668
+ send("VALUE.INCREMENT");
617
669
  } else if (dir === -1) {
618
- send("DECREMENT");
670
+ send("VALUE.DECREMENT");
619
671
  }
620
672
  }
621
- return (0, import_dom_event3.addDomEvent)(input, "wheel", onWheel, { passive: false });
673
+ return (0, import_dom_event2.addDomEvent)(inputEl, "wheel", onWheel, { passive: false });
622
674
  },
623
675
  activatePointerLock(ctx2) {
624
676
  if ((0, import_dom_query3.isSafari)())
625
677
  return;
626
- return (0, import_dom_event3.requestPointerLock)(dom.getDoc(ctx2));
678
+ return (0, import_dom_event2.requestPointerLock)(dom.getDoc(ctx2));
627
679
  },
628
680
  trackMousemove(ctx2, _evt, { send }) {
629
681
  const doc = dom.getDoc(ctx2);
@@ -634,17 +686,17 @@ function machine(userContext) {
634
686
  if (!value.hint)
635
687
  return;
636
688
  send({
637
- type: "POINTER_MOVE_SCRUBBER",
689
+ type: "SCRUBBER.POINTER_MOVE",
638
690
  hint: value.hint,
639
691
  point: value.point
640
692
  });
641
693
  }
642
694
  function onMouseup() {
643
- send("POINTER_UP_SCRUBBER");
695
+ send("SCRUBBER.POINTER_UP");
644
696
  }
645
697
  return (0, import_utils.callAll)(
646
- (0, import_dom_event3.addDomEvent)(doc, "mousemove", onMousemove, false),
647
- (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)
648
700
  );
649
701
  }
650
702
  },
@@ -653,37 +705,34 @@ function machine(userContext) {
653
705
  if (!ctx2.focusInputOnChange)
654
706
  return;
655
707
  const inputEl = dom.getInputEl(ctx2);
656
- (0, import_dom_query3.raf)(() => {
657
- inputEl?.focus();
658
- });
708
+ if (dom.isActiveElement(ctx2, inputEl))
709
+ return;
710
+ (0, import_dom_query3.raf)(() => inputEl?.focus({ preventScroll: true }));
659
711
  },
660
712
  increment(ctx2, evt) {
661
- 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)));
662
715
  },
663
716
  decrement(ctx2, evt) {
664
- 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)));
665
719
  },
666
720
  clampValue(ctx2) {
667
- set.value(ctx2, utils.clamp(ctx2));
668
- },
669
- roundValue(ctx2) {
670
- if (ctx2.value === "")
671
- return;
672
- set.value(ctx2, utils.round(ctx2));
721
+ const nextValue = (0, import_number_utils3.clamp)(ctx2.value, ctx2);
722
+ set.value(ctx2, String(nextValue));
673
723
  },
674
724
  setValue(ctx2, evt) {
675
- let value = evt.target?.value ?? evt.value;
676
- value = utils.sanitize(ctx2, utils.parse(ctx2, value.toString()));
725
+ const value = evt.target?.value ?? evt.value;
677
726
  set.value(ctx2, value);
678
727
  },
679
728
  clearValue(ctx2) {
680
729
  set.value(ctx2, "");
681
730
  },
682
- setToMax(ctx2) {
683
- set.value(ctx2, ctx2.max.toString());
731
+ incrementToMax(ctx2) {
732
+ set.value(ctx2, String(ctx2.max));
684
733
  },
685
- setToMin(ctx2) {
686
- set.value(ctx2, ctx2.min.toString());
734
+ decrementToMin(ctx2) {
735
+ set.value(ctx2, String(ctx2.min));
687
736
  },
688
737
  setHint(ctx2, evt) {
689
738
  ctx2.hint = evt.hint;
@@ -694,15 +743,9 @@ function machine(userContext) {
694
743
  setHintToSet(ctx2) {
695
744
  ctx2.hint = "set";
696
745
  },
697
- invokeOnFocus(ctx2, evt) {
698
- const srcElement = (0, import_utils.match)(evt.type, {
699
- PRESS_DOWN: dom.getPressedTriggerEl(ctx2, evt.hint),
700
- FOCUS: dom.getInputEl(ctx2),
701
- PRESS_DOWN_SCRUBBER: dom.getScrubberEl(ctx2)
702
- });
746
+ invokeOnFocus(ctx2) {
703
747
  ctx2.onFocusChange?.({
704
748
  focused: true,
705
- srcElement,
706
749
  value: ctx2.formattedValue,
707
750
  valueAsNumber: ctx2.valueAsNumber
708
751
  });
@@ -724,16 +767,20 @@ function machine(userContext) {
724
767
  valueAsNumber: ctx2.valueAsNumber
725
768
  });
726
769
  },
727
- syncInputElement(ctx2) {
770
+ syncInputElement(ctx2, evt) {
728
771
  const inputEl = dom.getInputEl(ctx2);
729
- 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
+ });
730
778
  },
731
779
  syncInputValue(ctx2) {
732
780
  const inputEl = dom.getInputEl(ctx2);
733
781
  if (!inputEl || inputEl.value == ctx2.value)
734
782
  return;
735
- const value = utils.parse(ctx2, inputEl.value);
736
- set.value(ctx2, utils.sanitize(ctx2, value));
783
+ set.value(ctx2, ctx2.formattedValue);
737
784
  },
738
785
  setCursorPoint(ctx2, evt) {
739
786
  ctx2.scrubberCursorPoint = evt.point;
@@ -742,19 +789,50 @@ function machine(userContext) {
742
789
  ctx2.scrubberCursorPoint = null;
743
790
  },
744
791
  setVirtualCursorPosition(ctx2) {
745
- const cursor = dom.getCursorEl(ctx2);
746
- if (!cursor || !ctx2.scrubberCursorPoint)
792
+ const cursorEl = dom.getCursorEl(ctx2);
793
+ if (!cursorEl || !ctx2.scrubberCursorPoint)
747
794
  return;
748
795
  const { x, y } = ctx2.scrubberCursorPoint;
749
- 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);
750
809
  }
810
+ },
811
+ compareFns: {
812
+ formatOptions: (a, b) => (0, import_utils.isEqual)(a, b)
751
813
  }
752
814
  }
753
815
  );
754
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
+ };
755
830
  var invoke = {
756
831
  onChange: (ctx) => {
757
- ctx.onValueChange?.({ value: ctx.value, valueAsNumber: ctx.valueAsNumber });
832
+ ctx.onValueChange?.({
833
+ value: ctx.value,
834
+ valueAsNumber: ctx.valueAsNumber
835
+ });
758
836
  }
759
837
  };
760
838
  var set = {