@salesforce/webapp-template-app-react-template-b2x-experimental 1.43.1 → 1.45.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.
Files changed (41) hide show
  1. package/dist/CHANGELOG.md +16 -0
  2. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/package-lock.json +1306 -534
  3. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/package.json +1 -3
  4. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/app.tsx +2 -5
  5. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/auth/authHelpers.ts +73 -0
  6. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/{utils → components/auth}/authenticationConfig.ts +9 -0
  7. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/auth/{authentication-route.tsx → authenticationRouteLayout.tsx} +1 -1
  8. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/auth/{private-route.tsx → privateRouteLayout.tsx} +1 -1
  9. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/auth/sessionTimeout/SessionTimeoutValidator.tsx +616 -0
  10. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/auth/sessionTimeout/sessionTimeService.ts +161 -0
  11. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/auth/sessionTimeout/sessionTimeoutConfig.ts +77 -0
  12. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/alert.tsx +17 -13
  13. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/button.tsx +35 -22
  14. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/card.tsx +27 -12
  15. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/dialog.tsx +143 -0
  16. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/field.tsx +157 -46
  17. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/index.ts +1 -0
  18. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/input.tsx +3 -3
  19. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/label.tsx +2 -2
  20. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/pagination.tsx +87 -74
  21. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/select.tsx +156 -124
  22. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/separator.tsx +26 -0
  23. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/skeleton.tsx +1 -0
  24. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/spinner.tsx +5 -16
  25. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/table.tsx +68 -95
  26. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/components/ui/tabs.tsx +47 -84
  27. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/context/AuthContext.tsx +12 -0
  28. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/hooks/form.tsx +1 -1
  29. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/hooks/useCountdownTimer.ts +266 -0
  30. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/hooks/useRetryWithBackoff.ts +109 -0
  31. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/layouts/AuthAppLayout.tsx +12 -0
  32. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/pages/ChangePassword.tsx +3 -2
  33. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/pages/ForgotPassword.tsx +1 -1
  34. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/pages/Login.tsx +3 -3
  35. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/pages/Profile.tsx +3 -2
  36. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/pages/Register.tsx +4 -5
  37. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/pages/ResetPassword.tsx +3 -2
  38. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/routes.tsx +4 -4
  39. package/dist/force-app/main/default/webapplications/appreacttemplateb2x/src/utils/helpers.ts +0 -74
  40. package/dist/package.json +1 -1
  41. package/package.json +2 -2
@@ -1,151 +1,183 @@
1
1
  import * as React from "react";
2
- import * as SelectPrimitive from "@radix-ui/react-select";
3
- import { Check, ChevronDown, ChevronUp } from "lucide-react";
2
+ import { Select as SelectPrimitive } from "radix-ui";
4
3
 
5
4
  import { cn } from "../../lib/utils";
5
+ import { ChevronDownIcon, CheckIcon, ChevronUpIcon } from "lucide-react";
6
6
 
7
- const Select = SelectPrimitive.Root;
7
+ function Select({ ...props }: React.ComponentProps<typeof SelectPrimitive.Root>) {
8
+ return <SelectPrimitive.Root data-slot="select" {...props} />;
9
+ }
8
10
 
