@etsoo/materialui 1.5.31 → 1.5.33
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/lib/cjs/ListMultipler.d.ts +51 -0
- package/lib/cjs/ListMultipler.js +61 -0
- package/lib/cjs/html/HtmlDiv.js +16 -0
- package/lib/cjs/index.d.ts +1 -0
- package/lib/cjs/index.js +1 -0
- package/lib/mjs/ListMultipler.d.ts +51 -0
- package/lib/mjs/ListMultipler.js +55 -0
- package/lib/mjs/html/HtmlDiv.js +16 -0
- package/lib/mjs/index.d.ts +1 -0
- package/lib/mjs/index.js +1 -0
- package/package.json +4 -4
- package/src/ListMultipler.tsx +153 -0
- package/src/html/HtmlDiv.tsx +17 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { DataTypes, IdType } from "@etsoo/shared";
|
|
2
|
+
import { ListProps } from "@mui/material/List";
|
|
3
|
+
import { ListItemProps } from "@mui/material/ListItem";
|
|
4
|
+
import { ListItemTextProps } from "@mui/material/ListItemText";
|
|
5
|
+
type ListItemLabel<T extends object> = DataTypes.Keys<T, string | undefined> | ((item: T) => string | undefined);
|
|
6
|
+
/**
|
|
7
|
+
* List multipler component props
|
|
8
|
+
*/
|
|
9
|
+
export type ListMultiplerProps<T extends object> = ListProps & {
|
|
10
|
+
/**
|
|
11
|
+
* List data
|
|
12
|
+
*/
|
|
13
|
+
data: T[];
|
|
14
|
+
/**
|
|
15
|
+
* Id field name
|
|
16
|
+
*/
|
|
17
|
+
idField: DataTypes.Keys<T, IdType>;
|
|
18
|
+
/**
|
|
19
|
+
* Primary label field name or function
|
|
20
|
+
*/
|
|
21
|
+
primaryLabel: ListItemLabel<T>;
|
|
22
|
+
/**
|
|
23
|
+
* Secondary label field name or function
|
|
24
|
+
*/
|
|
25
|
+
secondaryLabel?: ListItemLabel<T>;
|
|
26
|
+
/**
|
|
27
|
+
* List item props
|
|
28
|
+
*/
|
|
29
|
+
listItemProps?: ListItemProps;
|
|
30
|
+
/**
|
|
31
|
+
* List item text props
|
|
32
|
+
*/
|
|
33
|
+
listItemTextProps?: Omit<ListItemTextProps, "primary" | "secondary">;
|
|
34
|
+
/**
|
|
35
|
+
* Input name
|
|
36
|
+
*/
|
|
37
|
+
name?: string;
|
|
38
|
+
/**
|
|
39
|
+
* On change event
|
|
40
|
+
* @param items The selected items
|
|
41
|
+
* @param ids The selected IDs
|
|
42
|
+
*/
|
|
43
|
+
onCheckItems?: (items: T[], ids: unknown[]) => void;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* List multipler component
|
|
47
|
+
* @param props Props
|
|
48
|
+
* @returns Component
|
|
49
|
+
*/
|
|
50
|
+
export declare function ListMultipler<T extends object>(props: ListMultiplerProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
51
|
+
export {};
|
|
@@ -0,0 +1,61 @@
|
|
|
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.ListMultipler = ListMultipler;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const Checkbox_1 = __importDefault(require("@mui/material/Checkbox"));
|
|
9
|
+
const List_1 = __importDefault(require("@mui/material/List"));
|
|
10
|
+
const ListItem_1 = __importDefault(require("@mui/material/ListItem"));
|
|
11
|
+
const ListItemButton_1 = __importDefault(require("@mui/material/ListItemButton"));
|
|
12
|
+
const ListItemIcon_1 = __importDefault(require("@mui/material/ListItemIcon"));
|
|
13
|
+
const ListItemText_1 = __importDefault(require("@mui/material/ListItemText"));
|
|
14
|
+
const react_1 = __importDefault(require("react"));
|
|
15
|
+
function GetListItemLabel(data, label) {
|
|
16
|
+
if (label == null)
|
|
17
|
+
return undefined;
|
|
18
|
+
if (typeof label === "function") {
|
|
19
|
+
return label(data);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
return data[label];
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* List multipler component
|
|
27
|
+
* @param props Props
|
|
28
|
+
* @returns Component
|
|
29
|
+
*/
|
|
30
|
+
function ListMultipler(props) {
|
|
31
|
+
// Destruct
|
|
32
|
+
const { data, idField, primaryLabel, secondaryLabel, listItemProps, listItemTextProps, name, onCheckItems, ...rest } = props;
|
|
33
|
+
// Refs
|
|
34
|
+
const initialized = react_1.default.useRef(false);
|
|
35
|
+
react_1.default.useEffect(() => {
|
|
36
|
+
initialized.current = true;
|
|
37
|
+
}, []);
|
|
38
|
+
// State
|
|
39
|
+
const [checked, setChecked] = react_1.default.useState([]);
|
|
40
|
+
const ids = react_1.default.useMemo(() => {
|
|
41
|
+
const ids = checked.map((u) => u[idField]);
|
|
42
|
+
if (onCheckItems && initialized.current) {
|
|
43
|
+
onCheckItems(checked, ids);
|
|
44
|
+
}
|
|
45
|
+
return ids;
|
|
46
|
+
}, [checked]);
|
|
47
|
+
function handleToggle(id) {
|
|
48
|
+
if (ids.includes(id)) {
|
|
49
|
+
setChecked((prev) => prev.filter((u) => u[idField] !== id));
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const item = data.find((u) => u[idField] === id);
|
|
53
|
+
if (item) {
|
|
54
|
+
setChecked((prev) => [...prev, item]);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const inputType = typeof ids[0] === "string" ? "text" : "number";
|
|
59
|
+
// Layout
|
|
60
|
+
return ((0, jsx_runtime_1.jsxs)(List_1.default, { ...rest, children: [name && ((0, jsx_runtime_1.jsx)("input", { type: inputType, style: { display: "none" }, name: name, value: ids.join(","), readOnly: true })), data.map((u) => ((0, jsx_runtime_1.jsx)(ListItem_1.default, { ...listItemProps, children: (0, jsx_runtime_1.jsxs)(ListItemButton_1.default, { dense: true, onClick: () => handleToggle(u[idField]), children: [(0, jsx_runtime_1.jsx)(ListItemIcon_1.default, { children: (0, jsx_runtime_1.jsx)(Checkbox_1.default, { edge: "start", disableRipple: true, checked: ids.includes(u[idField]) }) }), (0, jsx_runtime_1.jsx)(ListItemText_1.default, { primary: GetListItemLabel(u, primaryLabel), secondary: GetListItemLabel(u, secondaryLabel), ...listItemTextProps })] }) }, `${u[idField]}`)))] }));
|
|
61
|
+
}
|
package/lib/cjs/html/HtmlDiv.js
CHANGED
|
@@ -28,6 +28,22 @@ class HtmlDivElement extends HTMLElement {
|
|
|
28
28
|
connectedCallback() {
|
|
29
29
|
// Create a shadow root
|
|
30
30
|
const shadow = this.attachShadow({ mode: "open" });
|
|
31
|
+
// Default styles
|
|
32
|
+
// Comply with @etsoo/editor default styles
|
|
33
|
+
const style = document.createElement("style");
|
|
34
|
+
style.textContent = `
|
|
35
|
+
:host {
|
|
36
|
+
box-sizing: border-box;
|
|
37
|
+
}
|
|
38
|
+
img {
|
|
39
|
+
max-width: 100%;
|
|
40
|
+
}
|
|
41
|
+
pre {
|
|
42
|
+
background-color: #f3f3f3;
|
|
43
|
+
padding: 12px;
|
|
44
|
+
}
|
|
45
|
+
`;
|
|
46
|
+
shadow.appendChild(style);
|
|
31
47
|
// Create a wrapper element to hold the sanitized HTML content
|
|
32
48
|
const wrapper = document.createElement("div");
|
|
33
49
|
wrapper.style.cssText = this.displayStyle ?? "";
|
package/lib/cjs/index.d.ts
CHANGED
|
@@ -73,6 +73,7 @@ export * from "./LinkEx";
|
|
|
73
73
|
export * from "./ListChooser";
|
|
74
74
|
export * from "./ListItemRightIcon";
|
|
75
75
|
export * from "./ListMoreDisplay";
|
|
76
|
+
export * from "./ListMultipler";
|
|
76
77
|
export * from "./LoadingButton";
|
|
77
78
|
export * from "./MaskInput";
|
|
78
79
|
export * from "./MenuButton";
|
package/lib/cjs/index.js
CHANGED
|
@@ -89,6 +89,7 @@ __exportStar(require("./LinkEx"), exports);
|
|
|
89
89
|
__exportStar(require("./ListChooser"), exports);
|
|
90
90
|
__exportStar(require("./ListItemRightIcon"), exports);
|
|
91
91
|
__exportStar(require("./ListMoreDisplay"), exports);
|
|
92
|
+
__exportStar(require("./ListMultipler"), exports);
|
|
92
93
|
__exportStar(require("./LoadingButton"), exports);
|
|
93
94
|
__exportStar(require("./MaskInput"), exports);
|
|
94
95
|
__exportStar(require("./MenuButton"), exports);
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { DataTypes, IdType } from "@etsoo/shared";
|
|
2
|
+
import { ListProps } from "@mui/material/List";
|
|
3
|
+
import { ListItemProps } from "@mui/material/ListItem";
|
|
4
|
+
import { ListItemTextProps } from "@mui/material/ListItemText";
|
|
5
|
+
type ListItemLabel<T extends object> = DataTypes.Keys<T, string | undefined> | ((item: T) => string | undefined);
|
|
6
|
+
/**
|
|
7
|
+
* List multipler component props
|
|
8
|
+
*/
|
|
9
|
+
export type ListMultiplerProps<T extends object> = ListProps & {
|
|
10
|
+
/**
|
|
11
|
+
* List data
|
|
12
|
+
*/
|
|
13
|
+
data: T[];
|
|
14
|
+
/**
|
|
15
|
+
* Id field name
|
|
16
|
+
*/
|
|
17
|
+
idField: DataTypes.Keys<T, IdType>;
|
|
18
|
+
/**
|
|
19
|
+
* Primary label field name or function
|
|
20
|
+
*/
|
|
21
|
+
primaryLabel: ListItemLabel<T>;
|
|
22
|
+
/**
|
|
23
|
+
* Secondary label field name or function
|
|
24
|
+
*/
|
|
25
|
+
secondaryLabel?: ListItemLabel<T>;
|
|
26
|
+
/**
|
|
27
|
+
* List item props
|
|
28
|
+
*/
|
|
29
|
+
listItemProps?: ListItemProps;
|
|
30
|
+
/**
|
|
31
|
+
* List item text props
|
|
32
|
+
*/
|
|
33
|
+
listItemTextProps?: Omit<ListItemTextProps, "primary" | "secondary">;
|
|
34
|
+
/**
|
|
35
|
+
* Input name
|
|
36
|
+
*/
|
|
37
|
+
name?: string;
|
|
38
|
+
/**
|
|
39
|
+
* On change event
|
|
40
|
+
* @param items The selected items
|
|
41
|
+
* @param ids The selected IDs
|
|
42
|
+
*/
|
|
43
|
+
onCheckItems?: (items: T[], ids: unknown[]) => void;
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* List multipler component
|
|
47
|
+
* @param props Props
|
|
48
|
+
* @returns Component
|
|
49
|
+
*/
|
|
50
|
+
export declare function ListMultipler<T extends object>(props: ListMultiplerProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
51
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import Checkbox from "@mui/material/Checkbox";
|
|
3
|
+
import List from "@mui/material/List";
|
|
4
|
+
import ListItem from "@mui/material/ListItem";
|
|
5
|
+
import ListItemButton from "@mui/material/ListItemButton";
|
|
6
|
+
import ListItemIcon from "@mui/material/ListItemIcon";
|
|
7
|
+
import ListItemText from "@mui/material/ListItemText";
|
|
8
|
+
import React from "react";
|
|
9
|
+
function GetListItemLabel(data, label) {
|
|
10
|
+
if (label == null)
|
|
11
|
+
return undefined;
|
|
12
|
+
if (typeof label === "function") {
|
|
13
|
+
return label(data);
|
|
14
|
+
}
|
|
15
|
+
else {
|
|
16
|
+
return data[label];
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* List multipler component
|
|
21
|
+
* @param props Props
|
|
22
|
+
* @returns Component
|
|
23
|
+
*/
|
|
24
|
+
export function ListMultipler(props) {
|
|
25
|
+
// Destruct
|
|
26
|
+
const { data, idField, primaryLabel, secondaryLabel, listItemProps, listItemTextProps, name, onCheckItems, ...rest } = props;
|
|
27
|
+
// Refs
|
|
28
|
+
const initialized = React.useRef(false);
|
|
29
|
+
React.useEffect(() => {
|
|
30
|
+
initialized.current = true;
|
|
31
|
+
}, []);
|
|
32
|
+
// State
|
|
33
|
+
const [checked, setChecked] = React.useState([]);
|
|
34
|
+
const ids = React.useMemo(() => {
|
|
35
|
+
const ids = checked.map((u) => u[idField]);
|
|
36
|
+
if (onCheckItems && initialized.current) {
|
|
37
|
+
onCheckItems(checked, ids);
|
|
38
|
+
}
|
|
39
|
+
return ids;
|
|
40
|
+
}, [checked]);
|
|
41
|
+
function handleToggle(id) {
|
|
42
|
+
if (ids.includes(id)) {
|
|
43
|
+
setChecked((prev) => prev.filter((u) => u[idField] !== id));
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
const item = data.find((u) => u[idField] === id);
|
|
47
|
+
if (item) {
|
|
48
|
+
setChecked((prev) => [...prev, item]);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const inputType = typeof ids[0] === "string" ? "text" : "number";
|
|
53
|
+
// Layout
|
|
54
|
+
return (_jsxs(List, { ...rest, children: [name && (_jsx("input", { type: inputType, style: { display: "none" }, name: name, value: ids.join(","), readOnly: true })), data.map((u) => (_jsx(ListItem, { ...listItemProps, children: _jsxs(ListItemButton, { dense: true, onClick: () => handleToggle(u[idField]), children: [_jsx(ListItemIcon, { children: _jsx(Checkbox, { edge: "start", disableRipple: true, checked: ids.includes(u[idField]) }) }), _jsx(ListItemText, { primary: GetListItemLabel(u, primaryLabel), secondary: GetListItemLabel(u, secondaryLabel), ...listItemTextProps })] }) }, `${u[idField]}`)))] }));
|
|
55
|
+
}
|
package/lib/mjs/html/HtmlDiv.js
CHANGED
|
@@ -25,6 +25,22 @@ class HtmlDivElement extends HTMLElement {
|
|
|
25
25
|
connectedCallback() {
|
|
26
26
|
// Create a shadow root
|
|
27
27
|
const shadow = this.attachShadow({ mode: "open" });
|
|
28
|
+
// Default styles
|
|
29
|
+
// Comply with @etsoo/editor default styles
|
|
30
|
+
const style = document.createElement("style");
|
|
31
|
+
style.textContent = `
|
|
32
|
+
:host {
|
|
33
|
+
box-sizing: border-box;
|
|
34
|
+
}
|
|
35
|
+
img {
|
|
36
|
+
max-width: 100%;
|
|
37
|
+
}
|
|
38
|
+
pre {
|
|
39
|
+
background-color: #f3f3f3;
|
|
40
|
+
padding: 12px;
|
|
41
|
+
}
|
|
42
|
+
`;
|
|
43
|
+
shadow.appendChild(style);
|
|
28
44
|
// Create a wrapper element to hold the sanitized HTML content
|
|
29
45
|
const wrapper = document.createElement("div");
|
|
30
46
|
wrapper.style.cssText = this.displayStyle ?? "";
|
package/lib/mjs/index.d.ts
CHANGED
|
@@ -73,6 +73,7 @@ export * from "./LinkEx";
|
|
|
73
73
|
export * from "./ListChooser";
|
|
74
74
|
export * from "./ListItemRightIcon";
|
|
75
75
|
export * from "./ListMoreDisplay";
|
|
76
|
+
export * from "./ListMultipler";
|
|
76
77
|
export * from "./LoadingButton";
|
|
77
78
|
export * from "./MaskInput";
|
|
78
79
|
export * from "./MenuButton";
|
package/lib/mjs/index.js
CHANGED
|
@@ -73,6 +73,7 @@ export * from "./LinkEx";
|
|
|
73
73
|
export * from "./ListChooser";
|
|
74
74
|
export * from "./ListItemRightIcon";
|
|
75
75
|
export * from "./ListMoreDisplay";
|
|
76
|
+
export * from "./ListMultipler";
|
|
76
77
|
export * from "./LoadingButton";
|
|
77
78
|
export * from "./MaskInput";
|
|
78
79
|
export * from "./MenuButton";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@etsoo/materialui",
|
|
3
|
-
"version": "1.5.
|
|
3
|
+
"version": "1.5.33",
|
|
4
4
|
"description": "TypeScript Material-UI Implementation",
|
|
5
5
|
"main": "lib/cjs/index.js",
|
|
6
6
|
"module": "lib/mjs/index.js",
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"@dnd-kit/sortable": "^10.0.0",
|
|
41
41
|
"@emotion/react": "^11.14.0",
|
|
42
42
|
"@emotion/styled": "^11.14.0",
|
|
43
|
-
"@etsoo/appscript": "^1.6.
|
|
43
|
+
"@etsoo/appscript": "^1.6.26",
|
|
44
44
|
"@etsoo/notificationbase": "^1.1.60",
|
|
45
45
|
"@etsoo/react": "^1.8.40",
|
|
46
46
|
"@etsoo/shared": "^1.2.69",
|
|
@@ -81,9 +81,9 @@
|
|
|
81
81
|
"@types/react-dom": "^18.3.6",
|
|
82
82
|
"@types/react-input-mask": "^3.0.6",
|
|
83
83
|
"@types/react-window": "^1.8.8",
|
|
84
|
-
"@vitejs/plugin-react": "^4.4.
|
|
84
|
+
"@vitejs/plugin-react": "^4.4.1",
|
|
85
85
|
"jsdom": "^26.1.0",
|
|
86
86
|
"typescript": "^5.8.3",
|
|
87
|
-
"vitest": "^3.1.
|
|
87
|
+
"vitest": "^3.1.2"
|
|
88
88
|
}
|
|
89
89
|
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { DataTypes, IdType } from "@etsoo/shared";
|
|
2
|
+
import Checkbox from "@mui/material/Checkbox";
|
|
3
|
+
import List, { ListProps } from "@mui/material/List";
|
|
4
|
+
import ListItem, { ListItemProps } from "@mui/material/ListItem";
|
|
5
|
+
import ListItemButton from "@mui/material/ListItemButton";
|
|
6
|
+
import ListItemIcon from "@mui/material/ListItemIcon";
|
|
7
|
+
import ListItemText, { ListItemTextProps } from "@mui/material/ListItemText";
|
|
8
|
+
import React from "react";
|
|
9
|
+
|
|
10
|
+
type ListItemLabel<T extends object> =
|
|
11
|
+
| DataTypes.Keys<T, string | undefined>
|
|
12
|
+
| ((item: T) => string | undefined);
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* List multipler component props
|
|
16
|
+
*/
|
|
17
|
+
export type ListMultiplerProps<T extends object> = ListProps & {
|
|
18
|
+
/**
|
|
19
|
+
* List data
|
|
20
|
+
*/
|
|
21
|
+
data: T[];
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Id field name
|
|
25
|
+
*/
|
|
26
|
+
idField: DataTypes.Keys<T, IdType>;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Primary label field name or function
|
|
30
|
+
*/
|
|
31
|
+
primaryLabel: ListItemLabel<T>;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Secondary label field name or function
|
|
35
|
+
*/
|
|
36
|
+
secondaryLabel?: ListItemLabel<T>;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* List item props
|
|
40
|
+
*/
|
|
41
|
+
listItemProps?: ListItemProps;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* List item text props
|
|
45
|
+
*/
|
|
46
|
+
listItemTextProps?: Omit<ListItemTextProps, "primary" | "secondary">;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Input name
|
|
50
|
+
*/
|
|
51
|
+
name?: string;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* On change event
|
|
55
|
+
* @param items The selected items
|
|
56
|
+
* @param ids The selected IDs
|
|
57
|
+
*/
|
|
58
|
+
onCheckItems?: (items: T[], ids: unknown[]) => void;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
function GetListItemLabel<T extends object>(data: T, label?: ListItemLabel<T>) {
|
|
62
|
+
if (label == null) return undefined;
|
|
63
|
+
if (typeof label === "function") {
|
|
64
|
+
return label(data);
|
|
65
|
+
} else {
|
|
66
|
+
return data[label] as string | undefined;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* List multipler component
|
|
72
|
+
* @param props Props
|
|
73
|
+
* @returns Component
|
|
74
|
+
*/
|
|
75
|
+
export function ListMultipler<T extends object>(props: ListMultiplerProps<T>) {
|
|
76
|
+
// Destruct
|
|
77
|
+
const {
|
|
78
|
+
data,
|
|
79
|
+
idField,
|
|
80
|
+
primaryLabel,
|
|
81
|
+
secondaryLabel,
|
|
82
|
+
listItemProps,
|
|
83
|
+
listItemTextProps,
|
|
84
|
+
name,
|
|
85
|
+
onCheckItems,
|
|
86
|
+
...rest
|
|
87
|
+
} = props;
|
|
88
|
+
|
|
89
|
+
// Refs
|
|
90
|
+
const initialized = React.useRef(false);
|
|
91
|
+
React.useEffect(() => {
|
|
92
|
+
initialized.current = true;
|
|
93
|
+
}, []);
|
|
94
|
+
|
|
95
|
+
// State
|
|
96
|
+
const [checked, setChecked] = React.useState<T[]>([]);
|
|
97
|
+
|
|
98
|
+
const ids = React.useMemo(() => {
|
|
99
|
+
const ids = checked.map((u) => u[idField]);
|
|
100
|
+
|
|
101
|
+
if (onCheckItems && initialized.current) {
|
|
102
|
+
onCheckItems(checked, ids);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return ids;
|
|
106
|
+
}, [checked]);
|
|
107
|
+
|
|
108
|
+
function handleToggle(id: T[DataTypes.Keys<T, IdType>]) {
|
|
109
|
+
if (ids.includes(id)) {
|
|
110
|
+
setChecked((prev) => prev.filter((u) => u[idField] !== id));
|
|
111
|
+
} else {
|
|
112
|
+
const item = data.find((u) => u[idField] === id);
|
|
113
|
+
if (item) {
|
|
114
|
+
setChecked((prev) => [...prev, item]);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const inputType = typeof ids[0] === "string" ? "text" : "number";
|
|
120
|
+
|
|
121
|
+
// Layout
|
|
122
|
+
return (
|
|
123
|
+
<List {...rest}>
|
|
124
|
+
{name && (
|
|
125
|
+
<input
|
|
126
|
+
type={inputType}
|
|
127
|
+
style={{ display: "none" }}
|
|
128
|
+
name={name}
|
|
129
|
+
value={ids.join(",")}
|
|
130
|
+
readOnly
|
|
131
|
+
/>
|
|
132
|
+
)}
|
|
133
|
+
{data.map((u) => (
|
|
134
|
+
<ListItem key={`${u[idField]}`} {...listItemProps}>
|
|
135
|
+
<ListItemButton dense onClick={() => handleToggle(u[idField])}>
|
|
136
|
+
<ListItemIcon>
|
|
137
|
+
<Checkbox
|
|
138
|
+
edge="start"
|
|
139
|
+
disableRipple
|
|
140
|
+
checked={ids.includes(u[idField])}
|
|
141
|
+
/>
|
|
142
|
+
</ListItemIcon>
|
|
143
|
+
<ListItemText
|
|
144
|
+
primary={GetListItemLabel(u, primaryLabel)}
|
|
145
|
+
secondary={GetListItemLabel(u, secondaryLabel)}
|
|
146
|
+
{...listItemTextProps}
|
|
147
|
+
/>
|
|
148
|
+
</ListItemButton>
|
|
149
|
+
</ListItem>
|
|
150
|
+
))}
|
|
151
|
+
</List>
|
|
152
|
+
);
|
|
153
|
+
}
|
package/src/html/HtmlDiv.tsx
CHANGED
|
@@ -32,6 +32,23 @@ class HtmlDivElement extends HTMLElement {
|
|
|
32
32
|
// Create a shadow root
|
|
33
33
|
const shadow = this.attachShadow({ mode: "open" });
|
|
34
34
|
|
|
35
|
+
// Default styles
|
|
36
|
+
// Comply with @etsoo/editor default styles
|
|
37
|
+
const style = document.createElement("style");
|
|
38
|
+
style.textContent = `
|
|
39
|
+
:host {
|
|
40
|
+
box-sizing: border-box;
|
|
41
|
+
}
|
|
42
|
+
img {
|
|
43
|
+
max-width: 100%;
|
|
44
|
+
}
|
|
45
|
+
pre {
|
|
46
|
+
background-color: #f3f3f3;
|
|
47
|
+
padding: 12px;
|
|
48
|
+
}
|
|
49
|
+
`;
|
|
50
|
+
shadow.appendChild(style);
|
|
51
|
+
|
|
35
52
|
// Create a wrapper element to hold the sanitized HTML content
|
|
36
53
|
const wrapper = document.createElement("div");
|
|
37
54
|
wrapper.style.cssText = this.displayStyle ?? "";
|
package/src/index.ts
CHANGED
|
@@ -79,6 +79,7 @@ export * from "./LinkEx";
|
|
|
79
79
|
export * from "./ListChooser";
|
|
80
80
|
export * from "./ListItemRightIcon";
|
|
81
81
|
export * from "./ListMoreDisplay";
|
|
82
|
+
export * from "./ListMultipler";
|
|
82
83
|
export * from "./LoadingButton";
|
|
83
84
|
export * from "./MaskInput";
|
|
84
85
|
export * from "./MenuButton";
|