@qoretechnologies/reqore 0.29.8 → 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__/popover.test.tsx +24 -2
- package/__tests__/tabs.test.tsx +32 -0
- package/dist/components/Button/index.js +6 -6
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/Collection/index.d.ts +3 -2
- package/dist/components/Collection/index.d.ts.map +1 -1
- package/dist/components/Collection/index.js +19 -44
- package/dist/components/Collection/index.js.map +1 -1
- package/dist/components/Collection/item.d.ts +2 -3
- package/dist/components/Collection/item.d.ts.map +1 -1
- package/dist/components/Collection/item.js +8 -4
- package/dist/components/Collection/item.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 +7 -4
- package/dist/components/ControlGroup/index.d.ts.map +1 -1
- package/dist/components/ControlGroup/index.js +118 -22
- 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/Icon/index.d.ts +3 -5
- package/dist/components/Icon/index.d.ts.map +1 -1
- package/dist/components/Icon/index.js +10 -6
- package/dist/components/Icon/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 +6 -3
- package/dist/components/Panel/index.d.ts.map +1 -1
- package/dist/components/Panel/index.js +64 -32
- 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/content.d.ts +3 -1
- package/dist/components/Tabs/content.d.ts.map +1 -1
- package/dist/components/Tabs/content.js +8 -3
- package/dist/components/Tabs/content.js.map +1 -1
- package/dist/components/Tabs/index.d.ts +4 -1
- package/dist/components/Tabs/index.d.ts.map +1 -1
- package/dist/components/Tabs/index.js +12 -4
- package/dist/components/Tabs/index.js.map +1 -1
- package/dist/components/Tabs/item.d.ts +1 -0
- package/dist/components/Tabs/item.d.ts.map +1 -1
- package/dist/components/Tabs/item.js +7 -7
- package/dist/components/Tabs/item.js.map +1 -1
- package/dist/components/Tabs/list.d.ts +1 -1
- package/dist/components/Tabs/list.d.ts.map +1 -1
- package/dist/components/Tabs/list.js +3 -2
- package/dist/components/Tabs/list.js.map +1 -1
- package/dist/components/Tag/index.d.ts +3 -2
- package/dist/components/Tag/index.d.ts.map +1 -1
- package/dist/components/Tag/index.js +10 -2
- 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/constants/sizes.js +7 -7
- package/dist/containers/PopoverProvider.js +3 -3
- package/dist/containers/PopoverProvider.js.map +1 -1
- package/dist/containers/ReqoreProvider.d.ts.map +1 -1
- package/dist/containers/ReqoreProvider.js +1 -0
- package/dist/containers/ReqoreProvider.js.map +1 -1
- package/dist/containers/UIProvider.d.ts +7 -0
- package/dist/containers/UIProvider.d.ts.map +1 -1
- package/dist/containers/UIProvider.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.map +1 -1
- package/dist/hooks/usePopover.d.ts.map +1 -1
- package/dist/hooks/usePopover.js +4 -2
- package/dist/hooks/usePopover.js.map +1 -1
- package/dist/types/global.d.ts +13 -0
- package/dist/types/global.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/components/Button/index.tsx +2 -2
- package/src/components/Collection/index.tsx +29 -39
- package/src/components/Collection/item.tsx +14 -6
- package/src/components/Columns/column.tsx +1 -0
- package/src/components/ControlGroup/index.tsx +390 -227
- package/src/components/Drawer/index.tsx +6 -4
- package/src/components/Effect/index.tsx +1 -0
- package/src/components/Icon/index.tsx +78 -62
- 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 +171 -77
- package/src/components/Spacer/index.tsx +63 -14
- package/src/components/Tabs/content.tsx +11 -3
- package/src/components/Tabs/index.tsx +14 -3
- package/src/components/Tabs/item.tsx +24 -1
- package/src/components/Tabs/list.tsx +3 -0
- package/src/components/Tag/index.tsx +30 -23
- package/src/components/Tree/index.tsx +1 -1
- package/src/constants/animations.ts +1 -1
- package/src/constants/sizes.ts +7 -7
- package/src/containers/PopoverProvider.tsx +3 -3
- package/src/containers/ReqoreProvider.tsx +1 -0
- package/src/containers/UIProvider.tsx +7 -0
- package/src/context/ReqoreContext.tsx +1 -0
- package/src/hooks/usePopover.tsx +4 -2
- package/src/mock/collectionData.tsx +21 -1
- package/src/stories/ControlGroup/ControlGroup.stories.tsx +68 -6
- package/src/stories/Icon/Icon.stories.tsx +1 -0
- package/src/stories/Input/Input.stories.tsx +2 -1
- package/src/stories/Panel/Panel.stories.tsx +83 -2
- package/src/stories/Popover/Popover.stories.tsx +5 -5
- package/src/stories/Tabs/Tabs.stories.tsx +30 -14
- package/src/stories/Tag/Tag.stories.tsx +12 -2
- package/src/types/global.ts +14 -0
- 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,16 +19,21 @@ 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
|
|
25
33
|
*/
|
|
26
34
|
vertical?: boolean;
|
|
35
|
+
verticalAlign?: 'flex-start' | 'center' | 'flex-end';
|
|
36
|
+
horizontalAlign?: 'flex-start' | 'center' | 'flex-end';
|
|
27
37
|
wrap?: boolean;
|
|
28
38
|
isInsideStackGroup?: boolean;
|
|
29
39
|
isInsideVerticalGroup?: boolean;
|
|
@@ -46,162 +56,211 @@ export interface IReqoreControlGroupStyle extends IReqoreControlGroupProps {
|
|
|
46
56
|
export const StyledReqoreControlGroup = styled.div<IReqoreControlGroupStyle>`
|
|
47
57
|
display: flex;
|
|
48
58
|
flex: 0 auto;
|
|
49
|
-
width: ${({ fluid }) => (fluid ? '100%' : undefined)};
|
|
50
|
-
|
|
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};
|
|
51
63
|
flex-flow: ${({ vertical }) => (vertical ? 'column' : 'row')};
|
|
52
64
|
gap: ${({ gapSize, stack }) => (!stack ? `${GAP_FROM_SIZE[gapSize]}px` : undefined)};
|
|
53
65
|
flex-wrap: ${({ wrap }) => (wrap ? 'wrap' : 'nowrap')};
|
|
54
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
|
+
|
|
55
91
|
> * {
|
|
56
92
|
border-radius: ${({ stack }) => (!stack ? undefined : 0)};
|
|
57
93
|
}
|
|
58
94
|
`;
|
|
59
95
|
|
|
60
96
|
const ReqoreControlGroup = memo(
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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
|
-
|
|
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++;
|
|
106
152
|
}
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
countChildren(children);
|
|
110
|
-
|
|
111
|
-
return count < 0 ? 0 : count;
|
|
112
|
-
}, [children]);
|
|
113
|
-
|
|
114
|
-
const getIsFirst = (index: number): boolean => {
|
|
115
|
-
return !isInsideStackGroup || childrenCount === 1
|
|
116
|
-
? index === 0
|
|
117
|
-
: (isFirst || isFirst !== false) && index === 0;
|
|
118
|
-
};
|
|
119
|
-
const getIsLast = (index: number): boolean => {
|
|
120
|
-
return !isInsideStackGroup
|
|
121
|
-
? index === realChildCount - 1
|
|
122
|
-
: (isLast || isLast !== false) && index === realChildCount - 1;
|
|
123
|
-
};
|
|
124
|
-
const getIsLastInFirstGroup = (index: number): boolean => {
|
|
125
|
-
return !isInsideStackGroup
|
|
126
|
-
? index === 0
|
|
127
|
-
: isFirstGroup && (isLast || isLast !== false) && index === realChildCount - 1;
|
|
128
|
-
};
|
|
129
|
-
const getIsFirstInLastGroup = (index: number): boolean => {
|
|
130
|
-
return !isInsideStackGroup
|
|
131
|
-
? index === realChildCount - 1
|
|
132
|
-
: isLastGroup && (isFirst || isFirst !== false) && childId === 1 && index === 0;
|
|
133
|
-
};
|
|
134
|
-
const getIsLastInLastGroup = (index: number): boolean => {
|
|
135
|
-
return !isInsideStackGroup
|
|
136
|
-
? index === realChildCount - 1
|
|
137
|
-
: isLastGroup && (isLast || isLast !== false) && index === realChildCount - 1;
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
const getBorderTopLeftRadius = (index: number): number | undefined => {
|
|
141
|
-
const _isFirstGroup =
|
|
142
|
-
!isInsideStackGroup || childrenCount === 1 ? true : isChild ? isFirstGroup : index === 0;
|
|
143
|
-
|
|
144
|
-
// If this is the first item
|
|
145
|
-
if (_isFirstGroup && getIsFirst(index)) {
|
|
146
|
-
return RADIUS_FROM_SIZE[size];
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
return undefined;
|
|
150
|
-
};
|
|
151
|
-
|
|
152
|
-
const getBorderTopRightRadius = (index: number): number | undefined => {
|
|
153
|
-
// If this group is not vertical we need to style the very last item
|
|
154
|
-
if (!isVertical || !isStack) {
|
|
155
|
-
const _isLastGroup =
|
|
156
|
-
!isInsideStackGroup || childrenCount === 1
|
|
157
|
-
? true
|
|
158
|
-
: isChild
|
|
159
|
-
? isLastGroup
|
|
160
|
-
: index === realChildCount - 1;
|
|
161
|
-
|
|
162
|
-
if (_isLastGroup && getIsLast(index)) {
|
|
163
|
-
return RADIUS_FROM_SIZE[size];
|
|
164
153
|
}
|
|
154
|
+
});
|
|
165
155
|
|
|
166
|
-
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
// This border only needs to apply when this group is vertical
|
|
170
|
-
// AND this item is the last item of the first group
|
|
171
|
-
if (getIsLastInFirstGroup(index)) {
|
|
172
|
-
return RADIUS_FROM_SIZE[size];
|
|
173
|
-
}
|
|
156
|
+
countChildren(children);
|
|
174
157
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
const getBorderBottomLeftRadius = (index: number): number | undefined => {
|
|
179
|
-
// If this group is not vertical we need to style the very first item
|
|
180
|
-
if (!isVertical || !isStack) {
|
|
181
|
-
const _isFirstGroup =
|
|
182
|
-
!isInsideStackGroup || childrenCount === 1
|
|
183
|
-
? true
|
|
184
|
-
: isChild
|
|
185
|
-
? isFirstGroup
|
|
186
|
-
: index === 0;
|
|
187
|
-
|
|
188
|
-
if (_isFirstGroup && getIsFirst(index)) {
|
|
189
|
-
return RADIUS_FROM_SIZE[size];
|
|
190
|
-
}
|
|
158
|
+
return count < 0 ? 0 : count;
|
|
159
|
+
}, [children]);
|
|
191
160
|
|
|
192
|
-
|
|
193
|
-
|
|
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
|
+
});
|
|
194
192
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
if (getIsFirstInLastGroup(index)) {
|
|
198
|
-
return RADIUS_FROM_SIZE[size];
|
|
193
|
+
observer.current.observe(ref.current);
|
|
194
|
+
resizeTimerObserver.current.observe(ref.current);
|
|
199
195
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
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) {
|
|
205
264
|
const _isLastGroup =
|
|
206
265
|
!isInsideStackGroup || childrenCount === 1
|
|
207
266
|
? true
|
|
@@ -209,117 +268,221 @@ const ReqoreControlGroup = memo(
|
|
|
209
268
|
? isLastGroup
|
|
210
269
|
: index === realChildCount - 1;
|
|
211
270
|
|
|
212
|
-
// If this is the last item
|
|
213
271
|
if (_isLastGroup && getIsLast(index)) {
|
|
214
272
|
return RADIUS_FROM_SIZE[size];
|
|
215
273
|
}
|
|
216
274
|
|
|
217
275
|
return undefined;
|
|
218
|
-
}
|
|
276
|
+
}
|
|
219
277
|
|
|
220
|
-
|
|
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
|
+
}
|
|
221
283
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
return React.Children.map(children, (child) => {
|
|
225
|
-
if (child && React.isValidElement(child)) {
|
|
226
|
-
if (child.type === React.Fragment) {
|
|
227
|
-
// just compare to `React.Fragment`
|
|
228
|
-
return cloneThroughFragments(child.props.children);
|
|
229
|
-
}
|
|
284
|
+
return undefined;
|
|
285
|
+
};
|
|
230
286
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
? child.props.minimal
|
|
237
|
-
: minimal,
|
|
238
|
-
size: child.props?.size || size,
|
|
239
|
-
flat: child.props?.flat || child.props?.flat === false ? child.props.flat : flat,
|
|
240
|
-
fluid:
|
|
241
|
-
child.props?.fluid || child.props?.fluid === false ? child.props.fluid : fluid,
|
|
242
|
-
stack:
|
|
243
|
-
child.props?.stack || child.props?.stack === false ? child.props.stack : isStack,
|
|
244
|
-
intent: child.props?.intent || intent,
|
|
245
|
-
};
|
|
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;
|
|
246
292
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
style: {
|
|
251
|
-
borderTopLeftRadius: getBorderTopLeftRadius(index),
|
|
252
|
-
borderBottomLeftRadius: getBorderBottomLeftRadius(index),
|
|
253
|
-
borderTopRightRadius: getBorderTopRightRadius(index),
|
|
254
|
-
borderBottomRightRadius: getBorderBottomRightRadius(index),
|
|
255
|
-
...(child.props?.style || {}),
|
|
256
|
-
},
|
|
257
|
-
rounded: !isStack,
|
|
258
|
-
isInsideStackGroup: isStack,
|
|
259
|
-
isInsideVerticalGroup: isVertical,
|
|
260
|
-
isFirst: isChild ? getIsFirst(index) : undefined,
|
|
261
|
-
isLast: isChild ? getIsLast(index) : undefined,
|
|
262
|
-
isLastInFirstGroup: getIsLastInFirstGroup(index),
|
|
263
|
-
isLastInLastGroup: getIsLastInLastGroup(index),
|
|
264
|
-
isFirstInLastGroup: getIsFirstInLastGroup(index),
|
|
265
|
-
childrenCount: realChildCount,
|
|
266
|
-
childId: index + 1,
|
|
267
|
-
isChild: true,
|
|
268
|
-
isFirstGroup: isChild ? isFirstGroup : index === 0,
|
|
269
|
-
isLastGroup: isChild ? isLastGroup : index === realChildCount - 1,
|
|
270
|
-
};
|
|
271
|
-
}
|
|
293
|
+
if (_isFirstGroup && getIsFirst(index)) {
|
|
294
|
+
return RADIUS_FROM_SIZE[size];
|
|
295
|
+
}
|
|
272
296
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
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
|
+
}
|
|
281
335
|
|
|
282
|
-
|
|
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
|
+
};
|
|
283
378
|
}
|
|
284
379
|
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
isLastGroup,
|
|
294
|
-
isFirstGroup,
|
|
295
|
-
realChildCount,
|
|
296
|
-
index,
|
|
297
|
-
fluid,
|
|
298
|
-
flat,
|
|
299
|
-
minimal,
|
|
300
|
-
size,
|
|
301
|
-
intent,
|
|
302
|
-
]
|
|
303
|
-
);
|
|
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;
|
|
304
388
|
|
|
305
|
-
|
|
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}
|
|
306
461
|
<StyledReqoreControlGroup
|
|
307
462
|
{...rest}
|
|
308
463
|
vertical={vertical}
|
|
464
|
+
style={{
|
|
465
|
+
overflowX: responsive ? 'auto' : undefined,
|
|
466
|
+
visibility: isResizing ? 'hidden' : undefined,
|
|
467
|
+
...rest.style,
|
|
468
|
+
}}
|
|
309
469
|
size={size}
|
|
310
470
|
gapSize={gapSize}
|
|
311
471
|
ref={ref}
|
|
312
472
|
rounded={rounded}
|
|
313
473
|
fluid={fluid}
|
|
474
|
+
fixed={fixed}
|
|
314
475
|
wrap={wrap}
|
|
315
476
|
stack={isStack}
|
|
477
|
+
verticalAlign={verticalAlign}
|
|
478
|
+
horizontalAlign={horizontalAlign}
|
|
316
479
|
className={`${className || ''} reqore-control-group`}
|
|
317
480
|
>
|
|
318
|
-
{cloneThroughFragments(
|
|
481
|
+
{cloneThroughFragments(_children)}
|
|
319
482
|
</StyledReqoreControlGroup>
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
483
|
+
</>
|
|
484
|
+
);
|
|
485
|
+
}
|
|
323
486
|
);
|
|
324
487
|
|
|
325
488
|
export default ReqoreControlGroup;
|