9
- const SelectGroup = SelectPrimitive.Group;
10
-
11
- const SelectValue = SelectPrimitive.Value;
12
-
13
- const SelectTrigger = React.forwardRef<
14
- React.ElementRef<typeof SelectPrimitive.Trigger>,
15
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
16
- >(({ className, children, ...props }, ref) => (
17
- <SelectPrimitive.Trigger
18
- ref={ref}
19
- className={cn(
20
- "flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-xs ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
21
- className,
22
- )}
23
- {...props}
24
- >
25
- {children}
26
- <SelectPrimitive.Icon asChild>
27
- <ChevronDown className="h-4 w-4 opacity-50" />
28
- </SelectPrimitive.Icon>
29
- </SelectPrimitive.Trigger>
30
- ));
31
- SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
32
-
33
- const SelectScrollUpButton = React.forwardRef<
34
- React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
35
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
36
- >(({ className, ...props }, ref) => (
37
- <SelectPrimitive.ScrollUpButton
38
- ref={ref}
39
- className={cn("flex cursor-default items-center justify-center py-1 bg-white", className)}
40
- {...props}
41
- >
42
- <ChevronUp className="h-4 w-4" />
43
- </SelectPrimitive.ScrollUpButton>
44
- ));
45
- SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
11
+ function SelectGroup({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Group>) {
12
+ return (
13
+ <SelectPrimitive.Group
14
+ data-slot="select-group"
15
+ className={cn("scroll-my-1 p-1", className)}
16
+ {...props}
17
+ />
18
+ );
19
+ }
46
20
 
47
- const SelectScrollDownButton = React.forwardRef<
48
- React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
49
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
50
- >(({ className, ...props }, ref) => (
51
- <SelectPrimitive.ScrollDownButton
52
- ref={ref}
53
- className={cn("flex cursor-default items-center justify-center py-1 bg-white", className)}
54
- {...props}
55
- >
56
- <ChevronDown className="h-4 w-4" />
57
- </SelectPrimitive.ScrollDownButton>
58
- ));
59
- SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
21
+ function SelectValue({ ...props }: React.ComponentProps<typeof SelectPrimitive.Value>) {
22
+ return <SelectPrimitive.Value data-slot="select-value" {...props} />;
23
+ }
60
24
 
61
- const SelectContent = React.forwardRef<
62
- React.ElementRef<typeof SelectPrimitive.Content>,
63
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
64
- >(({ className, children, position = "popper", ...props }, ref) => (
65
- <SelectPrimitive.Portal>
66
- <SelectPrimitive.Content
67
- ref={ref}
25
+ function SelectTrigger({
26
+ className,
27
+ size = "default",
28
+ children,
29
+ ...props
30
+ }: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
31
+ size?: "sm" | "default";
32
+ }) {
33
+ return (
34
+ <SelectPrimitive.Trigger
35
+ data-slot="select-trigger"
36
+ data-size={size}
68
37
  className={cn(
69
- "relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-white text-gray-900 shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
70
- position === "popper" &&
71
- "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
38
+ "border-input data-placeholder:text-muted-foreground dark:bg-input/30 dark:hover:bg-input/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 gap-1.5 rounded-lg border bg-transparent py-2 pr-2 pl-2.5 text-sm transition-colors select-none focus-visible:ring-3 aria-invalid:ring-3 data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-[min(var(--radius-md),10px)] *:data-[slot=select-value]:gap-1.5 [&_svg:not([class*='size-'])]:size-4 flex w-fit items-center justify-between whitespace-nowrap outline-none disabled:cursor-not-allowed disabled:opacity-50 *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center [&_svg]:pointer-events-none [&_svg]:shrink-0",
72
39
  className,
73
40
  )}
74
- position={position}
75
41
  {...props}
76
42
  >
77
- <SelectScrollUpButton />
78
- <SelectPrimitive.Viewport
43
+ {children}
44
+ <SelectPrimitive.Icon asChild>
45
+ <ChevronDownIcon className="text-muted-foreground size-4 pointer-events-none" />
46
+ </SelectPrimitive.Icon>
47
+ </SelectPrimitive.Trigger>
48
+ );
49
+ }
50
+
51
+ function SelectContent({
52
+ className,
53
+ children,
54
+ position = "item-aligned",
55
+ align = "center",
56
+ ...props
57
+ }: React.ComponentProps<typeof SelectPrimitive.Content>) {
58
+ return (
59
+ <SelectPrimitive.Portal>
60
+ <SelectPrimitive.Content
61
+ data-slot="select-content"
62
+ data-align-trigger={position === "item-aligned"}
79
63
  className={cn(
80
- "p-1 bg-white",
64
+ "bg-popover text-popover-foreground data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-open:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 ring-foreground/10 min-w-36 rounded-lg shadow-md ring-1 duration-100 relative z-50 max-h-(--radix-select-content-available-height) origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto data-[align-trigger=true]:animate-none",
81
65
  position === "popper" &&
82
- "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]",
66
+ "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
67
+ className,
83
68
  )}
69
+ position={position}
70
+ align={align}
71
+ {...props}
84
72
  >
85
- {children}
86
- </SelectPrimitive.Viewport>
87
- <SelectScrollDownButton />
88
- </SelectPrimitive.Content>
89
- </SelectPrimitive.Portal>
90
- ));
91
- SelectContent.displayName = SelectPrimitive.Content.displayName;
73
+ <SelectScrollUpButton />
74
+ <SelectPrimitive.Viewport
75
+ data-position={position}
76
+ className={cn(
77
+ "data-[position=popper]:h-(--radix-select-trigger-height) data-[position=popper]:w-full data-[position=popper]:min-w-(--radix-select-trigger-width)",
78
+ position === "popper" && "",
79
+ )}
80
+ >
81
+ {children}
82
+ </SelectPrimitive.Viewport>
83
+ <SelectScrollDownButton />
84
+ </SelectPrimitive.Content>
85
+ </SelectPrimitive.Portal>
86
+ );
87
+ }
92
88
 
