uikit-react-public 0.49.4 → 0.49.6
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/Overlay/Overlay.d.ts +2 -2
- package/dist/components/Overlay/Overlay.stories.d.ts +13 -1
- package/dist/components/Select/index.d.ts +1 -1
- package/dist/components/Select/subcomponents/Panel.d.ts +1 -2
- package/dist/components/ToggleGroup/ToggleGroup.d.ts +15 -0
- package/dist/components/ToggleGroup/ToggleGroup.stories.d.ts +18 -0
- package/dist/components/ToggleGroup/ToggleGroupContext.d.ts +8 -0
- package/dist/components/ToggleGroup/__tests__/ToggleGroup.test.d.ts +1 -0
- package/dist/components/ToggleGroup/index.d.ts +4 -0
- package/dist/components/ToggleGroup/subcomponents/Item.d.ts +11 -0
- package/dist/components/ToggleGroup/subcomponents/Item.stories.d.ts +331 -0
- package/dist/components/ToggleGroup/subcomponents/__tests__/Item.test.d.ts +1 -0
- package/dist/components/index.d.ts +2 -0
- package/dist/index.js +8351 -8121
- package/lib/components/Icon/svgImports.ts +4 -2
- package/lib/components/Overlay/Overlay.tsx +9 -3
- package/lib/components/Select/Select.mdx +1 -0
- package/lib/components/Select/__tests__/Select.test.tsx +137 -4
- package/lib/components/Select/index.ts +5 -1
- package/lib/components/Select/subcomponents/CustomSelect.tsx +42 -43
- package/lib/components/Select/subcomponents/Panel.tsx +2 -8
- package/lib/components/ToggleGroup/ToggleGroup.mdx +31 -0
- package/lib/components/ToggleGroup/ToggleGroup.stories.tsx +120 -0
- package/lib/components/ToggleGroup/ToggleGroup.tsx +144 -0
- package/lib/components/ToggleGroup/ToggleGroupContext.tsx +25 -0
- package/lib/components/ToggleGroup/__tests__/ToggleGroup.test.tsx +468 -0
- package/lib/components/ToggleGroup/index.ts +4 -0
- package/lib/components/ToggleGroup/subcomponents/Item.stories.tsx +63 -0
- package/lib/components/ToggleGroup/subcomponents/Item.tsx +233 -0
- package/lib/components/ToggleGroup/subcomponents/__tests__/Item.test.tsx +195 -0
- package/lib/components/index.ts +3 -0
- package/package.json +3 -3
- package/dist/components/Icon/svgImports.d.ts +0 -8
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
import type { InputHTMLAttributes } from 'react';
|
|
2
|
+
import { css, cx } from '@emotion/css';
|
|
3
|
+
|
|
4
|
+
import useTheme from '../../../theme/useTheme';
|
|
5
|
+
import Text from '../../Text';
|
|
6
|
+
import Icon from '../../Icon';
|
|
7
|
+
import type { SpecificIconsType } from '../../Icon/Icon';
|
|
8
|
+
import { useToggleGroupContext } from '../ToggleGroupContext';
|
|
9
|
+
|
|
10
|
+
export interface ItemProps extends InputHTMLAttributes<HTMLInputElement> {
|
|
11
|
+
value: string;
|
|
12
|
+
label: string;
|
|
13
|
+
icon?: keyof SpecificIconsType;
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
sublabel?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const Item = ({
|
|
19
|
+
value,
|
|
20
|
+
label,
|
|
21
|
+
sublabel,
|
|
22
|
+
icon,
|
|
23
|
+
disabled = false,
|
|
24
|
+
}: ItemProps) => {
|
|
25
|
+
const [theme] = useTheme();
|
|
26
|
+
const { value: selectedValue, setValue, name } = useToggleGroupContext();
|
|
27
|
+
const selected = selectedValue === value;
|
|
28
|
+
|
|
29
|
+
const toggleGroupItemContainerStyle = css`
|
|
30
|
+
box-sizing: border-box;
|
|
31
|
+
position: relative;
|
|
32
|
+
display: flex;
|
|
33
|
+
flex: 1 0 auto;
|
|
34
|
+
height: ${theme.height.h40};
|
|
35
|
+
padding: ${theme.padding.p8};
|
|
36
|
+
align-items: center;
|
|
37
|
+
justify-content: center;
|
|
38
|
+
border-radius: ${theme.radius.r4};
|
|
39
|
+
cursor: ${disabled ? 'not-allowed' : 'pointer'};
|
|
40
|
+
transition:
|
|
41
|
+
background-color 150ms ease-in-out,
|
|
42
|
+
box-shadow 150ms ease-in-out;
|
|
43
|
+
|
|
44
|
+
background-color: ${
|
|
45
|
+
disabled
|
|
46
|
+
? theme.colour.fill.disabled
|
|
47
|
+
: selected
|
|
48
|
+
? theme.colour.fill.default
|
|
49
|
+
: theme.colour.fill.subtle
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
${
|
|
53
|
+
!disabled &&
|
|
54
|
+
`
|
|
55
|
+
:hover {
|
|
56
|
+
background-color: ${theme.colour.fill.brandSubtle};
|
|
57
|
+
}
|
|
58
|
+
`
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
&:has(input:focus-visible) {
|
|
62
|
+
box-shadow: ${theme.boxShadow.focus};
|
|
63
|
+
z-index: 1;
|
|
64
|
+
}
|
|
65
|
+
`;
|
|
66
|
+
|
|
67
|
+
const toggleGroupItemInputStyle = css`
|
|
68
|
+
position: absolute;
|
|
69
|
+
inset: 0;
|
|
70
|
+
width: 100%;
|
|
71
|
+
height: 100%;
|
|
72
|
+
margin: 0;
|
|
73
|
+
padding: 0;
|
|
74
|
+
border: 0;
|
|
75
|
+
opacity: 0;
|
|
76
|
+
cursor: inherit;
|
|
77
|
+
`;
|
|
78
|
+
|
|
79
|
+
const flexRowStyle = css`
|
|
80
|
+
display: flex;
|
|
81
|
+
align-items: center;
|
|
82
|
+
gap: ${theme.padding.p8};
|
|
83
|
+
`;
|
|
84
|
+
|
|
85
|
+
const toggleGroupItemSizerStyle = cx(
|
|
86
|
+
flexRowStyle,
|
|
87
|
+
css`
|
|
88
|
+
visibility: hidden;
|
|
89
|
+
`
|
|
90
|
+
);
|
|
91
|
+
|
|
92
|
+
const toggleGroupItemContentStyle = cx(
|
|
93
|
+
flexRowStyle,
|
|
94
|
+
css`
|
|
95
|
+
box-sizing: border-box;
|
|
96
|
+
position: absolute;
|
|
97
|
+
inset: 0;
|
|
98
|
+
justify-content: ${sublabel && icon ? 'space-between' : 'center'};
|
|
99
|
+
padding: ${theme.padding.p8};
|
|
100
|
+
`
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
const toggleGroupItemLabelBaseStyle = css`
|
|
104
|
+
text-align: ${sublabel && icon ? 'left' : 'center'};
|
|
105
|
+
`;
|
|
106
|
+
|
|
107
|
+
const toggleGroupItemLabelSelectedStyle = css`
|
|
108
|
+
color: ${theme.colour.text.brand};
|
|
109
|
+
font-weight: ${theme.typography.body.smSemibold.fontWeight};
|
|
110
|
+
`;
|
|
111
|
+
|
|
112
|
+
const toggleGroupItemLabelDisabledStyle = css`
|
|
113
|
+
color: ${theme.colour.text.disabled};
|
|
114
|
+
`;
|
|
115
|
+
|
|
116
|
+
const toggleGroupItemLabelStyle = cx(
|
|
117
|
+
toggleGroupItemLabelBaseStyle,
|
|
118
|
+
selected && !disabled && toggleGroupItemLabelSelectedStyle,
|
|
119
|
+
disabled && toggleGroupItemLabelDisabledStyle
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
const toggleGroupItemIconBaseStyle = css`
|
|
123
|
+
display: flex;
|
|
124
|
+
align-items: center;
|
|
125
|
+
color: ${theme.colour.icon.default};
|
|
126
|
+
`;
|
|
127
|
+
|
|
128
|
+
const toggleGroupItemIconSelectedStyle = css`
|
|
129
|
+
color: ${theme.colour.icon.brand};
|
|
130
|
+
`;
|
|
131
|
+
|
|
132
|
+
const toggleGroupItemIconDisabledStyle = css`
|
|
133
|
+
color: ${theme.colour.icon.disabled};
|
|
134
|
+
`;
|
|
135
|
+
|
|
136
|
+
const toggleGroupItemIconStyle = cx(
|
|
137
|
+
toggleGroupItemIconBaseStyle,
|
|
138
|
+
selected && !disabled && toggleGroupItemIconSelectedStyle,
|
|
139
|
+
disabled && toggleGroupItemIconDisabledStyle
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
const toggleGroupItemTextStyle = css`
|
|
143
|
+
display: flex;
|
|
144
|
+
flex-direction: column;
|
|
145
|
+
`;
|
|
146
|
+
|
|
147
|
+
const toggleGroupItemSublabelBaseStyle = css`
|
|
148
|
+
color: ${theme.colour.text.secondary};
|
|
149
|
+
`;
|
|
150
|
+
|
|
151
|
+
const toggleGroupItemSublabelDisabledStyle = css`
|
|
152
|
+
color: ${theme.colour.text.disabled};
|
|
153
|
+
`;
|
|
154
|
+
|
|
155
|
+
const toggleGroupItemSublabelStyle = cx(
|
|
156
|
+
toggleGroupItemSublabelBaseStyle,
|
|
157
|
+
disabled && toggleGroupItemSublabelDisabledStyle
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
const toggleGroupItemLabelGroupStyle = flexRowStyle;
|
|
161
|
+
|
|
162
|
+
const toggleGroupItemCheckIconStyle = css`
|
|
163
|
+
color: ${theme.colour.icon.brand};
|
|
164
|
+
`;
|
|
165
|
+
|
|
166
|
+
const IconComponent = icon ? Icon[icon] : undefined;
|
|
167
|
+
|
|
168
|
+
const labelContent = (
|
|
169
|
+
<div className={toggleGroupItemLabelGroupStyle}>
|
|
170
|
+
{IconComponent && (
|
|
171
|
+
<span className={toggleGroupItemIconStyle}>
|
|
172
|
+
<IconComponent size={16} />
|
|
173
|
+
</span>
|
|
174
|
+
)}
|
|
175
|
+
<div className={toggleGroupItemTextStyle}>
|
|
176
|
+
<Text
|
|
177
|
+
level='sm'
|
|
178
|
+
className={toggleGroupItemLabelStyle}
|
|
179
|
+
>
|
|
180
|
+
{label}
|
|
181
|
+
</Text>
|
|
182
|
+
{sublabel && (
|
|
183
|
+
<Text
|
|
184
|
+
level='xs'
|
|
185
|
+
className={toggleGroupItemSublabelStyle}
|
|
186
|
+
>
|
|
187
|
+
{sublabel}
|
|
188
|
+
</Text>
|
|
189
|
+
)}
|
|
190
|
+
</div>
|
|
191
|
+
</div>
|
|
192
|
+
);
|
|
193
|
+
|
|
194
|
+
return (
|
|
195
|
+
<label className={toggleGroupItemContainerStyle}>
|
|
196
|
+
<input
|
|
197
|
+
type='radio'
|
|
198
|
+
className={toggleGroupItemInputStyle}
|
|
199
|
+
role='radio'
|
|
200
|
+
aria-checked={selected}
|
|
201
|
+
checked={selected}
|
|
202
|
+
disabled={disabled}
|
|
203
|
+
name={name}
|
|
204
|
+
value={value}
|
|
205
|
+
tabIndex={selected ? 0 : -1}
|
|
206
|
+
data-ucl-toggle-group-value={value}
|
|
207
|
+
onChange={() => {
|
|
208
|
+
if (disabled) return;
|
|
209
|
+
setValue(value);
|
|
210
|
+
}}
|
|
211
|
+
/>
|
|
212
|
+
<div
|
|
213
|
+
aria-hidden
|
|
214
|
+
className={toggleGroupItemSizerStyle}
|
|
215
|
+
>
|
|
216
|
+
{labelContent}
|
|
217
|
+
<Icon.Check size={16} />
|
|
218
|
+
</div>
|
|
219
|
+
<div className={toggleGroupItemContentStyle}>
|
|
220
|
+
{labelContent}
|
|
221
|
+
{selected && (
|
|
222
|
+
<Icon.Check
|
|
223
|
+
aria-hidden
|
|
224
|
+
className={toggleGroupItemCheckIconStyle}
|
|
225
|
+
size={16}
|
|
226
|
+
/>
|
|
227
|
+
)}
|
|
228
|
+
</div>
|
|
229
|
+
</label>
|
|
230
|
+
);
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
export default Item;
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import { describe, expect, test, vi } from 'vitest';
|
|
2
|
+
import { fireEvent, render, screen } from '@testing-library/react';
|
|
3
|
+
import ToggleGroup from '../../ToggleGroup';
|
|
4
|
+
import ToggleGroupItem from '../Item';
|
|
5
|
+
import { ThemeContextProvider } from '../../../../theme/useTheme';
|
|
6
|
+
|
|
7
|
+
const wrap = (ui: React.ReactElement) =>
|
|
8
|
+
render(<ThemeContextProvider>{ui}</ThemeContextProvider>);
|
|
9
|
+
|
|
10
|
+
describe('ToggleGroupItem', () => {
|
|
11
|
+
test('renders as an unchecked radio by default', () => {
|
|
12
|
+
wrap(
|
|
13
|
+
<ToggleGroup>
|
|
14
|
+
<ToggleGroupItem
|
|
15
|
+
value='option-1'
|
|
16
|
+
label='Option 1'
|
|
17
|
+
/>
|
|
18
|
+
</ToggleGroup>
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
const item = screen.getByRole('radio', { name: 'Option 1' });
|
|
22
|
+
|
|
23
|
+
expect(item).toHaveAttribute('aria-checked', 'false');
|
|
24
|
+
expect(item).toHaveAttribute('tabindex', '-1');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
test('reflects selection state from the surrounding ToggleGroup', () => {
|
|
28
|
+
wrap(
|
|
29
|
+
<ToggleGroup defaultValue='option-1'>
|
|
30
|
+
<ToggleGroupItem
|
|
31
|
+
value='option-1'
|
|
32
|
+
label='Option 1'
|
|
33
|
+
/>
|
|
34
|
+
<ToggleGroupItem
|
|
35
|
+
value='option-2'
|
|
36
|
+
label='Option 2'
|
|
37
|
+
/>
|
|
38
|
+
</ToggleGroup>
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
expect(screen.getByRole('radio', { name: 'Option 1' })).toHaveAttribute(
|
|
42
|
+
'aria-checked',
|
|
43
|
+
'true'
|
|
44
|
+
);
|
|
45
|
+
expect(screen.getByRole('radio', { name: 'Option 1' })).toHaveAttribute(
|
|
46
|
+
'tabindex',
|
|
47
|
+
'0'
|
|
48
|
+
);
|
|
49
|
+
expect(screen.getByRole('radio', { name: 'Option 2' })).toHaveAttribute(
|
|
50
|
+
'tabindex',
|
|
51
|
+
'-1'
|
|
52
|
+
);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('calls setValue via the ToggleGroup on click', () => {
|
|
56
|
+
const onValueChange = vi.fn();
|
|
57
|
+
|
|
58
|
+
wrap(
|
|
59
|
+
<ToggleGroup
|
|
60
|
+
defaultValue='option-1'
|
|
61
|
+
onValueChange={onValueChange}
|
|
62
|
+
>
|
|
63
|
+
<ToggleGroupItem
|
|
64
|
+
value='option-1'
|
|
65
|
+
label='Option 1'
|
|
66
|
+
/>
|
|
67
|
+
<ToggleGroupItem
|
|
68
|
+
value='option-2'
|
|
69
|
+
label='Option 2'
|
|
70
|
+
/>
|
|
71
|
+
</ToggleGroup>
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
fireEvent.click(screen.getByRole('radio', { name: 'Option 2' }));
|
|
75
|
+
|
|
76
|
+
expect(onValueChange).toHaveBeenCalledWith('option-2');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test('does not select or fire onValueChange when disabled', () => {
|
|
80
|
+
const onValueChange = vi.fn();
|
|
81
|
+
|
|
82
|
+
wrap(
|
|
83
|
+
<ToggleGroup
|
|
84
|
+
defaultValue='option-1'
|
|
85
|
+
onValueChange={onValueChange}
|
|
86
|
+
>
|
|
87
|
+
<ToggleGroupItem
|
|
88
|
+
value='option-1'
|
|
89
|
+
label='Option 1'
|
|
90
|
+
/>
|
|
91
|
+
<ToggleGroupItem
|
|
92
|
+
value='option-2'
|
|
93
|
+
label='Option 2'
|
|
94
|
+
disabled
|
|
95
|
+
/>
|
|
96
|
+
</ToggleGroup>
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const disabledItem = screen.getByRole('radio', { name: 'Option 2' });
|
|
100
|
+
|
|
101
|
+
expect(disabledItem).toBeDisabled();
|
|
102
|
+
|
|
103
|
+
fireEvent.click(disabledItem);
|
|
104
|
+
|
|
105
|
+
expect(onValueChange).not.toHaveBeenCalled();
|
|
106
|
+
expect(disabledItem).toHaveAttribute('aria-checked', 'false');
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
test('throws when rendered outside a ToggleGroup', () => {
|
|
110
|
+
const consoleError = vi
|
|
111
|
+
.spyOn(console, 'error')
|
|
112
|
+
.mockImplementation(() => {});
|
|
113
|
+
|
|
114
|
+
expect(() =>
|
|
115
|
+
render(
|
|
116
|
+
<ThemeContextProvider>
|
|
117
|
+
<ToggleGroupItem
|
|
118
|
+
value='option-1'
|
|
119
|
+
label='Option 1'
|
|
120
|
+
/>
|
|
121
|
+
</ThemeContextProvider>
|
|
122
|
+
)
|
|
123
|
+
).toThrow('ToggleGroupItem must be used within a ToggleGroup component');
|
|
124
|
+
|
|
125
|
+
consoleError.mockRestore();
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
test('renders the specified icon next to the label', () => {
|
|
129
|
+
wrap(
|
|
130
|
+
<ToggleGroup defaultValue='option-1'>
|
|
131
|
+
<ToggleGroupItem
|
|
132
|
+
value='option-1'
|
|
133
|
+
label='Option 1'
|
|
134
|
+
icon='BookOpen'
|
|
135
|
+
/>
|
|
136
|
+
<ToggleGroupItem
|
|
137
|
+
value='option-2'
|
|
138
|
+
label='Option 2'
|
|
139
|
+
/>
|
|
140
|
+
</ToggleGroup>
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
const withIcon = screen
|
|
144
|
+
.getByRole('radio', { name: 'Option 1' })
|
|
145
|
+
.closest('label');
|
|
146
|
+
const withoutIcon = screen
|
|
147
|
+
.getByRole('radio', { name: 'Option 2' })
|
|
148
|
+
.closest('label');
|
|
149
|
+
|
|
150
|
+
expect(withIcon!.querySelectorAll('svg').length).toBeGreaterThan(
|
|
151
|
+
withoutIcon!.querySelectorAll('svg').length
|
|
152
|
+
);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
test('includes the sublabel in the accessible name', () => {
|
|
156
|
+
wrap(
|
|
157
|
+
<ToggleGroup defaultValue='option-1'>
|
|
158
|
+
<ToggleGroupItem
|
|
159
|
+
value='option-1'
|
|
160
|
+
label='Option 1'
|
|
161
|
+
sublabel='Sublabel 1'
|
|
162
|
+
/>
|
|
163
|
+
</ToggleGroup>
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
expect(
|
|
167
|
+
screen.getByRole('radio', { name: 'Option 1 Sublabel 1' })
|
|
168
|
+
).toBeInTheDocument();
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
test('only shows a visible checkmark once selected, without changing when it is reserved', () => {
|
|
172
|
+
wrap(
|
|
173
|
+
<ToggleGroup defaultValue='option-1'>
|
|
174
|
+
<ToggleGroupItem
|
|
175
|
+
value='option-1'
|
|
176
|
+
label='Option 1'
|
|
177
|
+
/>
|
|
178
|
+
<ToggleGroupItem
|
|
179
|
+
value='option-2'
|
|
180
|
+
label='Option 2'
|
|
181
|
+
/>
|
|
182
|
+
</ToggleGroup>
|
|
183
|
+
);
|
|
184
|
+
|
|
185
|
+
const selected = screen
|
|
186
|
+
.getByRole('radio', { name: 'Option 1' })
|
|
187
|
+
.closest('label');
|
|
188
|
+
const unselected = screen
|
|
189
|
+
.getByRole('radio', { name: 'Option 2' })
|
|
190
|
+
.closest('label');
|
|
191
|
+
|
|
192
|
+
expect(selected!.querySelectorAll('svg').length).toBe(2);
|
|
193
|
+
expect(unselected!.querySelectorAll('svg').length).toBe(1);
|
|
194
|
+
});
|
|
195
|
+
});
|
package/lib/components/index.ts
CHANGED
|
@@ -133,6 +133,9 @@ export type { CheckboxProps, LabelledCheckboxProps } from './Checkbox';
|
|
|
133
133
|
export { default as Toggle } from './Toggle';
|
|
134
134
|
export type { ToggleProps } from './Toggle';
|
|
135
135
|
|
|
136
|
+
export { default as ToggleGroup } from './ToggleGroup';
|
|
137
|
+
export type { ToggleGroupProps, ItemProps } from './ToggleGroup';
|
|
138
|
+
|
|
136
139
|
export { default as Chip } from './Chip';
|
|
137
140
|
export type { ChipProps } from './Chip';
|
|
138
141
|
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "uikit-react-public",
|
|
3
3
|
"private": false,
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
|
-
"version": "0.49.
|
|
5
|
+
"version": "0.49.6",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"types": "dist/index.d.ts",
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"@typescript-eslint/parser": "^8.26.1",
|
|
70
70
|
"@vitejs/plugin-basic-ssl": "^2.0.0",
|
|
71
71
|
"@vitejs/plugin-react": "^4.3.4",
|
|
72
|
-
"@vitest/coverage-v8": "^4.1.
|
|
72
|
+
"@vitest/coverage-v8": "^4.1.11",
|
|
73
73
|
"eslint": "^9.22.0",
|
|
74
74
|
"eslint-plugin-babel": "^5.3.1",
|
|
75
75
|
"eslint-plugin-ft-flow": "^3.0.11",
|
|
@@ -94,7 +94,7 @@
|
|
|
94
94
|
"typescript-eslint": "^8.26.1",
|
|
95
95
|
"vite": "^6.2.1",
|
|
96
96
|
"vite-plugin-dts": "^4.5.4",
|
|
97
|
-
"vitest": "^4.1.
|
|
97
|
+
"vitest": "^4.1.11",
|
|
98
98
|
"wouter": "^3.6.0"
|
|
99
99
|
}
|
|
100
100
|
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { ReactNode, SVGProps } from 'react';
|
|
2
|
-
interface SVGRProps {
|
|
3
|
-
title?: string;
|
|
4
|
-
titleId?: string;
|
|
5
|
-
}
|
|
6
|
-
type IconComponent = (props: SVGProps<SVGSVGElement> & SVGRProps) => ReactNode;
|
|
7
|
-
declare const iconSvgs: Record<string, IconComponent>;
|
|
8
|
-
export default iconSvgs;
|