@vuu-ui/vuu-layout 2.1.19-beta.1 → 2.1.19-beta.2
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/package.json +12 -13
- package/src/Component.js +14 -0
- package/src/LayoutContainer.css.js +24 -0
- package/src/LayoutContainer.js +26 -0
- package/src/debug.js +16 -0
- package/src/dock-layout/DockLayout.css.js +36 -0
- package/src/dock-layout/DockLayout.js +43 -0
- package/src/dock-layout/Drawer.css.js +150 -0
- package/src/dock-layout/Drawer.js +82 -0
- package/src/dock-layout/index.js +2 -0
- package/src/drag-drop/BoxModel.js +337 -0
- package/src/drag-drop/DragState.js +119 -0
- package/src/drag-drop/Draggable.js +140 -0
- package/src/drag-drop/DropTarget.js +286 -0
- package/src/drag-drop/DropTargetRenderer.js +275 -0
- package/src/drag-drop/dragDropTypes.js +0 -0
- package/src/drag-drop/index.js +3 -0
- package/src/flexbox/Flexbox.css.js +45 -0
- package/src/flexbox/Flexbox.js +45 -0
- package/src/flexbox/FlexboxLayout.js +27 -0
- package/src/flexbox/Splitter.css.js +57 -0
- package/src/flexbox/Splitter.js +112 -0
- package/src/flexbox/flexbox-utils.js +92 -0
- package/src/flexbox/flexboxTypes.js +0 -0
- package/src/flexbox/index.js +2 -0
- package/src/flexbox/useSplitterResizing.js +181 -0
- package/src/index.js +20 -0
- package/src/layout-action.js +20 -0
- package/src/layout-header/ActionButton.js +15 -0
- package/src/layout-header/Header.css.js +32 -0
- package/src/layout-header/Header.js +99 -0
- package/src/layout-header/index.js +1 -0
- package/src/layout-header/useHeader.js +76 -0
- package/src/layout-provider/LayoutProvider.js +242 -0
- package/src/layout-provider/LayoutProviderContext.js +13 -0
- package/src/layout-provider/index.js +2 -0
- package/src/layout-provider/useLayoutDragDrop.js +147 -0
- package/src/layout-reducer/flexUtils.js +186 -0
- package/src/layout-reducer/index.js +4 -0
- package/src/layout-reducer/insert-layout-element.js +179 -0
- package/src/layout-reducer/layout-reducer.js +121 -0
- package/src/layout-reducer/layoutTypes.js +34 -0
- package/src/layout-reducer/layoutUtils.js +178 -0
- package/src/layout-reducer/move-layout-element.js +18 -0
- package/src/layout-reducer/remove-layout-element.js +161 -0
- package/src/layout-reducer/replace-layout-element.js +70 -0
- package/src/layout-reducer/resize-flex-children.js +48 -0
- package/src/layout-reducer/wrap-layout-element.js +134 -0
- package/src/layout-view/View.css.js +76 -0
- package/src/layout-view/View.js +116 -0
- package/src/layout-view/useView.js +69 -0
- package/src/layout-view/useViewBroadcastChannel.js +29 -0
- package/src/layout-view/useViewResize.js +27 -0
- package/src/layout-view/viewTypes.js +0 -0
- package/src/layout-view-actions/ViewContext.js +11 -0
- package/src/layout-view-actions/useViewActionDispatcher.js +116 -0
- package/src/layout-view-actions/useViewContributions.js +31 -0
- package/src/palette/Palette.css.js +31 -0
- package/src/palette/Palette.js +85 -0
- package/src/palette/index.js +1 -0
- package/src/placeholder/LayoutStartPanel.css.js +35 -0
- package/src/placeholder/LayoutStartPanel.js +57 -0
- package/src/placeholder/Placeholder.css.js +20 -0
- package/src/placeholder/Placeholder.js +33 -0
- package/src/placeholder/index.js +1 -0
- package/src/responsive/index.js +2 -0
- package/src/responsive/measureMinimumNodeSize.js +24 -0
- package/src/responsive/useResizeObserver.js +109 -0
- package/src/responsive/utils.js +27 -0
- package/src/stack/Stack.css.js +44 -0
- package/src/stack/Stack.js +98 -0
- package/src/stack/StackLayout.js +116 -0
- package/src/stack/index.js +3 -0
- package/src/stack/stackTypes.js +0 -0
- package/src/tabs/TabPanel.css.js +17 -0
- package/src/tabs/TabPanel.js +11 -0
- package/src/tabs/index.js +1 -0
- package/src/tools/config-wrapper/ConfigWrapper.js +55 -0
- package/src/tools/config-wrapper/index.js +1 -0
- package/src/tools/devtools-box/layout-configurator.css.js +113 -0
- package/src/tools/devtools-tree/layout-tree-viewer.css.js +17 -0
- package/src/tools/index.js +3 -0
- package/src/use-persistent-state.js +43 -0
- package/src/utils/index.js +5 -0
- package/src/utils/pathUtils.js +212 -0
- package/src/utils/propUtils.js +15 -0
- package/src/utils/refUtils.js +5 -0
- package/src/utils/styleUtils.js +9 -0
- package/src/utils/typeOf.js +15 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { isContainer } from "@vuu-ui/vuu-utils";
|
|
2
|
+
import react, { isValidElement } from "react";
|
|
3
|
+
import { getProp, getProps } from "./propUtils.js";
|
|
4
|
+
import { typeOf } from "./typeOf.js";
|
|
5
|
+
const removeFinalPathSegment = (path)=>{
|
|
6
|
+
const pos = path.lastIndexOf(".");
|
|
7
|
+
if (-1 === pos) return path;
|
|
8
|
+
return path.slice(0, pos);
|
|
9
|
+
};
|
|
10
|
+
const getChildren = (c)=>react.isValidElement(c.props.children) ? [
|
|
11
|
+
c.props.children
|
|
12
|
+
] : c.props.children;
|
|
13
|
+
const resolvePath = (source, path = "")=>{
|
|
14
|
+
const [step1, ...steps] = path.split(".");
|
|
15
|
+
if (step1?.startsWith("#")) {
|
|
16
|
+
const node = findTargetById(source, step1.slice(1), true);
|
|
17
|
+
if (node && steps.length) return resolvePath(node, steps.join("."));
|
|
18
|
+
} else if ("ACTIVE_CHILD" === step1) {
|
|
19
|
+
const { active } = getProps(source);
|
|
20
|
+
const children = getChildren(source);
|
|
21
|
+
const { path } = getProps(children[active]);
|
|
22
|
+
return path;
|
|
23
|
+
}
|
|
24
|
+
return "";
|
|
25
|
+
};
|
|
26
|
+
const resolveJSONPath = (source, path = "")=>{
|
|
27
|
+
const [step1, ...steps] = path.split(".");
|
|
28
|
+
if (step1?.startsWith("#")) {
|
|
29
|
+
const node = findTargetJSONById(source, step1.slice(1), true);
|
|
30
|
+
if (node && steps.length) return resolveJSONPath(node, steps.join("."));
|
|
31
|
+
} else if ("ACTIVE_CHILD" === step1) {
|
|
32
|
+
const { children, props } = source;
|
|
33
|
+
const { active } = props;
|
|
34
|
+
if ("number" == typeof active && children?.[active]) return children[active];
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
function followPathToParent(source, path) {
|
|
38
|
+
const { "data-path": dataPath, path: sourcePath = dataPath } = getProps(source);
|
|
39
|
+
if ("0" === path) return null;
|
|
40
|
+
if (path === sourcePath) return null;
|
|
41
|
+
return followPath(source, removeFinalPathSegment(path), true);
|
|
42
|
+
}
|
|
43
|
+
function findTarget(source, test) {
|
|
44
|
+
if (source) {
|
|
45
|
+
const { children, ...props } = getProps(source);
|
|
46
|
+
if (test(props)) return source;
|
|
47
|
+
if (react.Children.count(children) > 0) {
|
|
48
|
+
const array = react.isValidElement(children) ? [
|
|
49
|
+
children
|
|
50
|
+
] : children;
|
|
51
|
+
for (const child of array){
|
|
52
|
+
const target = findTarget(child, test);
|
|
53
|
+
if (target) return target;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function containerOf(source, target) {
|
|
59
|
+
if (target === source) return null;
|
|
60
|
+
const { path: sourcePath, children } = getProps(source);
|
|
61
|
+
const { idx, finalStep } = pathUtils_nextStep(sourcePath, getProp(target, "path"));
|
|
62
|
+
if (finalStep) return source;
|
|
63
|
+
if (void 0 === children || void 0 === children[idx]) return null;
|
|
64
|
+
return containerOf(children[idx], target);
|
|
65
|
+
}
|
|
66
|
+
const getChild = (children, idx)=>{
|
|
67
|
+
if (react.isValidElement(children) && 0 == idx) return children;
|
|
68
|
+
if (Array.isArray(children)) return children[idx];
|
|
69
|
+
};
|
|
70
|
+
function followPathToComponent(component, path) {
|
|
71
|
+
const paths = path.split(".");
|
|
72
|
+
let children = [
|
|
73
|
+
component
|
|
74
|
+
];
|
|
75
|
+
for(let i = 0; i < paths.length; i++){
|
|
76
|
+
const idx = parseInt(paths[i]);
|
|
77
|
+
const child = children[idx];
|
|
78
|
+
if (i === paths.length - 1) return child;
|
|
79
|
+
children = getChildren(child);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
const findTargetById = (source, id, throwIfNotFound = true)=>{
|
|
83
|
+
const { children, id: idProp } = source.props;
|
|
84
|
+
if (idProp === id) return source;
|
|
85
|
+
if (react.Children.count(children) > 0) {
|
|
86
|
+
const childArray = isValidElement(children) ? [
|
|
87
|
+
children
|
|
88
|
+
] : children;
|
|
89
|
+
for (const child of childArray)if (isValidElement(child)) {
|
|
90
|
+
const target = findTargetById(child, id, false);
|
|
91
|
+
if (target) return target;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (true === throwIfNotFound) throw Error(`pathUtils.findTargetById id #${id} not found in source`);
|
|
95
|
+
};
|
|
96
|
+
const findTargetJSONById = (source, id, throwIfNotFound = true)=>{
|
|
97
|
+
const { children, id: idProp } = source;
|
|
98
|
+
if (idProp === id) return source;
|
|
99
|
+
if (Array.isArray(children) && children.length > 0) {
|
|
100
|
+
for (const child of children)if (null !== child && "object" == typeof child) {
|
|
101
|
+
const target = findTargetJSONById(child, id, false);
|
|
102
|
+
if (target) return target;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
if (true === throwIfNotFound) throw Error(`pathUtils.findTargetJSONById id #${id} not found in source`);
|
|
106
|
+
};
|
|
107
|
+
function followPath(source, path, throwIfNotFound = false) {
|
|
108
|
+
if (path.startsWith("#")) return findTargetById(source, path.slice(1), throwIfNotFound);
|
|
109
|
+
const { "data-path": dataPath, path: sourcePath = dataPath } = getProps(source);
|
|
110
|
+
if (0 !== path.indexOf(sourcePath)) throw Error(`pathUtils.followPath path ${path} is not within source path ${sourcePath}`);
|
|
111
|
+
const route = path.slice(sourcePath.length + 1);
|
|
112
|
+
if ("" === route) return source;
|
|
113
|
+
let target = source;
|
|
114
|
+
const paths = route.split(".");
|
|
115
|
+
for(let i = 0; i < paths.length; i++){
|
|
116
|
+
if (0 === react.Children.count(target.props.children)) {
|
|
117
|
+
const message = `element at 0.${paths.slice(0, i).join(".")} has no children, so cannot fulfill rest of path ${paths.slice(i).join(".")}`;
|
|
118
|
+
if (!throwIfNotFound) return void console.warn(message);
|
|
119
|
+
throw Error(message);
|
|
120
|
+
}
|
|
121
|
+
target = getChild(target.props.children, parseInt(paths[i]));
|
|
122
|
+
if (void 0 === target) {
|
|
123
|
+
const message = `model at 0.${paths.slice(0, i).join(".")} has no children that fulfill next step of path ${paths.slice(i).join(".")}`;
|
|
124
|
+
if (throwIfNotFound) throw Error(message);
|
|
125
|
+
console.warn(message);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return target;
|
|
129
|
+
}
|
|
130
|
+
function nextLeaf(root, path) {
|
|
131
|
+
const parent = followPathToParent(root, path);
|
|
132
|
+
let pathIndices = path.split(".").map((idx)=>parseInt(idx, 10));
|
|
133
|
+
if (parent) {
|
|
134
|
+
const lastIdx = pathIndices.pop();
|
|
135
|
+
const { children } = parent.props;
|
|
136
|
+
if (children.length - 1 > lastIdx) return firstLeaf(children[lastIdx + 1]);
|
|
137
|
+
{
|
|
138
|
+
const parentIdx = pathIndices.pop();
|
|
139
|
+
const nextParent = followPathToParent(root, getProp(parent, "path"));
|
|
140
|
+
if (nextParent && "number" == typeof parentIdx) {
|
|
141
|
+
pathIndices = nextParent.props.path.split(".").map((idx)=>parseInt(idx, 10));
|
|
142
|
+
if (nextParent.props.children.length - 1 > parentIdx) {
|
|
143
|
+
const nextStep = nextParent.props.children[parentIdx + 1];
|
|
144
|
+
if (isContainer(typeOf(nextStep))) return firstLeaf(nextStep);
|
|
145
|
+
return nextStep;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return firstLeaf(root);
|
|
151
|
+
}
|
|
152
|
+
function previousLeaf(root, path) {
|
|
153
|
+
const pathIndices = path.split(".").map((idx)=>parseInt(idx, 10));
|
|
154
|
+
let lastIdx = pathIndices.pop();
|
|
155
|
+
let parent = followPathToParent(root, path);
|
|
156
|
+
if (null != parent && "number" == typeof lastIdx) {
|
|
157
|
+
const { children } = parent.props;
|
|
158
|
+
if (lastIdx > 0) return lastLeaf(children[lastIdx - 1]);
|
|
159
|
+
while(pathIndices.length > 1){
|
|
160
|
+
lastIdx = pathIndices.pop();
|
|
161
|
+
parent = followPathToParent(root, getProp(parent, "path"));
|
|
162
|
+
if (lastIdx > 0) {
|
|
163
|
+
const nextStep = parent.props.children[lastIdx - 1];
|
|
164
|
+
if (isContainer(typeOf(nextStep))) return lastLeaf(nextStep);
|
|
165
|
+
return nextStep;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return lastLeaf(root);
|
|
170
|
+
}
|
|
171
|
+
function firstLeaf(layoutRoot) {
|
|
172
|
+
if (isContainer(typeOf(layoutRoot))) {
|
|
173
|
+
const { children } = layoutRoot.props || layoutRoot;
|
|
174
|
+
return firstLeaf(children[0]);
|
|
175
|
+
}
|
|
176
|
+
return layoutRoot;
|
|
177
|
+
}
|
|
178
|
+
function lastLeaf(root) {
|
|
179
|
+
if (isContainer(typeOf(root))) {
|
|
180
|
+
const { children } = root.props || root;
|
|
181
|
+
return lastLeaf(children[children.length - 1]);
|
|
182
|
+
}
|
|
183
|
+
return root;
|
|
184
|
+
}
|
|
185
|
+
function pathUtils_nextStep(pathSoFar, targetPath, followPathToEnd = false) {
|
|
186
|
+
if (pathSoFar === targetPath) return {
|
|
187
|
+
idx: -1,
|
|
188
|
+
finalStep: true
|
|
189
|
+
};
|
|
190
|
+
const pathVisited = `${pathSoFar}.`;
|
|
191
|
+
if (!targetPath.startsWith(pathVisited)) throw Error("pathUtils nextStep has strayed from the path");
|
|
192
|
+
const endOfTheLine = followPathToEnd ? 0 : 1;
|
|
193
|
+
const paths = targetPath.replace(pathVisited, "").split(".").map((n)=>parseInt(n, 10));
|
|
194
|
+
return {
|
|
195
|
+
idx: paths[0],
|
|
196
|
+
finalStep: paths.length === endOfTheLine
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
function resetPath(model, path, additionalProps) {
|
|
200
|
+
if (getProp(model, "path") === path) return model;
|
|
201
|
+
const children = [];
|
|
202
|
+
react.Children.forEach(model.props.children, (child, i)=>{
|
|
203
|
+
if (getProp(child, "path")) children.push(resetPath(child, `${path}.${i}`));
|
|
204
|
+
else children.push(child);
|
|
205
|
+
});
|
|
206
|
+
const pathPropName = model.props["data-path"] ? "data-path" : "path";
|
|
207
|
+
return react.cloneElement(model, {
|
|
208
|
+
[pathPropName]: path,
|
|
209
|
+
...additionalProps
|
|
210
|
+
}, children);
|
|
211
|
+
}
|
|
212
|
+
export { containerOf, findTarget, followPath, followPathToComponent, followPathToParent, getChild, nextLeaf, pathUtils_nextStep as nextStep, previousLeaf, resetPath, resolveJSONPath, resolvePath };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const NO_PROPS = {};
|
|
2
|
+
const getProp = (component, propName)=>{
|
|
3
|
+
const props = getProps(component);
|
|
4
|
+
return props[propName] ?? props[`data-${propName}`];
|
|
5
|
+
};
|
|
6
|
+
const getProps = (component)=>component?.props || component || NO_PROPS;
|
|
7
|
+
const getChildProp = (container)=>{
|
|
8
|
+
const props = getProps(container);
|
|
9
|
+
if (props.children) {
|
|
10
|
+
const { children: [target, ...rest] } = props;
|
|
11
|
+
if (rest.length > 0) console.warn(`getChild expected a single child, found ${rest.length + 1}`);
|
|
12
|
+
return target;
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
export { getChildProp, getProp, getProps };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
function typeOf(element) {
|
|
2
|
+
if (element) {
|
|
3
|
+
const type = element.type;
|
|
4
|
+
if ("function" == typeof type || "object" == typeof type) {
|
|
5
|
+
const elementName = type.displayName || type.name || type.type?.name;
|
|
6
|
+
if ("string" == typeof elementName) return elementName;
|
|
7
|
+
}
|
|
8
|
+
if ("string" == typeof element.type) return element.type;
|
|
9
|
+
if (element.constructor) return element.constructor.displayName;
|
|
10
|
+
throw Error("typeOf unable to determine type of element");
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
const isTypeOf = (element, type)=>typeOf(element) === type;
|
|
14
|
+
const isLayoutJSON = (layout)=>void 0 !== layout && "type" in layout;
|
|
15
|
+
export { isLayoutJSON, isTypeOf, typeOf };
|