@vuu-ui/vuu-layout 0.5.13 → 0.5.15

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.
Files changed (114) hide show
  1. package/package.json +10 -13
  2. package/src/Component.css +0 -0
  3. package/src/Component.tsx +20 -0
  4. package/src/DraggableLayout.css +18 -0
  5. package/src/DraggableLayout.tsx +26 -0
  6. package/src/__tests__/flexbox-utils.spec.js +90 -0
  7. package/src/chest-of-drawers/Chest.css +36 -0
  8. package/src/chest-of-drawers/Chest.tsx +42 -0
  9. package/src/chest-of-drawers/Drawer.css +159 -0
  10. package/src/chest-of-drawers/Drawer.tsx +118 -0
  11. package/src/chest-of-drawers/index.ts +2 -0
  12. package/src/common-types.ts +9 -0
  13. package/src/debug.ts +16 -0
  14. package/src/drag-drop/BoxModel.ts +551 -0
  15. package/src/drag-drop/DragState.ts +219 -0
  16. package/src/drag-drop/Draggable.ts +282 -0
  17. package/src/drag-drop/DropMenu.css +71 -0
  18. package/src/drag-drop/DropMenu.tsx +61 -0
  19. package/src/drag-drop/DropTarget.ts +393 -0
  20. package/src/drag-drop/DropTargetRenderer.css +40 -0
  21. package/src/drag-drop/DropTargetRenderer.tsx +277 -0
  22. package/src/drag-drop/dragDropTypes.ts +47 -0
  23. package/src/drag-drop/index.ts +5 -0
  24. package/src/editable-label/EditableLabel.css +28 -0
  25. package/src/editable-label/EditableLabel.tsx +99 -0
  26. package/src/editable-label/index.ts +1 -0
  27. package/src/flexbox/Flexbox.css +45 -0
  28. package/src/flexbox/Flexbox.tsx +70 -0
  29. package/src/flexbox/FlexboxLayout.tsx +28 -0
  30. package/src/flexbox/FluidGrid.css +134 -0
  31. package/src/flexbox/FluidGrid.tsx +82 -0
  32. package/src/flexbox/FluidGridLayout.tsx +9 -0
  33. package/src/flexbox/Splitter.css +140 -0
  34. package/src/flexbox/Splitter.tsx +127 -0
  35. package/src/flexbox/flexbox-utils.ts +128 -0
  36. package/src/flexbox/flexboxTypes.ts +68 -0
  37. package/src/flexbox/index.ts +5 -0
  38. package/src/flexbox/useResponsiveSizing.ts +82 -0
  39. package/src/flexbox/useSplitterResizing.ts +270 -0
  40. package/src/index.ts +19 -0
  41. package/src/layout-action.ts +21 -0
  42. package/src/layout-header/ActionButton.tsx +23 -0
  43. package/src/layout-header/Header.css +8 -0
  44. package/src/layout-header/Header.tsx +216 -0
  45. package/src/layout-header/index.ts +1 -0
  46. package/src/layout-provider/LayoutProvider.tsx +161 -0
  47. package/src/layout-provider/LayoutProviderContext.ts +17 -0
  48. package/src/layout-provider/index.ts +3 -0
  49. package/src/layout-provider/useLayoutDragDrop.ts +210 -0
  50. package/src/layout-reducer/flexUtils.ts +276 -0
  51. package/src/layout-reducer/index.ts +5 -0
  52. package/src/layout-reducer/insert-layout-element.ts +365 -0
  53. package/src/layout-reducer/layout-reducer.ts +237 -0
  54. package/src/layout-reducer/layoutTypes.ts +159 -0
  55. package/src/layout-reducer/layoutUtils.ts +288 -0
  56. package/src/layout-reducer/remove-layout-element.ts +226 -0
  57. package/src/layout-reducer/replace-layout-element.ts +113 -0
  58. package/src/layout-reducer/resize-flex-children.ts +55 -0
  59. package/src/layout-reducer/wrap-layout-element.ts +307 -0
  60. package/src/layout-view/View.css +61 -0
  61. package/src/layout-view/View.tsx +143 -0
  62. package/src/layout-view/ViewContext.ts +30 -0
  63. package/src/layout-view/index.ts +5 -0
  64. package/src/layout-view/useView.tsx +104 -0
  65. package/src/layout-view/useViewActionDispatcher.ts +123 -0
  66. package/src/layout-view/useViewResize.ts +53 -0
  67. package/src/layout-view/viewTypes.ts +35 -0
  68. package/src/palette/Palette.css +33 -0
  69. package/src/palette/Palette.tsx +140 -0
  70. package/src/palette/PaletteSalt.css +9 -0
  71. package/src/palette/PaletteSalt.tsx +79 -0
  72. package/src/palette/index.ts +3 -0
  73. package/src/placeholder/Placeholder.css +10 -0
  74. package/src/placeholder/Placeholder.tsx +38 -0
  75. package/src/placeholder/index.ts +1 -0
  76. package/src/registry/ComponentRegistry.ts +44 -0
  77. package/src/registry/index.ts +1 -0
  78. package/src/responsive/breakpoints.ts +62 -0
  79. package/src/responsive/index.ts +3 -0
  80. package/src/responsive/measureMinimumNodeSize.ts +23 -0
  81. package/src/responsive/overflowUtils.js +14 -0
  82. package/src/responsive/use-breakpoints.ts +101 -0
  83. package/src/responsive/useResizeObserver.ts +154 -0
  84. package/src/responsive/utils.ts +37 -0
  85. package/src/stack/Stack.css +39 -0
  86. package/src/stack/Stack.tsx +173 -0
  87. package/src/stack/StackLayout.tsx +119 -0
  88. package/src/stack/index.ts +4 -0
  89. package/src/stack/stackTypes.ts +22 -0
  90. package/src/tabs/TabPanel.css +12 -0
  91. package/src/tabs/TabPanel.tsx +17 -0
  92. package/src/tabs/index.ts +1 -0
  93. package/src/tools/config-wrapper/ConfigWrapper.tsx +55 -0
  94. package/src/tools/config-wrapper/index.ts +1 -0
  95. package/src/tools/devtools-box/layout-configurator.css +112 -0
  96. package/src/tools/devtools-box/layout-configurator.jsx +369 -0
  97. package/src/tools/devtools-tree/layout-tree-viewer.css +15 -0
  98. package/src/tools/devtools-tree/layout-tree-viewer.jsx +36 -0
  99. package/src/tools/index.ts +4 -0
  100. package/src/use-persistent-state.ts +112 -0
  101. package/src/utils/index.ts +5 -0
  102. package/src/utils/pathUtils.ts +283 -0
  103. package/src/utils/propUtils.ts +26 -0
  104. package/src/utils/refUtils.ts +16 -0
  105. package/src/utils/styleUtils.ts +13 -0
  106. package/src/utils/typeOf.ts +25 -0
  107. package/tsconfig-emit-types.json +11 -0
  108. package/LICENSE +0 -201
  109. package/cjs/index.js +0 -20
  110. package/cjs/index.js.map +0 -7
  111. package/esm/index.js +0 -20
  112. package/esm/index.js.map +0 -7
  113. package/index.css +0 -2
  114. package/index.css.map +0 -7
