@rnaga/wp-next-ui 1.1.3 → 1.1.4

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/SortableList.d.ts CHANGED
@@ -15,10 +15,25 @@ export declare const SortableList: <T extends any = string>(props: {
15
15
  label?: SxProps;
16
16
  };
17
17
  displayType: DisplayType;
18
+ /**
19
+ * Unique ID for this list. Used as a `data-drop-target-id` on the wrapper Box
20
+ * so that items dragged from another SortableList can be dropped here via
21
+ * the dragging list's `onDropToTarget` callback.
22
+ * Also used to prevent cross-list item swapping.
23
+ */
24
+ dropZoneId?: string;
18
25
  renderItem?: (item: SortableListItemType<T>) => JSX.Element;
19
26
  onDelete?: (index: number) => void;
20
27
  onEdit?: (index: number) => void;
21
28
  onChange?: (items: SortableListItemType<T>[], fromIndex: number, toIndex: number) => void;
29
+ onDrop?: (item: SortableListItemType<T>) => void;
30
+ onDropToTarget?: (item: SortableListItemType<T>, targetId: string) => void;
31
+ onDropTargetEnter?: (targetId: string) => void;
32
+ onDropTargetLeave?: (targetId: string) => void;
33
+ cursor?: {
34
+ idle?: string;
35
+ dragging?: string;
36
+ };
22
37
  }) => import("react/jsx-runtime").JSX.Element;
23
38
  export {};
24
39
  //# sourceMappingURL=SortableList.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SortableList.d.ts","sourceRoot":"","sources":["../src/SortableList.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,EAEL,GAAG,EAKJ,MAAM,OAAO,CAAC;AAGf,MAAM,MAAM,oBAAoB,CAAC,CAAC,GAAG,MAAM,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC;AAE/D,KAAK,WAAW,GAAG,UAAU,GAAG,YAAY,GAAG,MAAM,GAAG,gBAAgB,CAAC;AAczE,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;AAEnE,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,GAAG,GAAG,MAAM,EAAE,OAAO;IAC1D,IAAI,EAAE;QAAE,KAAK,EAAE,CAAC,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACpC,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC1B,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,WAAW,CAAC,EAAE;QACZ,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB,CAAC;IACF,WAAW,EAAE,WAAW,CAAC;IACzB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC;IAC5D,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,CACT,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC,EAAE,EAChC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,KACZ,IAAI,CAAC;CACX,4CA8OA,CAAC"}
