@zag-js/pin-input 0.1.9 → 0.1.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.
package/dist/index.js CHANGED
@@ -43,17 +43,85 @@ __export(src_exports, {
43
43
  module.exports = __toCommonJS(src_exports);
44
44
 
45
45
  // ../../utilities/dom/dist/index.mjs
46
+ var __defProp2 = Object.defineProperty;
47
+ var __getOwnPropSymbols2 = Object.getOwnPropertySymbols;
48
+ var __hasOwnProp2 = Object.prototype.hasOwnProperty;
49
+ var __propIsEnum2 = Object.prototype.propertyIsEnumerable;
50
+ var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
51
+ var __spreadValues2 = (a, b) => {
52
+ for (var prop in b || (b = {}))
53
+ if (__hasOwnProp2.call(b, prop))
54
+ __defNormalProp2(a, prop, b[prop]);
55
+ if (__getOwnPropSymbols2)
56
+ for (var prop of __getOwnPropSymbols2(b)) {
57
+ if (__propIsEnum2.call(b, prop))
58
+ __defNormalProp2(a, prop, b[prop]);
59
+ }
60
+ return a;
61
+ };
46
62
  var dataAttr = (guard) => {
47
63
  return guard ? "" : void 0;
48
64
  };
49
65
  var ariaAttr = (guard) => {
50
66
  return guard ? "true" : void 0;
51
67
  };
68
+ function isDocument(el) {
69
+ return el.nodeType === Node.DOCUMENT_NODE;
70
+ }
71
+ function isWindow(value) {
72
+ return (value == null ? void 0 : value.toString()) === "[object Window]";
73
+ }
74
+ function getDocument(el) {
75
+ var _a;
76
+ if (isWindow(el))
77
+ return el.document;
78
+ if (isDocument(el))
79
+ return el;
80
+ return (_a = el == null ? void 0 : el.ownerDocument) != null ? _a : document;
81
+ }
82
+ function getWindow(el) {
83
+ var _a;
84
+ return (_a = el == null ? void 0 : el.ownerDocument.defaultView) != null ? _a : window;
85
+ }
86
+ function defineDomHelpers(helpers) {
87
+ const dom2 = {
88
+ getRootNode: (ctx) => {
89
+ var _a, _b;
90
+ return (_b = (_a = ctx.getRootNode) == null ? void 0 : _a.call(ctx)) != null ? _b : document;
91
+ },
92
+ getDoc: (ctx) => getDocument(dom2.getRootNode(ctx)),
93
+ getWin: (ctx) => {
94
+ var _a;
95
+ return (_a = dom2.getDoc(ctx).defaultView) != null ? _a : window;
96
+ },
97
+ getActiveElement: (ctx) => dom2.getDoc(ctx).activeElement,
98
+ getById: (ctx, id) => dom2.getRootNode(ctx).getElementById(id)
99
+ };
100
+ return __spreadValues2(__spreadValues2({}, dom2), helpers);
101
+ }
52
102
  function getNativeEvent(e) {
53
103
  var _a;
54
104
  return (_a = e.nativeEvent) != null ? _a : e;
55
105
  }
56
106
  var isModifiedEvent = (v) => v.ctrlKey || v.altKey || v.metaKey;
107
+ function getDescriptor(el, options) {
108
+ var _a;
109
+ const { type, property } = options;
110
+ const proto = getWindow(el)[type].prototype;
111
+ return (_a = Object.getOwnPropertyDescriptor(proto, property)) != null ? _a : {};
112
+ }
113
+ function dispatchInputValueEvent(el, value) {
114
+ var _a;
115
+ if (!el)
116
+ return;
117
+ const win = getWindow(el);
118
+ if (!(el instanceof win.HTMLInputElement))
119
+ return;
120
+ const desc = getDescriptor(el, { type: "HTMLInputElement", property: "value" });
121
+ (_a = desc.set) == null ? void 0 : _a.call(el, value);
122
+ const event = new win.Event("input", { bubbles: true });
123
+ el.dispatchEvent(event);
124
+ }
57
125
  var rtlKeyMap = {
58
126
  ArrowLeft: "ArrowRight",
59
127
  ArrowRight: "ArrowLeft",
@@ -80,19 +148,6 @@ function getEventKey(event, options = {}) {
80
148
  }
81
149
  return key;
82
150
  }
83
- function nextTick(fn) {
84
- const set = /* @__PURE__ */ new Set();
85
- function raf2(fn2) {
86
- const id = globalThis.requestAnimationFrame(fn2);
87
- set.add(() => globalThis.cancelAnimationFrame(id));
88
- }
89
- raf2(() => raf2(fn));
90
- return function cleanup() {
91
- set.forEach(function(fn2) {
92
- fn2();
93
- });
94
- };
95
- }
96
151
  function raf(fn) {
97
152
  const id = globalThis.requestAnimationFrame(fn);
98
153
  return function cleanup() {
@@ -103,9 +158,20 @@ function queryAll(root, selector) {
103
158
  var _a;
104
159
  return Array.from((_a = root == null ? void 0 : root.querySelectorAll(selector)) != null ? _a : []);
105
160
  }
161
+ var visuallyHiddenStyle = {
162
+ border: "0",
163
+ clip: "rect(0 0 0 0)",
164
+ height: "1px",
165
+ margin: "-1px",
166
+ overflow: "hidden",
167
+ padding: "0",
168
+ position: "absolute",
169
+ width: "1px",
170
+ whiteSpace: "nowrap",
171
+ wordWrap: "normal"
172
+ };
106
173
 
107
174
  // ../../utilities/core/dist/index.mjs
108
- var fromLength = (length) => Array.from(Array(length).keys());
109
175
  function invariant(...a) {
110
176
  const m = a.length === 1 ? a[0] : a[1];
111
177
  const c = a.length === 2 ? a[0] : true;
@@ -115,32 +181,29 @@ function invariant(...a) {
115
181
  }
116
182
 
117
183
  // src/pin-input.dom.ts
118
- var dom = {
119
- getDoc: (ctx) => {
120
- var _a;
121
- return (_a = ctx.doc) != null ? _a : document;
122
- },
123
- getRootNode: (ctx) => {
124
- var _a;
125
- return (_a = ctx.rootNode) != null ? _a : dom.getDoc(ctx);
126
- },
184
+ var dom = defineDomHelpers({
127
185
  getRootId: (ctx) => {
128
186
  var _a, _b;
129
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.root) != null ? _b : `pin-input:${ctx.uid}`;
187
+ return (_b = (_a = ctx.ids) == null ? void 0 : _a.root) != null ? _b : `pin-input:${ctx.id}`;
130
188
  },
131
189
  getInputId: (ctx, id) => {
132
190
  var _a, _b, _c;
133
- return (_c = (_b = (_a = ctx.ids) == null ? void 0 : _a.input) == null ? void 0 : _b.call(_a, id)) != null ? _c : `pin-input:${ctx.uid}:${id}`;
191
+ 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}`;
192
+ },
193
+ getHiddenInputId: (ctx) => {
194
+ var _a, _b;
195
+ return (_b = (_a = ctx.ids) == null ? void 0 : _a.hiddenInput) != null ? _b : `pin-input:${ctx.id}:hidden`;
134
196
  },
135
- getRootEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getRootId(ctx)),
197
+ getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
136
198
  getElements: (ctx) => {
137
199
  const ownerId = CSS.escape(dom.getRootId(ctx));
138
200
  const selector = `input[data-ownedby=${ownerId}]`;
139
201
  return queryAll(dom.getRootEl(ctx), selector);
140
202
  },
141
203
  getFocusedEl: (ctx) => dom.getElements(ctx)[ctx.focusedIndex],
142
- getFirstInputEl: (ctx) => dom.getElements(ctx)[0]
143
- };
204
+ getFirstInputEl: (ctx) => dom.getElements(ctx)[0],
205
+ getHiddenInputEl: (ctx) => dom.getById(ctx, dom.getHiddenInputId(ctx))
206
+ });
144
207
 
145
208
  // src/pin-input.connect.ts
146
209
  function connect(state, send, normalize) {
@@ -176,6 +239,16 @@ function connect(state, send, normalize) {
176
239
  "data-disabled": dataAttr(state.context.disabled),
177
240
  "data-complete": dataAttr(isValueComplete)
178
241
  }),
242
+ hiddenInputProps: normalize.input({
243
+ "aria-hidden": true,
244
+ type: "text",
245
+ tabIndex: -1,
246
+ id: dom.getHiddenInputId(state.context),
247
+ name: state.context.name,
248
+ style: visuallyHiddenStyle,
249
+ maxLength: state.context.valueLength,
250
+ defaultValue: state.context.valueAsString
251
+ }),
179
252
  getInputProps({ index }) {
180
253
  const inputType = state.context.type === "numeric" ? "tel" : "text";
181
254
  return normalize.input({
@@ -224,6 +297,9 @@ function connect(state, send, normalize) {
224
297
  },
225
298
  ArrowRight() {
226
299
  send("ARROW_RIGHT");
300
+ },
301
+ Enter() {
302
+ send("ENTER");
227
303
  }
228
304
  };
229
305
  const key = getEventKey(event, { dir: state.context.dir });
@@ -249,12 +325,11 @@ function connect(state, send, normalize) {
249
325
  // src/pin-input.machine.ts
250
326
  var import_core = require("@zag-js/core");
251
327
  var { and, not } = import_core.guards;
252
- function machine(ctx = {}) {
328
+ function machine(ctx) {
253
329
  return (0, import_core.createMachine)({
254
330
  id: "pin-input",
255
331
  initial: "unknown",
256
332
  context: __spreadProps(__spreadValues({
257
- uid: "pin-input",
258
333
  value: [],
259
334
  focusedIndex: -1,
260
335
  placeholder: "\u25CB",
@@ -274,7 +349,7 @@ function machine(ctx = {}) {
274
349
  watch: {
275
350
  focusedIndex: "focusInput",
276
351
  value: "invokeOnChange",
277
- isValueComplete: ["invokeComplete", "blurFocusedInputIfNeeded"]
352
+ isValueComplete: ["invokeOnComplete", "blurFocusedInputIfNeeded"]
278
353
  },
279
354
  on: {
280
355
  SET_VALUE: [
@@ -301,11 +376,11 @@ function machine(ctx = {}) {
301
376
  {
302
377
  guard: "autoFocus",
303
378
  target: "focused",
304
- actions: ["setupDocument", "setupValue", "setFocusIndexToFirst"]
379
+ actions: ["setupValue", "setFocusIndexToFirst"]
305
380
  },
306
381
  {
307
382
  target: "idle",
308
- actions: ["setupDocument", "setupValue"]
383
+ actions: "setupValue"
309
384
  }
310
385
  ]
311
386
  }
@@ -357,6 +432,10 @@ function machine(ctx = {}) {
357
432
  actions: ["setPrevFocusedIndex", "clearFocusedValue"]
358
433
  }
359
434
  ],
435
+ ENTER: {
436
+ guard: "isValueComplete",
437
+ actions: "requestFormSubmit"
438
+ },
360
439
  KEY_DOWN: {
361
440
  guard: not("isValidValue"),
362
441
  actions: ["preventDefault", "invokeOnInvalid"]
@@ -370,7 +449,12 @@ function machine(ctx = {}) {
370
449
  isValueEmpty: (_ctx, evt) => evt.value === "",
371
450
  hasValue: (ctx2) => ctx2.value[ctx2.focusedIndex] !== "",
372
451
  isValueComplete: (ctx2) => ctx2.isValueComplete,
373
- isValidValue: (ctx2, evt) => isValidType(evt.value, ctx2.type),
452
+ isValidValue: (ctx2, evt) => {
453
+ if (!ctx2.pattern)
454
+ return isValidType(evt.value, ctx2.type);
455
+ const regex = new RegExp(ctx2.pattern, "g");
456
+ return regex.test(evt.value);
457
+ },
374
458
  isFinalValue: (ctx2) => {
375
459
  return ctx2.filledValueLength + 1 === ctx2.valueLength && ctx2.value.findIndex((v) => v.trim() === "") === ctx2.focusedIndex;
376
460
  },
@@ -379,19 +463,10 @@ function machine(ctx = {}) {
379
463
  isDisabled: (ctx2) => !!ctx2.disabled
380
464
  },
381
465
  actions: {
382
- setupDocument: (ctx2, evt) => {
383
- if (evt.doc)
384
- ctx2.doc = (0, import_core.ref)(evt.doc);
385
- if (evt.root)
386
- ctx2.rootNode = (0, import_core.ref)(evt.root);
387
- ctx2.uid = evt.id;
388
- },
389
466
  setupValue: (ctx2) => {
390
- nextTick(() => {
391
- const inputs = dom.getElements(ctx2);
392
- const empty = fromLength(inputs.length).map(() => "");
393
- ctx2.value = Object.assign(empty, ctx2.value);
394
- });
467
+ const inputs = dom.getElements(ctx2);
468
+ const empty = Array.from({ length: inputs.length }).map(() => "");
469
+ ctx2.value = Object.assign(empty, ctx2.value);
395
470
  },
396
471
  focusInput: (ctx2) => {
397
472
  raf(() => {
@@ -401,17 +476,18 @@ function machine(ctx = {}) {
401
476
  (_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.focus();
402
477
  });
403
478
  },
404
- invokeComplete: (ctx2) => {
479
+ invokeOnComplete: (ctx2) => {
405
480
  var _a;
406
- if (ctx2.isValueComplete) {
407
- (_a = ctx2.onComplete) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value), valueAsString: ctx2.valueAsString });
408
- }
481
+ if (!ctx2.isValueComplete)
482
+ return;
483
+ (_a = ctx2.onComplete) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value), valueAsString: ctx2.valueAsString });
409
484
  },
410
485
  invokeOnChange: (ctx2, evt) => {
411
486
  var _a;
412
- if (evt.type !== "SETUP") {
413
- (_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value) });
414
- }
487
+ if (evt.type === "SETUP")
488
+ return;
489
+ (_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value) });
490
+ dispatchInputValueEvent(dom.getHiddenInputEl(ctx2), ctx2.valueAsString);
415
491
  },
416
492
  invokeOnInvalid: (ctx2, evt) => {
417
493
  var _a;
@@ -468,6 +544,13 @@ function machine(ctx = {}) {
468
544
  var _a;
469
545
  (_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.blur();
470
546
  });
547
+ },
548
+ requestFormSubmit(ctx2) {
549
+ var _a;
550
+ if (!ctx2.name)
551
+ return;
552
+ const input = dom.getHiddenInputEl(ctx2);
553
+ (_a = input == null ? void 0 : input.form) == null ? void 0 : _a.requestSubmit();
471
554
  }
472
555
  }
473
556
  });
package/dist/index.mjs CHANGED
@@ -19,17 +19,85 @@ var __spreadValues = (a, b) => {
19
19
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
20
 
21
21
  // ../../utilities/dom/dist/index.mjs
22
+ var __defProp2 = Object.defineProperty;
23
+ var __getOwnPropSymbols2 = Object.getOwnPropertySymbols;
24
+ var __hasOwnProp2 = Object.prototype.hasOwnProperty;
25
+ var __propIsEnum2 = Object.prototype.propertyIsEnumerable;
26
+ var __defNormalProp2 = (obj, key, value) => key in obj ? __defProp2(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
27
+ var __spreadValues2 = (a, b) => {
28
+ for (var prop in b || (b = {}))
29
+ if (__hasOwnProp2.call(b, prop))
30
+ __defNormalProp2(a, prop, b[prop]);
31
+ if (__getOwnPropSymbols2)
32
+ for (var prop of __getOwnPropSymbols2(b)) {
33
+ if (__propIsEnum2.call(b, prop))
34
+ __defNormalProp2(a, prop, b[prop]);
35
+ }
36
+ return a;
37
+ };
22
38
  var dataAttr = (guard) => {
23
39
  return guard ? "" : void 0;
24
40
  };
25
41
  var ariaAttr = (guard) => {
26
42
  return guard ? "true" : void 0;
27
43
  };
44
+ function isDocument(el) {
45
+ return el.nodeType === Node.DOCUMENT_NODE;
46
+ }
47
+ function isWindow(value) {
48
+ return (value == null ? void 0 : value.toString()) === "[object Window]";
49
+ }
50
+ function getDocument(el) {
51
+ var _a;
52
+ if (isWindow(el))
53
+ return el.document;
54
+ if (isDocument(el))
55
+ return el;
56
+ return (_a = el == null ? void 0 : el.ownerDocument) != null ? _a : document;
57
+ }
58
+ function getWindow(el) {
59
+ var _a;
60
+ return (_a = el == null ? void 0 : el.ownerDocument.defaultView) != null ? _a : window;
61
+ }
62
+ function defineDomHelpers(helpers) {
63
+ const dom2 = {
64
+ getRootNode: (ctx) => {
65
+ var _a, _b;
66
+ return (_b = (_a = ctx.getRootNode) == null ? void 0 : _a.call(ctx)) != null ? _b : document;
67
+ },
68
+ getDoc: (ctx) => getDocument(dom2.getRootNode(ctx)),
69
+ getWin: (ctx) => {
70
+ var _a;
71
+ return (_a = dom2.getDoc(ctx).defaultView) != null ? _a : window;
72
+ },
73
+ getActiveElement: (ctx) => dom2.getDoc(ctx).activeElement,
74
+ getById: (ctx, id) => dom2.getRootNode(ctx).getElementById(id)
75
+ };
76
+ return __spreadValues2(__spreadValues2({}, dom2), helpers);
77
+ }
28
78
  function getNativeEvent(e) {
29
79
  var _a;
30
80
  return (_a = e.nativeEvent) != null ? _a : e;
31
81
  }
32
82
  var isModifiedEvent = (v) => v.ctrlKey || v.altKey || v.metaKey;
83
+ function getDescriptor(el, options) {
84
+ var _a;
85
+ const { type, property } = options;
86
+ const proto = getWindow(el)[type].prototype;
87
+ return (_a = Object.getOwnPropertyDescriptor(proto, property)) != null ? _a : {};
88
+ }
89
+ function dispatchInputValueEvent(el, value) {
90
+ var _a;
91
+ if (!el)
92
+ return;
93
+ const win = getWindow(el);
94
+ if (!(el instanceof win.HTMLInputElement))
95
+ return;
96
+ const desc = getDescriptor(el, { type: "HTMLInputElement", property: "value" });
97
+ (_a = desc.set) == null ? void 0 : _a.call(el, value);
98
+ const event = new win.Event("input", { bubbles: true });
99
+ el.dispatchEvent(event);
100
+ }
33
101
  var rtlKeyMap = {
34
102
  ArrowLeft: "ArrowRight",
35
103
  ArrowRight: "ArrowLeft",
@@ -56,19 +124,6 @@ function getEventKey(event, options = {}) {
56
124
  }
57
125
  return key;
58
126
  }
59
- function nextTick(fn) {
60
- const set = /* @__PURE__ */ new Set();
61
- function raf2(fn2) {
62
- const id = globalThis.requestAnimationFrame(fn2);
63
- set.add(() => globalThis.cancelAnimationFrame(id));
64
- }
65
- raf2(() => raf2(fn));
66
- return function cleanup() {
67
- set.forEach(function(fn2) {
68
- fn2();
69
- });
70
- };
71
- }
72
127
  function raf(fn) {
73
128
  const id = globalThis.requestAnimationFrame(fn);
74
129
  return function cleanup() {
@@ -79,9 +134,20 @@ function queryAll(root, selector) {
79
134
  var _a;
80
135
  return Array.from((_a = root == null ? void 0 : root.querySelectorAll(selector)) != null ? _a : []);
81
136
  }
137
+ var visuallyHiddenStyle = {
138
+ border: "0",
139
+ clip: "rect(0 0 0 0)",
140
+ height: "1px",
141
+ margin: "-1px",
142
+ overflow: "hidden",
143
+ padding: "0",
144
+ position: "absolute",
145
+ width: "1px",
146
+ whiteSpace: "nowrap",
147
+ wordWrap: "normal"
148
+ };
82
149
 
83
150
  // ../../utilities/core/dist/index.mjs
84
- var fromLength = (length) => Array.from(Array(length).keys());
85
151
  function invariant(...a) {
86
152
  const m = a.length === 1 ? a[0] : a[1];
87
153
  const c = a.length === 2 ? a[0] : true;
@@ -91,32 +157,29 @@ function invariant(...a) {
91
157
  }
92
158
 
93
159
  // src/pin-input.dom.ts
94
- var dom = {
95
- getDoc: (ctx) => {
96
- var _a;
97
- return (_a = ctx.doc) != null ? _a : document;
98
- },
99
- getRootNode: (ctx) => {
100
- var _a;
101
- return (_a = ctx.rootNode) != null ? _a : dom.getDoc(ctx);
102
- },
160
+ var dom = defineDomHelpers({
103
161
  getRootId: (ctx) => {
104
162
  var _a, _b;
105
- return (_b = (_a = ctx.ids) == null ? void 0 : _a.root) != null ? _b : `pin-input:${ctx.uid}`;
163
+ return (_b = (_a = ctx.ids) == null ? void 0 : _a.root) != null ? _b : `pin-input:${ctx.id}`;
106
164
  },
107
165
  getInputId: (ctx, id) => {
108
166
  var _a, _b, _c;
109
- return (_c = (_b = (_a = ctx.ids) == null ? void 0 : _a.input) == null ? void 0 : _b.call(_a, id)) != null ? _c : `pin-input:${ctx.uid}:${id}`;
167
+ 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}`;
110
168
  },
111
- getRootEl: (ctx) => dom.getRootNode(ctx).getElementById(dom.getRootId(ctx)),
169
+ getHiddenInputId: (ctx) => {
170
+ var _a, _b;
171
+ return (_b = (_a = ctx.ids) == null ? void 0 : _a.hiddenInput) != null ? _b : `pin-input:${ctx.id}:hidden`;
172
+ },
173
+ getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
112
174
  getElements: (ctx) => {
113
175
  const ownerId = CSS.escape(dom.getRootId(ctx));
114
176
  const selector = `input[data-ownedby=${ownerId}]`;
115
177
  return queryAll(dom.getRootEl(ctx), selector);
116
178
  },
117
179
  getFocusedEl: (ctx) => dom.getElements(ctx)[ctx.focusedIndex],
118
- getFirstInputEl: (ctx) => dom.getElements(ctx)[0]
119
- };
180
+ getFirstInputEl: (ctx) => dom.getElements(ctx)[0],
181
+ getHiddenInputEl: (ctx) => dom.getById(ctx, dom.getHiddenInputId(ctx))
182
+ });
120
183
 
121
184
  // src/pin-input.connect.ts
122
185
  function connect(state, send, normalize) {
@@ -152,6 +215,16 @@ function connect(state, send, normalize) {
152
215
  "data-disabled": dataAttr(state.context.disabled),
153
216
  "data-complete": dataAttr(isValueComplete)
154
217
  }),
218
+ hiddenInputProps: normalize.input({
219
+ "aria-hidden": true,
220
+ type: "text",
221
+ tabIndex: -1,
222
+ id: dom.getHiddenInputId(state.context),
223
+ name: state.context.name,
224
+ style: visuallyHiddenStyle,
225
+ maxLength: state.context.valueLength,
226
+ defaultValue: state.context.valueAsString
227
+ }),
155
228
  getInputProps({ index }) {
156
229
  const inputType = state.context.type === "numeric" ? "tel" : "text";
157
230
  return normalize.input({
@@ -200,6 +273,9 @@ function connect(state, send, normalize) {
200
273
  },
201
274
  ArrowRight() {
202
275
  send("ARROW_RIGHT");
276
+ },
277
+ Enter() {
278
+ send("ENTER");
203
279
  }
204
280
  };
205
281
  const key = getEventKey(event, { dir: state.context.dir });
@@ -223,14 +299,13 @@ function connect(state, send, normalize) {
223
299
  }
224
300
 
225
301
  // src/pin-input.machine.ts
226
- import { createMachine, guards, ref } from "@zag-js/core";
302
+ import { createMachine, guards } from "@zag-js/core";
227
303
  var { and, not } = guards;
228
- function machine(ctx = {}) {
304
+ function machine(ctx) {
229
305
  return createMachine({
230
306
  id: "pin-input",
231
307
  initial: "unknown",
232
308
  context: __spreadProps(__spreadValues({
233
- uid: "pin-input",
234
309
  value: [],
235
310
  focusedIndex: -1,
236
311
  placeholder: "\u25CB",
@@ -250,7 +325,7 @@ function machine(ctx = {}) {
250
325
  watch: {
251
326
  focusedIndex: "focusInput",
252
327
  value: "invokeOnChange",
253
- isValueComplete: ["invokeComplete", "blurFocusedInputIfNeeded"]
328
+ isValueComplete: ["invokeOnComplete", "blurFocusedInputIfNeeded"]
254
329
  },
255
330
  on: {
256
331
  SET_VALUE: [
@@ -277,11 +352,11 @@ function machine(ctx = {}) {
277
352
  {
278
353
  guard: "autoFocus",
279
354
  target: "focused",
280
- actions: ["setupDocument", "setupValue", "setFocusIndexToFirst"]
355
+ actions: ["setupValue", "setFocusIndexToFirst"]
281
356
  },
282
357
  {
283
358
  target: "idle",
284
- actions: ["setupDocument", "setupValue"]
359
+ actions: "setupValue"
285
360
  }
286
361
  ]
287
362
  }
@@ -333,6 +408,10 @@ function machine(ctx = {}) {
333
408
  actions: ["setPrevFocusedIndex", "clearFocusedValue"]
334
409
  }
335
410
  ],
411
+ ENTER: {
412
+ guard: "isValueComplete",
413
+ actions: "requestFormSubmit"
414
+ },
336
415
  KEY_DOWN: {
337
416
  guard: not("isValidValue"),
338
417
  actions: ["preventDefault", "invokeOnInvalid"]
@@ -346,7 +425,12 @@ function machine(ctx = {}) {
346
425
  isValueEmpty: (_ctx, evt) => evt.value === "",
347
426
  hasValue: (ctx2) => ctx2.value[ctx2.focusedIndex] !== "",
348
427
  isValueComplete: (ctx2) => ctx2.isValueComplete,
349
- isValidValue: (ctx2, evt) => isValidType(evt.value, ctx2.type),
428
+ isValidValue: (ctx2, evt) => {
429
+ if (!ctx2.pattern)
430
+ return isValidType(evt.value, ctx2.type);
431
+ const regex = new RegExp(ctx2.pattern, "g");
432
+ return regex.test(evt.value);
433
+ },
350
434
  isFinalValue: (ctx2) => {
351
435
  return ctx2.filledValueLength + 1 === ctx2.valueLength && ctx2.value.findIndex((v) => v.trim() === "") === ctx2.focusedIndex;
352
436
  },
@@ -355,19 +439,10 @@ function machine(ctx = {}) {
355
439
  isDisabled: (ctx2) => !!ctx2.disabled
356
440
  },
357
441
  actions: {
358
- setupDocument: (ctx2, evt) => {
359
- if (evt.doc)
360
- ctx2.doc = ref(evt.doc);
361
- if (evt.root)
362
- ctx2.rootNode = ref(evt.root);
363
- ctx2.uid = evt.id;
364
- },
365
442
  setupValue: (ctx2) => {
366
- nextTick(() => {
367
- const inputs = dom.getElements(ctx2);
368
- const empty = fromLength(inputs.length).map(() => "");
369
- ctx2.value = Object.assign(empty, ctx2.value);
370
- });
443
+ const inputs = dom.getElements(ctx2);
444
+ const empty = Array.from({ length: inputs.length }).map(() => "");
445
+ ctx2.value = Object.assign(empty, ctx2.value);
371
446
  },
372
447
  focusInput: (ctx2) => {
373
448
  raf(() => {
@@ -377,17 +452,18 @@ function machine(ctx = {}) {
377
452
  (_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.focus();
378
453
  });
379
454
  },
380
- invokeComplete: (ctx2) => {
455
+ invokeOnComplete: (ctx2) => {
381
456
  var _a;
382
- if (ctx2.isValueComplete) {
383
- (_a = ctx2.onComplete) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value), valueAsString: ctx2.valueAsString });
384
- }
457
+ if (!ctx2.isValueComplete)
458
+ return;
459
+ (_a = ctx2.onComplete) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value), valueAsString: ctx2.valueAsString });
385
460
  },
386
461
  invokeOnChange: (ctx2, evt) => {
387
462
  var _a;
388
- if (evt.type !== "SETUP") {
389
- (_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value) });
390
- }
463
+ if (evt.type === "SETUP")
464
+ return;
465
+ (_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value) });
466
+ dispatchInputValueEvent(dom.getHiddenInputEl(ctx2), ctx2.valueAsString);
391
467
  },
392
468
  invokeOnInvalid: (ctx2, evt) => {
393
469
  var _a;
@@ -444,6 +520,13 @@ function machine(ctx = {}) {
444
520
  var _a;
445
521
  (_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.blur();
446
522
  });
523
+ },
524
+ requestFormSubmit(ctx2) {
525
+ var _a;
526
+ if (!ctx2.name)
527
+ return;
528
+ const input = dom.getHiddenInputEl(ctx2);
529
+ (_a = input == null ? void 0 : input.form) == null ? void 0 : _a.requestSubmit();
447
530
  }
448
531
  }
449
532
  });
@@ -9,6 +9,7 @@ export declare function connect<T extends PropTypes>(state: State, send: Send, n
9
9
  setValueAtIndex(index: number, value: string): void;
10
10
  focus(): void;
11
11
  rootProps: T["element"];
12
+ hiddenInputProps: T["input"];
12
13
  getInputProps({ index }: {
13
14
  index: number;
14
15
  }): T["input"];
@@ -1,11 +1,27 @@
1
1
  import type { MachineContext as Ctx } from "./pin-input.types";
2
2
  export declare const dom: {
3
- getDoc: (ctx: Ctx) => Document;
4
- getRootNode: (ctx: Ctx) => Document | ShadowRoot;
3
+ getRootNode: (ctx: {
4
+ getRootNode?: () => Node | Document | ShadowRoot;
5
+ }) => Document | ShadowRoot;
6
+ getDoc: (ctx: {
7
+ getRootNode?: () => Node | Document | ShadowRoot;
8
+ }) => Document;
9
+ getWin: (ctx: {
10
+ getRootNode?: () => Node | Document | ShadowRoot;
11
+ }) => Window & typeof globalThis;
12
+ getActiveElement: (ctx: {
13
+ getRootNode?: () => Node | Document | ShadowRoot;
14
+ }) => HTMLElement;
15
+ getById: <T_1 = HTMLElement>(ctx: {
16
+ getRootNode?: () => Node | Document | ShadowRoot;
17
+ }, id: string) => T_1;
18
+ } & {
5
19
  getRootId: (ctx: Ctx) => string;
6
20
  getInputId: (ctx: Ctx, id: string) => string;
21
+ getHiddenInputId: (ctx: Ctx) => string;
7
22
  getRootEl: (ctx: Ctx) => HTMLElement;
8
23
  getElements: (ctx: Ctx) => HTMLInputElement[];
9
24
  getFocusedEl: (ctx: Ctx) => HTMLInputElement;
10
25
  getFirstInputEl: (ctx: Ctx) => HTMLInputElement;
26
+ getHiddenInputEl: (ctx: Ctx) => HTMLInputElement;
11
27
  };
@@ -1,2 +1,2 @@
1
1
  import type { MachineContext, MachineState, UserDefinedContext } from "./pin-input.types";
2
- export declare function machine(ctx?: UserDefinedContext): import("@zag-js/core").Machine<MachineContext, MachineState, import("@zag-js/core").StateMachine.AnyEventObject>;
2
+ export declare function machine(ctx: UserDefinedContext): import("@zag-js/core").Machine<MachineContext, MachineState, import("@zag-js/core").StateMachine.AnyEventObject>;
@@ -1,13 +1,22 @@
1
1
  import type { StateMachine as S } from "@zag-js/core";
2
- import type { Context, DirectionProperty } from "@zag-js/types";
2
+ import type { CommonProperties, Context, DirectionProperty, RequiredBy } from "@zag-js/types";
3
3
  declare type IntlMessages = {
4
4
  inputLabel: (index: number, length: number) => string;
5
5
  };
6
6
  declare type ElementIds = Partial<{
7
7
  root: string;
8
+ hiddenInput: string;
8
9
  input(id: string): string;
9
10
  }>;
10
- declare type PublicContext = DirectionProperty & {
11
+ declare type PublicContext = DirectionProperty & CommonProperties & {
12
+ /**
13
+ * The name of the input element. Useful for form submission.
14
+ */
15
+ name?: string;
16
+ /**
17
+ * The regular expression that the user-entered input value is checked against.
18
+ */
19
+ pattern?: string;
11
20
  /**
12
21
  * The ids of the elements in the pin input. Useful for composition.
13
22
  */
@@ -74,7 +83,7 @@ declare type PublicContext = DirectionProperty & {
74
83
  */
75
84
  messages: IntlMessages;
76
85
  };
77
- export declare type UserDefinedContext = Partial<PublicContext>;
86
+ export declare type UserDefinedContext = RequiredBy<PublicContext, "id">;
78
87
  declare type ComputedContext = Readonly<{
79
88
  /**
80
89
  * @computed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zag-js/pin-input",
3
- "version": "0.1.9",
3
+ "version": "0.1.10",
4
4
  "description": "Core logic for the pin-input widget implemented as a state machine",
5
5
  "keywords": [
6
6
  "js",
@@ -29,9 +29,11 @@
29
29
  "url": "https://github.com/chakra-ui/zag/issues"
30
30
  },
31
31
  "dependencies": {
32
- "@zag-js/core": "0.1.7",
33
- "@zag-js/dom-utils": "0.1.6",
34
- "@zag-js/types": "0.2.1",
32
+ "@zag-js/core": "0.1.8",
33
+ "@zag-js/types": "0.2.2"
34
+ },
35
+ "devDependencies": {
36
+ "@zag-js/dom-utils": "0.1.7",
35
37
  "@zag-js/utils": "0.1.2"
36
38
  },
37
39
  "scripts": {