@xsolla/xui-input 0.149.1 → 0.151.0

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.
Files changed (2) hide show
  1. package/README.md +89 -344
  2. package/package.json +4 -4
package/README.md CHANGED
@@ -1,397 +1,142 @@
1
1
  # Input
2
2
 
3
- A cross-platform React input component with label, error states, icons, clear button, and validation support. Works on both React (web) and React Native.
3
+ A cross-platform text input with label, error, icon, clear and validation support; works on web and React Native via `XUIProvider` themed contexts.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
8
  npm install @xsolla/xui-input
9
- # or
10
- yarn add @xsolla/xui-input
11
9
  ```
12
10
 
13
- ## Prerequisites
14
-
15
- **Important:** Input requires `XUIProvider` from `@xsolla/xui-core` to be wrapped around your app for proper theming.
16
-
17
- If your input appears white or washed out on a light background, you need to set the theme mode:
11
+ ## Imports
18
12
 
19
13
  ```tsx
20
- import { XUIProvider } from '@xsolla/xui-core';
21
-
22
- // For light/white page backgrounds
23
- <XUIProvider initialMode="light">
24
- <YourApp />
25
- </XUIProvider>
26
-
27
- // For dark page backgrounds (default)
28
- <XUIProvider initialMode="dark">
29
- <YourApp />
30
- </XUIProvider>
14
+ import { Input } from '@xsolla/xui-input';
15
+ import type { InputProps } from '@xsolla/xui-input';
31
16
  ```
32
17
 
33
- See [Quick Start](../overview/quick-start.md) for more details.
34
-
35
- ## Demo
36
-
37
- ### Basic Input
18
+ ## Quick start
38
19
 
39
20
  ```tsx
40
- import * as React from 'react';
41
- import { Input } from '@xsolla/xui-input';
21
+ const [value, setValue] = useState('');
42
22
 
43
- export default function BasicInput() {
44
- const [value, setValue] = React.useState('');
45
-
46
- return (
47
- <Input
48
- value={value}
49
- onChangeText={setValue}
50
- placeholder="Enter text"
51
- />
52
- );
53
- }
23
+ <Input
24
+ label="Email"
25
+ value={value}
26
+ onChangeText={setValue}
27
+ placeholder="you@example.com"
28
+ />;
54
29
  ```
55
30
 
56
- ### Input with Label
31
+ ## API Reference
57
32
 
58
- ```tsx
59
- import * as React from 'react';
60
- import { Input } from '@xsolla/xui-input';
33
+ ### `<Input>`
61
34
 
62
- export default function LabeledInput() {
63
- const [email, setEmail] = React.useState('');
35
+ | Prop | Type | Default | Description |
36
+ | --- | --- | --- | --- |
37
+ | `value` | `string` | — | Controlled value. |
38
+ | `placeholder` | `string` | — | Placeholder shown when empty. |
39
+ | `onChange` | `(e: ChangeEvent<HTMLInputElement>) => void` | — | Native change handler. |
40
+ | `onChangeText` | `(text: string) => void` | — | Simplified change handler receiving the text. |
41
+ | `size` | `'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl'` | `'md'` | Control size. |
42
+ | `disabled` | `boolean` | `false` | Disable the input. |
43
+ | `label` | `string` | — | Label rendered above the input. |
44
+ | `error` | `boolean` | `false` | Apply error styling. |
45
+ | `errorMessage` | `string` | — | Error message; also marks the input invalid. |
46
+ | `iconLeft` | `ReactNode` | — | Icon on the left. |
47
+ | `iconRight` | `ReactNode` | — | Icon on the right. |
48
+ | `iconRightSize` | `number \| string` | — | Override the right-icon size. |
49
+ | `extraClear` | `boolean` | `false` | Show a clear button when the input has a value. |
50
+ | `onRemove` | `() => void` | — | Fired when the clear button is pressed. |
51
+ | `checked` | `boolean` | `false` | Show a success indicator (suppressed when `errorMessage` is set). |
52
+ | `checkedIcon` | `ReactNode` | `<CheckCr />` | Override the checked icon. |
53
+ | `borderTopLeftRadius` | `number` | — | Override top-left corner radius. |
54
+ | `borderTopRightRadius` | `number` | — | Override top-right corner radius. |
55
+ | `borderBottomLeftRadius` | `number` | — | Override bottom-left corner radius. |
56
+ | `borderBottomRightRadius` | `number` | — | Override bottom-right corner radius. |
57
+ | `backgroundColor` | `string` | — | Override the background colour. |
58
+ | `id` | `string` | `auto` | HTML id; also wires up the label. |
59
+ | `aria-label` | `string` | — | Accessible label when no visible label is present. |
60
+ | `testID` | `string` | — | Test identifier. |
61
+
62
+ `Input` also accepts the standard `InputHTMLAttributes` (excluding `size` and `onChange`, which are redefined above).
63
+
64
+ Inherits `ThemeOverrideProps` (`themeMode`, `themeProductContext`).
64
65
 
65
- return (
66
- <Input
67
- label="Email Address"
68
- value={email}
69
- onChangeText={setEmail}
70
- placeholder="you@example.com"
71
- />
72
- );
73
- }
74
- ```
66
+ ## Examples
75
67
 
76
- ### Input Sizes
68
+ ### Sizes
77
69
 
78
70
  ```tsx
