@xqmsg/ui-core 0.9.2 → 0.10.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/InputTypes.d.ts +5 -3
- package/dist/components/input/StackedInput/StackedInput.d.ts +0 -3
- package/dist/components/input/StackedMultiSelect/index.d.ts +1 -1
- package/dist/components/input/StackedSelect/StackedSelect.d.ts +7 -3
- package/dist/components/input/components/dropdown/index.d.ts +10 -0
- package/dist/components/input/components/label/index.d.ts +9 -0
- package/dist/components/input/components/token/Token.stories.d.ts +5 -0
- package/dist/components/input/components/token/index.d.ts +7 -0
- package/dist/components/input/index.d.ts +1 -3
- package/dist/theme/components/form-error.d.ts +3 -3
- package/dist/theme/components/form-label.d.ts +4 -6
- package/dist/theme/components/form.d.ts +3 -3
- package/dist/theme/components/input.d.ts +32 -161
- package/dist/theme/components/select.d.ts +27 -153
- package/dist/theme/components/textarea.d.ts +10 -117
- package/dist/theme/foundations/colors.d.ts +30 -0
- package/dist/ui-core.cjs.development.js +455 -490
- 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 +459 -494
- package/dist/ui-core.esm.js.map +1 -1
- package/package.json +5 -3
- package/src/components/input/Input.stories.tsx +28 -12
- package/src/components/input/InputTypes.ts +7 -1
- package/src/components/input/StackedInput/StackedInput.tsx +3 -15
- package/src/components/input/StackedMultiSelect/components/MultiValue/index.tsx +2 -2
- package/src/components/input/StackedMultiSelect/index.tsx +89 -93
- package/src/components/input/StackedPilledInput/index.tsx +145 -56
- package/src/components/input/StackedSelect/StackedSelect.tsx +63 -20
- package/src/components/input/StackedSelect/assets/svg/subtract.svg +3 -0
- package/src/components/input/components/dropdown/index.tsx +79 -0
- package/src/components/input/components/label/index.tsx +24 -0
- package/src/components/input/components/token/Token.stories.tsx +22 -0
- package/src/components/input/components/token/assets/svg/close.svg +3 -0
- package/src/components/input/components/token/index.tsx +37 -0
- package/src/components/input/index.tsx +8 -20
- package/src/theme/components/alert.ts +4 -4
- package/src/theme/components/form-error.ts +11 -14
- package/src/theme/components/form-label.ts +8 -8
- package/src/theme/components/form.ts +10 -13
- package/src/theme/components/input.ts +17 -191
- package/src/theme/components/select.ts +5 -10
- package/src/theme/components/textarea.ts +2 -38
- package/src/theme/foundations/colors.ts +17 -1
- package/dist/components/input/components/InputTag/index.d.ts +0 -7
- package/src/components/input/components/InputTag/index.tsx +0 -24
package/package.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "0.
|
|
2
|
+
"version": "0.10.0",
|
|
3
3
|
"license": "MIT",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"typings": "dist/index.d.ts",
|
|
@@ -79,6 +79,10 @@
|
|
|
79
79
|
"tsdx": "^0.14.1",
|
|
80
80
|
"tslib": "^2.4.0",
|
|
81
81
|
"typescript": "^4.8.2",
|
|
82
|
+
"generate-changelog": "^1.8.0",
|
|
83
|
+
"yalc": "^1.0.0-pre.53"
|
|
84
|
+
},
|
|
85
|
+
"dependencies": {
|
|
82
86
|
"@chakra-ui/icons": "^2.0.0",
|
|
83
87
|
"@chakra-ui/media-query": "^2.0.0",
|
|
84
88
|
"@chakra-ui/progress": "^2.0.0",
|
|
@@ -94,7 +98,6 @@
|
|
|
94
98
|
"@hookform/resolvers": "^2.9.7",
|
|
95
99
|
"axios": "^0.27.2",
|
|
96
100
|
"framer-motion": "6.3.0",
|
|
97
|
-
"generate-changelog": "^1.8.0",
|
|
98
101
|
"ip-regex": "^5.0.0",
|
|
99
102
|
"react": "^18.0.0",
|
|
100
103
|
"react-dom": "^18.0.0",
|
|
@@ -102,7 +105,6 @@
|
|
|
102
105
|
"react-icons": "^4.4.0",
|
|
103
106
|
"react-is": "^18.2.0",
|
|
104
107
|
"react-select": "^5.4.0",
|
|
105
|
-
"yalc": "^1.0.0-pre.53",
|
|
106
108
|
"yup": "^0.32.11"
|
|
107
109
|
},
|
|
108
110
|
"resolutions": {
|
|
@@ -7,6 +7,7 @@ import * as Yup from 'yup';
|
|
|
7
7
|
import { Form } from '../form';
|
|
8
8
|
import ipRegex from 'ip-regex';
|
|
9
9
|
import { useEffect, useMemo } from '@storybook/addons';
|
|
10
|
+
import { Box } from '@chakra-ui/react';
|
|
10
11
|
|
|
11
12
|
const meta: Meta<InputProps<StoryFormSchema>> = {
|
|
12
13
|
title: 'Input example',
|
|
@@ -85,7 +86,7 @@ const storyFormSchema: Yup.SchemaOf<StoryFormSchema> = Yup.object().shape({
|
|
|
85
86
|
(value, testContext) => {
|
|
86
87
|
if (value) {
|
|
87
88
|
const ipStringsToArray = value.split(',');
|
|
88
|
-
const isIPValidArray = ipStringsToArray.map(ip => {
|
|
89
|
+
const isIPValidArray = ipStringsToArray.map((ip) => {
|
|
89
90
|
return ipRegex({ exact: true }).test(ip as string);
|
|
90
91
|
});
|
|
91
92
|
|
|
@@ -99,7 +100,7 @@ const storyFormSchema: Yup.SchemaOf<StoryFormSchema> = Yup.object().shape({
|
|
|
99
100
|
return malformedIP.trim();
|
|
100
101
|
}
|
|
101
102
|
})
|
|
102
|
-
.filter(invalidIP => invalidIP !== undefined);
|
|
103
|
+
.filter((invalidIP) => invalidIP !== undefined);
|
|
103
104
|
|
|
104
105
|
const errorMessage = `Malformed IPs: ${malformedIPList.join(', ')}`;
|
|
105
106
|
return testContext.createError({
|
|
@@ -114,7 +115,7 @@ const storyFormSchema: Yup.SchemaOf<StoryFormSchema> = Yup.object().shape({
|
|
|
114
115
|
});
|
|
115
116
|
|
|
116
117
|
export default meta;
|
|
117
|
-
const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
118
|
+
const Template: Story<InputProps<StoryFormSchema>> = (args) => {
|
|
118
119
|
const formHandler = useFormHandler<StoryFormSchema>(
|
|
119
120
|
onStubbedSubmit,
|
|
120
121
|
storyFormDefaultValues,
|
|
@@ -129,20 +130,15 @@ const Template: Story<InputProps<StoryFormSchema>> = args => {
|
|
|
129
130
|
if (form.formState.errors) return form.formState.errors.prop?.message;
|
|
130
131
|
}, [form.formState.errors]);
|
|
131
132
|
|
|
132
|
-
console.log(form.watch('prop'));
|
|
133
|
-
|
|
134
133
|
useEffect(() => {
|
|
135
134
|
form.resetField('prop');
|
|
136
|
-
}, [args.inputType]);
|
|
135
|
+
}, [args.inputType, form]);
|
|
137
136
|
|
|
138
137
|
return (
|
|
139
138
|
<Form formHandler={formHandler}>
|
|
140
|
-
<Input
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
errorText={valueErrorMessage}
|
|
144
|
-
isInvalid={!!valueErrorMessage}
|
|
145
|
-
/>
|
|
139
|
+
<Input {...args} setValue={form.setValue} errorText={valueErrorMessage} />
|
|
140
|
+
<Box mb={10}>Hi</Box> <Box mb={10}>there</Box> <Box mb={10}>Hi</Box>{' '}
|
|
141
|
+
<Box mb={10}>hey</Box> hello
|
|
146
142
|
</Form>
|
|
147
143
|
);
|
|
148
144
|
};
|
|
@@ -153,17 +149,37 @@ Default.args = {
|
|
|
153
149
|
inputType: 'text',
|
|
154
150
|
name: 'prop',
|
|
155
151
|
options: [
|
|
152
|
+
{ value: 'section_header', label: 'Section 1', sortValue: 0 },
|
|
156
153
|
{
|
|
157
154
|
value: 'value1',
|
|
158
155
|
label: 'Value 1',
|
|
156
|
+
sortValue: 1,
|
|
159
157
|
},
|
|
160
158
|
{
|
|
161
159
|
value: 'value2',
|
|
162
160
|
label: 'Value 2',
|
|
161
|
+
sortValue: 2,
|
|
163
162
|
},
|
|
164
163
|
{
|
|
165
164
|
value: 'value3',
|
|
166
165
|
label: 'Value 3',
|
|
166
|
+
sortValue: 3,
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
value: 'value4',
|
|
170
|
+
label: 'Value 4',
|
|
171
|
+
sortValue: 4,
|
|
172
|
+
},
|
|
173
|
+
{ value: 'section_header', label: 'Section 2', sortValue: 5 },
|
|
174
|
+
{
|
|
175
|
+
value: 'value5',
|
|
176
|
+
label: 'Value 5',
|
|
177
|
+
sortValue: 6,
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
value: 'value6',
|
|
181
|
+
label: 'Value 6',
|
|
182
|
+
sortValue: 7,
|
|
167
183
|
},
|
|
168
184
|
],
|
|
169
185
|
isRequired: true,
|
|
@@ -18,7 +18,13 @@ export type InputType =
|
|
|
18
18
|
| 'checkbox'
|
|
19
19
|
| 'switch';
|
|
20
20
|
|
|
21
|
-
export type
|
|
21
|
+
export type FieldOption = {
|
|
22
|
+
label: string;
|
|
23
|
+
value: string | 'section_header';
|
|
24
|
+
sortValue: number;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type FieldOptions = FieldOption[];
|
|
22
28
|
|
|
23
29
|
export interface ValidationProps {
|
|
24
30
|
isRequired: boolean;
|
|
@@ -1,29 +1,17 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { Input
|
|
2
|
+
import { Input } from '@chakra-ui/react';
|
|
3
3
|
import { InputFieldProps } from '../InputTypes';
|
|
4
4
|
|
|
5
5
|
export interface StackedInputProps extends InputFieldProps {
|
|
6
|
-
label?: string;
|
|
7
6
|
isRequired?: boolean;
|
|
8
|
-
leftElement?: React.ReactNode;
|
|
9
|
-
rightElement?: React.ReactNode;
|
|
10
7
|
}
|
|
11
8
|
|
|
12
9
|
/**
|
|
13
10
|
* A functional React component utilized to render the `StackedInput` component.
|
|
14
11
|
*/
|
|
15
12
|
const StackedInput = React.forwardRef<HTMLInputElement, StackedInputProps>(
|
|
16
|
-
(
|
|
17
|
-
{ type
|
|
18
|
-
_ref
|
|
19
|
-
) => {
|
|
20
|
-
return (
|
|
21
|
-
<InputGroup>
|
|
22
|
-
{leftElement && leftElement}
|
|
23
|
-
<Input ref={_ref} type={type} isRequired={isRequired} {...props} />
|
|
24
|
-
{rightElement && rightElement}
|
|
25
|
-
</InputGroup>
|
|
26
|
-
);
|
|
13
|
+
({ type = 'text', isRequired, ...props }, _ref) => {
|
|
14
|
+
return <Input ref={_ref} type={type} isRequired={isRequired} {...props} />;
|
|
27
15
|
}
|
|
28
16
|
);
|
|
29
17
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Box } from '@chakra-ui/react';
|
|
2
2
|
import React, { PropsWithChildren } from 'react';
|
|
3
|
-
import InputTag from '../../../components/
|
|
3
|
+
import InputTag from '../../../components/token';
|
|
4
4
|
|
|
5
5
|
interface MultiValueProps extends PropsWithChildren {
|
|
6
6
|
clearValue: () => void;
|
|
@@ -13,7 +13,7 @@ interface MultiValueProps extends PropsWithChildren {
|
|
|
13
13
|
const MultiValue: React.FC<MultiValueProps> = ({ children, clearValue }) => {
|
|
14
14
|
return (
|
|
15
15
|
<Box marginRight="5px">
|
|
16
|
-
<InputTag
|
|
16
|
+
<InputTag label={children} onDelete={clearValue} />
|
|
17
17
|
</Box>
|
|
18
18
|
);
|
|
19
19
|
};
|
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
import React, { useEffect, useState } from 'react';
|
|
2
|
-
import { Flex } from '@chakra-ui/react';
|
|
3
|
-
import {
|
|
4
|
-
|
|
1
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { Box, Flex, Text, Image, useOutsideClick } from '@chakra-ui/react';
|
|
3
|
+
import {
|
|
4
|
+
FieldOption,
|
|
5
|
+
FieldOptions,
|
|
6
|
+
ReactSelectFieldProps,
|
|
7
|
+
} from '../InputTypes';
|
|
5
8
|
import colors from '../../../theme/foundations/colors';
|
|
6
|
-
import MultiValue from './components/MultiValue';
|
|
7
9
|
import {
|
|
8
10
|
Control,
|
|
9
11
|
FieldValues,
|
|
10
12
|
UseFormSetValue,
|
|
11
13
|
useWatch,
|
|
12
14
|
} from 'react-hook-form';
|
|
15
|
+
import SubtractIcon from '../StackedSelect/assets/svg/subtract.svg';
|
|
16
|
+
import { Dropdown } from '../components/dropdown';
|
|
17
|
+
import Token from '../components/token';
|
|
13
18
|
|
|
14
19
|
export interface StackedMultiSelectProps extends ReactSelectFieldProps {
|
|
15
20
|
options: FieldOptions;
|
|
@@ -21,124 +26,115 @@ export interface StackedMultiSelectProps extends ReactSelectFieldProps {
|
|
|
21
26
|
* A functional React component utilized to render the `StackedMultiSelect` component.
|
|
22
27
|
*/
|
|
23
28
|
const StackedMultiSelect = React.forwardRef<
|
|
24
|
-
|
|
29
|
+
HTMLInputElement,
|
|
25
30
|
StackedMultiSelectProps
|
|
26
|
-
>(({ options, setValue, control, name }, _ref) => {
|
|
31
|
+
>(({ options, setValue, control, name, placeholder, disabled }, _ref) => {
|
|
27
32
|
const watchedValue = useWatch({ control, name: name as string });
|
|
33
|
+
const dropdownRef = useRef(null);
|
|
34
|
+
|
|
35
|
+
const [localValues, setLocalValues] = useState<FieldOptions>([]);
|
|
36
|
+
const [localOptions, setLocalOptions] = useState<FieldOptions>(options);
|
|
37
|
+
const [isFocussed, setIsFocussed] = useState(false);
|
|
28
38
|
|
|
29
|
-
|
|
30
|
-
const [localValue, setLocalValue] = useState([]);
|
|
39
|
+
useOutsideClick({ ref: dropdownRef, handler: () => setIsFocussed(false) });
|
|
31
40
|
|
|
32
41
|
// gets latest watched form value (common delimited) from RHF state and creates a list
|
|
33
42
|
useEffect(() => {
|
|
34
43
|
if (watchedValue !== undefined && !watchedValue.length) {
|
|
35
|
-
|
|
44
|
+
setLocalValues([]);
|
|
36
45
|
}
|
|
37
46
|
|
|
38
47
|
if (watchedValue !== undefined && watchedValue?.length) {
|
|
39
|
-
|
|
48
|
+
setLocalValues(
|
|
40
49
|
watchedValue
|
|
41
50
|
.split(',')
|
|
42
51
|
.filter(Boolean)
|
|
43
52
|
.map((value: string) =>
|
|
44
|
-
options.find(option => option.value === value)
|
|
53
|
+
options.find((option) => option.value === value)
|
|
45
54
|
)
|
|
46
55
|
);
|
|
47
56
|
}
|
|
48
57
|
}, [options, watchedValue]);
|
|
49
58
|
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
clearValue={() => {
|
|
55
|
-
const arrayValue = watchedValue
|
|
56
|
-
.split(',')
|
|
57
|
-
.filter((_: string, index: number) => index !== props.index);
|
|
58
|
-
|
|
59
|
-
setLocalValue(
|
|
60
|
-
arrayValue.map((value: string) =>
|
|
61
|
-
options.find(option => option.value === value)
|
|
62
|
-
)
|
|
63
|
-
);
|
|
64
|
-
|
|
65
|
-
setValue(name as string, arrayValue.join(','), {
|
|
66
|
-
shouldValidate: true,
|
|
67
|
-
shouldDirty: true,
|
|
68
|
-
});
|
|
69
|
-
}}
|
|
70
|
-
>
|
|
71
|
-
{props.children}
|
|
72
|
-
</MultiValue>
|
|
73
|
-
),
|
|
74
|
-
};
|
|
59
|
+
const handleChange = (option: FieldOption) => {
|
|
60
|
+
const newValue = [...localValues, option]
|
|
61
|
+
.map(({ value }) => value)
|
|
62
|
+
.join(',');
|
|
75
63
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
64
|
+
setValue(name as string, newValue, {
|
|
65
|
+
shouldValidate: true,
|
|
66
|
+
shouldDirty: true,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
setLocalOptions((prevLocalOptions) =>
|
|
70
|
+
prevLocalOptions.filter((prevLocalOption) => prevLocalOption !== option)
|
|
84
71
|
);
|
|
72
|
+
|
|
73
|
+
setLocalValues((prevLocalValues) => [...prevLocalValues, option]);
|
|
85
74
|
};
|
|
86
75
|
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
76
|
+
const handleDelete = (option: FieldOption) => {
|
|
77
|
+
const newValue = localValues
|
|
78
|
+
.filter((localValue) => localValue !== option)
|
|
79
|
+
.map(({ value }) => value)
|
|
80
|
+
.join(',');
|
|
91
81
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
82
|
+
setValue(name as string, newValue, {
|
|
83
|
+
shouldValidate: true,
|
|
84
|
+
shouldDirty: true,
|
|
85
|
+
});
|
|
95
86
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
<Flex alignItems="center" justifyContent="space-between">
|
|
99
|
-
<span>{data.label}</span>
|
|
100
|
-
</Flex>
|
|
87
|
+
setLocalOptions((prevLocalOptions) =>
|
|
88
|
+
[...prevLocalOptions, option].sort((a, b) => a.sortValue - b.sortValue)
|
|
101
89
|
);
|
|
102
|
-
};
|
|
103
90
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
fontSize: '16px',
|
|
108
|
-
color: '#202020',
|
|
109
|
-
backgroundColor: '#FFFFFF',
|
|
110
|
-
border: '1px solid',
|
|
111
|
-
borderColor: colors.gray[200],
|
|
112
|
-
minHeight: '48px',
|
|
113
|
-
display: 'flex',
|
|
114
|
-
padding: '2px 6px',
|
|
115
|
-
}),
|
|
116
|
-
menu: () => ({
|
|
117
|
-
boxShadow: '0 5px 5px 0 rgba(16, 27, 79, 0.15)',
|
|
118
|
-
borderRadius: '6px',
|
|
119
|
-
backgroundColor: 'white',
|
|
120
|
-
}),
|
|
121
|
-
indicatorsContainer: () => ({ display: 'none' }),
|
|
122
|
-
placeholder: () => ({ color: '#CBCDCF', fontSize: '16px' }),
|
|
91
|
+
setLocalValues((prevLocalValues) =>
|
|
92
|
+
prevLocalValues.filter((prevLocalValue) => prevLocalValue !== option)
|
|
93
|
+
);
|
|
123
94
|
};
|
|
124
95
|
|
|
125
96
|
return (
|
|
126
|
-
<
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
97
|
+
<Box ref={dropdownRef} position="relative">
|
|
98
|
+
<Flex
|
|
99
|
+
fontSize="13px"
|
|
100
|
+
border={isFocussed ? '2px solid' : '1px solid'}
|
|
101
|
+
borderColor={isFocussed ? colors.border.focus : colors.border.default}
|
|
102
|
+
py="5px"
|
|
103
|
+
pl="8px"
|
|
104
|
+
borderRadius="4px"
|
|
105
|
+
alignItems="center"
|
|
106
|
+
justifyContent="space-between"
|
|
107
|
+
onClick={() => !disabled && setIsFocussed(true)}
|
|
108
|
+
bg={disabled ? colors.fill.light : '#ffffff'}
|
|
109
|
+
cursor={disabled ? 'not-allowed' : 'pointer'}
|
|
110
|
+
>
|
|
111
|
+
<Flex height="28px" alignItems="center">
|
|
112
|
+
{localValues.length ? (
|
|
113
|
+
localValues.map((option) => (
|
|
114
|
+
<Box mr="4px">
|
|
115
|
+
<Token
|
|
116
|
+
label={option.label}
|
|
117
|
+
onDelete={() => handleDelete(option)}
|
|
118
|
+
/>
|
|
119
|
+
</Box>
|
|
120
|
+
))
|
|
121
|
+
) : (
|
|
122
|
+
<Text color={colors.label.secondary.light} fontSize="13px">
|
|
123
|
+
{placeholder}
|
|
124
|
+
</Text>
|
|
125
|
+
)}
|
|
126
|
+
</Flex>
|
|
127
|
+
<Flex width="39px" justifyContent="center" alignItems="center">
|
|
128
|
+
<Image src={SubtractIcon} alt="subtract" boxSize="16px" />
|
|
129
|
+
</Flex>
|
|
130
|
+
</Flex>
|
|
131
|
+
{isFocussed && (
|
|
132
|
+
<Dropdown
|
|
133
|
+
onSelectItem={(option) => handleChange(option)}
|
|
134
|
+
options={localOptions}
|
|
135
|
+
/>
|
|
136
|
+
)}
|
|
137
|
+
</Box>
|
|
142
138
|
);
|
|
143
139
|
});
|
|
144
140
|
|