@noya-app/noya-designsystem 0.1.76 → 0.1.78
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 +20 -12
- package/CHANGELOG.md +19 -0
- package/dist/chunk-D57E6H3M.mjs +36 -0
- package/dist/chunk-D57E6H3M.mjs.map +1 -0
- package/dist/emojis.d.mts +1 -0
- package/dist/emojis.d.ts +1 -0
- package/dist/emojis.js +31 -0
- package/dist/emojis.js.map +1 -0
- package/dist/emojis.mjs +8 -0
- package/dist/emojis.mjs.map +1 -0
- package/dist/index.css +1 -1
- package/dist/index.d.mts +192 -93
- package/dist/index.d.ts +192 -93
- package/dist/index.js +3355 -1763
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3622 -2030
- package/dist/index.mjs.map +1 -1
- package/package.json +13 -9
- package/src/__tests__/__snapshots__/fuzzyScorer.test.ts.snap +1 -1
- package/src/components/Avatar.tsx +10 -10
- package/src/components/Banner.tsx +1 -1
- package/src/components/BaseToolbar.tsx +20 -6
- package/src/components/Button.tsx +2 -1
- package/src/components/Chip.tsx +1 -1
- package/src/components/ColorSwatchControl.tsx +22 -14
- package/src/components/CommandPalette.tsx +10 -6
- package/src/components/ContextMenu.tsx +249 -38
- package/src/components/Dialog.tsx +70 -67
- package/src/components/Drawer.tsx +56 -17
- package/src/components/DropdownMenu.tsx +307 -46
- package/src/components/EditableText.tsx +1 -1
- package/src/components/EmojiPicker.tsx +645 -0
- package/src/components/GridBackground.tsx +40 -0
- package/src/components/GridView.tsx +5 -1
- package/src/components/IVirtualizedList.tsx +21 -1
- package/src/components/InputField.tsx +2 -10
- package/src/components/InspectorContainer.tsx +4 -2
- package/src/components/Message.tsx +5 -16
- package/src/components/OverlayToolbar.tsx +97 -0
- package/src/components/Popover.tsx +73 -107
- package/src/components/Progress.tsx +18 -18
- package/src/components/ScrollArea.tsx +66 -31
- package/src/components/ScrollableSidebar.tsx +1 -1
- package/src/components/SegmentedControl.tsx +166 -38
- package/src/components/SelectMenu.tsx +193 -101
- package/src/components/Slider.tsx +40 -38
- package/src/components/StackNavigator.tsx +1 -0
- package/src/components/Switch.tsx +4 -4
- package/src/components/TextArea.tsx +1 -1
- package/src/components/Toast.tsx +99 -26
- package/src/components/Toolbar.tsx +133 -24
- package/src/components/Tooltip.tsx +18 -8
- package/src/components/UserPointer.tsx +5 -3
- package/src/components/Virtualized.tsx +193 -14
- package/src/components/VisuallyHidden.tsx +20 -0
- package/src/components/__tests__/Virtualized.math.test.ts +426 -1
- package/src/components/__tests__/Virtualized.test.tsx +129 -1
- package/src/components/ai-assistant/AIAssistantLayout.tsx +11 -6
- package/src/components/internal/Menu.tsx +4 -0
- package/src/components/listView/ListViewEditableRowTitle.tsx +1 -1
- package/src/components/listView/ListViewRoot.tsx +5 -1
- package/src/components/resizablePanels/Panel.tsx +94 -0
- package/src/components/resizablePanels/PanelGroup.tsx +498 -0
- package/src/components/resizablePanels/PanelGroupContext.tsx +14 -0
- package/src/components/resizablePanels/PanelResizeHandle.tsx +61 -0
- package/src/components/resizablePanels/index.ts +7 -0
- package/src/components/resizablePanels/types.ts +65 -0
- package/src/components/workspace/DrawerWorkspaceLayout.tsx +22 -7
- package/src/components/workspace/PanelWorkspaceLayout.tsx +30 -84
- package/src/components/workspace/WorkspaceLayout.tsx +82 -76
- package/src/components/workspace/types.ts +6 -4
- package/src/contexts/DialogContext.tsx +15 -24
- package/src/emojis.ts +1 -0
- package/src/hooks/useTriggerToggle.ts +95 -0
- package/src/index.css +2 -0
- package/src/index.tsx +3 -2
- package/src/theme/proseTheme.ts +22 -0
- package/src/utils/mergeProps.ts +57 -0
- package/src/utils/skinTone.ts +90 -0
- package/tailwind.config.ts +6 -1
- package/tsup.config.ts +1 -1
- package/src/__tests__/workspaceLayout.test.ts +0 -281
- package/src/components/ScrollArea2.tsx +0 -76
- package/src/components/internal/MenuViewport.tsx +0 -178
- package/src/components/internal/SelectItem.tsx +0 -138
- package/src/components/workspace/panelStorage.ts +0 -216
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { ReactNode, RefObject } from "react";
|
|
2
|
+
|
|
3
|
+
export interface PanelGroupProps {
|
|
4
|
+
id?: string;
|
|
5
|
+
className?: string;
|
|
6
|
+
direction: "horizontal";
|
|
7
|
+
autoSaveId?: string;
|
|
8
|
+
onLayout?: (sizes: number[]) => void;
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
ref?: RefObject<ImperativePanelGroupHandle | null>;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface PanelProps {
|
|
14
|
+
id?: string;
|
|
15
|
+
order: number;
|
|
16
|
+
className?: string;
|
|
17
|
+
defaultSize?: number;
|
|
18
|
+
minSize?: number;
|
|
19
|
+
maxSize?: number;
|
|
20
|
+
collapsible?: boolean;
|
|
21
|
+
defaultCollapsed?: boolean;
|
|
22
|
+
children?: ReactNode;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface ImperativePanelHandle {
|
|
26
|
+
expand: () => void;
|
|
27
|
+
collapse: () => void;
|
|
28
|
+
isExpanded: () => boolean;
|
|
29
|
+
getSize: () => number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface ImperativePanelGroupHandle {
|
|
33
|
+
getLayout: () => number[];
|
|
34
|
+
setLayout: (sizes: number[]) => void;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface PanelResizeHandleProps {
|
|
38
|
+
className?: string;
|
|
39
|
+
disabled?: boolean;
|
|
40
|
+
/** The index of this handle (0 = between panels 0 and 1, 1 = between panels 1 and 2, etc.) */
|
|
41
|
+
index: number;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface PanelRegistration {
|
|
45
|
+
id: string;
|
|
46
|
+
order: number;
|
|
47
|
+
defaultSize?: number;
|
|
48
|
+
minSize?: number;
|
|
49
|
+
maxSize?: number;
|
|
50
|
+
collapsible?: boolean;
|
|
51
|
+
defaultCollapsed?: boolean;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface PanelGroupContextValue {
|
|
55
|
+
registerPanel: (panel: PanelRegistration) => void;
|
|
56
|
+
unregisterPanel: (id: string) => void;
|
|
57
|
+
getPanelSize: (id: string) => number;
|
|
58
|
+
setPanelSize: (id: string, size: number) => void;
|
|
59
|
+
getPanelIndex: (id: string) => number;
|
|
60
|
+
expandPanel: (id: string) => void;
|
|
61
|
+
collapsePanel: (id: string) => void;
|
|
62
|
+
isPanelExpanded: (id: string) => boolean;
|
|
63
|
+
startResize: (handleIndex: number, startX: number) => void;
|
|
64
|
+
containerWidth: number;
|
|
65
|
+
}
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
import { memoGeneric } from "@noya-app/react-utils";
|
|
4
4
|
import React, { useMemo, useRef, useState } from "react";
|
|
5
|
+
import { Button } from "../Button";
|
|
5
6
|
import { DividerVertical } from "../Divider";
|
|
6
7
|
import { Drawer } from "../Drawer";
|
|
7
8
|
import { isSelectableMenuItem, MenuItem } from "../internal/Menu";
|
|
8
9
|
import { EDITOR_PANEL_GROUP_ID, RIGHT_SIDEBAR_ID } from "./constants";
|
|
9
10
|
import { LayoutProps, PanelLayoutState, SidebarRef } from "./types";
|
|
10
11
|
import { VerticalTabMenu } from "./VerticalTabMenu";
|
|
11
|
-
import { Button } from "../Button";
|
|
12
12
|
|
|
13
13
|
export const DrawerWorkspaceLayout = memoGeneric(function DrawerWorkspaceLayout<
|
|
14
14
|
LeftTab extends string = string,
|
|
@@ -138,16 +138,29 @@ export const DrawerWorkspaceLayout = memoGeneric(function DrawerWorkspaceLayout<
|
|
|
138
138
|
}}
|
|
139
139
|
icon={allSelectableTabItems[0].icon}
|
|
140
140
|
tooltip={
|
|
141
|
-
allSelectableTabItems[0].tooltip ??
|
|
141
|
+
allSelectableTabItems[0].tooltip ??
|
|
142
|
+
allSelectableTabItems[0].title
|
|
142
143
|
}
|
|
143
144
|
active={(() => {
|
|
144
|
-
const value = allSelectableTabItems[0].value as
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
145
|
+
const value = allSelectableTabItems[0].value as
|
|
146
|
+
| LeftTab
|
|
147
|
+
| RightTab;
|
|
148
|
+
const isLeftItem = leftSelectableTabItems.some(
|
|
149
|
+
(i) => i.value === value
|
|
150
|
+
);
|
|
151
|
+
const isRightItem = rightSelectableTabItems.some(
|
|
152
|
+
(i) => i.value === value
|
|
153
|
+
);
|
|
154
|
+
return isLeftItem
|
|
155
|
+
? !leftSidebarCollapsed
|
|
156
|
+
: isRightItem
|
|
157
|
+
? !rightSidebarCollapsed
|
|
158
|
+
: false;
|
|
148
159
|
})()}
|
|
149
160
|
onClick={() => {
|
|
150
|
-
const value = allSelectableTabItems[0].value as
|
|
161
|
+
const value = allSelectableTabItems[0].value as
|
|
162
|
+
| LeftTab
|
|
163
|
+
| RightTab;
|
|
151
164
|
handleSelectTab(value);
|
|
152
165
|
}}
|
|
153
166
|
/>
|
|
@@ -159,6 +172,7 @@ export const DrawerWorkspaceLayout = memoGeneric(function DrawerWorkspaceLayout<
|
|
|
159
172
|
|
|
160
173
|
{leftPanel && (
|
|
161
174
|
<Drawer
|
|
175
|
+
modal={false}
|
|
162
176
|
ref={leftSidebarRef}
|
|
163
177
|
className="n-flex-1"
|
|
164
178
|
style={
|
|
@@ -185,6 +199,7 @@ export const DrawerWorkspaceLayout = memoGeneric(function DrawerWorkspaceLayout<
|
|
|
185
199
|
{rightPanel && (
|
|
186
200
|
<Drawer
|
|
187
201
|
id={RIGHT_SIDEBAR_ID}
|
|
202
|
+
modal={false}
|
|
188
203
|
ref={rightSidebarRef}
|
|
189
204
|
className="n-flex-1"
|
|
190
205
|
style={
|
|
@@ -1,18 +1,14 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
memoGeneric,
|
|
6
|
-
usePersistentStateObject,
|
|
7
|
-
} from "@noya-app/react-utils";
|
|
8
|
-
import React, { useCallback, useMemo, useRef } from "react";
|
|
3
|
+
import { memoGeneric } from "@noya-app/react-utils";
|
|
4
|
+
import React, { useCallback, useMemo, useRef, useState } from "react";
|
|
9
5
|
import {
|
|
10
6
|
ImperativePanelGroupHandle,
|
|
11
7
|
ImperativePanelHandle,
|
|
12
8
|
Panel,
|
|
13
9
|
PanelGroup,
|
|
14
10
|
PanelResizeHandle,
|
|
15
|
-
} from "
|
|
11
|
+
} from "../resizablePanels";
|
|
16
12
|
import { DividerVertical } from "../Divider";
|
|
17
13
|
import {
|
|
18
14
|
CONTENT_AREA_ID,
|
|
@@ -20,17 +16,7 @@ import {
|
|
|
20
16
|
LEFT_SIDEBAR_ID,
|
|
21
17
|
RIGHT_SIDEBAR_ID,
|
|
22
18
|
} 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";
|
|
19
|
+
import { LayoutProps } from "./types";
|
|
34
20
|
import { VerticalTabMenu } from "./VerticalTabMenu";
|
|
35
21
|
|
|
36
22
|
export const PanelWorkspaceLayout = memoGeneric(function PanelWorkspaceLayout<
|
|
@@ -42,7 +28,6 @@ export const PanelWorkspaceLayout = memoGeneric(function PanelWorkspaceLayout<
|
|
|
42
28
|
centerPanel,
|
|
43
29
|
leftSidebarOptions,
|
|
44
30
|
rightSidebarOptions,
|
|
45
|
-
centerPanelPercentage,
|
|
46
31
|
autoSavePrefix,
|
|
47
32
|
leftSidebarRef,
|
|
48
33
|
rightSidebarRef,
|
|
@@ -56,56 +41,35 @@ export const PanelWorkspaceLayout = memoGeneric(function PanelWorkspaceLayout<
|
|
|
56
41
|
}: LayoutProps<LeftTab, RightTab>) {
|
|
57
42
|
const panelGroupRef = useRef<ImperativePanelGroupHandle>(null);
|
|
58
43
|
|
|
59
|
-
const hasLeftPanel = !!leftPanel;
|
|
60
|
-
const hasRightPanel = !!rightPanel;
|
|
61
|
-
const hasCenterPanel = !!centerPanel;
|
|
62
|
-
|
|
63
44
|
const autoSaveId = useMemo(() => {
|
|
64
45
|
return autoSavePrefix
|
|
65
|
-
? `${autoSavePrefix}--
|
|
46
|
+
? `${autoSavePrefix}--v3--${EDITOR_PANEL_GROUP_ID}`
|
|
66
47
|
: Math.random().toString(36).substring(2, 15);
|
|
67
48
|
}, [autoSavePrefix]);
|
|
68
49
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
setInitialLayout({
|
|
78
|
-
storageKey,
|
|
79
|
-
propertyKey,
|
|
80
|
-
calculateLayout: () => {
|
|
81
|
-
return getInitialLayout({
|
|
82
|
-
layoutIds,
|
|
83
|
-
leftSidebarOptions,
|
|
84
|
-
rightSidebarOptions,
|
|
85
|
-
centerPanelPercentage,
|
|
86
|
-
hasLeftPanel,
|
|
87
|
-
hasRightPanel,
|
|
88
|
-
hasCenterPanel,
|
|
89
|
-
});
|
|
90
|
-
},
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
const [data, setData] = usePersistentStateObject<
|
|
94
|
-
WorkspaceLayoutState,
|
|
95
|
-
string
|
|
96
|
-
>(clientStorage, storageKey, {});
|
|
50
|
+
// Track collapsed state based on layout changes
|
|
51
|
+
const [leftSidebarCollapsed, setLeftSidebarCollapsed] = useState(
|
|
52
|
+
leftSidebarOptions.defaultCollapsed ?? false
|
|
53
|
+
);
|
|
54
|
+
const [rightSidebarCollapsed, setRightSidebarCollapsed] = useState(
|
|
55
|
+
rightSidebarOptions.defaultCollapsed ?? false
|
|
56
|
+
);
|
|
97
57
|
|
|
98
|
-
const
|
|
58
|
+
const handleLayoutChange = useCallback(
|
|
59
|
+
(sizes: number[]) => {
|
|
60
|
+
// Update collapsed state based on sizes
|
|
61
|
+
const leftIndex = leftPanel ? 0 : -1;
|
|
62
|
+
const rightIndex = rightPanel ? (leftPanel ? 2 : 1) : -1;
|
|
99
63
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
64
|
+
if (leftIndex >= 0) {
|
|
65
|
+
setLeftSidebarCollapsed(sizes[leftIndex] === 0);
|
|
66
|
+
}
|
|
67
|
+
if (rightIndex >= 0) {
|
|
68
|
+
setRightSidebarCollapsed(sizes[rightIndex] === 0);
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
[leftPanel, rightPanel]
|
|
72
|
+
);
|
|
109
73
|
|
|
110
74
|
const handleLeftTabChange = useCallback(
|
|
111
75
|
(value: LeftTab) => {
|
|
@@ -143,23 +107,6 @@ export const PanelWorkspaceLayout = memoGeneric(function PanelWorkspaceLayout<
|
|
|
143
107
|
[onChangeRightTab, rightSidebarRef, rightTabValue]
|
|
144
108
|
);
|
|
145
109
|
|
|
146
|
-
const handleLayoutChange = useCallback(
|
|
147
|
-
(layout: number[]) => {
|
|
148
|
-
setData((prev) => {
|
|
149
|
-
const newData = {
|
|
150
|
-
...prev,
|
|
151
|
-
[propertyKey]: {
|
|
152
|
-
layout: layout.map((size) => toPixelSize(size)),
|
|
153
|
-
expandToSizes: prev?.[propertyKey]?.expandToSizes ?? {},
|
|
154
|
-
},
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
return newData;
|
|
158
|
-
});
|
|
159
|
-
},
|
|
160
|
-
[setData, propertyKey]
|
|
161
|
-
);
|
|
162
|
-
|
|
163
110
|
const showLeftTabs =
|
|
164
111
|
!!leftSidebarOptions.showTabs &&
|
|
165
112
|
!!leftTabItems &&
|
|
@@ -173,7 +120,6 @@ export const PanelWorkspaceLayout = memoGeneric(function PanelWorkspaceLayout<
|
|
|
173
120
|
id={EDITOR_PANEL_GROUP_ID}
|
|
174
121
|
className="n-flex-1"
|
|
175
122
|
direction="horizontal"
|
|
176
|
-
storage={panelStorage}
|
|
177
123
|
autoSaveId={autoSaveId}
|
|
178
124
|
onLayout={handleLayoutChange}
|
|
179
125
|
>
|
|
@@ -205,24 +151,23 @@ export const PanelWorkspaceLayout = memoGeneric(function PanelWorkspaceLayout<
|
|
|
205
151
|
: undefined)
|
|
206
152
|
}
|
|
207
153
|
collapsible
|
|
154
|
+
defaultCollapsed={leftSidebarOptions.defaultCollapsed}
|
|
208
155
|
>
|
|
209
156
|
{leftSidebarCollapsed ? null : leftPanel}
|
|
210
157
|
</Panel>
|
|
211
|
-
<PanelResizeHandle className="n-cursor-col-resize n-w-px n-h-full n-bg-divider" />
|
|
158
|
+
<PanelResizeHandle index={0} className="n-cursor-col-resize n-w-px n-h-full n-bg-divider" />
|
|
212
159
|
</>
|
|
213
160
|
)}
|
|
214
161
|
<Panel
|
|
215
162
|
id={CONTENT_AREA_ID}
|
|
216
163
|
order={2}
|
|
217
|
-
defaultSize={centerPanelPercentage}
|
|
218
|
-
minSize={10}
|
|
219
164
|
className="n-flex n-relative"
|
|
220
165
|
>
|
|
221
166
|
{centerPanel}
|
|
222
167
|
</Panel>
|
|
223
168
|
{rightPanel && (
|
|
224
169
|
<>
|
|
225
|
-
<PanelResizeHandle className="n-cursor-col-resize n-w-px n-h-full n-bg-divider" />
|
|
170
|
+
<PanelResizeHandle index={1} className="n-cursor-col-resize n-w-px n-h-full n-bg-divider" />
|
|
226
171
|
<Panel
|
|
227
172
|
id={RIGHT_SIDEBAR_ID}
|
|
228
173
|
className="n-relative"
|
|
@@ -237,6 +182,7 @@ export const PanelWorkspaceLayout = memoGeneric(function PanelWorkspaceLayout<
|
|
|
237
182
|
: undefined)
|
|
238
183
|
}
|
|
239
184
|
collapsible
|
|
185
|
+
defaultCollapsed={rightSidebarOptions.defaultCollapsed}
|
|
240
186
|
>
|
|
241
187
|
{rightSidebarCollapsed ? null : rightPanel}
|
|
242
188
|
</Panel>
|
|
@@ -16,13 +16,14 @@ import React, {
|
|
|
16
16
|
} from "react";
|
|
17
17
|
import { cx } from "../../utils/classNames";
|
|
18
18
|
import { MenuItem } from "../internal/Menu";
|
|
19
|
+
import { OverlayLayout, OverlayToolbar } from "../OverlayToolbar";
|
|
19
20
|
import { DrawerWorkspaceLayout } from "./DrawerWorkspaceLayout";
|
|
20
21
|
import { PanelWorkspaceLayout } from "./PanelWorkspaceLayout";
|
|
21
22
|
import { renderPanelChildren } from "./renderPanelChildren";
|
|
22
23
|
import {
|
|
23
24
|
LayoutProps,
|
|
24
|
-
PercentageSidebarOptions,
|
|
25
25
|
RenderPanel,
|
|
26
|
+
SidebarOptions,
|
|
26
27
|
SidebarRef,
|
|
27
28
|
} from "./types";
|
|
28
29
|
import { WorkspaceSideProvider } from "./WorkspaceSideContext";
|
|
@@ -31,6 +32,8 @@ export type SideType = "auto" | "panel" | "drawer";
|
|
|
31
32
|
|
|
32
33
|
export type DetectSizeType = "container" | "window";
|
|
33
34
|
|
|
35
|
+
export type ToolbarVariant = "default" | "overlay";
|
|
36
|
+
|
|
34
37
|
export interface WorkspaceLayoutProps<
|
|
35
38
|
LeftTab extends string,
|
|
36
39
|
RightTab extends string,
|
|
@@ -54,6 +57,24 @@ export interface WorkspaceLayoutProps<
|
|
|
54
57
|
right?: RenderPanel<RightTab>;
|
|
55
58
|
rightOptions?: SideOptions;
|
|
56
59
|
toolbar?: React.ReactNode;
|
|
60
|
+
/**
|
|
61
|
+
* Toolbar variant - "default" renders above content, "overlay" renders floating panels
|
|
62
|
+
* @default "default"
|
|
63
|
+
*/
|
|
64
|
+
toolbarVariant?: ToolbarVariant;
|
|
65
|
+
/**
|
|
66
|
+
* Content for the left/bottom-center overlay panel (when toolbarVariant is "overlay")
|
|
67
|
+
*/
|
|
68
|
+
overlayToolbarLeft?: React.ReactNode;
|
|
69
|
+
/**
|
|
70
|
+
* Content for the right overlay panel (when toolbarVariant is "overlay")
|
|
71
|
+
*/
|
|
72
|
+
overlayToolbarRight?: React.ReactNode;
|
|
73
|
+
/**
|
|
74
|
+
* Layout configuration for overlay toolbar
|
|
75
|
+
* @default "bottomCenterTopRight"
|
|
76
|
+
*/
|
|
77
|
+
overlayLayout?: OverlayLayout;
|
|
57
78
|
sideType?: SideType;
|
|
58
79
|
sideTypeBreakpoint?: number;
|
|
59
80
|
detectSize?: DetectSizeType;
|
|
@@ -125,6 +146,10 @@ export const WorkspaceLayout = forwardRefGeneric(function WorkspaceLayout<
|
|
|
125
146
|
className,
|
|
126
147
|
style,
|
|
127
148
|
toolbar,
|
|
149
|
+
toolbarVariant = "default",
|
|
150
|
+
overlayToolbarLeft,
|
|
151
|
+
overlayToolbarRight,
|
|
152
|
+
overlayLayout,
|
|
128
153
|
children,
|
|
129
154
|
sideType = "auto",
|
|
130
155
|
sideTypeBreakpoint = 800,
|
|
@@ -169,46 +194,22 @@ export const WorkspaceLayout = forwardRefGeneric(function WorkspaceLayout<
|
|
|
169
194
|
? containerSize
|
|
170
195
|
: windowSize;
|
|
171
196
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
197
|
+
// Convert size to pixels (handles both number and percentage string)
|
|
198
|
+
function toPixels(size: number | string | undefined): number | undefined {
|
|
199
|
+
if (size === undefined) return undefined;
|
|
200
|
+
if (typeof size === "number") return size;
|
|
201
|
+
// Parse percentage string like "20%"
|
|
202
|
+
const percentage = parseFloat(size);
|
|
203
|
+
return Math.round((percentage / 100) * parentSize.width);
|
|
176
204
|
}
|
|
177
205
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
max: number | undefined
|
|
182
|
-
) {
|
|
183
|
-
let result = value;
|
|
184
|
-
if (min !== undefined) {
|
|
185
|
-
result = Math.max(result, min);
|
|
186
|
-
}
|
|
187
|
-
if (max !== undefined) {
|
|
188
|
-
result = Math.min(result, max);
|
|
189
|
-
}
|
|
190
|
-
return result;
|
|
191
|
-
}
|
|
206
|
+
const leftSidebarMinPixels = toPixels(leftMinSize);
|
|
207
|
+
const leftSidebarMaxPixels = toPixels(leftMaxSize);
|
|
208
|
+
const leftSidebarInitialPixels = toPixels(leftInitialSize) ?? 280;
|
|
192
209
|
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
const
|
|
196
|
-
rightMinSize !== undefined ? getPercentage(rightMinSize) : undefined;
|
|
197
|
-
const leftSidebarMaxPercentage =
|
|
198
|
-
leftMaxSize !== undefined ? getPercentage(leftMaxSize) : undefined;
|
|
199
|
-
const rightSidebarMaxPercentage =
|
|
200
|
-
rightMaxSize !== undefined ? getPercentage(rightMaxSize) : undefined;
|
|
201
|
-
|
|
202
|
-
const leftSidebarPercentage = clampPercentage(
|
|
203
|
-
getPercentage(leftInitialSize),
|
|
204
|
-
leftSidebarMinPercentage,
|
|
205
|
-
leftSidebarMaxPercentage
|
|
206
|
-
);
|
|
207
|
-
const rightSidebarPercentage = clampPercentage(
|
|
208
|
-
getPercentage(rightInitialSize),
|
|
209
|
-
rightSidebarMinPercentage,
|
|
210
|
-
rightSidebarMaxPercentage
|
|
211
|
-
);
|
|
210
|
+
const rightSidebarMinPixels = toPixels(rightMinSize);
|
|
211
|
+
const rightSidebarMaxPixels = toPixels(rightMaxSize);
|
|
212
|
+
const rightSidebarInitialPixels = toPixels(rightInitialSize) ?? 280;
|
|
212
213
|
|
|
213
214
|
const leftSidebarRef = useRef<SidebarRef>(null);
|
|
214
215
|
const rightSidebarRef = useRef<SidebarRef>(null);
|
|
@@ -288,11 +289,6 @@ export const WorkspaceLayout = forwardRefGeneric(function WorkspaceLayout<
|
|
|
288
289
|
},
|
|
289
290
|
});
|
|
290
291
|
|
|
291
|
-
const centerPanelPercentage =
|
|
292
|
-
100 -
|
|
293
|
-
(left ? leftSidebarPercentage : 0) -
|
|
294
|
-
(right ? rightSidebarPercentage : 0);
|
|
295
|
-
|
|
296
292
|
const isDrawerActive =
|
|
297
293
|
sideType === "drawer" ||
|
|
298
294
|
(sideType === "auto" && parentSize.width <= sideTypeBreakpoint);
|
|
@@ -365,38 +361,38 @@ export const WorkspaceLayout = forwardRefGeneric(function WorkspaceLayout<
|
|
|
365
361
|
<PanelInner className="n-bg-canvas-background">{children}</PanelInner>
|
|
366
362
|
);
|
|
367
363
|
|
|
368
|
-
const leftSidebarOptions:
|
|
364
|
+
const leftSidebarOptions: SidebarOptions = useMemo(
|
|
369
365
|
() => ({
|
|
370
|
-
minSize:
|
|
371
|
-
maxSize:
|
|
372
|
-
initialSize:
|
|
366
|
+
minSize: leftSidebarMinPixels,
|
|
367
|
+
maxSize: leftSidebarMaxPixels,
|
|
368
|
+
initialSize: leftSidebarInitialPixels,
|
|
373
369
|
resizable: leftResizable,
|
|
374
370
|
defaultCollapsed: leftDefaultCollapsed,
|
|
375
371
|
showTabs: leftShowTabs,
|
|
376
372
|
}),
|
|
377
373
|
[
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
374
|
+
leftSidebarMinPixels,
|
|
375
|
+
leftSidebarMaxPixels,
|
|
376
|
+
leftSidebarInitialPixels,
|
|
381
377
|
leftResizable,
|
|
382
378
|
leftDefaultCollapsed,
|
|
383
379
|
leftShowTabs,
|
|
384
380
|
]
|
|
385
381
|
);
|
|
386
382
|
|
|
387
|
-
const rightSidebarOptions:
|
|
383
|
+
const rightSidebarOptions: SidebarOptions = useMemo(
|
|
388
384
|
() => ({
|
|
389
|
-
minSize:
|
|
390
|
-
maxSize:
|
|
391
|
-
initialSize:
|
|
385
|
+
minSize: rightSidebarMinPixels,
|
|
386
|
+
maxSize: rightSidebarMaxPixels,
|
|
387
|
+
initialSize: rightSidebarInitialPixels,
|
|
392
388
|
resizable: rightResizable,
|
|
393
389
|
defaultCollapsed: rightDefaultCollapsed,
|
|
394
390
|
showTabs: rightShowTabs,
|
|
395
391
|
}),
|
|
396
392
|
[
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
393
|
+
rightSidebarMinPixels,
|
|
394
|
+
rightSidebarMaxPixels,
|
|
395
|
+
rightSidebarInitialPixels,
|
|
400
396
|
rightResizable,
|
|
401
397
|
rightDefaultCollapsed,
|
|
402
398
|
rightShowTabs,
|
|
@@ -422,6 +418,8 @@ export const WorkspaceLayout = forwardRefGeneric(function WorkspaceLayout<
|
|
|
422
418
|
const readyToRender =
|
|
423
419
|
detectSize === "window" || (containerSize && containerSize.width > 0);
|
|
424
420
|
|
|
421
|
+
const isOverlay = toolbarVariant === "overlay";
|
|
422
|
+
|
|
425
423
|
return (
|
|
426
424
|
<div
|
|
427
425
|
ref={containerRef}
|
|
@@ -433,27 +431,35 @@ export const WorkspaceLayout = forwardRefGeneric(function WorkspaceLayout<
|
|
|
433
431
|
style={style}
|
|
434
432
|
data-theme={theme}
|
|
435
433
|
>
|
|
436
|
-
{toolbar}
|
|
434
|
+
{!isOverlay && toolbar}
|
|
437
435
|
<div className="n-flex n-flex-row n-flex-1 n-relative">
|
|
438
436
|
{readyToRender && (
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
437
|
+
<>
|
|
438
|
+
<LayoutComponent
|
|
439
|
+
leftPanel={leftPanel}
|
|
440
|
+
rightPanel={rightPanel}
|
|
441
|
+
centerPanel={centerPanel}
|
|
442
|
+
leftTabItems={leftTabItems}
|
|
443
|
+
leftTabValue={leftTabValue}
|
|
444
|
+
onChangeLeftTab={setLeftTabValue}
|
|
445
|
+
rightTabItems={rightTabItems}
|
|
446
|
+
rightTabValue={rightTabValue}
|
|
447
|
+
onChangeRightTab={setRightTabValue}
|
|
448
|
+
leftSidebarOptions={leftSidebarOptions}
|
|
449
|
+
rightSidebarOptions={rightSidebarOptions}
|
|
450
|
+
autoSavePrefix={autoSavePrefix}
|
|
451
|
+
leftSidebarRef={leftSidebarRef}
|
|
452
|
+
rightSidebarRef={rightSidebarRef}
|
|
453
|
+
compactDrawerMenu={compactDrawerMenu}
|
|
454
|
+
/>
|
|
455
|
+
{isOverlay && (
|
|
456
|
+
<OverlayToolbar
|
|
457
|
+
left={overlayToolbarLeft}
|
|
458
|
+
right={overlayToolbarRight}
|
|
459
|
+
overlayLayout={overlayLayout}
|
|
460
|
+
/>
|
|
461
|
+
)}
|
|
462
|
+
</>
|
|
457
463
|
)}
|
|
458
464
|
</div>
|
|
459
465
|
</div>
|
|
@@ -7,7 +7,10 @@ export type SidebarRef = {
|
|
|
7
7
|
isExpanded: () => boolean;
|
|
8
8
|
};
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Sidebar options with pixel-based sizing.
|
|
12
|
+
*/
|
|
13
|
+
export type SidebarOptions = {
|
|
11
14
|
minSize?: number;
|
|
12
15
|
maxSize?: number;
|
|
13
16
|
initialSize?: number;
|
|
@@ -45,9 +48,8 @@ export type LayoutProps<
|
|
|
45
48
|
rightTabValue?: RightTab;
|
|
46
49
|
onChangeRightTab?: (value: RightTab) => void;
|
|
47
50
|
centerPanel: React.ReactNode;
|
|
48
|
-
leftSidebarOptions:
|
|
49
|
-
rightSidebarOptions:
|
|
50
|
-
centerPanelPercentage: number;
|
|
51
|
+
leftSidebarOptions: SidebarOptions;
|
|
52
|
+
rightSidebarOptions: SidebarOptions;
|
|
51
53
|
autoSavePrefix?: string;
|
|
52
54
|
leftSidebarRef: React.RefObject<SidebarRef | null>;
|
|
53
55
|
rightSidebarRef: React.RefObject<SidebarRef | null>;
|
|
@@ -231,6 +231,21 @@ export const DialogProvider = function DialogProvider({
|
|
|
231
231
|
const confirmButtonRef = useRef<HTMLButtonElement>(null);
|
|
232
232
|
const dialogRef = useRef<IDialog>(null);
|
|
233
233
|
|
|
234
|
+
// Handle auto-focus when dialog opens
|
|
235
|
+
React.useEffect(() => {
|
|
236
|
+
if (!contents) return;
|
|
237
|
+
|
|
238
|
+
// Use requestAnimationFrame to ensure the dialog is rendered
|
|
239
|
+
requestAnimationFrame(() => {
|
|
240
|
+
if (contents.type === "input") {
|
|
241
|
+
inputRef.current?.focus();
|
|
242
|
+
inputRef.current?.setSelectionRange(0, inputRef.current.value.length);
|
|
243
|
+
} else if (contents.type === "confirmation") {
|
|
244
|
+
confirmButtonRef.current?.focus();
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
}, [contents]);
|
|
248
|
+
|
|
234
249
|
const containsElement = useCallback((element: HTMLElement) => {
|
|
235
250
|
if (!dialogRef.current) return false;
|
|
236
251
|
|
|
@@ -267,30 +282,6 @@ export const DialogProvider = function DialogProvider({
|
|
|
267
282
|
},
|
|
268
283
|
[close]
|
|
269
284
|
)}
|
|
270
|
-
onOpenAutoFocus={useCallback(
|
|
271
|
-
(event: Event) => {
|
|
272
|
-
if (!contents) return;
|
|
273
|
-
|
|
274
|
-
if (contents.type === "input") {
|
|
275
|
-
event.stopPropagation();
|
|
276
|
-
event.preventDefault();
|
|
277
|
-
inputRef.current?.focus();
|
|
278
|
-
inputRef.current?.setSelectionRange(
|
|
279
|
-
0,
|
|
280
|
-
inputRef.current.value.length
|
|
281
|
-
);
|
|
282
|
-
return;
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
if (contents.type === "confirmation") {
|
|
286
|
-
event.stopPropagation();
|
|
287
|
-
event.preventDefault();
|
|
288
|
-
confirmButtonRef.current?.focus();
|
|
289
|
-
return;
|
|
290
|
-
}
|
|
291
|
-
},
|
|
292
|
-
[contents]
|
|
293
|
-
)}
|
|
294
285
|
>
|
|
295
286
|
{contents?.type === "confirmation" ? (
|
|
296
287
|
<div className="n-flex n-flex-1 n-flex-row n-items-center">
|
package/src/emojis.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { gemoji as emojis } from "gemoji";
|