@majapisoftwares/ui 6.1.0 → 6.1.2
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/AGENTS.md +27 -27
- package/README.md +79 -79
- package/THIRD_PARTY_NOTICES.md +39 -39
- package/components.json +25 -25
- package/docs/MIGRATION-0.2.md +20 -20
- package/docs/MIGRATION-6.0.md +33 -33
- package/docs/NEXT-STARTER-VALIDATION.md +14 -14
- package/docs/STANDARDS.md +41 -41
- package/docs/VALIDATION.md +11 -11
- package/docs/VERSIONING.md +28 -28
- package/docs/validation/preference-titles.md +22 -0
- package/package.json +88 -84
- package/scripts/check-standards.mjs +41 -41
- package/src/components/ui/accordion.tsx +82 -82
- package/src/components/ui/alert-dialog.tsx +187 -187
- package/src/components/ui/alert.tsx +77 -77
- package/src/components/ui/avatar.tsx +108 -108
- package/src/components/ui/badge.tsx +55 -55
- package/src/components/ui/breadcrumb.tsx +125 -125
- package/src/components/ui/button-group.tsx +89 -89
- package/src/components/ui/button.tsx +59 -59
- package/src/components/ui/card.tsx +101 -101
- package/src/components/ui/checkbox.tsx +27 -27
- package/src/components/ui/collapsible.tsx +21 -21
- package/src/components/ui/context-menu.tsx +271 -271
- package/src/components/ui/dialog.tsx +161 -161
- package/src/components/ui/dropdown-menu.tsx +271 -271
- package/src/components/ui/empty.tsx +105 -105
- package/src/components/ui/field.tsx +238 -238
- package/src/components/ui/hover-card.tsx +50 -50
- package/src/components/ui/input-group.tsx +155 -155
- package/src/components/ui/input.tsx +21 -21
- package/src/components/ui/kbd.tsx +28 -28
- package/src/components/ui/label.tsx +19 -19
- package/src/components/ui/orb.css +1002 -1002
- package/src/components/ui/orb.tsx +752 -752
- package/src/components/ui/popover.tsx +89 -89
- package/src/components/ui/progress.tsx +82 -82
- package/src/components/ui/radio-group.tsx +37 -37
- package/src/components/ui/scroll-area.tsx +54 -54
- package/src/components/ui/select.tsx +204 -204
- package/src/components/ui/separator.tsx +24 -24
- package/src/components/ui/sheet.tsx +139 -139
- package/src/components/ui/sidebar.tsx +1039 -1035
- package/src/components/ui/skeleton.tsx +15 -15
- package/src/components/ui/slider.tsx +53 -53
- package/src/components/ui/sonner.tsx +44 -44
- package/src/components/ui/spinner.tsx +32 -32
- package/src/components/ui/switch.tsx +31 -31
- package/src/components/ui/table.tsx +121 -121
- package/src/components/ui/tabs.tsx +81 -81
- package/src/components/ui/textarea.tsx +19 -19
- package/src/components/ui/toggle-group.tsx +89 -89
- package/src/components/ui/toggle.tsx +44 -44
- package/src/components/ui/tooltip.tsx +65 -65
- package/src/hooks/use-mobile.ts +20 -20
- package/src/lib/i18n.tsx +109 -109
- package/src/lib/utils.ts +1 -1
- package/src/patterns/app-shell.tsx +177 -179
- package/src/patterns/data-table.tsx +2486 -2486
- package/src/patterns/details-sheet.tsx +54 -54
- package/src/patterns/filter-tabs.tsx +53 -53
- package/src/patterns/majapi-logo.tsx +32 -32
- package/src/patterns/page-header.tsx +62 -62
- package/src/patterns/preferences.tsx +15 -7
- package/src/patterns/status-badge.tsx +24 -24
- package/src/patterns/user-menu.tsx +218 -218
- package/src/patterns/workspace-switcher.tsx +176 -173
- package/src/styles.css +165 -165
- package/src/templates/admin-dashboard.tsx +44 -44
- package/src/templates/auth-layout.tsx +30 -30
- package/src/templates/login-form.tsx +129 -129
- package/src/templates/signup-form.tsx +177 -177
|
@@ -1,15 +1,15 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { cn } from "cn";
|
|
4
|
-
|
|
5
|
-
function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
|
|
6
|
-
return (
|
|
7
|
-
<div
|
|
8
|
-
data-slot="skeleton"
|
|
9
|
-
className={cn("animate-pulse rounded-2xl bg-muted", className)}
|
|
10
|
-
{...props}
|
|
11
|
-
/>
|
|
12
|
-
);
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export { Skeleton };
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { cn } from "cn";
|
|
4
|
+
|
|
5
|
+
function Skeleton({ className, ...props }: React.ComponentProps<"div">) {
|
|
6
|
+
return (
|
|
7
|
+
<div
|
|
8
|
+
data-slot="skeleton"
|
|
9
|
+
className={cn("animate-pulse rounded-2xl bg-muted", className)}
|
|
10
|
+
{...props}
|
|
11
|
+
/>
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { Skeleton };
|
|
@@ -1,53 +1,53 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { Slider as SliderPrimitive } from "@base-ui/react/slider";
|
|
4
|
-
import { cn } from "cn";
|
|
5
|
-
|
|
6
|
-
function Slider({
|
|
7
|
-
className,
|
|
8
|
-
defaultValue,
|
|
9
|
-
value,
|
|
10
|
-
min = 0,
|
|
11
|
-
max = 100,
|
|
12
|
-
...props
|
|
13
|
-
}: SliderPrimitive.Root.Props) {
|
|
14
|
-
const _values = Array.isArray(value)
|
|
15
|
-
? value
|
|
16
|
-
: Array.isArray(defaultValue)
|
|
17
|
-
? defaultValue
|
|
18
|
-
: [min, max];
|
|
19
|
-
|
|
20
|
-
return (
|
|
21
|
-
<SliderPrimitive.Root
|
|
22
|
-
className={cn("data-horizontal:w-full data-vertical:h-full", className)}
|
|
23
|
-
data-slot="slider"
|
|
24
|
-
defaultValue={defaultValue}
|
|
25
|
-
value={value}
|
|
26
|
-
min={min}
|
|
27
|
-
max={max}
|
|
28
|
-
thumbAlignment="edge"
|
|
29
|
-
{...props}
|
|
30
|
-
>
|
|
31
|
-
<SliderPrimitive.Control className="relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-vertical:h-full data-vertical:min-h-40 data-vertical:w-auto data-vertical:flex-col">
|
|
32
|
-
<SliderPrimitive.Track
|
|
33
|
-
data-slot="slider-track"
|
|
34
|
-
className="relative grow overflow-hidden rounded-full bg-input/90 select-none data-horizontal:h-2 data-horizontal:w-full data-vertical:h-full data-vertical:w-2"
|
|
35
|
-
>
|
|
36
|
-
<SliderPrimitive.Indicator
|
|
37
|
-
data-slot="slider-range"
|
|
38
|
-
className="bg-primary select-none data-horizontal:h-full data-vertical:w-full"
|
|
39
|
-
/>
|
|
40
|
-
</SliderPrimitive.Track>
|
|
41
|
-
{Array.from({ length: _values.length }, (_, index) => (
|
|
42
|
-
<SliderPrimitive.Thumb
|
|
43
|
-
data-slot="slider-thumb"
|
|
44
|
-
key={index}
|
|
45
|
-
className="block h-4 w-6 shrink-0 rounded-full bg-white shadow-md ring-1 ring-black/10 transition-[color,box-shadow,background-color] select-none not-dark:bg-clip-padding hover:ring-4 hover:ring-ring/30 focus-visible:ring-4 focus-visible:ring-ring/30 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50 data-vertical:h-6 data-vertical:w-4"
|
|
46
|
-
/>
|
|
47
|
-
))}
|
|
48
|
-
</SliderPrimitive.Control>
|
|
49
|
-
</SliderPrimitive.Root>
|
|
50
|
-
);
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
export { Slider };
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Slider as SliderPrimitive } from "@base-ui/react/slider";
|
|
4
|
+
import { cn } from "cn";
|
|
5
|
+
|
|
6
|
+
function Slider({
|
|
7
|
+
className,
|
|
8
|
+
defaultValue,
|
|
9
|
+
value,
|
|
10
|
+
min = 0,
|
|
11
|
+
max = 100,
|
|
12
|
+
...props
|
|
13
|
+
}: SliderPrimitive.Root.Props) {
|
|
14
|
+
const _values = Array.isArray(value)
|
|
15
|
+
? value
|
|
16
|
+
: Array.isArray(defaultValue)
|
|
17
|
+
? defaultValue
|
|
18
|
+
: [min, max];
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<SliderPrimitive.Root
|
|
22
|
+
className={cn("data-horizontal:w-full data-vertical:h-full", className)}
|
|
23
|
+
data-slot="slider"
|
|
24
|
+
defaultValue={defaultValue}
|
|
25
|
+
value={value}
|
|
26
|
+
min={min}
|
|
27
|
+
max={max}
|
|
28
|
+
thumbAlignment="edge"
|
|
29
|
+
{...props}
|
|
30
|
+
>
|
|
31
|
+
<SliderPrimitive.Control className="relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-vertical:h-full data-vertical:min-h-40 data-vertical:w-auto data-vertical:flex-col">
|
|
32
|
+
<SliderPrimitive.Track
|
|
33
|
+
data-slot="slider-track"
|
|
34
|
+
className="relative grow overflow-hidden rounded-full bg-input/90 select-none data-horizontal:h-2 data-horizontal:w-full data-vertical:h-full data-vertical:w-2"
|
|
35
|
+
>
|
|
36
|
+
<SliderPrimitive.Indicator
|
|
37
|
+
data-slot="slider-range"
|
|
38
|
+
className="bg-primary select-none data-horizontal:h-full data-vertical:w-full"
|
|
39
|
+
/>
|
|
40
|
+
</SliderPrimitive.Track>
|
|
41
|
+
{Array.from({ length: _values.length }, (_, index) => (
|
|
42
|
+
<SliderPrimitive.Thumb
|
|
43
|
+
data-slot="slider-thumb"
|
|
44
|
+
key={index}
|
|
45
|
+
className="block h-4 w-6 shrink-0 rounded-full bg-white shadow-md ring-1 ring-black/10 transition-[color,box-shadow,background-color] select-none not-dark:bg-clip-padding hover:ring-4 hover:ring-ring/30 focus-visible:ring-4 focus-visible:ring-ring/30 focus-visible:outline-hidden disabled:pointer-events-none disabled:opacity-50 data-vertical:h-6 data-vertical:w-4"
|
|
46
|
+
/>
|
|
47
|
+
))}
|
|
48
|
+
</SliderPrimitive.Control>
|
|
49
|
+
</SliderPrimitive.Root>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { Slider };
|
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { Orb } from "./orb";
|
|
4
|
-
import { Toaster as Sonner, type ToasterProps } from "sonner";
|
|
5
|
-
import {
|
|
6
|
-
CircleCheckIcon,
|
|
7
|
-
InfoIcon,
|
|
8
|
-
TriangleAlertIcon,
|
|
9
|
-
OctagonXIcon,
|
|
10
|
-
} from "lucide-react";
|
|
11
|
-
|
|
12
|
-
// Theme comes from the caller (Preferences passes the active theme).
|
|
13
|
-
const Toaster = ({ theme = "system", ...props }: ToasterProps) => {
|
|
14
|
-
return (
|
|
15
|
-
<Sonner
|
|
16
|
-
theme={theme}
|
|
17
|
-
className="toaster group"
|
|
18
|
-
icons={{
|
|
19
|
-
success: <CircleCheckIcon className="size-4" />,
|
|
20
|
-
info: <InfoIcon className="size-4" />,
|
|
21
|
-
warning: <TriangleAlertIcon className="size-4" />,
|
|
22
|
-
error: <OctagonXIcon className="size-4" />,
|
|
23
|
-
loading: <Orb size={16} />,
|
|
24
|
-
}}
|
|
25
|
-
style={
|
|
26
|
-
{
|
|
27
|
-
"--normal-bg": "var(--popover)",
|
|
28
|
-
"--normal-text": "var(--popover-foreground)",
|
|
29
|
-
"--normal-border": "var(--border)",
|
|
30
|
-
"--border-radius": "var(--radius)",
|
|
31
|
-
} as React.CSSProperties
|
|
32
|
-
}
|
|
33
|
-
toastOptions={{
|
|
34
|
-
classNames: {
|
|
35
|
-
toast: "cn-toast",
|
|
36
|
-
},
|
|
37
|
-
}}
|
|
38
|
-
{...props}
|
|
39
|
-
/>
|
|
40
|
-
);
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export { Toaster };
|
|
44
|
-
export { toast } from "sonner";
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Orb } from "./orb";
|
|
4
|
+
import { Toaster as Sonner, type ToasterProps } from "sonner";
|
|
5
|
+
import {
|
|
6
|
+
CircleCheckIcon,
|
|
7
|
+
InfoIcon,
|
|
8
|
+
TriangleAlertIcon,
|
|
9
|
+
OctagonXIcon,
|
|
10
|
+
} from "lucide-react";
|
|
11
|
+
|
|
12
|
+
// Theme comes from the caller (Preferences passes the active theme).
|
|
13
|
+
const Toaster = ({ theme = "system", ...props }: ToasterProps) => {
|
|
14
|
+
return (
|
|
15
|
+
<Sonner
|
|
16
|
+
theme={theme}
|
|
17
|
+
className="toaster group"
|
|
18
|
+
icons={{
|
|
19
|
+
success: <CircleCheckIcon className="size-4" />,
|
|
20
|
+
info: <InfoIcon className="size-4" />,
|
|
21
|
+
warning: <TriangleAlertIcon className="size-4" />,
|
|
22
|
+
error: <OctagonXIcon className="size-4" />,
|
|
23
|
+
loading: <Orb size={16} />,
|
|
24
|
+
}}
|
|
25
|
+
style={
|
|
26
|
+
{
|
|
27
|
+
"--normal-bg": "var(--popover)",
|
|
28
|
+
"--normal-text": "var(--popover-foreground)",
|
|
29
|
+
"--normal-border": "var(--border)",
|
|
30
|
+
"--border-radius": "var(--radius)",
|
|
31
|
+
} as React.CSSProperties
|
|
32
|
+
}
|
|
33
|
+
toastOptions={{
|
|
34
|
+
classNames: {
|
|
35
|
+
toast: "cn-toast",
|
|
36
|
+
},
|
|
37
|
+
}}
|
|
38
|
+
{...props}
|
|
39
|
+
/>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export { Toaster };
|
|
44
|
+
export { toast } from "sonner";
|
|
@@ -1,32 +1,32 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import type * as React from "react";
|
|
4
|
-
import { cn } from "cn";
|
|
5
|
-
import { Orb, type OrbVariant } from "./orb";
|
|
6
|
-
import { useUiMessages } from "../../lib/i18n";
|
|
7
|
-
|
|
8
|
-
// Majapi UI: loading uses the animated Orb instead of a rotating icon.
|
|
9
|
-
function Spinner({
|
|
10
|
-
className,
|
|
11
|
-
size = 16,
|
|
12
|
-
variant = "S1",
|
|
13
|
-
label,
|
|
14
|
-
...props
|
|
15
|
-
}: React.ComponentProps<"span"> & {
|
|
16
|
-
size?: number;
|
|
17
|
-
variant?: OrbVariant;
|
|
18
|
-
label?: string;
|
|
19
|
-
}) {
|
|
20
|
-
const messages = useUiMessages();
|
|
21
|
-
return (
|
|
22
|
-
<span
|
|
23
|
-
data-slot="spinner"
|
|
24
|
-
className={cn("inline-flex shrink-0", className)}
|
|
25
|
-
{...props}
|
|
26
|
-
>
|
|
27
|
-
<Orb variant={variant} size={size} label={label ?? messages.loading} />
|
|
28
|
-
</span>
|
|
29
|
-
);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export { Spinner };
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type * as React from "react";
|
|
4
|
+
import { cn } from "cn";
|
|
5
|
+
import { Orb, type OrbVariant } from "./orb";
|
|
6
|
+
import { useUiMessages } from "../../lib/i18n";
|
|
7
|
+
|
|
8
|
+
// Majapi UI: loading uses the animated Orb instead of a rotating icon.
|
|
9
|
+
function Spinner({
|
|
10
|
+
className,
|
|
11
|
+
size = 16,
|
|
12
|
+
variant = "S1",
|
|
13
|
+
label,
|
|
14
|
+
...props
|
|
15
|
+
}: React.ComponentProps<"span"> & {
|
|
16
|
+
size?: number;
|
|
17
|
+
variant?: OrbVariant;
|
|
18
|
+
label?: string;
|
|
19
|
+
}) {
|
|
20
|
+
const messages = useUiMessages();
|
|
21
|
+
return (
|
|
22
|
+
<span
|
|
23
|
+
data-slot="spinner"
|
|
24
|
+
className={cn("inline-flex shrink-0", className)}
|
|
25
|
+
{...props}
|
|
26
|
+
>
|
|
27
|
+
<Orb variant={variant} size={size} label={label ?? messages.loading} />
|
|
28
|
+
</span>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export { Spinner };
|
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import { Switch as SwitchPrimitive } from "@base-ui/react/switch";
|
|
4
|
-
import { cn } from "cn";
|
|
5
|
-
|
|
6
|
-
function Switch({
|
|
7
|
-
className,
|
|
8
|
-
size = "default",
|
|
9
|
-
...props
|
|
10
|
-
}: SwitchPrimitive.Root.Props & {
|
|
11
|
-
size?: "sm" | "default";
|
|
12
|
-
}) {
|
|
13
|
-
return (
|
|
14
|
-
<SwitchPrimitive.Root
|
|
15
|
-
data-slot="switch"
|
|
16
|
-
data-size={size}
|
|
17
|
-
className={cn(
|
|
18
|
-
"peer group/switch relative inline-flex shrink-0 items-center rounded-full border-2 transition-all outline-none group-has-[:focus-visible]/field-label:ring-0 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/30 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-[size=default]:h-5 data-[size=default]:w-11 data-[size=sm]:h-4 data-[size=sm]:w-7 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary group-has-[:focus-visible]/field-label:data-checked:border-primary data-unchecked:border-transparent data-unchecked:bg-input/90 group-has-[:focus-visible]/field-label:data-unchecked:border-transparent data-disabled:cursor-not-allowed data-disabled:opacity-50",
|
|
19
|
-
className,
|
|
20
|
-
)}
|
|
21
|
-
{...props}
|
|
22
|
-
>
|
|
23
|
-
<SwitchPrimitive.Thumb
|
|
24
|
-
data-slot="switch-thumb"
|
|
25
|
-
className="pointer-events-none block rounded-full bg-background shadow-sm ring-0 transition-transform not-dark:bg-clip-padding group-data-[size=default]/switch:h-4 group-data-[size=default]/switch:w-6 group-data-[size=sm]/switch:h-3 group-data-[size=sm]/switch:w-4 data-checked:translate-x-[calc(100%-8px)] dark:data-checked:bg-primary-foreground data-unchecked:translate-x-0 dark:data-unchecked:bg-foreground"
|
|
26
|
-
/>
|
|
27
|
-
</SwitchPrimitive.Root>
|
|
28
|
-
);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export { Switch };
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { Switch as SwitchPrimitive } from "@base-ui/react/switch";
|
|
4
|
+
import { cn } from "cn";
|
|
5
|
+
|
|
6
|
+
function Switch({
|
|
7
|
+
className,
|
|
8
|
+
size = "default",
|
|
9
|
+
...props
|
|
10
|
+
}: SwitchPrimitive.Root.Props & {
|
|
11
|
+
size?: "sm" | "default";
|
|
12
|
+
}) {
|
|
13
|
+
return (
|
|
14
|
+
<SwitchPrimitive.Root
|
|
15
|
+
data-slot="switch"
|
|
16
|
+
data-size={size}
|
|
17
|
+
className={cn(
|
|
18
|
+
"peer group/switch relative inline-flex shrink-0 items-center rounded-full border-2 transition-all outline-none group-has-[:focus-visible]/field-label:ring-0 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/30 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-[size=default]:h-5 data-[size=default]:w-11 data-[size=sm]:h-4 data-[size=sm]:w-7 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary group-has-[:focus-visible]/field-label:data-checked:border-primary data-unchecked:border-transparent data-unchecked:bg-input/90 group-has-[:focus-visible]/field-label:data-unchecked:border-transparent data-disabled:cursor-not-allowed data-disabled:opacity-50",
|
|
19
|
+
className,
|
|
20
|
+
)}
|
|
21
|
+
{...props}
|
|
22
|
+
>
|
|
23
|
+
<SwitchPrimitive.Thumb
|
|
24
|
+
data-slot="switch-thumb"
|
|
25
|
+
className="pointer-events-none block rounded-full bg-background shadow-sm ring-0 transition-transform not-dark:bg-clip-padding group-data-[size=default]/switch:h-4 group-data-[size=default]/switch:w-6 group-data-[size=sm]/switch:h-3 group-data-[size=sm]/switch:w-4 data-checked:translate-x-[calc(100%-8px)] dark:data-checked:bg-primary-foreground data-unchecked:translate-x-0 dark:data-unchecked:bg-foreground"
|
|
26
|
+
/>
|
|
27
|
+
</SwitchPrimitive.Root>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { Switch };
|
|
@@ -1,121 +1,121 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import { cn } from "cn";
|
|
5
|
-
|
|
6
|
-
// Majapi UI: `containerClassName` styles the scroll container (e.g. to fill
|
|
7
|
-
// the available height and scroll vertically).
|
|
8
|
-
function Table({
|
|
9
|
-
className,
|
|
10
|
-
containerClassName,
|
|
11
|
-
...props
|
|
12
|
-
}: React.ComponentProps<"table"> & { containerClassName?: string }) {
|
|
13
|
-
return (
|
|
14
|
-
<div
|
|
15
|
-
data-slot="table-container"
|
|
16
|
-
className={cn("relative w-full overflow-x-auto", containerClassName)}
|
|
17
|
-
>
|
|
18
|
-
<table
|
|
19
|
-
data-slot="table"
|
|
20
|
-
className={cn("w-full caption-bottom text-sm", className)}
|
|
21
|
-
{...props}
|
|
22
|
-
/>
|
|
23
|
-
</div>
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
|
|
28
|
-
return (
|
|
29
|
-
<thead
|
|
30
|
-
data-slot="table-header"
|
|
31
|
-
className={cn("[&_tr]:border-b", className)}
|
|
32
|
-
{...props}
|
|
33
|
-
/>
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
|
|
38
|
-
return (
|
|
39
|
-
<tbody
|
|
40
|
-
data-slot="table-body"
|
|
41
|
-
className={cn("[&_tr:last-child]:border-0", className)}
|
|
42
|
-
{...props}
|
|
43
|
-
/>
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
|
|
48
|
-
return (
|
|
49
|
-
<tfoot
|
|
50
|
-
data-slot="table-footer"
|
|
51
|
-
className={cn(
|
|
52
|
-
"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
|
|
53
|
-
className,
|
|
54
|
-
)}
|
|
55
|
-
{...props}
|
|
56
|
-
/>
|
|
57
|
-
);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
|
|
61
|
-
return (
|
|
62
|
-
<tr
|
|
63
|
-
data-slot="table-row"
|
|
64
|
-
className={cn(
|
|
65
|
-
"border-b transition-colors hover:bg-muted/50 has-aria-expanded:bg-muted/50 data-[state=selected]:bg-muted",
|
|
66
|
-
className,
|
|
67
|
-
)}
|
|
68
|
-
{...props}
|
|
69
|
-
/>
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
function TableHead({ className, ...props }: React.ComponentProps<"th">) {
|
|
74
|
-
return (
|
|
75
|
-
<th
|
|
76
|
-
data-slot="table-head"
|
|
77
|
-
className={cn(
|
|
78
|
-
"h-12 px-3 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0",
|
|
79
|
-
className,
|
|
80
|
-
)}
|
|
81
|
-
{...props}
|
|
82
|
-
/>
|
|
83
|
-
);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
function TableCell({ className, ...props }: React.ComponentProps<"td">) {
|
|
87
|
-
return (
|
|
88
|
-
<td
|
|
89
|
-
data-slot="table-cell"
|
|
90
|
-
className={cn(
|
|
91
|
-
"p-3 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0",
|
|
92
|
-
className,
|
|
93
|
-
)}
|
|
94
|
-
{...props}
|
|
95
|
-
/>
|
|
96
|
-
);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function TableCaption({
|
|
100
|
-
className,
|
|
101
|
-
...props
|
|
102
|
-
}: React.ComponentProps<"caption">) {
|
|
103
|
-
return (
|
|
104
|
-
<caption
|
|
105
|
-
data-slot="table-caption"
|
|
106
|
-
className={cn("mt-4 text-sm text-muted-foreground", className)}
|
|
107
|
-
{...props}
|
|
108
|
-
/>
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
export {
|
|
113
|
-
Table,
|
|
114
|
-
TableHeader,
|
|
115
|
-
TableBody,
|
|
116
|
-
TableFooter,
|
|
117
|
-
TableHead,
|
|
118
|
-
TableRow,
|
|
119
|
-
TableCell,
|
|
120
|
-
TableCaption,
|
|
121
|
-
};
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "cn";
|
|
5
|
+
|
|
6
|
+
// Majapi UI: `containerClassName` styles the scroll container (e.g. to fill
|
|
7
|
+
// the available height and scroll vertically).
|
|
8
|
+
function Table({
|
|
9
|
+
className,
|
|
10
|
+
containerClassName,
|
|
11
|
+
...props
|
|
12
|
+
}: React.ComponentProps<"table"> & { containerClassName?: string }) {
|
|
13
|
+
return (
|
|
14
|
+
<div
|
|
15
|
+
data-slot="table-container"
|
|
16
|
+
className={cn("relative w-full overflow-x-auto", containerClassName)}
|
|
17
|
+
>
|
|
18
|
+
<table
|
|
19
|
+
data-slot="table"
|
|
20
|
+
className={cn("w-full caption-bottom text-sm", className)}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
</div>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function TableHeader({ className, ...props }: React.ComponentProps<"thead">) {
|
|
28
|
+
return (
|
|
29
|
+
<thead
|
|
30
|
+
data-slot="table-header"
|
|
31
|
+
className={cn("[&_tr]:border-b", className)}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
|
|
38
|
+
return (
|
|
39
|
+
<tbody
|
|
40
|
+
data-slot="table-body"
|
|
41
|
+
className={cn("[&_tr:last-child]:border-0", className)}
|
|
42
|
+
{...props}
|
|
43
|
+
/>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function TableFooter({ className, ...props }: React.ComponentProps<"tfoot">) {
|
|
48
|
+
return (
|
|
49
|
+
<tfoot
|
|
50
|
+
data-slot="table-footer"
|
|
51
|
+
className={cn(
|
|
52
|
+
"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
|
|
53
|
+
className,
|
|
54
|
+
)}
|
|
55
|
+
{...props}
|
|
56
|
+
/>
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
|
|
61
|
+
return (
|
|
62
|
+
<tr
|
|
63
|
+
data-slot="table-row"
|
|
64
|
+
className={cn(
|
|
65
|
+
"border-b transition-colors hover:bg-muted/50 has-aria-expanded:bg-muted/50 data-[state=selected]:bg-muted",
|
|
66
|
+
className,
|
|
67
|
+
)}
|
|
68
|
+
{...props}
|
|
69
|
+
/>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function TableHead({ className, ...props }: React.ComponentProps<"th">) {
|
|
74
|
+
return (
|
|
75
|
+
<th
|
|
76
|
+
data-slot="table-head"
|
|
77
|
+
className={cn(
|
|
78
|
+
"h-12 px-3 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0",
|
|
79
|
+
className,
|
|
80
|
+
)}
|
|
81
|
+
{...props}
|
|
82
|
+
/>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function TableCell({ className, ...props }: React.ComponentProps<"td">) {
|
|
87
|
+
return (
|
|
88
|
+
<td
|
|
89
|
+
data-slot="table-cell"
|
|
90
|
+
className={cn(
|
|
91
|
+
"p-3 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0",
|
|
92
|
+
className,
|
|
93
|
+
)}
|
|
94
|
+
{...props}
|
|
95
|
+
/>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function TableCaption({
|
|
100
|
+
className,
|
|
101
|
+
...props
|
|
102
|
+
}: React.ComponentProps<"caption">) {
|
|
103
|
+
return (
|
|
104
|
+
<caption
|
|
105
|
+
data-slot="table-caption"
|
|
106
|
+
className={cn("mt-4 text-sm text-muted-foreground", className)}
|
|
107
|
+
{...props}
|
|
108
|
+
/>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export {
|
|
113
|
+
Table,
|
|
114
|
+
TableHeader,
|
|
115
|
+
TableBody,
|
|
116
|
+
TableFooter,
|
|
117
|
+
TableHead,
|
|
118
|
+
TableRow,
|
|
119
|
+
TableCell,
|
|
120
|
+
TableCaption,
|
|
121
|
+
};
|