@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,48 @@
|
|
|
1
|
+
// should we have some global; defaults ?
|
|
2
|
+
|
|
3
|
+
import { BreakPointsProp } from '../flexbox/flexboxTypes';
|
|
4
|
+
|
|
5
|
+
export type BreakPointRamp = [string, number, number];
|
|
6
|
+
|
|
7
|
+
function breakpointReader(themeName: string, defaultBreakpoints?: BreakPointsProp) {
|
|
8
|
+
//TODO ownerDocument
|
|
9
|
+
const themeRoot = document.body.querySelector(`.${themeName}`);
|
|
10
|
+
const handler = {
|
|
11
|
+
get: function (style: CSSStyleDeclaration, stopName: string) {
|
|
12
|
+
const val = style.getPropertyValue(
|
|
13
|
+
// lets assume we have the following naming convention
|
|
14
|
+
`--${themeName}-breakpoint-${stopName}`
|
|
15
|
+
);
|
|
16
|
+
return val ? parseInt(val) : undefined;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
return themeRoot ? new Proxy(getComputedStyle(themeRoot), handler) : defaultBreakpoints ?? {};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const byDescendingStopSize = ([, s1]: [string, number], [, s2]: [string, number]) => s2 - s1;
|
|
24
|
+
|
|
25
|
+
// These are assumed to be min-width (aka mobile-first) stops, we could take a
|
|
26
|
+
// paramneter to support max-width as well ?
|
|
27
|
+
// return [stopName, minWidth, maxWidth]
|
|
28
|
+
export const breakpointRamp = (breakpoints: BreakPointsProp): BreakPointRamp[] =>
|
|
29
|
+
Object.entries(breakpoints)
|
|
30
|
+
.sort(byDescendingStopSize)
|
|
31
|
+
.map(([name, value], i, all) => [name, value, i < all.length - 1 ? all[i + 1][1] : 9999]);
|
|
32
|
+
|
|
33
|
+
let documentBreakpoints: BreakPointRamp[] | null = null;
|
|
34
|
+
|
|
35
|
+
const loadBreakpoints = (themeName = 'uitk') => {
|
|
36
|
+
// TODO would be nice to read these breakpoint labels from a css variable to
|
|
37
|
+
// avoid hard-coding them here ?
|
|
38
|
+
const { xs, sm, md, lg, xl } = breakpointReader(themeName) as BreakPointsProp;
|
|
39
|
+
return breakpointRamp({ xs, sm, md, lg, xl });
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
//TODO support multiple themes loaded
|
|
43
|
+
export const getBreakPoints = (themeName?: string) => {
|
|
44
|
+
if (documentBreakpoints === null) {
|
|
45
|
+
documentBreakpoints = loadBreakpoints(themeName);
|
|
46
|
+
}
|
|
47
|
+
return documentBreakpoints;
|
|
48
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const LEFT_RIGHT = ['left', 'right'];
|
|
2
|
+
const TOP_BOTTOM = ['top', 'bottom'];
|
|
3
|
+
|
|
4
|
+
export function measureMinimumNodeSize(node: HTMLElement, dimension: 'width' | 'height' = 'width') {
|
|
5
|
+
const { [dimension]: size } = node.getBoundingClientRect();
|
|
6
|
+
const { padRight = false, padLeft = false } = node.dataset;
|
|
7
|
+
const style = getComputedStyle(node);
|
|
8
|
+
const [start, end] = dimension === 'width' ? LEFT_RIGHT : TOP_BOTTOM;
|
|
9
|
+
const marginStart = padLeft ? 0 : parseInt(style.getPropertyValue(`margin-${start}`), 10);
|
|
10
|
+
const marginEnd = padRight ? 0 : parseInt(style.getPropertyValue(`margin-${end}`), 10);
|
|
11
|
+
|
|
12
|
+
let minWidth = size;
|
|
13
|
+
const flexShrink = parseInt(style.getPropertyValue('flex-shrink'), 10);
|
|
14
|
+
if (flexShrink > 0) {
|
|
15
|
+
const flexBasis = parseInt(style.getPropertyValue('flex-basis'), 10);
|
|
16
|
+
// TODO what about percentage values ?
|
|
17
|
+
if (!isNaN(flexBasis)) {
|
|
18
|
+
minWidth = flexBasis;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return marginStart + minWidth + marginEnd;
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export const getOverflowedItems = (containerRef, height = 64) => {
|
|
2
|
+
const elements = Array.from(containerRef.current.childNodes);
|
|
3
|
+
const firstOverflowIdx = findFirstOverflow(elements, height);
|
|
4
|
+
return [elements.slice(0, firstOverflowIdx), elements.slice(firstOverflowIdx)];
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export const findFirstOverflow = (elements, height) => {
|
|
8
|
+
for (let i = 0; i < elements.length; i++) {
|
|
9
|
+
if (elements[i].offsetTop >= height) {
|
|
10
|
+
return i;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return -1;
|
|
14
|
+
};
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { RefObject, useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { useResizeObserver } from './useResizeObserver';
|
|
3
|
+
import {
|
|
4
|
+
BreakPointRamp,
|
|
5
|
+
breakpointRamp,
|
|
6
|
+
getBreakPoints as getDocumentBreakpoints
|
|
7
|
+
} from './breakpoints';
|
|
8
|
+
import { BreakPoint, BreakPointsProp } from '../flexbox/flexboxTypes';
|
|
9
|
+
import { ExecFileOptionsWithStringEncoding } from 'child_process';
|
|
10
|
+
|
|
11
|
+
const EMPTY_ARRAY: BreakPoint[] = [];
|
|
12
|
+
|
|
13
|
+
export interface BreakpointsHookProps {
|
|
14
|
+
breakPoints?: BreakPointsProp;
|
|
15
|
+
smallerThan?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// TODO how do we cater for smallerThan/greaterThan breakpoints
|
|
19
|
+
export const useBreakpoints = (
|
|
20
|
+
{ breakPoints: breakPointsProp, smallerThan }: BreakpointsHookProps,
|
|
21
|
+
ref: RefObject<any>
|
|
22
|
+
) => {
|
|
23
|
+
const [breakpointMatch, setBreakpointmatch] = useState(smallerThan ? false : 'lg');
|
|
24
|
+
const bodyRef = useRef(document.body);
|
|
25
|
+
const breakPointsRef = useRef(
|
|
26
|
+
breakPointsProp ? breakpointRamp(breakPointsProp) : getDocumentBreakpoints()
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
// TODO how do we identify the default
|
|
30
|
+
const sizeRef = useRef('lg');
|
|
31
|
+
|
|
32
|
+
const stopFromMinWidth = useCallback(
|
|
33
|
+
(w) => {
|
|
34
|
+
if (breakPointsRef.current) {
|
|
35
|
+
for (let [name, size] of breakPointsRef.current) {
|
|
36
|
+
if (w >= size) {
|
|
37
|
+
return name;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
[breakPointsRef]
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const matchSizeAgainstBreakpoints = useCallback(
|
|
46
|
+
(width) => {
|
|
47
|
+
if (smallerThan) {
|
|
48
|
+
const breakPointRamp = breakPointsRef.current.find(
|
|
49
|
+
([name]: BreakPointRamp) => name === smallerThan
|
|
50
|
+
);
|
|
51
|
+
if (breakPointRamp) {
|
|
52
|
+
const [, , maxValue] = breakPointRamp;
|
|
53
|
+
return width < maxValue;
|
|
54
|
+
}
|
|
55
|
+
} else {
|
|
56
|
+
return stopFromMinWidth(width);
|
|
57
|
+
}
|
|
58
|
+
// is this right ?
|
|
59
|
+
return width;
|
|
60
|
+
},
|
|
61
|
+
[smallerThan, stopFromMinWidth]
|
|
62
|
+
);
|
|
63
|
+
|
|
64
|
+
// TODO need to make the dimension a config
|
|
65
|
+
useResizeObserver(
|
|
66
|
+
ref || bodyRef,
|
|
67
|
+
breakPointsRef.current ? ['width'] : EMPTY_ARRAY,
|
|
68
|
+
({ width: measuredWidth }: { width: number }) => {
|
|
69
|
+
const result = matchSizeAgainstBreakpoints(measuredWidth);
|
|
70
|
+
if (result !== sizeRef.current) {
|
|
71
|
+
sizeRef.current = result;
|
|
72
|
+
setBreakpointmatch(result);
|
|
73
|
+
}
|
|
74
|
+
},
|
|
75
|
+
true
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
const target = ref || bodyRef;
|
|
80
|
+
if (target.current) {
|
|
81
|
+
const prevSize = sizeRef.current;
|
|
82
|
+
if (breakPointsRef.current) {
|
|
83
|
+
// We're measuring here when the resizeObserver has also measured
|
|
84
|
+
// There isn't a convenient way to get the Resizeobserver to
|
|
85
|
+
// notify initial size - that's not really its job, unless we
|
|
86
|
+
// set a flag ?
|
|
87
|
+
const { clientWidth } = target.current;
|
|
88
|
+
const result = matchSizeAgainstBreakpoints(clientWidth);
|
|
89
|
+
sizeRef.current = result;
|
|
90
|
+
// If initial size of ref does not match the default, notify client after render
|
|
91
|
+
if (result !== prevSize) {
|
|
92
|
+
setBreakpointmatch(result);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}, [setBreakpointmatch, matchSizeAgainstBreakpoints, ref]);
|
|
97
|
+
|
|
98
|
+
// No, just ass the class directly to the ref, no need to render
|
|
99
|
+
return breakpointMatch;
|
|
100
|
+
};
|