@tulipfarm/sprout 0.3.0 → 0.4.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 +45 -40
- package/dist/components/accordion.d.ts +2 -2
- package/dist/components/accordion.js +9 -9
- package/dist/components/agent-fanout.d.ts +2 -2
- package/dist/components/agent-fanout.js +65 -87
- package/dist/components/alert-dialog.d.ts +6 -6
- package/dist/components/alert-dialog.js +20 -20
- package/dist/components/alert.d.ts +6 -6
- package/dist/components/alert.js +13 -13
- package/dist/components/aspect-ratio.d.ts +2 -2
- package/dist/components/aspect-ratio.js +2 -2
- package/dist/components/attachment.d.ts +17 -17
- package/dist/components/attachment.js +82 -115
- package/dist/components/avatar.d.ts +10 -10
- package/dist/components/avatar.js +14 -14
- package/dist/components/badge.d.ts +4 -4
- package/dist/components/badge.js +18 -18
- package/dist/components/board.d.ts +107 -0
- package/dist/components/board.js +640 -0
- package/dist/components/brand-icon.d.ts +6 -6
- package/dist/components/brand-icon.js +55 -63
- package/dist/components/breadcrumb.d.ts +11 -11
- package/dist/components/breadcrumb.js +16 -18
- package/dist/components/button-group.d.ts +6 -6
- package/dist/components/button-group.js +14 -14
- package/dist/components/button.d.ts +11 -11
- package/dist/components/button.js +46 -56
- package/dist/components/calendar.d.ts +5 -5
- package/dist/components/calendar.js +44 -53
- package/dist/components/canvas.d.ts +4 -4
- package/dist/components/canvas.js +39 -46
- package/dist/components/card.d.ts +6 -6
- package/dist/components/card.js +17 -17
- package/dist/components/carousel.d.ts +7 -7
- package/dist/components/carousel.js +57 -75
- package/dist/components/chart.d.ts +5 -112
- package/dist/components/chart.js +5 -172
- package/dist/components/chat-confirmation.d.ts +13 -11
- package/dist/components/chat-confirmation.js +32 -38
- package/dist/components/chat-input.d.ts +4 -4
- package/dist/components/chat-input.js +74 -81
- package/dist/components/chat-plan.d.ts +2 -2
- package/dist/components/chat-plan.js +15 -20
- package/dist/components/chat-sources.d.ts +8 -8
- package/dist/components/chat-sources.js +18 -27
- package/dist/components/checkbox.d.ts +1 -1
- package/dist/components/checkbox.js +9 -9
- package/dist/components/choice-list.d.ts +2 -2
- package/dist/components/choice-list.js +16 -18
- package/dist/components/code-block.d.ts +5 -5
- package/dist/components/code-block.js +26 -26
- package/dist/components/collapsible.d.ts +1 -1
- package/dist/components/collapsible.js +7 -11
- package/dist/components/combobox.d.ts +3 -3
- package/dist/components/combobox.js +24 -24
- package/dist/components/command.d.ts +13 -13
- package/dist/components/command.js +61 -73
- package/dist/components/context-menu.d.ts +5 -5
- package/dist/components/context-menu.js +22 -22
- package/dist/components/dialog.d.ts +6 -6
- package/dist/components/dialog.js +23 -28
- package/dist/components/direction.d.ts +1 -1
- package/dist/components/direction.js +1 -1
- package/dist/components/dropdown-menu.d.ts +5 -5
- package/dist/components/dropdown-menu.js +20 -20
- package/dist/components/field.d.ts +11 -11
- package/dist/components/field.js +41 -61
- package/dist/components/file-explorer.d.ts +2 -2
- package/dist/components/file-explorer.js +89 -105
- package/dist/components/file-viewer.d.ts +10 -10
- package/dist/components/file-viewer.js +112 -140
- package/dist/components/form.d.ts +7 -7
- package/dist/components/form.js +24 -28
- package/dist/components/glass-banner.d.ts +3 -3
- package/dist/components/glass-banner.js +21 -24
- package/dist/components/gradient-banner.d.ts +5 -5
- package/dist/components/gradient-banner.js +13 -22
- package/dist/components/hover-card.d.ts +4 -4
- package/dist/components/hover-card.js +6 -6
- package/dist/components/input-group.d.ts +11 -11
- package/dist/components/input-group.js +22 -36
- package/dist/components/input-otp.d.ts +10 -10
- package/dist/components/input-otp.js +13 -15
- package/dist/components/input.d.ts +1 -1
- package/dist/components/input.js +7 -7
- package/dist/components/kbd.d.ts +3 -3
- package/dist/components/kbd.js +5 -5
- package/dist/components/label.d.ts +2 -2
- package/dist/components/label.js +2 -2
- package/dist/components/mention-list.d.ts +3 -3
- package/dist/components/mention-list.js +10 -10
- package/dist/components/menubar.d.ts +6 -6
- package/dist/components/menubar.js +22 -22
- package/dist/components/message-actions.d.ts +2 -2
- package/dist/components/message-actions.js +29 -31
- package/dist/components/message-response.d.ts +3 -3
- package/dist/components/message-response.js +18 -18
- package/dist/components/message-scroller.d.ts +12 -12
- package/dist/components/message-scroller.js +44 -56
- package/dist/components/message.d.ts +11 -11
- package/dist/components/message.js +25 -25
- package/dist/components/navigation-menu.d.ts +2 -2
- package/dist/components/navigation-menu.js +15 -15
- package/dist/components/notice-banner.d.ts +2 -2
- package/dist/components/notice-banner.js +2 -2
- package/dist/components/page-content.d.ts +2 -2
- package/dist/components/page-content.js +2 -2
- package/dist/components/page-header.d.ts +1 -1
- package/dist/components/page-header.js +16 -16
- package/dist/components/pagination.d.ts +9 -9
- package/dist/components/pagination.js +17 -17
- package/dist/components/plan-outline.d.ts +2 -2
- package/dist/components/plan-outline.js +43 -60
- package/dist/components/popover.d.ts +6 -6
- package/dist/components/popover.js +15 -15
- package/dist/components/presence-cursor.d.ts +2 -2
- package/dist/components/presence-cursor.js +3 -3
- package/dist/components/progress.d.ts +1 -1
- package/dist/components/progress.js +8 -8
- package/dist/components/prompt-list.d.ts +3 -3
- package/dist/components/prompt-list.js +6 -6
- package/dist/components/questionnaire.d.ts +19 -19
- package/dist/components/questionnaire.js +183 -242
- package/dist/components/radio-group.d.ts +2 -2
- package/dist/components/radio-group.js +6 -6
- package/dist/components/reasoning-effort.d.ts +3 -3
- package/dist/components/reasoning-effort.js +9 -12
- package/dist/components/record-list.d.ts +66 -0
- package/dist/components/record-list.js +151 -0
- package/dist/components/resizable.d.ts +5 -5
- package/dist/components/resizable.js +76 -102
- package/dist/components/result-card.d.ts +10 -5
- package/dist/components/result-card.js +42 -53
- package/dist/components/result-notice.d.ts +18 -0
- package/dist/components/result-notice.js +29 -0
- package/dist/components/review-card.d.ts +6 -6
- package/dist/components/review-card.js +18 -18
- package/dist/components/rich-text-editor.d.ts +2 -2
- package/dist/components/rich-text-editor.js +56 -72
- package/dist/components/schema-diagram.d.ts +3 -3
- package/dist/components/schema-diagram.js +39 -53
- package/dist/components/scroll-area.d.ts +1 -1
- package/dist/components/scroll-area.js +10 -14
- package/dist/components/search-dialog.d.ts +6 -6
- package/dist/components/search-dialog.js +16 -16
- package/dist/components/search-field.d.ts +1 -1
- package/dist/components/search-field.js +11 -11
- package/dist/components/select.d.ts +3 -3
- package/dist/components/select.js +20 -20
- package/dist/components/selection-slot.d.ts +2 -2
- package/dist/components/selection-slot.js +6 -9
- package/dist/components/separator.d.ts +15 -15
- package/dist/components/separator.js +22 -27
- package/dist/components/settings-list.d.ts +3 -3
- package/dist/components/settings-list.js +5 -5
- package/dist/components/sheet.d.ts +6 -6
- package/dist/components/sheet.js +27 -27
- package/dist/components/sidebar.d.ts +22 -22
- package/dist/components/sidebar.js +57 -58
- package/dist/components/skeleton.d.ts +5 -5
- package/dist/components/skeleton.js +14 -21
- package/dist/components/slider.d.ts +2 -2
- package/dist/components/slider.js +6 -6
- package/dist/components/spinner.d.ts +5 -5
- package/dist/components/spinner.js +22 -26
- package/dist/components/sql-viewer.d.ts +14 -14
- package/dist/components/sql-viewer.js +99 -128
- package/dist/components/state-panel-samples.d.ts +2 -2
- package/dist/components/state-panel-samples.js +209 -245
- package/dist/components/state-panel.d.ts +2 -35
- package/dist/components/state-panel.js +2 -29
- package/dist/components/state-sample.d.ts +7 -7
- package/dist/components/state-sample.js +18 -31
- package/dist/components/switch.d.ts +1 -1
- package/dist/components/switch.js +7 -7
- package/dist/components/table-nuqs.d.ts +2 -2
- package/dist/components/table-nuqs.js +11 -12
- package/dist/components/table.d.ts +4 -4
- package/dist/components/table.js +166 -235
- package/dist/components/tabs.d.ts +2 -2
- package/dist/components/tabs.js +12 -12
- package/dist/components/textarea.d.ts +2 -2
- package/dist/components/textarea.js +6 -8
- package/dist/components/timeline.d.ts +3 -0
- package/dist/components/timeline.js +3 -0
- package/dist/components/toast.d.ts +2 -2
- package/dist/components/toast.js +19 -25
- package/dist/components/toggle-group.d.ts +2 -2
- package/dist/components/toggle-group.js +18 -20
- package/dist/components/toggle.d.ts +2 -2
- package/dist/components/toggle.js +8 -8
- package/dist/components/tool-activity.d.ts +1 -1
- package/dist/components/tool-activity.js +83 -110
- package/dist/components/toolbar-status.d.ts +2 -2
- package/dist/components/toolbar-status.js +7 -7
- package/dist/components/tooltip.d.ts +5 -5
- package/dist/components/tooltip.js +12 -11
- package/dist/components/typed-text.d.ts +2 -2
- package/dist/components/typed-text.js +10 -12
- package/dist/components/view-switcher.d.ts +51 -0
- package/dist/components/view-switcher.js +114 -0
- package/dist/index.d.ts +98 -93
- package/dist/index.js +98 -93
- package/dist/internal/chart-kit.d.ts +142 -0
- package/dist/internal/chart-kit.js +200 -0
- package/dist/internal/charts/bars.d.ts +61 -0
- package/dist/internal/charts/bars.js +86 -0
- package/dist/internal/charts/lines.d.ts +67 -0
- package/dist/internal/charts/lines.js +70 -0
- package/dist/internal/charts/more.d.ts +77 -0
- package/dist/internal/charts/more.js +68 -0
- package/dist/internal/charts/parts.d.ts +54 -0
- package/dist/internal/charts/parts.js +82 -0
- package/dist/internal/charts/timeline-dates.d.ts +38 -0
- package/dist/internal/charts/timeline-dates.js +113 -0
- package/dist/internal/charts/timeline-window.d.ts +31 -0
- package/dist/internal/charts/timeline-window.js +26 -0
- package/dist/internal/charts/timeline.d.ts +72 -0
- package/dist/internal/charts/timeline.js +287 -0
- package/dist/internal/classes.d.ts +1 -1
- package/dist/internal/classes.js +7 -9
- package/dist/internal/code-tokens.d.ts +2 -2
- package/dist/internal/code-tokens.js +12 -12
- package/dist/internal/fieldset.d.ts +1 -1
- package/dist/internal/fieldset.js +6 -6
- package/dist/internal/file-kind.d.ts +1 -1
- package/dist/internal/file-kind.js +43 -51
- package/dist/internal/flow.d.ts +4 -4
- package/dist/internal/flow.js +20 -23
- package/dist/internal/languages.js +999 -999
- package/dist/internal/message-scroller.d.ts +3 -3
- package/dist/internal/message-scroller.js +64 -112
- package/dist/internal/pressable.d.ts +1 -1
- package/dist/internal/pressable.js +7 -7
- package/dist/internal/state-panel.d.ts +35 -0
- package/dist/internal/state-panel.js +22 -0
- package/dist/internal/syntax.d.ts +2 -2
- package/dist/internal/syntax.js +36 -47
- package/dist/styles/accordion.css +3 -5
- package/dist/styles/agent-fanout.css +64 -60
- package/dist/styles/alert-dialog.css +12 -26
- package/dist/styles/alert.css +10 -15
- package/dist/styles/attachment.css +51 -93
- package/dist/styles/avatar.css +17 -24
- package/dist/styles/badge.css +11 -36
- package/dist/styles/board.css +571 -0
- package/dist/styles/brand-icon.css +7 -8
- package/dist/styles/breadcrumb.css +4 -7
- package/dist/styles/button-group.css +8 -14
- package/dist/styles/button.css +22 -27
- package/dist/styles/calendar.css +24 -36
- package/dist/styles/canvas.css +2 -3
- package/dist/styles/card.css +7 -23
- package/dist/styles/carousel.css +11 -12
- package/dist/styles/chart.css +215 -31
- package/dist/styles/chat-input.css +15 -39
- package/dist/styles/chat-plan.css +3 -4
- package/dist/styles/chat-sources.css +3 -6
- package/dist/styles/checkbox.css +11 -25
- package/dist/styles/choice-list.css +17 -31
- package/dist/styles/code-block.css +11 -25
- package/dist/styles/collapsible.css +10 -15
- package/dist/styles/combobox.css +11 -15
- package/dist/styles/command.css +5 -8
- package/dist/styles/context-menu.css +2 -2
- package/dist/styles/dialog.css +5 -16
- package/dist/styles/dropdown-menu.css +2 -2
- package/dist/styles/field.css +15 -21
- package/dist/styles/file-explorer.css +19 -33
- package/dist/styles/file-viewer.css +13 -17
- package/dist/styles/form.css +3 -3
- package/dist/styles/glass-banner.css +12 -47
- package/dist/styles/gradient-banner.css +17 -35
- package/dist/styles/hover-card.css +9 -15
- package/dist/styles/index.css +116 -108
- package/dist/styles/input-group.css +25 -41
- package/dist/styles/input-otp.css +5 -6
- package/dist/styles/input.css +5 -5
- package/dist/styles/kbd.css +1 -1
- package/dist/styles/label.css +9 -30
- package/dist/styles/mention-list.css +6 -8
- package/dist/styles/menubar.css +5 -6
- package/dist/styles/message-actions.css +1 -1
- package/dist/styles/message-response.css +3 -5
- package/dist/styles/message-scroller.css +14 -21
- package/dist/styles/message.css +23 -60
- package/dist/styles/navigation-menu.css +14 -29
- package/dist/styles/notice-banner.css +1 -2
- package/dist/styles/page-header.css +7 -10
- package/dist/styles/pagination.css +1 -4
- package/dist/styles/plan-outline.css +20 -37
- package/dist/styles/popover.css +10 -19
- package/dist/styles/presence-cursor.css +1 -2
- package/dist/styles/progress.css +2 -4
- package/dist/styles/prompt-list.css +6 -17
- package/dist/styles/questionnaire.css +16 -40
- package/dist/styles/radio-group.css +12 -23
- package/dist/styles/reasoning-effort.css +8 -15
- package/dist/styles/record-list.css +243 -0
- package/dist/styles/resizable.css +10 -11
- package/dist/styles/result-card.css +17 -3
- package/dist/styles/result-notice.css +80 -0
- package/dist/styles/review-card.css +2 -3
- package/dist/styles/rich-text-editor.css +1 -2
- package/dist/styles/schema-diagram.css +12 -17
- package/dist/styles/scroll-area.css +8 -10
- package/dist/styles/search-dialog.css +1 -5
- package/dist/styles/search-field.css +1 -2
- package/dist/styles/select.css +7 -7
- package/dist/styles/selection-slot.css +1 -2
- package/dist/styles/separator.css +7 -8
- package/dist/styles/settings-list.css +1 -2
- package/dist/styles/sheet.css +40 -73
- package/dist/styles/sidebar.css +17 -21
- package/dist/styles/skeleton.css +9 -11
- package/dist/styles/slider.css +11 -21
- package/dist/styles/spinner.css +2 -2
- package/dist/styles/sql-viewer.css +29 -29
- package/dist/styles/state-panel.css +8 -9
- package/dist/styles/state-sample.css +20 -33
- package/dist/styles/switch.css +11 -18
- package/dist/styles/table.css +51 -77
- package/dist/styles/tabs.css +12 -16
- package/dist/styles/textarea.css +3 -3
- package/dist/styles/themes/chatgpt.css +11 -23
- package/dist/styles/themes/claude.css +12 -24
- package/dist/styles/themes/cloudflare.css +11 -23
- package/dist/styles/themes/discord.css +11 -23
- package/dist/styles/themes/github.css +11 -23
- package/dist/styles/themes/grok.css +11 -23
- package/dist/styles/themes/linear.css +12 -25
- package/dist/styles/themes/neutral.css +11 -23
- package/dist/styles/themes/notion.css +11 -23
- package/dist/styles/themes/perplexity.css +11 -23
- package/dist/styles/themes/raycast.css +11 -23
- package/dist/styles/themes/spotify.css +11 -23
- package/dist/styles/themes/stripe.css +11 -23
- package/dist/styles/themes/supabase.css +11 -23
- package/dist/styles/themes/tulipfarm.css +9 -10
- package/dist/styles/themes/vercel.css +12 -25
- package/dist/styles/timeline.css +276 -0
- package/dist/styles/toast.css +13 -20
- package/dist/styles/toggle-group.css +17 -23
- package/dist/styles/toggle.css +8 -8
- package/dist/styles/tool-activity.css +7 -13
- package/dist/styles/toolbar-status.css +2 -7
- package/dist/styles/tooltip.css +15 -21
- package/dist/styles/view-switcher.css +279 -0
- package/package.json +21 -1
package/dist/components/table.js
CHANGED
|
@@ -1,63 +1,45 @@
|
|
|
1
|
-
|
|
1
|
+
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { createContext, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState, } from
|
|
4
|
-
import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors, } from
|
|
5
|
-
import { SortableContext, arrayMove, horizontalListSortingStrategy, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy, } from
|
|
6
|
-
import { CSS } from
|
|
7
|
-
import { aggregationFn_count, aggregationFn_max, aggregationFn_mean, aggregationFn_min, aggregationFn_sum, columnFilteringFeature, columnGroupingFeature, columnOrderingFeature, columnPinningFeature, columnResizingFeature, columnSizingFeature, columnVisibilityFeature, constructFilterFn, createExpandedRowModel, createFilteredRowModel, createGroupedRowModel, createPaginatedRowModel, createSortedRowModel, filterFn_equals, filterFn_inDateRange, filterFn_inNumberRange, filterFn_includesString, functionalUpdate, globalFilteringFeature, rowAggregationFeature, rowExpandingFeature, rowPaginationFeature, rowSelectionFeature, rowSortingFeature, sortFn_alphanumeric, sortFn_basic, sortFn_datetime, sortFn_text, tableFeatures, useTable, } from
|
|
8
|
-
import { useVirtualizer } from
|
|
9
|
-
import { ArrowDown } from
|
|
10
|
-
import { ArrowUp } from
|
|
11
|
-
import { ChevronDown } from
|
|
12
|
-
import { ChevronRight } from
|
|
13
|
-
import { InfoCircle } from
|
|
14
|
-
import { Plus } from
|
|
15
|
-
import { Reorder } from
|
|
16
|
-
import { SortV } from
|
|
17
|
-
import { X } from
|
|
18
|
-
import { cn } from
|
|
19
|
-
import { Button } from
|
|
20
|
-
import { Checkbox } from
|
|
21
|
-
import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, } from
|
|
22
|
-
import { Input } from
|
|
23
|
-
import { Popover, PopoverContent, PopoverTrigger } from
|
|
24
|
-
import { ScrollArea } from
|
|
25
|
-
import { SearchField } from
|
|
26
|
-
import { Skeleton } from
|
|
27
|
-
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger
|
|
28
|
-
export const tableVariantNames = [
|
|
29
|
-
export const tableNarrowNames = [
|
|
30
|
-
export const tableAlignNames = [
|
|
31
|
-
export const tableFilterNames = [
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
"select",
|
|
35
|
-
"date",
|
|
36
|
-
"boolean",
|
|
37
|
-
];
|
|
38
|
-
export const tableEditNames = [
|
|
39
|
-
"text",
|
|
40
|
-
"number",
|
|
41
|
-
"select",
|
|
42
|
-
"date",
|
|
43
|
-
"checkbox",
|
|
44
|
-
];
|
|
45
|
-
export const tableAggregateNames = [
|
|
46
|
-
"sum",
|
|
47
|
-
"count",
|
|
48
|
-
"min",
|
|
49
|
-
"max",
|
|
50
|
-
"mean",
|
|
51
|
-
];
|
|
3
|
+
import { createContext, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
|
|
4
|
+
import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors, } from '@dnd-kit/core';
|
|
5
|
+
import { SortableContext, arrayMove, horizontalListSortingStrategy, sortableKeyboardCoordinates, useSortable, verticalListSortingStrategy, } from '@dnd-kit/sortable';
|
|
6
|
+
import { CSS } from '@dnd-kit/utilities';
|
|
7
|
+
import { aggregationFn_count, aggregationFn_max, aggregationFn_mean, aggregationFn_min, aggregationFn_sum, columnFilteringFeature, columnGroupingFeature, columnOrderingFeature, columnPinningFeature, columnResizingFeature, columnSizingFeature, columnVisibilityFeature, constructFilterFn, createExpandedRowModel, createFilteredRowModel, createGroupedRowModel, createPaginatedRowModel, createSortedRowModel, filterFn_equals, filterFn_inDateRange, filterFn_inNumberRange, filterFn_includesString, functionalUpdate, globalFilteringFeature, rowAggregationFeature, rowExpandingFeature, rowPaginationFeature, rowSelectionFeature, rowSortingFeature, sortFn_alphanumeric, sortFn_basic, sortFn_datetime, sortFn_text, tableFeatures, useTable, } from '@tanstack/react-table';
|
|
8
|
+
import { useVirtualizer } from '@tanstack/react-virtual';
|
|
9
|
+
import { ArrowDown } from 'reicon-react/icons/ArrowDown';
|
|
10
|
+
import { ArrowUp } from 'reicon-react/icons/ArrowUp';
|
|
11
|
+
import { ChevronDown } from 'reicon-react/icons/ChevronDown';
|
|
12
|
+
import { ChevronRight } from 'reicon-react/icons/ChevronRight';
|
|
13
|
+
import { InfoCircle } from 'reicon-react/icons/InfoCircle';
|
|
14
|
+
import { Plus } from 'reicon-react/icons/Plus';
|
|
15
|
+
import { Reorder } from 'reicon-react/icons/Reorder';
|
|
16
|
+
import { SortV } from 'reicon-react/icons/SortV';
|
|
17
|
+
import { X } from 'reicon-react/icons/X';
|
|
18
|
+
import { cn } from '../internal/classes.js';
|
|
19
|
+
import { Button } from './button.js';
|
|
20
|
+
import { Checkbox } from './checkbox.js';
|
|
21
|
+
import { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuItem, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger, } from './dropdown-menu.js';
|
|
22
|
+
import { Input } from './input.js';
|
|
23
|
+
import { Popover, PopoverContent, PopoverTrigger } from './popover.js';
|
|
24
|
+
import { ScrollArea } from './scroll-area.js';
|
|
25
|
+
import { SearchField } from './search-field.js';
|
|
26
|
+
import { Skeleton } from './skeleton.js';
|
|
27
|
+
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from './tooltip.js';
|
|
28
|
+
export const tableVariantNames = ['plain', 'grid'];
|
|
29
|
+
export const tableNarrowNames = ['scroll', 'stack'];
|
|
30
|
+
export const tableAlignNames = ['left', 'right'];
|
|
31
|
+
export const tableFilterNames = ['text', 'number', 'select', 'date', 'boolean'];
|
|
32
|
+
export const tableEditNames = ['text', 'number', 'select', 'date', 'checkbox'];
|
|
33
|
+
export const tableAggregateNames = ['sum', 'count', 'min', 'max', 'mean'];
|
|
52
34
|
export const tableLayoutKeys = [
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
35
|
+
'columnSizing',
|
|
36
|
+
'columnOrder',
|
|
37
|
+
'columnPinning',
|
|
38
|
+
'columnVisibility',
|
|
57
39
|
];
|
|
58
40
|
// dnd-kit's live region is a div; inside <table> it breaks the table roles.
|
|
59
41
|
const dndAccessibility = {
|
|
60
|
-
container: typeof document ===
|
|
42
|
+
container: typeof document === 'undefined' ? undefined : document.body,
|
|
61
43
|
};
|
|
62
44
|
const isAnyOf = constructFilterFn({
|
|
63
45
|
filter: (dataValue, filterValue) => filterValue.includes(String(dataValue)),
|
|
@@ -104,34 +86,29 @@ const features = tableFeatures({
|
|
|
104
86
|
},
|
|
105
87
|
});
|
|
106
88
|
const filterFnFor = {
|
|
107
|
-
text:
|
|
108
|
-
number:
|
|
109
|
-
select:
|
|
110
|
-
date:
|
|
111
|
-
boolean:
|
|
89
|
+
text: 'includesString',
|
|
90
|
+
number: 'inNumberRange',
|
|
91
|
+
select: 'isAnyOf',
|
|
92
|
+
date: 'inDateRange',
|
|
93
|
+
boolean: 'equals',
|
|
112
94
|
};
|
|
113
95
|
const DEFAULT_PAGE_SIZE = 10;
|
|
114
|
-
const pageResetKeys = new Set([
|
|
115
|
-
"sorting",
|
|
116
|
-
"columnFilters",
|
|
117
|
-
"globalFilter",
|
|
118
|
-
"grouping",
|
|
119
|
-
]);
|
|
96
|
+
const pageResetKeys = new Set(['sorting', 'columnFilters', 'globalFilter', 'grouping']);
|
|
120
97
|
function initialState(columns, pageSize) {
|
|
121
98
|
return {
|
|
122
99
|
sorting: [],
|
|
123
100
|
columnFilters: [],
|
|
124
|
-
globalFilter:
|
|
101
|
+
globalFilter: '',
|
|
125
102
|
grouping: [],
|
|
126
103
|
expanded: true,
|
|
127
104
|
pagination: { pageIndex: 0, pageSize: pageSize ?? DEFAULT_PAGE_SIZE },
|
|
128
105
|
columnSizing: {},
|
|
129
106
|
columnOrder: [],
|
|
130
107
|
columnPinning: {
|
|
131
|
-
start: columns.filter(
|
|
132
|
-
end: columns.filter(
|
|
108
|
+
start: columns.filter(c => c.pin === 'left').map(c => c.key),
|
|
109
|
+
end: columns.filter(c => c.pin === 'right').map(c => c.key),
|
|
133
110
|
},
|
|
134
|
-
columnVisibility: Object.fromEntries(columns.filter(
|
|
111
|
+
columnVisibility: Object.fromEntries(columns.filter(c => c.hidden).map(c => [c.key, false])),
|
|
135
112
|
};
|
|
136
113
|
}
|
|
137
114
|
const storageKey = (key) => `sprout-table:${key}`;
|
|
@@ -146,7 +123,7 @@ function readLayout(key) {
|
|
|
146
123
|
}
|
|
147
124
|
function writeLayout(key, state) {
|
|
148
125
|
try {
|
|
149
|
-
localStorage.setItem(storageKey(key), JSON.stringify(Object.fromEntries(tableLayoutKeys.map(
|
|
126
|
+
localStorage.setItem(storageKey(key), JSON.stringify(Object.fromEntries(tableLayoutKeys.map(k => [k, state[k]]))));
|
|
150
127
|
}
|
|
151
128
|
catch {
|
|
152
129
|
// Storage can be full or blocked; the Layout then lasts for this visit only.
|
|
@@ -158,8 +135,8 @@ function writeLayout(key, state) {
|
|
|
158
135
|
* paging, Row edit, and Layout changes for you.
|
|
159
136
|
*/
|
|
160
137
|
export function Table(props) {
|
|
161
|
-
const { data, columns, getRowId, rowLabel = getRowId, variant =
|
|
162
|
-
const label = props[
|
|
138
|
+
const { data, columns, getRowId, rowLabel = getRowId, variant = 'plain', narrow = 'scroll', caption, manual = false, rowCount, onStateChange, persistKey, searchable = false, columnMenu = false, resizable = false, reorderable = false, selectable = false, onSelectionChange, pageSize, virtual = false, onRowReorder, getSubRows, onRowSave, getRowHref, onRowClick, onRowDrop, actions, loading = false, empty, className, } = props;
|
|
139
|
+
const label = props['aria-label'];
|
|
163
140
|
const [inner, setInner] = useState(() => initialState(columns, pageSize));
|
|
164
141
|
const state = { ...inner, ...props.state };
|
|
165
142
|
const stateRef = useRef(state);
|
|
@@ -175,7 +152,7 @@ export function Table(props) {
|
|
|
175
152
|
return;
|
|
176
153
|
const saved = readLayout(persistKey);
|
|
177
154
|
if (Object.keys(saved).length)
|
|
178
|
-
setInner(
|
|
155
|
+
setInner(prev => ({ ...prev, ...saved }));
|
|
179
156
|
}, [persistKey]);
|
|
180
157
|
const setSlice = (key) => (updater) => {
|
|
181
158
|
const next = {
|
|
@@ -192,10 +169,10 @@ export function Table(props) {
|
|
|
192
169
|
}
|
|
193
170
|
onStateChange?.(next);
|
|
194
171
|
};
|
|
195
|
-
const byKey = useMemo(() => new Map(columns.map(
|
|
172
|
+
const byKey = useMemo(() => new Map(columns.map(c => [c.key, c])), [columns]);
|
|
196
173
|
const columnDefs = useMemo(() => columns.map((c) => ({
|
|
197
174
|
id: c.key,
|
|
198
|
-
accessorFn:
|
|
175
|
+
accessorFn: row => row[c.key],
|
|
199
176
|
header: c.header,
|
|
200
177
|
enableSorting: c.sort ?? false,
|
|
201
178
|
sortDescFirst: false,
|
|
@@ -212,28 +189,28 @@ export function Table(props) {
|
|
|
212
189
|
getRowId,
|
|
213
190
|
...(getSubRows ? { getSubRows } : {}),
|
|
214
191
|
state: { ...state, rowSelection },
|
|
215
|
-
onSortingChange: setSlice(
|
|
216
|
-
onColumnFiltersChange: setSlice(
|
|
217
|
-
onGlobalFilterChange: setSlice(
|
|
218
|
-
onGroupingChange: setSlice(
|
|
219
|
-
onExpandedChange: setSlice(
|
|
220
|
-
onPaginationChange: setSlice(
|
|
221
|
-
onColumnSizingChange: setSlice(
|
|
222
|
-
onColumnOrderChange: setSlice(
|
|
223
|
-
onColumnPinningChange: setSlice(
|
|
224
|
-
onColumnVisibilityChange: setSlice(
|
|
225
|
-
onRowSelectionChange:
|
|
192
|
+
onSortingChange: setSlice('sorting'),
|
|
193
|
+
onColumnFiltersChange: setSlice('columnFilters'),
|
|
194
|
+
onGlobalFilterChange: setSlice('globalFilter'),
|
|
195
|
+
onGroupingChange: setSlice('grouping'),
|
|
196
|
+
onExpandedChange: setSlice('expanded'),
|
|
197
|
+
onPaginationChange: setSlice('pagination'),
|
|
198
|
+
onColumnSizingChange: setSlice('columnSizing'),
|
|
199
|
+
onColumnOrderChange: setSlice('columnOrder'),
|
|
200
|
+
onColumnPinningChange: setSlice('columnPinning'),
|
|
201
|
+
onColumnVisibilityChange: setSlice('columnVisibility'),
|
|
202
|
+
onRowSelectionChange: updater => {
|
|
226
203
|
const next = functionalUpdate(updater, rowSelection);
|
|
227
204
|
setRowSelection(next);
|
|
228
|
-
onSelectionChange?.(Object.keys(next).filter(
|
|
205
|
+
onSelectionChange?.(Object.keys(next).filter(id => next[id]));
|
|
229
206
|
},
|
|
230
|
-
globalFilterFn:
|
|
231
|
-
groupedColumnMode:
|
|
207
|
+
globalFilterFn: 'includesString',
|
|
208
|
+
groupedColumnMode: 'remove',
|
|
232
209
|
// The reset would use TanStack's empty default, closing every group on each search.
|
|
233
210
|
autoResetExpanded: false,
|
|
234
211
|
// TanStack resets on every new state array (inline or URL state) and never in manual mode; setSlice resets instead.
|
|
235
212
|
autoResetPageIndex: false,
|
|
236
|
-
columnResizeMode:
|
|
213
|
+
columnResizeMode: 'onChange',
|
|
237
214
|
enableMultiSort: true,
|
|
238
215
|
manualSorting: manual,
|
|
239
216
|
manualFiltering: manual,
|
|
@@ -247,43 +224,38 @@ export function Table(props) {
|
|
|
247
224
|
...table.getCenterVisibleLeafColumns(),
|
|
248
225
|
...table.getEndVisibleLeafColumns(),
|
|
249
226
|
];
|
|
250
|
-
const editable = !!onRowSave && columns.some(
|
|
227
|
+
const editable = !!onRowSave && columns.some(c => c.edit);
|
|
251
228
|
const hasActions = !!actions || editable;
|
|
252
229
|
const draggableRows = !!onRowReorder &&
|
|
253
230
|
state.sorting.length === 0 &&
|
|
254
231
|
state.grouping.length === 0 &&
|
|
255
232
|
state.columnFilters.length === 0 &&
|
|
256
233
|
!state.globalFilter;
|
|
257
|
-
const totals = columns.some(
|
|
258
|
-
const colSpan = leafColumns.length +
|
|
259
|
-
|
|
260
|
-
(onRowReorder ? 1 : 0) +
|
|
261
|
-
(hasActions ? 1 : 0);
|
|
262
|
-
const sized = resizable || columns.some((c) => c.width);
|
|
234
|
+
const totals = columns.some(c => c.aggregate) && !loading && rows.length > 0;
|
|
235
|
+
const colSpan = leafColumns.length + (selectable ? 1 : 0) + (onRowReorder ? 1 : 0) + (hasActions ? 1 : 0);
|
|
236
|
+
const sized = resizable || columns.some(c => c.width);
|
|
263
237
|
const pinsStart = !!state.columnPinning.start?.length;
|
|
264
238
|
const pinned = pinsStart || !!state.columnPinning.end?.length;
|
|
265
|
-
const pinLayout = `${leafColumns.map(
|
|
239
|
+
const pinLayout = `${leafColumns.map(c => `${c.id}:${c.getIsPinned()}`).join()}|${selectable}|${!!onRowReorder}|${hasActions}`;
|
|
266
240
|
useLayoutEffect(() => {
|
|
267
241
|
const row = headRowRef.current;
|
|
268
242
|
if (!pinned || !row)
|
|
269
243
|
return;
|
|
270
244
|
const observer = new ResizeObserver(() => {
|
|
271
245
|
const next = measurePinOffsets(Array.from(row.children));
|
|
272
|
-
setPinOffsets(
|
|
246
|
+
setPinOffsets(prev => (JSON.stringify(prev) === JSON.stringify(next) ? prev : next));
|
|
273
247
|
});
|
|
274
248
|
for (const cell of row.children)
|
|
275
249
|
observer.observe(cell);
|
|
276
250
|
return () => observer.disconnect();
|
|
277
251
|
}, [pinned, pinLayout]);
|
|
278
252
|
const selectRow = (row, checked, range) => {
|
|
279
|
-
const ids = rows
|
|
280
|
-
.filter((r) => !r.getIsGrouped() && r.getCanSelect())
|
|
281
|
-
.map((r) => r.id);
|
|
253
|
+
const ids = rows.filter(r => !r.getIsGrouped() && r.getCanSelect()).map(r => r.id);
|
|
282
254
|
const from = anchorRef.current ? ids.indexOf(anchorRef.current) : -1;
|
|
283
255
|
const to = ids.indexOf(row.id);
|
|
284
256
|
if (range && from !== -1 && to !== -1) {
|
|
285
257
|
const span = ids.slice(Math.min(from, to), Math.max(from, to) + 1);
|
|
286
|
-
table.setRowSelection(
|
|
258
|
+
table.setRowSelection(prev => {
|
|
287
259
|
const next = { ...prev };
|
|
288
260
|
for (const id of span) {
|
|
289
261
|
if (checked)
|
|
@@ -311,16 +283,12 @@ export function Table(props) {
|
|
|
311
283
|
initialRect: { width: 0, height: 600 },
|
|
312
284
|
});
|
|
313
285
|
const virtualItems = virtualizer.getVirtualItems();
|
|
314
|
-
const visibleRows = virtual
|
|
315
|
-
? virtualItems.flatMap((item) => rows[item.index] ?? [])
|
|
316
|
-
: rows;
|
|
286
|
+
const visibleRows = virtual ? virtualItems.flatMap(item => rows[item.index] ?? []) : rows;
|
|
317
287
|
const paddingTop = virtual ? (virtualItems[0]?.start ?? 0) : 0;
|
|
318
|
-
const paddingBottom = virtual
|
|
319
|
-
? virtualizer.getTotalSize() - (virtualItems.at(-1)?.end ?? 0)
|
|
320
|
-
: 0;
|
|
288
|
+
const paddingBottom = virtual ? virtualizer.getTotalSize() - (virtualItems.at(-1)?.end ?? 0) : 0;
|
|
321
289
|
const startEdit = (row) => setEditing({
|
|
322
290
|
id: row.id,
|
|
323
|
-
draft: Object.fromEntries(columns.filter(
|
|
291
|
+
draft: Object.fromEntries(columns.filter(c => c.edit).map(c => [c.key, row.original[c.key]])),
|
|
324
292
|
});
|
|
325
293
|
const saveEdit = async (row) => {
|
|
326
294
|
if (!editing || !onRowSave)
|
|
@@ -342,9 +310,7 @@ export function Table(props) {
|
|
|
342
310
|
const onColumnDragEnd = ({ active, over }) => {
|
|
343
311
|
if (!over || active.id === over.id)
|
|
344
312
|
return;
|
|
345
|
-
const order = state.columnOrder.length
|
|
346
|
-
? state.columnOrder
|
|
347
|
-
: table.getAllLeafColumns().map((c) => c.id);
|
|
313
|
+
const order = state.columnOrder.length ? state.columnOrder : table.getAllLeafColumns().map(c => c.id);
|
|
348
314
|
table.setColumnOrder(arrayMove(order, order.indexOf(String(active.id)), order.indexOf(String(over.id))));
|
|
349
315
|
};
|
|
350
316
|
const onRowDragEnd = ({ active, over }) => {
|
|
@@ -353,44 +319,38 @@ export function Table(props) {
|
|
|
353
319
|
const ids = data.map(getRowId);
|
|
354
320
|
onRowReorder(ids.indexOf(String(active.id)), ids.indexOf(String(over.id)));
|
|
355
321
|
};
|
|
356
|
-
const toolbar = searchable || columns.some(
|
|
322
|
+
const toolbar = searchable || columns.some(c => c.filter || c.group) || columnMenu;
|
|
357
323
|
const allPageSelected = table.getIsAllPageRowsSelected();
|
|
358
324
|
const somePageSelected = table.getIsSomePageRowsSelected();
|
|
359
|
-
const stack = narrow ===
|
|
325
|
+
const stack = narrow === 'stack';
|
|
360
326
|
const role = (value) => (stack ? value : undefined);
|
|
361
|
-
const header = (_jsx("thead", { "data-slot": "table-header", className: "sprout-table-header", role: role(
|
|
327
|
+
const header = (_jsx("thead", { "data-slot": "table-header", className: "sprout-table-header", role: role('rowgroup'), children: _jsx(DndContext, { sensors: sensors, accessibility: dndAccessibility, collisionDetection: closestCenter, onDragEnd: onColumnDragEnd, children: _jsx(SortableContext, { items: leafColumns.map(c => c.id), strategy: horizontalListSortingStrategy, children: _jsxs("tr", { ref: headRowRef, "data-slot": "table-row", className: "sprout-table-row", role: role('row'), children: [onRowReorder && (_jsx("th", { className: "sprout-table-head", "data-selection": "", "data-column-id": "__reorder", role: role('columnheader'), children: _jsx("span", { className: "sprout-table-sr-only", children: "Reorder" }) })), selectable && (_jsx("th", { className: "sprout-table-head", "data-selection": "", "data-column-id": "__select", role: role('columnheader'), children: _jsx(Checkbox, { "aria-label": "Select all rows", checked: allPageSelected, indeterminate: !allPageSelected && somePageSelected, onCheckedChange: checked => table.toggleAllPageRowsSelected(checked) }) })), table
|
|
362
328
|
.getFlatHeaders()
|
|
363
|
-
.map(
|
|
364
|
-
const body = (_jsxs("tbody", { "data-slot": "table-body", className: "sprout-table-body", role: role(
|
|
329
|
+
.map(h => h.column.getIsVisible() ? (_jsx(HeadCell, { header: h, config: byKey.get(h.column.id), resizable: resizable, reorderable: reorderable, sized: sized, role: role('columnheader') }, h.id)) : null), hasActions && (_jsx("th", { className: "sprout-table-head", "data-sticky-end": "", "data-column-id": "__actions", role: role('columnheader'), children: _jsx("span", { className: "sprout-table-sr-only", children: "Actions" }) }))] }) }) }) }));
|
|
330
|
+
const body = (_jsxs("tbody", { "data-slot": "table-body", className: "sprout-table-body", role: role('rowgroup'), children: [paddingTop > 0 && (_jsx("tr", { "aria-hidden": "true", children: _jsx("td", { colSpan: colSpan, style: { height: paddingTop, padding: 0 } }) })), loading ? (Array.from({ length: 3 }, (_, i) => (_jsxs("tr", { className: "sprout-table-row", "data-loading-row": "", role: role('row'), children: [onRowReorder && _jsx("td", { className: "sprout-table-cell", "data-selection": "" }), selectable && (_jsx("td", { className: "sprout-table-cell", "data-selection": "", children: _jsx(Skeleton, { shape: "checkbox" }) })), leafColumns.map(c => (_jsx("td", { className: "sprout-table-cell", role: role('cell'), children: _jsx(Skeleton, {}) }, c.id))), hasActions && (_jsx("td", { className: "sprout-table-cell", "data-sticky-end": "", children: _jsx(Skeleton, { shape: "action" }) }))] }, i)))) : rows.length === 0 ? (_jsx("tr", { className: "sprout-table-row", role: role('row'), children: _jsx("td", { className: "sprout-table-cell sprout-table-empty", colSpan: colSpan, role: role('cell'), children: empty ?? 'No results.' }) })) : (_jsx(DndContext, { sensors: sensors, accessibility: dndAccessibility, collisionDetection: closestCenter, onDragEnd: onRowDragEnd, children: _jsx(SortableContext, { items: rows.map(r => r.id), strategy: verticalListSortingStrategy, children: visibleRows.map(row => row.getIsGrouped() ? (_jsx(GroupRow, { row: row, columns: leafColumns, byKey: byKey, selectable: selectable, reorder: !!onRowReorder, hasActions: hasActions, rowIndex: virtual ? row.index + 2 : undefined, role: role }, row.id)) : (_jsx(BodyRow, { row: row, columns: leafColumns, byKey: byKey, label: rowLabel(row.original), selectable: selectable, onSelect: (checked, range) => selectRow(row, checked, range), reorder: onRowReorder ? draggableRows : undefined, editing: editing?.id === row.id ? editing : null, editable: editable, onEditChange: (key, value) => setEditing(prev => prev && {
|
|
365
331
|
...prev,
|
|
366
332
|
draft: { ...prev.draft, [key]: value },
|
|
367
333
|
}), onEdit: () => startEdit(row), onSave: () => void saveEdit(row), onCancel: () => setEditing(null), actions: actions, hasActions: hasActions, href: getRowHref?.(row.original), onOpen: onRowClick ? () => onRowClick(row.original) : undefined, drop: onRowDrop
|
|
368
334
|
? {
|
|
369
335
|
active: dropTarget === row.id,
|
|
370
|
-
set:
|
|
371
|
-
onDrop:
|
|
336
|
+
set: on => setDropTarget(on ? row.id : null),
|
|
337
|
+
onDrop: files => onRowDrop(row.original, files),
|
|
372
338
|
}
|
|
373
339
|
: undefined, colSpan: colSpan, rowIndex: virtual ? row.index + 2 : undefined, role: role }, row.id))) }) })), paddingBottom > 0 && (_jsx("tr", { "aria-hidden": "true", children: _jsx("td", { colSpan: colSpan, style: { height: paddingBottom, padding: 0 } }) }))] }));
|
|
374
|
-
const footer = totals && (_jsx("tfoot", { "data-slot": "table-footer", className: "sprout-table-footer", role: role(
|
|
340
|
+
const footer = totals && (_jsx("tfoot", { "data-slot": "table-footer", className: "sprout-table-footer", role: role('rowgroup'), children: _jsxs("tr", { className: "sprout-table-row", role: role('row'), children: [onRowReorder && _jsx("td", { className: "sprout-table-cell", "data-selection": "" }), selectable && _jsx("td", { className: "sprout-table-cell", "data-selection": "" }), leafColumns.map((c, index) => {
|
|
375
341
|
const config = byKey.get(c.id);
|
|
376
|
-
return (_jsx("td", { className: "sprout-table-cell", "data-align": config?.align ??
|
|
377
|
-
? formatAggregate(config, c.getAggregationValue())
|
|
378
|
-
: index === 0
|
|
379
|
-
? "Total"
|
|
380
|
-
: null }, c.id));
|
|
342
|
+
return (_jsx("td", { className: "sprout-table-cell", "data-align": config?.align ?? 'left', "data-label": config?.header, role: role('cell'), style: pinStyle(c, sized, pinOffsets), "data-pinned": c.getIsPinned() || undefined, children: config?.aggregate ? formatAggregate(config, c.getAggregationValue()) : index === 0 ? 'Total' : null }, c.id));
|
|
381
343
|
}), hasActions && _jsx("td", { className: "sprout-table-cell", "data-sticky-end": "" })] }) }));
|
|
382
|
-
const tableElement = (_jsxs("table", { "data-slot": "table", "data-variant": variant, "data-narrow": narrow, "data-sized": sized || undefined, "data-pin-start": pinsStart || undefined, className: "sprout-table", "aria-label": label, "aria-rowcount": virtual ? rows.length + 1 : undefined, "aria-busy": loading || undefined, role: role(
|
|
344
|
+
const tableElement = (_jsxs("table", { "data-slot": "table", "data-variant": variant, "data-narrow": narrow, "data-sized": sized || undefined, "data-pin-start": pinsStart || undefined, className: "sprout-table", "aria-label": label, "aria-rowcount": virtual ? rows.length + 1 : undefined, "aria-busy": loading || undefined, role: role('table'), style: {
|
|
383
345
|
...(sized ? { minWidth: table.getTotalSize() } : {}),
|
|
384
|
-
...(pinOffsets.__select !== undefined
|
|
385
|
-
? { "--sprout-table-select-start": `${pinOffsets.__select}px` }
|
|
386
|
-
: {}),
|
|
346
|
+
...(pinOffsets.__select !== undefined ? { '--sprout-table-select-start': `${pinOffsets.__select}px` } : {}),
|
|
387
347
|
}, children: [caption && (_jsx("caption", { "data-slot": "table-caption", className: "sprout-table-caption", children: caption })), _jsxs(PinOffsetsContext, { value: pinOffsets, children: [header, body] }), footer] }));
|
|
388
348
|
const pageCount = table.getPageCount();
|
|
389
|
-
return (_jsx(TooltipProvider, { children: _jsxs("div", { "data-slot": "table-root", className: cn(
|
|
349
|
+
return (_jsx(TooltipProvider, { children: _jsxs("div", { "data-slot": "table-root", className: cn('sprout-table-root', className), children: [toolbar && (_jsx(Toolbar, { table: table, columns: columns, label: label, searchable: searchable, columnMenu: columnMenu, onReset: () => {
|
|
390
350
|
const reset = initialState(columns, pageSize);
|
|
391
351
|
for (const key of tableLayoutKeys)
|
|
392
352
|
setSlice(key)(reset[key]);
|
|
393
|
-
} })), virtual ? (_jsx("div", { ref: scrollRef, "data-slot": "table-container", "data-virtual": "", className: "sprout-table-container", tabIndex: 0, role: "region", "aria-label": label, children: tableElement })) : variant ===
|
|
353
|
+
} })), virtual ? (_jsx("div", { ref: scrollRef, "data-slot": "table-container", "data-virtual": "", className: "sprout-table-container", tabIndex: 0, role: "region", "aria-label": label, children: tableElement })) : variant === 'grid' ? (_jsx(ScrollArea, { variant: "table", orientation: "both", viewportLabel: label, "data-slot": "table-container", children: tableElement })) : (_jsx(PlainContainer, { label: label, children: tableElement })), pageSize && pageCount > 1 && (_jsxs("nav", { className: "sprout-table-pages", "aria-label": `${label} pages`, children: [_jsxs("span", { "aria-live": "polite", children: ["Page ", state.pagination.pageIndex + 1, " of ", pageCount] }), _jsx(Button, { variant: "outline", size: "sm", disabled: !table.getCanPreviousPage(), onClick: () => table.previousPage(), children: "Previous" }), _jsx(Button, { variant: "outline", size: "sm", disabled: !table.getCanNextPage(), onClick: () => table.nextPage(), children: "Next" })] }))] }) }));
|
|
394
354
|
}
|
|
395
355
|
const PinOffsetsContext = createContext({});
|
|
396
356
|
/** Sticky offsets from the real header cell widths, so columns without a set width pin in the right place. */
|
|
@@ -399,8 +359,7 @@ function measurePinOffsets(cells) {
|
|
|
399
359
|
let start = 0;
|
|
400
360
|
for (const cell of cells) {
|
|
401
361
|
const id = cell.dataset.columnId;
|
|
402
|
-
if (!id ||
|
|
403
|
-
(cell.dataset.selection === undefined && cell.dataset.pinned !== "start"))
|
|
362
|
+
if (!id || (cell.dataset.selection === undefined && cell.dataset.pinned !== 'start'))
|
|
404
363
|
continue;
|
|
405
364
|
offsets[id] = start;
|
|
406
365
|
start += cell.getBoundingClientRect().width;
|
|
@@ -408,8 +367,7 @@ function measurePinOffsets(cells) {
|
|
|
408
367
|
let end = 0;
|
|
409
368
|
for (const cell of [...cells].reverse()) {
|
|
410
369
|
const id = cell.dataset.columnId;
|
|
411
|
-
if (!id ||
|
|
412
|
-
(cell.dataset.stickyEnd === undefined && cell.dataset.pinned !== "end"))
|
|
370
|
+
if (!id || (cell.dataset.stickyEnd === undefined && cell.dataset.pinned !== 'end'))
|
|
413
371
|
continue;
|
|
414
372
|
offsets[id] = end;
|
|
415
373
|
end += cell.getBoundingClientRect().width;
|
|
@@ -421,27 +379,25 @@ function pinStyle(column, sized, offsets) {
|
|
|
421
379
|
const width = sized ? column.getSize() : undefined;
|
|
422
380
|
if (!pinned)
|
|
423
381
|
return width ? { width } : undefined;
|
|
424
|
-
return pinned ===
|
|
382
|
+
return pinned === 'start'
|
|
425
383
|
? {
|
|
426
384
|
width,
|
|
427
|
-
insetInlineStart: offsets[column.id] ?? column.getStart(
|
|
385
|
+
insetInlineStart: offsets[column.id] ?? column.getStart('start'),
|
|
428
386
|
}
|
|
429
|
-
: { width, insetInlineEnd: offsets[column.id] ?? column.getAfter(
|
|
387
|
+
: { width, insetInlineEnd: offsets[column.id] ?? column.getAfter('end') };
|
|
430
388
|
}
|
|
431
389
|
function formatAggregate(config, value) {
|
|
432
|
-
if (typeof value !==
|
|
390
|
+
if (typeof value !== 'number')
|
|
433
391
|
return null;
|
|
434
|
-
return config.formatAggregate
|
|
435
|
-
? config.formatAggregate(value)
|
|
436
|
-
: value.toLocaleString();
|
|
392
|
+
return config.formatAggregate ? config.formatAggregate(value) : value.toLocaleString();
|
|
437
393
|
}
|
|
438
394
|
/** Joins the Tab order only while the table is wider than its container, so keyboard users can scroll it. */
|
|
439
|
-
function PlainContainer({ label, children
|
|
395
|
+
function PlainContainer({ label, children }) {
|
|
440
396
|
const ref = useRef(null);
|
|
441
397
|
const [overflowing, setOverflowing] = useState(false);
|
|
442
398
|
useEffect(() => {
|
|
443
399
|
const element = ref.current;
|
|
444
|
-
if (!element || typeof ResizeObserver ===
|
|
400
|
+
if (!element || typeof ResizeObserver === 'undefined')
|
|
445
401
|
return;
|
|
446
402
|
const measure = () => setOverflowing(element.scrollWidth > element.clientWidth);
|
|
447
403
|
measure();
|
|
@@ -451,12 +407,12 @@ function PlainContainer({ label, children, }) {
|
|
|
451
407
|
observer.observe(element.firstElementChild);
|
|
452
408
|
return () => observer.disconnect();
|
|
453
409
|
}, []);
|
|
454
|
-
return (_jsx("div", { ref: ref, "data-slot": "table-container", "data-overflowing": overflowing || undefined, className: "sprout-table-container", tabIndex: overflowing ? 0 : undefined, role: overflowing ?
|
|
410
|
+
return (_jsx("div", { ref: ref, "data-slot": "table-container", "data-overflowing": overflowing || undefined, className: "sprout-table-container", tabIndex: overflowing ? 0 : undefined, role: overflowing ? 'region' : undefined, "aria-label": overflowing ? label : undefined, children: children }));
|
|
455
411
|
}
|
|
456
412
|
function HeadCell({ header, config, resizable, reorderable, sized, role, }) {
|
|
457
413
|
const column = header.column;
|
|
458
414
|
const title = config?.header ?? column.id;
|
|
459
|
-
const align = config?.align ??
|
|
415
|
+
const align = config?.align ?? 'left';
|
|
460
416
|
const sorted = column.getIsSorted();
|
|
461
417
|
const sortable = column.getCanSort();
|
|
462
418
|
const sortable_ = useSortable({ id: column.id, disabled: !reorderable });
|
|
@@ -472,67 +428,62 @@ function HeadCell({ header, config, resizable, reorderable, sized, role, }) {
|
|
|
472
428
|
: {}),
|
|
473
429
|
};
|
|
474
430
|
const next = column.getNextSortingOrder();
|
|
475
|
-
const hint = sorted ===
|
|
476
|
-
? `, ascending. ${next ===
|
|
477
|
-
: sorted ===
|
|
478
|
-
? `, descending. ${next ===
|
|
479
|
-
:
|
|
480
|
-
const Icon = sorted ===
|
|
431
|
+
const hint = sorted === 'asc'
|
|
432
|
+
? `, ascending. ${next === 'desc' ? 'Select for descending' : 'Select to clear'}`
|
|
433
|
+
: sorted === 'desc'
|
|
434
|
+
? `, descending. ${next === 'asc' ? 'Select for ascending' : 'Select to clear'}`
|
|
435
|
+
: '';
|
|
436
|
+
const Icon = sorted === 'asc' ? ArrowUp : sorted === 'desc' ? ArrowDown : SortV;
|
|
481
437
|
const onResizeKey = (event) => {
|
|
482
438
|
const step = event.shiftKey ? 40 : 10;
|
|
483
|
-
const delta = event.key ===
|
|
439
|
+
const delta = event.key === 'ArrowRight' ? step : event.key === 'ArrowLeft' ? -step : 0;
|
|
484
440
|
if (!delta)
|
|
485
441
|
return;
|
|
486
442
|
event.preventDefault();
|
|
487
|
-
column.table.setColumnSizing(
|
|
443
|
+
column.table.setColumnSizing(prev => ({
|
|
488
444
|
...prev,
|
|
489
445
|
[column.id]: Math.max(48, column.getSize() + delta),
|
|
490
446
|
}));
|
|
491
447
|
};
|
|
492
|
-
return (_jsxs("th", { ref: reorderable ? sortable_.setNodeRef : undefined, "data-slot": "table-head", "data-align": align, "data-pinned": pinned || undefined, "data-column-id": column.id, "data-dragging": sortable_.isDragging || undefined, className: "sprout-table-head", "aria-sort": sorted ===
|
|
493
|
-
? "ascending"
|
|
494
|
-
: sorted === "desc"
|
|
495
|
-
? "descending"
|
|
496
|
-
: undefined, role: role, style: style, children: [_jsxs("span", { className: "sprout-table-head-inner", children: [reorderable && (_jsx("button", { type: "button", className: "sprout-table-handle", "aria-label": `Move ${title} column`, ...sortable_.attributes, ...sortable_.listeners, children: _jsx(Reorder, { size: 14, "aria-hidden": "true" }) })), sortable ? (_jsxs(Button, { variant: sorted ? "secondary" : "ghost", size: align === "right" ? "column-header-end" : "column-header", "aria-label": `Sort by ${title}${hint}`, title: sorted ? undefined : "Sort ascending", onClick: column.getToggleSortingHandler(), children: [title, _jsx(Icon, { size: 14, "aria-hidden": "true" })] })) : (title), config?.hint && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { render: _jsx("button", { type: "button", "aria-label": `About ${title}`, className: "sprout-table-hint" }), children: _jsx(InfoCircle, { size: 14, "aria-hidden": "true" }) }), _jsx(TooltipContent, { children: config.hint })] }))] }), resizable && (_jsx("div", { role: "separator", "aria-orientation": "vertical", "aria-label": `Resize ${title} column`, "aria-valuenow": column.getSize(), "aria-valuemin": 48, tabIndex: 0, className: "sprout-table-resizer", "data-resizing": column.getIsResizing() || undefined, onMouseDown: header.getResizeHandler(), onTouchStart: header.getResizeHandler(), onKeyDown: onResizeKey, onDoubleClick: () => column.resetSize() }))] }));
|
|
448
|
+
return (_jsxs("th", { ref: reorderable ? sortable_.setNodeRef : undefined, "data-slot": "table-head", "data-align": align, "data-pinned": pinned || undefined, "data-column-id": column.id, "data-dragging": sortable_.isDragging || undefined, className: "sprout-table-head", "aria-sort": sorted === 'asc' ? 'ascending' : sorted === 'desc' ? 'descending' : undefined, role: role, style: style, children: [_jsxs("span", { className: "sprout-table-head-inner", children: [reorderable && (_jsx("button", { type: "button", className: "sprout-table-handle", "aria-label": `Move ${title} column`, ...sortable_.attributes, ...sortable_.listeners, children: _jsx(Reorder, { size: 14, "aria-hidden": "true" }) })), sortable ? (_jsxs(Button, { variant: sorted ? 'secondary' : 'ghost', size: align === 'right' ? 'column-header-end' : 'column-header', "aria-label": `Sort by ${title}${hint}`, title: sorted ? undefined : 'Sort ascending', onClick: column.getToggleSortingHandler(), children: [title, _jsx(Icon, { size: 14, "aria-hidden": "true" })] })) : (title), config?.hint && (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { render: _jsx("button", { type: "button", "aria-label": `About ${title}`, className: "sprout-table-hint" }), children: _jsx(InfoCircle, { size: 14, "aria-hidden": "true" }) }), _jsx(TooltipContent, { children: config.hint })] }))] }), resizable && (_jsx("div", { role: "separator", "aria-orientation": "vertical", "aria-label": `Resize ${title} column`, "aria-valuenow": column.getSize(), "aria-valuemin": 48, tabIndex: 0, className: "sprout-table-resizer", "data-resizing": column.getIsResizing() || undefined, onMouseDown: header.getResizeHandler(), onTouchStart: header.getResizeHandler(), onKeyDown: onResizeKey, onDoubleClick: () => column.resetSize() }))] }));
|
|
497
449
|
}
|
|
498
450
|
function GroupRow({ row, columns, byKey, selectable, reorder, hasActions, rowIndex, role, }) {
|
|
499
|
-
const groupColumn = byKey.get(row.groupingColumnId ??
|
|
451
|
+
const groupColumn = byKey.get(row.groupingColumnId ?? '');
|
|
500
452
|
const value = row.groupingValue;
|
|
501
|
-
const option = groupColumn?.options?.find(
|
|
502
|
-
const name = option?.label ?? (value == null || value ===
|
|
453
|
+
const option = groupColumn?.options?.find(o => o.value === String(value));
|
|
454
|
+
const name = option?.label ?? (value == null || value === '' ? 'None' : String(value));
|
|
503
455
|
const expanded = row.getIsExpanded();
|
|
504
|
-
const leafRows = row.getLeafRows().filter(
|
|
456
|
+
const leafRows = row.getLeafRows().filter(r => !r.getIsGrouped());
|
|
505
457
|
const offsets = useContext(PinOffsetsContext);
|
|
506
|
-
return (_jsxs("tr", { "data-slot": "table-row", "data-group": "", className: "sprout-table-row", "aria-rowindex": rowIndex, role: role(
|
|
458
|
+
return (_jsxs("tr", { "data-slot": "table-row", "data-group": "", className: "sprout-table-row", "aria-rowindex": rowIndex, role: role('row'), children: [reorder && _jsx("td", { className: "sprout-table-cell", "data-selection": "" }), selectable && _jsx("td", { className: "sprout-table-cell", "data-selection": "" }), columns.map((column, index) => {
|
|
507
459
|
const config = byKey.get(column.id);
|
|
508
|
-
return (_jsx("td", { className: "sprout-table-cell", "data-align": index === 0 ?
|
|
460
|
+
return (_jsx("td", { className: "sprout-table-cell", "data-align": index === 0 ? 'left' : (config?.align ?? 'left'), "data-pinned": column.getIsPinned() || undefined, role: role('cell'), style: pinStyle(column, false, offsets), children: index === 0 ? (_jsxs("button", { type: "button", className: "sprout-table-toggle", "aria-expanded": expanded, onClick: row.getToggleExpandedHandler(), style: { paddingInlineStart: row.depth * 16 }, children: [expanded ? (_jsx(ChevronDown, { size: 14, "aria-hidden": "true" })) : (_jsx(ChevronRight, { size: 14, "aria-hidden": "true" })), _jsxs("span", { className: "sprout-table-group-name", children: [groupColumn?.header, ": ", name] }), _jsx("span", { className: "sprout-table-group-count", children: leafRows.length })] })) : config?.aggregate ? (formatAggregate(config, column.getAggregationValue({ rows: leafRows }))) : null }, column.id));
|
|
509
461
|
}), hasActions && _jsx("td", { className: "sprout-table-cell", "data-sticky-end": "" })] }));
|
|
510
462
|
}
|
|
511
463
|
function BodyRow({ row, columns, byKey, label, selectable, onSelect, reorder, editing, editable, onEditChange, onEdit, onSave, onCancel, actions, hasActions, href, onOpen, drop, colSpan, rowIndex, role, }) {
|
|
512
464
|
const sortable = useSortable({ id: row.id, disabled: !reorder });
|
|
513
465
|
const selected = row.getIsSelected();
|
|
514
466
|
const offsets = useContext(PinOffsetsContext);
|
|
515
|
-
const hasFiles = (event) => event.dataTransfer.types.includes(
|
|
467
|
+
const hasFiles = (event) => event.dataTransfer.types.includes('Files');
|
|
516
468
|
const onKeyDown = (event) => {
|
|
517
469
|
if (!editing)
|
|
518
470
|
return;
|
|
519
|
-
if (event.key ===
|
|
471
|
+
if (event.key === 'Escape') {
|
|
520
472
|
event.preventDefault();
|
|
521
473
|
onCancel();
|
|
522
474
|
}
|
|
523
|
-
else if (event.key ===
|
|
524
|
-
event.target instanceof HTMLInputElement) {
|
|
475
|
+
else if (event.key === 'Enter' && event.target instanceof HTMLInputElement) {
|
|
525
476
|
event.preventDefault();
|
|
526
477
|
onSave();
|
|
527
478
|
}
|
|
528
479
|
};
|
|
529
|
-
return (_jsxs(_Fragment, { children: [_jsxs("tr", { ref: reorder !== undefined ? sortable.setNodeRef : undefined, "data-slot": "table-row", "data-state": selected ?
|
|
480
|
+
return (_jsxs(_Fragment, { children: [_jsxs("tr", { ref: reorder !== undefined ? sortable.setNodeRef : undefined, "data-slot": "table-row", "data-state": selected ? 'selected' : undefined, "data-editing": editing ? '' : undefined, "data-drop-target": drop?.active || undefined, "data-linked": href || onOpen ? '' : undefined, "data-dragging": sortable.isDragging || undefined, className: "sprout-table-row", "aria-rowindex": rowIndex, "aria-selected": selectable ? selected : undefined, role: role('row'), style: sortable.transform
|
|
530
481
|
? {
|
|
531
482
|
transform: CSS.Translate.toString(sortable.transform),
|
|
532
483
|
transition: sortable.transition,
|
|
533
484
|
}
|
|
534
485
|
: undefined, onKeyDown: onKeyDown, onDragOver: drop
|
|
535
|
-
?
|
|
486
|
+
? event => {
|
|
536
487
|
if (!hasFiles(event))
|
|
537
488
|
return;
|
|
538
489
|
event.preventDefault();
|
|
@@ -540,124 +491,104 @@ function BodyRow({ row, columns, byKey, label, selectable, onSelect, reorder, ed
|
|
|
540
491
|
drop.set(true);
|
|
541
492
|
}
|
|
542
493
|
: undefined, onDragLeave: drop
|
|
543
|
-
?
|
|
494
|
+
? event => {
|
|
544
495
|
if (!event.currentTarget.contains(event.relatedTarget))
|
|
545
496
|
drop.set(false);
|
|
546
497
|
}
|
|
547
498
|
: undefined, onDrop: drop
|
|
548
|
-
?
|
|
499
|
+
? event => {
|
|
549
500
|
if (!hasFiles(event))
|
|
550
501
|
return;
|
|
551
502
|
event.preventDefault();
|
|
552
503
|
drop.set(false);
|
|
553
504
|
drop.onDrop(Array.from(event.dataTransfer.files));
|
|
554
505
|
}
|
|
555
|
-
: undefined, children: [reorder !== undefined && (_jsx("td", { className: "sprout-table-cell", "data-selection": "", role: role(
|
|
556
|
-
? undefined
|
|
557
|
-
: "Clear sorting, filters, and grouping to reorder", ...sortable.attributes, ...sortable.listeners, children: _jsx(Reorder, { size: 14, "aria-hidden": "true" }) }) })), selectable && (_jsx("td", { className: "sprout-table-cell", "data-selection": "", role: role("cell"), children: _jsx(Checkbox, { "aria-label": `Select ${label}`, checked: selected, disabled: !row.getCanSelect(), onCheckedChange: (checked, details) => onSelect(checked, details.event.shiftKey ===
|
|
558
|
-
true) }) })), columns.map((column, index) => {
|
|
506
|
+
: undefined, children: [reorder !== undefined && (_jsx("td", { className: "sprout-table-cell", "data-selection": "", role: role('cell'), children: _jsx("button", { type: "button", className: "sprout-table-handle", "aria-label": `Move ${label}`, disabled: !reorder, title: reorder ? undefined : 'Clear sorting, filters, and grouping to reorder', ...sortable.attributes, ...sortable.listeners, children: _jsx(Reorder, { size: 14, "aria-hidden": "true" }) }) })), selectable && (_jsx("td", { className: "sprout-table-cell", "data-selection": "", role: role('cell'), children: _jsx(Checkbox, { "aria-label": `Select ${label}`, checked: selected, disabled: !row.getCanSelect(), onCheckedChange: (checked, details) => onSelect(checked, details.event.shiftKey === true) }) })), columns.map((column, index) => {
|
|
559
507
|
const config = byKey.get(column.id);
|
|
560
|
-
const content = config?.cell
|
|
561
|
-
? config.cell(row.original)
|
|
562
|
-
: row.getValue(column.id);
|
|
508
|
+
const content = config?.cell ? config.cell(row.original) : row.getValue(column.id);
|
|
563
509
|
const first = index === 0;
|
|
564
510
|
const canExpand = first && row.getCanExpand();
|
|
565
|
-
return (_jsx("td", { "data-slot": "table-cell", "data-align": config?.align ??
|
|
566
|
-
|
|
567
|
-
? { paddingInlineStart: row.depth * 16 }
|
|
568
|
-
: undefined, children: [canExpand && (_jsx("button", { type: "button", className: "sprout-table-toggle", "aria-expanded": row.getIsExpanded(), "aria-label": `${row.getIsExpanded() ? "Collapse" : "Expand"} ${label}`, onClick: row.getToggleExpandedHandler(), children: row.getIsExpanded() ? (_jsx(ChevronDown, { size: 14, "aria-hidden": "true" })) : (_jsx(ChevronRight, { size: 14, "aria-hidden": "true" })) })), href ? (_jsx("a", { className: "sprout-table-link", href: href, children: content })) : onOpen ? (_jsx("button", { type: "button", className: "sprout-table-link", onClick: onOpen, children: content })) : (content)] })) : (content) }, column.id));
|
|
569
|
-
}), hasActions && (_jsx("td", { className: "sprout-table-cell", "data-sticky-end": "", role: role("cell"), children: _jsx("span", { className: "sprout-table-actions", children: editing ? (_jsxs(_Fragment, { children: [_jsx(Button, { size: "sm", disabled: editing.saving, onClick: onSave, children: editing.saving ? "Saving" : "Save" }), _jsx(Button, { size: "sm", variant: "ghost", disabled: editing.saving, onClick: onCancel, children: "Cancel" })] })) : (_jsxs(_Fragment, { children: [editable && (_jsx(Button, { size: "sm", variant: "ghost", "aria-label": `Edit ${label}`, onClick: onEdit, children: "Edit" })), actions?.(row.original)] })) }) }))] }), editing?.error && (_jsx("tr", { className: "sprout-table-row", "data-error-row": "", role: role("row"), children: _jsx("td", { colSpan: colSpan, className: "sprout-table-cell sprout-table-error", role: "alert", children: editing.error }) }))] }));
|
|
511
|
+
return (_jsx("td", { "data-slot": "table-cell", "data-align": config?.align ?? 'left', "data-pinned": column.getIsPinned() || undefined, "data-label": config?.header, className: "sprout-table-cell", role: role('cell'), style: pinStyle(column, false, offsets), children: editing && config?.edit ? (_jsx(Editor, { config: config, label: `${config.header} for ${label}`, value: editing.draft[column.id], onChange: value => onEditChange(column.id, value), autoFocus: first || columns.findIndex(c => byKey.get(c.id)?.edit) === index })) : first ? (_jsxs("span", { className: "sprout-table-first", style: row.depth ? { paddingInlineStart: row.depth * 16 } : undefined, children: [canExpand && (_jsx("button", { type: "button", className: "sprout-table-toggle", "aria-expanded": row.getIsExpanded(), "aria-label": `${row.getIsExpanded() ? 'Collapse' : 'Expand'} ${label}`, onClick: row.getToggleExpandedHandler(), children: row.getIsExpanded() ? (_jsx(ChevronDown, { size: 14, "aria-hidden": "true" })) : (_jsx(ChevronRight, { size: 14, "aria-hidden": "true" })) })), href ? (_jsx("a", { className: "sprout-table-link", href: href, children: content })) : onOpen ? (_jsx("button", { type: "button", className: "sprout-table-link", onClick: onOpen, children: content })) : (content)] })) : (content) }, column.id));
|
|
512
|
+
}), hasActions && (_jsx("td", { className: "sprout-table-cell", "data-sticky-end": "", role: role('cell'), children: _jsx("span", { className: "sprout-table-actions", children: editing ? (_jsxs(_Fragment, { children: [_jsx(Button, { size: "sm", disabled: editing.saving, onClick: onSave, children: editing.saving ? 'Saving' : 'Save' }), _jsx(Button, { size: "sm", variant: "ghost", disabled: editing.saving, onClick: onCancel, children: "Cancel" })] })) : (_jsxs(_Fragment, { children: [editable && (_jsx(Button, { size: "sm", variant: "ghost", "aria-label": `Edit ${label}`, onClick: onEdit, children: "Edit" })), actions?.(row.original)] })) }) }))] }), editing?.error && (_jsx("tr", { className: "sprout-table-row", "data-error-row": "", role: role('row'), children: _jsx("td", { colSpan: colSpan, className: "sprout-table-cell sprout-table-error", role: "alert", children: editing.error }) }))] }));
|
|
570
513
|
}
|
|
571
514
|
function Editor({ config, label, value, onChange, autoFocus, }) {
|
|
572
|
-
if (config.edit ===
|
|
573
|
-
return (_jsx(Checkbox, { "aria-label": label, checked: Boolean(value), onCheckedChange:
|
|
515
|
+
if (config.edit === 'checkbox') {
|
|
516
|
+
return (_jsx(Checkbox, { "aria-label": label, checked: Boolean(value), onCheckedChange: checked => onChange(checked), autoFocus: autoFocus }));
|
|
574
517
|
}
|
|
575
|
-
if (config.edit ===
|
|
576
|
-
return (_jsx("select", { "aria-label": label, className: "sprout-table-select", value: String(value ??
|
|
518
|
+
if (config.edit === 'select') {
|
|
519
|
+
return (_jsx("select", { "aria-label": label, className: "sprout-table-select", value: String(value ?? ''), onChange: event => onChange(event.target.value), autoFocus: autoFocus, children: config.options?.map(o => (_jsx("option", { value: o.value, children: o.label }, o.value))) }));
|
|
577
520
|
}
|
|
578
|
-
return (_jsx(Input, { "aria-label": label, type: config.edit ===
|
|
579
|
-
? "number"
|
|
580
|
-
: config.edit === "date"
|
|
581
|
-
? "date"
|
|
582
|
-
: "text", value: value == null ? "" : String(value), onValueChange: (next) => onChange(config.edit === "number" ? (next === "" ? null : Number(next)) : next), autoFocus: autoFocus, className: "sprout-table-input" }));
|
|
521
|
+
return (_jsx(Input, { "aria-label": label, type: config.edit === 'number' ? 'number' : config.edit === 'date' ? 'date' : 'text', value: value == null ? '' : String(value), onValueChange: next => onChange(config.edit === 'number' ? (next === '' ? null : Number(next)) : next), autoFocus: autoFocus, className: "sprout-table-input" }));
|
|
583
522
|
}
|
|
584
523
|
function Toolbar({ table, columns, label, searchable, columnMenu, onReset, }) {
|
|
585
524
|
const [pending, setPending] = useState([]);
|
|
586
525
|
const [open, setOpen] = useState(null);
|
|
587
526
|
const filters = table.state.columnFilters;
|
|
588
|
-
const filterable = columns.filter(
|
|
589
|
-
const groupable = columns.filter(
|
|
527
|
+
const filterable = columns.filter(c => c.filter);
|
|
528
|
+
const groupable = columns.filter(c => c.group);
|
|
590
529
|
const grouping = table.state.grouping;
|
|
591
|
-
const chips = filterable.filter(
|
|
592
|
-
return (_jsxs("div", { className: "sprout-table-toolbar", role: "toolbar", "aria-label": `${label} tools`, children: [searchable && (_jsx(SearchField, { label: `Search ${label}`, value: String(table.state.globalFilter ??
|
|
530
|
+
const chips = filterable.filter(c => pending.includes(c.key) || filters.some(f => f.id === c.key));
|
|
531
|
+
return (_jsxs("div", { className: "sprout-table-toolbar", role: "toolbar", "aria-label": `${label} tools`, children: [searchable && (_jsx(SearchField, { label: `Search ${label}`, value: String(table.state.globalFilter ?? ''), onChange: value => table.setGlobalFilter(value) })), chips.map(c => {
|
|
593
532
|
const column = table.getColumn(c.key);
|
|
594
533
|
if (!column)
|
|
595
534
|
return null;
|
|
596
|
-
return (_jsxs("span", { className: "sprout-table-chip", children: [_jsxs(Popover, { open: open === c.key, onOpenChange:
|
|
535
|
+
return (_jsxs("span", { className: "sprout-table-chip", children: [_jsxs(Popover, { open: open === c.key, onOpenChange: next => setOpen(next ? c.key : null), children: [_jsxs(PopoverTrigger, { className: "sprout-table-chip-label", children: [c.header, describeFilter(c, column.getFilterValue())] }), _jsx(PopoverContent, { align: "start", children: _jsx(FilterEditor, { config: c, column: column }) })] }), _jsx("button", { type: "button", className: "sprout-table-chip-remove", "aria-label": `Remove ${c.header} filter`, onClick: () => {
|
|
597
536
|
column.setFilterValue(undefined);
|
|
598
|
-
setPending(
|
|
537
|
+
setPending(p => p.filter(k => k !== c.key));
|
|
599
538
|
}, children: _jsx(X, { size: 12, "aria-hidden": "true" }) })] }, c.key));
|
|
600
539
|
}), filterable.length > chips.length && (_jsxs(DropdownMenu, { children: [_jsxs(DropdownMenuTrigger, { render: _jsx(Button, { variant: "ghost", size: "sm" }), children: [_jsx(Plus, { size: 14, "aria-hidden": "true" }), "Filter"] }), _jsx(DropdownMenuContent, { align: "start", size: "menu", children: filterable
|
|
601
|
-
.filter(
|
|
602
|
-
.map(
|
|
603
|
-
setPending(
|
|
540
|
+
.filter(c => !chips.includes(c))
|
|
541
|
+
.map(c => (_jsx(DropdownMenuItem, { onClick: () => {
|
|
542
|
+
setPending(p => [...p, c.key]);
|
|
604
543
|
setOpen(c.key);
|
|
605
|
-
}, children: c.header }, c.key))) })] })), _jsxs("span", { className: "sprout-table-toolbar-end", children: [groupable.length > 0 && (_jsxs(DropdownMenu, { children: [_jsxs(DropdownMenuTrigger, { render: _jsx(Button, { variant: "ghost", size: "sm" }), children: [grouping.length ? `Group: ${grouping.length}` :
|
|
544
|
+
}, children: c.header }, c.key))) })] })), _jsxs("span", { className: "sprout-table-toolbar-end", children: [groupable.length > 0 && (_jsxs(DropdownMenu, { children: [_jsxs(DropdownMenuTrigger, { render: _jsx(Button, { variant: "ghost", size: "sm" }), children: [grouping.length ? `Group: ${grouping.length}` : 'Group', _jsx(ChevronDown, { size: 14, "aria-hidden": "true" })] }), _jsx(DropdownMenuContent, { align: "end", size: "menu", children: groupable.map(c => (_jsx(DropdownMenuCheckboxItem, { checked: grouping.includes(c.key), onCheckedChange: () => table.getColumn(c.key)?.toggleGrouping(), children: c.header }, c.key))) })] })), columnMenu && (_jsxs(DropdownMenu, { children: [_jsxs(DropdownMenuTrigger, { render: _jsx(Button, { variant: "ghost", size: "sm" }), children: ["Columns", _jsx(ChevronDown, { size: 14, "aria-hidden": "true" })] }), _jsxs(DropdownMenuContent, { align: "end", size: "menu", children: [columns.map(c => {
|
|
606
545
|
const column = table.getColumn(c.key);
|
|
607
546
|
if (!column)
|
|
608
547
|
return null;
|
|
609
|
-
return (_jsxs(DropdownMenuSub, { children: [_jsx(DropdownMenuSubTrigger, { children: c.header }), _jsxs(DropdownMenuSubContent, { children: [_jsx(DropdownMenuCheckboxItem, { checked: column.getIsVisible(), onCheckedChange:
|
|
610
|
-
? false
|
|
611
|
-
: value), children: [_jsx(DropdownMenuRadioItem, { value: "none", children: "Not pinned" }), _jsx(DropdownMenuRadioItem, { value: "start", children: "Pin to start" }), _jsx(DropdownMenuRadioItem, { value: "end", children: "Pin to end" })] })] })] }, c.key));
|
|
548
|
+
return (_jsxs(DropdownMenuSub, { children: [_jsx(DropdownMenuSubTrigger, { children: c.header }), _jsxs(DropdownMenuSubContent, { children: [_jsx(DropdownMenuCheckboxItem, { checked: column.getIsVisible(), onCheckedChange: checked => column.toggleVisibility(checked), children: "Show" }), _jsx(DropdownMenuSeparator, {}), _jsxs(DropdownMenuRadioGroup, { value: column.getIsPinned() || 'none', onValueChange: value => column.pin(value === 'none' ? false : value), children: [_jsx(DropdownMenuRadioItem, { value: "none", children: "Not pinned" }), _jsx(DropdownMenuRadioItem, { value: "start", children: "Pin to start" }), _jsx(DropdownMenuRadioItem, { value: "end", children: "Pin to end" })] })] })] }, c.key));
|
|
612
549
|
}), _jsx(DropdownMenuSeparator, {}), _jsx(DropdownMenuItem, { onClick: onReset, children: "Reset columns" })] })] }))] })] }));
|
|
613
550
|
}
|
|
614
551
|
function describeFilter(config, value) {
|
|
615
552
|
if (value === undefined)
|
|
616
|
-
return
|
|
617
|
-
if (config.filter ===
|
|
618
|
-
const labels = value.map(
|
|
619
|
-
return `: ${labels.join(
|
|
553
|
+
return '';
|
|
554
|
+
if (config.filter === 'select' && Array.isArray(value)) {
|
|
555
|
+
const labels = value.map(v => config.options?.find(o => o.value === v)?.label ?? String(v));
|
|
556
|
+
return `: ${labels.join(', ')}`;
|
|
620
557
|
}
|
|
621
|
-
if ((config.filter ===
|
|
622
|
-
Array.isArray(value)) {
|
|
558
|
+
if ((config.filter === 'number' || config.filter === 'date') && Array.isArray(value)) {
|
|
623
559
|
const [min, max] = value;
|
|
624
|
-
const has = (v) => v !== undefined && v !== null && v !==
|
|
560
|
+
const has = (v) => v !== undefined && v !== null && v !== '';
|
|
625
561
|
if (has(min) && has(max))
|
|
626
562
|
return `: ${min} – ${max}`;
|
|
627
563
|
if (has(min))
|
|
628
564
|
return `: ≥ ${min}`;
|
|
629
565
|
if (has(max))
|
|
630
566
|
return `: ≤ ${max}`;
|
|
631
|
-
return
|
|
567
|
+
return '';
|
|
632
568
|
}
|
|
633
|
-
if (config.filter ===
|
|
634
|
-
return `: ${value ?
|
|
569
|
+
if (config.filter === 'boolean')
|
|
570
|
+
return `: ${value ? 'Yes' : 'No'}`;
|
|
635
571
|
return `: ${String(value)}`;
|
|
636
572
|
}
|
|
637
|
-
function FilterEditor({ config, column
|
|
573
|
+
function FilterEditor({ config, column }) {
|
|
638
574
|
const value = column.getFilterValue();
|
|
639
575
|
const name = config.header;
|
|
640
|
-
if (config.filter ===
|
|
576
|
+
if (config.filter === 'select') {
|
|
641
577
|
const selected = value ?? [];
|
|
642
|
-
return (_jsxs("fieldset", { className: "sprout-table-filter", children: [_jsx("legend", { children: name }), config.options?.map(
|
|
643
|
-
? [...selected, o.value]
|
|
644
|
-
: selected.filter((v) => v !== o.value)) }), o.label] }, o.value)))] }));
|
|
578
|
+
return (_jsxs("fieldset", { className: "sprout-table-filter", children: [_jsx("legend", { children: name }), config.options?.map(o => (_jsxs("label", { className: "sprout-table-filter-option", children: [_jsx(Checkbox, { variant: "neutral", checked: selected.includes(o.value), onCheckedChange: checked => column.setFilterValue(checked ? [...selected, o.value] : selected.filter(v => v !== o.value)) }), o.label] }, o.value)))] }));
|
|
645
579
|
}
|
|
646
|
-
if (config.filter ===
|
|
647
|
-
return (_jsxs("fieldset", { className: "sprout-table-filter", children: [_jsx("legend", { children: name }), [true, false].map(
|
|
580
|
+
if (config.filter === 'boolean') {
|
|
581
|
+
return (_jsxs("fieldset", { className: "sprout-table-filter", children: [_jsx("legend", { children: name }), [true, false].map(option => (_jsxs("label", { className: "sprout-table-filter-option", children: [_jsx("input", { type: "radio", name: `${column.id}-filter`, checked: value === option, onChange: () => column.setFilterValue(option) }), option ? 'Yes' : 'No'] }, String(option))))] }));
|
|
648
582
|
}
|
|
649
|
-
if (config.filter ===
|
|
650
|
-
const [min, max] = value ?? [
|
|
651
|
-
|
|
652
|
-
undefined,
|
|
653
|
-
];
|
|
654
|
-
const type = config.filter === "number" ? "number" : "date";
|
|
583
|
+
if (config.filter === 'number' || config.filter === 'date') {
|
|
584
|
+
const [min, max] = value ?? [undefined, undefined];
|
|
585
|
+
const type = config.filter === 'number' ? 'number' : 'date';
|
|
655
586
|
const set = (index, next) => {
|
|
656
|
-
const parsed = next ===
|
|
587
|
+
const parsed = next === '' ? undefined : type === 'number' ? Number(next) : next;
|
|
657
588
|
const range = index === 0 ? [parsed, max] : [min, parsed];
|
|
658
589
|
column.setFilterValue(range[0] === undefined && range[1] === undefined ? undefined : range);
|
|
659
590
|
};
|
|
660
|
-
return (_jsxs("fieldset", { className: "sprout-table-filter", "data-range": "", children: [_jsx("legend", { children: name }), _jsx(Input, { "aria-label": `${name} from`, type: type, value: min == null ?
|
|
591
|
+
return (_jsxs("fieldset", { className: "sprout-table-filter", "data-range": "", children: [_jsx("legend", { children: name }), _jsx(Input, { "aria-label": `${name} from`, type: type, value: min == null ? '' : String(min), onValueChange: next => set(0, next) }), _jsx(Input, { "aria-label": `${name} to`, type: type, value: max == null ? '' : String(max), onValueChange: next => set(1, next) })] }));
|
|
661
592
|
}
|
|
662
|
-
return (_jsx(Input, { "aria-label": `${name} contains`, autoFocus: true, value: String(value ??
|
|
593
|
+
return (_jsx(Input, { "aria-label": `${name} contains`, autoFocus: true, value: String(value ?? ''), onValueChange: next => column.setFilterValue(next || undefined) }));
|
|
663
594
|
}
|