@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,44 @@
|
|
|
1
|
+
const css = `
|
|
2
|
+
.vuuTabs {
|
|
3
|
+
box-sizing: border-box;
|
|
4
|
+
flex-direction: column;
|
|
5
|
+
display: flex;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.vuuTabs-horizontal {
|
|
9
|
+
--vuu-tabs-border-style: none solid none none;
|
|
10
|
+
flex-direction: row;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.vuuTabs .Toolbar:before {
|
|
14
|
+
content: "";
|
|
15
|
+
background: var(--grey60);
|
|
16
|
+
width: 100%;
|
|
17
|
+
height: 1px;
|
|
18
|
+
position: absolute;
|
|
19
|
+
bottom: 0;
|
|
20
|
+
left: 0;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
.vuuTabs-tabPanel {
|
|
24
|
+
flex-direction: column;
|
|
25
|
+
flex: 1;
|
|
26
|
+
display: flex;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
.vuuTabs-tabPanel > * {
|
|
30
|
+
flex: auto;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.vuuTabHeader + .vuuView > .vuuHeader {
|
|
34
|
+
height: 0;
|
|
35
|
+
overflow: hidden;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.Layout-svg-button {
|
|
39
|
+
--spacing-medium: 5px;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
`;
|
|
44
|
+
export default css;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Tab, Tabstrip } from "@vuu-ui/vuu-ui-controls";
|
|
3
|
+
import { useId } from "@vuu-ui/vuu-utils";
|
|
4
|
+
import clsx from "clsx";
|
|
5
|
+
import { useComponentCssInjection } from "@salt-ds/styles";
|
|
6
|
+
import { useWindow } from "@salt-ds/window";
|
|
7
|
+
import react, { forwardRef, useCallback, useRef } from "react";
|
|
8
|
+
import { getDefaultTabLabel } from "../layout-reducer/index.js";
|
|
9
|
+
import Stack_0 from "./Stack.css";
|
|
10
|
+
const classBase = "vuuTabs";
|
|
11
|
+
const getDefaultTabIcon = ()=>void 0;
|
|
12
|
+
const getChildElements = (children)=>{
|
|
13
|
+
const elements = [];
|
|
14
|
+
react.Children.forEach(children, (child)=>{
|
|
15
|
+
if (/*#__PURE__*/ react.isValidElement(child)) elements.push(child);
|
|
16
|
+
else console.warn("Stack has unexpected child element type");
|
|
17
|
+
});
|
|
18
|
+
return elements;
|
|
19
|
+
};
|
|
20
|
+
const DefaultTabstripProps = {
|
|
21
|
+
allowAddTab: false,
|
|
22
|
+
allowCloseTab: false,
|
|
23
|
+
allowRenameTab: false
|
|
24
|
+
};
|
|
25
|
+
const Stack_Stack = /*#__PURE__*/ forwardRef(function({ TabstripProps = DefaultTabstripProps, active = 0, children, className: classNameProp, getTabIcon = getDefaultTabIcon, getTabLabel = getDefaultTabLabel, id: idProp, keyBoardActivation = "manual", onAddTab, onMoveTab, onTabClose, onTabEdit, onTabSelectionChanged, showTabs = "top", style }, ref) {
|
|
26
|
+
const targetWindow = useWindow();
|
|
27
|
+
useComponentCssInjection({
|
|
28
|
+
testId: "vuu-stack",
|
|
29
|
+
css: Stack_0,
|
|
30
|
+
window: targetWindow
|
|
31
|
+
});
|
|
32
|
+
const id = useId(idProp);
|
|
33
|
+
const tabLabelsRef = useRef([]);
|
|
34
|
+
const { allowCloseTab, allowRenameTab, className: tabstripClassName } = TabstripProps;
|
|
35
|
+
const handleExitEditMode = useCallback((_oldText, newText, _allowDeactivation, tabIndex)=>{
|
|
36
|
+
onTabEdit?.(tabIndex, newText);
|
|
37
|
+
}, [
|
|
38
|
+
onTabEdit
|
|
39
|
+
]);
|
|
40
|
+
const activeChild = ()=>{
|
|
41
|
+
if (/*#__PURE__*/ react.isValidElement(children)) return children;
|
|
42
|
+
if (Array.isArray(children)) return children[active] ?? null;
|
|
43
|
+
return null;
|
|
44
|
+
};
|
|
45
|
+
tabLabelsRef.current.length = 0;
|
|
46
|
+
const renderTabs = ()=>getChildElements(children).map((child, idx)=>{
|
|
47
|
+
const { closeable = allowCloseTab, id: childId = `${id}-${idx}`, "data-tab-location": tabLocation } = child.props;
|
|
48
|
+
const label = getTabLabel(child, idx, tabLabelsRef.current);
|
|
49
|
+
tabLabelsRef.current.push(label);
|
|
50
|
+
return /*#__PURE__*/ jsx(Tab, {
|
|
51
|
+
ariaControls: childId,
|
|
52
|
+
"data-icon": getTabIcon(child, idx),
|
|
53
|
+
id: `${childId}-tab`,
|
|
54
|
+
index: idx,
|
|
55
|
+
label: label,
|
|
56
|
+
location: tabLocation,
|
|
57
|
+
closeable: closeable,
|
|
58
|
+
editable: allowRenameTab
|
|
59
|
+
}, childId);
|
|
60
|
+
});
|
|
61
|
+
const child = activeChild();
|
|
62
|
+
const isHorizontal = "left" === showTabs || "right" === showTabs;
|
|
63
|
+
const tabstripOrientation = isHorizontal ? "vertical" : "horizontal";
|
|
64
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
65
|
+
className: clsx(classBase, classNameProp, {
|
|
66
|
+
[`${classBase}-horizontal`]: isHorizontal
|
|
67
|
+
}),
|
|
68
|
+
style: style,
|
|
69
|
+
id: id,
|
|
70
|
+
ref: ref,
|
|
71
|
+
children: [
|
|
72
|
+
showTabs ? /*#__PURE__*/ jsx(Tabstrip, {
|
|
73
|
+
"aria-label": "data tabs",
|
|
74
|
+
...TabstripProps,
|
|
75
|
+
activeTabIndex: TabstripProps?.activeTabIndex ?? (null === child ? -1 : active),
|
|
76
|
+
allowDragDrop: false !== TabstripProps.allowDragDrop,
|
|
77
|
+
animateSelectionThumb: true,
|
|
78
|
+
className: clsx("vuuTabHeader", tabstripClassName),
|
|
79
|
+
keyBoardActivation: keyBoardActivation,
|
|
80
|
+
onActiveChange: onTabSelectionChanged,
|
|
81
|
+
onAddTab: onAddTab,
|
|
82
|
+
onCloseTab: onTabClose,
|
|
83
|
+
onExitEditMode: handleExitEditMode,
|
|
84
|
+
onMoveTab: onMoveTab,
|
|
85
|
+
orientation: tabstripOrientation,
|
|
86
|
+
children: renderTabs()
|
|
87
|
+
}) : null,
|
|
88
|
+
/*#__PURE__*/ jsx("div", {
|
|
89
|
+
"aria-labelledby": `${id}-${active}`,
|
|
90
|
+
className: `${classBase}-tabPanel`,
|
|
91
|
+
role: "tabpanel",
|
|
92
|
+
children: child
|
|
93
|
+
})
|
|
94
|
+
]
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
Stack_Stack.displayName = "Stack";
|
|
98
|
+
export { Stack_Stack as Stack };
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import { registerComponent, useId } from "@vuu-ui/vuu-utils";
|
|
3
|
+
import react, { useCallback, useRef } from "react";
|
|
4
|
+
import { useLayoutCreateNewChild, useLayoutProviderDispatch } from "../layout-provider/index.js";
|
|
5
|
+
import { getDefaultTabLabel } from "../layout-reducer/index.js";
|
|
6
|
+
import { useViewActionDispatcher } from "../layout-view-actions/useViewActionDispatcher.js";
|
|
7
|
+
import { useViewBroadcastChannel } from "../layout-view/useViewBroadcastChannel.js";
|
|
8
|
+
import { usePersistentState } from "../use-persistent-state.js";
|
|
9
|
+
import { Stack } from "./Stack.js";
|
|
10
|
+
const StackLayout = (props)=>{
|
|
11
|
+
const rootRef = useRef(null);
|
|
12
|
+
const dispatch = useLayoutProviderDispatch();
|
|
13
|
+
const { loadState } = usePersistentState();
|
|
14
|
+
const { createNewChild: createNewChildProp, id: idProp, onTabSelectionChanged, path, ...restProps } = props;
|
|
15
|
+
const { children } = props;
|
|
16
|
+
const id = useId(idProp);
|
|
17
|
+
const sendMessage = useViewBroadcastChannel();
|
|
18
|
+
const [dispatchViewAction] = useViewActionDispatcher(id, rootRef, path);
|
|
19
|
+
const createNewChildFromContext = useLayoutCreateNewChild();
|
|
20
|
+
const createNewChild = createNewChildProp ?? createNewChildFromContext;
|
|
21
|
+
const handleTabSelection = (nextIdx)=>{
|
|
22
|
+
if (path) {
|
|
23
|
+
dispatch({
|
|
24
|
+
type: "switch-tab",
|
|
25
|
+
id,
|
|
26
|
+
path,
|
|
27
|
+
nextIdx
|
|
28
|
+
});
|
|
29
|
+
onTabSelectionChanged?.(nextIdx);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
const handleTabClose = useCallback((tabIndex)=>{
|
|
33
|
+
if (Array.isArray(children)) {
|
|
34
|
+
const { props: { "data-path": dataPath, path = dataPath } } = children[tabIndex];
|
|
35
|
+
sendMessage({
|
|
36
|
+
type: "layout-closed",
|
|
37
|
+
path
|
|
38
|
+
});
|
|
39
|
+
setTimeout(()=>{
|
|
40
|
+
dispatch({
|
|
41
|
+
type: "remove",
|
|
42
|
+
path
|
|
43
|
+
});
|
|
44
|
+
}, 100);
|
|
45
|
+
}
|
|
46
|
+
}, [
|
|
47
|
+
children,
|
|
48
|
+
dispatch,
|
|
49
|
+
sendMessage
|
|
50
|
+
]);
|
|
51
|
+
const handleTabAdd = useCallback(()=>{
|
|
52
|
+
if (path) {
|
|
53
|
+
const tabIndex = react.Children.count(children);
|
|
54
|
+
dispatch({
|
|
55
|
+
type: "add",
|
|
56
|
+
path,
|
|
57
|
+
component: createNewChild(tabIndex)
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}, [
|
|
61
|
+
children,
|
|
62
|
+
createNewChild,
|
|
63
|
+
dispatch,
|
|
64
|
+
path
|
|
65
|
+
]);
|
|
66
|
+
const handleMoveTab = useCallback((fromIndex, toIndex)=>{
|
|
67
|
+
if (path) dispatch({
|
|
68
|
+
fromIndex,
|
|
69
|
+
toIndex,
|
|
70
|
+
path,
|
|
71
|
+
type: "move-child"
|
|
72
|
+
});
|
|
73
|
+
}, [
|
|
74
|
+
dispatch,
|
|
75
|
+
path
|
|
76
|
+
]);
|
|
77
|
+
const handleMouseDown = async (e, index)=>{
|
|
78
|
+
let readyToDrag;
|
|
79
|
+
const preDragActivity = async ()=>new Promise((resolve)=>{
|
|
80
|
+
console.log("preDragActivity: Ok, gonna release the drag");
|
|
81
|
+
readyToDrag = resolve;
|
|
82
|
+
});
|
|
83
|
+
const dragging = await dispatchViewAction({
|
|
84
|
+
type: "mousedown",
|
|
85
|
+
index,
|
|
86
|
+
preDragActivity
|
|
87
|
+
}, e);
|
|
88
|
+
if (dragging) readyToDrag?.(void 0);
|
|
89
|
+
};
|
|
90
|
+
const handleTabEdit = (tabIndex, text)=>{
|
|
91
|
+
dispatch({
|
|
92
|
+
type: "set-title",
|
|
93
|
+
path: `${path}.${tabIndex}`,
|
|
94
|
+
title: text
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
const getTabLabel = (component, idx, existingLabels)=>{
|
|
98
|
+
const { id, title } = component.props;
|
|
99
|
+
return loadState(id, "view-title") || title || getDefaultTabLabel(component, idx, existingLabels);
|
|
100
|
+
};
|
|
101
|
+
return /*#__PURE__*/ jsx(Stack, {
|
|
102
|
+
...restProps,
|
|
103
|
+
id: id,
|
|
104
|
+
getTabLabel: getTabLabel,
|
|
105
|
+
onMouseDown: handleMouseDown,
|
|
106
|
+
onMoveTab: handleMoveTab,
|
|
107
|
+
onAddTab: handleTabAdd,
|
|
108
|
+
onTabClose: handleTabClose,
|
|
109
|
+
onTabEdit: handleTabEdit,
|
|
110
|
+
onTabSelectionChanged: handleTabSelection,
|
|
111
|
+
ref: rootRef
|
|
112
|
+
});
|
|
113
|
+
};
|
|
114
|
+
StackLayout.displayName = "Stack";
|
|
115
|
+
registerComponent("Stack", StackLayout, "container");
|
|
116
|
+
export { StackLayout };
|
|
File without changes
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
import "./TabPanel.css";
|
|
3
|
+
const TabPanel = ({ ariaLabelledBy, children, id })=>/*#__PURE__*/ jsx("div", {
|
|
4
|
+
className: "TabPanel",
|
|
5
|
+
id: id,
|
|
6
|
+
role: "tabpanel",
|
|
7
|
+
"aria-labelledby": ariaLabelledBy,
|
|
8
|
+
children: children
|
|
9
|
+
});
|
|
10
|
+
var tabs_TabPanel = TabPanel;
|
|
11
|
+
export default tabs_TabPanel;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as TabPanel } from "./TabPanel.js";
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import react, { useState } from "react";
|
|
3
|
+
import { LayoutConfigurator, LayoutTreeViewer } from "../index.js";
|
|
4
|
+
import { followPathToComponent } from "../../index.js";
|
|
5
|
+
const ConfigWrapper = ({ children })=>{
|
|
6
|
+
const designMode = false;
|
|
7
|
+
const [layout, setLayout] = useState(children);
|
|
8
|
+
const [selectedComponent, setSelectedComponent] = useState(children);
|
|
9
|
+
const handleSelection = (selectedPath)=>{
|
|
10
|
+
const targetComponent = followPathToComponent(layout, selectedPath);
|
|
11
|
+
setSelectedComponent(targetComponent);
|
|
12
|
+
};
|
|
13
|
+
const handleChange = (property, value)=>{
|
|
14
|
+
console.log(`change ${property} -> ${value}`);
|
|
15
|
+
const newComponent = /*#__PURE__*/ react.cloneElement(selectedComponent, {
|
|
16
|
+
style: {
|
|
17
|
+
...selectedComponent.props.style,
|
|
18
|
+
[property]: value
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
setSelectedComponent(newComponent);
|
|
22
|
+
setLayout(/*#__PURE__*/ react.cloneElement(layout, {}, newComponent));
|
|
23
|
+
};
|
|
24
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
25
|
+
"data-design-mode": `${designMode}`,
|
|
26
|
+
children: [
|
|
27
|
+
layout,
|
|
28
|
+
/*#__PURE__*/ jsx("br", {}),
|
|
29
|
+
/*#__PURE__*/ jsxs("div", {
|
|
30
|
+
style: {
|
|
31
|
+
display: "flex"
|
|
32
|
+
},
|
|
33
|
+
children: [
|
|
34
|
+
/*#__PURE__*/ jsx(LayoutConfigurator, {
|
|
35
|
+
height: 300,
|
|
36
|
+
managedStyle: selectedComponent.props.style,
|
|
37
|
+
width: 300,
|
|
38
|
+
onChange: handleChange,
|
|
39
|
+
style: void 0
|
|
40
|
+
}),
|
|
41
|
+
/*#__PURE__*/ jsx(LayoutTreeViewer, {
|
|
42
|
+
layout: layout,
|
|
43
|
+
onSelect: handleSelection,
|
|
44
|
+
style: {
|
|
45
|
+
width: 300,
|
|
46
|
+
height: 300,
|
|
47
|
+
backgroundColor: "#ccc"
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
]
|
|
51
|
+
})
|
|
52
|
+
]
|
|
53
|
+
});
|
|
54
|
+
};
|
|
55
|
+
export { ConfigWrapper };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./ConfigWrapper.js";
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
const css = `
|
|
2
|
+
[data-design-mode="true"] .Component {
|
|
3
|
+
filter: grayscale();
|
|
4
|
+
opacity: .4;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
[data-design-mode="true"] .Component:after {
|
|
8
|
+
color: #000;
|
|
9
|
+
content: "Component";
|
|
10
|
+
background-color: #ff0;
|
|
11
|
+
height: 12px;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.LayoutConfigurator {
|
|
15
|
+
--margin-color: #f3cea5;
|
|
16
|
+
--border-color: #fddda0;
|
|
17
|
+
--padding-color: #c6d092;
|
|
18
|
+
--content-color: #8cb6c0;
|
|
19
|
+
background-color: var(--margin-color);
|
|
20
|
+
flex-direction: column;
|
|
21
|
+
align-items: stretch;
|
|
22
|
+
display: flex;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.LayoutConfigurator .layout-outer {
|
|
26
|
+
flex-direction: column;
|
|
27
|
+
flex: auto;
|
|
28
|
+
align-items: stretch;
|
|
29
|
+
display: flex;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.LayoutBox {
|
|
33
|
+
--hw-control-font-size: 13px;
|
|
34
|
+
--hw-text-input-bg: #ffffff4d;
|
|
35
|
+
--hwTextInput-padding: 3px;
|
|
36
|
+
--hw-text-input-position: absolute;
|
|
37
|
+
--hwTextInput-width: 30px;
|
|
38
|
+
flex: auto;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.LayoutBox > .layout-top {
|
|
42
|
+
flex-direction: row;
|
|
43
|
+
flex: 0 0 40px;
|
|
44
|
+
align-items: center;
|
|
45
|
+
padding-left: 12px;
|
|
46
|
+
display: flex;
|
|
47
|
+
position: relative;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
.LayoutBox > .layout-bottom {
|
|
51
|
+
flex-direction: row;
|
|
52
|
+
flex: 0 0 40px;
|
|
53
|
+
align-items: center;
|
|
54
|
+
display: flex;
|
|
55
|
+
position: relative;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.LayoutBox > .layout-inner > .layout-right, .LayoutBox > .layout-inner > .layout-left {
|
|
59
|
+
flex-direction: column;
|
|
60
|
+
flex: 0 0 40px;
|
|
61
|
+
justify-content: center;
|
|
62
|
+
align-items: center;
|
|
63
|
+
display: flex;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.layout-top, .layout-bottom {
|
|
67
|
+
--hw-text-input-margin: 0 0 0 -15px;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.layout-top > .layout-input, .layout-bottom > .layout-input {
|
|
71
|
+
left: 50%;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.LayoutBox > .layout-inner {
|
|
75
|
+
flex-direction: row;
|
|
76
|
+
flex: auto;
|
|
77
|
+
align-items: stretch;
|
|
78
|
+
display: flex;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.LayoutBox.layout-margin {
|
|
82
|
+
background-color: var(--margin-color);
|
|
83
|
+
border: 2px dashed #000;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.LayoutBox.layout-border {
|
|
87
|
+
background-color: var(--border-color);
|
|
88
|
+
border: 2px solid #000;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.LayoutBox.layout-padding {
|
|
92
|
+
background-color: var(--padding-color);
|
|
93
|
+
border: 2px dashed #000;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.LayoutBox .layout-content {
|
|
97
|
+
background-color: var(--content-color);
|
|
98
|
+
border: 2px solid gray;
|
|
99
|
+
flex: auto;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.LayoutBox .layout-title {
|
|
103
|
+
color: #161616;
|
|
104
|
+
font-size: 11px;
|
|
105
|
+
line-height: 15px;
|
|
106
|
+
position: absolute;
|
|
107
|
+
top: 1px;
|
|
108
|
+
left: 4px;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
`;
|
|
113
|
+
export default css;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
const css = `
|
|
2
|
+
.hwLayoutTreeNode {
|
|
3
|
+
cursor: default;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.hwLayoutTreeNode:hover {
|
|
7
|
+
background-color: #fff3;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
.hwLayoutTreeNode[aria-selected="true"] {
|
|
11
|
+
color: #fff;
|
|
12
|
+
background-color: #6495ed;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
`;
|
|
17
|
+
export default css;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useCallback } from "react";
|
|
2
|
+
const persistentState = new Map();
|
|
3
|
+
const getPersistentState = (id)=>persistentState.get(id);
|
|
4
|
+
const hasPersistentState = (id)=>persistentState.has(id);
|
|
5
|
+
const setPersistentState = (id, value)=>persistentState.set(id, value);
|
|
6
|
+
const usePersistentState = ()=>{
|
|
7
|
+
const loadState = useCallback((id, key)=>{
|
|
8
|
+
const state = persistentState.get(id);
|
|
9
|
+
if (state) {
|
|
10
|
+
if (void 0 !== key) return state[key];
|
|
11
|
+
return state;
|
|
12
|
+
}
|
|
13
|
+
}, []);
|
|
14
|
+
const saveState = useCallback((id, key, data)=>{
|
|
15
|
+
if (void 0 === key) persistentState.set(id, data);
|
|
16
|
+
else if (persistentState.has(id)) {
|
|
17
|
+
const state = persistentState.get(id);
|
|
18
|
+
persistentState.set(id, {
|
|
19
|
+
...state,
|
|
20
|
+
[key]: data
|
|
21
|
+
});
|
|
22
|
+
} else persistentState.set(id, {
|
|
23
|
+
[key]: data
|
|
24
|
+
});
|
|
25
|
+
}, []);
|
|
26
|
+
const purgeState = useCallback((id, key)=>{
|
|
27
|
+
if (persistentState.has(id)) if (void 0 === key) persistentState.delete(id);
|
|
28
|
+
else {
|
|
29
|
+
const state = persistentState.get(id);
|
|
30
|
+
if (state[key]) {
|
|
31
|
+
const { [key]: _doomedState, ...rest } = persistentState.get(id);
|
|
32
|
+
if (Object.keys(rest).length > 0) persistentState.set(id, rest);
|
|
33
|
+
else persistentState.delete(id);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}, []);
|
|
37
|
+
return {
|
|
38
|
+
loadState,
|
|
39
|
+
saveState,
|
|
40
|
+
purgeState
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
export { getPersistentState, hasPersistentState, setPersistentState, usePersistentState };
|