@xsolla/xui-input 0.99.0 → 0.101.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 +377 -22
  2. package/package.json +4 -4
package/README.md CHANGED
@@ -1,42 +1,397 @@
1
- # @xsolla/xui-input
1
+ # Input
2
2
 
3
- Text input component with label, error, icon, clear, and checked state support.
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.
4
4
 
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
+ npm install @xsolla/xui-input
9
+ # or
8
10
  yarn add @xsolla/xui-input
9
11
  ```
10
12
 
11
- ## Usage
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:
18
+
19
+ ```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>
31
+ ```
32
+
33
+ See [Quick Start](../overview/quick-start.md) for more details.
34
+
35
+ ## Demo
36
+
37
+ ### Basic Input
38
+
39
+ ```tsx
40
+ import * as React from 'react';
41
+ import { Input } from '@xsolla/xui-input';
42
+
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
+ }
54
+ ```
55
+
56
+ ### Input with Label
57
+
58
+ ```tsx
59
+ import * as React from 'react';
60
+ import { Input } from '@xsolla/xui-input';
61
+
62
+ export default function LabeledInput() {
63
+ const [email, setEmail] = React.useState('');
64
+
65
+ return (
66
+ <Input
67
+ label="Email Address"
68
+ value={email}
69
+ onChangeText={setEmail}
70
+ placeholder="you@example.com"
71
+ />
72
+ );
73
+ }
74
+ ```
75
+
76
+ ### Input Sizes
12
77
 
13
78
  ```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
+ }
93
+ ```
94
+
95
+ ### Input with Icons
96
+
97
+ ```tsx
98
+ import * as React from 'react';
99
+ import { Input } from '@xsolla/xui-input';
100
+ 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');
132
+
133
+ return (
134
+ <Input
135
+ value={value}
136
+ onChangeText={setValue}
137
+ extraClear
138
+ onRemove={() => setValue('')}
139
+ placeholder="Type something..."
140
+ />
141
+ );
142
+ }
143
+ ```
144
+
145
+ ### Input with Validation
146
+
147
+ ```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
14
182
  import { Input } from '@xsolla/xui-input';
15
183
 
16
184
  <Input
17
- label="Email"
18
- placeholder="Enter email"
19
- value={value}
20
- onChange={(e) => setValue(e.target.value)}
21
- errorMessage="Invalid email"
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
22
195
  />
23
196
  ```
24
197
 
25
- ## Props
198
+ ## Examples
199
+
200
+ ### Disabled Input
201
+
202
+ ```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
236
+
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
+ }
252
+ ```
253
+
254
+ ### Search Input
255
+
256
+ ```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
+ }
276
+ ```
277
+
278
+ ### Form with Multiple Inputs
279
+
280
+ ```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
26
323
 
27
324
  ### Input
28
325
 
326
+ The main input component. Renders a semantic `<input>` element with wrapper styling.
327
+
328
+ **Input Props:**
329
+
29
330
  | 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 |
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
388
+ ```
389
+
390
+ ## Accessibility
391
+
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xsolla/xui-input",
3
- "version": "0.99.0",
3
+ "version": "0.101.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.101.0",
17
+ "@xsolla/xui-icons": "0.101.0",
18
+ "@xsolla/xui-primitives-core": "0.101.0"
19
19
  },
20
20
  "peerDependencies": {
21
21
  "react": ">=16.8.0",