@zag-js/number-input 0.1.3 → 0.1.6

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
@@ -45,19 +45,9 @@ module.exports = __toCommonJS(src_exports);
45
45
  var dataAttr = (guard) => {
46
46
  return guard ? "" : void 0;
47
47
  };
48
- function nextTick(fn) {
49
- const set = /* @__PURE__ */ new Set();
50
- function raf2(fn2) {
51
- const id = globalThis.requestAnimationFrame(fn2);
52
- set.add(() => globalThis.cancelAnimationFrame(id));
53
- }
54
- raf2(() => raf2(fn));
55
- return function cleanup() {
56
- set.forEach(function(fn2) {
57
- fn2();
58
- });
59
- };
60
- }
48
+ var ariaAttr = (guard) => {
49
+ return guard ? "true" : void 0;
50
+ };
61
51
  function raf(fn) {
62
52
  const id = globalThis.requestAnimationFrame(fn);
63
53
  return function cleanup() {
@@ -136,11 +126,11 @@ function addDomEvent(target, event, listener, options) {
136
126
  const node = isRef(target) ? target.current : runIfFn(target);
137
127
  return globalEventBus(node, event, listener, options);
138
128
  }
129
+ var MAX_Z_INDEX = 2147483647;
139
130
  function getNativeEvent(event) {
140
131
  var _a;
141
132
  return (_a = event.nativeEvent) != null ? _a : event;
142
133
  }
143
- var MAX_Z_INDEX = 2147483647;
144
134
  var PAGE_KEYS = /* @__PURE__ */ new Set(["PageUp", "PageDown"]);
145
135
  var ARROW_KEYS = /* @__PURE__ */ new Set(["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"]);
146
136
  function getEventStep(event) {
@@ -261,40 +251,11 @@ findByTypeahead.defaultOptions = {
261
251
  };
262
252
 
263
253
  // ../../utilities/number/dist/index.mjs
264
- var __defProp2 = Object.defineProperty;
265
- var __defProps2 = Object.defineProperties;
266
- var __getOwnPropDescs2 = Object.getOwnPropertyDescriptors;
267
- var __getOwnPropSymbols2 = Object.getOwnPropertySymbols;
268
- var __hasOwnProp2 = Object.prototype.hasOwnProperty;
269
- var __propIsEnum2 = Object.prototype.propertyIsEnumerable;
270
254
  var __pow = Math.pow;
271
- var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
272
- var __spreadValues2 = (a, b) => {
273
- for (var prop in b || (b = {}))
274
- if (__hasOwnProp2.call(b, prop))
275
- __defNormalProp2(a, prop, b[prop]);
276
- if (__getOwnPropSymbols2)
277
- for (var prop of __getOwnPropSymbols2(b)) {
278
- if (__propIsEnum2.call(b, prop))
279
- __defNormalProp2(a, prop, b[prop]);
280
- }
281
- return a;
282
- };
283
- var __spreadProps2 = (a, b) => __defProps2(a, __getOwnPropDescs2(b));
284
- var nf = new Intl.NumberFormat("en-US", { style: "decimal", maximumFractionDigits: 20 });
285
- function formatter(n) {
286
- return parseFloat(nf.format(n));
287
- }
288
255
  function wrap2(num, max) {
289
256
  return (num % max + max) % max;
290
257
  }
291
- function round(v, t2) {
292
- let num = valueOf(v);
293
- const p = __pow(10, t2 != null ? t2 : 10);
294
- num = Math.round(num * p) / p;
295
- return t2 ? num.toFixed(t2) : v.toString();
296
- }
297
- function roundToPx(num) {
258
+ function roundToDevicePixel(num) {
298
259
  if (typeof window === "undefined")
299
260
  return Math.round(num);
300
261
  const dp = window.devicePixelRatio;
@@ -306,30 +267,28 @@ function clamp(v, o) {
306
267
  function countDecimals(value) {
307
268
  if (!Number.isFinite(value))
308
269
  return 0;
309
- let e = 1;
310
- let p = 0;
270
+ let e = 1, p = 0;
311
271
  while (Math.round(value * e) / e !== value) {
312
272
  e *= 10;
313
273
  p += 1;
314
274
  }
315
275
  return p;
316
276
  }
317
- var increment = (v, s) => formatter(valueOf(v) + s);
318
- var decrement = (v, s) => formatter(valueOf(v) - s);
319
- var multiply = (v, s) => formatter(valueOf(v) * s);
277
+ var increment = (v, s) => decimalOperation(valueOf(v), "+", s);
278
+ var decrement = (v, s) => decimalOperation(valueOf(v), "-", s);
320
279
  function valueOf(v) {
321
280
  if (typeof v === "number")
322
281
  return v;
323
282
  const num = parseFloat(v.toString().replace(/[^\w.-]+/g, ""));
324
283
  return !Number.isNaN(num) ? num : 0;
325
284
  }
326
- function getMaxPrecision(o) {
327
- var _a;
328
- const stepPrecision = countDecimals(o.step);
329
- return Math.max(stepPrecision, (_a = o.precision) != null ? _a : 0);
330
- }
331
- function roundToPrecision(v, o) {
332
- return round(v, getMaxPrecision(__spreadProps2(__spreadValues2({}, o), { value: v })));
285
+ function formatDecimal(v, o) {
286
+ return new Intl.NumberFormat("en-US", {
287
+ useGrouping: false,
288
+ style: "decimal",
289
+ minimumFractionDigits: o.minFractionDigits,
290
+ maximumFractionDigits: o.maxFractionDigits
291
+ }).format(valueOf(v));
333
292
  }
334
293
  function isAtMax(v, o) {
335
294
  const val = valueOf(v);
@@ -343,6 +302,18 @@ function isWithinRange(v, o) {
343
302
  const val = valueOf(v);
344
303
  return val >= o.min && val <= o.max;
345
304
  }
305
+ function decimalOperation(a, op, b) {
306
+ let result = op === "+" ? a + b : a - b;
307
+ if (a % 1 !== 0 || b % 1 !== 0) {
308
+ const multiplier = __pow(10, Math.max(countDecimals(a), countDecimals(b)));
309
+ a = Math.round(a * multiplier);
310
+ b = Math.round(b * multiplier);
311
+ result = op === "+" ? a + b : a - b;
312
+ result /= multiplier;
313
+ }
314
+ return result;
315
+ }
316
+ var nf = new Intl.NumberFormat("en-US", { style: "decimal", maximumFractionDigits: 20 });
346
317
 
347
318
  // ../../utilities/rect/dist/index.mjs
348
319
  var isArray = (v) => Array.isArray(v);
@@ -360,6 +331,19 @@ function createNormalizer(fn) {
360
331
  }
361
332
  var normalizeProp = createNormalizer((v) => v);
362
333
 
334
+ // ../../utilities/core/dist/index.mjs
335
+ var pipe2 = (...fns) => (v) => fns.reduce((a, b) => b(a), v);
336
+ var platform = (v) => isDom() && v.test(navigator.platform);
337
+ var ua = (v) => isDom() && v.test(navigator.userAgent);
338
+ var isDom = () => !!(typeof window !== "undefined");
339
+ var isMac = () => platform(/^Mac/);
340
+ var isIPhone = () => platform(/^iPhone/);
341
+ var isIPad = () => platform(/^iPad/) || isMac() && navigator.maxTouchPoints > 1;
342
+ var isIos = () => isIPhone() || isIPad();
343
+ var isSafari = () => ua(/^((?!chrome|android).)*safari/i);
344
+ var supportsPointerEvent = () => isDom() && window.onpointerdown === null;
345
+ var isModifiedEvent = (v) => v.ctrlKey || v.altKey || v.metaKey;
346
+
363
347
  // src/number-input.dom.ts
364
348
  var dom = {
365
349
  getDoc: (ctx) => {
@@ -370,6 +354,10 @@ var dom = {
370
354
  var _a;
371
355
  return (_a = dom.getDoc(ctx).defaultView) != null ? _a : window;
372
356
  },
357
+ getRootNode: (ctx) => {
358
+ var _a;
359
+ return (_a = ctx.rootNode) != null ? _a : dom.getDoc(ctx);
360
+ },
373
361
  getRootId: (ctx) => {
374
362
  var _a, _b;
375
363
  return (_b = (_a = ctx.ids) == null ? void 0 : _a.root) != null ? _b : `number-input:${ctx.uid}`;
@@ -395,14 +383,14 @@ var dom = {
395
383
  var _a, _b;
396
384
  return (_b = (_a = ctx.ids) == null ? void 0 : _a.label) != null ? _b : `number-input:${ctx.uid}:label`;
397
385
  },
398
- getInputEl: (ctx) => dom.getDoc(ctx).getElementById(dom.getInputId(ctx)),
399
- getIncButtonEl: (ctx) => dom.getDoc(ctx).getElementById(dom.getIncButtonId(ctx)),
400
- getDecButtonEl: (ctx) => dom.getDoc(ctx).getElementById(dom.getDecButtonId(ctx)),
401
- getScrubberEl: (ctx) => dom.getDoc(ctx).getElementById(dom.getScrubberId(ctx)),
386
+ getInputEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getInputId(ctx)),
387
+ getIncButtonEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getIncButtonId(ctx)),
388
+ getDecButtonEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getDecButtonId(ctx)),
389
+ getScrubberEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getScrubberId(ctx)),
402
390
  getCursorEl: (ctx) => dom.getDoc(ctx).getElementById(dom.getCursorId(ctx)),
403
391
  getMousementValue(ctx, event) {
404
- const x = roundToPx(event.movementX);
405
- const y = roundToPx(event.movementY);
392
+ const x = roundToDevicePixel(event.movementX);
393
+ const y = roundToDevicePixel(event.movementY);
406
394
  let hint = x > 0 ? "increment" : x < 0 ? "decrement" : null;
407
395
  if (ctx.isRtl && hint === "increment")
408
396
  hint = "decrement";
@@ -414,7 +402,7 @@ var dom = {
414
402
  };
415
403
  const win = dom.getWin(ctx);
416
404
  const width = win.innerWidth;
417
- const half = roundToPx(7.5);
405
+ const half = roundToDevicePixel(7.5);
418
406
  point.x = wrap2(point.x + half, width) - half;
419
407
  return { hint, point };
420
408
  },
@@ -445,14 +433,6 @@ var dom = {
445
433
  }
446
434
  };
447
435
 
448
- // ../../utilities/core/dist/index.mjs
449
- var pipe2 = (...fns) => (v) => fns.reduce((a, b) => b(a), v);
450
- var ua = (v) => isDom() && v.test(navigator.userAgent);
451
- var isDom = () => !!(typeof window !== "undefined");
452
- var isSafari = () => ua(/^((?!chrome|android).)*safari/i);
453
- var supportsPointerEvent = () => isDom() && window.onpointerdown === null;
454
- var isModifiedEvent = (v) => v.ctrlKey || v.altKey || v.metaKey;
455
-
456
436
  // src/number-input.utils.ts
457
437
  var utils = {
458
438
  isValidNumericEvent: (ctx, event) => {
@@ -471,18 +451,15 @@ var utils = {
471
451
  return value.split("").filter((_a = ctx.validateCharacter) != null ? _a : utils.isFloatingPoint).join("");
472
452
  },
473
453
  increment: (ctx, step) => {
474
- let value = increment(ctx.value, step != null ? step : ctx.step);
475
- value = clamp(value, ctx);
476
- return roundToPrecision(value, ctx);
454
+ const value = increment(ctx.value, step != null ? step : ctx.step);
455
+ return formatDecimal(clamp(value, ctx), ctx);
477
456
  },
478
457
  decrement: (ctx, step) => {
479
- let value = decrement(ctx.value, step != null ? step : ctx.step);
480
- value = clamp(value, ctx);
481
- return roundToPrecision(value, ctx);
458
+ const value = decrement(ctx.value, step != null ? step : ctx.step);
459
+ return formatDecimal(clamp(value, ctx), ctx);
482
460
  },
483
461
  clamp: (ctx) => {
484
- let value = clamp(ctx.value, ctx);
485
- return roundToPrecision(value, ctx);
462
+ return formatDecimal(clamp(ctx.value, ctx), ctx);
486
463
  },
487
464
  parse: (ctx, value) => {
488
465
  var _a, _b;
@@ -494,7 +471,7 @@ var utils = {
494
471
  return (_b = (_a = ctx.format) == null ? void 0 : _a.call(ctx, _val)) != null ? _b : _val;
495
472
  },
496
473
  round: (ctx) => {
497
- return roundToPrecision(ctx.value, ctx);
474
+ return formatDecimal(ctx.value, ctx);
498
475
  }
499
476
  };
500
477
 
@@ -515,7 +492,7 @@ function connect(state, send, normalize = normalizeProp) {
515
492
  send({ type: "SET_VALUE", value: value.toString() });
516
493
  },
517
494
  clearValue() {
518
- send({ type: "SET_VALUE", value: "" });
495
+ send("CLEAR_VALUE");
519
496
  },
520
497
  increment() {
521
498
  send("INCREMENT");
@@ -545,6 +522,14 @@ function connect(state, send, normalize = normalizeProp) {
545
522
  id: dom.getLabelId(state.context),
546
523
  htmlFor: dom.getInputId(state.context)
547
524
  }),
525
+ groupProps: normalize.element({
526
+ "data-part": "group",
527
+ role: "group",
528
+ "aria-disabled": isDisabled,
529
+ "data-disabled": dataAttr(isDisabled),
530
+ "data-invalid": dataAttr(isInvalid),
531
+ "aria-invalid": ariaAttr(state.context.invalid)
532
+ }),
548
533
  inputProps: normalize.input({
549
534
  "data-part": "input",
550
535
  name: state.context.name,
@@ -562,7 +547,7 @@ function connect(state, send, normalize = normalizeProp) {
562
547
  autoCorrect: "off",
563
548
  spellCheck: "false",
564
549
  type: "text",
565
- "aria-roledescription": "number field",
550
+ "aria-roledescription": !isIos() ? "number field" : void 0,
566
551
  "aria-valuemin": state.context.min,
567
552
  "aria-valuemax": state.context.max,
568
553
  "aria-valuenow": isNaN(state.context.valueAsNumber) ? void 0 : state.context.valueAsNumber,
@@ -586,7 +571,7 @@ function connect(state, send, normalize = normalizeProp) {
586
571
  if (!utils.isValidNumericEvent(state.context, event)) {
587
572
  event.preventDefault();
588
573
  }
589
- const step = multiply(getEventStep(event), state.context.step);
574
+ const step = getEventStep(event) * state.context.step;
590
575
  const keyMap = {
591
576
  ArrowUp() {
592
577
  send({ type: "ARROW_UP", step });
@@ -610,6 +595,7 @@ function connect(state, send, normalize = normalizeProp) {
610
595
  }),
611
596
  decrementButtonProps: normalize.button({
612
597
  "data-part": "spin-button",
598
+ "data-type": "decrement",
613
599
  id: dom.getDecButtonId(state.context),
614
600
  disabled: isDecrementDisabled,
615
601
  "data-disabled": dataAttr(isDecrementDisabled),
@@ -634,6 +620,7 @@ function connect(state, send, normalize = normalizeProp) {
634
620
  }),
635
621
  incrementButtonProps: normalize.button({
636
622
  "data-part": "spin-button",
623
+ "data-type": "increment",
637
624
  id: dom.getIncButtonId(state.context),
638
625
  disabled: isIncrementDisabled,
639
626
  "data-disabled": dataAttr(isIncrementDisabled),
@@ -665,8 +652,8 @@ function connect(state, send, normalize = normalizeProp) {
665
652
  const evt = getNativeEvent(event);
666
653
  event.preventDefault();
667
654
  const point = getEventPoint(evt);
668
- point.x = point.x - roundToPx(7.5);
669
- point.y = point.y - roundToPx(7.5);
655
+ point.x = point.x - roundToDevicePixel(7.5);
656
+ point.y = point.y - roundToDevicePixel(7.5);
670
657
  send({ type: "PRESS_DOWN_SCRUBBER", point });
671
658
  },
672
659
  style: {
@@ -696,8 +683,6 @@ function machine(ctx = {}) {
696
683
  step: 1,
697
684
  min: Number.MIN_SAFE_INTEGER,
698
685
  max: Number.MAX_SAFE_INTEGER,
699
- precision: 0,
700
- inputSelection: null,
701
686
  scrubberCursorPoint: null,
702
687
  invalid: false
703
688
  }, ctx), {
@@ -727,20 +712,26 @@ function machine(ctx = {}) {
727
712
  value: ["invokeOnChange"],
728
713
  isOutOfRange: ["invokeOnInvalid"]
729
714
  },
730
- entry: ["syncInputValue"],
731
715
  on: {
732
716
  SET_VALUE: {
733
717
  actions: ["setValue", "setHintToSet"]
734
718
  },
735
- INCREMENT: { actions: ["increment"] },
736
- DECREMENT: { actions: ["decrement"] }
719
+ CLEAR_VALUE: {
720
+ actions: ["clearValue"]
721
+ },
722
+ INCREMENT: {
723
+ actions: ["increment"]
724
+ },
725
+ DECREMENT: {
726
+ actions: ["decrement"]
727
+ }
737
728
  },
738
729
  states: {
739
730
  unknown: {
740
731
  on: {
741
732
  SETUP: {
742
733
  target: "idle",
743
- actions: "setupDocument"
734
+ actions: ["setupDocument", "syncInputValue"]
744
735
  }
745
736
  }
746
737
  },
@@ -804,6 +795,7 @@ function machine(ctx = {}) {
804
795
  },
805
796
  "before:spin": {
806
797
  tags: ["focus"],
798
+ activities: "trackButtonDisabled",
807
799
  entry: (0, import_core.choose)([
808
800
  { guard: "isIncrementHint", actions: "increment" },
809
801
  { guard: "isDecrementHint", actions: "decrement" }
@@ -899,26 +891,23 @@ function machine(ctx = {}) {
899
891
  send("PRESS_UP");
900
892
  });
901
893
  },
902
- attachWheelListener(ctx2) {
903
- const cleanups = [];
904
- cleanups.push(nextTick(() => {
905
- const input = dom.getInputEl(ctx2);
906
- if (!input)
894
+ attachWheelListener(ctx2, _evt, { send }) {
895
+ const input = dom.getInputEl(ctx2);
896
+ if (!input)
897
+ return;
898
+ function onWheel(event) {
899
+ const isInputFocused = dom.getDoc(ctx2).activeElement === input;
900
+ if (!ctx2.allowMouseWheel || !isInputFocused)
907
901
  return;
908
- function onWheel(event) {
909
- const isInputFocused = dom.getDoc(ctx2).activeElement === input;
910
- if (!ctx2.allowMouseWheel || !isInputFocused)
911
- return;
912
- event.preventDefault();
913
- const dir = Math.sign(event.deltaY) * -1;
914
- if (dir === 1)
915
- ctx2.value = utils.increment(ctx2);
916
- else if (dir === -1)
917
- ctx2.value = utils.decrement(ctx2);
902
+ event.preventDefault();
903
+ const dir = Math.sign(event.deltaY) * -1;
904
+ if (dir === 1) {
905
+ send("INCREMENT");
906
+ } else if (dir === -1) {
907
+ send("DECREMENT");
918
908
  }
919
- cleanups.push(addDomEvent(input, "wheel", onWheel, { passive: false }));
920
- }));
921
- return () => cleanups.forEach((c) => c());
909
+ }
910
+ return addDomEvent(input, "wheel", onWheel, { passive: false });
922
911
  },
923
912
  activatePointerLock(ctx2) {
924
913
  if (isSafari() || !supportsPointerEvent())
@@ -933,7 +922,11 @@ function machine(ctx = {}) {
933
922
  const value = dom.getMousementValue(ctx2, event);
934
923
  if (!value.hint)
935
924
  return;
936
- send({ type: "POINTER_MOVE_SCRUBBER", hint: value.hint, point: value.point });
925
+ send({
926
+ type: "POINTER_MOVE_SCRUBBER",
927
+ hint: value.hint,
928
+ point: value.point
929
+ });
937
930
  }
938
931
  function onMouseup() {
939
932
  send("POINTER_UP_SCRUBBER");
@@ -945,6 +938,8 @@ function machine(ctx = {}) {
945
938
  setupDocument: (ctx2, evt) => {
946
939
  if (evt.doc)
947
940
  ctx2.doc = (0, import_core.ref)(evt.doc);
941
+ if (evt.root)
942
+ ctx2.rootNode = (0, import_core.ref)(evt.root);
948
943
  ctx2.uid = evt.id;
949
944
  },
950
945
  focusInput(ctx2) {
@@ -963,7 +958,9 @@ function machine(ctx = {}) {
963
958
  ctx2.value = utils.clamp(ctx2);
964
959
  },
965
960
  roundValue(ctx2) {
966
- ctx2.value = utils.round(ctx2);
961
+ if (ctx2.value !== "") {
962
+ ctx2.value = utils.round(ctx2);
963
+ }
967
964
  },
968
965
  setValue(ctx2, evt) {
969
966
  var _a, _b;
@@ -990,14 +987,21 @@ function machine(ctx = {}) {
990
987
  },
991
988
  invokeOnChange(ctx2) {
992
989
  var _a;
993
- (_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, { value: ctx2.value, valueAsNumber: ctx2.valueAsNumber });
990
+ (_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, {
991
+ value: ctx2.value,
992
+ valueAsNumber: ctx2.valueAsNumber
993
+ });
994
994
  },
995
995
  invokeOnInvalid(ctx2) {
996
996
  var _a;
997
997
  if (!ctx2.isOutOfRange)
998
998
  return;
999
999
  const reason = ctx2.valueAsNumber > ctx2.max ? "rangeOverflow" : "rangeUnderflow";
1000
- (_a = ctx2.onInvalid) == null ? void 0 : _a.call(ctx2, { reason, value: ctx2.formattedValue, valueAsNumber: ctx2.valueAsNumber });
1000
+ (_a = ctx2.onInvalid) == null ? void 0 : _a.call(ctx2, {
1001
+ reason,
1002
+ value: ctx2.formattedValue,
1003
+ valueAsNumber: ctx2.valueAsNumber
1004
+ });
1001
1005
  },
1002
1006
  syncInputValue(ctx2) {
1003
1007
  const input = dom.getInputEl(ctx2);
@@ -1016,7 +1020,8 @@ function machine(ctx = {}) {
1016
1020
  const cursor = dom.getCursorEl(ctx2);
1017
1021
  if (!cursor || !ctx2.scrubberCursorPoint)
1018
1022
  return;
1019
- cursor.style.transform = `translate3d(${ctx2.scrubberCursorPoint.x}px, ${ctx2.scrubberCursorPoint.y}px, 0px)`;
1023
+ const { x, y } = ctx2.scrubberCursorPoint;
1024
+ cursor.style.transform = `translate3d(${x}px, ${y}px, 0px)`;
1020
1025
  },
1021
1026
  addCustomCursor(ctx2) {
1022
1027
  if (isSafari() || !supportsPointerEvent())
@@ -1024,11 +1029,10 @@ function machine(ctx = {}) {
1024
1029
  dom.createVirtualCursor(ctx2);
1025
1030
  },
1026
1031
  removeCustomCursor(ctx2) {
1032
+ var _a;
1027
1033
  if (isSafari() || !supportsPointerEvent())
1028
1034
  return;
1029
- const doc = dom.getDoc(ctx2);
1030
- const el = doc.getElementById(dom.getCursorId(ctx2));
1031
- el == null ? void 0 : el.remove();
1035
+ (_a = dom.getCursorEl(ctx2)) == null ? void 0 : _a.remove();
1032
1036
  },
1033
1037
  disableTextSelection(ctx2) {
1034
1038
  const doc = dom.getDoc(ctx2);