@noya-app/noya-designsystem 0.1.63 → 0.1.64
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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +13 -0
- package/dist/index.css +1 -1
- package/dist/index.d.mts +169 -127
- package/dist/index.d.ts +169 -127
- package/dist/index.js +3131 -2642
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2941 -2459
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -22
- package/src/__tests__/validateDropIndicator.test.ts +26 -41
- package/src/__tests__/workspaceLayout.test.ts +281 -0
- package/src/components/ActionMenu.tsx +2 -0
- package/src/components/ActivityIndicator.tsx +5 -3
- package/src/components/AnimatePresence.tsx +6 -4
- package/src/components/Avatar.tsx +4 -2
- package/src/components/BaseToolbar.tsx +45 -34
- package/src/components/Breadcrumbs.tsx +2 -0
- package/src/components/Button.tsx +9 -3
- package/src/components/Chip.tsx +2 -0
- package/src/components/Collection.tsx +4 -1
- package/src/components/ColorSwatch.tsx +42 -22
- package/src/components/ColorSwatchControl.tsx +5 -3
- package/src/components/Combobox.tsx +2 -0
- package/src/components/CommandPalette.tsx +2 -0
- package/src/components/ContextMenu.tsx +3 -1
- package/src/components/Dialog.tsx +3 -1
- package/src/components/DimensionInput.tsx +2 -0
- package/src/components/Divider.tsx +10 -6
- package/src/components/DraggableMenuButton.tsx +2 -0
- package/src/components/Drawer.tsx +11 -3
- package/src/components/DropdownMenu.tsx +3 -1
- package/src/components/EditableText.tsx +2 -0
- package/src/components/FileUploadIndicator.tsx +108 -0
- package/src/components/FillPreviewBackground.tsx +2 -0
- package/src/components/FloatingWindow.tsx +2 -0
- package/src/components/GradientPicker.tsx +2 -0
- package/src/components/Grid.tsx +47 -38
- package/src/components/GridView.tsx +33 -11
- package/src/components/IconButton.tsx +2 -0
- package/src/components/Icons.tsx +1 -1
- package/src/components/InputField.tsx +2 -0
- package/src/components/Label.tsx +1 -1
- package/src/components/LabeledElementView.tsx +6 -2
- package/src/components/LabeledField.tsx +2 -0
- package/src/components/List.tsx +10 -2
- package/src/components/ListView.tsx +27 -14
- package/src/components/MediaThumbnail.tsx +31 -2
- package/src/components/Message.tsx +8 -9
- package/src/components/Popover.tsx +3 -1
- package/src/components/Progress.tsx +20 -7
- package/src/components/ScrollArea.tsx +3 -1
- package/src/components/SearchCompletionMenu.tsx +2 -0
- package/src/components/Section.tsx +2 -0
- package/src/components/SegmentedControl.tsx +42 -16
- package/src/components/SelectMenu.tsx +3 -1
- package/src/components/SelectionToolbar.tsx +3 -1
- package/src/components/Slider.tsx +3 -1
- package/src/components/Switch.tsx +3 -1
- package/src/components/Tabs.tsx +3 -1
- package/src/components/Text.tsx +6 -5
- package/src/components/TextArea.tsx +2 -0
- package/src/components/Toast.tsx +1 -1
- package/src/components/Toolbar.tsx +8 -2
- package/src/components/ToolbarDrawer.tsx +29 -0
- package/src/components/Tooltip.tsx +1 -1
- package/src/components/TreeView.tsx +2 -0
- package/src/components/UserPointer.tsx +2 -0
- package/src/components/ai-assistant/AIAssistantLayout.tsx +2 -0
- package/src/components/blocks/ImageBlockComponent.tsx +156 -0
- package/src/components/connected-users-menu/ConnectedUsersMenuLayout.tsx +2 -0
- package/src/components/file-explorer/FileExplorerLayout.tsx +2 -0
- package/src/components/internal/Checkmark.tsx +24 -0
- package/src/components/internal/Menu.tsx +2 -1
- package/src/components/internal/MenuViewport.tsx +4 -2
- package/src/components/internal/SelectItem.tsx +4 -23
- package/src/components/internal/TextInput.tsx +2 -0
- package/src/components/sorting/DragRegistration.tsx +8 -4
- package/src/components/sorting/SharedDragProvider.tsx +43 -18
- package/src/components/sorting/Sortable.tsx +19 -10
- package/src/components/sorting/createSharedDrag.tsx +7 -6
- package/src/components/sorting/sorting.ts +6 -9
- package/src/components/workspace/DrawerWorkspaceLayout.tsx +107 -26
- package/src/components/workspace/PanelWorkspaceLayout.tsx +98 -65
- package/src/components/workspace/VerticalTabMenu.tsx +36 -0
- package/src/components/workspace/WorkspaceLayout.tsx +46 -42
- package/src/components/workspace/constants.ts +4 -0
- package/src/components/workspace/panelStorage.ts +216 -0
- package/src/components/workspace/types.ts +11 -4
- package/src/contexts/DesignSystemConfiguration.tsx +12 -5
- package/src/contexts/DialogContext.tsx +2 -0
- package/src/contexts/FloatingWindowContext.tsx +2 -0
- package/src/contexts/GlobalInputBlurContext.tsx +2 -0
- package/src/contexts/ImageDataContext.tsx +2 -0
- package/src/contexts/LinkComponentContext.tsx +17 -0
- package/src/contexts/OpenPortalsContext.tsx +2 -0
- package/src/contexts/PortalScopeContext.tsx +2 -0
- package/src/hooks/mergeEventHandlers.ts +1 -1
- package/src/hooks/useHover.ts +30 -17
- package/src/hooks/useIndent.ts +2 -0
- package/src/hooks/useLabel.ts +2 -0
- package/src/hooks/useObjectURL.ts +5 -3
- package/src/hooks/usePlatform.ts +5 -3
- package/src/hooks/useTheme.ts +3 -1
- package/src/index.css +19 -0
- package/src/index.tsx +5 -2
- package/src/utils/classNames.ts +4 -3
- package/src/utils/combobox.ts +2 -0
- package/src/utils/formatByteSize.ts +8 -0
- package/src/utils/withSeparatorElements.ts +1 -1
- package/src/hooks/usePreservePanelSize.tsx +0 -183
- package/src/mediaQuery.ts +0 -13
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import {
|
|
2
4
|
Active,
|
|
3
5
|
closestCenter,
|
|
@@ -15,7 +17,7 @@ import {
|
|
|
15
17
|
} from "@dnd-kit/core";
|
|
16
18
|
import { Point, rectContainsPoint, unionRects } from "@noya-app/noya-geometry";
|
|
17
19
|
import { windowsOf } from "@noya-app/noya-utils";
|
|
18
|
-
import {
|
|
20
|
+
import { useIsomorphicLayoutEffect } from "@noya-app/react-utils";
|
|
19
21
|
import * as React from "react";
|
|
20
22
|
import { useMemo } from "react";
|
|
21
23
|
import { createPortal } from "react-dom";
|
|
@@ -30,6 +32,7 @@ import {
|
|
|
30
32
|
useDragRegistrationManager,
|
|
31
33
|
} from "./DragRegistration";
|
|
32
34
|
import {
|
|
35
|
+
AcceptsDrop,
|
|
33
36
|
DragItem,
|
|
34
37
|
DragState,
|
|
35
38
|
MoveDragItemHandler,
|
|
@@ -37,14 +40,16 @@ import {
|
|
|
37
40
|
RelativeDropPosition,
|
|
38
41
|
} from "./sorting";
|
|
39
42
|
|
|
40
|
-
type SharedDragProviderProps = {
|
|
43
|
+
export type SharedDragProviderProps = {
|
|
41
44
|
children: React.ReactNode;
|
|
45
|
+
acceptsDrop?: AcceptsDrop;
|
|
42
46
|
onMoveItem?: MoveDragItemHandler;
|
|
43
47
|
sharedDragProps?: SharedDragProps;
|
|
44
48
|
};
|
|
45
49
|
|
|
46
50
|
export function SharedDragProvider({
|
|
47
51
|
children,
|
|
52
|
+
acceptsDrop,
|
|
48
53
|
onMoveItem,
|
|
49
54
|
sharedDragProps = {
|
|
50
55
|
dragRegistrationContext: DragRegistrationContext,
|
|
@@ -66,6 +71,16 @@ export function SharedDragProvider({
|
|
|
66
71
|
indicator: null,
|
|
67
72
|
});
|
|
68
73
|
|
|
74
|
+
const stableOnMoveItem = React.useRef(onMoveItem);
|
|
75
|
+
useIsomorphicLayoutEffect(() => {
|
|
76
|
+
stableOnMoveItem.current = onMoveItem;
|
|
77
|
+
}, [onMoveItem]);
|
|
78
|
+
|
|
79
|
+
const stableAcceptsDrop = React.useRef(acceptsDrop);
|
|
80
|
+
useIsomorphicLayoutEffect(() => {
|
|
81
|
+
stableAcceptsDrop.current = acceptsDrop;
|
|
82
|
+
}, [acceptsDrop]);
|
|
83
|
+
|
|
69
84
|
// console.log("dragState", dragState.target);
|
|
70
85
|
|
|
71
86
|
const { registerList, unregisterList, registeredLists } =
|
|
@@ -117,6 +132,7 @@ export function SharedDragProvider({
|
|
|
117
132
|
active,
|
|
118
133
|
source: dragState.source,
|
|
119
134
|
registeredLists,
|
|
135
|
+
acceptsDrop: stableAcceptsDrop.current,
|
|
120
136
|
});
|
|
121
137
|
|
|
122
138
|
setDragState({
|
|
@@ -128,8 +144,6 @@ export function SharedDragProvider({
|
|
|
128
144
|
[registeredLists, dragState.source]
|
|
129
145
|
);
|
|
130
146
|
|
|
131
|
-
const stableOnMoveItem = useStableCallback(onMoveItem);
|
|
132
|
-
|
|
133
147
|
const handleDragEnd = React.useCallback(
|
|
134
148
|
(event: DragEndEvent) => {
|
|
135
149
|
const { active, over } = event;
|
|
@@ -146,6 +160,7 @@ export function SharedDragProvider({
|
|
|
146
160
|
active,
|
|
147
161
|
source: dragState.source,
|
|
148
162
|
registeredLists,
|
|
163
|
+
acceptsDrop: stableAcceptsDrop.current,
|
|
149
164
|
});
|
|
150
165
|
|
|
151
166
|
setDragState({
|
|
@@ -170,14 +185,16 @@ export function SharedDragProvider({
|
|
|
170
185
|
targetListId: dropTarget.target.listId,
|
|
171
186
|
};
|
|
172
187
|
|
|
173
|
-
|
|
174
|
-
|
|
188
|
+
if (stableOnMoveItem.current) {
|
|
189
|
+
stableOnMoveItem.current(parameters);
|
|
190
|
+
} else {
|
|
191
|
+
// Both lists have the opportunity to handle the move
|
|
192
|
+
sourceList.onMoveItem(parameters);
|
|
175
193
|
|
|
176
|
-
|
|
177
|
-
|
|
194
|
+
if (dropTarget.target.listId !== dropTarget.source.listId) {
|
|
195
|
+
targetList.onMoveItem(parameters);
|
|
196
|
+
}
|
|
178
197
|
}
|
|
179
|
-
|
|
180
|
-
stableOnMoveItem?.(parameters);
|
|
181
198
|
},
|
|
182
199
|
[registeredLists, dragState.source, stableOnMoveItem]
|
|
183
200
|
);
|
|
@@ -327,6 +344,7 @@ function findDropTarget({
|
|
|
327
344
|
active,
|
|
328
345
|
source,
|
|
329
346
|
registeredLists,
|
|
347
|
+
acceptsDrop: acceptsDropProp,
|
|
330
348
|
}: {
|
|
331
349
|
activationPoint: Point;
|
|
332
350
|
delta: Point;
|
|
@@ -334,6 +352,7 @@ function findDropTarget({
|
|
|
334
352
|
active: Active;
|
|
335
353
|
source: DragItem;
|
|
336
354
|
registeredLists: Map<string, RegisteredList>;
|
|
355
|
+
acceptsDrop?: AcceptsDrop;
|
|
337
356
|
}):
|
|
338
357
|
| {
|
|
339
358
|
source: DragItem;
|
|
@@ -379,9 +398,11 @@ function findDropTarget({
|
|
|
379
398
|
return;
|
|
380
399
|
}
|
|
381
400
|
|
|
401
|
+
const acceptsDrop = acceptsDropProp ?? targetList.acceptsDrop;
|
|
402
|
+
|
|
382
403
|
// Dropping on the list container itself
|
|
383
404
|
if (over.id === targetList.id) {
|
|
384
|
-
const canDrop =
|
|
405
|
+
const canDrop = acceptsDrop({
|
|
385
406
|
sourceIndex: source.index,
|
|
386
407
|
targetIndex: Math.max(0, targetList.keys.length - 1), // Use last valid index or 0 for empty lists
|
|
387
408
|
position: "below",
|
|
@@ -408,13 +429,17 @@ function findDropTarget({
|
|
|
408
429
|
const currentY = eventY + delta.y;
|
|
409
430
|
const absolutePosition = { x: currentX, y: currentY };
|
|
410
431
|
|
|
411
|
-
const indicator = targetList.getDropIndicator(
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
432
|
+
const indicator = targetList.getDropIndicator(
|
|
433
|
+
{
|
|
434
|
+
absolutePosition,
|
|
435
|
+
activeIndex: source.index,
|
|
436
|
+
overIndex: targetIndex,
|
|
437
|
+
overRect: over.rect,
|
|
438
|
+
sourceListId: sourceList.id,
|
|
439
|
+
targetListId: targetList.id,
|
|
440
|
+
},
|
|
441
|
+
acceptsDrop
|
|
442
|
+
);
|
|
418
443
|
|
|
419
444
|
if (indicator) {
|
|
420
445
|
return {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { UniqueIdentifier, useDroppable } from "@dnd-kit/core";
|
|
2
4
|
import {
|
|
3
5
|
horizontalListSortingStrategy,
|
|
@@ -74,7 +76,9 @@ function useSortableDropIndicator({
|
|
|
74
76
|
}
|
|
75
77
|
|
|
76
78
|
const targetParentIndex =
|
|
77
|
-
target.index === -1
|
|
79
|
+
listId !== target.listId || target.index === -1
|
|
80
|
+
? undefined
|
|
81
|
+
: getDropTargetParentIndex?.(target.index);
|
|
78
82
|
|
|
79
83
|
const isValidParent =
|
|
80
84
|
targetParentIndex === undefined || targetParentIndex === -1
|
|
@@ -117,7 +121,7 @@ interface RootProps {
|
|
|
117
121
|
acceptsDrop?: DropValidator;
|
|
118
122
|
getDropTargetParentIndex?: (index: number) => number | undefined;
|
|
119
123
|
sharedDragProps?: SharedDragProps;
|
|
120
|
-
containerRef?: React.RefObject<HTMLElement>;
|
|
124
|
+
containerRef?: React.RefObject<HTMLElement | null>;
|
|
121
125
|
}
|
|
122
126
|
|
|
123
127
|
function SortableItem<TElement extends HTMLElement>({
|
|
@@ -202,20 +206,25 @@ function SortableRoot_({
|
|
|
202
206
|
},
|
|
203
207
|
acceptsFromList: acceptsFromList ?? (() => true),
|
|
204
208
|
acceptsDrop,
|
|
205
|
-
getDropIndicator: (parameters) => {
|
|
206
|
-
const {
|
|
207
|
-
|
|
209
|
+
getDropIndicator: (parameters, acceptsDrop) => {
|
|
210
|
+
const {
|
|
211
|
+
absolutePosition,
|
|
212
|
+
activeIndex,
|
|
213
|
+
overIndex,
|
|
214
|
+
overRect,
|
|
215
|
+
sourceListId,
|
|
216
|
+
targetListId,
|
|
217
|
+
} = parameters;
|
|
208
218
|
|
|
209
219
|
const offsetStart =
|
|
210
220
|
axis === "x" ? absolutePosition.x : absolutePosition.y;
|
|
211
|
-
const elementStart = axis === "x" ?
|
|
212
|
-
const elementSize = axis === "x" ?
|
|
221
|
+
const elementStart = axis === "x" ? overRect.left : overRect.top;
|
|
222
|
+
const elementSize = axis === "x" ? overRect.width : overRect.height;
|
|
213
223
|
|
|
214
224
|
const relativeDropPosition = validateDropIndicator({
|
|
215
225
|
acceptsDrop,
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
overId: over.id,
|
|
226
|
+
activeIndex,
|
|
227
|
+
overIndex,
|
|
219
228
|
offsetStart,
|
|
220
229
|
elementStart,
|
|
221
230
|
elementSize,
|
|
@@ -4,7 +4,10 @@ import {
|
|
|
4
4
|
DragRegistrationContextType,
|
|
5
5
|
SharedDragProps,
|
|
6
6
|
} from "./DragRegistration";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
SharedDragProvider,
|
|
9
|
+
SharedDragProviderProps,
|
|
10
|
+
} from "./SharedDragProvider";
|
|
8
11
|
import { Sortable, SortableProps } from "./Sortable";
|
|
9
12
|
|
|
10
13
|
export function createSharedDrag(): {
|
|
@@ -25,11 +28,9 @@ export function createSharedDrag(): {
|
|
|
25
28
|
activeDragContext,
|
|
26
29
|
};
|
|
27
30
|
|
|
28
|
-
const Provider = (
|
|
29
|
-
<
|
|
30
|
-
|
|
31
|
-
</SharedDragProvider>
|
|
32
|
-
);
|
|
31
|
+
const Provider = (
|
|
32
|
+
props: Omit<SharedDragProviderProps, "sharedDragProps">
|
|
33
|
+
) => <SharedDragProvider sharedDragProps={sharedDragProps} {...props} />;
|
|
33
34
|
|
|
34
35
|
return {
|
|
35
36
|
Provider,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { UniqueIdentifier } from "@dnd-kit/core";
|
|
2
4
|
import * as React from "react";
|
|
3
5
|
|
|
@@ -83,9 +85,8 @@ export const SortableItemContext =
|
|
|
83
85
|
|
|
84
86
|
export type ValidateDropIndicatorParams = {
|
|
85
87
|
acceptsDrop: DropValidator; // Function that validates if a drop is allowed
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
overId: UniqueIdentifier; // ID of item being dragged over
|
|
88
|
+
activeIndex: number; // ID of item being dragged
|
|
89
|
+
overIndex: number; // ID of item being dragged over
|
|
89
90
|
offsetStart: number; // Current drag position (x or y coordinate)
|
|
90
91
|
elementStart: number; // Start position of target element (left or top)
|
|
91
92
|
elementSize: number; // Size of target element (width or height)
|
|
@@ -95,18 +96,14 @@ export type ValidateDropIndicatorParams = {
|
|
|
95
96
|
|
|
96
97
|
export function validateDropIndicator({
|
|
97
98
|
acceptsDrop,
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
overId,
|
|
99
|
+
activeIndex,
|
|
100
|
+
overIndex,
|
|
101
101
|
offsetStart,
|
|
102
102
|
elementStart,
|
|
103
103
|
elementSize,
|
|
104
104
|
sourceListId,
|
|
105
105
|
targetListId,
|
|
106
106
|
}: ValidateDropIndicatorParams): RelativeDropPosition | undefined {
|
|
107
|
-
const activeIndex = keys.findIndex((id) => id === activeId); // index of item being dragged
|
|
108
|
-
const overIndex = keys.findIndex((id) => id === overId); // index of item being dragged over
|
|
109
|
-
|
|
110
107
|
if (overIndex === -1) return undefined;
|
|
111
108
|
if (activeIndex === -1 && sourceListId === targetListId) return undefined;
|
|
112
109
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
1
3
|
import { memoGeneric } from "@noya-app/react-utils";
|
|
2
|
-
import React, {
|
|
3
|
-
import {
|
|
4
|
-
EDITOR_PANEL_GROUP_ID,
|
|
5
|
-
LEFT_SIDEBAR_ID,
|
|
6
|
-
RIGHT_SIDEBAR_ID,
|
|
7
|
-
} from "../../hooks/usePreservePanelSize";
|
|
4
|
+
import React, { useMemo, useRef, useState } from "react";
|
|
5
|
+
import { DividerVertical } from "../Divider";
|
|
8
6
|
import { Drawer } from "../Drawer";
|
|
9
|
-
import {
|
|
7
|
+
import { isSelectableMenuItem, MenuItem } from "../internal/Menu";
|
|
8
|
+
import { EDITOR_PANEL_GROUP_ID, RIGHT_SIDEBAR_ID } from "./constants";
|
|
9
|
+
import { LayoutProps, PanelLayoutState } from "./types";
|
|
10
|
+
import { VerticalTabMenu } from "./VerticalTabMenu";
|
|
10
11
|
|
|
11
12
|
export const DrawerWorkspaceLayout = memoGeneric(function DrawerWorkspaceLayout<
|
|
12
13
|
LeftTab extends string = string,
|
|
@@ -17,26 +18,51 @@ export const DrawerWorkspaceLayout = memoGeneric(function DrawerWorkspaceLayout<
|
|
|
17
18
|
rightPanel,
|
|
18
19
|
rightSidebarRef,
|
|
19
20
|
centerPanel,
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
leftTabItems,
|
|
22
|
+
leftTabValue,
|
|
23
|
+
rightTabItems,
|
|
24
|
+
rightTabValue,
|
|
25
|
+
onChangeRightTab,
|
|
26
|
+
onChangeLeftTab,
|
|
22
27
|
}: LayoutProps<LeftTab, RightTab>) {
|
|
23
28
|
const portalContainer = useRef<HTMLDivElement>(null);
|
|
24
|
-
const [mounted, setMounted] = useState(false);
|
|
25
|
-
|
|
26
|
-
useLayoutEffect(() => {
|
|
27
|
-
if (mounted) return;
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
|
|
30
|
+
const [{ leftSidebarCollapsed, rightSidebarCollapsed }, setLayoutState] =
|
|
31
|
+
useState<PanelLayoutState>({
|
|
31
32
|
leftSidebarCollapsed: true,
|
|
32
33
|
rightSidebarCollapsed: true,
|
|
33
34
|
});
|
|
34
|
-
}, [handleChangeLayoutState, mounted]);
|
|
35
35
|
|
|
36
|
-
const
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
36
|
+
const allTabItems = useMemo(
|
|
37
|
+
() =>
|
|
38
|
+
[
|
|
39
|
+
...(leftPanel ? leftTabItems ?? [] : []),
|
|
40
|
+
...(rightPanel ? rightTabItems ?? [] : []),
|
|
41
|
+
] as MenuItem<LeftTab | RightTab>[],
|
|
42
|
+
[leftTabItems, rightTabItems, leftPanel, rightPanel]
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
const hasTabs = allTabItems.length > 0;
|
|
46
|
+
|
|
47
|
+
const leftSelectableTabItems = useMemo(
|
|
48
|
+
() => (leftTabItems ?? []).filter(isSelectableMenuItem),
|
|
49
|
+
[leftTabItems]
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
const rightSelectableTabItems = useMemo(
|
|
53
|
+
() => (rightTabItems ?? []).filter(isSelectableMenuItem),
|
|
54
|
+
[rightTabItems]
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const { activeValue, isSidebarCollapsed } =
|
|
58
|
+
leftSelectableTabItems.length > 0 && !leftSidebarCollapsed
|
|
59
|
+
? { activeValue: leftTabValue, isSidebarCollapsed: leftSidebarCollapsed }
|
|
60
|
+
: rightSelectableTabItems.length > 0 && !rightSidebarCollapsed
|
|
61
|
+
? {
|
|
62
|
+
activeValue: rightTabValue,
|
|
63
|
+
isSidebarCollapsed: rightSidebarCollapsed,
|
|
64
|
+
}
|
|
65
|
+
: { activeValue: undefined, isSidebarCollapsed: true };
|
|
40
66
|
|
|
41
67
|
return (
|
|
42
68
|
<div
|
|
@@ -44,39 +70,94 @@ export const DrawerWorkspaceLayout = memoGeneric(function DrawerWorkspaceLayout<
|
|
|
44
70
|
id={EDITOR_PANEL_GROUP_ID}
|
|
45
71
|
className="flex flex-1 relative focus:outline-none"
|
|
46
72
|
>
|
|
73
|
+
{hasTabs && (
|
|
74
|
+
<VerticalTabMenu
|
|
75
|
+
tooltipSide="right"
|
|
76
|
+
items={allTabItems}
|
|
77
|
+
activeValue={activeValue}
|
|
78
|
+
isSidebarCollapsed={isSidebarCollapsed}
|
|
79
|
+
onChange={(value) => {
|
|
80
|
+
if (leftSelectableTabItems.some((item) => item.value === value)) {
|
|
81
|
+
if (value === leftTabValue) {
|
|
82
|
+
if (leftSidebarRef.current?.isExpanded()) {
|
|
83
|
+
leftSidebarRef.current?.collapse();
|
|
84
|
+
} else {
|
|
85
|
+
leftSidebarRef.current?.expand();
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
if (!leftSidebarRef.current?.isExpanded()) {
|
|
89
|
+
leftSidebarRef.current?.expand();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
onChangeLeftTab?.(value as LeftTab);
|
|
93
|
+
}
|
|
94
|
+
} else if (
|
|
95
|
+
rightSelectableTabItems.some((item) => item.value === value)
|
|
96
|
+
) {
|
|
97
|
+
if (value === rightTabValue) {
|
|
98
|
+
if (rightSidebarRef.current?.isExpanded()) {
|
|
99
|
+
rightSidebarRef.current?.collapse();
|
|
100
|
+
} else {
|
|
101
|
+
rightSidebarRef.current?.expand();
|
|
102
|
+
}
|
|
103
|
+
} else {
|
|
104
|
+
if (!rightSidebarRef.current?.isExpanded()) {
|
|
105
|
+
rightSidebarRef.current?.expand();
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
onChangeRightTab?.(value as RightTab);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}}
|
|
112
|
+
/>
|
|
113
|
+
)}
|
|
114
|
+
{hasTabs && <DividerVertical className="h-full" />}
|
|
115
|
+
<div className="flex-1 flex relative">{centerPanel}</div>
|
|
47
116
|
{leftPanel && (
|
|
48
117
|
<Drawer
|
|
49
|
-
id={LEFT_SIDEBAR_ID}
|
|
50
118
|
ref={leftSidebarRef}
|
|
51
119
|
className="flex-1"
|
|
120
|
+
style={{
|
|
121
|
+
left: 48,
|
|
122
|
+
maxWidth: "calc(100% - 48px)",
|
|
123
|
+
}}
|
|
124
|
+
overlayStyle={{
|
|
125
|
+
left: 48,
|
|
126
|
+
}}
|
|
52
127
|
open={!leftSidebarCollapsed}
|
|
53
128
|
positioning="absolute"
|
|
54
129
|
side="left"
|
|
55
130
|
trigger={null}
|
|
56
131
|
portalContainer={portalContainer.current}
|
|
57
132
|
onOpenChange={(open) => {
|
|
58
|
-
|
|
59
|
-
rightSidebarCollapsed: rightSidebarCollapsed,
|
|
133
|
+
setLayoutState({
|
|
60
134
|
leftSidebarCollapsed: !open,
|
|
135
|
+
rightSidebarCollapsed: rightSidebarCollapsed,
|
|
61
136
|
});
|
|
62
137
|
}}
|
|
63
138
|
>
|
|
64
139
|
{leftPanel}
|
|
65
140
|
</Drawer>
|
|
66
141
|
)}
|
|
67
|
-
{centerPanel}
|
|
68
142
|
{rightPanel && (
|
|
69
143
|
<Drawer
|
|
70
144
|
id={RIGHT_SIDEBAR_ID}
|
|
71
145
|
ref={rightSidebarRef}
|
|
72
146
|
className="flex-1"
|
|
147
|
+
style={{
|
|
148
|
+
left: 48,
|
|
149
|
+
maxWidth: "calc(100% - 48px)",
|
|
150
|
+
}}
|
|
151
|
+
overlayStyle={{
|
|
152
|
+
left: 48,
|
|
153
|
+
}}
|
|
73
154
|
open={!rightSidebarCollapsed}
|
|
74
155
|
positioning="absolute"
|
|
75
|
-
side="
|
|
156
|
+
side="left"
|
|
76
157
|
trigger={null}
|
|
77
158
|
portalContainer={portalContainer.current}
|
|
78
159
|
onOpenChange={(open) => {
|
|
79
|
-
|
|
160
|
+
setLayoutState({
|
|
80
161
|
leftSidebarCollapsed: leftSidebarCollapsed,
|
|
81
162
|
rightSidebarCollapsed: !open,
|
|
82
163
|
});
|