@zag-js/number-input 0.1.0 → 0.1.3

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
@@ -35,6 +35,12 @@ function nextTick(fn) {
35
35
  });
36
36
  };
37
37
  }
38
+ function raf(fn) {
39
+ const id = globalThis.requestAnimationFrame(fn);
40
+ return function cleanup() {
41
+ globalThis.cancelAnimationFrame(id);
42
+ };
43
+ }
38
44
  var noop = () => {
39
45
  };
40
46
  var pipe = (...fns) => (v) => fns.reduce((a, b) => b(a), v);
@@ -138,6 +144,30 @@ function observeAttributes(node, attributes, fn) {
138
144
  obs.observe(node, { attributes: true, attributeFilter: attrs });
139
145
  return () => obs.disconnect();
140
146
  }
147
+ function itemById(v, id) {
148
+ return v.find((node) => node.id === id);
149
+ }
150
+ function indexOfId(v, id) {
151
+ const item = itemById(v, id);
152
+ return item ? v.indexOf(item) : -1;
153
+ }
154
+ var getValueText = (item) => {
155
+ var _a, _b;
156
+ return (_b = (_a = item.dataset.valuetext) != null ? _a : item.textContent) != null ? _b : "";
157
+ };
158
+ var match = (valueText, query2) => valueText.toLowerCase().startsWith(query2.toLowerCase());
159
+ var wrap = (v, idx) => {
160
+ return v.map((_, index) => v[(Math.max(idx, 0) + index) % v.length]);
161
+ };
162
+ function findByText(v, text, currentId) {
163
+ const index = currentId ? indexOfId(v, currentId) : -1;
164
+ let items = currentId ? wrap(v, index) : v;
165
+ const isSingleKey = text.length === 1;
166
+ if (isSingleKey) {
167
+ items = items.filter((item) => item.id !== currentId);
168
+ }
169
+ return items.find((item) => match(getValueText(item), text));
170
+ }
141
171
  function addPointerlockChangeListener(doc, fn) {
142
172
  return addDomEvent(doc, "pointerlockchange", fn, false);
143
173
  }
@@ -178,6 +208,34 @@ function requestPointerLock(doc, handlers = {}) {
178
208
  exit();
179
209
  };
180
210
  }
211
+ function findByTypeahead(_items, options) {
212
+ const { state: state2, activeId, key, timeout = 350 } = options;
213
+ const search = state2.keysSoFar + key;
214
+ const isRepeated = search.length > 1 && Array.from(search).every((char) => char === search[0]);
215
+ const query2 = isRepeated ? search[0] : search;
216
+ let items = _items.slice();
217
+ const next = findByText(items, query2, activeId);
218
+ function cleanup() {
219
+ clearTimeout(state2.timer);
220
+ state2.timer = -1;
221
+ }
222
+ function update(value) {
223
+ state2.keysSoFar = value;
224
+ cleanup();
225
+ if (value !== "") {
226
+ state2.timer = +setTimeout(() => {
227
+ update("");
228
+ cleanup();
229
+ }, timeout);
230
+ }
231
+ }
232
+ update(search);
233
+ return next;
234
+ }
235
+ findByTypeahead.defaultOptions = {
236
+ keysSoFar: "",
237
+ timer: -1
238
+ };
181
239
 
182
240
  // ../../utilities/number/dist/index.mjs
183
241
  var __defProp2 = Object.defineProperty;
@@ -200,11 +258,11 @@ var __spreadValues2 = (a, b) => {
200
258
  return a;
201
259
  };
202
260
  var __spreadProps2 = (a, b) => __defProps2(a, __getOwnPropDescs2(b));
203
- var nf = new Intl.NumberFormat("en-US", { style: "decimal" });
261
+ var nf = new Intl.NumberFormat("en-US", { style: "decimal", maximumFractionDigits: 20 });
204
262
  function formatter(n) {
205
263
  return parseFloat(nf.format(n));
206
264
  }
