@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.
Files changed (117) hide show
  1. package/README.md +1 -0
  2. package/package.json +30 -0
  3. package/src/Component.css +2 -0
  4. package/src/Component.tsx +20 -0
  5. package/src/DraggableLayout.css +18 -0
  6. package/src/DraggableLayout.tsx +29 -0
  7. package/src/__tests__/flexbox-utils.spec.js +90 -0
  8. package/src/action-buttons/action-buttons.css +12 -0
  9. package/src/action-buttons/action-buttons.tsx +30 -0
  10. package/src/action-buttons/index.ts +1 -0
  11. package/src/chest-of-drawers/Chest.css +36 -0
  12. package/src/chest-of-drawers/Chest.tsx +42 -0
  13. package/src/chest-of-drawers/Drawer.css +153 -0
  14. package/src/chest-of-drawers/Drawer.tsx +118 -0
  15. package/src/chest-of-drawers/index.ts +2 -0
  16. package/src/common-types.ts +9 -0
  17. package/src/debug.ts +16 -0
  18. package/src/dialog/Dialog.css +16 -0
  19. package/src/dialog/Dialog.tsx +59 -0
  20. package/src/dialog/index.ts +1 -0
  21. package/src/drag-drop/BoxModel.ts +546 -0
  22. package/src/drag-drop/DragState.ts +222 -0
  23. package/src/drag-drop/Draggable.ts +282 -0
  24. package/src/drag-drop/DropMenu.css +70 -0
  25. package/src/drag-drop/DropMenu.tsx +68 -0
  26. package/src/drag-drop/DropTarget.ts +392 -0
  27. package/src/drag-drop/DropTargetRenderer.css +40 -0
  28. package/src/drag-drop/DropTargetRenderer.tsx +284 -0
  29. package/src/drag-drop/dragDropTypes.ts +49 -0
  30. package/src/drag-drop/index.ts +4 -0
  31. package/src/editable-label/EditableLabel.css +28 -0
  32. package/src/editable-label/EditableLabel.tsx +99 -0
  33. package/src/editable-label/index.ts +1 -0
  34. package/src/flexbox/Flexbox.css +45 -0
  35. package/src/flexbox/Flexbox.tsx +70 -0
  36. package/src/flexbox/FlexboxLayout.jsx +26 -0
  37. package/src/flexbox/FluidGrid.css +134 -0
  38. package/src/flexbox/FluidGrid.tsx +84 -0
  39. package/src/flexbox/FluidGridLayout.tsx +10 -0
  40. package/src/flexbox/Splitter.css +140 -0
  41. package/src/flexbox/Splitter.tsx +135 -0
  42. package/src/flexbox/flexbox-utils.ts +128 -0
  43. package/src/flexbox/flexboxTypes.ts +63 -0
  44. package/src/flexbox/index.ts +4 -0
  45. package/src/flexbox/useResponsiveSizing.ts +85 -0
  46. package/src/flexbox/useSplitterResizing.ts +272 -0
  47. package/src/index.ts +20 -0
  48. package/src/layout-action.ts +21 -0
  49. package/src/layout-header/ActionButton.tsx +23 -0
  50. package/src/layout-header/Header.css +8 -0
  51. package/src/layout-header/Header.tsx +222 -0
  52. package/src/layout-header/index.ts +1 -0
  53. package/src/layout-provider/LayoutProvider.tsx +160 -0
  54. package/src/layout-provider/LayoutProviderContext.ts +17 -0
  55. package/src/layout-provider/index.ts +2 -0
  56. package/src/layout-provider/useLayoutDragDrop.ts +241 -0
  57. package/src/layout-reducer/flexUtils.ts +281 -0
  58. package/src/layout-reducer/index.ts +4 -0
  59. package/src/layout-reducer/insert-layout-element.ts +365 -0
  60. package/src/layout-reducer/layout-reducer.ts +255 -0
  61. package/src/layout-reducer/layoutTypes.ts +151 -0
  62. package/src/layout-reducer/layoutUtils.ts +302 -0
  63. package/src/layout-reducer/remove-layout-element.ts +240 -0
  64. package/src/layout-reducer/replace-layout-element.ts +118 -0
  65. package/src/layout-reducer/resize-flex-children.ts +56 -0
  66. package/src/layout-reducer/wrap-layout-element.ts +317 -0
  67. package/src/layout-view/View.css +58 -0
  68. package/src/layout-view/View.tsx +149 -0
  69. package/src/layout-view/ViewContext.ts +31 -0
  70. package/src/layout-view/index.ts +4 -0
  71. package/src/layout-view/useView.tsx +104 -0
  72. package/src/layout-view/useViewActionDispatcher.ts +133 -0
  73. package/src/layout-view/useViewResize.ts +53 -0
  74. package/src/layout-view/viewTypes.ts +37 -0
  75. package/src/palette/Palette.css +37 -0
  76. package/src/palette/Palette.tsx +140 -0
  77. package/src/palette/PaletteUitk.css +9 -0
  78. package/src/palette/PaletteUitk.tsx +79 -0
  79. package/src/palette/index.ts +2 -0
  80. package/src/placeholder/Placeholder.css +10 -0
  81. package/src/placeholder/Placeholder.tsx +39 -0
  82. package/src/placeholder/index.ts +1 -0
  83. package/src/registry/ComponentRegistry.ts +35 -0
  84. package/src/registry/index.ts +1 -0
  85. package/src/responsive/OverflowMenu.css +31 -0
  86. package/src/responsive/OverflowMenu.jsx +56 -0
  87. package/src/responsive/breakpoints.ts +48 -0
  88. package/src/responsive/index.ts +4 -0
  89. package/src/responsive/measureMinimumNodeSize.ts +23 -0
  90. package/src/responsive/overflowUtils.js +14 -0
  91. package/src/responsive/use-breakpoints.ts +100 -0
  92. package/src/responsive/useOverflowObserver.ts +606 -0
  93. package/src/responsive/useResizeObserver.ts +154 -0
  94. package/src/responsive/utils.ts +37 -0
  95. package/src/stack/Stack.css +39 -0
  96. package/src/stack/Stack.tsx +160 -0
  97. package/src/stack/StackLayout.tsx +137 -0
  98. package/src/stack/index.ts +3 -0
  99. package/src/stack/stackTypes.ts +19 -0
  100. package/src/tabs/TabPanel.css +12 -0
  101. package/src/tabs/TabPanel.tsx +17 -0
  102. package/src/tabs/index.ts +1 -0
  103. package/src/tools/config-wrapper/ConfigWrapper.jsx +53 -0
  104. package/src/tools/config-wrapper/index.js +1 -0
  105. package/src/tools/devtools-box/layout-configurator.css +112 -0
  106. package/src/tools/devtools-box/layout-configurator.jsx +369 -0
  107. package/src/tools/devtools-tree/layout-tree-viewer.css +15 -0
  108. package/src/tools/devtools-tree/layout-tree-viewer.jsx +36 -0
  109. package/src/tools/index.js +3 -0
  110. package/src/use-persistent-state.ts +115 -0
  111. package/src/utils/componentFromLayout.tsx +30 -0
  112. package/src/utils/index.ts +6 -0
  113. package/src/utils/pathUtils.ts +294 -0
  114. package/src/utils/propUtils.ts +24 -0
  115. package/src/utils/refUtils.ts +16 -0
  116. package/src/utils/styleUtils.ts +14 -0
  117. 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,4 @@
1
+ export * from "./use-breakpoints";
2
+ export * from "./useOverflowObserver";
3
+ export * from "./useResizeObserver";
4
+ export * from "./utils";
@@ -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
+ };