@rnaga/wp-next-ui 1.0.7 → 1.0.9
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/Button.d.ts +2 -1
- package/Button.d.ts.map +1 -1
- package/Button.js +2 -2
- package/Checkmarks.d.ts +17 -0
- package/Checkmarks.d.ts.map +1 -0
- package/Checkmarks.js +76 -0
- package/DraggableBox.d.ts +2 -0
- package/DraggableBox.d.ts.map +1 -1
- package/DraggableBox.js +15 -6
- package/ListBase.d.ts +50 -0
- package/ListBase.d.ts.map +1 -0
- package/ListBase.js +106 -0
- package/SortableList.d.ts +3 -7
- package/SortableList.d.ts.map +1 -1
- package/SortableList.js +88 -136
- package/package.json +3 -1
package/Button.d.ts
CHANGED
|
@@ -6,5 +6,6 @@ export declare const Button: (props: {
|
|
|
6
6
|
bold?: boolean;
|
|
7
7
|
loading?: boolean;
|
|
8
8
|
color?: "info" | "success" | "warning" | "error" | "primary" | "secondary";
|
|
9
|
-
|
|
9
|
+
endIcon?: React.ReactNode;
|
|
10
|
+
} & Omit<Parameters<typeof MuiButton>[0], "children" | "size" | "endIcon">) => import("react/jsx-runtime").JSX.Element;
|
|
10
11
|
//# sourceMappingURL=Button.d.ts.map
|
package/Button.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../src/Button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,eAAe,CAAC;AAIpD,eAAO,MAAM,MAAM,GACjB,OAAO;IACL,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IAEpC,SAAS,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC;IAC9B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"Button.d.ts","sourceRoot":"","sources":["../src/Button.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,SAAS,EAAE,MAAM,eAAe,CAAC;AAIpD,eAAO,MAAM,MAAM,GACjB,OAAO;IACL,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,OAAO,CAAC;IAEpC,SAAS,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC;IAC9B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,GAAG,WAAW,CAAC;IAC3E,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,SAAS,CAAC,4CAkC3E,CAAC"}
|
package/Button.js
CHANGED
|
@@ -3,7 +3,7 @@ import { Button as MuiButton } from "@mui/material";
|
|
|
3
3
|
import { CircularProgress } from "@mui/material";
|
|
4
4
|
import { useWPTheme } from "./ThemeRegistry";
|
|
5
5
|
export const Button = (props) => {
|
|
6
|
-
const { children, size, component, bold, loading, color, disabled, ...rest } = props;
|
|
6
|
+
const { children, size, component, bold, loading, color, disabled, endIcon, ...rest } = props;
|
|
7
7
|
const { wpTheme } = useWPTheme();
|
|
8
8
|
return (_jsx(MuiButton, { ...rest, component: component, variant: "contained", size: "small", disableElevation: true, disabled: loading || disabled === true, sx: {
|
|
9
9
|
textTransform: "none",
|
|
@@ -11,5 +11,5 @@ export const Button = (props) => {
|
|
|
11
11
|
...(bold ? { fontWeight: "bold" } : {}),
|
|
12
12
|
...(color ? { backgroundColor: wpTheme.colors[color] } : {}),
|
|
13
13
|
...rest.sx,
|
|
14
|
-
}, endIcon: loading ? _jsx(CircularProgress, { size: 20 }) :
|
|
14
|
+
}, endIcon: loading ? _jsx(CircularProgress, { size: 20 }) : endIcon, children: children }));
|
|
15
15
|
};
|
package/Checkmarks.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Button } from "./Button";
|
|
2
|
+
import { RefObject } from "react";
|
|
3
|
+
export type CheckmarksItem = {
|
|
4
|
+
label: string;
|
|
5
|
+
value: string;
|
|
6
|
+
};
|
|
7
|
+
export declare const Checkmarks: (props: {
|
|
8
|
+
ref?: RefObject<HTMLElement | null>;
|
|
9
|
+
items: CheckmarksItem[];
|
|
10
|
+
onChange: (values: string[], items: CheckmarksItem[]) => void;
|
|
11
|
+
label?: string;
|
|
12
|
+
size?: "small" | "medium";
|
|
13
|
+
values?: string[];
|
|
14
|
+
showArrowIcon?: boolean;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
} & Omit<Parameters<typeof Button>[0], "onChange" | "ref" | "label" | "value" | "children" | "disabled">) => import("react/jsx-runtime").JSX.Element;
|
|
17
|
+
//# sourceMappingURL=Checkmarks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Checkmarks.d.ts","sourceRoot":"","sources":["../src/Checkmarks.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAKlC,OAAO,EAAY,SAAS,EAAuB,MAAM,OAAO,CAAC;AAKjE,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,eAAO,MAAM,UAAU,GACrB,OAAO;IACL,GAAG,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACpC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,cAAc,EAAE,KAAK,IAAI,CAAC;IAC9D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,GAAG,IAAI,CACN,UAAU,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,EAC5B,UAAU,GAAG,KAAK,GAAG,OAAO,GAAG,OAAO,GAAG,UAAU,GAAG,UAAU,CACjE,4CAoJF,CAAC"}
|
package/Checkmarks.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button } from "./Button";
|
|
3
|
+
import Menu from "@mui/material/Menu";
|
|
4
|
+
import MenuItem from "@mui/material/MenuItem";
|
|
5
|
+
import ArrowDropDownIcon from "@mui/icons-material/ArrowDropDown";
|
|
6
|
+
import ArrowDropUpIcon from "@mui/icons-material/ArrowDropUp";
|
|
7
|
+
import { Fragment, useEffect, useState } from "react";
|
|
8
|
+
import { Typography } from "./Typography";
|
|
9
|
+
import { useWPTheme } from "./ThemeRegistry";
|
|
10
|
+
import { Checkbox } from "./Checkbox";
|
|
11
|
+
export const Checkmarks = (props) => {
|
|
12
|
+
const { onChange, label, ref: buttonRef, size, showArrowIcon = true, disabled = false, values = [], ...rest } = props;
|
|
13
|
+
const fontSize = size == "medium" ? 14 : 12;
|
|
14
|
+
const { wpTheme } = useWPTheme();
|
|
15
|
+
const [anchorEl, setAnchorEl] = useState(null);
|
|
16
|
+
const open = Boolean(anchorEl);
|
|
17
|
+
const [selectedValues, setSelectedValues] = useState(values);
|
|
18
|
+
const [buttonWidth, setButtonWidth] = useState("100px");
|
|
19
|
+
const [items, setItems] = useState();
|
|
20
|
+
const handleClick = (event) => {
|
|
21
|
+
setAnchorEl(event.currentTarget);
|
|
22
|
+
};
|
|
23
|
+
const handleClose = () => {
|
|
24
|
+
setAnchorEl(null);
|
|
25
|
+
};
|
|
26
|
+
const handleToggle = (value, item) => {
|
|
27
|
+
const newSelectedValues = selectedValues.includes(value)
|
|
28
|
+
? selectedValues.filter((v) => v !== value)
|
|
29
|
+
: [...selectedValues, value];
|
|
30
|
+
setSelectedValues(newSelectedValues);
|
|
31
|
+
const selectedItems = props.items.filter((item) => newSelectedValues.includes(item.value));
|
|
32
|
+
onChange(newSelectedValues, selectedItems);
|
|
33
|
+
};
|
|
34
|
+
useEffect(() => {
|
|
35
|
+
setSelectedValues(values);
|
|
36
|
+
}, [values]);
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
setItems(props.items);
|
|
39
|
+
}, [props.items]);
|
|
40
|
+
const buttonLabel = selectedValues.length > 0
|
|
41
|
+
? `${selectedValues.length} selected`
|
|
42
|
+
: label || "Select items";
|
|
43
|
+
return (_jsxs(Fragment, { children: [_jsxs(Button, { ...rest, id: "checkmarks-button", size: "small", disabled: disabled, "aria-controls": open ? "checkmarks-menu" : undefined, "aria-haspopup": "true", "aria-expanded": open ? "true" : undefined, onClick: handleClick, sx: {
|
|
44
|
+
textTransform: "none",
|
|
45
|
+
border: "1px solid",
|
|
46
|
+
borderColor: wpTheme.border.color,
|
|
47
|
+
justifyContent: "space-between",
|
|
48
|
+
height: size == "medium" ? 32 : 24,
|
|
49
|
+
backgroundColor: wpTheme.background.color,
|
|
50
|
+
color: wpTheme.text.color,
|
|
51
|
+
...rest.sx,
|
|
52
|
+
}, ref: (ref) => {
|
|
53
|
+
if (ref) {
|
|
54
|
+
setButtonWidth(ref.clientWidth + "px");
|
|
55
|
+
if (buttonRef) {
|
|
56
|
+
buttonRef.current = ref;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}, children: [_jsx(Typography, { fontSize: fontSize, sx: {
|
|
60
|
+
...(disabled ? { opacity: 0.5 } : {}),
|
|
61
|
+
}, children: buttonLabel }), disabled === false && (_jsxs(_Fragment, { children: [showArrowIcon && !open && _jsx(ArrowDropDownIcon, { fontSize: "small" }), showArrowIcon && open && _jsx(ArrowDropUpIcon, { fontSize: "small" })] }))] }), _jsx(Menu, { id: "checkmarks-menu", anchorEl: anchorEl, open: disabled === true ? false : open, onClose: handleClose, sx: {
|
|
62
|
+
width: "100%",
|
|
63
|
+
}, children: items?.map((item, index) => {
|
|
64
|
+
const isChecked = selectedValues.includes(item.value);
|
|
65
|
+
return (_jsxs(MenuItem, { onClick: (e) => {
|
|
66
|
+
handleToggle(item.value, item);
|
|
67
|
+
}, sx: {
|
|
68
|
+
width: buttonWidth,
|
|
69
|
+
}, children: [_jsx(Checkbox, { checked: isChecked, size: size, sx: {
|
|
70
|
+
padding: 0,
|
|
71
|
+
marginRight: 1,
|
|
72
|
+
} }), _jsx(Typography, { fontSize: fontSize, sx: {
|
|
73
|
+
minHeight: size == "medium" ? 20 : 16,
|
|
74
|
+
}, component: "div", children: item.label })] }, index));
|
|
75
|
+
}) })] }, label));
|
|
76
|
+
};
|
package/DraggableBox.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ import { SxProps } from "@mui/material";
|
|
|
17
17
|
type SlotSxProps = {
|
|
18
18
|
header?: SxProps;
|
|
19
19
|
title?: SxProps;
|
|
20
|
+
content?: SxProps;
|
|
20
21
|
border?: {
|
|
21
22
|
width?: number;
|
|
22
23
|
color?: string;
|
|
@@ -39,6 +40,7 @@ export declare const DraggableBox: (props: {
|
|
|
39
40
|
zIndexLayer?: number;
|
|
40
41
|
placement?: "target" | "left";
|
|
41
42
|
resizable?: boolean;
|
|
43
|
+
onResize?: (width: number, height: number, event?: Event) => void;
|
|
42
44
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
43
45
|
export {};
|
|
44
46
|
//# sourceMappingURL=DraggableBox.d.ts.map
|
package/DraggableBox.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DraggableBox.d.ts","sourceRoot":"","sources":["../src/DraggableBox.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,EACZ,SAAS,EAKV,MAAM,OAAO,CAAC;AACf,OAAO,EAAmB,OAAO,EAAE,MAAM,eAAe,CAAC;AAOzD,KAAK,WAAW,GAAG;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,OAAO;IAClC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,CAAC,EAAE;QACP,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC1B,SAAS,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC1C,GAAG,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACpC,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC9B,SAAS,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"DraggableBox.d.ts","sourceRoot":"","sources":["../src/DraggableBox.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,EACZ,SAAS,EAKV,MAAM,OAAO,CAAC;AACf,OAAO,EAAmB,OAAO,EAAE,MAAM,eAAe,CAAC;AAOzD,KAAK,WAAW,GAAG;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE;QACP,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH,CAAC;AAEF,eAAO,MAAM,YAAY,GAAI,OAAO;IAClC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,YAAY,CAAC;IACtB,MAAM,CAAC,EAAE;QACP,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,GAAG,CAAC,EAAE,MAAM,CAAC;KACd,CAAC;IACF,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;IAC1B,SAAS,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IAC1C,GAAG,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACpC,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;IAC9B,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC;CACnE,4CA4cA,CAAC"}
|
package/DraggableBox.js
CHANGED
|
@@ -21,7 +21,7 @@ import { Background } from "./Background";
|
|
|
21
21
|
import { Portal } from "./portal";
|
|
22
22
|
export const DraggableBox = (props) => {
|
|
23
23
|
// Destructure props
|
|
24
|
-
const { children, targetRef, ref: selfRef, title, size, onClose, open, sx, slotSxProps, offset: initialOffset = {}, zIndexLayer = 0, placement = "left", resizable = false, } = props;
|
|
24
|
+
const { children, targetRef, ref: selfRef, title, size, onClose, open, sx, slotSxProps, offset: initialOffset = {}, zIndexLayer = 0, placement = "left", resizable = false, onResize, } = props;
|
|
25
25
|
// Provide default offset values for the box
|
|
26
26
|
const { left = 0, top = 0 } = initialOffset;
|
|
27
27
|
// Reference to the draggable box DOM element
|
|
@@ -43,6 +43,13 @@ export const DraggableBox = (props) => {
|
|
|
43
43
|
width: 0,
|
|
44
44
|
height: 0,
|
|
45
45
|
});
|
|
46
|
+
/**
|
|
47
|
+
* Updates the box size and triggers the onResize callback.
|
|
48
|
+
*/
|
|
49
|
+
const updateBoxSize = useCallback((width, height, event) => {
|
|
50
|
+
setBoxSize({ width, height });
|
|
51
|
+
onResize?.(width, height, event);
|
|
52
|
+
}, [onResize]);
|
|
46
53
|
/**
|
|
47
54
|
* Ensures the new position is within the browser window bounds.
|
|
48
55
|
* Returns null if the position would place the box partially off-screen.
|
|
@@ -142,7 +149,7 @@ export const DraggableBox = (props) => {
|
|
|
142
149
|
if (isResizing.includes("top")) {
|
|
143
150
|
newHeight = Math.max(200, resizeStart.height - deltaY);
|
|
144
151
|
}
|
|
145
|
-
|
|
152
|
+
updateBoxSize(newWidth, newHeight, e);
|
|
146
153
|
}
|
|
147
154
|
};
|
|
148
155
|
// Called when the mouse is released. Ends the dragging session.
|
|
@@ -184,8 +191,8 @@ export const DraggableBox = (props) => {
|
|
|
184
191
|
if (direction.includes("bottom") || direction.includes("top")) {
|
|
185
192
|
newHeight = Math.max(200, newHeight + delta);
|
|
186
193
|
}
|
|
187
|
-
|
|
188
|
-
}, [boxSize.width, boxSize.height]);
|
|
194
|
+
updateBoxSize(newWidth, newHeight, e.nativeEvent);
|
|
195
|
+
}, [boxSize.width, boxSize.height, updateBoxSize]);
|
|
189
196
|
/**
|
|
190
197
|
* Subscribes to mousemove and mouseup while dragging or resizing; unsubscribes otherwise.
|
|
191
198
|
* This ensures we only respond to these events when necessary.
|
|
@@ -203,7 +210,7 @@ export const DraggableBox = (props) => {
|
|
|
203
210
|
window.removeEventListener("mousemove", handleMouseMove);
|
|
204
211
|
window.removeEventListener("mouseup", handleMouseUp);
|
|
205
212
|
};
|
|
206
|
-
}, [isDragging, isResizing, offset, resizeStart]);
|
|
213
|
+
}, [isDragging, isResizing, offset, resizeStart, updateBoxSize]);
|
|
207
214
|
/**
|
|
208
215
|
* Observes changes to the box size and repositions if part of the box
|
|
209
216
|
* moves off-screen. This keeps the box fully visible upon resizing.
|
|
@@ -272,7 +279,9 @@ export const DraggableBox = (props) => {
|
|
|
272
279
|
"&:hover": {
|
|
273
280
|
bgcolor: "action.hover",
|
|
274
281
|
},
|
|
275
|
-
}, children: _jsx(CloseIcon, { fontSize: "small" }) })] }), _jsx(Box, {
|
|
282
|
+
}, children: _jsx(CloseIcon, { fontSize: "small" }) })] }), _jsx(Box, { sx: {
|
|
283
|
+
...slotSxProps?.content,
|
|
284
|
+
}, children: children }), resizable && (_jsxs(_Fragment, { children: [_jsx(Box, { sx: {
|
|
276
285
|
position: "absolute",
|
|
277
286
|
right: 0,
|
|
278
287
|
top: 0,
|
package/ListBase.d.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { SxProps } from "@mui/material";
|
|
2
|
+
import { JSX, RefObject } from "react";
|
|
3
|
+
export type ListItemType<T = string> = {
|
|
4
|
+
index: number;
|
|
5
|
+
value: T;
|
|
6
|
+
label: string;
|
|
7
|
+
ref?: RefObject<HTMLElement | null>;
|
|
8
|
+
};
|
|
9
|
+
type DisplayType = "vertical" | "horizontal" | "grid" | "horizontal-fit";
|
|
10
|
+
type ListItemEventHandlers<T = string> = {
|
|
11
|
+
onClick?: (item: ListItemType<T>, event: React.MouseEvent) => void;
|
|
12
|
+
onMouseDown?: (item: ListItemType<T>, event: React.MouseEvent) => void;
|
|
13
|
+
onMouseUp?: (item: ListItemType<T>, event: React.MouseEvent) => void;
|
|
14
|
+
onMouseEnter?: (item: ListItemType<T>, event: React.MouseEvent) => void;
|
|
15
|
+
onMouseLeave?: (item: ListItemType<T>, event: React.MouseEvent) => void;
|
|
16
|
+
onDoubleClick?: (item: ListItemType<T>, event: React.MouseEvent) => void;
|
|
17
|
+
onContextMenu?: (item: ListItemType<T>, event: React.MouseEvent) => void;
|
|
18
|
+
onMouseOver?: (item: ListItemType<T>, event: React.MouseEvent) => void;
|
|
19
|
+
};
|
|
20
|
+
export declare const ListItem: (props: {
|
|
21
|
+
item: ListItemType<any>;
|
|
22
|
+
index: number;
|
|
23
|
+
size: "small" | "medium";
|
|
24
|
+
dataAttributes?: Record<string, string | number>;
|
|
25
|
+
sx?: SxProps;
|
|
26
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
27
|
+
export type ListBaseProps<T = string> = {
|
|
28
|
+
items: {
|
|
29
|
+
value: T;
|
|
30
|
+
label: string;
|
|
31
|
+
}[];
|
|
32
|
+
size?: "small" | "medium";
|
|
33
|
+
sx?: SxProps;
|
|
34
|
+
displayType?: DisplayType;
|
|
35
|
+
renderItem?: (item: ListItemType<T>) => JSX.Element;
|
|
36
|
+
onDelete?: (index: number) => void;
|
|
37
|
+
onEdit?: (index: number) => void;
|
|
38
|
+
editable?: boolean;
|
|
39
|
+
onClick?: (item: ListItemType<T>, event: React.MouseEvent) => void;
|
|
40
|
+
onMouseDown?: (item: ListItemType<T>, event: React.MouseEvent) => void;
|
|
41
|
+
itemEventHandlers?: ListItemEventHandlers<T>;
|
|
42
|
+
getItemSx?: (item: ListItemType<T>, index: number) => SxProps;
|
|
43
|
+
dataAttributes?: Record<string, string | number>;
|
|
44
|
+
slotSxProps?: {
|
|
45
|
+
listItem?: SxProps;
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
export declare const ListBase: <T extends any = string>(props: ListBaseProps<T>) => import("react/jsx-runtime").JSX.Element;
|
|
49
|
+
export {};
|
|
50
|
+
//# sourceMappingURL=ListBase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListBase.d.ts","sourceRoot":"","sources":["../src/ListBase.tsx"],"names":[],"mappings":"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"}
|
package/ListBase.js
ADDED
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, IconButton, List as MuiList, ListItem as MuiListItem, } from "@mui/material";
|
|
3
|
+
import { Typography } from "./Typography";
|
|
4
|
+
import { createContext, useContext, useRef, useState, } from "react";
|
|
5
|
+
import { Close } from "@mui/icons-material";
|
|
6
|
+
import EditIcon from "@mui/icons-material/Edit";
|
|
7
|
+
import { useWPTheme } from "./ThemeRegistry";
|
|
8
|
+
const ListContext = createContext({});
|
|
9
|
+
export const ListItem = (props) => {
|
|
10
|
+
const { item, index, size, dataAttributes, sx } = props;
|
|
11
|
+
const ref = useRef(null);
|
|
12
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
13
|
+
const { displayType, renderItem, onDelete, onEdit, itemEventHandlers, getItemSx, slotSxProps, editable, } = useContext(ListContext);
|
|
14
|
+
const { wpTheme } = useWPTheme();
|
|
15
|
+
const handleEvent = (handler) => {
|
|
16
|
+
return handler
|
|
17
|
+
? (event) => handler(item, event)
|
|
18
|
+
: undefined;
|
|
19
|
+
};
|
|
20
|
+
const handleMouseEnter = (event) => {
|
|
21
|
+
setIsHovered(true);
|
|
22
|
+
itemEventHandlers?.onMouseEnter?.(item, event);
|
|
23
|
+
};
|
|
24
|
+
const handleMouseLeave = (event) => {
|
|
25
|
+
setIsHovered(false);
|
|
26
|
+
itemEventHandlers?.onMouseLeave?.(item, event);
|
|
27
|
+
};
|
|
28
|
+
const customSx = {
|
|
29
|
+
...(getItemSx ? getItemSx(item, index) : {}),
|
|
30
|
+
...(slotSxProps?.listItem || {}),
|
|
31
|
+
...sx,
|
|
32
|
+
};
|
|
33
|
+
return (_jsxs(MuiListItem, { ref: ref, value: item.value, onClick: handleEvent(itemEventHandlers?.onClick), onMouseDown: handleEvent(itemEventHandlers?.onMouseDown), onMouseUp: handleEvent(itemEventHandlers?.onMouseUp), onMouseEnter: handleMouseEnter, onMouseLeave: handleMouseLeave, onDoubleClick: handleEvent(itemEventHandlers?.onDoubleClick), onContextMenu: handleEvent(itemEventHandlers?.onContextMenu), onMouseOver: handleEvent(itemEventHandlers?.onMouseOver), ...(dataAttributes || {}), sx: {
|
|
34
|
+
position: "relative",
|
|
35
|
+
"&:hover": {
|
|
36
|
+
backgroundColor: wpTheme.background.hoverColor,
|
|
37
|
+
},
|
|
38
|
+
border: (theme) => `1px solid ${theme.palette.divider}`,
|
|
39
|
+
p: 0,
|
|
40
|
+
width: displayType === "horizontal" ? "auto" : "100%",
|
|
41
|
+
display: "flex",
|
|
42
|
+
...customSx,
|
|
43
|
+
}, children: [_jsx(Box, { sx: { flexGrow: 1, display: "flex", alignItems: "center" }, children: renderItem ? (renderItem(item)) : (_jsx(Typography, { size: size, sx: {
|
|
44
|
+
p: 0.5,
|
|
45
|
+
}, children: item.label })) }), (onEdit || editable) && isHovered && (_jsx(IconButton, { size: "small", sx: {
|
|
46
|
+
height: "100%",
|
|
47
|
+
}, onMouseDown: (e) => {
|
|
48
|
+
onEdit && e.stopPropagation();
|
|
49
|
+
onEdit?.(index);
|
|
50
|
+
}, children: _jsx(EditIcon, { sx: {
|
|
51
|
+
fontSize: size === "small" ? "small" : "medium",
|
|
52
|
+
} }) })), onDelete && (_jsx(IconButton, { size: "small", sx: {
|
|
53
|
+
height: "100%",
|
|
54
|
+
}, onMouseDown: (e) => {
|
|
55
|
+
e.stopPropagation();
|
|
56
|
+
console.log("Removing item at index", index);
|
|
57
|
+
onDelete?.(index);
|
|
58
|
+
}, children: _jsx(Close, { sx: {
|
|
59
|
+
fontSize: size === "small" ? "small" : "medium",
|
|
60
|
+
} }) }))] }));
|
|
61
|
+
};
|
|
62
|
+
export const ListBase = (props) => {
|
|
63
|
+
const { items, size = "small", displayType = "vertical", renderItem, onDelete, onEdit, onClick, onMouseDown, itemEventHandlers, getItemSx, dataAttributes, slotSxProps, editable = false, } = props;
|
|
64
|
+
const listItems = items.map((item, index) => ({
|
|
65
|
+
index,
|
|
66
|
+
value: item.value,
|
|
67
|
+
label: item.label,
|
|
68
|
+
}));
|
|
69
|
+
let sx = {};
|
|
70
|
+
if (displayType === "horizontal") {
|
|
71
|
+
sx = {
|
|
72
|
+
display: "flex",
|
|
73
|
+
flexDirection: "row",
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
else if (displayType === "horizontal-fit") {
|
|
77
|
+
sx = {
|
|
78
|
+
display: "flex",
|
|
79
|
+
flexDirection: "row",
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
else if (displayType === "grid") {
|
|
83
|
+
sx = {
|
|
84
|
+
display: "grid",
|
|
85
|
+
gridTemplateColumns: "repeat(auto-fill, minmax(100px, 1fr))",
|
|
86
|
+
gap: 1,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
// Merge standalone onClick/onMouseDown/onMouseOver with itemEventHandlers
|
|
90
|
+
const mergedEventHandlers = {
|
|
91
|
+
...itemEventHandlers,
|
|
92
|
+
onClick: onClick || itemEventHandlers?.onClick,
|
|
93
|
+
onMouseDown: onMouseDown || itemEventHandlers?.onMouseDown,
|
|
94
|
+
};
|
|
95
|
+
return (_jsx(ListContext.Provider, { value: {
|
|
96
|
+
items: listItems,
|
|
97
|
+
displayType,
|
|
98
|
+
renderItem: renderItem,
|
|
99
|
+
onDelete,
|
|
100
|
+
onEdit,
|
|
101
|
+
itemEventHandlers: mergedEventHandlers,
|
|
102
|
+
getItemSx: getItemSx,
|
|
103
|
+
slotSxProps,
|
|
104
|
+
editable,
|
|
105
|
+
}, children: _jsx(MuiList, { sx: { ...sx, ...props.sx }, children: listItems.map((item, index) => (_jsx(ListItem, { item: item, index: index, size: size, dataAttributes: dataAttributes, sx: slotSxProps?.listItem }, item.index))) }) }));
|
|
106
|
+
};
|
package/SortableList.d.ts
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
import { SxProps } from "@mui/material";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
value: T;
|
|
6
|
-
label: string;
|
|
7
|
-
ref: RefObject<HTMLElement | null>;
|
|
8
|
-
};
|
|
2
|
+
import { ListItemType } from "./ListBase";
|
|
3
|
+
import { JSX } from "react";
|
|
4
|
+
export type SortableListItemType<T = string> = ListItemType<T>;
|
|
9
5
|
type DisplayType = "vertical" | "horizontal" | "grid" | "horizontal-fit";
|
|
10
6
|
export type SortableListProps = Parameters<typeof SortableList>[0];
|
|
11
7
|
export declare const SortableList: <T extends any = string>(props: {
|
package/SortableList.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SortableList.d.ts","sourceRoot":"","sources":["../src/SortableList.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"SortableList.d.ts","sourceRoot":"","sources":["../src/SortableList.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAO,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,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,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC;CACvD,4CA2MA,CAAC"}
|
package/SortableList.js
CHANGED
|
@@ -1,130 +1,9 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
2
|
-
import { Box
|
|
3
|
-
import { Typography } from "./Typography";
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Box } from "@mui/material";
|
|
4
3
|
import { useMouseMove } from "./hooks/use-mouse-move";
|
|
5
|
-
import { createContext,
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
import { useWPTheme } from "./ThemeRegistry";
|
|
9
|
-
const Context = createContext({});
|
|
10
|
-
const SortableListItem = (props) => {
|
|
11
|
-
const { index, size } = props;
|
|
12
|
-
const ref = useRef(null);
|
|
13
|
-
const { findItem, swapItems, refPos, targetRef, items, displayType, renderItem, onDelete, onEdit, } = useContext(Context);
|
|
14
|
-
const item = findItem(index);
|
|
15
|
-
const { wpTheme } = useWPTheme();
|
|
16
|
-
const handleDeltaChange = (e, delta) => {
|
|
17
|
-
// Get the rect of the item being dragged
|
|
18
|
-
const rect = ref.current?.getBoundingClientRect();
|
|
19
|
-
if (!rect) {
|
|
20
|
-
console.warn("SortableListItem ref is not set or does not have a bounding rect.");
|
|
21
|
-
return;
|
|
22
|
-
}
|
|
23
|
-
let newY, newX, transformValues = [];
|
|
24
|
-
//if (displayType === "horizontal" || displayType === "grid") {
|
|
25
|
-
if (["horizontal", "horizontal-fit", "grid"].includes(displayType)) {
|
|
26
|
-
newX = refPos.current.x + delta.x; // Update the X position relative to the element
|
|
27
|
-
transformValues.push(`translateX(${newX}px)`);
|
|
28
|
-
refPos.current.x = newX; // Update the reference position
|
|
29
|
-
}
|
|
30
|
-
if (displayType === "vertical" || displayType === "grid") {
|
|
31
|
-
newY = refPos.current.y + delta.y; // Update the Y position relative to the element
|
|
32
|
-
transformValues.push(`translateY(${newY}px)`);
|
|
33
|
-
refPos.current.y = newY; // Update the reference position
|
|
34
|
-
}
|
|
35
|
-
ref.current.style.transform = transformValues.join(" ");
|
|
36
|
-
// Get elements on the currrent moust position
|
|
37
|
-
const elementsAtPoint = document.elementsFromPoint(e.clientX, e.clientY);
|
|
38
|
-
// timeoutId.current = setTimeout(() => {
|
|
39
|
-
for (const element of elementsAtPoint) {
|
|
40
|
-
// get the data attribute
|
|
41
|
-
const itemIndex = element.getAttribute("data-sortable-item-index");
|
|
42
|
-
if (!itemIndex) {
|
|
43
|
-
// Skip if the element does not have the data attribute
|
|
44
|
-
continue;
|
|
45
|
-
}
|
|
46
|
-
// Skip if itemValue is null or the same as the current value
|
|
47
|
-
if (itemIndex === String(index)) {
|
|
48
|
-
if (targetRef.current) {
|
|
49
|
-
targetRef.current.style.removeProperty("border");
|
|
50
|
-
targetRef.current = null;
|
|
51
|
-
}
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
const itemIndexNumber = parseInt(itemIndex);
|
|
55
|
-
if (itemIndexNumber < 0 || itemIndexNumber >= items.length) {
|
|
56
|
-
continue; // Skip invalid indices
|
|
57
|
-
}
|
|
58
|
-
if (targetRef.current) {
|
|
59
|
-
targetRef.current.style.removeProperty("border");
|
|
60
|
-
}
|
|
61
|
-
targetRef.current = element;
|
|
62
|
-
targetRef.current.style.border = "1px solid red";
|
|
63
|
-
break;
|
|
64
|
-
}
|
|
65
|
-
};
|
|
66
|
-
const handleMouseDown = (e) => {
|
|
67
|
-
console.log("mouse down on item", index, e);
|
|
68
|
-
const rect = ref.current?.getBoundingClientRect();
|
|
69
|
-
if (rect) {
|
|
70
|
-
refPos.current.y = e.clientY - rect.top - rect.height / 2; // Calculate the initial Y offset
|
|
71
|
-
refPos.current.x = 0;
|
|
72
|
-
ref.current.style.zIndex = "100000"; // Bring the item to the front
|
|
73
|
-
ref.current.style.transform = `translate(${refPos.current.x}px, ${refPos.current.y}px)`;
|
|
74
|
-
}
|
|
75
|
-
};
|
|
76
|
-
const handleMouseUp = (e) => {
|
|
77
|
-
refPos.current.y = 0; // Reset Y position
|
|
78
|
-
refPos.current.x = 0; // Reset X position
|
|
79
|
-
ref.current?.style.removeProperty("transform");
|
|
80
|
-
ref.current?.style.removeProperty("z-index");
|
|
81
|
-
if (targetRef.current) {
|
|
82
|
-
const toItemIndex = targetRef.current.getAttribute("data-sortable-item-index");
|
|
83
|
-
swapItems(e, index, toItemIndex ? parseInt(toItemIndex) : -1);
|
|
84
|
-
targetRef.current?.style.removeProperty("border");
|
|
85
|
-
targetRef.current = null;
|
|
86
|
-
}
|
|
87
|
-
};
|
|
88
|
-
const { initMouseMove } = useMouseMove({
|
|
89
|
-
onDeltaChange: handleDeltaChange,
|
|
90
|
-
onMouseUp: handleMouseUp,
|
|
91
|
-
onMouseDown: handleMouseDown,
|
|
92
|
-
cursor: "grabbing",
|
|
93
|
-
threshold: 1,
|
|
94
|
-
});
|
|
95
|
-
// Assign the ref to the item
|
|
96
|
-
useEffect(() => {
|
|
97
|
-
item.ref = ref;
|
|
98
|
-
}, [item]);
|
|
99
|
-
return (_jsxs(ListItem, { ref: ref, value: item.value, onMouseDown: initMouseMove(ref), "data-sortable-item-index": index, sx: {
|
|
100
|
-
position: "relative",
|
|
101
|
-
cursor: "move",
|
|
102
|
-
"&:hover": {
|
|
103
|
-
backgroundColor: wpTheme.background.hoverColor, // Use theme hover color
|
|
104
|
-
},
|
|
105
|
-
border: (theme) => `1px solid ${theme.palette.divider}`,
|
|
106
|
-
p: 0,
|
|
107
|
-
width: displayType === "horizontal" ? "auto" : "100%",
|
|
108
|
-
display: "flex",
|
|
109
|
-
}, children: [_jsx(Box, { sx: { flexGrow: 1, display: "flex", alignItems: "center" }, children: renderItem ? (renderItem(item)) : (_jsx(Typography, { size: size, sx: {
|
|
110
|
-
p: 0.5,
|
|
111
|
-
}, children: item.label })) }), onEdit && (_jsx(IconButton, { size: "small", sx: {
|
|
112
|
-
height: "100%",
|
|
113
|
-
}, onMouseDown: (e) => {
|
|
114
|
-
e.stopPropagation();
|
|
115
|
-
onEdit?.(index);
|
|
116
|
-
}, children: _jsx(EditIcon, { sx: {
|
|
117
|
-
fontSize: size === "small" ? "small" : "medium",
|
|
118
|
-
} }) })), onDelete && (_jsx(IconButton, { size: "small", sx: {
|
|
119
|
-
height: "100%",
|
|
120
|
-
}, onMouseDown: (e) => {
|
|
121
|
-
e.stopPropagation();
|
|
122
|
-
console.log("Removing item at index", index);
|
|
123
|
-
onDelete?.(index);
|
|
124
|
-
}, children: _jsx(Close, { sx: {
|
|
125
|
-
fontSize: size === "small" ? "small" : "medium",
|
|
126
|
-
} }) }))] }));
|
|
127
|
-
};
|
|
4
|
+
import { createContext, useEffect, useRef, useState, } from "react";
|
|
5
|
+
import { ListBase } from "./ListBase";
|
|
6
|
+
const SortableContext = createContext({});
|
|
128
7
|
export const SortableList = (props) => {
|
|
129
8
|
const { size = "small", displayType = "vertical", renderItem, onDelete, onChange, onEdit, } = props;
|
|
130
9
|
const [items, setItems] = useState([]);
|
|
@@ -133,7 +12,7 @@ export const SortableList = (props) => {
|
|
|
133
12
|
const findItem = (index) => {
|
|
134
13
|
return items.find((item) => item.index === index);
|
|
135
14
|
};
|
|
136
|
-
const swapItems = (
|
|
15
|
+
const swapItems = (_e, fromIndex, toIndex) => {
|
|
137
16
|
console.log("Swapping items", fromIndex, toIndex);
|
|
138
17
|
if (fromIndex < 0 ||
|
|
139
18
|
toIndex < 0 ||
|
|
@@ -141,18 +20,16 @@ export const SortableList = (props) => {
|
|
|
141
20
|
toIndex >= items.length) {
|
|
142
21
|
return;
|
|
143
22
|
}
|
|
144
|
-
// Swap items in the state
|
|
145
23
|
const newItems = [...items];
|
|
146
24
|
const temp = newItems[fromIndex];
|
|
147
25
|
newItems[fromIndex] = newItems[toIndex];
|
|
148
26
|
newItems[toIndex] = temp;
|
|
149
|
-
newItems[fromIndex].index = fromIndex;
|
|
150
|
-
newItems[toIndex].index = toIndex;
|
|
27
|
+
newItems[fromIndex].index = fromIndex;
|
|
28
|
+
newItems[toIndex].index = toIndex;
|
|
151
29
|
setItems(newItems);
|
|
152
30
|
onChange?.(newItems);
|
|
153
31
|
};
|
|
154
32
|
useEffect(() => {
|
|
155
|
-
// Initialize items from the enum prop
|
|
156
33
|
const initialItems = props.enum.map((item, index) => ({
|
|
157
34
|
index,
|
|
158
35
|
value: item.value,
|
|
@@ -181,15 +58,90 @@ export const SortableList = (props) => {
|
|
|
181
58
|
gap: 1,
|
|
182
59
|
};
|
|
183
60
|
}
|
|
184
|
-
|
|
61
|
+
const renderSortableItem = (item) => {
|
|
62
|
+
return (_jsx(Box, { ref: item.ref, onMouseDown: initMouseMoveForItem(item), "data-sortable-item-index": item.index, sx: {
|
|
63
|
+
cursor: "move",
|
|
64
|
+
}, children: renderItem ? renderItem(item) : item.label }));
|
|
65
|
+
};
|
|
66
|
+
const initMouseMoveForItem = (item) => {
|
|
67
|
+
const ref = item.ref;
|
|
68
|
+
if (!ref)
|
|
69
|
+
return () => { };
|
|
70
|
+
const handleDeltaChange = (e, delta) => {
|
|
71
|
+
const rect = ref.current?.getBoundingClientRect();
|
|
72
|
+
if (!rect)
|
|
73
|
+
return;
|
|
74
|
+
let newY;
|
|
75
|
+
let newX;
|
|
76
|
+
const transformValues = [];
|
|
77
|
+
if (["horizontal", "horizontal-fit", "grid"].includes(displayType)) {
|
|
78
|
+
newX = refPos.current.x + delta.x;
|
|
79
|
+
transformValues.push(`translateX(${newX}px)`);
|
|
80
|
+
refPos.current.x = newX;
|
|
81
|
+
}
|
|
82
|
+
if (displayType === "vertical" || displayType === "grid") {
|
|
83
|
+
newY = refPos.current.y + delta.y;
|
|
84
|
+
transformValues.push(`translateY(${newY}px)`);
|
|
85
|
+
refPos.current.y = newY;
|
|
86
|
+
}
|
|
87
|
+
ref.current.style.transform = transformValues.join(" ");
|
|
88
|
+
const elementsAtPoint = document.elementsFromPoint(e.clientX, e.clientY);
|
|
89
|
+
for (const element of elementsAtPoint) {
|
|
90
|
+
const itemIndex = element.getAttribute("data-sortable-item-index");
|
|
91
|
+
if (!itemIndex || itemIndex === String(item.index)) {
|
|
92
|
+
if (targetRef.current) {
|
|
93
|
+
targetRef.current.style.removeProperty("border");
|
|
94
|
+
targetRef.current = null;
|
|
95
|
+
}
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const itemIndexNumber = parseInt(itemIndex);
|
|
99
|
+
if (itemIndexNumber < 0 || itemIndexNumber >= items.length)
|
|
100
|
+
continue;
|
|
101
|
+
if (targetRef.current) {
|
|
102
|
+
targetRef.current.style.removeProperty("border");
|
|
103
|
+
}
|
|
104
|
+
targetRef.current = element;
|
|
105
|
+
targetRef.current.style.border = "1px solid red";
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
const handleMouseDown = (e) => {
|
|
110
|
+
const rect = ref.current?.getBoundingClientRect();
|
|
111
|
+
if (rect) {
|
|
112
|
+
refPos.current.y = e.clientY - rect.top - rect.height / 2;
|
|
113
|
+
refPos.current.x = 0;
|
|
114
|
+
ref.current.style.zIndex = "100000";
|
|
115
|
+
ref.current.style.transform = `translate(${refPos.current.x}px, ${refPos.current.y}px)`;
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
const handleMouseUp = (e) => {
|
|
119
|
+
refPos.current.y = 0;
|
|
120
|
+
refPos.current.x = 0;
|
|
121
|
+
ref.current?.style.removeProperty("transform");
|
|
122
|
+
ref.current?.style.removeProperty("z-index");
|
|
123
|
+
if (targetRef.current) {
|
|
124
|
+
const toItemIndex = targetRef.current.getAttribute("data-sortable-item-index");
|
|
125
|
+
swapItems(e, item.index, toItemIndex ? parseInt(toItemIndex) : -1);
|
|
126
|
+
targetRef.current?.style.removeProperty("border");
|
|
127
|
+
targetRef.current = null;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
const { initMouseMove } = useMouseMove({
|
|
131
|
+
onDeltaChange: handleDeltaChange,
|
|
132
|
+
onMouseUp: handleMouseUp,
|
|
133
|
+
onMouseDown: handleMouseDown,
|
|
134
|
+
cursor: "grabbing",
|
|
135
|
+
threshold: 1,
|
|
136
|
+
});
|
|
137
|
+
return initMouseMove(ref);
|
|
138
|
+
};
|
|
139
|
+
return (_jsx(SortableContext.Provider, { value: {
|
|
185
140
|
items,
|
|
186
141
|
findItem: findItem,
|
|
187
142
|
swapItems,
|
|
188
143
|
refPos,
|
|
189
144
|
targetRef,
|
|
190
145
|
displayType,
|
|
191
|
-
|
|
192
|
-
onDelete,
|
|
193
|
-
onEdit,
|
|
194
|
-
}, children: _jsx(List, { sx: { ...sx, ...props.sx }, children: items.map((item, index) => (_jsx(SortableListItem, { index: index, size: size }, item.index))) }) }));
|
|
146
|
+
}, children: _jsx(ListBase, { items: items, size: size, sx: { ...sx, ...props.sx }, displayType: displayType, renderItem: renderSortableItem, onDelete: onDelete, onEdit: onEdit }) }));
|
|
195
147
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rnaga/wp-next-ui",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.9",
|
|
4
4
|
"scripts": {
|
|
5
5
|
"build": "node ../../scripts/build-ui.mjs",
|
|
6
6
|
"release-old": "node ../../scripts/release.mjs",
|
|
@@ -17,7 +17,9 @@
|
|
|
17
17
|
"license": "MIT",
|
|
18
18
|
"description": "User Interface components for WP Next",
|
|
19
19
|
"dependencies": {
|
|
20
|
+
"@mui/icons-material": "^7.3.6",
|
|
20
21
|
"@mui/material": "^7.0.2",
|
|
22
|
+
"@mui/x-date-pickers": "^7.29.4",
|
|
21
23
|
"@rnaga/wp-next-core": "^1.0"
|
|
22
24
|
},
|
|
23
25
|
"devDependencies": {
|