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