@zag-js/pin-input 1.0.2 → 1.1.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.d.mts CHANGED
@@ -122,12 +122,16 @@ interface PinInputSchema {
122
122
  focusedIndex: number;
123
123
  };
124
124
  computed: {
125
+ _value: string[];
125
126
  valueLength: number;
126
127
  filledValueLength: number;
127
128
  isValueComplete: boolean;
128
129
  valueAsString: string;
129
130
  focusedValue: string;
130
131
  };
132
+ refs: {
133
+ count: number;
134
+ };
131
135
  event: EventObject;
132
136
  action: string;
133
137
  effect: string;
package/dist/index.d.ts CHANGED
@@ -122,12 +122,16 @@ interface PinInputSchema {
122
122
  focusedIndex: number;
123
123
  };
124
124
  computed: {
125
+ _value: string[];
125
126
  valueLength: number;
126
127
  filledValueLength: number;
127
128
  isValueComplete: boolean;
128
129
  valueAsString: string;
129
130
  focusedValue: string;
130
131
  };
132
+ refs: {
133
+ count: number;
134
+ };
131
135
  event: EventObject;
132
136
  action: string;
133
137
  effect: string;
package/dist/index.js CHANGED
@@ -233,7 +233,6 @@ var machine = createMachine({
233
233
  sync: true,
234
234
  value: prop("value"),
235
235
  defaultValue: prop("defaultValue"),
236
- isEqual: utils.isEqual,
237
236
  onChange(value) {
238
237
  prop("onValueChange")?.({ value, valueAsString: value.join("") });
239
238
  }
@@ -244,23 +243,25 @@ var machine = createMachine({
244
243
  }))
245
244
  };
246
245
  },
246
+ refs() {
247
+ return {
248
+ count: 0
249
+ };
250
+ },
247
251
  computed: {
248
- valueLength: ({ context }) => context.get("value").length,
249
- filledValueLength: ({ context }) => context.get("value").filter((v) => v?.trim() !== "").length,
250
- isValueComplete: ({ context }) => {
251
- const value = context.get("value");
252
- const filledValueLength = value.filter((v) => v?.trim() !== "").length;
253
- return value.length === filledValueLength;
254
- },
255
- valueAsString: ({ context }) => context.get("value").join(""),
256
- focusedValue: ({ context }) => context.get("value")[context.get("focusedIndex")] || ""
252
+ _value: ({ context, refs }) => fill(context.get("value"), refs.get("count")),
253
+ valueLength: ({ computed }) => computed("_value").length,
254
+ filledValueLength: ({ computed }) => computed("_value").filter((v) => v?.trim() !== "").length,
255
+ isValueComplete: ({ computed }) => computed("valueLength") === computed("filledValueLength"),
256
+ valueAsString: ({ computed }) => computed("_value").join(""),
257
+ focusedValue: ({ computed, context }) => computed("_value")[context.get("focusedIndex")] || ""
257
258
  },
258
259
  entry: choose([
259
260
  {
260
261
  guard: "autoFocus",
261
- actions: ["setupValue", "setFocusIndexToFirst"]
262
+ actions: ["setInputCount", "setFocusIndexToFirst"]
262
263
  },
263
- { actions: ["setupValue"] }
264
+ { actions: ["setInputCount"] }
264
265
  ]),
