@ioca/react 1.5.19 → 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/form/useForm.js +1 -1
- package/lib/cjs/components/form/useForm.js.map +1 -1
- 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/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 +0 -4
- package/lib/es/components/datagrid/virtual.js +130 -103
- package/lib/es/components/datagrid/virtual.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/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/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 +338 -197
- 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';
|
|
@@ -1186,7 +1186,7 @@ function Row(props) {
|
|
|
1186
1186
|
}, [data, onRowClick, row]);
|
|
1187
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))) }));
|
|
1188
1188
|
}
|
|
1189
|
-
function Header
|
|
1189
|
+
function Header(props) {
|
|
1190
1190
|
const { columns, resizable, cellEllipsis, sortBy, sortType, onWidthChange, onHeaderClick, } = props;
|
|
1191
1191
|
const columnById = useMemo(() => {
|
|
1192
1192
|
const map = new Map();
|
|
@@ -1216,6 +1216,84 @@ function Header$1(props) {
|
|
|
1216
1216
|
}) }));
|
|
1217
1217
|
}
|
|
1218
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
|
+
// ---------------------------------------------------------------------------
|
|
1219
1297
|
function VirtualDatagrid(props) {
|
|
1220
1298
|
const { virtual, columns, rows, header, sortBy, sortType, height, loading, resizable, striped, cellEllipsis, empty, wrapRef, containerRef, onHeaderClick, onWidthChange, onRowClick, onCellClick, onCellDoubleClick, onScroll, } = props;
|
|
1221
1299
|
const headerRef = useRef(null);
|
|
@@ -1228,6 +1306,7 @@ function VirtualDatagrid(props) {
|
|
|
1228
1306
|
const rafRef = useRef({
|
|
1229
1307
|
viewport: 0,
|
|
1230
1308
|
contentWidth: 0,
|
|
1309
|
+
scrollSync: 0,
|
|
1231
1310
|
});
|
|
1232
1311
|
const columnById = useMemo(() => {
|
|
1233
1312
|
const map = new Map();
|
|
@@ -1239,38 +1318,6 @@ function VirtualDatagrid(props) {
|
|
|
1239
1318
|
columns.forEach((c, i) => map.set(c.id, i));
|
|
1240
1319
|
return map;
|
|
1241
1320
|
}, [columns]);
|
|
1242
|
-
const getVirtualCellStyle = useCallback(({ justify, col, colSpan = 1, }) => {
|
|
1243
|
-
return {
|
|
1244
|
-
"--datagrid-justify": justify,
|
|
1245
|
-
gridColumn: `${col + 1} / span ${colSpan}`,
|
|
1246
|
-
insetInline: `var(--datagrid-cell-inset-${col})`,
|
|
1247
|
-
};
|
|
1248
|
-
}, []);
|
|
1249
|
-
const renderVirtualCell = useCallback(({ column, data, row, col, isHeader, }) => {
|
|
1250
|
-
const { id, fixed, justify, colSpan, render, title, sorter, renderHeader, } = column;
|
|
1251
|
-
const style = {
|
|
1252
|
-
...getVirtualCellStyle({ justify, col, colSpan }),
|
|
1253
|
-
...(isHeader ? { insetBlockStart: 0 } : null),
|
|
1254
|
-
};
|
|
1255
|
-
const order = isHeader && sortBy === id ? sortType : "";
|
|
1256
|
-
return (jsxs("div", { "data-col": id, className: classNames("i-datagrid-cell", {
|
|
1257
|
-
[`i-datagrid-cell-fixed-${fixed}`]: fixed,
|
|
1258
|
-
"i-datagrid-has-sorter": isHeader && sorter,
|
|
1259
|
-
}), style: style, children: [isHeader
|
|
1260
|
-
? (renderHeader?.(column, col) ?? (jsx("div", { className: classNames("i-datagrid-cell-content", {
|
|
1261
|
-
"i-datagrid-cell-content-ellipsis": cellEllipsis,
|
|
1262
|
-
}), children: title || id })))
|
|
1263
|
-
: (render?.(data?.[id], data, row, col) ?? (jsx("div", { className: classNames("i-datagrid-cell-content", {
|
|
1264
|
-
"i-datagrid-cell-content-ellipsis": cellEllipsis,
|
|
1265
|
-
}), children: data?.[id] }))), isHeader && sorter && jsx(Sorter, { type: order }), isHeader && resizable && (jsx(Resize, { index: col, onWidthChange: onWidthChange }))] }, id));
|
|
1266
|
-
}, [
|
|
1267
|
-
cellEllipsis,
|
|
1268
|
-
getVirtualCellStyle,
|
|
1269
|
-
onWidthChange,
|
|
1270
|
-
resizable,
|
|
1271
|
-
sortBy,
|
|
1272
|
-
sortType,
|
|
1273
|
-
]);
|
|
1274
1321
|
const handleHeaderClick = useCallback((e) => {
|
|
1275
1322
|
const el = e.target?.closest?.(".i-datagrid-cell[data-col]");
|
|
1276
1323
|
const id = el?.dataset?.col;
|
|
@@ -1280,10 +1327,17 @@ function VirtualDatagrid(props) {
|
|
|
1280
1327
|
const el = e.currentTarget;
|
|
1281
1328
|
if (!el)
|
|
1282
1329
|
return;
|
|
1283
|
-
if (
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
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
|
+
});
|
|
1287
1341
|
}, []);
|
|
1288
1342
|
const handleReachEnd = useCallback(() => {
|
|
1289
1343
|
if (virtual.onReachEnd) {
|
|
@@ -1313,32 +1367,6 @@ function VirtualDatagrid(props) {
|
|
|
1313
1367
|
listEl.scrollLeft = el.scrollLeft;
|
|
1314
1368
|
}
|
|
1315
1369
|
}, []);
|
|
1316
|
-
const handleBodyClickCapture = useCallback((e, rowData, rowNum) => {
|
|
1317
|
-
if (!onCellClick)
|
|
1318
|
-
return;
|
|
1319
|
-
const el = e.target?.closest?.(".i-datagrid-cell[data-col]");
|
|
1320
|
-
const id = el?.dataset?.col;
|
|
1321
|
-
if (!id)
|
|
1322
|
-
return;
|
|
1323
|
-
const column = columnById.get(id);
|
|
1324
|
-
const col = columnIndexById.get(id);
|
|
1325
|
-
if (!column || col == null)
|
|
1326
|
-
return;
|
|
1327
|
-
onCellClick(rowData, column, rowNum, col, e);
|
|
1328
|
-
}, [columnById, columnIndexById, onCellClick]);
|
|
1329
|
-
const handleBodyDoubleClickCapture = useCallback((e, rowData, rowNum) => {
|
|
1330
|
-
if (!onCellDoubleClick)
|
|
1331
|
-
return;
|
|
1332
|
-
const el = e.target?.closest?.(".i-datagrid-cell[data-col]");
|
|
1333
|
-
const id = el?.dataset?.col;
|
|
1334
|
-
if (!id)
|
|
1335
|
-
return;
|
|
1336
|
-
const column = columnById.get(id);
|
|
1337
|
-
const col = columnIndexById.get(id);
|
|
1338
|
-
if (!column || col == null)
|
|
1339
|
-
return;
|
|
1340
|
-
onCellDoubleClick(rowData, column, rowNum, col, e);
|
|
1341
|
-
}, [columnById, columnIndexById, onCellDoubleClick]);
|
|
1342
1370
|
useEffect(() => {
|
|
1343
1371
|
const el = wrapRef.current;
|
|
1344
1372
|
if (!el)
|
|
@@ -1409,12 +1437,14 @@ function VirtualDatagrid(props) {
|
|
|
1409
1437
|
const contentWidthPx = measuredContentWidth
|
|
1410
1438
|
? `${measuredContentWidth}px`
|
|
1411
1439
|
: "fit-content";
|
|
1412
|
-
const headerCells = useMemo(() => columns.map((c, col) =>
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
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
|
+
]);
|
|
1418
1448
|
const headerInnerStyle = useMemo(() => ({
|
|
1419
1449
|
display: "grid",
|
|
1420
1450
|
gridTemplateColumns: "var(--grid-template-columns)",
|
|
@@ -1434,50 +1464,47 @@ function VirtualDatagrid(props) {
|
|
|
1434
1464
|
}
|
|
1435
1465
|
: undefined, [scrollbarSize]);
|
|
1436
1466
|
const loaderNode = useMemo(() => virtual.loader ?? jsx(Loading, { className: 'my-12' }), [virtual.loader]);
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
...itemStyle,
|
|
1441
|
-
width: contentWidthPx,
|
|
1442
|
-
minWidth: "100%",
|
|
1443
|
-
display: "flex",
|
|
1444
|
-
alignItems: "center",
|
|
1445
|
-
justifyContent: "center",
|
|
1446
|
-
}, children: loaderNode }));
|
|
1447
|
-
}
|
|
1448
|
-
const rowData = rows[index];
|
|
1449
|
-
const rowNum = index + (header ? 1 : 0);
|
|
1450
|
-
const bg = striped && index % 2 === 0 ? "var(--background-1)" : undefined;
|
|
1451
|
-
return (jsx("div", { style: {
|
|
1452
|
-
...itemStyle,
|
|
1453
|
-
width: contentWidthPx,
|
|
1454
|
-
minWidth: "100%",
|
|
1455
|
-
display: "grid",
|
|
1456
|
-
gridTemplateColumns: "var(--grid-template-columns)",
|
|
1457
|
-
height: virtual.rowHeight,
|
|
1458
|
-
"--datagrid-cell-background": bg,
|
|
1459
|
-
}, 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({
|
|
1460
|
-
column: c,
|
|
1461
|
-
data: rowData,
|
|
1462
|
-
row: rowNum,
|
|
1463
|
-
col,
|
|
1464
|
-
})) }));
|
|
1465
|
-
}, [
|
|
1467
|
+
// Stable row-component reference so react-window can memoise rows.
|
|
1468
|
+
const rowProps = useMemo(() => ({
|
|
1469
|
+
rows,
|
|
1466
1470
|
columns,
|
|
1471
|
+
columnById,
|
|
1472
|
+
columnIndexById,
|
|
1467
1473
|
contentWidthPx,
|
|
1468
|
-
|
|
1469
|
-
handleBodyDoubleClickCapture,
|
|
1474
|
+
virtualRowHeight: virtual.rowHeight,
|
|
1470
1475
|
header,
|
|
1476
|
+
striped,
|
|
1477
|
+
cellEllipsis,
|
|
1471
1478
|
loaderNode,
|
|
1479
|
+
sortBy,
|
|
1480
|
+
sortType,
|
|
1481
|
+
resizable,
|
|
1482
|
+
onWidthChange,
|
|
1472
1483
|
onRowClick,
|
|
1473
|
-
|
|
1484
|
+
onCellClick,
|
|
1485
|
+
onCellDoubleClick,
|
|
1486
|
+
}), [
|
|
1474
1487
|
rows,
|
|
1475
|
-
|
|
1488
|
+
columns,
|
|
1489
|
+
columnById,
|
|
1490
|
+
columnIndexById,
|
|
1491
|
+
contentWidthPx,
|
|
1476
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,
|
|
1477
1504
|
]);
|
|
1478
1505
|
return (jsxs("div", { ref: containerRef, className: classNames("i-datagrid", {
|
|
1479
1506
|
"i-datagrid-loading": loading,
|
|
1480
|
-
}), 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] }));
|
|
1481
1508
|
}
|
|
1482
1509
|
|
|
1483
1510
|
const Datagrid = (props) => {
|
|
@@ -1675,7 +1702,7 @@ const Datagrid = (props) => {
|
|
|
1675
1702
|
"i-datagrid-striped": striped,
|
|
1676
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", {
|
|
1677
1704
|
"i-datagrid-loading": loading,
|
|
1678
|
-
}), 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()] }));
|
|
1679
1706
|
};
|
|
1680
1707
|
|
|
1681
1708
|
const Description = (props) => {
|
|
@@ -3142,7 +3169,7 @@ class IFormInstance {
|
|
|
3142
3169
|
const { id, rules, data } = this;
|
|
3143
3170
|
if (!rules)
|
|
3144
3171
|
return data;
|
|
3145
|
-
const names = field ? [field] : Object.keys(this.cacheData);
|
|
3172
|
+
const names = field ? [field] : [...new Set([...Object.keys(this.cacheData), ...Object.keys(rules)])];
|
|
3146
3173
|
let isAllValid = true;
|
|
3147
3174
|
names.forEach((name) => {
|
|
3148
3175
|
const o = rules[name];
|
|
@@ -3894,7 +3921,7 @@ function renderFile(props) {
|
|
|
3894
3921
|
}
|
|
3895
3922
|
|
|
3896
3923
|
function Content(props) {
|
|
3897
|
-
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;
|
|
3898
3925
|
const state = useReactive({
|
|
3899
3926
|
current: initial,
|
|
3900
3927
|
rotate: 0,
|
|
@@ -4030,9 +4057,9 @@ function Content(props) {
|
|
|
4030
4057
|
transform: `translate(${state.translate
|
|
4031
4058
|
.map((n) => `${n}px`)
|
|
4032
4059
|
.join(",")}) rotate(${state.rotate}deg) scale(${state.scale})`,
|
|
4033
|
-
}, 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", {
|
|
4034
4061
|
"i-preview-controls-hidden": state.controlHidden,
|
|
4035
|
-
}), 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, {}) }) })] }))] }))] }));
|
|
4036
4063
|
}
|
|
4037
4064
|
|
|
4038
4065
|
function usePreview() {
|
|
@@ -6052,11 +6079,8 @@ const Tabs = ((props) => {
|
|
|
6052
6079
|
});
|
|
6053
6080
|
sourceKeysRef.current = sourceKeys;
|
|
6054
6081
|
contentsRef.current = nextContents;
|
|
6055
|
-
const nextTabs = [
|
|
6056
|
-
|
|
6057
|
-
...dynamicTabs,
|
|
6058
|
-
];
|
|
6059
|
-
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));
|
|
6060
6084
|
}, [parsedTabs]);
|
|
6061
6085
|
const add = (tab, position) => {
|
|
6062
6086
|
const currentTabs = tabsRef.current;
|
|
@@ -6070,9 +6094,7 @@ const Tabs = ((props) => {
|
|
|
6070
6094
|
const { content, ...rest } = tab;
|
|
6071
6095
|
setTabs((ts) => {
|
|
6072
6096
|
const nextTabs = [...ts];
|
|
6073
|
-
const index = position === undefined
|
|
6074
|
-
? nextTabs.length
|
|
6075
|
-
: Math.max(0, Math.min(position, nextTabs.length));
|
|
6097
|
+
const index = position === undefined ? nextTabs.length : Math.max(0, Math.min(position, nextTabs.length));
|
|
6076
6098
|
nextTabs.splice(index, 0, { ...rest, key: tkey });
|
|
6077
6099
|
return nextTabs;
|
|
6078
6100
|
});
|
|
@@ -6154,8 +6176,7 @@ const Tabs = ((props) => {
|
|
|
6154
6176
|
setTabs((ts) => {
|
|
6155
6177
|
let changed = false;
|
|
6156
6178
|
const next = ts.map((t) => {
|
|
6157
|
-
if (t.intersecting === undefined ||
|
|
6158
|
-
t.intersecting === true) {
|
|
6179
|
+
if (t.intersecting === undefined || t.intersecting === true) {
|
|
6159
6180
|
return t;
|
|
6160
6181
|
}
|
|
6161
6182
|
changed = true;
|
|
@@ -6176,7 +6197,7 @@ const Tabs = ((props) => {
|
|
|
6176
6197
|
return ts;
|
|
6177
6198
|
if (ts[i]?.intersecting === visible)
|
|
6178
6199
|
return ts;
|
|
6179
|
-
return ts.map((t, idx) => idx === i ? { ...t, intersecting: visible } : t);
|
|
6200
|
+
return ts.map((t, idx) => (idx === i ? { ...t, intersecting: visible } : t));
|
|
6180
6201
|
});
|
|
6181
6202
|
});
|
|
6182
6203
|
});
|
|
@@ -6201,10 +6222,9 @@ const Tabs = ((props) => {
|
|
|
6201
6222
|
});
|
|
6202
6223
|
}
|
|
6203
6224
|
const { offsetHeight, offsetLeft, offsetTop, offsetWidth } = nav;
|
|
6204
|
-
const isLine = type === "line";
|
|
6205
6225
|
setBarStyle({
|
|
6206
|
-
height:
|
|
6207
|
-
width:
|
|
6226
|
+
height: offsetHeight * 0.5,
|
|
6227
|
+
width: offsetWidth,
|
|
6208
6228
|
transform: `translate(${offsetLeft}px, ${offsetTop}px)`,
|
|
6209
6229
|
});
|
|
6210
6230
|
}, 16);
|
|
@@ -6246,39 +6266,14 @@ const Tabs = ((props) => {
|
|
|
6246
6266
|
navs: navsRef,
|
|
6247
6267
|
}));
|
|
6248
6268
|
const cachedTabKeySet = useMemo(() => new Set(cachedTabs), [cachedTabs]);
|
|
6249
|
-
const moreTabs = useMemo(() => !hideMore && overflow
|
|
6250
|
-
? tabs.filter((tab) => tab.intersecting === false)
|
|
6251
|
-
: [], [hideMore, overflow, tabs]);
|
|
6269
|
+
const moreTabs = useMemo(() => (!hideMore && overflow ? tabs.filter((tab) => tab.intersecting === false) : []), [hideMore, overflow, tabs]);
|
|
6252
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, {
|
|
6253
6271
|
"i-tab-navs-vertical": vertical,
|
|
6254
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 })] }));
|
|
6255
6273
|
});
|
|
6256
6274
|
Tabs.Item = Item;
|
|
6257
6275
|
|
|
6258
|
-
|
|
6259
|
-
const { data = [], depth = 0, round, style, className, parent, nodeProps, ...restProps } = props;
|
|
6260
|
-
const contents = data.map((item, i) => {
|
|
6261
|
-
const { type } = item;
|
|
6262
|
-
const title = item[nodeProps.title];
|
|
6263
|
-
const itemKey = item[nodeProps.key] ||
|
|
6264
|
-
(parent?.key !== undefined ? `${parent.key}-${i}` : `${i}`);
|
|
6265
|
-
item.key = itemKey;
|
|
6266
|
-
item.parent = parent;
|
|
6267
|
-
if (type === "title") {
|
|
6268
|
-
return (jsx("div", { className: 'i-tree-group-title', children: title }, i));
|
|
6269
|
-
}
|
|
6270
|
-
if (type && type !== "item") {
|
|
6271
|
-
return (jsx("div", { className: `i-tree-type-${type}`, children: title }, i));
|
|
6272
|
-
}
|
|
6273
|
-
return (jsx(TreeItem, { index: i, item: item, depth: depth, nodeProps: nodeProps, ...restProps }, itemKey));
|
|
6274
|
-
});
|
|
6275
|
-
if (depth > 0)
|
|
6276
|
-
return jsx(Fragment, { children: contents });
|
|
6277
|
-
return (jsx("div", { className: classNames("i-tree", className, {
|
|
6278
|
-
"i-tree-round": round,
|
|
6279
|
-
}), style: style, children: contents }));
|
|
6280
|
-
}
|
|
6281
|
-
const Header = (props) => {
|
|
6276
|
+
const TreeItemHeader = (props) => {
|
|
6282
6277
|
const { as: Tag = "a", href, selected, children, ...restProps } = props;
|
|
6283
6278
|
const className = classNames("i-tree-item-header", {
|
|
6284
6279
|
"i-tree-item-selected": selected,
|
|
@@ -6288,50 +6283,166 @@ const Header = (props) => {
|
|
|
6288
6283
|
}
|
|
6289
6284
|
return (jsx(Tag, { to: href || "", className: className, ...restProps, children: children }));
|
|
6290
6285
|
};
|
|
6291
|
-
|
|
6292
|
-
const {
|
|
6293
|
-
const {
|
|
6294
|
-
const
|
|
6295
|
-
const
|
|
6296
|
-
const
|
|
6297
|
-
|
|
6298
|
-
|
|
6299
|
-
|
|
6300
|
-
|
|
6301
|
-
|
|
6302
|
-
|
|
6303
|
-
|
|
6304
|
-
}
|
|
6305
|
-
|
|
6306
|
-
|
|
6307
|
-
|
|
6308
|
-
|
|
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)
|
|
6309
6336
|
return;
|
|
6310
|
-
|
|
6311
|
-
|
|
6312
|
-
|
|
6313
|
-
|
|
6314
|
-
|
|
6315
|
-
|
|
6316
|
-
|
|
6317
|
-
|
|
6318
|
-
|
|
6319
|
-
|
|
6320
|
-
|
|
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
|
+
}
|
|
6321
6361
|
|
|
6322
6362
|
const defaultNodeProps = {
|
|
6323
6363
|
key: "key",
|
|
6324
6364
|
title: "title",
|
|
6325
6365
|
children: "children",
|
|
6326
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
|
+
}
|
|
6327
6384
|
const Tree = (props) => {
|
|
6328
|
-
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;
|
|
6329
6386
|
const [selectedKey, setSelectedKey] = useState(selected);
|
|
6330
6387
|
const [checkedKeys, setCheckedKeys] = useState(checked);
|
|
6331
6388
|
const [partofs, setPartofs] = useState({});
|
|
6389
|
+
const [loadingMap, setLoadingMap] = useState({});
|
|
6390
|
+
const [asyncChildrenMap, setAsyncChildrenMap] = useState({});
|
|
6332
6391
|
const nodeMapsRef = useRef(new Map());
|
|
6333
|
-
const oNodeProps =
|
|
6334
|
-
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]);
|
|
6335
6446
|
const checkItem = (item, checked, direction) => {
|
|
6336
6447
|
const { key = "", parent, children } = item;
|
|
6337
6448
|
const shouldChanged = { [key]: checked };
|
|
@@ -6340,7 +6451,9 @@ const Tree = (props) => {
|
|
|
6340
6451
|
return [shouldChanged];
|
|
6341
6452
|
if (checked) {
|
|
6342
6453
|
if (parent && direction !== "leaf") {
|
|
6343
|
-
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;
|
|
6344
6457
|
const [changes, parts] = checkItem(parent, true, "root");
|
|
6345
6458
|
if (!hasUnchecked) {
|
|
6346
6459
|
Object.assign(shouldChanged, changes);
|
|
@@ -6349,9 +6462,9 @@ const Tree = (props) => {
|
|
|
6349
6462
|
[parent.key]: true,
|
|
6350
6463
|
});
|
|
6351
6464
|
}
|
|
6352
|
-
if (children
|
|
6465
|
+
if (Array.isArray(children) && children.length && direction !== "root") {
|
|
6353
6466
|
children.map((o) => {
|
|
6354
|
-
if (
|
|
6467
|
+
if (checkedSet.has(o.key))
|
|
6355
6468
|
return;
|
|
6356
6469
|
const [changes] = checkItem(o, true, "leaf");
|
|
6357
6470
|
Object.assign(shouldChanged, changes);
|
|
@@ -6363,16 +6476,18 @@ const Tree = (props) => {
|
|
|
6363
6476
|
if (parent && direction !== "leaf") {
|
|
6364
6477
|
const [changes, parts] = checkItem(parent, false, "root");
|
|
6365
6478
|
Object.assign(shouldChanged, changes);
|
|
6366
|
-
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;
|
|
6367
6482
|
Object.assign(partofs, hasChecked ? {} : parts, {
|
|
6368
6483
|
[parent.key]: hasChecked,
|
|
6369
6484
|
[key]: false,
|
|
6370
6485
|
});
|
|
6371
6486
|
}
|
|
6372
|
-
if (children
|
|
6487
|
+
if (Array.isArray(children) && children.length && direction !== "root") {
|
|
6373
6488
|
children.map((o) => {
|
|
6374
6489
|
const [changes] = checkItem(o, false, "leaf");
|
|
6375
|
-
if (!
|
|
6490
|
+
if (!checkedSet.has(o.key))
|
|
6376
6491
|
return;
|
|
6377
6492
|
Object.assign(shouldChanged, changes);
|
|
6378
6493
|
partofs[o.key] = false;
|
|
@@ -6383,9 +6498,10 @@ const Tree = (props) => {
|
|
|
6383
6498
|
const handleCheck = (item, checked) => {
|
|
6384
6499
|
const [shouldChanged, partofs] = checkItem(item, checked);
|
|
6385
6500
|
const changedKeys = Object.keys(shouldChanged);
|
|
6501
|
+
const changedKeysSet = new Set(changedKeys);
|
|
6386
6502
|
const nextChecked = checked
|
|
6387
6503
|
? Array.from(new Set([...checkedKeys, ...changedKeys]))
|
|
6388
|
-
: checkedKeys.filter((k) => !
|
|
6504
|
+
: checkedKeys.filter((k) => !changedKeysSet.has(k));
|
|
6389
6505
|
setCheckedKeys(nextChecked);
|
|
6390
6506
|
setPartofs((p) => ({ ...p, ...partofs }));
|
|
6391
6507
|
onItemCheck?.(item, checked, nextChecked);
|
|
@@ -6403,15 +6519,37 @@ const Tree = (props) => {
|
|
|
6403
6519
|
}, [selected]);
|
|
6404
6520
|
useEffect(() => {
|
|
6405
6521
|
nodeMapsRef.current.clear();
|
|
6406
|
-
const { key, children } = oNodeProps;
|
|
6407
|
-
const
|
|
6408
|
-
nodes.
|
|
6409
|
-
|
|
6410
|
-
|
|
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
|
+
}
|
|
6411
6532
|
});
|
|
6412
6533
|
};
|
|
6413
|
-
|
|
6414
|
-
}, [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]);
|
|
6415
6553
|
useImperativeHandle(ref, () => {
|
|
6416
6554
|
return {
|
|
6417
6555
|
getChecked: () => {
|
|
@@ -6440,7 +6578,10 @@ const Tree = (props) => {
|
|
|
6440
6578
|
},
|
|
6441
6579
|
};
|
|
6442
6580
|
});
|
|
6443
|
-
|
|
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 }));
|
|
6444
6585
|
};
|
|
6445
6586
|
|
|
6446
6587
|
const Dropbox = (props) => {
|