@xsolla/xui-input-pin 0.148.0 → 0.148.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +227 -0
- package/package.json +4 -4
package/README.md
ADDED
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
# Input Pin
|
|
2
|
+
|
|
3
|
+
A cross-platform React PIN/OTP input component with individual cells for each digit. Features auto-advance between cells, paste support, and completion callbacks.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @xsolla/xui-input-pin
|
|
9
|
+
# or
|
|
10
|
+
yarn add @xsolla/xui-input-pin
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Demo
|
|
14
|
+
|
|
15
|
+
### Basic PIN Input
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
import * as React from 'react';
|
|
19
|
+
import { InputPin } from '@xsolla/xui-input-pin';
|
|
20
|
+
|
|
21
|
+
export default function BasicPinInput() {
|
|
22
|
+
const handleComplete = ({ value, isComplete }) => {
|
|
23
|
+
if (isComplete) {
|
|
24
|
+
console.log('PIN entered:', value);
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<InputPin
|
|
30
|
+
codeLength={4}
|
|
31
|
+
onComplete={handleComplete}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### Six-Digit Code
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import * as React from 'react';
|
|
41
|
+
import { InputPin } from '@xsolla/xui-input-pin';
|
|
42
|
+
|
|
43
|
+
export default function SixDigitPin() {
|
|
44
|
+
return (
|
|
45
|
+
<InputPin
|
|
46
|
+
codeLength={6}
|
|
47
|
+
label="Enter verification code"
|
|
48
|
+
onComplete={({ value }) => console.log('Code:', value)}
|
|
49
|
+
/>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Controlled PIN Input
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
import * as React from 'react';
|
|
58
|
+
import { InputPin } from '@xsolla/xui-input-pin';
|
|
59
|
+
|
|
60
|
+
export default function ControlledPinInput() {
|
|
61
|
+
const [pin, setPin] = React.useState('');
|
|
62
|
+
|
|
63
|
+
return (
|
|
64
|
+
<div>
|
|
65
|
+
<InputPin
|
|
66
|
+
value={pin}
|
|
67
|
+
codeLength={4}
|
|
68
|
+
onChange={({ value }) => setPin(value)}
|
|
69
|
+
/>
|
|
70
|
+
<p>Current value: {pin}</p>
|
|
71
|
+
</div>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### Secure Entry
|
|
77
|
+
|
|
78
|
+
```tsx
|
|
79
|
+
import * as React from 'react';
|
|
80
|
+
import { InputPin } from '@xsolla/xui-input-pin';
|
|
81
|
+
|
|
82
|
+
export default function SecurePinInput() {
|
|
83
|
+
return (
|
|
84
|
+
<InputPin
|
|
85
|
+
codeLength={4}
|
|
86
|
+
secureTextEntry={true}
|
|
87
|
+
label="Enter your PIN"
|
|
88
|
+
/>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Anatomy
|
|
94
|
+
|
|
95
|
+
```jsx
|
|
96
|
+
import { InputPin } from '@xsolla/xui-input-pin';
|
|
97
|
+
|
|
98
|
+
<InputPin
|
|
99
|
+
value={pinValue} // Controlled value
|
|
100
|
+
onChange={handleChange} // Change handler with {value, isComplete}
|
|
101
|
+
onComplete={handleComplete} // Called when all digits entered
|
|
102
|
+
codeLength={4} // Number of digits
|
|
103
|
+
size="md" // Size variant
|
|
104
|
+
label="Label" // Label above input
|
|
105
|
+
secureTextEntry={false} // Hide entered digits
|
|
106
|
+
showPlaceholderDots={true} // Show dot placeholders
|
|
107
|
+
flexibleWidth={false} // Expand cells to fill width
|
|
108
|
+
disabled={false} // Disabled state
|
|
109
|
+
error={false} // Error state
|
|
110
|
+
errorMessage="Error" // Error message text
|
|
111
|
+
/>
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Examples
|
|
115
|
+
|
|
116
|
+
### Full Width
|
|
117
|
+
|
|
118
|
+
```tsx
|
|
119
|
+
import * as React from 'react';
|
|
120
|
+
import { InputPin } from '@xsolla/xui-input-pin';
|
|
121
|
+
|
|
122
|
+
export default function FullWidthPin() {
|
|
123
|
+
return (
|
|
124
|
+
<div style={{ width: 300 }}>
|
|
125
|
+
<InputPin
|
|
126
|
+
codeLength={6}
|
|
127
|
+
flexibleWidth={true}
|
|
128
|
+
label="Verification Code"
|
|
129
|
+
/>
|
|
130
|
+
</div>
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
### With Error
|
|
136
|
+
|
|
137
|
+
```tsx
|
|
138
|
+
import * as React from 'react';
|
|
139
|
+
import { InputPin } from '@xsolla/xui-input-pin';
|
|
140
|
+
|
|
141
|
+
export default function ErrorPinInput() {
|
|
142
|
+
return (
|
|
143
|
+
<InputPin
|
|
144
|
+
codeLength={4}
|
|
145
|
+
error={true}
|
|
146
|
+
errorMessage="Invalid PIN. Please try again."
|
|
147
|
+
label="Enter PIN"
|
|
148
|
+
/>
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### PIN Input Sizes
|
|
154
|
+
|
|
155
|
+
```tsx
|
|
156
|
+
import * as React from 'react';
|
|
157
|
+
import { InputPin } from '@xsolla/xui-input-pin';
|
|
158
|
+
|
|
159
|
+
export default function PinInputSizes() {
|
|
160
|
+
return (
|
|
161
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: 24 }}>
|
|
162
|
+
<InputPin size="xs" codeLength={4} />
|
|
163
|
+
<InputPin size="sm" codeLength={4} />
|
|
164
|
+
<InputPin size="md" codeLength={4} />
|
|
165
|
+
<InputPin size="lg" codeLength={4} />
|
|
166
|
+
<InputPin size="xl" codeLength={4} />
|
|
167
|
+
</div>
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## API Reference
|
|
173
|
+
|
|
174
|
+
### InputPin
|
|
175
|
+
|
|
176
|
+
**InputPin Props:**
|
|
177
|
+
|
|
178
|
+
| Prop | Type | Default | Description |
|
|
179
|
+
| :--- | :--- | :------ | :---------- |
|
|
180
|
+
| value | `string` | `""` | Current PIN value. |
|
|
181
|
+
| onChange | `(props: OnInputPinCompleteProps) => void` | - | Called on every change. |
|
|
182
|
+
| onComplete | `(props: OnInputPinCompleteProps) => void` | - | Called when all digits entered. |
|
|
183
|
+
| codeLength | `number` | `4` | Number of PIN digits. |
|
|
184
|
+
| size | `"xl" \| "lg" \| "md" \| "sm" \| "xs"` | `"md"` | Component size. |
|
|
185
|
+
| label | `string` | - | Label above input. |
|
|
186
|
+
| secureTextEntry | `boolean` | `false` | Hide entered digits. |
|
|
187
|
+
| showPlaceholderDots | `boolean` | `true` | Show dot placeholders. |
|
|
188
|
+
| flexibleWidth | `boolean` | `false` | Expand cells to fill container. |
|
|
189
|
+
| disabled | `boolean` | `false` | Disabled state. |
|
|
190
|
+
| error | `boolean` | `false` | Error state. |
|
|
191
|
+
| errorMessage | `string` | - | Error message text. |
|
|
192
|
+
| testID | `string` | - | Test identifier. |
|
|
193
|
+
| aria-label | `string` | - | Accessible label for screen readers. |
|
|
194
|
+
|
|
195
|
+
**OnInputPinCompleteProps:**
|
|
196
|
+
|
|
197
|
+
```typescript
|
|
198
|
+
interface OnInputPinCompleteProps {
|
|
199
|
+
isComplete: boolean; // Whether all digits are filled
|
|
200
|
+
value: string; // Current PIN value
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
## Keyboard Navigation
|
|
205
|
+
|
|
206
|
+
| Key | Action |
|
|
207
|
+
| :-- | :----- |
|
|
208
|
+
| 0-9, A-Z | Enter character and advance |
|
|
209
|
+
| Backspace | Clear current cell and move back |
|
|
210
|
+
| Arrow Left | Move to previous cell |
|
|
211
|
+
| Arrow Right | Move to next cell |
|
|
212
|
+
| Ctrl/Cmd + V | Paste and auto-fill cells |
|
|
213
|
+
|
|
214
|
+
## Behavior
|
|
215
|
+
|
|
216
|
+
- Auto-advances to next cell after input
|
|
217
|
+
- Supports paste to fill multiple cells
|
|
218
|
+
- Backspace clears current or moves to previous
|
|
219
|
+
- Only alphanumeric characters are accepted
|
|
220
|
+
- Uses `inputMode="numeric"` for mobile keyboards
|
|
221
|
+
|
|
222
|
+
## Accessibility
|
|
223
|
+
|
|
224
|
+
- Each cell has `aria-label` indicating digit position
|
|
225
|
+
- `role="group"` on container with `aria-labelledby`
|
|
226
|
+
- `aria-invalid` when in error state
|
|
227
|
+
- Error messages linked via `aria-describedby`
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xsolla/xui-input-pin",
|
|
3
|
-
"version": "0.148.
|
|
3
|
+
"version": "0.148.1",
|
|
4
4
|
"main": "./web/index.js",
|
|
5
5
|
"module": "./web/index.mjs",
|
|
6
6
|
"types": "./web/index.d.ts",
|
|
@@ -13,9 +13,9 @@
|
|
|
13
13
|
"test:coverage": "vitest run --coverage"
|
|
14
14
|
},
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@xsolla/xui-button": "0.148.
|
|
17
|
-
"@xsolla/xui-core": "0.148.
|
|
18
|
-
"@xsolla/xui-primitives-core": "0.148.
|
|
16
|
+
"@xsolla/xui-button": "0.148.1",
|
|
17
|
+
"@xsolla/xui-core": "0.148.1",
|
|
18
|
+
"@xsolla/xui-primitives-core": "0.148.1"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
21
|
"react": ">=16.8.0",
|