@shipfox/react-ui 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.storybook/preview.tsx +7 -0
- package/.turbo/turbo-build.log +7 -7
- package/.turbo/turbo-check.log +2 -2
- package/.turbo/turbo-type.log +1 -1
- package/CHANGELOG.md +16 -0
- package/dist/components/avatar/avatar.js +1 -1
- package/dist/components/avatar/avatar.js.map +1 -1
- package/dist/components/button-group/button-group.d.ts +17 -0
- package/dist/components/button-group/button-group.d.ts.map +1 -0
- package/dist/components/button-group/button-group.js +74 -0
- package/dist/components/button-group/button-group.js.map +1 -0
- package/dist/components/button-group/button-group.stories.js +644 -0
- package/dist/components/button-group/button-group.stories.js.map +1 -0
- package/dist/components/button-group/index.d.ts +2 -0
- package/dist/components/button-group/index.d.ts.map +1 -0
- package/dist/components/button-group/index.js +3 -0
- package/dist/components/button-group/index.js.map +1 -0
- package/dist/components/code-block/code-block-footer.d.ts.map +1 -1
- package/dist/components/code-block/code-block-footer.js +13 -5
- package/dist/components/code-block/code-block-footer.js.map +1 -1
- package/dist/components/command/command.d.ts +28 -0
- package/dist/components/command/command.d.ts.map +1 -0
- package/dist/components/command/command.js +190 -0
- package/dist/components/command/command.js.map +1 -0
- package/dist/components/command/command.stories.js +228 -0
- package/dist/components/command/command.stories.js.map +1 -0
- package/dist/components/command/index.d.ts +2 -0
- package/dist/components/command/index.d.ts.map +1 -0
- package/dist/components/command/index.js +3 -0
- package/dist/components/command/index.js.map +1 -0
- package/dist/components/confetti/confetti.d.ts +21 -0
- package/dist/components/confetti/confetti.d.ts.map +1 -0
- package/dist/components/confetti/confetti.js +101 -0
- package/dist/components/confetti/confetti.js.map +1 -0
- package/dist/components/confetti/confetti.stories.js +41 -0
- package/dist/components/confetti/confetti.stories.js.map +1 -0
- package/dist/components/confetti/index.d.ts +2 -0
- package/dist/components/confetti/index.d.ts.map +1 -0
- package/dist/components/confetti/index.js +3 -0
- package/dist/components/confetti/index.js.map +1 -0
- package/dist/components/dashboard/components/analytics-content.d.ts +2 -0
- package/dist/components/dashboard/components/analytics-content.d.ts.map +1 -0
- package/dist/components/dashboard/components/analytics-content.js +180 -0
- package/dist/components/dashboard/components/analytics-content.js.map +1 -0
- package/dist/components/dashboard/components/animated-logo.d.ts +4 -0
- package/dist/components/dashboard/components/animated-logo.d.ts.map +1 -0
- package/dist/components/dashboard/components/animated-logo.js +23 -0
- package/dist/components/dashboard/components/animated-logo.js.map +1 -0
- package/dist/components/dashboard/components/complete-setup-button.d.ts +4 -0
- package/dist/components/dashboard/components/complete-setup-button.d.ts.map +1 -0
- package/dist/components/dashboard/components/complete-setup-button.js +28 -0
- package/dist/components/dashboard/components/complete-setup-button.js.map +1 -0
- package/dist/components/dashboard/components/jobs-content.d.ts +2 -0
- package/dist/components/dashboard/components/jobs-content.d.ts.map +1 -0
- package/dist/components/dashboard/components/jobs-content.js +69 -0
- package/dist/components/dashboard/components/jobs-content.js.map +1 -0
- package/dist/components/dashboard/components/mobile-menu.d.ts +2 -0
- package/dist/components/dashboard/components/mobile-menu.d.ts.map +1 -0
- package/dist/components/dashboard/components/mobile-menu.js +65 -0
- package/dist/components/dashboard/components/mobile-menu.js.map +1 -0
- package/dist/components/dashboard/components/organization-selector.d.ts +2 -0
- package/dist/components/dashboard/components/organization-selector.d.ts.map +1 -0
- package/dist/components/dashboard/components/organization-selector.js +92 -0
- package/dist/components/dashboard/components/organization-selector.js.map +1 -0
- package/dist/components/dashboard/components/top-menu.d.ts +5 -0
- package/dist/components/dashboard/components/top-menu.d.ts.map +1 -0
- package/dist/components/dashboard/components/top-menu.js +31 -0
- package/dist/components/dashboard/components/top-menu.js.map +1 -0
- package/dist/components/dashboard/components/topbar-button.d.ts +7 -0
- package/dist/components/dashboard/components/topbar-button.d.ts.map +1 -0
- package/dist/components/dashboard/components/topbar-button.js +18 -0
- package/dist/components/dashboard/components/topbar-button.js.map +1 -0
- package/dist/components/dashboard/components/topbar.d.ts +4 -0
- package/dist/components/dashboard/components/topbar.d.ts.map +1 -0
- package/dist/components/dashboard/components/topbar.js +62 -0
- package/dist/components/dashboard/components/topbar.js.map +1 -0
- package/dist/components/dashboard/components/user-profile.d.ts +2 -0
- package/dist/components/dashboard/components/user-profile.d.ts.map +1 -0
- package/dist/components/dashboard/components/user-profile.js +146 -0
- package/dist/components/dashboard/components/user-profile.js.map +1 -0
- package/dist/components/dashboard/dashboard.d.ts +2 -0
- package/dist/components/dashboard/dashboard.d.ts.map +1 -0
- package/dist/components/dashboard/dashboard.js +70 -0
- package/dist/components/dashboard/dashboard.js.map +1 -0
- package/dist/components/dashboard/dashboard.stories.js +23 -0
- package/dist/components/dashboard/dashboard.stories.js.map +1 -0
- package/dist/components/dashboard/index.d.ts +2 -0
- package/dist/components/dashboard/index.d.ts.map +1 -0
- package/dist/components/dashboard/index.js +3 -0
- package/dist/components/dashboard/index.js.map +1 -0
- package/dist/components/form/form.stories.js +6 -1
- package/dist/components/form/form.stories.js.map +1 -1
- package/dist/components/icon/icon.d.ts +3 -2
- package/dist/components/icon/icon.d.ts.map +1 -1
- package/dist/components/icon/icon.js +7 -2
- package/dist/components/icon/icon.js.map +1 -1
- package/dist/components/index.d.ts +9 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +9 -0
- package/dist/components/index.js.map +1 -1
- package/dist/components/kbd/index.d.ts +2 -0
- package/dist/components/kbd/index.d.ts.map +1 -0
- package/dist/components/kbd/index.js +3 -0
- package/dist/components/kbd/index.js.map +1 -0
- package/dist/components/kbd/kbd.d.ts +7 -0
- package/dist/components/kbd/kbd.d.ts.map +1 -0
- package/dist/components/kbd/kbd.js +18 -0
- package/dist/components/kbd/kbd.js.map +1 -0
- package/dist/components/kbd/kbd.stories.js +119 -0
- package/dist/components/kbd/kbd.stories.js.map +1 -0
- package/dist/components/modal/modal.stories.js +227 -168
- package/dist/components/modal/modal.stories.js.map +1 -1
- package/dist/components/search/index.d.ts +7 -0
- package/dist/components/search/index.d.ts.map +1 -0
- package/dist/components/search/index.js +8 -0
- package/dist/components/search/index.js.map +1 -0
- package/dist/components/search/search-context.d.ts +11 -0
- package/dist/components/search/search-context.d.ts.map +1 -0
- package/dist/components/search/search-context.js +56 -0
- package/dist/components/search/search-context.js.map +1 -0
- package/dist/components/search/search-inline.d.ts +9 -0
- package/dist/components/search/search-inline.d.ts.map +1 -0
- package/dist/components/search/search-inline.js +85 -0
- package/dist/components/search/search-inline.js.map +1 -0
- package/dist/components/search/search-modal.d.ts +25 -0
- package/dist/components/search/search-modal.d.ts.map +1 -0
- package/dist/components/search/search-modal.js +162 -0
- package/dist/components/search/search-modal.js.map +1 -0
- package/dist/components/search/search-trigger.d.ts +9 -0
- package/dist/components/search/search-trigger.d.ts.map +1 -0
- package/dist/components/search/search-trigger.js +37 -0
- package/dist/components/search/search-trigger.js.map +1 -0
- package/dist/components/search/search-variants.d.ts +14 -0
- package/dist/components/search/search-variants.d.ts.map +1 -0
- package/dist/components/search/search-variants.js +90 -0
- package/dist/components/search/search-variants.js.map +1 -0
- package/dist/components/search/search.d.ts +11 -0
- package/dist/components/search/search.d.ts.map +1 -0
- package/dist/components/search/search.js +35 -0
- package/dist/components/search/search.js.map +1 -0
- package/dist/components/search/search.stories.js +630 -0
- package/dist/components/search/search.stories.js.map +1 -0
- package/dist/components/select/index.d.ts +2 -0
- package/dist/components/select/index.d.ts.map +1 -0
- package/dist/components/select/index.js +3 -0
- package/dist/components/select/index.js.map +1 -0
- package/dist/components/select/select.d.ts +25 -0
- package/dist/components/select/select.d.ts.map +1 -0
- package/dist/components/select/select.js +153 -0
- package/dist/components/select/select.js.map +1 -0
- package/dist/components/select/select.stories.js +393 -0
- package/dist/components/select/select.stories.js.map +1 -0
- package/dist/components/shiny-text/index.d.ts +2 -0
- package/dist/components/shiny-text/index.d.ts.map +1 -0
- package/dist/components/shiny-text/index.js +3 -0
- package/dist/components/shiny-text/index.js.map +1 -0
- package/dist/components/shiny-text/shiny-text.d.ts +10 -0
- package/dist/components/shiny-text/shiny-text.d.ts.map +1 -0
- package/dist/components/shiny-text/shiny-text.js +17 -0
- package/dist/components/shiny-text/shiny-text.js.map +1 -0
- package/dist/components/skeleton/index.d.ts +2 -0
- package/dist/components/skeleton/index.d.ts.map +1 -0
- package/dist/components/skeleton/index.js +3 -0
- package/dist/components/skeleton/index.js.map +1 -0
- package/dist/components/skeleton/skeleton.d.ts +5 -0
- package/dist/components/skeleton/skeleton.d.ts.map +1 -0
- package/dist/components/skeleton/skeleton.js +11 -0
- package/dist/components/skeleton/skeleton.js.map +1 -0
- package/dist/components/skeleton/skeleton.stories.js +345 -0
- package/dist/components/skeleton/skeleton.stories.js.map +1 -0
- package/dist/components/table/data-table.d.ts +70 -0
- package/dist/components/table/data-table.d.ts.map +1 -0
- package/dist/components/table/data-table.js +159 -0
- package/dist/components/table/data-table.js.map +1 -0
- package/dist/components/table/index.d.ts +6 -0
- package/dist/components/table/index.d.ts.map +1 -0
- package/dist/components/table/index.js +6 -0
- package/dist/components/table/index.js.map +1 -0
- package/dist/components/table/table-column-header.d.ts +79 -0
- package/dist/components/table/table-column-header.d.ts.map +1 -0
- package/dist/components/table/table-column-header.js +99 -0
- package/dist/components/table/table-column-header.js.map +1 -0
- package/dist/components/table/table-pagination.d.ts +53 -0
- package/dist/components/table/table-pagination.d.ts.map +1 -0
- package/dist/components/table/table-pagination.js +139 -0
- package/dist/components/table/table-pagination.js.map +1 -0
- package/dist/components/table/table.d.ts +11 -0
- package/dist/components/table/table.d.ts.map +1 -0
- package/dist/components/table/table.js +64 -0
- package/dist/components/table/table.js.map +1 -0
- package/dist/components/table/table.stories.columns.d.ts +24 -0
- package/dist/components/table/table.stories.columns.d.ts.map +1 -0
- package/dist/components/table/table.stories.columns.js +310 -0
- package/dist/components/table/table.stories.columns.js.map +1 -0
- package/dist/components/table/table.stories.components.d.ts +14 -0
- package/dist/components/table/table.stories.components.d.ts.map +1 -0
- package/dist/components/table/table.stories.components.js +107 -0
- package/dist/components/table/table.stories.components.js.map +1 -0
- package/dist/components/table/table.stories.data.d.ts +54 -0
- package/dist/components/table/table.stories.data.d.ts.map +1 -0
- package/dist/components/table/table.stories.data.js +122 -0
- package/dist/components/table/table.stories.data.js.map +1 -0
- package/dist/components/table/table.stories.js +302 -0
- package/dist/components/table/table.stories.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/index.css +79 -0
- package/package.json +6 -2
- package/src/components/avatar/avatar.tsx +1 -1
- package/src/components/button-group/button-group.stories.tsx +361 -0
- package/src/components/button-group/button-group.tsx +111 -0
- package/src/components/button-group/index.ts +1 -0
- package/src/components/code-block/code-block-footer.tsx +19 -2
- package/src/components/command/command.stories.tsx +133 -0
- package/src/components/command/command.tsx +265 -0
- package/src/components/command/index.ts +1 -0
- package/src/components/confetti/confetti.stories.tsx +38 -0
- package/src/components/confetti/confetti.tsx +140 -0
- package/src/components/confetti/index.ts +1 -0
- package/src/components/dashboard/components/analytics-content.tsx +102 -0
- package/src/components/dashboard/components/animated-logo.tsx +25 -0
- package/src/components/dashboard/components/complete-setup-button.tsx +30 -0
- package/src/components/dashboard/components/jobs-content.tsx +51 -0
- package/src/components/dashboard/components/mobile-menu.tsx +50 -0
- package/src/components/dashboard/components/organization-selector.tsx +51 -0
- package/src/components/dashboard/components/top-menu.tsx +26 -0
- package/src/components/dashboard/components/topbar-button.tsx +27 -0
- package/src/components/dashboard/components/topbar.tsx +40 -0
- package/src/components/dashboard/components/user-profile.tsx +90 -0
- package/src/components/dashboard/dashboard.stories.tsx +25 -0
- package/src/components/dashboard/dashboard.tsx +61 -0
- package/src/components/dashboard/index.ts +1 -0
- package/src/components/form/form.stories.tsx +5 -0
- package/src/components/icon/icon.tsx +7 -3
- package/src/components/index.ts +9 -0
- package/src/components/kbd/index.ts +1 -0
- package/src/components/kbd/kbd.stories.tsx +64 -0
- package/src/components/kbd/kbd.tsx +32 -0
- package/src/components/modal/modal.stories.tsx +58 -4
- package/src/components/search/index.ts +28 -0
- package/src/components/search/search-context.tsx +78 -0
- package/src/components/search/search-inline.tsx +107 -0
- package/src/components/search/search-modal.tsx +198 -0
- package/src/components/search/search-trigger.tsx +47 -0
- package/src/components/search/search-variants.ts +88 -0
- package/src/components/search/search.stories.tsx +392 -0
- package/src/components/search/search.tsx +47 -0
- package/src/components/select/index.ts +1 -0
- package/src/components/select/select.stories.tsx +207 -0
- package/src/components/select/select.tsx +220 -0
- package/src/components/shiny-text/index.ts +1 -0
- package/src/components/shiny-text/shiny-text.tsx +21 -0
- package/src/components/skeleton/index.ts +1 -0
- package/src/components/skeleton/skeleton.stories.tsx +178 -0
- package/src/components/skeleton/skeleton.tsx +14 -0
- package/src/components/table/data-table.tsx +254 -0
- package/src/components/table/index.ts +5 -0
- package/src/components/table/table-column-header.tsx +141 -0
- package/src/components/table/table-pagination.tsx +161 -0
- package/src/components/table/table.stories.columns.tsx +198 -0
- package/src/components/table/table.stories.components.tsx +104 -0
- package/src/components/table/table.stories.data.ts +117 -0
- package/src/components/table/table.stories.tsx +256 -0
- package/src/components/table/table.tsx +95 -0
- package/src/index.ts +1 -0
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
import * as SelectPrimitive from '@radix-ui/react-select';
|
|
2
|
+
import {cva, type VariantProps} from 'class-variance-authority';
|
|
3
|
+
import type {ComponentProps} from 'react';
|
|
4
|
+
import {cn} from 'utils/cn';
|
|
5
|
+
import {Icon, type IconName} from '../icon';
|
|
6
|
+
|
|
7
|
+
function Select({...props}: ComponentProps<typeof SelectPrimitive.Root>) {
|
|
8
|
+
return <SelectPrimitive.Root data-slot="select" {...props} />;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function SelectGroup({...props}: ComponentProps<typeof SelectPrimitive.Group>) {
|
|
12
|
+
return <SelectPrimitive.Group data-slot="select-group" {...props} />;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function SelectValue({...props}: ComponentProps<typeof SelectPrimitive.Value>) {
|
|
16
|
+
return <SelectPrimitive.Value data-slot="select-value" {...props} />;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const selectTriggerVariants = cva(
|
|
20
|
+
[
|
|
21
|
+
'flex items-center justify-between gap-8',
|
|
22
|
+
'w-full rounded-6 px-8 text-sm leading-20',
|
|
23
|
+
'bg-background-field-base text-foreground-neutral-subtle',
|
|
24
|
+
'shadow-button-neutral transition-[color,box-shadow] outline-none',
|
|
25
|
+
'hover:bg-background-field-hover',
|
|
26
|
+
'focus-visible:shadow-border-interactive-with-active',
|
|
27
|
+
'disabled:pointer-events-none disabled:cursor-not-allowed disabled:bg-background-neutral-disabled disabled:shadow-none disabled:text-foreground-neutral-disabled',
|
|
28
|
+
'data-[placeholder]:text-foreground-neutral-muted',
|
|
29
|
+
],
|
|
30
|
+
{
|
|
31
|
+
variants: {
|
|
32
|
+
variant: {
|
|
33
|
+
base: 'bg-background-field-base',
|
|
34
|
+
component: 'bg-background-field-component',
|
|
35
|
+
},
|
|
36
|
+
size: {
|
|
37
|
+
small: 'h-28 py-4',
|
|
38
|
+
base: 'h-32 py-6',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
defaultVariants: {
|
|
42
|
+
variant: 'base',
|
|
43
|
+
size: 'base',
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
type SelectTriggerProps = ComponentProps<typeof SelectPrimitive.Trigger> &
|
|
49
|
+
VariantProps<typeof selectTriggerVariants>;
|
|
50
|
+
|
|
51
|
+
function SelectTrigger({className, variant, size, children, ...props}: SelectTriggerProps) {
|
|
52
|
+
return (
|
|
53
|
+
<SelectPrimitive.Trigger
|
|
54
|
+
data-slot="select-trigger"
|
|
55
|
+
className={cn(selectTriggerVariants({variant, size}), className)}
|
|
56
|
+
{...props}
|
|
57
|
+
>
|
|
58
|
+
{children}
|
|
59
|
+
<SelectPrimitive.Icon asChild>
|
|
60
|
+
<Icon name="expandUpDownLine" className="size-16 text-foreground-neutral-muted shrink-0" />
|
|
61
|
+
</SelectPrimitive.Icon>
|
|
62
|
+
</SelectPrimitive.Trigger>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function SelectScrollUpButton({
|
|
67
|
+
className,
|
|
68
|
+
...props
|
|
69
|
+
}: ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
|
|
70
|
+
return (
|
|
71
|
+
<SelectPrimitive.ScrollUpButton
|
|
72
|
+
data-slot="select-scroll-up-button"
|
|
73
|
+
className={cn('flex cursor-default items-center justify-center py-4', className)}
|
|
74
|
+
{...props}
|
|
75
|
+
>
|
|
76
|
+
<Icon name="arrowUpSLine" className="size-16 text-foreground-neutral-muted" />
|
|
77
|
+
</SelectPrimitive.ScrollUpButton>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function SelectScrollDownButton({
|
|
82
|
+
className,
|
|
83
|
+
...props
|
|
84
|
+
}: ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
|
|
85
|
+
return (
|
|
86
|
+
<SelectPrimitive.ScrollDownButton
|
|
87
|
+
data-slot="select-scroll-down-button"
|
|
88
|
+
className={cn('flex cursor-default items-center justify-center py-4', className)}
|
|
89
|
+
{...props}
|
|
90
|
+
>
|
|
91
|
+
<Icon name="arrowDownSLine" className="size-16 text-foreground-neutral-muted" />
|
|
92
|
+
</SelectPrimitive.ScrollDownButton>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function SelectContent({
|
|
97
|
+
className,
|
|
98
|
+
children,
|
|
99
|
+
position = 'popper',
|
|
100
|
+
sideOffset = 4,
|
|
101
|
+
align = 'center',
|
|
102
|
+
...props
|
|
103
|
+
}: ComponentProps<typeof SelectPrimitive.Content>) {
|
|
104
|
+
return (
|
|
105
|
+
<SelectPrimitive.Portal>
|
|
106
|
+
<SelectPrimitive.Content
|
|
107
|
+
data-slot="select-content"
|
|
108
|
+
className={cn(
|
|
109
|
+
'relative z-50 max-h-300 min-w-180 overflow-hidden rounded-10 p-4',
|
|
110
|
+
'bg-background-neutral-overlay shadow-tooltip',
|
|
111
|
+
'data-[state=open]:animate-in data-[state=closed]:animate-out',
|
|
112
|
+
'data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0',
|
|
113
|
+
'data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95',
|
|
114
|
+
'data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2',
|
|
115
|
+
'data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',
|
|
116
|
+
position === 'popper' &&
|
|
117
|
+
'data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1',
|
|
118
|
+
className,
|
|
119
|
+
)}
|
|
120
|
+
position={position}
|
|
121
|
+
sideOffset={sideOffset}
|
|
122
|
+
align={align}
|
|
123
|
+
{...props}
|
|
124
|
+
>
|
|
125
|
+
<SelectScrollUpButton />
|
|
126
|
+
<SelectPrimitive.Viewport
|
|
127
|
+
data-slot="select-viewport"
|
|
128
|
+
className={cn(
|
|
129
|
+
'p-0',
|
|
130
|
+
position === 'popper' &&
|
|
131
|
+
'h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]',
|
|
132
|
+
)}
|
|
133
|
+
>
|
|
134
|
+
{children}
|
|
135
|
+
</SelectPrimitive.Viewport>
|
|
136
|
+
<SelectScrollDownButton />
|
|
137
|
+
</SelectPrimitive.Content>
|
|
138
|
+
</SelectPrimitive.Portal>
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function SelectLabel({className, ...props}: ComponentProps<typeof SelectPrimitive.Label>) {
|
|
143
|
+
return (
|
|
144
|
+
<SelectPrimitive.Label
|
|
145
|
+
data-slot="select-label"
|
|
146
|
+
className={cn(
|
|
147
|
+
'px-8 py-4 text-xs leading-20 text-foreground-neutral-subtle select-none',
|
|
148
|
+
className,
|
|
149
|
+
)}
|
|
150
|
+
{...props}
|
|
151
|
+
/>
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
type SelectItemProps = ComponentProps<typeof SelectPrimitive.Item> & {
|
|
156
|
+
icon?: IconName;
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
function SelectItem({className, children, icon, ...props}: SelectItemProps) {
|
|
160
|
+
return (
|
|
161
|
+
<SelectPrimitive.Item
|
|
162
|
+
data-slot="select-item"
|
|
163
|
+
className={cn(
|
|
164
|
+
'relative flex cursor-pointer select-none items-center gap-8 rounded-6 py-6 pl-32 pr-8',
|
|
165
|
+
'text-sm leading-20 text-foreground-neutral-subtle outline-none transition-colors',
|
|
166
|
+
'focus:bg-background-components-hover',
|
|
167
|
+
'data-disabled:pointer-events-none data-disabled:text-foreground-neutral-disabled',
|
|
168
|
+
'data-[state=checked]:text-foreground-neutral-base',
|
|
169
|
+
icon && 'pl-56',
|
|
170
|
+
className,
|
|
171
|
+
)}
|
|
172
|
+
{...props}
|
|
173
|
+
>
|
|
174
|
+
<span className="absolute left-8 flex size-16 items-center justify-center">
|
|
175
|
+
<SelectPrimitive.ItemIndicator>
|
|
176
|
+
<Icon name="check" className="size-14 text-foreground-neutral-base" />
|
|
177
|
+
</SelectPrimitive.ItemIndicator>
|
|
178
|
+
</span>
|
|
179
|
+
{icon && (
|
|
180
|
+
<Icon
|
|
181
|
+
name={icon}
|
|
182
|
+
className="size-16 shrink-0 text-foreground-neutral-subtle absolute left-32"
|
|
183
|
+
/>
|
|
184
|
+
)}
|
|
185
|
+
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
|
186
|
+
</SelectPrimitive.Item>
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function SelectSeparator({className, ...props}: ComponentProps<typeof SelectPrimitive.Separator>) {
|
|
191
|
+
return (
|
|
192
|
+
<SelectPrimitive.Separator
|
|
193
|
+
data-slot="select-separator"
|
|
194
|
+
className={cn(
|
|
195
|
+
'relative -mx-4 my-4 h-px',
|
|
196
|
+
'bg-border-neutral-menu-top',
|
|
197
|
+
'after:absolute after:inset-x-0 after:top-px after:h-px',
|
|
198
|
+
'after:bg-border-neutral-menu-bottom',
|
|
199
|
+
className,
|
|
200
|
+
)}
|
|
201
|
+
{...props}
|
|
202
|
+
/>
|
|
203
|
+
);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
export {
|
|
207
|
+
Select,
|
|
208
|
+
SelectGroup,
|
|
209
|
+
SelectValue,
|
|
210
|
+
SelectTrigger,
|
|
211
|
+
SelectContent,
|
|
212
|
+
SelectLabel,
|
|
213
|
+
SelectItem,
|
|
214
|
+
SelectSeparator,
|
|
215
|
+
SelectScrollUpButton,
|
|
216
|
+
SelectScrollDownButton,
|
|
217
|
+
selectTriggerVariants,
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
export type {SelectTriggerProps, SelectItemProps};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './shiny-text';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {cn} from 'utils/cn';
|
|
2
|
+
|
|
3
|
+
type ShinyTextProps = {
|
|
4
|
+
text: string;
|
|
5
|
+
disabled?: boolean;
|
|
6
|
+
speed?: number;
|
|
7
|
+
className?: string;
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
function ShinyText({text, disabled = false, speed = 5, className = ''}: ShinyTextProps) {
|
|
11
|
+
const animationDuration = `${speed}s`;
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<span className={cn('shiny-text', {disabled: disabled}, className)} style={{animationDuration}}>
|
|
15
|
+
{text}
|
|
16
|
+
</span>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export {ShinyText};
|
|
21
|
+
export type {ShinyTextProps};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './skeleton';
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import type {Meta, StoryObj} from '@storybook/react';
|
|
2
|
+
import {Code, Header} from 'components/typography';
|
|
3
|
+
import {Skeleton} from './skeleton';
|
|
4
|
+
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'Components/Skeleton',
|
|
7
|
+
component: Skeleton,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
} satisfies Meta<typeof Skeleton>;
|
|
10
|
+
|
|
11
|
+
export default meta;
|
|
12
|
+
|
|
13
|
+
type Story = StoryObj<typeof meta>;
|
|
14
|
+
|
|
15
|
+
export const Default: Story = {
|
|
16
|
+
render: () => <Skeleton className="w-200 h-20" />,
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export const Card: Story = {
|
|
20
|
+
render: () => (
|
|
21
|
+
<div className="flex flex-col gap-12 p-16 rounded-10 border border-border-neutral-base bg-background-field-base max-w-400">
|
|
22
|
+
<Skeleton className="h-200 w-full rounded-6" />
|
|
23
|
+
<div className="space-y-8">
|
|
24
|
+
<Skeleton className="h-20 w-3/4" />
|
|
25
|
+
<Skeleton className="h-16 w-full" />
|
|
26
|
+
<Skeleton className="h-16 w-5/6" />
|
|
27
|
+
</div>
|
|
28
|
+
<div className="flex gap-8 pt-8">
|
|
29
|
+
<Skeleton className="h-32 w-100 rounded-6" />
|
|
30
|
+
<Skeleton className="h-32 w-100 rounded-6" />
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
),
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const List: Story = {
|
|
37
|
+
render: () => (
|
|
38
|
+
<div className="flex flex-col gap-8 max-w-500">
|
|
39
|
+
{Array.from({length: 5}, (_, i) => i).map((id) => (
|
|
40
|
+
<div
|
|
41
|
+
key={`list-${id}`}
|
|
42
|
+
className="flex items-center gap-12 p-12 rounded-6 border border-border-neutral-base bg-background-field-base"
|
|
43
|
+
>
|
|
44
|
+
<Skeleton className="h-48 w-48 rounded-full shrink-0" />
|
|
45
|
+
<div className="flex-1 space-y-8">
|
|
46
|
+
<Skeleton className="h-16 w-3/4" />
|
|
47
|
+
<Skeleton className="h-14 w-1/2" />
|
|
48
|
+
</div>
|
|
49
|
+
<Skeleton className="h-32 w-80 rounded-6" />
|
|
50
|
+
</div>
|
|
51
|
+
))}
|
|
52
|
+
</div>
|
|
53
|
+
),
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export const Showcase: Story = {
|
|
57
|
+
render: () => (
|
|
58
|
+
<div className="flex flex-col gap-32">
|
|
59
|
+
<div className="flex flex-col gap-16">
|
|
60
|
+
<Header variant="h3">Basic Shapes</Header>
|
|
61
|
+
<div className="flex flex-col gap-12">
|
|
62
|
+
<div className="flex flex-col gap-8">
|
|
63
|
+
<Code variant="label" className="text-foreground-neutral-subtle">
|
|
64
|
+
Rectangle
|
|
65
|
+
</Code>
|
|
66
|
+
<Skeleton className="h-20 w-200" />
|
|
67
|
+
</div>
|
|
68
|
+
|
|
69
|
+
<div className="flex flex-col gap-8">
|
|
70
|
+
<Code variant="label" className="text-foreground-neutral-subtle">
|
|
71
|
+
Circle
|
|
72
|
+
</Code>
|
|
73
|
+
<Skeleton className="h-48 w-48 rounded-full" />
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<div className="flex flex-col gap-8">
|
|
77
|
+
<Code variant="label" className="text-foreground-neutral-subtle">
|
|
78
|
+
Square
|
|
79
|
+
</Code>
|
|
80
|
+
<Skeleton className="h-100 w-100" />
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
<div className="flex flex-col gap-16">
|
|
86
|
+
<Header variant="h3">Card Loading</Header>
|
|
87
|
+
<div className="flex flex-col gap-12 p-16 rounded-10 border border-border-neutral-base bg-background-field-base max-w-400">
|
|
88
|
+
<Skeleton className="h-200 w-full rounded-6" />
|
|
89
|
+
<div className="space-y-8">
|
|
90
|
+
<Skeleton className="h-20 w-3/4" />
|
|
91
|
+
<Skeleton className="h-16 w-full" />
|
|
92
|
+
<Skeleton className="h-16 w-2/3" />
|
|
93
|
+
</div>
|
|
94
|
+
<div className="flex gap-8 pt-8">
|
|
95
|
+
<Skeleton className="h-32 w-100 rounded-6" />
|
|
96
|
+
<Skeleton className="h-32 w-100 rounded-6" />
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
|
|
101
|
+
<div className="flex flex-col gap-16">
|
|
102
|
+
<Header variant="h3">List Loading</Header>
|
|
103
|
+
<div className="flex flex-col gap-8 max-w-500">
|
|
104
|
+
{Array.from({length: 4}, (_, i) => i).map((id) => (
|
|
105
|
+
<div
|
|
106
|
+
key={`list-loading-${id}`}
|
|
107
|
+
className="flex items-center gap-12 p-12 rounded-6 border border-border-neutral-base bg-background-field-base"
|
|
108
|
+
>
|
|
109
|
+
<Skeleton className="h-48 w-48 rounded-full shrink-0" />
|
|
110
|
+
<div className="flex-1 space-y-8">
|
|
111
|
+
<Skeleton className="h-16 w-3/4" />
|
|
112
|
+
<Skeleton className="h-14 w-1/2" />
|
|
113
|
+
</div>
|
|
114
|
+
<Skeleton className="h-32 w-80 rounded-6" />
|
|
115
|
+
</div>
|
|
116
|
+
))}
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
|
|
120
|
+
<div className="flex flex-col gap-16">
|
|
121
|
+
<Header variant="h3">Table Loading</Header>
|
|
122
|
+
<div className="rounded-10 border border-border-neutral-base bg-background-field-base overflow-hidden max-w-700">
|
|
123
|
+
<div className="flex gap-16 p-12 border-b border-border-neutral-base bg-background-neutral-base">
|
|
124
|
+
<Skeleton className="h-16 w-140" />
|
|
125
|
+
<Skeleton className="h-16 w-220" />
|
|
126
|
+
<Skeleton className="h-16 w-120" />
|
|
127
|
+
<Skeleton className="h-16 w-100 ml-auto" />
|
|
128
|
+
</div>
|
|
129
|
+
{Array.from({length: 5}, (_, i) => i).map((id) => (
|
|
130
|
+
<div
|
|
131
|
+
key={`table-row-${id}`}
|
|
132
|
+
className="flex gap-16 p-12 border-b border-border-neutral-base last:border-0"
|
|
133
|
+
>
|
|
134
|
+
<Skeleton className="h-14 w-140" />
|
|
135
|
+
<Skeleton className="h-14 w-220" />
|
|
136
|
+
<Skeleton className="h-14 w-120" />
|
|
137
|
+
<Skeleton className="h-14 w-100 ml-auto" />
|
|
138
|
+
</div>
|
|
139
|
+
))}
|
|
140
|
+
</div>
|
|
141
|
+
</div>
|
|
142
|
+
|
|
143
|
+
<div className="flex flex-col gap-16">
|
|
144
|
+
<Header variant="h3">Form Loading</Header>
|
|
145
|
+
<div className="max-w-400 space-y-16 p-16 rounded-10 border border-border-neutral-base bg-background-field-base">
|
|
146
|
+
<div className="space-y-8">
|
|
147
|
+
<Skeleton className="h-16 w-100" />
|
|
148
|
+
<Skeleton className="h-32 w-full rounded-6" />
|
|
149
|
+
</div>
|
|
150
|
+
<div className="space-y-8">
|
|
151
|
+
<Skeleton className="h-16 w-120" />
|
|
152
|
+
<Skeleton className="h-32 w-full rounded-6" />
|
|
153
|
+
</div>
|
|
154
|
+
<div className="space-y-8">
|
|
155
|
+
<Skeleton className="h-16 w-80" />
|
|
156
|
+
<Skeleton className="h-96 w-full rounded-6" />
|
|
157
|
+
</div>
|
|
158
|
+
<div className="flex gap-8 pt-8">
|
|
159
|
+
<Skeleton className="h-32 w-100 rounded-6" />
|
|
160
|
+
<Skeleton className="h-32 w-100 rounded-6" />
|
|
161
|
+
</div>
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
|
|
165
|
+
<div className="flex flex-col gap-16">
|
|
166
|
+
<Header variant="h3">Avatar Group Loading</Header>
|
|
167
|
+
<div className="flex -space-x-8">
|
|
168
|
+
{Array.from({length: 5}, (_, i) => i).map((id) => (
|
|
169
|
+
<Skeleton
|
|
170
|
+
key={`avatar-${id}`}
|
|
171
|
+
className="h-40 w-40 rounded-full border-2 border-background-field-base"
|
|
172
|
+
/>
|
|
173
|
+
))}
|
|
174
|
+
</div>
|
|
175
|
+
</div>
|
|
176
|
+
</div>
|
|
177
|
+
),
|
|
178
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type {ComponentProps} from 'react';
|
|
2
|
+
import {cn} from 'utils/cn';
|
|
3
|
+
|
|
4
|
+
type SkeletonProps = ComponentProps<'div'>;
|
|
5
|
+
|
|
6
|
+
export function Skeleton({className, ...props}: SkeletonProps) {
|
|
7
|
+
return (
|
|
8
|
+
<div
|
|
9
|
+
data-slot="skeleton"
|
|
10
|
+
className={cn('animate-pulse rounded-6 bg-background-neutral-disabled', className)}
|
|
11
|
+
{...props}
|
|
12
|
+
/>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ColumnDef,
|
|
3
|
+
ColumnFiltersState,
|
|
4
|
+
PaginationState,
|
|
5
|
+
SortingState,
|
|
6
|
+
VisibilityState,
|
|
7
|
+
} from '@tanstack/react-table';
|
|
8
|
+
import {
|
|
9
|
+
flexRender,
|
|
10
|
+
getCoreRowModel,
|
|
11
|
+
getFilteredRowModel,
|
|
12
|
+
getPaginationRowModel,
|
|
13
|
+
getSortedRowModel,
|
|
14
|
+
useReactTable,
|
|
15
|
+
} from '@tanstack/react-table';
|
|
16
|
+
import {Checkbox} from 'components/checkbox';
|
|
17
|
+
import {Icon} from 'components/icon';
|
|
18
|
+
import {Text} from 'components/typography';
|
|
19
|
+
import {type ComponentProps, useEffect, useMemo, useState} from 'react';
|
|
20
|
+
import {cn} from 'utils/cn';
|
|
21
|
+
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from './table';
|
|
22
|
+
import {TablePagination} from './table-pagination';
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Props for the {@link DataTable} component.
|
|
26
|
+
*
|
|
27
|
+
* @typeParam TData - The shape of the row data.
|
|
28
|
+
* @typeParam TValue - The value type used by column definitions.
|
|
29
|
+
*/
|
|
30
|
+
interface DataTableProps<TData, TValue> extends Omit<ComponentProps<'div'>, 'children'> {
|
|
31
|
+
/**
|
|
32
|
+
* Column definitions for the table, as expected by `@tanstack/react-table`.
|
|
33
|
+
*
|
|
34
|
+
* These control how each field in {@link data} is rendered and interacted with.
|
|
35
|
+
*/
|
|
36
|
+
columns: ColumnDef<TData, TValue>[];
|
|
37
|
+
/**
|
|
38
|
+
* Array of data items to render as table rows.
|
|
39
|
+
*/
|
|
40
|
+
data: TData[];
|
|
41
|
+
/**
|
|
42
|
+
* Enables client-side pagination when `true`.
|
|
43
|
+
*
|
|
44
|
+
* Defaults to `true`. When set to `false`, all rows are rendered in a single
|
|
45
|
+
* page and the pagination controls are disabled. In that case, the
|
|
46
|
+
* {@link pageSize} value is effectively ignored.
|
|
47
|
+
*/
|
|
48
|
+
pagination?: boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Number of rows to display per page when pagination is enabled.
|
|
51
|
+
*
|
|
52
|
+
* Defaults to `10`. This value is used to initialize the internal pagination
|
|
53
|
+
* state and only has an effect when {@link pagination} is `true`.
|
|
54
|
+
*/
|
|
55
|
+
pageSize?: number;
|
|
56
|
+
/**
|
|
57
|
+
* Array of page size options to display in the page size selector.
|
|
58
|
+
* When provided, a dropdown will be rendered in the pagination footer allowing
|
|
59
|
+
* users to change the number of rows per page.
|
|
60
|
+
*
|
|
61
|
+
* @default [10, 20, 50, 100]
|
|
62
|
+
* @example
|
|
63
|
+
* ```tsx
|
|
64
|
+
* <DataTable columns={columns} data={data} pageSizeOptions={[5, 10, 25]} />
|
|
65
|
+
* ```
|
|
66
|
+
*/
|
|
67
|
+
pageSizeOptions?: number[];
|
|
68
|
+
/**
|
|
69
|
+
* When `true`, displays the count of selected rows.
|
|
70
|
+
*
|
|
71
|
+
* This is useful when row selection is enabled to give users feedback on how
|
|
72
|
+
* many rows are currently selected.
|
|
73
|
+
*/
|
|
74
|
+
showSelectedCount?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Optional callback invoked when a table row is clicked.
|
|
77
|
+
*
|
|
78
|
+
* The callback receives the corresponding data item for the clicked row.
|
|
79
|
+
*/
|
|
80
|
+
onRowClick?: (row: TData) => void;
|
|
81
|
+
/**
|
|
82
|
+
* React node to render when there are no rows to display.
|
|
83
|
+
*
|
|
84
|
+
* If not provided, the table will render without rows and without a custom
|
|
85
|
+
* empty state message or placeholder.
|
|
86
|
+
*/
|
|
87
|
+
emptyState?: React.ReactNode;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function DataTable<TData, TValue>({
|
|
91
|
+
columns,
|
|
92
|
+
data,
|
|
93
|
+
pagination = true,
|
|
94
|
+
pageSize = 10,
|
|
95
|
+
pageSizeOptions,
|
|
96
|
+
showSelectedCount = false,
|
|
97
|
+
onRowClick,
|
|
98
|
+
emptyState,
|
|
99
|
+
className,
|
|
100
|
+
...props
|
|
101
|
+
}: DataTableProps<TData, TValue>) {
|
|
102
|
+
const [sorting, setSorting] = useState<SortingState>([]);
|
|
103
|
+
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
|
|
104
|
+
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({});
|
|
105
|
+
const [rowSelection, setRowSelection] = useState({});
|
|
106
|
+
const [paginationState, setPaginationState] = useState<PaginationState>({
|
|
107
|
+
pageIndex: 0,
|
|
108
|
+
pageSize,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
setPaginationState((prev) => ({...prev, pageSize, pageIndex: 0}));
|
|
113
|
+
}, [pageSize]);
|
|
114
|
+
|
|
115
|
+
// Add selection column if showSelectedCount is enabled
|
|
116
|
+
const columnsWithSelection = useMemo(() => {
|
|
117
|
+
if (!showSelectedCount) {
|
|
118
|
+
return columns;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const selectionColumn: ColumnDef<TData, TValue> = {
|
|
122
|
+
id: 'select',
|
|
123
|
+
header: ({table}) => {
|
|
124
|
+
const isAllSelected = table.getIsAllPageRowsSelected();
|
|
125
|
+
const isSomeSelected = table.getIsSomePageRowsSelected();
|
|
126
|
+
return (
|
|
127
|
+
<Checkbox
|
|
128
|
+
checked={isAllSelected ? true : isSomeSelected ? 'indeterminate' : false}
|
|
129
|
+
onCheckedChange={(checked) => table.toggleAllPageRowsSelected(!!checked)}
|
|
130
|
+
onClick={(e) => e.stopPropagation()}
|
|
131
|
+
aria-label="Select all"
|
|
132
|
+
/>
|
|
133
|
+
);
|
|
134
|
+
},
|
|
135
|
+
cell: ({row}) => (
|
|
136
|
+
<Checkbox
|
|
137
|
+
checked={row.getIsSelected()}
|
|
138
|
+
onCheckedChange={(checked) => row.toggleSelected(!!checked)}
|
|
139
|
+
onClick={(e) => e.stopPropagation()}
|
|
140
|
+
aria-label="Select row"
|
|
141
|
+
/>
|
|
142
|
+
),
|
|
143
|
+
enableSorting: false,
|
|
144
|
+
enableHiding: false,
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
return [selectionColumn, ...columns];
|
|
148
|
+
}, [columns, showSelectedCount]);
|
|
149
|
+
|
|
150
|
+
const table = useReactTable({
|
|
151
|
+
data,
|
|
152
|
+
columns: columnsWithSelection,
|
|
153
|
+
getCoreRowModel: getCoreRowModel(),
|
|
154
|
+
getFilteredRowModel: getFilteredRowModel(),
|
|
155
|
+
getSortedRowModel: getSortedRowModel(),
|
|
156
|
+
getPaginationRowModel: pagination ? getPaginationRowModel() : undefined,
|
|
157
|
+
enableRowSelection: showSelectedCount,
|
|
158
|
+
onSortingChange: setSorting,
|
|
159
|
+
onColumnFiltersChange: setColumnFilters,
|
|
160
|
+
onColumnVisibilityChange: setColumnVisibility,
|
|
161
|
+
onRowSelectionChange: setRowSelection,
|
|
162
|
+
onPaginationChange: setPaginationState,
|
|
163
|
+
state: {
|
|
164
|
+
sorting,
|
|
165
|
+
columnFilters,
|
|
166
|
+
columnVisibility,
|
|
167
|
+
rowSelection,
|
|
168
|
+
pagination: pagination ? paginationState : undefined,
|
|
169
|
+
},
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
return (
|
|
173
|
+
<div
|
|
174
|
+
className={cn('rounded-8 border border-border-neutral-base overflow-hidden', className)}
|
|
175
|
+
{...props}
|
|
176
|
+
>
|
|
177
|
+
<Table>
|
|
178
|
+
{table.getRowModel().rows.length > 0 ? (
|
|
179
|
+
<TableHeader>
|
|
180
|
+
{table.getHeaderGroups().map((headerGroup) => (
|
|
181
|
+
<TableRow key={headerGroup.id} className="hover:bg-transparent border-b">
|
|
182
|
+
{headerGroup.headers.map((header) => (
|
|
183
|
+
<TableHead key={header.id}>
|
|
184
|
+
{header.isPlaceholder
|
|
185
|
+
? null
|
|
186
|
+
: flexRender(header.column.columnDef.header, header.getContext())}
|
|
187
|
+
</TableHead>
|
|
188
|
+
))}
|
|
189
|
+
</TableRow>
|
|
190
|
+
))}
|
|
191
|
+
</TableHeader>
|
|
192
|
+
) : null}
|
|
193
|
+
<TableBody>
|
|
194
|
+
{table.getRowModel().rows?.length ? (
|
|
195
|
+
table.getRowModel().rows.map((row) => (
|
|
196
|
+
<TableRow
|
|
197
|
+
key={row.id}
|
|
198
|
+
onClick={() => onRowClick?.(row.original)}
|
|
199
|
+
data-selected={row.getIsSelected()}
|
|
200
|
+
className={onRowClick ? 'cursor-pointer' : ''}
|
|
201
|
+
tabIndex={onRowClick ? 0 : undefined}
|
|
202
|
+
role={onRowClick ? 'button' : undefined}
|
|
203
|
+
onKeyDown={(event) => {
|
|
204
|
+
if (!onRowClick) return;
|
|
205
|
+
if (event.key === 'Enter' || event.key === ' ') {
|
|
206
|
+
event.preventDefault();
|
|
207
|
+
onRowClick(row.original);
|
|
208
|
+
}
|
|
209
|
+
}}
|
|
210
|
+
>
|
|
211
|
+
{row.getVisibleCells().map((cell) => (
|
|
212
|
+
<TableCell key={cell.id}>
|
|
213
|
+
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
|
214
|
+
</TableCell>
|
|
215
|
+
))}
|
|
216
|
+
</TableRow>
|
|
217
|
+
))
|
|
218
|
+
) : (
|
|
219
|
+
<TableRow className="hover:bg-transparent">
|
|
220
|
+
<TableCell colSpan={table.getAllColumns().length} className="h-240 text-center">
|
|
221
|
+
{emptyState || (
|
|
222
|
+
<div className="flex flex-col items-center justify-center gap-12 py-48">
|
|
223
|
+
<div className="size-32 rounded-6 bg-transparent border border-border-neutral-strong flex items-center justify-center">
|
|
224
|
+
<Icon
|
|
225
|
+
name="fileDamageLine"
|
|
226
|
+
className="size-16 text-foreground-neutral-subtle"
|
|
227
|
+
color="var(--foreground-neutral-subtle, #a1a1aa)"
|
|
228
|
+
/>
|
|
229
|
+
</div>
|
|
230
|
+
<div className="text-center space-y-4">
|
|
231
|
+
<Text size="sm" className="text-foreground-neutral-base">
|
|
232
|
+
No results
|
|
233
|
+
</Text>
|
|
234
|
+
<Text size="xs" className="text-foreground-neutral-muted">
|
|
235
|
+
Looks like there are no results.
|
|
236
|
+
</Text>
|
|
237
|
+
</div>
|
|
238
|
+
</div>
|
|
239
|
+
)}
|
|
240
|
+
</TableCell>
|
|
241
|
+
</TableRow>
|
|
242
|
+
)}
|
|
243
|
+
</TableBody>
|
|
244
|
+
{pagination && table.getRowModel().rows?.length > 0 && (
|
|
245
|
+
<TablePagination
|
|
246
|
+
table={table}
|
|
247
|
+
pageSizeOptions={pageSizeOptions}
|
|
248
|
+
showSelectedCount={showSelectedCount}
|
|
249
|
+
/>
|
|
250
|
+
)}
|
|
251
|
+
</Table>
|
|
252
|
+
</div>
|
|
253
|
+
);
|
|
254
|
+
}
|