1
+ {"version":3,"file":"SortableList.d.ts","sourceRoot":"","sources":["../src/SortableList.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAE1C,OAAO,EAEL,GAAG,EAOJ,MAAM,OAAO,CAAC;AAIf,MAAM,MAAM,oBAAoB,CAAC,CAAC,GAAG,MAAM,IAAI,YAAY,CAAC,CAAC,CAAC,CAAC;AAE/D,KAAK,WAAW,GAAG,UAAU,GAAG,YAAY,GAAG,MAAM,GAAG,gBAAgB,CAAC;AAczE,MAAM,MAAM,iBAAiB,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC;AAEnE,eAAO,MAAM,YAAY,GAAI,CAAC,SAAS,GAAG,GAAG,MAAM,EAAE,OAAO;IAC1D,IAAI,EAAE;QAAE,KAAK,EAAE,CAAC,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACpC,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC1B,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,WAAW,CAAC,EAAE;QACZ,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB,CAAC;IACF,WAAW,EAAE,WAAW,CAAC;IACzB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC;IAC5D,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACnC,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,CACT,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC,EAAE,EAChC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,KACZ,IAAI,CAAC;IACV,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC;IACjD,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,oBAAoB,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC3E,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,iBAAiB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,MAAM,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC/C,4CA8TA,CAAC"}
package/SortableList.js CHANGED
@@ -1,12 +1,17 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
2
  import { useMouseMove } from "./hooks/use-mouse-move";
3
- import { createContext, useEffect, useRef, useState, } from "react";
3
+ import { createContext, useEffect, useId, useMemo, useRef, useState, } from "react";
4
+ import { Box } from "@mui/material";
4
5
  import { ListBase } from "./ListBase";
5
6
  const SortableContext = createContext({});
6
7
  export const SortableList = (props) => {
7
- const { size = "small", displayType = "vertical", renderItem, onDelete, onChange, onEdit, } = props;
8
+ const { size = "small", displayType = "vertical", renderItem, onDelete, onChange, onEdit, onDrop, onDropToTarget, onDropTargetEnter, onDropTargetLeave, cursor, dropZoneId, } = props;
9
+ // Stable unique ID for this list instance (used to tag items)
10
+ const generatedId = useId();
11
+ const listId = dropZoneId ?? generatedId;
8
12
  const [items, setItems] = useState([]);
9
13
  const targetRef = useRef(null);
14
+ const dropTargetRef = useRef(null);
10
15
  const refPos = useRef({ x: 0, y: 0 });
11
16
  const itemRefs = useRef(new Map());
12
17
  const draggedItemRef = useRef(null);
@@ -61,12 +66,18 @@ export const SortableList = (props) => {
61
66
  const sortableItem = el.closest("[data-sortable-item-index]");
62
67
  if (!sortableItem)
63
68
  continue;
69
+ // Only accept items that belong to THIS list (same listId)
70
+ if (sortableItem.getAttribute("data-sortable-list-id") !== listId) {
71
+ continue;
72
+ }
64
73
  const itemIndex = sortableItem.getAttribute("data-sortable-item-index");
65
- if (!itemIndex || itemIndex === String(index))
74
+ if (!itemIndex || itemIndex === String(index)) {
66
75
  continue;
76
+ }
67
77
  const itemIndexNumber = parseInt(itemIndex);
68
- if (itemIndexNumber < 0 || itemIndexNumber >= itemsRef.current.length)
78
+ if (itemIndexNumber < 0 || itemIndexNumber >= itemsRef.current.length) {
69
79
  continue;
80
+ }
70
81
  foundTarget = sortableItem;
71
82
  break;
72
83
  }
@@ -77,6 +88,41 @@ export const SortableList = (props) => {
77
88
  foundTarget.style.border = "1px solid red";
78
89
  }
79
90
  targetRef.current = foundTarget;
91
+ // Check for external drop targets: both explicit [data-drop-target-id] elements
92
+ // and foreign SortableList drop zones ([data-sortable-drop-zone-id] that differ from this list)
93
+ {
94
+ let foundDropTarget = null;
95
+ if (!foundTarget) {
96
+ for (const el of elementsAtPoint) {
97
+ // Look for explicit external drop targets (e.g. collection headers)
98
+ const explicitTarget = el.closest("[data-drop-target-id]");
99
+ if (explicitTarget) {
100
+ foundDropTarget = explicitTarget;
101
+ break;
102
+ }
103
+ // Look for foreign SortableList drop zones (different list ID)
104
+ const dropZone = el.closest("[data-sortable-drop-zone-id]");
105
+ if (dropZone &&
106
+ dropZone.getAttribute("data-sortable-drop-zone-id") !== listId) {
107
+ foundDropTarget = dropZone;
108
+ break;
109
+ }
110
+ }
111
+ }
112
+ if (dropTargetRef.current && dropTargetRef.current !== foundDropTarget) {
113
+ const leavingId = dropTargetRef.current.getAttribute("data-drop-target-id") ??
114
+ dropTargetRef.current.getAttribute("data-sortable-drop-zone-id");
115
+ if (leavingId)
116
+ onDropTargetLeave?.(leavingId);
117
+ }
118
+ if (foundDropTarget && foundDropTarget !== dropTargetRef.current) {
119
+ const enteringId = foundDropTarget.getAttribute("data-drop-target-id") ??
120
+ foundDropTarget.getAttribute("data-sortable-drop-zone-id");
121
+ if (enteringId)
122
+ onDropTargetEnter?.(enteringId);
123
+ }
124
+ dropTargetRef.current = foundDropTarget;
125
+ }
80
126
  };
81
127
  const handleMouseDown = (e) => {
82
128
  const dragged = draggedItemRef.current;
@@ -103,16 +149,34 @@ export const SortableList = (props) => {
103
149
  if (targetRef.current) {
104
150
  const toItemIndex = targetRef.current.getAttribute("data-sortable-item-index");
105
151
  swapItems(e, index, toItemIndex ? parseInt(toItemIndex) : -1);
106
- targetRef.current?.style.removeProperty("border");
152
+ targetRef.current.style.removeProperty("border");
107
153
  targetRef.current = null;
108
154
  }
155
+ else if (dropTargetRef.current) {
156
+ // Dropped onto an external drop target or foreign SortableList drop zone
157
+ const targetId = dropTargetRef.current.getAttribute("data-drop-target-id") ??
158
+ dropTargetRef.current.getAttribute("data-sortable-drop-zone-id");
159
+ const droppedItem = itemsRef.current.find((i) => i.index === index);
160
+ if (droppedItem && targetId) {
161
+ onDropToTarget?.(droppedItem, targetId);
162
+ }
163
+ onDropTargetLeave?.(targetId ?? "");
164
+ dropTargetRef.current = null;
165
+ }
166
+ else {
167
+ // Dropped outside any list or target — fire onDrop
168
+ const droppedItem = itemsRef.current.find((i) => i.index === index);
169
+ if (droppedItem) {
170
+ onDrop?.(droppedItem);
171
+ }
172
+ }
109
173
  draggedItemRef.current = null;
110
174
  };
111
175
  const { initMouseMove } = useMouseMove({
112
176
  onDeltaChange: handleDeltaChange,
113
177
  onMouseUp: handleMouseUp,
114
178
  onMouseDown: handleMouseDown,
115
- cursor: "grabbing",
179
+ cursor: cursor?.dragging ?? "grabbing",
116
180
  threshold: 1,
117
181
  });
118
182
  useEffect(() => {
@@ -124,26 +188,20 @@ export const SortableList = (props) => {
124
188
  }));
125
189
  setItems(initialItems);
126
190
  }, [props.enum]);
