@vuu-ui/vuu-layout 0.0.27
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/README.md +1 -0
- package/package.json +30 -0
- package/src/Component.css +2 -0
- package/src/Component.tsx +20 -0
- package/src/DraggableLayout.css +18 -0
- package/src/DraggableLayout.tsx +29 -0
- package/src/__tests__/flexbox-utils.spec.js +90 -0
- package/src/action-buttons/action-buttons.css +12 -0
- package/src/action-buttons/action-buttons.tsx +30 -0
- package/src/action-buttons/index.ts +1 -0
- package/src/chest-of-drawers/Chest.css +36 -0
- package/src/chest-of-drawers/Chest.tsx +42 -0
- package/src/chest-of-drawers/Drawer.css +153 -0
- package/src/chest-of-drawers/Drawer.tsx +118 -0
- package/src/chest-of-drawers/index.ts +2 -0
- package/src/common-types.ts +9 -0
- package/src/debug.ts +16 -0
- package/src/dialog/Dialog.css +16 -0
- package/src/dialog/Dialog.tsx +59 -0
- package/src/dialog/index.ts +1 -0
- package/src/drag-drop/BoxModel.ts +546 -0
- package/src/drag-drop/DragState.ts +222 -0
- package/src/drag-drop/Draggable.ts +282 -0
- package/src/drag-drop/DropMenu.css +70 -0
- package/src/drag-drop/DropMenu.tsx +68 -0
- package/src/drag-drop/DropTarget.ts +392 -0
- package/src/drag-drop/DropTargetRenderer.css +40 -0
- package/src/drag-drop/DropTargetRenderer.tsx +284 -0
- package/src/drag-drop/dragDropTypes.ts +49 -0
- package/src/drag-drop/index.ts +4 -0
- package/src/editable-label/EditableLabel.css +28 -0
- package/src/editable-label/EditableLabel.tsx +99 -0
- package/src/editable-label/index.ts +1 -0
- package/src/flexbox/Flexbox.css +45 -0
- package/src/flexbox/Flexbox.tsx +70 -0
- package/src/flexbox/FlexboxLayout.jsx +26 -0
- package/src/flexbox/FluidGrid.css +134 -0
- package/src/flexbox/FluidGrid.tsx +84 -0
- package/src/flexbox/FluidGridLayout.tsx +10 -0
- package/src/flexbox/Splitter.css +140 -0
- package/src/flexbox/Splitter.tsx +135 -0
- package/src/flexbox/flexbox-utils.ts +128 -0
- package/src/flexbox/flexboxTypes.ts +63 -0
- package/src/flexbox/index.ts +4 -0
- package/src/flexbox/useResponsiveSizing.ts +85 -0
- package/src/flexbox/useSplitterResizing.ts +272 -0
- package/src/index.ts +20 -0
- package/src/layout-action.ts +21 -0
- package/src/layout-header/ActionButton.tsx +23 -0
- package/src/layout-header/Header.css +8 -0
- package/src/layout-header/Header.tsx +222 -0
- package/src/layout-header/index.ts +1 -0
- package/src/layout-provider/LayoutProvider.tsx +160 -0
- package/src/layout-provider/LayoutProviderContext.ts +17 -0
- package/src/layout-provider/index.ts +2 -0
- package/src/layout-provider/useLayoutDragDrop.ts +241 -0
- package/src/layout-reducer/flexUtils.ts +281 -0
- package/src/layout-reducer/index.ts +4 -0
- package/src/layout-reducer/insert-layout-element.ts +365 -0
- package/src/layout-reducer/layout-reducer.ts +255 -0
- package/src/layout-reducer/layoutTypes.ts +151 -0
- package/src/layout-reducer/layoutUtils.ts +302 -0
- package/src/layout-reducer/remove-layout-element.ts +240 -0
- package/src/layout-reducer/replace-layout-element.ts +118 -0
- package/src/layout-reducer/resize-flex-children.ts +56 -0
- package/src/layout-reducer/wrap-layout-element.ts +317 -0
- package/src/layout-view/View.css +58 -0
- package/src/layout-view/View.tsx +149 -0
- package/src/layout-view/ViewContext.ts +31 -0
- package/src/layout-view/index.ts +4 -0
- package/src/layout-view/useView.tsx +104 -0
- package/src/layout-view/useViewActionDispatcher.ts +133 -0
- package/src/layout-view/useViewResize.ts +53 -0
- package/src/layout-view/viewTypes.ts +37 -0
- package/src/palette/Palette.css +37 -0
- package/src/palette/Palette.tsx +140 -0
- package/src/palette/PaletteUitk.css +9 -0
- package/src/palette/PaletteUitk.tsx +79 -0
- package/src/palette/index.ts +2 -0
- package/src/placeholder/Placeholder.css +10 -0
- package/src/placeholder/Placeholder.tsx +39 -0
- package/src/placeholder/index.ts +1 -0
- package/src/registry/ComponentRegistry.ts +35 -0
- package/src/registry/index.ts +1 -0
- package/src/responsive/OverflowMenu.css +31 -0
- package/src/responsive/OverflowMenu.jsx +56 -0
- package/src/responsive/breakpoints.ts +48 -0
- package/src/responsive/index.ts +4 -0
- package/src/responsive/measureMinimumNodeSize.ts +23 -0
- package/src/responsive/overflowUtils.js +14 -0
- package/src/responsive/use-breakpoints.ts +100 -0
- package/src/responsive/useOverflowObserver.ts +606 -0
- package/src/responsive/useResizeObserver.ts +154 -0
- package/src/responsive/utils.ts +37 -0
- package/src/stack/Stack.css +39 -0
- package/src/stack/Stack.tsx +160 -0
- package/src/stack/StackLayout.tsx +137 -0
- package/src/stack/index.ts +3 -0
- package/src/stack/stackTypes.ts +19 -0
- package/src/tabs/TabPanel.css +12 -0
- package/src/tabs/TabPanel.tsx +17 -0
- package/src/tabs/index.ts +1 -0
- package/src/tools/config-wrapper/ConfigWrapper.jsx +53 -0
- package/src/tools/config-wrapper/index.js +1 -0
- package/src/tools/devtools-box/layout-configurator.css +112 -0
- package/src/tools/devtools-box/layout-configurator.jsx +369 -0
- package/src/tools/devtools-tree/layout-tree-viewer.css +15 -0
- package/src/tools/devtools-tree/layout-tree-viewer.jsx +36 -0
- package/src/tools/index.js +3 -0
- package/src/use-persistent-state.ts +115 -0
- package/src/utils/componentFromLayout.tsx +30 -0
- package/src/utils/index.ts +6 -0
- package/src/utils/pathUtils.ts +294 -0
- package/src/utils/propUtils.ts +24 -0
- package/src/utils/refUtils.ts +16 -0
- package/src/utils/styleUtils.ts +14 -0
- package/src/utils/typeOf.ts +22 -0
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import React, { ReactElement } from 'react';
|
|
2
|
+
import { createPlaceHolder } from './flexUtils';
|
|
3
|
+
import { swapChild } from './replace-layout-element';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
followPath,
|
|
7
|
+
followPathToParent,
|
|
8
|
+
getProp,
|
|
9
|
+
getProps,
|
|
10
|
+
nextStep,
|
|
11
|
+
resetPath,
|
|
12
|
+
typeOf
|
|
13
|
+
} from '../utils';
|
|
14
|
+
import { RemoveAction } from './layoutTypes';
|
|
15
|
+
|
|
16
|
+
export function removeChild(layoutRoot: ReactElement, { path }: RemoveAction) {
|
|
17
|
+
const target = followPath(layoutRoot, path!) as ReactElement;
|
|
18
|
+
let targetParent = followPathToParent(layoutRoot, path!);
|
|
19
|
+
if (targetParent === null) {
|
|
20
|
+
return layoutRoot;
|
|
21
|
+
}
|
|
22
|
+
const { children } = getProps(targetParent);
|
|
23
|
+
if (children.length > 1 && allOtherChildrenArePlaceholders(children, path)) {
|
|
24
|
+
// eslint-disable-next-line no-unused-vars
|
|
25
|
+
const {
|
|
26
|
+
style: { flexBasis, display, flexDirection, ...style }
|
|
27
|
+
} = getProps(targetParent);
|
|
28
|
+
let containerPath = getProp(targetParent, 'path');
|
|
29
|
+
let newLayout = swapChild(
|
|
30
|
+
layoutRoot,
|
|
31
|
+
targetParent,
|
|
32
|
+
createPlaceHolder(containerPath, flexBasis, style)
|
|
33
|
+
);
|
|
34
|
+
// eslint-disable-next-line no-cond-assign
|
|
35
|
+
while ((targetParent = followPathToParent(newLayout, containerPath))) {
|
|
36
|
+
if (getProp(targetParent, 'path') === '0') {
|
|
37
|
+
break;
|
|
38
|
+
}
|
|
39
|
+
const { children } = getProps(targetParent);
|
|
40
|
+
if (allOtherChildrenArePlaceholders(children)) {
|
|
41
|
+
containerPath = getProp(targetParent, 'path');
|
|
42
|
+
// eslint-disable-next-line no-unused-vars
|
|
43
|
+
const {
|
|
44
|
+
style: { flexBasis, display, flexDirection, ...style }
|
|
45
|
+
} = getProps(targetParent);
|
|
46
|
+
newLayout = swapChild(
|
|
47
|
+
layoutRoot,
|
|
48
|
+
targetParent,
|
|
49
|
+
createPlaceHolder(containerPath, flexBasis, style)
|
|
50
|
+
);
|
|
51
|
+
} else if (hasAdjacentPlaceholders(children)) {
|
|
52
|
+
newLayout = collapsePlaceholders(layoutRoot, targetParent as ReactElement);
|
|
53
|
+
// } else if (hasRedundantPlaceholders(children)){
|
|
54
|
+
/*
|
|
55
|
+
We may have redundany placeholders for example where we have a tower containing a Terrace and a placeholder
|
|
56
|
+
If all the components bordering on the lower placeholder are themselves placeholders, the lower placeholder
|
|
57
|
+
is redundant
|
|
58
|
+
*/
|
|
59
|
+
} else {
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return newLayout;
|
|
64
|
+
// return removeChild(rootProps, {path: targetParent.props.path});
|
|
65
|
+
// return removeChildAndPlaceholder(rootProps, {path: targetParent.props.path});
|
|
66
|
+
} else {
|
|
67
|
+
return _removeChild(layoutRoot, target);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function _removeChild(container: ReactElement, child: ReactElement): ReactElement {
|
|
72
|
+
let { active, children: componentChildren, path, preserve } = getProps(container);
|
|
73
|
+
const { idx, finalStep } = nextStep(path, getProp(child, 'path'));
|
|
74
|
+
const type = typeOf(container) as string;
|
|
75
|
+
let children = componentChildren.slice() as ReactElement[];
|
|
76
|
+
if (finalStep) {
|
|
77
|
+
children.splice(idx, 1);
|
|
78
|
+
if (active !== undefined && active >= idx) {
|
|
79
|
+
active = Math.max(0, active - 1);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
if (children.length === 1 && !preserve && path !== '0' && type.match(/Flexbox|Stack/)) {
|
|
83
|
+
return unwrap(container, children[0]);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Not 100% sure we should do this, unless configured to
|
|
87
|
+
if (!children.some(isFlexible) && children.some(canBeMadeFlexible)) {
|
|
88
|
+
children = makeFlexible(children);
|
|
89
|
+
}
|
|
90
|
+
} else {
|
|
91
|
+
children[idx] = _removeChild(children[idx], child) as ReactElement;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
children = children.map((child, i) => resetPath(child, `${path}.${i}`));
|
|
95
|
+
return React.cloneElement(container, { active }, children);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function unwrap(container: ReactElement, child: ReactElement) {
|
|
99
|
+
const type = typeOf(container);
|
|
100
|
+
const {
|
|
101
|
+
path,
|
|
102
|
+
style: { flexBasis, flexGrow, flexShrink, width, height }
|
|
103
|
+
} = getProps(container);
|
|
104
|
+
|
|
105
|
+
let unwrappedChild = resetPath(child, path);
|
|
106
|
+
if (path === '0') {
|
|
107
|
+
unwrappedChild = React.cloneElement(unwrappedChild, {
|
|
108
|
+
style: {
|
|
109
|
+
...child.props.style,
|
|
110
|
+
width,
|
|
111
|
+
height
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
} else if (type === 'Flexbox') {
|
|
115
|
+
const dim = container.props.style.flexDirection === 'column' ? 'height' : 'width';
|
|
116
|
+
const {
|
|
117
|
+
// eslint-disable-next-line no-unused-vars
|
|
118
|
+
style: { [dim]: size, ...style }
|
|
119
|
+
} = unwrappedChild.props;
|
|
120
|
+
// Need to overwrite key
|
|
121
|
+
unwrappedChild = React.cloneElement(unwrappedChild, {
|
|
122
|
+
// Need to assign key
|
|
123
|
+
flexFill: undefined,
|
|
124
|
+
style: {
|
|
125
|
+
...style,
|
|
126
|
+
// flexFill, if present described the childs relationship to the doomed flexbox,
|
|
127
|
+
// must not be applied to new parent
|
|
128
|
+
flexGrow,
|
|
129
|
+
flexShrink,
|
|
130
|
+
flexBasis,
|
|
131
|
+
width,
|
|
132
|
+
height
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return unwrappedChild;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function isFlexible(element: ReactElement) {
|
|
140
|
+
return element.props.style.flexGrow > 0;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function canBeMadeFlexible(element: ReactElement) {
|
|
144
|
+
const { width, height, flexGrow } = element.props.style;
|
|
145
|
+
return flexGrow === 0 && typeof width !== 'number' && typeof height !== 'number';
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function makeFlexible(children: ReactElement[]) {
|
|
149
|
+
return children.map((child) =>
|
|
150
|
+
canBeMadeFlexible(child)
|
|
151
|
+
? React.cloneElement(child, {
|
|
152
|
+
style: {
|
|
153
|
+
...child.props.style,
|
|
154
|
+
flexGrow: 1
|
|
155
|
+
}
|
|
156
|
+
})
|
|
157
|
+
: child
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const hasAdjacentPlaceholders = (children: ReactElement[]) => {
|
|
162
|
+
if (children && children.length > 0) {
|
|
163
|
+
let wasPlaceholder = getProp(children[0], 'placeholder');
|
|
164
|
+
let isPlaceholder = false;
|
|
165
|
+
for (let i = 1; i < children.length; i++) {
|
|
166
|
+
isPlaceholder = getProp(children[i], 'placeholder');
|
|
167
|
+
if (wasPlaceholder && isPlaceholder) {
|
|
168
|
+
return true;
|
|
169
|
+
}
|
|
170
|
+
wasPlaceholder = isPlaceholder;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
const collapsePlaceholders = (container: ReactElement, target: ReactElement) => {
|
|
176
|
+
let { children: componentChildren, path } = getProps(container);
|
|
177
|
+
const { idx, finalStep } = nextStep(path, getProp(target, 'path'));
|
|
178
|
+
let children = componentChildren.slice() as ReactElement[];
|
|
179
|
+
if (finalStep) {
|
|
180
|
+
children[idx] = _collapsePlaceHolders(target);
|
|
181
|
+
} else {
|
|
182
|
+
children[idx] = collapsePlaceholders(children[idx], target) as ReactElement;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
children = children.map((child, i) => resetPath(child, `${path}.${i}`));
|
|
186
|
+
return React.cloneElement(container, undefined, children);
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
const _collapsePlaceHolders = (container: ReactElement) => {
|
|
190
|
+
const { children } = getProps(container);
|
|
191
|
+
const newChildren = [];
|
|
192
|
+
const placeholders: ReactElement[] = [];
|
|
193
|
+
|
|
194
|
+
for (let i = 0; i < children.length; i++) {
|
|
195
|
+
if (getProp(children[i], 'placeholder')) {
|
|
196
|
+
placeholders.push(children[i]);
|
|
197
|
+
} else {
|
|
198
|
+
if (placeholders.length === 1) {
|
|
199
|
+
newChildren.push(placeholders.pop());
|
|
200
|
+
} else if (placeholders.length > 0) {
|
|
201
|
+
newChildren.push(mergePlaceholders(placeholders));
|
|
202
|
+
placeholders.length = 0;
|
|
203
|
+
}
|
|
204
|
+
newChildren.push(children[i]);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (placeholders.length === 1) {
|
|
209
|
+
newChildren.push(placeholders.pop());
|
|
210
|
+
} else if (placeholders.length > 0) {
|
|
211
|
+
newChildren.push(mergePlaceholders(placeholders));
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const containerPath = getProp(container, 'path');
|
|
215
|
+
return React.cloneElement(
|
|
216
|
+
container,
|
|
217
|
+
undefined,
|
|
218
|
+
newChildren.map((child, i) => resetPath(child, `${containerPath}.${i}`))
|
|
219
|
+
);
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
const mergePlaceholders = ([placeholder, ...placeholders]: ReactElement[]) => {
|
|
223
|
+
const targetStyle = getProp(placeholder, 'style');
|
|
224
|
+
let { flexBasis, flexGrow, flexShrink } = targetStyle;
|
|
225
|
+
for (let {
|
|
226
|
+
props: { style }
|
|
227
|
+
} of placeholders) {
|
|
228
|
+
flexBasis += style.flexBasis;
|
|
229
|
+
flexGrow = Math.max(flexGrow, style.flexGrow);
|
|
230
|
+
flexShrink = Math.max(flexShrink, style.flexShrink);
|
|
231
|
+
}
|
|
232
|
+
return React.cloneElement(placeholder, {
|
|
233
|
+
style: { ...targetStyle, flexBasis, flexGrow, flexShrink }
|
|
234
|
+
});
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
const allOtherChildrenArePlaceholders = (children: ReactElement[], path?: string) =>
|
|
238
|
+
children.every(
|
|
239
|
+
(child) => getProp(child, 'placeholder') || (path && getProp(child, 'path') === path)
|
|
240
|
+
);
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import React, { ReactElement } from 'react';
|
|
2
|
+
import { getProp, getProps, nextStep } from '../utils';
|
|
3
|
+
import { Action } from '../layout-action';
|
|
4
|
+
import { applyLayoutProps, LayoutProps } from './layoutUtils';
|
|
5
|
+
import { ReplaceAction } from './layoutTypes';
|
|
6
|
+
|
|
7
|
+
export function replaceChild(model: ReactElement, { target, replacement }: ReplaceAction) {
|
|
8
|
+
return _replaceChild(model, target, replacement);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function _replaceChild(
|
|
12
|
+
model: ReactElement,
|
|
13
|
+
child: ReactElement,
|
|
14
|
+
replacement: ReactElement<LayoutProps>
|
|
15
|
+
) {
|
|
16
|
+
const path = getProp(child, 'path');
|
|
17
|
+
const resizeable = getProp(child, 'resizeable');
|
|
18
|
+
const { style } = getProps(child);
|
|
19
|
+
const newChild =
|
|
20
|
+
// applyLayoutProps is a bit heavy here - it supports the scenario
|
|
21
|
+
// where we drop/replace a template. Might want to make it somehow
|
|
22
|
+
// an opt-in option
|
|
23
|
+
applyLayoutProps(
|
|
24
|
+
React.cloneElement(replacement, {
|
|
25
|
+
resizeable,
|
|
26
|
+
style: {
|
|
27
|
+
...style,
|
|
28
|
+
...replacement.props.style
|
|
29
|
+
}
|
|
30
|
+
}),
|
|
31
|
+
path
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
return swapChild(model, child, newChild);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function swapChild(
|
|
38
|
+
model: ReactElement,
|
|
39
|
+
child: ReactElement,
|
|
40
|
+
replacement: ReactElement,
|
|
41
|
+
op?: 'maximize' | 'minimize' | 'restore'
|
|
42
|
+
): ReactElement {
|
|
43
|
+
if (model === child) {
|
|
44
|
+
return replacement as any;
|
|
45
|
+
} else {
|
|
46
|
+
const { idx, finalStep } = nextStep(getProp(model, 'path'), getProp(child, 'path'));
|
|
47
|
+
const children = model.props.children.slice();
|
|
48
|
+
if (finalStep) {
|
|
49
|
+
if (!op) {
|
|
50
|
+
children[idx] = replacement;
|
|
51
|
+
} else if (op === Action.MINIMIZE) {
|
|
52
|
+
children[idx] = minimize(model, children[idx]);
|
|
53
|
+
} else if (op === Action.RESTORE) {
|
|
54
|
+
children[idx] = restore(children[idx]);
|
|
55
|
+
}
|
|
56
|
+
} else {
|
|
57
|
+
children[idx] = swapChild(children[idx], child, replacement, op);
|
|
58
|
+
}
|
|
59
|
+
return React.cloneElement(model, undefined, children);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function minimize(parent: ReactElement, child: ReactElement) {
|
|
64
|
+
// Right now, parent is always going to be a FLexbox, but might not always be the case
|
|
65
|
+
const { style: parentStyle } = getProps(parent);
|
|
66
|
+
const { style: childStyle } = getProps(child);
|
|
67
|
+
|
|
68
|
+
const { width, height, flexBasis, flexShrink, flexGrow, ...rest } = childStyle;
|
|
69
|
+
|
|
70
|
+
const restoreStyle = {
|
|
71
|
+
width,
|
|
72
|
+
height,
|
|
73
|
+
flexBasis,
|
|
74
|
+
flexShrink,
|
|
75
|
+
flexGrow
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const style = {
|
|
79
|
+
...rest,
|
|
80
|
+
flexBasis: 0,
|
|
81
|
+
flexGrow: 0,
|
|
82
|
+
flexShrink: 0
|
|
83
|
+
};
|
|
84
|
+
const collapsed =
|
|
85
|
+
parentStyle.flexDirection === 'row'
|
|
86
|
+
? 'vertical'
|
|
87
|
+
: parentStyle.flexDirection === 'column'
|
|
88
|
+
? 'horizontal'
|
|
89
|
+
: false;
|
|
90
|
+
|
|
91
|
+
if (collapsed) {
|
|
92
|
+
return React.cloneElement(child, {
|
|
93
|
+
collapsed,
|
|
94
|
+
restoreStyle,
|
|
95
|
+
style
|
|
96
|
+
});
|
|
97
|
+
} else {
|
|
98
|
+
return child;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function restore(child: ReactElement) {
|
|
103
|
+
// Right now, parent is always going to be a FLexbox, but might not always be the case
|
|
104
|
+
const { style: childStyle, restoreStyle } = getProps(child);
|
|
105
|
+
|
|
106
|
+
const { flexBasis, flexShrink, flexGrow, ...rest } = childStyle;
|
|
107
|
+
|
|
108
|
+
const style = {
|
|
109
|
+
...rest,
|
|
110
|
+
...restoreStyle
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
return React.cloneElement(child, {
|
|
114
|
+
collapsed: false,
|
|
115
|
+
style,
|
|
116
|
+
restoreStyle: undefined
|
|
117
|
+
});
|
|
118
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import React, { CSSProperties, ReactElement } from 'react';
|
|
2
|
+
import { followPath, getProps } from '../utils';
|
|
3
|
+
import { swapChild } from './replace-layout-element';
|
|
4
|
+
import { SplitterResizeAction } from './layoutTypes';
|
|
5
|
+
import { dimension } from '../common-types';
|
|
6
|
+
|
|
7
|
+
export function resizeFlexChildren(
|
|
8
|
+
layoutRoot: ReactElement,
|
|
9
|
+
{ path, sizes }: SplitterResizeAction
|
|
10
|
+
) {
|
|
11
|
+
const target = followPath(layoutRoot, path, true);
|
|
12
|
+
const { children, style } = getProps(target);
|
|
13
|
+
|
|
14
|
+
const dimension = style.flexDirection === 'column' ? 'height' : 'width';
|
|
15
|
+
const replacementChildren = applySizesToChildren(children, sizes, dimension);
|
|
16
|
+
|
|
17
|
+
const replacement = React.cloneElement(target, undefined, replacementChildren);
|
|
18
|
+
|
|
19
|
+
return swapChild(layoutRoot, target, replacement);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function applySizesToChildren(
|
|
23
|
+
children: ReactElement[],
|
|
24
|
+
sizes: { currentSize: number; flexBasis: number }[],
|
|
25
|
+
dimension: dimension
|
|
26
|
+
) {
|
|
27
|
+
return children.map((child, i) => {
|
|
28
|
+
const {
|
|
29
|
+
style: { [dimension]: size, flexBasis: actualFlexBasis }
|
|
30
|
+
} = getProps(child);
|
|
31
|
+
const meta = sizes[i];
|
|
32
|
+
let { currentSize, flexBasis } = meta;
|
|
33
|
+
const hasCurrentSize = currentSize !== undefined;
|
|
34
|
+
const newSize = hasCurrentSize ? meta.currentSize : flexBasis;
|
|
35
|
+
|
|
36
|
+
if (newSize === undefined || size === newSize || actualFlexBasis === newSize) {
|
|
37
|
+
return child;
|
|
38
|
+
} else {
|
|
39
|
+
return React.cloneElement(child, {
|
|
40
|
+
style: applySizeToChild(child.props.style, dimension, newSize)
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function applySizeToChild(style: CSSProperties, dimension: dimension, newSize: number) {
|
|
47
|
+
const hasSize = typeof style[dimension] === 'number';
|
|
48
|
+
const { flexShrink = 1, flexGrow = 1 } = style;
|
|
49
|
+
return {
|
|
50
|
+
...style,
|
|
51
|
+
[dimension]: hasSize ? newSize : 'auto',
|
|
52
|
+
flexBasis: hasSize ? 'auto' : newSize,
|
|
53
|
+
flexShrink,
|
|
54
|
+
flexGrow
|
|
55
|
+
};
|
|
56
|
+
}
|