@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,49 @@
|
|
|
1
|
+
import type { ReactElement } from 'react';
|
|
2
|
+
import type { rect } from '../common-types';
|
|
3
|
+
import { DropTarget } from './DropTarget';
|
|
4
|
+
export interface DragDropRect extends rect {
|
|
5
|
+
children?: DragDropRect[];
|
|
6
|
+
header?: {
|
|
7
|
+
top: number;
|
|
8
|
+
left: number;
|
|
9
|
+
right: number;
|
|
10
|
+
bottom: number;
|
|
11
|
+
titleWidth?: number;
|
|
12
|
+
};
|
|
13
|
+
height: number;
|
|
14
|
+
scrolling?: { id: string; scrollTop: number; scrollHeight: number };
|
|
15
|
+
Stack?: { left: number; right: number }[];
|
|
16
|
+
width: number;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface DropPosition {
|
|
20
|
+
Absolute: boolean;
|
|
21
|
+
Centre: boolean;
|
|
22
|
+
East: boolean;
|
|
23
|
+
EastOrWest: boolean;
|
|
24
|
+
Header: boolean;
|
|
25
|
+
North: boolean;
|
|
26
|
+
NorthOrSouth: boolean;
|
|
27
|
+
offset: number;
|
|
28
|
+
South: boolean;
|
|
29
|
+
SouthOrEast: boolean;
|
|
30
|
+
West: boolean;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export type RelativePosition = 'after' | 'before';
|
|
34
|
+
|
|
35
|
+
export type DropPosTab = {
|
|
36
|
+
index: number;
|
|
37
|
+
left: number;
|
|
38
|
+
positionRelativeToTab: RelativePosition;
|
|
39
|
+
width: number;
|
|
40
|
+
};
|
|
41
|
+
export interface DropPos {
|
|
42
|
+
closeToTheEdge: number;
|
|
43
|
+
height?: number;
|
|
44
|
+
position: DropPosition;
|
|
45
|
+
tab?: DropPosTab;
|
|
46
|
+
width?: number;
|
|
47
|
+
x: number;
|
|
48
|
+
y: number;
|
|
49
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
.hwEditableLabel {
|
|
2
|
+
--input-border-width: 1px;
|
|
3
|
+
color: inherit;
|
|
4
|
+
font-size: inherit;
|
|
5
|
+
z-index: 1;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
.hwEditableLabel-editing::after {
|
|
9
|
+
content: attr(data-text) ' ';
|
|
10
|
+
visibility: hidden;
|
|
11
|
+
white-space: pre-wrap;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.hwEditableLabel-input {
|
|
15
|
+
bottom: 0;
|
|
16
|
+
border: solid grey var(--input-border-width);
|
|
17
|
+
/* font-weight: var(--hw-font-weight-regular); */
|
|
18
|
+
left: var(--tab-spacing, 0);
|
|
19
|
+
outline: none;
|
|
20
|
+
padding: 0;
|
|
21
|
+
position: absolute;
|
|
22
|
+
outline-style: none;
|
|
23
|
+
right: var(--tab-spacing, 0);
|
|
24
|
+
top: 0;
|
|
25
|
+
height: calc(100% - 2 * var(--input-border-width));
|
|
26
|
+
width: calc(100% - 2 * var(--input-border-width));
|
|
27
|
+
white-space: nowrap;
|
|
28
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import React, { ChangeEvent, FocusEvent, HTMLAttributes, KeyboardEvent, MouseEvent, useLayoutEffect, useRef, useState } from 'react';
|
|
2
|
+
import cx from 'classnames';
|
|
3
|
+
|
|
4
|
+
import './EditableLabel.css';
|
|
5
|
+
|
|
6
|
+
export interface EditableLabelProps extends HTMLAttributes<HTMLDivElement>{
|
|
7
|
+
onEnterEditMode?: (evt: MouseEvent) => void;
|
|
8
|
+
onExitEditMode?: (evt: FocusEvent | KeyboardEvent, value: string) => void;
|
|
9
|
+
value: string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const EditableLabel = ({
|
|
13
|
+
className: classNameProp,
|
|
14
|
+
onEnterEditMode,
|
|
15
|
+
onExitEditMode,
|
|
16
|
+
value: valueProp
|
|
17
|
+
}: EditableLabelProps) => {
|
|
18
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
19
|
+
const [editing, setEditing] = useState(false);
|
|
20
|
+
const isEditing = useRef(false);
|
|
21
|
+
const [value, setValue] = useState(valueProp);
|
|
22
|
+
const classBase = 'hwEditableLabel';
|
|
23
|
+
|
|
24
|
+
useLayoutEffect(() => {
|
|
25
|
+
if (editing) {
|
|
26
|
+
inputRef.current?.select();
|
|
27
|
+
inputRef.current?.focus();
|
|
28
|
+
}
|
|
29
|
+
}, [editing, inputRef]);
|
|
30
|
+
|
|
31
|
+
const enterEditMode = (evt: MouseEvent) => {
|
|
32
|
+
if (!isEditing.current) {
|
|
33
|
+
setEditing((isEditing.current = true));
|
|
34
|
+
onEnterEditMode && onEnterEditMode(evt);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const exitEditMode = (evt: FocusEvent | KeyboardEvent) => {
|
|
39
|
+
if (isEditing.current) {
|
|
40
|
+
setEditing((isEditing.current = false));
|
|
41
|
+
onExitEditMode && onExitEditMode(evt, value);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
const handleChange = (evt: ChangeEvent) => {
|
|
46
|
+
evt.stopPropagation();
|
|
47
|
+
setValue((evt.target as HTMLInputElement).value);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const handleDoubleClick = (evt: MouseEvent<HTMLSpanElement>) => {
|
|
51
|
+
enterEditMode(evt);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
const handleBlur = (evt: FocusEvent<HTMLInputElement>) => {
|
|
55
|
+
exitEditMode(evt);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const handleKeyDown = (evt: KeyboardEvent<HTMLInputElement>) => {
|
|
59
|
+
evt.stopPropagation();
|
|
60
|
+
if (evt.key === 'Enter') {
|
|
61
|
+
exitEditMode(evt);
|
|
62
|
+
} else if (evt.key === 'ArrowRight' || evt.key === 'ArrowLeft') {
|
|
63
|
+
evt.stopPropagation();
|
|
64
|
+
} else if (evt.key === 'Escape') {
|
|
65
|
+
// TODO restore original value
|
|
66
|
+
exitEditMode(evt);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const handleKeyUp = (evt: KeyboardEvent<HTMLInputElement>) => {
|
|
71
|
+
evt.stopPropagation();
|
|
72
|
+
evt.preventDefault();
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const className = cx(classBase, classNameProp, {
|
|
76
|
+
[`${classBase}-editing`]: editing
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
return (
|
|
80
|
+
<span className={className} onDoubleClick={handleDoubleClick} data-text={value}>
|
|
81
|
+
{editing ? (
|
|
82
|
+
<input
|
|
83
|
+
className={`${classBase}-input`}
|
|
84
|
+
value={value}
|
|
85
|
+
onBlur={handleBlur}
|
|
86
|
+
onChange={handleChange}
|
|
87
|
+
onKeyDown={handleKeyDown}
|
|
88
|
+
onKeyUp={handleKeyUp}
|
|
89
|
+
ref={inputRef}
|
|
90
|
+
style={{ padding: 0 }}
|
|
91
|
+
/>
|
|
92
|
+
) : (
|
|
93
|
+
value
|
|
94
|
+
)}
|
|
95
|
+
</span>
|
|
96
|
+
);
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export default EditableLabel;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as EditableLabel } from './EditableLabel';
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--hw-space-unit: 4px;
|
|
3
|
+
--hw-flex-gap: 3;
|
|
4
|
+
--hw-fluid-grid-col-bg: rgba(200, 200, 200, 0.3);
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.hwFlexbox {
|
|
8
|
+
background-color: var(--container1-background);
|
|
9
|
+
box-sizing: border-box;
|
|
10
|
+
display: flex;
|
|
11
|
+
gap: calc(var(--spacing) * var(--space));
|
|
12
|
+
min-height: 0;
|
|
13
|
+
min-width: 0;
|
|
14
|
+
overflow: hidden;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
.hwFlexbox-column {
|
|
18
|
+
flex-direction: column;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.hwFlexbox-row {
|
|
22
|
+
flex-direction: row;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.hwFlexbox > .Splitter {
|
|
26
|
+
flex-basis: auto;
|
|
27
|
+
flex-grow: 0;
|
|
28
|
+
flex-shrink: 0;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.hwFlexbox.full-page {
|
|
32
|
+
height: 100vh;
|
|
33
|
+
width: 100vw;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.flex-fill {
|
|
37
|
+
border-color: red;
|
|
38
|
+
flex: 0;
|
|
39
|
+
flex-grow: 1;
|
|
40
|
+
flex-shrink: 1;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.vuuView.flex-fill {
|
|
44
|
+
border-color: red;
|
|
45
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { useForkRef } from "@heswell/uitk-core";
|
|
2
|
+
import cx from "classnames";
|
|
3
|
+
import { CSSProperties, ForwardedRef, forwardRef } from "react";
|
|
4
|
+
import { FlexboxProps } from "./flexboxTypes";
|
|
5
|
+
import { useSplitterResizing } from "./useSplitterResizing";
|
|
6
|
+
|
|
7
|
+
import "./Flexbox.css";
|
|
8
|
+
|
|
9
|
+
const classBase = "hwFlexbox";
|
|
10
|
+
|
|
11
|
+
const Flexbox = forwardRef(function Flexbox(
|
|
12
|
+
props: FlexboxProps,
|
|
13
|
+
ref: ForwardedRef<HTMLDivElement>
|
|
14
|
+
) {
|
|
15
|
+
const {
|
|
16
|
+
breakPoints,
|
|
17
|
+
children,
|
|
18
|
+
// cols: colsProp,
|
|
19
|
+
column,
|
|
20
|
+
className: classNameProp,
|
|
21
|
+
flexFill,
|
|
22
|
+
gap,
|
|
23
|
+
fullPage,
|
|
24
|
+
id,
|
|
25
|
+
onSplitterMoved,
|
|
26
|
+
resizeable,
|
|
27
|
+
row,
|
|
28
|
+
spacing,
|
|
29
|
+
splitterSize,
|
|
30
|
+
style,
|
|
31
|
+
...rest
|
|
32
|
+
} = props;
|
|
33
|
+
|
|
34
|
+
const { content, rootRef } = useSplitterResizing({
|
|
35
|
+
children,
|
|
36
|
+
// cols: colsProp,
|
|
37
|
+
onSplitterMoved,
|
|
38
|
+
style,
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const className = cx(classBase, classNameProp, {
|
|
42
|
+
[`${classBase}-column`]: column,
|
|
43
|
+
[`${classBase}-row`]: row,
|
|
44
|
+
"flex-fill": flexFill,
|
|
45
|
+
"full-page": fullPage,
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<div
|
|
50
|
+
{...rest}
|
|
51
|
+
className={className}
|
|
52
|
+
// data-cols={cols}
|
|
53
|
+
data-resizeable={resizeable || undefined}
|
|
54
|
+
id={id}
|
|
55
|
+
ref={useForkRef(rootRef, ref)}
|
|
56
|
+
style={
|
|
57
|
+
{
|
|
58
|
+
...style,
|
|
59
|
+
gap,
|
|
60
|
+
"--spacing": spacing,
|
|
61
|
+
} as CSSProperties
|
|
62
|
+
}
|
|
63
|
+
>
|
|
64
|
+
{content}
|
|
65
|
+
</div>
|
|
66
|
+
);
|
|
67
|
+
});
|
|
68
|
+
Flexbox.displayName = "Flexbox";
|
|
69
|
+
|
|
70
|
+
export default Flexbox;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React, { useCallback } from 'react';
|
|
2
|
+
import Flexbox from './Flexbox';
|
|
3
|
+
import { Action } from '../layout-action';
|
|
4
|
+
import { registerComponent } from '../registry/ComponentRegistry';
|
|
5
|
+
import { useLayoutProviderDispatch } from '../layout-provider';
|
|
6
|
+
|
|
7
|
+
export const FlexboxLayout = function FlexboxLayout(props) {
|
|
8
|
+
const { path } = props;
|
|
9
|
+
const dispatch = useLayoutProviderDispatch();
|
|
10
|
+
|
|
11
|
+
const handleSplitterMoved = useCallback(
|
|
12
|
+
(sizes) => {
|
|
13
|
+
dispatch({
|
|
14
|
+
type: Action.SPLITTER_RESIZE,
|
|
15
|
+
path,
|
|
16
|
+
sizes
|
|
17
|
+
});
|
|
18
|
+
},
|
|
19
|
+
[dispatch, path]
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
return <Flexbox {...props} onSplitterMoved={handleSplitterMoved} />;
|
|
23
|
+
};
|
|
24
|
+
FlexboxLayout.displayName = 'Flexbox';
|
|
25
|
+
|
|
26
|
+
registerComponent('Flexbox', FlexboxLayout, 'container');
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--hw-space-unit: 4px;
|
|
3
|
+
--hw-fluid-grid-col-bg: rgba(252, 209, 232, 0.7);
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
.hwFluidGrid {
|
|
7
|
+
--gap: var(--gutter-width);
|
|
8
|
+
|
|
9
|
+
display: flex;
|
|
10
|
+
gap: calc(var(--grid-gap) * var(--hw-space-unit));
|
|
11
|
+
flex-wrap: wrap;
|
|
12
|
+
padding: 0;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
.hwFluidGrid > * {
|
|
16
|
+
--gutter-width: calc(var(--hw-flex-gap) * var(--hw-space-unit));
|
|
17
|
+
--gutter-count: calc(var(--parent-col-count) - 1);
|
|
18
|
+
--total-gutter-width: calc(var(--gutter-count) * var(--gutter-width));
|
|
19
|
+
--available-width: calc(100% - var(--total-gutter-width));
|
|
20
|
+
|
|
21
|
+
flex-basis: 0;
|
|
22
|
+
flex-grow: 1;
|
|
23
|
+
flex-shrink: 1;
|
|
24
|
+
position: relative;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.hwFluidGrid > *:after {
|
|
28
|
+
content: '';
|
|
29
|
+
position: absolute;
|
|
30
|
+
top: 0;
|
|
31
|
+
left: 0;
|
|
32
|
+
right: 0;
|
|
33
|
+
bottom: 0;
|
|
34
|
+
border: dashed 2px blue;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.hwFluidGrid > [data-xs] {
|
|
38
|
+
--internal-gutter-count: calc(var(--col-span) - 1);
|
|
39
|
+
--percent-width: calc(var(--col-span) / var(--parent-col-count));
|
|
40
|
+
--internal-gutter-width: calc(var(--internal-gutter-count) * var(--gutter-width));
|
|
41
|
+
flex-basis: calc(var(--available-width) * var(--percent-width) + var(--internal-gutter-width));
|
|
42
|
+
flex-grow: 0;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.hwFluidGrid > [data-xs='1'] {
|
|
46
|
+
--col-span: 1;
|
|
47
|
+
}
|
|
48
|
+
.hwFluidGrid > [data-xs='2'] {
|
|
49
|
+
--col-span: 2;
|
|
50
|
+
}
|
|
51
|
+
.hwFluidGrid > [data-xs='3'] {
|
|
52
|
+
--col-span: 3;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.hwFluidGrid > [data-xs='4'] {
|
|
56
|
+
--col-span: 4;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.hwFluidGrid > [data-xs='6'] {
|
|
60
|
+
--col-span: 6;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.hwFluidGrid > [data-xs='8'] {
|
|
64
|
+
--col-span: 8;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
.hwFluidGrid > [data-xs='9'] {
|
|
68
|
+
--col-span: 9;
|
|
69
|
+
}
|
|
70
|
+
.hwFluidGrid > [data-xs='10'] {
|
|
71
|
+
--col-span: 10;
|
|
72
|
+
}
|
|
73
|
+
.hwFluidGrid > [data-xs='11'] {
|
|
74
|
+
--col-span: 11;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.hwFluidGrid > [data-xs='12'] {
|
|
78
|
+
--col-span: 12;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@media (min-width: 600px) {
|
|
82
|
+
.hwFluidGrid > [data-sm='1'] {
|
|
83
|
+
--col-span: 1;
|
|
84
|
+
}
|
|
85
|
+
.hwFluidGrid > [data-sm='2'] {
|
|
86
|
+
--col-span: 2;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.hwFluidGrid > [data-sm='3'] {
|
|
90
|
+
--col-span: 3;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.hwFluidGrid > [data-sm='4'] {
|
|
94
|
+
--col-span: 4;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.hwFluidGrid > [data-sm='6'] {
|
|
98
|
+
--col-span: 6;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.hwFluidGrid > [data-sm='8'] {
|
|
102
|
+
--col-span: 8;
|
|
103
|
+
}
|
|
104
|
+
.hwFluidGrid > [data-sm='9'] {
|
|
105
|
+
--col-span: 9;
|
|
106
|
+
}
|
|
107
|
+
.hwFluidGrid > [data-sm='10'] {
|
|
108
|
+
--col-span: 10;
|
|
109
|
+
}
|
|
110
|
+
.hwFluidGrid > [data-sm='11'] {
|
|
111
|
+
--col-span: 11;
|
|
112
|
+
}
|
|
113
|
+
.hwFluidGrid > [data-sm='12'] {
|
|
114
|
+
--col-span: 12;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* Display the grid background */
|
|
119
|
+
|
|
120
|
+
.hwFluidGrid-show-grid {
|
|
121
|
+
--gutter-width: calc(var(--hw-flex-gap) * var(--hw-space-unit));
|
|
122
|
+
--grid-gutter-count: calc(var(--grid-col-count, var(--parent-col-count)) - 1);
|
|
123
|
+
--grid-total-gutter-width: calc(var(--grid-gutter-count) * var(--gutter-width));
|
|
124
|
+
--grid-available-width: calc(100% - var(--grid-total-gutter-width));
|
|
125
|
+
--grid-percent-width: calc(1 / var(--grid-col-count, var(--parent-col-count)));
|
|
126
|
+
--column-width: calc(var(--grid-available-width) * var(--grid-percent-width));
|
|
127
|
+
background: repeating-linear-gradient(
|
|
128
|
+
to right,
|
|
129
|
+
var(--hw-fluid-grid-col-bg) 0,
|
|
130
|
+
var(--hw-fluid-grid-col-bg) var(--column-width),
|
|
131
|
+
white var(--column-width),
|
|
132
|
+
white calc(var(--column-width) + var(--gutter-width))
|
|
133
|
+
);
|
|
134
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { useForkRef } from "@heswell/uitk-core";
|
|
2
|
+
import cx from "classnames";
|
|
3
|
+
import { ForwardedRef, forwardRef } from "react";
|
|
4
|
+
import { useBreakpoints } from "../responsive";
|
|
5
|
+
import { FlexboxProps } from "./flexboxTypes";
|
|
6
|
+
import "./FluidGrid.css";
|
|
7
|
+
import { useResponsiveSizing } from "./useResponsiveSizing";
|
|
8
|
+
|
|
9
|
+
const classBase = "hwFluidGrid";
|
|
10
|
+
|
|
11
|
+
export interface FluidGridProps extends FlexboxProps {
|
|
12
|
+
showGrid?: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const FluidGrid = forwardRef(function FluidGrid(
|
|
16
|
+
props: FluidGridProps,
|
|
17
|
+
ref: ForwardedRef<HTMLDivElement>
|
|
18
|
+
) {
|
|
19
|
+
const {
|
|
20
|
+
breakPoints,
|
|
21
|
+
children,
|
|
22
|
+
column,
|
|
23
|
+
cols: colsProp = 12,
|
|
24
|
+
className: classNameProp,
|
|
25
|
+
flexFill,
|
|
26
|
+
gap = 3,
|
|
27
|
+
fullPage,
|
|
28
|
+
id,
|
|
29
|
+
onSplitterMoved,
|
|
30
|
+
resizeable,
|
|
31
|
+
row,
|
|
32
|
+
showGrid,
|
|
33
|
+
spacing,
|
|
34
|
+
splitterSize,
|
|
35
|
+
style: styleProp,
|
|
36
|
+
...rest
|
|
37
|
+
} = props;
|
|
38
|
+
|
|
39
|
+
const { cols, content, rootRef } = useResponsiveSizing({
|
|
40
|
+
children,
|
|
41
|
+
cols: colsProp,
|
|
42
|
+
// onSplitterMoved,
|
|
43
|
+
style: styleProp,
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const breakpoint = useBreakpoints(
|
|
47
|
+
{
|
|
48
|
+
breakPoints,
|
|
49
|
+
},
|
|
50
|
+
rootRef
|
|
51
|
+
);
|
|
52
|
+
|
|
53
|
+
const className = cx(classBase, classNameProp, {
|
|
54
|
+
[`${classBase}-column`]: column,
|
|
55
|
+
[`${classBase}-row`]: row,
|
|
56
|
+
[`${classBase}-show-grid`]: showGrid,
|
|
57
|
+
"flex-fill": flexFill,
|
|
58
|
+
"full-page": fullPage,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
const style = {
|
|
62
|
+
...styleProp,
|
|
63
|
+
"--spacing": spacing,
|
|
64
|
+
// only needed to display the cols
|
|
65
|
+
"--grid-col-count": cols,
|
|
66
|
+
"--grid-gap": gap,
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<div
|
|
71
|
+
{...rest}
|
|
72
|
+
className={className}
|
|
73
|
+
data-breakpoint={breakpoint}
|
|
74
|
+
data-cols={cols}
|
|
75
|
+
data-resizeable={resizeable || undefined}
|
|
76
|
+
id={id}
|
|
77
|
+
ref={useForkRef(rootRef, ref)}
|
|
78
|
+
style={style}
|
|
79
|
+
>
|
|
80
|
+
{content}
|
|
81
|
+
</div>
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
FluidGrid.displayName = "FluidGrid";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import {FluidGrid, FluidGridProps} from './FluidGrid';
|
|
3
|
+
import { registerComponent } from '../registry/ComponentRegistry';
|
|
4
|
+
|
|
5
|
+
export const FluidGridLayout = function FluidGridLayout(props: FluidGridProps) {
|
|
6
|
+
return <FluidGrid {...props} />;
|
|
7
|
+
};
|
|
8
|
+
FluidGridLayout.displayName = 'FluidGrid';
|
|
9
|
+
|
|
10
|
+
registerComponent('FluidGrid', FluidGridLayout, 'container');
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
.Splitter {
|
|
2
|
+
--splitter-size: 3px;
|
|
3
|
+
--splitter-border-width: 4px;
|
|
4
|
+
--splitter-border-style: none;
|
|
5
|
+
--splitter-border-color: white;
|
|
6
|
+
|
|
7
|
+
align-items: center;
|
|
8
|
+
background-color: var(--grey60);
|
|
9
|
+
border-color: var(--splitter-border-color);
|
|
10
|
+
border-style: var(--splitter-border-style);
|
|
11
|
+
box-sizing: border-box;
|
|
12
|
+
display: flex;
|
|
13
|
+
justify-content: center;
|
|
14
|
+
position: relative;
|
|
15
|
+
outline: none;
|
|
16
|
+
z-index: 1;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.Splitter:hover {
|
|
20
|
+
background-color: var(--grey40);
|
|
21
|
+
}
|
|
22
|
+
.active.Splitter {
|
|
23
|
+
background-color: var(--blue500);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
.Splitter.column {
|
|
27
|
+
cursor: ns-resize;
|
|
28
|
+
height: var(--splitter-size);
|
|
29
|
+
border-width: var(--splitter-border-width) 0;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.Splitter:not(.column) {
|
|
33
|
+
cursor: ew-resize;
|
|
34
|
+
width: var(--splitter-size);
|
|
35
|
+
border-width: 0 var(--splitter-border-width);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.Splitter:before {
|
|
39
|
+
border: none;
|
|
40
|
+
border-radius: 0;
|
|
41
|
+
content: '';
|
|
42
|
+
display: block;
|
|
43
|
+
padding: 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.Splitter .grab-zone {
|
|
47
|
+
position: absolute;
|
|
48
|
+
background-color: rgba(255, 0, 0, 0.01);
|
|
49
|
+
cursor: inherit;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
.Splitter.column .grab-zone {
|
|
53
|
+
left: 0;
|
|
54
|
+
right: 0;
|
|
55
|
+
top: -5px;
|
|
56
|
+
bottom: -5px;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.Splitter:not(column) .grab-zone {
|
|
60
|
+
left: -5px;
|
|
61
|
+
right: -5px;
|
|
62
|
+
top: 0;
|
|
63
|
+
bottom: 0;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
.Splitter:not(.column):before {
|
|
67
|
+
width: 1px;
|
|
68
|
+
height: 10px;
|
|
69
|
+
background: linear-gradient(
|
|
70
|
+
to bottom,
|
|
71
|
+
var(--grey900) 10%,
|
|
72
|
+
transparent 10%,
|
|
73
|
+
transparent 30%,
|
|
74
|
+
var(--grey900) 30%,
|
|
75
|
+
var(--grey900) 40%,
|
|
76
|
+
transparent 40%,
|
|
77
|
+
transparent 60%,
|
|
78
|
+
var(--grey900) 60%,
|
|
79
|
+
var(--grey900) 70%,
|
|
80
|
+
transparent 70%,
|
|
81
|
+
transparent 90%,
|
|
82
|
+
var(--grey900) 90%
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.active.Splitter.column:before {
|
|
87
|
+
background: linear-gradient(
|
|
88
|
+
to right,
|
|
89
|
+
#ffffff 10%,
|
|
90
|
+
transparent 10%,
|
|
91
|
+
transparent 30%,
|
|
92
|
+
#ffffff 30%,
|
|
93
|
+
#ffffff 40%,
|
|
94
|
+
transparent 40%,
|
|
95
|
+
transparent 60%,
|
|
96
|
+
#ffffff 60%,
|
|
97
|
+
#ffffff 70%,
|
|
98
|
+
transparent 70%,
|
|
99
|
+
transparent 90%,
|
|
100
|
+
#ffffff 90%
|
|
101
|
+
);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.active.Splitter:not(.column):before {
|
|
105
|
+
background: linear-gradient(
|
|
106
|
+
to bottom,
|
|
107
|
+
#ffffff 10%,
|
|
108
|
+
transparent 10%,
|
|
109
|
+
transparent 30%,
|
|
110
|
+
#ffffff 30%,
|
|
111
|
+
#ffffff 40%,
|
|
112
|
+
transparent 40%,
|
|
113
|
+
transparent 60%,
|
|
114
|
+
#ffffff 60%,
|
|
115
|
+
#ffffff 70%,
|
|
116
|
+
transparent 70%,
|
|
117
|
+
transparent 90%,
|
|
118
|
+
#ffffff 90%
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.Splitter.column:before {
|
|
123
|
+
width: 10px;
|
|
124
|
+
height: 1px;
|
|
125
|
+
background: linear-gradient(
|
|
126
|
+
to right,
|
|
127
|
+
var(--grey900) 10%,
|
|
128
|
+
transparent 10%,
|
|
129
|
+
transparent 30%,
|
|
130
|
+
var(--grey900) 30%,
|
|
131
|
+
var(--grey900) 40%,
|
|
132
|
+
transparent 40%,
|
|
133
|
+
transparent 60%,
|
|
134
|
+
var(--grey900) 60%,
|
|
135
|
+
var(--grey900) 70%,
|
|
136
|
+
transparent 70%,
|
|
137
|
+
transparent 90%,
|
|
138
|
+
var(--grey900) 90%
|
|
139
|
+
);
|
|
140
|
+
}
|