@noya-app/noya-designsystem 0.1.56 → 0.1.58
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 +14 -0
- package/dist/index.d.mts +61 -46
- package/dist/index.d.ts +61 -46
- package/dist/index.js +1150 -1056
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +356 -265
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/validateDropIndicator.test.ts +64 -31
- package/src/components/Collection.tsx +3 -0
- package/src/components/List.tsx +4 -0
- package/src/components/ListView.tsx +7 -0
- package/src/components/sorting/DragRegistration.tsx +3 -6
- package/src/components/sorting/SharedDragProvider.tsx +258 -135
- package/src/components/sorting/Sortable.tsx +54 -108
- package/src/components/sorting/createSharedDrag.tsx +10 -15
- package/src/components/sorting/sorting.ts +48 -44
- package/src/utils/moveTreeItem.ts +6 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@noya-app/noya-designsystem",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.58",
|
|
4
4
|
"main": "./dist/index.js",
|
|
5
5
|
"module": "./dist/index.mjs",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"dependencies": {
|
|
23
23
|
"@dnd-kit/core": "6.3.1",
|
|
24
24
|
"@dnd-kit/sortable": "10.0.0",
|
|
25
|
-
"@noya-app/noya-colorpicker": "0.1.
|
|
25
|
+
"@noya-app/noya-colorpicker": "0.1.22",
|
|
26
26
|
"@noya-app/noya-utils": "0.1.5",
|
|
27
27
|
"@noya-app/noya-geometry": "0.1.11",
|
|
28
28
|
"@noya-app/noya-icons": "0.1.10",
|
|
@@ -1,88 +1,121 @@
|
|
|
1
1
|
import { describe, expect, it } from "bun:test";
|
|
2
2
|
import {
|
|
3
3
|
defaultAcceptsDrop,
|
|
4
|
+
MoveDragItemParameters,
|
|
4
5
|
validateDropIndicator,
|
|
5
6
|
} from "../components/sorting/sorting";
|
|
6
7
|
|
|
7
8
|
describe("defaultAcceptsDrop", () => {
|
|
8
9
|
it("should return false if the active item is the same as the over item", () => {
|
|
9
|
-
const result = defaultAcceptsDrop(
|
|
10
|
+
const result = defaultAcceptsDrop({
|
|
11
|
+
sourceIndex: 0,
|
|
12
|
+
targetIndex: 0,
|
|
13
|
+
position: "inside",
|
|
14
|
+
sourceListId: "",
|
|
15
|
+
targetListId: "",
|
|
16
|
+
});
|
|
10
17
|
expect(result).toBe(false);
|
|
11
18
|
});
|
|
12
19
|
|
|
13
20
|
it("should return false for 'inside' position", () => {
|
|
14
|
-
const result = defaultAcceptsDrop(
|
|
21
|
+
const result = defaultAcceptsDrop({
|
|
22
|
+
sourceIndex: 0,
|
|
23
|
+
targetIndex: 1,
|
|
24
|
+
position: "inside",
|
|
25
|
+
sourceListId: "",
|
|
26
|
+
targetListId: "",
|
|
27
|
+
});
|
|
15
28
|
expect(result).toBe(false);
|
|
16
29
|
});
|
|
17
30
|
|
|
18
31
|
it("should return false when dropping above the same item", () => {
|
|
19
|
-
const result = defaultAcceptsDrop(
|
|
32
|
+
const result = defaultAcceptsDrop({
|
|
33
|
+
sourceIndex: 0,
|
|
34
|
+
targetIndex: 0,
|
|
35
|
+
position: "above",
|
|
36
|
+
sourceListId: "",
|
|
37
|
+
targetListId: "",
|
|
38
|
+
});
|
|
20
39
|
expect(result).toBe(false);
|
|
21
40
|
});
|
|
22
41
|
|
|
23
42
|
it("should return false when dropping below the same item", () => {
|
|
24
|
-
const result = defaultAcceptsDrop(
|
|
43
|
+
const result = defaultAcceptsDrop({
|
|
44
|
+
sourceIndex: 0,
|
|
45
|
+
targetIndex: 0,
|
|
46
|
+
position: "below",
|
|
47
|
+
sourceListId: "",
|
|
48
|
+
targetListId: "",
|
|
49
|
+
});
|
|
25
50
|
expect(result).toBe(false);
|
|
26
51
|
});
|
|
27
52
|
|
|
28
53
|
it("should return false when dropping above the item below the source", () => {
|
|
29
|
-
const result = defaultAcceptsDrop(
|
|
54
|
+
const result = defaultAcceptsDrop({
|
|
55
|
+
sourceIndex: 0,
|
|
56
|
+
targetIndex: 1,
|
|
57
|
+
position: "above",
|
|
58
|
+
sourceListId: "",
|
|
59
|
+
targetListId: "",
|
|
60
|
+
});
|
|
30
61
|
expect(result).toBe(false);
|
|
31
62
|
});
|
|
32
63
|
|
|
33
64
|
it("should return false when dropping below the item above the source", () => {
|
|
34
|
-
const result = defaultAcceptsDrop(
|
|
65
|
+
const result = defaultAcceptsDrop({
|
|
66
|
+
sourceIndex: 1,
|
|
67
|
+
targetIndex: 0,
|
|
68
|
+
position: "below",
|
|
69
|
+
sourceListId: "",
|
|
70
|
+
targetListId: "",
|
|
71
|
+
});
|
|
35
72
|
expect(result).toBe(false);
|
|
36
73
|
});
|
|
37
74
|
|
|
38
75
|
it("should return true when dropping above a valid target", () => {
|
|
39
|
-
const result = defaultAcceptsDrop(
|
|
76
|
+
const result = defaultAcceptsDrop({
|
|
77
|
+
sourceIndex: 0,
|
|
78
|
+
targetIndex: 2,
|
|
79
|
+
position: "above",
|
|
80
|
+
sourceListId: "",
|
|
81
|
+
targetListId: "",
|
|
82
|
+
});
|
|
40
83
|
expect(result).toBe(true);
|
|
41
84
|
});
|
|
42
85
|
|
|
43
86
|
it("should return true when dropping below a valid target", () => {
|
|
44
|
-
const result = defaultAcceptsDrop(
|
|
87
|
+
const result = defaultAcceptsDrop({
|
|
88
|
+
sourceIndex: 2,
|
|
89
|
+
targetIndex: 0,
|
|
90
|
+
position: "below",
|
|
91
|
+
sourceListId: "",
|
|
92
|
+
targetListId: "",
|
|
93
|
+
});
|
|
45
94
|
expect(result).toBe(true);
|
|
46
95
|
});
|
|
47
96
|
});
|
|
48
97
|
|
|
49
98
|
describe("validateDropIndicator", () => {
|
|
50
|
-
const mockAcceptsDrop = (
|
|
51
|
-
sourceIndex: number,
|
|
52
|
-
targetIndex: number,
|
|
53
|
-
position: "above" | "below" | "inside"
|
|
54
|
-
) => {
|
|
99
|
+
const mockAcceptsDrop = (parameters: MoveDragItemParameters) => {
|
|
55
100
|
// Mock that only allows dropping inside
|
|
56
|
-
if (position === "inside") return true;
|
|
101
|
+
if (parameters.position === "inside") return true;
|
|
57
102
|
return false;
|
|
58
103
|
};
|
|
59
104
|
|
|
60
|
-
const mockAcceptsDropAboveBelow = (
|
|
61
|
-
sourceIndex: number,
|
|
62
|
-
targetIndex: number,
|
|
63
|
-
position: "above" | "below" | "inside"
|
|
64
|
-
) => {
|
|
105
|
+
const mockAcceptsDropAboveBelow = (parameters: MoveDragItemParameters) => {
|
|
65
106
|
// Mock that only allows dropping above/below
|
|
66
|
-
if (position === "inside") return false;
|
|
107
|
+
if (parameters.position === "inside") return false;
|
|
67
108
|
return true;
|
|
68
109
|
};
|
|
69
110
|
|
|
70
|
-
const mockAcceptsAll = (
|
|
71
|
-
sourceIndex: number,
|
|
72
|
-
targetIndex: number,
|
|
73
|
-
position: "above" | "below" | "inside"
|
|
74
|
-
) => {
|
|
111
|
+
const mockAcceptsAll = (_: MoveDragItemParameters) => {
|
|
75
112
|
// Mock that allows all drop positions
|
|
76
113
|
return true;
|
|
77
114
|
};
|
|
78
115
|
|
|
79
|
-
const mockAcceptsAboveAndInside = (
|
|
80
|
-
sourceIndex: number,
|
|
81
|
-
targetIndex: number,
|
|
82
|
-
position: "above" | "below" | "inside"
|
|
83
|
-
) => {
|
|
116
|
+
const mockAcceptsAboveAndInside = (parameters: MoveDragItemParameters) => {
|
|
84
117
|
// Mock that allows dropping above and inside, but not below
|
|
85
|
-
return position !== "below";
|
|
118
|
+
return parameters.position !== "below";
|
|
86
119
|
};
|
|
87
120
|
|
|
88
121
|
const keys = ["item1", "item2", "item3"];
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
ListViewRowProps,
|
|
9
9
|
} from "../components/ListView";
|
|
10
10
|
import { List } from "./List";
|
|
11
|
+
import { SharedDragProps } from "./sorting/DragRegistration";
|
|
11
12
|
|
|
12
13
|
export type CollectionViewType = "grid" | "list";
|
|
13
14
|
|
|
@@ -93,6 +94,8 @@ export interface CollectionProps<T, M extends string = string> {
|
|
|
93
94
|
/** @default false */
|
|
94
95
|
sortable?: boolean;
|
|
95
96
|
dragIndicatorStyle?: ListViewRowProps<M>["dragIndicatorStyle"];
|
|
97
|
+
sharedDragProps?: SharedDragProps;
|
|
98
|
+
sortableId?: string;
|
|
96
99
|
}
|
|
97
100
|
|
|
98
101
|
export const Collection = forwardRefGeneric(function Collection<
|
package/src/components/List.tsx
CHANGED
|
@@ -64,6 +64,8 @@ export const List = memoGeneric(
|
|
|
64
64
|
getPlaceholder,
|
|
65
65
|
onClickItem,
|
|
66
66
|
dragIndicatorStyle,
|
|
67
|
+
sortableId,
|
|
68
|
+
sharedDragProps,
|
|
67
69
|
} = props;
|
|
68
70
|
|
|
69
71
|
const [internalHoveredId, setHoveredId] = useState<string>();
|
|
@@ -133,6 +135,8 @@ export const List = memoGeneric(
|
|
|
133
135
|
onMoveItem={onMoveItem}
|
|
134
136
|
renderEmptyState={renderEmptyState}
|
|
135
137
|
getDropTargetParentIndex={getDropTargetParentIndex}
|
|
138
|
+
sharedDragProps={sharedDragProps}
|
|
139
|
+
sortableId={sortableId}
|
|
136
140
|
{...dropTargetProps}
|
|
137
141
|
renderItem={(
|
|
138
142
|
item: T,
|
|
@@ -31,6 +31,7 @@ import { ContextMenu } from "./ContextMenu";
|
|
|
31
31
|
import { InputField } from "./InputField";
|
|
32
32
|
import { MenuItem } from "./internal/Menu";
|
|
33
33
|
import { ScrollArea } from "./ScrollArea";
|
|
34
|
+
import { SharedDragProps } from "./sorting/DragRegistration";
|
|
34
35
|
import { Sortable } from "./sorting/Sortable";
|
|
35
36
|
import {
|
|
36
37
|
DropValidator,
|
|
@@ -793,6 +794,8 @@ export type ListViewRootProps = {
|
|
|
793
794
|
onDrop?: React.DragEventHandler<HTMLDivElement>;
|
|
794
795
|
renderEmptyState?: () => ReactNode;
|
|
795
796
|
getDropTargetParentIndex?: SortableItemContextProps["getDropTargetParentIndex"];
|
|
797
|
+
sharedDragProps?: SharedDragProps;
|
|
798
|
+
sortableId?: string;
|
|
796
799
|
};
|
|
797
800
|
|
|
798
801
|
const ListViewRootInner = forwardRefGeneric(function ListViewRootInner<T>(
|
|
@@ -828,6 +831,8 @@ const ListViewRootInner = forwardRefGeneric(function ListViewRootInner<T>(
|
|
|
828
831
|
onDrop,
|
|
829
832
|
renderEmptyState,
|
|
830
833
|
getDropTargetParentIndex,
|
|
834
|
+
sharedDragProps,
|
|
835
|
+
sortableId,
|
|
831
836
|
}: RenderProps<T> & ListViewRootProps,
|
|
832
837
|
forwardedRef: ForwardedRef<IVirtualizedList>
|
|
833
838
|
) {
|
|
@@ -1000,11 +1005,13 @@ const ListViewRootInner = forwardRefGeneric(function ListViewRootInner<T>(
|
|
|
1000
1005
|
const withSortable = (children: ReactNode) =>
|
|
1001
1006
|
sortable ? (
|
|
1002
1007
|
<Sortable.Root
|
|
1008
|
+
id={sortableId}
|
|
1003
1009
|
onMoveItem={onMoveItem}
|
|
1004
1010
|
keys={ids}
|
|
1005
1011
|
renderOverlay={renderOverlay}
|
|
1006
1012
|
acceptsDrop={acceptsDrop}
|
|
1007
1013
|
getDropTargetParentIndex={getDropTargetParentIndex}
|
|
1014
|
+
sharedDragProps={sharedDragProps}
|
|
1008
1015
|
>
|
|
1009
1016
|
{children}
|
|
1010
1017
|
</Sortable.Root>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
AcceptsDrop,
|
|
3
|
+
DragState,
|
|
3
4
|
MoveDragItemHandler,
|
|
4
5
|
RelativeDropPosition,
|
|
5
6
|
} from "./sorting";
|
|
@@ -9,7 +10,6 @@ import { AcceptsFromList } from "./sorting";
|
|
|
9
10
|
|
|
10
11
|
import { Point } from "@noya-app/noya-geometry";
|
|
11
12
|
import React from "react";
|
|
12
|
-
import { DragItem } from "./sorting";
|
|
13
13
|
|
|
14
14
|
export type GetDropIndicatorParameters = {
|
|
15
15
|
absolutePosition: Point;
|
|
@@ -73,10 +73,7 @@ export function useDragRegistrationManager() {
|
|
|
73
73
|
return { registerList, unregisterList, registeredLists };
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
export type ActiveDragContextType =
|
|
77
|
-
activeItem: DragItem | null;
|
|
78
|
-
delta: Point;
|
|
79
|
-
};
|
|
76
|
+
export type ActiveDragContextType = DragState;
|
|
80
77
|
|
|
81
78
|
export const ActiveDragContext =
|
|
82
79
|
React.createContext<ActiveDragContextType | null>(null);
|
|
@@ -104,7 +101,7 @@ export function useAnyDragContext() {
|
|
|
104
101
|
return React.useContext(AnyDragContext);
|
|
105
102
|
}
|
|
106
103
|
|
|
107
|
-
export type
|
|
104
|
+
export type SharedDragProps = {
|
|
108
105
|
dragRegistrationContext: React.Context<DragRegistrationContextType | null>;
|
|
109
106
|
activeDragContext: React.Context<ActiveDragContextType | null>;
|
|
110
107
|
};
|