@@ -0,0 +1,37 @@
1
+ const COLLAPSIBLE = 'data-collapsible';
2
+
3
+ const RESPONSIVE_ATTRIBUTE: { [key: string]: boolean } = {
4
+ [COLLAPSIBLE]: true,
5
+ 'data-pad-start': true,
6
+ 'data-pad-end': true
7
+ };
8
+
9
+ export const isResponsiveAttribute = (propName: string): boolean =>
10
+ RESPONSIVE_ATTRIBUTE[propName] ?? false;
11
+
12
+ const isCollapsible = (propName: string) => propName === COLLAPSIBLE;
13
+
14
+ const COLLAPSIBLE_VALUE: { [key: string]: string } = {
15
+ dynamic: 'dynamic',
16
+ instant: 'instant',
17
+ true: 'instant'
18
+ };
19
+
20
+ const collapsibleValue = (value: string) => COLLAPSIBLE_VALUE[value] ?? 'none';
21
+
22
+ type Props = { [key: string]: any };
23
+ export const extractResponsiveProps = (props: Props) => {
24
+ return Object.keys(props).reduce<[Props, Props]>(
25
+ (result, propName) => {
26
+ const [toolbarProps, rest] = result;
27
+ if (isResponsiveAttribute(propName)) {
28
+ const value = isCollapsible(propName) ? collapsibleValue(props[propName]) : props[propName];
29
+
30
+ toolbarProps[propName] = value;
31
+ rest[propName] = undefined;
32
+ }
33
+ return result;
34
+ },
35
+ [{}, {}]
36
+ );
37
+ };
@@ -0,0 +1,39 @@
1
+ .Tabs {
2
+ display: flex;
3
+ box-sizing: border-box;
4
+ flex-direction: column;
5
+ }
6
+
7
+ .Tabs-horizontal {
8
+ flex-direction: row;
9
+ }
10
+
11
+ .Tabs .Toolbar:before {
12
+ left: 0;
13
+ width: 100%;
14
+ bottom: 0;
15
+ height: 1px;
16
+ content: '';
17
+ position: absolute;
18
+ background: var(--grey60);
19
+ }
20
+
21
+ .vuuTabHeader {
22
+ --saltTabs-activationIndicator-background: transparent;
23
+ --saltToolbarField-marginTop: calc(var(--salt-size-unit) - 1px);
24
+ border-bottom: solid 1px var(--salt-container-primary-borderColor);
25
+ }
26
+
27
+ .vuuTabHeader + .hwFlexbox,
28
+ .vuuTabHeader + * {
29
+ flex: 1;
30
+ }
31
+
32
+ .vuuTabHeader + .vuuView > .vuuHeader {
33
+ height: 0;
34
+ overflow: hidden;
35
+ }
36
+
37
+ .Layout-svg-button {
38
+ --spacing-medium: 5px;
39
+ }
@@ -0,0 +1,173 @@
1
+ import { Tab, Tabstrip, Toolbar, ToolbarField } from "@heswell/salt-lab";
2
+ import { useIdMemo as useId } from "@salt-ds/core";
3
+ import cx from "classnames";
4
+ import React, {
5
+ ForwardedRef,
6
+ forwardRef,
7
+ MouseEvent,
8
+ ReactElement,
9
+ ReactNode,
10
+ useCallback
11
+ } from "react";
12
+ import { StackProps } from "./stackTypes";
13
+
14
+ import "./Stack.css";
15
+
16
+ const classBase = "Tabs";
17
+
18
+ const getDefaultTabIcon = () =>
19
+ undefined;
20
+
21
+ const getDefaultTabLabel = (component: ReactElement, tabIndex: number) =>
22
+ component.props?.title ?? `Tab ${tabIndex + 1}`;
23
+
24
+ const getChildElements = <T extends ReactElement = ReactElement>(
25
+ children: ReactNode
26
+ ): T[] => {
27
+ const elements: T[] = [];
28
+ React.Children.forEach(children, (child) => {
29
+ if (React.isValidElement(child)) {
30
+ elements.push(child as T);
31
+ } else {
32
+ console.warn(`Stack has unexpected child element type`);
33
+ }
34
+ });
35
+ return elements;
36
+ };
37
+
38
+ export const Stack = forwardRef(function Stack(
39
+ {
40
+ active = 0,
41
+ children,
42
+ className: classNameProp,
43
+ enableAddTab,
44
+ enableCloseTabs,
45
+ getTabIcon = getDefaultTabIcon,
46
+ getTabLabel = getDefaultTabLabel,
47
+ id: idProp,
48
+ keyBoardActivation = "manual",
49
+ onMouseDown,
50
+ onTabAdd,
51
+ onTabClose,
52
+ onTabEdit,
53
+ onTabSelectionChanged,
54
+ showTabs,
55
+ style,
56
+ TabstripProps,
57
+ }: StackProps,
58
+ ref: ForwardedRef<HTMLDivElement>
59
+ ) {
60
+ const id = useId(idProp);
61
+
62
+ const handleTabSelection = (nextIdx: number) => {
63
+ onTabSelectionChanged?.(nextIdx);
64
+ };
65
+
66
+ const handleTabClose = (tabIndex: number) => {
67
+ onTabClose?.(tabIndex);
68
+ };
69
+
70
+ const handleAddTab = () => {
71
+ onTabAdd?.(React.Children.count(children));
72
+ };
73
+
74
+ const handleMouseDown = (e: MouseEvent<HTMLDivElement>) => {
75
+ const target = e.target as HTMLElement;
76
+ const tabElement = target.closest('[role^="tab"]') as HTMLDivElement;
77
+ const role = tabElement?.getAttribute("role");
78
+ if (role === "tab") {
79
+ const tabIndex = parseInt(tabElement.dataset.idx ?? "-1");
80
+ if (tabIndex === -1) {
81
+ throw Error("Stack: mousedown on tab with unknown index");
82
+ }
83
+ onMouseDown?.(e, tabIndex);
84
+ }
85
+ };
86
+
87
+ const handleExitEditMode = useCallback(
88
+ (
89
+ _oldText: string,
90
+ newText: string,
91
+ _allowDeactivation: boolean,
92
+ tabIndex: number
93
+ ) => {
94
+ onTabEdit?.(tabIndex, newText);
95
+ },
96
+ [onTabEdit]
97
+ );
98
+
99
+ const activeChild = () => {
100
+ if (React.isValidElement(children)) {
101
+ return children;
102
+ }
103
+ if (Array.isArray(children)) {
104
+ return children[active] ?? null;
105
+ }
106
+ return null;
107
+ };
108
+
109
+ const renderTabs = () =>
110
+ getChildElements(children).map((child, idx) => {
111
+ const rootId = `${id}-${idx}`;
112
+ const { closeable, id: childId } = child.props;
113
+ return (
114
+ <Tab
115
+ ariaControls={`${rootId}-tab`}
116
+ data-icon={getTabIcon(child, idx)}
117
+ draggable
118
+ key={childId ?? idx}
119
+ id={rootId}
120
+ label={getTabLabel(child, idx)}
121
+ closeable={closeable}
122
+ editable={TabstripProps?.enableRenameTab !== false}
123
+ />
124
+ );
125
+ });
126
+
127
+ const child = activeChild();
128
+
129
+ return (
130
+ <div
131
+ className={cx(classBase, classNameProp, {
132
+ [`${classBase}-horizontal`]: TabstripProps?.orientation === "vertical",
133
+ })}
134
+ style={style}
135
+ id={id}
136
+ ref={ref}
137
+ >
138
+ {showTabs ? (
139
+ <Toolbar
140
+ className="vuuTabHeader vuuHeader"
141
+ orientation={TabstripProps?.orientation}
142
+ >
143
+ <ToolbarField
144
+ disableFocusRing
145
+ data-collapsible="dynamic"
146
+ data-priority="3"
147
+ style={{ alignSelf: "flex-end" }}
148
+ >
149
+ <Tabstrip
150
+ {...TabstripProps}
151
+ enableRenameTab={TabstripProps?.enableRenameTab !== false}
152
+ enableAddTab={enableAddTab}
153
+ enableCloseTab={enableCloseTabs}
154
+ keyBoardActivation={keyBoardActivation}
155
+ onActiveChange={handleTabSelection}
156
+ onAddTab={handleAddTab}
157
+ onCloseTab={handleTabClose}
158
+ onExitEditMode={handleExitEditMode}
159
+ onMouseDown={handleMouseDown}
160
+ activeTabIndex={
161
+ TabstripProps?.activeTabIndex ?? (child === null ? -1 : active)
162
+ }
163
+ >
164
+ {renderTabs()}
165
+ </Tabstrip>
166
+ </ToolbarField>
167
+ </Toolbar>
168
+ ) : null}
169
+ {child}
170
+ </div>
171
+ );
172
+ });
173
+ Stack.displayName = "Stack";
@@ -0,0 +1,119 @@
1
+ import { useIdMemo as useId } from "@salt-ds/core";
2
+ import React, { ReactElement, useRef } from "react";
3
+ import Component from "../Component";
4
+ import { useLayoutProviderDispatch } from "../layout-provider";
5
+ import { useViewActionDispatcher, View } from "../layout-view";
6
+ import { registerComponent } from "../registry/ComponentRegistry";
7
+ import { usePersistentState } from "../use-persistent-state";
8
+ import { Stack } from "./Stack";
9
+ import { StackProps } from "./stackTypes";
10
+
11
+ import "./Stack.css";
12
+
13
+ const defaultCreateNewChild = (index: number) => (
14
+ <View
15
+ resizeable
16
+ title={`Tab ${index}`}
17
+ style={{ flexGrow: 1, flexShrink: 0, flexBasis: 0 }}
18
+ header
19
+ closeable
20
+ >
21
+ <Component style={{ flex: 1 }} />
22
+ </View>
23
+ );
24
+
25
+ export const StackLayout = (props: StackProps) => {
26
+ const ref = useRef<HTMLDivElement>(null);
27
+ const dispatch = useLayoutProviderDispatch();
28
+ const { loadState } = usePersistentState();
29
+
30
+ const {
31
+ createNewChild = defaultCreateNewChild,
32
+ id: idProp,
33
+ onTabSelectionChanged,
34
+ path,
35
+ ...restProps
36
+ } = props;
37
+
38
+ const { children } = props;
39
+
40
+ const id = useId(idProp);
41
+
42
+ const [dispatchViewAction] = useViewActionDispatcher(id, ref, path);
43
+
44
+ const handleTabSelection = (nextIdx: number) => {
45
+ console.log(`StackLayout handleTabSelection nextTab = ${nextIdx}`);
46
+ if (path) {
47
+ dispatch({ type: "switch-tab", path, nextIdx });
48
+ onTabSelectionChanged?.(nextIdx);
49
+ }
50
+ };
51
+
52
+ const handleTabClose = (tabIndex: number) => {
53
+ if (Array.isArray(children)) {
54
+ const {
55
+ props: { "data-path": dataPath, path = dataPath },
56
+ } = children[tabIndex];
57
+ dispatch({ type: "remove", path });
58
+ }
59
+ };
60
+
61
+ const handleTabAdd = (e: unknown, tabIndex = React.Children.count(children)) => {
62
+ if (path) {
63
+ console.log(`[StackLayout] handleTabAdd`);
64
+ const component = createNewChild(tabIndex);
65
+ console.log({ component });
66
+ dispatch({
67
+ type: "add",
68
+ path,
69
+ component,
70
+ });
71
+ }
72
+ };
73
+
74
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
75
+ const handleMouseDown = async (e: any, index: number) => {
76
+ let readyToDrag: undefined | ((value: unknown) => void);
77
+
78
+ const preDragActivity = async () =>
79
+ new Promise((resolve) => {
80
+ console.log("preDragActivity: Ok, gonna release the drag");
81
+ readyToDrag = resolve;
82
+ });
83
+
84
+ const dragging = await dispatchViewAction(
85
+ { type: "mousedown", index, preDragActivity },
86
+ e
87
+ );
88
+
89
+ if (dragging) {
90
+ readyToDrag?.(undefined);
91
+ }
92
+ };
93
+
94
+ const handleTabEdit = (tabIndex: number, text: string) => {
95
+ dispatch({ type: "set-title", path: `${path}.${tabIndex}`, title: text });
96
+ };
97
+
98
+ const getTabLabel = (component: ReactElement, idx: number) => {
99
+ const { id, title } = component.props;
100
+ return loadState(id, "view-title") || title || `Tab ${idx + 1}`;
101
+ };
102
+
103
+ return (
104
+ <Stack
105
+ {...restProps}
106
+ id={id}
107
+ getTabLabel={getTabLabel}
108
+ onMouseDown={handleMouseDown}
109
+ onTabAdd={handleTabAdd}
110
+ onTabClose={handleTabClose}
111
+ onTabEdit={handleTabEdit}
112
+ onTabSelectionChanged={handleTabSelection}
113
+ ref={ref}
114
+ />
115
+ );
116
+ };
117
+ StackLayout.displayName = "Stack";
118
+
119
+ registerComponent("Stack", StackLayout, "container");
@@ -0,0 +1,4 @@
1
+ export * from "./Stack";
2
+ export * from "./StackLayout";
3
+ export * from "./stackTypes";
4
+
@@ -0,0 +1,22 @@
1
+ import { TabstripProps } from "@heswell/salt-lab";
2
+ import { HTMLAttributes, MouseEvent, ReactElement, ReactNode } from "react";
3
+
4
+ export interface StackProps
5
+ extends Omit<HTMLAttributes<HTMLDivElement>, "onMouseDown"> {
6
+ active?: number;
7
+ createNewChild?: (index: number) => ReactElement;
8
+ enableAddTab?: boolean;
9
+ enableCloseTabs?: boolean;
10
+ getTabIcon?: (component: ReactElement, index: number) => string | undefined;
11
+ getTabLabel?: (component: ReactElement, index: number) => string | undefined;
12
+ keyBoardActivation?: "automatic" | "manual";
13
+ onMouseDown?: (e: MouseEvent, tabIndex: number) => void;
14
+ onTabAdd?: (tabIndex: number) => void;
15
+ onTabClose?: (tabIndex: number) => void;
16
+ onTabEdit?: (tabIndex: number, label: string) => void;
17
+ onTabSelectionChanged?: (nextIndex: number) => void;
18
+ path?: string;
19
+ showTabs?: boolean;
20
+ toolbarContent?: ReactNode;
21
+ TabstripProps?: Partial<TabstripProps>;
22
+ }
@@ -0,0 +1,12 @@
1
+ .TabPanel {
2
+ display: flex;
3
+ flex: 1;
4
+ }
5
+
6
+ .TabPanel > * {
7
+ height: 100%;
8
+ }
9
+
10
+ .TabPanel > .View > .Header {
11
+ display: none;
12
+ }
@@ -0,0 +1,17 @@
1
+ import { HTMLAttributes } from 'react';
2
+
3
+ import './TabPanel.css';
4
+
5
+ export interface TabPanelProps extends HTMLAttributes<HTMLDivElement>{
6
+ ariaLabelledBy: string;
7
+ }
8
+
9
+ const TabPanel = ({ ariaLabelledBy, children, id }: TabPanelProps) => {
10
+ return (
11
+ <div className="TabPanel" id={id} role="tabpanel" aria-labelledby={ariaLabelledBy}>
12
+ {children}
13
+ </div>
14
+ );
15
+ };
16
+
17
+ export default TabPanel;
@@ -0,0 +1 @@
1
+ export { default as TabPanel } from './TabPanel';
@@ -0,0 +1,55 @@
1
+ import React, { useState } from "react";
2
+
3
+ import { LayoutConfigurator, LayoutTreeViewer } from "..";
4
+ import { followPathToComponent } from "../..";
5
+
6
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
7
+ export const ConfigWrapper = ({ children }: any) => {
8
+ const designMode = false;
9
+ const [layout, setLayout] = useState(children);
10
+ const [selectedComponent, setSelectedComponent] = useState(children);
11
+
12
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
13
+ const handleSelection = (selectedPath: any) => {
14
+ const targetComponent = followPathToComponent(layout, selectedPath);
15
+ setSelectedComponent(targetComponent);
16
+ };
17
+
18
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
19
+ const handleChange = (property: any, value: any) => {
20
+ console.log(`change ${property} -> ${value}`);
21
+
22
+ const newComponent = React.cloneElement(selectedComponent, {
23
+ style: {
24
+ ...selectedComponent.props.style,
25
+ [property]: value,
26
+ },
27
+ });
28
+ setSelectedComponent(newComponent);
29
+ setLayout(React.cloneElement(layout, {}, newComponent));
30
+ };
31
+
32
+ return (
33
+ <div data-design-mode={`${designMode}`}>
34
+ {layout}
35
+ <br />
36
+ <div style={{ display: "flex" }}>
37
+ <LayoutConfigurator
38
+ height={300}
39
+ managedStyle={selectedComponent.props.style}
40
+ width={300}
41
+ onChange={handleChange}
42
+ style={undefined}
43
+ />
44
+ <LayoutTreeViewer
45
+ layout={layout}
46
+ onSelect={handleSelection}
47
+ style={{ width: 300, height: 300, backgroundColor: "#ccc" }}
48
+ />
49
+ </div>
50
+ {/* <StateButton
51
+ defaultChecked={false}
52
+ onChange={(e, value) => setDesignMode(value)}>Design Mode</StateButton> */}
53
+ </div>
54
+ );
55
+ };
@@ -0,0 +1 @@
1
+ export * from './ConfigWrapper';
@@ -0,0 +1,112 @@
1
+ [data-design-mode='true'] .Component {
2
+ filter: grayscale(100%);
3
+ opacity: 0.4;
4
+ }
5
+
6
+ [data-design-mode='true'] .Component:after {
7
+ color: black;
8
+ content: 'Component';
9
+ height: 12px;
10
+ background-color: yellow;
11
+ }
12
+
13
+ .LayoutConfigurator {
14
+ --margin-color: #f3cea5;
15
+ --border-color: #fddda0;
16
+ --padding-color: #c6d092;
17
+ --content-color: #8cb6c0;
18
+ display: flex;
19
+ flex-direction: column;
20
+ align-items: stretch;
21
+ background-color: var(--margin-color);
22
+ }
23
+
24
+ .LayoutConfigurator .layout-outer {
25
+ flex: 1 1 auto;
26
+ display: flex;
27
+ flex-direction: column;
28
+ align-items: stretch;
29
+ }
30
+
31
+ .LayoutBox {
32
+ --hw-control-font-size: 13px;
33
+ --hw-text-input-bg: rgba(255, 255, 255, 0.3);
34
+ --hwTextInput-padding: 3px;
35
+ --hw-text-input-position: absolute;
36
+ --hwTextInput-width: 30px;
37
+
38
+ flex: 1 1 auto;
39
+ }
40
+
41
+ .LayoutBox > .layout-top {
42
+ flex: 0 0 40px;
43
+ padding-left: 12px;
44
+ display: flex;
45
+ flex-direction: row;
46
+ align-items: center;
47
+ position: relative;
48
+ }
49
+
50
+ .LayoutBox > .layout-bottom {
51
+ flex: 0 0 40px;
52
+ position: relative;
53
+ display: flex;
54
+ flex-direction: row;
55
+ align-items: center;
56
+ }
57
+
58
+ .LayoutBox > .layout-inner > .layout-right,
59
+ .LayoutBox > .layout-inner > .layout-left {
60
+ flex: 0 0 40px;
61
+ display: flex;
62
+ flex-direction: column;
63
+ justify-content: center;
64
+ align-items: center;
65
+ }
66
+
67
+ .layout-top,
68
+ .layout-bottom {
69
+ --hw-text-input-margin: 0 0 0 -15px;
70
+ }
71
+
72
+ .layout-top > .layout-input,
73
+ .layout-bottom > .layout-input {
74
+ left: 50%;
75
+ }
76
+
77
+ .LayoutBox > .layout-inner {
78
+ flex: 1 1 auto;
79
+ display: flex;
80
+ flex-direction: row;
81
+ align-items: stretch;
82
+ }
83
+
84
+ .LayoutBox.layout-margin {
85
+ background-color: var(--margin-color);
86
+ border: dashed 2px black;
87
+ }
88
+
89
+ .LayoutBox.layout-border {
90
+ background-color: var(--border-color);
91
+ border: solid 2px black;
92
+ }
93
+
94
+ .LayoutBox.layout-padding {
95
+ background-color: var(--padding-color);
96
+ border: dashed 2px black;
97
+ }
98
+
99
+ .LayoutBox .layout-content {
100
+ flex: 1 1 auto;
101
+ background-color: var(--content-color);
102
+ border: solid 2px #808080;
103
+ }
104
+
105
+ .LayoutBox .layout-title {
106
+ color: #161616;
107
+ font-size: 11px;
108
+ left: 4px;
109
+ line-height: 15px;
110
+ position: absolute;
111
+ top: 1px;
112
+ }