@qoretechnologies/reqore 0.29.9 → 0.30.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/__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 +4 -1
- 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 +1 -0
- 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,10 +1,15 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import { debounce } from 'lodash';
|
|
2
|
+
import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
3
|
+
import { useMount, useUnmount } from 'react-use';
|
|
4
|
+
import styled, { css } from 'styled-components';
|
|
5
|
+
import { ReqoreButton, ReqoreModal } from '../..';
|
|
3
6
|
import { GAP_FROM_SIZE, RADIUS_FROM_SIZE, TSizes } from '../../constants/sizes';
|
|
4
7
|
import { IReqoreTheme } from '../../constants/theme';
|
|
5
8
|
import {
|
|
6
9
|
IReqoreIntent,
|
|
10
|
+
IWithReqoreCustomTheme,
|
|
7
11
|
IWithReqoreFlat,
|
|
12
|
+
IWithReqoreFluid,
|
|
8
13
|
IWithReqoreMinimal,
|
|
9
14
|
IWithReqoreSize,
|
|
10
15
|
} from '../../types/global';
|
|
@@ -14,11 +19,14 @@ export interface IReqoreControlGroupProps
|
|
|
14
19
|
IWithReqoreFlat,
|
|
15
20
|
IWithReqoreSize,
|
|
16
21
|
IWithReqoreMinimal,
|
|
17
|
-
IReqoreIntent
|
|
22
|
+
IReqoreIntent,
|
|
23
|
+
IWithReqoreFluid,
|
|
24
|
+
IWithReqoreCustomTheme {
|
|
18
25
|
stack?: boolean;
|
|
19
26
|
children: any;
|
|
20
|
-
|
|
27
|
+
fixed?: boolean;
|
|
21
28
|
rounded?: boolean;
|
|
29
|
+
responsive?: boolean;
|
|
22
30
|
gapSize?: TSizes;
|
|
23
31
|
/*
|
|
24
32
|
* Whether the contents of the control group should be stacked vertically
|
|
@@ -48,167 +56,211 @@ export interface IReqoreControlGroupStyle extends IReqoreControlGroupProps {
|
|
|
48
56
|
export const StyledReqoreControlGroup = styled.div<IReqoreControlGroupStyle>`
|
|
49
57
|
display: flex;
|
|
50
58
|
flex: 0 auto;
|
|
51
|
-
width: ${({ fluid }) => (fluid ? '100%' : undefined)};
|
|
52
|
-
justify-content: ${({ fluid, vertical
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
vertical ? (fluid ? 'stretch' : horizontalAlign) : verticalAlign};
|
|
59
|
+
width: ${({ fluid, fixed }) => (fluid && !fixed ? '100%' : undefined)};
|
|
60
|
+
justify-content: ${({ fluid, vertical }) => (vertical && fluid ? 'stretch' : undefined)};
|
|
61
|
+
align-items: ${({ vertical, fluid, horizontalAlign }) =>
|
|
62
|
+
vertical ? (fluid ? 'stretch' : horizontalAlign) : undefined};
|
|
56
63
|
flex-flow: ${({ vertical }) => (vertical ? 'column' : 'row')};
|
|
57
64
|
gap: ${({ gapSize, stack }) => (!stack ? `${GAP_FROM_SIZE[gapSize]}px` : undefined)};
|
|
58
65
|
flex-wrap: ${({ wrap }) => (wrap ? 'wrap' : 'nowrap')};
|
|
59
66
|
|
|
67
|
+
> * {
|
|
68
|
+
margin-top: ${({ verticalAlign }) =>
|
|
69
|
+
verticalAlign === 'flex-end' || verticalAlign === 'center' ? 'auto' : undefined};
|
|
70
|
+
margin-bottom: ${({ verticalAlign }) =>
|
|
71
|
+
verticalAlign === 'flex-start' || verticalAlign === 'center' ? 'auto' : undefined};
|
|
72
|
+
margin-right: ${({ horizontalAlign }) => (horizontalAlign === 'center' ? 'auto' : undefined)};
|
|
73
|
+
|
|
74
|
+
${({ vertical }) =>
|
|
75
|
+
vertical &&
|
|
76
|
+
css`
|
|
77
|
+
margin-left: ${({ horizontalAlign }) =>
|
|
78
|
+
horizontalAlign === 'flex-end' || horizontalAlign === 'center' ? 'auto' : undefined};
|
|
79
|
+
`}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
${({ vertical }) =>
|
|
83
|
+
!vertical &&
|
|
84
|
+
css`
|
|
85
|
+
> *:first-child {
|
|
86
|
+
margin-left: ${({ horizontalAlign }) =>
|
|
87
|
+
horizontalAlign === 'flex-end' || horizontalAlign === 'center' ? 'auto' : undefined};
|
|
88
|
+
}
|
|
89
|
+
`}
|
|
90
|
+
|
|
60
91
|
> * {
|
|
61
92
|
border-radius: ${({ stack }) => (!stack ? undefined : 0)};
|
|
62
93
|
}
|
|
63
94
|
`;
|
|
64
95
|
|
|
65
96
|
const ReqoreControlGroup = memo(
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
97
|
+
({
|
|
98
|
+
children,
|
|
99
|
+
className,
|
|
100
|
+
minimal,
|
|
101
|
+
size = 'normal',
|
|
102
|
+
gapSize = 'normal',
|
|
103
|
+
fluid,
|
|
104
|
+
flat,
|
|
105
|
+
fixed,
|
|
106
|
+
rounded = true,
|
|
107
|
+
wrap,
|
|
108
|
+
stack,
|
|
109
|
+
isInsideStackGroup,
|
|
110
|
+
isInsideVerticalGroup,
|
|
111
|
+
isFirstInLastGroup,
|
|
112
|
+
isLastInFirstGroup,
|
|
113
|
+
isLastInLastGroup,
|
|
114
|
+
intent,
|
|
115
|
+
customTheme,
|
|
116
|
+
isFirst,
|
|
117
|
+
isLast,
|
|
118
|
+
vertical,
|
|
119
|
+
childrenCount,
|
|
120
|
+
childId,
|
|
121
|
+
isChild,
|
|
122
|
+
isFirstGroup,
|
|
123
|
+
isLastGroup,
|
|
124
|
+
verticalAlign = 'center',
|
|
125
|
+
horizontalAlign = 'flex-start',
|
|
126
|
+
responsive,
|
|
127
|
+
...rest
|
|
128
|
+
}: IReqoreControlGroupProps) => {
|
|
129
|
+
const isStack = stack || isInsideStackGroup;
|
|
130
|
+
const isVertical = vertical || isInsideVerticalGroup;
|
|
131
|
+
|
|
132
|
+
const [overflowingChildren, setOverflowingChildren] = useState<number | undefined>(0);
|
|
133
|
+
const [lastReSize, setLastReSize] = useState<number>(0);
|
|
134
|
+
const [isResizing, setIsResizing] = useState<boolean>(false);
|
|
135
|
+
const [isOverflownDialogOpen, setIsOverflownDialogOpen] = useState<boolean>(false);
|
|
136
|
+
const observer = useRef<ResizeObserver | null>(null);
|
|
137
|
+
const ref = useRef<HTMLDivElement>(null);
|
|
138
|
+
const resizeTimerObserver = useRef<ResizeObserver | null>(null);
|
|
139
|
+
const resizingTimer = useRef<any>(null);
|
|
140
|
+
|
|
141
|
+
const realChildCount = useMemo((): number => {
|
|
142
|
+
let count = 0;
|
|
143
|
+
|
|
144
|
+
const countChildren = (children: React.ReactNode) =>
|
|
145
|
+
React.Children.forEach(children, (child: any) => {
|
|
146
|
+
if (child && React.isValidElement(child)) {
|
|
147
|
+
if (child.type === React.Fragment) {
|
|
148
|
+
// just compare to `React.Fragment`
|
|
149
|
+
countChildren((child.props as any).children);
|
|
150
|
+
} else {
|
|
151
|
+
count++;
|
|
113
152
|
}
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
countChildren(children);
|
|
117
|
-
|
|
118
|
-
return count < 0 ? 0 : count;
|
|
119
|
-
}, [children]);
|
|
120
|
-
|
|
121
|
-
const getIsFirst = (index: number): boolean => {
|
|
122
|
-
return !isInsideStackGroup || childrenCount === 1
|
|
123
|
-
? index === 0
|
|
124
|
-
: (isFirst || isFirst !== false) && index === 0;
|
|
125
|
-
};
|
|
126
|
-
const getIsLast = (index: number): boolean => {
|
|
127
|
-
return !isInsideStackGroup
|
|
128
|
-
? index === realChildCount - 1
|
|
129
|
-
: (isLast || isLast !== false) && index === realChildCount - 1;
|
|
130
|
-
};
|
|
131
|
-
const getIsLastInFirstGroup = (index: number): boolean => {
|
|
132
|
-
return !isInsideStackGroup
|
|
133
|
-
? index === 0
|
|
134
|
-
: isFirstGroup && (isLast || isLast !== false) && index === realChildCount - 1;
|
|
135
|
-
};
|
|
136
|
-
const getIsFirstInLastGroup = (index: number): boolean => {
|
|
137
|
-
return !isInsideStackGroup
|
|
138
|
-
? index === realChildCount - 1
|
|
139
|
-
: isLastGroup && (isFirst || isFirst !== false) && childId === 1 && index === 0;
|
|
140
|
-
};
|
|
141
|
-
const getIsLastInLastGroup = (index: number): boolean => {
|
|
142
|
-
return !isInsideStackGroup
|
|
143
|
-
? index === realChildCount - 1
|
|
144
|
-
: isLastGroup && (isLast || isLast !== false) && index === realChildCount - 1;
|
|
145
|
-
};
|
|
146
|
-
|
|
147
|
-
const getBorderTopLeftRadius = (index: number): number | undefined => {
|
|
148
|
-
const _isFirstGroup =
|
|
149
|
-
!isInsideStackGroup || childrenCount === 1 ? true : isChild ? isFirstGroup : index === 0;
|
|
150
|
-
|
|
151
|
-
// If this is the first item
|
|
152
|
-
if (_isFirstGroup && getIsFirst(index)) {
|
|
153
|
-
return RADIUS_FROM_SIZE[size];
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
return undefined;
|
|
157
|
-
};
|
|
158
|
-
|
|
159
|
-
const getBorderTopRightRadius = (index: number): number | undefined => {
|
|
160
|
-
// If this group is not vertical we need to style the very last item
|
|
161
|
-
if (!isVertical || !isStack) {
|
|
162
|
-
const _isLastGroup =
|
|
163
|
-
!isInsideStackGroup || childrenCount === 1
|
|
164
|
-
? true
|
|
165
|
-
: isChild
|
|
166
|
-
? isLastGroup
|
|
167
|
-
: index === realChildCount - 1;
|
|
168
|
-
|
|
169
|
-
if (_isLastGroup && getIsLast(index)) {
|
|
170
|
-
return RADIUS_FROM_SIZE[size];
|
|
171
153
|
}
|
|
154
|
+
});
|
|
172
155
|
|
|
173
|
-
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
// This border only needs to apply when this group is vertical
|
|
177
|
-
// AND this item is the last item of the first group
|
|
178
|
-
if (getIsLastInFirstGroup(index)) {
|
|
179
|
-
return RADIUS_FROM_SIZE[size];
|
|
180
|
-
}
|
|
156
|
+
countChildren(children);
|
|
181
157
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
const getBorderBottomLeftRadius = (index: number): number | undefined => {
|
|
186
|
-
// If this group is not vertical we need to style the very first item
|
|
187
|
-
if (!isVertical || !isStack) {
|
|
188
|
-
const _isFirstGroup =
|
|
189
|
-
!isInsideStackGroup || childrenCount === 1
|
|
190
|
-
? true
|
|
191
|
-
: isChild
|
|
192
|
-
? isFirstGroup
|
|
193
|
-
: index === 0;
|
|
194
|
-
|
|
195
|
-
if (_isFirstGroup && getIsFirst(index)) {
|
|
196
|
-
return RADIUS_FROM_SIZE[size];
|
|
197
|
-
}
|
|
158
|
+
return count < 0 ? 0 : count;
|
|
159
|
+
}, [children]);
|
|
198
160
|
|
|
199
|
-
|
|
200
|
-
|
|
161
|
+
const checkIfOverflowing = useCallback(() => {
|
|
162
|
+
return (
|
|
163
|
+
ref.current.clientWidth > 40 &&
|
|
164
|
+
!vertical &&
|
|
165
|
+
responsive &&
|
|
166
|
+
ref.current &&
|
|
167
|
+
ref.current.scrollWidth > ref.current.clientWidth
|
|
168
|
+
);
|
|
169
|
+
}, [vertical, responsive, ref, children]);
|
|
170
|
+
|
|
171
|
+
useMount(() => {
|
|
172
|
+
if (!vertical && responsive) {
|
|
173
|
+
if ('ResizeObserver' in window) {
|
|
174
|
+
observer.current = new ResizeObserver(
|
|
175
|
+
debounce(() => {
|
|
176
|
+
if (ref && ref.current) {
|
|
177
|
+
setOverflowingChildren(0);
|
|
178
|
+
setLastReSize(ref.current.clientWidth);
|
|
179
|
+
}
|
|
180
|
+
}, 200)
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
resizeTimerObserver.current = new ResizeObserver(() => {
|
|
184
|
+
if (ref && ref.current) {
|
|
185
|
+
setIsResizing(true);
|
|
186
|
+
clearTimeout(resizingTimer.current);
|
|
187
|
+
resizingTimer.current = setTimeout(() => {
|
|
188
|
+
setIsResizing(false);
|
|
189
|
+
}, 500);
|
|
190
|
+
}
|
|
191
|
+
});
|
|
201
192
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if (getIsFirstInLastGroup(index)) {
|
|
205
|
-
return RADIUS_FROM_SIZE[size];
|
|
193
|
+
observer.current.observe(ref.current);
|
|
194
|
+
resizeTimerObserver.current.observe(ref.current);
|
|
206
195
|
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
useUnmount(() => {
|
|
200
|
+
if (observer.current) {
|
|
201
|
+
observer.current.disconnect();
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
if (resizeTimerObserver.current) {
|
|
205
|
+
resizeTimerObserver.current.disconnect();
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
clearTimeout(resizingTimer.current);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
useEffect(() => {
|
|
212
|
+
// Is the control group still overflowing?
|
|
213
|
+
if ((overflowingChildren || overflowingChildren === 0) && checkIfOverflowing()) {
|
|
214
|
+
setOverflowingChildren(overflowingChildren + 1);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// Hide the dialog if the group was resized and the dialog was open
|
|
218
|
+
if (overflowingChildren === 0) {
|
|
219
|
+
setIsOverflownDialogOpen(false);
|
|
220
|
+
}
|
|
221
|
+
}, [overflowingChildren, lastReSize]);
|
|
222
|
+
|
|
223
|
+
const getIsFirst = (index: number): boolean => {
|
|
224
|
+
return !isInsideStackGroup || childrenCount === 1
|
|
225
|
+
? index === 0
|
|
226
|
+
: (isFirst || isFirst !== false) && index === 0;
|
|
227
|
+
};
|
|
228
|
+
const getIsLast = (index: number): boolean => {
|
|
229
|
+
return !isInsideStackGroup
|
|
230
|
+
? index === realChildCount - 1
|
|
231
|
+
: (isLast || isLast !== false) && index === realChildCount - 1;
|
|
232
|
+
};
|
|
233
|
+
const getIsLastInFirstGroup = (index: number): boolean => {
|
|
234
|
+
return !isInsideStackGroup
|
|
235
|
+
? index === 0
|
|
236
|
+
: isFirstGroup && (isLast || isLast !== false) && index === realChildCount - 1;
|
|
237
|
+
};
|
|
238
|
+
const getIsFirstInLastGroup = (index: number): boolean => {
|
|
239
|
+
return !isInsideStackGroup
|
|
240
|
+
? index === realChildCount - 1
|
|
241
|
+
: isLastGroup && (isFirst || isFirst !== false) && childId === 1 && index === 0;
|
|
242
|
+
};
|
|
243
|
+
const getIsLastInLastGroup = (index: number): boolean => {
|
|
244
|
+
return !isInsideStackGroup
|
|
245
|
+
? index === realChildCount - 1
|
|
246
|
+
: isLastGroup && (isLast || isLast !== false) && index === realChildCount - 1;
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
const getBorderTopLeftRadius = (index: number): number | undefined => {
|
|
250
|
+
const _isFirstGroup =
|
|
251
|
+
!isInsideStackGroup || childrenCount === 1 ? true : isChild ? isFirstGroup : index === 0;
|
|
252
|
+
|
|
253
|
+
// If this is the first item
|
|
254
|
+
if (_isFirstGroup && getIsFirst(index)) {
|
|
255
|
+
return RADIUS_FROM_SIZE[size];
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return undefined;
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
const getBorderTopRightRadius = (index: number): number | undefined => {
|
|
262
|
+
// If this group is not vertical we need to style the very last item
|
|
263
|
+
if (!isVertical || !isStack) {
|
|
212
264
|
const _isLastGroup =
|
|
213
265
|
!isInsideStackGroup || childrenCount === 1
|
|
214
266
|
? true
|
|
@@ -216,119 +268,221 @@ const ReqoreControlGroup = memo(
|
|
|
216
268
|
? isLastGroup
|
|
217
269
|
: index === realChildCount - 1;
|
|
218
270
|
|
|
219
|
-
// If this is the last item
|
|
220
271
|
if (_isLastGroup && getIsLast(index)) {
|
|
221
272
|
return RADIUS_FROM_SIZE[size];
|
|
222
273
|
}
|
|
223
274
|
|
|
224
275
|
return undefined;
|
|
225
|
-
}
|
|
276
|
+
}
|
|
226
277
|
|
|
227
|
-
|
|
278
|
+
// This border only needs to apply when this group is vertical
|
|
279
|
+
// AND this item is the last item of the first group
|
|
280
|
+
if (getIsLastInFirstGroup(index)) {
|
|
281
|
+
return RADIUS_FROM_SIZE[size];
|
|
282
|
+
}
|
|
228
283
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
return React.Children.map(children, (child) => {
|
|
232
|
-
if (child && React.isValidElement(child)) {
|
|
233
|
-
if (child.type === React.Fragment) {
|
|
234
|
-
// just compare to `React.Fragment`
|
|
235
|
-
return cloneThroughFragments(child.props.children);
|
|
236
|
-
}
|
|
284
|
+
return undefined;
|
|
285
|
+
};
|
|
237
286
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
? child.props.minimal
|
|
244
|
-
: minimal,
|
|
245
|
-
size: child.props?.size || size,
|
|
246
|
-
flat: child.props?.flat || child.props?.flat === false ? child.props.flat : flat,
|
|
247
|
-
fluid:
|
|
248
|
-
child.props?.fluid || child.props?.fluid === false ? child.props.fluid : fluid,
|
|
249
|
-
stack:
|
|
250
|
-
child.props?.stack || child.props?.stack === false ? child.props.stack : isStack,
|
|
251
|
-
intent: child.props?.intent || intent,
|
|
252
|
-
};
|
|
287
|
+
const getBorderBottomLeftRadius = (index: number): number | undefined => {
|
|
288
|
+
// If this group is not vertical we need to style the very first item
|
|
289
|
+
if (!isVertical || !isStack) {
|
|
290
|
+
const _isFirstGroup =
|
|
291
|
+
!isInsideStackGroup || childrenCount === 1 ? true : isChild ? isFirstGroup : index === 0;
|
|
253
292
|
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
style: {
|
|
258
|
-
borderTopLeftRadius: getBorderTopLeftRadius(index),
|
|
259
|
-
borderBottomLeftRadius: getBorderBottomLeftRadius(index),
|
|
260
|
-
borderTopRightRadius: getBorderTopRightRadius(index),
|
|
261
|
-
borderBottomRightRadius: getBorderBottomRightRadius(index),
|
|
262
|
-
...(child.props?.style || {}),
|
|
263
|
-
},
|
|
264
|
-
rounded: !isStack,
|
|
265
|
-
isInsideStackGroup: isStack,
|
|
266
|
-
isInsideVerticalGroup: isVertical,
|
|
267
|
-
isFirst: isChild ? getIsFirst(index) : undefined,
|
|
268
|
-
isLast: isChild ? getIsLast(index) : undefined,
|
|
269
|
-
isLastInFirstGroup: getIsLastInFirstGroup(index),
|
|
270
|
-
isLastInLastGroup: getIsLastInLastGroup(index),
|
|
271
|
-
isFirstInLastGroup: getIsFirstInLastGroup(index),
|
|
272
|
-
childrenCount: realChildCount,
|
|
273
|
-
childId: index + 1,
|
|
274
|
-
isChild: true,
|
|
275
|
-
isFirstGroup: isChild ? isFirstGroup : index === 0,
|
|
276
|
-
isLastGroup: isChild ? isLastGroup : index === realChildCount - 1,
|
|
277
|
-
};
|
|
278
|
-
}
|
|
293
|
+
if (_isFirstGroup && getIsFirst(index)) {
|
|
294
|
+
return RADIUS_FROM_SIZE[size];
|
|
295
|
+
}
|
|
279
296
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
297
|
+
return undefined;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// This border only needs to apply when this group is vertical
|
|
301
|
+
// AND this item is the first item of the last group
|
|
302
|
+
if (getIsFirstInLastGroup(index)) {
|
|
303
|
+
return RADIUS_FROM_SIZE[size];
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return undefined;
|
|
307
|
+
};
|
|
308
|
+
|
|
309
|
+
const getBorderBottomRightRadius = (index: number): number | undefined => {
|
|
310
|
+
const _isLastGroup =
|
|
311
|
+
!isInsideStackGroup || childrenCount === 1
|
|
312
|
+
? true
|
|
313
|
+
: isChild
|
|
314
|
+
? isLastGroup
|
|
315
|
+
: index === realChildCount - 1;
|
|
316
|
+
|
|
317
|
+
// If this is the last item
|
|
318
|
+
if (_isLastGroup && getIsLast(index)) {
|
|
319
|
+
return RADIUS_FROM_SIZE[size];
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
return undefined;
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
let index = 0;
|
|
326
|
+
|
|
327
|
+
const cloneThroughFragments = useCallback(
|
|
328
|
+
(children: React.ReactNode): React.ReactNode => {
|
|
329
|
+
return React.Children.map(children, (child) => {
|
|
330
|
+
if (child && React.isValidElement(child)) {
|
|
331
|
+
if (child.type === React.Fragment) {
|
|
332
|
+
// just compare to `React.Fragment`
|
|
333
|
+
return cloneThroughFragments(child.props.children);
|
|
334
|
+
}
|
|
288
335
|
|
|
289
|
-
|
|
336
|
+
let newProps = {
|
|
337
|
+
...child.props,
|
|
338
|
+
key: index,
|
|
339
|
+
minimal:
|
|
340
|
+
child.props?.minimal || child.props?.minimal === false
|
|
341
|
+
? child.props.minimal
|
|
342
|
+
: minimal,
|
|
343
|
+
size: child.props?.size || size,
|
|
344
|
+
flat: child.props?.flat || child.props?.flat === false ? child.props.flat : flat,
|
|
345
|
+
fluid: child.props?.fluid || child.props?.fluid === false ? child.props.fluid : fluid,
|
|
346
|
+
fixed: child.props?.fixed || child.props?.fixed === false ? child.props.fixed : fixed,
|
|
347
|
+
stack:
|
|
348
|
+
child.props?.stack || child.props?.stack === false ? child.props.stack : isStack,
|
|
349
|
+
intent: child.props?.intent || intent,
|
|
350
|
+
customTheme: child.props?.customTheme || customTheme,
|
|
351
|
+
};
|
|
352
|
+
|
|
353
|
+
if (isStack) {
|
|
354
|
+
newProps = {
|
|
355
|
+
...newProps,
|
|
356
|
+
style: {
|
|
357
|
+
borderTopLeftRadius: getBorderTopLeftRadius(index),
|
|
358
|
+
borderBottomLeftRadius: getBorderBottomLeftRadius(index),
|
|
359
|
+
borderTopRightRadius: getBorderTopRightRadius(index),
|
|
360
|
+
borderBottomRightRadius: getBorderBottomRightRadius(index),
|
|
361
|
+
...(child.props?.style || {}),
|
|
362
|
+
},
|
|
363
|
+
isChild: true,
|
|
364
|
+
rounded: !isStack,
|
|
365
|
+
isInsideStackGroup: isStack,
|
|
366
|
+
isInsideVerticalGroup: isVertical,
|
|
367
|
+
isFirst: isChild ? getIsFirst(index) : undefined,
|
|
368
|
+
isLast: isChild ? getIsLast(index) : undefined,
|
|
369
|
+
isLastInFirstGroup: getIsLastInFirstGroup(index),
|
|
370
|
+
isLastInLastGroup: getIsLastInLastGroup(index),
|
|
371
|
+
isFirstInLastGroup: getIsFirstInLastGroup(index),
|
|
372
|
+
childrenCount: realChildCount,
|
|
373
|
+
childId: index + 1,
|
|
374
|
+
|
|
375
|
+
isFirstGroup: isChild ? isFirstGroup : index === 0,
|
|
376
|
+
isLastGroup: isChild ? isLastGroup : index === realChildCount - 1,
|
|
377
|
+
};
|
|
290
378
|
}
|
|
291
379
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
isLastGroup,
|
|
301
|
-
isFirstGroup,
|
|
302
|
-
realChildCount,
|
|
303
|
-
index,
|
|
304
|
-
fluid,
|
|
305
|
-
flat,
|
|
306
|
-
minimal,
|
|
307
|
-
size,
|
|
308
|
-
intent,
|
|
309
|
-
]
|
|
310
|
-
);
|
|
380
|
+
/*
|
|
381
|
+
* Because of the way React.Children.map works, we have to
|
|
382
|
+
* manually decrement the index for every child that is `null`
|
|
383
|
+
* because react maps through null children and returns them in `Count`
|
|
384
|
+
* We filter these children out in the `realChildCount` variable,
|
|
385
|
+
* but the index is still incremented
|
|
386
|
+
* */
|
|
387
|
+
index = index + 1;
|
|
311
388
|
|
|
312
|
-
|
|
389
|
+
return React.cloneElement(child, newProps);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
return child;
|
|
393
|
+
});
|
|
394
|
+
},
|
|
395
|
+
[
|
|
396
|
+
children,
|
|
397
|
+
isStack,
|
|
398
|
+
isVertical,
|
|
399
|
+
isChild,
|
|
400
|
+
isLastGroup,
|
|
401
|
+
isFirstGroup,
|
|
402
|
+
realChildCount,
|
|
403
|
+
index,
|
|
404
|
+
fluid,
|
|
405
|
+
flat,
|
|
406
|
+
minimal,
|
|
407
|
+
size,
|
|
408
|
+
intent,
|
|
409
|
+
]
|
|
410
|
+
);
|
|
411
|
+
|
|
412
|
+
// Get the overflown children
|
|
413
|
+
const overflownChildren = useMemo(
|
|
414
|
+
() =>
|
|
415
|
+
overflowingChildren ? React.Children.toArray(children).slice(0, overflowingChildren) : [],
|
|
416
|
+
[children, overflowingChildren]
|
|
417
|
+
);
|
|
418
|
+
|
|
419
|
+
// Remove the overflowing children count from the start of the children array
|
|
420
|
+
const _children = useMemo(
|
|
421
|
+
() =>
|
|
422
|
+
overflowingChildren && responsive
|
|
423
|
+
? [
|
|
424
|
+
children.slice(overflowingChildren),
|
|
425
|
+
<ReqoreButton
|
|
426
|
+
icon='MenuLine'
|
|
427
|
+
customTheme={customTheme}
|
|
428
|
+
tooltip={{
|
|
429
|
+
content: `Show ${React.Children.count(overflownChildren)} hidden items`,
|
|
430
|
+
closeOnAnyClick: true,
|
|
431
|
+
}}
|
|
432
|
+
fixed
|
|
433
|
+
onClick={(e: React.MouseEvent<HTMLButtonElement>) => {
|
|
434
|
+
e.stopPropagation();
|
|
435
|
+
setIsOverflownDialogOpen(true);
|
|
436
|
+
}}
|
|
437
|
+
flat
|
|
438
|
+
/>,
|
|
439
|
+
]
|
|
440
|
+
: children,
|
|
441
|
+
[children, overflowingChildren, responsive, overflownChildren]
|
|
442
|
+
);
|
|
443
|
+
|
|
444
|
+
return (
|
|
445
|
+
<>
|
|
446
|
+
{isOverflownDialogOpen ? (
|
|
447
|
+
<ReqoreModal
|
|
448
|
+
isOpen
|
|
449
|
+
onClose={() => setIsOverflownDialogOpen(false)}
|
|
450
|
+
flat
|
|
451
|
+
minimal
|
|
452
|
+
hasBackdrop={false}
|
|
453
|
+
intent='info'
|
|
454
|
+
label='Hidden items'
|
|
455
|
+
>
|
|
456
|
+
<ReqoreControlGroup fluid wrap>
|
|
457
|
+
{overflownChildren}
|
|
458
|
+
</ReqoreControlGroup>
|
|
459
|
+
</ReqoreModal>
|
|
460
|
+
) : null}
|
|
313
461
|
<StyledReqoreControlGroup
|
|
314
462
|
{...rest}
|
|
315
463
|
vertical={vertical}
|
|
464
|
+
style={{
|
|
465
|
+
overflowX: responsive ? 'auto' : undefined,
|
|
466
|
+
visibility: isResizing ? 'hidden' : undefined,
|
|
467
|
+
...rest.style,
|
|
468
|
+
}}
|
|
316
469
|
size={size}
|
|
317
470
|
gapSize={gapSize}
|
|
318
471
|
ref={ref}
|
|
319
472
|
rounded={rounded}
|
|
320
473
|
fluid={fluid}
|
|
474
|
+
fixed={fixed}
|
|
321
475
|
wrap={wrap}
|
|
322
476
|
stack={isStack}
|
|
323
477
|
verticalAlign={verticalAlign}
|
|
324
478
|
horizontalAlign={horizontalAlign}
|
|
325
479
|
className={`${className || ''} reqore-control-group`}
|
|
326
480
|
>
|
|
327
|
-
{cloneThroughFragments(
|
|
481
|
+
{cloneThroughFragments(_children)}
|
|
328
482
|
</StyledReqoreControlGroup>
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
483
|
+
</>
|
|
484
|
+
);
|
|
485
|
+
}
|
|
332
486
|
);
|
|
333
487
|
|
|
334
488
|
export default ReqoreControlGroup;
|