@zag-js/pin-input 0.10.2 → 0.10.4

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.
@@ -1,172 +0,0 @@
1
- import {
2
- parts
3
- } from "./chunk-BJXKBZJG.mjs";
4
- import {
5
- dom
6
- } from "./chunk-CPXMEVTH.mjs";
7
-
8
- // src/pin-input.connect.ts
9
- import { getEventKey, getNativeEvent, isModifiedEvent } from "@zag-js/dom-event";
10
- import { ariaAttr, dataAttr } from "@zag-js/dom-query";
11
- import { invariant } from "@zag-js/utils";
12
- import { visuallyHiddenStyle } from "@zag-js/visually-hidden";
13
- function connect(state, send, normalize) {
14
- const isValueComplete = state.context.isValueComplete;
15
- const isInvalid = state.context.invalid;
16
- const focusedIndex = state.context.focusedIndex;
17
- const translations = state.context.translations;
18
- function focus() {
19
- dom.getFirstInputEl(state.context)?.focus();
20
- }
21
- return {
22
- /**
23
- * The value of the input as an array of strings.
24
- */
25
- value: state.context.value,
26
- /**
27
- * The value of the input as a string.
28
- */
29
- valueAsString: state.context.valueAsString,
30
- /**
31
- * Whether all inputs are filled.
32
- */
33
- isValueComplete,
34
- /**
35
- * Function to set the value of the inputs.
36
- */
37
- setValue(value) {
38
- if (!Array.isArray(value)) {
39
- invariant("[pin-input/setValue] value must be an array");
40
- }
41
- send({ type: "SET_VALUE", value });
42
- },
43
- /**
44
- * Function to clear the value of the inputs.
45
- */
46
- clearValue() {
47
- send({ type: "CLEAR_VALUE" });
48
- },
49
- /**
50
- * Function to set the value of the input at a specific index.
51
- */
52
- setValueAtIndex(index, value) {
53
- send({ type: "SET_VALUE", value, index });
54
- },
55
- /**
56
- * Function to focus the pin-input. This will focus the first input.
57
- */
58
- focus,
59
- rootProps: normalize.element({
60
- dir: state.context.dir,
61
- ...parts.root.attrs,
62
- id: dom.getRootId(state.context),
63
- "data-invalid": dataAttr(isInvalid),
64
- "data-disabled": dataAttr(state.context.disabled),
65
- "data-complete": dataAttr(isValueComplete)
66
- }),
67
- labelProps: normalize.label({
68
- ...parts.label.attrs,
69
- htmlFor: dom.getHiddenInputId(state.context),
70
- id: dom.getLabelId(state.context),
71
- "data-invalid": dataAttr(isInvalid),
72
- "data-disabled": dataAttr(state.context.disabled),
73
- "data-complete": dataAttr(isValueComplete),
74
- onClick: (event) => {
75
- event.preventDefault();
76
- focus();
77
- }
78
- }),
79
- hiddenInputProps: normalize.input({
80
- ...parts.hiddenInput.attrs,
81
- "aria-hidden": true,
82
- type: "text",
83
- tabIndex: -1,
84
- id: dom.getHiddenInputId(state.context),
85
- name: state.context.name,
86
- form: state.context.form,
87
- style: visuallyHiddenStyle,
88
- maxLength: state.context.valueLength,
89
- defaultValue: state.context.valueAsString
90
- }),
91
- controlProps: normalize.element({
92
- ...parts.control.attrs,
93
- id: dom.getControlId(state.context)
94
- }),
95
- getInputProps({ index }) {
96
- const inputType = state.context.type === "numeric" ? "tel" : "text";
97
- return normalize.input({
98
- ...parts.input.attrs,
99
- disabled: state.context.disabled,
100
- "data-disabled": dataAttr(state.context.disabled),
101
- "data-complete": dataAttr(isValueComplete),
102
- id: dom.getInputId(state.context, index.toString()),
103
- "data-ownedby": dom.getRootId(state.context),
104
- "aria-label": translations.inputLabel(index, state.context.valueLength),
105
- inputMode: state.context.otp || state.context.type === "numeric" ? "numeric" : "text",
106
- "aria-invalid": ariaAttr(isInvalid),
107
- "data-invalid": dataAttr(isInvalid),
108
- type: state.context.mask ? "password" : inputType,
109
- defaultValue: state.context.value[index] || "",
110
- autoCapitalize: "none",
111
- autoComplete: state.context.otp ? "one-time-code" : "off",
112
- placeholder: focusedIndex === index ? "" : state.context.placeholder,
113
- onChange(event) {
114
- const evt = getNativeEvent(event);
115
- const { value } = event.currentTarget;
116
- if (evt.inputType === "insertFromPaste" || value.length > 2) {
117
- send({ type: "PASTE", value });
118
- event.preventDefault();
119
- return;
120
- }
121
- if (evt.inputType === "deleteContentBackward") {
122
- send("BACKSPACE");
123
- return;
124
- }
125
- send({ type: "INPUT", value, index });
126
- },
127
- onKeyDown(event) {
128
- const evt = getNativeEvent(event);
129
- if (evt.isComposing || isModifiedEvent(evt))
130
- return;
131
- const keyMap = {
132
- Backspace() {
133
- send("BACKSPACE");
134
- },
135
- Delete() {
136
- send("DELETE");
137
- },
138
- ArrowLeft() {
139
- send("ARROW_LEFT");
140
- },
141
- ArrowRight() {
142
- send("ARROW_RIGHT");
143
- },
144
- Enter() {
145
- send("ENTER");
146
- }
147
- };
148
- const key = getEventKey(event, { dir: state.context.dir });
149
- const exec = keyMap[key];
150
- if (exec) {
151
- exec(event);
152
- event.preventDefault();
153
- } else {
154
- if (key === "Tab")
155
- return;
156
- send({ type: "KEY_DOWN", value: key, preventDefault: () => event.preventDefault() });
157
- }
158
- },
159
- onFocus() {
160
- send({ type: "FOCUS", index });
161
- },
162
- onBlur() {
163
- send({ type: "BLUR", index });
164
- }
165
- });
166
- }
167
- };
168
- }
169
-
170
- export {
171
- connect
172
- };
@@ -1,288 +0,0 @@
1
- import {
2
- dom
3
- } from "./chunk-CPXMEVTH.mjs";
4
-
5
- // src/pin-input.machine.ts
6
- import { createMachine, guards } from "@zag-js/core";
7
- import { raf } from "@zag-js/dom-query";
8
- import { dispatchInputValueEvent } from "@zag-js/form-utils";
9
- import { compact } from "@zag-js/utils";
10
- var { and, not } = guards;
11
- function machine(userContext) {
12
- const ctx = compact(userContext);
13
- return createMachine(
14
- {
15
- id: "pin-input",
16
- initial: ctx.autoFocus ? "focused" : "idle",
17
- context: {
18
- value: [],
19
- focusedIndex: -1,
20
- placeholder: "\u25CB",
21
- otp: false,
22
- type: "numeric",
23
- ...ctx,
24
- translations: {
25
- inputLabel: (index, length) => `pin code ${index + 1} of ${length}`,
26
- ...ctx.translations
27
- }
28
- },
29
- computed: {
30
- valueLength: (ctx2) => ctx2.value.length,
31
- filledValueLength: (ctx2) => ctx2.value.filter((v) => v?.trim() !== "").length,
32
- isValueComplete: (ctx2) => ctx2.valueLength === ctx2.filledValueLength,
33
- valueAsString: (ctx2) => ctx2.value.join(""),
34
- focusedValue: (ctx2) => ctx2.value[ctx2.focusedIndex]
35
- },
36
- watch: {
37
- focusedIndex: ["focusInput", "setInputSelection"],
38
- value: ["dispatchInputEvent", "syncInputElements"],
39
- isValueComplete: ["invokeOnComplete", "blurFocusedInputIfNeeded"]
40
- },
41
- entry: ctx.autoFocus ? ["setupValue", "setFocusIndexToFirst"] : ["setupValue"],
42
- on: {
43
- SET_VALUE: [
44
- {
45
- guard: "hasIndex",
46
- actions: ["setValueAtIndex", "invokeOnChange"]
47
- },
48
- { actions: ["setValue", "invokeOnChange"] }
49
- ],
50
- CLEAR_VALUE: [
51
- {
52
- guard: "isDisabled",
53
- actions: ["clearValue", "invokeOnChange"]
54
- },
55
- {
56
- actions: ["clearValue", "invokeOnChange", "setFocusIndexToFirst"]
57
- }
58
- ]
59
- },
60
- states: {
61
- idle: {
62
- on: {
63
- FOCUS: {
64
- target: "focused",
65
- actions: "setFocusedIndex"
66
- }
67
- }
68
- },
69
- focused: {
70
- on: {
71
- INPUT: [
72
- {
73
- guard: and("isFinalValue", "isValidValue"),
74
- actions: ["setFocusedValue", "invokeOnChange", "syncInputValue"]
75
- },
76
- {
77
- guard: "isValidValue",
78
- actions: ["setFocusedValue", "invokeOnChange", "setNextFocusedIndex", "syncInputValue"]
79
- }
80
- ],
81
- PASTE: [
82
- {
83
- guard: "isValidValue",
84
- actions: ["setPastedValue", "invokeOnChange", "setLastValueFocusIndex"]
85
- },
86
- { actions: ["resetFocusedValue", "invokeOnChange"] }
87
- ],
88
- BLUR: {
89
- target: "idle",
90
- actions: "clearFocusedIndex"
91
- },
92
- DELETE: {
93
- guard: "hasValue",
94
- actions: ["clearFocusedValue", "invokeOnChange"]
95
- },
96
- ARROW_LEFT: {
97
- actions: "setPrevFocusedIndex"
98
- },
99
- ARROW_RIGHT: {
100
- actions: "setNextFocusedIndex"
101
- },
102
- BACKSPACE: [
103
- {
104
- guard: "hasValue",
105
- actions: ["clearFocusedValue", "invokeOnChange"]
106
- },
107
- {
108
- actions: ["setPrevFocusedIndex", "clearFocusedValue", "invokeOnChange"]
109
- }
110
- ],
111
- ENTER: {
112
- guard: "isValueComplete",
113
- actions: "requestFormSubmit"
114
- },
115
- KEY_DOWN: {
116
- guard: not("isValidValue"),
117
- actions: ["preventDefault", "invokeOnInvalid"]
118
- }
119
- }
120
- }
121
- }
122
- },
123
- {
124
- guards: {
125
- autoFocus: (ctx2) => !!ctx2.autoFocus,
126
- isValueEmpty: (_ctx, evt) => evt.value === "",
127
- hasValue: (ctx2) => ctx2.value[ctx2.focusedIndex] !== "",
128
- isValueComplete: (ctx2) => ctx2.isValueComplete,
129
- isValidValue: (ctx2, evt) => {
130
- if (!ctx2.pattern)
131
- return isValidType(evt.value, ctx2.type);
132
- const regex = new RegExp(ctx2.pattern, "g");
133
- return regex.test(evt.value);
134
- },
135
- isFinalValue: (ctx2) => {
136
- return ctx2.filledValueLength + 1 === ctx2.valueLength && ctx2.value.findIndex((v) => v.trim() === "") === ctx2.focusedIndex;
137
- },
138
- isLastInputFocused: (ctx2) => ctx2.focusedIndex === ctx2.valueLength - 1,
139
- hasIndex: (_ctx, evt) => evt.index !== void 0,
140
- isDisabled: (ctx2) => !!ctx2.disabled
141
- },
142
- actions: {
143
- setupValue: (ctx2) => {
144
- if (ctx2.value.length)
145
- return;
146
- const inputs = dom.getElements(ctx2);
147
- const emptyValues = Array.from({ length: inputs.length }).fill("");
148
- assign(ctx2, emptyValues);
149
- },
150
- focusInput: (ctx2) => {
151
- raf(() => {
152
- if (ctx2.focusedIndex === -1)
153
- return;
154
- dom.getFocusedInputEl(ctx2)?.focus();
155
- });
156
- },
157
- setInputSelection: (ctx2) => {
158
- raf(() => {
159
- if (ctx2.focusedIndex === -1)
160
- return;
161
- const input = dom.getFocusedInputEl(ctx2);
162
- const length = input.value.length;
163
- input.selectionStart = ctx2.selectOnFocus ? 0 : length;
164
- input.selectionEnd = length;
165
- });
166
- },
167
- invokeOnComplete: (ctx2) => {
168
- if (!ctx2.isValueComplete)
169
- return;
170
- ctx2.onComplete?.({ value: Array.from(ctx2.value), valueAsString: ctx2.valueAsString });
171
- },
172
- invokeOnChange: (ctx2) => {
173
- ctx2.onChange?.({ value: Array.from(ctx2.value) });
174
- },
175
- dispatchInputEvent: (ctx2) => {
176
- const inputEl = dom.getHiddenInputEl(ctx2);
177
- dispatchInputValueEvent(inputEl, { value: ctx2.valueAsString });
178
- },
179
- invokeOnInvalid: (ctx2, evt) => {
180
- ctx2.onInvalid?.({ value: evt.value, index: ctx2.focusedIndex });
181
- },
182
- clearFocusedIndex: (ctx2) => {
183
- ctx2.focusedIndex = -1;
184
- },
185
- setValue: (ctx2, evt) => {
186
- assign(ctx2, evt.value);
187
- },
188
- setFocusedIndex: (ctx2, evt) => {
189
- ctx2.focusedIndex = evt.index;
190
- },
191
- setFocusedValue: (ctx2, evt) => {
192
- ctx2.value[ctx2.focusedIndex] = getNextValue(ctx2.focusedValue, evt.value);
193
- },
194
- syncInputValue(ctx2, evt) {
195
- const input = dom.getInputEl(ctx2, evt.index.toString());
196
- if (!input)
197
- return;
198
- input.value = ctx2.value[evt.index];
199
- },
200
- syncInputElements(ctx2) {
201
- const inputs = dom.getElements(ctx2);
202
- inputs.forEach((input, index) => {
203
- input.value = ctx2.value[index];
204
- });
205
- },
206
- setPastedValue(ctx2, evt) {
207
- raf(() => {
208
- const startIndex = ctx2.focusedValue ? 1 : 0;
209
- const value = evt.value.substring(startIndex, startIndex + ctx2.valueLength);
210
- assign(ctx2, value);
211
- });
212
- },
213
- setValueAtIndex: (ctx2, evt) => {
214
- ctx2.value[evt.index] = getNextValue(ctx2.focusedValue, evt.value);
215
- },
216
- clearValue: (ctx2) => {
217
- const nextValue = Array.from({ length: ctx2.valueLength }).fill("");
218
- assign(ctx2, nextValue);
219
- },
220
- clearFocusedValue: (ctx2) => {
221
- ctx2.value[ctx2.focusedIndex] = "";
222
- },
223
- resetFocusedValue: (ctx2) => {
224
- const input = dom.getFocusedInputEl(ctx2);
225
- input.value = ctx2.focusedValue;
226
- },
227
- setFocusIndexToFirst: (ctx2) => {
228
- ctx2.focusedIndex = 0;
229
- },
230
- setNextFocusedIndex: (ctx2) => {
231
- ctx2.focusedIndex = Math.min(ctx2.focusedIndex + 1, ctx2.valueLength - 1);
232
- },
233
- setPrevFocusedIndex: (ctx2) => {
234
- ctx2.focusedIndex = Math.max(ctx2.focusedIndex - 1, 0);
235
- },
236
- setLastValueFocusIndex: (ctx2) => {
237
- raf(() => {
238
- ctx2.focusedIndex = Math.min(ctx2.filledValueLength, ctx2.valueLength - 1);
239
- });
240
- },
241
- preventDefault(_, evt) {
242
- evt.preventDefault();
243
- },
244
- blurFocusedInputIfNeeded(ctx2) {
245
- if (!ctx2.blurOnComplete)
246
- return;
247
- raf(() => {
248
- dom.getFocusedInputEl(ctx2)?.blur();
249
- });
250
- },
251
- requestFormSubmit(ctx2) {
252
- if (!ctx2.name || !ctx2.isValueComplete)
253
- return;
254
- const input = dom.getHiddenInputEl(ctx2);
255
- input?.form?.requestSubmit();
256
- }
257
- }
258
- }
259
- );
260
- }
261
- var REGEX = {
262
- numeric: /^[0-9]+$/,
263
- alphabetic: /^[A-Za-z]+$/,
264
- alphanumeric: /^[a-zA-Z0-9]+$/i
265
- };
266
- function isValidType(value, type) {
267
- if (!type)
268
- return true;
269
- return !!REGEX[type]?.test(value);
270
- }
271
- function assign(ctx, value) {
272
- const arr = Array.isArray(value) ? value : value.split("").filter(Boolean);
273
- arr.forEach((value2, index) => {
274
- ctx.value[index] = value2;
275
- });
276
- }
277
- function getNextValue(current, next) {
278
- let nextValue = next;
279
- if (current[0] === next[0])
280
- nextValue = next[1];
281
- else if (current[0] === next[1])
282
- nextValue = next[0];
283
- return nextValue;
284
- }
285
-
286
- export {
287
- machine
288
- };
@@ -1,18 +0,0 @@
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 __copyProps = (to, from, except, desc) => {
7
- if (from && typeof from === "object" || typeof from === "function") {
8
- for (let key of __getOwnPropNames(from))
9
- if (!__hasOwnProp.call(to, key) && key !== except)
10
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
11
- }
12
- return to;
13
- };
14
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
15
-
16
- // src/pin-input.types.ts
17
- var pin_input_types_exports = {};
18
- module.exports = __toCommonJS(pin_input_types_exports);
File without changes