@zag-js/pin-input 0.1.11 → 0.1.12

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.
Files changed (3) hide show
  1. package/dist/index.js +237 -230
  2. package/dist/index.mjs +237 -230
  3. package/package.json +3 -2
package/dist/index.js CHANGED
@@ -45,9 +45,6 @@ function getDocument(el) {
45
45
  return el;
46
46
  return (el == null ? void 0 : el.ownerDocument) ?? document;
47
47
  }
48
- function getWindow(el) {
49
- return (el == null ? void 0 : el.ownerDocument.defaultView) ?? window;
50
- }
51
48
  function defineDomHelpers(helpers) {
52
49
  const dom2 = {
53
50
  getRootNode: (ctx) => {
@@ -68,23 +65,6 @@ function getNativeEvent(e) {
68
65
  return e.nativeEvent ?? e;
69
66
  }
70
67
  var isModifiedEvent = (v) => v.ctrlKey || v.altKey || v.metaKey;
71
- function getDescriptor(el, options) {
72
- const { type, property } = options;
73
- const proto = getWindow(el)[type].prototype;
74
- return Object.getOwnPropertyDescriptor(proto, property) ?? {};
75
- }
76
- function dispatchInputValueEvent(el, value) {
77
- var _a;
78
- if (!el)
79
- return;
80
- const win = getWindow(el);
81
- if (!(el instanceof win.HTMLInputElement))
82
- return;
83
- const desc = getDescriptor(el, { type: "HTMLInputElement", property: "value" });
84
- (_a = desc.set) == null ? void 0 : _a.call(el, value);
85
- const event = new win.Event("input", { bubbles: true });
86
- el.dispatchEvent(event);
87
- }
88
68
  var rtlKeyMap = {
89
69
  ArrowLeft: "ArrowRight",
90
70
  ArrowRight: "ArrowLeft",
@@ -285,237 +265,264 @@ function connect(state, send, normalize) {
285
265
 
286
266
  // src/pin-input.machine.ts
287
267
  var import_core = require("@zag-js/core");
268
+
269
+ // ../../utilities/form-utils/dist/index.mjs
270
+ function getWindow(el) {
271
+ return (el == null ? void 0 : el.ownerDocument.defaultView) ?? window;
272
+ }
273
+ function getDescriptor(el, options) {
274
+ const { type, property } = options;
275
+ const proto = getWindow(el)[type].prototype;
276
+ return Object.getOwnPropertyDescriptor(proto, property) ?? {};
277
+ }
278
+ function dispatchInputValueEvent(el, value) {
279
+ var _a;
280
+ if (!el)
281
+ return;
282
+ const win = getWindow(el);
283
+ if (!(el instanceof win.HTMLInputElement))
284
+ return;
285
+ const desc = getDescriptor(el, { type: "HTMLInputElement", property: "value" });
286
+ (_a = desc.set) == null ? void 0 : _a.call(el, value);
287
+ const event = new win.Event("input", { bubbles: true });
288
+ el.dispatchEvent(event);
289
+ }
290
+
291
+ // src/pin-input.machine.ts
288
292
  var { and, not } = import_core.guards;
289
293
  function machine(ctx) {
290
- return (0, import_core.createMachine)({
291
- id: "pin-input",
292
- initial: "unknown",
293
- context: {
294
- value: [],
295
- focusedIndex: -1,
296
- placeholder: "\u25CB",
297
- otp: false,
298
- type: "numeric",
299
- ...ctx,
300
- messages: {
301
- inputLabel: (index, length) => `pin code ${index + 1} of ${length}`,
302
- ...ctx.messages
303
- }
304
- },
305
- computed: {
306
- valueLength: (ctx2) => ctx2.value.length,
307
- filledValueLength: (ctx2) => ctx2.value.filter((v) => (v == null ? void 0 : v.trim()) !== "").length,
308
- isValueComplete: (ctx2) => ctx2.valueLength === ctx2.filledValueLength,
309
- valueAsString: (ctx2) => ctx2.value.join("")
310
- },
311
- watch: {
312
- focusedIndex: "focusInput",
313
- value: "invokeOnChange",
314
- isValueComplete: ["invokeOnComplete", "blurFocusedInputIfNeeded"]
315
- },
316
- on: {
317
- SET_VALUE: [
318
- {
319
- guard: "hasIndex",
320
- actions: "setValueAtIndex"
321
- },
322
- { actions: "setValue" }
323
- ],
324
- CLEAR_VALUE: [
325
- {
326
- guard: "isDisabled",
327
- actions: "clearValue"
328
- },
329
- {
330
- actions: ["clearValue", "setFocusIndexToFirst"]
331
- }
332
- ]
333
- },
334
- states: {
335
- unknown: {
336
- on: {
337
- SETUP: [
338
- {
339
- guard: "autoFocus",
340
- target: "focused",
341
- actions: ["setupValue", "setFocusIndexToFirst"]
342
- },
343
- {
344
- target: "idle",
345
- actions: "setupValue"
346
- }
347
- ]
294
+ return (0, import_core.createMachine)(
295
+ {
296
+ id: "pin-input",
297
+ initial: "unknown",
298
+ context: {
299
+ value: [],
300
+ focusedIndex: -1,
301
+ placeholder: "\u25CB",
302
+ otp: false,
303
+ type: "numeric",
304
+ ...ctx,
305
+ messages: {
306
+ inputLabel: (index, length) => `pin code ${index + 1} of ${length}`,
307
+ ...ctx.messages
348
308
  }
349
309
  },
350
- idle: {
351
- on: {
352
- FOCUS: {
353
- target: "focused",
354
- actions: "setFocusedIndex"
355
- }
356
- }
310
+ computed: {
311
+ valueLength: (ctx2) => ctx2.value.length,
312
+ filledValueLength: (ctx2) => ctx2.value.filter((v) => (v == null ? void 0 : v.trim()) !== "").length,
313
+ isValueComplete: (ctx2) => ctx2.valueLength === ctx2.filledValueLength,
314
+ valueAsString: (ctx2) => ctx2.value.join("")
357
315
  },
358
- focused: {
359
- on: {
360
- INPUT: [
361
- {
362
- guard: and("isFinalValue", "isValidValue"),
363
- actions: "setFocusedValue"
364
- },
365
- {
366
- guard: "isValidValue",
367
- actions: ["setFocusedValue", "setNextFocusedIndex"]
368
- }
369
- ],
370
- PASTE: {
371
- guard: "isValidValue",
372
- actions: ["setPastedValue", "setLastValueFocusIndex"]
373
- },
374
- BLUR: {
375
- target: "idle",
376
- actions: "clearFocusedIndex"
377
- },
378
- DELETE: {
379
- guard: "hasValue",
380
- actions: "clearFocusedValue"
381
- },
382
- ARROW_LEFT: {
383
- actions: "setPrevFocusedIndex"
316
+ watch: {
317
+ focusedIndex: "focusInput",
318
+ value: "invokeOnChange",
319
+ isValueComplete: ["invokeOnComplete", "blurFocusedInputIfNeeded"]
320
+ },
321
+ on: {
322
+ SET_VALUE: [
323
+ {
324
+ guard: "hasIndex",
325
+ actions: "setValueAtIndex"
384
326
  },
385
- ARROW_RIGHT: {
386
- actions: "setNextFocusedIndex"
327
+ { actions: "setValue" }
328
+ ],
329
+ CLEAR_VALUE: [
330
+ {
331
+ guard: "isDisabled",
332
+ actions: "clearValue"
387
333
  },
388
- BACKSPACE: [
389
- {
334
+ {
335
+ actions: ["clearValue", "setFocusIndexToFirst"]
336
+ }
337
+ ]
338
+ },
339
+ states: {
340
+ unknown: {
341
+ on: {
342
+ SETUP: [
343
+ {
344
+ guard: "autoFocus",
345
+ target: "focused",
346
+ actions: ["setupValue", "setFocusIndexToFirst"]
347
+ },
348
+ {
349
+ target: "idle",
350
+ actions: "setupValue"
351
+ }
352
+ ]
353
+ }
354
+ },
355
+ idle: {
356
+ on: {
357
+ FOCUS: {
358
+ target: "focused",
359
+ actions: "setFocusedIndex"
360
+ }
361
+ }
362
+ },
363
+ focused: {
364
+ on: {
365
+ INPUT: [
366
+ {
367
+ guard: and("isFinalValue", "isValidValue"),
368
+ actions: "setFocusedValue"
369
+ },
370
+ {
371
+ guard: "isValidValue",
372
+ actions: ["setFocusedValue", "setNextFocusedIndex"]
373
+ }
374
+ ],
375
+ PASTE: {
376
+ guard: "isValidValue",
377
+ actions: ["setPastedValue", "setLastValueFocusIndex"]
378
+ },
379
+ BLUR: {
380
+ target: "idle",
381
+ actions: "clearFocusedIndex"
382
+ },
383
+ DELETE: {
390
384
  guard: "hasValue",
391
385
  actions: "clearFocusedValue"
392
386
  },
393
- {
394
- actions: ["setPrevFocusedIndex", "clearFocusedValue"]
387
+ ARROW_LEFT: {
388
+ actions: "setPrevFocusedIndex"
389
+ },
390
+ ARROW_RIGHT: {
391
+ actions: "setNextFocusedIndex"
392
+ },
393
+ BACKSPACE: [
394
+ {
395
+ guard: "hasValue",
396
+ actions: "clearFocusedValue"
397
+ },
398
+ {
399
+ actions: ["setPrevFocusedIndex", "clearFocusedValue"]
400
+ }
401
+ ],
402
+ ENTER: {
403
+ guard: "isValueComplete",
404
+ actions: "requestFormSubmit"
405
+ },
406
+ KEY_DOWN: {
407
+ guard: not("isValidValue"),
408
+ actions: ["preventDefault", "invokeOnInvalid"]
395
409
  }
396
- ],
397
- ENTER: {
398
- guard: "isValueComplete",
399
- actions: "requestFormSubmit"
400
- },
401
- KEY_DOWN: {
402
- guard: not("isValidValue"),
403
- actions: ["preventDefault", "invokeOnInvalid"]
404
410
  }
405
411
  }
406
412
  }
407
- }
408
- }, {
409
- guards: {
410
- autoFocus: (ctx2) => !!ctx2.autoFocus,
411
- isValueEmpty: (_ctx, evt) => evt.value === "",
412
- hasValue: (ctx2) => ctx2.value[ctx2.focusedIndex] !== "",
413
- isValueComplete: (ctx2) => ctx2.isValueComplete,
414
- isValidValue: (ctx2, evt) => {
415
- if (!ctx2.pattern)
416
- return isValidType(evt.value, ctx2.type);
417
- const regex = new RegExp(ctx2.pattern, "g");
418
- return regex.test(evt.value);
419
- },
420
- isFinalValue: (ctx2) => {
421
- return ctx2.filledValueLength + 1 === ctx2.valueLength && ctx2.value.findIndex((v) => v.trim() === "") === ctx2.focusedIndex;
422
- },
423
- isLastInputFocused: (ctx2) => ctx2.focusedIndex === ctx2.valueLength - 1,
424
- hasIndex: (_ctx, evt) => evt.index !== void 0,
425
- isDisabled: (ctx2) => !!ctx2.disabled
426
413
  },
427
- actions: {
428
- setupValue: (ctx2) => {
429
- const inputs = dom.getElements(ctx2);
430
- const empty = Array.from({ length: inputs.length }).map(() => "");
431
- ctx2.value = Object.assign(empty, ctx2.value);
414
+ {
415
+ guards: {
416
+ autoFocus: (ctx2) => !!ctx2.autoFocus,
417
+ isValueEmpty: (_ctx, evt) => evt.value === "",
418
+ hasValue: (ctx2) => ctx2.value[ctx2.focusedIndex] !== "",
419
+ isValueComplete: (ctx2) => ctx2.isValueComplete,
420
+ isValidValue: (ctx2, evt) => {
421
+ if (!ctx2.pattern)
422
+ return isValidType(evt.value, ctx2.type);
423
+ const regex = new RegExp(ctx2.pattern, "g");
424
+ return regex.test(evt.value);
425
+ },
426
+ isFinalValue: (ctx2) => {
427
+ return ctx2.filledValueLength + 1 === ctx2.valueLength && ctx2.value.findIndex((v) => v.trim() === "") === ctx2.focusedIndex;
428
+ },
429
+ isLastInputFocused: (ctx2) => ctx2.focusedIndex === ctx2.valueLength - 1,
430
+ hasIndex: (_ctx, evt) => evt.index !== void 0,
431
+ isDisabled: (ctx2) => !!ctx2.disabled
432
432
  },
433
- focusInput: (ctx2) => {
434
- raf(() => {
433
+ actions: {
434
+ setupValue: (ctx2) => {
435
+ const inputs = dom.getElements(ctx2);
436
+ const empty = Array.from({ length: inputs.length }).map(() => "");
437
+ ctx2.value = Object.assign(empty, ctx2.value);
438
+ },
439
+ focusInput: (ctx2) => {
440
+ raf(() => {
441
+ var _a;
442
+ if (ctx2.focusedIndex === -1)
443
+ return;
444
+ (_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.focus();
445
+ });
446
+ },
447
+ invokeOnComplete: (ctx2) => {
435
448
  var _a;
436
- if (ctx2.focusedIndex === -1)
449
+ if (!ctx2.isValueComplete)
437
450
  return;
438
- (_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.focus();
439
- });
440
- },
441
- invokeOnComplete: (ctx2) => {
442
- var _a;
443
- if (!ctx2.isValueComplete)
444
- return;
445
- (_a = ctx2.onComplete) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value), valueAsString: ctx2.valueAsString });
446
- },
447
- invokeOnChange: (ctx2, evt) => {
448
- var _a;
449
- if (evt.type === "SETUP")
450
- return;
451
- (_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value) });
452
- dispatchInputValueEvent(dom.getHiddenInputEl(ctx2), ctx2.valueAsString);
453
- },
454
- invokeOnInvalid: (ctx2, evt) => {
455
- var _a;
456
- (_a = ctx2.onInvalid) == null ? void 0 : _a.call(ctx2, { value: evt.value, index: ctx2.focusedIndex });
457
- },
458
- clearFocusedIndex: (ctx2) => {
459
- ctx2.focusedIndex = -1;
460
- },
461
- setValue: (ctx2, evt) => {
462
- assign(ctx2, evt.value);
463
- },
464
- setFocusedIndex: (ctx2, evt) => {
465
- ctx2.focusedIndex = evt.index;
466
- },
467
- setFocusedValue: (ctx2, evt) => {
468
- ctx2.value[ctx2.focusedIndex] = lastChar(evt.value);
469
- },
470
- setPastedValue(ctx2, evt) {
471
- raf(() => {
472
- const value = evt.value.substring(0, ctx2.valueLength);
473
- assign(ctx2, value.split("").filter(Boolean));
474
- });
475
- },
476
- setValueAtIndex: (ctx2, evt) => {
477
- ctx2.value[evt.index] = lastChar(evt.value);
478
- },
479
- clearValue: (ctx2) => {
480
- assign(ctx2, "");
481
- },
482
- clearFocusedValue: (ctx2) => {
483
- ctx2.value[ctx2.focusedIndex] = "";
484
- },
485
- setFocusIndexToFirst: (ctx2) => {
486
- ctx2.focusedIndex = 0;
487
- },
488
- setNextFocusedIndex: (ctx2) => {
489
- ctx2.focusedIndex = Math.min(ctx2.focusedIndex + 1, ctx2.valueLength - 1);
490
- },
491
- setPrevFocusedIndex: (ctx2) => {
492
- ctx2.focusedIndex = Math.max(ctx2.focusedIndex - 1, 0);
493
- },
494
- setLastValueFocusIndex: (ctx2) => {
495
- raf(() => {
496
- ctx2.focusedIndex = Math.min(ctx2.filledValueLength, ctx2.valueLength - 1);
497
- });
498
- },
499
- preventDefault(_, evt) {
500
- evt.preventDefault();
501
- },
502
- blurFocusedInputIfNeeded(ctx2) {
503
- if (!ctx2.blurOnComplete)
504
- return;
505
- raf(() => {
451
+ (_a = ctx2.onComplete) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value), valueAsString: ctx2.valueAsString });
452
+ },
453
+ invokeOnChange: (ctx2, evt) => {
506
454
  var _a;
507
- (_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.blur();
508
- });
509
- },
510
- requestFormSubmit(ctx2) {
511
- var _a;
512
- if (!ctx2.name)
513
- return;
514
- const input = dom.getHiddenInputEl(ctx2);
515
- (_a = input == null ? void 0 : input.form) == null ? void 0 : _a.requestSubmit();
455
+ if (evt.type === "SETUP")
456
+ return;
457
+ (_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value) });
458
+ dispatchInputValueEvent(dom.getHiddenInputEl(ctx2), ctx2.valueAsString);
459
+ },
460
+ invokeOnInvalid: (ctx2, evt) => {
461
+ var _a;
462
+ (_a = ctx2.onInvalid) == null ? void 0 : _a.call(ctx2, { value: evt.value, index: ctx2.focusedIndex });
463
+ },
464
+ clearFocusedIndex: (ctx2) => {
465
+ ctx2.focusedIndex = -1;
466
+ },
467
+ setValue: (ctx2, evt) => {
468
+ assign(ctx2, evt.value);
469
+ },
470
+ setFocusedIndex: (ctx2, evt) => {
471
+ ctx2.focusedIndex = evt.index;
472
+ },
473
+ setFocusedValue: (ctx2, evt) => {
474
+ ctx2.value[ctx2.focusedIndex] = lastChar(evt.value);
475
+ },
476
+ setPastedValue(ctx2, evt) {
477
+ raf(() => {
478
+ const value = evt.value.substring(0, ctx2.valueLength);
479
+ assign(ctx2, value.split("").filter(Boolean));
480
+ });
481
+ },
482
+ setValueAtIndex: (ctx2, evt) => {
483
+ ctx2.value[evt.index] = lastChar(evt.value);
484
+ },
485
+ clearValue: (ctx2) => {
486
+ assign(ctx2, "");
487
+ },
488
+ clearFocusedValue: (ctx2) => {
489
+ ctx2.value[ctx2.focusedIndex] = "";
490
+ },
491
+ setFocusIndexToFirst: (ctx2) => {
492
+ ctx2.focusedIndex = 0;
493
+ },
494
+ setNextFocusedIndex: (ctx2) => {
495
+ ctx2.focusedIndex = Math.min(ctx2.focusedIndex + 1, ctx2.valueLength - 1);
496
+ },
497
+ setPrevFocusedIndex: (ctx2) => {
498
+ ctx2.focusedIndex = Math.max(ctx2.focusedIndex - 1, 0);
499
+ },
500
+ setLastValueFocusIndex: (ctx2) => {
501
+ raf(() => {
502
+ ctx2.focusedIndex = Math.min(ctx2.filledValueLength, ctx2.valueLength - 1);
503
+ });
504
+ },
505
+ preventDefault(_, evt) {
506
+ evt.preventDefault();
507
+ },
508
+ blurFocusedInputIfNeeded(ctx2) {
509
+ if (!ctx2.blurOnComplete)
510
+ return;
511
+ raf(() => {
512
+ var _a;
513
+ (_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.blur();
514
+ });
515
+ },
516
+ requestFormSubmit(ctx2) {
517
+ var _a;
518
+ if (!ctx2.name)
519
+ return;
520
+ const input = dom.getHiddenInputEl(ctx2);
521
+ (_a = input == null ? void 0 : input.form) == null ? void 0 : _a.requestSubmit();
522
+ }
516
523
  }
517
524
  }
518
- });
525
+ );
519
526
  }
520
527
  var REGEX = {
521
528
  numeric: /^[0-9]+$/,
package/dist/index.mjs CHANGED
@@ -18,9 +18,6 @@ function getDocument(el) {
18
18
  return el;
19
19
  return (el == null ? void 0 : el.ownerDocument) ?? document;
20
20
  }
21
- function getWindow(el) {
22
- return (el == null ? void 0 : el.ownerDocument.defaultView) ?? window;
23
- }
24
21
  function defineDomHelpers(helpers) {
25
22
  const dom2 = {
26
23
  getRootNode: (ctx) => {
@@ -41,23 +38,6 @@ function getNativeEvent(e) {
41
38
  return e.nativeEvent ?? e;
42
39
  }
43
40
  var isModifiedEvent = (v) => v.ctrlKey || v.altKey || v.metaKey;
44
- function getDescriptor(el, options) {
45
- const { type, property } = options;
46
- const proto = getWindow(el)[type].prototype;
47
- return Object.getOwnPropertyDescriptor(proto, property) ?? {};
48
- }
49
- function dispatchInputValueEvent(el, value) {
50
- var _a;
51
- if (!el)
52
- return;
53
- const win = getWindow(el);
54
- if (!(el instanceof win.HTMLInputElement))
55
- return;
56
- const desc = getDescriptor(el, { type: "HTMLInputElement", property: "value" });
57
- (_a = desc.set) == null ? void 0 : _a.call(el, value);
58
- const event = new win.Event("input", { bubbles: true });
59
- el.dispatchEvent(event);
60
- }
61
41
  var rtlKeyMap = {
62
42
  ArrowLeft: "ArrowRight",
63
43
  ArrowRight: "ArrowLeft",
@@ -258,237 +238,264 @@ function connect(state, send, normalize) {
258
238
 
259
239
  // src/pin-input.machine.ts
260
240
  import { createMachine, guards } from "@zag-js/core";
241
+
242
+ // ../../utilities/form-utils/dist/index.mjs
243
+ function getWindow(el) {
244
+ return (el == null ? void 0 : el.ownerDocument.defaultView) ?? window;
245
+ }
246
+ function getDescriptor(el, options) {
247
+ const { type, property } = options;
248
+ const proto = getWindow(el)[type].prototype;
249
+ return Object.getOwnPropertyDescriptor(proto, property) ?? {};
250
+ }
251
+ function dispatchInputValueEvent(el, value) {
252
+ var _a;
253
+ if (!el)
254
+ return;
255
+ const win = getWindow(el);
256
+ if (!(el instanceof win.HTMLInputElement))
257
+ return;
258
+ const desc = getDescriptor(el, { type: "HTMLInputElement", property: "value" });
259
+ (_a = desc.set) == null ? void 0 : _a.call(el, value);
260
+ const event = new win.Event("input", { bubbles: true });
261
+ el.dispatchEvent(event);
262
+ }
263
+
264
+ // src/pin-input.machine.ts
261
265
  var { and, not } = guards;
262
266
  function machine(ctx) {
263
- return createMachine({
264
- id: "pin-input",
265
- initial: "unknown",
266
- context: {
267
- value: [],
268
- focusedIndex: -1,
269
- placeholder: "\u25CB",
270
- otp: false,
271
- type: "numeric",
272
- ...ctx,
273
- messages: {
274
- inputLabel: (index, length) => `pin code ${index + 1} of ${length}`,
275
- ...ctx.messages
276
- }
277
- },
278
- computed: {
279
- valueLength: (ctx2) => ctx2.value.length,
280
- filledValueLength: (ctx2) => ctx2.value.filter((v) => (v == null ? void 0 : v.trim()) !== "").length,
281
- isValueComplete: (ctx2) => ctx2.valueLength === ctx2.filledValueLength,
282
- valueAsString: (ctx2) => ctx2.value.join("")
283
- },
284
- watch: {
285
- focusedIndex: "focusInput",
286
- value: "invokeOnChange",
287
- isValueComplete: ["invokeOnComplete", "blurFocusedInputIfNeeded"]
288
- },
289
- on: {
290
- SET_VALUE: [
291
- {
292
- guard: "hasIndex",
293
- actions: "setValueAtIndex"
294
- },
295
- { actions: "setValue" }
296
- ],
297
- CLEAR_VALUE: [
298
- {
299
- guard: "isDisabled",
300
- actions: "clearValue"
301
- },
302
- {
303
- actions: ["clearValue", "setFocusIndexToFirst"]
304
- }
305
- ]
306
- },
307
- states: {
308
- unknown: {
309
- on: {
310
- SETUP: [
311
- {
312
- guard: "autoFocus",
313
- target: "focused",
314
- actions: ["setupValue", "setFocusIndexToFirst"]
315
- },
316
- {
317
- target: "idle",
318
- actions: "setupValue"
319
- }
320
- ]
267
+ return createMachine(
268
+ {
269
+ id: "pin-input",
270
+ initial: "unknown",
271
+ context: {
272
+ value: [],
273
+ focusedIndex: -1,
274
+ placeholder: "\u25CB",
275
+ otp: false,
276
+ type: "numeric",
277
+ ...ctx,
278
+ messages: {
279
+ inputLabel: (index, length) => `pin code ${index + 1} of ${length}`,
280
+ ...ctx.messages
321
281
  }
322
282
  },
323
- idle: {
324
- on: {
325
- FOCUS: {
326
- target: "focused",
327
- actions: "setFocusedIndex"
328
- }
329
- }
283
+ computed: {
284
+ valueLength: (ctx2) => ctx2.value.length,
285
+ filledValueLength: (ctx2) => ctx2.value.filter((v) => (v == null ? void 0 : v.trim()) !== "").length,
286
+ isValueComplete: (ctx2) => ctx2.valueLength === ctx2.filledValueLength,
287
+ valueAsString: (ctx2) => ctx2.value.join("")
330
288
  },
331
- focused: {
332
- on: {
333
- INPUT: [
334
- {
335
- guard: and("isFinalValue", "isValidValue"),
336
- actions: "setFocusedValue"
337
- },
338
- {
339
- guard: "isValidValue",
340
- actions: ["setFocusedValue", "setNextFocusedIndex"]
341
- }
342
- ],
343
- PASTE: {
344
- guard: "isValidValue",
345
- actions: ["setPastedValue", "setLastValueFocusIndex"]
346
- },
347
- BLUR: {
348
- target: "idle",
349
- actions: "clearFocusedIndex"
350
- },
351
- DELETE: {
352
- guard: "hasValue",
353
- actions: "clearFocusedValue"
354
- },
355
- ARROW_LEFT: {
356
- actions: "setPrevFocusedIndex"
289
+ watch: {
290
+ focusedIndex: "focusInput",
291
+ value: "invokeOnChange",
292
+ isValueComplete: ["invokeOnComplete", "blurFocusedInputIfNeeded"]
293
+ },
294
+ on: {
295
+ SET_VALUE: [
296
+ {
297
+ guard: "hasIndex",
298
+ actions: "setValueAtIndex"
357
299
  },
358
- ARROW_RIGHT: {
359
- actions: "setNextFocusedIndex"
300
+ { actions: "setValue" }
301
+ ],
302
+ CLEAR_VALUE: [
303
+ {
304
+ guard: "isDisabled",
305
+ actions: "clearValue"
360
306
  },
361
- BACKSPACE: [
362
- {
307
+ {
308
+ actions: ["clearValue", "setFocusIndexToFirst"]
309
+ }
310
+ ]
311
+ },
312
+ states: {
313
+ unknown: {
314
+ on: {
315
+ SETUP: [
316
+ {
317
+ guard: "autoFocus",
318
+ target: "focused",
319
+ actions: ["setupValue", "setFocusIndexToFirst"]
320
+ },
321
+ {
322
+ target: "idle",
323
+ actions: "setupValue"
324
+ }
325
+ ]
326
+ }
327
+ },
328
+ idle: {
329
+ on: {
330
+ FOCUS: {
331
+ target: "focused",
332
+ actions: "setFocusedIndex"
333
+ }
334
+ }
335
+ },
336
+ focused: {
337
+ on: {
338
+ INPUT: [
339
+ {
340
+ guard: and("isFinalValue", "isValidValue"),
341
+ actions: "setFocusedValue"
342
+ },
343
+ {
344
+ guard: "isValidValue",
345
+ actions: ["setFocusedValue", "setNextFocusedIndex"]
346
+ }
347
+ ],
348
+ PASTE: {
349
+ guard: "isValidValue",
350
+ actions: ["setPastedValue", "setLastValueFocusIndex"]
351
+ },
352
+ BLUR: {
353
+ target: "idle",
354
+ actions: "clearFocusedIndex"
355
+ },
356
+ DELETE: {
363
357
  guard: "hasValue",
364
358
  actions: "clearFocusedValue"
365
359
  },
366
- {
367
- actions: ["setPrevFocusedIndex", "clearFocusedValue"]
360
+ ARROW_LEFT: {
361
+ actions: "setPrevFocusedIndex"
362
+ },
363
+ ARROW_RIGHT: {
364
+ actions: "setNextFocusedIndex"
365
+ },
366
+ BACKSPACE: [
367
+ {
368
+ guard: "hasValue",
369
+ actions: "clearFocusedValue"
370
+ },
371
+ {
372
+ actions: ["setPrevFocusedIndex", "clearFocusedValue"]
373
+ }
374
+ ],
375
+ ENTER: {
376
+ guard: "isValueComplete",
377
+ actions: "requestFormSubmit"
378
+ },
379
+ KEY_DOWN: {
380
+ guard: not("isValidValue"),
381
+ actions: ["preventDefault", "invokeOnInvalid"]
368
382
  }
369
- ],
370
- ENTER: {
371
- guard: "isValueComplete",
372
- actions: "requestFormSubmit"
373
- },
374
- KEY_DOWN: {
375
- guard: not("isValidValue"),
376
- actions: ["preventDefault", "invokeOnInvalid"]
377
383
  }
378
384
  }
379
385
  }
380
- }
381
- }, {
382
- guards: {
383
- autoFocus: (ctx2) => !!ctx2.autoFocus,
384
- isValueEmpty: (_ctx, evt) => evt.value === "",
385
- hasValue: (ctx2) => ctx2.value[ctx2.focusedIndex] !== "",
386
- isValueComplete: (ctx2) => ctx2.isValueComplete,
387
- isValidValue: (ctx2, evt) => {
388
- if (!ctx2.pattern)
389
- return isValidType(evt.value, ctx2.type);
390
- const regex = new RegExp(ctx2.pattern, "g");
391
- return regex.test(evt.value);
392
- },
393
- isFinalValue: (ctx2) => {
394
- return ctx2.filledValueLength + 1 === ctx2.valueLength && ctx2.value.findIndex((v) => v.trim() === "") === ctx2.focusedIndex;
395
- },
396
- isLastInputFocused: (ctx2) => ctx2.focusedIndex === ctx2.valueLength - 1,
397
- hasIndex: (_ctx, evt) => evt.index !== void 0,
398
- isDisabled: (ctx2) => !!ctx2.disabled
399
386
  },
400
- actions: {
401
- setupValue: (ctx2) => {
402
- const inputs = dom.getElements(ctx2);
403
- const empty = Array.from({ length: inputs.length }).map(() => "");
404
- ctx2.value = Object.assign(empty, ctx2.value);
387
+ {
388
+ guards: {
389
+ autoFocus: (ctx2) => !!ctx2.autoFocus,
390
+ isValueEmpty: (_ctx, evt) => evt.value === "",
391
+ hasValue: (ctx2) => ctx2.value[ctx2.focusedIndex] !== "",
392
+ isValueComplete: (ctx2) => ctx2.isValueComplete,
393
+ isValidValue: (ctx2, evt) => {
394
+ if (!ctx2.pattern)
395
+ return isValidType(evt.value, ctx2.type);
396
+ const regex = new RegExp(ctx2.pattern, "g");
397
+ return regex.test(evt.value);
398
+ },
399
+ isFinalValue: (ctx2) => {
400
+ return ctx2.filledValueLength + 1 === ctx2.valueLength && ctx2.value.findIndex((v) => v.trim() === "") === ctx2.focusedIndex;
401
+ },
402
+ isLastInputFocused: (ctx2) => ctx2.focusedIndex === ctx2.valueLength - 1,
403
+ hasIndex: (_ctx, evt) => evt.index !== void 0,
404
+ isDisabled: (ctx2) => !!ctx2.disabled
405
405
  },
406
- focusInput: (ctx2) => {
407
- raf(() => {
406
+ actions: {
407
+ setupValue: (ctx2) => {
408
+ const inputs = dom.getElements(ctx2);
409
+ const empty = Array.from({ length: inputs.length }).map(() => "");
410
+ ctx2.value = Object.assign(empty, ctx2.value);
411
+ },
412
+ focusInput: (ctx2) => {
413
+ raf(() => {
414
+ var _a;
415
+ if (ctx2.focusedIndex === -1)
416
+ return;
417
+ (_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.focus();
418
+ });
419
+ },
420
+ invokeOnComplete: (ctx2) => {
408
421
  var _a;
409
- if (ctx2.focusedIndex === -1)
422
+ if (!ctx2.isValueComplete)
410
423
  return;
411
- (_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.focus();
412
- });
413
- },
414
- invokeOnComplete: (ctx2) => {
415
- var _a;
416
- if (!ctx2.isValueComplete)
417
- return;
418
- (_a = ctx2.onComplete) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value), valueAsString: ctx2.valueAsString });
419
- },
420
- invokeOnChange: (ctx2, evt) => {
421
- var _a;
422
- if (evt.type === "SETUP")
423
- return;
424
- (_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value) });
425
- dispatchInputValueEvent(dom.getHiddenInputEl(ctx2), ctx2.valueAsString);
426
- },
427
- invokeOnInvalid: (ctx2, evt) => {
428
- var _a;
429
- (_a = ctx2.onInvalid) == null ? void 0 : _a.call(ctx2, { value: evt.value, index: ctx2.focusedIndex });
430
- },
431
- clearFocusedIndex: (ctx2) => {
432
- ctx2.focusedIndex = -1;
433
- },
434
- setValue: (ctx2, evt) => {
435
- assign(ctx2, evt.value);
436
- },
437
- setFocusedIndex: (ctx2, evt) => {
438
- ctx2.focusedIndex = evt.index;
439
- },
440
- setFocusedValue: (ctx2, evt) => {
441
- ctx2.value[ctx2.focusedIndex] = lastChar(evt.value);
442
- },
443
- setPastedValue(ctx2, evt) {
444
- raf(() => {
445
- const value = evt.value.substring(0, ctx2.valueLength);
446
- assign(ctx2, value.split("").filter(Boolean));
447
- });
448
- },
449
- setValueAtIndex: (ctx2, evt) => {
450
- ctx2.value[evt.index] = lastChar(evt.value);
451
- },
452
- clearValue: (ctx2) => {
453
- assign(ctx2, "");
454
- },
455
- clearFocusedValue: (ctx2) => {
456
- ctx2.value[ctx2.focusedIndex] = "";
457
- },
458
- setFocusIndexToFirst: (ctx2) => {
459
- ctx2.focusedIndex = 0;
460
- },
461
- setNextFocusedIndex: (ctx2) => {
462
- ctx2.focusedIndex = Math.min(ctx2.focusedIndex + 1, ctx2.valueLength - 1);
463
- },
464
- setPrevFocusedIndex: (ctx2) => {
465
- ctx2.focusedIndex = Math.max(ctx2.focusedIndex - 1, 0);
466
- },
467
- setLastValueFocusIndex: (ctx2) => {
468
- raf(() => {
469
- ctx2.focusedIndex = Math.min(ctx2.filledValueLength, ctx2.valueLength - 1);
470
- });
471
- },
472
- preventDefault(_, evt) {
473
- evt.preventDefault();
474
- },
475
- blurFocusedInputIfNeeded(ctx2) {
476
- if (!ctx2.blurOnComplete)
477
- return;
478
- raf(() => {
424
+ (_a = ctx2.onComplete) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value), valueAsString: ctx2.valueAsString });
425
+ },
426
+ invokeOnChange: (ctx2, evt) => {
479
427
  var _a;
480
- (_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.blur();
481
- });
482
- },
483
- requestFormSubmit(ctx2) {
484
- var _a;
485
- if (!ctx2.name)
486
- return;
487
- const input = dom.getHiddenInputEl(ctx2);
488
- (_a = input == null ? void 0 : input.form) == null ? void 0 : _a.requestSubmit();
428
+ if (evt.type === "SETUP")
429
+ return;
430
+ (_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value) });
431
+ dispatchInputValueEvent(dom.getHiddenInputEl(ctx2), ctx2.valueAsString);
432
+ },
433
+ invokeOnInvalid: (ctx2, evt) => {
434
+ var _a;
435
+ (_a = ctx2.onInvalid) == null ? void 0 : _a.call(ctx2, { value: evt.value, index: ctx2.focusedIndex });
436
+ },
437
+ clearFocusedIndex: (ctx2) => {
438
+ ctx2.focusedIndex = -1;
439
+ },
440
+ setValue: (ctx2, evt) => {
441
+ assign(ctx2, evt.value);
442
+ },
443
+ setFocusedIndex: (ctx2, evt) => {
444
+ ctx2.focusedIndex = evt.index;
445
+ },
446
+ setFocusedValue: (ctx2, evt) => {
447
+ ctx2.value[ctx2.focusedIndex] = lastChar(evt.value);
448
+ },
449
+ setPastedValue(ctx2, evt) {
450
+ raf(() => {
451
+ const value = evt.value.substring(0, ctx2.valueLength);
452
+ assign(ctx2, value.split("").filter(Boolean));
453
+ });
454
+ },
455
+ setValueAtIndex: (ctx2, evt) => {
456
+ ctx2.value[evt.index] = lastChar(evt.value);
457
+ },
458
+ clearValue: (ctx2) => {
459
+ assign(ctx2, "");
460
+ },
461
+ clearFocusedValue: (ctx2) => {
462
+ ctx2.value[ctx2.focusedIndex] = "";
463
+ },
464
+ setFocusIndexToFirst: (ctx2) => {
465
+ ctx2.focusedIndex = 0;
466
+ },
467
+ setNextFocusedIndex: (ctx2) => {
468
+ ctx2.focusedIndex = Math.min(ctx2.focusedIndex + 1, ctx2.valueLength - 1);
469
+ },
470
+ setPrevFocusedIndex: (ctx2) => {
471
+ ctx2.focusedIndex = Math.max(ctx2.focusedIndex - 1, 0);
472
+ },
473
+ setLastValueFocusIndex: (ctx2) => {
474
+ raf(() => {
475
+ ctx2.focusedIndex = Math.min(ctx2.filledValueLength, ctx2.valueLength - 1);
476
+ });
477
+ },
478
+ preventDefault(_, evt) {
479
+ evt.preventDefault();
480
+ },
481
+ blurFocusedInputIfNeeded(ctx2) {
482
+ if (!ctx2.blurOnComplete)
483
+ return;
484
+ raf(() => {
485
+ var _a;
486
+ (_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.blur();
487
+ });
488
+ },
489
+ requestFormSubmit(ctx2) {
490
+ var _a;
491
+ if (!ctx2.name)
492
+ return;
493
+ const input = dom.getHiddenInputEl(ctx2);
494
+ (_a = input == null ? void 0 : input.form) == null ? void 0 : _a.requestSubmit();
495
+ }
489
496
  }
490
497
  }
491
- });
498
+ );
492
499
  }
493
500
  var REGEX = {
494
501
  numeric: /^[0-9]+$/,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zag-js/pin-input",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "Core logic for the pin-input widget implemented as a state machine",
5
5
  "keywords": [
6
6
  "js",
@@ -33,7 +33,8 @@
33
33
  "@zag-js/types": "0.2.3"
34
34
  },
35
35
  "devDependencies": {
36
- "@zag-js/dom-utils": "0.1.8",
36
+ "@zag-js/dom-utils": "0.1.9",
37
+ "@zag-js/form-utils": "0.1.0",
37
38
  "@zag-js/utils": "0.1.3"
38
39
  },
39
40
  "scripts": {