93
- const SelectLabel = React.forwardRef<
94
- React.ElementRef<typeof SelectPrimitive.Label>,
95
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
96
- >(({ className, ...props }, ref) => (
97
- <SelectPrimitive.Label
98
- ref={ref}
99
- className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)}
100
- {...props}
101
- />
102
- ));
103
- SelectLabel.displayName = SelectPrimitive.Label.displayName;
89
+ function SelectLabel({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Label>) {
90
+ return (
91
+ <SelectPrimitive.Label
92
+ data-slot="select-label"
93
+ className={cn("text-muted-foreground px-1.5 py-1 text-xs", className)}
94
+ {...props}
95
+ />
96
+ );
97
+ }
104
98
 
105
- const SelectItem = React.forwardRef<
106
- React.ElementRef<typeof SelectPrimitive.Item>,
107
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
108
- >(({ className, children, ...props }, ref) => (
109
- <SelectPrimitive.Item
110
- ref={ref}
111
- className={cn(
112
- "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-gray-100 focus:text-gray-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
113
- className,
114
- )}
115
- {...props}
116
- >
117
- <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
118
- <SelectPrimitive.ItemIndicator>
119
- <Check className="h-4 w-4" />
120
- </SelectPrimitive.ItemIndicator>
121
- </span>
99
+ function SelectItem({
100
+ className,
101
+ children,
102
+ ...props
103
+ }: React.ComponentProps<typeof SelectPrimitive.Item>) {
104
+ return (
105
+ <SelectPrimitive.Item
106
+ data-slot="select-item"
107
+ className={cn(
108
+ "focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2 relative flex w-full cursor-default items-center outline-hidden select-none data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
109
+ className,
110
+ )}
111
+ {...props}
112
+ >
113
+ <span className="pointer-events-none absolute right-2 flex size-4 items-center justify-center">
114
+ <SelectPrimitive.ItemIndicator>
115
+ <CheckIcon className="pointer-events-none" />
116
+ </SelectPrimitive.ItemIndicator>
117
+ </span>
118
+ <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
119
+ </SelectPrimitive.Item>
120
+ );
121
+ }
122
122
 
123
- <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
124
- </SelectPrimitive.Item>
125
- ));
126
- SelectItem.displayName = SelectPrimitive.Item.displayName;
123
+ function SelectSeparator({
124
+ className,
125
+ ...props
126
+ }: React.ComponentProps<typeof SelectPrimitive.Separator>) {
127
+ return (
128
+ <SelectPrimitive.Separator
129
+ data-slot="select-separator"
130
+ className={cn("bg-border -mx-1 my-1 h-px pointer-events-none", className)}
131
+ {...props}
132
+ />
133
+ );
134
+ }
127
135
 
128
- const SelectSeparator = React.forwardRef<
129
- React.ElementRef<typeof SelectPrimitive.Separator>,
130
- React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
131
- >(({ className, ...props }, ref) => (
132
- <SelectPrimitive.Separator
133
- ref={ref}
134
- className={cn("-mx-1 my-1 h-px bg-muted", className)}
135
- {...props}
136
- />
137
- ));
138
- SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
136
+ function SelectScrollUpButton({
137
+ className,
138
+ ...props
139
+ }: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
140
+ return (
141
+ <SelectPrimitive.ScrollUpButton
142
+ data-slot="select-scroll-up-button"
143
+ className={cn(
144
+ "bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-4",
145
+ className,
146
+ )}
147
+ {...props}
148
+ >
149
+ <ChevronUpIcon />
150
+ </SelectPrimitive.ScrollUpButton>
151
+ );
152
+ }
153
+
154
+ function SelectScrollDownButton({
155
+ className,
156
+ ...props
157
+ }: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
158
+ return (
159
+ <SelectPrimitive.ScrollDownButton
160
+ data-slot="select-scroll-down-button"
161
+ className={cn(
162
+ "bg-popover z-10 flex cursor-default items-center justify-center py-1 [&_svg:not([class*='size-'])]:size-4",
163
+ className,
164
+ )}
165
+ {...props}
166
+ >
167
+ <ChevronDownIcon />
168
+ </SelectPrimitive.ScrollDownButton>
169
+ );
170
+ }
139
171
 
140
172
  export {
141
173
  Select,
142
- SelectGroup,
143
- SelectValue,
144
- SelectTrigger,
145
174
  SelectContent,
146
- SelectLabel,
175
+ SelectGroup,
147
176
  SelectItem,
148
- SelectSeparator,
149
- SelectScrollUpButton,
177
+ SelectLabel,
150
178
  SelectScrollDownButton,
179
+ SelectScrollUpButton,
180
+ SelectSeparator,
181
+ SelectTrigger,
182
+ SelectValue,
151
183
  };
@@ -0,0 +1,26 @@
1
+ import * as React from "react";
2
+ import { Separator as SeparatorPrimitive } from "radix-ui";
3
+
4
+ import { cn } from "../../lib/utils";
5
+
6
+ function Separator({
7
+ className,
8
+ orientation = "horizontal",
9
+ decorative = true,
10
+ ...props
11
+ }: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
12
+ return (
13
+ <SeparatorPrimitive.Root
14
+ data-slot="separator"
15
+ decorative={decorative}
16
+ orientation={orientation}
17
+ className={cn(
18
+ "bg-border shrink-0 data-horizontal:h-px data-horizontal:w-full data-vertical:w-px data-vertical:self-stretch",
19
+ className,
20
+ )}
21
+ {...props}
22
+ />
23
+ );
24
+ }
25
+
26
+ export { Separator };
@@ -1,3 +1,4 @@
1
+ import * as React from "react";
1
2
  import { cn } from "../../lib/utils";
2
3
 
3
4
  function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
@@ -1,26 +1,15 @@
1
- import * as React from "react";
2
- import { LoaderIcon } from "lucide-react";
3
-
4
1
  import { cn } from "../../lib/utils";
2
+ import { Loader2Icon } from "lucide-react";
5
3
 
6
- const Spinner = React.forwardRef<SVGSVGElement, React.ComponentProps<"svg">>(function Spinner(
7
- { className, ...props },
8
- ref,
9
- ) {
4
+ function Spinner({ className, ...props }: React.ComponentProps<"svg">) {
10
5
  return (
11
- <LoaderIcon
12
- ref={ref}
6
+ <Loader2Icon
13
7
  role="status"
14
8
  aria-label="Loading"
15
- className={cn(
16
- "size-4 animate-spin",
17
- // A11y: Respect user's motion preferences
18
- "motion-reduce:animate-none",
19
- className,
20
- )}
9
+ className={cn("size-4 animate-spin", className)}
21
10
  {...props}
22
11
  />
23
12
  );
24
- });
13
+ }
25
14
 
26
15
  export { Spinner };
@@ -1,114 +1,87 @@
1
1
  import * as React from "react";
2
- import { cn } from "../../lib/utils";
3
2
 
4
- /**
5
- * Shadcn-style Table components
6
- * These components follow shadcn/ui patterns for consistent styling
7
- */
3
+ import { cn } from "../../lib/utils";
8
4
 
9
- const Table = React.forwardRef<HTMLTableElement, React.HTMLAttributes<HTMLTableElement>>(
10
- ({ className, ...props }, ref) => (
11
- <div className="relative w-full overflow-auto">
12
- <table ref={ref} className={cn("w-full caption-bottom text-sm", className)} {...props} />
5
+ function Table({ className, ...props }: React.ComponentProps<"table">) {
6
+ return (
7
+ <div data-slot="table-container" className="relative w-full overflow-x-auto">
8
+ <table
9
+ data-slot="table"
10
+ className={cn("w-full caption-bottom text-sm", className)}
11
+ {...props}
12
+ />
13
13
  </div>
14
- ),
15
- );
16
- Table.displayName = "Table";
17
-
18
- const TableHeader = React.forwardRef<
19
- HTMLTableSectionElement,
20
- React.HTMLAttributes<HTMLTableSectionElement>
21
- >(({ className, ...props }, ref) => (
22
- <thead
23
- ref={ref}
24
- className={cn(
25
- // 1. Existing border style
26
- "[&_tr]:border-b",
14
+ );
15
+ }
27
16
 
28
- // 2. Make headers sticky
29
- // We apply this to the 'th' children using the [&_th] selector
30
- // This is often more robust across browsers than applying sticky to the <thead> itself
31
- "[&_th]:sticky [&_th]:top-0 [&_th]:z-10",
32
- // 3. CRITICAL: Add background color
33
- // Without this, content scrolls "under" the transparent text
34
- "[&_th]:bg-background",
17
+ function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
18
+ return <thead data-slot="table-header" className={cn("[&_tr]:border-b", className)} {...props} />;
19
+ }
35
20
 
36
- // 4. Optional: Add a subtle shadow for better visual separation when scrolling
37
- "[&_th]:shadow-[0_1px_0_0_theme(colors.border)]",
38
- className,
39
- )}
40
- {...props}
41
- />
42
- ));
43
- TableHeader.displayName = "TableHeader";
44
-
45
- const TableBody = React.forwardRef<
46
- HTMLTableSectionElement,
47
- React.HTMLAttributes<HTMLTableSectionElement>
48
- >(({ className, ...props }, ref) => (
49
- <tbody ref={ref} className={cn("[&_tr:last-child]:border-0", className)} {...props} />
50
- ));
51
- TableBody.displayName = "TableBody";
21
+ function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
22
+ return (
23
+ <tbody
24
+ data-slot="table-body"
25
+ className={cn("[&_tr:last-child]:border-0", className)}
26
+ {...props}
27
+ />
28
+ );
29
+ }
52
30
 
