@noya-app/noya-designsystem 0.1.63 → 0.1.65
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 +13 -10
- package/CHANGELOG.md +25 -0
- package/dist/index.css +1 -1
- package/dist/index.d.mts +648 -333
- package/dist/index.d.ts +648 -333
- package/dist/index.js +13813 -9157
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +13949 -9269
- 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 +13 -6
- package/src/components/ActivityLog.tsx +197 -0
- package/src/components/AnimatePresence.tsx +43 -26
- package/src/components/Avatar.tsx +45 -26
- package/src/components/Banner.tsx +57 -11
- package/src/components/BaseToolbar.tsx +67 -34
- package/src/components/Breadcrumbs.tsx +4 -2
- package/src/components/Button.tsx +28 -23
- package/src/components/Checkbox.tsx +6 -35
- package/src/components/Chip.tsx +47 -33
- package/src/components/Collection.tsx +20 -12
- package/src/components/ColorSwatch.tsx +42 -22
- package/src/components/ColorSwatchControl.tsx +7 -5
- package/src/components/Combobox.tsx +8 -6
- package/src/components/ComboboxMenu.tsx +6 -5
- package/src/components/CommandPalette.tsx +3 -1
- package/src/components/ContextMenu.tsx +3 -1
- package/src/components/Dialog.tsx +9 -13
- package/src/components/DimensionInput.tsx +2 -0
- package/src/components/Divider.tsx +18 -14
- package/src/components/DraggableMenuButton.tsx +11 -5
- package/src/components/Drawer.tsx +14 -6
- package/src/components/DropdownMenu.tsx +4 -2
- package/src/components/EditableText.tsx +4 -2
- package/src/components/Fade.tsx +13 -13
- package/src/components/FileUploadIndicator.tsx +108 -0
- package/src/components/FloatingWindow.tsx +4 -2
- package/src/components/Grid.tsx +58 -42
- package/src/components/GridView.tsx +65 -36
- package/src/components/IVirtualizedList.tsx +5 -0
- package/src/components/IconButton.tsx +2 -0
- package/src/components/Icons.tsx +24 -4
- package/src/components/InputField.tsx +21 -19
- package/src/components/InspectorContainer.tsx +2 -2
- package/src/components/InspectorPrimitives.tsx +15 -9
- package/src/components/Label.tsx +4 -3
- package/src/components/LabeledElementView.tsx +9 -5
- package/src/components/LabeledField.tsx +8 -6
- package/src/components/List.tsx +112 -46
- package/src/components/ListMenu.tsx +91 -0
- package/src/components/ListNavigator.tsx +106 -0
- package/src/components/ListView.tsx +22 -1147
- package/src/components/MediaThumbnail.tsx +84 -14
- package/src/components/Message.tsx +11 -12
- package/src/components/Navigator.tsx +461 -0
- package/src/components/NoyaLogo.tsx +1 -1
- package/src/components/Popover.tsx +12 -6
- package/src/components/Progress.tsx +31 -8
- package/src/components/ResizableContainer.tsx +187 -0
- package/src/components/RingProgress.tsx +128 -0
- package/src/components/ScrollArea.tsx +7 -5
- package/src/components/ScrollableSidebar.tsx +10 -0
- package/src/components/SearchCompletionMenu.tsx +5 -3
- package/src/components/Section.tsx +109 -57
- package/src/components/SegmentedControl.tsx +51 -25
- package/src/components/SelectMenu.tsx +16 -21
- package/src/components/SelectionToolbar.tsx +7 -4
- package/src/components/Slider.tsx +12 -10
- package/src/components/Spacer.tsx +2 -2
- package/src/components/StackNavigator.tsx +378 -0
- package/src/components/Stepper.tsx +88 -0
- package/src/components/Switch.tsx +7 -5
- package/src/components/Tabs.tsx +6 -4
- package/src/components/Text.tsx +29 -18
- package/src/components/TextArea.tsx +5 -3
- package/src/components/Toast.tsx +5 -5
- package/src/components/Toolbar.tsx +57 -10
- package/src/components/ToolbarDrawer.tsx +29 -0
- package/src/components/Tooltip.tsx +2 -2
- package/src/components/TreeView.tsx +13 -4
- package/src/components/UserPointer.tsx +6 -4
- package/src/components/ai-assistant/AIAssistantLayout.tsx +10 -8
- package/src/components/blocks/ImageBlockComponent.tsx +162 -0
- package/src/components/connected-users-menu/ConnectedUsersMenuLayout.tsx +6 -4
- package/src/components/file-explorer/FileExplorerLayout.tsx +22 -8
- package/src/components/internal/Checkmark.tsx +24 -0
- package/src/components/internal/Menu.tsx +24 -19
- package/src/components/internal/MenuViewport.tsx +15 -6
- package/src/components/internal/SelectItem.tsx +7 -26
- package/src/components/internal/TextInput.tsx +7 -1
- package/src/components/listView/ListViewContexts.tsx +68 -0
- package/src/components/listView/ListViewEditableRowTitle.tsx +55 -0
- package/src/components/listView/ListViewRoot.tsx +521 -0
- package/src/components/listView/ListViewRow.tsx +475 -0
- package/src/components/listView/ListViewRowTitle.tsx +21 -0
- package/src/components/listView/types.ts +11 -0
- package/src/components/pipeline/PipelineResultLayout.tsx +6 -6
- package/src/components/sorting/DragRegistration.tsx +10 -5
- package/src/components/sorting/SharedDragProvider.tsx +134 -27
- package/src/components/sorting/Sortable.tsx +90 -27
- package/src/components/sorting/createSharedDrag.tsx +7 -6
- package/src/components/sorting/sorting.ts +6 -9
- package/src/components/workspace/DrawerWorkspaceLayout.tsx +110 -29
- package/src/components/workspace/PanelWorkspaceLayout.tsx +148 -99
- package/src/components/workspace/VerticalTabMenu.tsx +46 -0
- package/src/components/workspace/WorkspaceLayout.tsx +76 -63
- 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 +19 -5
- 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 +5 -8
- 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 +43 -10
- package/src/index.tsx +15 -7
- package/src/utils/classNames.ts +56 -9
- package/src/utils/combobox.ts +2 -0
- package/src/utils/editableBlockStyles.ts +2 -2
- package/src/utils/formatByteSize.ts +9 -0
- package/src/utils/inputs.ts +8 -6
- package/src/utils/sketchColor.ts +0 -34
- package/src/utils/withSeparatorElements.ts +1 -1
- package/tailwind.config.ts +1 -0
- package/src/components/FillInputField.tsx +0 -37
- package/src/components/FillPreviewBackground.tsx +0 -132
- package/src/components/GradientPicker.tsx +0 -88
- package/src/hooks/usePreservePanelSize.tsx +0 -183
- package/src/mediaQuery.ts +0 -13
- package/src/utils/getGradientBackground.tsx +0 -31
|
@@ -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,66 +18,146 @@ 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
|
|
43
69
|
ref={portalContainer}
|
|
44
70
|
id={EDITOR_PANEL_GROUP_ID}
|
|
45
|
-
className="flex flex-1 relative focus:outline-none"
|
|
71
|
+
className="n-flex n-flex-1 n-relative focus:n-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="n-h-full" />}
|
|
115
|
+
<div className="n-flex-1 n-flex n-relative">{centerPanel}</div>
|
|
47
116
|
{leftPanel && (
|
|
48
117
|
<Drawer
|
|
49
|
-
id={LEFT_SIDEBAR_ID}
|
|
50
118
|
ref={leftSidebarRef}
|
|
51
|
-
className="flex-1"
|
|
119
|
+
className="n-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
|
-
className="flex-1"
|
|
146
|
+
className="n-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
|
});
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
clientStorage,
|
|
5
|
+
memoGeneric,
|
|
6
|
+
usePersistentStateObject,
|
|
7
|
+
} from "@noya-app/react-utils";
|
|
8
|
+
import React, { useCallback, useMemo, useRef } from "react";
|
|
3
9
|
import {
|
|
4
10
|
ImperativePanelGroupHandle,
|
|
5
11
|
ImperativePanelHandle,
|
|
@@ -7,19 +13,25 @@ import {
|
|
|
7
13
|
PanelGroup,
|
|
8
14
|
PanelResizeHandle,
|
|
9
15
|
} from "react-resizable-panels";
|
|
16
|
+
import { DividerVertical } from "../Divider";
|
|
10
17
|
import {
|
|
11
18
|
CONTENT_AREA_ID,
|
|
12
19
|
EDITOR_PANEL_GROUP_ID,
|
|
13
20
|
LEFT_SIDEBAR_ID,
|
|
14
21
|
RIGHT_SIDEBAR_ID,
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
} from "./constants";
|
|
23
|
+
import {
|
|
24
|
+
getInitialLayout,
|
|
25
|
+
getLayoutCollapsedState,
|
|
26
|
+
getLayoutIds,
|
|
27
|
+
getPropertyKey,
|
|
28
|
+
getStorageKey,
|
|
29
|
+
panelStorage,
|
|
30
|
+
setInitialLayout,
|
|
31
|
+
toPixelSize,
|
|
32
|
+
} from "./panelStorage";
|
|
33
|
+
import { LayoutProps, WorkspaceLayoutState } from "./types";
|
|
34
|
+
import { VerticalTabMenu } from "./VerticalTabMenu";
|
|
23
35
|
|
|
24
36
|
export const PanelWorkspaceLayout = memoGeneric(function PanelWorkspaceLayout<
|
|
25
37
|
LeftTab extends string,
|
|
@@ -32,7 +44,6 @@ export const PanelWorkspaceLayout = memoGeneric(function PanelWorkspaceLayout<
|
|
|
32
44
|
rightSidebarOptions,
|
|
33
45
|
centerPanelPercentage,
|
|
34
46
|
autoSavePrefix,
|
|
35
|
-
internalLayoutState,
|
|
36
47
|
leftSidebarRef,
|
|
37
48
|
rightSidebarRef,
|
|
38
49
|
leftTabItems,
|
|
@@ -41,56 +52,140 @@ export const PanelWorkspaceLayout = memoGeneric(function PanelWorkspaceLayout<
|
|
|
41
52
|
rightTabValue,
|
|
42
53
|
onChangeLeftTab,
|
|
43
54
|
onChangeRightTab,
|
|
44
|
-
handleChangeLayoutState,
|
|
45
55
|
}: LayoutProps<LeftTab, RightTab>) {
|
|
46
56
|
const panelGroupRef = useRef<ImperativePanelGroupHandle>(null);
|
|
47
57
|
|
|
48
|
-
|
|
58
|
+
const hasLeftPanel = !!leftPanel;
|
|
59
|
+
const hasRightPanel = !!rightPanel;
|
|
60
|
+
const hasCenterPanel = !!centerPanel;
|
|
61
|
+
|
|
62
|
+
const autoSaveId = useMemo(() => {
|
|
63
|
+
return autoSavePrefix
|
|
64
|
+
? `${autoSavePrefix}--v2--${EDITOR_PANEL_GROUP_ID}`
|
|
65
|
+
: Math.random().toString(36).substring(2, 15);
|
|
66
|
+
}, [autoSavePrefix]);
|
|
67
|
+
|
|
68
|
+
const layoutIds = getLayoutIds({
|
|
69
|
+
hasLeftPanel,
|
|
70
|
+
hasRightPanel,
|
|
71
|
+
hasCenterPanel,
|
|
72
|
+
});
|
|
73
|
+
const storageKey = getStorageKey(autoSaveId);
|
|
74
|
+
const propertyKey = getPropertyKey(layoutIds);
|
|
75
|
+
|
|
76
|
+
setInitialLayout({
|
|
77
|
+
storageKey,
|
|
78
|
+
propertyKey,
|
|
79
|
+
calculateLayout: () => {
|
|
80
|
+
return getInitialLayout({
|
|
81
|
+
layoutIds,
|
|
82
|
+
leftSidebarOptions,
|
|
83
|
+
rightSidebarOptions,
|
|
84
|
+
centerPanelPercentage,
|
|
85
|
+
hasLeftPanel,
|
|
86
|
+
hasRightPanel,
|
|
87
|
+
hasCenterPanel,
|
|
88
|
+
});
|
|
89
|
+
},
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
const [data, setData] = usePersistentStateObject<
|
|
93
|
+
WorkspaceLayoutState,
|
|
94
|
+
string
|
|
95
|
+
>(clientStorage, storageKey, {});
|
|
96
|
+
|
|
97
|
+
const layoutGroup = data?.[propertyKey];
|
|
98
|
+
|
|
99
|
+
const { leftSidebarCollapsed, rightSidebarCollapsed } = useMemo(() => {
|
|
100
|
+
return getLayoutCollapsedState({
|
|
101
|
+
layoutGroup,
|
|
102
|
+
propertyKey,
|
|
103
|
+
layoutIds,
|
|
104
|
+
hasLeftPanel,
|
|
105
|
+
hasRightPanel,
|
|
106
|
+
});
|
|
107
|
+
}, [layoutGroup, propertyKey, layoutIds, hasLeftPanel, hasRightPanel]);
|
|
108
|
+
|
|
109
|
+
const handleLeftTabChange = useCallback(
|
|
110
|
+
(value: LeftTab) => {
|
|
111
|
+
if (value === leftTabValue) {
|
|
112
|
+
if (leftSidebarRef.current?.isExpanded()) {
|
|
113
|
+
leftSidebarRef.current?.collapse();
|
|
114
|
+
} else {
|
|
115
|
+
leftSidebarRef.current?.expand();
|
|
116
|
+
}
|
|
117
|
+
} else {
|
|
118
|
+
if (!leftSidebarRef.current?.isExpanded()) {
|
|
119
|
+
leftSidebarRef.current?.expand();
|
|
120
|
+
}
|
|
121
|
+
onChangeLeftTab?.(value);
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
[leftSidebarRef, leftTabValue, onChangeLeftTab]
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
const handleRightTabChange = useCallback(
|
|
128
|
+
(value: RightTab) => {
|
|
129
|
+
if (value === rightTabValue) {
|
|
130
|
+
if (rightSidebarRef.current?.isExpanded()) {
|
|
131
|
+
rightSidebarRef.current?.collapse();
|
|
132
|
+
} else {
|
|
133
|
+
rightSidebarRef.current?.expand();
|
|
134
|
+
}
|
|
135
|
+
} else {
|
|
136
|
+
if (!rightSidebarRef.current?.isExpanded()) {
|
|
137
|
+
rightSidebarRef.current?.expand();
|
|
138
|
+
}
|
|
139
|
+
onChangeRightTab?.(value);
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
[onChangeRightTab, rightSidebarRef, rightTabValue]
|
|
143
|
+
);
|
|
144
|
+
|
|
145
|
+
const handleLayoutChange = useCallback(
|
|
146
|
+
(layout: number[]) => {
|
|
147
|
+
setData((prev) => {
|
|
148
|
+
const newData = {
|
|
149
|
+
...prev,
|
|
150
|
+
[propertyKey]: {
|
|
151
|
+
layout: layout.map((size) => toPixelSize(size)),
|
|
152
|
+
expandToSizes: prev?.[propertyKey]?.expandToSizes ?? {},
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
return newData;
|
|
157
|
+
});
|
|
158
|
+
},
|
|
159
|
+
[setData, propertyKey]
|
|
160
|
+
);
|
|
49
161
|
|
|
50
162
|
return (
|
|
51
163
|
<PanelGroup
|
|
52
164
|
ref={panelGroupRef}
|
|
53
165
|
id={EDITOR_PANEL_GROUP_ID}
|
|
54
|
-
className="flex-1"
|
|
166
|
+
className="n-flex-1"
|
|
55
167
|
direction="horizontal"
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
: undefined
|
|
60
|
-
}
|
|
168
|
+
storage={panelStorage}
|
|
169
|
+
autoSaveId={autoSaveId}
|
|
170
|
+
onLayout={handleLayoutChange}
|
|
61
171
|
>
|
|
62
172
|
{leftPanel && (
|
|
63
173
|
<>
|
|
64
|
-
{leftTabItems && (
|
|
174
|
+
{leftSidebarOptions.showTabs && leftTabItems && (
|
|
65
175
|
<VerticalTabMenu
|
|
66
176
|
tooltipSide="right"
|
|
67
177
|
items={leftTabItems}
|
|
68
178
|
activeValue={leftTabValue}
|
|
69
|
-
isSidebarCollapsed={
|
|
70
|
-
|
|
71
|
-
}
|
|
72
|
-
onChange={(value) => {
|
|
73
|
-
if (value === leftTabValue) {
|
|
74
|
-
if (leftSidebarRef.current?.isExpanded()) {
|
|
75
|
-
leftSidebarRef.current?.collapse();
|
|
76
|
-
} else {
|
|
77
|
-
leftSidebarRef.current?.expand();
|
|
78
|
-
}
|
|
79
|
-
} else {
|
|
80
|
-
if (!leftSidebarRef.current?.isExpanded()) {
|
|
81
|
-
leftSidebarRef.current?.expand();
|
|
82
|
-
}
|
|
83
|
-
onChangeLeftTab?.(value);
|
|
84
|
-
}
|
|
85
|
-
}}
|
|
179
|
+
isSidebarCollapsed={leftSidebarCollapsed}
|
|
180
|
+
onChange={handleLeftTabChange}
|
|
86
181
|
/>
|
|
87
182
|
)}
|
|
88
|
-
{
|
|
89
|
-
|
|
90
|
-
|
|
183
|
+
{leftSidebarOptions.showTabs &&
|
|
184
|
+
leftTabItems &&
|
|
185
|
+
!leftSidebarCollapsed && <DividerVertical className="n-h-full" />}
|
|
91
186
|
<Panel
|
|
92
187
|
id={LEFT_SIDEBAR_ID}
|
|
93
|
-
className="relative"
|
|
188
|
+
className="n-relative"
|
|
94
189
|
order={1}
|
|
95
190
|
ref={leftSidebarRef as React.RefObject<ImperativePanelHandle>}
|
|
96
191
|
defaultSize={leftSidebarOptions.initialSize}
|
|
@@ -103,9 +198,9 @@ export const PanelWorkspaceLayout = memoGeneric(function PanelWorkspaceLayout<
|
|
|
103
198
|
}
|
|
104
199
|
collapsible
|
|
105
200
|
>
|
|
106
|
-
{
|
|
201
|
+
{leftSidebarCollapsed ? null : leftPanel}
|
|
107
202
|
</Panel>
|
|
108
|
-
<PanelResizeHandle className="cursor-col-resize w-px h-full bg-divider" />
|
|
203
|
+
<PanelResizeHandle className="n-cursor-col-resize n-w-px n-h-full n-bg-divider" />
|
|
109
204
|
</>
|
|
110
205
|
)}
|
|
111
206
|
<Panel
|
|
@@ -113,16 +208,16 @@ export const PanelWorkspaceLayout = memoGeneric(function PanelWorkspaceLayout<
|
|
|
113
208
|
order={2}
|
|
114
209
|
defaultSize={centerPanelPercentage}
|
|
115
210
|
minSize={10}
|
|
116
|
-
className="flex relative"
|
|
211
|
+
className="n-flex n-relative"
|
|
117
212
|
>
|
|
118
213
|
{centerPanel}
|
|
119
214
|
</Panel>
|
|
120
215
|
{rightPanel && (
|
|
121
216
|
<>
|
|
122
|
-
<PanelResizeHandle className="cursor-col-resize w-px h-full bg-divider" />
|
|
217
|
+
<PanelResizeHandle className="n-cursor-col-resize n-w-px n-h-full n-bg-divider" />
|
|
123
218
|
<Panel
|
|
124
219
|
id={RIGHT_SIDEBAR_ID}
|
|
125
|
-
className="relative"
|
|
220
|
+
className="n-relative"
|
|
126
221
|
order={3}
|
|
127
222
|
ref={rightSidebarRef as React.RefObject<ImperativePanelHandle>}
|
|
128
223
|
minSize={rightSidebarOptions.minSize}
|
|
@@ -135,33 +230,18 @@ export const PanelWorkspaceLayout = memoGeneric(function PanelWorkspaceLayout<
|
|
|
135
230
|
}
|
|
136
231
|
collapsible
|
|
137
232
|
>
|
|
138
|
-
{
|
|
233
|
+
{rightSidebarCollapsed ? null : rightPanel}
|
|
139
234
|
</Panel>
|
|
140
|
-
{
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
{rightTabItems && (
|
|
235
|
+
{rightSidebarOptions.showTabs &&
|
|
236
|
+
rightTabItems &&
|
|
237
|
+
!rightSidebarCollapsed && <DividerVertical className="n-h-full" />}
|
|
238
|
+
{rightSidebarOptions.showTabs && rightTabItems && (
|
|
144
239
|
<VerticalTabMenu
|
|
145
240
|
tooltipSide="left"
|
|
146
241
|
items={rightTabItems}
|
|
147
242
|
activeValue={rightTabValue}
|
|
148
|
-
isSidebarCollapsed={
|
|
149
|
-
|
|
150
|
-
}
|
|
151
|
-
onChange={(value) => {
|
|
152
|
-
if (value === rightTabValue) {
|
|
153
|
-
if (rightSidebarRef.current?.isExpanded()) {
|
|
154
|
-
rightSidebarRef.current?.collapse();
|
|
155
|
-
} else {
|
|
156
|
-
rightSidebarRef.current?.expand();
|
|
157
|
-
}
|
|
158
|
-
} else {
|
|
159
|
-
if (!rightSidebarRef.current?.isExpanded()) {
|
|
160
|
-
rightSidebarRef.current?.expand();
|
|
161
|
-
}
|
|
162
|
-
onChangeRightTab?.(value);
|
|
163
|
-
}
|
|
164
|
-
}}
|
|
243
|
+
isSidebarCollapsed={rightSidebarCollapsed}
|
|
244
|
+
onChange={handleRightTabChange}
|
|
165
245
|
/>
|
|
166
246
|
)}
|
|
167
247
|
</>
|
|
@@ -169,34 +249,3 @@ export const PanelWorkspaceLayout = memoGeneric(function PanelWorkspaceLayout<
|
|
|
169
249
|
</PanelGroup>
|
|
170
250
|
);
|
|
171
251
|
});
|
|
172
|
-
|
|
173
|
-
function VerticalTabMenu<TabValue extends string>({
|
|
174
|
-
items,
|
|
175
|
-
activeValue,
|
|
176
|
-
isSidebarCollapsed,
|
|
177
|
-
onChange,
|
|
178
|
-
tooltipSide,
|
|
179
|
-
}: {
|
|
180
|
-
items: MenuItem<TabValue>[];
|
|
181
|
-
activeValue: TabValue | undefined;
|
|
182
|
-
isSidebarCollapsed: boolean;
|
|
183
|
-
onChange: (value: TabValue) => void;
|
|
184
|
-
tooltipSide?: ComponentProps<typeof Tooltip>["side"];
|
|
185
|
-
}) {
|
|
186
|
-
return (
|
|
187
|
-
<div
|
|
188
|
-
className="w-[47px] h-full bg-sidebar-background flex flex-col items-center py-3 gap-3"
|
|
189
|
-
style={{
|
|
190
|
-
[cssVarNames.colors.inputBackground]: "transparent",
|
|
191
|
-
[cssVarNames.colors.buttonBackground]: "transparent",
|
|
192
|
-
}}
|
|
193
|
-
>
|
|
194
|
-
<ToolbarMenu
|
|
195
|
-
items={items}
|
|
196
|
-
activeValue={isSidebarCollapsed ? undefined : activeValue}
|
|
197
|
-
onSelectMenuItem={onChange}
|
|
198
|
-
tooltipSide={tooltipSide}
|
|
199
|
-
/>
|
|
200
|
-
</div>
|
|
201
|
-
);
|
|
202
|
-
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { memoGeneric } from "@noya-app/react-utils";
|
|
2
|
+
import React, { ComponentProps, useMemo } from "react";
|
|
3
|
+
import { cssVarNames } from "../../theme";
|
|
4
|
+
import { MenuItem } from "../internal/Menu";
|
|
5
|
+
import { ToolbarMenu } from "../Toolbar";
|
|
6
|
+
import { Tooltip } from "../Tooltip";
|
|
7
|
+
|
|
8
|
+
type VerticalTabMenuProps<TabValue extends string> = {
|
|
9
|
+
items: MenuItem<TabValue>[];
|
|
10
|
+
activeValue: TabValue | undefined;
|
|
11
|
+
isSidebarCollapsed: boolean;
|
|
12
|
+
onChange: (value: TabValue) => void;
|
|
13
|
+
tooltipSide?: ComponentProps<typeof Tooltip>["side"];
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export const VerticalTabMenu = memoGeneric(function VerticalTabMenu<
|
|
17
|
+
TabValue extends string,
|
|
18
|
+
>({
|
|
19
|
+
items,
|
|
20
|
+
activeValue,
|
|
21
|
+
isSidebarCollapsed,
|
|
22
|
+
onChange,
|
|
23
|
+
tooltipSide,
|
|
24
|
+
}: VerticalTabMenuProps<TabValue>) {
|
|
25
|
+
const style = useMemo(() => {
|
|
26
|
+
return {
|
|
27
|
+
[cssVarNames.colors.inputBackground]: "transparent",
|
|
28
|
+
[cssVarNames.colors.buttonBackground]: "transparent",
|
|
29
|
+
};
|
|
30
|
+
}, []);
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<div
|
|
34
|
+
className="n-w-[47px] n-h-full n-bg-sidebar-background n-flex n-flex-col n-items-center n-py-3 n-gap-3"
|
|
35
|
+
style={style}
|
|
36
|
+
>
|
|
37
|
+
<ToolbarMenu
|
|
38
|
+
items={items}
|
|
39
|
+
activeValue={isSidebarCollapsed ? undefined : activeValue}
|
|
40
|
+
onSelectMenuItem={onChange}
|
|
41
|
+
tooltipSide={tooltipSide}
|
|
42
|
+
displayFilter="iconOnly"
|
|
43
|
+
/>
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
});
|