@etsoo/materialui 1.6.11 → 1.6.13

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.
@@ -1,5 +1,8 @@
1
1
  import { ButtonProps } from "@mui/material/Button";
2
- import { DataTypes, IdType } from "@etsoo/shared";
2
+ import { IdType } from "@etsoo/shared";
3
+ import { GridSize } from "@mui/material/Grid";
4
+ import { DnDSortableListProps } from "./DnDSortableList";
5
+ import { ResponsiveStyleValue } from "./ResponsiveStyleValue";
3
6
  type DnDItemType = {
4
7
  id: IdType;
5
8
  };
@@ -23,7 +26,7 @@ export type ButtonPopupCheckboxProps<D extends DnDItemType> = Omit<ButtonProps,
23
26
  /**
24
27
  * Label field in items
25
28
  */
26
- labelField: DataTypes.Keys<D>;
29
+ labelField: DnDSortableListProps<D>["labelField"];
27
30
  /**
28
31
  * Label formatter
29
32
  * @param item Item to be formatted
@@ -63,6 +66,10 @@ export type ButtonPopupCheckboxProps<D extends DnDItemType> = Omit<ButtonProps,
63
66
  * The field is required or not
64
67
  */
65
68
  required?: boolean;
69
+ /**
70
+ * Item size
71
+ */
72
+ itemSize?: ResponsiveStyleValue<GridSize>;
66
73
  /**
67
74
  * Value
68
75
  */
@@ -19,10 +19,10 @@ const TextField_1 = __importDefault(require("@mui/material/TextField"));
19
19
  const FlexBox_1 = require("./FlexBox");
20
20
  const ReactApp_1 = require("./app/ReactApp");
21
21
  const FormLabel_1 = __importDefault(require("@mui/material/FormLabel"));
22
- const DnDList_1 = require("./DnDList");
22
+ const DnDSortableList_1 = require("./DnDSortableList");
23
23
  function ButtonPopupList(props) {
24
24
  // Destruct
25
- const { addSplitter = /\s*[,;]\s*/, value = [], items, labelField, labelFormatter, labels, onAdd, onValueChange } = props;
25
+ const { addSplitter = /\s*[,;]\s*/, value = [], items, itemSize = { xs: 12, md: 6, lx: 4 }, labelField, labelFormatter, labels, onAdd, onValueChange } = props;
26
26
  // Methods
27
27
  const dndRef = react_1.default.createRef();
28
28
  // Refs
@@ -40,18 +40,18 @@ function ButtonPopupList(props) {
40
40
  // Set selected ids
41
41
  setSelectedIdsHandler([...value]);
42
42
  }, [value]);
