@qoretechnologies/reqore 0.28.6 → 0.29.1
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__/checkbox.test.tsx +7 -12
- package/__tests__/multiselect.test.tsx +407 -0
- package/__tests__/popover.test.tsx +35 -8
- package/dist/components/Button/index.js +1 -1
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/Checkbox/index.d.ts +7 -2
- package/dist/components/Checkbox/index.d.ts.map +1 -1
- package/dist/components/Checkbox/index.js +60 -26
- 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 +3 -4
- package/dist/components/ControlGroup/index.d.ts.map +1 -1
- package/dist/components/ControlGroup/index.js +7 -9
- 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 +15 -2
- package/dist/components/Effect/index.d.ts.map +1 -1
- package/dist/components/Effect/index.js +60 -23
- package/dist/components/Effect/index.js.map +1 -1
- package/dist/components/Icon/index.d.ts +2 -9
- package/dist/components/Icon/index.d.ts.map +1 -1
- package/dist/components/Icon/index.js +4 -28
- 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 +19 -5
- package/dist/components/InternalPopover/index.js.map +1 -1
- package/dist/components/Menu/divider.d.ts +3 -2
- package/dist/components/Menu/divider.d.ts.map +1 -1
- package/dist/components/Menu/divider.js +2 -2
- 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/MultiSelect/index.d.ts +34 -0
- package/dist/components/MultiSelect/index.d.ts.map +1 -0
- package/dist/components/MultiSelect/index.js +178 -0
- package/dist/components/MultiSelect/index.js.map +1 -0
- package/dist/components/Panel/index.d.ts.map +1 -1
- package/dist/components/Panel/index.js +1 -1
- 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 +3 -1
- package/dist/components/RadioGroup/index.d.ts.map +1 -1
- package/dist/components/RadioGroup/index.js +2 -2
- 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 +3 -3
- package/dist/components/Tag/group.d.ts.map +1 -1
- package/dist/components/Tag/group.js +6 -3
- package/dist/components/Tag/group.js.map +1 -1
- package/dist/components/Tag/index.d.ts +1 -1
- package/dist/components/Tag/index.d.ts.map +1 -1
- package/dist/components/Tag/index.js +21 -18
- package/dist/components/Tag/index.js.map +1 -1
- package/dist/components/Textarea/index.js +3 -3
- package/dist/components/Textarea/index.js.map +1 -1
- package/dist/components/Tree/index.js +1 -1
- package/dist/components/Tree/index.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 +27 -3
- package/dist/helpers/colors.js.map +1 -1
- package/dist/hooks/usePopover.d.ts +8 -1
- 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 +1 -1
- package/src/components/Checkbox/index.tsx +189 -34
- package/src/components/Collection/item.tsx +2 -2
- package/src/components/ControlGroup/index.tsx +46 -35
- package/src/components/Dropdown/index.tsx +5 -0
- package/src/components/Dropdown/list.tsx +29 -15
- package/src/components/Effect/index.tsx +123 -55
- package/src/components/Icon/index.tsx +4 -52
- package/src/components/Input/index.tsx +3 -3
- package/src/components/InputClearButton/index.tsx +1 -0
- package/src/components/InternalPopover/index.tsx +6 -3
- package/src/components/Menu/divider.tsx +15 -4
- package/src/components/Menu/index.tsx +3 -3
- package/src/components/MultiSelect/index.tsx +292 -0
- package/src/components/Panel/index.tsx +6 -4
- package/src/components/Popover/index.tsx +8 -3
- package/src/components/RadioGroup/index.tsx +6 -0
- 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 +10 -2
- package/src/components/Tag/index.tsx +26 -20
- package/src/components/Textarea/index.tsx +3 -3
- package/src/components/Tree/index.tsx +3 -3
- 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 +52 -4
- package/src/hooks/usePopover.tsx +24 -10
- package/src/hooks/useReqore.ts +12 -0
- package/src/hooks/useTheme.ts +6 -1
- package/src/index.tsx +3 -0
- package/src/mock/collectionData.tsx +6 -6
- package/src/mock/multiSelect.ts +69 -0
- package/src/stories/Button/Button.stories.tsx +20 -8
- package/src/stories/Checkbox/Checkbox.stories.tsx +42 -7
- package/src/stories/ControlGroup/ControlGroup.stories.tsx +7 -2
- package/src/stories/Dropdown/Dropdown.stories.tsx +6 -1
- package/src/stories/Icon/Icon.stories.tsx +42 -12
- package/src/stories/Input/Input.stories.tsx +25 -0
- package/src/stories/Menu/Menu.stories.tsx +3 -1
- package/src/stories/MultiSelect/MultiSelect.stories.tsx +106 -0
- package/src/stories/Popover/Popover.stories.tsx +19 -2
- package/src/stories/RadioGroup/RadioGroup.stories.tsx +51 -1
- package/src/stories/Tabs/Tabs.stories.tsx +23 -3
- package/src/stories/Tag/Tag.stories.tsx +10 -3
- package/src/stories/utils/args.ts +1 -1
- package/tests.json +1 -1
|
@@ -7,11 +7,12 @@ import { IWithReqoreEffect, IWithReqoreSize } from '../../types/global';
|
|
|
7
7
|
import { IReqoreEffect, StyledTextEffect } from '../Effect';
|
|
8
8
|
|
|
9
9
|
export interface IReqoreMenuDividerProps
|
|
10
|
-
extends React.HTMLAttributes<HTMLDivElement>,
|
|
10
|
+
extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'>,
|
|
11
11
|
IWithReqoreEffect,
|
|
12
12
|
IWithReqoreSize {
|
|
13
|
-
label?: string;
|
|
13
|
+
label?: string | number;
|
|
14
14
|
margin?: 'left' | 'right' | 'both';
|
|
15
|
+
align?: 'left' | 'center' | 'right';
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export const StyledMenuDivider = styled(StyledTextEffect)`
|
|
@@ -38,7 +39,17 @@ export const StyledMenuDivider = styled(StyledTextEffect)`
|
|
|
38
39
|
`;
|
|
39
40
|
|
|
40
41
|
const ReqoreMenuDivider = forwardRef<HTMLDivElement, IReqoreMenuDividerProps>(
|
|
41
|
-
(
|
|
42
|
+
(
|
|
43
|
+
{
|
|
44
|
+
label,
|
|
45
|
+
className,
|
|
46
|
+
effect,
|
|
47
|
+
size = 'normal',
|
|
48
|
+
align = 'center',
|
|
49
|
+
...rest
|
|
50
|
+
}: IReqoreMenuDividerProps,
|
|
51
|
+
ref: any
|
|
52
|
+
) => (
|
|
42
53
|
<StyledMenuDivider
|
|
43
54
|
as='div'
|
|
44
55
|
{...rest}
|
|
@@ -49,7 +60,7 @@ const ReqoreMenuDivider = forwardRef<HTMLDivElement, IReqoreMenuDividerProps>(
|
|
|
49
60
|
{
|
|
50
61
|
uppercase: true,
|
|
51
62
|
spaced: 2,
|
|
52
|
-
textAlign:
|
|
63
|
+
textAlign: align,
|
|
53
64
|
textSize: getOneLessSize(size),
|
|
54
65
|
weight: 'bold',
|
|
55
66
|
...effect,
|
|
@@ -81,10 +81,10 @@ const ReqoreMenu = forwardRef<HTMLDivElement, IReqoreMenuProps>(
|
|
|
81
81
|
React.cloneElement(child, {
|
|
82
82
|
_insidePopover,
|
|
83
83
|
_popoverId,
|
|
84
|
-
customTheme: child?.
|
|
84
|
+
customTheme: child.props?.customTheme || theme,
|
|
85
85
|
wrap: wrapText,
|
|
86
|
-
flat: 'flat' in child
|
|
87
|
-
minimal: 'minimal' in child
|
|
86
|
+
flat: 'flat' in (child.props || {}) ? child.props.flat : flat,
|
|
87
|
+
minimal: 'minimal' in (child.props || {}) ? child.props.minimal : minimal,
|
|
88
88
|
})
|
|
89
89
|
: null;
|
|
90
90
|
})}
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
import { omit, 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, 'asBadge' | 'rightIcon' | 'actions'> & { 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
|
+
onItemClickIcon?: IReqoreTagProps['rightIcon'];
|
|
25
|
+
canRemoveItems?: boolean;
|
|
26
|
+
canCreateItems?: boolean;
|
|
27
|
+
selectedItemEffect?: IReqoreEffect;
|
|
28
|
+
selectedItemSize?: TSizes;
|
|
29
|
+
selectorProps?: Omit<IReqoreInputProps, 'value' | 'onValueChange'> & IReqoreDropdownProps;
|
|
30
|
+
openOnMount?: IReqoreDropdownProps['openOnMount'];
|
|
31
|
+
enterKeySelects?: boolean;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface IReqoreMultiSelectItemProps
|
|
35
|
+
extends Pick<IReqoreMultiSelectProps, 'selectedItemEffect' | 'selectedItemSize'> {
|
|
36
|
+
item: TReqoreMultiSelectItem;
|
|
37
|
+
onClick?: () => void;
|
|
38
|
+
onRemoveClick?: () => void;
|
|
39
|
+
onItemClickIcon?: IReqoreTagProps['rightIcon'];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export const ReqoreMultiSelectItem = memo(
|
|
43
|
+
({
|
|
44
|
+
item,
|
|
45
|
+
onRemoveClick,
|
|
46
|
+
onClick,
|
|
47
|
+
selectedItemEffect,
|
|
48
|
+
selectedItemSize,
|
|
49
|
+
onItemClickIcon,
|
|
50
|
+
}: IReqoreMultiSelectItemProps) => {
|
|
51
|
+
if (!item) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
return (
|
|
56
|
+
<ReqoreTag
|
|
57
|
+
{...item}
|
|
58
|
+
label={item.label || item.value}
|
|
59
|
+
onRemoveClick={onRemoveClick}
|
|
60
|
+
intent={item.intent}
|
|
61
|
+
effect={!item.intent ? item.effect || selectedItemEffect : undefined}
|
|
62
|
+
size={selectedItemSize}
|
|
63
|
+
onClick={onClick}
|
|
64
|
+
rightIcon={item.rightIcon || item.disabled ? undefined : onItemClickIcon}
|
|
65
|
+
/>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
export const ReqoreMultiSelect = forwardRef<HTMLDivElement, IReqoreMultiSelectProps>(
|
|
71
|
+
(
|
|
72
|
+
{
|
|
73
|
+
value,
|
|
74
|
+
onValueChange,
|
|
75
|
+
onItemClick,
|
|
76
|
+
canRemoveItems,
|
|
77
|
+
canCreateItems,
|
|
78
|
+
items = [],
|
|
79
|
+
selectedItemEffect,
|
|
80
|
+
selectedItemSize,
|
|
81
|
+
selectorProps,
|
|
82
|
+
openOnMount,
|
|
83
|
+
enterKeySelects,
|
|
84
|
+
onItemClickIcon,
|
|
85
|
+
...rest
|
|
86
|
+
}: IReqoreMultiSelectProps,
|
|
87
|
+
ref
|
|
88
|
+
) => {
|
|
89
|
+
const [_value, setValue] = useState<string[]>(value || []);
|
|
90
|
+
const [createdItems, setCreatedItems] = useState<TReqoreMultiSelectItem[]>([]);
|
|
91
|
+
const [query, setQuery] = useState<string>('');
|
|
92
|
+
const popoverData = useRef<IPopoverControls>(undefined);
|
|
93
|
+
const [focused, setFocused] = useState<boolean>(false);
|
|
94
|
+
|
|
95
|
+
useUpdateEffect(() => {
|
|
96
|
+
onValueChange?.(_value);
|
|
97
|
+
}, [_value]);
|
|
98
|
+
|
|
99
|
+
useEffect(() => {
|
|
100
|
+
setValue(value || []);
|
|
101
|
+
}, [value]);
|
|
102
|
+
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
if (query && !popoverData.current?.isOpen()) {
|
|
105
|
+
popoverData.current?.open();
|
|
106
|
+
}
|
|
107
|
+
}, [query]);
|
|
108
|
+
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
if (enterKeySelects) {
|
|
111
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
return () => {
|
|
115
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
116
|
+
};
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
const addRemoveItem = useCallback(
|
|
120
|
+
(item: TReqoreMultiSelectItem): void => {
|
|
121
|
+
if (_value.includes(item.value)) {
|
|
122
|
+
setValue(_value.filter((v) => v !== item.value));
|
|
123
|
+
} else {
|
|
124
|
+
setValue([..._value, item.value]);
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
[_value, value]
|
|
128
|
+
);
|
|
129
|
+
|
|
130
|
+
const handleItemSelect = useCallback(
|
|
131
|
+
(item: Partial<TReqoreMultiSelectItem>) => {
|
|
132
|
+
addRemoveItem(item);
|
|
133
|
+
|
|
134
|
+
if (item.isNew) {
|
|
135
|
+
setCreatedItems([
|
|
136
|
+
...createdItems,
|
|
137
|
+
{
|
|
138
|
+
value: item.value,
|
|
139
|
+
},
|
|
140
|
+
]);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
setQuery('');
|
|
144
|
+
},
|
|
145
|
+
[createdItems, _value]
|
|
146
|
+
);
|
|
147
|
+
|
|
148
|
+
/*
|
|
149
|
+
This code creates a list of all items that are available
|
|
150
|
+
for selection in the dropdown. It will include the items
|
|
151
|
+
that are passed in as props, as well as any items that the
|
|
152
|
+
user has created.
|
|
153
|
+
*/
|
|
154
|
+
const allItems: TReqoreMultiSelectItem[] = useMemo(() => {
|
|
155
|
+
const customItems: TReqoreMultiSelectItem[] = size(createdItems)
|
|
156
|
+
? [{ divider: true, label: 'Custom Items' }, ...createdItems]
|
|
157
|
+
: [];
|
|
158
|
+
|
|
159
|
+
let filteredItems: TReqoreMultiSelectItem[] = [...items, ...customItems].filter((item) =>
|
|
160
|
+
query
|
|
161
|
+
? item.divider
|
|
162
|
+
? false
|
|
163
|
+
: (item.label || item.value)?.toString().toLowerCase().indexOf(query.toLowerCase()) !==
|
|
164
|
+
-1
|
|
165
|
+
: true
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
// Mark selected items as selected
|
|
169
|
+
filteredItems = filteredItems.map((item: TReqoreMultiSelectItem) => ({
|
|
170
|
+
...omit(item, ['actions', 'asBadge', 'rightIcon']),
|
|
171
|
+
selected: _value.includes(item.value),
|
|
172
|
+
}));
|
|
173
|
+
|
|
174
|
+
if (query && !size(filteredItems)) {
|
|
175
|
+
filteredItems = [
|
|
176
|
+
{ label: 'No existing items found', readOnly: true, minimal: true, icon: 'ForbidLine' },
|
|
177
|
+
];
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// If there is a query and there are filtered items
|
|
181
|
+
// and there is no item that exactly matches the query, add it to the list
|
|
182
|
+
if (
|
|
183
|
+
query &&
|
|
184
|
+
!filteredItems.some((item: TReqoreMultiSelectItem) => item.value === query) &&
|
|
185
|
+
canCreateItems
|
|
186
|
+
) {
|
|
187
|
+
filteredItems = [
|
|
188
|
+
{
|
|
189
|
+
label: `Create new "${query}"`,
|
|
190
|
+
value: query,
|
|
191
|
+
isNew: true,
|
|
192
|
+
icon: 'AddCircleLine',
|
|
193
|
+
minimal: true,
|
|
194
|
+
flat: false,
|
|
195
|
+
effect: {
|
|
196
|
+
gradient: {
|
|
197
|
+
colors: {
|
|
198
|
+
0: 'success',
|
|
199
|
+
100: 'success:darken:1',
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
{ divider: true, label: 'Items matching your query' },
|
|
205
|
+
...filteredItems,
|
|
206
|
+
];
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return filteredItems;
|
|
210
|
+
}, [items, createdItems, query, _value]);
|
|
211
|
+
|
|
212
|
+
const handleKeyDown = useCallback(
|
|
213
|
+
(e: KeyboardEvent) => {
|
|
214
|
+
if (e.key === 'Enter' && focused) {
|
|
215
|
+
const item = [...items, ...createdItems].find((item) => item.value === query);
|
|
216
|
+
|
|
217
|
+
if (item) {
|
|
218
|
+
handleItemSelect(item);
|
|
219
|
+
} else if (canCreateItems && query) {
|
|
220
|
+
handleItemSelect({
|
|
221
|
+
value: query,
|
|
222
|
+
isNew: true,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
},
|
|
227
|
+
[items, createdItems, query, canCreateItems, focused]
|
|
228
|
+
);
|
|
229
|
+
|
|
230
|
+
const getItemByValue = useCallback(
|
|
231
|
+
(value: string): TReqoreMultiSelectItem => {
|
|
232
|
+
return [...items, ...createdItems].find((item) => item.value === value);
|
|
233
|
+
},
|
|
234
|
+
[items, createdItems, _value]
|
|
235
|
+
);
|
|
236
|
+
|
|
237
|
+
return (
|
|
238
|
+
<ReqoreControlGroup vertical fluid {...rest} ref={ref}>
|
|
239
|
+
<ReqoreTagGroup minimal={rest.minimal} size={rest.size}>
|
|
240
|
+
{size(_value) ? (
|
|
241
|
+
_value.map((v) => (
|
|
242
|
+
<ReqoreMultiSelectItem
|
|
243
|
+
key={v}
|
|
244
|
+
item={getItemByValue(v)}
|
|
245
|
+
onItemClickIcon={onItemClickIcon}
|
|
246
|
+
onRemoveClick={canRemoveItems ? () => addRemoveItem(getItemByValue(v)) : undefined}
|
|
247
|
+
onClick={
|
|
248
|
+
onItemClick
|
|
249
|
+
? () => {
|
|
250
|
+
onItemClick(getItemByValue(v));
|
|
251
|
+
}
|
|
252
|
+
: undefined
|
|
253
|
+
}
|
|
254
|
+
selectedItemEffect={selectedItemEffect}
|
|
255
|
+
selectedItemSize={selectedItemSize}
|
|
256
|
+
/>
|
|
257
|
+
))
|
|
258
|
+
) : (
|
|
259
|
+
<ReqoreTag color='transparent' icon='ForbidLine' label='No items selected' />
|
|
260
|
+
)}
|
|
261
|
+
</ReqoreTagGroup>
|
|
262
|
+
<ReqoreControlGroup minimal={rest.minimal} flat={rest.flat} size={rest.size}>
|
|
263
|
+
<ReqoreDropdown<IReqoreInputProps>
|
|
264
|
+
{...selectorProps}
|
|
265
|
+
multiSelect
|
|
266
|
+
handler='focus'
|
|
267
|
+
onFocus={() => setFocused(true)}
|
|
268
|
+
onBlur={() => setFocused(false)}
|
|
269
|
+
passPopoverData={(data) => (popoverData.current = data)}
|
|
270
|
+
component={ReqoreInput}
|
|
271
|
+
onClearClick={() => setQuery('')}
|
|
272
|
+
value={query}
|
|
273
|
+
isDefaultOpen={openOnMount}
|
|
274
|
+
onItemSelect={handleItemSelect}
|
|
275
|
+
placeholder={
|
|
276
|
+
canCreateItems ? 'Type to search or create an item...' : 'Type to search...'
|
|
277
|
+
}
|
|
278
|
+
onChange={(e: any) => setQuery(e.target.value)}
|
|
279
|
+
items={
|
|
280
|
+
size(allItems)
|
|
281
|
+
? allItems
|
|
282
|
+
: canCreateItems
|
|
283
|
+
? [{ label: 'No items exist', readOnly: true, minimal: true, icon: 'ForbidLine' }]
|
|
284
|
+
: []
|
|
285
|
+
}
|
|
286
|
+
useTargetWidth
|
|
287
|
+
/>
|
|
288
|
+
</ReqoreControlGroup>
|
|
289
|
+
</ReqoreControlGroup>
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
);
|
|
@@ -8,14 +8,14 @@ import {
|
|
|
8
8
|
PADDING_FROM_SIZE,
|
|
9
9
|
RADIUS_FROM_SIZE,
|
|
10
10
|
TEXT_FROM_SIZE,
|
|
11
|
-
TSizes
|
|
11
|
+
TSizes,
|
|
12
12
|
} from '../../constants/sizes';
|
|
13
13
|
import { IReqoreTheme } from '../../constants/theme';
|
|
14
14
|
import {
|
|
15
15
|
changeDarkness,
|
|
16
16
|
changeLightness,
|
|
17
17
|
getMainBackgroundColor,
|
|
18
|
-
getReadableColor
|
|
18
|
+
getReadableColor,
|
|
19
19
|
} from '../../helpers/colors';
|
|
20
20
|
import { useCombinedRefs } from '../../hooks/useCombinedRefs';
|
|
21
21
|
import { useReqoreTheme } from '../../hooks/useTheme';
|
|
@@ -26,7 +26,7 @@ import {
|
|
|
26
26
|
IWithReqoreCustomTheme,
|
|
27
27
|
IWithReqoreFlat,
|
|
28
28
|
IWithReqoreSize,
|
|
29
|
-
IWithReqoreTooltip
|
|
29
|
+
IWithReqoreTooltip,
|
|
30
30
|
} from '../../types/global';
|
|
31
31
|
import { IReqoreIconName } from '../../types/icons';
|
|
32
32
|
import ReqoreButton, { ButtonBadge, IReqoreButtonProps, TReqoreBadge } from '../Button';
|
|
@@ -323,7 +323,9 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
323
323
|
(actionOrActions: IReqorePanelAction | IReqorePanelAction[], index: number) => {
|
|
324
324
|
if (Array.isArray(actionOrActions)) {
|
|
325
325
|
return (
|
|
326
|
-
<ReqoreControlGroup
|
|
326
|
+
<ReqoreControlGroup key={index} stack>
|
|
327
|
+
{actionOrActions.map(renderActions)}
|
|
328
|
+
</ReqoreControlGroup>
|
|
327
329
|
);
|
|
328
330
|
}
|
|
329
331
|
|
|
@@ -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 (
|
|
@@ -19,6 +19,8 @@ export interface IReqoreRadioGroupProps
|
|
|
19
19
|
size?: TSizes;
|
|
20
20
|
disabled?: boolean;
|
|
21
21
|
asSwitch?: boolean;
|
|
22
|
+
onText?: string;
|
|
23
|
+
offText?: string;
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
const ReqoreRadioGroup = ({
|
|
@@ -29,6 +31,8 @@ const ReqoreRadioGroup = ({
|
|
|
29
31
|
disabled,
|
|
30
32
|
asSwitch,
|
|
31
33
|
vertical = true,
|
|
34
|
+
onText,
|
|
35
|
+
offText,
|
|
32
36
|
...rest
|
|
33
37
|
}: IReqoreRadioGroupProps) => (
|
|
34
38
|
<ReqoreControlGroup {...rest} vertical={vertical}>
|
|
@@ -44,6 +48,8 @@ const ReqoreRadioGroup = ({
|
|
|
44
48
|
) : (
|
|
45
49
|
<ReqoreCheckbox
|
|
46
50
|
asSwitch={asSwitch}
|
|
51
|
+
onText={onText}
|
|
52
|
+
offText={offText}
|
|
47
53
|
{...itemRest}
|
|
48
54
|
key={value}
|
|
49
55
|
checked={value === selected}
|
|
@@ -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}>
|
|
@@ -2,10 +2,13 @@ import React from 'react';
|
|
|
2
2
|
import styled from 'styled-components';
|
|
3
3
|
import { StyledTag } from '.';
|
|
4
4
|
import { GAP_FROM_SIZE, TSizes } from '../../constants/sizes';
|
|
5
|
+
import { IWithReqoreMinimal, IWithReqoreSize } from '../../types/global';
|
|
5
6
|
|
|
6
|
-
export interface IReqoreTagGroup
|
|
7
|
+
export interface IReqoreTagGroup
|
|
8
|
+
extends React.HTMLAttributes<HTMLDivElement>,
|
|
9
|
+
IWithReqoreSize,
|
|
10
|
+
IWithReqoreMinimal {
|
|
7
11
|
children: any;
|
|
8
|
-
size?: TSizes;
|
|
9
12
|
gapSize?: TSizes;
|
|
10
13
|
columns?: 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10;
|
|
11
14
|
hasBottomMargin?: boolean;
|
|
@@ -27,6 +30,7 @@ const ReqoreTagGroup = ({
|
|
|
27
30
|
children,
|
|
28
31
|
size,
|
|
29
32
|
gapSize = 'normal',
|
|
33
|
+
minimal,
|
|
30
34
|
className,
|
|
31
35
|
columns,
|
|
32
36
|
hasBottomMargin = true,
|
|
@@ -43,6 +47,10 @@ const ReqoreTagGroup = ({
|
|
|
43
47
|
? React.cloneElement(child, {
|
|
44
48
|
size: child.props?.size || size,
|
|
45
49
|
width: columns ? `calc(${100 / columns}% - 5px)` : child.props.width,
|
|
50
|
+
minimal:
|
|
51
|
+
child.props?.minimal || child.props?.minimal === false
|
|
52
|
+
? child.props.minimal
|
|
53
|
+
: minimal,
|
|
46
54
|
})
|
|
47
55
|
: null
|
|
48
56
|
)}
|
|
@@ -53,7 +53,7 @@ export interface IReqoreTagProps
|
|
|
53
53
|
color?: TReqoreEffectColor;
|
|
54
54
|
actions?: IReqoreTagAction[];
|
|
55
55
|
width?: string;
|
|
56
|
-
|
|
56
|
+
asBadge?: boolean;
|
|
57
57
|
intent?: TReqoreIntent;
|
|
58
58
|
wrap?: boolean;
|
|
59
59
|
}
|
|
@@ -77,17 +77,18 @@ export const StyledTag = styled(StyledEffect)<IReqoreTagStyle>`
|
|
|
77
77
|
font-size: ${({ size }) => TEXT_FROM_SIZE[size]}px;
|
|
78
78
|
|
|
79
79
|
min-width: ${({ size }) => SIZE_TO_PX[size]}px;
|
|
80
|
-
border-radius: ${({
|
|
80
|
+
border-radius: ${({ asBadge, size }) => (asBadge ? 18 : RADIUS_FROM_SIZE[size])}px;
|
|
81
81
|
width: ${({ width }) => width || undefined};
|
|
82
82
|
transition: all 0.2s ease-out;
|
|
83
83
|
|
|
84
84
|
${({ wrap, hasWidth }) =>
|
|
85
85
|
wrap || hasWidth
|
|
86
86
|
? css`
|
|
87
|
-
min-height: ${({ size,
|
|
87
|
+
min-height: ${({ size, asBadge }) =>
|
|
88
|
+
asBadge ? BADGE_SIZE_TO_PX[size] : SIZE_TO_PX[size]}px;
|
|
88
89
|
`
|
|
89
90
|
: css`
|
|
90
|
-
height: ${({ size,
|
|
91
|
+
height: ${({ size, asBadge }) => (asBadge ? BADGE_SIZE_TO_PX[size] : SIZE_TO_PX[size])}px;
|
|
91
92
|
`}
|
|
92
93
|
|
|
93
94
|
${({ theme, color, labelKey, minimal }: IReqoreTagStyle) =>
|
|
@@ -220,7 +221,7 @@ const ReqoreTag = forwardRef<HTMLSpanElement, IReqoreTagProps>(
|
|
|
220
221
|
size = 'normal',
|
|
221
222
|
onRemoveClick,
|
|
222
223
|
actions,
|
|
223
|
-
|
|
224
|
+
asBadge,
|
|
224
225
|
intent,
|
|
225
226
|
color,
|
|
226
227
|
minimal,
|
|
@@ -236,10 +237,15 @@ const ReqoreTag = forwardRef<HTMLSpanElement, IReqoreTagProps>(
|
|
|
236
237
|
useTooltip(targetRef.current, tooltip);
|
|
237
238
|
|
|
238
239
|
// If color or intent was specified, set the color
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
240
|
+
const getCustomColor = (itemIntent?: TReqoreIntent): TReqoreHexColor => {
|
|
241
|
+
let customColor: TReqoreHexColor = itemIntent
|
|
242
|
+
? theme.intents[itemIntent]
|
|
243
|
+
: getColorFromMaybeString(theme, color);
|
|
244
|
+
|
|
245
|
+
customColor = minimal ? `${customColor || '#000000'}40` : customColor;
|
|
246
|
+
|
|
247
|
+
return customColor;
|
|
248
|
+
};
|
|
243
249
|
|
|
244
250
|
return (
|
|
245
251
|
<StyledTag
|
|
@@ -250,11 +256,11 @@ const ReqoreTag = forwardRef<HTMLSpanElement, IReqoreTagProps>(
|
|
|
250
256
|
}}
|
|
251
257
|
width={width}
|
|
252
258
|
labelKey={labelKey}
|
|
253
|
-
color={
|
|
259
|
+
color={getCustomColor(intent)}
|
|
254
260
|
className={`${className || ''} reqore-tag`}
|
|
255
261
|
size={size}
|
|
256
262
|
ref={targetRef}
|
|
257
|
-
|
|
263
|
+
asBadge={asBadge}
|
|
258
264
|
minimal={minimal}
|
|
259
265
|
removable={!!onRemoveClick}
|
|
260
266
|
interactive={!!onClick && !rest.disabled}
|
|
@@ -265,7 +271,7 @@ const ReqoreTag = forwardRef<HTMLSpanElement, IReqoreTagProps>(
|
|
|
265
271
|
<StyledTagKeyWrapper
|
|
266
272
|
size={size}
|
|
267
273
|
className='reqore-tag-key-content'
|
|
268
|
-
onClick={onClick}
|
|
274
|
+
onClick={rest.disabled ? undefined : onClick}
|
|
269
275
|
wrap={wrap}
|
|
270
276
|
hasWidth={!!width}
|
|
271
277
|
hasKey={!!labelKey}
|
|
@@ -282,13 +288,13 @@ const ReqoreTag = forwardRef<HTMLSpanElement, IReqoreTagProps>(
|
|
|
282
288
|
<StyledTagContentWrapper
|
|
283
289
|
size={size}
|
|
284
290
|
className='reqore-tag-content'
|
|
285
|
-
onClick={onClick}
|
|
291
|
+
onClick={rest.disabled ? undefined : onClick}
|
|
286
292
|
wrap={wrap}
|
|
287
293
|
hasWidth={!!width}
|
|
288
294
|
hasKey={!!labelKey}
|
|
289
295
|
>
|
|
290
296
|
{label || label === 0 ? (
|
|
291
|
-
<StyledTagContent size={size}
|
|
297
|
+
<StyledTagContent size={size} wrap={wrap} hasWidth={!!width}>
|
|
292
298
|
{label}
|
|
293
299
|
</StyledTagContent>
|
|
294
300
|
) : null}
|
|
@@ -302,13 +308,13 @@ const ReqoreTag = forwardRef<HTMLSpanElement, IReqoreTagProps>(
|
|
|
302
308
|
</StyledTagContentWrapper>
|
|
303
309
|
) : null}
|
|
304
310
|
{_size(actions)
|
|
305
|
-
? actions.map((action) => (
|
|
306
|
-
|
|
311
|
+
? actions.map((action, index) => (
|
|
312
|
+
<React.Fragment key={index}>
|
|
307
313
|
<ReqorePopover
|
|
308
314
|
component={StyledButtonWrapper}
|
|
309
315
|
componentProps={{
|
|
310
316
|
size,
|
|
311
|
-
color:
|
|
317
|
+
color: getCustomColor(action.intent),
|
|
312
318
|
className: 'reqore-tag-action',
|
|
313
319
|
onClick: action.onClick,
|
|
314
320
|
effect: rest.effect,
|
|
@@ -316,13 +322,13 @@ const ReqoreTag = forwardRef<HTMLSpanElement, IReqoreTagProps>(
|
|
|
316
322
|
{...(action.tooltip
|
|
317
323
|
? typeof action.tooltip === 'string'
|
|
318
324
|
? { tooltip: action.tooltip }
|
|
319
|
-
: action.tooltip
|
|
325
|
+
: action.tooltip
|
|
320
326
|
: {})}
|
|
321
327
|
noWrapper
|
|
322
328
|
>
|
|
323
329
|
<ReqoreIcon icon={action.icon} size={size} />
|
|
324
330
|
</ReqorePopover>
|
|
325
|
-
|
|
331
|
+
</React.Fragment>
|
|
326
332
|
))
|
|
327
333
|
: null}
|
|
328
334
|
{onRemoveClick && !rest.disabled ? (
|
|
@@ -330,7 +336,7 @@ const ReqoreTag = forwardRef<HTMLSpanElement, IReqoreTagProps>(
|
|
|
330
336
|
component={StyledButtonWrapper}
|
|
331
337
|
componentProps={{
|
|
332
338
|
size,
|
|
333
|
-
color:
|
|
339
|
+
color: getCustomColor(intent),
|
|
334
340
|
className: 'reqore-tag-remove',
|
|
335
341
|
onClick: onRemoveClick,
|
|
336
342
|
effect: rest.effect,
|