@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.mjs CHANGED
@@ -22,19 +22,9 @@ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
22
22
  var dataAttr = (guard) => {
23
23
  return guard ? "" : void 0;
24
24
  };
25
- function nextTick(fn) {
26
- const set = /* @__PURE__ */ new Set();
27
- function raf2(fn2) {
28
- const id = globalThis.requestAnimationFrame(fn2);
29
- set.add(() => globalThis.cancelAnimationFrame(id));
30
- }
31
- raf2(() => raf2(fn));
32
- return function cleanup() {
33
- set.forEach(function(fn2) {
34
- fn2();
35
- });
36
- };
37
- }
25
+ var ariaAttr = (guard) => {
26
+ return guard ? "true" : void 0;
27
+ };
38
28
  function raf(fn) {
39
29
  const id = globalThis.requestAnimationFrame(fn);
40
30
  return function cleanup() {
@@ -113,11 +103,11 @@ function addDomEvent(target, event, listener, options) {
113
103
  const node = isRef(target) ? target.current : runIfFn(target);
114
104
  return globalEventBus(node, event, listener, options);
115
105
  }
106
+ var MAX_Z_INDEX = 2147483647;
116
107
  function getNativeEvent(event) {
117
108
  var _a;
118
109
  return (_a = event.nativeEvent) != null ? _a : event;
119
110
  }
120
- var MAX_Z_INDEX = 2147483647;
121
111
  var PAGE_KEYS = /* @__PURE__ */ new Set(["PageUp", "PageDown"]);
122
112
  var ARROW_KEYS = /* @__PURE__ */ new Set(["ArrowUp", "ArrowDown", "ArrowLeft", "ArrowRight"]);
123
113
  function getEventStep(event) {
@@ -238,40 +228,11 @@ findByTypeahead.defaultOptions = {
238
228
  };
239
229
 
240
230
  // ../../utilities/number/dist/index.mjs
241
- var __defProp2 = Object.defineProperty;
242
- var __defProps2 = Object.defineProperties;
243
- var __getOwnPropDescs2 = Object.getOwnPropertyDescriptors;
244
- var __getOwnPropSymbols2 = Object.getOwnPropertySymbols;
245
- var __hasOwnProp2 = Object.prototype.hasOwnProperty;
246
- var __propIsEnum2 = Object.prototype.propertyIsEnumerable;
247
231
  var __pow = Math.pow;
248
- var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
249
- var __spreadValues2 = (a, b) => {
250
- for (var prop in b || (b = {}))
251
- if (__hasOwnProp2.call(b, prop))
252
- __defNormalProp2(a, prop, b[prop]);
253
- if (__getOwnPropSymbols2)
254
- for (var prop of __getOwnPropSymbols2(b)) {
255
- if (__propIsEnum2.call(b, prop))
256
- __defNormalProp2(a, prop, b[prop]);
257
- }
258
- return a;
259
- };
260
- var __spreadProps2 = (a, b) => __defProps2(a, __getOwnPropDescs2(b));
261
- var nf = new Intl.NumberFormat("en-US", { style: "decimal", maximumFractionDigits: 20 });
262
- function formatter(n) {
263
- return parseFloat(nf.format(n));
264
- }
265
232
  function wrap2(num, max) {
266
233
  return (num % max + max) % max;
267
234
  }
268
- function round(v, t2) {
269
- let num = valueOf(v);
270
- const p = __pow(10, t2 != null ? t2 : 10);
271
- num = Math.round(num * p) / p;
272
- return t2 ? num.toFixed(t2) : v.toString();
273
- }
274
- function roundToPx(num) {
235
+ function roundToDevicePixel(num) {
275
236
  if (typeof window === "undefined")
276
237
  return Math.round(num);
277
238
  const dp = window.devicePixelRatio;
@@ -283,30 +244,28 @@ function clamp(v, o) {
283
244
  function countDecimals(value) {
284
245
  if (!Number.isFinite(value))
285
246
  return 0;
286
- let e = 1;
287
- let p = 0;
247
+ let e = 1, p = 0;
288
248
  while (Math.round(value * e) / e !== value) {
289
249
  e *= 10;
290
250
  p += 1;
291
251
  }
292
252
  return p;
293
253
  }
294
- var increment = (v, s) => formatter(valueOf(v) + s);
295
- var decrement = (v, s) => formatter(valueOf(v) - s);
296
- var multiply = (v, s) => formatter(valueOf(v) * s);
254
+ var increment = (v, s) => decimalOperation(valueOf(v), "+", s);
255
+ var decrement = (v, s) => decimalOperation(valueOf(v), "-", s);
297
256
  function valueOf(v) {
298
257
  if (typeof v === "number")
299
258
  return v;
300
259
  const num = parseFloat(v.toString().replace(/[^\w.-]+/g, ""));
301
260
  return !Number.isNaN(num) ? num : 0;
302
261
  }
303
- function getMaxPrecision(o) {
304
- var _a;
305
- const stepPrecision = countDecimals(o.step);
306
- return Math.max(stepPrecision, (_a = o.precision) != null ? _a : 0);
307
- }
308
- function roundToPrecision(v, o) {
309
- return round(v, getMaxPrecision(__spreadProps2(__spreadValues2({}, o), { value: v })));
262
+ function formatDecimal(v, o) {
263
+ return new Intl.NumberFormat("en-US", {
264
+ useGrouping: false,
265
+ style: "decimal",
266
+ minimumFractionDigits: o.minFractionDigits,
267
+ maximumFractionDigits: o.maxFractionDigits
268
+ }).format(valueOf(v));
310
269
  }
311
270
  function isAtMax(v, o) {
312
271
  const val = valueOf(v);
@@ -320,6 +279,18 @@ function isWithinRange(v, o) {
320
279
  const val = valueOf(v);
321
280
  return val >= o.min && val <= o.max;
322
281
  }
282
+ function decimalOperation(a, op, b) {
283
+ let result = op === "+" ? a + b : a - b;
284
+ if (a % 1 !== 0 || b % 1 !== 0) {
285
+ const multiplier = __pow(10, Math.max(countDecimals(a), countDecimals(b)));
286
+ a = Math.round(a * multiplier);
287
+ b = Math.round(b * multiplier);
288
+ result = op === "+" ? a + b : a - b;
289
+ result /= multiplier;
290
+ }
291
+ return result;
292
+ }
293
+ var nf = new Intl.NumberFormat("en-US", { style: "decimal", maximumFractionDigits: 20 });
323
294
 
324
295
  // ../../utilities/rect/dist/index.mjs
325
296
  var isArray = (v) => Array.isArray(v);
@@ -337,6 +308,19 @@ function createNormalizer(fn) {
337
308
  }
338
309
  var normalizeProp = createNormalizer((v) => v);
339
310
 
311
+ // ../../utilities/core/dist/index.mjs
312
+ var pipe2 = (...fns) => (v) => fns.reduce((a, b) => b(a), v);
313
+ var platform = (v) => isDom() && v.test(navigator.platform);
314
+ var ua = (v) => isDom() && v.test(navigator.userAgent);
315
+ var isDom = () => !!(typeof window !== "undefined");
316
+ var isMac = () => platform(/^Mac/);
317
+ var isIPhone = () => platform(/^iPhone/);
318
+ var isIPad = () => platform(/^iPad/) || isMac() && navigator.maxTouchPoints > 1;
319
+ var isIos = () => isIPhone() || isIPad();
320
+ var isSafari = () => ua(/^((?!chrome|android).)*safari/i);
321
+ var supportsPointerEvent = () => isDom() && window.onpointerdown === null;
322
+ var isModifiedEvent = (v) => v.ctrlKey || v.altKey || v.metaKey;
323
+
340
324
  // src/number-input.dom.ts
341
325
  var dom = {
342
326
  getDoc: (ctx) => {
@@ -347,6 +331,10 @@ var dom = {
347
331
  var _a;
348
332
  return (_a = dom.getDoc(ctx).defaultView) != null ? _a : window;
349
333
  },
334
+ getRootNode: (ctx) => {
335
+ var _a;
336
+ return (_a = ctx.rootNode) != null ? _a : dom.getDoc(ctx);
337
+ },
350
338
  getRootId: (ctx) => {
351
339
  var _a, _b;
352
340
  return (_b = (_a = ctx.ids) == null ? void 0 : _a.root) != null ? _b : `number-input:${ctx.uid}`;
@@ -372,14 +360,14 @@ var dom = {
372
360
  var _a, _b;
373
361
  return (_b = (_a = ctx.ids) == null ? void 0 : _a.label) != null ? _b : `number-input:${ctx.uid}:label`;
374
362
  },
375
- getInputEl: (ctx) => dom.getDoc(ctx).getElementById(dom.getInputId(ctx)),
376
- getIncButtonEl: (ctx) => dom.getDoc(ctx).getElementById(dom.getIncButtonId(ctx)),
377
- getDecButtonEl: (ctx) => dom.getDoc(ctx).getElementById(dom.getDecButtonId(ctx)),
378
- getScrubberEl: (ctx) => dom.getDoc(ctx).getElementById(dom.getScrubberId(ctx)),
363
+ getInputEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getInputId(ctx)),
364
+ getIncButtonEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getIncButtonId(ctx)),
365
+ getDecButtonEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getDecButtonId(ctx)),
366
+ getScrubberEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getScrubberId(ctx)),
379
367
  getCursorEl: (ctx) => dom.getDoc(ctx).getElementById(dom.getCursorId(ctx)),
380
368
  getMousementValue(ctx, event) {
381
- const x = roundToPx(event.movementX);
382
- const y = roundToPx(event.movementY);
369
+ const x = roundToDevicePixel(event.movementX);
370
+ const y = roundToDevicePixel(event.movementY);
383
371
  let hint = x > 0 ? "increment" : x < 0 ? "decrement" : null;
384
372
  if (ctx.isRtl && hint === "increment")
385
373
  hint = "decrement";
@@ -391,7 +379,7 @@ var dom = {
391
379
  };
392
380
  const win = dom.getWin(ctx);
393
381
  const width = win.innerWidth;
394
- const half = roundToPx(7.5);
382
+ const half = roundToDevicePixel(7.5);
395
383
  point.x = wrap2(point.x + half, width) - half;
396
384
  return { hint, point };
397
385
  },
@@ -422,14 +410,6 @@ var dom = {
422
410
  }
423
411
  };
424
412
 
425
- // ../../utilities/core/dist/index.mjs
426
- var pipe2 = (...fns) => (v) => fns.reduce((a, b) => b(a), v);
427
- var ua = (v) => isDom() && v.test(navigator.userAgent);
428
- var isDom = () => !!(typeof window !== "undefined");
429
- var isSafari = () => ua(/^((?!chrome|android).)*safari/i);
430
- var supportsPointerEvent = () => isDom() && window.onpointerdown === null;
431
- var isModifiedEvent = (v) => v.ctrlKey || v.altKey || v.metaKey;
432
-
433
413
  // src/number-input.utils.ts
434
414
  var utils = {
435
415
  isValidNumericEvent: (ctx, event) => {
@@ -448,18 +428,15 @@ var utils = {
448
428
  return value.split("").filter((_a = ctx.validateCharacter) != null ? _a : utils.isFloatingPoint).join("");
449
429
  },
450
430
  increment: (ctx, step) => {
451
- let value = increment(ctx.value, step != null ? step : ctx.step);
452
- value = clamp(value, ctx);
453
- return roundToPrecision(value, ctx);
431
+ const value = increment(ctx.value, step != null ? step : ctx.step);
432
+ return formatDecimal(clamp(value, ctx), ctx);
454
433
  },
455
434
  decrement: (ctx, step) => {
456
- let value = decrement(ctx.value, step != null ? step : ctx.step);
457
- value = clamp(value, ctx);
458
- return roundToPrecision(value, ctx);
435
+ const value = decrement(ctx.value, step != null ? step : ctx.step);
436
+ return formatDecimal(clamp(value, ctx), ctx);
459
437
  },
460
438
  clamp: (ctx) => {
461
- let value = clamp(ctx.value, ctx);
462
- return roundToPrecision(value, ctx);
439
+ return formatDecimal(clamp(ctx.value, ctx), ctx);
463
440
  },
464
441
  parse: (ctx, value) => {
465
442
  var _a, _b;
@@ -471,7 +448,7 @@ var utils = {
471
448
  return (_b = (_a = ctx.format) == null ? void 0 : _a.call(ctx, _val)) != null ? _b : _val;
472
449
  },
473
450
  round: (ctx) => {
474
- return roundToPrecision(ctx.value, ctx);
451
+ return formatDecimal(ctx.value, ctx);
475
452
  }
476
453
  };
477
454
 
@@ -492,7 +469,7 @@ function connect(state, send, normalize = normalizeProp) {
492
469
  send({ type: "SET_VALUE", value: value.toString() });
493
470
  },
494
471
  clearValue() {
495
- send({ type: "SET_VALUE", value: "" });
472
+ send("CLEAR_VALUE");
496
473
  },
497
474
  increment() {
498
475
  send("INCREMENT");
@@ -522,6 +499,14 @@ function connect(state, send, normalize = normalizeProp) {
522
499
  id: dom.getLabelId(state.context),
523
500
  htmlFor: dom.getInputId(state.context)
524
501
  }),
502
+ groupProps: normalize.element({
503
+ "data-part": "group",
504
+ role: "group",
505
+ "aria-disabled": isDisabled,
506
+ "data-disabled": dataAttr(isDisabled),
507
+ "data-invalid": dataAttr(isInvalid),
508
+ "aria-invalid": ariaAttr(state.context.invalid)
509
+ }),
525
510
  inputProps: normalize.input({
526
511
  "data-part": "input",
527
512
  name: state.context.name,
@@ -539,7 +524,7 @@ function connect(state, send, normalize = normalizeProp) {
539
524
  autoCorrect: "off",
540
525
  spellCheck: "false",
541
526
  type: "text",
542
- "aria-roledescription": "number field",
527
+ "aria-roledescription": !isIos() ? "number field" : void 0,
543
528
  "aria-valuemin": state.context.min,
544
529
  "aria-valuemax": state.context.max,
545
530
  "aria-valuenow": isNaN(state.context.valueAsNumber) ? void 0 : state.context.valueAsNumber,
@@ -563,7 +548,7 @@ function connect(state, send, normalize = normalizeProp) {
563
548
  if (!utils.isValidNumericEvent(state.context, event)) {
564
549
  event.preventDefault();
565
550
  }
566
- const step = multiply(getEventStep(event), state.context.step);
551
+ const step = getEventStep(event) * state.context.step;
567
552
  const keyMap = {
568
553
  ArrowUp() {
569
554
  send({ type: "ARROW_UP", step });
@@ -587,6 +572,7 @@ function connect(state, send, normalize = normalizeProp) {
587
572
  }),
588
573
  decrementButtonProps: normalize.button({
589
574
  "data-part": "spin-button",
575
+ "data-type": "decrement",
590
576
  id: dom.getDecButtonId(state.context),
591
577
  disabled: isDecrementDisabled,
592
578
  "data-disabled": dataAttr(isDecrementDisabled),
@@ -611,6 +597,7 @@ function connect(state, send, normalize = normalizeProp) {
611
597
  }),
612
598
  incrementButtonProps: normalize.button({
613
599
  "data-part": "spin-button",
600
+ "data-type": "increment",
614
601
  id: dom.getIncButtonId(state.context),
615
602
  disabled: isIncrementDisabled,
616
603
  "data-disabled": dataAttr(isIncrementDisabled),
@@ -642,8 +629,8 @@ function connect(state, send, normalize = normalizeProp) {
642
629
  const evt = getNativeEvent(event);
643
630
  event.preventDefault();
644
631
  const point = getEventPoint(evt);
645
- point.x = point.x - roundToPx(7.5);
646
- point.y = point.y - roundToPx(7.5);
632
+ point.x = point.x - roundToDevicePixel(7.5);
633
+ point.y = point.y - roundToDevicePixel(7.5);
647
634
  send({ type: "PRESS_DOWN_SCRUBBER", point });
648
635
  },
649
636
  style: {
@@ -673,8 +660,6 @@ function machine(ctx = {}) {
673
660
  step: 1,
674
661
  min: Number.MIN_SAFE_INTEGER,
675
662
  max: Number.MAX_SAFE_INTEGER,
676
- precision: 0,
677
- inputSelection: null,
678
663
  scrubberCursorPoint: null,
679
664
  invalid: false
680
665
  }, ctx), {
@@ -704,20 +689,26 @@ function machine(ctx = {}) {
704
689
  value: ["invokeOnChange"],
705
690
  isOutOfRange: ["invokeOnInvalid"]
706
691
  },
707
- entry: ["syncInputValue"],
708
692
  on: {
709
693
  SET_VALUE: {
710
694
  actions: ["setValue", "setHintToSet"]
711
695
  },
712
- INCREMENT: { actions: ["increment"] },
713
- DECREMENT: { actions: ["decrement"] }
696
+ CLEAR_VALUE: {
697
+ actions: ["clearValue"]
698
+ },
699
+ INCREMENT: {
700
+ actions: ["increment"]
701
+ },
702
+ DECREMENT: {
703
+ actions: ["decrement"]
704
+ }
714
705
  },
715
706
  states: {
716
707
  unknown: {
717
708
  on: {
718
709
  SETUP: {
719
710
  target: "idle",
720
- actions: "setupDocument"
711
+ actions: ["setupDocument", "syncInputValue"]
721
712
  }
722
713
  }
723
714
  },
@@ -781,6 +772,7 @@ function machine(ctx = {}) {
781
772
  },
782
773
  "before:spin": {
783
774
  tags: ["focus"],
775
+ activities: "trackButtonDisabled",
784
776
  entry: choose([
785
777
  { guard: "isIncrementHint", actions: "increment" },
786
778
  { guard: "isDecrementHint", actions: "decrement" }
@@ -876,26 +868,23 @@ function machine(ctx = {}) {
876
868
  send("PRESS_UP");
877
869
  });
878
870
  },
879
- attachWheelListener(ctx2) {
880
- const cleanups = [];
881
- cleanups.push(nextTick(() => {
882
- const input = dom.getInputEl(ctx2);
883
- if (!input)
871
+ attachWheelListener(ctx2, _evt, { send }) {
872
+ const input = dom.getInputEl(ctx2);
873
+ if (!input)
874
+ return;
875
+ function onWheel(event) {
876
+ const isInputFocused = dom.getDoc(ctx2).activeElement === input;
877
+ if (!ctx2.allowMouseWheel || !isInputFocused)
884
878
  return;
885
- function onWheel(event) {
886
- const isInputFocused = dom.getDoc(ctx2).activeElement === input;
887
- if (!ctx2.allowMouseWheel || !isInputFocused)
888
- return;
889
- event.preventDefault();
890
- const dir = Math.sign(event.deltaY) * -1;
891
- if (dir === 1)
892
- ctx2.value = utils.increment(ctx2);
893
- else if (dir === -1)
894
- ctx2.value = utils.decrement(ctx2);
879
+ event.preventDefault();
880
+ const dir = Math.sign(event.deltaY) * -1;
881
+ if (dir === 1) {
882
+ send("INCREMENT");
883
+ } else if (dir === -1) {
884
+ send("DECREMENT");
895
885
  }
896
- cleanups.push(addDomEvent(input, "wheel", onWheel, { passive: false }));
897
- }));
898
- return () => cleanups.forEach((c) => c());
886
+ }
887
+ return addDomEvent(input, "wheel", onWheel, { passive: false });
899
888
  },
900
889
  activatePointerLock(ctx2) {
901
890
  if (isSafari() || !supportsPointerEvent())
@@ -910,7 +899,11 @@ function machine(ctx = {}) {
910
899
  const value = dom.getMousementValue(ctx2, event);
911
900
  if (!value.hint)
912
901
  return;
913
- send({ type: "POINTER_MOVE_SCRUBBER", hint: value.hint, point: value.point });
902
+ send({
903
+ type: "POINTER_MOVE_SCRUBBER",
904
+ hint: value.hint,
905
+ point: value.point
906
+ });
914
907
  }
915
908
  function onMouseup() {
916
909
  send("POINTER_UP_SCRUBBER");
@@ -922,6 +915,8 @@ function machine(ctx = {}) {
922
915
  setupDocument: (ctx2, evt) => {
923
916
  if (evt.doc)
924
917
  ctx2.doc = ref(evt.doc);
918
+ if (evt.root)
919
+ ctx2.rootNode = ref(evt.root);
925
920
  ctx2.uid = evt.id;
926
921
  },
927
922
  focusInput(ctx2) {
@@ -940,7 +935,9 @@ function machine(ctx = {}) {
940
935
  ctx2.value = utils.clamp(ctx2);
941
936
  },
942
937
  roundValue(ctx2) {
943
- ctx2.value = utils.round(ctx2);
938
+ if (ctx2.value !== "") {
939
+ ctx2.value = utils.round(ctx2);
940
+ }
944
941
  },
945
942
  setValue(ctx2, evt) {
946
943
  var _a, _b;
@@ -967,14 +964,21 @@ function machine(ctx = {}) {
967
964
  },
968
965
  invokeOnChange(ctx2) {
969
966
  var _a;
970
- (_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, { value: ctx2.value, valueAsNumber: ctx2.valueAsNumber });
967
+ (_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, {
968
+ value: ctx2.value,
969
+ valueAsNumber: ctx2.valueAsNumber
970
+ });
971
971
  },
972
972
  invokeOnInvalid(ctx2) {
973
973
  var _a;
974
974
  if (!ctx2.isOutOfRange)
975
975
  return;
976
976
  const reason = ctx2.valueAsNumber > ctx2.max ? "rangeOverflow" : "rangeUnderflow";
977
- (_a = ctx2.onInvalid) == null ? void 0 : _a.call(ctx2, { reason, value: ctx2.formattedValue, valueAsNumber: ctx2.valueAsNumber });
977
+ (_a = ctx2.onInvalid) == null ? void 0 : _a.call(ctx2, {
978
+ reason,
979
+ value: ctx2.formattedValue,
980
+ valueAsNumber: ctx2.valueAsNumber
981
+ });
978
982
  },
979
983
  syncInputValue(ctx2) {
980
984
  const input = dom.getInputEl(ctx2);
@@ -993,7 +997,8 @@ function machine(ctx = {}) {
993
997
  const cursor = dom.getCursorEl(ctx2);
994
998
  if (!cursor || !ctx2.scrubberCursorPoint)
995
999
  return;
996
- cursor.style.transform = `translate3d(${ctx2.scrubberCursorPoint.x}px, ${ctx2.scrubberCursorPoint.y}px, 0px)`;
1000
+ const { x, y } = ctx2.scrubberCursorPoint;
1001
+ cursor.style.transform = `translate3d(${x}px, ${y}px, 0px)`;
997
1002
  },
998
1003
  addCustomCursor(ctx2) {
999
1004
  if (isSafari() || !supportsPointerEvent())
@@ -1001,11 +1006,10 @@ function machine(ctx = {}) {
1001
1006
  dom.createVirtualCursor(ctx2);
1002
1007
  },
1003
1008
  removeCustomCursor(ctx2) {
1009
+ var _a;
1004
1010
  if (isSafari() || !supportsPointerEvent())
1005
1011
  return;
1006
- const doc = dom.getDoc(ctx2);
1007
- const el = doc.getElementById(dom.getCursorId(ctx2));
1008
- el == null ? void 0 : el.remove();
1012
+ (_a = dom.getCursorEl(ctx2)) == null ? void 0 : _a.remove();
1009
1013
  },
1010
1014
  disableTextSelection(ctx2) {
1011
1015
  const doc = dom.getDoc(ctx2);