@orfium/ictinus 5.43.2 → 5.43.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.
- package/.turbo/turbo-build.log +14 -14
- package/CHANGELOG.md +6 -0
- package/dist/package.json.d.ts +1 -1
- package/dist/package.json.js +1 -1
- package/dist/src/components/Box/Box.d.ts +5 -0
- package/dist/src/components/Table/Table.d.ts +5 -0
- package/dist/src/components/Typography/Typography.d.ts +5 -0
- package/dist/src/data-table/DataTable.test.d.ts +1 -0
- package/dist/src/data-table/DataTableBulkActions.d.ts +3 -0
- package/dist/src/data-table/DataTableCounter.d.ts +7 -0
- package/dist/src/data-table/index.d.ts +2 -0
- package/dist/vanilla/index.d.ts +12 -2
- package/dist/vanilla/index.js +2 -0
- package/dist/vanilla/package.json.js +1 -1
- package/dist/vanilla/src/data-table/DataTableBulkActions.js +13 -0
- package/dist/vanilla/src/data-table/DataTableCounter.js +25 -0
- package/dist/vanilla/src/data-table/DataTableEditColumns.js +1 -1
- package/dist/vanilla/src/data-table/DataTableHeaderCell.js +15 -13
- package/eslint.config.mjs +1 -1
- package/package.json +1 -1
- package/src/components/Box/Box.tsx +5 -0
- package/src/components/Table/Table.tsx +5 -0
- package/src/components/Typography/Typography.tsx +5 -0
- package/src/data-table/DataTable.test.tsx +425 -0
- package/src/data-table/DataTableBulkActions.tsx +17 -0
- package/src/data-table/DataTableCounter.tsx +37 -0
- package/src/data-table/DataTableEditColumns.tsx +3 -1
- package/src/data-table/DataTableHeaderCell.tsx +96 -90
- package/src/data-table/index.ts +2 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
|
|
2
|
-
> @orfium/ictinus@5.43.
|
|
2
|
+
> @orfium/ictinus@5.43.3 build /home/runner/work/orfium-ictinus/orfium-ictinus/packages/ictinus
|
|
3
3
|
> pnpm build:main && pnpm build:codemods && pnpm build:vanilla
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
> @orfium/ictinus@5.43.
|
|
6
|
+
> @orfium/ictinus@5.43.3 build:main /home/runner/work/orfium-ictinus/orfium-ictinus/packages/ictinus
|
|
7
7
|
> vite build --mode production
|
|
8
8
|
|
|
9
9
|
production /home/runner/work/orfium-ictinus/orfium-ictinus/packages/ictinus
|
|
10
10
|
[36mvite v7.3.1 [32mbuilding client environment for production...[36m[39m
|
|
11
11
|
production /home/runner/work/orfium-ictinus/orfium-ictinus/packages/ictinus
|
|
12
12
|
transforming...
|
|
13
|
-
[32m✓[39m
|
|
13
|
+
[32m✓[39m 806 modules transformed.
|
|
14
14
|
rendering chunks...
|
|
15
15
|
|
|
16
16
|
[vite:dts] Start generate declaration files...
|
|
@@ -52,10 +52,10 @@ computing gzip size...
|
|
|
52
52
|
[2mdist/[22m[36mcomponents/Table/components/TBody/TBody.style.js [39m[1m[2m 0.29 kB[22m[1m[22m[2m │ gzip: 0.21 kB[22m
|
|
53
53
|
[2mdist/[22m[36mhooks/useEscape.js [39m[1m[2m 0.29 kB[22m[1m[22m[2m │ gzip: 0.19 kB[22m
|
|
54
54
|
[2mdist/[22m[36mhooks/useCombinedRefs.js [39m[1m[2m 0.29 kB[22m[1m[22m[2m │ gzip: 0.20 kB[22m
|
|
55
|
-
[2mdist/[22m[36mcomponents/Controls/ControlLabel/ControlHelpText.js [39m[1m[2m 0.30 kB[22m[1m[22m[2m │ gzip: 0.24 kB[22m
|
|
56
55
|
[2mdist/[22m[36mcomponents/Icon/assets/usersAndStatus/statusIndicator.svg.js [39m[1m[2m 0.30 kB[22m[1m[22m[2m │ gzip: 0.23 kB[22m
|
|
57
|
-
[2mdist/[22m[36mcomponents/
|
|
56
|
+
[2mdist/[22m[36mcomponents/Controls/ControlLabel/ControlHelpText.js [39m[1m[2m 0.30 kB[22m[1m[22m[2m │ gzip: 0.24 kB[22m
|
|
58
57
|
[2mdist/[22m[36mcomponents/Chart/Wrapper.js [39m[1m[2m 0.30 kB[22m[1m[22m[2m │ gzip: 0.21 kB[22m
|
|
58
|
+
[2mdist/[22m[36mcomponents/Breadcrumb/Breadcrumb.style.js [39m[1m[2m 0.30 kB[22m[1m[22m[2m │ gzip: 0.23 kB[22m
|
|
59
59
|
[2mdist/[22m[36mcomponents/TableV4/components/RenderRowOrNestedRow/components/ContentCell/ContentCell.style.js [39m[1m[2m 0.30 kB[22m[1m[22m[2m │ gzip: 0.24 kB[22m
|
|
60
60
|
[2mdist/[22m[36mcomponents/Tabs/components/TabsContainer/TabsContainer.style.js [39m[1m[2m 0.31 kB[22m[1m[22m[2m │ gzip: 0.22 kB[22m
|
|
61
61
|
[2mdist/[22m[36mcomponents/TableV4/components/TableCell/utils.js [39m[1m[2m 0.31 kB[22m[1m[22m[2m │ gzip: 0.23 kB[22m
|
|
@@ -207,8 +207,8 @@ computing gzip size...
|
|
|
207
207
|
[2mdist/[22m[36mcomponents/Search/StatefulSearch.js [39m[1m[2m 0.89 kB[22m[1m[22m[2m │ gzip: 0.48 kB[22m
|
|
208
208
|
[2mdist/[22m[36mcomponents/Slider/components/SliderMark/SliderMark.js [39m[1m[2m 0.89 kB[22m[1m[22m[2m │ gzip: 0.50 kB[22m
|
|
209
209
|
[2mdist/[22m[36mcomponents/Icon/assets/musicBusiness/recording.svg.js [39m[1m[2m 0.90 kB[22m[1m[22m[2m │ gzip: 0.53 kB[22m
|
|
210
|
-
[2mdist/[22m[36mcomponents/TopAppBar/TopAppBar.style.js [39m[1m[2m 0.91 kB[22m[1m[22m[2m │ gzip: 0.46 kB[22m
|
|
211
210
|
[2mdist/[22m[36mcomponents/Icon/assets/generic/search filled.svg.js [39m[1m[2m 0.91 kB[22m[1m[22m[2m │ gzip: 0.48 kB[22m
|
|
211
|
+
[2mdist/[22m[36mcomponents/TopAppBar/TopAppBar.style.js [39m[1m[2m 0.91 kB[22m[1m[22m[2m │ gzip: 0.46 kB[22m
|
|
212
212
|
[2mdist/[22m[36micons/LicenseIcon.js [39m[1m[2m 0.91 kB[22m[1m[22m[2m │ gzip: 0.54 kB[22m
|
|
213
213
|
[2mdist/[22m[36mcomponents/Icon/assets/audioControls/rewind.svg.js [39m[1m[2m 0.91 kB[22m[1m[22m[2m │ gzip: 0.48 kB[22m
|
|
214
214
|
[2mdist/[22m[36mcomponents/Icon/Icon.style.js [39m[1m[2m 0.91 kB[22m[1m[22m[2m │ gzip: 0.48 kB[22m
|
|
@@ -394,8 +394,8 @@ computing gzip size...
|
|
|
394
394
|
[2mdist/[22m[36mcomponents/Icon/assets/musicBusiness/artist.svg.js [39m[1m[2m 1.54 kB[22m[1m[22m[2m │ gzip: 0.81 kB[22m
|
|
395
395
|
[2mdist/[22m[36mcomponents/Drawer/Drawer.js [39m[1m[2m 1.55 kB[22m[1m[22m[2m │ gzip: 0.70 kB[22m
|
|
396
396
|
[2mdist/[22m[36micons/DigitalIcon.js [39m[1m[2m 1.55 kB[22m[1m[22m[2m │ gzip: 0.78 kB[22m
|
|
397
|
-
[2mdist/[22m[36mcomponents/Table/components/OptimizedTableRow.js [39m[1m[2m 1.55 kB[22m[1m[22m[2m │ gzip: 0.73 kB[22m
|
|
398
397
|
[2mdist/[22m[36mcomponents/Controls/Switch/Switch.style.js [39m[1m[2m 1.55 kB[22m[1m[22m[2m │ gzip: 0.72 kB[22m
|
|
398
|
+
[2mdist/[22m[36mcomponents/Table/components/OptimizedTableRow.js [39m[1m[2m 1.55 kB[22m[1m[22m[2m │ gzip: 0.73 kB[22m
|
|
399
399
|
[2mdist/[22m[36micons/ConflictIcon.js [39m[1m[2m 1.55 kB[22m[1m[22m[2m │ gzip: 0.86 kB[22m
|
|
400
400
|
[2mdist/[22m[36micons/AssetIcon.js [39m[1m[2m 1.58 kB[22m[1m[22m[2m │ gzip: 0.85 kB[22m
|
|
401
401
|
[2mdist/[22m[36micons/LockIcon.js [39m[1m[2m 1.59 kB[22m[1m[22m[2m │ gzip: 0.81 kB[22m
|
|
@@ -605,11 +605,11 @@ computing gzip size...
|
|
|
605
605
|
[2mdist/[22m[36micon/Icon.js [39m[1m[2m 11.30 kB[22m[1m[22m[2m │ gzip: 2.63 kB[22m
|
|
606
606
|
[2mdist/[22m[36mindex.js [39m[1m[2m 13.17 kB[22m[1m[22m[2m │ gzip: 3.18 kB[22m
|
|
607
607
|
[2mdist/[22m[36msprinkles/properties.css.js [39m[1m[2m115.20 kB[22m[1m[22m[2m │ gzip: 14.54 kB[22m
|
|
608
|
-
[vite:dts] Declaration files built in
|
|
608
|
+
[vite:dts] Declaration files built in 10065ms.
|
|
609
609
|
|
|
610
|
-
[32m✓ built in 14.
|
|
610
|
+
[32m✓ built in 14.38s[39m
|
|
611
611
|
|
|
612
|
-
> @orfium/ictinus@5.43.
|
|
612
|
+
> @orfium/ictinus@5.43.3 build:codemods /home/runner/work/orfium-ictinus/orfium-ictinus/packages/ictinus
|
|
613
613
|
> vite build --config vite.codemods.config.ts
|
|
614
614
|
|
|
615
615
|
[36mvite v7.3.1 [32mbuilding client environment for production...[36m[39m
|
|
@@ -642,11 +642,11 @@ computing gzip size...
|
|
|
642
642
|
[2mdist/codemods/[22m[36mdrawerCodemod.cjs [39m[1m[2m1.07 kB[22m[1m[22m[2m │ gzip: 0.42 kB[22m
|
|
643
643
|
[2mdist/codemods/[22m[36munchangedIconsCodemod.cjs [39m[1m[2m1.12 kB[22m[1m[22m[2m │ gzip: 0.56 kB[22m
|
|
644
644
|
[2mdist/codemods/[22m[36mglobalsCodemod.cjs [39m[1m[2m6.99 kB[22m[1m[22m[2m │ gzip: 1.11 kB[22m
|
|
645
|
-
[vite:dts] Declaration files built in
|
|
645
|
+
[vite:dts] Declaration files built in 778ms.
|
|
646
646
|
|
|
647
|
-
[32m✓ built in
|
|
647
|
+
[32m✓ built in 953ms[39m
|
|
648
648
|
|
|
649
|
-
> @orfium/ictinus@5.43.
|
|
649
|
+
> @orfium/ictinus@5.43.3 build:vanilla /home/runner/work/orfium-ictinus/orfium-ictinus/packages/ictinus
|
|
650
650
|
> rm -rf dist/vanilla && NODE_ENV=production rollup -c
|
|
651
651
|
|
|
652
652
|
[36m
|
|
@@ -657,4 +657,4 @@ computing gzip size...
|
|
|
657
657
|
[1m[33m(!) Unresolved dependencies[39m[22m
|
|
658
658
|
[90mhttps://rollupjs.org/troubleshooting/#warning-treating-module-as-external-dependency[39m
|
|
659
659
|
[1mcsstype[22m (imported by "node_modules/@vanilla-extract/css/dist/vanilla-extract-css.cjs.d.ts")
|
|
660
|
-
[32mcreated [1mdist/vanilla[22m in [1m3.
|
|
660
|
+
[32mcreated [1mdist/vanilla[22m in [1m3.4s[22m[39m
|
package/CHANGELOG.md
CHANGED
package/dist/package.json.d.ts
CHANGED
package/dist/package.json.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { default as React } from 'react';
|
|
2
2
|
import { StyledBoxProps } from './Box.types';
|
|
3
3
|
export type BoxProps = StyledBoxProps & React.HTMLAttributes<HTMLDivElement>;
|
|
4
|
+
/**
|
|
5
|
+
*
|
|
6
|
+
* @deprecated {@link Box} has been deprecated; use vanilla Box instead.
|
|
7
|
+
*
|
|
8
|
+
*/
|
|
4
9
|
declare const Box: React.ForwardRefExoticComponent<StyledBoxProps & React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
5
10
|
export default Box;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { NoUndefined } from '.';
|
|
2
2
|
import { TableProps } from './types';
|
|
3
|
+
/**
|
|
4
|
+
*
|
|
5
|
+
* @deprecated {@link Table} has been deprecated; use DataTable instead.
|
|
6
|
+
*
|
|
7
|
+
*/
|
|
3
8
|
declare const Table: <TData extends NoUndefined<TData>>({ type, rowsConfig, data, columns, rowSize, columnsConfig, sorting, hasStickyHeader, pagination, sx, dataTestPrefixId, }: TableProps<TData>) => import("@emotion/react/jsx-runtime").JSX.Element;
|
|
4
9
|
declare const _default: typeof Table;
|
|
5
10
|
export default _default;
|
|
@@ -24,5 +24,10 @@ export type TypographyProps = {
|
|
|
24
24
|
id?: string;
|
|
25
25
|
};
|
|
26
26
|
export declare const detectComponentBasedOnType: (variant: TypographyVariant) => TypographyComponent;
|
|
27
|
+
/**
|
|
28
|
+
*
|
|
29
|
+
* @deprecated {@link Typography} has been deprecated; use vanilla Text instead.
|
|
30
|
+
*
|
|
31
|
+
*/
|
|
27
32
|
declare const Typography: React.ForwardRefExoticComponent<TypographyProps & React.RefAttributes<HTMLHeadingElement>>;
|
|
28
33
|
export default Typography;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { BoxProps } from '../vanilla/Box';
|
|
2
|
+
export type DataTableCounterProps = BoxProps<'div', {
|
|
3
|
+
count?: number;
|
|
4
|
+
singular?: string;
|
|
5
|
+
plural?: string;
|
|
6
|
+
}>;
|
|
7
|
+
export declare function DataTableCounter({ count: countProp, singular, plural, ...props }: DataTableCounterProps): import("@emotion/react/jsx-runtime").JSX.Element;
|
package/dist/vanilla/index.d.ts
CHANGED
|
@@ -1706,6 +1706,9 @@ declare const DataTableBody: react.ForwardRefExoticComponent<{
|
|
|
1706
1706
|
className?: string;
|
|
1707
1707
|
}>, "size"> & Omit<Omit<react.DetailedHTMLProps<react.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref">, "color" | "className"> & react.RefAttributes<HTMLDivElement>>;
|
|
1708
1708
|
|
|
1709
|
+
type DataTableBulkActionsProps = BoxProps<'div'>;
|
|
1710
|
+
declare function DataTableBulkActions({ children, ...props }: DataTableBulkActionsProps): _emotion_react_jsx_runtime.JSX.Element;
|
|
1711
|
+
|
|
1709
1712
|
declare const CheckBox: react__default.ForwardRefExoticComponent<any>;
|
|
1710
1713
|
|
|
1711
1714
|
type DataTableCheckboxProps = ComponentPropsWithoutRef<typeof CheckBox>;
|
|
@@ -1714,6 +1717,13 @@ type DataTableCheckboxProps = ComponentPropsWithoutRef<typeof CheckBox>;
|
|
|
1714
1717
|
*/
|
|
1715
1718
|
declare const DataTableCheckbox: react.ForwardRefExoticComponent<any>;
|
|
1716
1719
|
|
|
1720
|
+
type DataTableCounterProps = BoxProps<'div', {
|
|
1721
|
+
count?: number;
|
|
1722
|
+
singular?: string;
|
|
1723
|
+
plural?: string;
|
|
1724
|
+
}>;
|
|
1725
|
+
declare function DataTableCounter({ count: countProp, singular, plural, ...props }: DataTableCounterProps): _emotion_react_jsx_runtime.JSX.Element;
|
|
1726
|
+
|
|
1717
1727
|
declare function DataTableEditColumns(): _emotion_react_jsx_runtime.JSX.Element;
|
|
1718
1728
|
|
|
1719
1729
|
type DataTableHeaderProps = BoxProps;
|
|
@@ -6164,5 +6174,5 @@ declare namespace TooltipTrigger {
|
|
|
6164
6174
|
var displayName: string;
|
|
6165
6175
|
}
|
|
6166
6176
|
|
|
6167
|
-
export { AccountIcon, AlbumIcon, AnalyticsIcon, AppsIcon, ArrowDownIcon, ArrowLeftIcon, ArrowRightIcon, ArrowUpIcon, ArtistIcon, AssetIcon, AudioIcon, AudioOffIcon, BookmarkIcon, BookmarkOffIcon, Box, BroadcastIcon, CalendarIcon, CatalogIcon, ChannelIcon, ChatIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, CinemaIcon, ClaimIcon, CloseIcon, ColumnChooserIcon, CompositionIcon, ConcertIcon, ConflictIcon, ConvertIcon, CopyIcon, CueSheetIcon, DashboardIcon, DataTable, DataTableBody, DataTableCheckbox, DataTableEditColumns, DataTableHeader, DatasetIcon, DeleteIcon, DeliveryIcon, DetailsIcon, Dialog, DialogBody, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, DigitalIcon, DistributionIcon, DownloadIcon, EarningsIcon, EditIcon, EntitiesIcon, ErrorIcon, ExternalLinkIcon, EyeIcon, EyeOffIcon, FavoriteIcon, FavoriteOffIcon, FileIcon, FilterIcon, FlagIcon, FlagOffIcon, ForwardIcon, FreezeIcon, HelpIcon, ICONS, Icon, ImageIcon, ImageOffIcon, IncomeIcon, InformationalIcon, InsightIcon, InvoiceIcon, IssueIcon, KeywordIcon, LanguageIcon, LegalIcon, LicenseIcon, LinkIcon, LocationIcon, LockIcon, LoginIcon, LogoutIcon, MailIcon, ManualIcon, MediaFileIcon, Menu, MenuContent, MenuDescription, MenuHeader, MenuIcon, MenuItem, MenuLabel, MenuSection, MenuSeparator, MenuSubmenu, MenuTrigger, MinusIcon, MoreOptionsIcon, NextIcon, NotificationIcon, OrganizationIcon, PageFirstIcon, PageLastIcon, PairIcon, PauseIcon, PendingIcon, PlayIcon, PlaycountIcon, PlusIcon, PolicyIcon, Popover, PopoverBody, PopoverContent, PopoverDescription, PopoverFooter, PopoverHeader, PopoverTitle, PopoverTrigger, PreviousIcon, PublicPerformanceIcon, PublisherIcon, RadioIcon, RecordLabelIcon, RecordingIcon, RedoIcon, RefreshIcon, ReportIcon, RestoreIcon, ResumeIcon, ReviewIcon, RewindIcon, RoleIcon, SearchFilledIcon, SearchIcon, SettingsIcon, ShareIcon, SortAscendingIcon, SortDescendingIcon, SortIcon, StatusIndicatorIcon, StopIcon, SuccessIcon, Table, TableBody, TableCell, TableFooter, TableHeader, TableHeaderCell, TableRow, TagIcon, TelevisionIcon, Text, ThemeProvider, ThumbsDownIcon, ThumbsUpIcon, Tooltip, TooltipContent, TooltipTrigger, TrendingDownIcon, TrendingUpIcon, TriangleDownIcon, TriangleLeftIcon, TriangleRightIcon, TriangleUpIcon, UndoIcon, UnfreezeIcon, UnlinkIcon, UnlockIcon, UnpairIcon, UnverifiedIcon, UpdateIcon, UploadIcon, UsageIcon, UserIcon, UsersIcon, VerifiedIcon, VideoIcon, VideoOffIcon, WarningIcon, WorkIcon, WriterIcon, YouTubeIcon, extractBoxProps, useTheme };
|
|
6168
|
-
export type { BoxProps, DataTableBodyProps, DataTableCheckboxProps, DataTableHeaderProps, DataTableProps, DialogBodyProps, DialogDescriptionProps, DialogFooterProps, DialogHeaderProps, DialogTitleProps, IconProps, MenuContentProps, MenuHeaderProps, MenuItemProps, MenuSectionProps, MenuTriggerProps, PopoverContentProps, PopoverProps, TableBodyProps, TableCellProps, TableFooterProps, TableHeaderCellProps, TableHeaderProps, TableProps, TableRowProps, TextProps, TooltipContentProps, TooltipProps };
|
|
6177
|
+
export { AccountIcon, AlbumIcon, AnalyticsIcon, AppsIcon, ArrowDownIcon, ArrowLeftIcon, ArrowRightIcon, ArrowUpIcon, ArtistIcon, AssetIcon, AudioIcon, AudioOffIcon, BookmarkIcon, BookmarkOffIcon, Box, BroadcastIcon, CalendarIcon, CatalogIcon, ChannelIcon, ChatIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, CinemaIcon, ClaimIcon, CloseIcon, ColumnChooserIcon, CompositionIcon, ConcertIcon, ConflictIcon, ConvertIcon, CopyIcon, CueSheetIcon, DashboardIcon, DataTable, DataTableBody, DataTableBulkActions, DataTableCheckbox, DataTableCounter, DataTableEditColumns, DataTableHeader, DatasetIcon, DeleteIcon, DeliveryIcon, DetailsIcon, Dialog, DialogBody, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, DigitalIcon, DistributionIcon, DownloadIcon, EarningsIcon, EditIcon, EntitiesIcon, ErrorIcon, ExternalLinkIcon, EyeIcon, EyeOffIcon, FavoriteIcon, FavoriteOffIcon, FileIcon, FilterIcon, FlagIcon, FlagOffIcon, ForwardIcon, FreezeIcon, HelpIcon, ICONS, Icon, ImageIcon, ImageOffIcon, IncomeIcon, InformationalIcon, InsightIcon, InvoiceIcon, IssueIcon, KeywordIcon, LanguageIcon, LegalIcon, LicenseIcon, LinkIcon, LocationIcon, LockIcon, LoginIcon, LogoutIcon, MailIcon, ManualIcon, MediaFileIcon, Menu, MenuContent, MenuDescription, MenuHeader, MenuIcon, MenuItem, MenuLabel, MenuSection, MenuSeparator, MenuSubmenu, MenuTrigger, MinusIcon, MoreOptionsIcon, NextIcon, NotificationIcon, OrganizationIcon, PageFirstIcon, PageLastIcon, PairIcon, PauseIcon, PendingIcon, PlayIcon, PlaycountIcon, PlusIcon, PolicyIcon, Popover, PopoverBody, PopoverContent, PopoverDescription, PopoverFooter, PopoverHeader, PopoverTitle, PopoverTrigger, PreviousIcon, PublicPerformanceIcon, PublisherIcon, RadioIcon, RecordLabelIcon, RecordingIcon, RedoIcon, RefreshIcon, ReportIcon, RestoreIcon, ResumeIcon, ReviewIcon, RewindIcon, RoleIcon, SearchFilledIcon, SearchIcon, SettingsIcon, ShareIcon, SortAscendingIcon, SortDescendingIcon, SortIcon, StatusIndicatorIcon, StopIcon, SuccessIcon, Table, TableBody, TableCell, TableFooter, TableHeader, TableHeaderCell, TableRow, TagIcon, TelevisionIcon, Text, ThemeProvider, ThumbsDownIcon, ThumbsUpIcon, Tooltip, TooltipContent, TooltipTrigger, TrendingDownIcon, TrendingUpIcon, TriangleDownIcon, TriangleLeftIcon, TriangleRightIcon, TriangleUpIcon, UndoIcon, UnfreezeIcon, UnlinkIcon, UnlockIcon, UnpairIcon, UnverifiedIcon, UpdateIcon, UploadIcon, UsageIcon, UserIcon, UsersIcon, VerifiedIcon, VideoIcon, VideoOffIcon, WarningIcon, WorkIcon, WriterIcon, YouTubeIcon, extractBoxProps, useTheme };
|
|
6178
|
+
export type { BoxProps, DataTableBodyProps, DataTableBulkActionsProps, DataTableCheckboxProps, DataTableCounterProps, DataTableHeaderProps, DataTableProps, DialogBodyProps, DialogDescriptionProps, DialogFooterProps, DialogHeaderProps, DialogTitleProps, IconProps, MenuContentProps, MenuHeaderProps, MenuItemProps, MenuSectionProps, MenuTriggerProps, PopoverContentProps, PopoverProps, TableBodyProps, TableCellProps, TableFooterProps, TableHeaderCellProps, TableHeaderProps, TableProps, TableRowProps, TextProps, TooltipContentProps, TooltipProps };
|
package/dist/vanilla/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export { DataTable } from './src/data-table/DataTable.js';
|
|
2
2
|
export { DataTableBody } from './src/data-table/DataTableBody.js';
|
|
3
|
+
export { DataTableBulkActions } from './src/data-table/DataTableBulkActions.js';
|
|
3
4
|
export { DataTableCheckbox } from './src/data-table/DataTableCheckbox.js';
|
|
5
|
+
export { DataTableCounter } from './src/data-table/DataTableCounter.js';
|
|
4
6
|
export { DataTableEditColumns } from './src/data-table/DataTableEditColumns.js';
|
|
5
7
|
export { DataTableHeader } from './src/data-table/DataTableHeader.js';
|
|
6
8
|
export { ICONS, Icon } from './src/icon/Icon.js';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx } from '@emotion/react/jsx-runtime';
|
|
2
|
+
import { Box } from '../../Box/Box.js';
|
|
3
|
+
import '../sprinkles/sprinkles.js';
|
|
4
|
+
import { useDataTableContext } from './DataTableContext.js';
|
|
5
|
+
|
|
6
|
+
function DataTableBulkActions({ children, ...props }) {
|
|
7
|
+
const { table } = useDataTableContext();
|
|
8
|
+
const hasSelection = table.getSelectedRowModel().rows.length > 0;
|
|
9
|
+
if (!hasSelection) return null;
|
|
10
|
+
return /* @__PURE__ */ jsx(Box, { display: "flex", alignItems: "center", gap: "sm", ...props, children });
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export { DataTableBulkActions };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { jsxs, jsx } from '@emotion/react/jsx-runtime';
|
|
2
|
+
import { Box } from '../../Box/Box.js';
|
|
3
|
+
import '../sprinkles/sprinkles.js';
|
|
4
|
+
import { Text } from '../../Text/Text.js';
|
|
5
|
+
import { useDataTableContext } from './DataTableContext.js';
|
|
6
|
+
|
|
7
|
+
function DataTableCounter({
|
|
8
|
+
count: countProp,
|
|
9
|
+
singular = "item",
|
|
10
|
+
plural = "items",
|
|
11
|
+
...props
|
|
12
|
+
}) {
|
|
13
|
+
const { table } = useDataTableContext();
|
|
14
|
+
const selectedCount = table.getSelectedRowModel().rows.length;
|
|
15
|
+
const totalCount = countProp ?? table.getRowCount();
|
|
16
|
+
const hasSelection = selectedCount > 0;
|
|
17
|
+
const count = hasSelection ? selectedCount : totalCount;
|
|
18
|
+
const label = count === 1 ? singular : plural;
|
|
19
|
+
return /* @__PURE__ */ jsxs(Box, { display: "flex", alignItems: "center", gap: "sm", ...props, children: [
|
|
20
|
+
/* @__PURE__ */ jsx(Text, { typography: "label02", color: "active", children: count.toLocaleString() }),
|
|
21
|
+
/* @__PURE__ */ jsx(Text, { typography: "label02", children: hasSelection ? `${label} selected` : label })
|
|
22
|
+
] });
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export { DataTableCounter };
|
|
@@ -49,7 +49,7 @@ function DataTableEditColumns() {
|
|
|
49
49
|
children: allColumns.map((column) => {
|
|
50
50
|
const canHide = column.getCanHide();
|
|
51
51
|
const isSelected = canHide ? selectedColumns.has(column.id) : true;
|
|
52
|
-
const label = column.columnDef.meta?.label;
|
|
52
|
+
const label = column.columnDef.meta?.label ?? (typeof column.columnDef.header === "string" ? column.columnDef.header : void 0);
|
|
53
53
|
if (!label) {
|
|
54
54
|
return null;
|
|
55
55
|
}
|
|
@@ -36,7 +36,7 @@ const DataTableHeaderCell = forwardRef(
|
|
|
36
36
|
ref,
|
|
37
37
|
"data-test": true,
|
|
38
38
|
...props,
|
|
39
|
-
children: typeof children
|
|
39
|
+
children: typeof children === "string" ? /* @__PURE__ */ jsxs(
|
|
40
40
|
Box,
|
|
41
41
|
{
|
|
42
42
|
display: "flex",
|
|
@@ -84,7 +84,7 @@ const DataTableHeaderCell = forwardRef(
|
|
|
84
84
|
/* @__PURE__ */ jsx(TooltipTrigger, { children: /* @__PURE__ */ jsx(Box, { display: "flex", alignItems: "center", justifyContent: "center", size: "3", children: /* @__PURE__ */ jsx(Icon, { name: "informational", size: "xs", color: "secondary" }) }) }),
|
|
85
85
|
/* @__PURE__ */ jsx(TooltipContent, { maxW: "22", children: header.column.columnDef.meta.tooltip })
|
|
86
86
|
] }),
|
|
87
|
-
/* @__PURE__ */ jsxs(
|
|
87
|
+
header.column.getCanSort() && /* @__PURE__ */ jsxs(
|
|
88
88
|
ActionsContent,
|
|
89
89
|
{
|
|
90
90
|
display: "grid",
|
|
@@ -117,19 +117,21 @@ const DataTableHeaderCell = forwardRef(
|
|
|
117
117
|
}
|
|
118
118
|
)
|
|
119
119
|
] }),
|
|
120
|
-
/* @__PURE__ */ jsx(ActionsContent, { visible: sortDir ? "always" : "if-needed", children: /* @__PURE__ */ jsxs(Menu, { children: [
|
|
120
|
+
(header.column.getCanSort() || header.column.getCanPin()) && /* @__PURE__ */ jsx(ActionsContent, { visible: sortDir ? "always" : "if-needed", children: /* @__PURE__ */ jsxs(Menu, { children: [
|
|
121
121
|
/* @__PURE__ */ jsx(MenuTrigger, { children: /* @__PURE__ */ jsx(IconButton, { type: "tertiary", size: "compact", iconName: "moreOptions" }) }),
|
|
122
122
|
/* @__PURE__ */ jsxs(MenuContent, { style: { minWidth: "220px" }, children: [
|
|
123
|
-
|
|
124
|
-
/* @__PURE__ */ jsx(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
/* @__PURE__ */ jsx(
|
|
129
|
-
|
|
130
|
-
|
|
123
|
+
header.column.getCanSort() && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
124
|
+
/* @__PURE__ */ jsx(MenuItem, { onAction: () => header.column.toggleSorting(true), children: /* @__PURE__ */ jsxs(Box, { display: "flex", alignItems: "center", gap: "sm", children: [
|
|
125
|
+
/* @__PURE__ */ jsx(Icon, { name: "sortDescending" }),
|
|
126
|
+
/* @__PURE__ */ jsx(Text, { typography: "body03", children: "Sort descending (z-a)" })
|
|
127
|
+
] }) }),
|
|
128
|
+
/* @__PURE__ */ jsx(MenuItem, { onAction: () => header.column.toggleSorting(false), children: /* @__PURE__ */ jsxs(Box, { display: "flex", alignItems: "center", gap: "sm", children: [
|
|
129
|
+
/* @__PURE__ */ jsx(Icon, { name: "sortAscending" }),
|
|
130
|
+
/* @__PURE__ */ jsx(Text, { typography: "body03", children: "Sort ascending (a-z)" })
|
|
131
|
+
] }) })
|
|
132
|
+
] }),
|
|
131
133
|
header.column.getCanPin() && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
132
|
-
/* @__PURE__ */ jsx(MenuSeparator, {}),
|
|
134
|
+
header.column.getCanSort() && /* @__PURE__ */ jsx(MenuSeparator, {}),
|
|
133
135
|
/* @__PURE__ */ jsx(
|
|
134
136
|
MenuItem,
|
|
135
137
|
{
|
|
@@ -177,7 +179,7 @@ const DataTableHeaderCell = forwardRef(
|
|
|
177
179
|
] }) })
|
|
178
180
|
]
|
|
179
181
|
}
|
|
180
|
-
)
|
|
182
|
+
) : children
|
|
181
183
|
}
|
|
182
184
|
) });
|
|
183
185
|
}
|
package/eslint.config.mjs
CHANGED
|
@@ -111,7 +111,7 @@ export default defineConfig([
|
|
|
111
111
|
],
|
|
112
112
|
|
|
113
113
|
'react/prop-types': 'off',
|
|
114
|
-
'react/button-has-type': '
|
|
114
|
+
'react/button-has-type': 'off',
|
|
115
115
|
'@typescript-eslint/no-explicit-any': 'off',
|
|
116
116
|
'react/no-array-index-key': 'warn',
|
|
117
117
|
'react/no-render-return-value': 0,
|
package/package.json
CHANGED
|
@@ -10,6 +10,11 @@ import { cssResolver, omitedCSSprops, pickCSSProperties, pickNonCSSProps } from
|
|
|
10
10
|
|
|
11
11
|
export type BoxProps = StyledBoxProps & React.HTMLAttributes<HTMLDivElement>;
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
*
|
|
15
|
+
* @deprecated {@link Box} has been deprecated; use vanilla Box instead.
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
13
18
|
const Box = forwardRef<HTMLDivElement, BoxProps>(({ children, ...rest }, ref) => {
|
|
14
19
|
const theme = useTheme();
|
|
15
20
|
const cssPropsOnly = pickCSSProperties(rest);
|
|
@@ -13,6 +13,11 @@ import useTable from './hooks/useTable';
|
|
|
13
13
|
import { tableContainer, tableStyles } from './Table.style';
|
|
14
14
|
import type { TableProps } from './types';
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
*
|
|
18
|
+
* @deprecated {@link Table} has been deprecated; use DataTable instead.
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
16
21
|
const Table = <TData extends NoUndefined<TData>>({
|
|
17
22
|
type = 'read-only',
|
|
18
23
|
rowsConfig,
|
|
@@ -59,6 +59,11 @@ export const detectComponentBasedOnType = (variant: TypographyVariant): Typograp
|
|
|
59
59
|
return 'p';
|
|
60
60
|
};
|
|
61
61
|
|
|
62
|
+
/**
|
|
63
|
+
*
|
|
64
|
+
* @deprecated {@link Typography} has been deprecated; use vanilla Text instead.
|
|
65
|
+
*
|
|
66
|
+
*/
|
|
62
67
|
// display name breaks storybook props
|
|
63
68
|
// https://github.com/storybookjs/storybook/issues/13304
|
|
64
69
|
// eslint-disable-next-line react/display-name
|
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
import {
|
|
2
|
+
type ColumnDef,
|
|
3
|
+
createColumnHelper,
|
|
4
|
+
getCoreRowModel,
|
|
5
|
+
getSortedRowModel,
|
|
6
|
+
type RowSelectionState,
|
|
7
|
+
useReactTable,
|
|
8
|
+
type VisibilityState,
|
|
9
|
+
} from '@tanstack/react-table';
|
|
10
|
+
import userEvent from '@testing-library/user-event';
|
|
11
|
+
import { type ReactNode, useState } from 'react';
|
|
12
|
+
import { render, screen } from '../test';
|
|
13
|
+
import { DataTable } from './DataTable';
|
|
14
|
+
import { DataTableBody } from './DataTableBody';
|
|
15
|
+
import { DataTableBulkActions } from './DataTableBulkActions';
|
|
16
|
+
import { DataTableCounter } from './DataTableCounter';
|
|
17
|
+
import { DataTableEditColumns } from './DataTableEditColumns';
|
|
18
|
+
import { DataTableHeader } from './DataTableHeader';
|
|
19
|
+
|
|
20
|
+
type Person = {
|
|
21
|
+
firstName: string;
|
|
22
|
+
lastName: string;
|
|
23
|
+
age: number;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const testData: Person[] = [
|
|
27
|
+
{ firstName: 'Alice', lastName: 'Smith', age: 25 },
|
|
28
|
+
{ firstName: 'Bob', lastName: 'Jones', age: 30 },
|
|
29
|
+
{ firstName: 'Charlie', lastName: 'Brown', age: 35 },
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
const columnHelper = createColumnHelper<Person>();
|
|
33
|
+
|
|
34
|
+
const simpleColumns: ColumnDef<Person, any>[] = [
|
|
35
|
+
columnHelper.accessor('firstName', {
|
|
36
|
+
header: 'First Name',
|
|
37
|
+
meta: { label: 'First Name' },
|
|
38
|
+
enableHiding: false,
|
|
39
|
+
}),
|
|
40
|
+
columnHelper.accessor('lastName', {
|
|
41
|
+
header: 'Last Name',
|
|
42
|
+
meta: { label: 'Last Name' },
|
|
43
|
+
}),
|
|
44
|
+
columnHelper.accessor('age', {
|
|
45
|
+
header: 'Age',
|
|
46
|
+
meta: { label: 'Age' },
|
|
47
|
+
}),
|
|
48
|
+
];
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* A wrapper component that creates a `useReactTable` instance and renders
|
|
52
|
+
* DataTable with the provided children. Props allow controlling initial state.
|
|
53
|
+
*/
|
|
54
|
+
function DataTableFixture({
|
|
55
|
+
children,
|
|
56
|
+
data = testData,
|
|
57
|
+
columns = simpleColumns,
|
|
58
|
+
enableRowSelection = true,
|
|
59
|
+
enableSorting = true,
|
|
60
|
+
initialRowSelection = {},
|
|
61
|
+
initialVisibility = {},
|
|
62
|
+
}: {
|
|
63
|
+
children: ReactNode;
|
|
64
|
+
data?: Person[];
|
|
65
|
+
columns?: ColumnDef<Person, any>[];
|
|
66
|
+
enableRowSelection?: boolean;
|
|
67
|
+
enableSorting?: boolean;
|
|
68
|
+
initialRowSelection?: RowSelectionState;
|
|
69
|
+
initialVisibility?: VisibilityState;
|
|
70
|
+
}) {
|
|
71
|
+
const [rowSelection, setRowSelection] = useState<RowSelectionState>(initialRowSelection);
|
|
72
|
+
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>(initialVisibility);
|
|
73
|
+
|
|
74
|
+
const table = useReactTable({
|
|
75
|
+
columns,
|
|
76
|
+
data,
|
|
77
|
+
getCoreRowModel: getCoreRowModel(),
|
|
78
|
+
getSortedRowModel: getSortedRowModel(),
|
|
79
|
+
enableRowSelection,
|
|
80
|
+
enableSorting,
|
|
81
|
+
state: {
|
|
82
|
+
rowSelection,
|
|
83
|
+
columnVisibility,
|
|
84
|
+
},
|
|
85
|
+
onRowSelectionChange: setRowSelection,
|
|
86
|
+
onColumnVisibilityChange: setColumnVisibility,
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return <DataTable table={table}>{children}</DataTable>;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
describe('DataTable', () => {
|
|
93
|
+
it('renders children inside a flex container', () => {
|
|
94
|
+
render(
|
|
95
|
+
<DataTableFixture>
|
|
96
|
+
<div data-testid="child">Hello</div>
|
|
97
|
+
</DataTableFixture>
|
|
98
|
+
);
|
|
99
|
+
|
|
100
|
+
expect(screen.getByTestId('child')).toBeInTheDocument();
|
|
101
|
+
expect(screen.getByTestId('child').textContent).toBe('Hello');
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
it('renders with the DataTable displayName', () => {
|
|
105
|
+
expect(DataTable.displayName).toBe('DataTable');
|
|
106
|
+
});
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
describe('DataTableCounter', () => {
|
|
110
|
+
it('shows total row count with default plural label', () => {
|
|
111
|
+
render(
|
|
112
|
+
<DataTableFixture>
|
|
113
|
+
<DataTableCounter />
|
|
114
|
+
</DataTableFixture>
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
expect(screen.getByText('3')).toBeInTheDocument();
|
|
118
|
+
expect(screen.getByText('items')).toBeInTheDocument();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
it('shows singular label when there is exactly 1 row', () => {
|
|
122
|
+
render(
|
|
123
|
+
<DataTableFixture data={[testData[0]]}>
|
|
124
|
+
<DataTableCounter />
|
|
125
|
+
</DataTableFixture>
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
expect(screen.getByText('1')).toBeInTheDocument();
|
|
129
|
+
expect(screen.getByText('item')).toBeInTheDocument();
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it('uses custom singular/plural labels', () => {
|
|
133
|
+
render(
|
|
134
|
+
<DataTableFixture>
|
|
135
|
+
<DataTableCounter singular="Friend" plural="Friends" />
|
|
136
|
+
</DataTableFixture>
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
expect(screen.getByText('3')).toBeInTheDocument();
|
|
140
|
+
expect(screen.getByText('Friends')).toBeInTheDocument();
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it('shows selected count with "selected" suffix when rows are selected', () => {
|
|
144
|
+
render(
|
|
145
|
+
<DataTableFixture initialRowSelection={{ '0': true, '1': true }}>
|
|
146
|
+
<DataTableCounter singular="Friend" plural="Friends" />
|
|
147
|
+
</DataTableFixture>
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
expect(screen.getByText('2')).toBeInTheDocument();
|
|
151
|
+
expect(screen.getByText('Friends selected')).toBeInTheDocument();
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
it('uses singular label when exactly 1 row is selected', () => {
|
|
155
|
+
render(
|
|
156
|
+
<DataTableFixture initialRowSelection={{ '0': true }}>
|
|
157
|
+
<DataTableCounter singular="Friend" plural="Friends" />
|
|
158
|
+
</DataTableFixture>
|
|
159
|
+
);
|
|
160
|
+
|
|
161
|
+
expect(screen.getByText('1')).toBeInTheDocument();
|
|
162
|
+
expect(screen.getByText('Friend selected')).toBeInTheDocument();
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('accepts a custom count prop that overrides the table row count', () => {
|
|
166
|
+
render(
|
|
167
|
+
<DataTableFixture>
|
|
168
|
+
<DataTableCounter count={999} />
|
|
169
|
+
</DataTableFixture>
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
expect(screen.getByText('999')).toBeInTheDocument();
|
|
173
|
+
expect(screen.getByText('items')).toBeInTheDocument();
|
|
174
|
+
});
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
describe('DataTableBulkActions', () => {
|
|
178
|
+
it('does not render children when no rows are selected', () => {
|
|
179
|
+
render(
|
|
180
|
+
<DataTableFixture>
|
|
181
|
+
<DataTableBulkActions>
|
|
182
|
+
<button>Bulk Action</button>
|
|
183
|
+
</DataTableBulkActions>
|
|
184
|
+
</DataTableFixture>
|
|
185
|
+
);
|
|
186
|
+
|
|
187
|
+
expect(screen.queryByText('Bulk Action')).not.toBeInTheDocument();
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('renders children when rows are selected', () => {
|
|
191
|
+
render(
|
|
192
|
+
<DataTableFixture initialRowSelection={{ '0': true }}>
|
|
193
|
+
<DataTableBulkActions>
|
|
194
|
+
<button>Bulk Action</button>
|
|
195
|
+
</DataTableBulkActions>
|
|
196
|
+
</DataTableFixture>
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
expect(screen.getByText('Bulk Action')).toBeInTheDocument();
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
describe('DataTableBody', () => {
|
|
204
|
+
it('renders column headers', () => {
|
|
205
|
+
render(
|
|
206
|
+
<DataTableFixture>
|
|
207
|
+
<DataTableBody />
|
|
208
|
+
</DataTableFixture>
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
expect(screen.getByText('First Name')).toBeInTheDocument();
|
|
212
|
+
expect(screen.getByText('Last Name')).toBeInTheDocument();
|
|
213
|
+
expect(screen.getByText('Age')).toBeInTheDocument();
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
it('renders all data rows', () => {
|
|
217
|
+
render(
|
|
218
|
+
<DataTableFixture>
|
|
219
|
+
<DataTableBody />
|
|
220
|
+
</DataTableFixture>
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
expect(screen.getByText('Alice')).toBeInTheDocument();
|
|
224
|
+
expect(screen.getByText('Bob')).toBeInTheDocument();
|
|
225
|
+
expect(screen.getByText('Charlie')).toBeInTheDocument();
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it('renders cell values for each row', () => {
|
|
229
|
+
render(
|
|
230
|
+
<DataTableFixture>
|
|
231
|
+
<DataTableBody />
|
|
232
|
+
</DataTableFixture>
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
expect(screen.getByText('Smith')).toBeInTheDocument();
|
|
236
|
+
expect(screen.getByText('Jones')).toBeInTheDocument();
|
|
237
|
+
expect(screen.getByText('Brown')).toBeInTheDocument();
|
|
238
|
+
|
|
239
|
+
expect(screen.getByText('25')).toBeInTheDocument();
|
|
240
|
+
expect(screen.getByText('30')).toBeInTheDocument();
|
|
241
|
+
expect(screen.getByText('35')).toBeInTheDocument();
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
it('respects initial column visibility', () => {
|
|
245
|
+
render(
|
|
246
|
+
<DataTableFixture initialVisibility={{ age: false }}>
|
|
247
|
+
<DataTableBody />
|
|
248
|
+
</DataTableFixture>
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
// Age column should be hidden
|
|
252
|
+
expect(screen.queryByText('Age')).not.toBeInTheDocument();
|
|
253
|
+
expect(screen.queryByText('25')).not.toBeInTheDocument();
|
|
254
|
+
|
|
255
|
+
// Other columns should still be visible
|
|
256
|
+
expect(screen.getByText('First Name')).toBeInTheDocument();
|
|
257
|
+
expect(screen.getByText('Alice')).toBeInTheDocument();
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
it('renders an empty body when data is empty', () => {
|
|
261
|
+
render(
|
|
262
|
+
<DataTableFixture data={[]}>
|
|
263
|
+
<DataTableBody />
|
|
264
|
+
</DataTableFixture>
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
// Headers should still render
|
|
268
|
+
expect(screen.getByText('First Name')).toBeInTheDocument();
|
|
269
|
+
|
|
270
|
+
// No data rows
|
|
271
|
+
expect(screen.queryByText('Alice')).not.toBeInTheDocument();
|
|
272
|
+
});
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
describe('DataTableEditColumns', () => {
|
|
276
|
+
it('renders the "Edit columns" button', () => {
|
|
277
|
+
render(
|
|
278
|
+
<DataTableFixture>
|
|
279
|
+
<DataTableEditColumns />
|
|
280
|
+
</DataTableFixture>
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
expect(screen.getByText('Edit columns')).toBeInTheDocument();
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
it('shows hidable columns in the menu when clicked', async () => {
|
|
287
|
+
const user = userEvent.setup();
|
|
288
|
+
|
|
289
|
+
render(
|
|
290
|
+
<DataTableFixture>
|
|
291
|
+
<DataTableEditColumns />
|
|
292
|
+
</DataTableFixture>
|
|
293
|
+
);
|
|
294
|
+
|
|
295
|
+
await user.click(screen.getByText('Edit columns'));
|
|
296
|
+
|
|
297
|
+
expect(screen.getByText('First Name')).toBeInTheDocument();
|
|
298
|
+
expect(screen.getByText('Last Name')).toBeInTheDocument();
|
|
299
|
+
expect(screen.getByText('Age')).toBeInTheDocument();
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
it('toggles column visibility when a hidable column is clicked', async () => {
|
|
303
|
+
const user = userEvent.setup();
|
|
304
|
+
|
|
305
|
+
render(
|
|
306
|
+
<DataTableFixture>
|
|
307
|
+
<DataTableEditColumns />
|
|
308
|
+
<DataTableBody />
|
|
309
|
+
</DataTableFixture>
|
|
310
|
+
);
|
|
311
|
+
|
|
312
|
+
expect(screen.getByText('35')).toBeInTheDocument();
|
|
313
|
+
|
|
314
|
+
await user.click(screen.getByText('Edit columns'));
|
|
315
|
+
|
|
316
|
+
const ageOption = screen.getAllByText('Age');
|
|
317
|
+
// There may be multiple "Age" texts (header cell + menu item)
|
|
318
|
+
// The menu item is the last one
|
|
319
|
+
await user.click(ageOption[ageOption.length - 1]);
|
|
320
|
+
|
|
321
|
+
expect(screen.queryByText('35')).not.toBeInTheDocument();
|
|
322
|
+
});
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
describe('DataTableHeader', () => {
|
|
326
|
+
it('renders children', () => {
|
|
327
|
+
render(
|
|
328
|
+
<DataTableFixture>
|
|
329
|
+
<DataTableHeader>
|
|
330
|
+
<span data-testid="header-child">Header Content</span>
|
|
331
|
+
</DataTableHeader>
|
|
332
|
+
</DataTableFixture>
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
expect(screen.getByTestId('header-child')).toBeInTheDocument();
|
|
336
|
+
expect(screen.getByText('Header Content')).toBeInTheDocument();
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
describe('DataTable integration', () => {
|
|
341
|
+
it('counter updates when row selection changes via bulk actions', () => {
|
|
342
|
+
render(
|
|
343
|
+
<DataTableFixture initialRowSelection={{ '0': true }}>
|
|
344
|
+
<DataTableHeader>
|
|
345
|
+
<DataTableCounter singular="Friend" plural="Friends" />
|
|
346
|
+
<DataTableBulkActions>
|
|
347
|
+
<button>Delete</button>
|
|
348
|
+
</DataTableBulkActions>
|
|
349
|
+
</DataTableHeader>
|
|
350
|
+
<DataTableBody />
|
|
351
|
+
</DataTableFixture>
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
expect(screen.getByText('1')).toBeInTheDocument();
|
|
355
|
+
expect(screen.getByText('Friend selected')).toBeInTheDocument();
|
|
356
|
+
expect(screen.getByText('Delete')).toBeInTheDocument();
|
|
357
|
+
});
|
|
358
|
+
|
|
359
|
+
it('bulk actions disappear and counter shows total when no rows are selected', () => {
|
|
360
|
+
render(
|
|
361
|
+
<DataTableFixture>
|
|
362
|
+
<DataTableHeader>
|
|
363
|
+
<DataTableCounter singular="Friend" plural="Friends" />
|
|
364
|
+
<DataTableBulkActions>
|
|
365
|
+
<button>Delete</button>
|
|
366
|
+
</DataTableBulkActions>
|
|
367
|
+
</DataTableHeader>
|
|
368
|
+
<DataTableBody />
|
|
369
|
+
</DataTableFixture>
|
|
370
|
+
);
|
|
371
|
+
|
|
372
|
+
expect(screen.getByText('3')).toBeInTheDocument();
|
|
373
|
+
expect(screen.getByText('Friends')).toBeInTheDocument();
|
|
374
|
+
|
|
375
|
+
expect(screen.queryByText('Delete')).not.toBeInTheDocument();
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
it('renders the full composition (header + body) with data', () => {
|
|
379
|
+
render(
|
|
380
|
+
<DataTableFixture>
|
|
381
|
+
<DataTableHeader>
|
|
382
|
+
<DataTableCounter />
|
|
383
|
+
<DataTableEditColumns />
|
|
384
|
+
</DataTableHeader>
|
|
385
|
+
<DataTableBody />
|
|
386
|
+
</DataTableFixture>
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
// Header
|
|
390
|
+
expect(screen.getByText('3')).toBeInTheDocument();
|
|
391
|
+
expect(screen.getByText('items')).toBeInTheDocument();
|
|
392
|
+
expect(screen.getByText('Edit columns')).toBeInTheDocument();
|
|
393
|
+
|
|
394
|
+
// Body
|
|
395
|
+
expect(screen.getByText('Alice')).toBeInTheDocument();
|
|
396
|
+
expect(screen.getByText('Bob')).toBeInTheDocument();
|
|
397
|
+
expect(screen.getByText('Charlie')).toBeInTheDocument();
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
it('hides column via EditColumns and verifies body updates', async () => {
|
|
401
|
+
const user = userEvent.setup();
|
|
402
|
+
|
|
403
|
+
render(
|
|
404
|
+
<DataTableFixture>
|
|
405
|
+
<DataTableHeader>
|
|
406
|
+
<DataTableEditColumns />
|
|
407
|
+
</DataTableHeader>
|
|
408
|
+
<DataTableBody />
|
|
409
|
+
</DataTableFixture>
|
|
410
|
+
);
|
|
411
|
+
|
|
412
|
+
expect(screen.getByText('Smith')).toBeInTheDocument();
|
|
413
|
+
|
|
414
|
+
await user.click(screen.getByText('Edit columns'));
|
|
415
|
+
|
|
416
|
+
const lastNameOptions = screen.getAllByText('Last Name');
|
|
417
|
+
await user.click(lastNameOptions[lastNameOptions.length - 1]);
|
|
418
|
+
|
|
419
|
+
expect(screen.queryByText('Smith')).not.toBeInTheDocument();
|
|
420
|
+
expect(screen.queryByText('Jones')).not.toBeInTheDocument();
|
|
421
|
+
expect(screen.queryByText('Brown')).not.toBeInTheDocument();
|
|
422
|
+
|
|
423
|
+
expect(screen.getByText('Alice')).toBeInTheDocument();
|
|
424
|
+
});
|
|
425
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Box, type BoxProps } from '../vanilla/Box';
|
|
2
|
+
import { useDataTableContext } from './DataTableContext';
|
|
3
|
+
|
|
4
|
+
export type DataTableBulkActionsProps = BoxProps<'div'>;
|
|
5
|
+
|
|
6
|
+
export function DataTableBulkActions({ children, ...props }: DataTableBulkActionsProps) {
|
|
7
|
+
const { table } = useDataTableContext();
|
|
8
|
+
const hasSelection = table.getSelectedRowModel().rows.length > 0;
|
|
9
|
+
|
|
10
|
+
if (!hasSelection) return null;
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<Box display="flex" alignItems="center" gap="sm" {...props}>
|
|
14
|
+
{children}
|
|
15
|
+
</Box>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { Box, type BoxProps } from '../vanilla/Box';
|
|
2
|
+
import { Text } from '../vanilla/Text';
|
|
3
|
+
import { useDataTableContext } from './DataTableContext';
|
|
4
|
+
|
|
5
|
+
export type DataTableCounterProps = BoxProps<
|
|
6
|
+
'div',
|
|
7
|
+
{
|
|
8
|
+
count?: number;
|
|
9
|
+
singular?: string;
|
|
10
|
+
plural?: string;
|
|
11
|
+
}
|
|
12
|
+
>;
|
|
13
|
+
|
|
14
|
+
export function DataTableCounter({
|
|
15
|
+
count: countProp,
|
|
16
|
+
singular = 'item',
|
|
17
|
+
plural = 'items',
|
|
18
|
+
...props
|
|
19
|
+
}: DataTableCounterProps) {
|
|
20
|
+
const { table } = useDataTableContext();
|
|
21
|
+
|
|
22
|
+
const selectedCount = table.getSelectedRowModel().rows.length;
|
|
23
|
+
const totalCount = countProp ?? table.getRowCount();
|
|
24
|
+
const hasSelection = selectedCount > 0;
|
|
25
|
+
|
|
26
|
+
const count = hasSelection ? selectedCount : totalCount;
|
|
27
|
+
const label = count === 1 ? singular : plural;
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<Box display="flex" alignItems="center" gap="sm" {...props}>
|
|
31
|
+
<Text typography="label02" color="active">
|
|
32
|
+
{count.toLocaleString()}
|
|
33
|
+
</Text>
|
|
34
|
+
<Text typography="label02">{hasSelection ? `${label} selected` : label}</Text>
|
|
35
|
+
</Box>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -55,7 +55,9 @@ export function DataTableEditColumns() {
|
|
|
55
55
|
{allColumns.map((column) => {
|
|
56
56
|
const canHide = column.getCanHide();
|
|
57
57
|
const isSelected = canHide ? selectedColumns.has(column.id) : true;
|
|
58
|
-
const label =
|
|
58
|
+
const label =
|
|
59
|
+
(column.columnDef.meta as { label?: string })?.label ??
|
|
60
|
+
(typeof column.columnDef.header === 'string' ? column.columnDef.header : undefined);
|
|
59
61
|
|
|
60
62
|
if (!label) {
|
|
61
63
|
return null;
|
|
@@ -40,9 +40,7 @@ export const DataTableHeaderCell = forwardRef<HTMLTableCellElement, DataTableHea
|
|
|
40
40
|
data-test
|
|
41
41
|
{...props}
|
|
42
42
|
>
|
|
43
|
-
{typeof children
|
|
44
|
-
children
|
|
45
|
-
) : (
|
|
43
|
+
{typeof children === 'string' ? (
|
|
46
44
|
<Box
|
|
47
45
|
display="flex"
|
|
48
46
|
alignItems="center"
|
|
@@ -87,7 +85,6 @@ export const DataTableHeaderCell = forwardRef<HTMLTableCellElement, DataTableHea
|
|
|
87
85
|
</TooltipTrigger>
|
|
88
86
|
<TooltipContent>{children}</TooltipContent>
|
|
89
87
|
</Tooltip>
|
|
90
|
-
|
|
91
88
|
{header.column.columnDef.meta?.tooltip && (
|
|
92
89
|
<Tooltip>
|
|
93
90
|
<TooltipTrigger>
|
|
@@ -101,95 +98,104 @@ export const DataTableHeaderCell = forwardRef<HTMLTableCellElement, DataTableHea
|
|
|
101
98
|
</TooltipContent>
|
|
102
99
|
</Tooltip>
|
|
103
100
|
)}
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
101
|
+
{header.column.getCanSort() && (
|
|
102
|
+
<ActionsContent
|
|
103
|
+
display="grid"
|
|
104
|
+
placeItems="center"
|
|
105
|
+
position="relative"
|
|
106
|
+
visible={sortDir ? 'always' : 'if-needed'}
|
|
107
|
+
flexDirection={flexDir}
|
|
108
|
+
>
|
|
109
|
+
<IconButton
|
|
110
|
+
onClick={() =>
|
|
111
|
+
header.column.toggleSorting(undefined, header.column.getCanMultiSort())
|
|
112
|
+
}
|
|
113
|
+
type="tertiary"
|
|
114
|
+
size="compact"
|
|
115
|
+
iconName={getSortIcon(sortDir)}
|
|
116
|
+
/>
|
|
117
|
+
{header.column.getCanMultiSort() && header.column.getSortIndex() > -1 && (
|
|
118
|
+
<Text
|
|
119
|
+
typography="label04"
|
|
120
|
+
color="primary"
|
|
121
|
+
position="absolute"
|
|
122
|
+
pointerEvents="none"
|
|
123
|
+
style={{ top: 0, right: 0 }}
|
|
124
|
+
>
|
|
125
|
+
{header.column.getSortIndex() + 1}
|
|
126
|
+
</Text>
|
|
127
|
+
)}
|
|
128
|
+
</ActionsContent>
|
|
129
|
+
)}
|
|
132
130
|
</Box>
|
|
133
131
|
|
|
134
|
-
|
|
135
|
-
<
|
|
136
|
-
<
|
|
137
|
-
<
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
<
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
132
|
+
{(header.column.getCanSort() || header.column.getCanPin()) && (
|
|
133
|
+
<ActionsContent visible={sortDir ? 'always' : 'if-needed'}>
|
|
134
|
+
<Menu>
|
|
135
|
+
<MenuTrigger>
|
|
136
|
+
<IconButton type="tertiary" size="compact" iconName="moreOptions" />
|
|
137
|
+
</MenuTrigger>
|
|
138
|
+
<MenuContent style={{ minWidth: '220px' }}>
|
|
139
|
+
{header.column.getCanSort() && (
|
|
140
|
+
<>
|
|
141
|
+
<MenuItem onAction={() => header.column.toggleSorting(true)}>
|
|
142
|
+
<Box display="flex" alignItems="center" gap="sm">
|
|
143
|
+
<Icon name="sortDescending" />
|
|
144
|
+
<Text typography="body03">Sort descending (z-a)</Text>
|
|
145
|
+
</Box>
|
|
146
|
+
</MenuItem>
|
|
147
|
+
<MenuItem onAction={() => header.column.toggleSorting(false)}>
|
|
148
|
+
<Box display="flex" alignItems="center" gap="sm">
|
|
149
|
+
<Icon name="sortAscending" />
|
|
150
|
+
<Text typography="body03">Sort ascending (a-z)</Text>
|
|
151
|
+
</Box>
|
|
152
|
+
</MenuItem>
|
|
153
|
+
</>
|
|
154
|
+
)}
|
|
155
|
+
{header.column.getCanPin() && (
|
|
156
|
+
<>
|
|
157
|
+
{header.column.getCanSort() && <MenuSeparator />}
|
|
158
|
+
<MenuItem
|
|
159
|
+
onAction={() => {
|
|
160
|
+
const isPinnedLeft = header.column.getIsPinned() === 'left';
|
|
161
|
+
header.column.pin(isPinnedLeft ? false : 'left');
|
|
162
|
+
}}
|
|
163
|
+
>
|
|
164
|
+
<Box display="flex" alignItems="center" gap="sm" w="full">
|
|
165
|
+
<Icon name="freeze" />
|
|
166
|
+
<Text typography="body03">Freeze column (left)</Text>
|
|
167
|
+
<Box flex="1" />
|
|
168
|
+
<Switch
|
|
169
|
+
isSelected={header.column.getIsPinned() === 'left'}
|
|
170
|
+
isReadOnly
|
|
171
|
+
/>
|
|
172
|
+
</Box>
|
|
173
|
+
</MenuItem>
|
|
174
|
+
<MenuItem
|
|
175
|
+
onAction={() => {
|
|
176
|
+
const isPinnedRight = header.column.getIsPinned() === 'right';
|
|
177
|
+
header.column.pin(isPinnedRight ? false : 'right');
|
|
178
|
+
}}
|
|
179
|
+
>
|
|
180
|
+
<Box display="flex" alignItems="center" gap="sm" w="full">
|
|
181
|
+
<Icon name="freeze" />
|
|
182
|
+
<Text typography="body03">Freeze column (right)</Text>
|
|
183
|
+
<Box flex="1" />
|
|
184
|
+
<Switch
|
|
185
|
+
isSelected={header.column.getIsPinned() === 'right'}
|
|
186
|
+
isReadOnly
|
|
187
|
+
/>
|
|
188
|
+
</Box>
|
|
189
|
+
</MenuItem>
|
|
190
|
+
</>
|
|
191
|
+
)}
|
|
192
|
+
</MenuContent>
|
|
193
|
+
</Menu>
|
|
194
|
+
</ActionsContent>
|
|
195
|
+
)}
|
|
192
196
|
</Box>
|
|
197
|
+
) : (
|
|
198
|
+
children
|
|
193
199
|
)}
|
|
194
200
|
</TableHeaderCell>
|
|
195
201
|
</ActionsRoot>
|
package/src/data-table/index.ts
CHANGED