@noya-app/noya-designsystem 0.1.64 → 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 +12 -0
- package/dist/index.css +1 -1
- package/dist/index.d.mts +501 -228
- package/dist/index.d.ts +501 -228
- package/dist/index.js +6738 -2571
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +6697 -2499
- package/dist/index.mjs.map +1 -1
- package/package.json +6 -6
- package/src/components/ActivityIndicator.tsx +9 -4
- package/src/components/ActivityLog.tsx +197 -0
- package/src/components/AnimatePresence.tsx +37 -22
- package/src/components/Avatar.tsx +42 -25
- package/src/components/Banner.tsx +57 -11
- package/src/components/BaseToolbar.tsx +29 -7
- package/src/components/Breadcrumbs.tsx +2 -2
- package/src/components/Button.tsx +23 -24
- package/src/components/Checkbox.tsx +6 -35
- package/src/components/Chip.tsx +45 -33
- package/src/components/Collection.tsx +16 -11
- package/src/components/ColorSwatch.tsx +3 -3
- package/src/components/ColorSwatchControl.tsx +2 -2
- package/src/components/Combobox.tsx +6 -6
- package/src/components/ComboboxMenu.tsx +6 -5
- package/src/components/CommandPalette.tsx +1 -1
- package/src/components/Dialog.tsx +6 -12
- package/src/components/Divider.tsx +8 -8
- package/src/components/DraggableMenuButton.tsx +9 -5
- package/src/components/Drawer.tsx +5 -5
- package/src/components/DropdownMenu.tsx +1 -1
- package/src/components/EditableText.tsx +2 -2
- package/src/components/Fade.tsx +13 -13
- package/src/components/FileUploadIndicator.tsx +11 -11
- package/src/components/FloatingWindow.tsx +2 -2
- package/src/components/Grid.tsx +18 -11
- package/src/components/GridView.tsx +32 -25
- package/src/components/IVirtualizedList.tsx +5 -0
- package/src/components/Icons.tsx +24 -4
- package/src/components/InputField.tsx +19 -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 +3 -3
- package/src/components/LabeledField.tsx +6 -6
- package/src/components/List.tsx +103 -45
- package/src/components/ListMenu.tsx +91 -0
- package/src/components/ListNavigator.tsx +106 -0
- package/src/components/ListView.tsx +20 -1158
- package/src/components/MediaThumbnail.tsx +56 -15
- package/src/components/Message.tsx +5 -5
- package/src/components/Navigator.tsx +461 -0
- package/src/components/NoyaLogo.tsx +1 -1
- package/src/components/Popover.tsx +9 -5
- package/src/components/Progress.tsx +19 -9
- package/src/components/ResizableContainer.tsx +187 -0
- package/src/components/RingProgress.tsx +128 -0
- package/src/components/ScrollArea.tsx +4 -4
- package/src/components/ScrollableSidebar.tsx +10 -0
- package/src/components/SearchCompletionMenu.tsx +3 -3
- package/src/components/Section.tsx +107 -57
- package/src/components/SegmentedControl.tsx +29 -29
- package/src/components/SelectMenu.tsx +13 -20
- package/src/components/SelectionToolbar.tsx +4 -3
- package/src/components/Slider.tsx +9 -9
- 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 +4 -4
- package/src/components/Tabs.tsx +3 -3
- package/src/components/Text.tsx +23 -13
- package/src/components/TextArea.tsx +3 -3
- package/src/components/Toast.tsx +4 -4
- package/src/components/Toolbar.tsx +50 -9
- package/src/components/ToolbarDrawer.tsx +2 -2
- package/src/components/Tooltip.tsx +1 -1
- package/src/components/TreeView.tsx +11 -4
- package/src/components/UserPointer.tsx +4 -4
- package/src/components/ai-assistant/AIAssistantLayout.tsx +8 -8
- package/src/components/blocks/ImageBlockComponent.tsx +13 -7
- package/src/components/connected-users-menu/ConnectedUsersMenuLayout.tsx +4 -4
- package/src/components/file-explorer/FileExplorerLayout.tsx +20 -8
- package/src/components/internal/Checkmark.tsx +1 -1
- package/src/components/internal/Menu.tsx +22 -18
- package/src/components/internal/MenuViewport.tsx +13 -6
- package/src/components/internal/SelectItem.tsx +3 -3
- package/src/components/internal/TextInput.tsx +5 -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 +2 -1
- package/src/components/sorting/SharedDragProvider.tsx +91 -9
- package/src/components/sorting/Sortable.tsx +71 -17
- package/src/components/workspace/DrawerWorkspaceLayout.tsx +5 -5
- package/src/components/workspace/PanelWorkspaceLayout.tsx +65 -49
- package/src/components/workspace/VerticalTabMenu.tsx +25 -15
- package/src/components/workspace/WorkspaceLayout.tsx +30 -21
- package/src/contexts/DialogContext.tsx +17 -5
- package/src/hooks/useIndent.ts +3 -8
- package/src/index.css +24 -10
- package/src/index.tsx +10 -5
- package/src/utils/classNames.ts +52 -6
- package/src/utils/editableBlockStyles.ts +2 -2
- package/src/utils/formatByteSize.ts +1 -0
- package/src/utils/inputs.ts +8 -6
- package/src/utils/sketchColor.ts +0 -34
- package/tailwind.config.ts +1 -0
- package/src/components/FillInputField.tsx +0 -37
- package/src/components/FillPreviewBackground.tsx +0 -134
- package/src/components/GradientPicker.tsx +0 -90
- package/src/utils/getGradientBackground.tsx +0 -31
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
4
|
Active,
|
|
5
|
+
ClientRect,
|
|
5
6
|
closestCenter,
|
|
6
7
|
CollisionDetection,
|
|
7
8
|
DndContext,
|
|
@@ -15,7 +16,12 @@ import {
|
|
|
15
16
|
useSensor,
|
|
16
17
|
useSensors,
|
|
17
18
|
} from "@dnd-kit/core";
|
|
18
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
Insets,
|
|
21
|
+
Point,
|
|
22
|
+
rectContainsPoint,
|
|
23
|
+
unionRects,
|
|
24
|
+
} from "@noya-app/noya-geometry";
|
|
19
25
|
import { windowsOf } from "@noya-app/noya-utils";
|
|
20
26
|
import { useIsomorphicLayoutEffect } from "@noya-app/react-utils";
|
|
21
27
|
import * as React from "react";
|
|
@@ -45,6 +51,7 @@ export type SharedDragProviderProps = {
|
|
|
45
51
|
acceptsDrop?: AcceptsDrop;
|
|
46
52
|
onMoveItem?: MoveDragItemHandler;
|
|
47
53
|
sharedDragProps?: SharedDragProps;
|
|
54
|
+
itemHitSlop?: Insets;
|
|
48
55
|
};
|
|
49
56
|
|
|
50
57
|
export function SharedDragProvider({
|
|
@@ -55,6 +62,7 @@ export function SharedDragProvider({
|
|
|
55
62
|
dragRegistrationContext: DragRegistrationContext,
|
|
56
63
|
activeDragContext: ActiveDragContext,
|
|
57
64
|
},
|
|
65
|
+
itemHitSlop,
|
|
58
66
|
}: SharedDragProviderProps) {
|
|
59
67
|
const sensors = useSensors(
|
|
60
68
|
useSensor(PointerSensor, {
|
|
@@ -216,8 +224,8 @@ export function SharedDragProvider({
|
|
|
216
224
|
);
|
|
217
225
|
|
|
218
226
|
const collisionDetection = useMemo(() => {
|
|
219
|
-
return getItemFirstCollisionDetection(registeredLists);
|
|
220
|
-
}, [registeredLists]);
|
|
227
|
+
return getItemFirstCollisionDetection(registeredLists, itemHitSlop);
|
|
228
|
+
}, [registeredLists, itemHitSlop]);
|
|
221
229
|
|
|
222
230
|
return (
|
|
223
231
|
<AnyDragContext.Provider value={true}>
|
|
@@ -279,9 +287,18 @@ export function withDragProvider<T extends object>(
|
|
|
279
287
|
|
|
280
288
|
// Custom collision detection that prioritizes items over containers
|
|
281
289
|
export const getItemFirstCollisionDetection =
|
|
282
|
-
(
|
|
290
|
+
(
|
|
291
|
+
registeredLists: Map<string, RegisteredList>,
|
|
292
|
+
itemHitSlop: Insets | undefined
|
|
293
|
+
): CollisionDetection =>
|
|
283
294
|
(parameters) => {
|
|
284
|
-
const
|
|
295
|
+
const parametersWithHitSlop = getCollisionParametersWithHitSlop(
|
|
296
|
+
registeredLists,
|
|
297
|
+
parameters,
|
|
298
|
+
itemHitSlop
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
const pointerCollisions = pointerWithin(parametersWithHitSlop);
|
|
285
302
|
|
|
286
303
|
if (pointerCollisions.length > 0) {
|
|
287
304
|
const itemCollisions = pointerCollisions.filter((collision) => {
|
|
@@ -300,11 +317,11 @@ export const getItemFirstCollisionDetection =
|
|
|
300
317
|
}
|
|
301
318
|
|
|
302
319
|
const listCollision = pointerCollisions.at(0);
|
|
303
|
-
const nearestCenters = closestCenter(
|
|
320
|
+
const nearestCenters = closestCenter(parametersWithHitSlop);
|
|
304
321
|
|
|
305
322
|
// Handle a pointer between items by checking if the pointer is within
|
|
306
323
|
// a window of two items.
|
|
307
|
-
if (
|
|
324
|
+
if (parametersWithHitSlop.pointerCoordinates && listCollision) {
|
|
308
325
|
const list = registeredLists.get(listCollision.id as string);
|
|
309
326
|
|
|
310
327
|
if (list) {
|
|
@@ -312,7 +329,7 @@ export const getItemFirstCollisionDetection =
|
|
|
312
329
|
|
|
313
330
|
for (const pair of pairs) {
|
|
314
331
|
const clientRects = pair.map(
|
|
315
|
-
(key) =>
|
|
332
|
+
(key) => parametersWithHitSlop.droppableRects.get(key)!
|
|
316
333
|
);
|
|
317
334
|
|
|
318
335
|
const merged = unionRects(
|
|
@@ -324,7 +341,9 @@ export const getItemFirstCollisionDetection =
|
|
|
324
341
|
}))
|
|
325
342
|
);
|
|
326
343
|
|
|
327
|
-
if (
|
|
344
|
+
if (
|
|
345
|
+
rectContainsPoint(merged, parametersWithHitSlop.pointerCoordinates)
|
|
346
|
+
) {
|
|
328
347
|
return nearestCenters.filter((center) =>
|
|
329
348
|
pair.some((id) => id === center.id)
|
|
330
349
|
);
|
|
@@ -337,6 +356,69 @@ export const getItemFirstCollisionDetection =
|
|
|
337
356
|
return pointerCollisions;
|
|
338
357
|
};
|
|
339
358
|
|
|
359
|
+
type CollisionDetectionParameters = Parameters<CollisionDetection>[0];
|
|
360
|
+
|
|
361
|
+
function getCollisionParametersWithHitSlop(
|
|
362
|
+
registeredLists: Map<string, RegisteredList>,
|
|
363
|
+
parameters: CollisionDetectionParameters,
|
|
364
|
+
defaultHitSlop: Insets | undefined
|
|
365
|
+
): CollisionDetectionParameters {
|
|
366
|
+
const adjustedDroppableRects = createDroppableRectsWithHitSlop(
|
|
367
|
+
registeredLists,
|
|
368
|
+
parameters.droppableRects,
|
|
369
|
+
defaultHitSlop
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
if (!adjustedDroppableRects) {
|
|
373
|
+
return parameters;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
return {
|
|
377
|
+
...parameters,
|
|
378
|
+
droppableRects: adjustedDroppableRects,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
function createDroppableRectsWithHitSlop(
|
|
383
|
+
registeredLists: Map<string, RegisteredList>,
|
|
384
|
+
droppableRects: CollisionDetectionParameters["droppableRects"],
|
|
385
|
+
defaultHitSlop: Insets | undefined
|
|
386
|
+
): Map<string | number, ClientRect> | undefined {
|
|
387
|
+
let adjustedRects: Map<string | number, ClientRect> | undefined;
|
|
388
|
+
|
|
389
|
+
for (const [, list] of registeredLists) {
|
|
390
|
+
const hitSlop = list.itemHitSlop ?? defaultHitSlop;
|
|
391
|
+
|
|
392
|
+
if (!hitSlop) continue;
|
|
393
|
+
|
|
394
|
+
for (const key of list.keys) {
|
|
395
|
+
const rect = droppableRects.get(key);
|
|
396
|
+
|
|
397
|
+
if (!rect) continue;
|
|
398
|
+
|
|
399
|
+
if (!adjustedRects) {
|
|
400
|
+
adjustedRects = new Map(droppableRects);
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
adjustedRects.set(key, expandRectByInsets(rect, hitSlop));
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
return adjustedRects;
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
function expandRectByInsets(rect: ClientRect, hitSlop: Insets): ClientRect {
|
|
411
|
+
return {
|
|
412
|
+
...rect,
|
|
413
|
+
left: rect.left - hitSlop.left,
|
|
414
|
+
right: rect.right + hitSlop.right,
|
|
415
|
+
top: rect.top - hitSlop.top,
|
|
416
|
+
bottom: rect.bottom + hitSlop.bottom,
|
|
417
|
+
width: rect.width + hitSlop.left + hitSlop.right,
|
|
418
|
+
height: rect.height + hitSlop.top + hitSlop.bottom,
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
|
|
340
422
|
function findDropTarget({
|
|
341
423
|
activationPoint,
|
|
342
424
|
delta,
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
useSortable,
|
|
8
8
|
verticalListSortingStrategy,
|
|
9
9
|
} from "@dnd-kit/sortable";
|
|
10
|
+
import { Insets } from "@noya-app/noya-geometry";
|
|
10
11
|
import * as React from "react";
|
|
11
12
|
import {
|
|
12
13
|
ActiveDragContext,
|
|
@@ -30,12 +31,21 @@ import {
|
|
|
30
31
|
|
|
31
32
|
type UseSortableReturnType = ReturnType<typeof useSortable>;
|
|
32
33
|
|
|
33
|
-
type ItemChildrenProps<T> = {
|
|
34
|
-
ref: React.
|
|
35
|
-
relativeDropPosition?: RelativeDropPosition;
|
|
34
|
+
export type ItemChildrenProps<T> = {
|
|
35
|
+
ref: React.RefCallback<T>;
|
|
36
36
|
style?: React.CSSProperties;
|
|
37
|
+
onPointerDown?: React.PointerEventHandler;
|
|
37
38
|
} & UseSortableReturnType["attributes"];
|
|
38
39
|
|
|
40
|
+
export type ItemChildrenExtraProps = {
|
|
41
|
+
isDragging: boolean;
|
|
42
|
+
isOverlay: boolean;
|
|
43
|
+
relativeDropPosition: RelativeDropPosition | undefined;
|
|
44
|
+
setActivatorNodeRef: React.RefCallback<HTMLElement>;
|
|
45
|
+
setDraggableNodeRef: React.RefCallback<HTMLElement>;
|
|
46
|
+
setDroppableNodeRef: React.RefCallback<HTMLElement>;
|
|
47
|
+
};
|
|
48
|
+
|
|
39
49
|
// Context for drop indicators within a sortable list
|
|
40
50
|
interface SortableItemContextProps {
|
|
41
51
|
acceptsDrop: DropValidator;
|
|
@@ -117,11 +127,13 @@ interface RootProps {
|
|
|
117
127
|
children?: React.ReactNode;
|
|
118
128
|
renderOverlay?: (index: number) => React.ReactNode;
|
|
119
129
|
onMoveItem?: MoveDragItemHandler;
|
|
130
|
+
onIsDraggingChange?: (isDragging: boolean) => void;
|
|
120
131
|
acceptsFromList?: AcceptsFromList;
|
|
121
132
|
acceptsDrop?: DropValidator;
|
|
122
133
|
getDropTargetParentIndex?: (index: number) => number | undefined;
|
|
123
134
|
sharedDragProps?: SharedDragProps;
|
|
124
135
|
containerRef?: React.RefObject<HTMLElement | null>;
|
|
136
|
+
itemHitSlop?: Insets;
|
|
125
137
|
}
|
|
126
138
|
|
|
127
139
|
function SortableItem<TElement extends HTMLElement>({
|
|
@@ -131,14 +143,26 @@ function SortableItem<TElement extends HTMLElement>({
|
|
|
131
143
|
}: {
|
|
132
144
|
id: UniqueIdentifier;
|
|
133
145
|
disabled?: boolean;
|
|
134
|
-
children: (
|
|
146
|
+
children: (
|
|
147
|
+
props: ItemChildrenProps<TElement>,
|
|
148
|
+
extraProps: Omit<ItemChildrenExtraProps, "isOverlay">
|
|
149
|
+
) => React.ReactNode;
|
|
135
150
|
}) {
|
|
136
151
|
const { acceptsDrop, listId, getDropTargetParentIndex } =
|
|
137
152
|
React.useContext(SortableItemContext);
|
|
138
153
|
|
|
139
154
|
const dragItemKey = createDragItemKey(listId, id);
|
|
140
155
|
|
|
141
|
-
const {
|
|
156
|
+
const {
|
|
157
|
+
attributes,
|
|
158
|
+
listeners,
|
|
159
|
+
setNodeRef,
|
|
160
|
+
isDragging,
|
|
161
|
+
index,
|
|
162
|
+
setActivatorNodeRef,
|
|
163
|
+
setDraggableNodeRef,
|
|
164
|
+
setDroppableNodeRef,
|
|
165
|
+
} = useSortable({
|
|
142
166
|
id: dragItemKey,
|
|
143
167
|
disabled,
|
|
144
168
|
});
|
|
@@ -156,21 +180,28 @@ function SortableItem<TElement extends HTMLElement>({
|
|
|
156
180
|
getDropTargetParentIndex,
|
|
157
181
|
});
|
|
158
182
|
|
|
159
|
-
return children(
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
opacity: isDragging ? 0.5 : 1,
|
|
183
|
+
return children(
|
|
184
|
+
{
|
|
185
|
+
ref,
|
|
186
|
+
...attributes,
|
|
187
|
+
...listeners,
|
|
188
|
+
style: { opacity: isDragging ? 0.5 : 1 },
|
|
166
189
|
},
|
|
167
|
-
|
|
190
|
+
{
|
|
191
|
+
isDragging,
|
|
192
|
+
setActivatorNodeRef,
|
|
193
|
+
setDraggableNodeRef,
|
|
194
|
+
setDroppableNodeRef,
|
|
195
|
+
relativeDropPosition,
|
|
196
|
+
}
|
|
197
|
+
);
|
|
168
198
|
}
|
|
169
199
|
|
|
170
200
|
function SortableRoot_({
|
|
171
201
|
id: idProp,
|
|
172
202
|
keys: keysProp,
|
|
173
203
|
onMoveItem,
|
|
204
|
+
onIsDraggingChange,
|
|
174
205
|
renderOverlay,
|
|
175
206
|
acceptsFromList,
|
|
176
207
|
acceptsDrop = defaultAcceptsDrop,
|
|
@@ -179,6 +210,7 @@ function SortableRoot_({
|
|
|
179
210
|
getDropTargetParentIndex,
|
|
180
211
|
sharedDragProps,
|
|
181
212
|
containerRef,
|
|
213
|
+
itemHitSlop,
|
|
182
214
|
}: RootProps) {
|
|
183
215
|
const defaultId = React.useId();
|
|
184
216
|
const id = idProp ?? defaultId;
|
|
@@ -234,6 +266,7 @@ function SortableRoot_({
|
|
|
234
266
|
|
|
235
267
|
return relativeDropPosition;
|
|
236
268
|
},
|
|
269
|
+
itemHitSlop,
|
|
237
270
|
};
|
|
238
271
|
|
|
239
272
|
registerList(listConfig);
|
|
@@ -251,6 +284,7 @@ function SortableRoot_({
|
|
|
251
284
|
registerList,
|
|
252
285
|
unregisterList,
|
|
253
286
|
keys,
|
|
287
|
+
itemHitSlop,
|
|
254
288
|
]);
|
|
255
289
|
|
|
256
290
|
const contextValue: SortableItemContextProps = React.useMemo(
|
|
@@ -265,6 +299,16 @@ function SortableRoot_({
|
|
|
265
299
|
[keys, acceptsDrop, id, getDropTargetParentIndex, sharedDragProps]
|
|
266
300
|
);
|
|
267
301
|
|
|
302
|
+
// Notify drag state changes to consumers if requested
|
|
303
|
+
const activeDragContext =
|
|
304
|
+
sharedDragProps?.activeDragContext ?? ActiveDragContext;
|
|
305
|
+
const dragState = React.useContext(activeDragContext);
|
|
306
|
+
const isDragging = !!dragState?.source;
|
|
307
|
+
|
|
308
|
+
React.useEffect(() => {
|
|
309
|
+
onIsDraggingChange?.(isDragging);
|
|
310
|
+
}, [isDragging, onIsDraggingChange]);
|
|
311
|
+
|
|
268
312
|
// Set the droppable ref after every render.
|
|
269
313
|
// Since we don't render the dom node internally, we aggressively set it
|
|
270
314
|
// after every render to make sure we are using the latest.
|
|
@@ -300,7 +344,7 @@ export interface SortableProps<TItem, TElement extends HTMLElement>
|
|
|
300
344
|
renderItem: (
|
|
301
345
|
item: TItem,
|
|
302
346
|
props: ItemChildrenProps<TElement>,
|
|
303
|
-
|
|
347
|
+
extraProps: { isOverlay: boolean } & ItemChildrenExtraProps
|
|
304
348
|
) => React.ReactNode;
|
|
305
349
|
}
|
|
306
350
|
|
|
@@ -330,7 +374,14 @@ const Sortable_ = function Sortable_<TItem, TElement extends HTMLElement>({
|
|
|
330
374
|
"aria-describedby": "Item being dragged",
|
|
331
375
|
role: "button",
|
|
332
376
|
},
|
|
333
|
-
{
|
|
377
|
+
{
|
|
378
|
+
isOverlay: true,
|
|
379
|
+
setActivatorNodeRef: () => {},
|
|
380
|
+
setDraggableNodeRef: () => {},
|
|
381
|
+
setDroppableNodeRef: () => {},
|
|
382
|
+
relativeDropPosition: undefined,
|
|
383
|
+
isDragging: true,
|
|
384
|
+
}
|
|
334
385
|
);
|
|
335
386
|
},
|
|
336
387
|
[renderItem, items]
|
|
@@ -344,8 +395,11 @@ const Sortable_ = function Sortable_<TItem, TElement extends HTMLElement>({
|
|
|
344
395
|
>
|
|
345
396
|
{keys.map((key, index) => (
|
|
346
397
|
<SortableItem<TElement> key={key} id={key}>
|
|
347
|
-
{(props) => {
|
|
348
|
-
return renderItem(items[index], props, {
|
|
398
|
+
{(props, extraProps) => {
|
|
399
|
+
return renderItem(items[index], props, {
|
|
400
|
+
isOverlay: false,
|
|
401
|
+
...extraProps,
|
|
402
|
+
});
|
|
349
403
|
}}
|
|
350
404
|
</SortableItem>
|
|
351
405
|
))}
|
|
@@ -68,7 +68,7 @@ export const DrawerWorkspaceLayout = memoGeneric(function DrawerWorkspaceLayout<
|
|
|
68
68
|
<div
|
|
69
69
|
ref={portalContainer}
|
|
70
70
|
id={EDITOR_PANEL_GROUP_ID}
|
|
71
|
-
className="flex flex-1 relative focus:outline-none"
|
|
71
|
+
className="n-flex n-flex-1 n-relative focus:n-outline-none"
|
|
72
72
|
>
|
|
73
73
|
{hasTabs && (
|
|
74
74
|
<VerticalTabMenu
|
|
@@ -111,12 +111,12 @@ export const DrawerWorkspaceLayout = memoGeneric(function DrawerWorkspaceLayout<
|
|
|
111
111
|
}}
|
|
112
112
|
/>
|
|
113
113
|
)}
|
|
114
|
-
{hasTabs && <DividerVertical className="h-full" />}
|
|
115
|
-
<div className="flex-1 flex relative">{centerPanel}</div>
|
|
114
|
+
{hasTabs && <DividerVertical className="n-h-full" />}
|
|
115
|
+
<div className="n-flex-1 n-flex n-relative">{centerPanel}</div>
|
|
116
116
|
{leftPanel && (
|
|
117
117
|
<Drawer
|
|
118
118
|
ref={leftSidebarRef}
|
|
119
|
-
className="flex-1"
|
|
119
|
+
className="n-flex-1"
|
|
120
120
|
style={{
|
|
121
121
|
left: 48,
|
|
122
122
|
maxWidth: "calc(100% - 48px)",
|
|
@@ -143,7 +143,7 @@ export const DrawerWorkspaceLayout = memoGeneric(function DrawerWorkspaceLayout<
|
|
|
143
143
|
<Drawer
|
|
144
144
|
id={RIGHT_SIDEBAR_ID}
|
|
145
145
|
ref={rightSidebarRef}
|
|
146
|
-
className="flex-1"
|
|
146
|
+
className="n-flex-1"
|
|
147
147
|
style={{
|
|
148
148
|
left: 48,
|
|
149
149
|
maxWidth: "calc(100% - 48px)",
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
memoGeneric,
|
|
6
6
|
usePersistentStateObject,
|
|
7
7
|
} from "@noya-app/react-utils";
|
|
8
|
-
import React, { useMemo, useRef } from "react";
|
|
8
|
+
import React, { useCallback, useMemo, useRef } from "react";
|
|
9
9
|
import {
|
|
10
10
|
ImperativePanelGroupHandle,
|
|
11
11
|
ImperativePanelHandle,
|
|
@@ -106,26 +106,68 @@ export const PanelWorkspaceLayout = memoGeneric(function PanelWorkspaceLayout<
|
|
|
106
106
|
});
|
|
107
107
|
}, [layoutGroup, propertyKey, layoutIds, hasLeftPanel, hasRightPanel]);
|
|
108
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
|
+
);
|
|
161
|
+
|
|
109
162
|
return (
|
|
110
163
|
<PanelGroup
|
|
111
164
|
ref={panelGroupRef}
|
|
112
165
|
id={EDITOR_PANEL_GROUP_ID}
|
|
113
|
-
className="flex-1"
|
|
166
|
+
className="n-flex-1"
|
|
114
167
|
direction="horizontal"
|
|
115
168
|
storage={panelStorage}
|
|
116
169
|
autoSaveId={autoSaveId}
|
|
117
|
-
onLayout={
|
|
118
|
-
setData((prev) => {
|
|
119
|
-
const newData = {
|
|
120
|
-
...prev,
|
|
121
|
-
[propertyKey]: {
|
|
122
|
-
layout: layout.map((size) => toPixelSize(size)),
|
|
123
|
-
expandToSizes: prev?.[propertyKey]?.expandToSizes ?? {},
|
|
124
|
-
},
|
|
125
|
-
};
|
|
126
|
-
return newData;
|
|
127
|
-
});
|
|
128
|
-
}}
|
|
170
|
+
onLayout={handleLayoutChange}
|
|
129
171
|
>
|
|
130
172
|
{leftPanel && (
|
|
131
173
|
<>
|
|
@@ -135,28 +177,15 @@ export const PanelWorkspaceLayout = memoGeneric(function PanelWorkspaceLayout<
|
|
|
135
177
|
items={leftTabItems}
|
|
136
178
|
activeValue={leftTabValue}
|
|
137
179
|
isSidebarCollapsed={leftSidebarCollapsed}
|
|
138
|
-
onChange={
|
|
139
|
-
if (value === leftTabValue) {
|
|
140
|
-
if (leftSidebarRef.current?.isExpanded()) {
|
|
141
|
-
leftSidebarRef.current?.collapse();
|
|
142
|
-
} else {
|
|
143
|
-
leftSidebarRef.current?.expand();
|
|
144
|
-
}
|
|
145
|
-
} else {
|
|
146
|
-
if (!leftSidebarRef.current?.isExpanded()) {
|
|
147
|
-
leftSidebarRef.current?.expand();
|
|
148
|
-
}
|
|
149
|
-
onChangeLeftTab?.(value);
|
|
150
|
-
}
|
|
151
|
-
}}
|
|
180
|
+
onChange={handleLeftTabChange}
|
|
152
181
|
/>
|
|
153
182
|
)}
|
|
154
183
|
{leftSidebarOptions.showTabs &&
|
|
155
184
|
leftTabItems &&
|
|
156
|
-
!leftSidebarCollapsed && <DividerVertical className="h-full" />}
|
|
185
|
+
!leftSidebarCollapsed && <DividerVertical className="n-h-full" />}
|
|
157
186
|
<Panel
|
|
158
187
|
id={LEFT_SIDEBAR_ID}
|
|
159
|
-
className="relative"
|
|
188
|
+
className="n-relative"
|
|
160
189
|
order={1}
|
|
161
190
|
ref={leftSidebarRef as React.RefObject<ImperativePanelHandle>}
|
|
162
191
|
defaultSize={leftSidebarOptions.initialSize}
|
|
@@ -171,7 +200,7 @@ export const PanelWorkspaceLayout = memoGeneric(function PanelWorkspaceLayout<
|
|
|
171
200
|
>
|
|
172
201
|
{leftSidebarCollapsed ? null : leftPanel}
|
|
173
202
|
</Panel>
|
|
174
|
-
<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" />
|
|
175
204
|
</>
|
|
176
205
|
)}
|
|
177
206
|
<Panel
|
|
@@ -179,16 +208,16 @@ export const PanelWorkspaceLayout = memoGeneric(function PanelWorkspaceLayout<
|
|
|
179
208
|
order={2}
|
|
180
209
|
defaultSize={centerPanelPercentage}
|
|
181
210
|
minSize={10}
|
|
182
|
-
className="flex relative"
|
|
211
|
+
className="n-flex n-relative"
|
|
183
212
|
>
|
|
184
213
|
{centerPanel}
|
|
185
214
|
</Panel>
|
|
186
215
|
{rightPanel && (
|
|
187
216
|
<>
|
|
188
|
-
<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" />
|
|
189
218
|
<Panel
|
|
190
219
|
id={RIGHT_SIDEBAR_ID}
|
|
191
|
-
className="relative"
|
|
220
|
+
className="n-relative"
|
|
192
221
|
order={3}
|
|
193
222
|
ref={rightSidebarRef as React.RefObject<ImperativePanelHandle>}
|
|
194
223
|
minSize={rightSidebarOptions.minSize}
|
|
@@ -205,27 +234,14 @@ export const PanelWorkspaceLayout = memoGeneric(function PanelWorkspaceLayout<
|
|
|
205
234
|
</Panel>
|
|
206
235
|
{rightSidebarOptions.showTabs &&
|
|
207
236
|
rightTabItems &&
|
|
208
|
-
!rightSidebarCollapsed && <DividerVertical className="h-full" />}
|
|
237
|
+
!rightSidebarCollapsed && <DividerVertical className="n-h-full" />}
|
|
209
238
|
{rightSidebarOptions.showTabs && rightTabItems && (
|
|
210
239
|
<VerticalTabMenu
|
|
211
240
|
tooltipSide="left"
|
|
212
241
|
items={rightTabItems}
|
|
213
242
|
activeValue={rightTabValue}
|
|
214
243
|
isSidebarCollapsed={rightSidebarCollapsed}
|
|
215
|
-
onChange={
|
|
216
|
-
if (value === rightTabValue) {
|
|
217
|
-
if (rightSidebarRef.current?.isExpanded()) {
|
|
218
|
-
rightSidebarRef.current?.collapse();
|
|
219
|
-
} else {
|
|
220
|
-
rightSidebarRef.current?.expand();
|
|
221
|
-
}
|
|
222
|
-
} else {
|
|
223
|
-
if (!rightSidebarRef.current?.isExpanded()) {
|
|
224
|
-
rightSidebarRef.current?.expand();
|
|
225
|
-
}
|
|
226
|
-
onChangeRightTab?.(value);
|
|
227
|
-
}
|
|
228
|
-
}}
|
|
244
|
+
onChange={handleRightTabChange}
|
|
229
245
|
/>
|
|
230
246
|
)}
|
|
231
247
|
</>
|
|
@@ -1,36 +1,46 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { memoGeneric } from "@noya-app/react-utils";
|
|
2
|
+
import React, { ComponentProps, useMemo } from "react";
|
|
2
3
|
import { cssVarNames } from "../../theme";
|
|
3
4
|
import { MenuItem } from "../internal/Menu";
|
|
4
5
|
import { ToolbarMenu } from "../Toolbar";
|
|
5
6
|
import { Tooltip } from "../Tooltip";
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
items,
|
|
9
|
-
activeValue,
|
|
10
|
-
isSidebarCollapsed,
|
|
11
|
-
onChange,
|
|
12
|
-
tooltipSide,
|
|
13
|
-
}: {
|
|
8
|
+
type VerticalTabMenuProps<TabValue extends string> = {
|
|
14
9
|
items: MenuItem<TabValue>[];
|
|
15
10
|
activeValue: TabValue | undefined;
|
|
16
11
|
isSidebarCollapsed: boolean;
|
|
17
12
|
onChange: (value: TabValue) => void;
|
|
18
13
|
tooltipSide?: ComponentProps<typeof Tooltip>["side"];
|
|
19
|
-
}
|
|
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
|
+
|
|
20
32
|
return (
|
|
21
33
|
<div
|
|
22
|
-
className="w-[47px] h-full bg-sidebar-background flex flex-col items-center py-3 gap-3"
|
|
23
|
-
style={
|
|
24
|
-
[cssVarNames.colors.inputBackground]: "transparent",
|
|
25
|
-
[cssVarNames.colors.buttonBackground]: "transparent",
|
|
26
|
-
}}
|
|
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}
|
|
27
36
|
>
|
|
28
37
|
<ToolbarMenu
|
|
29
38
|
items={items}
|
|
30
39
|
activeValue={isSidebarCollapsed ? undefined : activeValue}
|
|
31
40
|
onSelectMenuItem={onChange}
|
|
32
41
|
tooltipSide={tooltipSide}
|
|
42
|
+
displayFilter="iconOnly"
|
|
33
43
|
/>
|
|
34
44
|
</div>
|
|
35
45
|
);
|
|
36
|
-
}
|
|
46
|
+
});
|