79
- import * as React from 'react';
80
- import { Input } from '@xsolla/xui-input';
81
-
82
- export default function InputSizes() {
83
- return (
84
- <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
85
- <Input size="xs" placeholder="Extra Small" />
86
- <Input size="sm" placeholder="Small" />
87
- <Input size="md" placeholder="Medium (default)" />
88
- <Input size="lg" placeholder="Large" />
89
- <Input size="xl" placeholder="Extra Large" />
90
- </div>
91
- );
92
- }
71
+ <Input size="xs" placeholder="Extra small" />
72
+ <Input size="sm" placeholder="Small" />
73
+ <Input size="md" placeholder="Medium" />
74
+ <Input size="lg" placeholder="Large" />
75
+ <Input size="xl" placeholder="Extra large" />
93
76
  ```
94
77
 
95
- ### Input with Icons
78
+ ### Icons
96
79
 
97
80
  ```tsx
98
- import * as React from 'react';
99
- import { Input } from '@xsolla/xui-input';
100
81
  import { Search, Check } from '@xsolla/xui-icons';
101
- import { Calendar, Mail } from '@xsolla/xui-icons-base';
102
-
103
- export default function InputWithIcons() {
104
- return (
105
- <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
106
- <Input
107
- iconLeft={<Search />}
108
- placeholder="Search..."
109
- />
110
- <Input
111
- iconRight={<Calendar />}
112
- placeholder="Select date"
113
- />
114
- <Input
115
- iconLeft={<Mail />}
116
- iconRight={<Check />}
117
- placeholder="Email"
118
- />
119
- </div>
120
- );
121
- }
122
- ```
123
-
124
- ### Input with Clear Button
125
-
126
- ```tsx
127
- import * as React from 'react';
128
- import { Input } from '@xsolla/xui-input';
129
-
130
- export default function ClearableInput() {
131
- const [value, setValue] = React.useState('Some text');
82
+ import { Mail } from '@xsolla/xui-icons-base';
132
83
 
133
- return (
134
- <Input
135
- value={value}
136
- onChangeText={setValue}
137
- extraClear
138
- onRemove={() => setValue('')}
139
- placeholder="Type something..."
140
- />
141
- );
142
- }
84
+ <Input iconLeft={<Search />} placeholder="Search..." />
85
+ <Input iconLeft={<Mail />} iconRight={<Check />} placeholder="Email" />
143
86
  ```
144
87
 
145
- ### Input with Validation
88
+ ### Clear button
146
89
 
147
90
  ```tsx
148
- import * as React from 'react';
149
- import { Input } from '@xsolla/xui-input';
150
-
151
- export default function ValidatedInput() {
152
- const [email, setEmail] = React.useState('');
153
- const [error, setError] = React.useState('');
154
-
155
- const validateEmail = (value: string) => {
156
- setEmail(value);
157
- if (value && !value.includes('@')) {
158
- setError('Please enter a valid email address');
159
- } else {
160
- setError('');
161
- }
162
- };
163
-
164
- return (
165
- <Input
166
- label="Email"
167
- value={email}
168
- onChangeText={validateEmail}
169
- error={!!error}
170
- errorMessage={error}
171
- placeholder="you@example.com"
172
- />
173
- );
174
- }
175
- ```
176
-
177
- ## Anatomy
178
-
179
- Import the component and use it directly:
180
-
181
- ```jsx
182
- import { Input } from '@xsolla/xui-input';
91
+ const [value, setValue] = useState('Some text');
183
92
 
184
93
  <Input
185
- label="Field Label" // Optional label above input
186
- value={value} // Controlled value
187
- onChangeText={setValue} // Value change handler
188
- placeholder="Placeholder" // Placeholder text
189
- iconLeft={<Icon />} // Optional left icon
190
- iconRight={<Icon />} // Optional right icon
191
- extraClear // Shows clear button when has value
192
- error // Error state boolean
193
- errorMessage="Error text" // Error message below input
194
- disabled // Disabled state
195
- />
94
+ value={value}
95
+ onChangeText={setValue}
96
+ extraClear
97
+ onRemove={() => setValue('')}
98
+ placeholder="Type something..."
99
+ />;
196
100
  ```
197
101
 
198
- ## Examples
199
-
200
- ### Disabled Input
102
+ ### Validation
201
103
 
202
104
  ```tsx
