@qoretechnologies/reqore 0.28.5 → 0.29.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/.vscode/settings.json +2 -1
- package/__tests__/multiselect.test.tsx +361 -0
- package/__tests__/popover.test.tsx +35 -8
- package/dist/components/Button/index.js +3 -3
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/Checkbox/index.d.ts +3 -2
- package/dist/components/Checkbox/index.d.ts.map +1 -1
- package/dist/components/Checkbox/index.js +28 -24
- package/dist/components/Checkbox/index.js.map +1 -1
- package/dist/components/Collection/item.js +2 -2
- package/dist/components/Collection/item.js.map +1 -1
- package/dist/components/ControlGroup/index.d.ts +4 -4
- package/dist/components/ControlGroup/index.d.ts.map +1 -1
- package/dist/components/ControlGroup/index.js +13 -15
- package/dist/components/ControlGroup/index.js.map +1 -1
- package/dist/components/Dropdown/index.d.ts +2 -1
- package/dist/components/Dropdown/index.d.ts.map +1 -1
- package/dist/components/Dropdown/index.js +3 -3
- package/dist/components/Dropdown/index.js.map +1 -1
- package/dist/components/Dropdown/list.d.ts +6 -3
- package/dist/components/Dropdown/list.d.ts.map +1 -1
- package/dist/components/Dropdown/list.js +19 -1
- package/dist/components/Dropdown/list.js.map +1 -1
- package/dist/components/Effect/index.d.ts +3 -1
- package/dist/components/Effect/index.d.ts.map +1 -1
- package/dist/components/Effect/index.js +24 -19
- package/dist/components/Effect/index.js.map +1 -1
- package/dist/components/Icon/index.d.ts +12 -2
- package/dist/components/Icon/index.d.ts.map +1 -1
- package/dist/components/Icon/index.js +35 -4
- package/dist/components/Icon/index.js.map +1 -1
- package/dist/components/Input/index.js +3 -3
- package/dist/components/Input/index.js.map +1 -1
- package/dist/components/InputClearButton/index.d.ts.map +1 -1
- package/dist/components/InputClearButton/index.js +1 -1
- package/dist/components/InputClearButton/index.js.map +1 -1
- package/dist/components/InternalPopover/index.d.ts.map +1 -1
- package/dist/components/InternalPopover/index.js +31 -37
- package/dist/components/InternalPopover/index.js.map +1 -1
- package/dist/components/Menu/divider.d.ts +5 -2
- package/dist/components/Menu/divider.d.ts.map +1 -1
- package/dist/components/Menu/divider.js +41 -8
- package/dist/components/Menu/divider.js.map +1 -1
- package/dist/components/Menu/index.js +4 -3
- package/dist/components/Menu/index.js.map +1 -1
- package/dist/components/Message/index.d.ts +3 -2
- package/dist/components/Message/index.d.ts.map +1 -1
- package/dist/components/Message/index.js.map +1 -1
- package/dist/components/MultiSelect/index.d.ts +32 -0
- package/dist/components/MultiSelect/index.d.ts.map +1 -0
- package/dist/components/MultiSelect/index.js +177 -0
- package/dist/components/MultiSelect/index.js.map +1 -0
- package/dist/components/Notifications/notification.d.ts +3 -3
- package/dist/components/Notifications/notification.d.ts.map +1 -1
- package/dist/components/Notifications/notification.js +11 -8
- package/dist/components/Notifications/notification.js.map +1 -1
- package/dist/components/Panel/index.d.ts +1 -0
- package/dist/components/Panel/index.d.ts.map +1 -1
- package/dist/components/Panel/index.js +7 -7
- package/dist/components/Panel/index.js.map +1 -1
- package/dist/components/Popover/index.d.ts +1 -1
- package/dist/components/Popover/index.d.ts.map +1 -1
- package/dist/components/Popover/index.js +5 -2
- package/dist/components/Popover/index.js.map +1 -1
- package/dist/components/RadioGroup/index.d.ts +8 -6
- package/dist/components/RadioGroup/index.d.ts.map +1 -1
- package/dist/components/RadioGroup/index.js +6 -12
- package/dist/components/RadioGroup/index.js.map +1 -1
- package/dist/components/Table/row.js +2 -2
- package/dist/components/Table/row.js.map +1 -1
- package/dist/components/Tabs/item.js +1 -1
- package/dist/components/Tabs/item.js.map +1 -1
- package/dist/components/Tabs/list.d.ts.map +1 -1
- package/dist/components/Tabs/list.js +5 -4
- package/dist/components/Tabs/list.js.map +1 -1
- package/dist/components/Tag/group.d.ts +4 -3
- package/dist/components/Tag/group.d.ts.map +1 -1
- package/dist/components/Tag/group.js +12 -5
- package/dist/components/Tag/group.js.map +1 -1
- package/dist/components/Tag/index.js +5 -5
- package/dist/components/Tag/index.js.map +1 -1
- package/dist/components/Tree/index.js +1 -1
- package/dist/components/Tree/index.js.map +1 -1
- package/dist/constants/sizes.d.ts +7 -0
- package/dist/constants/sizes.d.ts.map +1 -1
- package/dist/constants/sizes.js +8 -1
- package/dist/constants/sizes.js.map +1 -1
- package/dist/containers/PopoverProvider.d.ts.map +1 -1
- package/dist/containers/PopoverProvider.js +28 -3
- package/dist/containers/PopoverProvider.js.map +1 -1
- package/dist/containers/ReqoreProvider.d.ts.map +1 -1
- package/dist/containers/ReqoreProvider.js +6 -5
- package/dist/containers/ReqoreProvider.js.map +1 -1
- package/dist/containers/UIProvider.d.ts +1 -0
- package/dist/containers/UIProvider.d.ts.map +1 -1
- package/dist/containers/UIProvider.js.map +1 -1
- package/dist/context/PopoverContext.d.ts +1 -0
- package/dist/context/PopoverContext.d.ts.map +1 -1
- package/dist/context/PopoverContext.js.map +1 -1
- package/dist/context/ReqoreContext.d.ts +1 -0
- package/dist/context/ReqoreContext.d.ts.map +1 -1
- package/dist/context/ReqoreContext.js +2 -1
- package/dist/context/ReqoreContext.js.map +1 -1
- package/dist/helpers/colors.d.ts +3 -0
- package/dist/helpers/colors.d.ts.map +1 -1
- package/dist/helpers/colors.js +28 -5
- package/dist/helpers/colors.js.map +1 -1
- package/dist/hooks/usePopover.d.ts +14 -3
- package/dist/hooks/usePopover.d.ts.map +1 -1
- package/dist/hooks/usePopover.js +12 -7
- package/dist/hooks/usePopover.js.map +1 -1
- package/dist/hooks/useReqore.d.ts +3 -0
- package/dist/hooks/useReqore.d.ts.map +1 -0
- package/dist/hooks/useReqore.js +17 -0
- package/dist/hooks/useReqore.js.map +1 -0
- package/dist/hooks/useTheme.d.ts +1 -1
- package/dist/hooks/useTheme.d.ts.map +1 -1
- package/dist/hooks/useTheme.js +3 -0
- package/dist/hooks/useTheme.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Button/index.tsx +3 -3
- package/src/components/Checkbox/index.tsx +58 -30
- package/src/components/Collection/item.tsx +2 -2
- package/src/components/ControlGroup/index.tsx +54 -37
- package/src/components/Dropdown/index.tsx +7 -2
- package/src/components/Dropdown/list.tsx +29 -15
- package/src/components/Effect/index.tsx +58 -51
- package/src/components/Icon/index.tsx +75 -1
- package/src/components/Input/index.tsx +3 -3
- package/src/components/InputClearButton/index.tsx +1 -0
- package/src/components/InternalPopover/index.tsx +108 -50
- package/src/components/Menu/divider.tsx +35 -7
- package/src/components/Menu/index.tsx +3 -3
- package/src/components/Message/index.tsx +3 -0
- package/src/components/MultiSelect/index.tsx +283 -0
- package/src/components/Notifications/notification.tsx +23 -13
- package/src/components/Panel/index.tsx +14 -8
- package/src/components/Popover/index.tsx +8 -3
- package/src/components/RadioGroup/index.tsx +36 -27
- package/src/components/Table/row.tsx +2 -2
- package/src/components/Tabs/item.tsx +1 -1
- package/src/components/Tabs/list.tsx +11 -11
- package/src/components/Tag/group.tsx +15 -4
- package/src/components/Tag/index.tsx +7 -7
- package/src/components/Tree/index.tsx +3 -3
- package/src/constants/sizes.ts +8 -0
- package/src/containers/PopoverProvider.tsx +35 -3
- package/src/containers/ReqoreProvider.tsx +6 -4
- package/src/containers/UIProvider.tsx +1 -0
- package/src/context/PopoverContext.tsx +1 -0
- package/src/context/ReqoreContext.tsx +2 -0
- package/src/helpers/colors.ts +53 -7
- package/src/hooks/usePopover.tsx +39 -12
- package/src/hooks/useReqore.ts +12 -0
- package/src/hooks/useTheme.ts +6 -1
- package/src/index.tsx +3 -0
- package/src/mock/multiSelect.ts +61 -0
- package/src/stories/Button/Button.stories.tsx +20 -8
- package/src/stories/ControlGroup/ControlGroup.stories.tsx +13 -2
- package/src/stories/Dropdown/Dropdown.stories.tsx +6 -1
- package/src/stories/Icon/Icon.stories.tsx +99 -22
- package/src/stories/Input/Input.stories.tsx +25 -0
- package/src/stories/Menu/Menu.stories.tsx +3 -2
- package/src/stories/Message/Message.stories.tsx +7 -1
- package/src/stories/MultiSelect/MultiSelect.stories.tsx +99 -0
- package/src/stories/Panel/Panel.stories.tsx +3 -3
- package/src/stories/Popover/Popover.stories.tsx +91 -12
- package/src/stories/RadioGroup/RadioGroup.stories.tsx +29 -2
- package/src/stories/Tabs/Tabs.stories.tsx +23 -3
- package/src/stories/Tag/Tag.stories.tsx +12 -3
- package/src/stories/utils/args.ts +13 -0
- package/tests.json +1 -1
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { size } from 'lodash';
|
|
2
|
+
import { forwardRef, memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
+
import { useUpdateEffect } from 'react-use';
|
|
4
|
+
import { ReqoreDropdown, ReqoreInput } from '../..';
|
|
5
|
+
import { TSizes } from '../../constants/sizes';
|
|
6
|
+
import { IPopoverControls } from '../../hooks/usePopover';
|
|
7
|
+
import ReqoreControlGroup, { IReqoreControlGroupProps } from '../ControlGroup';
|
|
8
|
+
import { IReqoreDropdownProps } from '../Dropdown';
|
|
9
|
+
import { IReqoreDropdownItem } from '../Dropdown/list';
|
|
10
|
+
import { IReqoreEffect } from '../Effect';
|
|
11
|
+
import { IReqoreInputProps } from '../Input';
|
|
12
|
+
import ReqoreTag, { IReqoreTagProps } from '../Tag';
|
|
13
|
+
import ReqoreTagGroup from '../Tag/group';
|
|
14
|
+
|
|
15
|
+
export type TReqoreMultiSelectItem = Omit<IReqoreDropdownItem, 'color'> &
|
|
16
|
+
Pick<IReqoreTagProps, 'badge'> & { isNew?: boolean };
|
|
17
|
+
|
|
18
|
+
export interface IReqoreMultiSelectProps
|
|
19
|
+
extends Omit<IReqoreControlGroupProps, 'children' | 'vertical' | 'stack'> {
|
|
20
|
+
value?: string[];
|
|
21
|
+
onValueChange?: (value: string[]) => void;
|
|
22
|
+
items?: TReqoreMultiSelectItem[];
|
|
23
|
+
onItemClick?: (item: IReqoreDropdownItem) => void;
|
|
24
|
+
canRemoveItems?: boolean;
|
|
25
|
+
canCreateItems?: boolean;
|
|
26
|
+
selectedItemEffect?: IReqoreEffect;
|
|
27
|
+
selectedItemSize?: TSizes;
|
|
28
|
+
selectorProps?: Omit<IReqoreInputProps, 'value' | 'onValueChange'> & IReqoreDropdownProps;
|
|
29
|
+
openOnMount?: IReqoreDropdownProps['openOnMount'];
|
|
30
|
+
enterKeySelects?: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface IReqoreMultiSelectItemProps
|
|
34
|
+
extends Pick<IReqoreMultiSelectProps, 'selectedItemEffect' | 'selectedItemSize'> {
|
|
35
|
+
item: TReqoreMultiSelectItem;
|
|
36
|
+
onClick?: () => void;
|
|
37
|
+
onRemoveClick?: () => void;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export const ReqoreMultiSelectItem = memo(
|
|
41
|
+
({
|
|
42
|
+
item,
|
|
43
|
+
onRemoveClick,
|
|
44
|
+
onClick,
|
|
45
|
+
selectedItemEffect,
|
|
46
|
+
selectedItemSize,
|
|
47
|
+
}: IReqoreMultiSelectItemProps) => {
|
|
48
|
+
if (!item) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return (
|
|
53
|
+
<ReqoreTag
|
|
54
|
+
{...item}
|
|
55
|
+
label={item.label || item.value}
|
|
56
|
+
onRemoveClick={onRemoveClick}
|
|
57
|
+
intent={item.intent}
|
|
58
|
+
effect={!item.intent ? item.effect || selectedItemEffect : undefined}
|
|
59
|
+
size={selectedItemSize}
|
|
60
|
+
onClick={onClick}
|
|
61
|
+
/>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
export const ReqoreMultiSelect = forwardRef<HTMLDivElement, IReqoreMultiSelectProps>(
|
|
67
|
+
(
|
|
68
|
+
{
|
|
69
|
+
value,
|
|
70
|
+
onValueChange,
|
|
71
|
+
onItemClick,
|
|
72
|
+
canRemoveItems,
|
|
73
|
+
canCreateItems,
|
|
74
|
+
items = [],
|
|
75
|
+
selectedItemEffect,
|
|
76
|
+
selectedItemSize,
|
|
77
|
+
selectorProps,
|
|
78
|
+
openOnMount,
|
|
79
|
+
enterKeySelects,
|
|
80
|
+
...rest
|
|
81
|
+
}: IReqoreMultiSelectProps,
|
|
82
|
+
ref
|
|
83
|
+
) => {
|
|
84
|
+
const [_value, setValue] = useState<string[]>(value || []);
|
|
85
|
+
const [createdItems, setCreatedItems] = useState<TReqoreMultiSelectItem[]>([]);
|
|
86
|
+
const [query, setQuery] = useState<string>('');
|
|
87
|
+
const popoverData = useRef<IPopoverControls>(undefined);
|
|
88
|
+
|
|
89
|
+
useUpdateEffect(() => {
|
|
90
|
+
onValueChange?.(_value);
|
|
91
|
+
}, [_value]);
|
|
92
|
+
|
|
93
|
+
useEffect(() => {
|
|
94
|
+
setValue(value || []);
|
|
95
|
+
}, [value]);
|
|
96
|
+
|
|
97
|
+
useEffect(() => {
|
|
98
|
+
if (query && !popoverData.current?.isOpen()) {
|
|
99
|
+
popoverData.current?.open();
|
|
100
|
+
}
|
|
101
|
+
}, [query]);
|
|
102
|
+
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
if (enterKeySelects) {
|
|
105
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
return () => {
|
|
109
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
110
|
+
};
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
const addRemoveItem = useCallback(
|
|
114
|
+
(item: TReqoreMultiSelectItem): void => {
|
|
115
|
+
if (_value.includes(item.value)) {
|
|
116
|
+
setValue(_value.filter((v) => v !== item.value));
|
|
117
|
+
} else {
|
|
118
|
+
setValue([..._value, item.value]);
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
[_value, value]
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
const handleItemSelect = useCallback(
|
|
125
|
+
(item: Partial<TReqoreMultiSelectItem>) => {
|
|
126
|
+
addRemoveItem(item);
|
|
127
|
+
|
|
128
|
+
if (item.isNew) {
|
|
129
|
+
setCreatedItems([
|
|
130
|
+
...createdItems,
|
|
131
|
+
{
|
|
132
|
+
value: item.value,
|
|
133
|
+
},
|
|
134
|
+
]);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
setQuery('');
|
|
138
|
+
},
|
|
139
|
+
[createdItems, _value]
|
|
140
|
+
);
|
|
141
|
+
|
|
142
|
+
/*
|
|
143
|
+
This code creates a list of all items that are available
|
|
144
|
+
for selection in the dropdown. It will include the items
|
|
145
|
+
that are passed in as props, as well as any items that the
|
|
146
|
+
user has created.
|
|
147
|
+
*/
|
|
148
|
+
const allItems: TReqoreMultiSelectItem[] = useMemo(() => {
|
|
149
|
+
const customItems: TReqoreMultiSelectItem[] = size(createdItems)
|
|
150
|
+
? [{ divider: true, label: 'Custom Items' }, ...createdItems]
|
|
151
|
+
: [];
|
|
152
|
+
|
|
153
|
+
let filteredItems: TReqoreMultiSelectItem[] = [...items, ...customItems].filter((item) =>
|
|
154
|
+
query
|
|
155
|
+
? item.divider
|
|
156
|
+
? false
|
|
157
|
+
: (item.label || item.value)?.toString().toLowerCase().indexOf(query.toLowerCase()) !==
|
|
158
|
+
-1
|
|
159
|
+
: true
|
|
160
|
+
);
|
|
161
|
+
|
|
162
|
+
// Mark selected items as selected
|
|
163
|
+
filteredItems = filteredItems.map((item: TReqoreMultiSelectItem) => ({
|
|
164
|
+
...item,
|
|
165
|
+
selected: _value.includes(item.value),
|
|
166
|
+
}));
|
|
167
|
+
|
|
168
|
+
if (query && !size(filteredItems)) {
|
|
169
|
+
filteredItems = [
|
|
170
|
+
{ label: 'No existing items found', readOnly: true, minimal: true, icon: 'ForbidLine' },
|
|
171
|
+
];
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// If there is a query and there are filtered items
|
|
175
|
+
// and there is no item that exactly matches the query, add it to the list
|
|
176
|
+
if (
|
|
177
|
+
query &&
|
|
178
|
+
!filteredItems.some((item: TReqoreMultiSelectItem) => item.value === query) &&
|
|
179
|
+
canCreateItems
|
|
180
|
+
) {
|
|
181
|
+
filteredItems = [
|
|
182
|
+
{
|
|
183
|
+
label: `Create new "${query}"`,
|
|
184
|
+
value: query,
|
|
185
|
+
isNew: true,
|
|
186
|
+
icon: 'AddCircleLine',
|
|
187
|
+
minimal: true,
|
|
188
|
+
flat: false,
|
|
189
|
+
effect: {
|
|
190
|
+
gradient: {
|
|
191
|
+
colors: {
|
|
192
|
+
0: 'success',
|
|
193
|
+
100: 'success:darken:1',
|
|
194
|
+
},
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
{ divider: true, label: 'Items matching your query' },
|
|
199
|
+
...filteredItems,
|
|
200
|
+
];
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return filteredItems;
|
|
204
|
+
}, [items, createdItems, query, _value]);
|
|
205
|
+
|
|
206
|
+
const handleKeyDown = useCallback(
|
|
207
|
+
(e: KeyboardEvent) => {
|
|
208
|
+
if (e.key === 'Enter') {
|
|
209
|
+
const item = [...items, ...createdItems].find((item) => item.value === query);
|
|
210
|
+
|
|
211
|
+
if (item) {
|
|
212
|
+
handleItemSelect(item);
|
|
213
|
+
} else if (canCreateItems) {
|
|
214
|
+
handleItemSelect({
|
|
215
|
+
value: query,
|
|
216
|
+
isNew: true,
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
[items, createdItems, query, canCreateItems]
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
const getItemByValue = useCallback(
|
|
225
|
+
(value: string): TReqoreMultiSelectItem => {
|
|
226
|
+
return [...items, ...createdItems].find((item) => item.value === value);
|
|
227
|
+
},
|
|
228
|
+
[items, createdItems, _value]
|
|
229
|
+
);
|
|
230
|
+
|
|
231
|
+
return (
|
|
232
|
+
<ReqoreControlGroup vertical fluid {...rest} ref={ref}>
|
|
233
|
+
<ReqoreTagGroup minimal={rest.minimal} size={rest.size}>
|
|
234
|
+
{size(_value) ? (
|
|
235
|
+
_value.map((v) => (
|
|
236
|
+
<ReqoreMultiSelectItem
|
|
237
|
+
key={v}
|
|
238
|
+
item={getItemByValue(v)}
|
|
239
|
+
onRemoveClick={canRemoveItems ? () => addRemoveItem(getItemByValue(v)) : undefined}
|
|
240
|
+
onClick={
|
|
241
|
+
onItemClick
|
|
242
|
+
? () => {
|
|
243
|
+
onItemClick(getItemByValue(v));
|
|
244
|
+
}
|
|
245
|
+
: undefined
|
|
246
|
+
}
|
|
247
|
+
selectedItemEffect={selectedItemEffect}
|
|
248
|
+
selectedItemSize={selectedItemSize}
|
|
249
|
+
/>
|
|
250
|
+
))
|
|
251
|
+
) : (
|
|
252
|
+
<ReqoreTag color='transparent' icon='ForbidLine' label='No items selected' />
|
|
253
|
+
)}
|
|
254
|
+
</ReqoreTagGroup>
|
|
255
|
+
<ReqoreControlGroup minimal={rest.minimal} flat={rest.flat} size={rest.size}>
|
|
256
|
+
<ReqoreDropdown<IReqoreInputProps>
|
|
257
|
+
{...selectorProps}
|
|
258
|
+
multiSelect
|
|
259
|
+
handler='focus'
|
|
260
|
+
passPopoverData={(data) => (popoverData.current = data)}
|
|
261
|
+
component={ReqoreInput}
|
|
262
|
+
onClearClick={() => setQuery('')}
|
|
263
|
+
value={query}
|
|
264
|
+
isDefaultOpen={openOnMount}
|
|
265
|
+
onItemSelect={handleItemSelect}
|
|
266
|
+
placeholder={
|
|
267
|
+
canCreateItems ? 'Type to search or create an item...' : 'Type to search...'
|
|
268
|
+
}
|
|
269
|
+
onChange={(e: any) => setQuery(e.target.value)}
|
|
270
|
+
items={
|
|
271
|
+
size(allItems)
|
|
272
|
+
? allItems
|
|
273
|
+
: canCreateItems
|
|
274
|
+
? [{ label: 'No items exist', readOnly: true, minimal: true, icon: 'ForbidLine' }]
|
|
275
|
+
: []
|
|
276
|
+
}
|
|
277
|
+
useTargetWidth
|
|
278
|
+
/>
|
|
279
|
+
</ReqoreControlGroup>
|
|
280
|
+
</ReqoreControlGroup>
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
);
|
|
@@ -15,7 +15,7 @@ import { IReqoreTheme, TReqoreIntent } from '../../constants/theme';
|
|
|
15
15
|
import ReqoreThemeProvider from '../../containers/ThemeProvider';
|
|
16
16
|
import { fadeIn } from '../../helpers/animations';
|
|
17
17
|
import { changeLightness, getNotificationIntent, getReadableColor } from '../../helpers/colors';
|
|
18
|
-
import { IWithReqoreEffect, IWithReqoreMinimal } from '../../types/global';
|
|
18
|
+
import { IWithReqoreEffect, IWithReqoreMinimal, IWithReqoreOpaque } from '../../types/global';
|
|
19
19
|
import { IReqoreIconName } from '../../types/icons';
|
|
20
20
|
import { StyledEffect } from '../Effect';
|
|
21
21
|
import { ReqoreHeading } from '../Header';
|
|
@@ -23,7 +23,10 @@ import ReqoreIcon from '../Icon';
|
|
|
23
23
|
|
|
24
24
|
export type IReqoreNotificationType = TReqoreIntent;
|
|
25
25
|
|
|
26
|
-
export interface IReqoreNotificationProps
|
|
26
|
+
export interface IReqoreNotificationProps
|
|
27
|
+
extends IWithReqoreEffect,
|
|
28
|
+
IWithReqoreMinimal,
|
|
29
|
+
IWithReqoreOpaque {
|
|
27
30
|
type?: IReqoreNotificationType;
|
|
28
31
|
intent?: TReqoreIntent;
|
|
29
32
|
title?: string;
|
|
@@ -38,7 +41,7 @@ export interface IReqoreNotificationProps extends IWithReqoreEffect, IWithReqore
|
|
|
38
41
|
size?: TSizes;
|
|
39
42
|
}
|
|
40
43
|
|
|
41
|
-
export interface IReqoreNotificationStyle {
|
|
44
|
+
export interface IReqoreNotificationStyle extends IWithReqoreOpaque {
|
|
42
45
|
theme: IReqoreTheme;
|
|
43
46
|
type?: IReqoreNotificationType;
|
|
44
47
|
clickable?: boolean;
|
|
@@ -73,12 +76,14 @@ export const StyledReqoreNotification = styled(StyledEffect)<IReqoreNotification
|
|
|
73
76
|
transition: all 0.2s ease-out;
|
|
74
77
|
|
|
75
78
|
// Do not fade in the component if it's a message
|
|
76
|
-
${({ asMessage }) =>
|
|
77
|
-
asMessage
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
${({ asMessage }) => {
|
|
80
|
+
if (asMessage) {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
return css`
|
|
84
|
+
animation: 0.2s ${fadeIn} ease-in;
|
|
85
|
+
`;
|
|
86
|
+
}}
|
|
82
87
|
|
|
83
88
|
&:not(:first-child) {
|
|
84
89
|
margin-top: ${({ asMessage }) => (asMessage ? undefined : `10px`)};
|
|
@@ -93,12 +98,15 @@ export const StyledReqoreNotification = styled(StyledEffect)<IReqoreNotification
|
|
|
93
98
|
hasShadow,
|
|
94
99
|
flat,
|
|
95
100
|
minimal,
|
|
101
|
+
opaque,
|
|
96
102
|
}: IReqoreNotificationStyle) => css`
|
|
97
103
|
background-color: ${minimal
|
|
98
104
|
? 'transparent'
|
|
105
|
+
: opaque
|
|
106
|
+
? changeLightness(theme.main, 0.1)
|
|
99
107
|
: rgba(getNotificationIntent(theme, intent || type), 0.3)};
|
|
100
108
|
border: ${flat ? 0 : '1px solid'};
|
|
101
|
-
border-color: ${getNotificationIntent(theme, intent || type)};
|
|
109
|
+
border-color: ${changeLightness(getNotificationIntent(theme, intent || type), 0.2)};
|
|
102
110
|
|
|
103
111
|
${hasShadow &&
|
|
104
112
|
css`
|
|
@@ -113,13 +121,13 @@ export const StyledReqoreNotification = styled(StyledEffect)<IReqoreNotification
|
|
|
113
121
|
display: block;
|
|
114
122
|
top: 0;
|
|
115
123
|
height: 3px;
|
|
116
|
-
background-color: ${changeLightness(getNotificationIntent(theme, intent || type), 0.
|
|
124
|
+
background-color: ${changeLightness(getNotificationIntent(theme, intent || type), 0.2)};
|
|
117
125
|
animation-name: ${timeoutAnimation};
|
|
118
126
|
animation-duration: ${timeout}ms;
|
|
119
127
|
}
|
|
120
128
|
`}
|
|
121
129
|
|
|
122
|
-
color: ${getReadableColor(theme, null, null, true, theme.originalMain)};
|
|
130
|
+
color: ${getReadableColor(theme, null, null, true, !opaque ? theme.originalMain : undefined)};
|
|
123
131
|
|
|
124
132
|
${clickable &&
|
|
125
133
|
css`
|
|
@@ -129,7 +137,7 @@ export const StyledReqoreNotification = styled(StyledEffect)<IReqoreNotification
|
|
|
129
137
|
getNotificationIntent(theme, intent || type),
|
|
130
138
|
minimal ? 0.2 : 0.5
|
|
131
139
|
)};
|
|
132
|
-
border-color: ${changeLightness(getNotificationIntent(theme, intent || type), 0.
|
|
140
|
+
border-color: ${changeLightness(getNotificationIntent(theme, intent || type), 0.25)};
|
|
133
141
|
}
|
|
134
142
|
`}
|
|
135
143
|
`}
|
|
@@ -218,6 +226,7 @@ const ReqoreNotification = forwardRef<HTMLDivElement, IReqoreNotificationProps>(
|
|
|
218
226
|
onFinish,
|
|
219
227
|
flat,
|
|
220
228
|
minimal,
|
|
229
|
+
opaque,
|
|
221
230
|
size = 'normal',
|
|
222
231
|
},
|
|
223
232
|
ref: any
|
|
@@ -273,6 +282,7 @@ const ReqoreNotification = forwardRef<HTMLDivElement, IReqoreNotificationProps>(
|
|
|
273
282
|
ref={ref}
|
|
274
283
|
style={styles}
|
|
275
284
|
size={size}
|
|
285
|
+
opaque={opaque}
|
|
276
286
|
>
|
|
277
287
|
{type || intent || icon ? (
|
|
278
288
|
<StyledIconWrapper type={type || intent} size={size}>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { size } from 'lodash';
|
|
2
2
|
import { darken, rgba } from 'polished';
|
|
3
|
-
import {
|
|
3
|
+
import { forwardRef, ReactElement, useCallback, useMemo, useState } from 'react';
|
|
4
4
|
import { useUpdateEffect } from 'react-use';
|
|
5
5
|
import styled, { css } from 'styled-components';
|
|
6
6
|
import {
|
|
@@ -86,6 +86,7 @@ export interface IReqorePanelProps
|
|
|
86
86
|
contentSize?: TSizes;
|
|
87
87
|
contentEffect?: IReqoreEffect;
|
|
88
88
|
headerEffect?: IReqoreEffect;
|
|
89
|
+
transparent?: boolean;
|
|
89
90
|
}
|
|
90
91
|
|
|
91
92
|
export interface IStyledPanel extends IReqorePanelProps {
|
|
@@ -133,7 +134,7 @@ export const StyledPanel = styled(StyledEffect)<IStyledPanel>`
|
|
|
133
134
|
: `${rgba(
|
|
134
135
|
changeLightness(
|
|
135
136
|
intent ? theme.intents[intent] : getMainBackgroundColor(theme),
|
|
136
|
-
0.
|
|
137
|
+
0.25
|
|
137
138
|
),
|
|
138
139
|
opacity
|
|
139
140
|
)}`};
|
|
@@ -322,7 +323,9 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
322
323
|
(actionOrActions: IReqorePanelAction | IReqorePanelAction[], index: number) => {
|
|
323
324
|
if (Array.isArray(actionOrActions)) {
|
|
324
325
|
return (
|
|
325
|
-
<ReqoreControlGroup
|
|
326
|
+
<ReqoreControlGroup key={index} stack>
|
|
327
|
+
{actionOrActions.map(renderActions)}
|
|
328
|
+
</ReqoreControlGroup>
|
|
326
329
|
);
|
|
327
330
|
}
|
|
328
331
|
|
|
@@ -417,6 +420,8 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
417
420
|
return newContentEffect;
|
|
418
421
|
}, [intent, theme, contentEffect, interactive]);
|
|
419
422
|
|
|
423
|
+
const opacity = rest.transparent ? 0 : rest.opacity;
|
|
424
|
+
|
|
420
425
|
return (
|
|
421
426
|
<StyledPanel
|
|
422
427
|
{...rest}
|
|
@@ -430,6 +435,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
430
435
|
interactive={interactive}
|
|
431
436
|
theme={theme}
|
|
432
437
|
effect={transformedContentEffect}
|
|
438
|
+
opacity={opacity}
|
|
433
439
|
>
|
|
434
440
|
{hasTitleBar && (
|
|
435
441
|
<StyledPanelTitle
|
|
@@ -440,8 +446,8 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
440
446
|
onClick={handleCollapseClick}
|
|
441
447
|
theme={theme}
|
|
442
448
|
contentSize={contentSize}
|
|
443
|
-
opacity={
|
|
444
|
-
noHorizontalPadding={
|
|
449
|
+
opacity={opacity ?? (minimal ? 0 : 1)}
|
|
450
|
+
noHorizontalPadding={opacity === 0}
|
|
445
451
|
>
|
|
446
452
|
<StyledPanelTitleHeader>
|
|
447
453
|
{icon && (
|
|
@@ -509,7 +515,7 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
509
515
|
padded={padded}
|
|
510
516
|
minimal={minimal}
|
|
511
517
|
contentSize={contentSize}
|
|
512
|
-
noHorizontalPadding={
|
|
518
|
+
noHorizontalPadding={opacity === 0}
|
|
513
519
|
>
|
|
514
520
|
{children}
|
|
515
521
|
</StyledPanelContent>
|
|
@@ -519,8 +525,8 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
519
525
|
flat={flat}
|
|
520
526
|
className='reqore-panel-bottom-actions'
|
|
521
527
|
theme={theme}
|
|
522
|
-
opacity={
|
|
523
|
-
noHorizontalPadding={
|
|
528
|
+
opacity={opacity ?? (minimal ? 0 : 1)}
|
|
529
|
+
noHorizontalPadding={opacity === 0}
|
|
524
530
|
>
|
|
525
531
|
<ReqoreControlGroup>{leftBottomActions.map(renderActions)}</ReqoreControlGroup>
|
|
526
532
|
<ReqoreControlGroup>{rightBottomActions.map(renderActions)}</ReqoreControlGroup>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import React, { memo, useState } from 'react';
|
|
1
|
+
import React, { memo, useEffect, useState } from 'react';
|
|
2
2
|
import styled from 'styled-components';
|
|
3
|
-
import usePopover, { IPopoverOptions } from '../../hooks/usePopover';
|
|
3
|
+
import usePopover, { IPopoverControls, IPopoverOptions } from '../../hooks/usePopover';
|
|
4
4
|
import { IReqoreComponent } from '../../types/global';
|
|
5
5
|
|
|
6
6
|
export interface IReqorePopoverProps extends IReqoreComponent, IPopoverOptions {
|
|
@@ -26,13 +26,18 @@ const Popover = memo(
|
|
|
26
26
|
noWrapper,
|
|
27
27
|
wrapperTag = 'span',
|
|
28
28
|
wrapperStyle = {},
|
|
29
|
+
passPopoverData,
|
|
29
30
|
_insidePopover,
|
|
30
31
|
_popoverId,
|
|
31
32
|
...rest
|
|
32
33
|
}: IReqorePopoverProps) => {
|
|
33
34
|
const [ref, setRef] = useState(undefined);
|
|
34
35
|
|
|
35
|
-
usePopover({ targetElement: ref, ...rest });
|
|
36
|
+
const popoverData: IPopoverControls = usePopover({ targetElement: ref, ...rest });
|
|
37
|
+
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
passPopoverData?.(popoverData);
|
|
40
|
+
}, [popoverData]);
|
|
36
41
|
|
|
37
42
|
if (isReqoreComponent || noWrapper) {
|
|
38
43
|
return (
|
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import React from
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ReqoreCheckbox, ReqoreControlGroup } from '../..';
|
|
3
|
+
import { TSizes } from '../../constants/sizes';
|
|
4
|
+
import { IReqoreCheckboxProps } from '../Checkbox';
|
|
5
|
+
import { IReqoreControlGroupProps } from '../ControlGroup';
|
|
6
|
+
import ReqoreMenuDivider from '../Menu/divider';
|
|
6
7
|
|
|
7
8
|
export interface IReqoreRadioGroupItem extends IReqoreCheckboxProps {
|
|
8
|
-
value
|
|
9
|
+
value?: string;
|
|
10
|
+
divider?: boolean;
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
export interface IReqoreRadioGroupProps
|
|
12
|
-
extends
|
|
14
|
+
extends Omit<IReqoreControlGroupProps, 'children'>,
|
|
15
|
+
Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
13
16
|
items: IReqoreRadioGroupItem[];
|
|
14
17
|
selected?: string;
|
|
15
18
|
onSelectClick?: (value: string) => void;
|
|
@@ -18,11 +21,6 @@ export interface IReqoreRadioGroupProps
|
|
|
18
21
|
asSwitch?: boolean;
|
|
19
22
|
}
|
|
20
23
|
|
|
21
|
-
const StyledRadioGroup = styled.div`
|
|
22
|
-
display: flex;
|
|
23
|
-
flex-flow: column;
|
|
24
|
-
`;
|
|
25
|
-
|
|
26
24
|
const ReqoreRadioGroup = ({
|
|
27
25
|
items = [],
|
|
28
26
|
selected,
|
|
@@ -30,23 +28,34 @@ const ReqoreRadioGroup = ({
|
|
|
30
28
|
size,
|
|
31
29
|
disabled,
|
|
32
30
|
asSwitch,
|
|
31
|
+
vertical = true,
|
|
33
32
|
...rest
|
|
34
33
|
}: IReqoreRadioGroupProps) => (
|
|
35
|
-
<
|
|
36
|
-
{items.map(({ value, ...itemRest }) =>
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
34
|
+
<ReqoreControlGroup {...rest} vertical={vertical}>
|
|
35
|
+
{items.map(({ value, divider, ...itemRest }) =>
|
|
36
|
+
divider ? (
|
|
37
|
+
<ReqoreMenuDivider
|
|
38
|
+
{...itemRest}
|
|
39
|
+
size={size || itemRest.size}
|
|
40
|
+
effect={{ ...itemRest.effect, textAlign: 'left' }}
|
|
41
|
+
margin='left'
|
|
42
|
+
label={vertical ? itemRest.label : undefined}
|
|
43
|
+
/>
|
|
44
|
+
) : (
|
|
45
|
+
<ReqoreCheckbox
|
|
46
|
+
asSwitch={asSwitch}
|
|
47
|
+
{...itemRest}
|
|
48
|
+
key={value}
|
|
49
|
+
checked={value === selected}
|
|
50
|
+
size={size || itemRest.size}
|
|
51
|
+
disabled={disabled || itemRest.disabled}
|
|
52
|
+
onClick={() => {
|
|
53
|
+
onSelectClick(value);
|
|
54
|
+
}}
|
|
55
|
+
/>
|
|
56
|
+
)
|
|
57
|
+
)}
|
|
58
|
+
</ReqoreControlGroup>
|
|
50
59
|
);
|
|
51
60
|
|
|
52
61
|
export default ReqoreRadioGroup;
|
|
@@ -277,10 +277,10 @@ const ReqoreTableRow = ({
|
|
|
277
277
|
onClick: (e: React.MouseEvent<HTMLDivElement>) => {
|
|
278
278
|
if (onCellClick) {
|
|
279
279
|
e.stopPropagation();
|
|
280
|
-
onCellClick
|
|
280
|
+
onCellClick(data[index]);
|
|
281
281
|
} else if (onRowClick) {
|
|
282
282
|
e.stopPropagation();
|
|
283
|
-
onRowClick
|
|
283
|
+
onRowClick(data[index]);
|
|
284
284
|
} else if (selectable && data[index]._selectId) {
|
|
285
285
|
// Otherwise select the row if selectable
|
|
286
286
|
onSelectClick(data[index]._selectId);
|
|
@@ -35,7 +35,7 @@ export const StyledTabListItem = styled.div<IReqoreTabListItemStyle>`
|
|
|
35
35
|
position: relative;
|
|
36
36
|
align-items: center;
|
|
37
37
|
width: ${vertical ? `100%` : undefined};
|
|
38
|
-
padding: ${
|
|
38
|
+
padding: ${`${TABS_PADDING_TO_PX[size!]}px`};
|
|
39
39
|
padding-bottom: ${!vertical && 0};
|
|
40
40
|
padding-right: ${vertical && 0};
|
|
41
41
|
|
|
@@ -13,9 +13,14 @@ import {
|
|
|
13
13
|
} from '../../constants/sizes';
|
|
14
14
|
import { IReqoreBreadcrumbsTheme, IReqoreCustomTheme, IReqoreTheme } from '../../constants/theme';
|
|
15
15
|
import ReqoreThemeProvider from '../../containers/ThemeProvider';
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
changeLightness,
|
|
18
|
+
getColorFromMaybeString,
|
|
19
|
+
getNthGradientColor,
|
|
20
|
+
} from '../../helpers/colors';
|
|
17
21
|
import { calculateStringSizeInPixels } from '../../helpers/utils';
|
|
18
22
|
import { useReqoreTheme } from '../../hooks/useTheme';
|
|
23
|
+
import { TReqoreHexColor } from '../Effect';
|
|
19
24
|
import ReqoreMenu from '../Menu';
|
|
20
25
|
import ReqoreMenuItem, { IReqoreMenuItemProps } from '../Menu/item';
|
|
21
26
|
import { StyledPopover } from '../Popover';
|
|
@@ -159,23 +164,18 @@ const ReqoreTabsList = ({
|
|
|
159
164
|
intent,
|
|
160
165
|
...rest
|
|
161
166
|
}: IReqoreTabsListProps) => {
|
|
162
|
-
const [ref, { width
|
|
167
|
+
const [ref, { width }] = useMeasure();
|
|
163
168
|
const theme = useReqoreTheme('main', customTheme, intent);
|
|
164
169
|
const activeTabData = tabs.find((tab) => tab.id === activeTab);
|
|
165
|
-
const currentTabColor =
|
|
170
|
+
const currentTabColor: TReqoreHexColor =
|
|
166
171
|
activeTabIntent || activeTabData?.intent
|
|
167
172
|
? theme.intents[activeTabIntent || activeTabData.intent]
|
|
168
|
-
: activeTabData?.
|
|
173
|
+
: getNthGradientColor(theme, activeTabData?.effect?.gradient?.colors) ||
|
|
174
|
+
getColorFromMaybeString(theme, activeTabData?.customTheme?.main || theme.main);
|
|
169
175
|
|
|
170
176
|
const transformedItems = vertical
|
|
171
177
|
? tabs
|
|
172
|
-
: getTransformedItems(
|
|
173
|
-
tabs,
|
|
174
|
-
vertical ? height : _testWidth || width,
|
|
175
|
-
vertical ? 'height' : 'width',
|
|
176
|
-
activeTab,
|
|
177
|
-
size
|
|
178
|
-
);
|
|
178
|
+
: getTransformedItems(tabs, _testWidth || width, 'width', activeTab, size);
|
|
179
179
|
|
|
180
180
|
return (
|
|
181
181
|
<ReqoreThemeProvider theme={theme}>
|