53
- const TableFooter = React.forwardRef<
54
- HTMLTableSectionElement,
55
- React.HTMLAttributes<HTMLTableSectionElement>
56
- >(({ className, ...props }, ref) => (
57
- <tfoot
58
- ref={ref}
59
- className={cn("border-t bg-muted/50 font-medium [&>tr]:last:border-b-0", className)}
60
- {...props}
61
- />
62
- ));
63
- TableFooter.displayName = "TableFooter";
31
+ function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
32
+ return (
33
+ <tfoot
34
+ data-slot="table-footer"
35
+ className={cn("bg-muted/50 border-t font-medium [&>tr]:last:border-b-0", className)}
36
+ {...props}
37
+ />
38
+ );
39
+ }
64
40
 
65
- const TableRow = React.forwardRef<HTMLTableRowElement, React.HTMLAttributes<HTMLTableRowElement>>(
66
- ({ className, ...props }, ref) => (
41
+ function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
42
+ return (
67
43
  <tr
68
- ref={ref}
44
+ data-slot="table-row"
69
45
  className={cn(
70
- "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
46
+ "hover:bg-muted/50 data-[state=selected]:bg-muted border-b transition-colors",
71
47
  className,
72
48
  )}
73
49
  {...props}
74
50
  />
75
- ),
76
- );
77
- TableRow.displayName = "TableRow";
51
+ );
52
+ }
78
53
 
