@zag-js/pin-input 0.1.16 → 0.1.17
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 +2 -2
- package/dist/index.js +40 -12
- package/dist/index.mjs +546 -0
- package/package.json +11 -11
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { RequiredBy, DirectionProperty, CommonProperties, Context, PropTypes, No
|
|
|
2
2
|
import * as _zag_js_core from '@zag-js/core';
|
|
3
3
|
import { StateMachine } from '@zag-js/core';
|
|
4
4
|
|
|
5
|
-
declare type
|
|
5
|
+
declare type IntlTranslations = {
|
|
6
6
|
inputLabel: (index: number, length: number) => string;
|
|
7
7
|
};
|
|
8
8
|
declare type ElementIds = Partial<{
|
|
@@ -84,7 +84,7 @@ declare type PublicContext = DirectionProperty & CommonProperties & {
|
|
|
84
84
|
/**
|
|
85
85
|
* Specifies the localized strings that identifies the accessibility elements and their states
|
|
86
86
|
*/
|
|
87
|
-
|
|
87
|
+
translations: IntlTranslations;
|
|
88
88
|
};
|
|
89
89
|
declare type UserDefinedContext = RequiredBy<PublicContext, "id">;
|
|
90
90
|
declare type ComputedContext = Readonly<{
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,31 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
connect: () => connect,
|
|
24
|
+
machine: () => machine
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(src_exports);
|
|
27
|
+
|
|
28
|
+
// ../../utilities/dom/dist/index.mjs
|
|
2
29
|
var dataAttr = (guard) => {
|
|
3
30
|
return guard ? "" : void 0;
|
|
4
31
|
};
|
|
@@ -83,7 +110,7 @@ var visuallyHiddenStyle = {
|
|
|
83
110
|
wordWrap: "normal"
|
|
84
111
|
};
|
|
85
112
|
|
|
86
|
-
// ../../utilities/core/dist/index.
|
|
113
|
+
// ../../utilities/core/dist/index.mjs
|
|
87
114
|
function invariant(...a) {
|
|
88
115
|
const m = a.length === 1 ? a[0] : a[1];
|
|
89
116
|
const c = a.length === 2 ? a[0] : true;
|
|
@@ -126,7 +153,7 @@ function connect(state, send, normalize) {
|
|
|
126
153
|
const isValueComplete = state.context.isValueComplete;
|
|
127
154
|
const isInvalid = state.context.invalid;
|
|
128
155
|
const focusedIndex = state.context.focusedIndex;
|
|
129
|
-
const
|
|
156
|
+
const translations = state.context.translations;
|
|
130
157
|
function focus() {
|
|
131
158
|
var _a;
|
|
132
159
|
(_a = dom.getFirstInputEl(state.context)) == null ? void 0 : _a.focus();
|
|
@@ -187,7 +214,7 @@ function connect(state, send, normalize) {
|
|
|
187
214
|
"data-complete": dataAttr(isValueComplete),
|
|
188
215
|
id: dom.getInputId(state.context, index.toString()),
|
|
189
216
|
"data-ownedby": dom.getRootId(state.context),
|
|
190
|
-
"aria-label":
|
|
217
|
+
"aria-label": translations.inputLabel(index, state.context.valueLength),
|
|
191
218
|
inputMode: state.context.otp || state.context.type === "numeric" ? "numeric" : "text",
|
|
192
219
|
"aria-invalid": ariaAttr(isInvalid),
|
|
193
220
|
"data-invalid": dataAttr(isInvalid),
|
|
@@ -254,9 +281,9 @@ function connect(state, send, normalize) {
|
|
|
254
281
|
}
|
|
255
282
|
|
|
256
283
|
// src/pin-input.machine.ts
|
|
257
|
-
|
|
284
|
+
var import_core = require("@zag-js/core");
|
|
258
285
|
|
|
259
|
-
// ../../utilities/form-utils/dist/index.
|
|
286
|
+
// ../../utilities/form-utils/dist/index.mjs
|
|
260
287
|
function getWindow(el) {
|
|
261
288
|
return (el == null ? void 0 : el.ownerDocument.defaultView) ?? window;
|
|
262
289
|
}
|
|
@@ -279,9 +306,9 @@ function dispatchInputValueEvent(el, value) {
|
|
|
279
306
|
}
|
|
280
307
|
|
|
281
308
|
// src/pin-input.machine.ts
|
|
282
|
-
var { and, not } = guards;
|
|
309
|
+
var { and, not } = import_core.guards;
|
|
283
310
|
function machine(ctx) {
|
|
284
|
-
return createMachine(
|
|
311
|
+
return (0, import_core.createMachine)(
|
|
285
312
|
{
|
|
286
313
|
id: "pin-input",
|
|
287
314
|
initial: "unknown",
|
|
@@ -292,9 +319,9 @@ function machine(ctx) {
|
|
|
292
319
|
otp: false,
|
|
293
320
|
type: "numeric",
|
|
294
321
|
...ctx,
|
|
295
|
-
|
|
322
|
+
translations: {
|
|
296
323
|
inputLabel: (index, length) => `pin code ${index + 1} of ${length}`,
|
|
297
|
-
...ctx.
|
|
324
|
+
...ctx.translations
|
|
298
325
|
}
|
|
299
326
|
},
|
|
300
327
|
computed: {
|
|
@@ -540,7 +567,8 @@ function assign(ctx, value) {
|
|
|
540
567
|
function lastChar(value) {
|
|
541
568
|
return value.charAt(value.length - 1);
|
|
542
569
|
}
|
|
543
|
-
export
|
|
570
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
571
|
+
0 && (module.exports = {
|
|
544
572
|
connect,
|
|
545
573
|
machine
|
|
546
|
-
};
|
|
574
|
+
});
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
// ../../utilities/dom/dist/index.mjs
|
|
2
|
+
var dataAttr = (guard) => {
|
|
3
|
+
return guard ? "" : void 0;
|
|
4
|
+
};
|
|
5
|
+
var ariaAttr = (guard) => {
|
|
6
|
+
return guard ? "true" : void 0;
|
|
7
|
+
};
|
|
8
|
+
function isDocument(el) {
|
|
9
|
+
return el.nodeType === Node.DOCUMENT_NODE;
|
|
10
|
+
}
|
|
11
|
+
function isWindow(value) {
|
|
12
|
+
return (value == null ? void 0 : value.toString()) === "[object Window]";
|
|
13
|
+
}
|
|
14
|
+
function getDocument(el) {
|
|
15
|
+
if (isWindow(el))
|
|
16
|
+
return el.document;
|
|
17
|
+
if (isDocument(el))
|
|
18
|
+
return el;
|
|
19
|
+
return (el == null ? void 0 : el.ownerDocument) ?? document;
|
|
20
|
+
}
|
|
21
|
+
function defineDomHelpers(helpers) {
|
|
22
|
+
const dom2 = {
|
|
23
|
+
getRootNode: (ctx) => {
|
|
24
|
+
var _a;
|
|
25
|
+
return ((_a = ctx.getRootNode) == null ? void 0 : _a.call(ctx)) ?? document;
|
|
26
|
+
},
|
|
27
|
+
getDoc: (ctx) => getDocument(dom2.getRootNode(ctx)),
|
|
28
|
+
getWin: (ctx) => dom2.getDoc(ctx).defaultView ?? window,
|
|
29
|
+
getActiveElement: (ctx) => dom2.getDoc(ctx).activeElement,
|
|
30
|
+
getById: (ctx, id) => dom2.getRootNode(ctx).getElementById(id)
|
|
31
|
+
};
|
|
32
|
+
return {
|
|
33
|
+
...dom2,
|
|
34
|
+
...helpers
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
function getNativeEvent(e) {
|
|
38
|
+
return e.nativeEvent ?? e;
|
|
39
|
+
}
|
|
40
|
+
var isModifiedEvent = (v) => v.ctrlKey || v.altKey || v.metaKey;
|
|
41
|
+
var rtlKeyMap = {
|
|
42
|
+
ArrowLeft: "ArrowRight",
|
|
43
|
+
ArrowRight: "ArrowLeft"
|
|
44
|
+
};
|
|
45
|
+
var sameKeyMap = {
|
|
46
|
+
Up: "ArrowUp",
|
|
47
|
+
Down: "ArrowDown",
|
|
48
|
+
Esc: "Escape",
|
|
49
|
+
" ": "Space",
|
|
50
|
+
",": "Comma",
|
|
51
|
+
Left: "ArrowLeft",
|
|
52
|
+
Right: "ArrowRight"
|
|
53
|
+
};
|
|
54
|
+
function getEventKey(event, options = {}) {
|
|
55
|
+
const { dir = "ltr", orientation = "horizontal" } = options;
|
|
56
|
+
let { key } = event;
|
|
57
|
+
key = sameKeyMap[key] ?? key;
|
|
58
|
+
const isRtl = dir === "rtl" && orientation === "horizontal";
|
|
59
|
+
if (isRtl && key in rtlKeyMap) {
|
|
60
|
+
key = rtlKeyMap[key];
|
|
61
|
+
}
|
|
62
|
+
return key;
|
|
63
|
+
}
|
|
64
|
+
function raf(fn) {
|
|
65
|
+
const id = globalThis.requestAnimationFrame(fn);
|
|
66
|
+
return function cleanup() {
|
|
67
|
+
globalThis.cancelAnimationFrame(id);
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
function queryAll(root, selector) {
|
|
71
|
+
return Array.from((root == null ? void 0 : root.querySelectorAll(selector)) ?? []);
|
|
72
|
+
}
|
|
73
|
+
var visuallyHiddenStyle = {
|
|
74
|
+
border: "0",
|
|
75
|
+
clip: "rect(0 0 0 0)",
|
|
76
|
+
height: "1px",
|
|
77
|
+
margin: "-1px",
|
|
78
|
+
overflow: "hidden",
|
|
79
|
+
padding: "0",
|
|
80
|
+
position: "absolute",
|
|
81
|
+
width: "1px",
|
|
82
|
+
whiteSpace: "nowrap",
|
|
83
|
+
wordWrap: "normal"
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
// ../../utilities/core/dist/index.mjs
|
|
87
|
+
function invariant(...a) {
|
|
88
|
+
const m = a.length === 1 ? a[0] : a[1];
|
|
89
|
+
const c = a.length === 2 ? a[0] : true;
|
|
90
|
+
if (c && process.env.NODE_ENV !== "production") {
|
|
91
|
+
throw new Error(m);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// src/pin-input.dom.ts
|
|
96
|
+
var dom = defineDomHelpers({
|
|
97
|
+
getRootId: (ctx) => {
|
|
98
|
+
var _a;
|
|
99
|
+
return ((_a = ctx.ids) == null ? void 0 : _a.root) ?? `pin-input:${ctx.id}`;
|
|
100
|
+
},
|
|
101
|
+
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}`;
|
|
104
|
+
},
|
|
105
|
+
getHiddenInputId: (ctx) => {
|
|
106
|
+
var _a;
|
|
107
|
+
return ((_a = ctx.ids) == null ? void 0 : _a.hiddenInput) ?? `pin-input:${ctx.id}:hidden`;
|
|
108
|
+
},
|
|
109
|
+
getLabelId: (ctx) => {
|
|
110
|
+
var _a;
|
|
111
|
+
return ((_a = ctx.ids) == null ? void 0 : _a.label) ?? `pin-input:${ctx.id}:label`;
|
|
112
|
+
},
|
|
113
|
+
getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
|
|
114
|
+
getElements: (ctx) => {
|
|
115
|
+
const ownerId = CSS.escape(dom.getRootId(ctx));
|
|
116
|
+
const selector = `input[data-ownedby=${ownerId}]`;
|
|
117
|
+
return queryAll(dom.getRootEl(ctx), selector);
|
|
118
|
+
},
|
|
119
|
+
getFocusedEl: (ctx) => dom.getElements(ctx)[ctx.focusedIndex],
|
|
120
|
+
getFirstInputEl: (ctx) => dom.getElements(ctx)[0],
|
|
121
|
+
getHiddenInputEl: (ctx) => dom.getById(ctx, dom.getHiddenInputId(ctx))
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
// src/pin-input.connect.ts
|
|
125
|
+
function connect(state, send, normalize) {
|
|
126
|
+
const isValueComplete = state.context.isValueComplete;
|
|
127
|
+
const isInvalid = state.context.invalid;
|
|
128
|
+
const focusedIndex = state.context.focusedIndex;
|
|
129
|
+
const translations = state.context.translations;
|
|
130
|
+
function focus() {
|
|
131
|
+
var _a;
|
|
132
|
+
(_a = dom.getFirstInputEl(state.context)) == null ? void 0 : _a.focus();
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
value: state.context.value,
|
|
136
|
+
valueAsString: state.context.valueAsString,
|
|
137
|
+
isValueComplete,
|
|
138
|
+
setValue(value) {
|
|
139
|
+
if (!Array.isArray(value)) {
|
|
140
|
+
invariant("[pin-input/setValue] value must be an array");
|
|
141
|
+
}
|
|
142
|
+
send({ type: "SET_VALUE", value });
|
|
143
|
+
},
|
|
144
|
+
clearValue() {
|
|
145
|
+
send({ type: "CLEAR_VALUE" });
|
|
146
|
+
},
|
|
147
|
+
setValueAtIndex(index, value) {
|
|
148
|
+
send({ type: "SET_VALUE", value, index });
|
|
149
|
+
},
|
|
150
|
+
focus,
|
|
151
|
+
rootProps: normalize.element({
|
|
152
|
+
dir: state.context.dir,
|
|
153
|
+
"data-part": "root",
|
|
154
|
+
id: dom.getRootId(state.context),
|
|
155
|
+
"data-invalid": dataAttr(isInvalid),
|
|
156
|
+
"data-disabled": dataAttr(state.context.disabled),
|
|
157
|
+
"data-complete": dataAttr(isValueComplete)
|
|
158
|
+
}),
|
|
159
|
+
labelProps: normalize.label({
|
|
160
|
+
"data-part": "label",
|
|
161
|
+
htmlFor: dom.getHiddenInputId(state.context),
|
|
162
|
+
id: dom.getLabelId(state.context),
|
|
163
|
+
"data-invalid": dataAttr(isInvalid),
|
|
164
|
+
"data-disabled": dataAttr(state.context.disabled),
|
|
165
|
+
"data-complete": dataAttr(isValueComplete),
|
|
166
|
+
onClick: (event) => {
|
|
167
|
+
event.preventDefault();
|
|
168
|
+
focus();
|
|
169
|
+
}
|
|
170
|
+
}),
|
|
171
|
+
hiddenInputProps: normalize.input({
|
|
172
|
+
"aria-hidden": true,
|
|
173
|
+
type: "text",
|
|
174
|
+
tabIndex: -1,
|
|
175
|
+
id: dom.getHiddenInputId(state.context),
|
|
176
|
+
name: state.context.name,
|
|
177
|
+
style: visuallyHiddenStyle,
|
|
178
|
+
maxLength: state.context.valueLength,
|
|
179
|
+
defaultValue: state.context.valueAsString
|
|
180
|
+
}),
|
|
181
|
+
getInputProps({ index }) {
|
|
182
|
+
const inputType = state.context.type === "numeric" ? "tel" : "text";
|
|
183
|
+
return normalize.input({
|
|
184
|
+
"data-part": "input",
|
|
185
|
+
disabled: state.context.disabled,
|
|
186
|
+
"data-disabled": dataAttr(state.context.disabled),
|
|
187
|
+
"data-complete": dataAttr(isValueComplete),
|
|
188
|
+
id: dom.getInputId(state.context, index.toString()),
|
|
189
|
+
"data-ownedby": dom.getRootId(state.context),
|
|
190
|
+
"aria-label": translations.inputLabel(index, state.context.valueLength),
|
|
191
|
+
inputMode: state.context.otp || state.context.type === "numeric" ? "numeric" : "text",
|
|
192
|
+
"aria-invalid": ariaAttr(isInvalid),
|
|
193
|
+
"data-invalid": dataAttr(isInvalid),
|
|
194
|
+
type: state.context.mask ? "password" : inputType,
|
|
195
|
+
value: state.context.value[index] || "",
|
|
196
|
+
autoCapitalize: "none",
|
|
197
|
+
autoComplete: state.context.otp ? "one-time-code" : "off",
|
|
198
|
+
placeholder: focusedIndex === index ? "" : state.context.placeholder,
|
|
199
|
+
onChange(event) {
|
|
200
|
+
const evt = getNativeEvent(event);
|
|
201
|
+
const { value } = event.currentTarget;
|
|
202
|
+
if (evt.inputType === "insertFromPaste" || value.length > 2) {
|
|
203
|
+
send({ type: "PASTE", value });
|
|
204
|
+
event.preventDefault();
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
if (evt.inputType === "deleteContentBackward") {
|
|
208
|
+
send("BACKSPACE");
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
send({ type: "INPUT", value });
|
|
212
|
+
},
|
|
213
|
+
onKeyDown(event) {
|
|
214
|
+
const evt = getNativeEvent(event);
|
|
215
|
+
if (evt.isComposing || isModifiedEvent(evt))
|
|
216
|
+
return;
|
|
217
|
+
const keyMap = {
|
|
218
|
+
Backspace() {
|
|
219
|
+
send("BACKSPACE");
|
|
220
|
+
},
|
|
221
|
+
Delete() {
|
|
222
|
+
send("DELETE");
|
|
223
|
+
},
|
|
224
|
+
ArrowLeft() {
|
|
225
|
+
send("ARROW_LEFT");
|
|
226
|
+
},
|
|
227
|
+
ArrowRight() {
|
|
228
|
+
send("ARROW_RIGHT");
|
|
229
|
+
},
|
|
230
|
+
Enter() {
|
|
231
|
+
send("ENTER");
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
const key = getEventKey(event, { dir: state.context.dir });
|
|
235
|
+
const exec = keyMap[key];
|
|
236
|
+
if (exec) {
|
|
237
|
+
exec(event);
|
|
238
|
+
event.preventDefault();
|
|
239
|
+
} else {
|
|
240
|
+
if (key === "Tab")
|
|
241
|
+
return;
|
|
242
|
+
send({ type: "KEY_DOWN", value: key, preventDefault: () => event.preventDefault() });
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
onFocus() {
|
|
246
|
+
send({ type: "FOCUS", index });
|
|
247
|
+
},
|
|
248
|
+
onBlur() {
|
|
249
|
+
send({ type: "BLUR", index });
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// src/pin-input.machine.ts
|
|
257
|
+
import { createMachine, guards } from "@zag-js/core";
|
|
258
|
+
|
|
259
|
+
// ../../utilities/form-utils/dist/index.mjs
|
|
260
|
+
function getWindow(el) {
|
|
261
|
+
return (el == null ? void 0 : el.ownerDocument.defaultView) ?? window;
|
|
262
|
+
}
|
|
263
|
+
function getDescriptor(el, options) {
|
|
264
|
+
const { type, property } = options;
|
|
265
|
+
const proto = getWindow(el)[type].prototype;
|
|
266
|
+
return Object.getOwnPropertyDescriptor(proto, property) ?? {};
|
|
267
|
+
}
|
|
268
|
+
function dispatchInputValueEvent(el, value) {
|
|
269
|
+
var _a;
|
|
270
|
+
if (!el)
|
|
271
|
+
return;
|
|
272
|
+
const win = getWindow(el);
|
|
273
|
+
if (!(el instanceof win.HTMLInputElement))
|
|
274
|
+
return;
|
|
275
|
+
const desc = getDescriptor(el, { type: "HTMLInputElement", property: "value" });
|
|
276
|
+
(_a = desc.set) == null ? void 0 : _a.call(el, value);
|
|
277
|
+
const event = new win.Event("input", { bubbles: true });
|
|
278
|
+
el.dispatchEvent(event);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// src/pin-input.machine.ts
|
|
282
|
+
var { and, not } = guards;
|
|
283
|
+
function machine(ctx) {
|
|
284
|
+
return createMachine(
|
|
285
|
+
{
|
|
286
|
+
id: "pin-input",
|
|
287
|
+
initial: "unknown",
|
|
288
|
+
context: {
|
|
289
|
+
value: [],
|
|
290
|
+
focusedIndex: -1,
|
|
291
|
+
placeholder: "\u25CB",
|
|
292
|
+
otp: false,
|
|
293
|
+
type: "numeric",
|
|
294
|
+
...ctx,
|
|
295
|
+
translations: {
|
|
296
|
+
inputLabel: (index, length) => `pin code ${index + 1} of ${length}`,
|
|
297
|
+
...ctx.translations
|
|
298
|
+
}
|
|
299
|
+
},
|
|
300
|
+
computed: {
|
|
301
|
+
valueLength: (ctx2) => ctx2.value.length,
|
|
302
|
+
filledValueLength: (ctx2) => ctx2.value.filter((v) => (v == null ? void 0 : v.trim()) !== "").length,
|
|
303
|
+
isValueComplete: (ctx2) => ctx2.valueLength === ctx2.filledValueLength,
|
|
304
|
+
valueAsString: (ctx2) => ctx2.value.join("")
|
|
305
|
+
},
|
|
306
|
+
watch: {
|
|
307
|
+
focusedIndex: "focusInput",
|
|
308
|
+
value: "invokeOnChange",
|
|
309
|
+
isValueComplete: ["invokeOnComplete", "blurFocusedInputIfNeeded"]
|
|
310
|
+
},
|
|
311
|
+
on: {
|
|
312
|
+
SET_VALUE: [
|
|
313
|
+
{
|
|
314
|
+
guard: "hasIndex",
|
|
315
|
+
actions: "setValueAtIndex"
|
|
316
|
+
},
|
|
317
|
+
{ actions: "setValue" }
|
|
318
|
+
],
|
|
319
|
+
CLEAR_VALUE: [
|
|
320
|
+
{
|
|
321
|
+
guard: "isDisabled",
|
|
322
|
+
actions: "clearValue"
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
actions: ["clearValue", "setFocusIndexToFirst"]
|
|
326
|
+
}
|
|
327
|
+
]
|
|
328
|
+
},
|
|
329
|
+
states: {
|
|
330
|
+
unknown: {
|
|
331
|
+
on: {
|
|
332
|
+
SETUP: [
|
|
333
|
+
{
|
|
334
|
+
guard: "autoFocus",
|
|
335
|
+
target: "focused",
|
|
336
|
+
actions: ["setupValue", "setFocusIndexToFirst"]
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
target: "idle",
|
|
340
|
+
actions: "setupValue"
|
|
341
|
+
}
|
|
342
|
+
]
|
|
343
|
+
}
|
|
344
|
+
},
|
|
345
|
+
idle: {
|
|
346
|
+
on: {
|
|
347
|
+
FOCUS: {
|
|
348
|
+
target: "focused",
|
|
349
|
+
actions: "setFocusedIndex"
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
},
|
|
353
|
+
focused: {
|
|
354
|
+
on: {
|
|
355
|
+
INPUT: [
|
|
356
|
+
{
|
|
357
|
+
guard: and("isFinalValue", "isValidValue"),
|
|
358
|
+
actions: "setFocusedValue"
|
|
359
|
+
},
|
|
360
|
+
{
|
|
361
|
+
guard: "isValidValue",
|
|
362
|
+
actions: ["setFocusedValue", "setNextFocusedIndex"]
|
|
363
|
+
}
|
|
364
|
+
],
|
|
365
|
+
PASTE: {
|
|
366
|
+
guard: "isValidValue",
|
|
367
|
+
actions: ["setPastedValue", "setLastValueFocusIndex"]
|
|
368
|
+
},
|
|
369
|
+
BLUR: {
|
|
370
|
+
target: "idle",
|
|
371
|
+
actions: "clearFocusedIndex"
|
|
372
|
+
},
|
|
373
|
+
DELETE: {
|
|
374
|
+
guard: "hasValue",
|
|
375
|
+
actions: "clearFocusedValue"
|
|
376
|
+
},
|
|
377
|
+
ARROW_LEFT: {
|
|
378
|
+
actions: "setPrevFocusedIndex"
|
|
379
|
+
},
|
|
380
|
+
ARROW_RIGHT: {
|
|
381
|
+
actions: "setNextFocusedIndex"
|
|
382
|
+
},
|
|
383
|
+
BACKSPACE: [
|
|
384
|
+
{
|
|
385
|
+
guard: "hasValue",
|
|
386
|
+
actions: "clearFocusedValue"
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
actions: ["setPrevFocusedIndex", "clearFocusedValue"]
|
|
390
|
+
}
|
|
391
|
+
],
|
|
392
|
+
ENTER: {
|
|
393
|
+
guard: "isValueComplete",
|
|
394
|
+
actions: "requestFormSubmit"
|
|
395
|
+
},
|
|
396
|
+
KEY_DOWN: {
|
|
397
|
+
guard: not("isValidValue"),
|
|
398
|
+
actions: ["preventDefault", "invokeOnInvalid"]
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
guards: {
|
|
406
|
+
autoFocus: (ctx2) => !!ctx2.autoFocus,
|
|
407
|
+
isValueEmpty: (_ctx, evt) => evt.value === "",
|
|
408
|
+
hasValue: (ctx2) => ctx2.value[ctx2.focusedIndex] !== "",
|
|
409
|
+
isValueComplete: (ctx2) => ctx2.isValueComplete,
|
|
410
|
+
isValidValue: (ctx2, evt) => {
|
|
411
|
+
if (!ctx2.pattern)
|
|
412
|
+
return isValidType(evt.value, ctx2.type);
|
|
413
|
+
const regex = new RegExp(ctx2.pattern, "g");
|
|
414
|
+
return regex.test(evt.value);
|
|
415
|
+
},
|
|
416
|
+
isFinalValue: (ctx2) => {
|
|
417
|
+
return ctx2.filledValueLength + 1 === ctx2.valueLength && ctx2.value.findIndex((v) => v.trim() === "") === ctx2.focusedIndex;
|
|
418
|
+
},
|
|
419
|
+
isLastInputFocused: (ctx2) => ctx2.focusedIndex === ctx2.valueLength - 1,
|
|
420
|
+
hasIndex: (_ctx, evt) => evt.index !== void 0,
|
|
421
|
+
isDisabled: (ctx2) => !!ctx2.disabled
|
|
422
|
+
},
|
|
423
|
+
actions: {
|
|
424
|
+
setupValue: (ctx2) => {
|
|
425
|
+
const inputs = dom.getElements(ctx2);
|
|
426
|
+
const empty = Array.from({ length: inputs.length }).map(() => "");
|
|
427
|
+
ctx2.value = Object.assign(empty, ctx2.value);
|
|
428
|
+
},
|
|
429
|
+
focusInput: (ctx2) => {
|
|
430
|
+
raf(() => {
|
|
431
|
+
var _a;
|
|
432
|
+
if (ctx2.focusedIndex === -1)
|
|
433
|
+
return;
|
|
434
|
+
(_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.focus();
|
|
435
|
+
});
|
|
436
|
+
},
|
|
437
|
+
invokeOnComplete: (ctx2) => {
|
|
438
|
+
var _a;
|
|
439
|
+
if (!ctx2.isValueComplete)
|
|
440
|
+
return;
|
|
441
|
+
(_a = ctx2.onComplete) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value), valueAsString: ctx2.valueAsString });
|
|
442
|
+
},
|
|
443
|
+
invokeOnChange: (ctx2, evt) => {
|
|
444
|
+
var _a;
|
|
445
|
+
if (evt.type === "SETUP")
|
|
446
|
+
return;
|
|
447
|
+
(_a = ctx2.onChange) == null ? void 0 : _a.call(ctx2, { value: Array.from(ctx2.value) });
|
|
448
|
+
dispatchInputValueEvent(dom.getHiddenInputEl(ctx2), ctx2.valueAsString);
|
|
449
|
+
},
|
|
450
|
+
invokeOnInvalid: (ctx2, evt) => {
|
|
451
|
+
var _a;
|
|
452
|
+
(_a = ctx2.onInvalid) == null ? void 0 : _a.call(ctx2, { value: evt.value, index: ctx2.focusedIndex });
|
|
453
|
+
},
|
|
454
|
+
clearFocusedIndex: (ctx2) => {
|
|
455
|
+
ctx2.focusedIndex = -1;
|
|
456
|
+
},
|
|
457
|
+
setValue: (ctx2, evt) => {
|
|
458
|
+
assign(ctx2, evt.value);
|
|
459
|
+
},
|
|
460
|
+
setFocusedIndex: (ctx2, evt) => {
|
|
461
|
+
ctx2.focusedIndex = evt.index;
|
|
462
|
+
},
|
|
463
|
+
setFocusedValue: (ctx2, evt) => {
|
|
464
|
+
ctx2.value[ctx2.focusedIndex] = lastChar(evt.value);
|
|
465
|
+
},
|
|
466
|
+
setPastedValue(ctx2, evt) {
|
|
467
|
+
raf(() => {
|
|
468
|
+
const value = evt.value.substring(0, ctx2.valueLength);
|
|
469
|
+
assign(ctx2, value.split("").filter(Boolean));
|
|
470
|
+
});
|
|
471
|
+
},
|
|
472
|
+
setValueAtIndex: (ctx2, evt) => {
|
|
473
|
+
ctx2.value[evt.index] = lastChar(evt.value);
|
|
474
|
+
},
|
|
475
|
+
clearValue: (ctx2) => {
|
|
476
|
+
assign(ctx2, "");
|
|
477
|
+
},
|
|
478
|
+
clearFocusedValue: (ctx2) => {
|
|
479
|
+
ctx2.value[ctx2.focusedIndex] = "";
|
|
480
|
+
},
|
|
481
|
+
setFocusIndexToFirst: (ctx2) => {
|
|
482
|
+
ctx2.focusedIndex = 0;
|
|
483
|
+
},
|
|
484
|
+
setNextFocusedIndex: (ctx2) => {
|
|
485
|
+
ctx2.focusedIndex = Math.min(ctx2.focusedIndex + 1, ctx2.valueLength - 1);
|
|
486
|
+
},
|
|
487
|
+
setPrevFocusedIndex: (ctx2) => {
|
|
488
|
+
ctx2.focusedIndex = Math.max(ctx2.focusedIndex - 1, 0);
|
|
489
|
+
},
|
|
490
|
+
setLastValueFocusIndex: (ctx2) => {
|
|
491
|
+
raf(() => {
|
|
492
|
+
ctx2.focusedIndex = Math.min(ctx2.filledValueLength, ctx2.valueLength - 1);
|
|
493
|
+
});
|
|
494
|
+
},
|
|
495
|
+
preventDefault(_, evt) {
|
|
496
|
+
evt.preventDefault();
|
|
497
|
+
},
|
|
498
|
+
blurFocusedInputIfNeeded(ctx2) {
|
|
499
|
+
if (!ctx2.blurOnComplete)
|
|
500
|
+
return;
|
|
501
|
+
raf(() => {
|
|
502
|
+
var _a;
|
|
503
|
+
(_a = dom.getFocusedEl(ctx2)) == null ? void 0 : _a.blur();
|
|
504
|
+
});
|
|
505
|
+
},
|
|
506
|
+
requestFormSubmit(ctx2) {
|
|
507
|
+
var _a;
|
|
508
|
+
if (!ctx2.name)
|
|
509
|
+
return;
|
|
510
|
+
const input = dom.getHiddenInputEl(ctx2);
|
|
511
|
+
(_a = input == null ? void 0 : input.form) == null ? void 0 : _a.requestSubmit();
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
);
|
|
516
|
+
}
|
|
517
|
+
var REGEX = {
|
|
518
|
+
numeric: /^[0-9]+$/,
|
|
519
|
+
alphabetic: /^[A-Za-z]+$/,
|
|
520
|
+
alphanumeric: /^[a-zA-Z0-9]+$/i
|
|
521
|
+
};
|
|
522
|
+
function isValidType(value, type) {
|
|
523
|
+
var _a;
|
|
524
|
+
if (!type)
|
|
525
|
+
return true;
|
|
526
|
+
return !!((_a = REGEX[type]) == null ? void 0 : _a.test(value));
|
|
527
|
+
}
|
|
528
|
+
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
|
+
}
|
|
539
|
+
}
|
|
540
|
+
function lastChar(value) {
|
|
541
|
+
return value.charAt(value.length - 1);
|
|
542
|
+
}
|
|
543
|
+
export {
|
|
544
|
+
connect,
|
|
545
|
+
machine
|
|
546
|
+
};
|
package/package.json
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"type": "module",
|
|
3
2
|
"name": "@zag-js/pin-input",
|
|
4
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
5
4
|
"description": "Core logic for the pin-input widget implemented as a state machine",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
6
8
|
"keywords": [
|
|
7
9
|
"js",
|
|
8
10
|
"machine",
|
|
@@ -15,8 +17,6 @@
|
|
|
15
17
|
"author": "Segun Adebayo <sage@adebayosegun.com>",
|
|
16
18
|
"homepage": "https://github.com/chakra-ui/zag#readme",
|
|
17
19
|
"license": "MIT",
|
|
18
|
-
"main": "dist/index.js",
|
|
19
|
-
"types": "dist/index.d.ts",
|
|
20
20
|
"repository": "https://github.com/chakra-ui/zag/tree/main/packages/pin-input",
|
|
21
21
|
"sideEffects": false,
|
|
22
22
|
"files": [
|
|
@@ -29,18 +29,18 @@
|
|
|
29
29
|
"url": "https://github.com/chakra-ui/zag/issues"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@zag-js/core": "0.1.
|
|
33
|
-
"@zag-js/types": "0.2.
|
|
32
|
+
"@zag-js/core": "0.1.12",
|
|
33
|
+
"@zag-js/types": "0.2.7"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@zag-js/dom-utils": "0.1.
|
|
37
|
-
"@zag-js/form-utils": "0.1.
|
|
38
|
-
"@zag-js/utils": "0.1.
|
|
36
|
+
"@zag-js/dom-utils": "0.1.13",
|
|
37
|
+
"@zag-js/form-utils": "0.1.3",
|
|
38
|
+
"@zag-js/utils": "0.1.6"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
|
-
"build-fast": "tsup src/index.ts --format=esm",
|
|
41
|
+
"build-fast": "tsup src/index.ts --format=esm,cjs",
|
|
42
42
|
"start": "pnpm build --watch",
|
|
43
|
-
"build": "tsup src/index.ts --format=esm --dts",
|
|
43
|
+
"build": "tsup src/index.ts --format=esm,cjs --dts",
|
|
44
44
|
"test": "jest --config ../../../jest.config.js --rootDir . --passWithNoTests",
|
|
45
45
|
"lint": "eslint src --ext .ts,.tsx",
|
|
46
46
|
"test-ci": "pnpm test --ci --runInBand",
|