@ioca/react 1.5.18 → 1.5.20
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/components/datagrid/virtual.js +129 -102
- package/lib/cjs/components/datagrid/virtual.js.map +1 -1
- package/lib/cjs/components/editor/editor.js +4 -2
- package/lib/cjs/components/editor/editor.js.map +1 -1
- package/lib/cjs/components/form/useForm.js +1 -1
- package/lib/cjs/components/form/useForm.js.map +1 -1
- package/lib/cjs/components/input/textarea.js +1 -1
- package/lib/cjs/components/input/textarea.js.map +1 -1
- package/lib/cjs/components/modal/content.js +16 -8
- package/lib/cjs/components/modal/content.js.map +1 -1
- package/lib/cjs/components/modal/modal.js +60 -19
- package/lib/cjs/components/modal/modal.js.map +1 -1
- package/lib/cjs/components/modal/modalManager.js +83 -0
- package/lib/cjs/components/modal/modalManager.js.map +1 -0
- package/lib/cjs/components/tabs/tabs.js +8 -17
- package/lib/cjs/components/tabs/tabs.js.map +1 -1
- package/lib/cjs/components/tree/item.js +44 -56
- package/lib/cjs/components/tree/item.js.map +1 -1
- package/lib/cjs/components/tree/tree.js +121 -18
- package/lib/cjs/components/tree/tree.js.map +1 -1
- package/lib/cjs/components/tree/virtual.js +52 -0
- package/lib/cjs/components/tree/virtual.js.map +1 -0
- package/lib/cjs/js/hooks.js +5 -2
- package/lib/cjs/js/hooks.js.map +1 -1
- package/lib/cjs/js/usePreview/content.js +3 -3
- package/lib/cjs/js/usePreview/content.js.map +1 -1
- package/lib/cjs/js/usePreview/type.js.map +1 -1
- package/lib/css/index.css +1 -1
- package/lib/css/index.css.map +1 -1
- package/lib/css/input.css +8 -8
- package/lib/es/components/datagrid/virtual.js +130 -103
- package/lib/es/components/datagrid/virtual.js.map +1 -1
- package/lib/es/components/editor/editor.js +4 -2
- package/lib/es/components/editor/editor.js.map +1 -1
- package/lib/es/components/form/useForm.js +1 -1
- package/lib/es/components/form/useForm.js.map +1 -1
- package/lib/es/components/input/textarea.js +1 -1
- package/lib/es/components/input/textarea.js.map +1 -1
- package/lib/es/components/modal/content.js +18 -10
- package/lib/es/components/modal/content.js.map +1 -1
- package/lib/es/components/modal/modal.js +61 -20
- package/lib/es/components/modal/modal.js.map +1 -1
- package/lib/es/components/modal/modalManager.js +76 -0
- package/lib/es/components/modal/modalManager.js.map +1 -0
- package/lib/es/components/tabs/tabs.js +8 -17
- package/lib/es/components/tabs/tabs.js.map +1 -1
- package/lib/es/components/tree/item.js +44 -57
- package/lib/es/components/tree/item.js.map +1 -1
- package/lib/es/components/tree/tree.js +122 -19
- package/lib/es/components/tree/tree.js.map +1 -1
- package/lib/es/components/tree/virtual.js +44 -0
- package/lib/es/components/tree/virtual.js.map +1 -0
- package/lib/es/js/hooks.js +5 -2
- package/lib/es/js/hooks.js.map +1 -1
- package/lib/es/js/usePreview/content.js +3 -3
- package/lib/es/js/usePreview/content.js.map +1 -1
- package/lib/es/js/usePreview/type.js.map +1 -1
- package/lib/index.js +499 -231
- package/lib/types/components/tabs/type.d.ts +1 -1
- package/lib/types/components/tree/type.d.ts +8 -5
- package/lib/types/js/usePreview/type.d.ts +1 -1
- package/package.json +6 -5
package/lib/index.js
CHANGED
|
@@ -5,7 +5,7 @@ import { useState, useRef, useEffect, useCallback, useMemo, Children, cloneEleme
|
|
|
5
5
|
import { SkipPreviousRound, CloseRound, MinusRound, PlusRound, InboxTwotone, UndoRound, RedoRound, FormatBoldRound, FormatItalicRound, FormatUnderlinedRound, StrikethroughSRound, ClearAllRound, PlayArrowRound, PauseRound, StopRound, VolumeDownRound, VolumeOffRound, FullscreenRound, FullscreenExitRound, FeedOutlined, AspectRatioRound, OpenInNewRound, FileDownloadOutlined, RotateRightRound, RotateLeftRound, KeyboardArrowLeftRound, KeyboardArrowRightRound, KeyboardDoubleArrowUpRound, SyncAltRound, VisibilityRound, VisibilityOffRound, MoreHorizRound, SearchRound, CheckRound, UnfoldMoreRound, CalendarMonthTwotone, AccessTimeRound, KeyboardArrowDownRound, MoveToInboxTwotone, OutboxTwotone, FilePresentOutlined, DriveFolderUploadOutlined } from '@ricons/material';
|
|
6
6
|
import { createRoot } from 'react-dom/client';
|
|
7
7
|
import { getScrollbarSize, List as List$2 } from 'react-window';
|
|
8
|
-
import { createPortal } from 'react-dom';
|
|
8
|
+
import { createPortal, flushSync } from 'react-dom';
|
|
9
9
|
import xss from 'xss';
|
|
10
10
|
import { renderToStaticMarkup } from 'react-dom/server';
|
|
11
11
|
import PubSub from 'pubsub-js';
|
|
@@ -135,12 +135,15 @@ function useMouseUp(listener, options) {
|
|
|
135
135
|
}
|
|
136
136
|
function useKeydown(listener, options) {
|
|
137
137
|
initEventsOnce();
|
|
138
|
+
const listenerRef = useRef(listener);
|
|
139
|
+
listenerRef.current = listener;
|
|
138
140
|
useEffect(() => {
|
|
139
141
|
if (options?.disabled)
|
|
140
142
|
return;
|
|
141
|
-
|
|
143
|
+
const handler = (e) => listenerRef.current(e);
|
|
144
|
+
KeydownEvents.add(handler);
|
|
142
145
|
return () => {
|
|
143
|
-
KeydownEvents.delete(
|
|
146
|
+
KeydownEvents.delete(handler);
|
|
144
147
|
};
|
|
145
148
|
}, []);
|
|
146
149
|
}
|
|
@@ -1183,7 +1186,7 @@ function Row(props) {
|
|
|
1183
1186
|
}, [data, onRowClick, row]);
|
|
1184
1187
|
return (jsx("div", { className: 'i-datagrid-row', onClick: handleRowClick, children: columns.map((col, i) => (jsx(Cell, { column: col, col: i, row: row, data: data, cellEllipsis: cellEllipsis, onCellClick: onCellClick, onCellDoubleClick: onCellDoubleClick }, i))) }));
|
|
1185
1188
|
}
|
|
1186
|
-
function Header
|
|
1189
|
+
function Header(props) {
|
|
1187
1190
|
const { columns, resizable, cellEllipsis, sortBy, sortType, onWidthChange, onHeaderClick, } = props;
|
|
1188
1191
|
const columnById = useMemo(() => {
|
|
1189
1192
|
const map = new Map();
|
|
@@ -1213,6 +1216,84 @@ function Header$1(props) {
|
|
|
1213
1216
|
}) }));
|
|
1214
1217
|
}
|
|
1215
1218
|
|
|
1219
|
+
const VirtualCell = memo(function VirtualCell({ column, data, row, col, isHeader, cellEllipsis, sortBy, sortType, resizable, onWidthChange, }) {
|
|
1220
|
+
const { id, fixed, justify, colSpan, render, title, sorter, renderHeader } = column;
|
|
1221
|
+
const style = useMemo(() => ({
|
|
1222
|
+
"--datagrid-justify": justify,
|
|
1223
|
+
gridColumn: `${col + 1} / span ${colSpan ?? 1}`,
|
|
1224
|
+
insetInline: `var(--datagrid-cell-inset-${col})`,
|
|
1225
|
+
...(isHeader ? { insetBlockStart: 0 } : null),
|
|
1226
|
+
position: !isHeader && !fixed ? "static" : undefined,
|
|
1227
|
+
}), [col, colSpan, fixed, isHeader, justify]);
|
|
1228
|
+
const order = isHeader && sortBy === id ? sortType : "";
|
|
1229
|
+
return (jsxs("div", { "data-col": id, className: classNames("i-datagrid-cell", {
|
|
1230
|
+
[`i-datagrid-cell-fixed-${fixed}`]: fixed,
|
|
1231
|
+
"i-datagrid-has-sorter": isHeader && sorter,
|
|
1232
|
+
}), style: style, children: [isHeader
|
|
1233
|
+
? (renderHeader?.(column, col) ?? (jsx("div", { className: classNames("i-datagrid-cell-content", {
|
|
1234
|
+
"i-datagrid-cell-content-ellipsis": cellEllipsis,
|
|
1235
|
+
}), children: title || id })))
|
|
1236
|
+
: (render?.(data?.[id], data, row, col) ?? (jsx("div", { className: classNames("i-datagrid-cell-content", {
|
|
1237
|
+
"i-datagrid-cell-content-ellipsis": cellEllipsis,
|
|
1238
|
+
}), children: data?.[id] }))), isHeader && sorter && jsx(Sorter, { type: order }), isHeader && resizable && (jsx(Resize, { index: col, onWidthChange: onWidthChange }))] }));
|
|
1239
|
+
});
|
|
1240
|
+
// ---------------------------------------------------------------------------
|
|
1241
|
+
// VirtualRow — memoised row rendered by react-window
|
|
1242
|
+
// ---------------------------------------------------------------------------
|
|
1243
|
+
const VirtualRow = memo(function VirtualRow({ index, style: itemStyle, ariaAttributes, rows, columns, columnById, columnIndexById, contentWidthPx, virtualRowHeight, header, striped, cellEllipsis, loaderNode, sortBy, sortType, resizable, onWidthChange, onRowClick, onCellClick, onCellDoubleClick, }) {
|
|
1244
|
+
if (index >= rows.length) {
|
|
1245
|
+
return (jsx("div", { ...ariaAttributes, style: {
|
|
1246
|
+
...itemStyle,
|
|
1247
|
+
width: contentWidthPx,
|
|
1248
|
+
minWidth: "100%",
|
|
1249
|
+
display: "flex",
|
|
1250
|
+
alignItems: "center",
|
|
1251
|
+
justifyContent: "center",
|
|
1252
|
+
}, children: loaderNode }));
|
|
1253
|
+
}
|
|
1254
|
+
const rowData = rows[index];
|
|
1255
|
+
const rowNum = index + (header ? 1 : 0);
|
|
1256
|
+
const bg = striped && index % 2 === 0 ? "var(--background-1)" : undefined;
|
|
1257
|
+
const handleCellClick = useCallback((e) => {
|
|
1258
|
+
if (!onCellClick)
|
|
1259
|
+
return;
|
|
1260
|
+
const el = e.target?.closest?.(".i-datagrid-cell[data-col]");
|
|
1261
|
+
const id = el?.dataset?.col;
|
|
1262
|
+
if (!id)
|
|
1263
|
+
return;
|
|
1264
|
+
const column = columnById.get(id);
|
|
1265
|
+
const col = columnIndexById.get(id);
|
|
1266
|
+
if (!column || col == null)
|
|
1267
|
+
return;
|
|
1268
|
+
onCellClick(rowData, column, rowNum, col, e);
|
|
1269
|
+
}, [columnById, columnIndexById, onCellClick, rowData, rowNum]);
|
|
1270
|
+
const handleCellDoubleClick = useCallback((e) => {
|
|
1271
|
+
if (!onCellDoubleClick)
|
|
1272
|
+
return;
|
|
1273
|
+
const el = e.target?.closest?.(".i-datagrid-cell[data-col]");
|
|
1274
|
+
const id = el?.dataset?.col;
|
|
1275
|
+
if (!id)
|
|
1276
|
+
return;
|
|
1277
|
+
const column = columnById.get(id);
|
|
1278
|
+
const col = columnIndexById.get(id);
|
|
1279
|
+
if (!column || col == null)
|
|
1280
|
+
return;
|
|
1281
|
+
onCellDoubleClick(rowData, column, rowNum, col, e);
|
|
1282
|
+
}, [columnById, columnIndexById, onCellDoubleClick, rowData, rowNum]);
|
|
1283
|
+
const handleRowClick = useCallback(() => onRowClick?.(rowData, rowNum), [onRowClick, rowData, rowNum]);
|
|
1284
|
+
return (jsx("div", { style: {
|
|
1285
|
+
...itemStyle,
|
|
1286
|
+
width: contentWidthPx,
|
|
1287
|
+
minWidth: "100%",
|
|
1288
|
+
display: "grid",
|
|
1289
|
+
gridTemplateColumns: "var(--grid-template-columns)",
|
|
1290
|
+
height: virtualRowHeight,
|
|
1291
|
+
"--datagrid-cell-background": bg,
|
|
1292
|
+
}, className: 'i-datagrid-row', onClick: handleRowClick, onClickCapture: handleCellClick, onDoubleClickCapture: handleCellDoubleClick, children: columns.map((c, col) => (jsx(VirtualCell, { column: c, data: rowData, row: rowNum, col: col, cellEllipsis: cellEllipsis, sortBy: sortBy, sortType: sortType, resizable: resizable, onWidthChange: onWidthChange }, c.id))) }));
|
|
1293
|
+
});
|
|
1294
|
+
// ---------------------------------------------------------------------------
|
|
1295
|
+
// VirtualDatagrid
|
|
1296
|
+
// ---------------------------------------------------------------------------
|
|
1216
1297
|
function VirtualDatagrid(props) {
|
|
1217
1298
|
const { virtual, columns, rows, header, sortBy, sortType, height, loading, resizable, striped, cellEllipsis, empty, wrapRef, containerRef, onHeaderClick, onWidthChange, onRowClick, onCellClick, onCellDoubleClick, onScroll, } = props;
|
|
1218
1299
|
const headerRef = useRef(null);
|
|
@@ -1225,6 +1306,7 @@ function VirtualDatagrid(props) {
|
|
|
1225
1306
|
const rafRef = useRef({
|
|
1226
1307
|
viewport: 0,
|
|
1227
1308
|
contentWidth: 0,
|
|
1309
|
+
scrollSync: 0,
|
|
1228
1310
|
});
|
|
1229
1311
|
const columnById = useMemo(() => {
|
|
1230
1312
|
const map = new Map();
|
|
@@ -1236,38 +1318,6 @@ function VirtualDatagrid(props) {
|
|
|
1236
1318
|
columns.forEach((c, i) => map.set(c.id, i));
|
|
1237
1319
|
return map;
|
|
1238
1320
|
}, [columns]);
|
|
1239
|
-
const getVirtualCellStyle = useCallback(({ justify, col, colSpan = 1, }) => {
|
|
1240
|
-
return {
|
|
1241
|
-
"--datagrid-justify": justify,
|
|
1242
|
-
gridColumn: `${col + 1} / span ${colSpan}`,
|
|
1243
|
-
insetInline: `var(--datagrid-cell-inset-${col})`,
|
|
1244
|
-
};
|
|
1245
|
-
}, []);
|
|
1246
|
-
const renderVirtualCell = useCallback(({ column, data, row, col, isHeader, }) => {
|
|
1247
|
-
const { id, fixed, justify, colSpan, render, title, sorter, renderHeader, } = column;
|
|
1248
|
-
const style = {
|
|
1249
|
-
...getVirtualCellStyle({ justify, col, colSpan }),
|
|
1250
|
-
...(isHeader ? { insetBlockStart: 0 } : null),
|
|
1251
|
-
};
|
|
1252
|
-
const order = isHeader && sortBy === id ? sortType : "";
|
|
1253
|
-
return (jsxs("div", { "data-col": id, className: classNames("i-datagrid-cell", {
|
|
1254
|
-
[`i-datagrid-cell-fixed-${fixed}`]: fixed,
|
|
1255
|
-
"i-datagrid-has-sorter": isHeader && sorter,
|
|
1256
|
-
}), style: style, children: [isHeader
|
|
1257
|
-
? (renderHeader?.(column, col) ?? (jsx("div", { className: classNames("i-datagrid-cell-content", {
|
|
1258
|
-
"i-datagrid-cell-content-ellipsis": cellEllipsis,
|
|
1259
|
-
}), children: title || id })))
|
|
1260
|
-
: (render?.(data?.[id], data, row, col) ?? (jsx("div", { className: classNames("i-datagrid-cell-content", {
|
|
1261
|
-
"i-datagrid-cell-content-ellipsis": cellEllipsis,
|
|
1262
|
-
}), children: data?.[id] }))), isHeader && sorter && jsx(Sorter, { type: order }), isHeader && resizable && (jsx(Resize, { index: col, onWidthChange: onWidthChange }))] }, id));
|
|
1263
|
-
}, [
|
|
1264
|
-
cellEllipsis,
|
|
1265
|
-
getVirtualCellStyle,
|
|
1266
|
-
onWidthChange,
|
|
1267
|
-
resizable,
|
|
1268
|
-
sortBy,
|
|
1269
|
-
sortType,
|
|
1270
|
-
]);
|
|
1271
1321
|
const handleHeaderClick = useCallback((e) => {
|
|
1272
1322
|
const el = e.target?.closest?.(".i-datagrid-cell[data-col]");
|
|
1273
1323
|
const id = el?.dataset?.col;
|
|
@@ -1277,10 +1327,17 @@ function VirtualDatagrid(props) {
|
|
|
1277
1327
|
const el = e.currentTarget;
|
|
1278
1328
|
if (!el)
|
|
1279
1329
|
return;
|
|
1280
|
-
if (
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1330
|
+
if (rafRef.current.scrollSync)
|
|
1331
|
+
return;
|
|
1332
|
+
rafRef.current.scrollSync = requestAnimationFrame(() => {
|
|
1333
|
+
rafRef.current.scrollSync = 0;
|
|
1334
|
+
if (!headerRef.current)
|
|
1335
|
+
return;
|
|
1336
|
+
const target = el.scrollLeft;
|
|
1337
|
+
if (headerRef.current.scrollLeft !== target) {
|
|
1338
|
+
headerRef.current.scrollLeft = target;
|
|
1339
|
+
}
|
|
1340
|
+
});
|
|
1284
1341
|
}, []);
|
|
1285
1342
|
const handleReachEnd = useCallback(() => {
|
|
1286
1343
|
if (virtual.onReachEnd) {
|
|
@@ -1310,32 +1367,6 @@ function VirtualDatagrid(props) {
|
|
|
1310
1367
|
listEl.scrollLeft = el.scrollLeft;
|
|
1311
1368
|
}
|
|
1312
1369
|
}, []);
|
|
1313
|
-
const handleBodyClickCapture = useCallback((e, rowData, rowNum) => {
|
|
1314
|
-
if (!onCellClick)
|
|
1315
|
-
return;
|
|
1316
|
-
const el = e.target?.closest?.(".i-datagrid-cell[data-col]");
|
|
1317
|
-
const id = el?.dataset?.col;
|
|
1318
|
-
if (!id)
|
|
1319
|
-
return;
|
|
1320
|
-
const column = columnById.get(id);
|
|
1321
|
-
const col = columnIndexById.get(id);
|
|
1322
|
-
if (!column || col == null)
|
|
1323
|
-
return;
|
|
1324
|
-
onCellClick(rowData, column, rowNum, col, e);
|
|
1325
|
-
}, [columnById, columnIndexById, onCellClick]);
|
|
1326
|
-
const handleBodyDoubleClickCapture = useCallback((e, rowData, rowNum) => {
|
|
1327
|
-
if (!onCellDoubleClick)
|
|
1328
|
-
return;
|
|
1329
|
-
const el = e.target?.closest?.(".i-datagrid-cell[data-col]");
|
|
1330
|
-
const id = el?.dataset?.col;
|
|
1331
|
-
if (!id)
|
|
1332
|
-
return;
|
|
1333
|
-
const column = columnById.get(id);
|
|
1334
|
-
const col = columnIndexById.get(id);
|
|
1335
|
-
if (!column || col == null)
|
|
1336
|
-
return;
|
|
1337
|
-
onCellDoubleClick(rowData, column, rowNum, col, e);
|
|
1338
|
-
}, [columnById, columnIndexById, onCellDoubleClick]);
|
|
1339
1370
|
useEffect(() => {
|
|
1340
1371
|
const el = wrapRef.current;
|
|
1341
1372
|
if (!el)
|
|
@@ -1406,12 +1437,14 @@ function VirtualDatagrid(props) {
|
|
|
1406
1437
|
const contentWidthPx = measuredContentWidth
|
|
1407
1438
|
? `${measuredContentWidth}px`
|
|
1408
1439
|
: "fit-content";
|
|
1409
|
-
const headerCells = useMemo(() => columns.map((c, col) =>
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1440
|
+
const headerCells = useMemo(() => columns.map((c, col) => (jsx(VirtualCell, { column: c, row: 0, col: col, isHeader: true, cellEllipsis: cellEllipsis, sortBy: sortBy, sortType: sortType, resizable: resizable, onWidthChange: onWidthChange }, c.id))), [
|
|
1441
|
+
cellEllipsis,
|
|
1442
|
+
columns,
|
|
1443
|
+
onWidthChange,
|
|
1444
|
+
resizable,
|
|
1445
|
+
sortBy,
|
|
1446
|
+
sortType,
|
|
1447
|
+
]);
|
|
1415
1448
|
const headerInnerStyle = useMemo(() => ({
|
|
1416
1449
|
display: "grid",
|
|
1417
1450
|
gridTemplateColumns: "var(--grid-template-columns)",
|
|
@@ -1431,50 +1464,47 @@ function VirtualDatagrid(props) {
|
|
|
1431
1464
|
}
|
|
1432
1465
|
: undefined, [scrollbarSize]);
|
|
1433
1466
|
const loaderNode = useMemo(() => virtual.loader ?? jsx(Loading, { className: 'my-12' }), [virtual.loader]);
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
...itemStyle,
|
|
1438
|
-
width: contentWidthPx,
|
|
1439
|
-
minWidth: "100%",
|
|
1440
|
-
display: "flex",
|
|
1441
|
-
alignItems: "center",
|
|
1442
|
-
justifyContent: "center",
|
|
1443
|
-
}, children: loaderNode }));
|
|
1444
|
-
}
|
|
1445
|
-
const rowData = rows[index];
|
|
1446
|
-
const rowNum = index + (header ? 1 : 0);
|
|
1447
|
-
const bg = striped && index % 2 === 0 ? "var(--background-1)" : undefined;
|
|
1448
|
-
return (jsx("div", { style: {
|
|
1449
|
-
...itemStyle,
|
|
1450
|
-
width: contentWidthPx,
|
|
1451
|
-
minWidth: "100%",
|
|
1452
|
-
display: "grid",
|
|
1453
|
-
gridTemplateColumns: "var(--grid-template-columns)",
|
|
1454
|
-
height: virtual.rowHeight,
|
|
1455
|
-
"--datagrid-cell-background": bg,
|
|
1456
|
-
}, className: 'i-datagrid-row', onClickCapture: (e) => handleBodyClickCapture(e, rowData, rowNum), onDoubleClickCapture: (e) => handleBodyDoubleClickCapture(e, rowData, rowNum), onClick: () => onRowClick?.(rowData, rowNum), children: columns.map((c, col) => renderVirtualCell({
|
|
1457
|
-
column: c,
|
|
1458
|
-
data: rowData,
|
|
1459
|
-
row: rowNum,
|
|
1460
|
-
col,
|
|
1461
|
-
})) }));
|
|
1462
|
-
}, [
|
|
1467
|
+
// Stable row-component reference so react-window can memoise rows.
|
|
1468
|
+
const rowProps = useMemo(() => ({
|
|
1469
|
+
rows,
|
|
1463
1470
|
columns,
|
|
1471
|
+
columnById,
|
|
1472
|
+
columnIndexById,
|
|
1464
1473
|
contentWidthPx,
|
|
1465
|
-
|
|
1466
|
-
handleBodyDoubleClickCapture,
|
|
1474
|
+
virtualRowHeight: virtual.rowHeight,
|
|
1467
1475
|
header,
|
|
1476
|
+
striped,
|
|
1477
|
+
cellEllipsis,
|
|
1468
1478
|
loaderNode,
|
|
1479
|
+
sortBy,
|
|
1480
|
+
sortType,
|
|
1481
|
+
resizable,
|
|
1482
|
+
onWidthChange,
|
|
1469
1483
|
onRowClick,
|
|
1470
|
-
|
|
1484
|
+
onCellClick,
|
|
1485
|
+
onCellDoubleClick,
|
|
1486
|
+
}), [
|
|
1471
1487
|
rows,
|
|
1472
|
-
|
|
1488
|
+
columns,
|
|
1489
|
+
columnById,
|
|
1490
|
+
columnIndexById,
|
|
1491
|
+
contentWidthPx,
|
|
1473
1492
|
virtual.rowHeight,
|
|
1493
|
+
header,
|
|
1494
|
+
striped,
|
|
1495
|
+
cellEllipsis,
|
|
1496
|
+
loaderNode,
|
|
1497
|
+
sortBy,
|
|
1498
|
+
sortType,
|
|
1499
|
+
resizable,
|
|
1500
|
+
onWidthChange,
|
|
1501
|
+
onRowClick,
|
|
1502
|
+
onCellClick,
|
|
1503
|
+
onCellDoubleClick,
|
|
1474
1504
|
]);
|
|
1475
1505
|
return (jsxs("div", { ref: containerRef, className: classNames("i-datagrid", {
|
|
1476
1506
|
"i-datagrid-loading": loading,
|
|
1477
|
-
}), style: { display: "block", width: "100%", maxWidth: "100%" }, children: [header && (jsx("div", { ref: headerRef, className: 'i-datagrid-virtual-header', onScroll: handleHeaderScroll, style: headerWrapStyle, children: jsx("div", { ref: headerInnerRef, className: 'i-datagrid-header i-datagrid-row', style: headerInnerStyle, onClick: handleHeaderClick, children: headerCells }) })), jsx(List$2, { listRef: listRef, rowCount: rows.length + (virtual.hasMore ? 1 : 0), rowHeight: virtual.rowHeight, overscanCount: Math.max(3, virtual.threshold ?? 8), rowProps:
|
|
1507
|
+
}), style: { display: "block", width: "100%", maxWidth: "100%" }, children: [header && (jsx("div", { ref: headerRef, className: 'i-datagrid-virtual-header', onScroll: handleHeaderScroll, style: headerWrapStyle, children: jsx("div", { ref: headerInnerRef, className: 'i-datagrid-header i-datagrid-row', style: headerInnerStyle, onClick: handleHeaderClick, children: headerCells }) })), jsx(List$2, { listRef: listRef, rowCount: rows.length + (virtual.hasMore ? 1 : 0), rowHeight: virtual.rowHeight, overscanCount: Math.max(3, virtual.threshold ?? 8), rowProps: rowProps, style: listStyle, onScroll: handleBodyScroll, onRowsRendered: handleRowsRendered, rowComponent: VirtualRow }), rows.length < 1 && !virtual.hasMore && empty] }));
|
|
1478
1508
|
}
|
|
1479
1509
|
|
|
1480
1510
|
const Datagrid = (props) => {
|
|
@@ -1672,7 +1702,7 @@ const Datagrid = (props) => {
|
|
|
1672
1702
|
"i-datagrid-striped": striped,
|
|
1673
1703
|
}), children: [useVirtual && virtual ? (jsx(VirtualDatagrid, { virtual: virtual, columns: columns, rows: rows, header: header, sortBy: state.sortBy, sortType: state.sortType, height: height, loading: loading, resizable: resizable, striped: striped, cellEllipsis: cellEllipsis, empty: empty, wrapRef: wrapRef, containerRef: container, getRowKey: getRowKey, onHeaderClick: handleHeaderClick, onWidthChange: handleWidthChange, onRowClick: onRowClick, onCellClick: onCellClick, onCellDoubleClick: onCellDoubleClick, onScroll: onScroll })) : (jsxs("div", { ref: container, className: classNames("i-datagrid", {
|
|
1674
1704
|
"i-datagrid-loading": loading,
|
|
1675
|
-
}), onWheel: onScroll, children: [header && (jsx(Header
|
|
1705
|
+
}), onWheel: onScroll, children: [header && (jsx(Header, { columns: columns, resizable: resizable, sortType: state.sortType, sortBy: state.sortBy, cellEllipsis: cellEllipsis, onWidthChange: handleWidthChange, onHeaderClick: handleHeaderClick })), rows.map((row, i) => (jsx(Row, { row: i + (header ? 1 : 0), data: row, cellEllipsis: cellEllipsis, columns: columns, onCellClick: onCellClick, onRowClick: onRowClick, onCellDoubleClick: onCellDoubleClick }, getRowKey(row, i) ?? i))), rows.length < 1 && empty] })), loading && renderLoading()] }));
|
|
1676
1706
|
};
|
|
1677
1707
|
|
|
1678
1708
|
const Description = (props) => {
|
|
@@ -1785,7 +1815,7 @@ const List$1 = forwardRef((props, ref) => {
|
|
|
1785
1815
|
});
|
|
1786
1816
|
List$1.Item = Item$4;
|
|
1787
1817
|
|
|
1788
|
-
const Content$
|
|
1818
|
+
const Content$3 = forwardRef((props, ref) => {
|
|
1789
1819
|
const { arrow, arrowProps = {}, className, children, ...restProps } = props;
|
|
1790
1820
|
const arrowCSS = useMemo(() => {
|
|
1791
1821
|
let { left = 0, top = 0, pos } = arrowProps;
|
|
@@ -2297,7 +2327,7 @@ function Popup(props) {
|
|
|
2297
2327
|
window.removeEventListener("scroll", onScrollOrResize, true);
|
|
2298
2328
|
};
|
|
2299
2329
|
}, [show]);
|
|
2300
|
-
return (jsxs(Fragment, { children: [triggerNode, show && (jsx(Content$
|
|
2330
|
+
return (jsxs(Fragment, { children: [triggerNode, show && (jsx(Content$3, { ref: contentRef, arrow: arrow && trigger !== "contextmenu", style: {
|
|
2301
2331
|
...style,
|
|
2302
2332
|
position: "fixed",
|
|
2303
2333
|
}, className: className, ...contentTouch, trigger: triggerRef.current, children: content }))] }));
|
|
@@ -2703,6 +2733,7 @@ const Editor = (props) => {
|
|
|
2703
2733
|
const [memtionKeyword, setMemtionKeyword] = useState("");
|
|
2704
2734
|
const [memtionActiveIndex, setMemtionActiveIndex] = useState(0);
|
|
2705
2735
|
const [activeMemtionIndex, setActiveMemtionIndex] = useState(-1);
|
|
2736
|
+
const activeMemtionIndexRef = useRef(-1);
|
|
2706
2737
|
const memtionOptions = useMemo(() => {
|
|
2707
2738
|
if (activeMemtionIndex < 0 || !memtion?.length)
|
|
2708
2739
|
return [];
|
|
@@ -2838,6 +2869,7 @@ const Editor = (props) => {
|
|
|
2838
2869
|
memtionTriggerRangeRef.current =
|
|
2839
2870
|
selectionRef.current?.cloneRange() ?? null;
|
|
2840
2871
|
pendingMemtionRef.current = true;
|
|
2872
|
+
activeMemtionIndexRef.current = matchedIndex;
|
|
2841
2873
|
setActiveMemtionIndex(matchedIndex);
|
|
2842
2874
|
}
|
|
2843
2875
|
}
|
|
@@ -2887,8 +2919,8 @@ const Editor = (props) => {
|
|
|
2887
2919
|
setEditorValue(nextValue);
|
|
2888
2920
|
}
|
|
2889
2921
|
rememberSelection();
|
|
2890
|
-
if (
|
|
2891
|
-
const active = memtion?.[
|
|
2922
|
+
if (activeMemtionIndexRef.current >= 0 && (pendingMemtionRef.current || memtionVisible)) {
|
|
2923
|
+
const active = memtion?.[activeMemtionIndexRef.current];
|
|
2892
2924
|
if (!active) {
|
|
2893
2925
|
hideMemtion();
|
|
2894
2926
|
return;
|
|
@@ -3137,7 +3169,7 @@ class IFormInstance {
|
|
|
3137
3169
|
const { id, rules, data } = this;
|
|
3138
3170
|
if (!rules)
|
|
3139
3171
|
return data;
|
|
3140
|
-
const names = field ? [field] : Object.keys(this.cacheData);
|
|
3172
|
+
const names = field ? [field] : [...new Set([...Object.keys(this.cacheData), ...Object.keys(rules)])];
|
|
3141
3173
|
let isAllValid = true;
|
|
3142
3174
|
names.forEach((name) => {
|
|
3143
3175
|
const o = rules[name];
|
|
@@ -3261,14 +3293,21 @@ Form.useForm = useForm;
|
|
|
3261
3293
|
Form.Field = Field;
|
|
3262
3294
|
Form.useConfig = useConfig;
|
|
3263
3295
|
|
|
3264
|
-
|
|
3296
|
+
const Content$1 = (props) => {
|
|
3265
3297
|
const { title, footer, hideCloseButton, footerLeft, okButtonProps, cancelButtonProps, children, onOk, onClose, } = props;
|
|
3266
3298
|
const showHeader = title || !hideCloseButton;
|
|
3299
|
+
const [loading, setLoading] = useState(false);
|
|
3267
3300
|
const handleOk = async () => {
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3301
|
+
setLoading(true);
|
|
3302
|
+
try {
|
|
3303
|
+
const ret = await onOk?.();
|
|
3304
|
+
if (ret === false)
|
|
3305
|
+
return;
|
|
3306
|
+
onClose?.();
|
|
3307
|
+
}
|
|
3308
|
+
finally {
|
|
3309
|
+
setLoading(false);
|
|
3310
|
+
}
|
|
3272
3311
|
};
|
|
3273
3312
|
const renderFooter = useMemo(() => {
|
|
3274
3313
|
if (footer || footer === null)
|
|
@@ -3276,19 +3315,94 @@ function Content$1(props) {
|
|
|
3276
3315
|
const propsOk = Object.assign({
|
|
3277
3316
|
children: "确定",
|
|
3278
3317
|
onClick: handleOk,
|
|
3279
|
-
}, okButtonProps);
|
|
3318
|
+
}, okButtonProps, { loading });
|
|
3280
3319
|
const propsCancel = Object.assign({
|
|
3281
3320
|
secondary: true,
|
|
3282
3321
|
children: "关闭",
|
|
3283
3322
|
onClick: onClose,
|
|
3284
3323
|
}, cancelButtonProps);
|
|
3285
3324
|
return (jsxs(Fragment, { children: [footerLeft, jsx(Button, { ...propsOk }), jsx(Button, { ...propsCancel })] }));
|
|
3286
|
-
}, [footer, okButtonProps, cancelButtonProps]);
|
|
3325
|
+
}, [footer, okButtonProps, cancelButtonProps, loading]);
|
|
3287
3326
|
return (jsxs(Fragment, { children: [showHeader && (jsxs("header", { className: 'i-modal-header', children: [title && jsx("b", { children: title }), jsx(Helpericon, { active: !hideCloseButton, className: 'i-modal-close', onClick: onClose })] })), jsx("div", { className: 'i-modal-content', children: children }), jsx("footer", { className: 'i-modal-footer', children: renderFooter })] }));
|
|
3288
|
-
}
|
|
3327
|
+
};
|
|
3328
|
+
var Content$2 = memo(Content$1);
|
|
3289
3329
|
|
|
3290
3330
|
const ModalContext = createContext(false);
|
|
3291
3331
|
|
|
3332
|
+
const CONTAINER_ID = "i-modal-container";
|
|
3333
|
+
const BACKDROP_ID = "i-modal-backdrop";
|
|
3334
|
+
let containerEl = null;
|
|
3335
|
+
let backdropEl = null;
|
|
3336
|
+
const stack = [];
|
|
3337
|
+
const listeners = new Set();
|
|
3338
|
+
function ensureContainer() {
|
|
3339
|
+
if (containerEl)
|
|
3340
|
+
return containerEl;
|
|
3341
|
+
containerEl = document.createElement("div");
|
|
3342
|
+
containerEl.id = CONTAINER_ID;
|
|
3343
|
+
containerEl.className = "i-modal-container";
|
|
3344
|
+
document.body.append(containerEl);
|
|
3345
|
+
backdropEl = document.createElement("div");
|
|
3346
|
+
backdropEl.id = BACKDROP_ID;
|
|
3347
|
+
backdropEl.className = "i-modal-backdrop";
|
|
3348
|
+
containerEl.prepend(backdropEl);
|
|
3349
|
+
return containerEl;
|
|
3350
|
+
}
|
|
3351
|
+
function syncBackdrop() {
|
|
3352
|
+
if (!backdropEl)
|
|
3353
|
+
return;
|
|
3354
|
+
const show = stack.some((e) => e.visible && !e.hideBackdrop);
|
|
3355
|
+
backdropEl.classList.toggle("i-modal-backdrop-active", show);
|
|
3356
|
+
}
|
|
3357
|
+
function notify$1() {
|
|
3358
|
+
listeners.forEach((fn) => fn());
|
|
3359
|
+
}
|
|
3360
|
+
function register(entry) {
|
|
3361
|
+
ensureContainer();
|
|
3362
|
+
stack.push(entry);
|
|
3363
|
+
syncBackdrop();
|
|
3364
|
+
notify$1();
|
|
3365
|
+
return () => {
|
|
3366
|
+
const idx = stack.findIndex((e) => e.mid === entry.mid);
|
|
3367
|
+
if (idx !== -1)
|
|
3368
|
+
stack.splice(idx, 1);
|
|
3369
|
+
syncBackdrop();
|
|
3370
|
+
notify$1();
|
|
3371
|
+
if (stack.length === 0) {
|
|
3372
|
+
backdropEl?.remove();
|
|
3373
|
+
backdropEl = null;
|
|
3374
|
+
containerEl?.remove();
|
|
3375
|
+
containerEl = null;
|
|
3376
|
+
}
|
|
3377
|
+
};
|
|
3378
|
+
}
|
|
3379
|
+
function updateVisible(mid, visible) {
|
|
3380
|
+
const entry = stack.find((e) => e.mid === mid);
|
|
3381
|
+
if (entry) {
|
|
3382
|
+
entry.visible = visible;
|
|
3383
|
+
syncBackdrop();
|
|
3384
|
+
notify$1();
|
|
3385
|
+
}
|
|
3386
|
+
}
|
|
3387
|
+
function isTop(mid) {
|
|
3388
|
+
const top = getTopVisible();
|
|
3389
|
+
return top?.mid === mid;
|
|
3390
|
+
}
|
|
3391
|
+
function getTopVisible() {
|
|
3392
|
+
for (let i = stack.length - 1; i >= 0; i--) {
|
|
3393
|
+
if (stack[i].visible)
|
|
3394
|
+
return stack[i];
|
|
3395
|
+
}
|
|
3396
|
+
return undefined;
|
|
3397
|
+
}
|
|
3398
|
+
function getContainer() {
|
|
3399
|
+
return ensureContainer();
|
|
3400
|
+
}
|
|
3401
|
+
function subscribe(fn) {
|
|
3402
|
+
listeners.add(fn);
|
|
3403
|
+
return () => listeners.delete(fn);
|
|
3404
|
+
}
|
|
3405
|
+
|
|
3292
3406
|
function useModal() {
|
|
3293
3407
|
const ref = useRef(null);
|
|
3294
3408
|
const handleOpen = (props) => {
|
|
@@ -3316,26 +3430,41 @@ function useModal() {
|
|
|
3316
3430
|
};
|
|
3317
3431
|
}
|
|
3318
3432
|
|
|
3433
|
+
let midCounter = 0;
|
|
3319
3434
|
function Modal(props) {
|
|
3320
3435
|
const { visible, title, footer, okButtonProps, cancelButtonProps, closable = true, hideBackdrop, backdropClosable = true, hideCloseButton, disableEsc, width, height, customized, fixed, hideShadow, children, style, className, keepDOM, footerLeft, onClick, onVisibleChange, onClose, onOk, ...restProps } = props;
|
|
3436
|
+
const midRef = useRef(`modal-${++midCounter}`);
|
|
3437
|
+
const mid = midRef.current;
|
|
3321
3438
|
const [show, setShow] = useState(visible);
|
|
3322
3439
|
const [active, setActive] = useState(false);
|
|
3323
3440
|
const [bounced, setBounced] = useState(false);
|
|
3324
3441
|
const [mounted, setMounted] = useState(false);
|
|
3442
|
+
const [top, setTop] = useState(false);
|
|
3325
3443
|
const toggable = useRef(true);
|
|
3326
|
-
const
|
|
3444
|
+
const layerRef = useRef(null);
|
|
3445
|
+
const handleShow = useCallback(() => {
|
|
3327
3446
|
if (!toggable.current)
|
|
3328
3447
|
return;
|
|
3329
|
-
(!keepDOM || !show)
|
|
3448
|
+
if (!keepDOM || !show)
|
|
3449
|
+
setShow(true);
|
|
3330
3450
|
toggable.current = false;
|
|
3331
|
-
|
|
3451
|
+
updateVisible(mid, true);
|
|
3452
|
+
const raf = requestAnimationFrame(() => {
|
|
3453
|
+
if (!layerRef.current) {
|
|
3454
|
+
requestAnimationFrame(() => {
|
|
3455
|
+
setActive(true);
|
|
3456
|
+
onVisibleChange?.(true);
|
|
3457
|
+
toggable.current = true;
|
|
3458
|
+
});
|
|
3459
|
+
return;
|
|
3460
|
+
}
|
|
3332
3461
|
setActive(true);
|
|
3333
3462
|
onVisibleChange?.(true);
|
|
3334
3463
|
toggable.current = true;
|
|
3335
|
-
}
|
|
3336
|
-
return () =>
|
|
3337
|
-
};
|
|
3338
|
-
const handleHide = () => {
|
|
3464
|
+
});
|
|
3465
|
+
return () => cancelAnimationFrame(raf);
|
|
3466
|
+
}, [keepDOM, show, onVisibleChange]);
|
|
3467
|
+
const handleHide = useCallback(() => {
|
|
3339
3468
|
if (!toggable.current)
|
|
3340
3469
|
return;
|
|
3341
3470
|
toggable.current = false;
|
|
@@ -3348,28 +3477,53 @@ function Modal(props) {
|
|
|
3348
3477
|
return () => clearTimeout(timer);
|
|
3349
3478
|
}
|
|
3350
3479
|
setActive(false);
|
|
3480
|
+
updateVisible(mid, false);
|
|
3351
3481
|
const timer = setTimeout(() => {
|
|
3352
|
-
!keepDOM
|
|
3482
|
+
if (!keepDOM)
|
|
3483
|
+
setShow(false);
|
|
3353
3484
|
toggable.current = true;
|
|
3354
3485
|
onVisibleChange?.(false);
|
|
3355
3486
|
onClose?.();
|
|
3356
3487
|
}, 240);
|
|
3357
3488
|
return () => clearTimeout(timer);
|
|
3358
|
-
};
|
|
3489
|
+
}, [closable, keepDOM, onClose, onVisibleChange]);
|
|
3359
3490
|
const handleBackdropClick = () => {
|
|
3360
3491
|
backdropClosable && handleHide();
|
|
3361
3492
|
};
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3493
|
+
useEffect(() => {
|
|
3494
|
+
const unsub = subscribe(() => {
|
|
3495
|
+
setTop(isTop(mid));
|
|
3496
|
+
});
|
|
3497
|
+
return unsub;
|
|
3498
|
+
}, []);
|
|
3499
|
+
useEffect(() => {
|
|
3500
|
+
const unregister = register({
|
|
3501
|
+
mid,
|
|
3502
|
+
visible: !!visible,
|
|
3503
|
+
hideBackdrop: !!hideBackdrop,
|
|
3504
|
+
closable: !!closable,
|
|
3505
|
+
});
|
|
3506
|
+
return unregister;
|
|
3507
|
+
}, []);
|
|
3367
3508
|
useEffect(() => {
|
|
3368
3509
|
visible ? handleShow() : handleHide();
|
|
3369
3510
|
}, [visible]);
|
|
3511
|
+
useEffect(() => {
|
|
3512
|
+
if (!show)
|
|
3513
|
+
return;
|
|
3514
|
+
const raf = requestAnimationFrame(() => {
|
|
3515
|
+
setActive(top);
|
|
3516
|
+
});
|
|
3517
|
+
return () => cancelAnimationFrame(raf);
|
|
3518
|
+
}, [top]);
|
|
3370
3519
|
useEffect(() => {
|
|
3371
3520
|
setMounted(true);
|
|
3372
3521
|
}, []);
|
|
3522
|
+
useKeydown((e) => {
|
|
3523
|
+
if (e.code !== "Escape" || !visible || !top)
|
|
3524
|
+
return;
|
|
3525
|
+
handleHide();
|
|
3526
|
+
}, { disabled: disableEsc });
|
|
3373
3527
|
const handleClick = () => {
|
|
3374
3528
|
if (typeof document === "undefined")
|
|
3375
3529
|
return;
|
|
@@ -3377,12 +3531,12 @@ function Modal(props) {
|
|
|
3377
3531
|
};
|
|
3378
3532
|
if (!show || !mounted)
|
|
3379
3533
|
return null;
|
|
3380
|
-
return createPortal(jsx("div", { className: classNames("i-modal-
|
|
3381
|
-
"i-modal-backdrop": !hideBackdrop,
|
|
3382
|
-
"i-modal-customized": customized,
|
|
3534
|
+
return createPortal(jsx("div", { ref: layerRef, className: classNames("i-modal-layer", {
|
|
3383
3535
|
"i-modal-active": active,
|
|
3536
|
+
"i-modal-customized": customized,
|
|
3537
|
+
"i-modal-hide-backdrop": hideBackdrop,
|
|
3384
3538
|
fixed,
|
|
3385
|
-
}, className), style: style, onClick: handleBackdropClick,
|
|
3539
|
+
}, className), style: style, onClick: handleBackdropClick, children: jsx("div", { className: classNames("i-modal", {
|
|
3386
3540
|
bounced,
|
|
3387
3541
|
shadow: !hideShadow,
|
|
3388
3542
|
}), style: {
|
|
@@ -3392,7 +3546,7 @@ function Modal(props) {
|
|
|
3392
3546
|
e.stopPropagation();
|
|
3393
3547
|
handleClick();
|
|
3394
3548
|
onClick?.(e);
|
|
3395
|
-
}, role:
|
|
3549
|
+
}, role: "dialog", "aria-modal": top, "data-mid": mid, ...restProps, children: jsxs(ModalContext.Provider, { value: true, children: [customized && children, !customized && (jsx(Content$2, { title: title, hideCloseButton: hideCloseButton, footer: footer, okButtonProps: okButtonProps, cancelButtonProps: cancelButtonProps, children: children, footerLeft: footerLeft, onOk: onOk, onClose: handleHide }))] }) }) }), getContainer());
|
|
3396
3550
|
}
|
|
3397
3551
|
Modal.useModal = useModal;
|
|
3398
3552
|
|
|
@@ -3767,7 +3921,7 @@ function renderFile(props) {
|
|
|
3767
3921
|
}
|
|
3768
3922
|
|
|
3769
3923
|
function Content(props) {
|
|
3770
|
-
const { items = [], initial = 0, renderFile: renderFile$1 = renderFile, onRotate, onChange, onClose, onZoom, } = props;
|
|
3924
|
+
const { items = [], initial = 0, hideControl, renderFile: renderFile$1 = renderFile, onRotate, onChange, onClose, onZoom, } = props;
|
|
3771
3925
|
const state = useReactive({
|
|
3772
3926
|
current: initial,
|
|
3773
3927
|
rotate: 0,
|
|
@@ -3903,9 +4057,9 @@ function Content(props) {
|
|
|
3903
4057
|
transform: `translate(${state.translate
|
|
3904
4058
|
.map((n) => `${n}px`)
|
|
3905
4059
|
.join(",")}) rotate(${state.rotate}deg) scale(${state.scale})`,
|
|
3906
|
-
}, onMouseDown: handleMouseDown, onClick: (e) => e.stopPropagation(), children: content }), jsxs("div", { className: classNames("i-preview-controls", {
|
|
4060
|
+
}, onMouseDown: handleMouseDown, onClick: (e) => e.stopPropagation(), children: content }), !hideControl && (jsxs("div", { className: classNames("i-preview-controls", {
|
|
3907
4061
|
"i-preview-controls-hidden": state.controlHidden,
|
|
3908
|
-
}), children: [jsx(Button, { square: true, flat: true, onClick: onClose, children: jsx(Icon, { icon: jsx(CloseRound, {}) }) }), files.length > 1 && (jsxs("span", { className: 'px-8', children: [state.current + 1, " / ", files.length] })), state.scale !== 1 && (jsxs(Button, { flat: true, onClick: () => (state.scale = 1), children: [jsx(Icon, { icon: jsx(AspectRatioRound, {}) }), jsxs("span", { className: 'mt-2', children: [(state.scale * 100).toFixed(0), "%"] })] })), jsx(Button, { square: true, flat: true, href: file.src, target: '_blank', children: jsx(Icon, { icon: jsx(OpenInNewRound, {}) }) }), jsx(Button, { square: true, flat: true, href: file.src, download: true, target: '_blank', children: jsx(Icon, { icon: jsx(FileDownloadOutlined, {}) }) }), jsx(Button, { square: true, flat: true, onClick: () => handleRotate(90), children: jsx(Icon, { icon: jsx(RotateRightRound, {}) }) }), jsx(Button, { square: true, flat: true, onClick: () => handleRotate(-90), children: jsx(Icon, { icon: jsx(RotateLeftRound, {}) }) }), files.length > 1 && (jsxs(Fragment, { children: [jsx(Button, { square: true, flat: true, onClick: () => handleSwitch(state.current - 1), children: jsx(Icon, { icon: jsx(KeyboardArrowLeftRound, {}) }) }), jsx(Button, { square: true, flat: true, onClick: () => handleSwitch(state.current + 1), children: jsx(Icon, { icon: jsx(KeyboardArrowRightRound, {}) }) })] }))] })] }));
|
|
4062
|
+
}), children: [jsx(Button, { square: true, flat: true, onClick: onClose, children: jsx(Icon, { icon: jsx(CloseRound, {}) }) }), files.length > 1 && (jsxs("span", { className: 'px-8', children: [state.current + 1, " / ", files.length] })), state.scale !== 1 && (jsxs(Button, { flat: true, onClick: () => (state.scale = 1), children: [jsx(Icon, { icon: jsx(AspectRatioRound, {}) }), jsxs("span", { className: 'mt-2', children: [(state.scale * 100).toFixed(0), "%"] })] })), jsx(Button, { square: true, flat: true, href: file.src, target: '_blank', children: jsx(Icon, { icon: jsx(OpenInNewRound, {}) }) }), jsx(Button, { square: true, flat: true, href: file.src, download: true, target: '_blank', children: jsx(Icon, { icon: jsx(FileDownloadOutlined, {}) }) }), jsx(Button, { square: true, flat: true, onClick: () => handleRotate(90), children: jsx(Icon, { icon: jsx(RotateRightRound, {}) }) }), jsx(Button, { square: true, flat: true, onClick: () => handleRotate(-90), children: jsx(Icon, { icon: jsx(RotateLeftRound, {}) }) }), files.length > 1 && (jsxs(Fragment, { children: [jsx(Button, { square: true, flat: true, onClick: () => handleSwitch(state.current - 1), children: jsx(Icon, { icon: jsx(KeyboardArrowLeftRound, {}) }) }), jsx(Button, { square: true, flat: true, onClick: () => handleSwitch(state.current + 1), children: jsx(Icon, { icon: jsx(KeyboardArrowRightRound, {}) }) })] }))] }))] }));
|
|
3909
4063
|
}
|
|
3910
4064
|
|
|
3911
4065
|
function usePreview() {
|
|
@@ -4258,7 +4412,7 @@ const Textarea = (props) => {
|
|
|
4258
4412
|
onKeyDown: handleKeydown,
|
|
4259
4413
|
...restProps,
|
|
4260
4414
|
};
|
|
4261
|
-
return (jsx(InputContainer, { label: label, labelInline: labelInline, className: className, style: { width, ...style }, tip: message ?? tip, status: status, children: jsx("div", { className: classNames("i-input-item", {
|
|
4415
|
+
return (jsx(InputContainer, { label: label, labelInline: labelInline, className: classNames("i-textarea-label", className), style: { width, ...style }, tip: message ?? tip, status: status, children: jsx("div", { className: classNames("i-input-item", {
|
|
4262
4416
|
[`i-input-${status}`]: status !== "normal",
|
|
4263
4417
|
"i-input-borderless": !border,
|
|
4264
4418
|
}), children: jsx("textarea", { ...inputProps }) }) }));
|
|
@@ -5925,11 +6079,8 @@ const Tabs = ((props) => {
|
|
|
5925
6079
|
});
|
|
5926
6080
|
sourceKeysRef.current = sourceKeys;
|
|
5927
6081
|
contentsRef.current = nextContents;
|
|
5928
|
-
const nextTabs = [
|
|
5929
|
-
|
|
5930
|
-
...dynamicTabs,
|
|
5931
|
-
];
|
|
5932
|
-
setTabs((currentTabs) => isSameTabs(currentTabs, nextTabs) ? currentTabs : nextTabs);
|
|
6082
|
+
const nextTabs = [...sourceTabs.filter((tab) => !hiddenSourceKeysRef.current.has(String(tab.key))), ...dynamicTabs];
|
|
6083
|
+
setTabs((currentTabs) => (isSameTabs(currentTabs, nextTabs) ? currentTabs : nextTabs));
|
|
5933
6084
|
}, [parsedTabs]);
|
|
5934
6085
|
const add = (tab, position) => {
|
|
5935
6086
|
const currentTabs = tabsRef.current;
|
|
@@ -5943,9 +6094,7 @@ const Tabs = ((props) => {
|
|
|
5943
6094
|
const { content, ...rest } = tab;
|
|
5944
6095
|
setTabs((ts) => {
|
|
5945
6096
|
const nextTabs = [...ts];
|
|
5946
|
-
const index = position === undefined
|
|
5947
|
-
? nextTabs.length
|
|
5948
|
-
: Math.max(0, Math.min(position, nextTabs.length));
|
|
6097
|
+
const index = position === undefined ? nextTabs.length : Math.max(0, Math.min(position, nextTabs.length));
|
|
5949
6098
|
nextTabs.splice(index, 0, { ...rest, key: tkey });
|
|
5950
6099
|
return nextTabs;
|
|
5951
6100
|
});
|
|
@@ -6027,8 +6176,7 @@ const Tabs = ((props) => {
|
|
|
6027
6176
|
setTabs((ts) => {
|
|
6028
6177
|
let changed = false;
|
|
6029
6178
|
const next = ts.map((t) => {
|
|
6030
|
-
if (t.intersecting === undefined ||
|
|
6031
|
-
t.intersecting === true) {
|
|
6179
|
+
if (t.intersecting === undefined || t.intersecting === true) {
|
|
6032
6180
|
return t;
|
|
6033
6181
|
}
|
|
6034
6182
|
changed = true;
|
|
@@ -6049,7 +6197,7 @@ const Tabs = ((props) => {
|
|
|
6049
6197
|
return ts;
|
|
6050
6198
|
if (ts[i]?.intersecting === visible)
|
|
6051
6199
|
return ts;
|
|
6052
|
-
return ts.map((t, idx) => idx === i ? { ...t, intersecting: visible } : t);
|
|
6200
|
+
return ts.map((t, idx) => (idx === i ? { ...t, intersecting: visible } : t));
|
|
6053
6201
|
});
|
|
6054
6202
|
});
|
|
6055
6203
|
});
|
|
@@ -6074,10 +6222,9 @@ const Tabs = ((props) => {
|
|
|
6074
6222
|
});
|
|
6075
6223
|
}
|
|
6076
6224
|
const { offsetHeight, offsetLeft, offsetTop, offsetWidth } = nav;
|
|
6077
|
-
const isLine = type === "line";
|
|
6078
6225
|
setBarStyle({
|
|
6079
|
-
height:
|
|
6080
|
-
width:
|
|
6226
|
+
height: offsetHeight * 0.5,
|
|
6227
|
+
width: offsetWidth,
|
|
6081
6228
|
transform: `translate(${offsetLeft}px, ${offsetTop}px)`,
|
|
6082
6229
|
});
|
|
6083
6230
|
}, 16);
|
|
@@ -6119,39 +6266,14 @@ const Tabs = ((props) => {
|
|
|
6119
6266
|
navs: navsRef,
|
|
6120
6267
|
}));
|
|
6121
6268
|
const cachedTabKeySet = useMemo(() => new Set(cachedTabs), [cachedTabs]);
|
|
6122
|
-
const moreTabs = useMemo(() => !hideMore && overflow
|
|
6123
|
-
? tabs.filter((tab) => tab.intersecting === false)
|
|
6124
|
-
: [], [hideMore, overflow, tabs]);
|
|
6269
|
+
const moreTabs = useMemo(() => (!hideMore && overflow ? tabs.filter((tab) => tab.intersecting === false) : []), [hideMore, overflow, tabs]);
|
|
6125
6270
|
return (jsxs("div", { className: classNames("i-tabs", { flex: vertical, [`i-tabs-${type}`]: type !== "default" }, className), ...rest, children: [jsxs("div", { className: classNames("i-tab-navs-container", navsClass, {
|
|
6126
6271
|
"i-tab-navs-vertical": vertical,
|
|
6127
6272
|
}), children: [prepend, jsx(TabsNavs$1, { tabs: tabs, moreTabs: moreTabs, activeKey: activeKey, vertical: vertical, overflow: overflow, hideMore: hideMore, navsJustify: navsJustify, bar: bar, barClass: barClass, barStyle: barStyle, navsRef: navsRef, renderMore: renderMore, setNavRef: setNavRef, onOpen: open, onClose: close, onMoreTabClick: handleMoreTabClick, onKeyAction: handleKeyAction }), append] }), jsx(TabsContents$1, { tabs: tabs, activeKey: activeKey, cachedTabKeySet: cachedTabKeySet, getContent: getContent })] }));
|
|
6128
6273
|
});
|
|
6129
6274
|
Tabs.Item = Item;
|
|
6130
6275
|
|
|
6131
|
-
|
|
6132
|
-
const { data = [], depth = 0, round, style, className, parent, nodeProps, ...restProps } = props;
|
|
6133
|
-
const contents = data.map((item, i) => {
|
|
6134
|
-
const { type } = item;
|
|
6135
|
-
const title = item[nodeProps.title];
|
|
6136
|
-
const itemKey = item[nodeProps.key] ||
|
|
6137
|
-
(parent?.key !== undefined ? `${parent.key}-${i}` : `${i}`);
|
|
6138
|
-
item.key = itemKey;
|
|
6139
|
-
item.parent = parent;
|
|
6140
|
-
if (type === "title") {
|
|
6141
|
-
return (jsx("div", { className: 'i-tree-group-title', children: title }, i));
|
|
6142
|
-
}
|
|
6143
|
-
if (type && type !== "item") {
|
|
6144
|
-
return (jsx("div", { className: `i-tree-type-${type}`, children: title }, i));
|
|
6145
|
-
}
|
|
6146
|
-
return (jsx(TreeItem, { index: i, item: item, depth: depth, nodeProps: nodeProps, ...restProps }, itemKey));
|
|
6147
|
-
});
|
|
6148
|
-
if (depth > 0)
|
|
6149
|
-
return jsx(Fragment, { children: contents });
|
|
6150
|
-
return (jsx("div", { className: classNames("i-tree", className, {
|
|
6151
|
-
"i-tree-round": round,
|
|
6152
|
-
}), style: style, children: contents }));
|
|
6153
|
-
}
|
|
6154
|
-
const Header = (props) => {
|
|
6276
|
+
const TreeItemHeader = (props) => {
|
|
6155
6277
|
const { as: Tag = "a", href, selected, children, ...restProps } = props;
|
|
6156
6278
|
const className = classNames("i-tree-item-header", {
|
|
6157
6279
|
"i-tree-item-selected": selected,
|
|
@@ -6161,50 +6283,166 @@ const Header = (props) => {
|
|
|
6161
6283
|
}
|
|
6162
6284
|
return (jsx(Tag, { to: href || "", className: className, ...restProps, children: children }));
|
|
6163
6285
|
};
|
|
6164
|
-
|
|
6165
|
-
const {
|
|
6166
|
-
const {
|
|
6167
|
-
const
|
|
6168
|
-
const
|
|
6169
|
-
const
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
}
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6286
|
+
function TreeRow(props) {
|
|
6287
|
+
const { flatNode, wrapperStyle, virtualMode, selected, checkedSet, partofs = {}, checkable, nodeProps, renderExtra, loadingKeys, onExpand, onItemClick, onItemSelect, onItemCheck, } = props;
|
|
6288
|
+
const { node, depth, isExpanded } = flatNode;
|
|
6289
|
+
const { key = "", as, href, icon, title, disabled, type } = node;
|
|
6290
|
+
const children = node[nodeProps.children];
|
|
6291
|
+
const hasChildren = children instanceof Promise || (Array.isArray(children) && children.length > 0);
|
|
6292
|
+
const loading = loadingKeys?.includes(key);
|
|
6293
|
+
if (type === "title") {
|
|
6294
|
+
return jsx("div", { style: wrapperStyle, className: "i-tree-group-title", children: title });
|
|
6295
|
+
}
|
|
6296
|
+
if (type && type !== "item") {
|
|
6297
|
+
return jsx("div", { style: wrapperStyle, className: `i-tree-type-${type}`, children: title });
|
|
6298
|
+
}
|
|
6299
|
+
return (jsx("div", { className: !virtualMode ? classNames("i-tree-item", { "i-tree-expand": isExpanded }) : undefined, style: wrapperStyle, children: jsxs(TreeItemHeader, { as: as, href: href, style: { paddingLeft: `${depth * 1.5 + 0.5}em` }, selected: selected === key, onClick: (e) => {
|
|
6300
|
+
if (disabled) {
|
|
6301
|
+
e.preventDefault();
|
|
6302
|
+
e.stopPropagation();
|
|
6303
|
+
return;
|
|
6304
|
+
}
|
|
6305
|
+
if (hasChildren)
|
|
6306
|
+
onExpand(key);
|
|
6307
|
+
onItemClick?.(node, e);
|
|
6308
|
+
onItemSelect?.(key, node);
|
|
6309
|
+
}, children: [checkable && (jsx(Checkbox.Item, { value: checkedSet.has(key), partof: !checkedSet.has(key) && partofs[key], className: "i-tree-checkbox", onChange: () => onItemCheck?.(node, !checkedSet.has(key), []), onClick: (e) => e.stopPropagation() })), icon && jsx("span", { className: "i-tree-item-icon", children: icon }), jsx("span", { className: "i-tree-item-title", children: title }), renderExtra?.(node), hasChildren && (jsx(Icon, { icon: loading ? jsx(Loading, { size: ".86em" }) : jsx(KeyboardArrowDownRound, {}), className: classNames("i-tree-toggle", {
|
|
6310
|
+
"i-tree-expand": virtualMode ? isExpanded : false,
|
|
6311
|
+
}), onClick: (e) => {
|
|
6312
|
+
e.preventDefault();
|
|
6313
|
+
e.stopPropagation();
|
|
6314
|
+
onExpand(key);
|
|
6315
|
+
} }))] }) }));
|
|
6316
|
+
}
|
|
6317
|
+
function TreeList(props) {
|
|
6318
|
+
const { flatNodes, onExpand, selected, checkedSet, partofs = {}, checkable, nodeProps, renderExtra, loadingKeys, round, className, style, onItemClick, onItemSelect, onItemCheck } = props;
|
|
6319
|
+
return (jsx("div", { className: classNames("i-tree", className, {
|
|
6320
|
+
"i-tree-round": round,
|
|
6321
|
+
}), style: style, children: flatNodes.map((flatNode) => {
|
|
6322
|
+
const { key = "" } = flatNode.node;
|
|
6323
|
+
return (jsx(TreeRow, { flatNode: flatNode, selected: selected, checkedSet: checkedSet, partofs: partofs, checkable: checkable, nodeProps: nodeProps, renderExtra: renderExtra, loadingKeys: loadingKeys, onExpand: onExpand, onItemClick: onItemClick, onItemSelect: onItemSelect, onItemCheck: onItemCheck }, key));
|
|
6324
|
+
}) }));
|
|
6325
|
+
}
|
|
6326
|
+
|
|
6327
|
+
function VirtualTree(props) {
|
|
6328
|
+
const { flatNodes, onExpand, selected, checkedSet, partofs = {}, checkable, nodeProps, renderExtra, loadingKeys, height, useVirtual, className, style, onItemClick, onItemSelect, onItemCheck, } = props;
|
|
6329
|
+
const listRef = useRef(null);
|
|
6330
|
+
const wrapRef = useRef(null);
|
|
6331
|
+
const ro = useResizeObserver();
|
|
6332
|
+
const [viewportHeight, setViewportHeight] = useState(0);
|
|
6333
|
+
useEffect(() => {
|
|
6334
|
+
const el = wrapRef.current;
|
|
6335
|
+
if (!el)
|
|
6182
6336
|
return;
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6193
|
-
|
|
6337
|
+
const update = () => {
|
|
6338
|
+
const r = el.getBoundingClientRect();
|
|
6339
|
+
setViewportHeight((prev) => (prev === r.height ? prev : r.height));
|
|
6340
|
+
};
|
|
6341
|
+
update();
|
|
6342
|
+
ro.observe?.(el, update);
|
|
6343
|
+
return () => ro.unobserve?.(el);
|
|
6344
|
+
}, [ro]);
|
|
6345
|
+
const listHeight = Math.max(0, (typeof height === "number" ? height : viewportHeight || 360));
|
|
6346
|
+
const propsRef = useRef(props);
|
|
6347
|
+
propsRef.current = props;
|
|
6348
|
+
const rowComponent = useCallback(({ index, style, }) => {
|
|
6349
|
+
const p = propsRef.current;
|
|
6350
|
+
const flatNode = p.flatNodes[index];
|
|
6351
|
+
if (!flatNode)
|
|
6352
|
+
return null;
|
|
6353
|
+
return (jsx(TreeRow, { flatNode: flatNode, wrapperStyle: style, virtualMode: true, selected: p.selected, checkedSet: p.checkedSet, partofs: p.partofs, checkable: p.checkable, nodeProps: p.nodeProps, renderExtra: p.renderExtra, loadingKeys: p.loadingKeys, onExpand: p.onExpand, onItemClick: p.onItemClick, onItemSelect: p.onItemSelect, onItemCheck: p.onItemCheck }));
|
|
6354
|
+
}, []);
|
|
6355
|
+
return (jsx("div", { ref: wrapRef, className: classNames("i-tree", className), style: { display: "block", width: "100%", height: "100%", ...style }, children: jsx(List$2, { listRef: listRef, rowCount: flatNodes.length, rowHeight: useVirtual.rowHeight, overscanCount: Math.max(3, useVirtual.threshold ?? 8), rowProps: {}, style: {
|
|
6356
|
+
width: "100%",
|
|
6357
|
+
height: listHeight,
|
|
6358
|
+
overflow: "auto",
|
|
6359
|
+
}, rowComponent: rowComponent }) }));
|
|
6360
|
+
}
|
|
6194
6361
|
|
|
6195
6362
|
const defaultNodeProps = {
|
|
6196
6363
|
key: "key",
|
|
6197
6364
|
title: "title",
|
|
6198
6365
|
children: "children",
|
|
6199
6366
|
};
|
|
6367
|
+
function flattenTree(nodes, expandedMap, nodeProps, depth = 0, parentItem, asyncChildrenMap = {}) {
|
|
6368
|
+
const result = [];
|
|
6369
|
+
nodes.forEach((item, i) => {
|
|
6370
|
+
const mapKey = item[nodeProps.key];
|
|
6371
|
+
item.key = mapKey || `${parentItem?.key ?? ""}-${i}`;
|
|
6372
|
+
item.parent = parentItem;
|
|
6373
|
+
const isExpanded = !!expandedMap[item.key];
|
|
6374
|
+
result.push({ node: item, depth, isExpanded });
|
|
6375
|
+
const children = asyncChildrenMap[item.key] || item[nodeProps.children];
|
|
6376
|
+
if (Array.isArray(children) && children.length) {
|
|
6377
|
+
const childNodes = flattenTree(children, expandedMap, nodeProps, depth + 1, item, asyncChildrenMap);
|
|
6378
|
+
if (isExpanded)
|
|
6379
|
+
result.push(...childNodes);
|
|
6380
|
+
}
|
|
6381
|
+
});
|
|
6382
|
+
return result;
|
|
6383
|
+
}
|
|
6200
6384
|
const Tree = (props) => {
|
|
6201
|
-
const { data = [], ref, selected, checked = [], disabledRelated, nodeProps, onItemSelect, onItemCheck, ...restProps } = props;
|
|
6385
|
+
const { data = [], ref, selected, checked = [], disabledRelated, nodeProps, height, useVirtual, onItemSelect, onItemCheck, ...restProps } = props;
|
|
6202
6386
|
const [selectedKey, setSelectedKey] = useState(selected);
|
|
6203
6387
|
const [checkedKeys, setCheckedKeys] = useState(checked);
|
|
6204
6388
|
const [partofs, setPartofs] = useState({});
|
|
6389
|
+
const [loadingMap, setLoadingMap] = useState({});
|
|
6390
|
+
const [asyncChildrenMap, setAsyncChildrenMap] = useState({});
|
|
6205
6391
|
const nodeMapsRef = useRef(new Map());
|
|
6206
|
-
const oNodeProps =
|
|
6207
|
-
const
|
|
6392
|
+
const oNodeProps = useMemo(() => ({ ...defaultNodeProps, ...nodeProps }), [nodeProps]);
|
|
6393
|
+
const checkedSet = useMemo(() => new Set(checkedKeys), [checkedKeys]);
|
|
6394
|
+
const [expandedMap, setExpandedMap] = useState(() => {
|
|
6395
|
+
const map = {};
|
|
6396
|
+
const walk = (nodes, parentKey = "") => {
|
|
6397
|
+
nodes.forEach((item, i) => {
|
|
6398
|
+
const mapKey = item[oNodeProps.key];
|
|
6399
|
+
const key = mapKey || `${parentKey}-${i}`;
|
|
6400
|
+
if (item.expanded)
|
|
6401
|
+
map[key] = true;
|
|
6402
|
+
const children = item[oNodeProps.children];
|
|
6403
|
+
if (Array.isArray(children) && children.length)
|
|
6404
|
+
walk(children, key);
|
|
6405
|
+
});
|
|
6406
|
+
};
|
|
6407
|
+
walk(data);
|
|
6408
|
+
return map;
|
|
6409
|
+
});
|
|
6410
|
+
const handleExpand = (key) => {
|
|
6411
|
+
if (loadingMap[key])
|
|
6412
|
+
return;
|
|
6413
|
+
const item = nodeMapsRef.current.get(key);
|
|
6414
|
+
if (!item)
|
|
6415
|
+
return;
|
|
6416
|
+
const rawChildren = item[oNodeProps.children];
|
|
6417
|
+
const isAsync = rawChildren instanceof Promise;
|
|
6418
|
+
const isExpanded = !!expandedMap[key];
|
|
6419
|
+
if (isAsync && !isExpanded) {
|
|
6420
|
+
flushSync(() => {
|
|
6421
|
+
setLoadingMap((prev) => ({ ...prev, [key]: true }));
|
|
6422
|
+
setExpandedMap((prev) => ({ ...prev, [key]: true }));
|
|
6423
|
+
});
|
|
6424
|
+
rawChildren
|
|
6425
|
+
.then((resolved) => {
|
|
6426
|
+
item[oNodeProps.children] = resolved;
|
|
6427
|
+
setAsyncChildrenMap((prev) => ({ ...prev, [key]: resolved }));
|
|
6428
|
+
})
|
|
6429
|
+
.finally(() => {
|
|
6430
|
+
setLoadingMap((prev) => {
|
|
6431
|
+
const next = { ...prev };
|
|
6432
|
+
delete next[key];
|
|
6433
|
+
return next;
|
|
6434
|
+
});
|
|
6435
|
+
});
|
|
6436
|
+
}
|
|
6437
|
+
else {
|
|
6438
|
+
setExpandedMap((prev) => ({
|
|
6439
|
+
...prev,
|
|
6440
|
+
[key]: !prev[key],
|
|
6441
|
+
}));
|
|
6442
|
+
}
|
|
6443
|
+
};
|
|
6444
|
+
const flatNodes = useMemo(() => flattenTree(data, expandedMap, oNodeProps, 0, undefined, asyncChildrenMap), [data, expandedMap, oNodeProps, asyncChildrenMap]);
|
|
6445
|
+
const loadingKeys = useMemo(() => Object.keys(loadingMap).filter((k) => loadingMap[k]), [loadingMap]);
|
|
6208
6446
|
const checkItem = (item, checked, direction) => {
|
|
6209
6447
|
const { key = "", parent, children } = item;
|
|
6210
6448
|
const shouldChanged = { [key]: checked };
|
|
@@ -6213,7 +6451,9 @@ const Tree = (props) => {
|
|
|
6213
6451
|
return [shouldChanged];
|
|
6214
6452
|
if (checked) {
|
|
6215
6453
|
if (parent && direction !== "leaf") {
|
|
6216
|
-
const hasUnchecked = parent.children
|
|
6454
|
+
const hasUnchecked = Array.isArray(parent.children)
|
|
6455
|
+
? parent.children.some((o) => o.key !== key && !checkedSet.has(o.key))
|
|
6456
|
+
: false;
|
|
6217
6457
|
const [changes, parts] = checkItem(parent, true, "root");
|
|
6218
6458
|
if (!hasUnchecked) {
|
|
6219
6459
|
Object.assign(shouldChanged, changes);
|
|
@@ -6222,9 +6462,9 @@ const Tree = (props) => {
|
|
|
6222
6462
|
[parent.key]: true,
|
|
6223
6463
|
});
|
|
6224
6464
|
}
|
|
6225
|
-
if (children
|
|
6465
|
+
if (Array.isArray(children) && children.length && direction !== "root") {
|
|
6226
6466
|
children.map((o) => {
|
|
6227
|
-
if (
|
|
6467
|
+
if (checkedSet.has(o.key))
|
|
6228
6468
|
return;
|
|
6229
6469
|
const [changes] = checkItem(o, true, "leaf");
|
|
6230
6470
|
Object.assign(shouldChanged, changes);
|
|
@@ -6236,16 +6476,18 @@ const Tree = (props) => {
|
|
|
6236
6476
|
if (parent && direction !== "leaf") {
|
|
6237
6477
|
const [changes, parts] = checkItem(parent, false, "root");
|
|
6238
6478
|
Object.assign(shouldChanged, changes);
|
|
6239
|
-
const hasChecked = parent.children
|
|
6479
|
+
const hasChecked = Array.isArray(parent.children)
|
|
6480
|
+
? parent.children.some((o) => checkedSet.has(o.key) && o.key !== key)
|
|
6481
|
+
: false;
|
|
6240
6482
|
Object.assign(partofs, hasChecked ? {} : parts, {
|
|
6241
6483
|
[parent.key]: hasChecked,
|
|
6242
6484
|
[key]: false,
|
|
6243
6485
|
});
|
|
6244
6486
|
}
|
|
6245
|
-
if (children
|
|
6487
|
+
if (Array.isArray(children) && children.length && direction !== "root") {
|
|
6246
6488
|
children.map((o) => {
|
|
6247
6489
|
const [changes] = checkItem(o, false, "leaf");
|
|
6248
|
-
if (!
|
|
6490
|
+
if (!checkedSet.has(o.key))
|
|
6249
6491
|
return;
|
|
6250
6492
|
Object.assign(shouldChanged, changes);
|
|
6251
6493
|
partofs[o.key] = false;
|
|
@@ -6256,9 +6498,10 @@ const Tree = (props) => {
|
|
|
6256
6498
|
const handleCheck = (item, checked) => {
|
|
6257
6499
|
const [shouldChanged, partofs] = checkItem(item, checked);
|
|
6258
6500
|
const changedKeys = Object.keys(shouldChanged);
|
|
6501
|
+
const changedKeysSet = new Set(changedKeys);
|
|
6259
6502
|
const nextChecked = checked
|
|
6260
6503
|
? Array.from(new Set([...checkedKeys, ...changedKeys]))
|
|
6261
|
-
: checkedKeys.filter((k) => !
|
|
6504
|
+
: checkedKeys.filter((k) => !changedKeysSet.has(k));
|
|
6262
6505
|
setCheckedKeys(nextChecked);
|
|
6263
6506
|
setPartofs((p) => ({ ...p, ...partofs }));
|
|
6264
6507
|
onItemCheck?.(item, checked, nextChecked);
|
|
@@ -6276,15 +6519,37 @@ const Tree = (props) => {
|
|
|
6276
6519
|
}, [selected]);
|
|
6277
6520
|
useEffect(() => {
|
|
6278
6521
|
nodeMapsRef.current.clear();
|
|
6279
|
-
const { key, children } = oNodeProps;
|
|
6280
|
-
const
|
|
6281
|
-
nodes.
|
|
6282
|
-
|
|
6283
|
-
|
|
6522
|
+
const { key: keyProp, children: childrenProp } = oNodeProps;
|
|
6523
|
+
const walk = (nodes, parentKey = "") => {
|
|
6524
|
+
nodes.forEach((item, i) => {
|
|
6525
|
+
const mapKey = item[keyProp];
|
|
6526
|
+
const key = (mapKey || `${parentKey}-${i}`);
|
|
6527
|
+
nodeMapsRef.current.set(key, item);
|
|
6528
|
+
const itemChildren = item[childrenProp];
|
|
6529
|
+
if (Array.isArray(itemChildren) && itemChildren.length) {
|
|
6530
|
+
walk(itemChildren, key);
|
|
6531
|
+
}
|
|
6284
6532
|
});
|
|
6285
6533
|
};
|
|
6286
|
-
|
|
6287
|
-
}, [data]);
|
|
6534
|
+
walk(data);
|
|
6535
|
+
}, [data, oNodeProps, asyncChildrenMap]);
|
|
6536
|
+
useEffect(() => {
|
|
6537
|
+
if (!props.selected)
|
|
6538
|
+
return;
|
|
6539
|
+
const node = nodeMapsRef.current.get(props.selected);
|
|
6540
|
+
if (!node)
|
|
6541
|
+
return;
|
|
6542
|
+
const toExpand = {};
|
|
6543
|
+
let p = node.parent;
|
|
6544
|
+
while (p) {
|
|
6545
|
+
if (p.key)
|
|
6546
|
+
toExpand[p.key] = true;
|
|
6547
|
+
p = p.parent;
|
|
6548
|
+
}
|
|
6549
|
+
if (Object.keys(toExpand).length > 0) {
|
|
6550
|
+
setExpandedMap((prev) => ({ ...prev, ...toExpand }));
|
|
6551
|
+
}
|
|
6552
|
+
}, [props.selected]);
|
|
6288
6553
|
useImperativeHandle(ref, () => {
|
|
6289
6554
|
return {
|
|
6290
6555
|
getChecked: () => {
|
|
@@ -6313,7 +6578,10 @@ const Tree = (props) => {
|
|
|
6313
6578
|
},
|
|
6314
6579
|
};
|
|
6315
6580
|
});
|
|
6316
|
-
|
|
6581
|
+
if (useVirtual) {
|
|
6582
|
+
return (jsx(VirtualTree, { flatNodes: flatNodes, onExpand: handleExpand, height: height, useVirtual: useVirtual, selected: selectedKey, checkedSet: checkedSet, partofs: partofs, nodeProps: oNodeProps, loadingKeys: loadingKeys, onItemCheck: handleCheck, onItemSelect: handleSelect, ...restProps }));
|
|
6583
|
+
}
|
|
6584
|
+
return (jsx(TreeList, { flatNodes: flatNodes, onExpand: handleExpand, selected: selectedKey, checkedSet: checkedSet, partofs: partofs, nodeProps: oNodeProps, loadingKeys: loadingKeys, onItemCheck: handleCheck, onItemSelect: handleSelect, ...restProps }));
|
|
6317
6585
|
};
|
|
6318
6586
|
|
|
6319
6587
|
const Dropbox = (props) => {
|