@bmsuisse/datagrid 0.35.3 → 0.37.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/index.d.ts +25 -2
- package/dist/index.js +232 -87
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -204,12 +204,13 @@ import { forwardRef as forwardRef2 } from "react";
|
|
|
204
204
|
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
205
205
|
var Popover = PopoverPrimitive.Root;
|
|
206
206
|
var PopoverTrigger = PopoverPrimitive.Trigger;
|
|
207
|
-
var PopoverContent = forwardRef2(({ className, align = "start", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx2(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx2(
|
|
207
|
+
var PopoverContent = forwardRef2(({ className, align = "start", sideOffset = 4, collisionPadding = 8, ...props }, ref) => /* @__PURE__ */ jsx2(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx2(
|
|
208
208
|
PopoverPrimitive.Content,
|
|
209
209
|
{
|
|
210
210
|
ref,
|
|
211
211
|
align,
|
|
212
212
|
sideOffset,
|
|
213
|
+
collisionPadding,
|
|
213
214
|
className: cn(
|
|
214
215
|
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none",
|
|
215
216
|
className
|
|
@@ -358,10 +359,91 @@ import { CalendarDaysIcon } from "@heroicons/react/24/outline";
|
|
|
358
359
|
import { endOfDay, endOfMonth, format, parseISO as parseISO2, startOfDay, startOfMonth, subDays } from "date-fns";
|
|
359
360
|
|
|
360
361
|
// src/components/ui/calendar.tsx
|
|
361
|
-
import {
|
|
362
|
+
import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon } from "lucide-react";
|
|
363
|
+
import { useEffect, useRef } from "react";
|
|
364
|
+
import { DayPicker, getDefaultClassNames } from "react-day-picker";
|
|
362
365
|
import { jsx as jsx5 } from "react/jsx-runtime";
|
|
363
|
-
function Calendar({ className, ...props }) {
|
|
364
|
-
|
|
366
|
+
function Calendar({ className, classNames, ...props }) {
|
|
367
|
+
const defaultClassNames = getDefaultClassNames();
|
|
368
|
+
return /* @__PURE__ */ jsx5(
|
|
369
|
+
DayPicker,
|
|
370
|
+
{
|
|
371
|
+
className: cn("w-fit", className),
|
|
372
|
+
classNames: {
|
|
373
|
+
root: cn("relative", defaultClassNames.root),
|
|
374
|
+
months: cn(
|
|
375
|
+
"flex flex-col gap-4 sm:flex-row sm:divide-x sm:divide-border",
|
|
376
|
+
defaultClassNames.months
|
|
377
|
+
),
|
|
378
|
+
month: cn("flex flex-col gap-3", defaultClassNames.month),
|
|
379
|
+
month_caption: cn("flex items-center justify-center px-8 h-8", defaultClassNames.month_caption),
|
|
380
|
+
caption_label: cn("text-sm font-medium", defaultClassNames.caption_label),
|
|
381
|
+
nav: cn("flex items-center justify-between absolute inset-x-0 top-0 px-1", defaultClassNames.nav),
|
|
382
|
+
button_previous: cn(
|
|
383
|
+
buttonVariants({ variant: "outline", size: "icon" }),
|
|
384
|
+
"h-7 w-7 shrink-0 text-muted-foreground hover:text-foreground",
|
|
385
|
+
defaultClassNames.button_previous
|
|
386
|
+
),
|
|
387
|
+
button_next: cn(
|
|
388
|
+
buttonVariants({ variant: "outline", size: "icon" }),
|
|
389
|
+
"h-7 w-7 shrink-0 text-muted-foreground hover:text-foreground",
|
|
390
|
+
defaultClassNames.button_next
|
|
391
|
+
),
|
|
392
|
+
month_grid: cn("w-full border-collapse", defaultClassNames.month_grid),
|
|
393
|
+
weekdays: cn("flex", defaultClassNames.weekdays),
|
|
394
|
+
weekday: cn(
|
|
395
|
+
"w-8 text-center text-[0.7rem] font-normal text-muted-foreground",
|
|
396
|
+
defaultClassNames.weekday
|
|
397
|
+
),
|
|
398
|
+
week: cn("flex w-full mt-1", defaultClassNames.week),
|
|
399
|
+
day: cn(
|
|
400
|
+
"relative w-8 h-8 p-0 text-center text-sm focus-within:relative focus-within:z-20",
|
|
401
|
+
"[&:first-child[data-selected=true]_button]:rounded-l-md [&:last-child[data-selected=true]_button]:rounded-r-md",
|
|
402
|
+
defaultClassNames.day
|
|
403
|
+
),
|
|
404
|
+
range_start: cn("rounded-l-md bg-accent", defaultClassNames.range_start),
|
|
405
|
+
range_middle: cn("rounded-none bg-accent/60", defaultClassNames.range_middle),
|
|
406
|
+
range_end: cn("rounded-r-md bg-accent", defaultClassNames.range_end),
|
|
407
|
+
today: cn(
|
|
408
|
+
"[&:not([data-selected])]:text-primary [&:not([data-selected])]:font-semibold",
|
|
409
|
+
defaultClassNames.today
|
|
410
|
+
),
|
|
411
|
+
outside: cn("text-muted-foreground/50", defaultClassNames.outside),
|
|
412
|
+
disabled: cn("text-muted-foreground/30 line-through", defaultClassNames.disabled),
|
|
413
|
+
hidden: cn("invisible", defaultClassNames.hidden),
|
|
414
|
+
...classNames
|
|
415
|
+
},
|
|
416
|
+
components: {
|
|
417
|
+
Chevron: ({ className: chevronClassName, orientation }) => {
|
|
418
|
+
const Icon2 = orientation === "up" ? ChevronUpIcon : orientation === "down" ? ChevronDownIcon : orientation === "right" ? ChevronRightIcon : ChevronLeftIcon;
|
|
419
|
+
return /* @__PURE__ */ jsx5(Icon2, { className: cn("h-4 w-4", chevronClassName), "aria-hidden": true });
|
|
420
|
+
},
|
|
421
|
+
DayButton: ({ className: dayClassName, day: _day, modifiers, ...dayProps }) => {
|
|
422
|
+
const ref = useRef(null);
|
|
423
|
+
useEffect(() => {
|
|
424
|
+
if (modifiers.focused) ref.current?.focus();
|
|
425
|
+
}, [modifiers.focused]);
|
|
426
|
+
return /* @__PURE__ */ jsx5(
|
|
427
|
+
"button",
|
|
428
|
+
{
|
|
429
|
+
ref,
|
|
430
|
+
type: "button",
|
|
431
|
+
className: cn(
|
|
432
|
+
"h-8 w-8 rounded-md text-sm font-normal transition-colors hover:bg-accent hover:text-accent-foreground",
|
|
433
|
+
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
434
|
+
"data-[selected=true]:bg-primary data-[selected=true]:text-primary-foreground data-[selected=true]:hover:bg-primary data-[selected=true]:hover:text-primary-foreground",
|
|
435
|
+
modifiers.range_middle && "data-[selected=true]:bg-transparent data-[selected=true]:text-foreground data-[selected=true]:hover:bg-accent",
|
|
436
|
+
dayClassName
|
|
437
|
+
),
|
|
438
|
+
"data-selected": modifiers.selected || void 0,
|
|
439
|
+
...dayProps
|
|
440
|
+
}
|
|
441
|
+
);
|
|
442
|
+
}
|
|
443
|
+
},
|
|
444
|
+
...props
|
|
445
|
+
}
|
|
446
|
+
);
|
|
365
447
|
}
|
|
366
448
|
|
|
367
449
|
// src/filter/DateRangeFilter.tsx
|
|
@@ -436,7 +518,7 @@ function DateRangeFilter({
|
|
|
436
518
|
)),
|
|
437
519
|
/* @__PURE__ */ jsx6(Button, { type: "button", variant: "outline", size: "sm", onClick: () => emit(void 0), children: "Custom" })
|
|
438
520
|
] }),
|
|
439
|
-
/* @__PURE__ */ jsx6(Calendar, { mode: "range", selected: range, onSelect: emit, numberOfMonths:
|
|
521
|
+
/* @__PURE__ */ jsx6(Calendar, { mode: "range", selected: range, onSelect: emit, numberOfMonths: 2 })
|
|
440
522
|
] });
|
|
441
523
|
if (bare) {
|
|
442
524
|
return /* @__PURE__ */ jsx6("div", { "data-testid": `filter-${column.id}`, children: panel });
|
|
@@ -515,6 +597,27 @@ function selectedValuesOf(value) {
|
|
|
515
597
|
function toggle(selected, optionValue) {
|
|
516
598
|
return selected.includes(optionValue) ? selected.filter((v) => v !== optionValue) : [...selected, optionValue];
|
|
517
599
|
}
|
|
600
|
+
function buildRenderChunks(options) {
|
|
601
|
+
const chunks = [];
|
|
602
|
+
options.forEach((option, index) => {
|
|
603
|
+
const row = { option, index };
|
|
604
|
+
const last = chunks[chunks.length - 1];
|
|
605
|
+
if (option.group && last?.kind === "group" && last.group === option.group) {
|
|
606
|
+
last.rows.push(row);
|
|
607
|
+
} else if (option.group) {
|
|
608
|
+
chunks.push({ kind: "group", group: option.group, rows: [row] });
|
|
609
|
+
} else {
|
|
610
|
+
chunks.push({ kind: "single", row });
|
|
611
|
+
}
|
|
612
|
+
});
|
|
613
|
+
return chunks;
|
|
614
|
+
}
|
|
615
|
+
function groupCheckState(candidates, selected, group) {
|
|
616
|
+
const members = candidates.filter((o) => o.group === group).map((o) => o.value);
|
|
617
|
+
const selectedCount = members.filter((v) => selected.includes(v)).length;
|
|
618
|
+
if (members.length === 0 || selectedCount === 0) return "unchecked";
|
|
619
|
+
return selectedCount === members.length ? "checked" : "indeterminate";
|
|
620
|
+
}
|
|
518
621
|
function EnumFilter({
|
|
519
622
|
column,
|
|
520
623
|
value,
|
|
@@ -528,6 +631,7 @@ function EnumFilter({
|
|
|
528
631
|
if (!term) return column.options;
|
|
529
632
|
return column.options.filter((option) => option.label.toLowerCase().includes(term));
|
|
530
633
|
}, [column.options, search]);
|
|
634
|
+
const renderChunks = useMemo(() => buildRenderChunks(visibleOptions), [visibleOptions]);
|
|
531
635
|
function emit(next) {
|
|
532
636
|
onChange(next.length === 0 ? void 0 : { field: column.id, operator: "in", value: next });
|
|
533
637
|
}
|
|
@@ -544,6 +648,33 @@ function EnumFilter({
|
|
|
544
648
|
for (const v of visibleValues) next.add(v);
|
|
545
649
|
emit([...next]);
|
|
546
650
|
}
|
|
651
|
+
function toggleGroup(group) {
|
|
652
|
+
const members = visibleOptions.filter((o) => o.group === group).map((o) => o.value);
|
|
653
|
+
if (groupCheckState(visibleOptions, selected, group) === "checked") {
|
|
654
|
+
emit(selected.filter((v) => !members.includes(v)));
|
|
655
|
+
return;
|
|
656
|
+
}
|
|
657
|
+
emit([.../* @__PURE__ */ new Set([...selected, ...members])]);
|
|
658
|
+
}
|
|
659
|
+
function renderOption(option) {
|
|
660
|
+
return /* @__PURE__ */ jsxs4(
|
|
661
|
+
"label",
|
|
662
|
+
{
|
|
663
|
+
className: "flex items-center gap-2 rounded-sm px-2 py-1.5 text-sm hover:bg-accent hover:text-accent-foreground",
|
|
664
|
+
children: [
|
|
665
|
+
/* @__PURE__ */ jsx9(
|
|
666
|
+
Checkbox,
|
|
667
|
+
{
|
|
668
|
+
checked: selected.includes(option.value),
|
|
669
|
+
onCheckedChange: () => emit(toggle(selected, option.value))
|
|
670
|
+
}
|
|
671
|
+
),
|
|
672
|
+
option.label
|
|
673
|
+
]
|
|
674
|
+
},
|
|
675
|
+
option.value
|
|
676
|
+
);
|
|
677
|
+
}
|
|
547
678
|
const isFiltered = selected.length > 0;
|
|
548
679
|
const summary = `${selected.length} selected`;
|
|
549
680
|
const panel = /* @__PURE__ */ jsxs4("div", { className: bare ? "flex w-full flex-col gap-2" : "flex w-64 flex-col gap-2 p-2", children: [
|
|
@@ -567,23 +698,37 @@ function EnumFilter({
|
|
|
567
698
|
),
|
|
568
699
|
"Select all"
|
|
569
700
|
] }),
|
|
570
|
-
/* @__PURE__ */ jsx9("div", { className: "flex max-h-60 flex-col gap-
|
|
571
|
-
"
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
701
|
+
/* @__PURE__ */ jsx9("div", { className: "flex max-h-60 flex-col gap-0.5 overflow-y-auto", children: renderChunks.length === 0 ? /* @__PURE__ */ jsx9("p", { className: "py-2 text-center text-sm text-muted-foreground", children: "No matches." }) : renderChunks.map((chunk) => {
|
|
702
|
+
if (chunk.kind === "single") return renderOption(chunk.row.option);
|
|
703
|
+
const headerState = groupCheckState(visibleOptions, selected, chunk.group);
|
|
704
|
+
return (
|
|
705
|
+
// The header and every one of its group's rows share this wrapper --
|
|
706
|
+
// its bounds are the sticky header's containing block, so `sticky
|
|
707
|
+
// top-0` keeps the header pinned for the group's whole scroll extent
|
|
708
|
+
// instead of just past its first row.
|
|
709
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex flex-col gap-0.5", children: [
|
|
710
|
+
/* @__PURE__ */ jsxs4(
|
|
711
|
+
"label",
|
|
577
712
|
{
|
|
578
|
-
|
|
579
|
-
|
|
713
|
+
"data-group-header": true,
|
|
714
|
+
className: "sticky top-0 z-10 flex items-center gap-2 rounded-sm bg-muted px-2 py-1.5 text-sm font-semibold text-foreground",
|
|
715
|
+
children: [
|
|
716
|
+
/* @__PURE__ */ jsx9(
|
|
717
|
+
Checkbox,
|
|
718
|
+
{
|
|
719
|
+
checked: headerState === "indeterminate" ? "indeterminate" : headerState === "checked",
|
|
720
|
+
onCheckedChange: () => toggleGroup(chunk.group),
|
|
721
|
+
"aria-label": `Select all of ${chunk.group}`
|
|
722
|
+
}
|
|
723
|
+
),
|
|
724
|
+
chunk.group
|
|
725
|
+
]
|
|
580
726
|
}
|
|
581
727
|
),
|
|
582
|
-
option
|
|
583
|
-
]
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
)) })
|
|
728
|
+
chunk.rows.map((row) => renderOption(row.option))
|
|
729
|
+
] }, `group-${chunk.group}`)
|
|
730
|
+
);
|
|
731
|
+
}) })
|
|
587
732
|
] });
|
|
588
733
|
if (bare) {
|
|
589
734
|
return /* @__PURE__ */ jsx9("div", { "data-testid": `filter-${column.id}`, children: panel });
|
|
@@ -615,7 +760,7 @@ function EnumFilter({
|
|
|
615
760
|
|
|
616
761
|
// src/filter/NumberComparisonFilter.tsx
|
|
617
762
|
import { FunnelIcon as FunnelIcon3 } from "@heroicons/react/24/outline";
|
|
618
|
-
import { useEffect, useId, useRef, useState as useState2 } from "react";
|
|
763
|
+
import { useEffect as useEffect2, useId, useRef as useRef2, useState as useState2 } from "react";
|
|
619
764
|
|
|
620
765
|
// src/column/format.ts
|
|
621
766
|
import { parseISO as parseISO3 } from "date-fns";
|
|
@@ -802,8 +947,8 @@ function NumberComparisonFilter({
|
|
|
802
947
|
const [text2, setText2] = useState2(initial.text2);
|
|
803
948
|
const operatorId = useId();
|
|
804
949
|
const valueId = useId();
|
|
805
|
-
const lastEmittedRef =
|
|
806
|
-
|
|
950
|
+
const lastEmittedRef = useRef2(value);
|
|
951
|
+
useEffect2(() => {
|
|
807
952
|
if (value === lastEmittedRef.current) return;
|
|
808
953
|
lastEmittedRef.current = value;
|
|
809
954
|
const next = stateFromValue(value);
|
|
@@ -919,7 +1064,7 @@ function NumberComparisonFilter({
|
|
|
919
1064
|
|
|
920
1065
|
// src/filter/NumberRangeFilter.tsx
|
|
921
1066
|
import { FunnelIcon as FunnelIcon4 } from "@heroicons/react/24/outline";
|
|
922
|
-
import { useEffect as
|
|
1067
|
+
import { useEffect as useEffect3, useId as useId2, useRef as useRef3, useState as useState3 } from "react";
|
|
923
1068
|
import { jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
924
1069
|
function parseNumber2(raw) {
|
|
925
1070
|
if (raw.trim() === "") return void 0;
|
|
@@ -937,8 +1082,8 @@ function NumberRangeFilter({
|
|
|
937
1082
|
const [maxText, setMaxText] = useState3(initial.max?.toString() ?? "");
|
|
938
1083
|
const minId = useId2();
|
|
939
1084
|
const maxId = useId2();
|
|
940
|
-
const lastEmittedRef =
|
|
941
|
-
|
|
1085
|
+
const lastEmittedRef = useRef3(value);
|
|
1086
|
+
useEffect3(() => {
|
|
942
1087
|
if (value === lastEmittedRef.current) return;
|
|
943
1088
|
lastEmittedRef.current = value;
|
|
944
1089
|
const next = rangeOf2(value);
|
|
@@ -1019,7 +1164,7 @@ function NumberRangeFilter({
|
|
|
1019
1164
|
|
|
1020
1165
|
// src/filter/NumberHistogramFilter.tsx
|
|
1021
1166
|
import { FunnelIcon as FunnelIcon5 } from "@heroicons/react/24/outline";
|
|
1022
|
-
import { useCallback, useEffect as
|
|
1167
|
+
import { useCallback, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef4, useState as useState4 } from "react";
|
|
1023
1168
|
import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1024
1169
|
var BAR_HEIGHT_PX = 56;
|
|
1025
1170
|
var DEFAULT_BUCKETS = 24;
|
|
@@ -1041,12 +1186,12 @@ function NumberHistogramFilter({
|
|
|
1041
1186
|
}) {
|
|
1042
1187
|
const [openState, setOpen] = useState4(false);
|
|
1043
1188
|
const open = bare || openState;
|
|
1044
|
-
const trackRef =
|
|
1189
|
+
const trackRef = useRef4(null);
|
|
1045
1190
|
const [minOnTop, setMinOnTop] = useState4(false);
|
|
1046
1191
|
const [loadedValues, setLoadedValues] = useState4([]);
|
|
1047
1192
|
const [loading, setLoading] = useState4(false);
|
|
1048
1193
|
const { min, max } = rangeOf2(value);
|
|
1049
|
-
|
|
1194
|
+
useEffect4(() => {
|
|
1050
1195
|
if (!open || !loadValues) return;
|
|
1051
1196
|
let cancelled = false;
|
|
1052
1197
|
setLoading(true);
|
|
@@ -1070,7 +1215,7 @@ function NumberHistogramFilter({
|
|
|
1070
1215
|
const activeMax = max ?? dataMax;
|
|
1071
1216
|
const [minText, setMinText] = useState4("");
|
|
1072
1217
|
const [maxText, setMaxText] = useState4("");
|
|
1073
|
-
|
|
1218
|
+
useEffect4(() => {
|
|
1074
1219
|
if (!open) return;
|
|
1075
1220
|
setMinText(Number.isFinite(activeMin) ? String(Math.round(activeMin)) : "");
|
|
1076
1221
|
setMaxText(Number.isFinite(activeMax) ? String(Math.round(activeMax)) : "");
|
|
@@ -1283,7 +1428,7 @@ function facetedNumberValues(data, column, filter) {
|
|
|
1283
1428
|
|
|
1284
1429
|
// src/filter/StringFilter.tsx
|
|
1285
1430
|
import { FunnelIcon as FunnelIcon6 } from "@heroicons/react/24/outline";
|
|
1286
|
-
import { useEffect as
|
|
1431
|
+
import { useEffect as useEffect5, useId as useId3, useState as useState5 } from "react";
|
|
1287
1432
|
import { jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1288
1433
|
var STRING_OPERATORS = [
|
|
1289
1434
|
{ value: "contains", label: "Contains" },
|
|
@@ -1302,7 +1447,7 @@ function StringFilter({
|
|
|
1302
1447
|
const text = typeof value?.value === "string" ? value.value : "";
|
|
1303
1448
|
const inputId = useId3();
|
|
1304
1449
|
const isFiltered = text !== "";
|
|
1305
|
-
|
|
1450
|
+
useEffect5(() => {
|
|
1306
1451
|
setOperator(value?.operator ?? DEFAULT_OPERATOR2);
|
|
1307
1452
|
}, [value?.operator]);
|
|
1308
1453
|
function emit(nextOperator, nextText) {
|
|
@@ -1517,7 +1662,7 @@ function EnumEditor({
|
|
|
1517
1662
|
}
|
|
1518
1663
|
|
|
1519
1664
|
// src/edit/MultilineStringEditor.tsx
|
|
1520
|
-
import { useLayoutEffect, useRef as
|
|
1665
|
+
import { useLayoutEffect, useRef as useRef5 } from "react";
|
|
1521
1666
|
|
|
1522
1667
|
// src/components/ui/textarea.tsx
|
|
1523
1668
|
import { forwardRef as forwardRef6 } from "react";
|
|
@@ -1548,8 +1693,8 @@ function MultilineStringEditor({
|
|
|
1548
1693
|
autoFocus
|
|
1549
1694
|
}) {
|
|
1550
1695
|
const errorId = editErrorId(rowId, column.id);
|
|
1551
|
-
const textareaRef =
|
|
1552
|
-
const selectionRef =
|
|
1696
|
+
const textareaRef = useRef5(null);
|
|
1697
|
+
const selectionRef = useRef5(null);
|
|
1553
1698
|
const text = value === null || value === void 0 ? "" : String(value);
|
|
1554
1699
|
useLayoutEffect(() => {
|
|
1555
1700
|
const el = textareaRef.current;
|
|
@@ -1584,7 +1729,7 @@ function MultilineStringEditor({
|
|
|
1584
1729
|
}
|
|
1585
1730
|
|
|
1586
1731
|
// src/edit/NumberEditor.tsx
|
|
1587
|
-
import { useEffect as
|
|
1732
|
+
import { useEffect as useEffect6, useRef as useRef6, useState as useState6 } from "react";
|
|
1588
1733
|
import { jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1589
1734
|
function textFromValue(value) {
|
|
1590
1735
|
return value === null || value === void 0 ? "" : String(value);
|
|
@@ -1599,8 +1744,8 @@ function NumberEditor({
|
|
|
1599
1744
|
}) {
|
|
1600
1745
|
const errorId = editErrorId(rowId, column.id);
|
|
1601
1746
|
const [text, setText] = useState6(() => textFromValue(value));
|
|
1602
|
-
const lastEmittedRef =
|
|
1603
|
-
|
|
1747
|
+
const lastEmittedRef = useRef6(value);
|
|
1748
|
+
useEffect6(() => {
|
|
1604
1749
|
if (value === lastEmittedRef.current) return;
|
|
1605
1750
|
lastEmittedRef.current = value;
|
|
1606
1751
|
setText(textFromValue(value));
|
|
@@ -1678,7 +1823,7 @@ function renderDefaultEditWidget(column, rowId, value, onChange, error, autoFocu
|
|
|
1678
1823
|
}
|
|
1679
1824
|
|
|
1680
1825
|
// src/edit/editingState.ts
|
|
1681
|
-
import { useEffect as
|
|
1826
|
+
import { useEffect as useEffect7, useRef as useRef7, useState as useState7 } from "react";
|
|
1682
1827
|
function editValuesEqual(a, b) {
|
|
1683
1828
|
if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
|
|
1684
1829
|
return a === b;
|
|
@@ -1693,7 +1838,7 @@ function useEditingState(editing, getRowId) {
|
|
|
1693
1838
|
setActiveRowId(rowId);
|
|
1694
1839
|
setAutoFocusTarget({ rowId, columnId });
|
|
1695
1840
|
}
|
|
1696
|
-
|
|
1841
|
+
useEffect7(() => {
|
|
1697
1842
|
if (autoFocusTarget) setAutoFocusTarget(null);
|
|
1698
1843
|
}, [autoFocusTarget]);
|
|
1699
1844
|
function commitEdit(column, row, value) {
|
|
@@ -1780,7 +1925,7 @@ function useEditingState(editing, getRowId) {
|
|
|
1780
1925
|
editing?.onDiscard?.();
|
|
1781
1926
|
}
|
|
1782
1927
|
const ctx = editing ? { pendingEdits, editErrors, activeRowId, autoFocusTarget, getRowId, onEdit: commitEdit, onActivateRow: activateRow } : void 0;
|
|
1783
|
-
const ctxRef =
|
|
1928
|
+
const ctxRef = useRef7(void 0);
|
|
1784
1929
|
ctxRef.current = ctx;
|
|
1785
1930
|
return { pendingEdits, editErrors, hasEditErrors, ctx, ctxRef, handleSaveEdits, handleDiscardEdits };
|
|
1786
1931
|
}
|
|
@@ -1986,13 +2131,13 @@ function extendRangeForFillToCellRange(base, target, rowIds, columnIds, rowIndex
|
|
|
1986
2131
|
}
|
|
1987
2132
|
|
|
1988
2133
|
// src/cell-editing/useCellSelection.ts
|
|
1989
|
-
import { useCallback as useCallback2, useMemo as useMemo3, useRef as
|
|
2134
|
+
import { useCallback as useCallback2, useMemo as useMemo3, useRef as useRef8, useState as useState8 } from "react";
|
|
1990
2135
|
function useCellSelection({ rowIds, columnIds, onNavigateToRow }) {
|
|
1991
2136
|
const [selection, setSelectionState] = useState8(void 0);
|
|
1992
2137
|
const [isDragging, setIsDragging] = useState8(false);
|
|
1993
2138
|
const [dragFocus, setDragFocus] = useState8(void 0);
|
|
1994
|
-
const draggingRef =
|
|
1995
|
-
const dragFocusRef =
|
|
2139
|
+
const draggingRef = useRef8(false);
|
|
2140
|
+
const dragFocusRef = useRef8(void 0);
|
|
1996
2141
|
const rowIndex = useMemo3(() => buildIndexMap(rowIds), [rowIds]);
|
|
1997
2142
|
const columnIndex = useMemo3(() => buildIndexMap(columnIds), [columnIds]);
|
|
1998
2143
|
const startSelection = useCallback2((cell, options) => {
|
|
@@ -2055,9 +2200,9 @@ function useCellSelection({ rowIds, columnIds, onNavigateToRow }) {
|
|
|
2055
2200
|
}, [selection, isDragging, dragFocus]);
|
|
2056
2201
|
const [isFillDragging, setIsFillDragging] = useState8(false);
|
|
2057
2202
|
const [fillTarget, setFillTarget] = useState8(void 0);
|
|
2058
|
-
const fillDraggingRef =
|
|
2059
|
-
const fillTargetRef =
|
|
2060
|
-
const fillBaseRef =
|
|
2203
|
+
const fillDraggingRef = useRef8(false);
|
|
2204
|
+
const fillTargetRef = useRef8(void 0);
|
|
2205
|
+
const fillBaseRef = useRef8(void 0);
|
|
2061
2206
|
const startFillDrag = useCallback2(() => {
|
|
2062
2207
|
if (!selection) return;
|
|
2063
2208
|
fillBaseRef.current = selection;
|
|
@@ -2107,7 +2252,7 @@ function useCellSelection({ rowIds, columnIds, onNavigateToRow }) {
|
|
|
2107
2252
|
}
|
|
2108
2253
|
|
|
2109
2254
|
// src/cell-editing/useCellEditingState.ts
|
|
2110
|
-
import { useRef as
|
|
2255
|
+
import { useRef as useRef9, useState as useState9 } from "react";
|
|
2111
2256
|
function cellKey(rowId, columnId) {
|
|
2112
2257
|
return `${rowId}:${columnId}`;
|
|
2113
2258
|
}
|
|
@@ -2118,7 +2263,7 @@ function useCellEditingState(cellEditing, getRowId) {
|
|
|
2118
2263
|
const [draftValue, setDraftValue] = useState9(void 0);
|
|
2119
2264
|
const [overrides, setOverrides] = useState9(/* @__PURE__ */ new Map());
|
|
2120
2265
|
const [errors, setErrors] = useState9(/* @__PURE__ */ new Map());
|
|
2121
|
-
const justCommittedRef =
|
|
2266
|
+
const justCommittedRef = useRef9(false);
|
|
2122
2267
|
function closeEditor() {
|
|
2123
2268
|
setEditingCell(void 0);
|
|
2124
2269
|
setInitialText(void 0);
|
|
@@ -2216,7 +2361,7 @@ function useCellEditingState(cellEditing, getRowId) {
|
|
|
2216
2361
|
applyChange: (change) => applyChanges([change]),
|
|
2217
2362
|
consumeJustCommitted
|
|
2218
2363
|
} : void 0;
|
|
2219
|
-
const ctxRef =
|
|
2364
|
+
const ctxRef = useRef9(void 0);
|
|
2220
2365
|
ctxRef.current = ctx;
|
|
2221
2366
|
return { ctx, ctxRef, applyChanges };
|
|
2222
2367
|
}
|
|
@@ -2277,7 +2422,7 @@ function renderCellModeCell(column, row, rawValue, ctx) {
|
|
|
2277
2422
|
}
|
|
2278
2423
|
|
|
2279
2424
|
// src/cell-editing/SelectionOverlay.tsx
|
|
2280
|
-
import { useLayoutEffect as useLayoutEffect2, useRef as
|
|
2425
|
+
import { useLayoutEffect as useLayoutEffect2, useRef as useRef10, useState as useState10 } from "react";
|
|
2281
2426
|
import { Fragment as Fragment2, jsx as jsx27, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2282
2427
|
function cellSelector(rowId, columnId) {
|
|
2283
2428
|
const escape = (value) => typeof CSS !== "undefined" && CSS.escape ? CSS.escape(value) : value.replace(/["\\]/g, "\\$&");
|
|
@@ -2310,7 +2455,7 @@ function SelectionOverlay({
|
|
|
2310
2455
|
}) {
|
|
2311
2456
|
const [rect, setRect] = useState10(void 0);
|
|
2312
2457
|
const [previewRect, setPreviewRect] = useState10(void 0);
|
|
2313
|
-
const recomputeRef =
|
|
2458
|
+
const recomputeRef = useRef10(() => {
|
|
2314
2459
|
});
|
|
2315
2460
|
recomputeRef.current = () => {
|
|
2316
2461
|
const container = containerRef.current;
|
|
@@ -2557,7 +2702,7 @@ function computeFillChanges(sourceRange, finalRange, rowIds, columnIds, columns,
|
|
|
2557
2702
|
|
|
2558
2703
|
// src/column-selector/ColumnSelector.tsx
|
|
2559
2704
|
import { Columns3, GripVertical } from "lucide-react";
|
|
2560
|
-
import { useEffect as
|
|
2705
|
+
import { useEffect as useEffect8, useState as useState11 } from "react";
|
|
2561
2706
|
|
|
2562
2707
|
// src/components/ui/dialog.tsx
|
|
2563
2708
|
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
@@ -2724,12 +2869,12 @@ function ColumnSelector({
|
|
|
2724
2869
|
columnOrder,
|
|
2725
2870
|
onColumnOrderChange
|
|
2726
2871
|
}) {
|
|
2727
|
-
|
|
2872
|
+
useEffect8(() => {
|
|
2728
2873
|
if (!persistKey) return;
|
|
2729
2874
|
const restored = readPersistedVisibility(persistKey);
|
|
2730
2875
|
if (restored) onVisibilityChange({ ...visibility, ...restored });
|
|
2731
2876
|
}, [persistKey]);
|
|
2732
|
-
|
|
2877
|
+
useEffect8(() => {
|
|
2733
2878
|
if (!persistKey || !onColumnOrderChange) return;
|
|
2734
2879
|
const restored = readPersistedColumnOrder(persistKey);
|
|
2735
2880
|
if (restored) onColumnOrderChange(restored);
|
|
@@ -2912,11 +3057,11 @@ import { BarsArrowDownIcon, BarsArrowUpIcon, FunnelIcon as FunnelIcon7 } from "@
|
|
|
2912
3057
|
import { columnResizingFeature, columnSizingFeature, flexRender, tableFeatures, useTable } from "@tanstack/react-table";
|
|
2913
3058
|
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
2914
3059
|
import { ChevronRight, Loader2 } from "lucide-react";
|
|
2915
|
-
import { Fragment as Fragment3, useEffect as
|
|
3060
|
+
import { Fragment as Fragment3, useEffect as useEffect12, useMemo as useMemo8, useRef as useRef13, useState as useState16 } from "react";
|
|
2916
3061
|
|
|
2917
3062
|
// src/cell-editing/renderAlwaysEditCell.tsx
|
|
2918
3063
|
import {
|
|
2919
|
-
useEffect as
|
|
3064
|
+
useEffect as useEffect9,
|
|
2920
3065
|
useState as useState12
|
|
2921
3066
|
} from "react";
|
|
2922
3067
|
import { jsx as jsx32 } from "react/jsx-runtime";
|
|
@@ -2928,7 +3073,7 @@ function AlwaysEditCell(props) {
|
|
|
2928
3073
|
const [enumOpen, setEnumOpen] = useState12(false);
|
|
2929
3074
|
const isBuiltinEnum = column.type === "enum" && !column.renderEditCell;
|
|
2930
3075
|
const shouldOpenEnumNow = isBuiltinEnum && (atomicGesture?.shouldOpenEnum(rowId, column.id) ?? false);
|
|
2931
|
-
|
|
3076
|
+
useEffect9(() => {
|
|
2932
3077
|
if (shouldOpenEnumNow) setEnumOpen(true);
|
|
2933
3078
|
}, [shouldOpenEnumNow]);
|
|
2934
3079
|
if (!isEditable(column, row)) {
|
|
@@ -3051,9 +3196,9 @@ function useGroupExpansion(defaultGroupsExpanded, controlledExpandedGroups, onEx
|
|
|
3051
3196
|
}
|
|
3052
3197
|
|
|
3053
3198
|
// src/hooks/useStickyGroupHeaderTop.ts
|
|
3054
|
-
import { useLayoutEffect as useLayoutEffect3, useRef as
|
|
3199
|
+
import { useLayoutEffect as useLayoutEffect3, useRef as useRef11, useState as useState14 } from "react";
|
|
3055
3200
|
function useStickyGroupHeaderTop(enabled) {
|
|
3056
|
-
const theadRef =
|
|
3201
|
+
const theadRef = useRef11(null);
|
|
3057
3202
|
const [groupHeaderTop, setGroupHeaderTop] = useState14(0);
|
|
3058
3203
|
useLayoutEffect3(() => {
|
|
3059
3204
|
if (!enabled) return;
|
|
@@ -3118,15 +3263,15 @@ function processClientData(data, state) {
|
|
|
3118
3263
|
}
|
|
3119
3264
|
|
|
3120
3265
|
// src/grid/useGridState.ts
|
|
3121
|
-
import { useCallback as useCallback4, useEffect as
|
|
3266
|
+
import { useCallback as useCallback4, useEffect as useEffect11, useMemo as useMemo7, useState as useState15 } from "react";
|
|
3122
3267
|
|
|
3123
3268
|
// src/hooks/useDebouncedCallback.ts
|
|
3124
|
-
import { useEffect as
|
|
3269
|
+
import { useEffect as useEffect10, useMemo as useMemo6, useRef as useRef12 } from "react";
|
|
3125
3270
|
function useDebouncedCallback(callback, delayMs) {
|
|
3126
|
-
const callbackRef =
|
|
3271
|
+
const callbackRef = useRef12(callback);
|
|
3127
3272
|
callbackRef.current = callback;
|
|
3128
|
-
const timeoutRef =
|
|
3129
|
-
|
|
3273
|
+
const timeoutRef = useRef12(void 0);
|
|
3274
|
+
useEffect10(() => {
|
|
3130
3275
|
return () => {
|
|
3131
3276
|
clearTimeout(timeoutRef.current);
|
|
3132
3277
|
};
|
|
@@ -3179,7 +3324,7 @@ function useGridState(dataSource, initialState, externalState, showPagination =
|
|
|
3179
3324
|
},
|
|
3180
3325
|
[notifyRaw, cancelDebouncedNotify]
|
|
3181
3326
|
);
|
|
3182
|
-
|
|
3327
|
+
useEffect11(() => {
|
|
3183
3328
|
if (!externalState) return;
|
|
3184
3329
|
cancelDebouncedNotify();
|
|
3185
3330
|
setState(externalState);
|
|
@@ -3388,7 +3533,7 @@ function DataGrid({
|
|
|
3388
3533
|
hasCellEditing ? cellEditing : void 0,
|
|
3389
3534
|
getRowId
|
|
3390
3535
|
);
|
|
3391
|
-
const atomicGestureRef =
|
|
3536
|
+
const atomicGestureRef = useRef13(void 0);
|
|
3392
3537
|
const visibleColumns = useVisibleColumns(columns, columnVisibility);
|
|
3393
3538
|
const serverRowCount = dataSource.mode === "server" ? dataSource.rowCount : void 0;
|
|
3394
3539
|
const { rows, rowCount } = useMemo8(() => {
|
|
@@ -3543,8 +3688,8 @@ function DataGrid({
|
|
|
3543
3688
|
return map;
|
|
3544
3689
|
}, [visibleColumns, enableColumnResizing, leftPinnedOffsets, rightPinnedOffsets, columnSizing]);
|
|
3545
3690
|
const tableRows = table.getRowModel().rows;
|
|
3546
|
-
const truncationWarnedRef =
|
|
3547
|
-
|
|
3691
|
+
const truncationWarnedRef = useRef13(false);
|
|
3692
|
+
useEffect12(() => {
|
|
3548
3693
|
if (process.env.NODE_ENV === "production") return;
|
|
3549
3694
|
if (showPagination) return;
|
|
3550
3695
|
if (truncationWarnedRef.current) return;
|
|
@@ -3574,7 +3719,7 @@ function DataGrid({
|
|
|
3574
3719
|
}
|
|
3575
3720
|
return items;
|
|
3576
3721
|
}, [shouldVirtualize, groupedBuckets, tableRows, isGroupExpanded]);
|
|
3577
|
-
const scrollRef =
|
|
3722
|
+
const scrollRef = useRef13(null);
|
|
3578
3723
|
const virtualizer = useVirtualizer({
|
|
3579
3724
|
count: flatItems.length,
|
|
3580
3725
|
getScrollElement: () => scrollRef.current,
|
|
@@ -3586,11 +3731,11 @@ function DataGrid({
|
|
|
3586
3731
|
const paddingTop = virtualItems.length > 0 ? virtualItems[0].start : 0;
|
|
3587
3732
|
const paddingBottom = virtualItems.length > 0 ? virtualizer.getTotalSize() - virtualItems[virtualItems.length - 1].end : 0;
|
|
3588
3733
|
const lastVisibleIndex = virtualItems.length > 0 ? virtualItems[virtualItems.length - 1].index : -1;
|
|
3589
|
-
const notifiedForLengthRef =
|
|
3590
|
-
|
|
3734
|
+
const notifiedForLengthRef = useRef13(-1);
|
|
3735
|
+
useEffect12(() => {
|
|
3591
3736
|
notifiedForLengthRef.current = -1;
|
|
3592
3737
|
}, [state.filter, state.sort]);
|
|
3593
|
-
|
|
3738
|
+
useEffect12(() => {
|
|
3594
3739
|
if (!virtualize?.onEndReached) return;
|
|
3595
3740
|
if (lastVisibleIndex < 0 || lastVisibleIndex < flatItems.length - 1) return;
|
|
3596
3741
|
if (virtualize.hasMore === false) return;
|
|
@@ -3616,8 +3761,8 @@ function DataGrid({
|
|
|
3616
3761
|
if (index !== void 0) virtualizer.scrollToIndex(index);
|
|
3617
3762
|
}
|
|
3618
3763
|
});
|
|
3619
|
-
const clickCellRef =
|
|
3620
|
-
const dragMovedRef =
|
|
3764
|
+
const clickCellRef = useRef13(null);
|
|
3765
|
+
const dragMovedRef = useRef13(false);
|
|
3621
3766
|
const [pendingOpenEnumCell, setPendingOpenEnumCell] = useState16(void 0);
|
|
3622
3767
|
atomicGestureRef.current = {
|
|
3623
3768
|
shouldOpenEnum: (rowId, columnId) => pendingOpenEnumCell?.rowId === rowId && pendingOpenEnumCell?.columnId === columnId,
|
|
@@ -3641,9 +3786,9 @@ function DataGrid({
|
|
|
3641
3786
|
if (!column || row === void 0 || !isEditable(column, row)) return;
|
|
3642
3787
|
cellEditingCtx.onBeginEdit(cell);
|
|
3643
3788
|
}
|
|
3644
|
-
const pendingDragCellRef =
|
|
3645
|
-
const dragRafRef =
|
|
3646
|
-
|
|
3789
|
+
const pendingDragCellRef = useRef13(null);
|
|
3790
|
+
const dragRafRef = useRef13(null);
|
|
3791
|
+
useEffect12(() => {
|
|
3647
3792
|
if (!cellSelection.isDragging) return;
|
|
3648
3793
|
function handleMouseMove(event) {
|
|
3649
3794
|
const cellEl = event.target?.closest("[data-cell-row]");
|
|
@@ -3682,9 +3827,9 @@ function DataGrid({
|
|
|
3682
3827
|
dragRafRef.current = null;
|
|
3683
3828
|
};
|
|
3684
3829
|
}, [cellSelection.isDragging, cellSelection.updateDrag, cellSelection.endDrag]);
|
|
3685
|
-
const pendingFillCellRef =
|
|
3686
|
-
const fillRafRef =
|
|
3687
|
-
|
|
3830
|
+
const pendingFillCellRef = useRef13(null);
|
|
3831
|
+
const fillRafRef = useRef13(null);
|
|
3832
|
+
useEffect12(() => {
|
|
3688
3833
|
if (!cellSelection.isFillDragging) return;
|
|
3689
3834
|
function handleMouseMove(event) {
|
|
3690
3835
|
const cellEl = event.target?.closest("[data-cell-row]");
|
|
@@ -3720,8 +3865,8 @@ function DataGrid({
|
|
|
3720
3865
|
fillRafRef.current = null;
|
|
3721
3866
|
};
|
|
3722
3867
|
}, [cellSelection.isFillDragging, cellSelection.updateFillDrag, cellSelection.endFillDrag]);
|
|
3723
|
-
const wasEditingCellRef =
|
|
3724
|
-
|
|
3868
|
+
const wasEditingCellRef = useRef13(void 0);
|
|
3869
|
+
useEffect12(() => {
|
|
3725
3870
|
const wasEditing = wasEditingCellRef.current !== void 0;
|
|
3726
3871
|
wasEditingCellRef.current = cellEditingCtx?.editingCell;
|
|
3727
3872
|
if (!wasEditing || cellEditingCtx?.editingCell) return;
|
|
@@ -4144,7 +4289,7 @@ function DataGrid({
|
|
|
4144
4289
|
)
|
|
4145
4290
|
}
|
|
4146
4291
|
) }),
|
|
4147
|
-
/* @__PURE__ */ jsx33(PopoverContent, { children: renderFilterWidget(column) })
|
|
4292
|
+
/* @__PURE__ */ jsx33(PopoverContent, { className: "w-auto", children: renderFilterWidget(column) })
|
|
4148
4293
|
] })
|
|
4149
4294
|
] }),
|
|
4150
4295
|
enableColumnResizing && /* @__PURE__ */ jsx33(
|
|
@@ -4352,7 +4497,7 @@ function DataGrid({
|
|
|
4352
4497
|
// src/tree/TreeDataGrid.tsx
|
|
4353
4498
|
import { useVirtualizer as useVirtualizer2 } from "@tanstack/react-virtual";
|
|
4354
4499
|
import { AlertCircle, ChevronDown as ChevronDown2, ChevronRight as ChevronRight2, Loader2 as Loader22 } from "lucide-react";
|
|
4355
|
-
import { Fragment as Fragment5, useEffect as
|
|
4500
|
+
import { Fragment as Fragment5, useEffect as useEffect13, useMemo as useMemo10, useRef as useRef14 } from "react";
|
|
4356
4501
|
|
|
4357
4502
|
// src/tree/flattenTree.ts
|
|
4358
4503
|
function flattenTree(roots, accessors, expanded, childrenOverride) {
|
|
@@ -4606,8 +4751,8 @@ function TreeDataGrid({
|
|
|
4606
4751
|
childrenMap: controlledChildrenMap,
|
|
4607
4752
|
onChildrenMapChange
|
|
4608
4753
|
});
|
|
4609
|
-
const didAutoExpand =
|
|
4610
|
-
|
|
4754
|
+
const didAutoExpand = useRef14(false);
|
|
4755
|
+
useEffect13(() => {
|
|
4611
4756
|
if (didAutoExpand.current) return;
|
|
4612
4757
|
didAutoExpand.current = true;
|
|
4613
4758
|
if (initialExpandedLevel > 0) void expandToLevel(initialExpandedLevel);
|
|
@@ -4686,7 +4831,7 @@ function TreeDataGrid({
|
|
|
4686
4831
|
function renderGroupSummaryCells(rows) {
|
|
4687
4832
|
return visibleColumns.map((column) => /* @__PURE__ */ jsx34("td", { className: cn(bodyTdClassByColumn.get(column.id), "font-medium"), children: column.summary?.(rows) }, column.id));
|
|
4688
4833
|
}
|
|
4689
|
-
const scrollRef =
|
|
4834
|
+
const scrollRef = useRef14(null);
|
|
4690
4835
|
const shouldVirtualize = !groupBy && flatRows.length > virtualizeThreshold;
|
|
4691
4836
|
const virtualizer = useVirtualizer2({
|
|
4692
4837
|
count: flatRows.length,
|