periplo-ui 4.6.1 → 4.6.3

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.
Files changed (39) hide show
  1. package/dist/components/Combobox/Combobox.js.map +1 -1
  2. package/dist/components/DataTable/DataTable.js +39 -84
  3. package/dist/components/DataTable/DataTable.js.map +1 -1
  4. package/dist/components/DataTable/components/DataTableBody.d.ts +7 -13
  5. package/dist/components/DataTable/components/DataTableBody.js +41 -32
  6. package/dist/components/DataTable/components/DataTableBody.js.map +1 -1
  7. package/dist/components/DataTable/components/DataTableCell.d.ts +11 -0
  8. package/dist/components/DataTable/components/DataTableCell.js +28 -0
  9. package/dist/components/DataTable/components/DataTableCell.js.map +1 -0
  10. package/dist/components/DataTable/components/DataTableCheckbox.d.ts +30 -0
  11. package/dist/components/DataTable/components/DataTableCheckbox.js +68 -0
  12. package/dist/components/DataTable/components/DataTableCheckbox.js.map +1 -0
  13. package/dist/components/DataTable/components/DataTableGroupRow.js +19 -10
  14. package/dist/components/DataTable/components/DataTableGroupRow.js.map +1 -1
  15. package/dist/components/DataTable/components/DataTablePagination.d.ts +2 -23
  16. package/dist/components/DataTable/components/DataTablePagination.js +5 -4
  17. package/dist/components/DataTable/components/DataTablePagination.js.map +1 -1
  18. package/dist/components/DataTable/components/DataTableToolbar.js +3 -3
  19. package/dist/components/DataTable/components/DataTableToolbar.js.map +1 -1
  20. package/dist/components/DataTable/components/dataTableCellStyles.d.ts +8 -0
  21. package/dist/components/DataTable/components/dataTableCellStyles.js +27 -0
  22. package/dist/components/DataTable/components/dataTableCellStyles.js.map +1 -0
  23. package/dist/components/DataTable/hooks/useSelectColumn.d.ts +27 -0
  24. package/dist/components/DataTable/hooks/useSelectColumn.js +77 -0
  25. package/dist/components/DataTable/hooks/useSelectColumn.js.map +1 -0
  26. package/dist/components/DataTable/hooks/useSelection.d.ts +0 -3
  27. package/dist/components/DataTable/hooks/useSelection.js +1 -5
  28. package/dist/components/DataTable/hooks/useSelection.js.map +1 -1
  29. package/dist/components/DataTable/types.d.ts +13 -12
  30. package/package.json +1 -1
  31. package/dist/components/DataTable/components/DataTableGroupRowSelector.d.ts +0 -9
  32. package/dist/components/DataTable/components/DataTableGroupRowSelector.js +0 -32
  33. package/dist/components/DataTable/components/DataTableGroupRowSelector.js.map +0 -1
  34. package/dist/components/DataTable/components/DataTableRowSelector.d.ts +0 -11
  35. package/dist/components/DataTable/components/DataTableRowSelector.js +0 -34
  36. package/dist/components/DataTable/components/DataTableRowSelector.js.map +0 -1
  37. package/dist/components/DataTable/components/DataTableSelectHeader.d.ts +0 -11
  38. package/dist/components/DataTable/components/DataTableSelectHeader.js +0 -38
  39. package/dist/components/DataTable/components/DataTableSelectHeader.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Combobox.js","sources":["../../../src/components/Combobox/Combobox.tsx"],"sourcesContent":["import { X } from '@phosphor-icons/react/dist/ssr/X'\nimport { useEffect, useRef } from 'react'\n\nimport { cn } from '../../lib/utils'\nimport { Command, CommandInput } from '../Command'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from '../Popover'\n\nimport { ComboboxTrigger } from './ComboboxTrigger'\nimport { StaticComboboxList } from './StaticComboboxList'\nimport { useCombobox } from './useCombobox'\nimport { VirtualizedComboboxList } from './VirtualizedComboboxList'\n\ntype ComboboxBaseProps<T> = {\n /** Unique identifier for the combobox */\n id?: string\n /** Array of options to display in the combobox (static mode). */\n options?: Array<T>\n /** Function to get the unique identifier from an option. */\n getOptionValue: (option: T) => string\n /** Function to get the display text from an option. */\n getOptionLabel: (option: T) => string\n /** Custom render function for options. If not provided, defaults to showing a checkmark and label */\n renderOption?: (option: T, isSelected: boolean) => React.ReactNode\n /** Placeholder text shown when no option is selected */\n placeholder?: string\n /** Placeholder text for the search input field */\n searchPlaceholder?: string\n /** Message shown when no options match the search query */\n emptyMessage?: string\n /** Additional CSS classes to apply to the combobox trigger */\n className?: string\n /** Additional CSS classes to apply to the popover content */\n contentClassName?: string\n /** Whether the combobox is disabled */\n disabled?: boolean\n /** Maximum height of the options list. Can be any valid CSS height value */\n maxHeight?: string | number\n /** Whether to close the dropdown when an option is selected. Defaults to `true` for single select and `false` for multi-select. */\n closeOnSelect?: boolean\n /** Whether the combobox is in a loading state */\n loading?: boolean\n /** Message to show when in loading state */\n loadingPlaceholder?: string\n /** Whether the combobox has an error */\n error?: boolean | string\n /** Custom function to filter options based on search term (static mode only) */\n filterOptions?: (options: Array<T>, searchTerm: string) => Array<T>\n /** Callback function executed when the clear button is clicked. When provided, an X button will appear on hover to clear the selection. */\n onClear?: boolean | (() => void)\n /** Whether the selection can be cleared */\n clearable?: boolean\n /** Whether the combobox is inside a modal */\n modal?: boolean\n /** Placeholder text for the selected multiple options */\n selectedMultiplePlaceholder?: string\n /** Placeholder text for the multiple options */\n multipleOptionsPlaceholder?: string\n /** Special options that appear at the top with their own title. When selected, the combobox switches to single-select mode. */\n specialOptions?: Array<T>\n /** Title for the special options group */\n specialOptionsTitle?: string\n /** Container element to position the combobox relative to. */\n container?: HTMLElement\n /** Alignment of the dropdown relative to the trigger. Defaults to 'center'. */\n align?: 'start' | 'center' | 'end'\n /** Auto-focus the search input when the dropdown opens. */\n onOpenAutoFocus?: boolean\n}\n\nexport type ComboboxSingleProps<T> = ComboboxBaseProps<T> & {\n virtualized?: false\n multiple?: false\n value?: string\n onChange: (value: string) => void\n /** Custom render function for the selected value display. */\n renderLabel?: (selectedOption: T) => React.ReactNode\n}\n\nexport type ComboboxMultipleProps<T> = ComboboxBaseProps<T> & {\n virtualized?: false\n multiple: true\n value?: Array<string>\n onChange: (value: Array<string>) => void\n /** Custom render function for the selected value(s) display. */\n renderLabel?: (selectedOptions: Array<T>, onRemove: (value: string) => void) => React.ReactNode\n}\n\nexport type ComboboxVirtualizedProps<T> = ComboboxBaseProps<T> & {\n virtualized: true\n multiple?: false\n value?: string\n onChange: (value: string) => void\n /** Custom render function for the selected value display. */\n renderLabel?: (selectedOption: T) => React.ReactNode\n /** The accumulated, flattened list of loaded items. */\n items: Array<T>\n /** The resolved selected item, fetched independently of the list. Used for the trigger label. */\n selectedItem?: T\n /** Whether more pages can be loaded. */\n hasNextPage: boolean\n /** Whether the next page is currently being fetched. */\n isFetchingNextPage: boolean\n /** Request the next page (triggered near the end of the list). */\n onLoadMore: () => void\n /** Emitted (debounced) when the search term changes. The consumer refetches. */\n onSearchChange: (search: string) => void\n}\n\nexport type ComboboxProps<T> = ComboboxSingleProps<T> | ComboboxMultipleProps<T> | ComboboxVirtualizedProps<T>\n\n/**\n * A searchable combobox component with support for custom rendering, keyboard navigation, and search filtering.\n *\n * @example Basic usage\n * ```tsx\n * <Combobox<User>\n * options={users}\n * value={selectedUserId}\n * onChange={setSelectedUserId}\n * getOptionValue={(user) => user.id}\n * getOptionLabel={(user) => user.name}\n * />\n * ```\n */\nexport const Combobox = <T extends object>(props: ComboboxProps<T>) => {\n const {\n id,\n options = [],\n getOptionValue,\n getOptionLabel,\n searchPlaceholder = 'Search...',\n emptyMessage = 'No results found.',\n className = 'w-60',\n contentClassName,\n disabled = false,\n maxHeight = '300px',\n renderOption,\n loading = false,\n loadingPlaceholder = 'Cargando...',\n error = false,\n multiple,\n onClear,\n modal = false,\n selectedMultiplePlaceholder = 'Selected',\n multipleOptionsPlaceholder = 'Options',\n specialOptions,\n specialOptionsTitle,\n container,\n align,\n onOpenAutoFocus = false,\n } = props\n\n const searchInputRef = useRef<HTMLInputElement>(null)\n\n const normalizedMaxHeight = typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight\n const boundedListMaxHeight = `min(${normalizedMaxHeight}, max(120px, calc(var(--radix-popover-content-available-height, 100dvh) - 68px)))`\n\n const {\n open,\n setOpen,\n searchTerm,\n setSearchTerm,\n setIsHovered,\n hasNextPage,\n loadingMore,\n isVirtualized,\n filteredOptions,\n displayValue,\n hasValue,\n showClearButton,\n handleSelect,\n handleClear,\n loadNextPage,\n } = useCombobox(props)\n\n useEffect(() => {\n if (!open || !onOpenAutoFocus) return\n const timeoutId = globalThis.setTimeout(() => searchInputRef.current?.focus(), 0)\n return () => globalThis.clearTimeout(timeoutId)\n }, [open, onOpenAutoFocus])\n\n const hasMultipleRenderLabel = !!(multiple && 'renderLabel' in props && props.renderLabel)\n\n return (\n <div className=\"flex w-full flex-col gap-1\">\n <PopoverRoot open={open} onOpenChange={setOpen} modal={modal}>\n <div\n className={cn('relative', className)}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n <PopoverTrigger\n asChild\n onPointerDown={(event) => {\n event.stopPropagation()\n if (open) {\n setOpen(false)\n event.preventDefault()\n } else {\n setOpen(true)\n }\n }}\n onClick={(event) => {\n event.preventDefault()\n event.stopPropagation()\n }}\n >\n <ComboboxTrigger\n id={id}\n disabled={disabled}\n open={open}\n error={error}\n hasValue={hasValue}\n showClearButton={showClearButton}\n isMultilineLabel={hasMultipleRenderLabel}\n displayValue={displayValue}\n className=\"w-full\"\n />\n </PopoverTrigger>\n {!!onClear && hasValue && (\n <X\n data-testid=\"clear-button\"\n className={cn(\n 'absolute top-1/2 right-4 z-10 h-4 w-4 -translate-y-1/2 cursor-pointer transition-opacity duration-150',\n showClearButton ? 'opacity-100 hover:opacity-70' : 'opacity-0',\n )}\n onPointerDown={(event) => event.stopPropagation()}\n onClick={handleClear}\n />\n )}\n </div>\n <PopoverContent\n className={cn('overflow-hidden p-0', contentClassName)}\n container={container}\n side=\"bottom\"\n align={align}\n onOpenAutoFocus={onOpenAutoFocus ? (event) => event.preventDefault() : undefined}\n >\n <Command shouldFilter={false}>\n <CommandInput\n ref={searchInputRef}\n placeholder={searchPlaceholder}\n value={searchTerm}\n onValueChange={setSearchTerm}\n />\n {isVirtualized ? (\n <VirtualizedComboboxList\n localOptions={filteredOptions}\n loading={loading}\n loadingPlaceholder={loadingPlaceholder}\n emptyMessage={emptyMessage}\n value={props.value as string}\n getOptionValue={getOptionValue}\n getOptionLabel={getOptionLabel}\n handleSelect={handleSelect}\n renderOption={renderOption}\n maxHeight={boundedListMaxHeight}\n hasNextPage={hasNextPage}\n loadingMore={loadingMore}\n onLoadMore={loadNextPage}\n />\n ) : (\n <StaticComboboxList\n filteredOptions={filteredOptions}\n loading={loading}\n loadingPlaceholder={loadingPlaceholder}\n emptyMessage={emptyMessage}\n multiple={!!multiple}\n value={props.value}\n getOptionValue={getOptionValue}\n getOptionLabel={getOptionLabel}\n handleSelect={handleSelect}\n renderOption={renderOption}\n maxHeight={boundedListMaxHeight}\n selectedMultiplePlaceholder={selectedMultiplePlaceholder}\n multipleOptionsPlaceholder={multipleOptionsPlaceholder}\n options={options}\n specialOptions={specialOptions}\n specialOptionsTitle={specialOptionsTitle}\n />\n )}\n </Command>\n </PopoverContent>\n </PopoverRoot>\n {typeof error === 'string' && <span className=\"text-error-500 text-sm\">{error}</span>}\n </div>\n )\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Combobox.js","sources":["../../../src/components/Combobox/Combobox.tsx"],"sourcesContent":["import { X } from '@phosphor-icons/react/dist/ssr/X'\nimport { useEffect, useRef } from 'react'\n\nimport { cn } from '../../lib/utils'\nimport { Command, CommandInput } from '../Command'\nimport { PopoverContent, PopoverRoot, PopoverTrigger } from '../Popover'\n\nimport { ComboboxTrigger } from './ComboboxTrigger'\nimport { StaticComboboxList } from './StaticComboboxList'\nimport { useCombobox } from './useCombobox'\nimport { VirtualizedComboboxList } from './VirtualizedComboboxList'\n\ntype ComboboxBaseProps<T> = {\n /** Unique identifier for the combobox */\n id?: string\n /** Array of options to display in the combobox (static mode). */\n options?: Array<T>\n /** Function to get the unique identifier from an option. */\n getOptionValue: (option: T) => string\n /** Function to get the display text from an option. */\n getOptionLabel: (option: T) => string\n /** Custom render function for options. If not provided, defaults to showing a checkmark and label */\n renderOption?: (option: T, isSelected: boolean) => React.ReactNode\n /** Placeholder text shown when no option is selected */\n placeholder?: string\n /** Placeholder text for the search input field */\n searchPlaceholder?: string\n /** Message shown when no options match the search query */\n emptyMessage?: string\n /** Additional CSS classes to apply to the combobox trigger */\n className?: string\n /** Additional CSS classes to apply to the popover content */\n contentClassName?: string\n /** Whether the combobox is disabled */\n disabled?: boolean\n /** Maximum height of the options list. Can be any valid CSS height value */\n maxHeight?: string | number\n /** Whether to close the dropdown when an option is selected. Defaults to `true` for single select and `false` for multi-select. */\n closeOnSelect?: boolean\n /** Whether the combobox is in a loading state */\n loading?: boolean\n /** Message to show when in loading state */\n loadingPlaceholder?: string\n /** Whether the combobox has an error */\n error?: boolean | string\n /** Custom function to filter options based on search term (static mode only) */\n filterOptions?: (options: Array<T>, searchTerm: string) => Array<T>\n /** Callback function executed when the clear button is clicked. When provided, an X button will appear on hover to clear the selection. */\n onClear?: boolean | (() => void)\n /** Whether the selection can be cleared */\n clearable?: boolean\n /** Whether the combobox is inside a modal */\n modal?: boolean\n /** Placeholder text for the selected multiple options */\n selectedMultiplePlaceholder?: string\n /** Placeholder text for the multiple options */\n multipleOptionsPlaceholder?: string\n /** Special options that appear at the top with their own title. When selected, the combobox switches to single-select mode. */\n specialOptions?: Array<T>\n /** Title for the special options group */\n specialOptionsTitle?: string\n /** Container element to position the combobox relative to. */\n container?: HTMLElement\n /** Alignment of the dropdown relative to the trigger. Defaults to 'center'. */\n align?: 'start' | 'center' | 'end'\n /** Auto-focus the search input when the dropdown opens. */\n onOpenAutoFocus?: boolean\n}\n\nexport type ComboboxSingleProps<T> = ComboboxBaseProps<T> & {\n virtualized?: false\n multiple?: false\n value?: string\n onChange: (value: string) => void\n /** Custom render function for the selected value display. */\n renderLabel?: (selectedOption: T) => React.ReactNode\n}\n\nexport type ComboboxMultipleProps<T> = ComboboxBaseProps<T> & {\n virtualized?: false\n multiple: true\n value?: Array<string>\n onChange: (value: Array<string>) => void\n /** Custom render function for the selected value(s) display. */\n renderLabel?: (selectedOptions: Array<T>, onRemove: (value: string) => void) => React.ReactNode\n}\n\nexport type ComboboxVirtualizedProps<T> = ComboboxBaseProps<T> & {\n virtualized: true\n multiple?: false\n value?: string\n onChange: (value: string) => void\n /** Custom render function for the selected value display. */\n renderLabel?: (selectedOption: T) => React.ReactNode\n /** The accumulated, flattened list of loaded items. */\n items: Array<T>\n /** The resolved selected item, fetched independently of the list. Used for the trigger label. */\n selectedItem?: T\n /** Whether more pages can be loaded. */\n hasNextPage: boolean\n /** Whether the next page is currently being fetched. */\n isFetchingNextPage: boolean\n /** Request the next page (triggered near the end of the list). */\n onLoadMore: () => void\n /** Emitted (debounced) when the search term changes. The consumer refetches. */\n onSearchChange: (search: string) => void\n}\n\nexport type ComboboxProps<T> = ComboboxSingleProps<T> | ComboboxMultipleProps<T> | ComboboxVirtualizedProps<T>\n\n/**\n * A searchable combobox component with support for custom rendering, keyboard navigation, and search filtering.\n *\n * @example Basic usage\n * ```tsx\n * <Combobox<User>\n * options={users}\n * value={selectedUserId}\n * onChange={setSelectedUserId}\n * getOptionValue={(user) => user.id}\n * getOptionLabel={(user) => user.name}\n * />\n * ```\n */\nexport const Combobox = <T extends object>(props: ComboboxProps<T>) => {\n const {\n id,\n options = [],\n getOptionValue,\n getOptionLabel,\n searchPlaceholder = 'Search...',\n emptyMessage = 'No results found.',\n className = 'w-60',\n contentClassName,\n disabled = false,\n maxHeight = '300px',\n renderOption,\n loading = false,\n loadingPlaceholder = 'Cargando...',\n error = false,\n multiple,\n onClear,\n modal = false,\n selectedMultiplePlaceholder = 'Selected',\n multipleOptionsPlaceholder = 'Options',\n specialOptions,\n specialOptionsTitle,\n container,\n align,\n onOpenAutoFocus = false,\n } = props\n\n const searchInputRef = useRef<HTMLInputElement>(null)\n const normalizedMaxHeight = typeof maxHeight === 'number' ? `${maxHeight}px` : maxHeight\n const boundedListMaxHeight = `min(${normalizedMaxHeight}, max(120px, calc(var(--radix-popover-content-available-height, 100dvh) - 68px)))`\n\n const {\n open,\n setOpen,\n searchTerm,\n setSearchTerm,\n setIsHovered,\n hasNextPage,\n loadingMore,\n isVirtualized,\n filteredOptions,\n displayValue,\n hasValue,\n showClearButton,\n handleSelect,\n handleClear,\n loadNextPage,\n } = useCombobox(props)\n\n useEffect(() => {\n if (!open || !onOpenAutoFocus) return\n const timeoutId = globalThis.setTimeout(() => searchInputRef.current?.focus(), 0)\n return () => globalThis.clearTimeout(timeoutId)\n }, [open, onOpenAutoFocus])\n\n const hasMultipleRenderLabel = !!(multiple && 'renderLabel' in props && props.renderLabel)\n\n return (\n <div className=\"flex w-full flex-col gap-1\">\n <PopoverRoot open={open} onOpenChange={setOpen} modal={modal}>\n <div\n className={cn('relative', className)}\n onMouseEnter={() => setIsHovered(true)}\n onMouseLeave={() => setIsHovered(false)}\n >\n <PopoverTrigger\n asChild\n onPointerDown={(event) => {\n event.stopPropagation()\n if (open) {\n setOpen(false)\n event.preventDefault()\n } else {\n setOpen(true)\n }\n }}\n onClick={(event) => {\n event.preventDefault()\n event.stopPropagation()\n }}\n >\n <ComboboxTrigger\n id={id}\n disabled={disabled}\n open={open}\n error={error}\n hasValue={hasValue}\n showClearButton={showClearButton}\n isMultilineLabel={hasMultipleRenderLabel}\n displayValue={displayValue}\n className=\"w-full\"\n />\n </PopoverTrigger>\n {!!onClear && hasValue && (\n <X\n data-testid=\"clear-button\"\n className={cn(\n 'absolute top-1/2 right-4 z-10 h-4 w-4 -translate-y-1/2 cursor-pointer transition-opacity duration-150',\n showClearButton ? 'opacity-100 hover:opacity-70' : 'opacity-0',\n )}\n onPointerDown={(event) => event.stopPropagation()}\n onClick={handleClear}\n />\n )}\n </div>\n <PopoverContent\n className={cn('overflow-hidden p-0', contentClassName)}\n container={container}\n side=\"bottom\"\n align={align}\n onOpenAutoFocus={onOpenAutoFocus ? (event) => event.preventDefault() : undefined}\n >\n <Command shouldFilter={false}>\n <CommandInput\n ref={searchInputRef}\n placeholder={searchPlaceholder}\n value={searchTerm}\n onValueChange={setSearchTerm}\n />\n {isVirtualized ? (\n <VirtualizedComboboxList\n localOptions={filteredOptions}\n loading={loading}\n loadingPlaceholder={loadingPlaceholder}\n emptyMessage={emptyMessage}\n value={props.value as string}\n getOptionValue={getOptionValue}\n getOptionLabel={getOptionLabel}\n handleSelect={handleSelect}\n renderOption={renderOption}\n maxHeight={boundedListMaxHeight}\n hasNextPage={hasNextPage}\n loadingMore={loadingMore}\n onLoadMore={loadNextPage}\n />\n ) : (\n <StaticComboboxList\n filteredOptions={filteredOptions}\n loading={loading}\n loadingPlaceholder={loadingPlaceholder}\n emptyMessage={emptyMessage}\n multiple={!!multiple}\n value={props.value}\n getOptionValue={getOptionValue}\n getOptionLabel={getOptionLabel}\n handleSelect={handleSelect}\n renderOption={renderOption}\n maxHeight={boundedListMaxHeight}\n selectedMultiplePlaceholder={selectedMultiplePlaceholder}\n multipleOptionsPlaceholder={multipleOptionsPlaceholder}\n options={options}\n specialOptions={specialOptions}\n specialOptionsTitle={specialOptionsTitle}\n />\n )}\n </Command>\n </PopoverContent>\n </PopoverRoot>\n {typeof error === 'string' && <span className=\"text-error-500 text-sm\">{error}</span>}\n </div>\n )\n}\n"],"names":[],"mappings":"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"}
@@ -1,16 +1,14 @@
1
1
  "use client";
2
- import { jsx, jsxs } from 'react/jsx-runtime';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
3
  import { getPaginationRowModel, useReactTable, getExpandedRowModel, getCoreRowModel, flexRender } from '@tanstack/react-table';
4
4
  import * as React from 'react';
5
5
  import { Table, TableHeader, TableRow, TableHead } from '../Table/Table.js';
6
- import { Typography } from '../Typography/Typography.js';
7
6
  import { DataTableBody } from './components/DataTableBody.js';
8
- import { DataTableGroupRowSelector } from './components/DataTableGroupRowSelector.js';
7
+ import { getDataTableCellClassName } from './components/dataTableCellStyles.js';
9
8
  import { DataTablePagination } from './components/DataTablePagination.js';
10
- import { DataTableRowSelector } from './components/DataTableRowSelector.js';
11
- import { DataTableSelectHeader } from './components/DataTableSelectHeader.js';
12
9
  import { DataTableToolbar } from './components/DataTableToolbar.js';
13
10
  import { useGroupExpansion } from './hooks/useGroupExpansion.js';
11
+ import { useSelectColumn } from './hooks/useSelectColumn.js';
14
12
  import { useSelection } from './hooks/useSelection.js';
15
13
  import { flattenLeaves } from './utils.js';
16
14
  import { cn } from '../../lib/utils.js';
@@ -61,76 +59,20 @@ function DataTable({
61
59
  () => Object.fromEntries(Array.from(selectedIds).map((id) => [id, true])),
62
60
  [selectedIds]
63
61
  );
64
- const SelectColumnHeader = React.useCallback(
65
- () => /* @__PURE__ */ jsx(
66
- DataTableSelectHeader,
67
- {
68
- isBackendPagination,
69
- selectedIds,
70
- data: selectionData,
71
- handleSelectAll,
72
- isLoading,
73
- isSelectionDisabled: selection?.isSelectionDisabled ?? false,
74
- selectionDisabledTooltip: selection?.labels?.selectionDisabledTooltip
75
- }
76
- ),
77
- [
78
- isBackendPagination,
79
- selectedIds,
80
- selectionData,
81
- handleSelectAll,
82
- isLoading,
83
- selection?.isSelectionDisabled,
84
- selection?.labels?.selectionDisabledTooltip
85
- ]
86
- );
87
- const SelectColumnCell = React.useCallback(
88
- ({ row }) => {
89
- if (grouping && row.getCanExpand()) {
90
- return /* @__PURE__ */ jsx(
91
- DataTableGroupRowSelector,
92
- {
93
- row,
94
- selectedIds,
95
- getRowId,
96
- handleRowSelect
97
- }
98
- );
99
- }
100
- return /* @__PURE__ */ jsx(
101
- DataTableRowSelector,
102
- {
103
- row,
104
- selectedIds,
105
- getRowId,
106
- handleRowSelect,
107
- isRowSelectionDisabled: selection?.isRowSelectionDisabled,
108
- rowSelectionDisabledTooltip: selection?.labels?.rowSelectionDisabledTooltip
109
- }
110
- );
111
- },
112
- [
113
- grouping,
114
- selectedIds,
115
- getRowId,
116
- handleRowSelect,
117
- selection?.isRowSelectionDisabled,
118
- selection?.labels?.rowSelectionDisabledTooltip
119
- ]
120
- );
62
+ const selectColumn = useSelectColumn({
63
+ selection,
64
+ selectedIds,
65
+ selectionData,
66
+ getRowId,
67
+ handleRowSelect,
68
+ handleSelectAll,
69
+ isBackendPagination,
70
+ isLoading
71
+ });
121
72
  const tableColumns = React.useMemo(() => {
122
- const baseColumns = [...userColumns];
123
- if (selection !== void 0) {
124
- const selectColumn = {
125
- id: "select",
126
- size: 50,
127
- cell: SelectColumnCell,
128
- header: SelectColumnHeader
129
- };
130
- baseColumns.unshift(selectColumn);
131
- }
132
- return baseColumns;
133
- }, [userColumns, selection, SelectColumnCell, SelectColumnHeader]);
73
+ if (!selectColumn) return userColumns;
74
+ return [selectColumn.column, ...userColumns];
75
+ }, [userColumns, selectColumn]);
134
76
  const toolbarSelectionProps = React.useMemo(() => {
135
77
  if (isBackendPagination && selection) {
136
78
  return {
@@ -165,8 +107,18 @@ function DataTable({
165
107
  setPageIndex(newState.pageIndex);
166
108
  }
167
109
  },
168
- [pageIndex, pageSize, setPageIndex]
110
+ [pageIndex, pageSize]
169
111
  );
112
+ const groupConfig = React.useMemo(() => {
113
+ if (!grouping) return void 0;
114
+ return {
115
+ renderGroupRow: grouping.renderGroupRow,
116
+ renderGroupSelector: selectColumn?.GroupSelectCell,
117
+ isGroupOpen,
118
+ toggleGroup,
119
+ getRowId
120
+ };
121
+ }, [grouping, selectColumn, isGroupOpen, toggleGroup, getRowId]);
170
122
  const table = useReactTable({
171
123
  data,
172
124
  columns: tableColumns,
@@ -201,8 +153,16 @@ function DataTable({
201
153
  }
202
154
  ),
203
155
  /* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 flex-col rounded-md border bg-white", children: [
204
- /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-auto", children: /* @__PURE__ */ jsx("div", { className: "h-full scrollbar-gutter-stable overflow-auto overscroll-x-none overscroll-y-auto", children: /* @__PURE__ */ jsxs(Table, { className: "w-full", tableClassName: cn("min-w-max", tableClassName), children: [
205
- /* @__PURE__ */ jsx(TableHeader, { className: "sticky top-0 z-10 bg-neutral-50", children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx(TableRow, { children: headerGroup.headers.map((header) => /* @__PURE__ */ jsx(TableHead, { style: { width: header.column.columnDef.size }, children: /* @__PURE__ */ jsx(Typography, { weight: "medium", className: "whitespace-nowrap", children: header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext()) }) }, header.id)) }, headerGroup.id)) }),
156
+ /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-auto overscroll-x-none overscroll-y-auto", children: /* @__PURE__ */ jsxs(Table, { className: "w-full", tableClassName: cn("min-w-max", tableClassName), children: [
157
+ /* @__PURE__ */ jsx(TableHeader, { className: "sticky top-0 z-10 bg-neutral-50", children: table.getHeaderGroups().map((headerGroup) => /* @__PURE__ */ jsx(TableRow, { children: headerGroup.headers.map((header) => /* @__PURE__ */ jsx(
158
+ TableHead,
159
+ {
160
+ style: { width: header.column.columnDef.size },
161
+ className: "h-auto p-0 text-neutral-900",
162
+ children: /* @__PURE__ */ jsx("div", { className: getDataTableCellClassName({ columnId: header.column.id, kind: "header" }), children: header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext()) })
163
+ },
164
+ header.id
165
+ )) }, headerGroup.id)) }),
206
166
  /* @__PURE__ */ jsx(
207
167
  DataTableBody,
208
168
  {
@@ -212,15 +172,10 @@ function DataTable({
212
172
  getRowId,
213
173
  rowSelection,
214
174
  emptyState,
215
- group: grouping ? {
216
- renderGroupRow: grouping.renderGroupRow,
217
- renderGroupSelector: selection ? SelectColumnCell : void 0,
218
- isOpen: (row) => isGroupOpen(getRowId(row.original)),
219
- onToggle: (row) => toggleGroup(getRowId(row.original))
220
- } : void 0
175
+ group: groupConfig
221
176
  }
222
177
  )
223
- ] }) }) }),
178
+ ] }) }),
224
179
  !!pagination && /* @__PURE__ */ jsx("div", { className: "border-t px-4 py-2", children: /* @__PURE__ */ jsx(
225
180
  DataTablePagination,
226
181
  {
@@ -1 +1 @@
1
- {"version":3,"file":"DataTable.js","sources":["../../../src/components/DataTable/DataTable.tsx"],"sourcesContent":["'use client'\n\nimport {\n flexRender,\n getCoreRowModel,\n getExpandedRowModel,\n getPaginationRowModel,\n useReactTable,\n VisibilityState,\n Row,\n PaginationState,\n Updater,\n} from '@tanstack/react-table'\nimport * as React from 'react'\n\nimport { Table as TableComponent, TableHeader, TableHead, TableRow } from '../Table'\nimport { Typography } from '../Typography'\n\nimport { DataTableBody } from './components/DataTableBody'\nimport { DataTableGroupRowSelector } from './components/DataTableGroupRowSelector'\nimport { DataTablePagination } from './components/DataTablePagination'\nimport { DataTableRowSelector } from './components/DataTableRowSelector'\nimport { DataTableSelectHeader } from './components/DataTableSelectHeader'\nimport { DataTableToolbar } from './components/DataTableToolbar'\nimport { useGroupExpansion } from './hooks/useGroupExpansion'\nimport { useSelection } from './hooks/useSelection'\nimport { DataTableProps } from './types'\nimport { flattenLeaves } from './utils'\n\nimport { cn } from '@/lib/utils'\n\n/**\n * A feature-rich data table component built on top of TanStack Table.\n * Provides sorting, filtering, pagination, and column visibility controls.\n */\nexport function DataTable<TData extends object>({\n columns: userColumns,\n data,\n getRowId = (row: TData) => (row as { id: string }).id,\n columnVisibility: columnVisibilityConfig,\n isLoading = false,\n pagination,\n grouping,\n primaryFilters,\n secondaryFilters,\n activePrimaryFiltersCount = 0,\n activeSecondaryFiltersCount = 0,\n selection,\n labels = {\n filters: 'Filters',\n moreFilters: 'More filters',\n },\n emptyState = {\n title: 'No data available',\n description: 'Try adjusting your filters or search criteria',\n },\n className,\n tableClassName,\n}: DataTableProps<TData>) {\n const [internalColumnVisibility, setInternalColumnVisibility] = React.useState<VisibilityState>({})\n const [pageIndex, setPageIndex] = React.useState(0)\n\n const columnVisibilityState = columnVisibilityConfig?.state ?? internalColumnVisibility\n const setColumnVisibilityState = columnVisibilityConfig?.onChange ?? setInternalColumnVisibility\n\n const { isGroupOpen, toggleGroup } = useGroupExpansion({ grouping, data, getRowId })\n\n const selectionData = React.useMemo(\n () => (grouping ? flattenLeaves(data, grouping.getSubRows) : data),\n [grouping, data],\n )\n\n const isBackendPagination = pagination !== undefined && 'onPageChange' in pagination\n\n const total = isBackendPagination ? pagination.total : data.length\n const pageSize = pagination?.pageSize ?? (isLoading ? 10 : data.length)\n const totalPages = Math.ceil(total / pageSize)\n\n const { selectedIds, handleRowSelect, handleSelectAll } = useSelection({\n data: selectionData,\n getRowId,\n selection,\n })\n\n const rowSelection = React.useMemo(\n () => Object.fromEntries(Array.from(selectedIds).map((id) => [id, true])),\n [selectedIds],\n )\n\n const SelectColumnHeader = React.useCallback(\n () => (\n <DataTableSelectHeader\n isBackendPagination={isBackendPagination}\n selectedIds={selectedIds}\n data={selectionData}\n handleSelectAll={handleSelectAll}\n isLoading={isLoading}\n isSelectionDisabled={selection?.isSelectionDisabled ?? false}\n selectionDisabledTooltip={selection?.labels?.selectionDisabledTooltip}\n />\n ),\n [\n isBackendPagination,\n selectedIds,\n selectionData,\n handleSelectAll,\n isLoading,\n selection?.isSelectionDisabled,\n selection?.labels?.selectionDisabledTooltip,\n ],\n )\n\n const SelectColumnCell = React.useCallback(\n ({ row }: { row: Row<TData> }) => {\n if (grouping && row.getCanExpand()) {\n return (\n <DataTableGroupRowSelector\n row={row}\n selectedIds={selectedIds}\n getRowId={getRowId}\n handleRowSelect={handleRowSelect}\n />\n )\n }\n return (\n <DataTableRowSelector\n row={row}\n selectedIds={selectedIds}\n getRowId={getRowId}\n handleRowSelect={handleRowSelect}\n isRowSelectionDisabled={selection?.isRowSelectionDisabled}\n rowSelectionDisabledTooltip={selection?.labels?.rowSelectionDisabledTooltip}\n />\n )\n },\n [\n grouping,\n selectedIds,\n getRowId,\n handleRowSelect,\n selection?.isRowSelectionDisabled,\n selection?.labels?.rowSelectionDisabledTooltip,\n ],\n )\n\n const tableColumns = React.useMemo(() => {\n const baseColumns = [...userColumns]\n if (selection !== undefined) {\n const selectColumn = {\n id: 'select',\n size: 50,\n cell: SelectColumnCell,\n header: SelectColumnHeader,\n }\n baseColumns.unshift(selectColumn)\n }\n return baseColumns\n }, [userColumns, selection, SelectColumnCell, SelectColumnHeader])\n\n const toolbarSelectionProps = React.useMemo(() => {\n if (isBackendPagination && selection) {\n return {\n isSelectionStarted: selection.isSelectionStarted,\n onSelectionStart: selection.onSelectionStart,\n onSelectionCancel: selection.onSelectionCancel,\n selectionSummary: selection.labels?.selectionSummary,\n isSelectionDisabled: selection.isSelectionDisabled,\n labels: selection.labels,\n }\n }\n return undefined\n }, [isBackendPagination, selection])\n\n const currentPage = isBackendPagination ? pagination.currentPage : pageIndex + 1\n const handlePageChange = isBackendPagination ? pagination.onPageChange : (page: number) => setPageIndex(page - 1)\n\n const tablePaginationState = React.useMemo(() => {\n if (!pagination) {\n return undefined\n }\n return {\n pageIndex: isBackendPagination ? pagination.currentPage - 1 : pageIndex,\n pageSize,\n }\n }, [pagination, isBackendPagination, pageIndex, pageSize])\n\n const tableGetPaginationRowModel = React.useMemo(() => {\n return pagination && !isBackendPagination ? getPaginationRowModel() : undefined\n }, [pagination, isBackendPagination])\n\n const tableOnPaginationChange = React.useCallback(\n (updater: Updater<PaginationState>) => {\n if (typeof updater === 'function') {\n const newState = updater({ pageIndex, pageSize })\n setPageIndex(newState.pageIndex)\n }\n },\n [pageIndex, pageSize, setPageIndex],\n )\n\n const table = useReactTable({\n data,\n columns: tableColumns,\n getCoreRowModel: getCoreRowModel(),\n getPaginationRowModel: tableGetPaginationRowModel,\n getSubRows: grouping?.getSubRows,\n getExpandedRowModel: grouping ? getExpandedRowModel() : undefined,\n onColumnVisibilityChange: setColumnVisibilityState,\n enableRowSelection: !!selection,\n getRowId: getRowId,\n state: {\n columnVisibility: columnVisibilityState,\n rowSelection,\n pagination: tablePaginationState,\n expanded: grouping ? true : undefined,\n },\n manualPagination: isBackendPagination,\n onPaginationChange: isBackendPagination ? undefined : tableOnPaginationChange,\n })\n\n return (\n <div className={cn('flex h-full min-h-0 w-full flex-1 flex-col gap-2 overflow-hidden', className)}>\n <DataTableToolbar\n table={table}\n columnVisibility={columnVisibilityConfig}\n primaryFilters={primaryFilters}\n secondaryFilters={secondaryFilters}\n activePrimaryFiltersCount={activePrimaryFiltersCount}\n activeSecondaryFiltersCount={activeSecondaryFiltersCount}\n labels={labels}\n selection={toolbarSelectionProps}\n />\n\n <div className=\"flex min-h-0 flex-1 flex-col rounded-md border bg-white\">\n <div className=\"min-h-0 flex-1 overflow-auto\">\n <div className=\"h-full scrollbar-gutter-stable overflow-auto overscroll-x-none overscroll-y-auto\">\n <TableComponent className=\"w-full\" tableClassName={cn('min-w-max', tableClassName)}>\n <TableHeader className=\"sticky top-0 z-10 bg-neutral-50\">\n {table.getHeaderGroups().map((headerGroup) => (\n <TableRow key={headerGroup.id}>\n {headerGroup.headers.map((header) => (\n <TableHead key={header.id} style={{ width: header.column.columnDef.size }}>\n <Typography weight=\"medium\" className=\"whitespace-nowrap\">\n {header.isPlaceholder\n ? null\n : flexRender(header.column.columnDef.header, header.getContext())}\n </Typography>\n </TableHead>\n ))}\n </TableRow>\n ))}\n </TableHeader>\n <DataTableBody\n table={table}\n isLoading={isLoading}\n pageSize={pageSize}\n getRowId={getRowId}\n rowSelection={rowSelection}\n emptyState={emptyState}\n group={\n grouping\n ? {\n renderGroupRow: grouping.renderGroupRow,\n renderGroupSelector: selection ? SelectColumnCell : undefined,\n isOpen: (row: Row<TData>) => isGroupOpen(getRowId(row.original)),\n onToggle: (row: Row<TData>) => toggleGroup(getRowId(row.original)),\n }\n : undefined\n }\n />\n </TableComponent>\n </div>\n </div>\n {!!pagination && (\n <div className=\"border-t px-4 py-2\">\n <DataTablePagination\n table={table}\n total={total}\n pageSize={pageSize}\n currentPage={currentPage}\n totalPages={totalPages}\n onPageChange={handlePageChange}\n isLoading={pagination.isLoading}\n labels={pagination.labels}\n />\n </div>\n )}\n </div>\n </div>\n )\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAmCO;AAAyC;AACrC;AACT;AACmD;AACjC;AACN;AACZ;AACA;AACA;AACA;AAC4B;AACE;AAC9B;AACS;AACE;AACI;AACf;AACa;AACJ;AACM;AACf;AACA;AAEF;AACE;AACA;AAEA;AACA;AAEA;AAEA;AAA4B;AACmC;AAC9C;AAGjB;AAEA;AACA;AACA;AAEA;AAAuE;AAC/D;AACN;AACA;AAGF;AAA2B;AAC+C;AAC5D;AAGd;AAAiC;AAE7B;AAAC;AAAA;AACC;AACA;AACM;AACN;AACA;AACuD;AACV;AAAA;AAC/C;AAEF;AACE;AACA;AACA;AACA;AACA;AACW;AACQ;AACrB;AAGF;AAA+B;AAE3B;AACE;AACE;AAAC;AAAA;AACC;AACA;AACA;AACA;AAAA;AACF;AAGJ;AACE;AAAC;AAAA;AACC;AACA;AACA;AACA;AACmC;AACa;AAAA;AAClD;AAEJ;AACA;AACE;AACA;AACA;AACA;AACW;AACQ;AACrB;AAGF;AACE;AACA;AACE;AAAqB;AACf;AACE;AACA;AACE;AAEV;AAAgC;AAElC;AAAO;AAGT;AACE;AACE;AAAO;AACyB;AACF;AACC;AACO;AACL;AACb;AACpB;AAEF;AAAO;AAGT;AACA;AAEA;AACE;AACE;AAAO;AAET;AAAO;AACyD;AAC9D;AACF;AAGF;AACE;AAAsE;AAGxE;AAAsC;AAElC;AACE;AACA;AAA+B;AACjC;AACF;AACkC;AAGpC;AAA4B;AAC1B;AACS;AACwB;AACV;AACD;AACkC;AAC9B;AACJ;AACtB;AACO;AACa;AAClB;AACY;AACgB;AAC9B;AACkB;AACoC;AAGxD;AAEI;AAAA;AAAC;AAAA;AACC;AACkB;AAClB;AACA;AACA;AACA;AACA;AACW;AAAA;AACb;AAGE;AAGM;AAcA;AACA;AAAC;AAAA;AACC;AACA;AACA;AACA;AACA;AACA;AAGM;AAC2B;AAC2B;AACW;AACE;AAEnE;AAAA;AAER;AAGN;AAGI;AAAC;AAAA;AACC;AACA;AACA;AACA;AACA;AACc;AACQ;AACH;AAAA;AAEvB;AAEJ;AAGN;;"}
1
+ {"version":3,"file":"DataTable.js","sources":["../../../src/components/DataTable/DataTable.tsx"],"sourcesContent":["'use client'\n\nimport {\n flexRender,\n getCoreRowModel,\n getExpandedRowModel,\n getPaginationRowModel,\n useReactTable,\n VisibilityState,\n PaginationState,\n Updater,\n} from '@tanstack/react-table'\nimport * as React from 'react'\n\nimport { Table as TableComponent, TableHeader, TableHead, TableRow } from '../Table'\n\nimport { DataTableBody } from './components/DataTableBody'\nimport { getDataTableCellClassName } from './components/dataTableCellStyles'\nimport { DataTablePagination } from './components/DataTablePagination'\nimport { DataTableToolbar } from './components/DataTableToolbar'\nimport { useGroupExpansion } from './hooks/useGroupExpansion'\nimport { useSelectColumn } from './hooks/useSelectColumn'\nimport { useSelection } from './hooks/useSelection'\nimport { DataTableProps } from './types'\nimport { flattenLeaves } from './utils'\n\nimport { cn } from '@/lib/utils'\n\n/**\n * A feature-rich data table component built on top of TanStack Table.\n * Provides sorting, filtering, pagination, and column visibility controls.\n */\nexport function DataTable<TData extends object>({\n columns: userColumns,\n data,\n getRowId = (row: TData) => (row as { id: string }).id,\n columnVisibility: columnVisibilityConfig,\n isLoading = false,\n pagination,\n grouping,\n primaryFilters,\n secondaryFilters,\n activePrimaryFiltersCount = 0,\n activeSecondaryFiltersCount = 0,\n selection,\n labels = {\n filters: 'Filters',\n moreFilters: 'More filters',\n },\n emptyState = {\n title: 'No data available',\n description: 'Try adjusting your filters or search criteria',\n },\n className,\n tableClassName,\n}: DataTableProps<TData>) {\n const [internalColumnVisibility, setInternalColumnVisibility] = React.useState<VisibilityState>({})\n const [pageIndex, setPageIndex] = React.useState(0)\n\n const columnVisibilityState = columnVisibilityConfig?.state ?? internalColumnVisibility\n const setColumnVisibilityState = columnVisibilityConfig?.onChange ?? setInternalColumnVisibility\n\n const { isGroupOpen, toggleGroup } = useGroupExpansion({ grouping, data, getRowId })\n\n const selectionData = React.useMemo(\n () => (grouping ? flattenLeaves(data, grouping.getSubRows) : data),\n [grouping, data],\n )\n\n const isBackendPagination = pagination !== undefined && 'onPageChange' in pagination\n\n const total = isBackendPagination ? pagination.total : data.length\n const pageSize = pagination?.pageSize ?? (isLoading ? 10 : data.length)\n const totalPages = Math.ceil(total / pageSize)\n\n const { selectedIds, handleRowSelect, handleSelectAll } = useSelection({\n data: selectionData,\n getRowId,\n selection,\n })\n\n const rowSelection = React.useMemo(\n () => Object.fromEntries(Array.from(selectedIds).map((id) => [id, true])),\n [selectedIds],\n )\n\n const selectColumn = useSelectColumn({\n selection,\n selectedIds,\n selectionData,\n getRowId,\n handleRowSelect,\n handleSelectAll,\n isBackendPagination,\n isLoading,\n })\n\n const tableColumns = React.useMemo(() => {\n if (!selectColumn) return userColumns\n return [selectColumn.column, ...userColumns]\n }, [userColumns, selectColumn])\n\n const toolbarSelectionProps = React.useMemo(() => {\n if (isBackendPagination && selection) {\n return {\n isSelectionStarted: selection.isSelectionStarted,\n onSelectionStart: selection.onSelectionStart,\n onSelectionCancel: selection.onSelectionCancel,\n selectionSummary: selection.labels?.selectionSummary,\n isSelectionDisabled: selection.isSelectionDisabled,\n labels: selection.labels,\n }\n }\n return undefined\n }, [isBackendPagination, selection])\n\n const currentPage = isBackendPagination ? pagination.currentPage : pageIndex + 1\n const handlePageChange = isBackendPagination ? pagination.onPageChange : (page: number) => setPageIndex(page - 1)\n\n const tablePaginationState = React.useMemo(() => {\n if (!pagination) {\n return undefined\n }\n return {\n pageIndex: isBackendPagination ? pagination.currentPage - 1 : pageIndex,\n pageSize,\n }\n }, [pagination, isBackendPagination, pageIndex, pageSize])\n\n const tableGetPaginationRowModel = React.useMemo(() => {\n return pagination && !isBackendPagination ? getPaginationRowModel() : undefined\n }, [pagination, isBackendPagination])\n\n const tableOnPaginationChange = React.useCallback(\n (updater: Updater<PaginationState>) => {\n if (typeof updater === 'function') {\n const newState = updater({ pageIndex, pageSize })\n setPageIndex(newState.pageIndex)\n }\n },\n [pageIndex, pageSize],\n )\n\n const groupConfig = React.useMemo(() => {\n if (!grouping) return undefined\n\n return {\n renderGroupRow: grouping.renderGroupRow,\n renderGroupSelector: selectColumn?.GroupSelectCell,\n isGroupOpen,\n toggleGroup,\n getRowId,\n }\n }, [grouping, selectColumn, isGroupOpen, toggleGroup, getRowId])\n\n const table = useReactTable({\n data,\n columns: tableColumns,\n getCoreRowModel: getCoreRowModel(),\n getPaginationRowModel: tableGetPaginationRowModel,\n getSubRows: grouping?.getSubRows,\n getExpandedRowModel: grouping ? getExpandedRowModel() : undefined,\n onColumnVisibilityChange: setColumnVisibilityState,\n enableRowSelection: !!selection,\n getRowId,\n state: {\n columnVisibility: columnVisibilityState,\n rowSelection,\n pagination: tablePaginationState,\n expanded: grouping ? true : undefined,\n },\n manualPagination: isBackendPagination,\n onPaginationChange: isBackendPagination ? undefined : tableOnPaginationChange,\n })\n\n return (\n <div className={cn('flex h-full min-h-0 w-full flex-1 flex-col gap-2 overflow-hidden', className)}>\n <DataTableToolbar\n table={table}\n columnVisibility={columnVisibilityConfig}\n primaryFilters={primaryFilters}\n secondaryFilters={secondaryFilters}\n activePrimaryFiltersCount={activePrimaryFiltersCount}\n activeSecondaryFiltersCount={activeSecondaryFiltersCount}\n labels={labels}\n selection={toolbarSelectionProps}\n />\n\n <div className=\"flex min-h-0 flex-1 flex-col rounded-md border bg-white\">\n <div className=\"min-h-0 flex-1 overflow-auto overscroll-x-none overscroll-y-auto\">\n <TableComponent className=\"w-full\" tableClassName={cn('min-w-max', tableClassName)}>\n <TableHeader className=\"sticky top-0 z-10 bg-neutral-50\">\n {table.getHeaderGroups().map((headerGroup) => (\n <TableRow key={headerGroup.id}>\n {headerGroup.headers.map((header) => (\n <TableHead\n key={header.id}\n style={{ width: header.column.columnDef.size }}\n className=\"h-auto p-0 text-neutral-900\"\n >\n <div className={getDataTableCellClassName({ columnId: header.column.id, kind: 'header' })}>\n {header.isPlaceholder\n ? null\n : flexRender(header.column.columnDef.header, header.getContext())}\n </div>\n </TableHead>\n ))}\n </TableRow>\n ))}\n </TableHeader>\n <DataTableBody\n table={table}\n isLoading={isLoading}\n pageSize={pageSize}\n getRowId={getRowId}\n rowSelection={rowSelection}\n emptyState={emptyState}\n group={groupConfig}\n />\n </TableComponent>\n </div>\n {!!pagination && (\n <div className=\"border-t px-4 py-2\">\n <DataTablePagination\n table={table}\n total={total}\n pageSize={pageSize}\n currentPage={currentPage}\n totalPages={totalPages}\n onPageChange={handlePageChange}\n isLoading={pagination.isLoading}\n labels={pagination.labels}\n />\n </div>\n )}\n </div>\n </div>\n )\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;AAgCO;AAAyC;AACrC;AACT;AACmD;AACjC;AACN;AACZ;AACA;AACA;AACA;AAC4B;AACE;AAC9B;AACS;AACE;AACI;AACf;AACa;AACJ;AACM;AACf;AACA;AAEF;AACE;AACA;AAEA;AACA;AAEA;AAEA;AAA4B;AACmC;AAC9C;AAGjB;AAEA;AACA;AACA;AAEA;AAAuE;AAC/D;AACN;AACA;AAGF;AAA2B;AAC+C;AAC5D;AAGd;AAAqC;AACnC;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AAGF;AACE;AACA;AAA2C;AAG7C;AACE;AACE;AAAO;AACyB;AACF;AACC;AACO;AACL;AACb;AACpB;AAEF;AAAO;AAGT;AACA;AAEA;AACE;AACE;AAAO;AAET;AAAO;AACyD;AAC9D;AACF;AAGF;AACE;AAAsE;AAGxE;AAAsC;AAElC;AACE;AACA;AAA+B;AACjC;AACF;AACoB;AAGtB;AACE;AAEA;AAAO;AACoB;AACU;AACnC;AACA;AACA;AACF;AAGF;AAA4B;AAC1B;AACS;AACwB;AACV;AACD;AACkC;AAC9B;AACJ;AACtB;AACO;AACa;AAClB;AACY;AACgB;AAC9B;AACkB;AACoC;AAGxD;AAEI;AAAA;AAAC;AAAA;AACC;AACkB;AAClB;AACA;AACA;AACA;AACA;AACW;AAAA;AACb;AAGE;AAEI;AAIQ;AAAC;AAAA;AAE8C;AACnC;AAMV;AAAA;AARY;AAatB;AACA;AAAC;AAAA;AACC;AACA;AACA;AACA;AACA;AACA;AACO;AAAA;AACT;AAEJ;AAGI;AAAC;AAAA;AACC;AACA;AACA;AACA;AACA;AACc;AACQ;AACH;AAAA;AAEvB;AAEJ;AAGN;;"}
@@ -1,13 +1,13 @@
1
- import { Table, Row } from '@tanstack/react-table';
2
- import { ReactNode } from 'react';
3
- import { RowIdentifierFn } from '../types';
1
+ import { Row, Table } from '@tanstack/react-table';
2
+ import { EmptyStateConfig, RowIdentifierFn } from '../types';
4
3
  type GroupRenderConfig<TData> = {
5
- readonly renderGroupRow?: (row: Row<TData>) => ReactNode;
4
+ readonly renderGroupRow?: (row: Row<TData>) => React.ReactNode;
6
5
  readonly renderGroupSelector?: React.ComponentType<{
7
6
  row: Row<TData>;
8
7
  }>;
9
- readonly isOpen: (row: Row<TData>) => boolean;
10
- readonly onToggle: (row: Row<TData>) => void;
8
+ readonly isGroupOpen: (groupId: string) => boolean;
9
+ readonly toggleGroup: (groupId: string) => void;
10
+ readonly getRowId: RowIdentifierFn<TData>;
11
11
  };
12
12
  type DataTableBodyProps<TData> = {
13
13
  readonly table: Table<TData>;
@@ -15,13 +15,7 @@ type DataTableBodyProps<TData> = {
15
15
  readonly pageSize: number;
16
16
  readonly getRowId: RowIdentifierFn<TData>;
17
17
  readonly rowSelection: Record<string, boolean>;
18
- readonly emptyState: {
19
- title: string;
20
- description: string;
21
- imageRoute?: string;
22
- imageAlt?: string;
23
- imageClassName?: string;
24
- };
18
+ readonly emptyState: EmptyStateConfig;
25
19
  readonly group?: GroupRenderConfig<TData>;
26
20
  };
27
21
  export declare function DataTableBody<TData>({ table, isLoading, pageSize, getRowId, rowSelection, emptyState, group, }: DataTableBodyProps<TData>): import("react/jsx-runtime").JSX.Element;
@@ -3,23 +3,38 @@ import { flexRender } from '@tanstack/react-table';
3
3
  import { Skeleton } from '../../Skeleton/Skeleton.js';
4
4
  import { TableBody, TableRow, TableCell } from '../../Table/Table.js';
5
5
  import { Typography } from '../../Typography/Typography.js';
6
+ import { DataTableCell } from './DataTableCell.js';
7
+ import { getSkeletonClassName, SELECT_COLUMN_ID, ACTIONS_COLUMN_ID } from './dataTableCellStyles.js';
6
8
  import { DataTableGroupRow } from './DataTableGroupRow.js';
7
9
  import { cn } from '../../../lib/utils.js';
8
10
 
9
- function TableRowComponent({ row, isSelected, isCollapsible = false, isOpen = true }) {
10
- if (!isCollapsible) {
11
- return /* @__PURE__ */ jsx(TableRow, { "data-selected": isSelected, children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx(TableCell, { style: { width: cell.column.columnDef.size }, children: /* @__PURE__ */ jsx(Typography, { className: "whitespace-nowrap", children: cell.column.columnDef.cell && flexRender(cell.column.columnDef.cell, cell.getContext()) }) }, cell.id)) });
12
- }
13
- return /* @__PURE__ */ jsx(TableRow, { "data-selected": isSelected, className: cn("transition-colors", !isOpen && "border-b-0"), children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx(TableCell, { style: { width: cell.column.columnDef.size }, className: "p-0", children: /* @__PURE__ */ jsx(
14
- "div",
11
+ function DataTableRow({
12
+ row,
13
+ isSelected,
14
+ isCollapsible = false,
15
+ isOpen = true
16
+ }) {
17
+ return /* @__PURE__ */ jsx(
18
+ TableRow,
15
19
  {
16
- className: cn(
17
- "grid transition-[grid-template-rows] duration-200 ease-in-out",
18
- isOpen ? "grid-rows-[1fr]" : "grid-rows-[0fr]"
19
- ),
20
- children: /* @__PURE__ */ jsx("div", { className: "min-w-max overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "px-4 py-4", children: /* @__PURE__ */ jsx(Typography, { className: "whitespace-nowrap", children: cell.column.columnDef.cell && flexRender(cell.column.columnDef.cell, cell.getContext()) }) }) })
20
+ "data-selected": isSelected,
21
+ className: cn(isCollapsible && "transition-colors", isCollapsible && !isOpen && "border-b-0"),
22
+ children: row.getVisibleCells().map((cell) => {
23
+ const content = cell.column.columnDef.cell && flexRender(cell.column.columnDef.cell, cell.getContext());
24
+ return /* @__PURE__ */ jsx(
25
+ DataTableCell,
26
+ {
27
+ columnId: cell.column.id,
28
+ isCollapsible,
29
+ isOpen,
30
+ style: { width: cell.column.columnDef.size },
31
+ children: content
32
+ },
33
+ cell.id
34
+ );
35
+ })
21
36
  }
22
- ) }, cell.id)) });
37
+ );
23
38
  }
24
39
  function DataTableBody({
25
40
  table,
@@ -31,22 +46,16 @@ function DataTableBody({
31
46
  group
32
47
  }) {
33
48
  if (isLoading) {
34
- return /* @__PURE__ */ jsx(TableBody, { children: Array.from({ length: pageSize }).map((_unused, index) => /* @__PURE__ */ jsx(TableRow, { children: table.getAllColumns().filter((column) => column.getIsVisible()).map((column) => {
35
- let skeletonClass = "h-[20px] w-full";
36
- if (column.id === "actions") skeletonClass = "h-8 w-8 shrink-0";
37
- else if (column.id === "select") skeletonClass = "h-5 w-5 shrink-0";
38
- let justifyClass = "justify-center";
39
- if (column.id === "actions") justifyClass = "justify-end";
40
- else if (column.id === "select") justifyClass = "justify-start";
41
- return /* @__PURE__ */ jsx(
42
- TableCell,
43
- {
44
- style: { width: column.columnDef.size },
45
- children: /* @__PURE__ */ jsx("div", { className: cn("flex items-center", justifyClass), children: /* @__PURE__ */ jsx(Skeleton, { className: cn(skeletonClass) }) })
46
- },
47
- `skeleton-cell-${String(index)}-${column.id}`
48
- );
49
- }) }, `skeleton-row-${String(index)}`)) });
49
+ return /* @__PURE__ */ jsx(TableBody, { children: Array.from({ length: pageSize }).map((_unused, index) => /* @__PURE__ */ jsx(TableRow, { children: table.getAllColumns().filter((column) => column.getIsVisible()).map((column) => /* @__PURE__ */ jsx(
50
+ DataTableCell,
51
+ {
52
+ columnId: column.id,
53
+ style: { width: column.columnDef.size },
54
+ className: column.id !== SELECT_COLUMN_ID && column.id !== ACTIONS_COLUMN_ID ? "w-full" : void 0,
55
+ children: /* @__PURE__ */ jsx(Skeleton, { className: getSkeletonClassName(column.id) })
56
+ },
57
+ `skeleton-cell-${String(index)}-${column.id}`
58
+ )) }, `skeleton-row-${String(index)}`)) });
50
59
  }
51
60
  const rows = table.getRowModel().rows;
52
61
  if (!rows.length) {
@@ -75,8 +84,8 @@ function DataTableBody({
75
84
  colSpan: visibleColumnCount,
76
85
  selector: group.renderGroupSelector ? /* @__PURE__ */ jsx(group.renderGroupSelector, { row }) : void 0,
77
86
  content,
78
- isOpen: group.isOpen(row),
79
- onToggle: () => group.onToggle(row)
87
+ isOpen: group.isGroupOpen(rowId),
88
+ onToggle: () => group.toggleGroup(rowId)
80
89
  },
81
90
  rowId
82
91
  );
@@ -84,12 +93,12 @@ function DataTableBody({
84
93
  const isSelected = rowSelection[rowId] ?? false;
85
94
  const parentRow = group ? row.getParentRow() : void 0;
86
95
  return /* @__PURE__ */ jsx(
87
- TableRowComponent,
96
+ DataTableRow,
88
97
  {
89
98
  row,
90
99
  isSelected,
91
100
  isCollapsible: !!group,
92
- isOpen: parentRow ? group?.isOpen(parentRow) ?? true : true
101
+ isOpen: parentRow ? group?.isGroupOpen(getRowId(parentRow.original)) ?? true : true
93
102
  },
94
103
  rowId
95
104
  );
@@ -1 +1 @@
1
- {"version":3,"file":"DataTableBody.js","sources":["../../../../src/components/DataTable/components/DataTableBody.tsx"],"sourcesContent":["import { Table, flexRender, Row } from '@tanstack/react-table'\nimport { ReactNode } from 'react'\n\nimport { Skeleton } from '../../Skeleton'\nimport { TableBody, TableCell, TableRow } from '../../Table'\nimport { Typography } from '../../Typography'\nimport { RowIdentifierFn } from '../types'\n\nimport { DataTableGroupRow } from './DataTableGroupRow'\n\nimport { cn } from '@/lib/utils'\n\ntype GroupRenderConfig<TData> = {\n readonly renderGroupRow?: (row: Row<TData>) => ReactNode\n readonly renderGroupSelector?: React.ComponentType<{ row: Row<TData> }>\n readonly isOpen: (row: Row<TData>) => boolean\n readonly onToggle: (row: Row<TData>) => void\n}\n\ntype DataTableBodyProps<TData> = {\n readonly table: Table<TData>\n readonly isLoading?: boolean\n readonly pageSize: number\n readonly getRowId: RowIdentifierFn<TData>\n readonly rowSelection: Record<string, boolean>\n readonly emptyState: {\n title: string\n description: string\n imageRoute?: string\n imageAlt?: string\n imageClassName?: string\n }\n readonly group?: GroupRenderConfig<TData>\n}\n\ntype TableRowProps<TData> = {\n readonly row: Row<TData>\n readonly isSelected: boolean\n readonly isCollapsible?: boolean\n readonly isOpen?: boolean\n}\n\nfunction TableRowComponent<TData>({ row, isSelected, isCollapsible = false, isOpen = true }: TableRowProps<TData>) {\n if (!isCollapsible) {\n return (\n <TableRow data-selected={isSelected}>\n {row.getVisibleCells().map((cell) => (\n <TableCell key={cell.id} style={{ width: cell.column.columnDef.size }}>\n <Typography className=\"whitespace-nowrap\">\n {cell.column.columnDef.cell && flexRender(cell.column.columnDef.cell, cell.getContext())}\n </Typography>\n </TableCell>\n ))}\n </TableRow>\n )\n }\n\n return (\n <TableRow data-selected={isSelected} className={cn('transition-colors', !isOpen && 'border-b-0')}>\n {row.getVisibleCells().map((cell) => (\n <TableCell key={cell.id} style={{ width: cell.column.columnDef.size }} className=\"p-0\">\n <div\n className={cn(\n 'grid transition-[grid-template-rows] duration-200 ease-in-out',\n isOpen ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]',\n )}\n >\n <div className=\"min-w-max overflow-hidden\">\n <div className=\"px-4 py-4\">\n <Typography className=\"whitespace-nowrap\">\n {cell.column.columnDef.cell && flexRender(cell.column.columnDef.cell, cell.getContext())}\n </Typography>\n </div>\n </div>\n </div>\n </TableCell>\n ))}\n </TableRow>\n )\n}\n\nexport function DataTableBody<TData>({\n table,\n isLoading,\n pageSize,\n getRowId,\n rowSelection,\n emptyState,\n group,\n}: DataTableBodyProps<TData>) {\n if (isLoading) {\n return (\n <TableBody>\n {Array.from({ length: pageSize }).map((_unused, index) => (\n <TableRow key={`skeleton-row-${String(index)}`}>\n {table\n .getAllColumns()\n .filter((column) => column.getIsVisible())\n .map((column) => {\n let skeletonClass = 'h-[20px] w-full'\n if (column.id === 'actions') skeletonClass = 'h-8 w-8 shrink-0'\n else if (column.id === 'select') skeletonClass = 'h-5 w-5 shrink-0'\n\n let justifyClass = 'justify-center'\n if (column.id === 'actions') justifyClass = 'justify-end'\n else if (column.id === 'select') justifyClass = 'justify-start'\n\n return (\n <TableCell\n key={`skeleton-cell-${String(index)}-${column.id}`}\n style={{ width: column.columnDef.size }}\n >\n <div className={cn('flex items-center', justifyClass)}>\n <Skeleton className={cn(skeletonClass)} />\n </div>\n </TableCell>\n )\n })}\n </TableRow>\n ))}\n </TableBody>\n )\n }\n\n const rows = table.getRowModel().rows\n\n if (!rows.length) {\n const visibleColumns = table.getAllColumns().filter((col) => col.getIsVisible())\n\n return (\n <TableBody>\n <TableRow className=\"h-full\">\n <TableCell colSpan={visibleColumns.length} className=\"h-full p-0\">\n <div className=\"mt-20 flex h-full w-full flex-col items-center justify-center\">\n {emptyState.imageRoute && (\n <img\n className={cn('mb-6 w-[200px] md:w-[300px]', emptyState.imageClassName)}\n src={emptyState.imageRoute}\n alt={emptyState.imageAlt ?? 'No data available'}\n />\n )}\n <Typography variant=\"title-md\" weight=\"semibold\" className=\"text-center\">\n {emptyState.title}\n </Typography>\n <Typography variant=\"title-sm\" className=\"text-center opacity-80\">\n {emptyState.description}\n </Typography>\n </div>\n </TableCell>\n </TableRow>\n </TableBody>\n )\n }\n\n const visibleColumnCount = table.getVisibleLeafColumns().length\n\n return (\n <TableBody>\n {rows.map((row) => {\n const rowId = getRowId(row.original)\n\n if (group && row.getCanExpand()) {\n const content = group.renderGroupRow?.(row) ?? `${String(row.getLeafRows().length)} items`\n return (\n <DataTableGroupRow\n key={rowId}\n colSpan={visibleColumnCount}\n selector={group.renderGroupSelector ? <group.renderGroupSelector row={row} /> : undefined}\n content={content}\n isOpen={group.isOpen(row)}\n onToggle={() => group.onToggle(row)}\n />\n )\n }\n\n const isSelected = rowSelection[rowId] ?? false\n const parentRow = group ? row.getParentRow() : undefined\n return (\n <TableRowComponent\n key={rowId}\n row={row}\n isSelected={isSelected}\n isCollapsible={!!group}\n isOpen={parentRow ? (group?.isOpen(parentRow) ?? true) : true}\n />\n )\n })}\n </TableBody>\n )\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DataTableBody.js","sources":["../../../../src/components/DataTable/components/DataTableBody.tsx"],"sourcesContent":["import { flexRender, Row, Table } from '@tanstack/react-table'\n\nimport { Skeleton } from '../../Skeleton'\nimport { TableBody, TableCell, TableRow } from '../../Table'\nimport { Typography } from '../../Typography'\nimport { EmptyStateConfig, RowIdentifierFn } from '../types'\n\nimport { DataTableCell } from './DataTableCell'\nimport { ACTIONS_COLUMN_ID, getSkeletonClassName, SELECT_COLUMN_ID } from './dataTableCellStyles'\nimport { DataTableGroupRow } from './DataTableGroupRow'\n\nimport { cn } from '@/lib/utils'\n\ntype GroupRenderConfig<TData> = {\n readonly renderGroupRow?: (row: Row<TData>) => React.ReactNode\n readonly renderGroupSelector?: React.ComponentType<{ row: Row<TData> }>\n readonly isGroupOpen: (groupId: string) => boolean\n readonly toggleGroup: (groupId: string) => void\n readonly getRowId: RowIdentifierFn<TData>\n}\n\ntype DataTableBodyProps<TData> = {\n readonly table: Table<TData>\n readonly isLoading?: boolean\n readonly pageSize: number\n readonly getRowId: RowIdentifierFn<TData>\n readonly rowSelection: Record<string, boolean>\n readonly emptyState: EmptyStateConfig\n readonly group?: GroupRenderConfig<TData>\n}\n\ntype DataTableRowProps<TData> = {\n readonly row: Row<TData>\n readonly isSelected: boolean\n readonly isCollapsible?: boolean\n readonly isOpen?: boolean\n}\n\nfunction DataTableRow<TData>({\n row,\n isSelected,\n isCollapsible = false,\n isOpen = true,\n}: DataTableRowProps<TData>) {\n return (\n <TableRow\n data-selected={isSelected}\n className={cn(isCollapsible && 'transition-colors', isCollapsible && !isOpen && 'border-b-0')}\n >\n {row.getVisibleCells().map((cell) => {\n const content = cell.column.columnDef.cell && flexRender(cell.column.columnDef.cell, cell.getContext())\n\n return (\n <DataTableCell\n key={cell.id}\n columnId={cell.column.id}\n isCollapsible={isCollapsible}\n isOpen={isOpen}\n style={{ width: cell.column.columnDef.size }}\n >\n {content}\n </DataTableCell>\n )\n })}\n </TableRow>\n )\n}\n\nexport function DataTableBody<TData>({\n table,\n isLoading,\n pageSize,\n getRowId,\n rowSelection,\n emptyState,\n group,\n}: DataTableBodyProps<TData>) {\n if (isLoading) {\n return (\n <TableBody>\n {Array.from({ length: pageSize }).map((_unused, index) => (\n <TableRow key={`skeleton-row-${String(index)}`}>\n {table\n .getAllColumns()\n .filter((column) => column.getIsVisible())\n .map((column) => (\n <DataTableCell\n key={`skeleton-cell-${String(index)}-${column.id}`}\n columnId={column.id}\n style={{ width: column.columnDef.size }}\n className={\n column.id !== SELECT_COLUMN_ID && column.id !== ACTIONS_COLUMN_ID ? 'w-full' : undefined\n }\n >\n <Skeleton className={getSkeletonClassName(column.id)} />\n </DataTableCell>\n ))}\n </TableRow>\n ))}\n </TableBody>\n )\n }\n\n const rows = table.getRowModel().rows\n\n if (!rows.length) {\n const visibleColumns = table.getAllColumns().filter((col) => col.getIsVisible())\n\n return (\n <TableBody>\n <TableRow className=\"h-full\">\n <TableCell colSpan={visibleColumns.length} className=\"h-full p-0\">\n <div className=\"mt-20 flex h-full w-full flex-col items-center justify-center\">\n {emptyState.imageRoute && (\n <img\n className={cn('mb-6 w-[200px] md:w-[300px]', emptyState.imageClassName)}\n src={emptyState.imageRoute}\n alt={emptyState.imageAlt ?? 'No data available'}\n />\n )}\n <Typography variant=\"title-md\" weight=\"semibold\" className=\"text-center\">\n {emptyState.title}\n </Typography>\n <Typography variant=\"title-sm\" className=\"text-center opacity-80\">\n {emptyState.description}\n </Typography>\n </div>\n </TableCell>\n </TableRow>\n </TableBody>\n )\n }\n\n const visibleColumnCount = table.getVisibleLeafColumns().length\n\n return (\n <TableBody>\n {rows.map((row) => {\n const rowId = getRowId(row.original)\n\n if (group && row.getCanExpand()) {\n const content = group.renderGroupRow?.(row) ?? `${String(row.getLeafRows().length)} items`\n return (\n <DataTableGroupRow\n key={rowId}\n colSpan={visibleColumnCount}\n selector={group.renderGroupSelector ? <group.renderGroupSelector row={row} /> : undefined}\n content={content}\n isOpen={group.isGroupOpen(rowId)}\n onToggle={() => group.toggleGroup(rowId)}\n />\n )\n }\n\n const isSelected = rowSelection[rowId] ?? false\n const parentRow = group ? row.getParentRow() : undefined\n return (\n <DataTableRow\n key={rowId}\n row={row}\n isSelected={isSelected}\n isCollapsible={!!group}\n isOpen={parentRow ? (group?.isGroupOpen(getRowId(parentRow.original)) ?? true) : true}\n />\n )\n })}\n </TableBody>\n )\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { ComponentProps, ReactNode } from 'react';
2
+ import { TableCell } from '../../Table';
3
+ type DataTableCellProps = {
4
+ readonly columnId: string;
5
+ readonly isCollapsible?: boolean;
6
+ readonly isOpen?: boolean;
7
+ readonly className?: string;
8
+ readonly children: ReactNode;
9
+ } & Omit<ComponentProps<typeof TableCell>, 'className' | 'children'>;
10
+ export declare function DataTableCell({ columnId, isCollapsible, isOpen, className, children, ...tableCellProps }: DataTableCellProps): import("react/jsx-runtime").JSX.Element;
11
+ export {};
@@ -0,0 +1,28 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { TableCell } from '../../Table/Table.js';
3
+ import { getDataTableCellClassName } from './dataTableCellStyles.js';
4
+ import { cn } from '../../../lib/utils.js';
5
+
6
+ function DataTableCell({
7
+ columnId,
8
+ isCollapsible = false,
9
+ isOpen = true,
10
+ className,
11
+ children,
12
+ ...tableCellProps
13
+ }) {
14
+ const content = /* @__PURE__ */ jsx("div", { className: cn(getDataTableCellClassName({ columnId }), className), children });
15
+ return /* @__PURE__ */ jsx(TableCell, { className: "p-0", ...tableCellProps, children: isCollapsible ? /* @__PURE__ */ jsx(
16
+ "div",
17
+ {
18
+ className: cn(
19
+ "grid transition-[grid-template-rows] duration-200 ease-in-out",
20
+ isOpen ? "grid-rows-[1fr]" : "grid-rows-[0fr]"
21
+ ),
22
+ children: /* @__PURE__ */ jsx("div", { className: "min-w-max overflow-hidden", children: content })
23
+ }
24
+ ) : content });
25
+ }
26
+
27
+ export { DataTableCell };
28
+ //# sourceMappingURL=DataTableCell.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataTableCell.js","sources":["../../../../src/components/DataTable/components/DataTableCell.tsx"],"sourcesContent":["import { ComponentProps, ReactNode } from 'react'\n\nimport { TableCell } from '../../Table'\n\nimport { getDataTableCellClassName } from './dataTableCellStyles'\n\nimport { cn } from '@/lib/utils'\n\ntype DataTableCellProps = {\n readonly columnId: string\n readonly isCollapsible?: boolean\n readonly isOpen?: boolean\n readonly className?: string\n readonly children: ReactNode\n} & Omit<ComponentProps<typeof TableCell>, 'className' | 'children'>\n\nexport function DataTableCell({\n columnId,\n isCollapsible = false,\n isOpen = true,\n className,\n children,\n ...tableCellProps\n}: DataTableCellProps) {\n const content = (\n <div className={cn(getDataTableCellClassName({ columnId }), className)}>{children}</div>\n )\n\n return (\n <TableCell className=\"p-0\" {...tableCellProps}>\n {isCollapsible ? (\n <div\n className={cn(\n 'grid transition-[grid-template-rows] duration-200 ease-in-out',\n isOpen ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]',\n )}\n >\n <div className=\"min-w-max overflow-hidden\">{content}</div>\n </div>\n ) : (\n content\n )}\n </TableCell>\n )\n}\n"],"names":[],"mappings":";;;;;AAgBO,SAAS,aAAA,CAAc;AAAA,EAC5B,QAAA;AAAA,EACA,aAAA,GAAgB,KAAA;AAAA,EAChB,MAAA,GAAS,IAAA;AAAA,EACT,SAAA;AAAA,EACA,QAAA;AAAA,EACA,GAAG;AACL,CAAA,EAAuB;AACrB,EAAA,MAAM,OAAA,mBACJ,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAW,EAAA,CAAG,yBAAA,CAA0B,EAAE,QAAA,EAAU,CAAA,EAAG,SAAS,CAAA,EAAI,QAAA,EAAS,CAAA;AAGpF,EAAA,2BACG,SAAA,EAAA,EAAU,SAAA,EAAU,KAAA,EAAO,GAAG,gBAC5B,QAAA,EAAA,aAAA,mBACC,GAAA;AAAA,IAAC,KAAA;AAAA,IAAA;AAAA,MACC,SAAA,EAAW,EAAA;AAAA,QACT,+DAAA;AAAA,QACA,SAAS,iBAAA,GAAoB;AAAA,OAC/B;AAAA,MAEA,QAAA,kBAAA,GAAA,CAAC,KAAA,EAAA,EAAI,SAAA,EAAU,2BAAA,EAA6B,QAAA,EAAA,OAAA,EAAQ;AAAA;AAAA,MAGtD,OAAA,EAEJ,CAAA;AAEJ;;;;"}
@@ -0,0 +1,30 @@
1
+ import { Row } from '@tanstack/react-table';
2
+ type HeaderProps<TData> = {
3
+ readonly variant: 'header';
4
+ readonly isBackendPagination: boolean;
5
+ readonly selectedIds: Set<string>;
6
+ readonly data: Array<TData>;
7
+ readonly handleSelectAll: (checked: boolean) => void;
8
+ readonly isLoading: boolean;
9
+ readonly isSelectionDisabled: boolean;
10
+ readonly selectionDisabledTooltip?: string;
11
+ };
12
+ type RowProps<TData extends object> = {
13
+ readonly variant: 'row';
14
+ readonly row: Row<TData>;
15
+ readonly selectedIds: Set<string>;
16
+ readonly getRowId: (original: TData) => string;
17
+ readonly handleRowSelect: (rowId: string, checked: boolean) => void;
18
+ readonly isRowSelectionDisabled?: boolean | ((row: TData) => boolean);
19
+ readonly rowSelectionDisabledTooltip?: string | ((row: TData) => string | undefined);
20
+ };
21
+ type GroupProps<TData extends object> = {
22
+ readonly variant: 'group';
23
+ readonly row: Row<TData>;
24
+ readonly selectedIds: Set<string>;
25
+ readonly getRowId: (original: TData) => string;
26
+ readonly handleRowSelect: (rowId: string, checked: boolean) => void;
27
+ };
28
+ type DataTableCheckboxProps<TData extends object> = HeaderProps<TData> | RowProps<TData> | GroupProps<TData>;
29
+ export declare function DataTableCheckbox<TData extends object>(props: DataTableCheckboxProps<TData>): import("react/jsx-runtime").JSX.Element;
30
+ export {};