@vuu-ui/vuu-layout 0.5.10 → 0.5.11

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/LICENSE +201 -0
  2. package/cjs/index.js +20 -0
  3. package/cjs/index.js.map +7 -0
  4. package/esm/index.js +20 -0
  5. package/esm/index.js.map +7 -0
  6. package/index.css +2 -0
  7. package/index.css.map +7 -0
  8. package/package.json +13 -10
  9. package/src/Component.css +0 -0
  10. package/src/Component.tsx +0 -20
  11. package/src/DraggableLayout.css +0 -18
  12. package/src/DraggableLayout.tsx +0 -26
  13. package/src/__tests__/flexbox-utils.spec.js +0 -90
  14. package/src/chest-of-drawers/Chest.css +0 -36
  15. package/src/chest-of-drawers/Chest.tsx +0 -42
  16. package/src/chest-of-drawers/Drawer.css +0 -159
  17. package/src/chest-of-drawers/Drawer.tsx +0 -118
  18. package/src/chest-of-drawers/index.ts +0 -2
  19. package/src/common-types.ts +0 -9
  20. package/src/debug.ts +0 -16
  21. package/src/drag-drop/BoxModel.ts +0 -551
  22. package/src/drag-drop/DragState.ts +0 -219
  23. package/src/drag-drop/Draggable.ts +0 -282
  24. package/src/drag-drop/DropMenu.css +0 -71
  25. package/src/drag-drop/DropMenu.tsx +0 -61
  26. package/src/drag-drop/DropTarget.ts +0 -393
  27. package/src/drag-drop/DropTargetRenderer.css +0 -40
  28. package/src/drag-drop/DropTargetRenderer.tsx +0 -277
  29. package/src/drag-drop/dragDropTypes.ts +0 -47
  30. package/src/drag-drop/index.ts +0 -5
  31. package/src/editable-label/EditableLabel.css +0 -28
  32. package/src/editable-label/EditableLabel.tsx +0 -99
  33. package/src/editable-label/index.ts +0 -1
  34. package/src/flexbox/Flexbox.css +0 -45
  35. package/src/flexbox/Flexbox.tsx +0 -70
  36. package/src/flexbox/FlexboxLayout.tsx +0 -28
  37. package/src/flexbox/FluidGrid.css +0 -134
  38. package/src/flexbox/FluidGrid.tsx +0 -82
  39. package/src/flexbox/FluidGridLayout.tsx +0 -9
  40. package/src/flexbox/Splitter.css +0 -140
  41. package/src/flexbox/Splitter.tsx +0 -127
  42. package/src/flexbox/flexbox-utils.ts +0 -128
  43. package/src/flexbox/flexboxTypes.ts +0 -68
  44. package/src/flexbox/index.ts +0 -5
  45. package/src/flexbox/useResponsiveSizing.ts +0 -82
  46. package/src/flexbox/useSplitterResizing.ts +0 -270
  47. package/src/index.ts +0 -19
  48. package/src/layout-action.ts +0 -21
  49. package/src/layout-header/ActionButton.tsx +0 -23
  50. package/src/layout-header/Header.css +0 -8
  51. package/src/layout-header/Header.tsx +0 -216
  52. package/src/layout-header/index.ts +0 -1
  53. package/src/layout-provider/LayoutProvider.tsx +0 -161
  54. package/src/layout-provider/LayoutProviderContext.ts +0 -17
  55. package/src/layout-provider/index.ts +0 -3
  56. package/src/layout-provider/useLayoutDragDrop.ts +0 -210
  57. package/src/layout-reducer/flexUtils.ts +0 -276
  58. package/src/layout-reducer/index.ts +0 -5
  59. package/src/layout-reducer/insert-layout-element.ts +0 -365
  60. package/src/layout-reducer/layout-reducer.ts +0 -237
  61. package/src/layout-reducer/layoutTypes.ts +0 -159
  62. package/src/layout-reducer/layoutUtils.ts +0 -288
  63. package/src/layout-reducer/remove-layout-element.ts +0 -226
  64. package/src/layout-reducer/replace-layout-element.ts +0 -113
  65. package/src/layout-reducer/resize-flex-children.ts +0 -55
  66. package/src/layout-reducer/wrap-layout-element.ts +0 -307
  67. package/src/layout-view/View.css +0 -61
  68. package/src/layout-view/View.tsx +0 -143
  69. package/src/layout-view/ViewContext.ts +0 -30
  70. package/src/layout-view/index.ts +0 -5
  71. package/src/layout-view/useView.tsx +0 -104
  72. package/src/layout-view/useViewActionDispatcher.ts +0 -123
  73. package/src/layout-view/useViewResize.ts +0 -53
  74. package/src/layout-view/viewTypes.ts +0 -35
  75. package/src/palette/Palette.css +0 -33
  76. package/src/palette/Palette.tsx +0 -140
  77. package/src/palette/PaletteSalt.css +0 -9
  78. package/src/palette/PaletteSalt.tsx +0 -79
  79. package/src/palette/index.ts +0 -3
  80. package/src/placeholder/Placeholder.css +0 -10
  81. package/src/placeholder/Placeholder.tsx +0 -38
  82. package/src/placeholder/index.ts +0 -1
  83. package/src/registry/ComponentRegistry.ts +0 -44
  84. package/src/registry/index.ts +0 -1
  85. package/src/responsive/breakpoints.ts +0 -62
  86. package/src/responsive/index.ts +0 -3
  87. package/src/responsive/measureMinimumNodeSize.ts +0 -23
  88. package/src/responsive/overflowUtils.js +0 -14
  89. package/src/responsive/use-breakpoints.ts +0 -101
  90. package/src/responsive/useResizeObserver.ts +0 -154
  91. package/src/responsive/utils.ts +0 -37
  92. package/src/stack/Stack.css +0 -39
  93. package/src/stack/Stack.tsx +0 -173
  94. package/src/stack/StackLayout.tsx +0 -119
  95. package/src/stack/index.ts +0 -4
  96. package/src/stack/stackTypes.ts +0 -22
  97. package/src/tabs/TabPanel.css +0 -12
  98. package/src/tabs/TabPanel.tsx +0 -17
  99. package/src/tabs/index.ts +0 -1
  100. package/src/tools/config-wrapper/ConfigWrapper.tsx +0 -55
  101. package/src/tools/config-wrapper/index.ts +0 -1
  102. package/src/tools/devtools-box/layout-configurator.css +0 -112
  103. package/src/tools/devtools-box/layout-configurator.jsx +0 -369
  104. package/src/tools/devtools-tree/layout-tree-viewer.css +0 -15
  105. package/src/tools/devtools-tree/layout-tree-viewer.jsx +0 -36
  106. package/src/tools/index.ts +0 -4
  107. package/src/use-persistent-state.ts +0 -112
  108. package/src/utils/index.ts +0 -5
  109. package/src/utils/pathUtils.ts +0 -283
  110. package/src/utils/propUtils.ts +0 -26
  111. package/src/utils/refUtils.ts +0 -16
  112. package/src/utils/styleUtils.ts +0 -13
  113. package/src/utils/typeOf.ts +0 -25
  114. package/tsconfig-emit-types.json +0 -11
