@bccampus/ui-components 0.9.17 → 0.9.18
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/dist/components/ui/banner.js +3 -3
- package/dist/components/ui/horizontal-list.js +1 -1
- package/dist/components/ui/page-section.js +1 -1
- package/package.json +6 -6
- package/src/components/ui/banner.tsx +91 -90
- package/src/components/ui/horizontal-list.tsx +84 -84
- package/src/components/ui/page-section.tsx +39 -39
- package/src/styles/theme.css +186 -184
|
@@ -28,7 +28,7 @@ const __iconNode = [
|
|
|
28
28
|
["path", { d: "m6 6 12 12", key: "d8bk6v" }]
|
|
29
29
|
];
|
|
30
30
|
const X = createLucideIcon("x", __iconNode);
|
|
31
|
-
const bannerVariants = cva("flex flex-row items-start justify-between px-(--spacing-section) text-sm", {
|
|
31
|
+
const bannerVariants = cva("flex flex-row gap-2 items-start justify-between px-(--spacing-section) text-sm", {
|
|
32
32
|
variants: {
|
|
33
33
|
variant: {
|
|
34
34
|
default: "bg-complement-3 text-white dark:text-white",
|
|
@@ -74,11 +74,11 @@ function Banner({
|
|
|
74
74
|
/* @__PURE__ */ jsxs(
|
|
75
75
|
"div",
|
|
76
76
|
{
|
|
77
|
-
className: cn("flex-auto flex flex-col justify-center items-center", {
|
|
77
|
+
className: cn("flex-auto flex flex-col gap-1 justify-center items-center", {
|
|
78
78
|
"items-start": children
|
|
79
79
|
}),
|
|
80
80
|
children: [
|
|
81
|
-
/* @__PURE__ */ jsxs("div", { className: "flex-
|
|
81
|
+
/* @__PURE__ */ jsxs("div", { className: "flex gap-2 justify-center items-center", children: [
|
|
82
82
|
variant === "alert" ? /* @__PURE__ */ jsx(TriangleAlert, { className: "size-5" }) : /* @__PURE__ */ jsx(Info, { className: "size-5" }),
|
|
83
83
|
/* @__PURE__ */ jsx("div", { className: cn({ "text-md font-semibold": size === "lg" }), dangerouslySetInnerHTML: { __html: title } })
|
|
84
84
|
] }),
|
|
@@ -14,7 +14,7 @@ const horizontalListVariants = cva(
|
|
|
14
14
|
variants: {
|
|
15
15
|
variant: {
|
|
16
16
|
contain: "w-full",
|
|
17
|
-
overflow: "w-screen px-section -ms-section scroll-px-section
|
|
17
|
+
overflow: "w-screen px-section -ms-section scroll-px-section clamp:px-clamp clamp:-ms-clamp clamp:scroll-px-clamp"
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
defaultVariants: {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bccampus/ui-components",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.18",
|
|
4
4
|
"description": "BCcampus React components",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@radix-ui/react-slot": "^1.2.4",
|
|
45
45
|
"class-variance-authority": "^0.7.1",
|
|
46
46
|
"clsx": "^2.1.1",
|
|
47
|
-
"lucide-react": "^0.
|
|
47
|
+
"lucide-react": "^0.577.0",
|
|
48
48
|
"nanostores": "^1.1.1",
|
|
49
49
|
"react": "^19.2.4",
|
|
50
50
|
"react-dom": "^19.2.4",
|
|
@@ -53,21 +53,21 @@
|
|
|
53
53
|
"tw-animate-css": "^1.4.0"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@eslint/js": "^9.39.
|
|
56
|
+
"@eslint/js": "^9.39.4",
|
|
57
57
|
"@ladle/react": "^5.1.1",
|
|
58
58
|
"@tailwindcss/vite": "^4.2.1",
|
|
59
|
-
"@types/node": "^24.
|
|
59
|
+
"@types/node": "^24.12.0",
|
|
60
60
|
"@types/react": "^19.2.14",
|
|
61
61
|
"@types/react-dom": "^19.2.3",
|
|
62
62
|
"@vitejs/plugin-react-swc": "^4.2.3",
|
|
63
63
|
"baseline-browser-mapping": "^2.10.0",
|
|
64
|
-
"eslint": "^9.39.
|
|
64
|
+
"eslint": "^9.39.4",
|
|
65
65
|
"eslint-plugin-react-hooks": "^7.0.1",
|
|
66
66
|
"eslint-plugin-react-refresh": "^0.5.2",
|
|
67
67
|
"glob": "^13.0.6",
|
|
68
68
|
"globals": "^17.4.0",
|
|
69
69
|
"typescript": "~5.9.3",
|
|
70
|
-
"typescript-eslint": "^8.
|
|
70
|
+
"typescript-eslint": "^8.57.0",
|
|
71
71
|
"vite": "^7.3.1",
|
|
72
72
|
"vite-plugin-dts": "^4.5.4"
|
|
73
73
|
}
|
|
@@ -1,90 +1,91 @@
|
|
|
1
|
-
import { cva, type VariantProps } from "class-variance-authority";
|
|
2
|
-
import { cn } from "@/lib/utils";
|
|
3
|
-
import { useCallback, useState } from "react";
|
|
4
|
-
import { Button } from "./button";
|
|
5
|
-
import { Info, TriangleAlert, X } from "lucide-react";
|
|
6
|
-
import { PageSection } from "./page-section";
|
|
7
|
-
|
|
8
|
-
export type BannerVariantsProps = VariantProps<typeof bannerVariants>;
|
|
9
|
-
export const bannerVariants = cva("flex flex-row items-start justify-between px-(--spacing-section) text-sm", {
|
|
10
|
-
variants: {
|
|
11
|
-
variant: {
|
|
12
|
-
default: "bg-complement-3 text-white dark:text-white",
|
|
13
|
-
alert: "bg-complement-2 text-black dark:text-black",
|
|
14
|
-
},
|
|
15
|
-
size: {
|
|
16
|
-
default: "py-2",
|
|
17
|
-
sm: "py-1",
|
|
18
|
-
lg: "py-3",
|
|
19
|
-
},
|
|
20
|
-
},
|
|
21
|
-
defaultVariants: {
|
|
22
|
-
variant: "default",
|
|
23
|
-
size: "default",
|
|
24
|
-
},
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
export interface BannerProps extends React.ComponentProps<"div">, BannerVariantsProps {
|
|
28
|
-
id: string;
|
|
29
|
-
title: string;
|
|
30
|
-
dismissible?: boolean;
|
|
31
|
-
onDismiss?: (id: string) => void;
|
|
32
|
-
}
|
|
33
|
-
export function Banner({
|
|
34
|
-
className,
|
|
35
|
-
size,
|
|
36
|
-
variant,
|
|
37
|
-
dismissible,
|
|
38
|
-
onDismiss,
|
|
39
|
-
id,
|
|
40
|
-
title,
|
|
41
|
-
children,
|
|
42
|
-
...props
|
|
43
|
-
}: BannerProps) {
|
|
44
|
-
const [dismissed, setDismissed] = useState(false);
|
|
45
|
-
|
|
46
|
-
const dismiss = useCallback(() => {
|
|
47
|
-
setDismissed(true);
|
|
48
|
-
onDismiss?.(id);
|
|
49
|
-
}, [id, onDismiss]);
|
|
50
|
-
|
|
51
|
-
if (dismissed) return null;
|
|
52
|
-
|
|
53
|
-
return (
|
|
54
|
-
<PageSection
|
|
55
|
-
py="none"
|
|
56
|
-
data-slot="banner"
|
|
57
|
-
id={`announcement-${id}`}
|
|
58
|
-
className={cn(bannerVariants({ variant, size }), className)}
|
|
59
|
-
{...props}
|
|
60
|
-
>
|
|
61
|
-
<div
|
|
62
|
-
className={cn("flex-auto flex flex-col justify-center items-center", {
|
|
63
|
-
"items-start": children,
|
|
64
|
-
})}
|
|
65
|
-
>
|
|
66
|
-
<div className="flex-
|
|
67
|
-
{variant === "alert" ? <TriangleAlert className="size-5" /> : <Info className="size-5" />}
|
|
68
|
-
<div className={cn({ "text-md font-semibold": size === "lg" })} dangerouslySetInnerHTML={{ __html: title }} />
|
|
69
|
-
</div>
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
"text-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
1
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
import { useCallback, useState } from "react";
|
|
4
|
+
import { Button } from "./button";
|
|
5
|
+
import { Info, TriangleAlert, X } from "lucide-react";
|
|
6
|
+
import { PageSection } from "./page-section";
|
|
7
|
+
|
|
8
|
+
export type BannerVariantsProps = VariantProps<typeof bannerVariants>;
|
|
9
|
+
export const bannerVariants = cva("flex flex-row gap-2 items-start justify-between px-(--spacing-section) text-sm", {
|
|
10
|
+
variants: {
|
|
11
|
+
variant: {
|
|
12
|
+
default: "bg-complement-3 text-white dark:text-white",
|
|
13
|
+
alert: "bg-complement-2 text-black dark:text-black",
|
|
14
|
+
},
|
|
15
|
+
size: {
|
|
16
|
+
default: "py-2",
|
|
17
|
+
sm: "py-1",
|
|
18
|
+
lg: "py-3",
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
defaultVariants: {
|
|
22
|
+
variant: "default",
|
|
23
|
+
size: "default",
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export interface BannerProps extends React.ComponentProps<"div">, BannerVariantsProps {
|
|
28
|
+
id: string;
|
|
29
|
+
title: string;
|
|
30
|
+
dismissible?: boolean;
|
|
31
|
+
onDismiss?: (id: string) => void;
|
|
32
|
+
}
|
|
33
|
+
export function Banner({
|
|
34
|
+
className,
|
|
35
|
+
size,
|
|
36
|
+
variant,
|
|
37
|
+
dismissible,
|
|
38
|
+
onDismiss,
|
|
39
|
+
id,
|
|
40
|
+
title,
|
|
41
|
+
children,
|
|
42
|
+
...props
|
|
43
|
+
}: BannerProps) {
|
|
44
|
+
const [dismissed, setDismissed] = useState(false);
|
|
45
|
+
|
|
46
|
+
const dismiss = useCallback(() => {
|
|
47
|
+
setDismissed(true);
|
|
48
|
+
onDismiss?.(id);
|
|
49
|
+
}, [id, onDismiss]);
|
|
50
|
+
|
|
51
|
+
if (dismissed) return null;
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<PageSection
|
|
55
|
+
py="none"
|
|
56
|
+
data-slot="banner"
|
|
57
|
+
id={`announcement-${id}`}
|
|
58
|
+
className={cn(bannerVariants({ variant, size }), className)}
|
|
59
|
+
{...props}
|
|
60
|
+
>
|
|
61
|
+
<div
|
|
62
|
+
className={cn("flex-auto flex flex-col gap-1 justify-center items-center", {
|
|
63
|
+
"items-start": children,
|
|
64
|
+
})}
|
|
65
|
+
>
|
|
66
|
+
<div className="flex gap-2 justify-center items-center">
|
|
67
|
+
{variant === "alert" ? <TriangleAlert className="size-5" /> : <Info className="size-5" />}
|
|
68
|
+
<div className={cn({ "text-md font-semibold": size === "lg" })} dangerouslySetInnerHTML={{ __html: title }} />
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
{children && <div className="pl-7" dangerouslySetInnerHTML={{ __html: children }} />}
|
|
72
|
+
</div>
|
|
73
|
+
{dismissible && (
|
|
74
|
+
<div>
|
|
75
|
+
<Button
|
|
76
|
+
variant="ghost"
|
|
77
|
+
icon
|
|
78
|
+
size="icon"
|
|
79
|
+
className={cn("size-6", {
|
|
80
|
+
"text-white dark:text-white": !variant || variant === "default",
|
|
81
|
+
"text-black dark:text-black": variant === "alert",
|
|
82
|
+
})}
|
|
83
|
+
onClick={dismiss}
|
|
84
|
+
>
|
|
85
|
+
<X />
|
|
86
|
+
</Button>
|
|
87
|
+
</div>
|
|
88
|
+
)}
|
|
89
|
+
</PageSection>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
@@ -1,84 +1,84 @@
|
|
|
1
|
-
import { cn } from "@/lib/utils";
|
|
2
|
-
import { Button } from "./button";
|
|
3
|
-
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
4
|
-
import { useCallback, useEffect, useRef, useState } from "react";
|
|
5
|
-
import { cva, type VariantProps } from "class-variance-authority";
|
|
6
|
-
|
|
7
|
-
export type HorizontalListVariantsProps = VariantProps<typeof horizontalListVariants>;
|
|
8
|
-
export const horizontalListVariants = cva(
|
|
9
|
-
"py-1 scrollbar-hidden overscroll-x-contain overflow-x-auto snap-start snap-mandatory scroll-smooth *:shrink-0 *:grow-0 *:snap-center *:select-none",
|
|
10
|
-
{
|
|
11
|
-
variants: {
|
|
12
|
-
variant: {
|
|
13
|
-
contain: "w-full",
|
|
14
|
-
overflow:
|
|
15
|
-
"w-screen px-section -ms-section scroll-px-section
|
|
16
|
-
},
|
|
17
|
-
},
|
|
18
|
-
defaultVariants: {
|
|
19
|
-
variant: "contain",
|
|
20
|
-
},
|
|
21
|
-
},
|
|
22
|
-
);
|
|
23
|
-
|
|
24
|
-
export interface HorizontalListProps extends React.ComponentProps<"div">, HorizontalListVariantsProps {
|
|
25
|
-
toolbarLocation?: "bottom" | "top";
|
|
26
|
-
scrollBy?: number;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
export function HorizontalList({
|
|
30
|
-
variant,
|
|
31
|
-
className,
|
|
32
|
-
children,
|
|
33
|
-
toolbarLocation = "bottom",
|
|
34
|
-
scrollBy = 360,
|
|
35
|
-
...props
|
|
36
|
-
}: HorizontalListProps) {
|
|
37
|
-
const rootRef = useRef<HTMLDivElement>(null);
|
|
38
|
-
const containerRef = useRef<HTMLDivElement>(null);
|
|
39
|
-
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
40
|
-
const [isOverflowed, setIsOverflowed] = useState<boolean>(true);
|
|
41
|
-
|
|
42
|
-
const scrollLeft = useCallback(() => {
|
|
43
|
-
containerRef.current?.scrollBy({ left: -scrollBy });
|
|
44
|
-
}, [scrollBy]);
|
|
45
|
-
|
|
46
|
-
const scrollRight = useCallback(() => {
|
|
47
|
-
containerRef.current?.scrollBy({ left: scrollBy });
|
|
48
|
-
}, [scrollBy]);
|
|
49
|
-
|
|
50
|
-
useEffect(() => {
|
|
51
|
-
if (rootRef.current && wrapperRef.current) {
|
|
52
|
-
const rootRect = rootRef.current.getBoundingClientRect();
|
|
53
|
-
const wrapperRect = wrapperRef.current.getBoundingClientRect();
|
|
54
|
-
|
|
55
|
-
setIsOverflowed(wrapperRect.width - rootRect.width > 8);
|
|
56
|
-
}
|
|
57
|
-
}, []);
|
|
58
|
-
|
|
59
|
-
return (
|
|
60
|
-
<div
|
|
61
|
-
ref={rootRef}
|
|
62
|
-
className={cn("flex gap-4", {
|
|
63
|
-
"flex-col": toolbarLocation === "bottom",
|
|
64
|
-
"flex-col-reverse": toolbarLocation === "top",
|
|
65
|
-
})}
|
|
66
|
-
>
|
|
67
|
-
<div ref={containerRef} className={cn(horizontalListVariants({ variant }), className)} {...props}>
|
|
68
|
-
<div className="w-fit flex flex-row flex-nowrap gap-(--gap-card) " ref={wrapperRef}>
|
|
69
|
-
{children}
|
|
70
|
-
</div>
|
|
71
|
-
</div>
|
|
72
|
-
{isOverflowed && (
|
|
73
|
-
<div className="flex justify-center sm:justify-start">
|
|
74
|
-
<Button size="icon" variant="ghost" className="rounded-full" onClick={scrollLeft}>
|
|
75
|
-
<ChevronLeft className="size-9" />
|
|
76
|
-
</Button>
|
|
77
|
-
<Button size="icon" variant="ghost" className="rounded-full" onClick={scrollRight}>
|
|
78
|
-
<ChevronRight className="size-9" />
|
|
79
|
-
</Button>
|
|
80
|
-
</div>
|
|
81
|
-
)}
|
|
82
|
-
</div>
|
|
83
|
-
);
|
|
84
|
-
}
|
|
1
|
+
import { cn } from "@/lib/utils";
|
|
2
|
+
import { Button } from "./button";
|
|
3
|
+
import { ChevronLeft, ChevronRight } from "lucide-react";
|
|
4
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
5
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
6
|
+
|
|
7
|
+
export type HorizontalListVariantsProps = VariantProps<typeof horizontalListVariants>;
|
|
8
|
+
export const horizontalListVariants = cva(
|
|
9
|
+
"py-1 scrollbar-hidden overscroll-x-contain overflow-x-auto snap-start snap-mandatory scroll-smooth *:shrink-0 *:grow-0 *:snap-center *:select-none",
|
|
10
|
+
{
|
|
11
|
+
variants: {
|
|
12
|
+
variant: {
|
|
13
|
+
contain: "w-full",
|
|
14
|
+
overflow:
|
|
15
|
+
"w-screen px-section -ms-section scroll-px-section clamp:px-clamp clamp:-ms-clamp clamp:scroll-px-clamp",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
defaultVariants: {
|
|
19
|
+
variant: "contain",
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
export interface HorizontalListProps extends React.ComponentProps<"div">, HorizontalListVariantsProps {
|
|
25
|
+
toolbarLocation?: "bottom" | "top";
|
|
26
|
+
scrollBy?: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function HorizontalList({
|
|
30
|
+
variant,
|
|
31
|
+
className,
|
|
32
|
+
children,
|
|
33
|
+
toolbarLocation = "bottom",
|
|
34
|
+
scrollBy = 360,
|
|
35
|
+
...props
|
|
36
|
+
}: HorizontalListProps) {
|
|
37
|
+
const rootRef = useRef<HTMLDivElement>(null);
|
|
38
|
+
const containerRef = useRef<HTMLDivElement>(null);
|
|
39
|
+
const wrapperRef = useRef<HTMLDivElement>(null);
|
|
40
|
+
const [isOverflowed, setIsOverflowed] = useState<boolean>(true);
|
|
41
|
+
|
|
42
|
+
const scrollLeft = useCallback(() => {
|
|
43
|
+
containerRef.current?.scrollBy({ left: -scrollBy });
|
|
44
|
+
}, [scrollBy]);
|
|
45
|
+
|
|
46
|
+
const scrollRight = useCallback(() => {
|
|
47
|
+
containerRef.current?.scrollBy({ left: scrollBy });
|
|
48
|
+
}, [scrollBy]);
|
|
49
|
+
|
|
50
|
+
useEffect(() => {
|
|
51
|
+
if (rootRef.current && wrapperRef.current) {
|
|
52
|
+
const rootRect = rootRef.current.getBoundingClientRect();
|
|
53
|
+
const wrapperRect = wrapperRef.current.getBoundingClientRect();
|
|
54
|
+
|
|
55
|
+
setIsOverflowed(wrapperRect.width - rootRect.width > 8);
|
|
56
|
+
}
|
|
57
|
+
}, []);
|
|
58
|
+
|
|
59
|
+
return (
|
|
60
|
+
<div
|
|
61
|
+
ref={rootRef}
|
|
62
|
+
className={cn("flex gap-4", {
|
|
63
|
+
"flex-col": toolbarLocation === "bottom",
|
|
64
|
+
"flex-col-reverse": toolbarLocation === "top",
|
|
65
|
+
})}
|
|
66
|
+
>
|
|
67
|
+
<div ref={containerRef} className={cn(horizontalListVariants({ variant }), className)} {...props}>
|
|
68
|
+
<div className="w-fit flex flex-row flex-nowrap gap-(--gap-card) " ref={wrapperRef}>
|
|
69
|
+
{children}
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
{isOverflowed && (
|
|
73
|
+
<div className="flex justify-center sm:justify-start">
|
|
74
|
+
<Button size="icon" variant="ghost" className="rounded-full" onClick={scrollLeft}>
|
|
75
|
+
<ChevronLeft className="size-9" />
|
|
76
|
+
</Button>
|
|
77
|
+
<Button size="icon" variant="ghost" className="rounded-full" onClick={scrollRight}>
|
|
78
|
+
<ChevronRight className="size-9" />
|
|
79
|
+
</Button>
|
|
80
|
+
</div>
|
|
81
|
+
)}
|
|
82
|
+
</div>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
@@ -1,39 +1,39 @@
|
|
|
1
|
-
import { cn } from "@/lib/utils";
|
|
2
|
-
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
-
|
|
4
|
-
export type PageSectionVariantsProps = VariantProps<typeof pageSectionVariants>;
|
|
5
|
-
export const pageSectionVariants = cva("group @container/page-section relative text-foreground", {
|
|
6
|
-
variants: {
|
|
7
|
-
px: {
|
|
8
|
-
none: "px-0",
|
|
9
|
-
default: "px-(--spacing-section)",
|
|
10
|
-
sm: "px-(--spacing-section-sm)",
|
|
11
|
-
lg: "px-(--spacing-section-lg)",
|
|
12
|
-
xl: "px-(--spacing-section-xl)",
|
|
13
|
-
},
|
|
14
|
-
py: {
|
|
15
|
-
none: "py-0",
|
|
16
|
-
default: "py-(--spacing-section)",
|
|
17
|
-
sm: "py-(--spacing-section-sm)",
|
|
18
|
-
lg: "py-(--spacing-section-lg)",
|
|
19
|
-
xl: "py-(--spacing-section-xl)",
|
|
20
|
-
},
|
|
21
|
-
noClamp: {
|
|
22
|
-
true: "w-full",
|
|
23
|
-
false: "w-full
|
|
24
|
-
},
|
|
25
|
-
},
|
|
26
|
-
defaultVariants: {
|
|
27
|
-
px: "default",
|
|
28
|
-
py: "default",
|
|
29
|
-
noClamp: false,
|
|
30
|
-
},
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
export type PageSectionProps = React.ComponentProps<"div"> & VariantProps<typeof pageSectionVariants>;
|
|
34
|
-
|
|
35
|
-
export function PageSection({ className, px, py, noClamp, ...props }: PageSectionProps) {
|
|
36
|
-
return (
|
|
37
|
-
<div data-slot="page-section" className={cn(pageSectionVariants({ px, py, noClamp }), className)} {...props} />
|
|
38
|
-
);
|
|
39
|
-
}
|
|
1
|
+
import { cn } from "@/lib/utils";
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
+
|
|
4
|
+
export type PageSectionVariantsProps = VariantProps<typeof pageSectionVariants>;
|
|
5
|
+
export const pageSectionVariants = cva("group @container/page-section relative text-foreground", {
|
|
6
|
+
variants: {
|
|
7
|
+
px: {
|
|
8
|
+
none: "px-0",
|
|
9
|
+
default: "px-(--spacing-section)",
|
|
10
|
+
sm: "px-(--spacing-section-sm)",
|
|
11
|
+
lg: "px-(--spacing-section-lg)",
|
|
12
|
+
xl: "px-(--spacing-section-xl)",
|
|
13
|
+
},
|
|
14
|
+
py: {
|
|
15
|
+
none: "py-0",
|
|
16
|
+
default: "py-(--spacing-section)",
|
|
17
|
+
sm: "py-(--spacing-section-sm)",
|
|
18
|
+
lg: "py-(--spacing-section-lg)",
|
|
19
|
+
xl: "py-(--spacing-section-xl)",
|
|
20
|
+
},
|
|
21
|
+
noClamp: {
|
|
22
|
+
true: "w-full",
|
|
23
|
+
false: "w-full clamp:px-clamp",
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
defaultVariants: {
|
|
27
|
+
px: "default",
|
|
28
|
+
py: "default",
|
|
29
|
+
noClamp: false,
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export type PageSectionProps = React.ComponentProps<"div"> & VariantProps<typeof pageSectionVariants>;
|
|
34
|
+
|
|
35
|
+
export function PageSection({ className, px, py, noClamp, ...props }: PageSectionProps) {
|
|
36
|
+
return (
|
|
37
|
+
<div data-slot="page-section" className={cn(pageSectionVariants({ px, py, noClamp }), className)} {...props} />
|
|
38
|
+
);
|
|
39
|
+
}
|
package/src/styles/theme.css
CHANGED
|
@@ -1,184 +1,186 @@
|
|
|
1
|
-
@custom-variant dark (&:is(.dark *));
|
|
2
|
-
|
|
3
|
-
@theme inline {
|
|
4
|
-
--radius-sm: calc(var(--radius) - 4px);
|
|
5
|
-
--radius-md: calc(var(--radius) - 2px);
|
|
6
|
-
--radius-lg: var(--radius);
|
|
7
|
-
--radius-xl: calc(var(--radius) + 4px);
|
|
8
|
-
--radius-container: var(--radius);
|
|
9
|
-
--color-background: var(--background);
|
|
10
|
-
--color-foreground: var(--foreground);
|
|
11
|
-
--color-card: var(--card);
|
|
12
|
-
--color-card-foreground: var(--card-foreground);
|
|
13
|
-
--color-popover: var(--popover);
|
|
14
|
-
--color-popover-foreground: var(--popover-foreground);
|
|
15
|
-
--color-primary: var(--primary);
|
|
16
|
-
--color-primary-foreground: var(--primary-foreground);
|
|
17
|
-
--color-secondary: var(--secondary);
|
|
18
|
-
--color-secondary-foreground: var(--secondary-foreground);
|
|
19
|
-
--color-muted: var(--muted);
|
|
20
|
-
--color-muted-foreground: var(--muted-foreground);
|
|
21
|
-
--color-accent: var(--accent);
|
|
22
|
-
--color-accent-foreground: var(--accent-foreground);
|
|
23
|
-
--color-destructive: var(--destructive);
|
|
24
|
-
--color-border: var(--border);
|
|
25
|
-
--color-input: var(--input);
|
|
26
|
-
--color-ring: var(--ring);
|
|
27
|
-
--color-chart-1: var(--chart-1);
|
|
28
|
-
--color-chart-2: var(--chart-2);
|
|
29
|
-
--color-chart-3: var(--chart-3);
|
|
30
|
-
--color-chart-4: var(--chart-4);
|
|
31
|
-
--color-chart-5: var(--chart-5);
|
|
32
|
-
--color-sidebar: var(--sidebar);
|
|
33
|
-
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
34
|
-
--color-sidebar-primary: var(--sidebar-primary);
|
|
35
|
-
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
36
|
-
--color-sidebar-accent: var(--sidebar-accent);
|
|
37
|
-
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
38
|
-
--color-sidebar-border: var(--sidebar-border);
|
|
39
|
-
--color-sidebar-ring: var(--sidebar-ring);
|
|
40
|
-
|
|
41
|
-
--
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
--spacing-
|
|
45
|
-
|
|
46
|
-
--spacing-
|
|
47
|
-
|
|
48
|
-
--spacing-section
|
|
49
|
-
--spacing-section-
|
|
50
|
-
|
|
51
|
-
--spacing-
|
|
52
|
-
|
|
53
|
-
--spacing-card
|
|
54
|
-
--spacing-card-
|
|
55
|
-
|
|
56
|
-
--
|
|
57
|
-
|
|
58
|
-
--gap-
|
|
59
|
-
--gap-card
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
--
|
|
66
|
-
--
|
|
67
|
-
--
|
|
68
|
-
--
|
|
69
|
-
--
|
|
70
|
-
--
|
|
71
|
-
--
|
|
72
|
-
--
|
|
73
|
-
--
|
|
74
|
-
--
|
|
75
|
-
--
|
|
76
|
-
--
|
|
77
|
-
--
|
|
78
|
-
--
|
|
79
|
-
--
|
|
80
|
-
--
|
|
81
|
-
--
|
|
82
|
-
--
|
|
83
|
-
--
|
|
84
|
-
--chart-
|
|
85
|
-
--chart-
|
|
86
|
-
--chart-
|
|
87
|
-
--
|
|
88
|
-
--
|
|
89
|
-
--sidebar
|
|
90
|
-
--sidebar-
|
|
91
|
-
--sidebar-
|
|
92
|
-
--sidebar-
|
|
93
|
-
--sidebar-
|
|
94
|
-
--sidebar-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
--
|
|
100
|
-
--card-
|
|
101
|
-
--
|
|
102
|
-
--card-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
--
|
|
108
|
-
--card-
|
|
109
|
-
--
|
|
110
|
-
--card-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
--
|
|
117
|
-
--card-
|
|
118
|
-
--
|
|
119
|
-
--card-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
--
|
|
127
|
-
--
|
|
128
|
-
--
|
|
129
|
-
--
|
|
130
|
-
--
|
|
131
|
-
--
|
|
132
|
-
--
|
|
133
|
-
--
|
|
134
|
-
--
|
|
135
|
-
--
|
|
136
|
-
--
|
|
137
|
-
--
|
|
138
|
-
--
|
|
139
|
-
--
|
|
140
|
-
--
|
|
141
|
-
--
|
|
142
|
-
--
|
|
143
|
-
--
|
|
144
|
-
--chart-
|
|
145
|
-
--chart-
|
|
146
|
-
--chart-
|
|
147
|
-
--
|
|
148
|
-
--
|
|
149
|
-
--sidebar
|
|
150
|
-
--sidebar-
|
|
151
|
-
--sidebar-
|
|
152
|
-
--sidebar-
|
|
153
|
-
--sidebar-
|
|
154
|
-
--sidebar-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
1
|
+
@custom-variant dark (&:is(.dark *));
|
|
2
|
+
|
|
3
|
+
@theme inline {
|
|
4
|
+
--radius-sm: calc(var(--radius) - 4px);
|
|
5
|
+
--radius-md: calc(var(--radius) - 2px);
|
|
6
|
+
--radius-lg: var(--radius);
|
|
7
|
+
--radius-xl: calc(var(--radius) + 4px);
|
|
8
|
+
--radius-container: var(--radius);
|
|
9
|
+
--color-background: var(--background);
|
|
10
|
+
--color-foreground: var(--foreground);
|
|
11
|
+
--color-card: var(--card);
|
|
12
|
+
--color-card-foreground: var(--card-foreground);
|
|
13
|
+
--color-popover: var(--popover);
|
|
14
|
+
--color-popover-foreground: var(--popover-foreground);
|
|
15
|
+
--color-primary: var(--primary);
|
|
16
|
+
--color-primary-foreground: var(--primary-foreground);
|
|
17
|
+
--color-secondary: var(--secondary);
|
|
18
|
+
--color-secondary-foreground: var(--secondary-foreground);
|
|
19
|
+
--color-muted: var(--muted);
|
|
20
|
+
--color-muted-foreground: var(--muted-foreground);
|
|
21
|
+
--color-accent: var(--accent);
|
|
22
|
+
--color-accent-foreground: var(--accent-foreground);
|
|
23
|
+
--color-destructive: var(--destructive);
|
|
24
|
+
--color-border: var(--border);
|
|
25
|
+
--color-input: var(--input);
|
|
26
|
+
--color-ring: var(--ring);
|
|
27
|
+
--color-chart-1: var(--chart-1);
|
|
28
|
+
--color-chart-2: var(--chart-2);
|
|
29
|
+
--color-chart-3: var(--chart-3);
|
|
30
|
+
--color-chart-4: var(--chart-4);
|
|
31
|
+
--color-chart-5: var(--chart-5);
|
|
32
|
+
--color-sidebar: var(--sidebar);
|
|
33
|
+
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
34
|
+
--color-sidebar-primary: var(--sidebar-primary);
|
|
35
|
+
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
36
|
+
--color-sidebar-accent: var(--sidebar-accent);
|
|
37
|
+
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
38
|
+
--color-sidebar-border: var(--sidebar-border);
|
|
39
|
+
--color-sidebar-ring: var(--sidebar-ring);
|
|
40
|
+
|
|
41
|
+
--breakpoint-clamp: 100rem;
|
|
42
|
+
|
|
43
|
+
--container-clamp: 96rem;
|
|
44
|
+
--spacing-clamp: calc((100dvw - var(--container-clamp)) / 2);
|
|
45
|
+
|
|
46
|
+
--spacing-page-nav: --spacing(18);
|
|
47
|
+
|
|
48
|
+
--spacing-section: var(--section-p);
|
|
49
|
+
--spacing-section-sm: calc(var(--spacing-section) / 2);
|
|
50
|
+
--spacing-section-lg: calc(var(--spacing-section) * 2);
|
|
51
|
+
--spacing-section-xl: calc(var(--spacing-section) * 5);
|
|
52
|
+
|
|
53
|
+
--spacing-card: var(--card-p);
|
|
54
|
+
--spacing-card-sm: calc(var(--spacing-card) / 2);
|
|
55
|
+
--spacing-card-lg: calc(var(--spacing-card) * 2);
|
|
56
|
+
--spacing-card-xl: calc(var(--spacing-card) * 5);
|
|
57
|
+
|
|
58
|
+
--gap-page: var(--page-gap);
|
|
59
|
+
--gap-card: var(--card-gap);
|
|
60
|
+
--gap-card-area: var(--card-area-gap);
|
|
61
|
+
--gap-card-item-group: var(--card-item-group-gap);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
:root {
|
|
65
|
+
--radius: 0.625rem;
|
|
66
|
+
--background: oklch(1 0 0);
|
|
67
|
+
--foreground: oklch(0.141 0.005 285.823);
|
|
68
|
+
--card: oklch(1 0 0);
|
|
69
|
+
--card-foreground: oklch(0.3741 0.0774 245.65);
|
|
70
|
+
--popover: oklch(1 0 0);
|
|
71
|
+
--popover-foreground: oklch(0.3741 0.0774 245.65);
|
|
72
|
+
--primary: oklch(0.3741 0.0774 245.65);
|
|
73
|
+
--primary-foreground: oklch(0.985 0 0);
|
|
74
|
+
--secondary: oklch(0.5393 0.0909 200);
|
|
75
|
+
--secondary-foreground: oklch(0.985 0 0);
|
|
76
|
+
--muted: oklch(0.967 0.001 286.375);
|
|
77
|
+
--muted-foreground: oklch(0.45 0.0236 285.938);
|
|
78
|
+
--accent: oklch(0.967 0.001 286.375);
|
|
79
|
+
--accent-foreground: oklch(0.3741 0.0774 245.65);
|
|
80
|
+
--destructive: oklch(0.577 0.245 27.325);
|
|
81
|
+
--border: oklch(0.92 0.004 286.32);
|
|
82
|
+
--input: oklch(0.92 0.004 286.32);
|
|
83
|
+
--ring: var(--color-complement-1-200);
|
|
84
|
+
--chart-1: oklch(0.646 0.222 41.116);
|
|
85
|
+
--chart-2: oklch(0.6 0.118 184.704);
|
|
86
|
+
--chart-3: oklch(0.398 0.07 227.392);
|
|
87
|
+
--chart-4: oklch(0.828 0.189 84.429);
|
|
88
|
+
--chart-5: oklch(0.769 0.188 70.08);
|
|
89
|
+
--sidebar: oklch(0.985 0 0);
|
|
90
|
+
--sidebar-foreground: oklch(0.3741 0.0774 245.65);
|
|
91
|
+
--sidebar-primary: oklch(0.3741 0.0774 245.65);
|
|
92
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
93
|
+
--sidebar-accent: oklch(0.967 0.001 286.375);
|
|
94
|
+
--sidebar-accent-foreground: oklch(0.3741 0.0774 245.65);
|
|
95
|
+
--sidebar-border: oklch(0.92 0.004 286.32);
|
|
96
|
+
--sidebar-ring: var(--color-complement-1-200);
|
|
97
|
+
|
|
98
|
+
/* Responsive Layout Spacing */
|
|
99
|
+
--section-p: --spacing(4);
|
|
100
|
+
--card-p: --spacing(4);
|
|
101
|
+
--page-gap: --spacing(0);
|
|
102
|
+
--card-gap: --spacing(4);
|
|
103
|
+
--card-area-gap: --spacing(4);
|
|
104
|
+
--card-item-group-gap: --spacing(2);
|
|
105
|
+
|
|
106
|
+
@media (width >= 40rem) {
|
|
107
|
+
--section-p: --spacing(8);
|
|
108
|
+
--card-p: --spacing(6);
|
|
109
|
+
--page-gap: --spacing(4);
|
|
110
|
+
--card-gap: --spacing(6);
|
|
111
|
+
--card-area-gap: --spacing(6);
|
|
112
|
+
--card-item-group-gap: --spacing(2);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
@media (width >= 80rem) {
|
|
116
|
+
--section-p: --spacing(12);
|
|
117
|
+
--card-p: --spacing(6);
|
|
118
|
+
--page-gap: --spacing(0);
|
|
119
|
+
--card-gap: --spacing(6);
|
|
120
|
+
--card-area-gap: --spacing(6);
|
|
121
|
+
--card-item-group-gap: --spacing(2);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.dark {
|
|
126
|
+
--background: oklch(0.141 0.005 285.823);
|
|
127
|
+
--foreground: oklch(0.985 0 0);
|
|
128
|
+
--card: oklch(0.141 0.005 285.823);
|
|
129
|
+
--card-foreground: oklch(0.985 0 0);
|
|
130
|
+
--popover: oklch(0.141 0.005 285.823);
|
|
131
|
+
--popover-foreground: oklch(0.985 0 0);
|
|
132
|
+
--primary: oklch(0.985 0 0);
|
|
133
|
+
--primary-foreground: oklch(0.3741 0.0774 245.65);
|
|
134
|
+
--secondary: oklch(0.9156 0.0315 200);
|
|
135
|
+
--secondary-foreground: oklch(0 0 0);
|
|
136
|
+
--muted: oklch(0.274 0.006 286.033);
|
|
137
|
+
--muted-foreground: oklch(0.705 0.015 286.067);
|
|
138
|
+
--accent: oklch(0.274 0.006 286.033);
|
|
139
|
+
--accent-foreground: oklch(0.985 0 0);
|
|
140
|
+
--destructive: oklch(0.704 0.191 22.216);
|
|
141
|
+
--border: oklch(1 0 0 / 10%);
|
|
142
|
+
--input: oklch(1 0 0 / 15%);
|
|
143
|
+
--ring: var(--color-complement-1-600);
|
|
144
|
+
--chart-1: oklch(0.488 0.243 264.376);
|
|
145
|
+
--chart-2: oklch(0.696 0.17 162.48);
|
|
146
|
+
--chart-3: oklch(0.769 0.188 70.08);
|
|
147
|
+
--chart-4: oklch(0.627 0.265 303.9);
|
|
148
|
+
--chart-5: oklch(0.645 0.246 16.439);
|
|
149
|
+
--sidebar: oklch(0.3741 0.0774 245.65);
|
|
150
|
+
--sidebar-foreground: oklch(0.985 0 0);
|
|
151
|
+
--sidebar-primary: oklch(0.3741 0.0774 245.65);
|
|
152
|
+
--sidebar-primary-foreground: oklch(0.985 0 0);
|
|
153
|
+
--sidebar-accent: oklch(0.274 0.006 286.033);
|
|
154
|
+
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
155
|
+
--sidebar-border: oklch(1 0 0 / 10%);
|
|
156
|
+
--sidebar-ring: var(--color-complement-1-600);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
@layer base {
|
|
160
|
+
* {
|
|
161
|
+
@apply border-border outline-ring/50;
|
|
162
|
+
}
|
|
163
|
+
body {
|
|
164
|
+
@apply bg-background text-foreground;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
@utility scrollbar-hidden {
|
|
169
|
+
-ms-overflow-style: none;
|
|
170
|
+
scrollbar-width: none;
|
|
171
|
+
&::-webkit-scrollbar {
|
|
172
|
+
display: none;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/* prettier-ignore */
|
|
177
|
+
@utility areas-* {
|
|
178
|
+
grid-template-areas: --value([*]);
|
|
179
|
+
grid-template-columns: --modifier([*]);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
@utility stick-to-page {
|
|
183
|
+
position: sticky;
|
|
184
|
+
top: calc(var(--spacing-section) + var(--spacing-page-nav));
|
|
185
|
+
height: fit-content;
|
|
186
|
+
}
|