265
266
  watch({ action, track, context, computed }) {
266
267
  track([() => context.get("focusedIndex")], () => {
@@ -296,18 +297,15 @@ var machine = createMachine({
296
297
  },
297
298
  focused: {
298
299
  on: {
299
- "INPUT.CHANGE": [
300
- {
301
- guard: "isFinalValue",
302
- actions: ["setFocusedValue", "syncInputValue"]
303
- },
304
- {
305
- actions: ["setFocusedValue", "setNextFocusedIndex", "syncInputValue"]
306
- }
307
- ],
300
+ "INPUT.CHANGE": {
301
+ actions: ["setFocusedValue", "syncInputValue", "setNextFocusedIndex"]
302
+ },
308
303
  "INPUT.PASTE": {
309
304
  actions: ["setPastedValue", "setLastValueFocusIndex"]
310
305
  },
306
+ "INPUT.FOCUS": {
307
+ actions: ["setFocusedIndex"]
308
+ },
311
309
  "INPUT.BLUR": {
312
310
  target: "idle",
313
311
  actions: ["clearFocusedIndex"]
@@ -346,7 +344,6 @@ var machine = createMachine({
346
344
  autoFocus: ({ prop }) => !!prop("autoFocus"),
347
345
  hasValue: ({ context }) => context.get("value")[context.get("focusedIndex")] !== "",
348
346
  isValueComplete: ({ computed }) => computed("isValueComplete"),
349
- isFinalValue: ({ context, computed }) => computed("filledValueLength") + 1 === computed("valueLength") && context.get("value").findIndex((v) => v.trim() === "") === context.get("focusedIndex"),
350
347
  hasIndex: ({ event }) => event.index !== void 0
351
348
  },
352
349
  actions: {
@@ -354,13 +351,9 @@ var machine = createMachine({
354
351
  const inputEl = getHiddenInputEl(scope);
355
352
  domQuery.dispatchInputValueEvent(inputEl, { value: computed("valueAsString") });
356
353
  },
357
- setupValue({ context, scope }) {
358
- queueMicrotask(() => {
359
- if (context.get("value").length) return;
360
- const inputEls = getInputEls(scope);
361
- const emptyValues = Array.from({ length: inputEls.length }).fill("");
362
- context.set("value", emptyValues);
363
- });
354
+ setInputCount({ scope, refs }) {
355
+ const inputEls = getInputEls(scope);
356
+ refs.set("count", inputEls.length);
364
357
  },
365
358
  focusInput({ context, scope }) {
366
359
  const focusedIndex = context.get("focusedIndex");
@@ -374,10 +367,10 @@ var machine = createMachine({
374
367
  getInputElAtIndex(scope, focusedIndex)?.select();
375
368
  });
376
369
  },
377
- invokeOnComplete({ context, computed, prop }) {
370
+ invokeOnComplete({ computed, prop }) {
378
371
  if (!computed("isValueComplete")) return;
379
372
  prop("onValueComplete")?.({
380
- value: Array.from(context.get("value")),
373
+ value: computed("_value"),
381
374
  valueAsString: computed("valueAsString")
382
375
  });
383
376
  },
@@ -393,31 +386,30 @@ var machine = createMachine({
393
386
  setFocusedIndex({ context, event }) {
394
387
  context.set("focusedIndex", event.index);
395
388
  },
396
- setValue({ context, event }) {
397
- context.set("value", event.value);
389
+ setValue({ context, event, refs }) {
390
+ const value = fill(event.value, refs.get("count"));
391
+ context.set("value", value);
398
392
  },
399
393
  setFocusedValue({ context, event, computed }) {
400
394
  const focusedValue = computed("focusedValue");
401
- const nextValue = getNextValue(focusedValue, event.value);
402
- context.set("value", (prev) => {
403
- const next = [...prev];
404
- next[context.get("focusedIndex")] = nextValue;
405
- return next;
406
- });
395
+ const focusedIndex = context.get("focusedIndex");
396
+ const value = getNextValue(focusedValue, event.value);
397
+ context.set("value", utils.setValueAtIndex(computed("_value"), focusedIndex, value));
407
398
  },
408
399
  revertInputValue({ context, computed, scope }) {
409
400
  const inputEl = getInputElAtIndex(scope, context.get("focusedIndex"));
410
- domQuery.setElementValue(inputEl, computed("focusedValue"));
401
+ inputEl.value = computed("focusedValue");
411
402
  },
412
403
  syncInputValue({ context, event, scope }) {
413
404
  const value = context.get("value");
414
405
  const inputEl = getInputElAtIndex(scope, event.index);
415
- domQuery.setElementValue(inputEl, value[event.index]);
406
+ inputEl.value = value[event.index];
416
407
  },
417
408
  syncInputElements({ context, scope }) {
418
409
  const inputEls = getInputEls(scope);
410
+ const value = context.get("value");
419
411
  inputEls.forEach((inputEl, index) => {
420
- domQuery.setElementValue(inputEl, context.get("value")[index]);
412
+ inputEl.value = value[index];
421
413
  });
422
414
  },
423
415
  setPastedValue({ context, event, computed }) {
@@ -428,30 +420,22 @@ var machine = createMachine({
428
420
  const startIndex = Math.min(focusedIndex, filledValueLength);
429
421
  const left = startIndex > 0 ? valueAsString.substring(0, focusedIndex) : "";
430
422
  const right = event.value.substring(0, computed("valueLength") - startIndex);
431
- const value = left + right;
432
- context.set("value", value.split(""));
423
+ const value = fill(`${left}${right}`.split(""), computed("valueLength"));
424
+ context.set("value", value);
433
425
  });
434
426
  },
435
427
  setValueAtIndex({ context, event, computed }) {
436
428
  const nextValue = getNextValue(computed("focusedValue"), event.value);
437
- context.set("value", (prev) => {
438
- const next = [...prev];
439
- next[event.index] = nextValue;
440
- return next;
441
- });
429
+ context.set("value", utils.setValueAtIndex(computed("_value"), event.index, nextValue));
442
430
  },
443
- clearValue({ context, computed }) {
444
- const nextValue = Array.from({ length: computed("valueLength") }).fill("");
431
+ clearValue({ context, refs }) {
432
+ const nextValue = Array.from({ length: refs.get("count") }).fill("");
445
433
  context.set("value", nextValue);
446
434
  },
447
- clearFocusedValue({ context }) {
435
+ clearFocusedValue({ context, computed }) {
448
436
  const focusedIndex = context.get("focusedIndex");
449
437
  if (focusedIndex === -1) return;
450
- context.set("value", (prev) => {
451
- const next = [...prev];
452
- next[focusedIndex] = "";
453
- return next;
454
- });
438
+ context.set("value", utils.setValueAtIndex(computed("_value"), focusedIndex, ""));
455
439
  },
456
440
  setFocusIndexToFirst({ context }) {
457
441
  context.set("focusedIndex", 0);
@@ -487,6 +471,9 @@ function getNextValue(current, next) {
487
471
  else if (current[0] === next[1]) nextValue = next[0];
488
472
  return nextValue.split("")[nextValue.length - 1];
489
473
  }
474
+ function fill(value, count) {
475
+ return Array.from({ length: count }).fill("").map((v, i) => value[i] || v);
476
+ }
490
477
  var props = types.createProps()([
491
478
  "autoFocus",
492
479
  "blurOnComplete",
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { createAnatomy } from '@zag-js/anatomy';
2
- import { dispatchInputValueEvent, raf, setElementValue, queryAll, dataAttr, visuallyHiddenStyle, ariaAttr, getBeforeInputValue, getNativeEvent, isComposingEvent, isModifierKey, getEventKey } from '@zag-js/dom-query';
3
- import { isEqual, createSplitProps, invariant } from '@zag-js/utils';
2
+ import { dispatchInputValueEvent, raf, queryAll, dataAttr, visuallyHiddenStyle, ariaAttr, getBeforeInputValue, getNativeEvent, isComposingEvent, isModifierKey, getEventKey } from '@zag-js/dom-query';
3
+ import { setValueAtIndex, createSplitProps, invariant } from '@zag-js/utils';
4
4
  import { setup } from '@zag-js/core';
5
5
  import { createProps } from '@zag-js/types';
6
6
 
@@ -231,7 +231,6 @@ var machine = createMachine({
231
231
  sync: true,
232
232
  value: prop("value"),
233
233
  defaultValue: prop("defaultValue"),
234
- isEqual,
235
234
  onChange(value) {
236
235
  prop("onValueChange")?.({ value, valueAsString: value.join("") });
237
236
  }
@@ -242,23 +241,25 @@ var machine = createMachine({
242
241
  }))
243
242
  };
244
243
  },
244
+ refs() {
245
+ return {
246
+ count: 0
247
+ };
248
+ },
245
249
  computed: {
246
- valueLength: ({ context }) => context.get("value").length,
247
- filledValueLength: ({ context }) => context.get("value").filter((v) => v?.trim() !== "").length,
248
- isValueComplete: ({ context }) => {
249
- const value = context.get("value");
250
- const filledValueLength = value.filter((v) => v?.trim() !== "").length;
251
- return value.length === filledValueLength;
252
- },
253
- valueAsString: ({ context }) => context.get("value").join(""),
254
- focusedValue: ({ context }) => context.get("value")[context.get("focusedIndex")] || ""
250
+ _value: ({ context, refs }) => fill(context.get("value"), refs.get("count")),
251
+ valueLength: ({ computed }) => computed("_value").length,
252
+ filledValueLength: ({ computed }) => computed("_value").filter((v) => v?.trim() !== "").length,
253
+ isValueComplete: ({ computed }) => computed("valueLength") === computed("filledValueLength"),
254
+ valueAsString: ({ computed }) => computed("_value").join(""),
255
+ focusedValue: ({ computed, context }) => computed("_value")[context.get("focusedIndex")] || ""
255
256
  },
256
257
  entry: choose([
257
258
  {
258
259
  guard: "autoFocus",
259
- actions: ["setupValue", "setFocusIndexToFirst"]
260
+ actions: ["setInputCount", "setFocusIndexToFirst"]
260
261
  },
261
- { actions: ["setupValue"] }
262
+ { actions: ["setInputCount"] }
262
263
  ]),
263
264
  watch({ action, track, context, computed }) {
264
265
  track([() => context.get("focusedIndex")], () => {
@@ -294,18 +295,15 @@ var machine = createMachine({
294
295
  },
295
296
  focused: {
296
297
  on: {
297
- "INPUT.CHANGE": [
298
- {
299
- guard: "isFinalValue",
300
- actions: ["setFocusedValue", "syncInputValue"]
301
- },
302
- {
303
- actions: ["setFocusedValue", "setNextFocusedIndex", "syncInputValue"]
304
- }
305
- ],
298
+ "INPUT.CHANGE": {
299
+ actions: ["setFocusedValue", "syncInputValue", "setNextFocusedIndex"]
300
+ },
306
301
  "INPUT.PASTE": {
307
302
  actions: ["setPastedValue", "setLastValueFocusIndex"]
308
303
  },
304
+ "INPUT.FOCUS": {
305
+ actions: ["setFocusedIndex"]
306
+ },
309
307
  "INPUT.BLUR": {
310
308
  target: "idle",
311
309
  actions: ["clearFocusedIndex"]
@@ -344,7 +342,6 @@ var machine = createMachine({
344
342
  autoFocus: ({ prop }) => !!prop("autoFocus"),
345
343
  hasValue: ({ context }) => context.get("value")[context.get("focusedIndex")] !== "",
346
344
  isValueComplete: ({ computed }) => computed("isValueComplete"),
347
- isFinalValue: ({ context, computed }) => computed("filledValueLength") + 1 === computed("valueLength") && context.get("value").findIndex((v) => v.trim() === "") === context.get("focusedIndex"),
348
345
  hasIndex: ({ event }) => event.index !== void 0
349
346
  },
350
347
  actions: {
@@ -352,13 +349,9 @@ var machine = createMachine({
352
349
  const inputEl = getHiddenInputEl(scope);
353
350
  dispatchInputValueEvent(inputEl, { value: computed("valueAsString") });
354
351
  },
355
- setupValue({ context, scope }) {
356
- queueMicrotask(() => {
357
- if (context.get("value").length) return;
358
- const inputEls = getInputEls(scope);
359
- const emptyValues = Array.from({ length: inputEls.length }).fill("");
360
- context.set("value", emptyValues);
361
- });
352
+ setInputCount({ scope, refs }) {
353
+ const inputEls = getInputEls(scope);
354
+ refs.set("count", inputEls.length);
362
355
  },
363
356
  focusInput({ context, scope }) {
364
357
  const focusedIndex = context.get("focusedIndex");
@@ -372,10 +365,10 @@ var machine = createMachine({
372
365
  getInputElAtIndex(scope, focusedIndex)?.select();
373
366
  });
374
367
  },
375
- invokeOnComplete({ context, computed, prop }) {
368
+ invokeOnComplete({ computed, prop }) {
376
369
  if (!computed("isValueComplete")) return;
377
370
  prop("onValueComplete")?.({
378
- value: Array.from(context.get("value")),
371
+ value: computed("_value"),
379
372
  valueAsString: computed("valueAsString")
380
373
  });
381
374
  },
@@ -391,31 +384,30 @@ var machine = createMachine({
391
384
  setFocusedIndex({ context, event }) {
392
385
  context.set("focusedIndex", event.index);
393
386
  },
394
- setValue({ context, event }) {
395
- context.set("value", event.value);
387
+ setValue({ context, event, refs }) {
388
+ const value = fill(event.value, refs.get("count"));
389
+ context.set("value", value);
396
390
  },
397
391
  setFocusedValue({ context, event, computed }) {
398
392
  const focusedValue = computed("focusedValue");
399
- const nextValue = getNextValue(focusedValue, event.value);
400
- context.set("value", (prev) => {
401
- const next = [...prev];
402
- next[context.get("focusedIndex")] = nextValue;
403
- return next;
404
- });
393
+ const focusedIndex = context.get("focusedIndex");
394
+ const value = getNextValue(focusedValue, event.value);
395
+ context.set("value", setValueAtIndex(computed("_value"), focusedIndex, value));
405
396
  },
406
397
  revertInputValue({ context, computed, scope }) {
407
398
  const inputEl = getInputElAtIndex(scope, context.get("focusedIndex"));
408
- setElementValue(inputEl, computed("focusedValue"));
399
+ inputEl.value = computed("focusedValue");
409
400
  },
410
401
  syncInputValue({ context, event, scope }) {
411
402
  const value = context.get("value");
412
403
  const inputEl = getInputElAtIndex(scope, event.index);
413
- setElementValue(inputEl, value[event.index]);
404
+ inputEl.value = value[event.index];
414
405
  },
415
406
  syncInputElements({ context, scope }) {
416
407
  const inputEls = getInputEls(scope);
408
+ const value = context.get("value");
417
409
  inputEls.forEach((inputEl, index) => {
418
- setElementValue(inputEl, context.get("value")[index]);
410
+ inputEl.value = value[index];
419
411
  });
420
412
  },
421
413
  setPastedValue({ context, event, computed }) {
@@ -426,30 +418,22 @@ var machine = createMachine({
426
418
  const startIndex = Math.min(focusedIndex, filledValueLength);
427
419
  const left = startIndex > 0 ? valueAsString.substring(0, focusedIndex) : "";
428
420
  const right = event.value.substring(0, computed("valueLength") - startIndex);
429
- const value = left + right;
430
- context.set("value", value.split(""));
421
+ const value = fill(`${left}${right}`.split(""), computed("valueLength"));
422
+ context.set("value", value);
431
423
  });
432
424
  },
433
425
  setValueAtIndex({ context, event, computed }) {
434
426
  const nextValue = getNextValue(computed("focusedValue"), event.value);
435
- context.set("value", (prev) => {
436
- const next = [...prev];
437
- next[event.index] = nextValue;
438
- return next;
439
- });
427
+ context.set("value", setValueAtIndex(computed("_value"), event.index, nextValue));
440
428
  },
441
- clearValue({ context, computed }) {
442
- const nextValue = Array.from({ length: computed("valueLength") }).fill("");
429
+ clearValue({ context, refs }) {
430
+ const nextValue = Array.from({ length: refs.get("count") }).fill("");
443
431
  context.set("value", nextValue);
444
432
  },
445
- clearFocusedValue({ context }) {
433
+ clearFocusedValue({ context, computed }) {
446
434
  const focusedIndex = context.get("focusedIndex");
447
435
  if (focusedIndex === -1) return;
448
- context.set("value", (prev) => {
449
- const next = [...prev];
450
- next[focusedIndex] = "";
451
- return next;
452
- });
436
+ context.set("value", setValueAtIndex(computed("_value"), focusedIndex, ""));
453
437
  },
454
438
  setFocusIndexToFirst({ context }) {
455
439
  context.set("focusedIndex", 0);
@@ -485,6 +469,9 @@ function getNextValue(current, next) {
485
469
  else if (current[0] === next[1]) nextValue = next[0];
486
470
  return nextValue.split("")[nextValue.length - 1];
487
471
  }
472
+ function fill(value, count) {
473
+ return Array.from({ length: count }).fill("").map((v, i) => value[i] || v);
474
+ }
488
475
  var props = createProps()([
489
476
  "autoFocus",
490
477
  "blurOnComplete",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zag-js/pin-input",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "Core logic for the pin-input widget implemented as a state machine",
5
5
  "keywords": [
6
6
  "js",
@@ -26,11 +26,11 @@
26
26
  "url": "https://github.com/chakra-ui/zag/issues"
27
27
  },
28
28
  "dependencies": {
29
- "@zag-js/anatomy": "1.0.2",
30
- "@zag-js/dom-query": "1.0.2",
31
- "@zag-js/utils": "1.0.2",
32
- "@zag-js/core": "1.0.2",
33
- "@zag-js/types": "1.0.2"
29
+ "@zag-js/anatomy": "1.1.0",
30
+ "@zag-js/utils": "1.1.0",
31
+ "@zag-js/dom-query": "1.1.0",
32
+ "@zag-js/core": "1.1.0",
33
+ "@zag-js/types": "1.1.0"
34
34
  },
35
35
  "devDependencies": {
36
36
  "clean-package": "2.2.0"