@zag-js/pin-input 0.2.8 → 0.2.10

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.
@@ -4,7 +4,7 @@ import {
4
4
  import {
5
5
  dom,
6
6
  getWindow
7
- } from "./chunk-APRO2TYE.mjs";
7
+ } from "./chunk-T5OKDF74.mjs";
8
8
 
9
9
  // src/pin-input.machine.ts
10
10
  import { createMachine, guards } from "@zag-js/core";
@@ -28,20 +28,18 @@ function raf(fn) {
28
28
 
29
29
  // ../../utilities/form-utils/src/input-event.ts
30
30
  function getDescriptor(el, options) {
31
- var _a;
32
31
  const { type, property = "value" } = options;
33
32
  const proto = getWindow(el)[type].prototype;
34
- return (_a = Object.getOwnPropertyDescriptor(proto, property)) != null ? _a : {};
33
+ return Object.getOwnPropertyDescriptor(proto, property) ?? {};
35
34
  }
36
35
  function dispatchInputValueEvent(el, value) {
37
- var _a;
38
36
  if (!el)
39
37
  return;
40
38
  const win = getWindow(el);
41
39
  if (!(el instanceof win.HTMLInputElement))
42
40
  return;
43
41
  const desc = getDescriptor(el, { type: "HTMLInputElement", property: "value" });
44
- (_a = desc.set) == null ? void 0 : _a.call(el, value);
42
+ desc.set?.call(el, value);
45
43
  const event = new win.Event("input", { bubbles: true });
46
44
  el.dispatchEvent(event);
47
45
  }
@@ -53,10 +51,10 @@ function machine(userContext) {
53
51
  return createMachine(
54
52
  {
55
53
  id: "pin-input",
56
- initial: "unknown",
54
+ initial: ctx.autoFocus ? "focused" : "idle",
57
55
  context: {
58
56
  value: [],
59
- focusedIndex: -1,
57
+ focusedIndex: ctx.autoFocus ? 0 : -1,
60
58
  placeholder: "\u25CB",
61
59
  otp: false,
62
60
  type: "numeric",
@@ -68,7 +66,7 @@ function machine(userContext) {
68
66
  },
69
67
  computed: {
70
68
  valueLength: (ctx2) => ctx2.value.length,
71
- filledValueLength: (ctx2) => ctx2.value.filter((v) => (v == null ? void 0 : v.trim()) !== "").length,
69
+ filledValueLength: (ctx2) => ctx2.value.filter((v) => v?.trim() !== "").length,
72
70
  isValueComplete: (ctx2) => ctx2.valueLength === ctx2.filledValueLength,
73
71
  valueAsString: (ctx2) => ctx2.value.join(""),
74
72
  focusedValue: (ctx2) => ctx2.value[ctx2.focusedIndex]
@@ -78,6 +76,7 @@ function machine(userContext) {
78
76
  value: ["dispatchInputEvent"],
79
77
  isValueComplete: ["invokeOnComplete", "blurFocusedInputIfNeeded"]
80
78
  },
79
+ entry: ["setupValue"],
81
80
  on: {
82
81
  SET_VALUE: [
83
82
  {
@@ -97,21 +96,6 @@ function machine(userContext) {
97
96
  ]
98
97
  },
99
98
  states: {
100
- unknown: {
101
- on: {
102
- SETUP: [
103
- {
104
- guard: "autoFocus",
105
- target: "focused",
106
- actions: ["setupValue", "setFocusIndexToFirst"]
107
- },
108
- {
109
- target: "idle",
110
- actions: "setupValue"
111
- }
112
- ]
113
- }
114
- },
115
99
  idle: {
116
100
  on: {
117
101
  FOCUS: {
@@ -125,11 +109,11 @@ function machine(userContext) {
125
109
  INPUT: [
126
110
  {
127
111
  guard: and("isFinalValue", "isValidValue"),
128
- actions: ["setFocusedValue", "invokeOnChange", "dispatchInputEventIfNeeded"]
112
+ actions: ["setFocusedValue", "invokeOnChange", "syncInputValue"]
129
113
  },
130
114
  {
131
115
  guard: "isValidValue",
132
- actions: ["setFocusedValue", "invokeOnChange", "setNextFocusedIndex", "dispatchInputEventIfNeeded"]
116
+ actions: ["setFocusedValue", "invokeOnChange", "setNextFocusedIndex", "syncInputValue"]
133
117
  }
134
118
  ],
135
119
  PASTE: [
@@ -196,15 +180,14 @@ function machine(userContext) {
196
180
  actions: {
197
181
  setupValue: (ctx2) => {
198
182
  const inputs = dom.getElements(ctx2);
199
- const empty = Array.from({ length: inputs.length }).map(() => "");
200
- ctx2.value = Object.assign(empty, ctx2.value);
183
+ const emptyValues = Array.from({ length: inputs.length }).fill("");
184
+ assign(ctx2, emptyValues);
201
185
  },
202
186
  focusInput: (ctx2) => {
203
187
  raf(() => {
204
- var _a;
205
188
  if (ctx2.focusedIndex === -1)
206
189
  return;
207
- (_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.focus();
190
+ dom.getFocusedEl(ctx2)?.focus();
208
191
  });
209
192
  },
210
193
  setInputSelection: (ctx2) => {
@@ -218,16 +201,14 @@ function machine(userContext) {
218
201
  });
219
202
  },
220
203
  invokeOnComplete: (ctx2) => {
221
- var _a;
222
204
  if (!ctx2.isValueComplete)
223
205
  return;
224
- (_a = ctx2.onComplete) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value), valueAsString: ctx2.valueAsString });
206
+ ctx2.onComplete?.({ value: Array.from(ctx2.value), valueAsString: ctx2.valueAsString });
225
207
  },
226
208
  invokeOnChange: (ctx2, evt) => {
227
- var _a;
228
209
  if (evt.type === "SETUP")
229
210
  return;
230
- (_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value) });
211
+ ctx2.onChange?.({ value: Array.from(ctx2.value) });
231
212
  },
232
213
  dispatchInputEvent: (ctx2, evt) => {
233
214
  if (evt.type === "SETUP")
@@ -240,8 +221,7 @@ function machine(userContext) {
240
221
  });
241
222
  },
242
223
  invokeOnInvalid: (ctx2, evt) => {
243
- var _a;
244
- (_a = ctx2.onInvalid) == null ? void 0 : _a.call(ctx2, { value: evt.value, index: ctx2.focusedIndex });
224
+ ctx2.onInvalid?.({ value: evt.value, index: ctx2.focusedIndex });
245
225
  },
246
226
  clearFocusedIndex: (ctx2) => {
247
227
  ctx2.focusedIndex = -1;
@@ -253,15 +233,16 @@ function machine(userContext) {
253
233
  ctx2.focusedIndex = evt.index;
254
234
  },
255
235
  setFocusedValue: (ctx2, evt) => {
256
- ctx2.value[ctx2.focusedIndex] = lastChar(evt.value);
236
+ ctx2.value[ctx2.focusedIndex] = getNextValue(ctx2.focusedValue, evt.value);
257
237
  },
258
- dispatchInputEventIfNeeded: (ctx2, evt) => {
259
- const valueIsChanged = lastChar(evt.value) !== ctx2.focusedValue;
260
- if (evt.value.length <= 1 || valueIsChanged)
238
+ syncInputValue: (ctx2, evt) => {
239
+ const nextValue = getNextValue(ctx2.focusedValue, evt.value);
240
+ const changed = nextValue !== ctx2.focusedValue;
241
+ if (evt.value.length <= 1 || changed)
261
242
  return;
262
243
  const inputs = dom.getElements(ctx2);
263
244
  const input = inputs[ctx2.focusedIndex];
264
- input.value = lastChar(evt.value);
245
+ input.value = nextValue;
265
246
  },
266
247
  setPastedValue(ctx2, evt) {
267
248
  raf(() => {
@@ -271,10 +252,11 @@ function machine(userContext) {
271
252
  });
272
253
  },
273
254
  setValueAtIndex: (ctx2, evt) => {
274
- ctx2.value[evt.index] = lastChar(evt.value);
255
+ ctx2.value[evt.index] = getNextValue(ctx2.focusedValue, evt.value);
275
256
  },
276
257
  clearValue: (ctx2) => {
277
- ctx2.value = ctx2.value.map(() => "");
258
+ const nextValue = Array.from({ length: ctx2.valueLength }).fill("");
259
+ assign(ctx2, nextValue);
278
260
  },
279
261
  clearFocusedValue: (ctx2) => {
280
262
  ctx2.value[ctx2.focusedIndex] = "";
@@ -304,16 +286,14 @@ function machine(userContext) {
304
286
  if (!ctx2.blurOnComplete)
305
287
  return;
306
288
  raf(() => {
307
- var _a;
308
- (_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.blur();
289
+ dom.getFocusedEl(ctx2)?.blur();
309
290
  });
310
291
  },
311
292
  requestFormSubmit(ctx2) {
312
- var _a;
313
- if (!ctx2.name)
293
+ if (!ctx2.name || !ctx2.isValueComplete)
314
294
  return;
315
295
  const input = dom.getHiddenInputEl(ctx2);
316
- (_a = input == null ? void 0 : input.form) == null ? void 0 : _a.requestSubmit();
296
+ input?.form?.requestSubmit();
317
297
  }
318
298
  }
319
299
  }
@@ -325,18 +305,23 @@ var REGEX = {
325
305
  alphanumeric: /^[a-zA-Z0-9]+$/i
326
306
  };
327
307
  function isValidType(value, type) {
328
- var _a;
329
308
  if (!type)
330
309
  return true;
331
- return !!((_a = REGEX[type]) == null ? void 0 : _a.test(value));
310
+ return !!REGEX[type]?.test(value);
332
311
  }
333
312
  function assign(ctx, value) {
334
- const valueArr = Array.isArray(value) ? value : value.split("").filter(Boolean);
335
- const valueObj = Object.assign({}, ctx.value, valueArr);
336
- ctx.value = Object.values(valueObj);
313
+ const arr = Array.isArray(value) ? value : value.split("").filter(Boolean);
314
+ arr.forEach((value2, index) => {
315
+ ctx.value[index] = value2;
316
+ });
337
317
  }
338
- function lastChar(value) {
339
- return value.charAt(value.length - 1);
318
+ function getNextValue(current, next) {
319
+ let nextValue = next;
320
+ if (current[0] === next[0])
321
+ nextValue = next[1];
322
+ else if (current[0] === next[1])
323
+ nextValue = next[0];
324
+ return nextValue;
340
325
  }
341
326
 
342
327
  export {
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-BJXKBZJG.mjs";
4
4
  import {
5
5
  dom
6
- } from "./chunk-APRO2TYE.mjs";
6
+ } from "./chunk-T5OKDF74.mjs";
7
7
 
8
8
  // ../../utilities/dom/src/attrs.ts
9
9
  var dataAttr = (guard) => {
@@ -24,8 +24,7 @@ function invariant(...a) {
24
24
 
25
25
  // ../../utilities/dom/src/event.ts
26
26
  function getNativeEvent(e) {
27
- var _a;
28
- return (_a = e.nativeEvent) != null ? _a : e;
27
+ return e.nativeEvent ?? e;
29
28
  }
30
29
  var isModifiedEvent = (v) => v.ctrlKey || v.altKey || v.metaKey;
31
30
 
@@ -44,10 +43,9 @@ var sameKeyMap = {
44
43
  Right: "ArrowRight"
45
44
  };
46
45
  function getEventKey(event, options = {}) {
47
- var _a;
48
46
  const { dir = "ltr", orientation = "horizontal" } = options;
49
47
  let { key } = event;
50
- key = (_a = sameKeyMap[key]) != null ? _a : key;
48
+ key = sameKeyMap[key] ?? key;
51
49
  const isRtl = dir === "rtl" && orientation === "horizontal";
52
50
  if (isRtl && key in rtlKeyMap) {
53
51
  key = rtlKeyMap[key];
@@ -76,8 +74,7 @@ function connect(state, send, normalize) {
76
74
  const focusedIndex = state.context.focusedIndex;
77
75
  const translations = state.context.translations;
78
76
  function focus() {
79
- var _a;
80
- (_a = dom.getFirstInputEl(state.context)) == null ? void 0 : _a.focus();
77
+ dom.getFirstInputEl(state.context)?.focus();
81
78
  }
82
79
  return {
83
80
  value: state.context.value,
@@ -0,0 +1,58 @@
1
+ // ../../utilities/dom/src/query.ts
2
+ function isDocument(el) {
3
+ return el.nodeType === Node.DOCUMENT_NODE;
4
+ }
5
+ function isWindow(value) {
6
+ return value?.toString() === "[object Window]";
7
+ }
8
+ function getDocument(el) {
9
+ if (isWindow(el))
10
+ return el.document;
11
+ if (isDocument(el))
12
+ return el;
13
+ return el?.ownerDocument ?? document;
14
+ }
15
+ function getWindow(el) {
16
+ return el?.ownerDocument.defaultView ?? window;
17
+ }
18
+ function defineDomHelpers(helpers) {
19
+ const dom2 = {
20
+ getRootNode: (ctx) => ctx.getRootNode?.() ?? document,
21
+ getDoc: (ctx) => getDocument(dom2.getRootNode(ctx)),
22
+ getWin: (ctx) => dom2.getDoc(ctx).defaultView ?? window,
23
+ getActiveElement: (ctx) => dom2.getDoc(ctx).activeElement,
24
+ getById: (ctx, id) => dom2.getRootNode(ctx).getElementById(id)
25
+ };
26
+ return {
27
+ ...dom2,
28
+ ...helpers
29
+ };
30
+ }
31
+
32
+ // ../../utilities/dom/src/nodelist.ts
33
+ function queryAll(root, selector) {
34
+ return Array.from(root?.querySelectorAll(selector) ?? []);
35
+ }
36
+
37
+ // src/pin-input.dom.ts
38
+ var dom = defineDomHelpers({
39
+ getRootId: (ctx) => ctx.ids?.root ?? `pin-input:${ctx.id}`,
40
+ getInputId: (ctx, id) => ctx.ids?.input?.(id) ?? `pin-input:${ctx.id}:${id}`,
41
+ getHiddenInputId: (ctx) => ctx.ids?.hiddenInput ?? `pin-input:${ctx.id}:hidden`,
42
+ getLabelId: (ctx) => ctx.ids?.label ?? `pin-input:${ctx.id}:label`,
43
+ getControlId: (ctx) => ctx.ids?.control ?? `pin-input:${ctx.id}:control`,
44
+ getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
45
+ getElements: (ctx) => {
46
+ const ownerId = CSS.escape(dom.getRootId(ctx));
47
+ const selector = `input[data-ownedby=${ownerId}]`;
48
+ return queryAll(dom.getRootEl(ctx), selector);
49
+ },
50
+ getFocusedEl: (ctx) => dom.getElements(ctx)[ctx.focusedIndex],
51
+ getFirstInputEl: (ctx) => dom.getElements(ctx)[0],
52
+ getHiddenInputEl: (ctx) => dom.getById(ctx, dom.getHiddenInputId(ctx))
53
+ });
54
+
55
+ export {
56
+ getWindow,
57
+ dom
58
+ };
package/dist/index.js CHANGED
@@ -66,31 +66,23 @@ function isDocument(el) {
66
66
  return el.nodeType === Node.DOCUMENT_NODE;
67
67
  }
68
68
  function isWindow(value) {
69
- return (value == null ? void 0 : value.toString()) === "[object Window]";
69
+ return value?.toString() === "[object Window]";
70
70
  }
71
71
  function getDocument(el) {
72
- var _a;
73
72
  if (isWindow(el))
74
73
  return el.document;
75
74
  if (isDocument(el))
76
75
  return el;
77
- return (_a = el == null ? void 0 : el.ownerDocument) != null ? _a : document;
76
+ return el?.ownerDocument ?? document;
78
77
  }
79
78
  function getWindow(el) {
80
- var _a;
81
- return (_a = el == null ? void 0 : el.ownerDocument.defaultView) != null ? _a : window;
79
+ return el?.ownerDocument.defaultView ?? window;
82
80
  }
83
81
  function defineDomHelpers(helpers) {
84
82
  const dom2 = {
85
- getRootNode: (ctx) => {
86
- var _a, _b;
87
- return (_b = (_a = ctx.getRootNode) == null ? void 0 : _a.call(ctx)) != null ? _b : document;
88
- },
83
+ getRootNode: (ctx) => ctx.getRootNode?.() ?? document,
89
84
  getDoc: (ctx) => getDocument(dom2.getRootNode(ctx)),
90
- getWin: (ctx) => {
91
- var _a;
92
- return (_a = dom2.getDoc(ctx).defaultView) != null ? _a : window;
93
- },
85
+ getWin: (ctx) => dom2.getDoc(ctx).defaultView ?? window,
94
86
  getActiveElement: (ctx) => dom2.getDoc(ctx).activeElement,
95
87
  getById: (ctx, id) => dom2.getRootNode(ctx).getElementById(id)
96
88
  };
@@ -102,8 +94,7 @@ function defineDomHelpers(helpers) {
102
94
 
103
95
  // ../../utilities/dom/src/event.ts
104
96
  function getNativeEvent(e) {
105
- var _a;
106
- return (_a = e.nativeEvent) != null ? _a : e;
97
+ return e.nativeEvent ?? e;
107
98
  }
108
99
  var isModifiedEvent = (v) => v.ctrlKey || v.altKey || v.metaKey;
109
100
 
@@ -122,10 +113,9 @@ var sameKeyMap = {
122
113
  Right: "ArrowRight"
123
114
  };
124
115
  function getEventKey(event, options = {}) {
125
- var _a;
126
116
  const { dir = "ltr", orientation = "horizontal" } = options;
127
117
  let { key } = event;
128
- key = (_a = sameKeyMap[key]) != null ? _a : key;
118
+ key = sameKeyMap[key] ?? key;
129
119
  const isRtl = dir === "rtl" && orientation === "horizontal";
130
120
  if (isRtl && key in rtlKeyMap) {
131
121
  key = rtlKeyMap[key];
@@ -143,8 +133,7 @@ function raf(fn) {
143
133
 
144
134
  // ../../utilities/dom/src/nodelist.ts
145
135
  function queryAll(root, selector) {
146
- var _a;
147
- return Array.from((_a = root == null ? void 0 : root.querySelectorAll(selector)) != null ? _a : []);
136
+ return Array.from(root?.querySelectorAll(selector) ?? []);
148
137
  }
149
138
 
150
139
  // ../../utilities/dom/src/visually-hidden.ts
@@ -163,26 +152,11 @@ var visuallyHiddenStyle = {
163
152
 
164
153
  // src/pin-input.dom.ts
165
154
  var dom = defineDomHelpers({
166
- getRootId: (ctx) => {
167
- var _a, _b;
168
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.root) != null ? _b : `pin-input:${ctx.id}`;
169
- },
170
- getInputId: (ctx, id) => {
171
- var _a, _b, _c;
172
- 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}`;
173
- },
174
- getHiddenInputId: (ctx) => {
175
- var _a, _b;
176
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.hiddenInput) != null ? _b : `pin-input:${ctx.id}:hidden`;
177
- },
178
- getLabelId: (ctx) => {
179
- var _a, _b;
180
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.label) != null ? _b : `pin-input:${ctx.id}:label`;
181
- },
182
- getControlId: (ctx) => {
183
- var _a, _b;
184
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.control) != null ? _b : `pin-input:${ctx.id}:control`;
185
- },
155
+ getRootId: (ctx) => ctx.ids?.root ?? `pin-input:${ctx.id}`,
156
+ getInputId: (ctx, id) => ctx.ids?.input?.(id) ?? `pin-input:${ctx.id}:${id}`,
157
+ getHiddenInputId: (ctx) => ctx.ids?.hiddenInput ?? `pin-input:${ctx.id}:hidden`,
158
+ getLabelId: (ctx) => ctx.ids?.label ?? `pin-input:${ctx.id}:label`,
159
+ getControlId: (ctx) => ctx.ids?.control ?? `pin-input:${ctx.id}:control`,
186
160
  getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
187
161
  getElements: (ctx) => {
188
162
  const ownerId = CSS.escape(dom.getRootId(ctx));
@@ -201,8 +175,7 @@ function connect(state, send, normalize) {
201
175
  const focusedIndex = state.context.focusedIndex;
202
176
  const translations = state.context.translations;
203
177
  function focus() {
204
- var _a;
205
- (_a = dom.getFirstInputEl(state.context)) == null ? void 0 : _a.focus();
178
+ dom.getFirstInputEl(state.context)?.focus();
206
179
  }
207
180
  return {
208
181
  value: state.context.value,
@@ -337,20 +310,18 @@ var import_core = require("@zag-js/core");
337
310
 
338
311
  // ../../utilities/form-utils/src/input-event.ts
339
312
  function getDescriptor(el, options) {
340
- var _a;
341
313
  const { type, property = "value" } = options;
342
314
  const proto = getWindow(el)[type].prototype;
343
- return (_a = Object.getOwnPropertyDescriptor(proto, property)) != null ? _a : {};
315
+ return Object.getOwnPropertyDescriptor(proto, property) ?? {};
344
316
  }
345
317
  function dispatchInputValueEvent(el, value) {
346
- var _a;
347
318
  if (!el)
348
319
  return;
349
320
  const win = getWindow(el);
350
321
  if (!(el instanceof win.HTMLInputElement))
351
322
  return;
352
323
  const desc = getDescriptor(el, { type: "HTMLInputElement", property: "value" });
353
- (_a = desc.set) == null ? void 0 : _a.call(el, value);
324
+ desc.set?.call(el, value);
354
325
  const event = new win.Event("input", { bubbles: true });
355
326
  el.dispatchEvent(event);
356
327
  }
@@ -362,10 +333,10 @@ function machine(userContext) {
362
333
  return (0, import_core.createMachine)(
363
334
  {
364
335
  id: "pin-input",
365
- initial: "unknown",
336
+ initial: ctx.autoFocus ? "focused" : "idle",
366
337
  context: {
367
338
  value: [],
368
- focusedIndex: -1,
339
+ focusedIndex: ctx.autoFocus ? 0 : -1,
369
340
  placeholder: "\u25CB",
370
341
  otp: false,
371
342
  type: "numeric",
@@ -377,7 +348,7 @@ function machine(userContext) {
377
348
  },
378
349
  computed: {
379
350
  valueLength: (ctx2) => ctx2.value.length,
380
- filledValueLength: (ctx2) => ctx2.value.filter((v) => (v == null ? void 0 : v.trim()) !== "").length,
351
+ filledValueLength: (ctx2) => ctx2.value.filter((v) => v?.trim() !== "").length,
381
352
  isValueComplete: (ctx2) => ctx2.valueLength === ctx2.filledValueLength,
382
353
  valueAsString: (ctx2) => ctx2.value.join(""),
383
354
  focusedValue: (ctx2) => ctx2.value[ctx2.focusedIndex]
@@ -387,6 +358,7 @@ function machine(userContext) {
387
358
  value: ["dispatchInputEvent"],
388
359
  isValueComplete: ["invokeOnComplete", "blurFocusedInputIfNeeded"]
389
360
  },
361
+ entry: ["setupValue"],
390
362
  on: {
391
363
  SET_VALUE: [
392
364
  {
@@ -406,21 +378,6 @@ function machine(userContext) {
406
378
  ]
407
379
  },
408
380
  states: {
409
- unknown: {
410
- on: {
411
- SETUP: [
412
- {
413
- guard: "autoFocus",
414
- target: "focused",
415
- actions: ["setupValue", "setFocusIndexToFirst"]
416
- },
417
- {
418
- target: "idle",
419
- actions: "setupValue"
420
- }
421
- ]
422
- }
423
- },
424
381
  idle: {
425
382
  on: {
426
383
  FOCUS: {
@@ -434,11 +391,11 @@ function machine(userContext) {
434
391
  INPUT: [
435
392
  {
436
393
  guard: and("isFinalValue", "isValidValue"),
437
- actions: ["setFocusedValue", "invokeOnChange", "dispatchInputEventIfNeeded"]
394
+ actions: ["setFocusedValue", "invokeOnChange", "syncInputValue"]
438
395
  },
439
396
  {
440
397
  guard: "isValidValue",
441
- actions: ["setFocusedValue", "invokeOnChange", "setNextFocusedIndex", "dispatchInputEventIfNeeded"]
398
+ actions: ["setFocusedValue", "invokeOnChange", "setNextFocusedIndex", "syncInputValue"]
442
399
  }
443
400
  ],
444
401
  PASTE: [
@@ -505,15 +462,14 @@ function machine(userContext) {
505
462
  actions: {
506
463
  setupValue: (ctx2) => {
507
464
  const inputs = dom.getElements(ctx2);
508
- const empty = Array.from({ length: inputs.length }).map(() => "");
509
- ctx2.value = Object.assign(empty, ctx2.value);
465
+ const emptyValues = Array.from({ length: inputs.length }).fill("");
466
+ assign(ctx2, emptyValues);
510
467
  },
511
468
  focusInput: (ctx2) => {
512
469
  raf(() => {
513
- var _a;
514
470
  if (ctx2.focusedIndex === -1)
515
471
  return;
516
- (_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.focus();
472
+ dom.getFocusedEl(ctx2)?.focus();
517
473
  });
518
474
  },
519
475
  setInputSelection: (ctx2) => {
@@ -527,16 +483,14 @@ function machine(userContext) {
527
483
  });
528
484
  },
529
485
  invokeOnComplete: (ctx2) => {
530
- var _a;
531
486
  if (!ctx2.isValueComplete)
532
487
  return;
533
- (_a = ctx2.onComplete) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value), valueAsString: ctx2.valueAsString });
488
+ ctx2.onComplete?.({ value: Array.from(ctx2.value), valueAsString: ctx2.valueAsString });
534
489
  },
535
490
  invokeOnChange: (ctx2, evt) => {
536
- var _a;
537
491
  if (evt.type === "SETUP")
538
492
  return;
539
- (_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value) });
493
+ ctx2.onChange?.({ value: Array.from(ctx2.value) });
540
494
  },
541
495
  dispatchInputEvent: (ctx2, evt) => {
542
496
  if (evt.type === "SETUP")
@@ -549,8 +503,7 @@ function machine(userContext) {
549
503
  });
550
504
  },
551
505
  invokeOnInvalid: (ctx2, evt) => {
552
- var _a;
553
- (_a = ctx2.onInvalid) == null ? void 0 : _a.call(ctx2, { value: evt.value, index: ctx2.focusedIndex });
506
+ ctx2.onInvalid?.({ value: evt.value, index: ctx2.focusedIndex });
554
507
  },
555
508
  clearFocusedIndex: (ctx2) => {
556
509
  ctx2.focusedIndex = -1;
@@ -562,15 +515,16 @@ function machine(userContext) {
562
515
  ctx2.focusedIndex = evt.index;
563
516
  },
564
517
  setFocusedValue: (ctx2, evt) => {
565
- ctx2.value[ctx2.focusedIndex] = lastChar(evt.value);
518
+ ctx2.value[ctx2.focusedIndex] = getNextValue(ctx2.focusedValue, evt.value);
566
519
  },
567
- dispatchInputEventIfNeeded: (ctx2, evt) => {
568
- const valueIsChanged = lastChar(evt.value) !== ctx2.focusedValue;
569
- if (evt.value.length <= 1 || valueIsChanged)
520
+ syncInputValue: (ctx2, evt) => {
521
+ const nextValue = getNextValue(ctx2.focusedValue, evt.value);
522
+ const changed = nextValue !== ctx2.focusedValue;
523
+ if (evt.value.length <= 1 || changed)
570
524
  return;
571
525
  const inputs = dom.getElements(ctx2);
572
526
  const input = inputs[ctx2.focusedIndex];
573
- input.value = lastChar(evt.value);
527
+ input.value = nextValue;
574
528
  },
575
529
  setPastedValue(ctx2, evt) {
576
530
  raf(() => {
@@ -580,10 +534,11 @@ function machine(userContext) {
580
534
  });
581
535
  },
582
536
  setValueAtIndex: (ctx2, evt) => {
583
- ctx2.value[evt.index] = lastChar(evt.value);
537
+ ctx2.value[evt.index] = getNextValue(ctx2.focusedValue, evt.value);
584
538
  },
585
539
  clearValue: (ctx2) => {
586
- ctx2.value = ctx2.value.map(() => "");
540
+ const nextValue = Array.from({ length: ctx2.valueLength }).fill("");
541
+ assign(ctx2, nextValue);
587
542
  },
588
543
  clearFocusedValue: (ctx2) => {
589
544
  ctx2.value[ctx2.focusedIndex] = "";
@@ -613,16 +568,14 @@ function machine(userContext) {
613
568
  if (!ctx2.blurOnComplete)
614
569
  return;
615
570
  raf(() => {
616
- var _a;
617
- (_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.blur();
571
+ dom.getFocusedEl(ctx2)?.blur();
618
572
  });
619
573
  },
620
574
  requestFormSubmit(ctx2) {
621
- var _a;
622
- if (!ctx2.name)
575
+ if (!ctx2.name || !ctx2.isValueComplete)
623
576
  return;
624
577
  const input = dom.getHiddenInputEl(ctx2);
625
- (_a = input == null ? void 0 : input.form) == null ? void 0 : _a.requestSubmit();
578
+ input?.form?.requestSubmit();
626
579
  }
627
580
  }
628
581
  }
@@ -634,18 +587,23 @@ var REGEX = {
634
587
  alphanumeric: /^[a-zA-Z0-9]+$/i
635
588
  };
636
589
  function isValidType(value, type) {
637
- var _a;
638
590
  if (!type)
639
591
  return true;
640
- return !!((_a = REGEX[type]) == null ? void 0 : _a.test(value));
592
+ return !!REGEX[type]?.test(value);
641
593
  }
642
594
  function assign(ctx, value) {
643
- const valueArr = Array.isArray(value) ? value : value.split("").filter(Boolean);
644
- const valueObj = Object.assign({}, ctx.value, valueArr);
645
- ctx.value = Object.values(valueObj);
595
+ const arr = Array.isArray(value) ? value : value.split("").filter(Boolean);
596
+ arr.forEach((value2, index) => {
597
+ ctx.value[index] = value2;
598
+ });
646
599
  }
647
- function lastChar(value) {
648
- return value.charAt(value.length - 1);
600
+ function getNextValue(current, next) {
601
+ let nextValue = next;
602
+ if (current[0] === next[0])
603
+ nextValue = next[1];
604
+ else if (current[0] === next[1])
605
+ nextValue = next[0];
606
+ return nextValue;
649
607
  }
650
608
  // Annotate the CommonJS export names for ESM import in node:
651
609
  0 && (module.exports = {
package/dist/index.mjs CHANGED
@@ -1,14 +1,14 @@
1
1
  import {
2
2
  connect
3
- } from "./chunk-3SENCEI3.mjs";
3
+ } from "./chunk-QVOI2QEW.mjs";
4
4
  import {
5
5
  anatomy
6
6
  } from "./chunk-BJXKBZJG.mjs";
7
7
  import {
8
8
  machine
9
- } from "./chunk-CDDLX3AG.mjs";
9
+ } from "./chunk-53K4IC6M.mjs";
10
10
  import "./chunk-NT4W6JYX.mjs";
11
- import "./chunk-APRO2TYE.mjs";
11
+ import "./chunk-T5OKDF74.mjs";
12
12
  export {
13
13
  anatomy,
14
14
  connect,
@@ -46,27 +46,20 @@ function isDocument(el) {
46
46
  return el.nodeType === Node.DOCUMENT_NODE;
47
47
  }
48
48
  function isWindow(value) {
49
- return (value == null ? void 0 : value.toString()) === "[object Window]";
49
+ return value?.toString() === "[object Window]";
50
50
  }
51
51
  function getDocument(el) {
52
- var _a;
53
52
  if (isWindow(el))
54
53
  return el.document;
55
54
  if (isDocument(el))
56
55
  return el;
57
- return (_a = el == null ? void 0 : el.ownerDocument) != null ? _a : document;
56
+ return el?.ownerDocument ?? document;
58
57
  }
59
58
  function defineDomHelpers(helpers) {
60
59
  const dom2 = {
61
- getRootNode: (ctx) => {
62
- var _a, _b;
63
- return (_b = (_a = ctx.getRootNode) == null ? void 0 : _a.call(ctx)) != null ? _b : document;
64
- },
60
+ getRootNode: (ctx) => ctx.getRootNode?.() ?? document,
65
61
  getDoc: (ctx) => getDocument(dom2.getRootNode(ctx)),
66
- getWin: (ctx) => {
67
- var _a;
68
- return (_a = dom2.getDoc(ctx).defaultView) != null ? _a : window;
69
- },
62
+ getWin: (ctx) => dom2.getDoc(ctx).defaultView ?? window,
70
63
  getActiveElement: (ctx) => dom2.getDoc(ctx).activeElement,
71
64
  getById: (ctx, id) => dom2.getRootNode(ctx).getElementById(id)
72
65
  };
@@ -78,8 +71,7 @@ function defineDomHelpers(helpers) {
78
71
 
79
72
  // ../../utilities/dom/src/event.ts
80
73
  function getNativeEvent(e) {
81
- var _a;
82
- return (_a = e.nativeEvent) != null ? _a : e;
74
+ return e.nativeEvent ?? e;
83
75
  }
84
76
  var isModifiedEvent = (v) => v.ctrlKey || v.altKey || v.metaKey;
85
77
 
@@ -98,10 +90,9 @@ var sameKeyMap = {
98
90
  Right: "ArrowRight"
99
91
  };
100
92
  function getEventKey(event, options = {}) {
101
- var _a;
102
93
  const { dir = "ltr", orientation = "horizontal" } = options;
103
94
  let { key } = event;
104
- key = (_a = sameKeyMap[key]) != null ? _a : key;
95
+ key = sameKeyMap[key] ?? key;
105
96
  const isRtl = dir === "rtl" && orientation === "horizontal";
106
97
  if (isRtl && key in rtlKeyMap) {
107
98
  key = rtlKeyMap[key];
@@ -111,8 +102,7 @@ function getEventKey(event, options = {}) {
111
102
 
112
103
  // ../../utilities/dom/src/nodelist.ts
113
104
  function queryAll(root, selector) {
114
- var _a;
115
- return Array.from((_a = root == null ? void 0 : root.querySelectorAll(selector)) != null ? _a : []);
105
+ return Array.from(root?.querySelectorAll(selector) ?? []);
116
106
  }
117
107
 
118
108
  // ../../utilities/dom/src/visually-hidden.ts
@@ -136,26 +126,11 @@ var parts = anatomy.build();
136
126
 
137
127
  // src/pin-input.dom.ts
138
128
  var dom = defineDomHelpers({
139
- getRootId: (ctx) => {
140
- var _a, _b;
141
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.root) != null ? _b : `pin-input:${ctx.id}`;
142
- },
143
- getInputId: (ctx, id) => {
144
- var _a, _b, _c;
145
- 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}`;
146
- },
147
- getHiddenInputId: (ctx) => {
148
- var _a, _b;
149
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.hiddenInput) != null ? _b : `pin-input:${ctx.id}:hidden`;
150
- },
151
- getLabelId: (ctx) => {
152
- var _a, _b;
153
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.label) != null ? _b : `pin-input:${ctx.id}:label`;
154
- },
155
- getControlId: (ctx) => {
156
- var _a, _b;
157
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.control) != null ? _b : `pin-input:${ctx.id}:control`;
158
- },
129
+ getRootId: (ctx) => ctx.ids?.root ?? `pin-input:${ctx.id}`,
130
+ getInputId: (ctx, id) => ctx.ids?.input?.(id) ?? `pin-input:${ctx.id}:${id}`,
131
+ getHiddenInputId: (ctx) => ctx.ids?.hiddenInput ?? `pin-input:${ctx.id}:hidden`,
132
+ getLabelId: (ctx) => ctx.ids?.label ?? `pin-input:${ctx.id}:label`,
133
+ getControlId: (ctx) => ctx.ids?.control ?? `pin-input:${ctx.id}:control`,
159
134
  getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
160
135
  getElements: (ctx) => {
161
136
  const ownerId = CSS.escape(dom.getRootId(ctx));
@@ -174,8 +149,7 @@ function connect(state, send, normalize) {
174
149
  const focusedIndex = state.context.focusedIndex;
175
150
  const translations = state.context.translations;
176
151
  function focus() {
177
- var _a;
178
- (_a = dom.getFirstInputEl(state.context)) == null ? void 0 : _a.focus();
152
+ dom.getFirstInputEl(state.context)?.focus();
179
153
  }
180
154
  return {
181
155
  value: state.context.value,
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  connect
3
- } from "./chunk-3SENCEI3.mjs";
3
+ } from "./chunk-QVOI2QEW.mjs";
4
4
  import "./chunk-BJXKBZJG.mjs";
5
5
  import "./chunk-NT4W6JYX.mjs";
6
- import "./chunk-APRO2TYE.mjs";
6
+ import "./chunk-T5OKDF74.mjs";
7
7
  export {
8
8
  connect
9
9
  };
@@ -29,27 +29,20 @@ function isDocument(el) {
29
29
  return el.nodeType === Node.DOCUMENT_NODE;
30
30
  }
31
31
  function isWindow(value) {
32
- return (value == null ? void 0 : value.toString()) === "[object Window]";
32
+ return value?.toString() === "[object Window]";
33
33
  }
34
34
  function getDocument(el) {
35
- var _a;
36
35
  if (isWindow(el))
37
36
  return el.document;
38
37
  if (isDocument(el))
39
38
  return el;
40
- return (_a = el == null ? void 0 : el.ownerDocument) != null ? _a : document;
39
+ return el?.ownerDocument ?? document;
41
40
  }
42
41
  function defineDomHelpers(helpers) {
43
42
  const dom2 = {
44
- getRootNode: (ctx) => {
45
- var _a, _b;
46
- return (_b = (_a = ctx.getRootNode) == null ? void 0 : _a.call(ctx)) != null ? _b : document;
47
- },
43
+ getRootNode: (ctx) => ctx.getRootNode?.() ?? document,
48
44
  getDoc: (ctx) => getDocument(dom2.getRootNode(ctx)),
49
- getWin: (ctx) => {
50
- var _a;
51
- return (_a = dom2.getDoc(ctx).defaultView) != null ? _a : window;
52
- },
45
+ getWin: (ctx) => dom2.getDoc(ctx).defaultView ?? window,
53
46
  getActiveElement: (ctx) => dom2.getDoc(ctx).activeElement,
54
47
  getById: (ctx, id) => dom2.getRootNode(ctx).getElementById(id)
55
48
  };
@@ -61,32 +54,16 @@ function defineDomHelpers(helpers) {
61
54
 
62
55
  // ../../utilities/dom/src/nodelist.ts
63
56
  function queryAll(root, selector) {
64
- var _a;
65
- return Array.from((_a = root == null ? void 0 : root.querySelectorAll(selector)) != null ? _a : []);
57
+ return Array.from(root?.querySelectorAll(selector) ?? []);
66
58
  }
67
59
 
68
60
  // src/pin-input.dom.ts
69
61
  var dom = defineDomHelpers({
70
- getRootId: (ctx) => {
71
- var _a, _b;
72
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.root) != null ? _b : `pin-input:${ctx.id}`;
73
- },
74
- getInputId: (ctx, id) => {
75
- var _a, _b, _c;
76
- 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}`;
77
- },
78
- getHiddenInputId: (ctx) => {
79
- var _a, _b;
80
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.hiddenInput) != null ? _b : `pin-input:${ctx.id}:hidden`;
81
- },
82
- getLabelId: (ctx) => {
83
- var _a, _b;
84
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.label) != null ? _b : `pin-input:${ctx.id}:label`;
85
- },
86
- getControlId: (ctx) => {
87
- var _a, _b;
88
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.control) != null ? _b : `pin-input:${ctx.id}:control`;
89
- },
62
+ getRootId: (ctx) => ctx.ids?.root ?? `pin-input:${ctx.id}`,
63
+ getInputId: (ctx, id) => ctx.ids?.input?.(id) ?? `pin-input:${ctx.id}:${id}`,
64
+ getHiddenInputId: (ctx) => ctx.ids?.hiddenInput ?? `pin-input:${ctx.id}:hidden`,
65
+ getLabelId: (ctx) => ctx.ids?.label ?? `pin-input:${ctx.id}:label`,
66
+ getControlId: (ctx) => ctx.ids?.control ?? `pin-input:${ctx.id}:control`,
90
67
  getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
91
68
  getElements: (ctx) => {
92
69
  const ownerId = CSS.escape(dom.getRootId(ctx));
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  dom
3
- } from "./chunk-APRO2TYE.mjs";
3
+ } from "./chunk-T5OKDF74.mjs";
4
4
  export {
5
5
  dom
6
6
  };
@@ -43,31 +43,23 @@ function isDocument(el) {
43
43
  return el.nodeType === Node.DOCUMENT_NODE;
44
44
  }
45
45
  function isWindow(value) {
46
- return (value == null ? void 0 : value.toString()) === "[object Window]";
46
+ return value?.toString() === "[object Window]";
47
47
  }
48
48
  function getDocument(el) {
49
- var _a;
50
49
  if (isWindow(el))
51
50
  return el.document;
52
51
  if (isDocument(el))
53
52
  return el;
54
- return (_a = el == null ? void 0 : el.ownerDocument) != null ? _a : document;
53
+ return el?.ownerDocument ?? document;
55
54
  }
56
55
  function getWindow(el) {
57
- var _a;
58
- return (_a = el == null ? void 0 : el.ownerDocument.defaultView) != null ? _a : window;
56
+ return el?.ownerDocument.defaultView ?? window;
59
57
  }
60
58
  function defineDomHelpers(helpers) {
61
59
  const dom2 = {
62
- getRootNode: (ctx) => {
63
- var _a, _b;
64
- return (_b = (_a = ctx.getRootNode) == null ? void 0 : _a.call(ctx)) != null ? _b : document;
65
- },
60
+ getRootNode: (ctx) => ctx.getRootNode?.() ?? document,
66
61
  getDoc: (ctx) => getDocument(dom2.getRootNode(ctx)),
67
- getWin: (ctx) => {
68
- var _a;
69
- return (_a = dom2.getDoc(ctx).defaultView) != null ? _a : window;
70
- },
62
+ getWin: (ctx) => dom2.getDoc(ctx).defaultView ?? window,
71
63
  getActiveElement: (ctx) => dom2.getDoc(ctx).activeElement,
72
64
  getById: (ctx, id) => dom2.getRootNode(ctx).getElementById(id)
73
65
  };
@@ -87,52 +79,34 @@ function raf(fn) {
87
79
 
88
80
  // ../../utilities/dom/src/nodelist.ts
89
81
  function queryAll(root, selector) {
90
- var _a;
91
- return Array.from((_a = root == null ? void 0 : root.querySelectorAll(selector)) != null ? _a : []);
82
+ return Array.from(root?.querySelectorAll(selector) ?? []);
92
83
  }
93
84
 
94
85
  // ../../utilities/form-utils/src/input-event.ts
95
86
  function getDescriptor(el, options) {
96
- var _a;
97
87
  const { type, property = "value" } = options;
98
88
  const proto = getWindow(el)[type].prototype;
99
- return (_a = Object.getOwnPropertyDescriptor(proto, property)) != null ? _a : {};
89
+ return Object.getOwnPropertyDescriptor(proto, property) ?? {};
100
90
  }
101
91
  function dispatchInputValueEvent(el, value) {
102
- var _a;
103
92
  if (!el)
104
93
  return;
105
94
  const win = getWindow(el);
106
95
  if (!(el instanceof win.HTMLInputElement))
107
96
  return;
108
97
  const desc = getDescriptor(el, { type: "HTMLInputElement", property: "value" });
109
- (_a = desc.set) == null ? void 0 : _a.call(el, value);
98
+ desc.set?.call(el, value);
110
99
  const event = new win.Event("input", { bubbles: true });
111
100
  el.dispatchEvent(event);
112
101
  }
113
102
 
114
103
  // src/pin-input.dom.ts
115
104
  var dom = defineDomHelpers({
116
- getRootId: (ctx) => {
117
- var _a, _b;
118
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.root) != null ? _b : `pin-input:${ctx.id}`;
119
- },
120
- getInputId: (ctx, id) => {
121
- var _a, _b, _c;
122
- 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}`;
123
- },
124
- getHiddenInputId: (ctx) => {
125
- var _a, _b;
126
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.hiddenInput) != null ? _b : `pin-input:${ctx.id}:hidden`;
127
- },
128
- getLabelId: (ctx) => {
129
- var _a, _b;
130
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.label) != null ? _b : `pin-input:${ctx.id}:label`;
131
- },
132
- getControlId: (ctx) => {
133
- var _a, _b;
134
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.control) != null ? _b : `pin-input:${ctx.id}:control`;
135
- },
105
+ getRootId: (ctx) => ctx.ids?.root ?? `pin-input:${ctx.id}`,
106
+ getInputId: (ctx, id) => ctx.ids?.input?.(id) ?? `pin-input:${ctx.id}:${id}`,
107
+ getHiddenInputId: (ctx) => ctx.ids?.hiddenInput ?? `pin-input:${ctx.id}:hidden`,
108
+ getLabelId: (ctx) => ctx.ids?.label ?? `pin-input:${ctx.id}:label`,
109
+ getControlId: (ctx) => ctx.ids?.control ?? `pin-input:${ctx.id}:control`,
136
110
  getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
137
111
  getElements: (ctx) => {
138
112
  const ownerId = CSS.escape(dom.getRootId(ctx));
@@ -151,10 +125,10 @@ function machine(userContext) {
151
125
  return (0, import_core.createMachine)(
152
126
  {
153
127
  id: "pin-input",
154
- initial: "unknown",
128
+ initial: ctx.autoFocus ? "focused" : "idle",
155
129
  context: {
156
130
  value: [],
157
- focusedIndex: -1,
131
+ focusedIndex: ctx.autoFocus ? 0 : -1,
158
132
  placeholder: "\u25CB",
159
133
  otp: false,
160
134
  type: "numeric",
@@ -166,7 +140,7 @@ function machine(userContext) {
166
140
  },
167
141
  computed: {
168
142
  valueLength: (ctx2) => ctx2.value.length,
169
- filledValueLength: (ctx2) => ctx2.value.filter((v) => (v == null ? void 0 : v.trim()) !== "").length,
143
+ filledValueLength: (ctx2) => ctx2.value.filter((v) => v?.trim() !== "").length,
170
144
  isValueComplete: (ctx2) => ctx2.valueLength === ctx2.filledValueLength,
171
145
  valueAsString: (ctx2) => ctx2.value.join(""),
172
146
  focusedValue: (ctx2) => ctx2.value[ctx2.focusedIndex]
@@ -176,6 +150,7 @@ function machine(userContext) {
176
150
  value: ["dispatchInputEvent"],
177
151
  isValueComplete: ["invokeOnComplete", "blurFocusedInputIfNeeded"]
178
152
  },
153
+ entry: ["setupValue"],
179
154
  on: {
180
155
  SET_VALUE: [
181
156
  {
@@ -195,21 +170,6 @@ function machine(userContext) {
195
170
  ]
196
171
  },
197
172
  states: {
198
- unknown: {
199
- on: {
200
- SETUP: [
201
- {
202
- guard: "autoFocus",
203
- target: "focused",
204
- actions: ["setupValue", "setFocusIndexToFirst"]
205
- },
206
- {
207
- target: "idle",
208
- actions: "setupValue"
209
- }
210
- ]
211
- }
212
- },
213
173
  idle: {
214
174
  on: {
215
175
  FOCUS: {
@@ -223,11 +183,11 @@ function machine(userContext) {
223
183
  INPUT: [
224
184
  {
225
185
  guard: and("isFinalValue", "isValidValue"),
226
- actions: ["setFocusedValue", "invokeOnChange", "dispatchInputEventIfNeeded"]
186
+ actions: ["setFocusedValue", "invokeOnChange", "syncInputValue"]
227
187
  },
228
188
  {
229
189
  guard: "isValidValue",
230
- actions: ["setFocusedValue", "invokeOnChange", "setNextFocusedIndex", "dispatchInputEventIfNeeded"]
190
+ actions: ["setFocusedValue", "invokeOnChange", "setNextFocusedIndex", "syncInputValue"]
231
191
  }
232
192
  ],
233
193
  PASTE: [
@@ -294,15 +254,14 @@ function machine(userContext) {
294
254
  actions: {
295
255
  setupValue: (ctx2) => {
296
256
  const inputs = dom.getElements(ctx2);
297
- const empty = Array.from({ length: inputs.length }).map(() => "");
298
- ctx2.value = Object.assign(empty, ctx2.value);
257
+ const emptyValues = Array.from({ length: inputs.length }).fill("");
258
+ assign(ctx2, emptyValues);
299
259
  },
300
260
  focusInput: (ctx2) => {
301
261
  raf(() => {
302
- var _a;
303
262
  if (ctx2.focusedIndex === -1)
304
263
  return;
305
- (_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.focus();
264
+ dom.getFocusedEl(ctx2)?.focus();
306
265
  });
307
266
  },
308
267
  setInputSelection: (ctx2) => {
@@ -316,16 +275,14 @@ function machine(userContext) {
316
275
  });
317
276
  },
318
277
  invokeOnComplete: (ctx2) => {
319
- var _a;
320
278
  if (!ctx2.isValueComplete)
321
279
  return;
322
- (_a = ctx2.onComplete) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value), valueAsString: ctx2.valueAsString });
280
+ ctx2.onComplete?.({ value: Array.from(ctx2.value), valueAsString: ctx2.valueAsString });
323
281
  },
324
282
  invokeOnChange: (ctx2, evt) => {
325
- var _a;
326
283
  if (evt.type === "SETUP")
327
284
  return;
328
- (_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value) });
285
+ ctx2.onChange?.({ value: Array.from(ctx2.value) });
329
286
  },
330
287
  dispatchInputEvent: (ctx2, evt) => {
331
288
  if (evt.type === "SETUP")
@@ -338,8 +295,7 @@ function machine(userContext) {
338
295
  });
339
296
  },
340
297
  invokeOnInvalid: (ctx2, evt) => {
341
- var _a;
342
- (_a = ctx2.onInvalid) == null ? void 0 : _a.call(ctx2, { value: evt.value, index: ctx2.focusedIndex });
298
+ ctx2.onInvalid?.({ value: evt.value, index: ctx2.focusedIndex });
343
299
  },
344
300
  clearFocusedIndex: (ctx2) => {
345
301
  ctx2.focusedIndex = -1;
@@ -351,15 +307,16 @@ function machine(userContext) {
351
307
  ctx2.focusedIndex = evt.index;
352
308
  },
353
309
  setFocusedValue: (ctx2, evt) => {
354
- ctx2.value[ctx2.focusedIndex] = lastChar(evt.value);
310
+ ctx2.value[ctx2.focusedIndex] = getNextValue(ctx2.focusedValue, evt.value);
355
311
  },
356
- dispatchInputEventIfNeeded: (ctx2, evt) => {
357
- const valueIsChanged = lastChar(evt.value) !== ctx2.focusedValue;
358
- if (evt.value.length <= 1 || valueIsChanged)
312
+ syncInputValue: (ctx2, evt) => {
313
+ const nextValue = getNextValue(ctx2.focusedValue, evt.value);
314
+ const changed = nextValue !== ctx2.focusedValue;
315
+ if (evt.value.length <= 1 || changed)
359
316
  return;
360
317
  const inputs = dom.getElements(ctx2);
361
318
  const input = inputs[ctx2.focusedIndex];
362
- input.value = lastChar(evt.value);
319
+ input.value = nextValue;
363
320
  },
364
321
  setPastedValue(ctx2, evt) {
365
322
  raf(() => {
@@ -369,10 +326,11 @@ function machine(userContext) {
369
326
  });
370
327
  },
371
328
  setValueAtIndex: (ctx2, evt) => {
372
- ctx2.value[evt.index] = lastChar(evt.value);
329
+ ctx2.value[evt.index] = getNextValue(ctx2.focusedValue, evt.value);
373
330
  },
374
331
  clearValue: (ctx2) => {
375
- ctx2.value = ctx2.value.map(() => "");
332
+ const nextValue = Array.from({ length: ctx2.valueLength }).fill("");
333
+ assign(ctx2, nextValue);
376
334
  },
377
335
  clearFocusedValue: (ctx2) => {
378
336
  ctx2.value[ctx2.focusedIndex] = "";
@@ -402,16 +360,14 @@ function machine(userContext) {
402
360
  if (!ctx2.blurOnComplete)
403
361
  return;
404
362
  raf(() => {
405
- var _a;
406
- (_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.blur();
363
+ dom.getFocusedEl(ctx2)?.blur();
407
364
  });
408
365
  },
409
366
  requestFormSubmit(ctx2) {
410
- var _a;
411
- if (!ctx2.name)
367
+ if (!ctx2.name || !ctx2.isValueComplete)
412
368
  return;
413
369
  const input = dom.getHiddenInputEl(ctx2);
414
- (_a = input == null ? void 0 : input.form) == null ? void 0 : _a.requestSubmit();
370
+ input?.form?.requestSubmit();
415
371
  }
416
372
  }
417
373
  }
@@ -423,18 +379,23 @@ var REGEX = {
423
379
  alphanumeric: /^[a-zA-Z0-9]+$/i
424
380
  };
425
381
  function isValidType(value, type) {
426
- var _a;
427
382
  if (!type)
428
383
  return true;
429
- return !!((_a = REGEX[type]) == null ? void 0 : _a.test(value));
384
+ return !!REGEX[type]?.test(value);
430
385
  }
431
386
  function assign(ctx, value) {
432
- const valueArr = Array.isArray(value) ? value : value.split("").filter(Boolean);
433
- const valueObj = Object.assign({}, ctx.value, valueArr);
434
- ctx.value = Object.values(valueObj);
387
+ const arr = Array.isArray(value) ? value : value.split("").filter(Boolean);
388
+ arr.forEach((value2, index) => {
389
+ ctx.value[index] = value2;
390
+ });
435
391
  }
436
- function lastChar(value) {
437
- return value.charAt(value.length - 1);
392
+ function getNextValue(current, next) {
393
+ let nextValue = next;
394
+ if (current[0] === next[0])
395
+ nextValue = next[1];
396
+ else if (current[0] === next[1])
397
+ nextValue = next[0];
398
+ return nextValue;
438
399
  }
439
400
  // Annotate the CommonJS export names for ESM import in node:
440
401
  0 && (module.exports = {
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  machine
3
- } from "./chunk-CDDLX3AG.mjs";
3
+ } from "./chunk-53K4IC6M.mjs";
4
4
  import "./chunk-NT4W6JYX.mjs";
5
- import "./chunk-APRO2TYE.mjs";
5
+ import "./chunk-T5OKDF74.mjs";
6
6
  export {
7
7
  machine
8
8
  };
@@ -125,7 +125,7 @@ type ComputedContext = Readonly<{
125
125
  type PrivateContext = Context<{}>;
126
126
  type MachineContext = PublicContext & PrivateContext & ComputedContext;
127
127
  type MachineState = {
128
- value: "unknown" | "idle" | "focused";
128
+ value: "idle" | "focused";
129
129
  };
130
130
  type State = StateMachine.State<MachineContext, MachineState>;
131
131
  type Send = StateMachine.Send<StateMachine.AnyEventObject>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zag-js/pin-input",
3
- "version": "0.2.8",
3
+ "version": "0.2.10",
4
4
  "description": "Core logic for the pin-input widget implemented as a state machine",
5
5
  "keywords": [
6
6
  "js",
@@ -26,15 +26,15 @@
26
26
  "url": "https://github.com/chakra-ui/zag/issues"
27
27
  },
28
28
  "dependencies": {
29
- "@zag-js/anatomy": "0.1.3",
30
- "@zag-js/core": "0.2.5",
31
- "@zag-js/types": "0.3.3"
29
+ "@zag-js/anatomy": "0.1.4",
30
+ "@zag-js/core": "0.2.7",
31
+ "@zag-js/types": "0.3.4"
32
32
  },
33
33
  "devDependencies": {
34
34
  "clean-package": "2.2.0",
35
- "@zag-js/dom-utils": "0.2.3",
36
- "@zag-js/form-utils": "0.2.3",
37
- "@zag-js/utils": "0.3.2"
35
+ "@zag-js/dom-utils": "0.2.4",
36
+ "@zag-js/form-utils": "0.2.4",
37
+ "@zag-js/utils": "0.3.3"
38
38
  },
39
39
  "clean-package": "../../../clean-package.config.json",
40
40
  "main": "dist/index.js",
@@ -1,82 +0,0 @@
1
- // ../../utilities/dom/src/query.ts
2
- function isDocument(el) {
3
- return el.nodeType === Node.DOCUMENT_NODE;
4
- }
5
- function isWindow(value) {
6
- return (value == null ? void 0 : value.toString()) === "[object Window]";
7
- }
8
- function getDocument(el) {
9
- var _a;
10
- if (isWindow(el))
11
- return el.document;
12
- if (isDocument(el))
13
- return el;
14
- return (_a = el == null ? void 0 : el.ownerDocument) != null ? _a : document;
15
- }
16
- function getWindow(el) {
17
- var _a;
18
- return (_a = el == null ? void 0 : el.ownerDocument.defaultView) != null ? _a : window;
19
- }
20
- function defineDomHelpers(helpers) {
21
- const dom2 = {
22
- getRootNode: (ctx) => {
23
- var _a, _b;
24
- return (_b = (_a = ctx.getRootNode) == null ? void 0 : _a.call(ctx)) != null ? _b : document;
25
- },
26
- getDoc: (ctx) => getDocument(dom2.getRootNode(ctx)),
27
- getWin: (ctx) => {
28
- var _a;
29
- return (_a = dom2.getDoc(ctx).defaultView) != null ? _a : window;
30
- },
31
- getActiveElement: (ctx) => dom2.getDoc(ctx).activeElement,
32
- getById: (ctx, id) => dom2.getRootNode(ctx).getElementById(id)
33
- };
34
- return {
35
- ...dom2,
36
- ...helpers
37
- };
38
- }
39
-
40
- // ../../utilities/dom/src/nodelist.ts
41
- function queryAll(root, selector) {
42
- var _a;
43
- return Array.from((_a = root == null ? void 0 : root.querySelectorAll(selector)) != null ? _a : []);
44
- }
45
-
46
- // src/pin-input.dom.ts
47
- var dom = defineDomHelpers({
48
- getRootId: (ctx) => {
49
- var _a, _b;
50
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.root) != null ? _b : `pin-input:${ctx.id}`;
51
- },
52
- getInputId: (ctx, id) => {
53
- var _a, _b, _c;
54
- 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}`;
55
- },
56
- getHiddenInputId: (ctx) => {
57
- var _a, _b;
58
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.hiddenInput) != null ? _b : `pin-input:${ctx.id}:hidden`;
59
- },
60
- getLabelId: (ctx) => {
61
- var _a, _b;
62
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.label) != null ? _b : `pin-input:${ctx.id}:label`;
63
- },
64
- getControlId: (ctx) => {
65
- var _a, _b;
66
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.control) != null ? _b : `pin-input:${ctx.id}:control`;
67
- },
68
- getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
69
- getElements: (ctx) => {
70
- const ownerId = CSS.escape(dom.getRootId(ctx));
71
- const selector = `input[data-ownedby=${ownerId}]`;
72
- return queryAll(dom.getRootEl(ctx), selector);
73
- },
74
- getFocusedEl: (ctx) => dom.getElements(ctx)[ctx.focusedIndex],
75
- getFirstInputEl: (ctx) => dom.getElements(ctx)[0],
76
- getHiddenInputEl: (ctx) => dom.getById(ctx, dom.getHiddenInputId(ctx))
77
- });
78
-
79
- export {
80
- getWindow,
81
- dom
82
- };