203
- import * as React from 'react';
204
- import { Input } from '@xsolla/xui-input';
205
-
206
- export default function DisabledInput() {
207
- return (
208
- <Input
209
- label="Disabled Field"
210
- value="Cannot edit this"
211
- disabled
212
- />
213
- );
214
- }
215
- ```
216
-
217
- ### Input with Success State
218
-
219
- ```tsx
220
- import * as React from 'react';
221
- import { Input } from '@xsolla/xui-input';
222
-
223
- export default function SuccessInput() {
224
- return (
225
- <Input
226
- label="Username"
227
- value="johndoe"
228
- checked
229
- placeholder="Enter username"
230
- />
231
- );
232
- }
233
- ```
234
-
235
- ### Custom Border Radius
105
+ const [email, setEmail] = useState('');
106
+ const error = email && !email.includes('@') ? 'Invalid email' : '';
236
107
 
237
- ```tsx
238
- import * as React from 'react';
239
- import { Input } from '@xsolla/xui-input';
240
-
241
- export default function CustomRadiusInput() {
242
- return (
243
- <Input
244
- placeholder="Rounded input"
245
- borderTopLeftRadius={20}
246
- borderTopRightRadius={20}
247
- borderBottomLeftRadius={20}
248
- borderBottomRightRadius={20}
249
- />
250
- );
251
- }
108
+ <Input
109
+ label="Email"
110
+ value={email}
111
+ onChangeText={setEmail}
112
+ error={!!error}
113
+ errorMessage={error}
114
+ placeholder="you@example.com"
115
+ />;
252
116
  ```
253
117
 
254
- ### Search Input
118
+ ### Disabled and success
255
119
 
256
120
  ```tsx
257
- import * as React from 'react';
258
- import { Input } from '@xsolla/xui-input';
259
- import { Search } from '@xsolla/xui-icons';
260
-
261
- export default function SearchInput() {
262
- const [query, setQuery] = React.useState('');
263
-
264
- return (
265
- <Input
266
- value={query}
267
- onChangeText={setQuery}
268
- iconLeft={<Search />}
269
- extraClear
270
- onRemove={() => setQuery('')}
271
- placeholder="Search..."
272
- size="md"
273
- />
274
- );
275
- }
121
+ <Input label="Disabled" value="Cannot edit" disabled />
122
+ <Input label="Username" value="johndoe" checked />
276
123
  ```
277
124
 
278
- ### Form with Multiple Inputs
125
+ ### Custom border radius
279
126
 
280
127
  ```tsx
