@bmsuisse/datagrid 0.37.1 → 0.38.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/README.md +24 -0
- package/dist/index.d.ts +110 -9
- package/dist/index.js +437 -351
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -147,6 +147,70 @@ function evaluateFilter(row, filter) {
|
|
|
147
147
|
return evaluateLeaf(row, filter);
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
+
// src/filter/labels.tsx
|
|
151
|
+
import { createContext, useContext, useMemo } from "react";
|
|
152
|
+
import { jsx } from "react/jsx-runtime";
|
|
153
|
+
var defaultFilterLabels = {
|
|
154
|
+
filterAriaLabel: (header) => `Filter ${header}`,
|
|
155
|
+
searchPlaceholder: (header) => `Search ${header.toLowerCase()}...`,
|
|
156
|
+
selectAll: "Select all",
|
|
157
|
+
selectAllOfGroup: (group) => `Select all of ${group}`,
|
|
158
|
+
noMatches: "No matches.",
|
|
159
|
+
selectedCount: (count) => `${count} selected`,
|
|
160
|
+
stringPlaceholder: (header) => `Filter ${header.toLowerCase()}...`,
|
|
161
|
+
stringContains: "Contains",
|
|
162
|
+
stringIs: "Is",
|
|
163
|
+
stringStartsWith: "Starts with",
|
|
164
|
+
stringEndsWith: "Ends with",
|
|
165
|
+
operatorAriaLabel: (header) => `${header} filter operator`,
|
|
166
|
+
booleanAll: "All",
|
|
167
|
+
booleanYes: "Yes",
|
|
168
|
+
booleanNo: "No",
|
|
169
|
+
booleanAriaLabel: (header) => `${header} filter`,
|
|
170
|
+
minPlaceholder: "Min",
|
|
171
|
+
maxPlaceholder: "Max",
|
|
172
|
+
valuePlaceholder: "Value",
|
|
173
|
+
rangeSeparator: "to",
|
|
174
|
+
minimumAriaLabel: (header) => `${header} minimum`,
|
|
175
|
+
maximumAriaLabel: (header) => `${header} maximum`,
|
|
176
|
+
minimumSliderAriaLabel: (header) => `${header} minimum (slider)`,
|
|
177
|
+
maximumSliderAriaLabel: (header) => `${header} maximum (slider)`,
|
|
178
|
+
numberGreaterThan: "Greater than",
|
|
179
|
+
numberGreaterThanOrEqual: "Greater than or equal to",
|
|
180
|
+
numberLessThan: "Less than",
|
|
181
|
+
numberLessThanOrEqual: "Less than or equal to",
|
|
182
|
+
numberEquals: "Equals",
|
|
183
|
+
numberNotEquals: "Does not equal",
|
|
184
|
+
numberBetween: "Between",
|
|
185
|
+
clear: "Clear",
|
|
186
|
+
loading: "Loading\u2026",
|
|
187
|
+
dateToday: "Today",
|
|
188
|
+
dateLast7Days: "Last 7 days",
|
|
189
|
+
dateThisMonth: "This month",
|
|
190
|
+
dateCustom: "Custom"
|
|
191
|
+
};
|
|
192
|
+
function mergeFilterLabels(base, overrides) {
|
|
193
|
+
if (!overrides) return base;
|
|
194
|
+
const merged = { ...base };
|
|
195
|
+
for (const [key, value] of Object.entries(overrides)) {
|
|
196
|
+
if (value !== void 0) merged[key] = value;
|
|
197
|
+
}
|
|
198
|
+
return merged;
|
|
199
|
+
}
|
|
200
|
+
var FilterLabelsContext = createContext(defaultFilterLabels);
|
|
201
|
+
function FilterLabelsProvider({
|
|
202
|
+
labels,
|
|
203
|
+
children
|
|
204
|
+
}) {
|
|
205
|
+
const parent = useContext(FilterLabelsContext);
|
|
206
|
+
const value = useMemo(() => mergeFilterLabels(parent, labels), [parent, labels]);
|
|
207
|
+
return /* @__PURE__ */ jsx(FilterLabelsContext.Provider, { value, children });
|
|
208
|
+
}
|
|
209
|
+
function useFilterLabels(overrides) {
|
|
210
|
+
const fromContext = useContext(FilterLabelsContext);
|
|
211
|
+
return useMemo(() => mergeFilterLabels(fromContext, overrides), [fromContext, overrides]);
|
|
212
|
+
}
|
|
213
|
+
|
|
150
214
|
// src/filter/BooleanFilter.tsx
|
|
151
215
|
import { FunnelIcon } from "@heroicons/react/24/outline";
|
|
152
216
|
|
|
@@ -166,7 +230,7 @@ function stopRowClick(event) {
|
|
|
166
230
|
}
|
|
167
231
|
|
|
168
232
|
// src/components/ui/button.tsx
|
|
169
|
-
import { jsx } from "react/jsx-runtime";
|
|
233
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
170
234
|
var buttonVariants = cva(
|
|
171
235
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
|
|
172
236
|
{
|
|
@@ -193,7 +257,7 @@ var Button = forwardRef(
|
|
|
193
257
|
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
194
258
|
const Comp = asChild ? Slot : "button";
|
|
195
259
|
const variantClass = buttonVariants({ variant, size });
|
|
196
|
-
return /* @__PURE__ */
|
|
260
|
+
return /* @__PURE__ */ jsx2(Comp, { className: className ? cn(variantClass, className) : variantClass, ref, ...props });
|
|
197
261
|
}
|
|
198
262
|
);
|
|
199
263
|
Button.displayName = "Button";
|
|
@@ -201,10 +265,10 @@ Button.displayName = "Button";
|
|
|
201
265
|
// src/components/ui/popover.tsx
|
|
202
266
|
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
203
267
|
import { forwardRef as forwardRef2 } from "react";
|
|
204
|
-
import { jsx as
|
|
268
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
205
269
|
var Popover = PopoverPrimitive.Root;
|
|
206
270
|
var PopoverTrigger = PopoverPrimitive.Trigger;
|
|
207
|
-
var PopoverContent = forwardRef2(({ className, align = "start", sideOffset = 4, collisionPadding = 8, ...props }, ref) => /* @__PURE__ */
|
|
271
|
+
var PopoverContent = forwardRef2(({ className, align = "start", sideOffset = 4, collisionPadding = 8, ...props }, ref) => /* @__PURE__ */ jsx3(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx3(
|
|
208
272
|
PopoverPrimitive.Content,
|
|
209
273
|
{
|
|
210
274
|
ref,
|
|
@@ -224,7 +288,7 @@ PopoverContent.displayName = "PopoverContent";
|
|
|
224
288
|
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
225
289
|
import { Check, ChevronDown } from "lucide-react";
|
|
226
290
|
import { forwardRef as forwardRef3 } from "react";
|
|
227
|
-
import { jsx as
|
|
291
|
+
import { jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
228
292
|
var Select = SelectPrimitive.Root;
|
|
229
293
|
var SelectValue = SelectPrimitive.Value;
|
|
230
294
|
var SelectTrigger = forwardRef3(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
@@ -238,12 +302,12 @@ var SelectTrigger = forwardRef3(({ className, children, ...props }, ref) => /* @
|
|
|
238
302
|
...props,
|
|
239
303
|
children: [
|
|
240
304
|
children,
|
|
241
|
-
/* @__PURE__ */
|
|
305
|
+
/* @__PURE__ */ jsx4(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx4(ChevronDown, { className: "h-4 w-4 opacity-50" }) })
|
|
242
306
|
]
|
|
243
307
|
}
|
|
244
308
|
));
|
|
245
309
|
SelectTrigger.displayName = "SelectTrigger";
|
|
246
|
-
var SelectContent = forwardRef3(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */
|
|
310
|
+
var SelectContent = forwardRef3(({ className, children, position = "popper", ...props }, ref) => /* @__PURE__ */ jsx4(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsx4(
|
|
247
311
|
SelectPrimitive.Content,
|
|
248
312
|
{
|
|
249
313
|
ref,
|
|
@@ -254,7 +318,7 @@ var SelectContent = forwardRef3(({ className, children, position = "popper", ...
|
|
|
254
318
|
className
|
|
255
319
|
),
|
|
256
320
|
...props,
|
|
257
|
-
children: /* @__PURE__ */
|
|
321
|
+
children: /* @__PURE__ */ jsx4(SelectPrimitive.Viewport, { className: "p-1", children })
|
|
258
322
|
}
|
|
259
323
|
) }));
|
|
260
324
|
SelectContent.displayName = "SelectContent";
|
|
@@ -268,19 +332,19 @@ var SelectItem = forwardRef3(({ className, children, ...props }, ref) => /* @__P
|
|
|
268
332
|
),
|
|
269
333
|
...props,
|
|
270
334
|
children: [
|
|
271
|
-
/* @__PURE__ */
|
|
272
|
-
/* @__PURE__ */
|
|
335
|
+
/* @__PURE__ */ jsx4("span", { className: "absolute left-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx4(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx4(Check, { className: "h-4 w-4" }) }) }),
|
|
336
|
+
/* @__PURE__ */ jsx4(SelectPrimitive.ItemText, { children })
|
|
273
337
|
]
|
|
274
338
|
}
|
|
275
339
|
));
|
|
276
340
|
SelectItem.displayName = "SelectItem";
|
|
277
341
|
|
|
278
342
|
// src/filter/BooleanFilter.tsx
|
|
279
|
-
import { jsx as
|
|
343
|
+
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
280
344
|
var BOOLEAN_CHOICES = [
|
|
281
|
-
{ value: "all",
|
|
282
|
-
{ value: "yes",
|
|
283
|
-
{ value: "no",
|
|
345
|
+
{ value: "all", labelKey: "booleanAll" },
|
|
346
|
+
{ value: "yes", labelKey: "booleanYes" },
|
|
347
|
+
{ value: "no", labelKey: "booleanNo" }
|
|
284
348
|
];
|
|
285
349
|
function choiceOf(value) {
|
|
286
350
|
if (!value) return "all";
|
|
@@ -300,11 +364,13 @@ function BooleanFilter({
|
|
|
300
364
|
column,
|
|
301
365
|
value,
|
|
302
366
|
onChange,
|
|
303
|
-
bare = false
|
|
367
|
+
bare = false,
|
|
368
|
+
labels: labelOverrides
|
|
304
369
|
}) {
|
|
370
|
+
const labels = useFilterLabels(labelOverrides);
|
|
305
371
|
const choice = choiceOf(value);
|
|
306
372
|
const isFiltered = choice !== "all";
|
|
307
|
-
const summary = choice === "yes" ?
|
|
373
|
+
const summary = choice === "yes" ? labels.booleanYes : choice === "no" ? labels.booleanNo : "";
|
|
308
374
|
function emit(next) {
|
|
309
375
|
if (next === "all") {
|
|
310
376
|
onChange(void 0);
|
|
@@ -321,36 +387,36 @@ function BooleanFilter({
|
|
|
321
387
|
if (match) emit(match);
|
|
322
388
|
},
|
|
323
389
|
children: [
|
|
324
|
-
/* @__PURE__ */
|
|
325
|
-
/* @__PURE__ */
|
|
390
|
+
/* @__PURE__ */ jsx5(SelectTrigger, { "aria-label": labels.booleanAriaLabel(column.header), children: /* @__PURE__ */ jsx5(SelectValue, {}) }),
|
|
391
|
+
/* @__PURE__ */ jsx5(SelectContent, { children: BOOLEAN_CHOICES.map((option) => /* @__PURE__ */ jsx5(SelectItem, { value: option.value, children: labels[option.labelKey] }, option.value)) })
|
|
326
392
|
]
|
|
327
393
|
}
|
|
328
394
|
);
|
|
329
395
|
if (bare) {
|
|
330
|
-
return /* @__PURE__ */
|
|
396
|
+
return /* @__PURE__ */ jsx5("div", { "data-testid": `filter-${column.id}`, children: panel });
|
|
331
397
|
}
|
|
332
398
|
return /* @__PURE__ */ jsxs2(Popover, { children: [
|
|
333
|
-
/* @__PURE__ */
|
|
399
|
+
/* @__PURE__ */ jsx5(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs2(
|
|
334
400
|
Button,
|
|
335
401
|
{
|
|
336
402
|
variant: "outline",
|
|
337
403
|
size: "sm",
|
|
338
404
|
className: cn("gap-1", isFiltered ? "max-w-[140px] px-2" : "w-8 justify-center px-0"),
|
|
339
|
-
"aria-label":
|
|
405
|
+
"aria-label": labels.filterAriaLabel(column.header),
|
|
340
406
|
"data-testid": `filter-${column.id}`,
|
|
341
407
|
children: [
|
|
342
|
-
/* @__PURE__ */
|
|
408
|
+
/* @__PURE__ */ jsx5(
|
|
343
409
|
FunnelIcon,
|
|
344
410
|
{
|
|
345
411
|
className: cn("h-3.5 w-3.5 shrink-0", isFiltered ? "opacity-100 text-primary" : "opacity-40"),
|
|
346
412
|
"aria-hidden": true
|
|
347
413
|
}
|
|
348
414
|
),
|
|
349
|
-
isFiltered && /* @__PURE__ */
|
|
415
|
+
isFiltered && /* @__PURE__ */ jsx5("span", { className: "truncate", children: summary })
|
|
350
416
|
]
|
|
351
417
|
}
|
|
352
418
|
) }),
|
|
353
|
-
/* @__PURE__ */
|
|
419
|
+
/* @__PURE__ */ jsx5(PopoverContent, { className: "w-40 p-2", children: panel })
|
|
354
420
|
] });
|
|
355
421
|
}
|
|
356
422
|
|
|
@@ -362,10 +428,10 @@ import { endOfDay, endOfMonth, format, parseISO as parseISO2, startOfDay, startO
|
|
|
362
428
|
import { ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon } from "lucide-react";
|
|
363
429
|
import { useEffect, useRef } from "react";
|
|
364
430
|
import { DayPicker, getDefaultClassNames } from "react-day-picker";
|
|
365
|
-
import { jsx as
|
|
431
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
366
432
|
function Calendar({ className, classNames, ...props }) {
|
|
367
433
|
const defaultClassNames = getDefaultClassNames();
|
|
368
|
-
return /* @__PURE__ */
|
|
434
|
+
return /* @__PURE__ */ jsx6(
|
|
369
435
|
DayPicker,
|
|
370
436
|
{
|
|
371
437
|
className: cn("w-fit", className),
|
|
@@ -416,14 +482,14 @@ function Calendar({ className, classNames, ...props }) {
|
|
|
416
482
|
components: {
|
|
417
483
|
Chevron: ({ className: chevronClassName, orientation }) => {
|
|
418
484
|
const Icon2 = orientation === "up" ? ChevronUpIcon : orientation === "down" ? ChevronDownIcon : orientation === "right" ? ChevronRightIcon : ChevronLeftIcon;
|
|
419
|
-
return /* @__PURE__ */
|
|
485
|
+
return /* @__PURE__ */ jsx6(Icon2, { className: cn("h-4 w-4", chevronClassName), "aria-hidden": true });
|
|
420
486
|
},
|
|
421
487
|
DayButton: ({ className: dayClassName, day: _day, modifiers, ...dayProps }) => {
|
|
422
488
|
const ref = useRef(null);
|
|
423
489
|
useEffect(() => {
|
|
424
490
|
if (modifiers.focused) ref.current?.focus();
|
|
425
491
|
}, [modifiers.focused]);
|
|
426
|
-
return /* @__PURE__ */
|
|
492
|
+
return /* @__PURE__ */ jsx6(
|
|
427
493
|
"button",
|
|
428
494
|
{
|
|
429
495
|
ref,
|
|
@@ -447,21 +513,21 @@ function Calendar({ className, classNames, ...props }) {
|
|
|
447
513
|
}
|
|
448
514
|
|
|
449
515
|
// src/filter/DateRangeFilter.tsx
|
|
450
|
-
import { jsx as
|
|
516
|
+
import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
451
517
|
var PRESETS = [
|
|
452
518
|
{
|
|
453
519
|
key: "today",
|
|
454
|
-
|
|
520
|
+
labelKey: "dateToday",
|
|
455
521
|
range: (today) => ({ from: startOfDay(today), to: endOfDay(today) })
|
|
456
522
|
},
|
|
457
523
|
{
|
|
458
524
|
key: "last7",
|
|
459
|
-
|
|
525
|
+
labelKey: "dateLast7Days",
|
|
460
526
|
range: (today) => ({ from: startOfDay(subDays(today, 6)), to: endOfDay(today) })
|
|
461
527
|
},
|
|
462
528
|
{
|
|
463
529
|
key: "thisMonth",
|
|
464
|
-
|
|
530
|
+
labelKey: "dateThisMonth",
|
|
465
531
|
range: (today) => ({ from: startOfMonth(today), to: endOfMonth(today) })
|
|
466
532
|
}
|
|
467
533
|
];
|
|
@@ -486,8 +552,11 @@ function DateRangeFilter({
|
|
|
486
552
|
value,
|
|
487
553
|
onChange,
|
|
488
554
|
today = /* @__PURE__ */ new Date(),
|
|
489
|
-
bare = false
|
|
555
|
+
bare = false,
|
|
556
|
+
labels: labelOverrides
|
|
490
557
|
}) {
|
|
558
|
+
const labels = useFilterLabels(labelOverrides);
|
|
559
|
+
const locale = labels.dateLocale ? { locale: labels.dateLocale } : void 0;
|
|
491
560
|
const range = rangeOf(value);
|
|
492
561
|
function emit(next) {
|
|
493
562
|
if (!next?.from || !next.to) {
|
|
@@ -502,56 +571,56 @@ function DateRangeFilter({
|
|
|
502
571
|
});
|
|
503
572
|
}
|
|
504
573
|
const isFiltered = range?.from !== void 0;
|
|
505
|
-
const summary = range?.from ? range.to ? `${format(range.from, "PP")} - ${format(range.to, "PP")}` : format(range.from, "PP") : "";
|
|
574
|
+
const summary = range?.from ? range.to ? `${format(range.from, "PP", locale)} - ${format(range.to, "PP", locale)}` : format(range.from, "PP", locale) : "";
|
|
506
575
|
const panel = /* @__PURE__ */ jsxs3("div", { className: "space-y-2", children: [
|
|
507
576
|
/* @__PURE__ */ jsxs3("div", { className: "flex flex-wrap gap-2", children: [
|
|
508
|
-
PRESETS.map((preset) => /* @__PURE__ */
|
|
577
|
+
PRESETS.map((preset) => /* @__PURE__ */ jsx7(
|
|
509
578
|
Button,
|
|
510
579
|
{
|
|
511
580
|
type: "button",
|
|
512
581
|
variant: "outline",
|
|
513
582
|
size: "sm",
|
|
514
583
|
onClick: () => emit(preset.range(today)),
|
|
515
|
-
children: preset.
|
|
584
|
+
children: labels[preset.labelKey]
|
|
516
585
|
},
|
|
517
586
|
preset.key
|
|
518
587
|
)),
|
|
519
|
-
/* @__PURE__ */
|
|
588
|
+
/* @__PURE__ */ jsx7(Button, { type: "button", variant: "outline", size: "sm", onClick: () => emit(void 0), children: labels.dateCustom })
|
|
520
589
|
] }),
|
|
521
|
-
/* @__PURE__ */
|
|
590
|
+
/* @__PURE__ */ jsx7(Calendar, { mode: "range", selected: range, onSelect: emit, numberOfMonths: 2, locale: labels.dateLocale })
|
|
522
591
|
] });
|
|
523
592
|
if (bare) {
|
|
524
|
-
return /* @__PURE__ */
|
|
593
|
+
return /* @__PURE__ */ jsx7("div", { "data-testid": `filter-${column.id}`, children: panel });
|
|
525
594
|
}
|
|
526
595
|
return /* @__PURE__ */ jsxs3(Popover, { children: [
|
|
527
|
-
/* @__PURE__ */
|
|
596
|
+
/* @__PURE__ */ jsx7(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs3(
|
|
528
597
|
Button,
|
|
529
598
|
{
|
|
530
599
|
variant: "outline",
|
|
531
600
|
size: "sm",
|
|
532
601
|
className: cn("gap-1", isFiltered ? "max-w-[220px] px-2" : "w-8 justify-center px-0"),
|
|
533
|
-
"aria-label":
|
|
602
|
+
"aria-label": labels.filterAriaLabel(column.header),
|
|
534
603
|
"data-testid": `filter-${column.id}`,
|
|
535
604
|
children: [
|
|
536
|
-
/* @__PURE__ */
|
|
537
|
-
isFiltered && /* @__PURE__ */
|
|
605
|
+
/* @__PURE__ */ jsx7(CalendarDaysIcon, { className: "h-3.5 w-3.5 shrink-0 opacity-70", "aria-hidden": true }),
|
|
606
|
+
isFiltered && /* @__PURE__ */ jsx7("span", { className: "truncate", children: summary })
|
|
538
607
|
]
|
|
539
608
|
}
|
|
540
609
|
) }),
|
|
541
|
-
/* @__PURE__ */
|
|
610
|
+
/* @__PURE__ */ jsx7(PopoverContent, { className: "w-auto max-w-[var(--radix-popover-content-available-width)]", children: panel })
|
|
542
611
|
] });
|
|
543
612
|
}
|
|
544
613
|
|
|
545
614
|
// src/filter/EnumFilter.tsx
|
|
546
615
|
import { FunnelIcon as FunnelIcon2 } from "@heroicons/react/24/outline";
|
|
547
|
-
import { useMemo, useState } from "react";
|
|
616
|
+
import { useMemo as useMemo2, useState } from "react";
|
|
548
617
|
|
|
549
618
|
// src/components/ui/checkbox.tsx
|
|
550
619
|
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
|
|
551
620
|
import { Check as Check2, Minus } from "lucide-react";
|
|
552
621
|
import { forwardRef as forwardRef4 } from "react";
|
|
553
|
-
import { jsx as
|
|
554
|
-
var Checkbox = forwardRef4(({ className, ...props }, ref) => /* @__PURE__ */
|
|
622
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
623
|
+
var Checkbox = forwardRef4(({ className, ...props }, ref) => /* @__PURE__ */ jsx8(
|
|
555
624
|
CheckboxPrimitive.Root,
|
|
556
625
|
{
|
|
557
626
|
ref,
|
|
@@ -564,16 +633,16 @@ var Checkbox = forwardRef4(({ className, ...props }, ref) => /* @__PURE__ */ jsx
|
|
|
564
633
|
className
|
|
565
634
|
),
|
|
566
635
|
...props,
|
|
567
|
-
children: /* @__PURE__ */
|
|
636
|
+
children: /* @__PURE__ */ jsx8(CheckboxPrimitive.Indicator, { className: "flex items-center justify-center text-current", children: props.checked === "indeterminate" ? /* @__PURE__ */ jsx8(Minus, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx8(Check2, { className: "h-3 w-3" }) })
|
|
568
637
|
}
|
|
569
638
|
));
|
|
570
639
|
Checkbox.displayName = "Checkbox";
|
|
571
640
|
|
|
572
641
|
// src/components/ui/input.tsx
|
|
573
642
|
import { forwardRef as forwardRef5 } from "react";
|
|
574
|
-
import { jsx as
|
|
643
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
575
644
|
var Input = forwardRef5(({ className, type, ...props }, ref) => {
|
|
576
|
-
return /* @__PURE__ */
|
|
645
|
+
return /* @__PURE__ */ jsx9(
|
|
577
646
|
"input",
|
|
578
647
|
{
|
|
579
648
|
type,
|
|
@@ -589,7 +658,7 @@ var Input = forwardRef5(({ className, type, ...props }, ref) => {
|
|
|
589
658
|
Input.displayName = "Input";
|
|
590
659
|
|
|
591
660
|
// src/filter/EnumFilter.tsx
|
|
592
|
-
import { jsx as
|
|
661
|
+
import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
593
662
|
function selectedValuesOf(value) {
|
|
594
663
|
if (!value || value.operator !== "in" || !Array.isArray(value.value)) return [];
|
|
595
664
|
return value.value.filter((entry) => typeof entry === "string");
|
|
@@ -622,16 +691,18 @@ function EnumFilter({
|
|
|
622
691
|
column,
|
|
623
692
|
value,
|
|
624
693
|
onChange,
|
|
625
|
-
bare = false
|
|
694
|
+
bare = false,
|
|
695
|
+
labels: labelOverrides
|
|
626
696
|
}) {
|
|
697
|
+
const labels = useFilterLabels(labelOverrides);
|
|
627
698
|
const [search, setSearch] = useState("");
|
|
628
699
|
const selected = selectedValuesOf(value);
|
|
629
|
-
const visibleOptions =
|
|
700
|
+
const visibleOptions = useMemo2(() => {
|
|
630
701
|
const term = search.trim().toLowerCase();
|
|
631
702
|
if (!term) return column.options;
|
|
632
703
|
return column.options.filter((option) => option.label.toLowerCase().includes(term));
|
|
633
704
|
}, [column.options, search]);
|
|
634
|
-
const renderChunks =
|
|
705
|
+
const renderChunks = useMemo2(() => buildRenderChunks(visibleOptions), [visibleOptions]);
|
|
635
706
|
function emit(next) {
|
|
636
707
|
onChange(next.length === 0 ? void 0 : { field: column.id, operator: "in", value: next });
|
|
637
708
|
}
|
|
@@ -662,7 +733,7 @@ function EnumFilter({
|
|
|
662
733
|
{
|
|
663
734
|
className: "flex items-center gap-2 rounded-sm px-2 py-1.5 text-sm hover:bg-accent hover:text-accent-foreground",
|
|
664
735
|
children: [
|
|
665
|
-
/* @__PURE__ */
|
|
736
|
+
/* @__PURE__ */ jsx10(
|
|
666
737
|
Checkbox,
|
|
667
738
|
{
|
|
668
739
|
checked: selected.includes(option.value),
|
|
@@ -676,29 +747,29 @@ function EnumFilter({
|
|
|
676
747
|
);
|
|
677
748
|
}
|
|
678
749
|
const isFiltered = selected.length > 0;
|
|
679
|
-
const summary =
|
|
750
|
+
const summary = labels.selectedCount(selected.length);
|
|
680
751
|
const panel = /* @__PURE__ */ jsxs4("div", { className: bare ? "flex w-full flex-col gap-2" : "flex w-64 flex-col gap-2 p-2", children: [
|
|
681
|
-
/* @__PURE__ */
|
|
752
|
+
/* @__PURE__ */ jsx10(
|
|
682
753
|
Input,
|
|
683
754
|
{
|
|
684
|
-
placeholder:
|
|
755
|
+
placeholder: labels.searchPlaceholder(column.header),
|
|
685
756
|
value: search,
|
|
686
757
|
onChange: (event) => setSearch(event.target.value)
|
|
687
758
|
}
|
|
688
759
|
),
|
|
689
760
|
/* @__PURE__ */ jsxs4("label", { className: "flex items-center gap-2 border-b px-1 pb-2 text-sm", children: [
|
|
690
|
-
/* @__PURE__ */
|
|
761
|
+
/* @__PURE__ */ jsx10(
|
|
691
762
|
Checkbox,
|
|
692
763
|
{
|
|
693
764
|
checked: someVisibleSelected ? "indeterminate" : allVisibleSelected,
|
|
694
765
|
disabled: visibleValues.length === 0,
|
|
695
766
|
onCheckedChange: toggleSelectAllVisible,
|
|
696
|
-
"aria-label":
|
|
767
|
+
"aria-label": labels.selectAll
|
|
697
768
|
}
|
|
698
769
|
),
|
|
699
|
-
|
|
770
|
+
labels.selectAll
|
|
700
771
|
] }),
|
|
701
|
-
/* @__PURE__ */
|
|
772
|
+
/* @__PURE__ */ jsx10("div", { className: "flex max-h-60 flex-col gap-0.5 overflow-y-auto", children: renderChunks.length === 0 ? /* @__PURE__ */ jsx10("p", { className: "py-2 text-center text-sm text-muted-foreground", children: labels.noMatches }) : renderChunks.map((chunk) => {
|
|
702
773
|
if (chunk.kind === "single") return renderOption(chunk.row.option);
|
|
703
774
|
const headerState = groupCheckState(visibleOptions, selected, chunk.group);
|
|
704
775
|
return (
|
|
@@ -713,12 +784,12 @@ function EnumFilter({
|
|
|
713
784
|
"data-group-header": true,
|
|
714
785
|
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
786
|
children: [
|
|
716
|
-
/* @__PURE__ */
|
|
787
|
+
/* @__PURE__ */ jsx10(
|
|
717
788
|
Checkbox,
|
|
718
789
|
{
|
|
719
790
|
checked: headerState === "indeterminate" ? "indeterminate" : headerState === "checked",
|
|
720
791
|
onCheckedChange: () => toggleGroup(chunk.group),
|
|
721
|
-
"aria-label":
|
|
792
|
+
"aria-label": labels.selectAllOfGroup(chunk.group)
|
|
722
793
|
}
|
|
723
794
|
),
|
|
724
795
|
chunk.group
|
|
@@ -731,30 +802,30 @@ function EnumFilter({
|
|
|
731
802
|
}) })
|
|
732
803
|
] });
|
|
733
804
|
if (bare) {
|
|
734
|
-
return /* @__PURE__ */
|
|
805
|
+
return /* @__PURE__ */ jsx10("div", { "data-testid": `filter-${column.id}`, children: panel });
|
|
735
806
|
}
|
|
736
807
|
return /* @__PURE__ */ jsxs4(Popover, { children: [
|
|
737
|
-
/* @__PURE__ */
|
|
808
|
+
/* @__PURE__ */ jsx10(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs4(
|
|
738
809
|
Button,
|
|
739
810
|
{
|
|
740
811
|
variant: "outline",
|
|
741
812
|
size: "sm",
|
|
742
813
|
className: cn("gap-1", isFiltered ? "max-w-[180px] px-2" : "w-8 justify-center px-0"),
|
|
743
|
-
"aria-label":
|
|
814
|
+
"aria-label": labels.filterAriaLabel(column.header),
|
|
744
815
|
"data-testid": `filter-${column.id}`,
|
|
745
816
|
children: [
|
|
746
|
-
/* @__PURE__ */
|
|
817
|
+
/* @__PURE__ */ jsx10(
|
|
747
818
|
FunnelIcon2,
|
|
748
819
|
{
|
|
749
820
|
className: cn("h-3.5 w-3.5 shrink-0", isFiltered ? "opacity-100 text-primary" : "opacity-40"),
|
|
750
821
|
"aria-hidden": true
|
|
751
822
|
}
|
|
752
823
|
),
|
|
753
|
-
isFiltered && /* @__PURE__ */
|
|
824
|
+
isFiltered && /* @__PURE__ */ jsx10("span", { className: "truncate", children: summary })
|
|
754
825
|
]
|
|
755
826
|
}
|
|
756
827
|
) }),
|
|
757
|
-
/* @__PURE__ */
|
|
828
|
+
/* @__PURE__ */ jsx10(PopoverContent, { className: "w-64 p-2", children: panel })
|
|
758
829
|
] });
|
|
759
830
|
}
|
|
760
831
|
|
|
@@ -897,15 +968,15 @@ function descriptorFor(field, range) {
|
|
|
897
968
|
}
|
|
898
969
|
|
|
899
970
|
// src/filter/NumberComparisonFilter.tsx
|
|
900
|
-
import { Fragment, jsx as
|
|
971
|
+
import { Fragment, jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
901
972
|
var NUMBER_OPERATORS = [
|
|
902
|
-
{ value: "gt",
|
|
903
|
-
{ value: "gte",
|
|
904
|
-
{ value: "lt",
|
|
905
|
-
{ value: "lte",
|
|
906
|
-
{ value: "eq",
|
|
907
|
-
{ value: "neq",
|
|
908
|
-
{ value: "between",
|
|
973
|
+
{ value: "gt", labelKey: "numberGreaterThan" },
|
|
974
|
+
{ value: "gte", labelKey: "numberGreaterThanOrEqual" },
|
|
975
|
+
{ value: "lt", labelKey: "numberLessThan" },
|
|
976
|
+
{ value: "lte", labelKey: "numberLessThanOrEqual" },
|
|
977
|
+
{ value: "eq", labelKey: "numberEquals" },
|
|
978
|
+
{ value: "neq", labelKey: "numberNotEquals" },
|
|
979
|
+
{ value: "between", labelKey: "numberBetween" }
|
|
909
980
|
];
|
|
910
981
|
var OPERATOR_SYMBOL = {
|
|
911
982
|
gt: ">",
|
|
@@ -939,8 +1010,10 @@ function NumberComparisonFilter({
|
|
|
939
1010
|
column,
|
|
940
1011
|
value,
|
|
941
1012
|
onChange,
|
|
942
|
-
bare = true
|
|
1013
|
+
bare = true,
|
|
1014
|
+
labels: labelOverrides
|
|
943
1015
|
}) {
|
|
1016
|
+
const labels = useFilterLabels(labelOverrides);
|
|
944
1017
|
const initial = stateFromValue(value);
|
|
945
1018
|
const [operator, setOperator] = useState2(initial.operator);
|
|
946
1019
|
const [text, setText] = useState2(initial.text);
|
|
@@ -994,20 +1067,20 @@ function NumberComparisonFilter({
|
|
|
994
1067
|
emit(nextOperator, text, text2);
|
|
995
1068
|
},
|
|
996
1069
|
children: [
|
|
997
|
-
/* @__PURE__ */
|
|
998
|
-
/* @__PURE__ */
|
|
1070
|
+
/* @__PURE__ */ jsx11(SelectTrigger, { id: operatorId, "aria-label": labels.operatorAriaLabel(column.header), children: /* @__PURE__ */ jsx11(SelectValue, {}) }),
|
|
1071
|
+
/* @__PURE__ */ jsx11(SelectContent, { children: NUMBER_OPERATORS.map((option) => /* @__PURE__ */ jsx11(SelectItem, { value: option.value, children: labels[option.labelKey] }, option.value)) })
|
|
999
1072
|
]
|
|
1000
1073
|
}
|
|
1001
1074
|
),
|
|
1002
1075
|
/* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
|
|
1003
|
-
/* @__PURE__ */
|
|
1076
|
+
/* @__PURE__ */ jsx11(
|
|
1004
1077
|
Input,
|
|
1005
1078
|
{
|
|
1006
1079
|
id: valueId,
|
|
1007
1080
|
type: "number",
|
|
1008
1081
|
className: "min-w-0",
|
|
1009
|
-
"aria-label": isBetween ?
|
|
1010
|
-
placeholder: isBetween ?
|
|
1082
|
+
"aria-label": isBetween ? labels.minimumAriaLabel(column.header) : column.header,
|
|
1083
|
+
placeholder: isBetween ? labels.minPlaceholder : labels.valuePlaceholder,
|
|
1011
1084
|
value: text,
|
|
1012
1085
|
onChange: (event) => {
|
|
1013
1086
|
setText(event.target.value);
|
|
@@ -1016,14 +1089,14 @@ function NumberComparisonFilter({
|
|
|
1016
1089
|
}
|
|
1017
1090
|
),
|
|
1018
1091
|
isBetween && /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
1019
|
-
/* @__PURE__ */
|
|
1020
|
-
/* @__PURE__ */
|
|
1092
|
+
/* @__PURE__ */ jsx11("span", { className: "shrink-0 text-xs text-muted-foreground", children: labels.rangeSeparator }),
|
|
1093
|
+
/* @__PURE__ */ jsx11(
|
|
1021
1094
|
Input,
|
|
1022
1095
|
{
|
|
1023
1096
|
type: "number",
|
|
1024
1097
|
className: "min-w-0",
|
|
1025
|
-
"aria-label":
|
|
1026
|
-
placeholder:
|
|
1098
|
+
"aria-label": labels.maximumAriaLabel(column.header),
|
|
1099
|
+
placeholder: labels.maxPlaceholder,
|
|
1027
1100
|
value: text2,
|
|
1028
1101
|
onChange: (event) => {
|
|
1029
1102
|
setText2(event.target.value);
|
|
@@ -1035,37 +1108,37 @@ function NumberComparisonFilter({
|
|
|
1035
1108
|
] })
|
|
1036
1109
|
] });
|
|
1037
1110
|
if (bare) {
|
|
1038
|
-
return /* @__PURE__ */
|
|
1111
|
+
return /* @__PURE__ */ jsx11("div", { "data-testid": `filter-${column.id}`, children: panel });
|
|
1039
1112
|
}
|
|
1040
1113
|
return /* @__PURE__ */ jsxs5(Popover, { children: [
|
|
1041
|
-
/* @__PURE__ */
|
|
1114
|
+
/* @__PURE__ */ jsx11(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs5(
|
|
1042
1115
|
Button,
|
|
1043
1116
|
{
|
|
1044
1117
|
variant: "outline",
|
|
1045
1118
|
size: "sm",
|
|
1046
1119
|
className: cn("gap-1", isFiltered ? "max-w-[180px] px-2" : "w-8 justify-center px-0"),
|
|
1047
|
-
"aria-label":
|
|
1120
|
+
"aria-label": labels.filterAriaLabel(column.header),
|
|
1048
1121
|
"data-testid": `filter-${column.id}`,
|
|
1049
1122
|
children: [
|
|
1050
|
-
/* @__PURE__ */
|
|
1123
|
+
/* @__PURE__ */ jsx11(
|
|
1051
1124
|
FunnelIcon3,
|
|
1052
1125
|
{
|
|
1053
1126
|
className: cn("h-3.5 w-3.5 shrink-0", isFiltered ? "opacity-100 text-primary" : "opacity-40"),
|
|
1054
1127
|
"aria-hidden": true
|
|
1055
1128
|
}
|
|
1056
1129
|
),
|
|
1057
|
-
isFiltered && /* @__PURE__ */
|
|
1130
|
+
isFiltered && /* @__PURE__ */ jsx11("span", { className: "truncate", children: summary })
|
|
1058
1131
|
]
|
|
1059
1132
|
}
|
|
1060
1133
|
) }),
|
|
1061
|
-
/* @__PURE__ */
|
|
1134
|
+
/* @__PURE__ */ jsx11(PopoverContent, { className: "w-auto p-3", children: panel })
|
|
1062
1135
|
] });
|
|
1063
1136
|
}
|
|
1064
1137
|
|
|
1065
1138
|
// src/filter/NumberRangeFilter.tsx
|
|
1066
1139
|
import { FunnelIcon as FunnelIcon4 } from "@heroicons/react/24/outline";
|
|
1067
1140
|
import { useEffect as useEffect3, useId as useId2, useRef as useRef3, useState as useState3 } from "react";
|
|
1068
|
-
import { jsx as
|
|
1141
|
+
import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
1069
1142
|
function parseNumber2(raw) {
|
|
1070
1143
|
if (raw.trim() === "") return void 0;
|
|
1071
1144
|
const parsed = Number(raw);
|
|
@@ -1075,8 +1148,10 @@ function NumberRangeFilter({
|
|
|
1075
1148
|
column,
|
|
1076
1149
|
value,
|
|
1077
1150
|
onChange,
|
|
1078
|
-
bare = false
|
|
1151
|
+
bare = false,
|
|
1152
|
+
labels: labelOverrides
|
|
1079
1153
|
}) {
|
|
1154
|
+
const labels = useFilterLabels(labelOverrides);
|
|
1080
1155
|
const initial = rangeOf2(value);
|
|
1081
1156
|
const [minText, setMinText] = useState3(initial.min?.toString() ?? "");
|
|
1082
1157
|
const [maxText, setMaxText] = useState3(initial.max?.toString() ?? "");
|
|
@@ -1102,13 +1177,13 @@ function NumberRangeFilter({
|
|
|
1102
1177
|
const isFiltered = min !== void 0 || max !== void 0;
|
|
1103
1178
|
const summary = min !== void 0 && max !== void 0 ? `${defaultFormat(column, min)} \u2013 ${defaultFormat(column, max)}` : min !== void 0 ? `\u2265 ${defaultFormat(column, min)}` : max !== void 0 ? `\u2264 ${defaultFormat(column, max)}` : "";
|
|
1104
1179
|
const panel = /* @__PURE__ */ jsxs6("div", { className: "flex w-full max-w-[220px] items-center gap-2", children: [
|
|
1105
|
-
/* @__PURE__ */
|
|
1180
|
+
/* @__PURE__ */ jsx12(
|
|
1106
1181
|
Input,
|
|
1107
1182
|
{
|
|
1108
1183
|
id: minId,
|
|
1109
1184
|
type: "number",
|
|
1110
|
-
"aria-label":
|
|
1111
|
-
placeholder:
|
|
1185
|
+
"aria-label": labels.minimumAriaLabel(column.header),
|
|
1186
|
+
placeholder: labels.minPlaceholder,
|
|
1112
1187
|
className: "min-w-0",
|
|
1113
1188
|
value: minText,
|
|
1114
1189
|
onChange: (event) => {
|
|
@@ -1117,14 +1192,14 @@ function NumberRangeFilter({
|
|
|
1117
1192
|
}
|
|
1118
1193
|
}
|
|
1119
1194
|
),
|
|
1120
|
-
/* @__PURE__ */
|
|
1121
|
-
/* @__PURE__ */
|
|
1195
|
+
/* @__PURE__ */ jsx12("span", { className: "shrink-0 text-xs text-muted-foreground", children: labels.rangeSeparator }),
|
|
1196
|
+
/* @__PURE__ */ jsx12(
|
|
1122
1197
|
Input,
|
|
1123
1198
|
{
|
|
1124
1199
|
id: maxId,
|
|
1125
1200
|
type: "number",
|
|
1126
|
-
"aria-label":
|
|
1127
|
-
placeholder:
|
|
1201
|
+
"aria-label": labels.maximumAriaLabel(column.header),
|
|
1202
|
+
placeholder: labels.maxPlaceholder,
|
|
1128
1203
|
className: "min-w-0",
|
|
1129
1204
|
value: maxText,
|
|
1130
1205
|
onChange: (event) => {
|
|
@@ -1135,37 +1210,37 @@ function NumberRangeFilter({
|
|
|
1135
1210
|
)
|
|
1136
1211
|
] });
|
|
1137
1212
|
if (bare) {
|
|
1138
|
-
return /* @__PURE__ */
|
|
1213
|
+
return /* @__PURE__ */ jsx12("div", { "data-testid": `filter-${column.id}`, children: panel });
|
|
1139
1214
|
}
|
|
1140
1215
|
return /* @__PURE__ */ jsxs6(Popover, { children: [
|
|
1141
|
-
/* @__PURE__ */
|
|
1216
|
+
/* @__PURE__ */ jsx12(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs6(
|
|
1142
1217
|
Button,
|
|
1143
1218
|
{
|
|
1144
1219
|
variant: "outline",
|
|
1145
1220
|
size: "sm",
|
|
1146
1221
|
className: cn("gap-1", isFiltered ? "max-w-[180px] px-2" : "w-8 justify-center px-0"),
|
|
1147
|
-
"aria-label":
|
|
1222
|
+
"aria-label": labels.filterAriaLabel(column.header),
|
|
1148
1223
|
"data-testid": `filter-${column.id}`,
|
|
1149
1224
|
children: [
|
|
1150
|
-
/* @__PURE__ */
|
|
1225
|
+
/* @__PURE__ */ jsx12(
|
|
1151
1226
|
FunnelIcon4,
|
|
1152
1227
|
{
|
|
1153
1228
|
className: cn("h-3.5 w-3.5 shrink-0", isFiltered ? "opacity-100 text-primary" : "opacity-40"),
|
|
1154
1229
|
"aria-hidden": true
|
|
1155
1230
|
}
|
|
1156
1231
|
),
|
|
1157
|
-
isFiltered && /* @__PURE__ */
|
|
1232
|
+
isFiltered && /* @__PURE__ */ jsx12("span", { className: "truncate", children: summary })
|
|
1158
1233
|
]
|
|
1159
1234
|
}
|
|
1160
1235
|
) }),
|
|
1161
|
-
/* @__PURE__ */
|
|
1236
|
+
/* @__PURE__ */ jsx12(PopoverContent, { className: "w-auto p-3", children: panel })
|
|
1162
1237
|
] });
|
|
1163
1238
|
}
|
|
1164
1239
|
|
|
1165
1240
|
// src/filter/NumberHistogramFilter.tsx
|
|
1166
1241
|
import { FunnelIcon as FunnelIcon5 } from "@heroicons/react/24/outline";
|
|
1167
|
-
import { useCallback, useEffect as useEffect4, useMemo as
|
|
1168
|
-
import { jsx as
|
|
1242
|
+
import { useCallback, useEffect as useEffect4, useMemo as useMemo3, useRef as useRef4, useState as useState4 } from "react";
|
|
1243
|
+
import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1169
1244
|
var BAR_HEIGHT_PX = 56;
|
|
1170
1245
|
var DEFAULT_BUCKETS = 24;
|
|
1171
1246
|
function tLog(v) {
|
|
@@ -1182,8 +1257,10 @@ function NumberHistogramFilter({
|
|
|
1182
1257
|
loadValues,
|
|
1183
1258
|
format: format2 = (v) => v.toLocaleString(),
|
|
1184
1259
|
buckets = DEFAULT_BUCKETS,
|
|
1185
|
-
bare = true
|
|
1260
|
+
bare = true,
|
|
1261
|
+
labels: labelOverrides
|
|
1186
1262
|
}) {
|
|
1263
|
+
const labels = useFilterLabels(labelOverrides);
|
|
1187
1264
|
const [openState, setOpen] = useState4(false);
|
|
1188
1265
|
const open = bare || openState;
|
|
1189
1266
|
const trackRef = useRef4(null);
|
|
@@ -1205,12 +1282,12 @@ function NumberHistogramFilter({
|
|
|
1205
1282
|
};
|
|
1206
1283
|
}, [open, loadValues]);
|
|
1207
1284
|
const sourceValues = allValues ?? loadedValues;
|
|
1208
|
-
const nums =
|
|
1285
|
+
const nums = useMemo3(
|
|
1209
1286
|
() => open ? sourceValues.filter((v) => v != null) : [],
|
|
1210
1287
|
[sourceValues, open]
|
|
1211
1288
|
);
|
|
1212
|
-
const dataMin =
|
|
1213
|
-
const dataMax =
|
|
1289
|
+
const dataMin = useMemo3(() => nums.reduce((a, b) => Math.min(a, b), Infinity), [nums]);
|
|
1290
|
+
const dataMax = useMemo3(() => nums.reduce((a, b) => Math.max(a, b), -Infinity), [nums]);
|
|
1214
1291
|
const activeMin = min ?? dataMin;
|
|
1215
1292
|
const activeMax = max ?? dataMax;
|
|
1216
1293
|
const [minText, setMinText] = useState4("");
|
|
@@ -1227,7 +1304,7 @@ function NumberHistogramFilter({
|
|
|
1227
1304
|
(v) => logDataMax === logDataMin ? 0 : (tLog(v) - logDataMin) / (logDataMax - logDataMin) * 100,
|
|
1228
1305
|
[logDataMin, logDataMax]
|
|
1229
1306
|
);
|
|
1230
|
-
const histBars =
|
|
1307
|
+
const histBars = useMemo3(() => {
|
|
1231
1308
|
if (!nums.length || dataMin === dataMax || !Number.isFinite(dataMin) || !Number.isFinite(dataMax)) return [];
|
|
1232
1309
|
const step = (logDataMax - logDataMin) / buckets;
|
|
1233
1310
|
const counts = Array(buckets).fill(0);
|
|
@@ -1266,8 +1343,8 @@ function NumberHistogramFilter({
|
|
|
1266
1343
|
const isFiltered = value !== void 0;
|
|
1267
1344
|
const summary = isFiltered ? `${format2(activeMin)} \u2013 ${format2(activeMax)}` : "";
|
|
1268
1345
|
const panel = /* @__PURE__ */ jsxs7("div", { className: bare ? "flex w-full flex-col gap-3" : "flex w-80 flex-col gap-3", children: [
|
|
1269
|
-
loading && /* @__PURE__ */
|
|
1270
|
-
/* @__PURE__ */
|
|
1346
|
+
loading && /* @__PURE__ */ jsx13("p", { className: "text-xs text-muted-foreground", "data-testid": `filter-${column.id}-loading`, children: labels.loading }),
|
|
1347
|
+
/* @__PURE__ */ jsx13("div", { className: "flex items-end gap-px", style: { height: BAR_HEIGHT_PX }, "data-testid": `filter-${column.id}-histogram`, children: histBars.map((bar, i) => /* @__PURE__ */ jsx13(
|
|
1271
1348
|
"div",
|
|
1272
1349
|
{
|
|
1273
1350
|
className: cn("flex-1 rounded-sm", bar.active ? "bg-primary/70" : "bg-muted-foreground/20"),
|
|
@@ -1276,11 +1353,11 @@ function NumberHistogramFilter({
|
|
|
1276
1353
|
i
|
|
1277
1354
|
)) }),
|
|
1278
1355
|
/* @__PURE__ */ jsxs7("div", { ref: trackRef, className: "relative h-5", onMouseMove: handleTrackHover, children: [
|
|
1279
|
-
/* @__PURE__ */
|
|
1356
|
+
/* @__PURE__ */ jsx13(
|
|
1280
1357
|
"input",
|
|
1281
1358
|
{
|
|
1282
1359
|
type: "range",
|
|
1283
|
-
"aria-label":
|
|
1360
|
+
"aria-label": labels.minimumSliderAriaLabel(column.header),
|
|
1284
1361
|
min: logDataMin,
|
|
1285
1362
|
max: logDataMax,
|
|
1286
1363
|
step: logStep,
|
|
@@ -1290,11 +1367,11 @@ function NumberHistogramFilter({
|
|
|
1290
1367
|
style: { zIndex: minOnTop ? 5 : 3 }
|
|
1291
1368
|
}
|
|
1292
1369
|
),
|
|
1293
|
-
/* @__PURE__ */
|
|
1370
|
+
/* @__PURE__ */ jsx13(
|
|
1294
1371
|
"input",
|
|
1295
1372
|
{
|
|
1296
1373
|
type: "range",
|
|
1297
|
-
"aria-label":
|
|
1374
|
+
"aria-label": labels.maximumSliderAriaLabel(column.header),
|
|
1298
1375
|
min: logDataMin,
|
|
1299
1376
|
max: logDataMax,
|
|
1300
1377
|
step: logStep,
|
|
@@ -1304,14 +1381,14 @@ function NumberHistogramFilter({
|
|
|
1304
1381
|
style: { zIndex: minOnTop ? 3 : 5 }
|
|
1305
1382
|
}
|
|
1306
1383
|
),
|
|
1307
|
-
/* @__PURE__ */
|
|
1384
|
+
/* @__PURE__ */ jsx13("div", { className: "pointer-events-none absolute top-1/2 h-1.5 w-full -translate-y-1/2 rounded-full bg-muted", children: /* @__PURE__ */ jsx13(
|
|
1308
1385
|
"div",
|
|
1309
1386
|
{
|
|
1310
1387
|
className: "absolute h-full rounded-full bg-primary",
|
|
1311
1388
|
style: { left: `${logPct(activeMin)}%`, right: `${100 - logPct(activeMax)}%` }
|
|
1312
1389
|
}
|
|
1313
1390
|
) }),
|
|
1314
|
-
[activeMin, activeMax].map((v, i) => /* @__PURE__ */
|
|
1391
|
+
[activeMin, activeMax].map((v, i) => /* @__PURE__ */ jsx13(
|
|
1315
1392
|
"div",
|
|
1316
1393
|
{
|
|
1317
1394
|
className: "pointer-events-none absolute top-1/2 h-4 w-4 -translate-x-1/2 -translate-y-1/2 rounded-full border-2 border-primary bg-background shadow",
|
|
@@ -1321,12 +1398,12 @@ function NumberHistogramFilter({
|
|
|
1321
1398
|
))
|
|
1322
1399
|
] }),
|
|
1323
1400
|
/* @__PURE__ */ jsxs7("div", { className: "flex items-center gap-2", children: [
|
|
1324
|
-
/* @__PURE__ */
|
|
1401
|
+
/* @__PURE__ */ jsx13(
|
|
1325
1402
|
Input,
|
|
1326
1403
|
{
|
|
1327
1404
|
type: "text",
|
|
1328
1405
|
inputMode: "numeric",
|
|
1329
|
-
"aria-label":
|
|
1406
|
+
"aria-label": labels.minimumAriaLabel(column.header),
|
|
1330
1407
|
value: minText,
|
|
1331
1408
|
onChange: (event) => {
|
|
1332
1409
|
setMinText(event.target.value);
|
|
@@ -1335,13 +1412,13 @@ function NumberHistogramFilter({
|
|
|
1335
1412
|
}
|
|
1336
1413
|
}
|
|
1337
1414
|
),
|
|
1338
|
-
/* @__PURE__ */
|
|
1339
|
-
/* @__PURE__ */
|
|
1415
|
+
/* @__PURE__ */ jsx13("span", { className: "shrink-0 text-xs text-muted-foreground", children: labels.rangeSeparator }),
|
|
1416
|
+
/* @__PURE__ */ jsx13(
|
|
1340
1417
|
Input,
|
|
1341
1418
|
{
|
|
1342
1419
|
type: "text",
|
|
1343
1420
|
inputMode: "numeric",
|
|
1344
|
-
"aria-label":
|
|
1421
|
+
"aria-label": labels.maximumAriaLabel(column.header),
|
|
1345
1422
|
value: maxText,
|
|
1346
1423
|
onChange: (event) => {
|
|
1347
1424
|
setMaxText(event.target.value);
|
|
@@ -1351,33 +1428,33 @@ function NumberHistogramFilter({
|
|
|
1351
1428
|
}
|
|
1352
1429
|
)
|
|
1353
1430
|
] }),
|
|
1354
|
-
isFiltered && /* @__PURE__ */
|
|
1431
|
+
isFiltered && /* @__PURE__ */ jsx13(Button, { type: "button", variant: "ghost", size: "sm", onClick: () => onChange(void 0), children: labels.clear })
|
|
1355
1432
|
] });
|
|
1356
1433
|
if (bare) {
|
|
1357
|
-
return /* @__PURE__ */
|
|
1434
|
+
return /* @__PURE__ */ jsx13("div", { "data-testid": `filter-${column.id}`, children: panel });
|
|
1358
1435
|
}
|
|
1359
1436
|
return /* @__PURE__ */ jsxs7(Popover, { open, onOpenChange: setOpen, children: [
|
|
1360
|
-
/* @__PURE__ */
|
|
1437
|
+
/* @__PURE__ */ jsx13(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs7(
|
|
1361
1438
|
Button,
|
|
1362
1439
|
{
|
|
1363
1440
|
variant: "outline",
|
|
1364
1441
|
size: "sm",
|
|
1365
1442
|
className: cn("gap-1", isFiltered ? "max-w-[200px] px-2" : "w-8 justify-center px-0"),
|
|
1366
|
-
"aria-label":
|
|
1443
|
+
"aria-label": labels.filterAriaLabel(column.header),
|
|
1367
1444
|
"data-testid": `filter-${column.id}`,
|
|
1368
1445
|
children: [
|
|
1369
|
-
/* @__PURE__ */
|
|
1446
|
+
/* @__PURE__ */ jsx13(
|
|
1370
1447
|
FunnelIcon5,
|
|
1371
1448
|
{
|
|
1372
1449
|
className: cn("h-3.5 w-3.5 shrink-0", isFiltered ? "opacity-100 text-primary" : "opacity-40"),
|
|
1373
1450
|
"aria-hidden": true
|
|
1374
1451
|
}
|
|
1375
1452
|
),
|
|
1376
|
-
isFiltered && /* @__PURE__ */
|
|
1453
|
+
isFiltered && /* @__PURE__ */ jsx13("span", { className: "truncate", children: summary })
|
|
1377
1454
|
]
|
|
1378
1455
|
}
|
|
1379
1456
|
) }),
|
|
1380
|
-
/* @__PURE__ */
|
|
1457
|
+
/* @__PURE__ */ jsx13(PopoverContent, { className: "w-80", children: panel })
|
|
1381
1458
|
] });
|
|
1382
1459
|
}
|
|
1383
1460
|
|
|
@@ -1429,20 +1506,22 @@ function facetedNumberValues(data, column, filter) {
|
|
|
1429
1506
|
// src/filter/StringFilter.tsx
|
|
1430
1507
|
import { FunnelIcon as FunnelIcon6 } from "@heroicons/react/24/outline";
|
|
1431
1508
|
import { useEffect as useEffect5, useId as useId3, useState as useState5 } from "react";
|
|
1432
|
-
import { jsx as
|
|
1509
|
+
import { jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1433
1510
|
var STRING_OPERATORS = [
|
|
1434
|
-
{ value: "contains",
|
|
1435
|
-
{ value: "eq",
|
|
1436
|
-
{ value: "startsWith",
|
|
1437
|
-
{ value: "endsWith",
|
|
1511
|
+
{ value: "contains", labelKey: "stringContains" },
|
|
1512
|
+
{ value: "eq", labelKey: "stringIs" },
|
|
1513
|
+
{ value: "startsWith", labelKey: "stringStartsWith" },
|
|
1514
|
+
{ value: "endsWith", labelKey: "stringEndsWith" }
|
|
1438
1515
|
];
|
|
1439
1516
|
var DEFAULT_OPERATOR2 = "contains";
|
|
1440
1517
|
function StringFilter({
|
|
1441
1518
|
column,
|
|
1442
1519
|
value,
|
|
1443
1520
|
onChange,
|
|
1444
|
-
bare = false
|
|
1521
|
+
bare = false,
|
|
1522
|
+
labels: labelOverrides
|
|
1445
1523
|
}) {
|
|
1524
|
+
const labels = useFilterLabels(labelOverrides);
|
|
1446
1525
|
const [operator, setOperator] = useState5(value?.operator ?? DEFAULT_OPERATOR2);
|
|
1447
1526
|
const text = typeof value?.value === "string" ? value.value : "";
|
|
1448
1527
|
const inputId = useId3();
|
|
@@ -1469,66 +1548,66 @@ function StringFilter({
|
|
|
1469
1548
|
emit(nextOperator, text);
|
|
1470
1549
|
},
|
|
1471
1550
|
children: [
|
|
1472
|
-
/* @__PURE__ */
|
|
1473
|
-
/* @__PURE__ */
|
|
1551
|
+
/* @__PURE__ */ jsx14(SelectTrigger, { "aria-label": labels.operatorAriaLabel(column.header), children: /* @__PURE__ */ jsx14(SelectValue, {}) }),
|
|
1552
|
+
/* @__PURE__ */ jsx14(SelectContent, { children: STRING_OPERATORS.map((option) => /* @__PURE__ */ jsx14(SelectItem, { value: option.value, children: labels[option.labelKey] }, option.value)) })
|
|
1474
1553
|
]
|
|
1475
1554
|
}
|
|
1476
1555
|
),
|
|
1477
|
-
/* @__PURE__ */
|
|
1556
|
+
/* @__PURE__ */ jsx14(
|
|
1478
1557
|
Input,
|
|
1479
1558
|
{
|
|
1480
1559
|
id: inputId,
|
|
1481
1560
|
value: text,
|
|
1482
|
-
placeholder:
|
|
1561
|
+
placeholder: labels.stringPlaceholder(column.header),
|
|
1483
1562
|
onChange: (event) => emit(operator, event.target.value)
|
|
1484
1563
|
}
|
|
1485
1564
|
)
|
|
1486
1565
|
] });
|
|
1487
1566
|
if (bare) {
|
|
1488
|
-
return /* @__PURE__ */
|
|
1567
|
+
return /* @__PURE__ */ jsx14("div", { "data-testid": `filter-${column.id}`, children: panel });
|
|
1489
1568
|
}
|
|
1490
1569
|
return /* @__PURE__ */ jsxs8(Popover, { children: [
|
|
1491
|
-
/* @__PURE__ */
|
|
1570
|
+
/* @__PURE__ */ jsx14(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs8(
|
|
1492
1571
|
Button,
|
|
1493
1572
|
{
|
|
1494
1573
|
variant: "outline",
|
|
1495
1574
|
size: "sm",
|
|
1496
1575
|
className: cn("gap-1", isFiltered ? "max-w-[160px] px-2" : "w-8 justify-center px-0"),
|
|
1497
|
-
"aria-label":
|
|
1576
|
+
"aria-label": labels.filterAriaLabel(column.header),
|
|
1498
1577
|
"data-testid": `filter-${column.id}`,
|
|
1499
1578
|
children: [
|
|
1500
|
-
/* @__PURE__ */
|
|
1579
|
+
/* @__PURE__ */ jsx14(
|
|
1501
1580
|
FunnelIcon6,
|
|
1502
1581
|
{
|
|
1503
1582
|
className: cn("h-3.5 w-3.5 shrink-0", isFiltered ? "opacity-100 text-primary" : "opacity-40"),
|
|
1504
1583
|
"aria-hidden": true
|
|
1505
1584
|
}
|
|
1506
1585
|
),
|
|
1507
|
-
isFiltered && /* @__PURE__ */
|
|
1586
|
+
isFiltered && /* @__PURE__ */ jsx14("span", { className: "truncate", children: text })
|
|
1508
1587
|
]
|
|
1509
1588
|
}
|
|
1510
1589
|
) }),
|
|
1511
|
-
/* @__PURE__ */
|
|
1590
|
+
/* @__PURE__ */ jsx14(PopoverContent, { className: "w-auto p-3", children: panel })
|
|
1512
1591
|
] });
|
|
1513
1592
|
}
|
|
1514
1593
|
|
|
1515
1594
|
// src/filter/registry.tsx
|
|
1516
|
-
import { jsx as
|
|
1595
|
+
import { jsx as jsx15 } from "react/jsx-runtime";
|
|
1517
1596
|
function renderDefaultFilterWidget(column, value, onChange) {
|
|
1518
1597
|
const bare = column.filterDisplay !== "row";
|
|
1519
1598
|
switch (column.type) {
|
|
1520
1599
|
case "string":
|
|
1521
|
-
return /* @__PURE__ */
|
|
1600
|
+
return /* @__PURE__ */ jsx15(StringFilter, { column, value, onChange, bare });
|
|
1522
1601
|
case "enum":
|
|
1523
|
-
return /* @__PURE__ */
|
|
1602
|
+
return /* @__PURE__ */ jsx15(EnumFilter, { column, value, onChange, bare });
|
|
1524
1603
|
case "boolean":
|
|
1525
|
-
return /* @__PURE__ */
|
|
1604
|
+
return /* @__PURE__ */ jsx15(BooleanFilter, { column, value, onChange, bare });
|
|
1526
1605
|
case "number":
|
|
1527
1606
|
case "currency":
|
|
1528
|
-
return /* @__PURE__ */
|
|
1607
|
+
return /* @__PURE__ */ jsx15(NumberRangeFilter, { column, value, onChange, bare });
|
|
1529
1608
|
case "date":
|
|
1530
1609
|
case "datetime":
|
|
1531
|
-
return /* @__PURE__ */
|
|
1610
|
+
return /* @__PURE__ */ jsx15(DateRangeFilter, { column, value, onChange, bare });
|
|
1532
1611
|
}
|
|
1533
1612
|
}
|
|
1534
1613
|
|
|
@@ -1538,13 +1617,13 @@ function editErrorId(rowId, columnId) {
|
|
|
1538
1617
|
}
|
|
1539
1618
|
|
|
1540
1619
|
// src/edit/EditFieldError.tsx
|
|
1541
|
-
import { jsx as
|
|
1620
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
1542
1621
|
function EditFieldError({ id, message }) {
|
|
1543
|
-
return /* @__PURE__ */
|
|
1622
|
+
return /* @__PURE__ */ jsx16("span", { id, className: "mt-0.5 block text-xs text-destructive", children: message });
|
|
1544
1623
|
}
|
|
1545
1624
|
|
|
1546
1625
|
// src/edit/BooleanEditor.tsx
|
|
1547
|
-
import { jsx as
|
|
1626
|
+
import { jsx as jsx17, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1548
1627
|
function toBoolean(value) {
|
|
1549
1628
|
if (typeof value === "boolean") return value;
|
|
1550
1629
|
if (typeof value === "string") return value.trim().toLowerCase() === "true";
|
|
@@ -1565,7 +1644,7 @@ function BooleanEditor({
|
|
|
1565
1644
|
// `mt-0.5` already provides the same spacing every other editor gets;
|
|
1566
1645
|
// adding both would double it for this one editor only.
|
|
1567
1646
|
/* @__PURE__ */ jsxs9("div", { className: "flex flex-col items-center", children: [
|
|
1568
|
-
/* @__PURE__ */
|
|
1647
|
+
/* @__PURE__ */ jsx17(
|
|
1569
1648
|
Checkbox,
|
|
1570
1649
|
{
|
|
1571
1650
|
"aria-label": `Edit ${column.header}`,
|
|
@@ -1577,14 +1656,14 @@ function BooleanEditor({
|
|
|
1577
1656
|
onCheckedChange: (next) => onChange(next === true)
|
|
1578
1657
|
}
|
|
1579
1658
|
),
|
|
1580
|
-
error && /* @__PURE__ */
|
|
1659
|
+
error && /* @__PURE__ */ jsx17(EditFieldError, { id: errorId, message: error })
|
|
1581
1660
|
] })
|
|
1582
1661
|
);
|
|
1583
1662
|
}
|
|
1584
1663
|
|
|
1585
1664
|
// src/edit/DateEditor.tsx
|
|
1586
1665
|
import { format as formatDate, parseISO as parseISO4 } from "date-fns";
|
|
1587
|
-
import { jsx as
|
|
1666
|
+
import { jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1588
1667
|
function inputValueOf(value, columnType) {
|
|
1589
1668
|
const date = toDate(value);
|
|
1590
1669
|
if (!date) return "";
|
|
@@ -1600,7 +1679,7 @@ function DateEditor({
|
|
|
1600
1679
|
}) {
|
|
1601
1680
|
const errorId = editErrorId(rowId, column.id);
|
|
1602
1681
|
return /* @__PURE__ */ jsxs10("div", { children: [
|
|
1603
|
-
/* @__PURE__ */
|
|
1682
|
+
/* @__PURE__ */ jsx18(
|
|
1604
1683
|
Input,
|
|
1605
1684
|
{
|
|
1606
1685
|
type: column.type === "datetime" ? "datetime-local" : "date",
|
|
@@ -1615,12 +1694,12 @@ function DateEditor({
|
|
|
1615
1694
|
onChange: (event) => onChange(event.target.value === "" ? null : parseISO4(event.target.value))
|
|
1616
1695
|
}
|
|
1617
1696
|
),
|
|
1618
|
-
error && /* @__PURE__ */
|
|
1697
|
+
error && /* @__PURE__ */ jsx18(EditFieldError, { id: errorId, message: error })
|
|
1619
1698
|
] });
|
|
1620
1699
|
}
|
|
1621
1700
|
|
|
1622
1701
|
// src/edit/EnumEditor.tsx
|
|
1623
|
-
import { jsx as
|
|
1702
|
+
import { jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1624
1703
|
function EnumEditor({
|
|
1625
1704
|
column,
|
|
1626
1705
|
rowId,
|
|
@@ -1641,7 +1720,7 @@ function EnumEditor({
|
|
|
1641
1720
|
open,
|
|
1642
1721
|
onOpenChange,
|
|
1643
1722
|
children: [
|
|
1644
|
-
/* @__PURE__ */
|
|
1723
|
+
/* @__PURE__ */ jsx19(
|
|
1645
1724
|
SelectTrigger,
|
|
1646
1725
|
{
|
|
1647
1726
|
className: "h-8",
|
|
@@ -1650,14 +1729,14 @@ function EnumEditor({
|
|
|
1650
1729
|
"aria-describedby": error ? errorId : void 0,
|
|
1651
1730
|
"data-testid": `edit-${rowId}-${column.id}`,
|
|
1652
1731
|
autoFocus,
|
|
1653
|
-
children: /* @__PURE__ */
|
|
1732
|
+
children: /* @__PURE__ */ jsx19(SelectValue, {})
|
|
1654
1733
|
}
|
|
1655
1734
|
),
|
|
1656
|
-
/* @__PURE__ */
|
|
1735
|
+
/* @__PURE__ */ jsx19(SelectContent, { children: column.options.map((option) => /* @__PURE__ */ jsx19(SelectItem, { value: option.value, children: option.label }, option.value)) })
|
|
1657
1736
|
]
|
|
1658
1737
|
}
|
|
1659
1738
|
),
|
|
1660
|
-
error && /* @__PURE__ */
|
|
1739
|
+
error && /* @__PURE__ */ jsx19(EditFieldError, { id: errorId, message: error })
|
|
1661
1740
|
] });
|
|
1662
1741
|
}
|
|
1663
1742
|
|
|
@@ -1666,9 +1745,9 @@ import { useLayoutEffect, useRef as useRef5 } from "react";
|
|
|
1666
1745
|
|
|
1667
1746
|
// src/components/ui/textarea.tsx
|
|
1668
1747
|
import { forwardRef as forwardRef6 } from "react";
|
|
1669
|
-
import { jsx as
|
|
1748
|
+
import { jsx as jsx20 } from "react/jsx-runtime";
|
|
1670
1749
|
var Textarea = forwardRef6(({ className, ...props }, ref) => {
|
|
1671
|
-
return /* @__PURE__ */
|
|
1750
|
+
return /* @__PURE__ */ jsx20(
|
|
1672
1751
|
"textarea",
|
|
1673
1752
|
{
|
|
1674
1753
|
className: cn(
|
|
@@ -1683,7 +1762,7 @@ var Textarea = forwardRef6(({ className, ...props }, ref) => {
|
|
|
1683
1762
|
Textarea.displayName = "Textarea";
|
|
1684
1763
|
|
|
1685
1764
|
// src/edit/MultilineStringEditor.tsx
|
|
1686
|
-
import { jsx as
|
|
1765
|
+
import { jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1687
1766
|
function MultilineStringEditor({
|
|
1688
1767
|
column,
|
|
1689
1768
|
rowId,
|
|
@@ -1707,7 +1786,7 @@ function MultilineStringEditor({
|
|
|
1707
1786
|
}
|
|
1708
1787
|
}, [text]);
|
|
1709
1788
|
return /* @__PURE__ */ jsxs12("div", { children: [
|
|
1710
|
-
/* @__PURE__ */
|
|
1789
|
+
/* @__PURE__ */ jsx21(
|
|
1711
1790
|
Textarea,
|
|
1712
1791
|
{
|
|
1713
1792
|
ref: textareaRef,
|
|
@@ -1724,13 +1803,13 @@ function MultilineStringEditor({
|
|
|
1724
1803
|
}
|
|
1725
1804
|
}
|
|
1726
1805
|
),
|
|
1727
|
-
error && /* @__PURE__ */
|
|
1806
|
+
error && /* @__PURE__ */ jsx21(EditFieldError, { id: errorId, message: error })
|
|
1728
1807
|
] });
|
|
1729
1808
|
}
|
|
1730
1809
|
|
|
1731
1810
|
// src/edit/NumberEditor.tsx
|
|
1732
1811
|
import { useEffect as useEffect6, useRef as useRef6, useState as useState6 } from "react";
|
|
1733
|
-
import { jsx as
|
|
1812
|
+
import { jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1734
1813
|
function textFromValue(value) {
|
|
1735
1814
|
return value === null || value === void 0 ? "" : String(value);
|
|
1736
1815
|
}
|
|
@@ -1751,7 +1830,7 @@ function NumberEditor({
|
|
|
1751
1830
|
setText(textFromValue(value));
|
|
1752
1831
|
}, [value]);
|
|
1753
1832
|
return /* @__PURE__ */ jsxs13("div", { children: [
|
|
1754
|
-
/* @__PURE__ */
|
|
1833
|
+
/* @__PURE__ */ jsx22(
|
|
1755
1834
|
Input,
|
|
1756
1835
|
{
|
|
1757
1836
|
type: "number",
|
|
@@ -1770,12 +1849,12 @@ function NumberEditor({
|
|
|
1770
1849
|
}
|
|
1771
1850
|
}
|
|
1772
1851
|
),
|
|
1773
|
-
error && /* @__PURE__ */
|
|
1852
|
+
error && /* @__PURE__ */ jsx22(EditFieldError, { id: errorId, message: error })
|
|
1774
1853
|
] });
|
|
1775
1854
|
}
|
|
1776
1855
|
|
|
1777
1856
|
// src/edit/StringEditor.tsx
|
|
1778
|
-
import { jsx as
|
|
1857
|
+
import { jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1779
1858
|
function StringEditor({
|
|
1780
1859
|
column,
|
|
1781
1860
|
rowId,
|
|
@@ -1786,7 +1865,7 @@ function StringEditor({
|
|
|
1786
1865
|
}) {
|
|
1787
1866
|
const errorId = editErrorId(rowId, column.id);
|
|
1788
1867
|
return /* @__PURE__ */ jsxs14("div", { children: [
|
|
1789
|
-
/* @__PURE__ */
|
|
1868
|
+
/* @__PURE__ */ jsx23(
|
|
1790
1869
|
Input,
|
|
1791
1870
|
{
|
|
1792
1871
|
className: "h-8",
|
|
@@ -1799,26 +1878,26 @@ function StringEditor({
|
|
|
1799
1878
|
onChange: (event) => onChange(event.target.value)
|
|
1800
1879
|
}
|
|
1801
1880
|
),
|
|
1802
|
-
error && /* @__PURE__ */
|
|
1881
|
+
error && /* @__PURE__ */ jsx23(EditFieldError, { id: errorId, message: error })
|
|
1803
1882
|
] });
|
|
1804
1883
|
}
|
|
1805
1884
|
|
|
1806
1885
|
// src/edit/registry.tsx
|
|
1807
|
-
import { jsx as
|
|
1886
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
1808
1887
|
function renderDefaultEditWidget(column, rowId, value, onChange, error, autoFocus) {
|
|
1809
1888
|
switch (column.type) {
|
|
1810
1889
|
case "string":
|
|
1811
|
-
return column.multiline ? /* @__PURE__ */
|
|
1890
|
+
return column.multiline ? /* @__PURE__ */ jsx24(MultilineStringEditor, { column, rowId, value, onChange, error, autoFocus }) : /* @__PURE__ */ jsx24(StringEditor, { column, rowId, value, onChange, error, autoFocus });
|
|
1812
1891
|
case "enum":
|
|
1813
|
-
return /* @__PURE__ */
|
|
1892
|
+
return /* @__PURE__ */ jsx24(EnumEditor, { column, rowId, value, onChange, error, autoFocus });
|
|
1814
1893
|
case "boolean":
|
|
1815
|
-
return /* @__PURE__ */
|
|
1894
|
+
return /* @__PURE__ */ jsx24(BooleanEditor, { column, rowId, value, onChange, error, autoFocus });
|
|
1816
1895
|
case "number":
|
|
1817
1896
|
case "currency":
|
|
1818
|
-
return /* @__PURE__ */
|
|
1897
|
+
return /* @__PURE__ */ jsx24(NumberEditor, { column, rowId, value, onChange, error, autoFocus });
|
|
1819
1898
|
case "date":
|
|
1820
1899
|
case "datetime":
|
|
1821
|
-
return /* @__PURE__ */
|
|
1900
|
+
return /* @__PURE__ */ jsx24(DateEditor, { column, rowId, value, onChange, error, autoFocus });
|
|
1822
1901
|
}
|
|
1823
1902
|
}
|
|
1824
1903
|
|
|
@@ -1931,7 +2010,7 @@ function useEditingState(editing, getRowId) {
|
|
|
1931
2010
|
}
|
|
1932
2011
|
|
|
1933
2012
|
// src/edit/renderEditableCell.tsx
|
|
1934
|
-
import { jsx as
|
|
2013
|
+
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
1935
2014
|
function renderEditableCell(column, row, rawValue, ctx) {
|
|
1936
2015
|
const staticContent = (value2) => column.cell ? column.cell(value2, row) : defaultFormat(column, value2);
|
|
1937
2016
|
if (!ctx || !isEditable(column, row)) return staticContent(rawValue);
|
|
@@ -1943,7 +2022,7 @@ function renderEditableCell(column, row, rawValue, ctx) {
|
|
|
1943
2022
|
const autoFocus = ctx.autoFocusTarget?.rowId === rowId && ctx.autoFocusTarget.columnId === column.id;
|
|
1944
2023
|
const onChange = (next) => ctx.onEdit(column, row, next);
|
|
1945
2024
|
const editor = column.renderEditCell ? column.renderEditCell(value, row, onChange, error, autoFocus) : renderDefaultEditWidget(column, rowId, value, onChange, error, autoFocus);
|
|
1946
|
-
return /* @__PURE__ */
|
|
2025
|
+
return /* @__PURE__ */ jsx25(
|
|
1947
2026
|
"div",
|
|
1948
2027
|
{
|
|
1949
2028
|
onKeyDown: (event) => {
|
|
@@ -1956,7 +2035,7 @@ function renderEditableCell(column, row, rawValue, ctx) {
|
|
|
1956
2035
|
}
|
|
1957
2036
|
);
|
|
1958
2037
|
}
|
|
1959
|
-
return /* @__PURE__ */
|
|
2038
|
+
return /* @__PURE__ */ jsx25(
|
|
1960
2039
|
"span",
|
|
1961
2040
|
{
|
|
1962
2041
|
role: "button",
|
|
@@ -1979,7 +2058,7 @@ function renderEditableCell(column, row, rawValue, ctx) {
|
|
|
1979
2058
|
}
|
|
1980
2059
|
|
|
1981
2060
|
// src/edit/EditingBar.tsx
|
|
1982
|
-
import { jsx as
|
|
2061
|
+
import { jsx as jsx26, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1983
2062
|
function resolveEditLabel(label, changedRowCount, fallback) {
|
|
1984
2063
|
if (label === void 0) return fallback(changedRowCount);
|
|
1985
2064
|
return typeof label === "function" ? label(changedRowCount) : label;
|
|
@@ -2017,7 +2096,7 @@ function EditingBar({
|
|
|
2017
2096
|
] })
|
|
2018
2097
|
] }),
|
|
2019
2098
|
/* @__PURE__ */ jsxs15("div", { className: "flex gap-2", children: [
|
|
2020
|
-
/* @__PURE__ */
|
|
2099
|
+
/* @__PURE__ */ jsx26(
|
|
2021
2100
|
Button,
|
|
2022
2101
|
{
|
|
2023
2102
|
type: "button",
|
|
@@ -2029,7 +2108,7 @@ function EditingBar({
|
|
|
2029
2108
|
children: resolveEditLabel(editing.discardLabel, pendingRowCount, () => "Discard")
|
|
2030
2109
|
}
|
|
2031
2110
|
),
|
|
2032
|
-
/* @__PURE__ */
|
|
2111
|
+
/* @__PURE__ */ jsx26(
|
|
2033
2112
|
Button,
|
|
2034
2113
|
{
|
|
2035
2114
|
type: "button",
|
|
@@ -2131,15 +2210,15 @@ function extendRangeForFillToCellRange(base, target, rowIds, columnIds, rowIndex
|
|
|
2131
2210
|
}
|
|
2132
2211
|
|
|
2133
2212
|
// src/cell-editing/useCellSelection.ts
|
|
2134
|
-
import { useCallback as useCallback2, useMemo as
|
|
2213
|
+
import { useCallback as useCallback2, useMemo as useMemo4, useRef as useRef8, useState as useState8 } from "react";
|
|
2135
2214
|
function useCellSelection({ rowIds, columnIds, onNavigateToRow }) {
|
|
2136
2215
|
const [selection, setSelectionState] = useState8(void 0);
|
|
2137
2216
|
const [isDragging, setIsDragging] = useState8(false);
|
|
2138
2217
|
const [dragFocus, setDragFocus] = useState8(void 0);
|
|
2139
2218
|
const draggingRef = useRef8(false);
|
|
2140
2219
|
const dragFocusRef = useRef8(void 0);
|
|
2141
|
-
const rowIndex =
|
|
2142
|
-
const columnIndex =
|
|
2220
|
+
const rowIndex = useMemo4(() => buildIndexMap(rowIds), [rowIds]);
|
|
2221
|
+
const columnIndex = useMemo4(() => buildIndexMap(columnIds), [columnIds]);
|
|
2143
2222
|
const startSelection = useCallback2((cell, options) => {
|
|
2144
2223
|
setSelectionState((prev) => options?.extend && prev ? { anchor: prev.anchor, focus: cell } : { anchor: cell, focus: cell });
|
|
2145
2224
|
draggingRef.current = true;
|
|
@@ -2193,7 +2272,7 @@ function useCellSelection({ rowIds, columnIds, onNavigateToRow }) {
|
|
|
2193
2272
|
setDragFocus(void 0);
|
|
2194
2273
|
setSelectionState(void 0);
|
|
2195
2274
|
}, []);
|
|
2196
|
-
const effectiveRange =
|
|
2275
|
+
const effectiveRange = useMemo4(() => {
|
|
2197
2276
|
if (!selection) return void 0;
|
|
2198
2277
|
if (isDragging && dragFocus) return { anchor: selection.anchor, focus: dragFocus };
|
|
2199
2278
|
return selection;
|
|
@@ -2229,7 +2308,7 @@ function useCellSelection({ rowIds, columnIds, onNavigateToRow }) {
|
|
|
2229
2308
|
setSelectionState(finalRange);
|
|
2230
2309
|
return { sourceRange, finalRange };
|
|
2231
2310
|
}, [rowIds, columnIds, rowIndex, columnIndex]);
|
|
2232
|
-
const fillPreviewRange =
|
|
2311
|
+
const fillPreviewRange = useMemo4(() => {
|
|
2233
2312
|
if (!isFillDragging || !selection || !fillTarget) return void 0;
|
|
2234
2313
|
return extendRangeForFillToCellRange(selection, fillTarget, rowIds, columnIds, rowIndex, columnIndex);
|
|
2235
2314
|
}, [isFillDragging, selection, fillTarget, rowIds, columnIds, rowIndex, columnIndex]);
|
|
@@ -2367,7 +2446,7 @@ function useCellEditingState(cellEditing, getRowId) {
|
|
|
2367
2446
|
}
|
|
2368
2447
|
|
|
2369
2448
|
// src/cell-editing/renderCellModeCell.tsx
|
|
2370
|
-
import { jsx as
|
|
2449
|
+
import { jsx as jsx27 } from "react/jsx-runtime";
|
|
2371
2450
|
function isAtomicEditorType(type) {
|
|
2372
2451
|
return type === "enum" || type === "boolean" || type === "date" || type === "datetime";
|
|
2373
2452
|
}
|
|
@@ -2378,7 +2457,7 @@ function renderCellModeCell(column, row, rawValue, ctx) {
|
|
|
2378
2457
|
const value = ctx.resolveValue(rowId, column.id, rawValue);
|
|
2379
2458
|
const isThisCellEditing = ctx.editingCell?.rowId === rowId && ctx.editingCell.columnId === column.id && isEditable(column, row);
|
|
2380
2459
|
if (!isThisCellEditing) {
|
|
2381
|
-
return /* @__PURE__ */
|
|
2460
|
+
return /* @__PURE__ */ jsx27("span", { "data-testid": `cell-${rowId}-${column.id}`, className: "block w-full", children: staticContent(value) });
|
|
2382
2461
|
}
|
|
2383
2462
|
const isAtomic = isAtomicEditorType(column.type);
|
|
2384
2463
|
const error = ctx.getError(rowId, column.id);
|
|
@@ -2418,12 +2497,12 @@ function renderCellModeCell(column, row, rawValue, ctx) {
|
|
|
2418
2497
|
if (validate(currentValue)) ctx.onCancelEdit();
|
|
2419
2498
|
else ctx.onCommitEdit(row, value);
|
|
2420
2499
|
}
|
|
2421
|
-
return /* @__PURE__ */
|
|
2500
|
+
return /* @__PURE__ */ jsx27("div", { onKeyDown: handleKeyDown, onBlur: handleBlur, children: editor });
|
|
2422
2501
|
}
|
|
2423
2502
|
|
|
2424
2503
|
// src/cell-editing/SelectionOverlay.tsx
|
|
2425
2504
|
import { useLayoutEffect as useLayoutEffect2, useRef as useRef10, useState as useState10 } from "react";
|
|
2426
|
-
import { Fragment as Fragment2, jsx as
|
|
2505
|
+
import { Fragment as Fragment2, jsx as jsx28, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
2427
2506
|
function cellSelector(rowId, columnId) {
|
|
2428
2507
|
const escape = (value) => typeof CSS !== "undefined" && CSS.escape ? CSS.escape(value) : value.replace(/["\\]/g, "\\$&");
|
|
2429
2508
|
return `[data-cell-row="${escape(rowId)}"][data-cell-col="${escape(columnId)}"]`;
|
|
@@ -2478,7 +2557,7 @@ function SelectionOverlay({
|
|
|
2478
2557
|
}, [containerRef.current]);
|
|
2479
2558
|
if (!rect) return null;
|
|
2480
2559
|
return /* @__PURE__ */ jsxs16(Fragment2, { children: [
|
|
2481
|
-
/* @__PURE__ */
|
|
2560
|
+
/* @__PURE__ */ jsx28(
|
|
2482
2561
|
"div",
|
|
2483
2562
|
{
|
|
2484
2563
|
"data-testid": "cell-selection-overlay",
|
|
@@ -2487,7 +2566,7 @@ function SelectionOverlay({
|
|
|
2487
2566
|
style: { top: rect.top, left: rect.left, width: rect.width, height: rect.height }
|
|
2488
2567
|
}
|
|
2489
2568
|
),
|
|
2490
|
-
previewRect && /* @__PURE__ */
|
|
2569
|
+
previewRect && /* @__PURE__ */ jsx28(
|
|
2491
2570
|
"div",
|
|
2492
2571
|
{
|
|
2493
2572
|
"data-testid": "cell-fill-preview-overlay",
|
|
@@ -2496,7 +2575,7 @@ function SelectionOverlay({
|
|
|
2496
2575
|
style: { top: previewRect.top, left: previewRect.left, width: previewRect.width, height: previewRect.height }
|
|
2497
2576
|
}
|
|
2498
2577
|
),
|
|
2499
|
-
onFillHandleMouseDown && /* @__PURE__ */
|
|
2578
|
+
onFillHandleMouseDown && /* @__PURE__ */ jsx28(
|
|
2500
2579
|
"div",
|
|
2501
2580
|
{
|
|
2502
2581
|
"data-testid": "cell-fill-handle",
|
|
@@ -2708,10 +2787,10 @@ import { useEffect as useEffect8, useState as useState11 } from "react";
|
|
|
2708
2787
|
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
2709
2788
|
import { X } from "lucide-react";
|
|
2710
2789
|
import { forwardRef as forwardRef7 } from "react";
|
|
2711
|
-
import { jsx as
|
|
2790
|
+
import { jsx as jsx29, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
2712
2791
|
var Dialog = DialogPrimitive.Root;
|
|
2713
2792
|
var DialogTrigger = DialogPrimitive.Trigger;
|
|
2714
|
-
var DialogOverlay = forwardRef7(({ className, ...props }, ref) => /* @__PURE__ */
|
|
2793
|
+
var DialogOverlay = forwardRef7(({ className, ...props }, ref) => /* @__PURE__ */ jsx29(
|
|
2715
2794
|
DialogPrimitive.Overlay,
|
|
2716
2795
|
{
|
|
2717
2796
|
ref,
|
|
@@ -2721,7 +2800,7 @@ var DialogOverlay = forwardRef7(({ className, ...props }, ref) => /* @__PURE__ *
|
|
|
2721
2800
|
));
|
|
2722
2801
|
DialogOverlay.displayName = "DialogOverlay";
|
|
2723
2802
|
var DialogContent = forwardRef7(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs17(DialogPrimitive.Portal, { children: [
|
|
2724
|
-
/* @__PURE__ */
|
|
2803
|
+
/* @__PURE__ */ jsx29(DialogOverlay, {}),
|
|
2725
2804
|
/* @__PURE__ */ jsxs17(
|
|
2726
2805
|
DialogPrimitive.Content,
|
|
2727
2806
|
{
|
|
@@ -2734,8 +2813,8 @@ var DialogContent = forwardRef7(({ className, children, ...props }, ref) => /* @
|
|
|
2734
2813
|
children: [
|
|
2735
2814
|
children,
|
|
2736
2815
|
/* @__PURE__ */ jsxs17(DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 hover:opacity-100", children: [
|
|
2737
|
-
/* @__PURE__ */
|
|
2738
|
-
/* @__PURE__ */
|
|
2816
|
+
/* @__PURE__ */ jsx29(X, { className: "h-4 w-4" }),
|
|
2817
|
+
/* @__PURE__ */ jsx29("span", { className: "sr-only", children: "Close" })
|
|
2739
2818
|
] })
|
|
2740
2819
|
]
|
|
2741
2820
|
}
|
|
@@ -2745,10 +2824,10 @@ DialogContent.displayName = "DialogContent";
|
|
|
2745
2824
|
var DialogHeader = ({
|
|
2746
2825
|
className,
|
|
2747
2826
|
...props
|
|
2748
|
-
}) => /* @__PURE__ */
|
|
2749
|
-
var DialogTitle = forwardRef7(({ className, ...props }, ref) => /* @__PURE__ */
|
|
2827
|
+
}) => /* @__PURE__ */ jsx29("div", { className: cn("flex flex-col gap-1.5", className), ...props });
|
|
2828
|
+
var DialogTitle = forwardRef7(({ className, ...props }, ref) => /* @__PURE__ */ jsx29(DialogPrimitive.Title, { ref, className: cn("text-lg font-semibold", className), ...props }));
|
|
2750
2829
|
DialogTitle.displayName = "DialogTitle";
|
|
2751
|
-
var DialogDescription = forwardRef7(({ className, ...props }, ref) => /* @__PURE__ */
|
|
2830
|
+
var DialogDescription = forwardRef7(({ className, ...props }, ref) => /* @__PURE__ */ jsx29(
|
|
2752
2831
|
DialogPrimitive.Description,
|
|
2753
2832
|
{
|
|
2754
2833
|
ref,
|
|
@@ -2857,7 +2936,7 @@ function canHideGroup(columns, visibility, groupColumnIds) {
|
|
|
2857
2936
|
}
|
|
2858
2937
|
|
|
2859
2938
|
// src/column-selector/ColumnSelector.tsx
|
|
2860
|
-
import { jsx as
|
|
2939
|
+
import { jsx as jsx30, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
2861
2940
|
function ColumnSelector({
|
|
2862
2941
|
columns,
|
|
2863
2942
|
visibility,
|
|
@@ -2903,11 +2982,11 @@ function ColumnSelector({
|
|
|
2903
2982
|
if (persistKey) writePersistedColumnOrder(persistKey, next);
|
|
2904
2983
|
}
|
|
2905
2984
|
return /* @__PURE__ */ jsxs18(Dialog, { open, onOpenChange, children: [
|
|
2906
|
-
/* @__PURE__ */
|
|
2985
|
+
/* @__PURE__ */ jsx30(DialogTrigger, { asChild: true, children: trigger ?? /* @__PURE__ */ jsx30(Button, { variant: "outline", size: "icon", "aria-label": "Choose columns", children: /* @__PURE__ */ jsx30(Columns3, { className: "h-4 w-4", "aria-hidden": true }) }) }),
|
|
2907
2986
|
/* @__PURE__ */ jsxs18(DialogContent, { className: "w-fit max-w-[calc(100vw-2rem)] sm:max-w-2xl", children: [
|
|
2908
|
-
/* @__PURE__ */
|
|
2909
|
-
/* @__PURE__ */
|
|
2910
|
-
group && /* @__PURE__ */
|
|
2987
|
+
/* @__PURE__ */ jsx30(DialogHeader, { children: /* @__PURE__ */ jsx30(DialogTitle, { children: "Columns" }) }),
|
|
2988
|
+
/* @__PURE__ */ jsx30("div", { className: "flex flex-wrap gap-x-8 gap-y-5", children: groups.map(({ group, columns: groupCols }) => /* @__PURE__ */ jsxs18("div", { className: "flex min-w-32 flex-col gap-1.5", children: [
|
|
2989
|
+
group && /* @__PURE__ */ jsx30("span", { className: "border-b pb-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground", children: group }),
|
|
2911
2990
|
groupCols.map((column) => {
|
|
2912
2991
|
const visible = isColumnVisible(visibility, column.id);
|
|
2913
2992
|
return /* @__PURE__ */ jsxs18(
|
|
@@ -2937,14 +3016,14 @@ function ColumnSelector({
|
|
|
2937
3016
|
overId === column.id && draggedId !== null && draggedId !== column.id && "outline -outline-offset-2 outline-2 outline-primary"
|
|
2938
3017
|
),
|
|
2939
3018
|
children: [
|
|
2940
|
-
canReorder && /* @__PURE__ */
|
|
3019
|
+
canReorder && /* @__PURE__ */ jsx30(
|
|
2941
3020
|
GripVertical,
|
|
2942
3021
|
{
|
|
2943
3022
|
className: "h-3.5 w-3.5 shrink-0 text-muted-foreground/50",
|
|
2944
3023
|
"aria-hidden": true
|
|
2945
3024
|
}
|
|
2946
3025
|
),
|
|
2947
|
-
/* @__PURE__ */
|
|
3026
|
+
/* @__PURE__ */ jsx30(
|
|
2948
3027
|
Checkbox,
|
|
2949
3028
|
{
|
|
2950
3029
|
checked: visible,
|
|
@@ -2976,15 +3055,15 @@ function resolveMenuItems(items, ctx) {
|
|
|
2976
3055
|
|
|
2977
3056
|
// src/menu/ActionsMenu.tsx
|
|
2978
3057
|
import { MoreVertical } from "lucide-react";
|
|
2979
|
-
import { useMemo as
|
|
3058
|
+
import { useMemo as useMemo5 } from "react";
|
|
2980
3059
|
|
|
2981
3060
|
// src/components/ui/dropdown-menu.tsx
|
|
2982
3061
|
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
2983
3062
|
import { forwardRef as forwardRef8 } from "react";
|
|
2984
|
-
import { jsx as
|
|
3063
|
+
import { jsx as jsx31 } from "react/jsx-runtime";
|
|
2985
3064
|
var DropdownMenu = DropdownMenuPrimitive.Root;
|
|
2986
3065
|
var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
|
2987
|
-
var DropdownMenuContent = forwardRef8(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */
|
|
3066
|
+
var DropdownMenuContent = forwardRef8(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx31(DropdownMenuPrimitive.Portal, { children: /* @__PURE__ */ jsx31(
|
|
2988
3067
|
DropdownMenuPrimitive.Content,
|
|
2989
3068
|
{
|
|
2990
3069
|
ref,
|
|
@@ -2997,7 +3076,7 @@ var DropdownMenuContent = forwardRef8(({ className, sideOffset = 4, ...props },
|
|
|
2997
3076
|
}
|
|
2998
3077
|
) }));
|
|
2999
3078
|
DropdownMenuContent.displayName = "DropdownMenuContent";
|
|
3000
|
-
var DropdownMenuItem = forwardRef8(({ className, danger, ...props }, ref) => /* @__PURE__ */
|
|
3079
|
+
var DropdownMenuItem = forwardRef8(({ className, danger, ...props }, ref) => /* @__PURE__ */ jsx31(
|
|
3001
3080
|
DropdownMenuPrimitive.Item,
|
|
3002
3081
|
{
|
|
3003
3082
|
ref,
|
|
@@ -3010,7 +3089,7 @@ var DropdownMenuItem = forwardRef8(({ className, danger, ...props }, ref) => /*
|
|
|
3010
3089
|
}
|
|
3011
3090
|
));
|
|
3012
3091
|
DropdownMenuItem.displayName = "DropdownMenuItem";
|
|
3013
|
-
var DropdownMenuSeparator = forwardRef8(({ className, ...props }, ref) => /* @__PURE__ */
|
|
3092
|
+
var DropdownMenuSeparator = forwardRef8(({ className, ...props }, ref) => /* @__PURE__ */ jsx31(
|
|
3014
3093
|
DropdownMenuPrimitive.Separator,
|
|
3015
3094
|
{
|
|
3016
3095
|
ref,
|
|
@@ -3019,7 +3098,7 @@ var DropdownMenuSeparator = forwardRef8(({ className, ...props }, ref) => /* @__
|
|
|
3019
3098
|
}
|
|
3020
3099
|
));
|
|
3021
3100
|
DropdownMenuSeparator.displayName = "DropdownMenuSeparator";
|
|
3022
|
-
var DropdownMenuLabel = forwardRef8(({ className, ...props }, ref) => /* @__PURE__ */
|
|
3101
|
+
var DropdownMenuLabel = forwardRef8(({ className, ...props }, ref) => /* @__PURE__ */ jsx31(
|
|
3023
3102
|
DropdownMenuPrimitive.Label,
|
|
3024
3103
|
{
|
|
3025
3104
|
ref,
|
|
@@ -3030,16 +3109,16 @@ var DropdownMenuLabel = forwardRef8(({ className, ...props }, ref) => /* @__PURE
|
|
|
3030
3109
|
DropdownMenuLabel.displayName = "DropdownMenuLabel";
|
|
3031
3110
|
|
|
3032
3111
|
// src/menu/ActionsMenu.tsx
|
|
3033
|
-
import { jsx as
|
|
3112
|
+
import { jsx as jsx32, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
3034
3113
|
function ActionsMenu({ items, ctx, triggerLabel }) {
|
|
3035
|
-
const resolved =
|
|
3114
|
+
const resolved = useMemo5(
|
|
3036
3115
|
() => resolveMenuItems(items, ctx),
|
|
3037
3116
|
[items, ctx.row, ctx.selectedRows]
|
|
3038
3117
|
);
|
|
3039
3118
|
if (resolved.length === 0) return null;
|
|
3040
3119
|
return /* @__PURE__ */ jsxs19(DropdownMenu, { children: [
|
|
3041
|
-
/* @__PURE__ */
|
|
3042
|
-
/* @__PURE__ */
|
|
3120
|
+
/* @__PURE__ */ jsx32(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsx32(Button, { variant: "ghost", size: "icon", "aria-label": triggerLabel, onClick: stopRowClick, children: /* @__PURE__ */ jsx32(MoreVertical, { className: "h-4 w-4", "aria-hidden": true }) }) }),
|
|
3121
|
+
/* @__PURE__ */ jsx32(DropdownMenuContent, { align: "end", children: resolved.map((item) => /* @__PURE__ */ jsx32(
|
|
3043
3122
|
DropdownMenuItem,
|
|
3044
3123
|
{
|
|
3045
3124
|
danger: item.danger,
|
|
@@ -3057,14 +3136,14 @@ import { BarsArrowDownIcon, BarsArrowUpIcon, FunnelIcon as FunnelIcon7 } from "@
|
|
|
3057
3136
|
import { columnResizingFeature, columnSizingFeature, flexRender, tableFeatures, useTable } from "@tanstack/react-table";
|
|
3058
3137
|
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
3059
3138
|
import { ChevronRight, Loader2 } from "lucide-react";
|
|
3060
|
-
import { Fragment as Fragment3, useEffect as useEffect12, useMemo as
|
|
3139
|
+
import { Fragment as Fragment3, useEffect as useEffect12, useMemo as useMemo9, useRef as useRef13, useState as useState16 } from "react";
|
|
3061
3140
|
|
|
3062
3141
|
// src/cell-editing/renderAlwaysEditCell.tsx
|
|
3063
3142
|
import {
|
|
3064
3143
|
useEffect as useEffect9,
|
|
3065
3144
|
useState as useState12
|
|
3066
3145
|
} from "react";
|
|
3067
|
-
import { jsx as
|
|
3146
|
+
import { jsx as jsx33 } from "react/jsx-runtime";
|
|
3068
3147
|
function AlwaysEditCell(props) {
|
|
3069
3148
|
const { column, row, rawValue, ctx, atomicGesture } = props;
|
|
3070
3149
|
const rowId = ctx.getRowId(row);
|
|
@@ -3077,7 +3156,7 @@ function AlwaysEditCell(props) {
|
|
|
3077
3156
|
if (shouldOpenEnumNow) setEnumOpen(true);
|
|
3078
3157
|
}, [shouldOpenEnumNow]);
|
|
3079
3158
|
if (!isEditable(column, row)) {
|
|
3080
|
-
return /* @__PURE__ */
|
|
3159
|
+
return /* @__PURE__ */ jsx33("span", { "data-testid": `cell-${rowId}-${column.id}`, className: "block w-full", children: column.cell ? column.cell(resolvedValue, row) : defaultFormat(column, resolvedValue) });
|
|
3081
3160
|
}
|
|
3082
3161
|
const isAtomic = isAtomicEditorType(column.type);
|
|
3083
3162
|
const error = ctx.getError(rowId, column.id);
|
|
@@ -3144,7 +3223,7 @@ function AlwaysEditCell(props) {
|
|
|
3144
3223
|
handleModifierCapture(event);
|
|
3145
3224
|
handleEnumOpenCapture(event);
|
|
3146
3225
|
}
|
|
3147
|
-
return /* @__PURE__ */
|
|
3226
|
+
return /* @__PURE__ */ jsx33(
|
|
3148
3227
|
"fieldset",
|
|
3149
3228
|
{
|
|
3150
3229
|
disabled: ctx.disabled,
|
|
@@ -3153,7 +3232,7 @@ function AlwaysEditCell(props) {
|
|
|
3153
3232
|
onPointerDownCapture: handlePointerDownCapture,
|
|
3154
3233
|
onClickCapture: handleClickCapture,
|
|
3155
3234
|
className: "contents",
|
|
3156
|
-
children: column.type === "enum" && !column.renderEditCell ? /* @__PURE__ */
|
|
3235
|
+
children: column.type === "enum" && !column.renderEditCell ? /* @__PURE__ */ jsx33(
|
|
3157
3236
|
EnumEditor,
|
|
3158
3237
|
{
|
|
3159
3238
|
column,
|
|
@@ -3214,9 +3293,9 @@ function useStickyGroupHeaderTop(enabled) {
|
|
|
3214
3293
|
}
|
|
3215
3294
|
|
|
3216
3295
|
// src/hooks/useVisibleColumns.ts
|
|
3217
|
-
import { useMemo as
|
|
3296
|
+
import { useMemo as useMemo6 } from "react";
|
|
3218
3297
|
function useVisibleColumns(columns, columnVisibility) {
|
|
3219
|
-
return
|
|
3298
|
+
return useMemo6(
|
|
3220
3299
|
() => columnVisibility ? columns.filter((column) => isColumnVisible(columnVisibility, column.id)) : columns,
|
|
3221
3300
|
[columns, columnVisibility]
|
|
3222
3301
|
);
|
|
@@ -3263,10 +3342,10 @@ function processClientData(data, state) {
|
|
|
3263
3342
|
}
|
|
3264
3343
|
|
|
3265
3344
|
// src/grid/useGridState.ts
|
|
3266
|
-
import { useCallback as useCallback4, useEffect as useEffect11, useMemo as
|
|
3345
|
+
import { useCallback as useCallback4, useEffect as useEffect11, useMemo as useMemo8, useState as useState15 } from "react";
|
|
3267
3346
|
|
|
3268
3347
|
// src/hooks/useDebouncedCallback.ts
|
|
3269
|
-
import { useEffect as useEffect10, useMemo as
|
|
3348
|
+
import { useEffect as useEffect10, useMemo as useMemo7, useRef as useRef12 } from "react";
|
|
3270
3349
|
function useDebouncedCallback(callback, delayMs) {
|
|
3271
3350
|
const callbackRef = useRef12(callback);
|
|
3272
3351
|
callbackRef.current = callback;
|
|
@@ -3276,7 +3355,7 @@ function useDebouncedCallback(callback, delayMs) {
|
|
|
3276
3355
|
clearTimeout(timeoutRef.current);
|
|
3277
3356
|
};
|
|
3278
3357
|
}, []);
|
|
3279
|
-
return
|
|
3358
|
+
return useMemo7(() => {
|
|
3280
3359
|
return {
|
|
3281
3360
|
run: (...args) => {
|
|
3282
3361
|
clearTimeout(timeoutRef.current);
|
|
@@ -3329,7 +3408,7 @@ function useGridState(dataSource, initialState, externalState, showPagination =
|
|
|
3329
3408
|
cancelDebouncedNotify();
|
|
3330
3409
|
setState(externalState);
|
|
3331
3410
|
}, [externalState, cancelDebouncedNotify]);
|
|
3332
|
-
const filtersByColumn =
|
|
3411
|
+
const filtersByColumn = useMemo8(() => {
|
|
3333
3412
|
const map = /* @__PURE__ */ new Map();
|
|
3334
3413
|
for (const child of state.filter?.filters ?? []) {
|
|
3335
3414
|
if ("operator" in child) map.set(fieldKey(child.field), child);
|
|
@@ -3393,7 +3472,7 @@ function useGridState(dataSource, initialState, externalState, showPagination =
|
|
|
3393
3472
|
}
|
|
3394
3473
|
|
|
3395
3474
|
// src/grid/DataGrid.tsx
|
|
3396
|
-
import { Fragment as Fragment4, jsx as
|
|
3475
|
+
import { Fragment as Fragment4, jsx as jsx34, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
3397
3476
|
var gridTableFeatures = tableFeatures({ columnSizingFeature, columnResizingFeature });
|
|
3398
3477
|
var DEFAULT_COLUMN_SIZE = 150;
|
|
3399
3478
|
var MIN_COLUMN_SIZE = 40;
|
|
@@ -3444,7 +3523,7 @@ function toTanstackColumns(columns, editingCtxRef, cellEditingCtxRef, atomicGest
|
|
|
3444
3523
|
cell: (info) => {
|
|
3445
3524
|
const cellEditingCtx = cellEditingCtxRef.current;
|
|
3446
3525
|
if (!cellEditingCtx) return renderEditableCell(column, info.row.original, info.getValue(), editingCtxRef.current);
|
|
3447
|
-
return cellEditingCtx.alwaysEdit ? /* @__PURE__ */
|
|
3526
|
+
return cellEditingCtx.alwaysEdit ? /* @__PURE__ */ jsx34(
|
|
3448
3527
|
AlwaysEditCell,
|
|
3449
3528
|
{
|
|
3450
3529
|
column,
|
|
@@ -3489,8 +3568,10 @@ function DataGrid({
|
|
|
3489
3568
|
zebra = true,
|
|
3490
3569
|
showTotals = false,
|
|
3491
3570
|
editing,
|
|
3492
|
-
cellEditing
|
|
3571
|
+
cellEditing,
|
|
3572
|
+
filterLabels
|
|
3493
3573
|
}) {
|
|
3574
|
+
const resolvedFilterLabels = useFilterLabels(filterLabels);
|
|
3494
3575
|
const hasCellEditing = Boolean(cellEditing) && !groupBy;
|
|
3495
3576
|
const { state, filtersByColumn, setColumnFilter, toggleSort, setPage } = useGridState(
|
|
3496
3577
|
dataSource,
|
|
@@ -3536,11 +3617,11 @@ function DataGrid({
|
|
|
3536
3617
|
const atomicGestureRef = useRef13(void 0);
|
|
3537
3618
|
const visibleColumns = useVisibleColumns(columns, columnVisibility);
|
|
3538
3619
|
const serverRowCount = dataSource.mode === "server" ? dataSource.rowCount : void 0;
|
|
3539
|
-
const { rows, rowCount } =
|
|
3620
|
+
const { rows, rowCount } = useMemo9(() => {
|
|
3540
3621
|
if (dataSource.mode === "client") return processClientData(dataSource.data, state);
|
|
3541
3622
|
return { rows: dataSource.data, rowCount: serverRowCount ?? 0 };
|
|
3542
3623
|
}, [dataSource.mode, dataSource.data, serverRowCount, state]);
|
|
3543
|
-
const selectedRows =
|
|
3624
|
+
const selectedRows = useMemo9(
|
|
3544
3625
|
() => rows.filter((row) => selectedIds.has(getRowId(row))),
|
|
3545
3626
|
[rows, selectedIds, getRowId]
|
|
3546
3627
|
);
|
|
@@ -3559,11 +3640,11 @@ function DataGrid({
|
|
|
3559
3640
|
}
|
|
3560
3641
|
updateSelectedIds(next);
|
|
3561
3642
|
}
|
|
3562
|
-
const tanstackColumns =
|
|
3643
|
+
const tanstackColumns = useMemo9(
|
|
3563
3644
|
() => toTanstackColumns(visibleColumns, editingCtxRef, cellEditingCtxRef, atomicGestureRef),
|
|
3564
3645
|
[visibleColumns]
|
|
3565
3646
|
);
|
|
3566
|
-
const columnById =
|
|
3647
|
+
const columnById = useMemo9(() => {
|
|
3567
3648
|
const map = /* @__PURE__ */ new Map();
|
|
3568
3649
|
for (const column of visibleColumns) map.set(column.id, column);
|
|
3569
3650
|
return map;
|
|
@@ -3591,7 +3672,7 @@ function DataGrid({
|
|
|
3591
3672
|
const showDetailColumn = Boolean(renderDetail);
|
|
3592
3673
|
const totalColumnCount = visibleColumns.length + (showDetailColumn ? 1 : 0) + (showSelectionColumn ? 1 : 0) + (showRowActionsColumn ? 1 : 0);
|
|
3593
3674
|
const hasFilterRow = visibleColumns.some((column) => isFilterable(column) && column.filterDisplay === "row");
|
|
3594
|
-
const headerRuns =
|
|
3675
|
+
const headerRuns = useMemo9(() => computeHeaderRuns(visibleColumns), [visibleColumns]);
|
|
3595
3676
|
const hasHeaderGroups = visibleColumns.some((column) => column.headerGroup);
|
|
3596
3677
|
const hasColumnSummary = visibleColumns.some((column) => column.summary);
|
|
3597
3678
|
function renderFilterWidget(column) {
|
|
@@ -3602,11 +3683,11 @@ function DataGrid({
|
|
|
3602
3683
|
const columnSize = (columnId) => table.getColumn(columnId)?.getSize() ?? DEFAULT_COLUMN_SIZE;
|
|
3603
3684
|
const leadingStructuralWidth = (showDetailColumn ? DETAIL_COLUMN_WIDTH : 0) + (showSelectionColumn ? SELECTION_COLUMN_WIDTH : 0);
|
|
3604
3685
|
const trailingStructuralWidth = showRowActionsColumn ? ROW_ACTIONS_COLUMN_WIDTH : 0;
|
|
3605
|
-
const leftPinnedOffsets =
|
|
3686
|
+
const leftPinnedOffsets = useMemo9(
|
|
3606
3687
|
() => pinnedOffsets(visibleColumns, "left", columnSize, leadingStructuralWidth),
|
|
3607
3688
|
[visibleColumns, columnSizing, leadingStructuralWidth]
|
|
3608
3689
|
);
|
|
3609
|
-
const rightPinnedOffsets =
|
|
3690
|
+
const rightPinnedOffsets = useMemo9(
|
|
3610
3691
|
() => pinnedOffsets(visibleColumns, "right", columnSize, trailingStructuralWidth),
|
|
3611
3692
|
[visibleColumns, columnSizing, trailingStructuralWidth]
|
|
3612
3693
|
);
|
|
@@ -3656,7 +3737,7 @@ function DataGrid({
|
|
|
3656
3737
|
style: pinnedProps?.style
|
|
3657
3738
|
};
|
|
3658
3739
|
}
|
|
3659
|
-
const bodyCellPropsByColumn =
|
|
3740
|
+
const bodyCellPropsByColumn = useMemo9(() => {
|
|
3660
3741
|
const map = /* @__PURE__ */ new Map();
|
|
3661
3742
|
for (const column of visibleColumns) map.set(column.id, bodyCellClassAndStyle(column));
|
|
3662
3743
|
return map;
|
|
@@ -3672,7 +3753,7 @@ function DataGrid({
|
|
|
3672
3753
|
);
|
|
3673
3754
|
return { className, style: pinnedProps.style };
|
|
3674
3755
|
}
|
|
3675
|
-
const leafHeaderCellPropsByColumn =
|
|
3756
|
+
const leafHeaderCellPropsByColumn = useMemo9(() => {
|
|
3676
3757
|
const map = /* @__PURE__ */ new Map();
|
|
3677
3758
|
for (const column of visibleColumns) {
|
|
3678
3759
|
map.set(
|
|
@@ -3682,7 +3763,7 @@ function DataGrid({
|
|
|
3682
3763
|
}
|
|
3683
3764
|
return map;
|
|
3684
3765
|
}, [visibleColumns, enableColumnResizing, leftPinnedOffsets, rightPinnedOffsets, columnSizing]);
|
|
3685
|
-
const filterHeaderCellPropsByColumn =
|
|
3766
|
+
const filterHeaderCellPropsByColumn = useMemo9(() => {
|
|
3686
3767
|
const map = /* @__PURE__ */ new Map();
|
|
3687
3768
|
for (const column of visibleColumns) {
|
|
3688
3769
|
map.set(column.id, headerCellClassAndStyle(column, "border-b border-border p-2 align-top font-normal"));
|
|
@@ -3702,13 +3783,13 @@ function DataGrid({
|
|
|
3702
3783
|
`[DataGrid] showPagination={false} but only ${tableRows.length} of ${rowCount} row(s) are rendered, with no pagination UI to reach the rest. Pass an explicit pageSize (via initialState or gridState) that covers every row you want visible, or a dataSource that returns all of them.`
|
|
3703
3784
|
);
|
|
3704
3785
|
}, [showPagination, gridState, initialState?.pageSize, tableRows.length, rowCount]);
|
|
3705
|
-
const groupedBuckets =
|
|
3786
|
+
const groupedBuckets = useMemo9(
|
|
3706
3787
|
() => groupBy ? groupRows(tableRows, (row) => groupBy(row.original)) : void 0,
|
|
3707
3788
|
[tableRows, groupBy]
|
|
3708
3789
|
);
|
|
3709
3790
|
const { theadRef, groupHeaderTop } = useStickyGroupHeaderTop(Boolean(groupBy));
|
|
3710
3791
|
const shouldVirtualize = Boolean(virtualize) && tableRows.length > (virtualize?.threshold ?? 100);
|
|
3711
|
-
const flatItems =
|
|
3792
|
+
const flatItems = useMemo9(() => {
|
|
3712
3793
|
if (!shouldVirtualize) return [];
|
|
3713
3794
|
if (!groupedBuckets) return tableRows.map((row) => ({ kind: "row", row }));
|
|
3714
3795
|
const items = [];
|
|
@@ -3745,15 +3826,15 @@ function DataGrid({
|
|
|
3745
3826
|
notifiedForLengthRef.current = tableRows.length;
|
|
3746
3827
|
virtualize.onEndReached();
|
|
3747
3828
|
}, [lastVisibleIndex, flatItems.length, tableRows.length, virtualize]);
|
|
3748
|
-
const cellEditingRowIds =
|
|
3829
|
+
const cellEditingRowIds = useMemo9(
|
|
3749
3830
|
() => hasCellEditing ? tableRows.map((row) => row.id) : EMPTY_ID_ARRAY,
|
|
3750
3831
|
[hasCellEditing, tableRows]
|
|
3751
3832
|
);
|
|
3752
|
-
const cellEditingColumnIds =
|
|
3833
|
+
const cellEditingColumnIds = useMemo9(
|
|
3753
3834
|
() => hasCellEditing ? visibleColumns.map((column) => column.id) : EMPTY_ID_ARRAY,
|
|
3754
3835
|
[hasCellEditing, visibleColumns]
|
|
3755
3836
|
);
|
|
3756
|
-
const cellEditingRowIndex =
|
|
3837
|
+
const cellEditingRowIndex = useMemo9(() => buildIndexMap(cellEditingRowIds), [cellEditingRowIds]);
|
|
3757
3838
|
const cellSelection = useCellSelection({
|
|
3758
3839
|
rowIds: cellEditingRowIds,
|
|
3759
3840
|
columnIds: cellEditingColumnIds,
|
|
@@ -4000,12 +4081,12 @@ function DataGrid({
|
|
|
4000
4081
|
"data-testid": rowTestId,
|
|
4001
4082
|
className: rowProps?.className ? cn("divide-x divide-border", rowProps.className, isOddRow && "bg-foreground/5") : `divide-x divide-border${isOddRow ? " bg-foreground/5" : ""}`,
|
|
4002
4083
|
children: [
|
|
4003
|
-
showDetailColumn && /* @__PURE__ */
|
|
4084
|
+
showDetailColumn && /* @__PURE__ */ jsx34(
|
|
4004
4085
|
"td",
|
|
4005
4086
|
{
|
|
4006
4087
|
className: isOddRow ? detailCellProps.classNameOdd : detailCellProps.className,
|
|
4007
4088
|
style: detailCellProps.style,
|
|
4008
|
-
children: /* @__PURE__ */
|
|
4089
|
+
children: /* @__PURE__ */ jsx34(
|
|
4009
4090
|
Button,
|
|
4010
4091
|
{
|
|
4011
4092
|
type: "button",
|
|
@@ -4017,7 +4098,7 @@ function DataGrid({
|
|
|
4017
4098
|
stopRowClick(event);
|
|
4018
4099
|
toggleRowExpanded(row.id);
|
|
4019
4100
|
},
|
|
4020
|
-
children: /* @__PURE__ */
|
|
4101
|
+
children: /* @__PURE__ */ jsx34(
|
|
4021
4102
|
ChevronRight,
|
|
4022
4103
|
{
|
|
4023
4104
|
className: `h-4 w-4 transition-transform${isExpanded ? " rotate-90" : ""}`,
|
|
@@ -4028,12 +4109,12 @@ function DataGrid({
|
|
|
4028
4109
|
)
|
|
4029
4110
|
}
|
|
4030
4111
|
),
|
|
4031
|
-
showSelectionColumn && /* @__PURE__ */
|
|
4112
|
+
showSelectionColumn && /* @__PURE__ */ jsx34(
|
|
4032
4113
|
"td",
|
|
4033
4114
|
{
|
|
4034
4115
|
className: isOddRow ? selectionCellProps.classNameOdd : selectionCellProps.className,
|
|
4035
4116
|
style: selectionCellProps.style,
|
|
4036
|
-
children: /* @__PURE__ */
|
|
4117
|
+
children: /* @__PURE__ */ jsx34(
|
|
4037
4118
|
"input",
|
|
4038
4119
|
{
|
|
4039
4120
|
type: "checkbox",
|
|
@@ -4047,7 +4128,7 @@ function DataGrid({
|
|
|
4047
4128
|
),
|
|
4048
4129
|
row.getAllCells().map((cell) => {
|
|
4049
4130
|
const cellProps = bodyCellPropsByColumn.get(cell.column.id);
|
|
4050
|
-
return /* @__PURE__ */
|
|
4131
|
+
return /* @__PURE__ */ jsx34(
|
|
4051
4132
|
"td",
|
|
4052
4133
|
{
|
|
4053
4134
|
style: cellProps?.style,
|
|
@@ -4059,24 +4140,24 @@ function DataGrid({
|
|
|
4059
4140
|
cell.id
|
|
4060
4141
|
);
|
|
4061
4142
|
}),
|
|
4062
|
-
showRowActionsColumn && rowActions && /* @__PURE__ */
|
|
4143
|
+
showRowActionsColumn && rowActions && /* @__PURE__ */ jsx34(
|
|
4063
4144
|
"td",
|
|
4064
4145
|
{
|
|
4065
4146
|
className: isOddRow ? rowActionsCellProps.classNameOdd : rowActionsCellProps.className,
|
|
4066
4147
|
style: rowActionsCellProps.style,
|
|
4067
|
-
children: /* @__PURE__ */
|
|
4148
|
+
children: /* @__PURE__ */ jsx34(ActionsMenu, { items: rowActions, ctx: { row: row.original }, triggerLabel: `Row actions for ${row.id}` })
|
|
4068
4149
|
}
|
|
4069
4150
|
)
|
|
4070
4151
|
]
|
|
4071
4152
|
}
|
|
4072
4153
|
),
|
|
4073
|
-
showDetailColumn && isExpanded && renderDetail && /* @__PURE__ */
|
|
4154
|
+
showDetailColumn && isExpanded && renderDetail && /* @__PURE__ */ jsx34("tr", { "data-testid": `${rowTestId}-detail`, children: /* @__PURE__ */ jsx34("td", { colSpan: totalColumnCount, className: "border-b border-border p-2", children: renderDetail(row.original) }) })
|
|
4074
4155
|
] }, row.id);
|
|
4075
4156
|
}
|
|
4076
4157
|
function renderGroupSummaryCells(rows2, bgClassName) {
|
|
4077
4158
|
return visibleColumns.map((column) => {
|
|
4078
4159
|
const cellProps = bodyCellPropsByColumn.get(column.id);
|
|
4079
|
-
return /* @__PURE__ */
|
|
4160
|
+
return /* @__PURE__ */ jsx34(
|
|
4080
4161
|
"td",
|
|
4081
4162
|
{
|
|
4082
4163
|
className: cn(cellProps?.className, bgClassName, "font-medium", alignClassName(column)),
|
|
@@ -4095,9 +4176,9 @@ function DataGrid({
|
|
|
4095
4176
|
const bgClassName = zebra ? "bg-muted" : "bg-background";
|
|
4096
4177
|
const fillerClass = cn("border-b border-border p-2", bgClassName);
|
|
4097
4178
|
return /* @__PURE__ */ jsxs20("tr", { "data-testid": "group-summary-row", className: "divide-x divide-border", children: [
|
|
4098
|
-
leadingSpan > 0 && /* @__PURE__ */
|
|
4179
|
+
leadingSpan > 0 && /* @__PURE__ */ jsx34("td", { colSpan: leadingSpan, className: fillerClass }),
|
|
4099
4180
|
renderGroupSummaryCells(rows2, bgClassName),
|
|
4100
|
-
showRowActionsColumn && /* @__PURE__ */
|
|
4181
|
+
showRowActionsColumn && /* @__PURE__ */ jsx34("td", { className: fillerClass, "aria-hidden": true })
|
|
4101
4182
|
] });
|
|
4102
4183
|
}
|
|
4103
4184
|
function renderTotalsFooter() {
|
|
@@ -4105,11 +4186,11 @@ function DataGrid({
|
|
|
4105
4186
|
const summaryRows = tableRows.map((row) => row.original);
|
|
4106
4187
|
const leadingSpan = summaryLeadingCellSpan();
|
|
4107
4188
|
const fillerClass = "sticky bottom-0 z-20 border-t border-border bg-muted p-2";
|
|
4108
|
-
return /* @__PURE__ */
|
|
4109
|
-
leadingSpan > 0 && /* @__PURE__ */
|
|
4189
|
+
return /* @__PURE__ */ jsx34("tfoot", { children: /* @__PURE__ */ jsxs20("tr", { "data-testid": "totals-row", className: "divide-x divide-border", children: [
|
|
4190
|
+
leadingSpan > 0 && /* @__PURE__ */ jsx34("td", { colSpan: leadingSpan, className: fillerClass }),
|
|
4110
4191
|
visibleColumns.map((column) => {
|
|
4111
4192
|
const pinnedProps = pinnedCellProps(column, "header");
|
|
4112
|
-
return /* @__PURE__ */
|
|
4193
|
+
return /* @__PURE__ */ jsx34(
|
|
4113
4194
|
"td",
|
|
4114
4195
|
{
|
|
4115
4196
|
className: cn(
|
|
@@ -4124,13 +4205,13 @@ function DataGrid({
|
|
|
4124
4205
|
column.id
|
|
4125
4206
|
);
|
|
4126
4207
|
}),
|
|
4127
|
-
showRowActionsColumn && /* @__PURE__ */
|
|
4208
|
+
showRowActionsColumn && /* @__PURE__ */ jsx34("td", { className: fillerClass, "aria-hidden": true })
|
|
4128
4209
|
] }) });
|
|
4129
4210
|
}
|
|
4130
4211
|
function renderGroupHeaderTbody(key, rows2, measureRef, dataIndex) {
|
|
4131
4212
|
const expanded = isGroupExpanded(key);
|
|
4132
4213
|
return /* @__PURE__ */ jsxs20("tbody", { ref: measureRef, "data-index": dataIndex, children: [
|
|
4133
|
-
/* @__PURE__ */
|
|
4214
|
+
/* @__PURE__ */ jsx34("tr", { "data-testid": `group-header-${key}`, children: /* @__PURE__ */ jsx34(
|
|
4134
4215
|
"td",
|
|
4135
4216
|
{
|
|
4136
4217
|
colSpan: totalColumnCount,
|
|
@@ -4144,7 +4225,7 @@ function DataGrid({
|
|
|
4144
4225
|
onClick: () => toggleGroupExpanded(key),
|
|
4145
4226
|
"aria-expanded": expanded,
|
|
4146
4227
|
children: [
|
|
4147
|
-
/* @__PURE__ */
|
|
4228
|
+
/* @__PURE__ */ jsx34(
|
|
4148
4229
|
ChevronRight,
|
|
4149
4230
|
{
|
|
4150
4231
|
className: `h-4 w-4 shrink-0 transition-transform${expanded ? " rotate-90" : ""}`,
|
|
@@ -4172,7 +4253,7 @@ function DataGrid({
|
|
|
4172
4253
|
if (item.kind === "header") return renderGroupHeaderTbody(item.key, item.rows, measureRef, index);
|
|
4173
4254
|
return renderRow(item.row, measureRef, index);
|
|
4174
4255
|
}
|
|
4175
|
-
|
|
4256
|
+
const grid = (
|
|
4176
4257
|
// `h-full`/`min-h-0` here and on the two wrappers below are no-ops unless
|
|
4177
4258
|
// a consumer itself gives <DataGrid> a bounded height (e.g. wraps it in
|
|
4178
4259
|
// its own `flex-1 min-h-0` container) -- percentage heights fall back to
|
|
@@ -4186,7 +4267,7 @@ function DataGrid({
|
|
|
4186
4267
|
// `overflow-x-auto` div scrolling horizontally) fighting over which one
|
|
4187
4268
|
// a sticky header/pinned column is actually stuck relative to.
|
|
4188
4269
|
/* @__PURE__ */ jsxs20("div", { className: "flex h-full min-h-0 flex-col gap-2", "data-testid": "datagrid", children: [
|
|
4189
|
-
editing && pendingEdits.size > 0 && /* @__PURE__ */
|
|
4270
|
+
editing && pendingEdits.size > 0 && /* @__PURE__ */ jsx34(
|
|
4190
4271
|
EditingBar,
|
|
4191
4272
|
{
|
|
4192
4273
|
editing,
|
|
@@ -4201,15 +4282,15 @@ function DataGrid({
|
|
|
4201
4282
|
selectedRows.length,
|
|
4202
4283
|
" selected"
|
|
4203
4284
|
] }),
|
|
4204
|
-
/* @__PURE__ */
|
|
4285
|
+
/* @__PURE__ */ jsx34(ActionsMenu, { items: headerActions, ctx: { selectedRows }, triggerLabel: "Bulk actions" })
|
|
4205
4286
|
] }),
|
|
4206
4287
|
/* @__PURE__ */ jsxs20("div", { className: "relative min-h-0 flex-1", children: [
|
|
4207
|
-
loading && /* @__PURE__ */
|
|
4288
|
+
loading && /* @__PURE__ */ jsx34(
|
|
4208
4289
|
"div",
|
|
4209
4290
|
{
|
|
4210
4291
|
"data-testid": "datagrid-loading-overlay",
|
|
4211
4292
|
className: "absolute inset-0 z-30 flex items-center justify-center bg-background/60",
|
|
4212
|
-
children: /* @__PURE__ */
|
|
4293
|
+
children: /* @__PURE__ */ jsx34(Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground", "aria-hidden": true })
|
|
4213
4294
|
}
|
|
4214
4295
|
),
|
|
4215
4296
|
/* @__PURE__ */ jsxs20(
|
|
@@ -4259,8 +4340,8 @@ function DataGrid({
|
|
|
4259
4340
|
onClick: (event) => toggleSort(column.id, enableMultiSort && event.shiftKey, column.sortDescFirst === true),
|
|
4260
4341
|
children: [
|
|
4261
4342
|
headerContent,
|
|
4262
|
-
sortEntry?.dir === "asc" && /* @__PURE__ */
|
|
4263
|
-
sortEntry?.dir === "desc" && /* @__PURE__ */
|
|
4343
|
+
sortEntry?.dir === "asc" && /* @__PURE__ */ jsx34(BarsArrowUpIcon, { className: "h-3 w-3", "aria-hidden": true }),
|
|
4344
|
+
sortEntry?.dir === "desc" && /* @__PURE__ */ jsx34(BarsArrowDownIcon, { className: "h-3 w-3", "aria-hidden": true })
|
|
4264
4345
|
]
|
|
4265
4346
|
}
|
|
4266
4347
|
) : (
|
|
@@ -4269,17 +4350,17 @@ function DataGrid({
|
|
|
4269
4350
|
// silently breaking any interactive content a column's own `renderHeader`
|
|
4270
4351
|
// embeds directly (bare filter inputs, "select/reject all" buttons) —
|
|
4271
4352
|
// clicks never reach them at all, even though nothing looks wrong visually.
|
|
4272
|
-
/* @__PURE__ */
|
|
4353
|
+
/* @__PURE__ */ jsx34("div", { id: headerLabelId, className: "flex items-center gap-1 px-1", children: headerContent })
|
|
4273
4354
|
),
|
|
4274
4355
|
filterable && /* @__PURE__ */ jsxs20(Popover, { children: [
|
|
4275
|
-
/* @__PURE__ */
|
|
4356
|
+
/* @__PURE__ */ jsx34(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx34(
|
|
4276
4357
|
Button,
|
|
4277
4358
|
{
|
|
4278
4359
|
variant: "ghost",
|
|
4279
4360
|
size: "icon",
|
|
4280
4361
|
"data-testid": `filter-trigger-${column.id}`,
|
|
4281
|
-
"aria-label":
|
|
4282
|
-
children: /* @__PURE__ */
|
|
4362
|
+
"aria-label": resolvedFilterLabels.filterAriaLabel(column.header),
|
|
4363
|
+
children: /* @__PURE__ */ jsx34(
|
|
4283
4364
|
FunnelIcon7,
|
|
4284
4365
|
{
|
|
4285
4366
|
className: cn(
|
|
@@ -4291,10 +4372,10 @@ function DataGrid({
|
|
|
4291
4372
|
)
|
|
4292
4373
|
}
|
|
4293
4374
|
) }),
|
|
4294
|
-
/* @__PURE__ */
|
|
4375
|
+
/* @__PURE__ */ jsx34(PopoverContent, { className: "w-auto max-w-[var(--radix-popover-content-available-width)]", children: renderFilterWidget(column) })
|
|
4295
4376
|
] })
|
|
4296
4377
|
] }),
|
|
4297
|
-
enableColumnResizing && /* @__PURE__ */
|
|
4378
|
+
enableColumnResizing && /* @__PURE__ */ jsx34(
|
|
4298
4379
|
"div",
|
|
4299
4380
|
{
|
|
4300
4381
|
"data-testid": `resize-handle-${column.id}`,
|
|
@@ -4321,7 +4402,7 @@ function DataGrid({
|
|
|
4321
4402
|
}
|
|
4322
4403
|
return /* @__PURE__ */ jsxs20(Fragment3, { children: [
|
|
4323
4404
|
hasHeaderGroups && /* @__PURE__ */ jsxs20("tr", { "data-testid": "header-group-row", className: "divide-x divide-border", children: [
|
|
4324
|
-
showDetailColumn && /* @__PURE__ */
|
|
4405
|
+
showDetailColumn && /* @__PURE__ */ jsx34(
|
|
4325
4406
|
"th",
|
|
4326
4407
|
{
|
|
4327
4408
|
rowSpan: 2,
|
|
@@ -4330,13 +4411,13 @@ function DataGrid({
|
|
|
4330
4411
|
"aria-hidden": true
|
|
4331
4412
|
}
|
|
4332
4413
|
),
|
|
4333
|
-
showSelectionColumn && /* @__PURE__ */
|
|
4414
|
+
showSelectionColumn && /* @__PURE__ */ jsx34(
|
|
4334
4415
|
"th",
|
|
4335
4416
|
{
|
|
4336
4417
|
rowSpan: 2,
|
|
4337
4418
|
className: selectionHeaderCellProps.className,
|
|
4338
4419
|
style: selectionHeaderCellProps.style,
|
|
4339
|
-
children: /* @__PURE__ */
|
|
4420
|
+
children: /* @__PURE__ */ jsx34(
|
|
4340
4421
|
"input",
|
|
4341
4422
|
{
|
|
4342
4423
|
type: "checkbox",
|
|
@@ -4348,7 +4429,7 @@ function DataGrid({
|
|
|
4348
4429
|
}
|
|
4349
4430
|
),
|
|
4350
4431
|
headerRuns.map(
|
|
4351
|
-
(run) => run.kind === "single" ? renderLeafHeaderCell(run.column, 2) : /* @__PURE__ */
|
|
4432
|
+
(run) => run.kind === "single" ? renderLeafHeaderCell(run.column, 2) : /* @__PURE__ */ jsx34(
|
|
4352
4433
|
"th",
|
|
4353
4434
|
{
|
|
4354
4435
|
colSpan: run.columns.length,
|
|
@@ -4358,7 +4439,7 @@ function DataGrid({
|
|
|
4358
4439
|
`group-${run.label}-${run.columns[0].id}`
|
|
4359
4440
|
)
|
|
4360
4441
|
),
|
|
4361
|
-
showRowActionsColumn && /* @__PURE__ */
|
|
4442
|
+
showRowActionsColumn && /* @__PURE__ */ jsx34(
|
|
4362
4443
|
"th",
|
|
4363
4444
|
{
|
|
4364
4445
|
rowSpan: 2,
|
|
@@ -4369,7 +4450,7 @@ function DataGrid({
|
|
|
4369
4450
|
)
|
|
4370
4451
|
] }, `${headerGroup.id}-groups`),
|
|
4371
4452
|
/* @__PURE__ */ jsxs20("tr", { className: "divide-x divide-border", children: [
|
|
4372
|
-
!hasHeaderGroups && showDetailColumn && /* @__PURE__ */
|
|
4453
|
+
!hasHeaderGroups && showDetailColumn && /* @__PURE__ */ jsx34(
|
|
4373
4454
|
"th",
|
|
4374
4455
|
{
|
|
4375
4456
|
className: detailHeaderCellProps.className,
|
|
@@ -4377,12 +4458,12 @@ function DataGrid({
|
|
|
4377
4458
|
"aria-hidden": true
|
|
4378
4459
|
}
|
|
4379
4460
|
),
|
|
4380
|
-
!hasHeaderGroups && showSelectionColumn && /* @__PURE__ */
|
|
4461
|
+
!hasHeaderGroups && showSelectionColumn && /* @__PURE__ */ jsx34(
|
|
4381
4462
|
"th",
|
|
4382
4463
|
{
|
|
4383
4464
|
className: selectionHeaderCellProps.className,
|
|
4384
4465
|
style: selectionHeaderCellProps.style,
|
|
4385
|
-
children: /* @__PURE__ */
|
|
4466
|
+
children: /* @__PURE__ */ jsx34(
|
|
4386
4467
|
"input",
|
|
4387
4468
|
{
|
|
4388
4469
|
type: "checkbox",
|
|
@@ -4398,7 +4479,7 @@ function DataGrid({
|
|
|
4398
4479
|
if (!column || hasHeaderGroups && !column.headerGroup) return null;
|
|
4399
4480
|
return renderLeafHeaderCell(column);
|
|
4400
4481
|
}),
|
|
4401
|
-
!hasHeaderGroups && showRowActionsColumn && /* @__PURE__ */
|
|
4482
|
+
!hasHeaderGroups && showRowActionsColumn && /* @__PURE__ */ jsx34(
|
|
4402
4483
|
"th",
|
|
4403
4484
|
{
|
|
4404
4485
|
className: rowActionsHeaderCellProps.className,
|
|
@@ -4410,8 +4491,8 @@ function DataGrid({
|
|
|
4410
4491
|
] }, headerGroup.id);
|
|
4411
4492
|
}),
|
|
4412
4493
|
hasFilterRow && /* @__PURE__ */ jsxs20("tr", { "data-testid": "filter-row", className: "divide-x divide-border", children: [
|
|
4413
|
-
showDetailColumn && /* @__PURE__ */
|
|
4414
|
-
showSelectionColumn && /* @__PURE__ */
|
|
4494
|
+
showDetailColumn && /* @__PURE__ */ jsx34("th", { className: detailHeaderCellProps.className, style: detailHeaderCellProps.style }),
|
|
4495
|
+
showSelectionColumn && /* @__PURE__ */ jsx34(
|
|
4415
4496
|
"th",
|
|
4416
4497
|
{
|
|
4417
4498
|
className: selectionHeaderCellProps.className,
|
|
@@ -4420,9 +4501,9 @@ function DataGrid({
|
|
|
4420
4501
|
),
|
|
4421
4502
|
visibleColumns.map((column) => {
|
|
4422
4503
|
const cellProps = filterHeaderCellPropsByColumn.get(column.id);
|
|
4423
|
-
return /* @__PURE__ */
|
|
4504
|
+
return /* @__PURE__ */ jsx34("th", { style: cellProps?.style, className: cellProps?.className, children: isFilterable(column) && column.filterDisplay === "row" ? renderFilterWidget(column) : null }, column.id);
|
|
4424
4505
|
}),
|
|
4425
|
-
showRowActionsColumn && /* @__PURE__ */
|
|
4506
|
+
showRowActionsColumn && /* @__PURE__ */ jsx34(
|
|
4426
4507
|
"th",
|
|
4427
4508
|
{
|
|
4428
4509
|
className: rowActionsHeaderCellProps.className,
|
|
@@ -4431,8 +4512,8 @@ function DataGrid({
|
|
|
4431
4512
|
)
|
|
4432
4513
|
] })
|
|
4433
4514
|
] }),
|
|
4434
|
-
rows.length === 0 ? /* @__PURE__ */
|
|
4435
|
-
paddingTop > 0 && /* @__PURE__ */
|
|
4515
|
+
rows.length === 0 ? /* @__PURE__ */ jsx34("tbody", { children: /* @__PURE__ */ jsx34("tr", { children: /* @__PURE__ */ jsx34("td", { colSpan: totalColumnCount, className: "p-4 text-center text-muted-foreground", children: loading ? "Loading..." : "No results." }) }) }) : shouldVirtualize ? /* @__PURE__ */ jsxs20(Fragment4, { children: [
|
|
4516
|
+
paddingTop > 0 && /* @__PURE__ */ jsx34("tbody", { children: /* @__PURE__ */ jsx34("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx34("td", { colSpan: totalColumnCount, style: { padding: 0, border: "none", height: paddingTop } }) }) }),
|
|
4436
4517
|
virtualItems.map(
|
|
4437
4518
|
(virtualItem) => renderFlatItem(
|
|
4438
4519
|
flatItems[virtualItem.index],
|
|
@@ -4440,11 +4521,11 @@ function DataGrid({
|
|
|
4440
4521
|
(el) => virtualizer.measureElement(el)
|
|
4441
4522
|
)
|
|
4442
4523
|
),
|
|
4443
|
-
paddingBottom > 0 && /* @__PURE__ */
|
|
4524
|
+
paddingBottom > 0 && /* @__PURE__ */ jsx34("tbody", { children: /* @__PURE__ */ jsx34("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx34("td", { colSpan: totalColumnCount, style: { padding: 0, border: "none", height: paddingBottom } }) }) })
|
|
4444
4525
|
] }) : groupedBuckets ? groupedBuckets.map((bucket) => renderGroupedBucket(bucket)) : tableRows.map((row) => renderRow(row)),
|
|
4445
4526
|
renderTotalsFooter()
|
|
4446
4527
|
] }),
|
|
4447
|
-
hasCellEditing && /* @__PURE__ */
|
|
4528
|
+
hasCellEditing && /* @__PURE__ */ jsx34(
|
|
4448
4529
|
SelectionOverlay,
|
|
4449
4530
|
{
|
|
4450
4531
|
containerRef: scrollRef,
|
|
@@ -4470,7 +4551,7 @@ function DataGrid({
|
|
|
4470
4551
|
")"
|
|
4471
4552
|
] }),
|
|
4472
4553
|
/* @__PURE__ */ jsxs20("div", { className: "flex gap-2", children: [
|
|
4473
|
-
/* @__PURE__ */
|
|
4554
|
+
/* @__PURE__ */ jsx34(
|
|
4474
4555
|
Button,
|
|
4475
4556
|
{
|
|
4476
4557
|
variant: "outline",
|
|
@@ -4480,7 +4561,7 @@ function DataGrid({
|
|
|
4480
4561
|
children: "Previous"
|
|
4481
4562
|
}
|
|
4482
4563
|
),
|
|
4483
|
-
/* @__PURE__ */
|
|
4564
|
+
/* @__PURE__ */ jsx34(
|
|
4484
4565
|
Button,
|
|
4485
4566
|
{
|
|
4486
4567
|
variant: "outline",
|
|
@@ -4494,12 +4575,13 @@ function DataGrid({
|
|
|
4494
4575
|
] })
|
|
4495
4576
|
] })
|
|
4496
4577
|
);
|
|
4578
|
+
return /* @__PURE__ */ jsx34(FilterLabelsProvider, { labels: filterLabels, children: grid });
|
|
4497
4579
|
}
|
|
4498
4580
|
|
|
4499
4581
|
// src/tree/TreeDataGrid.tsx
|
|
4500
4582
|
import { useVirtualizer as useVirtualizer2 } from "@tanstack/react-virtual";
|
|
4501
4583
|
import { AlertCircle, ChevronDown as ChevronDown2, ChevronRight as ChevronRight2, Loader2 as Loader22 } from "lucide-react";
|
|
4502
|
-
import { Fragment as Fragment5, useEffect as useEffect13, useMemo as
|
|
4584
|
+
import { Fragment as Fragment5, useEffect as useEffect13, useMemo as useMemo11, useRef as useRef14 } from "react";
|
|
4503
4585
|
|
|
4504
4586
|
// src/tree/flattenTree.ts
|
|
4505
4587
|
function flattenTree(roots, accessors, expanded, childrenOverride) {
|
|
@@ -4544,7 +4626,7 @@ function computeSelectionStates(roots, accessors, childrenOverride, selectedIds)
|
|
|
4544
4626
|
}
|
|
4545
4627
|
|
|
4546
4628
|
// src/tree/useTreeState.ts
|
|
4547
|
-
import { useCallback as useCallback5, useMemo as
|
|
4629
|
+
import { useCallback as useCallback5, useMemo as useMemo10, useState as useState17 } from "react";
|
|
4548
4630
|
function useTreeState({
|
|
4549
4631
|
data,
|
|
4550
4632
|
getRowId,
|
|
@@ -4582,7 +4664,7 @@ function useTreeState({
|
|
|
4582
4664
|
);
|
|
4583
4665
|
const [loadingIds, setLoadingIds] = useState17(/* @__PURE__ */ new Set());
|
|
4584
4666
|
const [errorIds, setErrorIds] = useState17(/* @__PURE__ */ new Map());
|
|
4585
|
-
const resolveHasChildren =
|
|
4667
|
+
const resolveHasChildren = useMemo10(
|
|
4586
4668
|
() => hasChildren ?? ((row) => (getChildren(row)?.length ?? 0) > 0),
|
|
4587
4669
|
[hasChildren, getChildren]
|
|
4588
4670
|
);
|
|
@@ -4661,7 +4743,7 @@ function useTreeState({
|
|
|
4661
4743
|
}
|
|
4662
4744
|
|
|
4663
4745
|
// src/tree/TreeDataGrid.tsx
|
|
4664
|
-
import { Fragment as Fragment6, jsx as
|
|
4746
|
+
import { Fragment as Fragment6, jsx as jsx35, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
4665
4747
|
var EMPTY_SELECTED_IDS = /* @__PURE__ */ new Set();
|
|
4666
4748
|
var UNCHECKED_STATE = { checked: false, indeterminate: false };
|
|
4667
4749
|
function renderCell(column, row, editingCtx) {
|
|
@@ -4678,7 +4760,7 @@ function TreeCell({
|
|
|
4678
4760
|
editingCtx
|
|
4679
4761
|
}) {
|
|
4680
4762
|
return /* @__PURE__ */ jsxs21("div", { className: "flex items-center gap-1", style: { paddingLeft: flatRow.depth * indentSize }, children: [
|
|
4681
|
-
flatRow.hasChildren ? /* @__PURE__ */
|
|
4763
|
+
flatRow.hasChildren ? /* @__PURE__ */ jsx35(
|
|
4682
4764
|
"button",
|
|
4683
4765
|
{
|
|
4684
4766
|
type: "button",
|
|
@@ -4690,14 +4772,14 @@ function TreeCell({
|
|
|
4690
4772
|
"aria-label": flatRow.isExpanded ? "Collapse" : "Expand",
|
|
4691
4773
|
"aria-expanded": flatRow.isExpanded,
|
|
4692
4774
|
className: "flex h-4 w-4 shrink-0 items-center justify-center text-muted-foreground hover:text-foreground disabled:opacity-50",
|
|
4693
|
-
children: isLoading ? /* @__PURE__ */
|
|
4775
|
+
children: isLoading ? /* @__PURE__ */ jsx35(Loader22, { className: "h-3.5 w-3.5 animate-spin", "aria-hidden": "true" }) : flatRow.isExpanded ? /* @__PURE__ */ jsx35(ChevronDown2, { className: "h-3.5 w-3.5", "aria-hidden": "true" }) : /* @__PURE__ */ jsx35(ChevronRight2, { className: "h-3.5 w-3.5", "aria-hidden": "true" })
|
|
4694
4776
|
}
|
|
4695
|
-
) : /* @__PURE__ */
|
|
4696
|
-
/* @__PURE__ */
|
|
4777
|
+
) : /* @__PURE__ */ jsx35("span", { className: "h-4 w-4 shrink-0", "aria-hidden": "true" }),
|
|
4778
|
+
/* @__PURE__ */ jsx35("span", { className: "min-w-0 flex-1 truncate", children: renderCell(column, flatRow.row, editingCtx) }),
|
|
4697
4779
|
flatRow.isExpanded && error ? /* @__PURE__ */ jsxs21("span", { className: "ml-1 flex shrink-0 items-center gap-1 text-xs text-destructive", children: [
|
|
4698
|
-
/* @__PURE__ */
|
|
4780
|
+
/* @__PURE__ */ jsx35(AlertCircle, { className: "h-3 w-3", "aria-hidden": "true" }),
|
|
4699
4781
|
"Failed to load.",
|
|
4700
|
-
/* @__PURE__ */
|
|
4782
|
+
/* @__PURE__ */ jsx35("button", { type: "button", className: "underline underline-offset-2", onClick: onRetry, children: "Retry" })
|
|
4701
4783
|
] }) : null
|
|
4702
4784
|
] });
|
|
4703
4785
|
}
|
|
@@ -4737,7 +4819,7 @@ function TreeDataGrid({
|
|
|
4737
4819
|
showTotals = false,
|
|
4738
4820
|
editing
|
|
4739
4821
|
}) {
|
|
4740
|
-
const accessors =
|
|
4822
|
+
const accessors = useMemo11(
|
|
4741
4823
|
() => ({ getRowId, getChildren, hasChildren }),
|
|
4742
4824
|
[getRowId, getChildren, hasChildren]
|
|
4743
4825
|
);
|
|
@@ -4765,11 +4847,11 @@ function TreeDataGrid({
|
|
|
4765
4847
|
controlledExpandedGroups,
|
|
4766
4848
|
onExpandedGroupsChange
|
|
4767
4849
|
);
|
|
4768
|
-
const flatRows =
|
|
4850
|
+
const flatRows = useMemo11(
|
|
4769
4851
|
() => groupBy ? [] : flattenTree(data, accessors, expanded, childrenMap),
|
|
4770
4852
|
[groupBy, data, accessors, expanded, childrenMap]
|
|
4771
4853
|
);
|
|
4772
|
-
const groupedBuckets =
|
|
4854
|
+
const groupedBuckets = useMemo11(
|
|
4773
4855
|
() => groupBy ? groupRows(data, groupBy).map((bucket) => ({
|
|
4774
4856
|
key: bucket.key,
|
|
4775
4857
|
roots: bucket.items,
|
|
@@ -4777,7 +4859,7 @@ function TreeDataGrid({
|
|
|
4777
4859
|
})) : void 0,
|
|
4778
4860
|
[groupBy, data, accessors, expanded, childrenMap]
|
|
4779
4861
|
);
|
|
4780
|
-
const groupedRender =
|
|
4862
|
+
const groupedRender = useMemo11(() => {
|
|
4781
4863
|
if (!groupedBuckets) return void 0;
|
|
4782
4864
|
const startIndexByBucket = /* @__PURE__ */ new Map();
|
|
4783
4865
|
const rows = [];
|
|
@@ -4794,7 +4876,7 @@ function TreeDataGrid({
|
|
|
4794
4876
|
const showSelectionColumn = controlledSelectedIds !== void 0;
|
|
4795
4877
|
const totalColumnCount = visibleColumns.length + (showRowActionsColumn ? 1 : 0) + (showSelectionColumn ? 1 : 0);
|
|
4796
4878
|
const { theadRef, groupHeaderTop } = useStickyGroupHeaderTop(Boolean(groupBy));
|
|
4797
|
-
const selectionStates =
|
|
4879
|
+
const selectionStates = useMemo11(
|
|
4798
4880
|
() => showSelectionColumn ? computeSelectionStates(data, accessors, childrenMap, controlledSelectedIds ?? EMPTY_SELECTED_IDS) : void 0,
|
|
4799
4881
|
[showSelectionColumn, data, accessors, childrenMap, controlledSelectedIds]
|
|
4800
4882
|
);
|
|
@@ -4810,7 +4892,7 @@ function TreeDataGrid({
|
|
|
4810
4892
|
else next.add(id);
|
|
4811
4893
|
onSelectedIdsChange?.(next);
|
|
4812
4894
|
}
|
|
4813
|
-
const selectableFlatRows =
|
|
4895
|
+
const selectableFlatRows = useMemo11(
|
|
4814
4896
|
() => allFlatRows.filter((flatRow) => !(isRowSelectionDisabled?.(flatRow.row) ?? false)),
|
|
4815
4897
|
[allFlatRows, isRowSelectionDisabled]
|
|
4816
4898
|
);
|
|
@@ -4824,14 +4906,14 @@ function TreeDataGrid({
|
|
|
4824
4906
|
}
|
|
4825
4907
|
onSelectedIdsChange?.(next);
|
|
4826
4908
|
}
|
|
4827
|
-
const bodyTdClassByColumn =
|
|
4909
|
+
const bodyTdClassByColumn = useMemo11(() => {
|
|
4828
4910
|
const map = /* @__PURE__ */ new Map();
|
|
4829
4911
|
for (const column of visibleColumns) map.set(column.id, `p-2 ${alignClassName(column)}`);
|
|
4830
4912
|
return map;
|
|
4831
4913
|
}, [visibleColumns]);
|
|
4832
4914
|
const hasColumnSummary = visibleColumns.some((column) => column.summary);
|
|
4833
4915
|
function renderGroupSummaryCells(rows) {
|
|
4834
|
-
return visibleColumns.map((column) => /* @__PURE__ */
|
|
4916
|
+
return visibleColumns.map((column) => /* @__PURE__ */ jsx35("td", { className: cn(bodyTdClassByColumn.get(column.id), "font-medium"), children: column.summary?.(rows) }, column.id));
|
|
4835
4917
|
}
|
|
4836
4918
|
const scrollRef = useRef14(null);
|
|
4837
4919
|
const shouldVirtualize = !groupBy && flatRows.length > virtualizeThreshold;
|
|
@@ -4859,9 +4941,9 @@ function TreeDataGrid({
|
|
|
4859
4941
|
isOddRow && "bg-foreground/5"
|
|
4860
4942
|
) : `border-b border-border divide-x divide-border${isOddRow ? " bg-foreground/5" : ""}`,
|
|
4861
4943
|
children: [
|
|
4862
|
-
showSelectionColumn && /* @__PURE__ */
|
|
4944
|
+
showSelectionColumn && /* @__PURE__ */ jsx35("td", { className: "p-1", style: { width: SELECTION_COLUMN_WIDTH }, children: (() => {
|
|
4863
4945
|
const state = resolveSelectionState(flatRow.row, flatRow.id);
|
|
4864
|
-
return /* @__PURE__ */
|
|
4946
|
+
return /* @__PURE__ */ jsx35(
|
|
4865
4947
|
Checkbox,
|
|
4866
4948
|
{
|
|
4867
4949
|
"aria-label": `Select row ${flatRow.id}`,
|
|
@@ -4872,7 +4954,7 @@ function TreeDataGrid({
|
|
|
4872
4954
|
}
|
|
4873
4955
|
);
|
|
4874
4956
|
})() }),
|
|
4875
|
-
visibleColumns.map((column) => /* @__PURE__ */
|
|
4957
|
+
visibleColumns.map((column) => /* @__PURE__ */ jsx35("td", { className: bodyTdClassByColumn.get(column.id), children: column.id === treeColId ? /* @__PURE__ */ jsx35(
|
|
4876
4958
|
TreeCell,
|
|
4877
4959
|
{
|
|
4878
4960
|
flatRow,
|
|
@@ -4885,7 +4967,7 @@ function TreeDataGrid({
|
|
|
4885
4967
|
editingCtx: editingState.ctx
|
|
4886
4968
|
}
|
|
4887
4969
|
) : renderCell(column, flatRow.row, editingState.ctx) }, column.id)),
|
|
4888
|
-
showRowActionsColumn && rowActions && /* @__PURE__ */
|
|
4970
|
+
showRowActionsColumn && rowActions && /* @__PURE__ */ jsx35("td", { className: "p-2", children: /* @__PURE__ */ jsx35(
|
|
4889
4971
|
ActionsMenu,
|
|
4890
4972
|
{
|
|
4891
4973
|
items: rowActions,
|
|
@@ -4902,7 +4984,7 @@ function TreeDataGrid({
|
|
|
4902
4984
|
const paddingTop = virtualItems.length > 0 ? virtualItems[0].start : 0;
|
|
4903
4985
|
const paddingBottom = virtualItems.length > 0 ? virtualizer.getTotalSize() - virtualItems[virtualItems.length - 1].end : 0;
|
|
4904
4986
|
return /* @__PURE__ */ jsxs21("div", { className: "flex flex-col gap-2", "data-testid": "tree-datagrid", children: [
|
|
4905
|
-
editing && editingState.pendingEdits.size > 0 && /* @__PURE__ */
|
|
4987
|
+
editing && editingState.pendingEdits.size > 0 && /* @__PURE__ */ jsx35(
|
|
4906
4988
|
EditingBar,
|
|
4907
4989
|
{
|
|
4908
4990
|
editing,
|
|
@@ -4913,7 +4995,7 @@ function TreeDataGrid({
|
|
|
4913
4995
|
testIdPrefix: "tree-datagrid"
|
|
4914
4996
|
}
|
|
4915
4997
|
),
|
|
4916
|
-
/* @__PURE__ */
|
|
4998
|
+
/* @__PURE__ */ jsx35(
|
|
4917
4999
|
"div",
|
|
4918
5000
|
{
|
|
4919
5001
|
ref: scrollRef,
|
|
@@ -4921,13 +5003,13 @@ function TreeDataGrid({
|
|
|
4921
5003
|
className: "overflow-y-auto",
|
|
4922
5004
|
style: { maxHeight: maxBodyHeight },
|
|
4923
5005
|
children: /* @__PURE__ */ jsxs21("table", { className: "w-full border-collapse text-sm", children: [
|
|
4924
|
-
/* @__PURE__ */
|
|
4925
|
-
showSelectionColumn && /* @__PURE__ */
|
|
5006
|
+
/* @__PURE__ */ jsx35("thead", { ref: theadRef, children: /* @__PURE__ */ jsxs21("tr", { className: "divide-x divide-border", children: [
|
|
5007
|
+
showSelectionColumn && /* @__PURE__ */ jsx35(
|
|
4926
5008
|
"th",
|
|
4927
5009
|
{
|
|
4928
5010
|
className: "sticky top-0 z-20 border-b border-border bg-muted p-1",
|
|
4929
5011
|
style: { width: SELECTION_COLUMN_WIDTH },
|
|
4930
|
-
children: /* @__PURE__ */
|
|
5012
|
+
children: /* @__PURE__ */ jsx35(
|
|
4931
5013
|
Checkbox,
|
|
4932
5014
|
{
|
|
4933
5015
|
"aria-label": "Select all visible rows",
|
|
@@ -4937,7 +5019,7 @@ function TreeDataGrid({
|
|
|
4937
5019
|
)
|
|
4938
5020
|
}
|
|
4939
5021
|
),
|
|
4940
|
-
visibleColumns.map((column) => /* @__PURE__ */
|
|
5022
|
+
visibleColumns.map((column) => /* @__PURE__ */ jsx35(
|
|
4941
5023
|
"th",
|
|
4942
5024
|
{
|
|
4943
5025
|
style: column.width ? { width: column.width } : void 0,
|
|
@@ -4949,15 +5031,15 @@ function TreeDataGrid({
|
|
|
4949
5031
|
},
|
|
4950
5032
|
column.id
|
|
4951
5033
|
)),
|
|
4952
|
-
showRowActionsColumn && /* @__PURE__ */
|
|
5034
|
+
showRowActionsColumn && /* @__PURE__ */ jsx35("th", { className: "sticky top-0 z-20 border-b border-border bg-muted p-2", "aria-label": "Row actions" })
|
|
4953
5035
|
] }) }),
|
|
4954
|
-
/* @__PURE__ */
|
|
4955
|
-
/* @__PURE__ */
|
|
5036
|
+
/* @__PURE__ */ jsx35("tbody", { children: data.length === 0 ? /* @__PURE__ */ jsx35("tr", { children: /* @__PURE__ */ jsx35("td", { colSpan: totalColumnCount, className: "p-4 text-center text-muted-foreground", children: loading ? /* @__PURE__ */ jsxs21("span", { className: "inline-flex items-center gap-2", children: [
|
|
5037
|
+
/* @__PURE__ */ jsx35(Loader22, { className: "h-4 w-4 animate-spin", "aria-hidden": "true" }),
|
|
4956
5038
|
"Loading..."
|
|
4957
5039
|
] }) : "No results." }) }) : groupedBuckets ? groupedBuckets.map((bucket) => {
|
|
4958
5040
|
const groupExpanded = isGroupExpanded(bucket.key);
|
|
4959
5041
|
return /* @__PURE__ */ jsxs21(Fragment5, { children: [
|
|
4960
|
-
/* @__PURE__ */
|
|
5042
|
+
/* @__PURE__ */ jsx35("tr", { "data-testid": `group-header-${bucket.key}`, children: /* @__PURE__ */ jsx35(
|
|
4961
5043
|
"td",
|
|
4962
5044
|
{
|
|
4963
5045
|
colSpan: totalColumnCount,
|
|
@@ -4974,7 +5056,7 @@ function TreeDataGrid({
|
|
|
4974
5056
|
onClick: () => toggleGroupExpanded(bucket.key),
|
|
4975
5057
|
"aria-expanded": groupExpanded,
|
|
4976
5058
|
children: [
|
|
4977
|
-
/* @__PURE__ */
|
|
5059
|
+
/* @__PURE__ */ jsx35(
|
|
4978
5060
|
ChevronRight2,
|
|
4979
5061
|
{
|
|
4980
5062
|
className: `h-4 w-4 shrink-0 transition-transform${groupExpanded ? " rotate-90" : ""}`,
|
|
@@ -4993,7 +5075,7 @@ function TreeDataGrid({
|
|
|
4993
5075
|
"data-testid": `group-summary-${bucket.key}`,
|
|
4994
5076
|
className: "border-b border-border divide-x divide-border",
|
|
4995
5077
|
children: [
|
|
4996
|
-
showSelectionColumn && /* @__PURE__ */
|
|
5078
|
+
showSelectionColumn && /* @__PURE__ */ jsx35(
|
|
4997
5079
|
"td",
|
|
4998
5080
|
{
|
|
4999
5081
|
className: cn("p-2", zebra ? "bg-muted" : "bg-background"),
|
|
@@ -5001,7 +5083,7 @@ function TreeDataGrid({
|
|
|
5001
5083
|
}
|
|
5002
5084
|
),
|
|
5003
5085
|
renderGroupSummaryCells(bucket.roots),
|
|
5004
|
-
showRowActionsColumn && /* @__PURE__ */
|
|
5086
|
+
showRowActionsColumn && /* @__PURE__ */ jsx35("td", { className: cn("p-2", zebra ? "bg-muted" : "bg-background"), "aria-hidden": true })
|
|
5005
5087
|
]
|
|
5006
5088
|
}
|
|
5007
5089
|
),
|
|
@@ -5011,11 +5093,11 @@ function TreeDataGrid({
|
|
|
5011
5093
|
})()
|
|
5012
5094
|
] }, `group-${bucket.key}`);
|
|
5013
5095
|
}) : shouldVirtualize ? /* @__PURE__ */ jsxs21(Fragment6, { children: [
|
|
5014
|
-
paddingTop > 0 && /* @__PURE__ */
|
|
5096
|
+
paddingTop > 0 && /* @__PURE__ */ jsx35("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx35("td", { colSpan: totalColumnCount, style: { padding: 0, border: "none", height: paddingTop } }) }),
|
|
5015
5097
|
virtualItems.map(
|
|
5016
5098
|
(virtualItem) => renderRow(flatRows[virtualItem.index], virtualItem.index, (el) => virtualizer.measureElement(el))
|
|
5017
5099
|
),
|
|
5018
|
-
paddingBottom > 0 && /* @__PURE__ */
|
|
5100
|
+
paddingBottom > 0 && /* @__PURE__ */ jsx35("tr", { "aria-hidden": "true", children: /* @__PURE__ */ jsx35(
|
|
5019
5101
|
"td",
|
|
5020
5102
|
{
|
|
5021
5103
|
colSpan: totalColumnCount,
|
|
@@ -5030,15 +5112,15 @@ function TreeDataGrid({
|
|
|
5030
5112
|
// "roots only" scope `groupBy` itself uses, and for the same
|
|
5031
5113
|
// reason (a child's value is usually already folded into its
|
|
5032
5114
|
// parent's).
|
|
5033
|
-
/* @__PURE__ */
|
|
5034
|
-
showSelectionColumn && /* @__PURE__ */
|
|
5115
|
+
/* @__PURE__ */ jsx35("tfoot", { children: /* @__PURE__ */ jsxs21("tr", { "data-testid": "totals-row", className: "divide-x divide-border", children: [
|
|
5116
|
+
showSelectionColumn && /* @__PURE__ */ jsx35(
|
|
5035
5117
|
"td",
|
|
5036
5118
|
{
|
|
5037
5119
|
className: "sticky bottom-0 z-20 border-t border-border bg-muted p-2",
|
|
5038
5120
|
style: { width: SELECTION_COLUMN_WIDTH }
|
|
5039
5121
|
}
|
|
5040
5122
|
),
|
|
5041
|
-
visibleColumns.map((column) => /* @__PURE__ */
|
|
5123
|
+
visibleColumns.map((column) => /* @__PURE__ */ jsx35(
|
|
5042
5124
|
"td",
|
|
5043
5125
|
{
|
|
5044
5126
|
style: column.width ? { width: column.width } : void 0,
|
|
@@ -5050,7 +5132,7 @@ function TreeDataGrid({
|
|
|
5050
5132
|
},
|
|
5051
5133
|
column.id
|
|
5052
5134
|
)),
|
|
5053
|
-
showRowActionsColumn && /* @__PURE__ */
|
|
5135
|
+
showRowActionsColumn && /* @__PURE__ */ jsx35("td", { className: "sticky bottom-0 z-20 border-t border-border bg-muted p-2", "aria-hidden": true })
|
|
5054
5136
|
] }) })
|
|
5055
5137
|
] })
|
|
5056
5138
|
}
|
|
@@ -5069,6 +5151,7 @@ export {
|
|
|
5069
5151
|
EditingBar,
|
|
5070
5152
|
EnumEditor,
|
|
5071
5153
|
EnumFilter,
|
|
5154
|
+
FilterLabelsProvider,
|
|
5072
5155
|
MultilineStringEditor,
|
|
5073
5156
|
NumberComparisonFilter,
|
|
5074
5157
|
NumberEditor,
|
|
@@ -5089,6 +5172,7 @@ export {
|
|
|
5089
5172
|
computeFillChanges,
|
|
5090
5173
|
countVisible,
|
|
5091
5174
|
defaultAlign,
|
|
5175
|
+
defaultFilterLabels,
|
|
5092
5176
|
defaultFormat,
|
|
5093
5177
|
editErrorId,
|
|
5094
5178
|
evaluateFilter,
|
|
@@ -5105,6 +5189,7 @@ export {
|
|
|
5105
5189
|
isFilterDescriptor,
|
|
5106
5190
|
isFilterable,
|
|
5107
5191
|
isSortable,
|
|
5192
|
+
mergeFilterLabels,
|
|
5108
5193
|
moveColumnBefore,
|
|
5109
5194
|
normalizeRange,
|
|
5110
5195
|
orderStorageKeyFor,
|
|
@@ -5122,6 +5207,7 @@ export {
|
|
|
5122
5207
|
useCellSelection,
|
|
5123
5208
|
useDebouncedCallback,
|
|
5124
5209
|
useEditingState,
|
|
5210
|
+
useFilterLabels,
|
|
5125
5211
|
useGridState,
|
|
5126
5212
|
useGroupExpansion,
|
|
5127
5213
|
useStickyGroupHeaderTop,
|