@@ -1,127 +0,0 @@
1
- import cx from 'classnames';
2
- import React, { HTMLAttributes, KeyboardEvent, useCallback, useRef, useState } from 'react';
3
-
4
- import './Splitter.css';
5
-
6
- export type SplitterDragStartHandler = (index: number) => void;
7
- export type SplitterDragHandler = (index: number, distance: number) => void;
8
- export type SplitterDragEndHandler = () => void;
9
-
10
- export interface SplitterProps
11
- extends Omit<HTMLAttributes<HTMLDivElement>, 'onDrag' | 'onDragStart'> {
12
- column: boolean;
13
- index: number;
14
- onDragStart: SplitterDragStartHandler;
15
- onDrag: SplitterDragHandler;
16
- onDragEnd: SplitterDragEndHandler;
17
- }
18
-
19
- export const Splitter = React.memo(function Splitter({
20
- column,
21
- index,
22
- onDrag,
23
- onDragEnd,
24
- onDragStart,
25
- style
26
- }: SplitterProps) {
27
- const ignoreClick = useRef<boolean>();
28
- const rootRef = useRef<HTMLDivElement>(null);
29
- const lastPos = useRef<number>(0);
30
-
31
- const [active, setActive] = useState(false);
32
-
33
- const handleKeyDownDrag = useCallback(
34
- ({ key, shiftKey }) => {
35
- const distance = shiftKey ? 10 : 1;
36
- if (column && key === 'ArrowDown') {
37
- onDrag(index, distance);
38
- } else if (column && key === 'ArrowUp') {
39
- onDrag(index, -distance);
40
- } else if (!column && key === 'ArrowLeft') {
41
- onDrag(index, -distance);
42
- } else if (!column && key === 'ArrowRight') {
43
- onDrag(index, distance);
44
- }
45
- },
46
- [column, index, onDrag]
47
- );
48
-
49
- const handleKeyDownInitDrag = useCallback(
50
- (evt) => {
51
- const { key } = evt;
52
- const horizontalMove = key === 'ArrowLeft' || key === 'ArrowRIght';
53
- const verticalMove = key === 'ArrowUp' || key === 'ArrowDown';
54
- if ((column && verticalMove) || (!column && horizontalMove)) {
55
- onDragStart(index);
56
- handleKeyDownDrag(evt);
57
- keyDownHandlerRef.current = handleKeyDownDrag;
58
- }
59
- },
60
- [column, handleKeyDownDrag, index, onDragStart]
61
- );
62
-
63
- const keyDownHandlerRef = useRef(handleKeyDownInitDrag);
64
- const handleKeyDown = (evt: KeyboardEvent) => keyDownHandlerRef.current(evt);
65
-
66
- const handleMouseMove = useCallback(
67
- (e) => {
68
- ignoreClick.current = true;
69
- const pos = e[column ? 'clientY' : 'clientX'];
70
- const diff = pos - lastPos.current;
71
- if (pos && pos !== lastPos.current) {
72
- onDrag(index, diff);
73
- }
74
- lastPos.current = pos;
75
- },
76
- [column, index, onDrag]
77
- );
78
-
79
- const handleMouseUp = useCallback(() => {
80
- window.removeEventListener('mousemove', handleMouseMove, false);
81
- window.removeEventListener('mouseup', handleMouseUp, false);
82
- onDragEnd();
83
- setActive(false);
84
- rootRef.current?.focus();
85
- }, [handleMouseMove, onDragEnd, setActive]);
86
-
87
- const handleMouseDown = useCallback(
88
- (e) => {
89
- lastPos.current = column ? e.clientY : e.clientX;
90
- onDragStart(index);
91
- window.addEventListener('mousemove', handleMouseMove, false);
92
- window.addEventListener('mouseup', handleMouseUp, false);
93
- e.preventDefault();
94
- setActive(true);
95
- },
96
- [column, handleMouseMove, handleMouseUp, index, onDragStart, setActive]
97
- );
98
-
99
- const handleClick = () => {
100
- if (ignoreClick.current) {
101
- ignoreClick.current = false;
102
- } else {
103
- rootRef.current?.focus();
104
- }
105
- };
106
-
107
- const handleBlur = () => {
108
- keyDownHandlerRef.current = handleKeyDownInitDrag;
109
- };
110
-
111
- const className = cx('Splitter', 'focusable', { active, column });
112
- return (
113
- <div
114
- className={className}
115
- data-splitter
116
- ref={rootRef}
117
- role="separator"
118
- style={style}
119
- onBlur={handleBlur}
120
- onClick={handleClick}
121
- onKeyDown={handleKeyDown}
122
- onMouseDown={handleMouseDown}
123
- tabIndex={0}>
124
- <div className="grab-zone" />
125
- </div>
126
- );
127
- });
@@ -1,128 +0,0 @@
1
- import { ReactElement } from 'react';
2
- import { getIntrinsicSize, hasUnboundedFlexStyle } from '../layout-reducer/flexUtils';
3
- import { getProp } from '../utils';
4
- import type { BreakPoint, ContentMeta } from './flexboxTypes';
5
-
6
- const NO_INTRINSIC_SIZE: {
7
- height?: number;
8
- width?: number;
9
- } = {};
10
-
11
- export const SPLITTER = 1;
12
- export const PLACEHOLDER = 2;
13
-
14
- const isIntrinsicallySized = (item: ContentMeta) => typeof item.intrinsicSize === 'number';
15
-
16
- const getBreakPointValues = (breakPoints: BreakPoint[], component: ReactElement) => {
17
- const values: { [key: string]: number | undefined } = {};
18
- breakPoints.forEach((breakPoint) => {
19
- values[breakPoint] = getProp(component, breakPoint);
20
- });
21
- return values;
22
- };
23
-
24
- export const gatherChildMeta = (
25
- children: ReactElement[],
26
- dimension: 'width' | 'height',
27
- breakPoints?: BreakPoint[]
28
- ) => {
29
- return children.map((child, index) => {
30
- const resizeable = getProp(child, 'resizeable');
31
- const { [dimension]: intrinsicSize } = getIntrinsicSize(child) ?? NO_INTRINSIC_SIZE;
32
- const flexOpen = hasUnboundedFlexStyle(child);
33
- if (breakPoints) {
34
- return {
35
- index,
36
- flexOpen,
37
- intrinsicSize,
38
- resizeable,
39
- ...getBreakPointValues(breakPoints, child)
40
- };
41
- } else {
42
- return { index, flexOpen, intrinsicSize, resizeable };
43
- }
44
- });
45
- };
46
-
47
- // Splitters are inserted AFTER the associated index, so
48
- // never a splitter in last position.
49
- // Placeholder goes before (first) OR after(last) index
50
- export const findSplitterAndPlaceholderPositions = (childMeta: ContentMeta[]) => {
51
- const count = childMeta.length;
52
- const allIntrinsic = childMeta.every(isIntrinsicallySized);
53
- const splitterPositions = Array(count).fill(0);
54
- if (allIntrinsic) {
55
- splitterPositions[0] = PLACEHOLDER;
56
- splitterPositions[count - 1] = PLACEHOLDER;
57
- }
58
- if (count < 2) {
59
- return splitterPositions;
60
- } else {
61
- // 1) From the left, check each item.
62
- // Once we hit a resizable item, set this index and all subsequent indices,
63
- // except for last, to SPLITTER
64
- for (let i = 0, resizeablesLeft = 0; i < count - 1; i++) {
65
- if (childMeta[i].resizeable && !resizeablesLeft) {
66
- resizeablesLeft = SPLITTER;
67
- }
68
- splitterPositions[i] += resizeablesLeft;
69
- }
70
- // 2) Now check from the right. Undo splitter insertion until we reach a point
71
- // where there is a resizeable to our right.
72
- for (let i = count - 1; i > 0; i--) {
73
- if (splitterPositions[i] & SPLITTER) {
74
- splitterPositions[i] -= SPLITTER;
75
- }
76
- if (childMeta[i].resizeable) {
77
- break;
78
- }
79
- }
80
- return splitterPositions;
81
- }
82
- };
83
-
84
- export const identifyResizeParties = (contentMeta: ContentMeta[], idx: number) => {
85
- const idx1 = getLeadingResizeablePos(contentMeta, idx);
86
- const idx2 = getTrailingResizeablePos(contentMeta, idx);
87
- const participants = idx1 !== -1 && idx2 !== -1 ? [idx1, idx2] : undefined;
88
- const bystanders = identifyResizeBystanders(contentMeta, participants);
89
- return [participants, bystanders];
90
- };
91
-
92
- function identifyResizeBystanders(contentMeta: ContentMeta[], participants?: number[]) {
93
- if (participants) {
94
- const bystanders = [];
95
- for (let i = 0; i < contentMeta.length; i++) {
96
- if (contentMeta[i].flexOpen && !participants.includes(i)) {
97
- bystanders.push(i);
98
- }
99
- }
100
- return bystanders;
101
- }
102
- }
103
-
104
- function getLeadingResizeablePos(contentMeta: ContentMeta[], idx: number) {
105
- let pos = idx,
106
- resizeable = false;
107
- while (pos >= 1 && !resizeable) {
108
- pos = pos - 1;
109
- resizeable = isResizeable(contentMeta, pos);
110
- }
111
- return pos;
112
- }
113
-
114
- function getTrailingResizeablePos(contentMeta: ContentMeta[], idx: number) {
115
- let pos = idx,
116
- resizeable = false;
117
- const count = contentMeta.length;
118
- while (pos < count && !resizeable) {
119
- pos = pos + 1;
120
- resizeable = isResizeable(contentMeta, pos);
121
- }
122
- return pos === count ? -1 : pos;
123
- }
124
-
125
- function isResizeable(contentMeta: ContentMeta[], idx: number): boolean {
126
- const { placeholder, splitter, resizeable, intrinsicSize } = contentMeta[idx];
127
- return Boolean(!splitter && !intrinsicSize && (placeholder || resizeable));
128
- }
@@ -1,68 +0,0 @@
1
- import {
2
- CSSProperties,
3
- HTMLAttributes,
4
- MutableRefObject,
5
- ReactElement,
6
- ReactNode,
7
- } from "react";
8
- import { SplitterProps } from "./Splitter";
9
-
10
- export interface LayoutContainerProps {
11
- resizeable?: boolean;
12
- }
13
-
14
- export interface FlexboxProps
15
- extends LayoutContainerProps,
16
- HTMLAttributes<HTMLDivElement> {
17
- breakPoints?: BreakPointsProp;
18
- children: ReactElement[];
19
- cols?: number;
20
- column?: true;
21
- fullPage?: number;
22
- flexFill?: boolean;
23
- gap?: number;
24
- onSplitterMoved?: (content: ContentMeta[]) => void;
25
- row?: true;
26
- spacing?: number;
27
- splitterSize?: number;
28
- }
29
-
30
- export interface FlexboxLayoutProps extends FlexboxProps {
31
- path: string;
32
- }
33
-
34
- export interface SplitterHookProps {
35
- children: ReactNode;
36
- onSplitterMoved?: (content: ContentMeta[]) => void;
37
- style?: CSSProperties;
38
- }
39
-
40
- export interface SplitterHookResult {
41
- content: ReactElement[];
42
- rootRef: MutableRefObject<HTMLDivElement | null>;
43
- }
44
-
45
- export type SplitterFactory = (index: number) => ReactElement<SplitterProps>;
46
-
47
- export type ContentMeta = {
48
- currentSize?: number;
49
- flexOpen?: boolean;
50
- flexBasis?: number;
51
- intrinsicSize?: number;
52
- minSize?: number;
53
- placeholder?: boolean;
54
- resizeable?: boolean;
55
- shim?: boolean;
56
- splitter?: boolean;
57
- };
58
-
59
- export type FlexSize = {
60
- size: number;
61
- minSize: number;
62
- };
63
-
64
- export type BreakPoint = "xs" | "sm" | "md" | "lg" | "xl";
65
- export type BreakPoints = BreakPoint[];
66
- export type BreakPointsProp = {
67
- [keys in BreakPoint]?: number;
68
- };
@@ -1,5 +0,0 @@
1
- export { default as Flexbox } from './Flexbox';
2
- export * from './FlexboxLayout';
3
- export * from './FluidGrid';
4
- export * from './FluidGridLayout';
5
-
@@ -1,82 +0,0 @@
1
- import { getUniqueId } from "@vuu-ui/vuu-utils";
2
- import {
3
- cloneElement,
4
- CSSProperties,
5
- isValidElement,
6
- ReactElement,
7
- useCallback,
8
- useMemo,
9
- useRef,
10
- } from "react";
11
- import { gatherChildMeta } from "./flexbox-utils";
12
- import { BreakPoint } from "./flexboxTypes";
13
-
14
- const breakPoints: BreakPoint[] = ["xs", "sm", "md", "lg", "xl"];
15
-
16
- const DEFAULT_COLS = 12;
17
-
18
- export const useResponsiveSizing = ({
19
- children: childrenProp,
20
- cols: colsProp,
21
- style,
22
- }: {
23
- children: ReactElement[];
24
- cols?: number;
25
- style?: CSSProperties;
26
- }) => {
27
- const rootRef = useRef(null);
28
- const metaRef = useRef(null);
29
- const contentRef = useRef<ReactElement[]>();
30
- const cols = colsProp ?? DEFAULT_COLS;
31
-
32
- const isColumn = style?.flexDirection === "column";
33
- const dimension = isColumn ? "height" : "width";
34
-
35
- const children = useMemo(
36
- () =>
37
- Array.isArray(childrenProp)
38
- ? childrenProp
39
- : isValidElement(childrenProp)
40
- ? [childrenProp]
41
- : [],
42
- [childrenProp]
43
- );
44
-
45
- const buildContent = useCallback(
46
- (children, dimension): [ReactElement[], any] => {
47
- const childMeta = gatherChildMeta(children, dimension, breakPoints);
48
- const content = [];
49
- const meta = [];
50
- for (let i = 0; i < children.length; i++) {
51
- const child = children[i];
52
- const {
53
- style: { flex, ...rest },
54
- } = child.props;
55
- content.push(
56
- cloneElement(child, {
57
- key: getUniqueId(),
58
- style: {
59
- ...rest,
60
- "--parent-col-count": cols,
61
- },
62
- })
63
- );
64
- meta.push(childMeta[i]);
65
- }
66
- return [content, meta];
67
- },
68
- [cols]
69
- );
70
-
71
- useMemo(() => {
72
- const [content, meta] = buildContent(children, dimension);
73
- metaRef.current = meta;
74
- contentRef.current = content;
75
- }, [buildContent, children, dimension]);
76
-
77
- return {
78
- cols,
79
- content: contentRef.current,
80
- rootRef,
81
- };
82
- };
@@ -1,270 +0,0 @@
1
- import { getUniqueId } from "@vuu-ui/vuu-utils";
2
- import React, {
3
- ReactElement,
4
- useCallback,
5
- useMemo,
6
- useRef,
7
- useState,
8
- } from "react";
9
- import { Placeholder } from "../placeholder";
10
- import { Splitter } from "./Splitter";
11
-
12
- import {
13
- findSplitterAndPlaceholderPositions,
14
- gatherChildMeta,
15
- identifyResizeParties,
16
- PLACEHOLDER,
17
- SPLITTER,
18
- } from "./flexbox-utils";
19
- import {
20
- ContentMeta,
21
- FlexSize,
22
- SplitterFactory,
23
- SplitterHookProps,
24
- SplitterHookResult,
25
- } from "./flexboxTypes";
26
-
27
- const originalContentOnly = (meta: ContentMeta) =>
28
- !meta.splitter && !meta.placeholder;
29
-
30
- export const useSplitterResizing = ({
31
- children: childrenProp,
32
- onSplitterMoved,
33
- style,
34
- }: SplitterHookProps): SplitterHookResult => {
35
- const rootRef = useRef<HTMLDivElement>(null);
36
- const metaRef = useRef<ContentMeta[]>();
37
- const contentRef = useRef<ReactElement[]>();
38
- const assignedKeys = useRef([]);
39
- const [, forceUpdate] = useState({});
40
-
41
- const setContent = (content: ReactElement[]) => {
42
- contentRef.current = content;
43
- forceUpdate({});
44
- };
45
-
46
- const isColumn = style?.flexDirection === "column";
47
- const dimension = isColumn ? "height" : "width";
48
- const children = useMemo(
49
- () =>
50
- Array.isArray(childrenProp)
51
- ? childrenProp
52
- : React.isValidElement(childrenProp)
53
- ? [childrenProp]
54
- : [],
55
- [childrenProp]
56
- );
57
-
58
- const handleDragStart = useCallback(
59
- (index) => {
60
- const { current: contentMeta } = metaRef;
61
- if (contentMeta) {
62
- const [participants, bystanders] = identifyResizeParties(
63
- contentMeta,
64
- index
65
- );
66
- if (participants) {
67
- participants.forEach((index) => {
68
- const el = rootRef.current?.childNodes[index] as HTMLElement;
69
- if (el) {
70
- const { size, minSize } = measureElement(el, dimension);
71
- contentMeta[index].currentSize = size;
72
- contentMeta[index].minSize = minSize;
73
- }
74
- });
75
- if (bystanders) {
76
- bystanders.forEach((index) => {
77
- const el = rootRef.current?.childNodes[index] as HTMLElement;
78
- if (el) {
79
- const { [dimension]: size } = el.getBoundingClientRect();
80
- contentMeta[index].flexBasis = size;
81
- }
82
- });
83
- }
84
- }
85
- }
86
- },
87
- [dimension]
88
- );
89
-
90
- const handleDrag = useCallback(
91
- (idx, distance) => {
92
- if (contentRef.current && metaRef.current) {
93
- setContent(
94
- resizeContent(
95
- contentRef.current,
96
- metaRef.current,
97
- distance,
98
- dimension
99
- )
100
- );
101
- }
102
- },
103
- [dimension]
104
- );
105
-
106
- const handleDragEnd = useCallback(() => {
107
- const contentMeta = metaRef.current;
108
- if (contentMeta) {
109
- onSplitterMoved?.(contentMeta.filter(originalContentOnly));
110
- }
111
- contentMeta?.forEach((meta) => {
112
- meta.currentSize = undefined;
113
- meta.flexBasis = undefined;
114
- meta.flexOpen = false;
115
- });
116
- }, [onSplitterMoved]);
117
-
118
- const createSplitter: SplitterFactory = useCallback(
119
- (i) => {
120
- return React.createElement(Splitter, {
121
- column: isColumn,
122
- index: i,
123
- key: `splitter-${i}`,
124
- onDrag: handleDrag,
125
- onDragEnd: handleDragEnd,
126
- onDragStart: handleDragStart,
127
- });
128
- },
129
- [handleDrag, handleDragEnd, handleDragStart, isColumn]
130
- );
131
-
132
- useMemo(() => {
133
- const [content, meta] = buildContent(
134
- children,
135
- dimension,
136
- createSplitter,
137
- assignedKeys.current
138
- );
139
- metaRef.current = meta;
140
- contentRef.current = content;
141
- }, [children, createSplitter, dimension]);
142
-
143
- return {
144
- content: contentRef.current || [],
145
- rootRef,
146
- };
147
- };
148
-
149
- function buildContent(
150
- children: ReactElement[],
151
- dimension: "width" | "height",
152
- createSplitter: SplitterFactory,
153
- keys: any[]
154
- ): [any[], ContentMeta[]] {
155
- const childMeta = gatherChildMeta(children, dimension);
156
- const splitterAndPlaceholderPositions =
157
- findSplitterAndPlaceholderPositions(childMeta);
158
- const content = [];
159
- const meta: ContentMeta[] = [];
160
- for (let i = 0; i < children.length; i++) {
161
- const child = children[i];
162
- if (i === 0 && splitterAndPlaceholderPositions[i] & PLACEHOLDER) {
163
- content.push(createPlaceholder(i));
164
- meta.push({ placeholder: true, shim: true });
165
- }
166
- if (child.key == null) {
167
- const key = keys[i] || (keys[i] = getUniqueId());
168
- content.push(React.cloneElement(child, { key }));
169
- } else {
170
- content.push(child);
171
- }
172
- meta.push(childMeta[i]);
173
-
174
- if (i > 0 && splitterAndPlaceholderPositions[i] & PLACEHOLDER) {
175
- content.push(createPlaceholder(i));
176
- meta.push({ placeholder: true });
177
- } else if (splitterAndPlaceholderPositions[i] & SPLITTER) {
178
- content.push(createSplitter(content.length));
179
- meta.push({ splitter: true });
180
- }
181
- }
182
- return [content, meta];
183
- }
184
-
185
- function resizeContent(
186
- content: ReactElement[],
187
- contentMeta: ContentMeta[],
188
- distance: number,
189
- dimension: "width" | "height"
190
- ) {
191
- const metaUpdated = updateMeta(contentMeta, distance);
192
- if (!metaUpdated) {
193
- return content;
194
- }
195
-
196
- return content.map((child, idx) => {
197
- const meta = contentMeta[idx];
198
- const { currentSize, flexOpen, flexBasis } = meta;
199
- const hasCurrentSize = currentSize !== undefined;
200
- if (hasCurrentSize || flexOpen) {
201
- const { flexBasis: actualFlexBasis } = child.props.style || {};
202
- const size = hasCurrentSize ? meta.currentSize : flexBasis;
203
- if (size !== actualFlexBasis) {
204
- return React.cloneElement(child, {
205
- style: {
206
- ...child.props.style,
207
- flexBasis: size,
208
- [dimension]: "auto",
209
- },
210
- });
211
- } else {
212
- return child;
213
- }
214
- } else {
215
- return child;
216
- }
217
- });
218
- }
219
-
220
- //TODO detect cursor move beyond drag limit and suspend further resize until cursoe re-engages with splitter
221
- function updateMeta(contentMeta: ContentMeta[], distance: number) {
222
- const resizeTargets: number[] = [];
223
-
224
- contentMeta.forEach((meta, idx) => {
225
- if (meta.currentSize !== undefined) {
226
- resizeTargets.push(idx);
227
- }
228
- });
229
-
230
- // we want the target being reduced first, this may limit the distance we can apply
231
- const target1 = distance < 0 ? resizeTargets[0] : resizeTargets[1];
232
-
233
- const { currentSize = 0, minSize = 0 } = contentMeta[target1];
234
- if (currentSize === minSize) {
235
- // size is already 0, we cannot go further
236
- return false;
237
- } else if (Math.abs(distance) > currentSize - minSize) {
238
- // reduce to 0
239
- const multiplier = distance < 0 ? -1 : 1;
240
- distance = Math.max(0, currentSize - minSize) * multiplier;
241
- }
242
-
243
- const leadingItem = contentMeta[resizeTargets[0]] as ContentMeta;
244
- const { currentSize: leadingSize = 0 } = leadingItem;
245
- leadingItem.currentSize = leadingSize + distance;
246
-
247
- const trailingItem = contentMeta[resizeTargets[1]] as ContentMeta;
248
- const { currentSize: trailingSize = 0 } = trailingItem;
249
- trailingItem.currentSize = trailingSize - distance;
250
-
251
- return true;
252
- }
253
-
254
- function createPlaceholder(index: number) {
255
- return React.createElement(Placeholder, {
256
- shim: index === 0,
257
- key: `placeholder-${index}`,
258
- } as any);
259
- }
260
-
261
- function measureElement(
262
- el: HTMLElement,
263
- dimension: "width" | "height"
264
- ): FlexSize {
265
- const { [dimension]: size } = el.getBoundingClientRect();
266
- const style = getComputedStyle(el);
267
- const minSizeVal = style.getPropertyValue(`min-${dimension}`);
268
- const minSize = minSizeVal.endsWith("px") ? parseInt(minSizeVal, 10) : 0;
269
- return { size, minSize };
270
- }
package/src/index.ts DELETED
@@ -1,19 +0,0 @@
1
- export * from "@vuu-ui/vuu-popups/src/dialog";
2
- export * from "./chest-of-drawers";
3
- export * from "./common-types";
4
- export { default as Component } from "./Component";
5
- export * from "./drag-drop";
6
- export * from "./DraggableLayout";
7
- export * from "./flexbox";
8
- export { Action } from "./layout-action";
9
- export * from "./layout-header";
10
- export * from "./layout-provider";
11
- export * from "./layout-view";
12
- export * from "./palette";
13
- export * from "./placeholder";
14
- export * from "./registry";
15
- export * from "./responsive";
16
- export * from "./stack";
17
- export * from "./tools";
18
- export * from "./use-persistent-state";
19
- export * from "./utils";