281
- import * as React from 'react';
282
- import { Input } from '@xsolla/xui-input';
283
- import { Mail } from '@xsolla/xui-icons-base';
284
-
285
- export default function FormInputs() {
286
- const [form, setForm] = React.useState({
287
- firstName: '',
288
- lastName: '',
289
- email: '',
290
- });
291
-
292
- const updateField = (field: string) => (value: string) => {
293
- setForm(prev => ({ ...prev, [field]: value }));
294
- };
295
-
296
- return (
297
- <div style={{ display: 'flex', flexDirection: 'column', gap: 16 }}>
298
- <Input
299
- label="First Name"
300
- value={form.firstName}
301
- onChangeText={updateField('firstName')}
302
- placeholder="John"
303
- />
304
- <Input
305
- label="Last Name"
306
- value={form.lastName}
307
- onChangeText={updateField('lastName')}
308
- placeholder="Doe"
309
- />
310
- <Input
311
- label="Email"
312
- value={form.email}
313
- onChangeText={updateField('email')}
314
- iconLeft={<Mail />}
315
- placeholder="john@example.com"
316
- />
317
- </div>
318
- );
319
- }
320
- ```
321
-
322
- ## API Reference
323
-
324
- ### Input
325
-
326
- The main input component. Renders a semantic `<input>` element with wrapper styling.
327
-
328
- **Input Props:**
329
-
330
- | Prop | Type | Default | Description |
331
- | :--- | :--- | :------ | :---------- |
332
- | value | `string` | - | The controlled value of the input. |
333
- | placeholder | `string` | - | Placeholder text shown when input is empty. |
334
- | onChange | `(e: ChangeEvent<HTMLInputElement>) => void` | - | Native change event handler. |
335
- | onChangeText | `(text: string) => void` | - | Simplified change handler receiving text value. |
336
- | size | `"xl" \| "lg" \| "md" \| "sm" \| "xs"` | `"md"` | The size of the input. |
337
- | disabled | `boolean` | `false` | Whether the input is disabled. |
338
- | label | `string` | - | Label text displayed above the input. |
339
- | errorMessage | `string` | - | Error message displayed below the input. |
340
- | error | `boolean` | `false` | Whether to show error styling. |
341
- | iconLeft | `ReactNode` | - | Icon displayed on the left side. |
342
- | iconRight | `ReactNode` | - | Icon displayed on the right side. |
343
- | extraClear | `boolean` | `false` | Whether to show clear button when input has value. |
344
- | onRemove | `() => void` | - | Callback when clear button is clicked. |
345
- | checked | `boolean` | `false` | Whether to show success/check icon. |
346
- | checkedIcon | `ReactNode` | `<Check />` | Custom icon for checked state. |
347
- | iconRightSize | `number \| string` | - | Custom size for right icon. |
348
- | borderTopLeftRadius | `number` | - | Custom top-left border radius. |
349
- | borderTopRightRadius | `number` | - | Custom top-right border radius. |
350
- | borderBottomLeftRadius | `number` | - | Custom bottom-left border radius. |
351
- | borderBottomRightRadius | `number` | - | Custom bottom-right border radius. |
352
- | backgroundColor | `string` | - | Custom background color. |
353
- | aria-label | `string` | - | Accessible label for the input. |
354
- | id | `string` | - | HTML id attribute (also links label). |
355
- | testID | `string` | - | Test identifier for testing frameworks. |
356
-
357
- **Size Configuration:**
358
-
359
- | Size | Height | Padding (V/H) | Font Size | Icon Size |
360
- | :--- | :----- | :------------ | :-------- | :-------- |
361
- | xl | 56px | 12px / 12px | 16px | 18px |
362
- | lg | 48px | 14px / 12px | 16px | 18px |
363
- | md | 40px | 11px / 12px | 14px | 18px |
364
- | sm | 32px | 7px / 10px | 14px | 16px |
365
- | xs | 28px | 7px / 10px | 12px | 16px |
366
-
367
- ## Theming
368
-
369
- Input components use the design system theme for colors and sizing:
370
-
371
- ```typescript
372
- // Colors accessed via theme
373
- theme.colors.control.input.bg // Background color
374
- theme.colors.control.input.bgHover // Hover background
375
- theme.colors.control.input.bgFocus // Focus background
376
- theme.colors.control.input.bgDisable // Disabled background
377
- theme.colors.control.input.border // Border color
378
- theme.colors.control.input.borderFocus // Focus border color
379
- theme.colors.control.input.borderError // Error border color
380
- theme.colors.control.input.text // Text color
381
- theme.colors.control.input.placeholder // Placeholder color
382
-
383
- // Sizing accessed via theme
384
- theme.sizing.input(size).height
385
- theme.sizing.input(size).paddingVertical
386
- theme.sizing.input(size).paddingHorizontal
387
- theme.sizing.input(size).fontSize
128
+ <Input
129
+ placeholder="Rounded"
130
+ borderTopLeftRadius={20}
131
+ borderTopRightRadius={20}
132
+ borderBottomLeftRadius={20}
133
+ borderBottomRightRadius={20}
134
+ />
388
135
  ```
389
136
 
390
137
  ## Accessibility
391
138
 
392
- - Uses semantic `<input>` element with proper `<label>` association
393
- - Label is linked via `htmlFor` attribute
394
- - Error messages use `aria-describedby` for screen readers
395
- - Focus indicators follow WCAG guidelines
396
- - Disabled state properly communicated to assistive technology
397
- - Clear button includes accessible label
139
+ - Renders a semantic `<input>` whose `aria-labelledby` points at the `id` of the rendered `<label>` element (rather than the standard `<label htmlFor>` pairing).
140
+ - Error messages are linked through `aria-describedby` and announced via `role="alert"`.
141
+ - `aria-invalid` and `aria-disabled` reflect error and disabled state.
142
+ - Pressing Escape blurs the input.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xsolla/xui-input",
3
- "version": "0.149.1",
3
+ "version": "0.151.0",
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-core": "0.149.1",
17
- "@xsolla/xui-icons-base": "0.149.1",
18
- "@xsolla/xui-primitives-core": "0.149.1"
16
+ "@xsolla/xui-core": "0.151.0",
17
+ "@xsolla/xui-icons-base": "0.151.0",
18
+ "@xsolla/xui-primitives-core": "0.151.0"
19
19
  },
20
20
  "peerDependencies": {
21
21
  "react": ">=16.8.0",