207
- function wrap(num, max) {
265
+ function wrap2(num, max) {
208
266
  return (num % max + max) % max;
209
267
  }
210
268
  function round(v, t2) {
@@ -222,9 +280,16 @@ function roundToPx(num) {
222
280
  function clamp(v, o) {
223
281
  return Math.min(Math.max(valueOf(v), o.min), o.max);
224
282
  }
225
- function countDecimals(v) {
226
- var _a, _b;
227
- return (_b = (_a = nf.formatToParts(v).find((p) => p.type === "fraction")) == null ? void 0 : _a.value.length) != null ? _b : 0;
283
+ function countDecimals(value) {
284
+ if (!Number.isFinite(value))
285
+ return 0;
286
+ let e = 1;
287
+ let p = 0;
288
+ while (Math.round(value * e) / e !== value) {
289
+ e *= 10;
290
+ p += 1;
291
+ }
292
+ return p;
228
293
  }
229
294
  var increment = (v, s) => formatter(valueOf(v) + s);
230
295
  var decrement = (v, s) => formatter(valueOf(v) - s);
@@ -238,9 +303,7 @@ function valueOf(v) {
238
303
  function getMaxPrecision(o) {
239
304
  var _a;
240
305
  const stepPrecision = countDecimals(o.step);
241
- const val = valueOf(o.value);
242
- const valuePrecision = Number.isNaN(val) ? stepPrecision : Math.max(countDecimals(val), stepPrecision);
243
- return Math.max(valuePrecision, (_a = o.precision) != null ? _a : 0);
306
+ return Math.max(stepPrecision, (_a = o.precision) != null ? _a : 0);
244
307
  }
245
308
  function roundToPrecision(v, o) {
246
309
  return round(v, getMaxPrecision(__spreadProps2(__spreadValues2({}, o), { value: v })));
@@ -329,7 +392,7 @@ var dom = {
329
392
  const win = dom.getWin(ctx);
330
393
  const width = win.innerWidth;
331
394
  const half = roundToPx(7.5);
332
- point.x = wrap(point.x + half, width) - half;
395
+ point.x = wrap2(point.x + half, width) - half;
333
396
  return { hint, point };
334
397
  },
335
398
  createVirtualCursor(ctx) {
@@ -359,15 +422,23 @@ var dom = {
359
422
  }
360
423
  };
361
424
 
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
+
362
433
  // src/number-input.utils.ts
363
434
  var utils = {
364
435
  isValidNumericEvent: (ctx, event) => {
365
436
  var _a, _b;
366
437
  if (event.key == null)
367
438
  return true;
368
- const isModifierKey = event.ctrlKey || event.altKey || event.metaKey;
369
- const isSingleCharacterKey = event.key.length === 1;
370
- if (isModifierKey || !isSingleCharacterKey)
439
+ const isModifier = isModifiedEvent(event);
440
+ const isSingleKey = event.key.length === 1;
441
+ if (isModifier || !isSingleKey)
371
442
  return true;
372
443
  return (_b = (_a = ctx.validateCharacter) == null ? void 0 : _a.call(ctx, event.key)) != null ? _b : utils.isFloatingPoint(event.key);
373
444
  },
@@ -436,10 +507,8 @@ function connect(state, send, normalize = normalizeProp) {
436
507
  send({ type: "SET_VALUE", value: state.context.min });
437
508
  },
438
509
  focus() {
439
- nextTick(() => {
440
- var _a;
441
- (_a = dom.getInputEl(state.context)) == null ? void 0 : _a.focus();
442
- });
510
+ var _a;
511
+ (_a = dom.getInputEl(state.context)) == null ? void 0 : _a.focus();
443
512
  },
444
513
  rootProps: normalize.element({
445
514
  id: dom.getRootId(state.context),
@@ -586,15 +655,6 @@ function connect(state, send, normalize = normalizeProp) {
586
655
 
587
656
  // src/number-input.machine.ts
588
657
  import { choose, createMachine, guards, ref } from "@zag-js/core";
589
-
590
- // ../../utilities/core/dist/index.mjs
591
- var pipe2 = (...fns) => (v) => fns.reduce((a, b) => b(a), v);
592
- var ua = (v) => isDom() && v.test(navigator.userAgent);
593
- var isDom = () => !!(typeof window !== "undefined");
594
- var isSafari = () => ua(/^((?!chrome|android).)*safari/i);
595
- var supportsPointerEvent = () => isDom() && window.onpointerdown === null;
596
-
597
- // src/number-input.machine.ts
598
658
  var { not, and } = guards;
599
659
  function machine(ctx = {}) {
600
660
  return createMachine({
@@ -699,7 +759,7 @@ function machine(ctx = {}) {
699
759
  actions: "setToMax"
700
760
  },
701
761
  CHANGE: {
702
- actions: ["setValue", "setSelectionRange", "setHint"]
762
+ actions: ["setValue", "setHint"]
703
763
  },
704
764
  BLUR: [
705
765
  {
@@ -713,6 +773,7 @@ function machine(ctx = {}) {
713
773
  actions: ["clampValue", "clearHint"]
714
774
  },
715
775
  {
776
+ target: "idle",
716
777
  actions: ["roundValue"]
717
778
  }
718
779
  ]
@@ -733,7 +794,7 @@ function machine(ctx = {}) {
733
794
  on: {
734
795
  PRESS_UP: {
735
796
  target: "focused",
736
- actions: ["clearHint", "restoreSelection"]
797
+ actions: "clearHint"
737
798
  }
738
799
  }
739
800
  },
@@ -755,7 +816,7 @@ function machine(ctx = {}) {
755
816
  on: {
756
817
  PRESS_UP: {
757
818
  target: "focused",
758
- actions: ["clearHint", "restoreSelection"]
819
+ actions: "clearHint"
759
820
  }
760
821
  }
761
822
  },
@@ -867,7 +928,7 @@ function machine(ctx = {}) {
867
928
  if (!ctx2.focusInputOnChange)
868
929
  return;
869
930
  const input = dom.getInputEl(ctx2);
870
- nextTick(() => input == null ? void 0 : input.focus());
931
+ raf(() => input == null ? void 0 : input.focus());
871
932
  },
872
933
  increment(ctx2, evt) {
873
934
  ctx2.value = utils.increment(ctx2, evt.step);
@@ -904,20 +965,6 @@ function machine(ctx = {}) {
904
965
  setHintToSet(ctx2) {
905
966
  ctx2.hint = "set";
906
967
  },
907
- setSelectionRange(ctx2, evt) {
908
- ctx2.inputSelection = {
909
- start: evt.target.selectionStart,
910
- end: evt.target.selectionEnd
911
- };
912
- },
913
- restoreSelection(ctx2) {
914
- var _a, _b, _c;
915
- const input = dom.getInputEl(ctx2);
916
- if (!input || !ctx2.inputSelection)
917
- return;
918
- input.selectionStart = (_b = ctx2.inputSelection.start) != null ? _b : (_a = input.value) == null ? void 0 : _a.length;
919
- input.selectionEnd = (_c = ctx2.inputSelection.end) != null ? _c : input.selectionStart;
920
- },
921
968
  invokeOnChange(ctx2) {
922
969
  var _a;
923
970
  (_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, { value: ctx2.value, valueAsNumber: ctx2.valueAsNumber });