@qoretechnologies/reqore 0.29.9 → 0.30.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/__tests__/collection.test.tsx +1 -1
- package/__tests__/{control_group.text.tsx → control_group.test.tsx} +4 -2
- package/__tests__/panel.test.tsx +22 -24
- package/__tests__/tabs.test.tsx +32 -0
- package/dist/components/Button/index.d.ts.map +1 -1
- package/dist/components/Button/index.js +5 -2
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/Collection/index.d.ts.map +1 -1
- package/dist/components/Collection/index.js +14 -37
- package/dist/components/Collection/index.js.map +1 -1
- package/dist/components/Columns/column.d.ts.map +1 -1
- package/dist/components/Columns/column.js +1 -1
- package/dist/components/Columns/column.js.map +1 -1
- package/dist/components/ControlGroup/index.d.ts +5 -4
- package/dist/components/ControlGroup/index.d.ts.map +1 -1
- package/dist/components/ControlGroup/index.js +117 -24
- package/dist/components/ControlGroup/index.js.map +1 -1
- package/dist/components/Drawer/index.d.ts.map +1 -1
- package/dist/components/Drawer/index.js +6 -4
- package/dist/components/Drawer/index.js.map +1 -1
- package/dist/components/Effect/index.d.ts.map +1 -1
- package/dist/components/Effect/index.js +1 -1
- package/dist/components/Effect/index.js.map +1 -1
- package/dist/components/Input/index.js +2 -2
- package/dist/components/Input/index.js.map +1 -1
- package/dist/components/InternalPopover/index.d.ts.map +1 -1
- package/dist/components/InternalPopover/index.js +5 -3
- package/dist/components/InternalPopover/index.js.map +1 -1
- package/dist/components/MultiSelect/index.d.ts +1 -1
- package/dist/components/MultiSelect/index.d.ts.map +1 -1
- package/dist/components/MultiSelect/index.js +10 -10
- package/dist/components/MultiSelect/index.js.map +1 -1
- package/dist/components/Panel/index.d.ts +4 -1
- package/dist/components/Panel/index.d.ts.map +1 -1
- package/dist/components/Panel/index.js +39 -16
- package/dist/components/Panel/index.js.map +1 -1
- package/dist/components/Spacer/index.d.ts +2 -0
- package/dist/components/Spacer/index.d.ts.map +1 -1
- package/dist/components/Spacer/index.js +29 -7
- package/dist/components/Spacer/index.js.map +1 -1
- package/dist/components/Tabs/index.d.ts.map +1 -1
- package/dist/components/Tabs/index.js +2 -1
- package/dist/components/Tabs/index.js.map +1 -1
- package/dist/components/Tag/index.d.ts +2 -2
- package/dist/components/Tag/index.d.ts.map +1 -1
- package/dist/components/Tag/index.js +7 -1
- 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/animations.js +1 -1
- package/dist/containers/PopoverProvider.js +3 -3
- package/dist/containers/PopoverProvider.js.map +1 -1
- package/package.json +1 -1
- package/src/components/Button/index.tsx +2 -1
- package/src/components/Collection/index.tsx +14 -37
- package/src/components/Columns/column.tsx +1 -0
- package/src/components/ControlGroup/index.tsx +386 -232
- package/src/components/Drawer/index.tsx +6 -4
- package/src/components/Effect/index.tsx +1 -0
- package/src/components/Input/index.tsx +1 -1
- package/src/components/InternalPopover/index.tsx +127 -123
- package/src/components/MultiSelect/index.tsx +180 -188
- package/src/components/Panel/index.tsx +127 -42
- package/src/components/Spacer/index.tsx +63 -14
- package/src/components/Tabs/index.tsx +3 -2
- package/src/components/Tag/index.tsx +5 -1
- package/src/components/Tree/index.tsx +1 -1
- package/src/constants/animations.ts +1 -1
- package/src/containers/PopoverProvider.tsx +3 -3
- package/src/stories/ControlGroup/ControlGroup.stories.tsx +55 -5
- package/src/stories/Panel/Panel.stories.tsx +60 -17
- package/src/stories/Popover/Popover.stories.tsx +5 -5
- package/tests.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { omit, size } from 'lodash';
|
|
2
|
-
import {
|
|
2
|
+
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
3
|
import { ReqoreDropdown, ReqoreInput } from '../..';
|
|
4
4
|
import { TSizes } from '../../constants/sizes';
|
|
5
5
|
import { IPopoverControls } from '../../hooks/usePopover';
|
|
@@ -74,217 +74,209 @@ export const ReqoreMultiSelectItem = memo(
|
|
|
74
74
|
}
|
|
75
75
|
);
|
|
76
76
|
|
|
77
|
-
export const ReqoreMultiSelect =
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const [createdItems, setCreatedItems] = useState<TReqoreMultiSelectItem[]>([]);
|
|
97
|
-
const [query, setQuery] = useState<string>('');
|
|
98
|
-
const popoverData = useRef<IPopoverControls>(undefined);
|
|
99
|
-
const [focused, setFocused] = useState<boolean>(false);
|
|
77
|
+
export const ReqoreMultiSelect = ({
|
|
78
|
+
value = [],
|
|
79
|
+
onValueChange,
|
|
80
|
+
onItemClick,
|
|
81
|
+
canRemoveItems,
|
|
82
|
+
canCreateItems,
|
|
83
|
+
items = [],
|
|
84
|
+
selectedItemEffect,
|
|
85
|
+
selectedItemSize,
|
|
86
|
+
selectorProps,
|
|
87
|
+
openOnMount,
|
|
88
|
+
enterKeySelects,
|
|
89
|
+
onItemClickIcon,
|
|
90
|
+
...rest
|
|
91
|
+
}: IReqoreMultiSelectProps) => {
|
|
92
|
+
const [createdItems, setCreatedItems] = useState<TReqoreMultiSelectItem[]>([]);
|
|
93
|
+
const [query, setQuery] = useState<string>('');
|
|
94
|
+
const popoverData = useRef<IPopoverControls>(undefined);
|
|
95
|
+
const [focused, setFocused] = useState<boolean>(false);
|
|
100
96
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
97
|
+
useEffect(() => {
|
|
98
|
+
if (query && !popoverData.current?.isOpen()) {
|
|
99
|
+
popoverData.current?.open();
|
|
100
|
+
}
|
|
101
|
+
}, [query]);
|
|
106
102
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
103
|
+
useEffect(() => {
|
|
104
|
+
if (enterKeySelects) {
|
|
105
|
+
document.addEventListener('keydown', handleKeyDown);
|
|
106
|
+
}
|
|
111
107
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
108
|
+
return () => {
|
|
109
|
+
document.removeEventListener('keydown', handleKeyDown);
|
|
110
|
+
};
|
|
111
|
+
});
|
|
116
112
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
113
|
+
const addRemoveItem = useCallback(
|
|
114
|
+
(item: TReqoreMultiSelectItem): void => {
|
|
115
|
+
if (value.includes(item.value)) {
|
|
116
|
+
onValueChange(value.filter((v) => v !== item.value));
|
|
117
|
+
} else {
|
|
118
|
+
onValueChange([...value, item.value]);
|
|
119
|
+
}
|
|
120
|
+
},
|
|
121
|
+
[value]
|
|
122
|
+
);
|
|
127
123
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
124
|
+
const handleItemSelect = useCallback(
|
|
125
|
+
(item: Partial<TReqoreMultiSelectItem>) => {
|
|
126
|
+
addRemoveItem(item);
|
|
131
127
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
128
|
+
if (item.isNew) {
|
|
129
|
+
setCreatedItems([
|
|
130
|
+
...createdItems,
|
|
131
|
+
{
|
|
132
|
+
value: item.value,
|
|
133
|
+
},
|
|
134
|
+
]);
|
|
135
|
+
}
|
|
140
136
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
137
|
+
setQuery('');
|
|
138
|
+
},
|
|
139
|
+
[createdItems, value]
|
|
140
|
+
);
|
|
145
141
|
|
|
146
|
-
|
|
142
|
+
/*
|
|
147
143
|
This code creates a list of all items that are available
|
|
148
144
|
for selection in the dropdown. It will include the items
|
|
149
145
|
that are passed in as props, as well as any items that the
|
|
150
146
|
user has created.
|
|
151
147
|
*/
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
148
|
+
const allItems: TReqoreMultiSelectItem[] = useMemo(() => {
|
|
149
|
+
const customItems: TReqoreMultiSelectItem[] = size(createdItems)
|
|
150
|
+
? [{ divider: true, label: 'Custom Items' }, ...createdItems]
|
|
151
|
+
: [];
|
|
156
152
|
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
);
|
|
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()) !== -1
|
|
158
|
+
: true
|
|
159
|
+
);
|
|
165
160
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
161
|
+
// Mark selected items as selected
|
|
162
|
+
filteredItems = filteredItems.map((item: TReqoreMultiSelectItem) => ({
|
|
163
|
+
...omit(item, ['actions', 'asBadge', 'rightIcon']),
|
|
164
|
+
selected: value.includes(item.value),
|
|
165
|
+
}));
|
|
171
166
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
167
|
+
if (query && !size(filteredItems)) {
|
|
168
|
+
filteredItems = [
|
|
169
|
+
{ label: 'No existing items found', readOnly: true, minimal: true, icon: 'ForbidLine' },
|
|
170
|
+
];
|
|
171
|
+
}
|
|
177
172
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
},
|
|
173
|
+
// If there is a query and there are filtered items
|
|
174
|
+
// and there is no item that exactly matches the query, add it to the list
|
|
175
|
+
if (
|
|
176
|
+
query &&
|
|
177
|
+
!filteredItems.some((item: TReqoreMultiSelectItem) => item.value === query) &&
|
|
178
|
+
canCreateItems
|
|
179
|
+
) {
|
|
180
|
+
filteredItems = [
|
|
181
|
+
{
|
|
182
|
+
label: `Create new "${query}"`,
|
|
183
|
+
value: query,
|
|
184
|
+
isNew: true,
|
|
185
|
+
icon: 'AddCircleLine',
|
|
186
|
+
minimal: true,
|
|
187
|
+
flat: false,
|
|
188
|
+
effect: {
|
|
189
|
+
gradient: {
|
|
190
|
+
colors: {
|
|
191
|
+
0: 'success',
|
|
192
|
+
100: 'success:darken:1',
|
|
199
193
|
},
|
|
200
194
|
},
|
|
201
195
|
},
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
196
|
+
},
|
|
197
|
+
{ divider: true, label: 'Items matching your query' },
|
|
198
|
+
...filteredItems,
|
|
199
|
+
];
|
|
200
|
+
}
|
|
206
201
|
|
|
207
|
-
|
|
208
|
-
|
|
202
|
+
return filteredItems;
|
|
203
|
+
}, [items, createdItems, query, value]);
|
|
209
204
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
205
|
+
const handleKeyDown = useCallback(
|
|
206
|
+
(e: KeyboardEvent) => {
|
|
207
|
+
if (e.key === 'Enter' && focused) {
|
|
208
|
+
const item = [...items, ...createdItems].find((item) => item.value === query);
|
|
214
209
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
210
|
+
if (item) {
|
|
211
|
+
handleItemSelect(item);
|
|
212
|
+
} else if (canCreateItems && query) {
|
|
213
|
+
handleItemSelect({
|
|
214
|
+
value: query,
|
|
215
|
+
isNew: true,
|
|
216
|
+
});
|
|
223
217
|
}
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
[items, createdItems, query, canCreateItems, focused]
|
|
221
|
+
);
|
|
227
222
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
223
|
+
const getItemByValue = useCallback(
|
|
224
|
+
(value: string): TReqoreMultiSelectItem => {
|
|
225
|
+
return [...items, ...createdItems].find((item) => item.value === value);
|
|
226
|
+
},
|
|
227
|
+
[items, createdItems, value]
|
|
228
|
+
);
|
|
234
229
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
useTargetWidth
|
|
285
|
-
/>
|
|
286
|
-
</ReqoreControlGroup>
|
|
230
|
+
return (
|
|
231
|
+
<ReqoreControlGroup vertical fluid {...rest}>
|
|
232
|
+
<ReqoreTagGroup minimal={rest.minimal} size={rest.size}>
|
|
233
|
+
{size(value) ? (
|
|
234
|
+
value.map((v) => (
|
|
235
|
+
<ReqoreMultiSelectItem
|
|
236
|
+
key={v}
|
|
237
|
+
item={getItemByValue(v)}
|
|
238
|
+
onItemClickIcon={onItemClickIcon}
|
|
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
|
+
onFocus={() => setFocused(true)}
|
|
261
|
+
onBlur={() => setFocused(false)}
|
|
262
|
+
passPopoverData={(data) => (popoverData.current = data)}
|
|
263
|
+
component={ReqoreInput}
|
|
264
|
+
onClearClick={() => setQuery('')}
|
|
265
|
+
value={query}
|
|
266
|
+
isDefaultOpen={openOnMount}
|
|
267
|
+
onItemSelect={handleItemSelect}
|
|
268
|
+
placeholder={canCreateItems ? 'Type to search or create an item...' : 'Type to search...'}
|
|
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
|
+
/>
|
|
287
279
|
</ReqoreControlGroup>
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
280
|
+
</ReqoreControlGroup>
|
|
281
|
+
);
|
|
282
|
+
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { size } from 'lodash';
|
|
2
2
|
import { darken, rgba } from 'polished';
|
|
3
|
-
import {
|
|
3
|
+
import { ReactElement, forwardRef, useCallback, useMemo, useState } from 'react';
|
|
4
4
|
import { useUpdateEffect } from 'react-use';
|
|
5
5
|
import styled, { css } from 'styled-components';
|
|
6
6
|
import {
|
|
7
|
+
GAP_FROM_SIZE,
|
|
7
8
|
ICON_FROM_HEADER_SIZE,
|
|
8
9
|
PADDING_FROM_SIZE,
|
|
9
10
|
RADIUS_FROM_SIZE,
|
|
@@ -38,7 +39,7 @@ import { IReqoreDropdownItem } from '../Dropdown/list';
|
|
|
38
39
|
import { IReqoreEffect, StyledEffect, TReqoreEffectColor } from '../Effect';
|
|
39
40
|
import { ReqoreHeading } from '../Header';
|
|
40
41
|
import ReqoreIcon, { StyledIconWrapper } from '../Icon';
|
|
41
|
-
import { ReqoreSpacer } from '../Spacer';
|
|
42
|
+
import { ReqoreHorizontalSpacer, ReqoreSpacer } from '../Spacer';
|
|
42
43
|
|
|
43
44
|
export interface IReqorePanelAction extends IReqoreButtonProps, IWithReqoreTooltip, IReqoreIntent {
|
|
44
45
|
label?: string | number;
|
|
@@ -46,9 +47,11 @@ export interface IReqorePanelAction extends IReqoreButtonProps, IWithReqoreToolt
|
|
|
46
47
|
actions?: Omit<IReqoreDropdownItem[], 'value'>;
|
|
47
48
|
// Custom react element
|
|
48
49
|
as?: React.ElementType;
|
|
49
|
-
props?: any;
|
|
50
|
+
props?: { [key: string | number]: any } | undefined;
|
|
50
51
|
// Hide the action if the condition is false
|
|
51
52
|
show?: boolean;
|
|
53
|
+
// Hide the action if the group is too small
|
|
54
|
+
responsive?: boolean;
|
|
52
55
|
}
|
|
53
56
|
|
|
54
57
|
export interface IReqorePanelBottomAction extends IReqorePanelAction {
|
|
@@ -116,6 +119,7 @@ export const StyledPanel = styled(StyledEffect)<IStyledPanel>`
|
|
|
116
119
|
backdrop-filter: ${({ blur, opacity }) => (blur && opacity < 1 ? `blur(${blur}px)` : undefined)};
|
|
117
120
|
transition: 0.2s ease-in-out;
|
|
118
121
|
width: ${({ fluid }) => (fluid ? '100%' : undefined)};
|
|
122
|
+
max-width: 100%;
|
|
119
123
|
flex: ${({ fluid }) => (fluid ? '1 auto' : '0 0 auto')};
|
|
120
124
|
|
|
121
125
|
${({ interactive, theme, opacity = 1, flat, intent }) =>
|
|
@@ -240,10 +244,13 @@ export const StyledPanelContent = styled.div<IStyledPanel>`
|
|
|
240
244
|
|
|
241
245
|
export const StyledPanelTitleHeader = styled.div`
|
|
242
246
|
display: flex;
|
|
243
|
-
justify-content:
|
|
247
|
+
justify-content: flex-start;
|
|
244
248
|
align-items: center;
|
|
245
|
-
overflow: hidden;
|
|
246
249
|
padding-right: 5px;
|
|
250
|
+
flex: 1 1 auto;
|
|
251
|
+
width: 100%;
|
|
252
|
+
overflow: hidden;
|
|
253
|
+
min-width: 100px;
|
|
247
254
|
`;
|
|
248
255
|
|
|
249
256
|
export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
@@ -328,17 +335,56 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
328
335
|
[leftBottomActions, rightBottomActions]
|
|
329
336
|
);
|
|
330
337
|
|
|
331
|
-
const
|
|
338
|
+
const renderResponsiveActions = useCallback(
|
|
332
339
|
(actionOrActions: IReqorePanelAction | IReqorePanelAction[], index: number) => {
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
+
return renderActions(actionOrActions, index, true);
|
|
341
|
+
},
|
|
342
|
+
[actions]
|
|
343
|
+
);
|
|
344
|
+
|
|
345
|
+
const hasNonResponsiveActions = useCallback(
|
|
346
|
+
(data: (IReqorePanelAction[] | IReqorePanelAction)[]) =>
|
|
347
|
+
data.some((action) => !Array.isArray(action) && action.responsive === false),
|
|
348
|
+
[actions, bottomActions]
|
|
349
|
+
);
|
|
340
350
|
|
|
341
|
-
|
|
351
|
+
const hasResponsiveActions = useCallback(
|
|
352
|
+
(data: (IReqorePanelAction[] | IReqorePanelAction)[]) =>
|
|
353
|
+
data.some((action) => Array.isArray(action) || action.responsive !== false),
|
|
354
|
+
[actions, bottomActions]
|
|
355
|
+
);
|
|
356
|
+
|
|
357
|
+
const renderNonResponsiveActions = useCallback(
|
|
358
|
+
(actionOrActions: IReqorePanelAction | IReqorePanelAction[], index: number) => {
|
|
359
|
+
return renderActions(actionOrActions, index, false);
|
|
360
|
+
},
|
|
361
|
+
[actions]
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
const renderActions = useCallback(
|
|
365
|
+
(
|
|
366
|
+
actionOrActions: IReqorePanelAction | IReqorePanelAction[],
|
|
367
|
+
index: number,
|
|
368
|
+
includeResponsive
|
|
369
|
+
) => {
|
|
370
|
+
const action: IReqorePanelAction = Array.isArray(actionOrActions)
|
|
371
|
+
? {
|
|
372
|
+
show: true,
|
|
373
|
+
responsive: true,
|
|
374
|
+
as: ReqoreControlGroup,
|
|
375
|
+
props: {
|
|
376
|
+
stack: true,
|
|
377
|
+
fluid: true,
|
|
378
|
+
children: actionOrActions.map(renderActions),
|
|
379
|
+
},
|
|
380
|
+
}
|
|
381
|
+
: actionOrActions;
|
|
382
|
+
|
|
383
|
+
if (
|
|
384
|
+
action.show === false ||
|
|
385
|
+
(includeResponsive && action.responsive === false) ||
|
|
386
|
+
(!includeResponsive && (action.responsive === true || !('responsive' in action)))
|
|
387
|
+
) {
|
|
342
388
|
return null;
|
|
343
389
|
}
|
|
344
390
|
|
|
@@ -349,20 +395,21 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
349
395
|
intent,
|
|
350
396
|
className,
|
|
351
397
|
as: CustomElement,
|
|
352
|
-
props,
|
|
398
|
+
props = {},
|
|
353
399
|
...rest
|
|
354
|
-
}: IReqorePanelAction =
|
|
400
|
+
}: IReqorePanelAction = action;
|
|
355
401
|
|
|
356
402
|
if (size(actions)) {
|
|
357
403
|
return (
|
|
358
404
|
<ReqoreDropdown<IReqoreButtonProps>
|
|
359
405
|
{...rest}
|
|
360
406
|
key={index}
|
|
407
|
+
fixed
|
|
361
408
|
label={label}
|
|
362
409
|
items={actions}
|
|
363
410
|
intent={intent}
|
|
364
411
|
className={className}
|
|
365
|
-
customTheme={theme}
|
|
412
|
+
customTheme={rest.customTheme || theme}
|
|
366
413
|
onClick={(e: React.MouseEvent<HTMLButtonElement>) => e.stopPropagation()}
|
|
367
414
|
id={id}
|
|
368
415
|
/>
|
|
@@ -372,9 +419,10 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
372
419
|
if (CustomElement) {
|
|
373
420
|
return (
|
|
374
421
|
<CustomElement
|
|
422
|
+
fixed
|
|
375
423
|
{...props}
|
|
376
424
|
key={index}
|
|
377
|
-
customTheme={theme}
|
|
425
|
+
customTheme={props.customTheme || theme}
|
|
378
426
|
onClick={(e: React.MouseEvent<any>) => {
|
|
379
427
|
e.stopPropagation();
|
|
380
428
|
props?.onClick?.(e);
|
|
@@ -387,9 +435,10 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
387
435
|
<ReqoreButton
|
|
388
436
|
{...rest}
|
|
389
437
|
id={id}
|
|
438
|
+
fixed
|
|
390
439
|
key={index}
|
|
391
440
|
className={className}
|
|
392
|
-
customTheme={theme}
|
|
441
|
+
customTheme={rest.customTheme || theme}
|
|
393
442
|
intent={intent}
|
|
394
443
|
onClick={
|
|
395
444
|
rest.onClick
|
|
@@ -494,27 +543,39 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
494
543
|
</>
|
|
495
544
|
) : null}
|
|
496
545
|
</StyledPanelTitleHeader>
|
|
497
|
-
|
|
498
|
-
{
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
546
|
+
{hasResponsiveActions(actions) && (
|
|
547
|
+
<ReqoreControlGroup responsive fluid horizontalAlign='flex-end' customTheme={theme}>
|
|
548
|
+
{actions.map(renderResponsiveActions)}
|
|
549
|
+
</ReqoreControlGroup>
|
|
550
|
+
)}
|
|
551
|
+
{collapsible || onClose || hasNonResponsiveActions(actions) ? (
|
|
552
|
+
<>
|
|
553
|
+
<ReqoreHorizontalSpacer width={GAP_FROM_SIZE.normal} />
|
|
554
|
+
<ReqoreControlGroup fixed horizontalAlign='flex-end'>
|
|
555
|
+
{actions.map(renderNonResponsiveActions)}
|
|
556
|
+
{collapsible && (
|
|
557
|
+
<ReqoreButton
|
|
558
|
+
customTheme={theme}
|
|
559
|
+
icon={_isCollapsed ? 'ArrowDownSLine' : 'ArrowUpSLine'}
|
|
560
|
+
onClick={handleCollapseClick}
|
|
561
|
+
tooltip={_isCollapsed ? 'Expand' : 'Collapse'}
|
|
562
|
+
fixed
|
|
563
|
+
/>
|
|
564
|
+
)}
|
|
565
|
+
{onClose && (
|
|
566
|
+
<ReqoreButton
|
|
567
|
+
fixed
|
|
568
|
+
customTheme={theme}
|
|
569
|
+
icon='CloseLine'
|
|
570
|
+
onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
|
|
571
|
+
e.stopPropagation();
|
|
572
|
+
onClose?.();
|
|
573
|
+
}}
|
|
574
|
+
/>
|
|
575
|
+
)}
|
|
576
|
+
</ReqoreControlGroup>
|
|
577
|
+
</>
|
|
578
|
+
) : null}
|
|
518
579
|
</StyledPanelTitle>
|
|
519
580
|
)}
|
|
520
581
|
{!_isCollapsed || (_isCollapsed && !unMountContentOnCollapse) ? (
|
|
@@ -540,8 +601,32 @@ export const ReqorePanel = forwardRef<HTMLDivElement, IReqorePanelProps>(
|
|
|
540
601
|
opacity={opacity ?? (minimal ? 0 : 1)}
|
|
541
602
|
noHorizontalPadding={noHorizontalPadding}
|
|
542
603
|
>
|
|
543
|
-
|
|
544
|
-
|
|
604
|
+
{hasNonResponsiveActions(leftBottomActions) ? (
|
|
605
|
+
<>
|
|
606
|
+
<ReqoreControlGroup>
|
|
607
|
+
{leftBottomActions.map(renderNonResponsiveActions)}
|
|
608
|
+
</ReqoreControlGroup>
|
|
609
|
+
<ReqoreHorizontalSpacer width={GAP_FROM_SIZE.normal} />
|
|
610
|
+
</>
|
|
611
|
+
) : null}
|
|
612
|
+
{hasResponsiveActions(leftBottomActions) && (
|
|
613
|
+
<ReqoreControlGroup fluid responsive customTheme={theme}>
|
|
614
|
+
{leftBottomActions.map(renderResponsiveActions)}
|
|
615
|
+
</ReqoreControlGroup>
|
|
616
|
+
)}
|
|
617
|
+
{hasResponsiveActions(rightBottomActions) && (
|
|
618
|
+
<ReqoreControlGroup fluid horizontalAlign='flex-end' responsive customTheme={theme}>
|
|
619
|
+
{rightBottomActions.map(renderResponsiveActions)}
|
|
620
|
+
</ReqoreControlGroup>
|
|
621
|
+
)}
|
|
622
|
+
{hasNonResponsiveActions(rightBottomActions) ? (
|
|
623
|
+
<>
|
|
624
|
+
<ReqoreHorizontalSpacer width={GAP_FROM_SIZE.normal} />
|
|
625
|
+
<ReqoreControlGroup horizontalAlign='flex-end'>
|
|
626
|
+
{rightBottomActions.map(renderNonResponsiveActions)}
|
|
627
|
+
</ReqoreControlGroup>
|
|
628
|
+
</>
|
|
629
|
+
) : null}
|
|
545
630
|
</StyledPanelBottomActions>
|
|
546
631
|
) : null}
|
|
547
632
|
</StyledPanel>
|