@zag-js/pin-input 0.1.17 → 0.2.1

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.ts CHANGED
@@ -81,6 +81,10 @@ declare type PublicContext = DirectionProperty & CommonProperties & {
81
81
  * Whether to blur the input when the value is complete
82
82
  */
83
83
  blurOnComplete?: boolean;
84
+ /**
85
+ * Whether to select input value when input is focused
86
+ */
87
+ selectOnFocus?: boolean;
84
88
  /**
85
89
  * Specifies the localized strings that identifies the accessibility elements and their states
86
90
  */
@@ -108,6 +112,11 @@ declare type ComputedContext = Readonly<{
108
112
  * The string representation of the input values
109
113
  */
110
114
  valueAsString: string;
115
+ /**
116
+ * @computed
117
+ * The value at focused index
118
+ */
119
+ focusedValue: string;
111
120
  }>;
112
121
  declare type PrivateContext = Context<{}>;
113
122
  declare type MachineContext = PublicContext & PrivateContext & ComputedContext;
@@ -133,6 +142,6 @@ declare function connect<T extends PropTypes>(state: State, send: Send, normaliz
133
142
  }): T["input"];
134
143
  };
135
144
 
136
- declare function machine(ctx: UserDefinedContext): _zag_js_core.Machine<MachineContext, MachineState, _zag_js_core.StateMachine.AnyEventObject>;
145
+ declare function machine(userContext: UserDefinedContext): _zag_js_core.Machine<MachineContext, MachineState, _zag_js_core.StateMachine.AnyEventObject>;
137
146
 
138
147
  export { UserDefinedContext as Context, connect, machine };
package/dist/index.js CHANGED
@@ -39,22 +39,44 @@ function isWindow(value) {
39
39
  return (value == null ? void 0 : value.toString()) === "[object Window]";
40
40
  }
41
41
  function getDocument(el) {
42
+ var _a;
42
43
  if (isWindow(el))
43
44
  return el.document;
44
45
  if (isDocument(el))
45
46
  return el;
46
- return (el == null ? void 0 : el.ownerDocument) ?? document;
47
+ return (_a = el == null ? void 0 : el.ownerDocument) != null ? _a : document;
47
48
  }