43
- return ((0, jsx_runtime_1.jsxs)(FlexBox_1.VBox, { gap: 2, children: [(0, jsx_runtime_1.jsx)(DnDList_1.DnDList, { component: Grid_1.default, componentProps: { container: true, spacing: 0 }, items: items, labelField: labelField, onFormChange: (items) => {
43
+ return ((0, jsx_runtime_1.jsxs)(FlexBox_1.VBox, { gap: 2, children: [(0, jsx_runtime_1.jsx)(DnDSortableList_1.DnDSortableList, { component: Grid_1.default, componentProps: { container: true, spacing: 0 }, items: items, labelField: labelField, onChange: (items) => {
44
44
  const ids = items
45
45
  .filter((item) => tempSelectedIds.current.includes(item.id))
46
46
  .map((item) => item.id);
47
47
  onValueChange(ids);
48
- }, itemRenderer: (item, index, nodeRef, actionNodeRef) => ((0, jsx_runtime_1.jsxs)(Grid_1.default, { size: { xs: 12, md: 6, lg: 4 }, display: "flex", justifyContent: "flex-start", alignItems: "center", gap: 1, ...nodeRef, children: [(0, jsx_runtime_1.jsx)(IconButton_1.default, { style: { cursor: "move" }, size: "small", title: labels?.dragIndicator, ...actionNodeRef, children: (0, jsx_runtime_1.jsx)(DragIndicator_1.default, {}) }), (0, jsx_runtime_1.jsx)(FormControlLabel_1.default, { control: (0, jsx_runtime_1.jsx)(Checkbox_1.default, { name: "item", value: item.id, checked: selectedIds.includes(item.id), onChange: (e) => {
48
+ }, itemRenderer: (item, style, { sortable: { index }, ref, handleRef }) => ((0, jsx_runtime_1.jsxs)(Grid_1.default, { size: itemSize, display: "flex", justifyContent: "flex-start", alignItems: "center", gap: 1, ref: ref, style: style, children: [(0, jsx_runtime_1.jsx)(IconButton_1.default, { style: { cursor: "move" }, size: "small", title: labels?.dragIndicator, ref: handleRef, children: (0, jsx_runtime_1.jsx)(DragIndicator_1.default, {}) }), (0, jsx_runtime_1.jsx)(FormControlLabel_1.default, { control: (0, jsx_runtime_1.jsx)(Checkbox_1.default, { name: "item", value: item.id, checked: selectedIds.includes(item.id), onChange: (e) => {
49
49
  const checked = e.target.checked;
50
50
  const newIds = [
51
51
  ...selectedIds.toggleItem(item.id, checked)
52
52
  ];
53
53
  setSelectedIdsHandler(newIds);
54
- } }), label: `${index + 1}. ${labelFormatter(item)}` })] })), height: 200, mRef: dndRef }), onAdd && ((0, jsx_runtime_1.jsxs)(FlexBox_1.HBox, { gap: 1, children: [(0, jsx_runtime_1.jsx)(TextField_1.default, { variant: "outlined", label: labels?.more, fullWidth: true, inputRef: inputRef }), (0, jsx_runtime_1.jsx)(Button_1.default, { sx: { width: "120px" }, variant: "contained", startIcon: (0, jsx_runtime_1.jsx)(Add_1.default, {}), size: "small", onClick: async () => {
54
+ } }), label: `${index + 1}. ${labelFormatter(item)}` })] })), mRef: dndRef }), onAdd && ((0, jsx_runtime_1.jsxs)(FlexBox_1.HBox, { gap: 1, children: [(0, jsx_runtime_1.jsx)(TextField_1.default, { variant: "outlined", label: labels?.more, fullWidth: true, inputRef: inputRef }), (0, jsx_runtime_1.jsx)(Button_1.default, { sx: { width: "120px" }, variant: "contained", startIcon: (0, jsx_runtime_1.jsx)(Add_1.default, {}), size: "small", onClick: async () => {
55
55
  if (inputRef.current == null)
56
56
  return;
57
57
  const input = inputRef.current.value.trim();
@@ -81,7 +81,9 @@ function ButtonPopupCheckbox(props) {
81
81
  // App
82
82
  const app = (0, ReactApp_1.useRequiredAppContext)();
83
83
  // Destruct
84
- const { addSplitter, value = [], inputName, label, labelEnd, labelFormatter = (data) => {
84
+ const { addSplitter, value = [], inputName, itemSize, label, labelEnd, labelFormatter = (data) => {
85
+ if (typeof labelField === "function")
86
+ return labelField(data);
85
87
  if (labelField in data) {
86
88
  return data[labelField];
87
89
  }
@@ -128,7 +130,7 @@ function ButtonPopupCheckbox(props) {
128
130
  setSelectedIds(ids);
129
131
  onValueChange?.(ids);
130
132
  },
131
- inputs: ((0, jsx_runtime_1.jsx)(ButtonPopupList, { addSplitter: addSplitter, value: selectedIds, items: items, labelFormatter: labelFormatter, labelField: labelField, labels: labels, onAdd: onAdd, onValueChange: (ids) => {
133
+ inputs: ((0, jsx_runtime_1.jsx)(ButtonPopupList, { addSplitter: addSplitter, value: selectedIds, items: items, labelFormatter: labelFormatter, labelField: labelField, itemSize: itemSize, labels: labels, onAdd: onAdd, onValueChange: (ids) => {
132
134
  tempSelectedIds.current = ids;
133
135
  } })),
134
136
  fullScreen: app.smDown
@@ -1,5 +1,7 @@
1
1
  import { ButtonProps } from "@mui/material/Button";
2
2
  import { DataTypes, IdType } from "@etsoo/shared";
3
+ import { GridSize } from "@mui/material/Grid";
4
+ import { ResponsiveStyleValue } from "./ResponsiveStyleValue";
3
5
  type DnDItemType = {
4
6
  id: IdType;
5
7
  };
@@ -63,6 +65,10 @@ export type ButtonPopupRadioProps<D extends DnDItemType> = Omit<ButtonProps, "ch
63
65
  * The field is required or not
64
66
  */
65
67
  required?: boolean;
68
+ /**
69
+ * Item size
70
+ */
71
+ itemSize?: ResponsiveStyleValue<GridSize>;
66
72
  /**
67
73
  * Value
68
74
  */
@@ -21,7 +21,7 @@ const FlexBox_1 = require("./FlexBox");
21
21
  const ReactApp_1 = require("./app/ReactApp");
22
22
  function ButtonPopupList(props) {
23
23
  // Destruct
24
- const { addSplitter = /\s*[,;]\s*/, value, items, labelFormatter, labels, onAdd, onValueChange } = props;
24
+ const { addSplitter = /\s*[,;]\s*/, value, items, labelFormatter, labels, itemSize = { xs: 12, md: 6, lx: 4 }, onAdd, onValueChange } = props;
25
25
  // Ref
26
26
  const inputRef = react_1.default.useRef(null);
27
27
  // State
@@ -38,7 +38,7 @@ function ButtonPopupList(props) {
38
38
  : undefined;
39
39
  setCurrentValue(value);
40
40
  onValueChange(value);
41
- }, children: (0, jsx_runtime_1.jsx)(Grid_1.default, { container: true, spacing: 0, children: items.map((item) => ((0, jsx_runtime_1.jsx)(Grid_1.default, { size: { xs: 12, md: 6, lg: 4 }, display: "flex", justifyContent: "flex-start", alignItems: "center", gap: 1, children: (0, jsx_runtime_1.jsx)(FormControlLabel_1.default, { control: (0, jsx_runtime_1.jsx)(Radio_1.default, { value: item.id }), label: `${labelFormatter(item)}` }) }, item.id))) }) }), onAdd && ((0, jsx_runtime_1.jsxs)(FlexBox_1.HBox, { gap: 1, children: [(0, jsx_runtime_1.jsx)(TextField_1.default, { variant: "outlined", label: labels?.more, fullWidth: true, inputRef: inputRef }), (0, jsx_runtime_1.jsx)(Button_1.default, { sx: { width: "120px" }, variant: "contained", startIcon: (0, jsx_runtime_1.jsx)(Add_1.default, {}), size: "small", onClick: async () => {
41
+ }, children: (0, jsx_runtime_1.jsx)(Grid_1.default, { container: true, spacing: 0, children: items.map((item) => ((0, jsx_runtime_1.jsx)(Grid_1.default, { size: itemSize, display: "flex", justifyContent: "flex-start", alignItems: "center", gap: 1, children: (0, jsx_runtime_1.jsx)(FormControlLabel_1.default, { control: (0, jsx_runtime_1.jsx)(Radio_1.default, { value: item.id }), label: `${labelFormatter(item)}` }) }, item.id))) }) }), onAdd && ((0, jsx_runtime_1.jsxs)(FlexBox_1.HBox, { gap: 1, children: [(0, jsx_runtime_1.jsx)(TextField_1.default, { variant: "outlined", label: labels?.more, fullWidth: true, inputRef: inputRef }), (0, jsx_runtime_1.jsx)(Button_1.default, { sx: { width: "120px" }, variant: "contained", startIcon: (0, jsx_runtime_1.jsx)(Add_1.default, {}), size: "small", onClick: async () => {
42
42
  if (inputRef.current == null)
43
43
  return;
44
44
  const input = inputRef.current.value.trim();
@@ -66,7 +66,7 @@ function ButtonPopupRadio(props) {
66
66
  // App
67
67
  const app = (0, ReactApp_1.useRequiredAppContext)();
68
68
  // Destruct
69
- const { addSplitter, inputName, label, labelEnd, labelFormatter = (data) => {
69
+ const { addSplitter, inputName, itemSize, label, labelEnd, labelFormatter = (data) => {
70
70
  if (labelField in data) {
71
71
  return data[labelField];
72
72
  }
@@ -115,7 +115,7 @@ function ButtonPopupRadio(props) {
115
115
  setCurrentValue(id);
116
116
  onValueChange?.(id);
117
117
  },
118
- inputs: ((0, jsx_runtime_1.jsx)(ButtonPopupList, { addSplitter: addSplitter, value: currentValue, items: items, labelFormatter: labelFormatter, labels: labels, onAdd: onAdd, onValueChange: (id) => {
118
+ inputs: ((0, jsx_runtime_1.jsx)(ButtonPopupList, { addSplitter: addSplitter, value: currentValue, items: items, itemSize: itemSize, labelFormatter: labelFormatter, labels: labels, onAdd: onAdd, onValueChange: (id) => {
119
119
  tempSelectedId.current = id;
120
120
  } })),
121
121
  fullScreen: app.smDown
@@ -0,0 +1,105 @@
1
+ import { DataTypes, IdType } from "@etsoo/shared";
2
+ import React from "react";
3
+ import { CSSProperties, Theme } from "@mui/material/styles";
4
+ import { useSortable } from "@dnd-kit/react/sortable";
5
+ import { DragDropEvents } from "@dnd-kit/react";
6
+ /**
7
+ * DnD sortable item default style
8
+ * @param index Item index
9
+ * @param isDragging Is dragging
10
+ * @param theme Theme
11
+ * @returns Style
12
+ */
13
+ export declare const DnDSortableItemStyle: (index: number, isDragging: boolean, theme: Theme) => {
14
+ padding: string;
15
+ transform: string;
16
+ zIndex: string | number;
17
+ boxShadow: string;
18
+ background: string;
19
+ };
20
+ /**
21
+ * DnD sortable list forward ref
22
+ */
23
+ export interface DnDSortableListRef<D extends object> {
24
+ /**
25
+ * Add item
26
+ * @param item New item
27
+ */
28
+ addItem(item: D): void;
29
+ /**
30
+ * Add items
31
+ * @param items items
32
+ */
33
+ addItems(items: D[]): void;
34
+ /**
35
+ * Delete item
36
+ * @param index Item index
37
+ */
38
+ deleteItem(index: number): void;
39
+ /**
40
+ * Edit item
41
+ * @param newItem New item
42
+ * @param index Index
43
+ */
44
+ editItem(newItem: D, index: number): boolean;
45
+ /**
46
+ * Get all items
47
+ */
48
+ getItems(): D[];
49
+ }
50
+ /**
51
+ * DnD sortable list props
52
+ */
53
+ export type DnDSortableListProps<D extends object, E extends React.ElementType = React.ElementType> = {
54
+ /**
55
+ * Component type to render the list into
56
+ * Default is React.Fragment
57
+ */
58
+ component?: E;
59
+ /**
60
+ * Component props
61
+ */
62
+ componentProps?: React.ComponentProps<E>;
63
+ /**
64
+ * List items
65
+ */
66
+ items: D[];
67
+ /**
68
+ * Id field
69
+ */
70
+ idField?: DataTypes.Keys<D> | ((item: D) => IdType);
71
+ /**
72
+ * Label field
73
+ */
74
+ labelField: DataTypes.Keys<D, string> | ((item: D) => string);
75
+ /**
76
+ * Methods ref
77
+ */
78
+ mRef?: React.Ref<DnDSortableListRef<D>>;
79
+ /**
80
+ * Item renderer
81
+ */
82
+ itemRenderer: (data: D, style: CSSProperties, state: ReturnType<typeof useSortable<D>>) => React.ReactElement;
83
+ /**
84
+ * Get list item style callback
85
+ */
86
+ itemStyle?: (index: number, isDragging: boolean) => CSSProperties;
87
+ /**
88
+ * Data change handler
89
+ */
90
+ onChange?: (items: D[]) => void;
91
+ /**
92
+ * Drag start handler
93
+ */
94
+ onDragStart?: (items: D[], event: Parameters<DragDropEvents["dragstart"]>[0]) => void;
95
+ /**
96
+ * Drag end handler
97
+ */
98
+ onDragEnd?: (items: D[], ...args: Parameters<DragDropEvents["dragend"]>) => void;
99
+ };
100
+ /**
101
+ * DnD sortable list component
102
+ * @param props Props
103
+ * @returns Component
104
+ */
105
+ export declare function DnDSortableList<D extends object, E extends React.ElementType = React.ElementType>(props: DnDSortableListProps<D, E>): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,151 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.DnDSortableItemStyle = void 0;
7
+ exports.DnDSortableList = DnDSortableList;
8
+ const jsx_runtime_1 = require("react/jsx-runtime");
9
+ const react_1 = __importDefault(require("react"));
10
+ const styles_1 = require("@mui/material/styles");
11
+ const sortable_1 = require("@dnd-kit/react/sortable");
12
+ const react_2 = require("@dnd-kit/react");
13
+ /**
14
+ * DnD sortable item default style
15
+ * @param index Item index
16
+ * @param isDragging Is dragging
17
+ * @param theme Theme
18
+ * @returns Style
19
+ */
20
+ const DnDSortableItemStyle = (index, isDragging, theme) => ({
21
+ padding: theme.spacing(1),
22
+ transform: isDragging ? "scale(1.03)" : "none",
23
+ zIndex: isDragging ? 1 : "auto",
24
+ boxShadow: isDragging
25
+ ? `-1px 0 8px 0 ${theme.palette.grey[400]}, 0px 8px 8px 0 ${theme.palette.grey[200]}`
26
+ : "none",
27
+ background: isDragging
28
+ ? theme.palette.primary.light
29
+ : index % 2 === 0
30
+ ? theme.palette.grey[100]
31
+ : theme.palette.grey[50]
32
+ });
33
+ exports.DnDSortableItemStyle = DnDSortableItemStyle;
34
+ function SortableItem(props) {
35
+ const theme = (0, styles_1.useTheme)();
36
+ const { id, data, index, itemRenderer, itemStyle = (index, isDragging) => (0, exports.DnDSortableItemStyle)(index, isDragging, theme) } = props;
37
+ const state = (0, sortable_1.useSortable)({ id, data, index });
38
+ const style = itemStyle(index, state.isDragging);
39
+ return itemRenderer(data, style, state);
40
+ }
41
+ /**
42
+ * DnD sortable list component
43
+ * @param props Props
44
+ * @returns Component
45
+ */
46
+ function DnDSortableList(props) {
47
+ // Destruct
48
+ const Component = props.component || react_1.default.Fragment;
49
+ const { componentProps, idField, itemRenderer, itemStyle, labelField, mRef, onChange, onDragStart, onDragEnd } = props;
50
+ const idFn = typeof idField === "function"
51
+ ? idField
52
+ : (item) => !idField
53
+ ? Reflect.get(item, "id")
54
+ : item[idField];
55
+ const labelFn = react_1.default.useCallback(typeof labelField === "function"
56
+ ? labelField
57
+ : (item) => item[labelField], [labelField]);
58
+ // States
59
+ const [items, setItems] = react_1.default.useState([]);
60
+ react_1.default.useEffect(() => {
61
+ setItems(props.items);
62
+ }, [props.items]);
63
+ const changeItems = react_1.default.useCallback((newItems) => {
64
+ // Possible to alter items with the handler
65
+ onChange?.(newItems);
66
+ // Update state
67
+ setItems(newItems);
68
+ }, [onChange]);
69
+ // Methods
70
+ react_1.default.useImperativeHandle(mRef, () => {
71
+ return {
72
+ addItem(newItem) {
73
+ // Existence check
74
+ if (items.some((item) => labelFn(item) === labelFn(newItem))) {
75
+ return false;
76
+ }
77
+ // Clone
78
+ const newItems = [newItem, ...items];
79
+ // Update the state
80
+ changeItems(newItems);
81
+ return true;
82
+ },
83
+ addItems(inputItems) {
84
+ // Clone
85
+ const newItems = [...items];
86
+ // Insert items
87
+ inputItems.forEach((newItem) => {
88
+ // Existence check
89
+ if (newItems.some((item) => labelFn(item) === labelFn(newItem))) {
90
+ return;
91
+ }
92
+ newItems.push(newItem);
93
+ });
94
+ // Update the state
95
+ changeItems(newItems);
96
+ return newItems.length - items.length;
97
+ },
98
+ editItem(newItem, index) {
99
+ // Existence check
100
+ const newIndex = items.findIndex((item) => labelFn(item) === labelFn(newItem));
101
+ if (newIndex >= 0 && newIndex !== index) {
102
+ // Label field is the same with a different item
103
+ return false;
104
+ }
105
+ // Clone
106
+ const newItems = [...items];
107
+ // Remove the item
108
+ newItems.splice(index, 1, newItem);
109
+ // Update the state
110
+ changeItems(newItems);
111
+ return true;
112
+ },
113
+ deleteItem(index) {
114
+ // Clone
115
+ const newItems = [...items];
116
+ // Remove the item
117
+ newItems.splice(index, 1);
118
+ // Update the state
119
+ changeItems(newItems);
120
+ },
121
+ getItems() {
122
+ return items;
123
+ }
124
+ };
125
+ }, [items, labelFn, changeItems]);
126
+ function handleDragEnd(...args) {
127
+ // Event
128
+ const event = args[0];
129
+ // Cancelled
130
+ if (event.canceled)
131
+ return;
132
+ if ((0, sortable_1.isSortableOperation)(event.operation) && event.operation.source) {
133
+ const { initialIndex, index } = event.operation.source;
134
+ if (initialIndex === index)
135
+ return;
136
+ // Clone
137
+ const newItems = [...items];
138
+ // Removed item
139
+ const [removed] = newItems.splice(initialIndex, 1);
140
+ // Insert to the destination index
141
+ newItems.splice(index, 0, removed);
142
+ changeItems(newItems);
143
+ // Drag end handler
144
+ onDragEnd?.(newItems, ...args);
145
+ }
146
+ }
147
+ return ((0, jsx_runtime_1.jsx)(react_2.DragDropProvider, { onDragStart: (event) => onDragStart?.(items, event), onDragEnd: (event, manager) => handleDragEnd(event, manager), children: (0, jsx_runtime_1.jsx)(Component, { ...componentProps, children: items.map((item, index) => {
148
+ const id = idFn(item);
149
+ return ((0, jsx_runtime_1.jsx)(SortableItem, { id: id, index: index, data: item, itemRenderer: itemRenderer, itemStyle: itemStyle }, id));
150
+ }) }) }));
151
+ }
@@ -54,7 +54,7 @@ export * from "./DataLoadField";
54
54
  export * from "./DataSteps";
55
55
  export * from "./DataTable";
56
56
  export * from "./DialogButton";
57
- export * from "./DnDList";
57
+ export * from "./DnDSortableList";
58
58
  export * from "./DownUpButton";
59
59
  export * from "./DraggablePaperComponent";
60
60
  export * from "./EmailInput";
package/lib/cjs/index.js CHANGED
@@ -70,7 +70,7 @@ __exportStar(require("./DataLoadField"), exports);
70
70
  __exportStar(require("./DataSteps"), exports);
71
71
  __exportStar(require("./DataTable"), exports);
72
72
  __exportStar(require("./DialogButton"), exports);
73
- __exportStar(require("./DnDList"), exports);
73
+ __exportStar(require("./DnDSortableList"), exports);
74
74
  __exportStar(require("./DownUpButton"), exports);
75
75
  __exportStar(require("./DraggablePaperComponent"), exports);
76
76
  __exportStar(require("./EmailInput"), exports);
@@ -1,5 +1,8 @@
1
1
  import { ButtonProps } from "@mui/material/Button";
2
- import { DataTypes, IdType } from "@etsoo/shared";
2
+ import { IdType } from "@etsoo/shared";
3
+ import { GridSize } from "@mui/material/Grid";
4
+ import { DnDSortableListProps } from "./DnDSortableList";
5
+ import { ResponsiveStyleValue } from "./ResponsiveStyleValue";
3
6
  type DnDItemType = {
4
7
  id: IdType;
5
8
  };
@@ -23,7 +26,7 @@ export type ButtonPopupCheckboxProps<D extends DnDItemType> = Omit<ButtonProps,
23
26
  /**
24
27
  * Label field in items
25
28
  */
26
- labelField: DataTypes.Keys<D>;
29
+ labelField: DnDSortableListProps<D>["labelField"];
27
30
  /**
28
31
  * Label formatter
29
32
  * @param item Item to be formatted
@@ -63,6 +66,10 @@ export type ButtonPopupCheckboxProps<D extends DnDItemType> = Omit<ButtonProps,
63
66
  * The field is required or not
64
67
  */
65
68
  required?: boolean;
69
+ /**
70
+ * Item size
71
+ */
72
+ itemSize?: ResponsiveStyleValue<GridSize>;
66
73
  /**
67
74
  * Value
68
75
  */
@@ -13,10 +13,10 @@ import TextField from "@mui/material/TextField";
13
13
  import { HBox, VBox } from "./FlexBox";
14
14
  import { useRequiredAppContext } from "./app/ReactApp";
15
15
  import FormLabel from "@mui/material/FormLabel";
16
- import { DnDList } from "./DnDList";
16
+ import { DnDSortableList } from "./DnDSortableList";
17
17
  function ButtonPopupList(props) {
18
18
  // Destruct
19
- const { addSplitter = /\s*[,;]\s*/, value = [], items, labelField, labelFormatter, labels, onAdd, onValueChange } = props;
19
+ const { addSplitter = /\s*[,;]\s*/, value = [], items, itemSize = { xs: 12, md: 6, lx: 4 }, labelField, labelFormatter, labels, onAdd, onValueChange } = props;
20
20
  // Methods
21
21
  const dndRef = React.createRef();
22
22
  // Refs
@@ -34,18 +34,18 @@ function ButtonPopupList(props) {
34
34
  // Set selected ids
35
35
  setSelectedIdsHandler([...value]);
36
36
  }, [value]);
37
- return (_jsxs(VBox, { gap: 2, children: [_jsx(DnDList, { component: Grid, componentProps: { container: true, spacing: 0 }, items: items, labelField: labelField, onFormChange: (items) => {
37
+ return (_jsxs(VBox, { gap: 2, children: [_jsx(DnDSortableList, { component: Grid, componentProps: { container: true, spacing: 0 }, items: items, labelField: labelField, onChange: (items) => {
38
38
  const ids = items
39
39
  .filter((item) => tempSelectedIds.current.includes(item.id))
40
40
  .map((item) => item.id);
41
41
  onValueChange(ids);
42
- }, itemRenderer: (item, index, nodeRef, actionNodeRef) => (_jsxs(Grid, { size: { xs: 12, md: 6, lg: 4 }, display: "flex", justifyContent: "flex-start", alignItems: "center", gap: 1, ...nodeRef, children: [_jsx(IconButton, { style: { cursor: "move" }, size: "small", title: labels?.dragIndicator, ...actionNodeRef, children: _jsx(DragIndicatorIcon, {}) }), _jsx(FormControlLabel, { control: _jsx(Checkbox, { name: "item", value: item.id, checked: selectedIds.includes(item.id), onChange: (e) => {
42
+ }, itemRenderer: (item, style, { sortable: { index }, ref, handleRef }) => (_jsxs(Grid, { size: itemSize, display: "flex", justifyContent: "flex-start", alignItems: "center", gap: 1, ref: ref, style: style, children: [_jsx(IconButton, { style: { cursor: "move" }, size: "small", title: labels?.dragIndicator, ref: handleRef, children: _jsx(DragIndicatorIcon, {}) }), _jsx(FormControlLabel, { control: _jsx(Checkbox, { name: "item", value: item.id, checked: selectedIds.includes(item.id), onChange: (e) => {
43
43
  const checked = e.target.checked;
44
44
  const newIds = [
45
45
  ...selectedIds.toggleItem(item.id, checked)
46
46
  ];
47
47
  setSelectedIdsHandler(newIds);
48
- } }), label: `${index + 1}. ${labelFormatter(item)}` })] })), height: 200, mRef: dndRef }), onAdd && (_jsxs(HBox, { gap: 1, children: [_jsx(TextField, { variant: "outlined", label: labels?.more, fullWidth: true, inputRef: inputRef }), _jsx(Button, { sx: { width: "120px" }, variant: "contained", startIcon: _jsx(AddIcon, {}), size: "small", onClick: async () => {
48
+ } }), label: `${index + 1}. ${labelFormatter(item)}` })] })), mRef: dndRef }), onAdd && (_jsxs(HBox, { gap: 1, children: [_jsx(TextField, { variant: "outlined", label: labels?.more, fullWidth: true, inputRef: inputRef }), _jsx(Button, { sx: { width: "120px" }, variant: "contained", startIcon: _jsx(AddIcon, {}), size: "small", onClick: async () => {
49
49
  if (inputRef.current == null)
50
50
  return;
51
51
  const input = inputRef.current.value.trim();
@@ -75,7 +75,9 @@ export function ButtonPopupCheckbox(props) {
75
75
  // App
76
76
  const app = useRequiredAppContext();
77
77
  // Destruct
78
- const { addSplitter, value = [], inputName, label, labelEnd, labelFormatter = (data) => {
78
+ const { addSplitter, value = [], inputName, itemSize, label, labelEnd, labelFormatter = (data) => {
79
+ if (typeof labelField === "function")
80
+ return labelField(data);
79
81
  if (labelField in data) {
80
82
  return data[labelField];
81
83
  }
@@ -122,7 +124,7 @@ export function ButtonPopupCheckbox(props) {
122
124
  setSelectedIds(ids);
123
125
  onValueChange?.(ids);
124
126
  },
125
- inputs: (_jsx(ButtonPopupList, { addSplitter: addSplitter, value: selectedIds, items: items, labelFormatter: labelFormatter, labelField: labelField, labels: labels, onAdd: onAdd, onValueChange: (ids) => {
127
+ inputs: (_jsx(ButtonPopupList, { addSplitter: addSplitter, value: selectedIds, items: items, labelFormatter: labelFormatter, labelField: labelField, itemSize: itemSize, labels: labels, onAdd: onAdd, onValueChange: (ids) => {
126
128
  tempSelectedIds.current = ids;
127
129
  } })),
128
130
  fullScreen: app.smDown
@@ -1,5 +1,7 @@
1
1
  import { ButtonProps } from "@mui/material/Button";
2
2
  import { DataTypes, IdType } from "@etsoo/shared";
3
+ import { GridSize } from "@mui/material/Grid";
4
+ import { ResponsiveStyleValue } from "./ResponsiveStyleValue";
3
5
  type DnDItemType = {
4
6
  id: IdType;
5
7
  };
@@ -63,6 +65,10 @@ export type ButtonPopupRadioProps<D extends DnDItemType> = Omit<ButtonProps, "ch
63
65
  * The field is required or not
64
66
  */
65
67
  required?: boolean;
68
+ /**
69
+ * Item size
70
+ */
71
+ itemSize?: ResponsiveStyleValue<GridSize>;
66
72
  /**
67
73
  * Value
68
74
  */
@@ -15,7 +15,7 @@ import { HBox, VBox } from "./FlexBox";
15
15
  import { useRequiredAppContext } from "./app/ReactApp";
16
16
  function ButtonPopupList(props) {
17
17
  // Destruct
18
- const { addSplitter = /\s*[,;]\s*/, value, items, labelFormatter, labels, onAdd, onValueChange } = props;
18
+ const { addSplitter = /\s*[,;]\s*/, value, items, labelFormatter, labels, itemSize = { xs: 12, md: 6, lx: 4 }, onAdd, onValueChange } = props;
19
19
  // Ref
20
20
  const inputRef = React.useRef(null);
21
21
  // State
@@ -32,7 +32,7 @@ function ButtonPopupList(props) {
32
32
  : undefined;
33
33
  setCurrentValue(value);
34
34
  onValueChange(value);
35
- }, children: _jsx(Grid, { container: true, spacing: 0, children: items.map((item) => (_jsx(Grid, { size: { xs: 12, md: 6, lg: 4 }, display: "flex", justifyContent: "flex-start", alignItems: "center", gap: 1, children: _jsx(FormControlLabel, { control: _jsx(Radio, { value: item.id }), label: `${labelFormatter(item)}` }) }, item.id))) }) }), onAdd && (_jsxs(HBox, { gap: 1, children: [_jsx(TextField, { variant: "outlined", label: labels?.more, fullWidth: true, inputRef: inputRef }), _jsx(Button, { sx: { width: "120px" }, variant: "contained", startIcon: _jsx(AddIcon, {}), size: "small", onClick: async () => {
35
+ }, children: _jsx(Grid, { container: true, spacing: 0, children: items.map((item) => (_jsx(Grid, { size: itemSize, display: "flex", justifyContent: "flex-start", alignItems: "center", gap: 1, children: _jsx(FormControlLabel, { control: _jsx(Radio, { value: item.id }), label: `${labelFormatter(item)}` }) }, item.id))) }) }), onAdd && (_jsxs(HBox, { gap: 1, children: [_jsx(TextField, { variant: "outlined", label: labels?.more, fullWidth: true, inputRef: inputRef }), _jsx(Button, { sx: { width: "120px" }, variant: "contained", startIcon: _jsx(AddIcon, {}), size: "small", onClick: async () => {
36
36
  if (inputRef.current == null)
37
37
  return;
38
38
  const input = inputRef.current.value.trim();
@@ -60,7 +60,7 @@ export function ButtonPopupRadio(props) {
60
60
  // App
61
61
  const app = useRequiredAppContext();
62
62
  // Destruct
63
- const { addSplitter, inputName, label, labelEnd, labelFormatter = (data) => {
63
+ const { addSplitter, inputName, itemSize, label, labelEnd, labelFormatter = (data) => {
64
64
  if (labelField in data) {
65
65
  return data[labelField];
66
66
  }
@@ -109,7 +109,7 @@ export function ButtonPopupRadio(props) {
109
109
  setCurrentValue(id);
110
110
  onValueChange?.(id);
111
111
  },
112
- inputs: (_jsx(ButtonPopupList, { addSplitter: addSplitter, value: currentValue, items: items, labelFormatter: labelFormatter, labels: labels, onAdd: onAdd, onValueChange: (id) => {
112
+ inputs: (_jsx(ButtonPopupList, { addSplitter: addSplitter, value: currentValue, items: items, itemSize: itemSize, labelFormatter: labelFormatter, labels: labels, onAdd: onAdd, onValueChange: (id) => {
113
113
  tempSelectedId.current = id;
114
114
  } })),
115
115
  fullScreen: app.smDown