@xjur-ui/react 1.0.1 → 1.0.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 +19 -13
- package/CHANGELOG.md +14 -0
- package/dist/components/avatar-group.d.ts +34 -0
- package/dist/components/avatar-group.js +179 -0
- package/dist/components/avatar.js +1 -0
- package/dist/components/badge.d.ts +13 -0
- package/dist/components/badge.js +111 -0
- package/dist/components/chip.d.ts +1 -1
- package/dist/components/chip.js +1 -0
- package/dist/components/date-picker.js +11 -9
- package/dist/components/icon.d.ts +1 -1
- package/dist/components/icon.js +3 -1
- package/dist/components/input.d.ts +1 -1
- package/dist/components/input.js +23 -7
- package/dist/components/select.js +11 -9
- package/dist/components/table.d.ts +17 -0
- package/dist/components/table.js +196 -0
- package/dist/components/tag.d.ts +1 -1
- package/dist/components/typography.d.ts +2 -2
- package/dist/index.css +288 -55
- package/package.json +5 -2
- package/src/components/avatar-group.tsx +76 -0
- package/src/components/avatar.tsx +1 -0
- package/src/components/badge.tsx +40 -0
- package/src/components/date-picker.tsx +15 -9
- package/src/components/input.tsx +22 -7
- package/src/components/select.tsx +15 -9
- package/src/components/table.tsx +160 -0
- package/src/resources/icons.ts +3 -1
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { cx } from '@xjur-ui/util'
|
|
2
|
+
import { AvatarRoot, AvatarImage, AvatarFallback } from './avatar'
|
|
3
|
+
import { Typography } from './typography'
|
|
4
|
+
|
|
5
|
+
export interface AvatarGroupProps {
|
|
6
|
+
/**
|
|
7
|
+
* Lista de avatares para exibir
|
|
8
|
+
*/
|
|
9
|
+
avatars: Array<{
|
|
10
|
+
src?: string
|
|
11
|
+
alt?: string
|
|
12
|
+
fallback?: string
|
|
13
|
+
}>
|
|
14
|
+
/**
|
|
15
|
+
* Número máximo de avatares a exibir antes de mostrar o indicador de overflow
|
|
16
|
+
* @default 3
|
|
17
|
+
*/
|
|
18
|
+
max?: number
|
|
19
|
+
/**
|
|
20
|
+
* Tamanho dos avatares
|
|
21
|
+
* @default 'md'
|
|
22
|
+
*/
|
|
23
|
+
size?: 'xs' | 'sm' | 'md' | 'lg'
|
|
24
|
+
/**
|
|
25
|
+
* Classe CSS adicional
|
|
26
|
+
*/
|
|
27
|
+
className?: string
|
|
28
|
+
/**
|
|
29
|
+
* Espaçamento entre os avatares (em pixels)
|
|
30
|
+
* @default -8
|
|
31
|
+
*/
|
|
32
|
+
spacing?: number
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function AvatarGroup({
|
|
36
|
+
avatars,
|
|
37
|
+
max = 3,
|
|
38
|
+
size = 'md',
|
|
39
|
+
className
|
|
40
|
+
}: AvatarGroupProps) {
|
|
41
|
+
const visibleAvatars = avatars.slice(0, max)
|
|
42
|
+
const remainingCount = avatars.length - max
|
|
43
|
+
|
|
44
|
+
return (
|
|
45
|
+
<div
|
|
46
|
+
className={cx('-space-x-small-1x flex items-center', className)}
|
|
47
|
+
data-slot="avatar-group"
|
|
48
|
+
>
|
|
49
|
+
{visibleAvatars.map((avatar, index) => (
|
|
50
|
+
<AvatarRoot
|
|
51
|
+
className="border-icon-neutral-5 border-2"
|
|
52
|
+
key={index}
|
|
53
|
+
size={size}
|
|
54
|
+
>
|
|
55
|
+
{avatar.src && (
|
|
56
|
+
<AvatarImage
|
|
57
|
+
alt={avatar.alt || `Avatar ${index + 1}`}
|
|
58
|
+
src={avatar.src}
|
|
59
|
+
/>
|
|
60
|
+
)}
|
|
61
|
+
<AvatarFallback>{avatar.fallback || `A${index + 1}`}</AvatarFallback>
|
|
62
|
+
</AvatarRoot>
|
|
63
|
+
))}
|
|
64
|
+
|
|
65
|
+
{remainingCount > 0 && (
|
|
66
|
+
<AvatarRoot className="bg-layer-1-hover" size={size}>
|
|
67
|
+
<AvatarFallback className="bg-layer-1-hover font-medium">
|
|
68
|
+
<Typography className="text-neutral-dark" weight="medium">
|
|
69
|
+
+{remainingCount}
|
|
70
|
+
</Typography>
|
|
71
|
+
</AvatarFallback>
|
|
72
|
+
</AvatarRoot>
|
|
73
|
+
)}
|
|
74
|
+
</div>
|
|
75
|
+
)
|
|
76
|
+
}
|
|
@@ -14,6 +14,7 @@ export function AvatarRoot({
|
|
|
14
14
|
className={cx(
|
|
15
15
|
'rounded-circle relative flex shrink-0 overflow-hidden',
|
|
16
16
|
'data-[size=lg]:size-large-8x data-[size=md]:size-large-4x data-[size=sm]:size-large-2x data-[size=xs]:size-large-1x',
|
|
17
|
+
'data-[size=lg]:text-size-headline-md data-[size=md]:text-size-label-lg data-[size=sm]:text-size-label-sm data-[size=xs]:text-size-label-sm',
|
|
17
18
|
className
|
|
18
19
|
)}
|
|
19
20
|
data-size={size}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { cva, type ClassVariantProps, cx } from '@xjur-ui/util'
|
|
2
|
+
import { Typography } from './typography'
|
|
3
|
+
|
|
4
|
+
const badgeVariants = cva(
|
|
5
|
+
[
|
|
6
|
+
'flex items-center justify-center size-large p-small-2x text-neutral-label rounded-circle'
|
|
7
|
+
],
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
variant: {
|
|
11
|
+
primary: 'bg-primary-idle',
|
|
12
|
+
secondary: 'bg-secondary-idle',
|
|
13
|
+
neutral: 'bg-alt-2-idle',
|
|
14
|
+
success: 'bg-success-idle',
|
|
15
|
+
warning: 'bg-warning-idle',
|
|
16
|
+
danger: 'bg-danger-idle'
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
defaultVariants: {
|
|
20
|
+
variant: 'neutral'
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
export function Badge({
|
|
26
|
+
variant = 'neutral',
|
|
27
|
+
children,
|
|
28
|
+
className
|
|
29
|
+
}: ClassVariantProps<typeof badgeVariants> & {
|
|
30
|
+
children: string
|
|
31
|
+
className?: string
|
|
32
|
+
}) {
|
|
33
|
+
return (
|
|
34
|
+
<span className={cx(badgeVariants({ variant }), className)}>
|
|
35
|
+
<Typography className="text-inherit" size="sm-2x" variant="label">
|
|
36
|
+
{children}
|
|
37
|
+
</Typography>
|
|
38
|
+
</span>
|
|
39
|
+
)
|
|
40
|
+
}
|
|
@@ -41,7 +41,7 @@ export function DatePickerContent({
|
|
|
41
41
|
align={align}
|
|
42
42
|
className={cx(
|
|
43
43
|
className,
|
|
44
|
-
'group z-10 max-h-[var(--radix-popover-content-available-height)] max-w-[var(--radix-popover-trigger-width)]'
|
|
44
|
+
'group z-10 max-h-[var(--radix-popover-content-available-height)] max-w-[var(--radix-popover-content-available-width)] min-w-[var(--radix-popover-trigger-width)]'
|
|
45
45
|
)}
|
|
46
46
|
side={side}
|
|
47
47
|
sideOffset={sideOffset}
|
|
@@ -88,25 +88,27 @@ export function DatePickerLabel({
|
|
|
88
88
|
<Typography
|
|
89
89
|
asChild={true}
|
|
90
90
|
className={cx(
|
|
91
|
-
'
|
|
92
|
-
'pointer-events-none absolute top-
|
|
93
|
-
'ease
|
|
91
|
+
'inline-block max-w-full truncate text-left font-normal',
|
|
92
|
+
'left-small right-small pointer-events-none absolute top-1/2 -translate-y-1/2',
|
|
93
|
+
'ease transition-all duration-250',
|
|
94
94
|
// Content Open
|
|
95
95
|
'group-data-[state=open]:text-primary-idle',
|
|
96
|
-
'group-data-[state=open]:bg-layer-2-idle',
|
|
97
96
|
'group-data-[state=open]:-top-[3px]',
|
|
98
97
|
'group-data-[state=open]:text-size-label-sm-1x',
|
|
99
98
|
'group-data-[state=open]:font-medium',
|
|
100
99
|
// Filled
|
|
101
100
|
'group-has-[input:not(:placeholder-shown)]:text-primary-idle',
|
|
102
|
-
'group-has-[input:not(:placeholder-shown)]:bg-layer-2-idle',
|
|
103
101
|
'group-has-[input:not(:placeholder-shown)]:-top-[3px]',
|
|
104
102
|
'group-has-[input:not(:placeholder-shown)]:text-size-label-sm-1x',
|
|
105
103
|
'group-has-[input:not(:placeholder-shown)]:font-medium',
|
|
106
104
|
// If has left slot
|
|
107
105
|
'group-has-[div[data-slot=date-picker-left-slot]]:left-large-4x',
|
|
108
|
-
'group-has-[div[data-slot=date-picker-left-slot]]:group-data-[state=open]:left-
|
|
109
|
-
'group-has-[div[data-slot=date-picker-left-slot]]:group-has-[input:not(:placeholder-shown)]:left-
|
|
106
|
+
'group-has-[div[data-slot=date-picker-left-slot]]:group-data-[state=open]:left-small',
|
|
107
|
+
'group-has-[div[data-slot=date-picker-left-slot]]:group-has-[input:not(:placeholder-shown)]:left-small',
|
|
108
|
+
// If has right slot
|
|
109
|
+
'group-has-[div[data-slot=date-picker-right-slot]]:right-large-4x',
|
|
110
|
+
'group-has-[div[data-slot=date-picker-right-slot]]:group-data-[state=open]:right-small',
|
|
111
|
+
'group-has-[div[data-slot=date-picker-right-slot]]:group-has-[input:not(:placeholder-shown)]:right-small',
|
|
110
112
|
// Animate
|
|
111
113
|
'group-data-[state=open]:animate-in',
|
|
112
114
|
'group-data-[state=closed]:animate-out',
|
|
@@ -116,7 +118,11 @@ export function DatePickerLabel({
|
|
|
116
118
|
weight="medium"
|
|
117
119
|
{...props}
|
|
118
120
|
>
|
|
119
|
-
<label htmlFor={htmlFor}>
|
|
121
|
+
<label htmlFor={htmlFor}>
|
|
122
|
+
<span className="bg-layer-2-idle rounded-small-1x max-w-full">
|
|
123
|
+
{children}
|
|
124
|
+
</span>
|
|
125
|
+
</label>
|
|
120
126
|
</Typography>
|
|
121
127
|
)
|
|
122
128
|
}
|
package/src/components/input.tsx
CHANGED
|
@@ -52,7 +52,7 @@ export function InputContent({ className, ...props }: ComponentProps<'div'>) {
|
|
|
52
52
|
variant: {
|
|
53
53
|
default: '',
|
|
54
54
|
outlined:
|
|
55
|
-
'bg-layer-2-idle border-border-layer-2 border hover:border-border-layer-3 has-[input:not(:placeholder-shown)]:border-primary-idle',
|
|
55
|
+
'bg-layer-2-idle border-border-layer-2 border hover:group-has-[input:not(:focus-within)]:border-border-layer-3 has-[input:not(:placeholder-shown)]:border-primary-idle',
|
|
56
56
|
filled:
|
|
57
57
|
'bg-layer-2-hover group-hover:border-border-layer-1 group-hover:border-1'
|
|
58
58
|
}
|
|
@@ -74,6 +74,7 @@ export function InputContent({ className, ...props }: ComponentProps<'div'>) {
|
|
|
74
74
|
export function InputLabel({
|
|
75
75
|
htmlFor,
|
|
76
76
|
className,
|
|
77
|
+
children,
|
|
77
78
|
...props
|
|
78
79
|
}: ComponentProps<'label'> & { htmlFor: string }) {
|
|
79
80
|
return (
|
|
@@ -82,10 +83,10 @@ export function InputLabel({
|
|
|
82
83
|
return (
|
|
83
84
|
<label
|
|
84
85
|
className={cx(
|
|
85
|
-
'
|
|
86
|
-
'ease animate-in pointer-events-none absolute top-1/2
|
|
86
|
+
'group text-size-body-md text-neutral-dark inline-block max-w-full truncate text-left',
|
|
87
|
+
'ease animate-in left-small right-small pointer-events-none absolute top-1/2 -translate-y-1/2 transition-all duration-250',
|
|
87
88
|
// Filled
|
|
88
|
-
'group-focus-within:text-primary-idle group-focus-within
|
|
89
|
+
'group-focus-within:text-primary-idle group-focus-within:-top-[3px]',
|
|
89
90
|
'group-focus-within:text-size-label-sm-1x group-focus-within:font-medium',
|
|
90
91
|
'group-has-[input:not(:placeholder-shown)]:-top-[3px]',
|
|
91
92
|
'group-has-[input:not(:placeholder-shown)]:text-size-label-sm-1x',
|
|
@@ -93,8 +94,12 @@ export function InputLabel({
|
|
|
93
94
|
'data-[variant=outlined]:group-has-[input:not(:placeholder-shown)]:text-primary-idle',
|
|
94
95
|
// If has left slot
|
|
95
96
|
'group-has-[div[data-slot=input-left-slot]]:left-large-4x',
|
|
96
|
-
'group-has-[div[data-slot=input-left-slot]]:group-focus-within:left-
|
|
97
|
-
'group-has-[div[data-slot=input-left-slot]]:group-has-[input:not(:placeholder-shown)]:left-
|
|
97
|
+
'group-has-[div[data-slot=input-left-slot]]:group-focus-within:left-small',
|
|
98
|
+
'group-has-[div[data-slot=input-left-slot]]:group-has-[input:not(:placeholder-shown)]:left-small',
|
|
99
|
+
// If has right slot
|
|
100
|
+
'group-has-[div[data-slot=input-right-slot]]:right-large-4x',
|
|
101
|
+
'group-has-[div[data-slot=input-right-slot]]:group-focus-within:right-small',
|
|
102
|
+
'group-has-[div[data-slot=input-right-slot]]:group-has-[input:not(:placeholder-shown)]:right-small',
|
|
98
103
|
// Animate
|
|
99
104
|
'group-focus-within:animate-in',
|
|
100
105
|
'group-has-[input:not(:placeholder-shown)]:animate-out',
|
|
@@ -103,7 +108,17 @@ export function InputLabel({
|
|
|
103
108
|
data-variant={variant}
|
|
104
109
|
htmlFor={htmlFor}
|
|
105
110
|
{...props}
|
|
106
|
-
|
|
111
|
+
>
|
|
112
|
+
<span
|
|
113
|
+
className={cx(
|
|
114
|
+
'rounded-small-1x max-w-full',
|
|
115
|
+
'group-data-[variant=outlined]:group-focus-within:bg-layer-2-idle group-data-[variant=filled]:group-focus-within:bg-layer-2-hover',
|
|
116
|
+
'group-data-[variant=outlined]:bg-layer-2-idle group-data-[variant=filled]:bg-layer-2-hover'
|
|
117
|
+
)}
|
|
118
|
+
>
|
|
119
|
+
{children}
|
|
120
|
+
</span>
|
|
121
|
+
</label>
|
|
107
122
|
)
|
|
108
123
|
}}
|
|
109
124
|
</FieldContext.Consumer>
|
|
@@ -54,7 +54,7 @@ export function SelectContent({
|
|
|
54
54
|
align={align}
|
|
55
55
|
className={cx(
|
|
56
56
|
className,
|
|
57
|
-
'group z-10 max-h-[var(--radix-popover-content-available-height)] w-[var(--radix-popover-trigger-width)]'
|
|
57
|
+
'group z-10 max-h-[var(--radix-popover-content-available-height)] max-w-[var(--radix-popover-content-available-width)] min-w-[var(--radix-popover-trigger-width)]'
|
|
58
58
|
)}
|
|
59
59
|
side={side}
|
|
60
60
|
sideOffset={sideOffset}
|
|
@@ -101,7 +101,7 @@ export function SelectMultiValue({
|
|
|
101
101
|
<div
|
|
102
102
|
className={cx(
|
|
103
103
|
className,
|
|
104
|
-
'gap-small-1x scrollbar-hide group-has-[div[data-slot=select-left-slot]]:pl-large-1x
|
|
104
|
+
'gap-small-1x scrollbar-hide group-has-[div[data-slot=select-left-slot]]:pl-large-1x overflow-x-small flex'
|
|
105
105
|
)}
|
|
106
106
|
{...props}
|
|
107
107
|
>
|
|
@@ -129,25 +129,27 @@ export function SelectLabel({
|
|
|
129
129
|
<Typography
|
|
130
130
|
asChild={true}
|
|
131
131
|
className={cx(
|
|
132
|
-
'
|
|
133
|
-
'pointer-events-none absolute top-1/2
|
|
132
|
+
'inline-block max-w-full truncate text-left font-normal',
|
|
133
|
+
'left-small right-small pointer-events-none absolute top-1/2 -translate-y-1/2',
|
|
134
134
|
'ease transition-all duration-250',
|
|
135
135
|
// Content Open
|
|
136
136
|
'group-data-[state=open]:text-primary-idle',
|
|
137
|
-
'group-data-[state=open]:bg-layer-2-idle',
|
|
138
137
|
'group-data-[state=open]:-top-[3px]',
|
|
139
138
|
'group-data-[state=open]:text-size-label-sm-1x',
|
|
140
139
|
'group-data-[state=open]:font-medium',
|
|
141
140
|
// Filled
|
|
142
141
|
'group-has-[input:not(:placeholder-shown)]:text-primary-idle',
|
|
143
|
-
'group-has-[input:not(:placeholder-shown)]:bg-layer-2-idle',
|
|
144
142
|
'group-has-[input:not(:placeholder-shown)]:-top-[3px]',
|
|
145
143
|
'group-has-[input:not(:placeholder-shown)]:text-size-label-sm-1x',
|
|
146
144
|
'group-has-[input:not(:placeholder-shown)]:font-medium',
|
|
147
145
|
// If has left slot
|
|
148
146
|
'group-has-[div[data-slot=select-left-slot]]:left-large-4x',
|
|
149
|
-
'group-has-[div[data-slot=select-left-slot]]:group-data-[state=open]:left-
|
|
150
|
-
'group-has-[div[data-slot=select-left-slot]]:group-has-[input:not(:placeholder-shown)]:left-
|
|
147
|
+
'group-has-[div[data-slot=select-left-slot]]:group-data-[state=open]:left-small',
|
|
148
|
+
'group-has-[div[data-slot=select-left-slot]]:group-has-[input:not(:placeholder-shown)]:left-small',
|
|
149
|
+
// If has right slot
|
|
150
|
+
'group-has-[div[data-slot=select-right-slot]]:right-large-4x',
|
|
151
|
+
'group-has-[div[data-slot=select-right-slot]]:group-data-[state=open]:right-small',
|
|
152
|
+
'group-has-[div[data-slot=select-right-slot]]:group-has-[input:not(:placeholder-shown)]:right-small',
|
|
151
153
|
// Animate
|
|
152
154
|
'group-data-[state=open]:animate-in',
|
|
153
155
|
'group-data-[state=closed]:animate-out',
|
|
@@ -157,7 +159,11 @@ export function SelectLabel({
|
|
|
157
159
|
weight="medium"
|
|
158
160
|
{...props}
|
|
159
161
|
>
|
|
160
|
-
<label htmlFor={htmlFor}>
|
|
162
|
+
<label htmlFor={htmlFor}>
|
|
163
|
+
<span className="bg-layer-2-idle rounded-small-1x max-w-full">
|
|
164
|
+
{children}
|
|
165
|
+
</span>
|
|
166
|
+
</label>
|
|
161
167
|
</Typography>
|
|
162
168
|
)
|
|
163
169
|
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { cx } from '@xjur-ui/util'
|
|
2
|
+
import { Icon } from './icon'
|
|
3
|
+
|
|
4
|
+
export function Table({ className, ...props }: React.ComponentProps<'table'>) {
|
|
5
|
+
return (
|
|
6
|
+
<div
|
|
7
|
+
className="text-size-body-md scrollbar-thin relative w-full overflow-hidden transition-all hover:overflow-x-auto"
|
|
8
|
+
data-slot="table-container"
|
|
9
|
+
>
|
|
10
|
+
<table
|
|
11
|
+
className={cx('w-full caption-bottom', className)}
|
|
12
|
+
data-slot="table"
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
</div>
|
|
16
|
+
)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export function TableHeader({
|
|
20
|
+
className,
|
|
21
|
+
...props
|
|
22
|
+
}: React.ComponentProps<'thead'>) {
|
|
23
|
+
return (
|
|
24
|
+
<thead
|
|
25
|
+
className={cx(
|
|
26
|
+
'group/table-header [&_tr]:border-border-layer-2 hover:bg-layer-2-hover [&_tr]:border-b',
|
|
27
|
+
className
|
|
28
|
+
)}
|
|
29
|
+
data-slot="table-header"
|
|
30
|
+
{...props}
|
|
31
|
+
/>
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function TableBody({
|
|
36
|
+
className,
|
|
37
|
+
...props
|
|
38
|
+
}: React.ComponentProps<'tbody'>) {
|
|
39
|
+
return (
|
|
40
|
+
<tbody
|
|
41
|
+
className={cx(
|
|
42
|
+
'[&_tr]:border-border-layer-2 [&_tr]:border-b [&_tr:last-child]:border-0',
|
|
43
|
+
className
|
|
44
|
+
)}
|
|
45
|
+
data-slot="table-body"
|
|
46
|
+
{...props}
|
|
47
|
+
/>
|
|
48
|
+
)
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function TableFooter({
|
|
52
|
+
className,
|
|
53
|
+
...props
|
|
54
|
+
}: React.ComponentProps<'tfoot'>) {
|
|
55
|
+
return (
|
|
56
|
+
<tfoot
|
|
57
|
+
className={cx(
|
|
58
|
+
'border-border-layer-2 border-t font-medium [&>tr]:last:border-b-0',
|
|
59
|
+
className
|
|
60
|
+
)}
|
|
61
|
+
data-slot="table-footer"
|
|
62
|
+
{...props}
|
|
63
|
+
/>
|
|
64
|
+
)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function TableRow({
|
|
68
|
+
className,
|
|
69
|
+
isSelected = false,
|
|
70
|
+
...props
|
|
71
|
+
}: React.ComponentProps<'tr'> & { isSelected?: boolean }) {
|
|
72
|
+
return (
|
|
73
|
+
<tr
|
|
74
|
+
className={cx(
|
|
75
|
+
'bg-layer-2-idle hover:bg-layer-2-hover ease border-b transition-colors duration-100',
|
|
76
|
+
'active:bg-layer-2-pressed',
|
|
77
|
+
'data-[selected=true]:bg-primary-alt-active',
|
|
78
|
+
className
|
|
79
|
+
)}
|
|
80
|
+
data-selected={isSelected}
|
|
81
|
+
data-slot="table-row"
|
|
82
|
+
{...props}
|
|
83
|
+
/>
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function TableHead({ className, ...props }: React.ComponentProps<'th'>) {
|
|
88
|
+
return (
|
|
89
|
+
<th
|
|
90
|
+
className={cx(
|
|
91
|
+
'group/th text-neutral-placeholder text-size-label-sm h-large-4x py-small-1x px-small text-left align-middle font-medium whitespace-nowrap',
|
|
92
|
+
'pr-large-2x relative',
|
|
93
|
+
'animate-in fade-in duration-200 ease-in',
|
|
94
|
+
className
|
|
95
|
+
)}
|
|
96
|
+
data-slot="table-head"
|
|
97
|
+
{...props}
|
|
98
|
+
/>
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export function TableHeadContent({
|
|
103
|
+
className,
|
|
104
|
+
...props
|
|
105
|
+
}: React.ComponentProps<'div'>) {
|
|
106
|
+
return (
|
|
107
|
+
<div
|
|
108
|
+
className={cx(
|
|
109
|
+
'gap-small pr-large-3x relative flex w-fit items-center',
|
|
110
|
+
className
|
|
111
|
+
)}
|
|
112
|
+
{...props}
|
|
113
|
+
/>
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export function TableSort({
|
|
118
|
+
className,
|
|
119
|
+
sortedDirection,
|
|
120
|
+
...props
|
|
121
|
+
}: React.ComponentProps<'button'> & { sortedDirection?: 'asc' | 'desc' }) {
|
|
122
|
+
return (
|
|
123
|
+
<button
|
|
124
|
+
className={cx(
|
|
125
|
+
'size-large-1x rounded-small-1x',
|
|
126
|
+
'flex cursor-pointer items-center justify-center',
|
|
127
|
+
'hidden group-hover/th:flex',
|
|
128
|
+
'data-[sorted=true]:flex',
|
|
129
|
+
'transition-all duration-200 ease-out',
|
|
130
|
+
'data-[sorted=true]:bg-primary-alt-active data-[sorted=true]:text-primary-label-active',
|
|
131
|
+
'absolute top-1/2 right-0 -translate-y-1/2',
|
|
132
|
+
className
|
|
133
|
+
)}
|
|
134
|
+
data-sorted={sortedDirection !== undefined}
|
|
135
|
+
type="button"
|
|
136
|
+
{...props}
|
|
137
|
+
>
|
|
138
|
+
{sortedDirection !== undefined ? (
|
|
139
|
+
<Icon
|
|
140
|
+
name={sortedDirection === 'asc' ? 'arrow_downward' : 'arrow_upward'}
|
|
141
|
+
/>
|
|
142
|
+
) : (
|
|
143
|
+
<Icon name="swap_vert" />
|
|
144
|
+
)}
|
|
145
|
+
</button>
|
|
146
|
+
)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export function TableCell({ className, ...props }: React.ComponentProps<'td'>) {
|
|
150
|
+
return (
|
|
151
|
+
<td
|
|
152
|
+
className={cx(
|
|
153
|
+
'px-small py-none h-large-8x text-left align-middle whitespace-nowrap',
|
|
154
|
+
className
|
|
155
|
+
)}
|
|
156
|
+
data-slot="table-cell"
|
|
157
|
+
{...props}
|
|
158
|
+
/>
|
|
159
|
+
)
|
|
160
|
+
}
|