79
- const TableHead = React.forwardRef<
80
- HTMLTableCellElement,
81
- React.ThHTMLAttributes<HTMLTableCellElement>
82
- >(({ className, ...props }, ref) => (
83
- <th
84
- ref={ref}
85
- className={cn(
86
- "h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
87
- className,
88
- )}
89
- {...props}
90
- />
91
- ));
92
- TableHead.displayName = "TableHead";
54
+ function TableHead({ className, ...props }: React.ComponentProps<"th">) {
55
+ return (
56
+ <th
57
+ data-slot="table-head"
58
+ className={cn(
59
+ "text-foreground h-10 px-2 text-left align-middle font-medium whitespace-nowrap [&:has([role=checkbox])]:pr-0",
60
+ className,
61
+ )}
62
+ {...props}
63
+ />
64
+ );
65
+ }
93
66
 
94
- const TableCell = React.forwardRef<
95
- HTMLTableCellElement,
96
- React.TdHTMLAttributes<HTMLTableCellElement>
97
- >(({ className, ...props }, ref) => (
98
- <td
99
- ref={ref}
100
- className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)}
101
- {...props}
102
- />
103
- ));
104
- TableCell.displayName = "TableCell";
67
+ function TableCell({ className, ...props }: React.ComponentProps<"td">) {
68
+ return (
69
+ <td
70
+ data-slot="table-cell"
71
+ className={cn("p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0", className)}
72
+ {...props}
73
+ />
74
+ );
75
+ }
105
76
 
106
- const TableCaption = React.forwardRef<
107
- HTMLTableCaptionElement,
108
- React.HTMLAttributes<HTMLTableCaptionElement>
109
- >(({ className, ...props }, ref) => (
110
- <caption ref={ref} className={cn("mt-4 text-sm text-muted-foreground", className)} {...props} />
111
- ));
112
- TableCaption.displayName = "TableCaption";
77
+ function TableCaption({ className, ...props }: React.ComponentProps<"caption">) {
78
+ return (
79
+ <caption
80
+ data-slot="table-caption"
81
+ className={cn("text-muted-foreground mt-4 text-sm", className)}
82
+ {...props}
83
+ />
84
+ );
85
+ }
113
86
 
114
87
  export { Table, TableHeader, TableBody, TableFooter, TableHead, TableRow, TableCell, TableCaption };