127
- let sx = {};
128
- if (props.displayType === "horizontal") {
129
- sx = {
130
- display: "flex",
131
- flexDirection: "row",
132
- };
133
- }
134
- else if (props.displayType === "horizontal-fit") {
135
- sx = {
136
- display: "flex",
137
- flexDirection: "row",
138
- };
139
- }
140
- else if (props.displayType === "grid") {
141
- sx = {
142
- display: "grid",
143
- gridTemplateColumns: "repeat(auto-fill, minmax(100px, 1fr))",
144
- gap: 1,
145
- };
146
- }
191
+ const sx = useMemo(() => {
192
+ if (props.displayType === "horizontal" ||
193
+ props.displayType === "horizontal-fit") {
194
+ return { display: "flex", flexDirection: "row" };
195
+ }
196
+ if (props.displayType === "grid") {
197
+ return {
198
+ display: "grid",
199
+ gridTemplateColumns: "repeat(auto-fill, minmax(100px, 1fr))",
200
+ gap: 1,
201
+ };
202
+ }
203
+ return {};
204
+ }, [props.displayType]);
147
205
  const handleItemMouseDown = (item, e) => {
148
206
  // Find the MuiListItem parent element
149
207
  const listItemElement = e.target.closest("[data-sortable-item-index]");
@@ -153,9 +211,6 @@ export const SortableList = (props) => {
153
211
  initMouseMove(listItemElement)(e);
154
212
  }
155
213
  };
156
- const renderSortableItem = (item) => {
157
- return renderItem ? renderItem(item) : item.label;
158
- };
159
214
  return (_jsx(SortableContext.Provider, { value: {
160
215
  items,
161
216
  findItem: findItem,
@@ -163,11 +218,12 @@ export const SortableList = (props) => {
163
218
  refPos,
164
219
  targetRef,
165
220
  displayType,
166
- }, children: _jsx(ListBase, { items: items, size: size, sx: { ...sx, ...props.sx }, displayType: displayType, renderItem: renderSortableItem, onDelete: onDelete, onEdit: onEdit, onMouseDown: handleItemMouseDown, getItemDataAttributes: (item) => ({
167
- "data-sortable-item-index": item.index,
168
- }), slotSxProps: {
169
- listItem: {
170
- cursor: "move",
171
- },
172
- } }) }));
221
+ }, children: _jsx(Box, { "data-sortable-drop-zone-id": listId, children: _jsx(ListBase, { items: items, size: size, sx: { ...sx, ...props.sx }, displayType: displayType, renderItem: (item) => renderItem ? renderItem(item) : _jsx(_Fragment, { children: item.label }), onDelete: onDelete, onEdit: onEdit, onMouseDown: handleItemMouseDown, getItemDataAttributes: (item) => ({
222
+ "data-sortable-item-index": item.index,
223
+ "data-sortable-list-id": listId,
224
+ }), slotSxProps: {
225
+ listItem: {
226
+ cursor: cursor?.idle ?? "move",
227
+ },
228
+ } }) }) }));
173
229
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rnaga/wp-next-ui",
3
- "version": "1.1.3",
3
+ "version": "1.1.4",
4
4
  "scripts": {
5
5
  "build": "node ../../scripts/build-ui.mjs",
6
6
  "release-old": "node ../../scripts/release.mjs",