@xqmsg/ui-core 0.26.1 → 0.27.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.
- package/dist/components/input/Input.stories.d.ts +1 -0
- package/dist/components/input/InputTypes.d.ts +2 -2
- package/dist/components/input/StackedNumberInput/StackedNumberInput.d.ts +20 -0
- package/dist/components/input/index.d.ts +10 -2
- package/dist/ui-core.cjs.development.js +96 -2
- package/dist/ui-core.cjs.development.js.map +1 -1
- package/dist/ui-core.cjs.production.min.js +1 -1
- package/dist/ui-core.cjs.production.min.js.map +1 -1
- package/dist/ui-core.esm.js +97 -3
- package/dist/ui-core.esm.js.map +1 -1
- package/package.json +1 -1
- package/src/components/input/Input.stories.tsx +41 -4
- package/src/components/input/InputTypes.ts +5 -1
- package/src/components/input/StackedInput/StackedInput.tsx +1 -1
- package/src/components/input/StackedNumberInput/StackedNumberInput.tsx +121 -0
- package/src/components/input/index.tsx +43 -3
- package/src/theme/customXQChakraTheme.ts +1 -0
package/package.json
CHANGED
|
@@ -76,6 +76,7 @@ interface StoryFormSchema {
|
|
|
76
76
|
prop4?: string;
|
|
77
77
|
prop5?: string;
|
|
78
78
|
prop6?: boolean;
|
|
79
|
+
prop7?: number;
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
const onStubbedSubmit = () => null;
|
|
@@ -87,6 +88,7 @@ const storyFormDefaultValues: StoryFormSchema = {
|
|
|
87
88
|
prop4: '',
|
|
88
89
|
prop5: '',
|
|
89
90
|
prop6: true,
|
|
91
|
+
prop7: undefined,
|
|
90
92
|
};
|
|
91
93
|
|
|
92
94
|
const storyFormSchema: Yup.SchemaOf<StoryFormSchema> = Yup.object().shape({
|
|
@@ -96,6 +98,7 @@ const storyFormSchema: Yup.SchemaOf<StoryFormSchema> = Yup.object().shape({
|
|
|
96
98
|
prop4: Yup.string(),
|
|
97
99
|
prop5: Yup.string(),
|
|
98
100
|
prop6: Yup.boolean(),
|
|
101
|
+
prop7: Yup.number(),
|
|
99
102
|
});
|
|
100
103
|
|
|
101
104
|
export default meta;
|
|
@@ -113,10 +116,10 @@ const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
|
113
116
|
return (
|
|
114
117
|
<Form formHandler={formHandler}>
|
|
115
118
|
<Input
|
|
116
|
-
label=
|
|
119
|
+
label={args.label + ' - Pilled Text - scroll mode'}
|
|
117
120
|
name="recipients"
|
|
118
121
|
inputType="pilled-text"
|
|
119
|
-
placeholder=
|
|
122
|
+
placeholder={args.placeholder ?? 'Enter email address...'}
|
|
120
123
|
isInvalid={!!form.formState.errors['prop5']?.message}
|
|
121
124
|
errorText={form.formState.errors['prop5']?.message}
|
|
122
125
|
control={form.control}
|
|
@@ -129,10 +132,10 @@ const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
|
129
132
|
overflowMode="scroll"
|
|
130
133
|
/>
|
|
131
134
|
<Input
|
|
132
|
-
label=
|
|
135
|
+
label={args.label + ' - Pilled Text - wrap mod'}
|
|
133
136
|
name="recipients"
|
|
134
137
|
inputType="pilled-text"
|
|
135
|
-
placeholder=
|
|
138
|
+
placeholder={args.placeholder ?? 'Enter email address...'}
|
|
136
139
|
isInvalid={!!form.formState.errors['prop5']?.message}
|
|
137
140
|
errorText={form.formState.errors['prop5']?.message}
|
|
138
141
|
control={form.control}
|
|
@@ -147,6 +150,7 @@ const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
|
147
150
|
<Input
|
|
148
151
|
{...args}
|
|
149
152
|
inputType="multi-select"
|
|
153
|
+
label={args.label + ' - multi-select'}
|
|
150
154
|
setValue={form.setValue}
|
|
151
155
|
setError={form.setError}
|
|
152
156
|
clearErrors={form.clearErrors}
|
|
@@ -156,6 +160,7 @@ const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
|
156
160
|
/>
|
|
157
161
|
<Input
|
|
158
162
|
{...args}
|
|
163
|
+
label={args.label + ' - multi-select'}
|
|
159
164
|
inputType="multi-select"
|
|
160
165
|
variant="mobile"
|
|
161
166
|
setValue={form.setValue}
|
|
@@ -168,13 +173,31 @@ const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
|
168
173
|
/>
|
|
169
174
|
<Input
|
|
170
175
|
{...args}
|
|
176
|
+
label={args.label + ' - text'}
|
|
171
177
|
inputType="text"
|
|
172
178
|
name="prop3"
|
|
173
179
|
onChange={e => form.setValue('prop3', e.target.value)}
|
|
174
180
|
/>
|
|
181
|
+
<Input
|
|
182
|
+
{...args}
|
|
183
|
+
label={args.label + ' - number'}
|
|
184
|
+
inputType="number"
|
|
185
|
+
name="prop7"
|
|
186
|
+
ariaLabel="number input"
|
|
187
|
+
min={0}
|
|
188
|
+
max={100}
|
|
189
|
+
step={1}
|
|
190
|
+
precision={2}
|
|
191
|
+
setValue={form.setValue}
|
|
192
|
+
setError={form.setError}
|
|
193
|
+
clearErrors={form.clearErrors}
|
|
194
|
+
isInvalid={!!form.formState.errors['prop7']?.message}
|
|
195
|
+
errorText={form.formState.errors['prop7']?.message}
|
|
196
|
+
/>
|
|
175
197
|
<Input
|
|
176
198
|
{...args}
|
|
177
199
|
inputType="text"
|
|
200
|
+
label={args.label + ' - text - variant mobile'}
|
|
178
201
|
variant="mobile"
|
|
179
202
|
name="prop3"
|
|
180
203
|
onChange={e => form.setValue('prop3', e.target.value)}
|
|
@@ -182,6 +205,7 @@ const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
|
182
205
|
<Input
|
|
183
206
|
{...args}
|
|
184
207
|
inputType="text"
|
|
208
|
+
label={args.label + ' - text - tooltip as react node'}
|
|
185
209
|
name="prop3"
|
|
186
210
|
onChange={e => form.setValue('prop3', e.target.value)}
|
|
187
211
|
tooltipText={
|
|
@@ -194,6 +218,7 @@ const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
|
194
218
|
<Input
|
|
195
219
|
{...args}
|
|
196
220
|
inputType="text"
|
|
221
|
+
label={args.label + ' - text - tooltip as string'}
|
|
197
222
|
name="prop3"
|
|
198
223
|
onChange={e => form.setValue('prop3', e.target.value)}
|
|
199
224
|
tooltipText="test text"
|
|
@@ -201,12 +226,14 @@ const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
|
201
226
|
<Input
|
|
202
227
|
{...args}
|
|
203
228
|
inputType="textarea"
|
|
229
|
+
label={args.label + ' - textarea'}
|
|
204
230
|
name="prop2"
|
|
205
231
|
onChange={e => form.setValue('prop2', e.target.value)}
|
|
206
232
|
/>
|
|
207
233
|
<Input
|
|
208
234
|
{...args}
|
|
209
235
|
inputType="textarea"
|
|
236
|
+
label={args.label + ' - textarea - variant mobile'}
|
|
210
237
|
variant="mobile"
|
|
211
238
|
name="prop2"
|
|
212
239
|
onChange={e => form.setValue('prop2', e.target.value)}
|
|
@@ -215,6 +242,7 @@ const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
|
215
242
|
{...args}
|
|
216
243
|
name="prop"
|
|
217
244
|
inputType="pilled-text"
|
|
245
|
+
label={args.label + ' - Pilled Text'}
|
|
218
246
|
setValue={form.setValue}
|
|
219
247
|
setError={form.setError}
|
|
220
248
|
clearErrors={form.clearErrors}
|
|
@@ -226,6 +254,7 @@ const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
|
226
254
|
name="prop"
|
|
227
255
|
variant="mobile"
|
|
228
256
|
inputType="pilled-text"
|
|
257
|
+
label={args.label + ' - Pilled Text - variant mobile'}
|
|
229
258
|
setValue={form.setValue}
|
|
230
259
|
setError={form.setError}
|
|
231
260
|
clearErrors={form.clearErrors}
|
|
@@ -235,6 +264,7 @@ const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
|
235
264
|
<Input
|
|
236
265
|
{...args}
|
|
237
266
|
inputType="select"
|
|
267
|
+
label={args.label + ' - select'}
|
|
238
268
|
setValue={form.setValue}
|
|
239
269
|
name="prop4"
|
|
240
270
|
defaultValue={'value1'}
|
|
@@ -242,6 +272,8 @@ const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
|
242
272
|
<Input
|
|
243
273
|
{...args}
|
|
244
274
|
inputType="select"
|
|
275
|
+
label={args.label + ' - select - variant mobile'}
|
|
276
|
+
variant="mobile"
|
|
245
277
|
setValue={form.setValue}
|
|
246
278
|
name="prop4"
|
|
247
279
|
defaultValue={'value1'}
|
|
@@ -250,6 +282,7 @@ const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
|
250
282
|
<Input
|
|
251
283
|
{...args}
|
|
252
284
|
inputType="select"
|
|
285
|
+
label={args.label + ' - select - tooltip as react node'}
|
|
253
286
|
setValue={form.setValue}
|
|
254
287
|
name="prop4"
|
|
255
288
|
defaultValue={'value1'}
|
|
@@ -263,6 +296,7 @@ const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
|
263
296
|
/>
|
|
264
297
|
<SelectNative
|
|
265
298
|
{...args}
|
|
299
|
+
label={args.label + ' - select native'}
|
|
266
300
|
setValue={form.setValue}
|
|
267
301
|
name="prop4"
|
|
268
302
|
setError={form.setError}
|
|
@@ -280,6 +314,7 @@ const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
|
280
314
|
{...args}
|
|
281
315
|
name="prop6"
|
|
282
316
|
inputType="switch"
|
|
317
|
+
label={args.label + ' - switch'}
|
|
283
318
|
setValue={form.setValue}
|
|
284
319
|
/>
|
|
285
320
|
<Input
|
|
@@ -287,6 +322,7 @@ const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
|
287
322
|
name="prop6"
|
|
288
323
|
variant="mobile"
|
|
289
324
|
inputType="switch"
|
|
325
|
+
label={args.label + ' - switch - variant mobile'}
|
|
290
326
|
setValue={form.setValue}
|
|
291
327
|
/>
|
|
292
328
|
<Input
|
|
@@ -299,6 +335,7 @@ const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
|
299
335
|
{...args}
|
|
300
336
|
name="prop6"
|
|
301
337
|
inputType="checkbox"
|
|
338
|
+
label={args.label + ' - checkbox - variant mobile'}
|
|
302
339
|
variant="mobile"
|
|
303
340
|
setValue={form.setValue}
|
|
304
341
|
/>
|
|
@@ -16,7 +16,8 @@ export type InputType =
|
|
|
16
16
|
| 'textarea'
|
|
17
17
|
| 'radio'
|
|
18
18
|
| 'checkbox'
|
|
19
|
-
| 'switch'
|
|
19
|
+
| 'switch'
|
|
20
|
+
| 'number';
|
|
20
21
|
|
|
21
22
|
export type FieldOption = {
|
|
22
23
|
label: string;
|
|
@@ -43,6 +44,9 @@ export interface InputFieldProps
|
|
|
43
44
|
| 'ref'
|
|
44
45
|
| 'onChange'
|
|
45
46
|
| 'defaultValue'
|
|
47
|
+
| 'min'
|
|
48
|
+
| 'max'
|
|
49
|
+
| 'step'
|
|
46
50
|
>,
|
|
47
51
|
FieldProps,
|
|
48
52
|
Partial<InputProps> {}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {
|
|
3
|
+
InputGroup,
|
|
4
|
+
NumberInput,
|
|
5
|
+
NumberInputField,
|
|
6
|
+
NumberInputStepper,
|
|
7
|
+
NumberIncrementStepper,
|
|
8
|
+
NumberDecrementStepper,
|
|
9
|
+
} from '@chakra-ui/react';
|
|
10
|
+
import { InputFieldProps } from '../InputTypes';
|
|
11
|
+
|
|
12
|
+
export interface StackedNumberInputProps extends InputFieldProps {
|
|
13
|
+
isRequired?: boolean;
|
|
14
|
+
leftElement?: React.ReactNode;
|
|
15
|
+
rightElement?: React.ReactNode;
|
|
16
|
+
variant?: string;
|
|
17
|
+
label?: string;
|
|
18
|
+
min?: number;
|
|
19
|
+
max?: number;
|
|
20
|
+
step?: number;
|
|
21
|
+
precision?: number;
|
|
22
|
+
showStepper?: boolean;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* A functional React component that renders Chakra UI's `NumberInput` wrapped
|
|
27
|
+
* in an `InputGroup`, following the same pattern as `StackedInput`.
|
|
28
|
+
*/
|
|
29
|
+
const StackedNumberInput = React.forwardRef<
|
|
30
|
+
HTMLInputElement,
|
|
31
|
+
StackedNumberInputProps
|
|
32
|
+
>(
|
|
33
|
+
(
|
|
34
|
+
{
|
|
35
|
+
name,
|
|
36
|
+
id,
|
|
37
|
+
placeholder,
|
|
38
|
+
isRequired,
|
|
39
|
+
isInvalid,
|
|
40
|
+
disabled,
|
|
41
|
+
value,
|
|
42
|
+
defaultValue,
|
|
43
|
+
min,
|
|
44
|
+
max,
|
|
45
|
+
step = 1,
|
|
46
|
+
precision = 0,
|
|
47
|
+
showStepper = false,
|
|
48
|
+
variant,
|
|
49
|
+
className,
|
|
50
|
+
label,
|
|
51
|
+
leftElement,
|
|
52
|
+
rightElement,
|
|
53
|
+
onChange,
|
|
54
|
+
onBlur,
|
|
55
|
+
},
|
|
56
|
+
ref
|
|
57
|
+
) => {
|
|
58
|
+
const isMobile = variant === 'mobile';
|
|
59
|
+
const resolvedPlaceholder = isMobile && label ? label : placeholder;
|
|
60
|
+
const inputValue =
|
|
61
|
+
typeof value === 'string' || typeof value === 'number' ? value : undefined;
|
|
62
|
+
const normalizedValue =
|
|
63
|
+
precision === 0 && inputValue !== undefined && inputValue !== ''
|
|
64
|
+
? Number.isNaN(Number(inputValue))
|
|
65
|
+
? inputValue
|
|
66
|
+
: String(Math.round(Number(inputValue)))
|
|
67
|
+
: inputValue;
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<InputGroup>
|
|
71
|
+
{leftElement && leftElement}
|
|
72
|
+
{label && !isMobile && label}
|
|
73
|
+
<NumberInput
|
|
74
|
+
id={id}
|
|
75
|
+
name={name}
|
|
76
|
+
isRequired={isRequired}
|
|
77
|
+
isInvalid={isInvalid}
|
|
78
|
+
isDisabled={disabled}
|
|
79
|
+
value={normalizedValue}
|
|
80
|
+
defaultValue={defaultValue}
|
|
81
|
+
min={min}
|
|
82
|
+
max={max}
|
|
83
|
+
step={step}
|
|
84
|
+
precision={precision}
|
|
85
|
+
onChange={(_: string, valueAsNumber: number) =>
|
|
86
|
+
onChange?.({
|
|
87
|
+
target: {
|
|
88
|
+
name,
|
|
89
|
+
value: Number.isNaN(valueAsNumber)
|
|
90
|
+
? ''
|
|
91
|
+
: precision === 0
|
|
92
|
+
? String(Math.round(valueAsNumber))
|
|
93
|
+
: String(valueAsNumber),
|
|
94
|
+
},
|
|
95
|
+
} as React.ChangeEvent<HTMLInputElement>)
|
|
96
|
+
}
|
|
97
|
+
className={className}
|
|
98
|
+
variant={variant === 'mobile' ? 'mobile' : 'default'}
|
|
99
|
+
width="100%"
|
|
100
|
+
>
|
|
101
|
+
<NumberInputField
|
|
102
|
+
ref={ref}
|
|
103
|
+
placeholder={resolvedPlaceholder}
|
|
104
|
+
onBlur={onBlur}
|
|
105
|
+
/>
|
|
106
|
+
{showStepper && (
|
|
107
|
+
<NumberInputStepper>
|
|
108
|
+
<NumberIncrementStepper />
|
|
109
|
+
<NumberDecrementStepper />
|
|
110
|
+
</NumberInputStepper>
|
|
111
|
+
)}
|
|
112
|
+
</NumberInput>
|
|
113
|
+
{rightElement && rightElement}
|
|
114
|
+
</InputGroup>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
StackedNumberInput.displayName = 'StackedNumberInput';
|
|
120
|
+
|
|
121
|
+
export default StackedNumberInput;
|
|
@@ -22,6 +22,7 @@ import {
|
|
|
22
22
|
UseFormSetValue,
|
|
23
23
|
} from 'react-hook-form';
|
|
24
24
|
import StackedMultiSelect from './StackedMultiSelect';
|
|
25
|
+
import StackedNumberInput from './StackedNumberInput/StackedNumberInput';
|
|
25
26
|
import StackedPilledInput from './StackedPilledInput';
|
|
26
27
|
import StackedSwitch from './StackedSwitch';
|
|
27
28
|
import { Label } from './components/label';
|
|
@@ -32,7 +33,7 @@ export interface InputProps<T extends FieldValues = FieldValues>
|
|
|
32
33
|
name: string;
|
|
33
34
|
ariaLabel: string;
|
|
34
35
|
placeholder?: string;
|
|
35
|
-
defaultValue?: string;
|
|
36
|
+
defaultValue?: string | number;
|
|
36
37
|
label?: string;
|
|
37
38
|
className?: string;
|
|
38
39
|
options?: FieldOption[];
|
|
@@ -54,6 +55,14 @@ export interface InputProps<T extends FieldValues = FieldValues>
|
|
|
54
55
|
truncatePillLength?: number;
|
|
55
56
|
searchable?: boolean;
|
|
56
57
|
overflowMode?: 'scroll' | 'wrap';
|
|
58
|
+
/** Minimum value (numberInput only) */
|
|
59
|
+
min?: number;
|
|
60
|
+
/** Maximum value (numberInput only) */
|
|
61
|
+
max?: number;
|
|
62
|
+
/** Increment/decrement step (numberInput only) */
|
|
63
|
+
step?: number;
|
|
64
|
+
/** Number of decimal places (numberInput only) */
|
|
65
|
+
precision?: number;
|
|
57
66
|
}
|
|
58
67
|
|
|
59
68
|
/**
|
|
@@ -90,12 +99,16 @@ export function Input<T extends FieldValues>({
|
|
|
90
99
|
truncatePillLength,
|
|
91
100
|
searchable,
|
|
92
101
|
overflowMode = 'scroll',
|
|
102
|
+
min,
|
|
103
|
+
max,
|
|
104
|
+
step,
|
|
105
|
+
precision,
|
|
93
106
|
}: InputProps<T>) {
|
|
94
107
|
function selectedInputField<T extends Element = Element>(
|
|
95
|
-
onChange: ((e: ChangeEvent<T>) => void) | ((v?: string) => void),
|
|
108
|
+
onChange: ((e: ChangeEvent<T>) => void) | ((v?: string | number) => void),
|
|
96
109
|
onBlur: () => void,
|
|
97
110
|
ref: RefCallBack,
|
|
98
|
-
value: string
|
|
111
|
+
value: string | number
|
|
99
112
|
) {
|
|
100
113
|
switch (inputType) {
|
|
101
114
|
case 'text':
|
|
@@ -121,6 +134,33 @@ export function Input<T extends FieldValues>({
|
|
|
121
134
|
label={label as string}
|
|
122
135
|
/>
|
|
123
136
|
);
|
|
137
|
+
case 'number':
|
|
138
|
+
return (
|
|
139
|
+
<StackedNumberInput
|
|
140
|
+
className={`input-${inputType} ${className ?? ''}`}
|
|
141
|
+
aria-label={ariaLabel}
|
|
142
|
+
name={name}
|
|
143
|
+
id={name}
|
|
144
|
+
placeholder={placeholder}
|
|
145
|
+
maxLength={maxLength}
|
|
146
|
+
isRequired={isRequired}
|
|
147
|
+
isInvalid={isInvalid}
|
|
148
|
+
onChange={onChange as (e: ChangeEvent) => void}
|
|
149
|
+
onBlur={onBlur}
|
|
150
|
+
ref={ref}
|
|
151
|
+
rightElement={rightElement}
|
|
152
|
+
leftElement={leftElement}
|
|
153
|
+
disabled={disabled}
|
|
154
|
+
defaultValue={defaultValue}
|
|
155
|
+
value={value}
|
|
156
|
+
variant={variant}
|
|
157
|
+
label={label as string}
|
|
158
|
+
min={min}
|
|
159
|
+
max={max}
|
|
160
|
+
step={step}
|
|
161
|
+
precision={precision}
|
|
162
|
+
/>
|
|
163
|
+
);
|
|
124
164
|
case 'radio':
|
|
125
165
|
return (
|
|
126
166
|
<StackedRadioGroup
|