@dataverse-kit/grid-kit 0.2.0 → 0.3.0
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/dist/hosts/nested/NestedTriggerCell.d.ts.map +1 -1
- package/dist/hosts/nested/useChildren.d.ts +1 -1
- package/dist/hosts/nested/useChildren.d.ts.map +1 -1
- package/dist/index.esm.js +50 -4
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +50 -4
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2309,10 +2309,17 @@ function GroupedGrid(props) {
|
|
|
2309
2309
|
* never fetches — this just normalizes the consumer-supplied resolver and tracks
|
|
2310
2310
|
* loading. Call `ensure(key, parent)` on demand (row expand / panel open / hover).
|
|
2311
2311
|
*/
|
|
2312
|
-
function useChildren(getChildren) {
|
|
2312
|
+
function useChildren(getChildren, reloadToken) {
|
|
2313
2313
|
const [cache, setCache] = React.useState({});
|
|
2314
2314
|
const cacheRef = React.useRef(cache);
|
|
2315
2315
|
cacheRef.current = cache;
|
|
2316
|
+
// Remember the parent object per cached key so a `reloadToken` bump can re-run
|
|
2317
|
+
// `getChildren(parent)` for already-loaded rows.
|
|
2318
|
+
const parentsRef = React.useRef({});
|
|
2319
|
+
// `getChildren` accessed via a ref inside the reload effect → the effect can depend
|
|
2320
|
+
// on `reloadToken` alone without a stale closure or an exhaustive-deps warning.
|
|
2321
|
+
const getChildrenRef = React.useRef(getChildren);
|
|
2322
|
+
getChildrenRef.current = getChildren;
|
|
2316
2323
|
// Guard against setState after unmount (e.g. host swapped while a child fetch
|
|
2317
2324
|
// is in flight) — mirrors NestedTriggerCell / DetailPaneChildren.
|
|
2318
2325
|
const mounted = React.useRef(true);
|
|
@@ -2325,6 +2332,7 @@ function useChildren(getChildren) {
|
|
|
2325
2332
|
const ensure = React.useCallback((key, parent) => {
|
|
2326
2333
|
if (cacheRef.current[key])
|
|
2327
2334
|
return;
|
|
2335
|
+
parentsRef.current[key] = parent;
|
|
2328
2336
|
const result = getChildren(parent);
|
|
2329
2337
|
if (Array.isArray(result)) {
|
|
2330
2338
|
setCache((p) => ({ ...p, [key]: { loading: false, rows: result } }));
|
|
@@ -2337,6 +2345,30 @@ function useChildren(getChildren) {
|
|
|
2337
2345
|
});
|
|
2338
2346
|
}
|
|
2339
2347
|
}, [getChildren]);
|
|
2348
|
+
// Re-fetch every already-loaded parent's children when `reloadToken` changes. Compare
|
|
2349
|
+
// the token by VALUE (not a first-run counter) so it's safe under StrictMode's
|
|
2350
|
+
// double-invoke. Crucially we do NOT flip `loading: true` here — the old rows stay
|
|
2351
|
+
// rendered until the fresh ones land, so there's no spinner flash and (since `ensure`
|
|
2352
|
+
// is only re-called on expand) no perpetual spinner for an already-expanded row.
|
|
2353
|
+
const prevToken = React.useRef(reloadToken);
|
|
2354
|
+
React.useEffect(() => {
|
|
2355
|
+
if (reloadToken === prevToken.current)
|
|
2356
|
+
return;
|
|
2357
|
+
prevToken.current = reloadToken;
|
|
2358
|
+
for (const key of Object.keys(parentsRef.current)) {
|
|
2359
|
+
const parent = parentsRef.current[key];
|
|
2360
|
+
const result = getChildrenRef.current(parent);
|
|
2361
|
+
if (Array.isArray(result)) {
|
|
2362
|
+
setCache((p) => ({ ...p, [key]: { loading: false, rows: result } }));
|
|
2363
|
+
}
|
|
2364
|
+
else {
|
|
2365
|
+
Promise.resolve(result).then((rows) => {
|
|
2366
|
+
if (mounted.current)
|
|
2367
|
+
setCache((p) => ({ ...p, [key]: { loading: false, rows } }));
|
|
2368
|
+
});
|
|
2369
|
+
}
|
|
2370
|
+
}
|
|
2371
|
+
}, [reloadToken]);
|
|
2340
2372
|
const get = React.useCallback((key) => cache[key], [cache]);
|
|
2341
2373
|
return { get, ensure };
|
|
2342
2374
|
}
|
|
@@ -2363,7 +2395,7 @@ function NestedInline(props) {
|
|
|
2363
2395
|
const { items, columns, nested, selectionMode, isLoading, compact, alternateRowColors, pagination, onPageChange, aggregateItems, onSelectionChanged, rowCommands, } = parentProps;
|
|
2364
2396
|
const { onItemContextMenu, contextMenuElement } = useRowContextMenu(rowCommands);
|
|
2365
2397
|
const [expanded, setExpanded] = React.useState(new Set());
|
|
2366
|
-
const { get, ensure } = useChildren(nested.getChildren);
|
|
2398
|
+
const { get, ensure } = useChildren(nested.getChildren, nested.reloadToken);
|
|
2367
2399
|
// Forward parent-row selection to the consumer (DataGrid does this; inline did
|
|
2368
2400
|
// not). A ref keeps the once-created Selection's callback from going stale when
|
|
2369
2401
|
// the prop changes (mirrors DataGrid's onSelectionChangedRef).
|
|
@@ -2491,7 +2523,7 @@ function NestedCardParent(props) {
|
|
|
2491
2523
|
const hasAggregate = columns.some((c) => c.aggregate);
|
|
2492
2524
|
const [selected, setSelected] = React.useState(new Set());
|
|
2493
2525
|
const [expanded, setExpanded] = React.useState(new Set());
|
|
2494
|
-
const { get, ensure } = useChildren(nested.getChildren);
|
|
2526
|
+
const { get, ensure } = useChildren(nested.getChildren, nested.reloadToken);
|
|
2495
2527
|
// requires-parent gating needs a Fluent Selection over the parent rows; cards have
|
|
2496
2528
|
// none, so surface the unsupported config and fall back to independent selection.
|
|
2497
2529
|
React.useEffect(() => {
|
|
@@ -2614,6 +2646,18 @@ function NestedTriggerCell(props) {
|
|
|
2614
2646
|
clearTimeout(hoverTimer.current);
|
|
2615
2647
|
};
|
|
2616
2648
|
}, []);
|
|
2649
|
+
// Invalidate the on-demand cache when `reloadToken` changes (e.g. after associating a
|
|
2650
|
+
// new child): drop the loaded `entry` so the next open/hover re-fetches via `load()`
|
|
2651
|
+
// (which early-returns on a non-null `entry`). Value-compared so it's StrictMode-safe.
|
|
2652
|
+
// Edge: if the panel/callout is OPEN at bump time it shows the spinner until reopened —
|
|
2653
|
+
// acceptable, these modes are on-demand and usually closed during a toolbar action.
|
|
2654
|
+
const prevReloadToken = React.useRef(nested.reloadToken);
|
|
2655
|
+
React.useEffect(() => {
|
|
2656
|
+
if (nested.reloadToken === prevReloadToken.current)
|
|
2657
|
+
return;
|
|
2658
|
+
prevReloadToken.current = nested.reloadToken;
|
|
2659
|
+
setEntry(null);
|
|
2660
|
+
}, [nested.reloadToken]);
|
|
2617
2661
|
// Resolve children once, on demand.
|
|
2618
2662
|
const load = React.useCallback(() => {
|
|
2619
2663
|
setEntry((prev) => {
|
|
@@ -2791,7 +2835,9 @@ function DetailPaneChildren(props) {
|
|
|
2791
2835
|
return () => {
|
|
2792
2836
|
alive = false;
|
|
2793
2837
|
};
|
|
2794
|
-
|
|
2838
|
+
// `nested.reloadToken` makes the refetch explicit on a child mutation (e.g. addExisting)
|
|
2839
|
+
// rather than relying on `nested`'s inline-literal identity changing each render.
|
|
2840
|
+
}, [parent, nested, nested.reloadToken]);
|
|
2795
2841
|
if (rows === null)
|
|
2796
2842
|
return jsxRuntime.jsx(react.Text, { variant: "small", children: "Loading\u2026" });
|
|
2797
2843
|
return (jsxRuntime.jsx(DataGrid, { items: rows, columns: nested.childColumns, registry: nested.childRegistry, compact: true, selectionMode: nested.childSelectionMode, onSelectionChanged: nested.onChildSelectionChanged ? (sel) => nested.onChildSelectionChanged(parent, sel) : undefined, editable: nested.childEditable, editTrigger: nested.childEditTrigger, onValueChange: nested.onChildValueChange
|