@ssa-ui-kit/core 1.0.4 → 1.0.7
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/Typeahead/Typeahead.context.d.ts +4 -2
- package/dist/components/Typeahead/Typeahead.d.ts +1 -1
- package/dist/components/Typeahead/styles.d.ts +10 -9
- package/dist/components/Typeahead/types.d.ts +4 -2
- package/dist/components/Typeahead/useTypeahead.d.ts +2 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/CollapsibleNavBar/CollapsibleNavBarBase.ts +3 -3
- package/src/components/ImageItem/ImageItem.tsx +1 -1
- package/src/components/NavBar/NavBar.stories.tsx +7 -2
- package/src/components/NavBar/NavBarWrapper.ts +1 -1
- package/src/components/NotificationMenu/NotificationMenu.spec.tsx +1 -1
- package/src/components/NotificationMenu/stories/StoryComponent.tsx +1 -1
- package/src/components/Radio/RadioBase.tsx +1 -1
- package/src/components/RadioGroup/RadioGroup.stories.tsx +1 -1
- package/src/components/TextField/TextField.stories.tsx +38 -45
- package/src/components/Typeahead/Typeahead.context.ts +2 -0
- package/src/components/Typeahead/Typeahead.spec.tsx +6 -3
- package/src/components/Typeahead/Typeahead.stories.tsx +1 -1
- package/src/components/Typeahead/Typeahead.tsx +9 -4
- package/src/components/Typeahead/components/MultipleTrigger.tsx +2 -2
- package/src/components/Typeahead/components/SingleTrigger.tsx +4 -2
- package/src/components/Typeahead/components/TypeaheadItem.ts +1 -1
- package/src/components/Typeahead/styles.ts +4 -2
- package/src/components/Typeahead/types.ts +4 -2
- package/src/components/Typeahead/useTypeahead.tsx +21 -4
- package/src/components/UserProfile/UserProfile.stories.tsx +4 -2
- package/tsbuildcache +1 -1
package/package.json
CHANGED
|
@@ -75,7 +75,7 @@ const CollapsibleNavBarBase = styled(NavBarBase)`
|
|
|
75
75
|
|
|
76
76
|
& ~ div:nth-of-type(2) {
|
|
77
77
|
display: block;
|
|
78
|
-
border-radius:
|
|
78
|
+
border-radius: 0;
|
|
79
79
|
height: calc(100vh - 60px);
|
|
80
80
|
|
|
81
81
|
${({ theme }) => theme.mediaQueries.xlg} {
|
|
@@ -101,8 +101,8 @@ const CollapsibleNavBarBase = styled(NavBarBase)`
|
|
|
101
101
|
|
|
102
102
|
${({ theme }) => theme.mediaQueries.lg} {
|
|
103
103
|
&.opened {
|
|
104
|
-
min-width:
|
|
105
|
-
width:
|
|
104
|
+
min-width: 240px;
|
|
105
|
+
width: 291px;
|
|
106
106
|
|
|
107
107
|
& > div:nth-of-type(2) {
|
|
108
108
|
width: 240px;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Fragment } from 'react';
|
|
2
2
|
import { Routes, Route, MemoryRouter } from 'react-router-dom';
|
|
3
3
|
import { Meta } from '@storybook/react';
|
|
4
|
-
import { Title, Description,
|
|
4
|
+
import { Title, Description, Subtitle, Primary } from '@storybook/addon-docs';
|
|
5
5
|
|
|
6
6
|
import { NavBar } from './NavBar';
|
|
7
7
|
import { DecoratorFunction } from '@storybook/types';
|
|
@@ -42,12 +42,17 @@ export default {
|
|
|
42
42
|
viewport: {
|
|
43
43
|
defaultViewport: 'mobile2',
|
|
44
44
|
},
|
|
45
|
+
source: {
|
|
46
|
+
type: 'code',
|
|
47
|
+
},
|
|
45
48
|
docs: {
|
|
49
|
+
inlineStories: false,
|
|
46
50
|
page: () => (
|
|
47
51
|
<Fragment>
|
|
48
52
|
<Title />
|
|
53
|
+
<Subtitle />
|
|
49
54
|
<Description />
|
|
50
|
-
<
|
|
55
|
+
<Primary />
|
|
51
56
|
</Fragment>
|
|
52
57
|
),
|
|
53
58
|
},
|
|
@@ -15,7 +15,7 @@ const NavBarWrapper = styled.div`
|
|
|
15
15
|
${({ theme }) => theme.colors.greyDarker} 100%
|
|
16
16
|
);
|
|
17
17
|
|
|
18
|
-
transform: translateY(-
|
|
18
|
+
transform: translateY(-300vh);
|
|
19
19
|
transition: height 475ms ease, transform 450ms ease, border-radius 450ms ease;
|
|
20
20
|
|
|
21
21
|
${({ theme }) => theme.mediaQueries.md} {
|
|
@@ -71,7 +71,7 @@ export const StoryComponent = () => {
|
|
|
71
71
|
}
|
|
72
72
|
rightButton={
|
|
73
73
|
<Link to={'/'} css={{ gridColumn: 2 }}>
|
|
74
|
-
<Button variant="info" text="View all
|
|
74
|
+
<Button variant="info" text="View all notifications" />
|
|
75
75
|
</Link>
|
|
76
76
|
}
|
|
77
77
|
isLoading={isLoading}>
|
|
@@ -6,6 +6,7 @@ export const RadioBase = styled(Label)`
|
|
|
6
6
|
flex-grow: 0;
|
|
7
7
|
align-items: center;
|
|
8
8
|
cursor: pointer;
|
|
9
|
+
gap: 5px;
|
|
9
10
|
|
|
10
11
|
&:has(input:disabled) {
|
|
11
12
|
cursor: default;
|
|
@@ -29,7 +30,6 @@ export const RadioBase = styled(Label)`
|
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
span {
|
|
32
|
-
margin-left: 10px;
|
|
33
33
|
font-size: 14px;
|
|
34
34
|
font-weight: 100;
|
|
35
35
|
}
|
|
@@ -47,7 +47,7 @@ export const HorizontalRadioGroupStories: StoryObj<typeof RadioGroup> = (
|
|
|
47
47
|
) => (
|
|
48
48
|
<Fragment>
|
|
49
49
|
<Typography variant="h4">Horizontal Radio Group</Typography>
|
|
50
|
-
<RadioGroup {...args} css={{ marginTop: '10px' }}>
|
|
50
|
+
<RadioGroup {...args} css={{ marginTop: '10px', gap: 10, display: 'flex' }}>
|
|
51
51
|
<Radio id="radio1" value="apple" text="Apple" />
|
|
52
52
|
<Radio id="radio2" value="orange" text="Orange" />
|
|
53
53
|
<Radio id="radio3" value="banana" text="Banana" isDisabled={true} />
|
|
@@ -37,11 +37,24 @@ export default {
|
|
|
37
37
|
},
|
|
38
38
|
},
|
|
39
39
|
decorators: [
|
|
40
|
-
(Story) =>
|
|
41
|
-
<
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
40
|
+
(Story, context) => {
|
|
41
|
+
const useFormResult = useForm<FieldValues>();
|
|
42
|
+
return (
|
|
43
|
+
<Form
|
|
44
|
+
onSubmit={useFormResult.handleSubmit((data) => {
|
|
45
|
+
console.log('>>>onSubmit', data);
|
|
46
|
+
})}>
|
|
47
|
+
<FormGroup>
|
|
48
|
+
{Story({
|
|
49
|
+
args: {
|
|
50
|
+
...context.args,
|
|
51
|
+
register: useFormResult.register,
|
|
52
|
+
},
|
|
53
|
+
})}
|
|
54
|
+
</FormGroup>
|
|
55
|
+
</Form>
|
|
56
|
+
);
|
|
57
|
+
},
|
|
45
58
|
],
|
|
46
59
|
} as Meta<typeof TextField>;
|
|
47
60
|
|
|
@@ -51,9 +64,7 @@ const mockError: FieldError = {
|
|
|
51
64
|
};
|
|
52
65
|
|
|
53
66
|
export const Basic: StoryObj<typeof TextField> = (args: Args) => {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
return <TextField {...args} register={register} />;
|
|
67
|
+
return <TextField {...args} register={args.register} />;
|
|
57
68
|
};
|
|
58
69
|
Basic.args = {
|
|
59
70
|
placeholder: 'Field',
|
|
@@ -65,15 +76,13 @@ Basic.args = {
|
|
|
65
76
|
helperText: 'some nice text',
|
|
66
77
|
};
|
|
67
78
|
|
|
68
|
-
export const WithError: StoryObj<typeof TextField> = () => {
|
|
69
|
-
const { register } = useForm<FieldValues>();
|
|
70
|
-
|
|
79
|
+
export const WithError: StoryObj<typeof TextField> = (args: Args) => {
|
|
71
80
|
return (
|
|
72
81
|
<TextField
|
|
73
82
|
placeholder="Field error"
|
|
74
83
|
label="Field"
|
|
75
84
|
name="field2"
|
|
76
|
-
register={register}
|
|
85
|
+
register={args.register}
|
|
77
86
|
validationSchema={{
|
|
78
87
|
required: 'Required',
|
|
79
88
|
}}
|
|
@@ -83,15 +92,13 @@ export const WithError: StoryObj<typeof TextField> = () => {
|
|
|
83
92
|
};
|
|
84
93
|
WithError.args = {};
|
|
85
94
|
|
|
86
|
-
export const WithSuccess: StoryObj<typeof TextField> = () => {
|
|
87
|
-
const { register } = useForm<FieldValues>();
|
|
88
|
-
|
|
95
|
+
export const WithSuccess: StoryObj<typeof TextField> = (args: Args) => {
|
|
89
96
|
return (
|
|
90
97
|
<TextField
|
|
91
98
|
placeholder="Field success"
|
|
92
99
|
label="Field"
|
|
93
100
|
name="field3"
|
|
94
|
-
register={register}
|
|
101
|
+
register={args.register}
|
|
95
102
|
validationSchema={{
|
|
96
103
|
required: 'Required',
|
|
97
104
|
}}
|
|
@@ -102,15 +109,13 @@ export const WithSuccess: StoryObj<typeof TextField> = () => {
|
|
|
102
109
|
};
|
|
103
110
|
WithSuccess.args = {};
|
|
104
111
|
|
|
105
|
-
export const Disabled: StoryObj<typeof TextField> = () => {
|
|
106
|
-
const { register } = useForm<FieldValues>();
|
|
107
|
-
|
|
112
|
+
export const Disabled: StoryObj<typeof TextField> = (args: Args) => {
|
|
108
113
|
return (
|
|
109
114
|
<TextField
|
|
110
115
|
placeholder="Field disabled"
|
|
111
116
|
label="Field"
|
|
112
117
|
name="field4"
|
|
113
|
-
register={register}
|
|
118
|
+
register={args.register}
|
|
114
119
|
helperText="some nice text"
|
|
115
120
|
disabled={true}
|
|
116
121
|
endElement={<Icon name="visible" size={16} />}
|
|
@@ -119,15 +124,13 @@ export const Disabled: StoryObj<typeof TextField> = () => {
|
|
|
119
124
|
};
|
|
120
125
|
Disabled.args = {};
|
|
121
126
|
|
|
122
|
-
export const WithStatusDisabled: StoryObj<typeof TextField> = () => {
|
|
123
|
-
const { register } = useForm<FieldValues>();
|
|
124
|
-
|
|
127
|
+
export const WithStatusDisabled: StoryObj<typeof TextField> = (args: Args) => {
|
|
125
128
|
return (
|
|
126
129
|
<TextField
|
|
127
130
|
placeholder="Field success disabled"
|
|
128
131
|
label="Field"
|
|
129
132
|
name="field5"
|
|
130
|
-
register={register}
|
|
133
|
+
register={args.register}
|
|
131
134
|
helperText="some nice text"
|
|
132
135
|
disabled={true}
|
|
133
136
|
success={true}
|
|
@@ -136,23 +139,21 @@ export const WithStatusDisabled: StoryObj<typeof TextField> = () => {
|
|
|
136
139
|
};
|
|
137
140
|
WithStatusDisabled.args = {};
|
|
138
141
|
|
|
139
|
-
export const WithAction: StoryObj<typeof TextField> = () => {
|
|
140
|
-
const { register } = useForm<FieldValues>();
|
|
141
|
-
|
|
142
|
+
export const WithAction: StoryObj<typeof TextField> = (args: Args) => {
|
|
142
143
|
return (
|
|
143
144
|
<TextField
|
|
144
145
|
type="password"
|
|
145
146
|
placeholder="Field"
|
|
146
147
|
label="Field"
|
|
147
148
|
name="field6"
|
|
148
|
-
register={register}
|
|
149
|
+
register={args.register}
|
|
149
150
|
helperText="some nice text"
|
|
150
151
|
endElement={
|
|
151
152
|
<button
|
|
153
|
+
type="submit"
|
|
152
154
|
onClick={(event) => {
|
|
153
|
-
|
|
155
|
+
console.log('>>>action...');
|
|
154
156
|
event.preventDefault();
|
|
155
|
-
console.log('calling action...');
|
|
156
157
|
}}>
|
|
157
158
|
Action
|
|
158
159
|
</button>
|
|
@@ -162,24 +163,20 @@ export const WithAction: StoryObj<typeof TextField> = () => {
|
|
|
162
163
|
};
|
|
163
164
|
WithAction.args = {};
|
|
164
165
|
|
|
165
|
-
export const MultilineSimple: StoryObj<typeof TextField> = () => {
|
|
166
|
-
const { register } = useForm<FieldValues>();
|
|
167
|
-
|
|
166
|
+
export const MultilineSimple: StoryObj<typeof TextField> = (args: Args) => {
|
|
168
167
|
return (
|
|
169
168
|
<TextField
|
|
170
169
|
multirow
|
|
171
170
|
rows={10}
|
|
172
171
|
placeholder="Textarea"
|
|
173
172
|
name="textarea"
|
|
174
|
-
register={register}
|
|
173
|
+
register={args.register}
|
|
175
174
|
/>
|
|
176
175
|
);
|
|
177
176
|
};
|
|
178
177
|
MultilineSimple.args = {};
|
|
179
178
|
|
|
180
|
-
export const Multiline: StoryObj<typeof TextField> = () => {
|
|
181
|
-
const { register } = useForm<FieldValues>();
|
|
182
|
-
|
|
179
|
+
export const Multiline: StoryObj<typeof TextField> = (args: Args) => {
|
|
183
180
|
return (
|
|
184
181
|
<TextField
|
|
185
182
|
multirow
|
|
@@ -188,15 +185,13 @@ export const Multiline: StoryObj<typeof TextField> = () => {
|
|
|
188
185
|
placeholder="Textarea"
|
|
189
186
|
name="textarea"
|
|
190
187
|
helperText="some nice text"
|
|
191
|
-
register={register}
|
|
188
|
+
register={args.register}
|
|
192
189
|
/>
|
|
193
190
|
);
|
|
194
191
|
};
|
|
195
192
|
Multiline.args = {};
|
|
196
193
|
|
|
197
|
-
export const MultilineDisabled: StoryObj<typeof TextField> = () => {
|
|
198
|
-
const { register } = useForm<FieldValues>();
|
|
199
|
-
|
|
194
|
+
export const MultilineDisabled: StoryObj<typeof TextField> = (args: Args) => {
|
|
200
195
|
return (
|
|
201
196
|
<TextField
|
|
202
197
|
multirow
|
|
@@ -205,16 +200,14 @@ export const MultilineDisabled: StoryObj<typeof TextField> = () => {
|
|
|
205
200
|
placeholder="Textarea"
|
|
206
201
|
name="textarea"
|
|
207
202
|
helperText="some nice text"
|
|
208
|
-
register={register}
|
|
203
|
+
register={args.register}
|
|
209
204
|
/>
|
|
210
205
|
);
|
|
211
206
|
};
|
|
212
207
|
MultilineDisabled.args = {};
|
|
213
208
|
|
|
214
209
|
export const Focused: StoryObj<typeof TextField> = (args: Args) => {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
return <TextField {...args} register={register} />;
|
|
210
|
+
return <TextField {...args} />;
|
|
218
211
|
};
|
|
219
212
|
Focused.args = {
|
|
220
213
|
...Basic.args,
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
|
+
import { FieldValues, UseFormReturn } from 'react-hook-form';
|
|
2
3
|
import { UseTypeaheadResult } from './useTypeahead';
|
|
3
4
|
|
|
4
5
|
export const TypeaheadContext = React.createContext<UseTypeaheadResult>({
|
|
@@ -23,6 +24,7 @@ export const TypeaheadContext = React.createContext<UseTypeaheadResult>({
|
|
|
23
24
|
isDisabled: false,
|
|
24
25
|
options: [],
|
|
25
26
|
placeholder: '',
|
|
27
|
+
useFormResult: {} as UseFormReturn<FieldValues>,
|
|
26
28
|
setValue: () => {
|
|
27
29
|
/* no-op */
|
|
28
30
|
},
|
|
@@ -492,15 +492,18 @@ describe('Typeahead', () => {
|
|
|
492
492
|
|
|
493
493
|
it('Error should be displayed', () => {
|
|
494
494
|
const selectedIDs = selectedItems.map((item) => item.id);
|
|
495
|
-
|
|
495
|
+
|
|
496
|
+
const additionalProps = {
|
|
496
497
|
initialSelectedItems: selectedIDs,
|
|
497
498
|
isMultiple: true,
|
|
498
499
|
label: 'Label',
|
|
499
|
-
|
|
500
|
+
error: {
|
|
501
|
+
type: 'required',
|
|
500
502
|
message: 'Error message',
|
|
501
503
|
},
|
|
502
|
-
}
|
|
504
|
+
};
|
|
503
505
|
|
|
506
|
+
const { getByTestId } = setup(additionalProps);
|
|
504
507
|
expect(getByTestId('helper-text')).toBeInTheDocument();
|
|
505
508
|
});
|
|
506
509
|
});
|
|
@@ -189,7 +189,7 @@ export const WithError: StoryObj = (args: TypeaheadProps) => {
|
|
|
189
189
|
validationSchema={{
|
|
190
190
|
required: 'Required',
|
|
191
191
|
}}
|
|
192
|
-
|
|
192
|
+
error={mockError}
|
|
193
193
|
renderOption={({ label, input }) => highlightInputMatch(label, input)}>
|
|
194
194
|
{items.map(({ label, value, id }) => (
|
|
195
195
|
<TypeaheadOption key={id} value={id} label={label || value}>
|
|
@@ -32,7 +32,7 @@ export const Typeahead = ({
|
|
|
32
32
|
className,
|
|
33
33
|
startIcon,
|
|
34
34
|
endIcon,
|
|
35
|
-
|
|
35
|
+
error,
|
|
36
36
|
success,
|
|
37
37
|
helperText,
|
|
38
38
|
validationSchema,
|
|
@@ -40,6 +40,8 @@ export const Typeahead = ({
|
|
|
40
40
|
startIconClassName,
|
|
41
41
|
endIconClassName,
|
|
42
42
|
optionsClassName,
|
|
43
|
+
wrapperClassName,
|
|
44
|
+
width = 300,
|
|
43
45
|
setValue,
|
|
44
46
|
register,
|
|
45
47
|
onChange,
|
|
@@ -58,7 +60,7 @@ export const Typeahead = ({
|
|
|
58
60
|
endIcon,
|
|
59
61
|
startIconClassName,
|
|
60
62
|
endIconClassName,
|
|
61
|
-
|
|
63
|
+
error,
|
|
62
64
|
success,
|
|
63
65
|
validationSchema,
|
|
64
66
|
placeholder,
|
|
@@ -74,7 +76,9 @@ export const Typeahead = ({
|
|
|
74
76
|
css={{
|
|
75
77
|
flexDirection: 'column',
|
|
76
78
|
alignItems: 'flex-start',
|
|
79
|
+
width,
|
|
77
80
|
}}
|
|
81
|
+
className={wrapperClassName}
|
|
78
82
|
data-testid="typeahead">
|
|
79
83
|
{label && (
|
|
80
84
|
<Label
|
|
@@ -94,6 +98,7 @@ export const Typeahead = ({
|
|
|
94
98
|
css={{
|
|
95
99
|
width: hookResult.triggerRef.current?.clientWidth,
|
|
96
100
|
boxShadow: `-4px 4px 14px 0px ${theme.colors.greyDarker14}`,
|
|
101
|
+
zIndex: 100,
|
|
97
102
|
}}
|
|
98
103
|
isFocusManagerDisabled>
|
|
99
104
|
<PopoverDescription css={{ width: '100%' }}>
|
|
@@ -105,13 +110,13 @@ export const Typeahead = ({
|
|
|
105
110
|
</PopoverDescription>
|
|
106
111
|
</PopoverContent>
|
|
107
112
|
</Popover>
|
|
108
|
-
{(
|
|
113
|
+
{(hookResult.status === 'error' || helperText) && (
|
|
109
114
|
<FormHelperText
|
|
110
115
|
role="status"
|
|
111
116
|
status={hookResult.status}
|
|
112
117
|
disabled={isDisabled}
|
|
113
118
|
data-testid="helper-text">
|
|
114
|
-
{
|
|
119
|
+
{error ? error?.message : helperText}
|
|
115
120
|
</FormHelperText>
|
|
116
121
|
)}
|
|
117
122
|
</Wrapper>
|
|
@@ -69,7 +69,7 @@ export const MultipleTrigger = () => {
|
|
|
69
69
|
onChange: context.handleInputChange,
|
|
70
70
|
value: context.inputValue,
|
|
71
71
|
autoComplete: 'off',
|
|
72
|
-
className: ['typeahead-input', S.TypeaheadInput].join(' '),
|
|
72
|
+
className: ['typeahead-input', S.TypeaheadInput(theme)].join(' '),
|
|
73
73
|
}}
|
|
74
74
|
wrapperClassName={S.TypeaheadInputWrapper}
|
|
75
75
|
ref={context.inputRef}
|
|
@@ -84,7 +84,7 @@ export const MultipleTrigger = () => {
|
|
|
84
84
|
disabled={context.isDisabled}
|
|
85
85
|
className={[
|
|
86
86
|
'typeahead-input',
|
|
87
|
-
S.TypeaheadInput,
|
|
87
|
+
S.TypeaheadInput(theme),
|
|
88
88
|
S.TypeaheadInputPlaceholder,
|
|
89
89
|
].join(' ')}
|
|
90
90
|
{...typeaheadInputAdditionalProps}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { InputHTMLAttributes } from 'react';
|
|
2
|
+
import { useTheme } from '@emotion/react';
|
|
2
3
|
import Input from '@components/Input';
|
|
3
4
|
import Button from '@components/Button';
|
|
4
5
|
import Icon from '@components/Icon';
|
|
@@ -7,6 +8,7 @@ import * as S from '../styles';
|
|
|
7
8
|
|
|
8
9
|
export const SingleTrigger = () => {
|
|
9
10
|
const context = useTypeaheadContext();
|
|
11
|
+
const theme = useTheme();
|
|
10
12
|
const typeaheadInputAdditionalProps: InputHTMLAttributes<HTMLInputElement> =
|
|
11
13
|
{};
|
|
12
14
|
if (!context.selectedItems.length && !!context.placeholder) {
|
|
@@ -26,7 +28,7 @@ export const SingleTrigger = () => {
|
|
|
26
28
|
onChange: context.handleInputChange,
|
|
27
29
|
value: context.inputValue,
|
|
28
30
|
autoComplete: 'off',
|
|
29
|
-
className: ['typeahead-input', S.TypeaheadInput].join(' '),
|
|
31
|
+
className: ['typeahead-input', S.TypeaheadInput(theme)].join(' '),
|
|
30
32
|
}}
|
|
31
33
|
wrapperClassName={S.TypeaheadInputWrapper}
|
|
32
34
|
ref={context.inputRef}
|
|
@@ -40,7 +42,7 @@ export const SingleTrigger = () => {
|
|
|
40
42
|
value={context.firstSuggestion}
|
|
41
43
|
className={[
|
|
42
44
|
'typeahead-input',
|
|
43
|
-
S.TypeaheadInput,
|
|
45
|
+
S.TypeaheadInput(theme),
|
|
44
46
|
S.TypeaheadInputPlaceholder,
|
|
45
47
|
].join(' ')}
|
|
46
48
|
{...typeaheadInputAdditionalProps}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Theme } from '@emotion/react';
|
|
1
2
|
import { css } from '@emotion/css';
|
|
2
3
|
import styled from '@emotion/styled';
|
|
3
4
|
import Wrapper from '@components/Wrapper';
|
|
@@ -35,8 +36,9 @@ export const TypeaheadOption = styled.li<TypeaheadItemProps>`
|
|
|
35
36
|
}
|
|
36
37
|
`;
|
|
37
38
|
|
|
38
|
-
export const TypeaheadInput = css`
|
|
39
|
+
export const TypeaheadInput = (theme: Theme) => css`
|
|
39
40
|
&.typeahead-input {
|
|
41
|
+
color: ${theme.colors.greyDarker};
|
|
40
42
|
border: none;
|
|
41
43
|
border-radius: 0;
|
|
42
44
|
height: 32px;
|
|
@@ -148,7 +150,7 @@ export const TypeaheadTrigger = styled(PopoverTrigger)<{
|
|
|
148
150
|
background: #fff;
|
|
149
151
|
gap: 8px;
|
|
150
152
|
padding: 5px 28px 5px 8px;
|
|
151
|
-
width:
|
|
153
|
+
width: 100%;
|
|
152
154
|
flex-wrap: wrap;
|
|
153
155
|
border-color: ${({ isOpen, theme, status }) =>
|
|
154
156
|
isOpen &&
|
|
@@ -17,6 +17,8 @@ export interface TypeaheadProps {
|
|
|
17
17
|
children?: React.ReactNode;
|
|
18
18
|
className?: string;
|
|
19
19
|
optionsClassName?: string;
|
|
20
|
+
wrapperClassName?: string;
|
|
21
|
+
width?: string | number;
|
|
20
22
|
isOpen?: boolean;
|
|
21
23
|
startIcon?: React.ReactNode;
|
|
22
24
|
endIcon?: React.ReactNode;
|
|
@@ -25,7 +27,7 @@ export interface TypeaheadProps {
|
|
|
25
27
|
name?: string;
|
|
26
28
|
label?: string;
|
|
27
29
|
helperText?: string;
|
|
28
|
-
|
|
30
|
+
error?: FieldError;
|
|
29
31
|
success?: boolean;
|
|
30
32
|
validationSchema?: Record<string, unknown>;
|
|
31
33
|
placeholder?: string | null;
|
|
@@ -57,7 +59,7 @@ export type UseTypeaheadProps = Pick<
|
|
|
57
59
|
| 'register'
|
|
58
60
|
| 'setValue'
|
|
59
61
|
| 'validationSchema'
|
|
60
|
-
| '
|
|
62
|
+
| 'error'
|
|
61
63
|
| 'success'
|
|
62
64
|
| 'placeholder'
|
|
63
65
|
>;
|
|
@@ -6,6 +6,7 @@ import React, {
|
|
|
6
6
|
useRef,
|
|
7
7
|
useState,
|
|
8
8
|
} from 'react';
|
|
9
|
+
import { useForm } from 'react-hook-form';
|
|
9
10
|
import { propOr } from '@ssa-ui-kit/utils';
|
|
10
11
|
import { TypeaheadOptionProps, UseTypeaheadProps } from './types';
|
|
11
12
|
|
|
@@ -22,7 +23,7 @@ export const useTypeahead = ({
|
|
|
22
23
|
startIconClassName,
|
|
23
24
|
endIconClassName,
|
|
24
25
|
validationSchema,
|
|
25
|
-
|
|
26
|
+
error,
|
|
26
27
|
success,
|
|
27
28
|
placeholder,
|
|
28
29
|
register,
|
|
@@ -41,12 +42,13 @@ export const useTypeahead = ({
|
|
|
41
42
|
const [items, setItems] = useState<Array<React.ReactElement> | undefined>();
|
|
42
43
|
const [inputValue, setInputValue] = useState<string>('');
|
|
43
44
|
const [status, setStatus] = useState<'basic' | 'success' | 'error'>('basic');
|
|
45
|
+
const [firstSuggestion, setFirstSuggestion] = useState('');
|
|
44
46
|
|
|
45
47
|
const inputRef = useRef<HTMLInputElement>(null);
|
|
46
48
|
const typeaheadId = useId();
|
|
47
49
|
const triggerRef: React.MutableRefObject<HTMLDivElement | null> =
|
|
48
50
|
useRef<HTMLDivElement>(null);
|
|
49
|
-
const
|
|
51
|
+
const useFormResult = useForm();
|
|
50
52
|
|
|
51
53
|
useEffect(() => {
|
|
52
54
|
if (!register) {
|
|
@@ -71,9 +73,21 @@ export const useTypeahead = ({
|
|
|
71
73
|
}, [isDisabled]);
|
|
72
74
|
|
|
73
75
|
useEffect(() => {
|
|
74
|
-
const status = success
|
|
76
|
+
const status = success
|
|
77
|
+
? 'success'
|
|
78
|
+
: useFormResult.formState.errors[name]
|
|
79
|
+
? 'error'
|
|
80
|
+
: 'basic';
|
|
75
81
|
setStatus(status);
|
|
76
|
-
}, [errors, success]);
|
|
82
|
+
}, [useFormResult.formState.errors[name], success]);
|
|
83
|
+
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
if (error) {
|
|
86
|
+
useFormResult.setError(name, error);
|
|
87
|
+
} else {
|
|
88
|
+
useFormResult.resetField(name);
|
|
89
|
+
}
|
|
90
|
+
}, [error]);
|
|
77
91
|
|
|
78
92
|
useEffect(() => {
|
|
79
93
|
const keyedOptions: Record<
|
|
@@ -201,6 +215,8 @@ export const useTypeahead = ({
|
|
|
201
215
|
setIsOpen(false);
|
|
202
216
|
setFirstSuggestion('');
|
|
203
217
|
inputRef.current?.focus();
|
|
218
|
+
setStatus('basic');
|
|
219
|
+
useFormResult.clearErrors();
|
|
204
220
|
onChange && onChange(changingValue, isNewSelected);
|
|
205
221
|
};
|
|
206
222
|
|
|
@@ -305,6 +321,7 @@ export const useTypeahead = ({
|
|
|
305
321
|
status,
|
|
306
322
|
placeholder,
|
|
307
323
|
options: items,
|
|
324
|
+
useFormResult,
|
|
308
325
|
register,
|
|
309
326
|
setValue,
|
|
310
327
|
handleChange,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
+
import { useTheme } from '@emotion/react';
|
|
1
2
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
-
import Avatar from '@components/Avatar';
|
|
3
3
|
import { UserProfile } from './UserProfile';
|
|
4
|
+
import Icon from '@components/Icon';
|
|
4
5
|
|
|
5
6
|
export default {
|
|
6
7
|
title: 'Widgets/UserProfile',
|
|
@@ -8,11 +9,12 @@ export default {
|
|
|
8
9
|
} as Meta<typeof UserProfile>;
|
|
9
10
|
|
|
10
11
|
export const Default: StoryObj<typeof UserProfile> = () => {
|
|
12
|
+
const theme = useTheme();
|
|
11
13
|
return (
|
|
12
14
|
<UserProfile
|
|
13
15
|
name="Josh Li"
|
|
14
16
|
email="Josh@gmail.com"
|
|
15
|
-
trigger={<
|
|
17
|
+
trigger={<Icon size={42} name="user" color={theme.colors.grey} />}
|
|
16
18
|
onClick={() => alert('Clicked!')}
|
|
17
19
|
/>
|
|
18
20
|
);
|