48
49
  function defineDomHelpers(helpers) {
49
50
  const dom2 = {
50
51
  getRootNode: (ctx) => {
51
- var _a;
52
- return ((_a = ctx.getRootNode) == null ? void 0 : _a.call(ctx)) ?? document;
52
+ var _a, _b;
53
+ return (_b = (_a = ctx.getRootNode) == null ? void 0 : _a.call(ctx)) != null ? _b : document;
53
54
  },
54
55
  getDoc: (ctx) => getDocument(dom2.getRootNode(ctx)),
55
- getWin: (ctx) => dom2.getDoc(ctx).defaultView ?? window,
56
+ getWin: (ctx) => {
57
+ var _a;
58
+ return (_a = dom2.getDoc(ctx).defaultView) != null ? _a : window;
59
+ },
56
60
  getActiveElement: (ctx) => dom2.getDoc(ctx).activeElement,
57
- getById: (ctx, id) => dom2.getRootNode(ctx).getElementById(id)
61
+ getById: (ctx, id) => dom2.getRootNode(ctx).getElementById(id),
62
+ createEmitter: (ctx, target) => {
63
+ const win = dom2.getWin(ctx);
64
+ return function emit(evt, detail, options) {
65
+ const { bubbles = true, cancelable, composed = true } = options != null ? options : {};
66
+ const eventName = `zag:${evt}`;
67
+ const init = { bubbles, cancelable, composed, detail };
68
+ const event = new win.CustomEvent(eventName, init);
69
+ target.dispatchEvent(event);
70
+ };
71
+ },
72
+ createListener: (target) => {
73
+ return function listen(evt, handler) {
74
+ const eventName = `zag:${evt}`;
75
+ const listener = (e) => handler(e);
76
+ target.addEventListener(eventName, listener);
77
+ return () => target.removeEventListener(eventName, listener);
78
+ };
79
+ }
58
80
  };
59
81
  return {
60
82
  ...dom2,
@@ -62,7 +84,8 @@ function defineDomHelpers(helpers) {
62
84
  };
63
85
  }
64
86
  function getNativeEvent(e) {
65
- return e.nativeEvent ?? e;
87
+ var _a;
88
+ return (_a = e.nativeEvent) != null ? _a : e;
66
89
  }
67
90
  var isModifiedEvent = (v) => v.ctrlKey || v.altKey || v.metaKey;
68
91
  var rtlKeyMap = {
@@ -79,9 +102,10 @@ var sameKeyMap = {
79
102
  Right: "ArrowRight"
80
103
  };
81
104
  function getEventKey(event, options = {}) {
105
+ var _a;
82
106
  const { dir = "ltr", orientation = "horizontal" } = options;
83
107
  let { key } = event;
84
- key = sameKeyMap[key] ?? key;
108
+ key = (_a = sameKeyMap[key]) != null ? _a : key;
85
109
  const isRtl = dir === "rtl" && orientation === "horizontal";
86
110
  if (isRtl && key in rtlKeyMap) {
87
111
  key = rtlKeyMap[key];
@@ -95,7 +119,8 @@ function raf(fn) {
95
119
  };
96
120
  }
97
121
  function queryAll(root, selector) {
98
- return Array.from((root == null ? void 0 : root.querySelectorAll(selector)) ?? []);
122
+ var _a;
123
+ return Array.from((_a = root == null ? void 0 : root.querySelectorAll(selector)) != null ? _a : []);
99
124
  }
100
125
  var visuallyHiddenStyle = {
101
126
  border: "0",
@@ -111,6 +136,15 @@ var visuallyHiddenStyle = {
111
136
  };
112
137
 
113
138
  // ../../utilities/core/dist/index.mjs
139
+ var isArray = (v) => Array.isArray(v);
140
+ var isObject = (v) => !(v == null || typeof v !== "object" || isArray(v));
141
+ function compact(obj) {
142
+ if (obj === void 0)
143
+ return obj;
144
+ return Object.fromEntries(
145
+ Object.entries(obj).filter(([, value]) => value !== void 0).map(([key, value]) => [key, isObject(value) ? compact(value) : value])
146
+ );
147
+ }
114
148
  function invariant(...a) {
115
149
  const m = a.length === 1 ? a[0] : a[1];
116
150
  const c = a.length === 2 ? a[0] : true;
@@ -122,20 +156,20 @@ function invariant(...a) {
122
156
  // src/pin-input.dom.ts
123
157
  var dom = defineDomHelpers({
124
158
  getRootId: (ctx) => {
125
- var _a;
126
- return ((_a = ctx.ids) == null ? void 0 : _a.root) ?? `pin-input:${ctx.id}`;
159
+ var _a, _b;
160
+ return (_b = (_a = ctx.ids) == null ? void 0 : _a.root) != null ? _b : `pin-input:${ctx.id}`;
127
161
  },
128
162
  getInputId: (ctx, id) => {
129
- var _a, _b;
130
- return ((_b = (_a = ctx.ids) == null ? void 0 : _a.input) == null ? void 0 : _b.call(_a, id)) ?? `pin-input:${ctx.id}:${id}`;
163
+ var _a, _b, _c;
164
+ return (_c = (_b = (_a = ctx.ids) == null ? void 0 : _a.input) == null ? void 0 : _b.call(_a, id)) != null ? _c : `pin-input:${ctx.id}:${id}`;
131
165
  },
132
166
  getHiddenInputId: (ctx) => {
133
- var _a;
134
- return ((_a = ctx.ids) == null ? void 0 : _a.hiddenInput) ?? `pin-input:${ctx.id}:hidden`;
167
+ var _a, _b;
168
+ return (_b = (_a = ctx.ids) == null ? void 0 : _a.hiddenInput) != null ? _b : `pin-input:${ctx.id}:hidden`;
135
169
  },
136
170
  getLabelId: (ctx) => {
137
- var _a;
138
- return ((_a = ctx.ids) == null ? void 0 : _a.label) ?? `pin-input:${ctx.id}:label`;
171
+ var _a, _b;
172
+ return (_b = (_a = ctx.ids) == null ? void 0 : _a.label) != null ? _b : `pin-input:${ctx.id}:label`;
139
173
  },
140
174
  getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
141
175
  getElements: (ctx) => {
@@ -219,7 +253,7 @@ function connect(state, send, normalize) {
219
253
  "aria-invalid": ariaAttr(isInvalid),
220
254
  "data-invalid": dataAttr(isInvalid),
221
255
  type: state.context.mask ? "password" : inputType,
222
- value: state.context.value[index] || "",
256
+ defaultValue: state.context.value[index] || "",
223
257
  autoCapitalize: "none",
224
258
  autoComplete: state.context.otp ? "one-time-code" : "off",
225
259
  placeholder: focusedIndex === index ? "" : state.context.placeholder,
@@ -285,12 +319,14 @@ var import_core = require("@zag-js/core");
285
319
 
286
320
  // ../../utilities/form-utils/dist/index.mjs
287
321
  function getWindow(el) {
288
- return (el == null ? void 0 : el.ownerDocument.defaultView) ?? window;
322
+ var _a;
323
+ return (_a = el == null ? void 0 : el.ownerDocument.defaultView) != null ? _a : window;
289
324
  }
290
325
  function getDescriptor(el, options) {
326
+ var _a;
291
327
  const { type, property } = options;
292
328
  const proto = getWindow(el)[type].prototype;
293
- return Object.getOwnPropertyDescriptor(proto, property) ?? {};
329
+ return (_a = Object.getOwnPropertyDescriptor(proto, property)) != null ? _a : {};
294
330
  }
295
331
  function dispatchInputValueEvent(el, value) {
296
332
  var _a;
@@ -307,7 +343,8 @@ function dispatchInputValueEvent(el, value) {
307
343
 
308
344
  // src/pin-input.machine.ts
309
345
  var { and, not } = import_core.guards;
310
- function machine(ctx) {
346
+ function machine(userContext) {
347
+ const ctx = compact(userContext);
311
348
  return (0, import_core.createMachine)(
312
349
  {
313
350
  id: "pin-input",
@@ -328,11 +365,12 @@ function machine(ctx) {
328
365
  valueLength: (ctx2) => ctx2.value.length,
329
366
  filledValueLength: (ctx2) => ctx2.value.filter((v) => (v == null ? void 0 : v.trim()) !== "").length,
330
367
  isValueComplete: (ctx2) => ctx2.valueLength === ctx2.filledValueLength,
331
- valueAsString: (ctx2) => ctx2.value.join("")
368
+ valueAsString: (ctx2) => ctx2.value.join(""),
369
+ focusedValue: (ctx2) => ctx2.value[ctx2.focusedIndex]
332
370
  },
333
371
  watch: {
334
- focusedIndex: "focusInput",
335
- value: "invokeOnChange",
372
+ focusedIndex: ["focusInput", "setInputSelection"],
373
+ value: ["invokeOnChange", "dispatchInputEvent"],
336
374
  isValueComplete: ["invokeOnComplete", "blurFocusedInputIfNeeded"]
337
375
  },
338
376
  on: {
@@ -382,17 +420,20 @@ function machine(ctx) {
382
420
  INPUT: [
383
421
  {
384
422
  guard: and("isFinalValue", "isValidValue"),
385
- actions: "setFocusedValue"
423
+ actions: ["setFocusedValue", "dispatchInputEventIfNeeded"]
386
424
  },
387
425
  {
388
426
  guard: "isValidValue",
389
- actions: ["setFocusedValue", "setNextFocusedIndex"]
427
+ actions: ["setFocusedValue", "setNextFocusedIndex", "dispatchInputEventIfNeeded"]
390
428
  }
391
429
  ],
392
- PASTE: {
393
- guard: "isValidValue",
394
- actions: ["setPastedValue", "setLastValueFocusIndex"]
395
- },
430
+ PASTE: [
431
+ {
432
+ guard: "isValidValue",
433
+ actions: ["setPastedValue", "setLastValueFocusIndex"]
434
+ },
435
+ { actions: "resetFocusedValue" }
436
+ ],
396
437
  BLUR: {
397
438
  target: "idle",
398
439
  actions: "clearFocusedIndex"
@@ -461,6 +502,16 @@ function machine(ctx) {
461
502
  (_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.focus();
462
503
  });
463
504
  },
505
+ setInputSelection: (ctx2) => {
506
+ raf(() => {
507
+ if (ctx2.focusedIndex === -1)
508
+ return;
509
+ const input = dom.getFocusedEl(ctx2);
510
+ const length = input.value.length;
511
+ input.selectionStart = ctx2.selectOnFocus ? 0 : length;
512
+ input.selectionEnd = length;
513
+ });
514
+ },
464
515
  invokeOnComplete: (ctx2) => {
465
516
  var _a;
466
517
  if (!ctx2.isValueComplete)
@@ -472,7 +523,16 @@ function machine(ctx) {
472
523
  if (evt.type === "SETUP")
473
524
  return;
474
525
  (_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value) });
526
+ },
527
+ dispatchInputEvent: (ctx2, evt) => {
528
+ if (evt.type === "SETUP")
529
+ return;
475
530
  dispatchInputValueEvent(dom.getHiddenInputEl(ctx2), ctx2.valueAsString);
531
+ const inputs = dom.getElements(ctx2);
532
+ ctx2.value.forEach((val, index) => {
533
+ const input = inputs[index];
534
+ input.value = val || "";
535
+ });
476
536
  },
477
537
  invokeOnInvalid: (ctx2, evt) => {
478
538
  var _a;
@@ -490,21 +550,34 @@ function machine(ctx) {
490
550
  setFocusedValue: (ctx2, evt) => {
491
551
  ctx2.value[ctx2.focusedIndex] = lastChar(evt.value);
492
552
  },
553
+ dispatchInputEventIfNeeded: (ctx2, evt) => {
554
+ const valueIsChanged = lastChar(evt.value) !== ctx2.focusedValue;
555
+ if (evt.value.length <= 1 || valueIsChanged)
556
+ return;
557
+ const inputs = dom.getElements(ctx2);
558
+ const input = inputs[ctx2.focusedIndex];
559
+ input.value = lastChar(evt.value);
560
+ },
493
561
  setPastedValue(ctx2, evt) {
494
562
  raf(() => {
495
- const value = evt.value.substring(0, ctx2.valueLength);
496
- assign(ctx2, value.split("").filter(Boolean));
563
+ const startIndex = ctx2.focusedValue ? 1 : 0;
564
+ const value = evt.value.substring(startIndex, ctx2.valueLength);
565
+ assign(ctx2, value);
497
566
  });
498
567
  },
499
568
  setValueAtIndex: (ctx2, evt) => {
500
569
  ctx2.value[evt.index] = lastChar(evt.value);
501
570
  },
502
571
  clearValue: (ctx2) => {
503
- assign(ctx2, "");
572
+ ctx2.value = ctx2.value.map(() => "");
504
573
  },
505
574
  clearFocusedValue: (ctx2) => {
506
575
  ctx2.value[ctx2.focusedIndex] = "";
507
576
  },
577
+ resetFocusedValue: (ctx2) => {
578
+ const input = dom.getFocusedEl(ctx2);
579
+ input.value = ctx2.focusedValue;
580
+ },
508
581
  setFocusIndexToFirst: (ctx2) => {
509
582
  ctx2.focusedIndex = 0;
510
583
  },
@@ -553,16 +626,10 @@ function isValidType(value, type) {
553
626
  return !!((_a = REGEX[type]) == null ? void 0 : _a.test(value));
554
627
  }
555
628
  function assign(ctx, value) {
556
- const len = ctx.value.length;
557
- for (let i = 0; i < len; i++) {
558
- if (Array.isArray(value)) {
559
- if (!value[i])
560
- continue;
561
- ctx.value[i] = value[i];
562
- } else {
563
- ctx.value[i] = value;
564
- }
565
- }
629
+ const valueArr = value.split("").filter(Boolean);
630
+ const valueObj = Object.assign({}, ctx.value, valueArr);
631
+ console.log("valueObj :>> ", valueObj);
632
+ ctx.value = Object.values(valueObj);
566
633
  }
567
634
  function lastChar(value) {
568
635
  return value.charAt(value.length - 1);
package/dist/index.mjs CHANGED
@@ -12,22 +12,44 @@ function isWindow(value) {
12
12
  return (value == null ? void 0 : value.toString()) === "[object Window]";
13
13
  }
14
14
  function getDocument(el) {
15
+ var _a;
15
16
  if (isWindow(el))
16
17
  return el.document;
17
18
  if (isDocument(el))
18
19
  return el;
19
- return (el == null ? void 0 : el.ownerDocument) ?? document;
20
+ return (_a = el == null ? void 0 : el.ownerDocument) != null ? _a : document;
20
21
  }
21
22
  function defineDomHelpers(helpers) {
22
23
  const dom2 = {
23
24
  getRootNode: (ctx) => {
24
- var _a;
25
- return ((_a = ctx.getRootNode) == null ? void 0 : _a.call(ctx)) ?? document;
25
+ var _a, _b;
26
+ return (_b = (_a = ctx.getRootNode) == null ? void 0 : _a.call(ctx)) != null ? _b : document;
26
27
  },
27
28
  getDoc: (ctx) => getDocument(dom2.getRootNode(ctx)),
28
- getWin: (ctx) => dom2.getDoc(ctx).defaultView ?? window,
29
+ getWin: (ctx) => {
30
+ var _a;
31
+ return (_a = dom2.getDoc(ctx).defaultView) != null ? _a : window;
32
+ },
29
33
  getActiveElement: (ctx) => dom2.getDoc(ctx).activeElement,
30
- getById: (ctx, id) => dom2.getRootNode(ctx).getElementById(id)
34
+ getById: (ctx, id) => dom2.getRootNode(ctx).getElementById(id),
35
+ createEmitter: (ctx, target) => {
36
+ const win = dom2.getWin(ctx);
37
+ return function emit(evt, detail, options) {
38
+ const { bubbles = true, cancelable, composed = true } = options != null ? options : {};
39
+ const eventName = `zag:${evt}`;
40
+ const init = { bubbles, cancelable, composed, detail };
41
+ const event = new win.CustomEvent(eventName, init);
42
+ target.dispatchEvent(event);
43
+ };
44
+ },
45
+ createListener: (target) => {
46
+ return function listen(evt, handler) {
47
+ const eventName = `zag:${evt}`;
48
+ const listener = (e) => handler(e);
49
+ target.addEventListener(eventName, listener);
50
+ return () => target.removeEventListener(eventName, listener);
51
+ };
52
+ }
31
53
  };
32
54
  return {
33
55
  ...dom2,
@@ -35,7 +57,8 @@ function defineDomHelpers(helpers) {
35
57
  };
36
58
  }
37
59
  function getNativeEvent(e) {
38
- return e.nativeEvent ?? e;
60
+ var _a;
61
+ return (_a = e.nativeEvent) != null ? _a : e;
39
62
  }
40
63
  var isModifiedEvent = (v) => v.ctrlKey || v.altKey || v.metaKey;
41
64
  var rtlKeyMap = {
@@ -52,9 +75,10 @@ var sameKeyMap = {
52
75
  Right: "ArrowRight"
53
76
  };
54
77
  function getEventKey(event, options = {}) {
78
+ var _a;
55
79
  const { dir = "ltr", orientation = "horizontal" } = options;
56
80
  let { key } = event;
57
- key = sameKeyMap[key] ?? key;
81
+ key = (_a = sameKeyMap[key]) != null ? _a : key;
58
82
  const isRtl = dir === "rtl" && orientation === "horizontal";
59
83
  if (isRtl && key in rtlKeyMap) {
60
84
  key = rtlKeyMap[key];
@@ -68,7 +92,8 @@ function raf(fn) {
68
92
  };
69
93
  }
70
94
  function queryAll(root, selector) {
71
- return Array.from((root == null ? void 0 : root.querySelectorAll(selector)) ?? []);
95
+ var _a;
96
+ return Array.from((_a = root == null ? void 0 : root.querySelectorAll(selector)) != null ? _a : []);
72
97
  }
73
98
  var visuallyHiddenStyle = {
74
99
  border: "0",
@@ -84,6 +109,15 @@ var visuallyHiddenStyle = {
84
109
  };
85
110
 
86
111
  // ../../utilities/core/dist/index.mjs
112
+ var isArray = (v) => Array.isArray(v);
113
+ var isObject = (v) => !(v == null || typeof v !== "object" || isArray(v));
114
+ function compact(obj) {
115
+ if (obj === void 0)
116
+ return obj;
117
+ return Object.fromEntries(
118
+ Object.entries(obj).filter(([, value]) => value !== void 0).map(([key, value]) => [key, isObject(value) ? compact(value) : value])
119
+ );
120
+ }
87
121
  function invariant(...a) {
88
122
  const m = a.length === 1 ? a[0] : a[1];
89
123
  const c = a.length === 2 ? a[0] : true;
@@ -95,20 +129,20 @@ function invariant(...a) {
95
129
  // src/pin-input.dom.ts
96
130
  var dom = defineDomHelpers({
97
131
  getRootId: (ctx) => {
98
- var _a;
99
- return ((_a = ctx.ids) == null ? void 0 : _a.root) ?? `pin-input:${ctx.id}`;
132
+ var _a, _b;
133
+ return (_b = (_a = ctx.ids) == null ? void 0 : _a.root) != null ? _b : `pin-input:${ctx.id}`;
100
134
  },
101
135
  getInputId: (ctx, id) => {
102
- var _a, _b;
103
- return ((_b = (_a = ctx.ids) == null ? void 0 : _a.input) == null ? void 0 : _b.call(_a, id)) ?? `pin-input:${ctx.id}:${id}`;
136
+ var _a, _b, _c;
137
+ return (_c = (_b = (_a = ctx.ids) == null ? void 0 : _a.input) == null ? void 0 : _b.call(_a, id)) != null ? _c : `pin-input:${ctx.id}:${id}`;
104
138
  },
105
139
  getHiddenInputId: (ctx) => {
106
- var _a;
107
- return ((_a = ctx.ids) == null ? void 0 : _a.hiddenInput) ?? `pin-input:${ctx.id}:hidden`;
140
+ var _a, _b;
141
+ return (_b = (_a = ctx.ids) == null ? void 0 : _a.hiddenInput) != null ? _b : `pin-input:${ctx.id}:hidden`;
108
142
  },
109
143
  getLabelId: (ctx) => {
110
- var _a;
111
- return ((_a = ctx.ids) == null ? void 0 : _a.label) ?? `pin-input:${ctx.id}:label`;
144
+ var _a, _b;
145
+ return (_b = (_a = ctx.ids) == null ? void 0 : _a.label) != null ? _b : `pin-input:${ctx.id}:label`;
112
146
  },
113
147
  getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
114
148
  getElements: (ctx) => {
@@ -192,7 +226,7 @@ function connect(state, send, normalize) {
192
226
  "aria-invalid": ariaAttr(isInvalid),
193
227
  "data-invalid": dataAttr(isInvalid),
194
228
  type: state.context.mask ? "password" : inputType,
195
- value: state.context.value[index] || "",
229
+ defaultValue: state.context.value[index] || "",
196
230
  autoCapitalize: "none",
197
231
  autoComplete: state.context.otp ? "one-time-code" : "off",
198
232
  placeholder: focusedIndex === index ? "" : state.context.placeholder,
@@ -258,12 +292,14 @@ import { createMachine, guards } from "@zag-js/core";
258
292
 
259
293
  // ../../utilities/form-utils/dist/index.mjs
260
294
  function getWindow(el) {
261
- return (el == null ? void 0 : el.ownerDocument.defaultView) ?? window;
295
+ var _a;
296
+ return (_a = el == null ? void 0 : el.ownerDocument.defaultView) != null ? _a : window;
262
297
  }
263
298
  function getDescriptor(el, options) {
299
+ var _a;
264
300
  const { type, property } = options;
265
301
  const proto = getWindow(el)[type].prototype;
266
- return Object.getOwnPropertyDescriptor(proto, property) ?? {};
302
+ return (_a = Object.getOwnPropertyDescriptor(proto, property)) != null ? _a : {};
267
303
  }
268
304
  function dispatchInputValueEvent(el, value) {
269
305
  var _a;
@@ -280,7 +316,8 @@ function dispatchInputValueEvent(el, value) {
280
316
 
281
317
  // src/pin-input.machine.ts
282
318
  var { and, not } = guards;
283
- function machine(ctx) {
319
+ function machine(userContext) {
320
+ const ctx = compact(userContext);
284
321
  return createMachine(
285
322
  {
286
323
  id: "pin-input",
@@ -301,11 +338,12 @@ function machine(ctx) {
301
338
  valueLength: (ctx2) => ctx2.value.length,
302
339
  filledValueLength: (ctx2) => ctx2.value.filter((v) => (v == null ? void 0 : v.trim()) !== "").length,
303
340
  isValueComplete: (ctx2) => ctx2.valueLength === ctx2.filledValueLength,
304
- valueAsString: (ctx2) => ctx2.value.join("")
341
+ valueAsString: (ctx2) => ctx2.value.join(""),
342
+ focusedValue: (ctx2) => ctx2.value[ctx2.focusedIndex]
305
343
  },
306
344
  watch: {
307
- focusedIndex: "focusInput",
308
- value: "invokeOnChange",
345
+ focusedIndex: ["focusInput", "setInputSelection"],
346
+ value: ["invokeOnChange", "dispatchInputEvent"],
309
347
  isValueComplete: ["invokeOnComplete", "blurFocusedInputIfNeeded"]
310
348
  },
311
349
  on: {
@@ -355,17 +393,20 @@ function machine(ctx) {
355
393
  INPUT: [
356
394
  {
357
395
  guard: and("isFinalValue", "isValidValue"),
358
- actions: "setFocusedValue"
396
+ actions: ["setFocusedValue", "dispatchInputEventIfNeeded"]
359
397
  },
360
398
  {
361
399
  guard: "isValidValue",
362
- actions: ["setFocusedValue", "setNextFocusedIndex"]
400
+ actions: ["setFocusedValue", "setNextFocusedIndex", "dispatchInputEventIfNeeded"]
363
401
  }
364
402
  ],
365
- PASTE: {
366
- guard: "isValidValue",
367
- actions: ["setPastedValue", "setLastValueFocusIndex"]
368
- },
403
+ PASTE: [
404
+ {
405
+ guard: "isValidValue",
406
+ actions: ["setPastedValue", "setLastValueFocusIndex"]
407
+ },
408
+ { actions: "resetFocusedValue" }
409
+ ],
369
410
  BLUR: {
370
411
  target: "idle",
371
412
  actions: "clearFocusedIndex"
@@ -434,6 +475,16 @@ function machine(ctx) {
434
475
  (_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.focus();
435
476
  });
436
477
  },
478
+ setInputSelection: (ctx2) => {
479
+ raf(() => {
480
+ if (ctx2.focusedIndex === -1)
481
+ return;
482
+ const input = dom.getFocusedEl(ctx2);
483
+ const length = input.value.length;
484
+ input.selectionStart = ctx2.selectOnFocus ? 0 : length;
485
+ input.selectionEnd = length;
486
+ });
487
+ },
437
488
  invokeOnComplete: (ctx2) => {
438
489
  var _a;
439
490
  if (!ctx2.isValueComplete)
@@ -445,7 +496,16 @@ function machine(ctx) {
445
496
  if (evt.type === "SETUP")
446
497
  return;
447
498
  (_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value) });
499
+ },
500
+ dispatchInputEvent: (ctx2, evt) => {
501
+ if (evt.type === "SETUP")
502
+ return;
448
503
  dispatchInputValueEvent(dom.getHiddenInputEl(ctx2), ctx2.valueAsString);
504
+ const inputs = dom.getElements(ctx2);
505
+ ctx2.value.forEach((val, index) => {
506
+ const input = inputs[index];
507
+ input.value = val || "";
508
+ });
449
509
  },
450
510
  invokeOnInvalid: (ctx2, evt) => {
451
511
  var _a;
@@ -463,21 +523,34 @@ function machine(ctx) {
463
523
  setFocusedValue: (ctx2, evt) => {
464
524
  ctx2.value[ctx2.focusedIndex] = lastChar(evt.value);
465
525
  },
526
+ dispatchInputEventIfNeeded: (ctx2, evt) => {
527
+ const valueIsChanged = lastChar(evt.value) !== ctx2.focusedValue;
528
+ if (evt.value.length <= 1 || valueIsChanged)
529
+ return;
530
+ const inputs = dom.getElements(ctx2);
531
+ const input = inputs[ctx2.focusedIndex];
532
+ input.value = lastChar(evt.value);
533
+ },
466
534
  setPastedValue(ctx2, evt) {
467
535
  raf(() => {
468
- const value = evt.value.substring(0, ctx2.valueLength);
469
- assign(ctx2, value.split("").filter(Boolean));
536
+ const startIndex = ctx2.focusedValue ? 1 : 0;
537
+ const value = evt.value.substring(startIndex, ctx2.valueLength);
538
+ assign(ctx2, value);
470
539
  });
471
540
  },
472
541
  setValueAtIndex: (ctx2, evt) => {
473
542
  ctx2.value[evt.index] = lastChar(evt.value);
474
543
  },
475
544
  clearValue: (ctx2) => {
476
- assign(ctx2, "");
545
+ ctx2.value = ctx2.value.map(() => "");
477
546
  },
478
547
  clearFocusedValue: (ctx2) => {
479
548
  ctx2.value[ctx2.focusedIndex] = "";
480
549
  },
550
+ resetFocusedValue: (ctx2) => {
551
+ const input = dom.getFocusedEl(ctx2);
552
+ input.value = ctx2.focusedValue;
553
+ },
481
554
  setFocusIndexToFirst: (ctx2) => {
482
555
  ctx2.focusedIndex = 0;
483
556
  },
@@ -526,16 +599,10 @@ function isValidType(value, type) {
526
599
  return !!((_a = REGEX[type]) == null ? void 0 : _a.test(value));
527
600
  }
528
601
  function assign(ctx, value) {
529
- const len = ctx.value.length;
530
- for (let i = 0; i < len; i++) {
531
- if (Array.isArray(value)) {
532
- if (!value[i])
533
- continue;
534
- ctx.value[i] = value[i];
535
- } else {
536
- ctx.value[i] = value;
537
- }
538
- }
602
+ const valueArr = value.split("").filter(Boolean);
603
+ const valueObj = Object.assign({}, ctx.value, valueArr);
604
+ console.log("valueObj :>> ", valueObj);
605
+ ctx.value = Object.values(valueObj);
539
606
  }
540
607
  function lastChar(value) {
541
608
  return value.charAt(value.length - 1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zag-js/pin-input",
3
- "version": "0.1.17",
3
+ "version": "0.2.1",
4
4
  "description": "Core logic for the pin-input widget implemented as a state machine",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -29,13 +29,13 @@
29
29
  "url": "https://github.com/chakra-ui/zag/issues"
30
30
  },
31
31
  "dependencies": {
32
- "@zag-js/core": "0.1.12",
33
- "@zag-js/types": "0.2.7"
32
+ "@zag-js/core": "0.2.1",
33
+ "@zag-js/types": "0.3.0"
34
34
  },
35
35
  "devDependencies": {
36
- "@zag-js/dom-utils": "0.1.13",
37
- "@zag-js/form-utils": "0.1.3",
38
- "@zag-js/utils": "0.1.6"
36
+ "@zag-js/dom-utils": "0.2.0",
37
+ "@zag-js/form-utils": "0.2.0",
38
+ "@zag-js/utils": "0.3.0"
39
39
  },
40
40
  "scripts": {
41
41
  "build-fast": "tsup src/index.ts --format=esm,cjs",