@camox/cli 0.44.0 → 0.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.
- package/README.md +129 -46
- package/dist/api-DNIQC1ea.mjs +104 -0
- package/dist/api-DeE66CPa.mjs +2 -0
- package/dist/{auth-core-4Jdf5q-u.mjs → auth-core-xLeorUUV.mjs} +35 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +633 -764
- package/dist/lib/auth-core.d.mts +12 -8
- package/dist/lib/auth-core.mjs +1 -2
- package/dist/local-dns-DQIT1ucr.mjs +22 -0
- package/package.json +23 -19
- package/dist/api-COfB7AKI.mjs +0 -82
- package/dist/api-LuNKejJE.mjs +0 -3
- package/templates/default/.env.example +0 -2
- package/templates/default/components.json +0 -25
- package/templates/default/package.json +0 -46
- package/templates/default/scripts/README.md +0 -35
- package/templates/default/scripts/production-smoke.mjs +0 -124
- package/templates/default/src/blocks/faq.tsx +0 -63
- package/templates/default/src/blocks/footer.tsx +0 -61
- package/templates/default/src/blocks/hero.tsx +0 -92
- package/templates/default/src/blocks/navbar.tsx +0 -110
- package/templates/default/src/blocks/youtube-video.tsx +0 -158
- package/templates/default/src/components/ui/accordion.tsx +0 -70
- package/templates/default/src/components/ui/button.tsx +0 -58
- package/templates/default/src/document.ts +0 -7
- package/templates/default/src/layouts/default.tsx +0 -88
- package/templates/default/src/lib/utils.ts +0 -6
- package/templates/default/src/styles.css +0 -162
- package/templates/default/tsconfig.json +0 -25
- package/templates/default/vite.config.ts +0 -25
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { Type, createBlock } from "camox/createBlock";
|
|
2
|
-
import { Link } from "camox/navigation";
|
|
3
|
-
import type { ReactElement } from "react";
|
|
4
|
-
|
|
5
|
-
import { Button } from "@/components/ui/button";
|
|
6
|
-
|
|
7
|
-
const navbar = createBlock({
|
|
8
|
-
id: "navbar",
|
|
9
|
-
title: "Navbar",
|
|
10
|
-
layoutOnly: true,
|
|
11
|
-
synced: true,
|
|
12
|
-
description:
|
|
13
|
-
"A navigation bar at the top of a page with a brand name, navigation links, and a call-to-action link.",
|
|
14
|
-
content: {
|
|
15
|
-
title: Type.Link({
|
|
16
|
-
title: "Site name",
|
|
17
|
-
default: {
|
|
18
|
-
href: "/",
|
|
19
|
-
text: "{{projectName}}",
|
|
20
|
-
newTab: false,
|
|
21
|
-
},
|
|
22
|
-
}),
|
|
23
|
-
links: Type.Repeater({
|
|
24
|
-
content: {
|
|
25
|
-
link: Type.Link({
|
|
26
|
-
default: { text: "Link", href: "#", newTab: false },
|
|
27
|
-
title: "Link",
|
|
28
|
-
}),
|
|
29
|
-
},
|
|
30
|
-
minItems: 1,
|
|
31
|
-
maxItems: 6,
|
|
32
|
-
title: "Links",
|
|
33
|
-
toMarkdown: (c) => [c.link],
|
|
34
|
-
}),
|
|
35
|
-
cta: Type.Link({
|
|
36
|
-
default: { text: "Get started", href: "#", newTab: false },
|
|
37
|
-
title: "Call to action",
|
|
38
|
-
}),
|
|
39
|
-
},
|
|
40
|
-
settings: {
|
|
41
|
-
sticky: Type.Boolean({
|
|
42
|
-
default: true,
|
|
43
|
-
title: "Sticky",
|
|
44
|
-
}),
|
|
45
|
-
},
|
|
46
|
-
component: NavbarComponent,
|
|
47
|
-
toMarkdown: (c) => [c.title, c.links, c.cta],
|
|
48
|
-
});
|
|
49
|
-
|
|
50
|
-
function NavbarComponent(): ReactElement {
|
|
51
|
-
const sticky = navbar.useSetting("sticky");
|
|
52
|
-
|
|
53
|
-
const innerContent = (
|
|
54
|
-
<div className="container mx-auto px-4">
|
|
55
|
-
<div className="flex h-16 items-center justify-between">
|
|
56
|
-
<navbar.Link name="title">
|
|
57
|
-
{(props) => <Link {...props} className="text-foreground text-lg font-bold" />}
|
|
58
|
-
</navbar.Link>
|
|
59
|
-
|
|
60
|
-
<div className="flex items-center gap-6">
|
|
61
|
-
<navbar.Repeater name="links">
|
|
62
|
-
{(linkItem) => (
|
|
63
|
-
<linkItem.Link name="link">
|
|
64
|
-
{(props) => (
|
|
65
|
-
<Link
|
|
66
|
-
{...props}
|
|
67
|
-
className="text-muted-foreground hover:text-foreground text-sm transition-colors"
|
|
68
|
-
/>
|
|
69
|
-
)}
|
|
70
|
-
</linkItem.Link>
|
|
71
|
-
)}
|
|
72
|
-
</navbar.Repeater>
|
|
73
|
-
|
|
74
|
-
<navbar.Link name="cta">
|
|
75
|
-
{(props) => (
|
|
76
|
-
<Button
|
|
77
|
-
size="sm"
|
|
78
|
-
variant="outline"
|
|
79
|
-
nativeButton={false}
|
|
80
|
-
render={<Link {...props} />}
|
|
81
|
-
/>
|
|
82
|
-
)}
|
|
83
|
-
</navbar.Link>
|
|
84
|
-
</div>
|
|
85
|
-
</div>
|
|
86
|
-
</div>
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
if (!sticky) {
|
|
90
|
-
return <nav className="dark bg-background border-border border-b">{innerContent}</nav>;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return (
|
|
94
|
-
<>
|
|
95
|
-
<div aria-hidden className="dark bg-background h-16 border-b border-transparent" />
|
|
96
|
-
<navbar.Detached>
|
|
97
|
-
{(props) => (
|
|
98
|
-
<nav
|
|
99
|
-
{...props}
|
|
100
|
-
className="dark bg-background border-border fixed top-0 right-0 left-0 z-50 border-b"
|
|
101
|
-
>
|
|
102
|
-
{innerContent}
|
|
103
|
-
</nav>
|
|
104
|
-
)}
|
|
105
|
-
</navbar.Detached>
|
|
106
|
-
</>
|
|
107
|
-
);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
export { navbar as block };
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
import { Type, createBlock } from "camox/createBlock";
|
|
2
|
-
|
|
3
|
-
import { cn } from "@/lib/utils";
|
|
4
|
-
|
|
5
|
-
const youtubeVideo = createBlock({
|
|
6
|
-
id: "youtube-video",
|
|
7
|
-
title: "YouTube Video",
|
|
8
|
-
description:
|
|
9
|
-
"Embeds a YouTube video. Use this block to display a single YouTube video on a page. Don't try to guess the URL, use a web search tool to find a specific video URL instead.",
|
|
10
|
-
content: {
|
|
11
|
-
url: Type.Embed({
|
|
12
|
-
pattern:
|
|
13
|
-
"https:\\/\\/(www\\.)?(youtube\\.com\\/(watch\\?v=|embed\\/|shorts\\/)|youtu\\.be\\/).+",
|
|
14
|
-
default: "https://www.youtube.com/watch?v=-W_nFlIAWFM",
|
|
15
|
-
title: "YouTube URL",
|
|
16
|
-
}),
|
|
17
|
-
},
|
|
18
|
-
settings: {
|
|
19
|
-
fullWidth: Type.Boolean({
|
|
20
|
-
default: false,
|
|
21
|
-
title: "Full Width",
|
|
22
|
-
}),
|
|
23
|
-
theme: Type.Enum({
|
|
24
|
-
options: {
|
|
25
|
-
light: "Light",
|
|
26
|
-
dark: "Dark",
|
|
27
|
-
},
|
|
28
|
-
default: "light",
|
|
29
|
-
title: "Theme",
|
|
30
|
-
}),
|
|
31
|
-
autoplay: Type.Boolean({
|
|
32
|
-
default: false,
|
|
33
|
-
title: "Autoplay",
|
|
34
|
-
}),
|
|
35
|
-
mute: Type.Boolean({
|
|
36
|
-
default: false,
|
|
37
|
-
title: "Mute",
|
|
38
|
-
}),
|
|
39
|
-
controls: Type.Boolean({
|
|
40
|
-
default: true,
|
|
41
|
-
title: "Controls",
|
|
42
|
-
}),
|
|
43
|
-
showCaptions: Type.Boolean({
|
|
44
|
-
default: false,
|
|
45
|
-
title: "Show Captions",
|
|
46
|
-
}),
|
|
47
|
-
rel: Type.Boolean({
|
|
48
|
-
default: false,
|
|
49
|
-
title: "Related Videos",
|
|
50
|
-
}),
|
|
51
|
-
fullscreen: Type.Boolean({
|
|
52
|
-
default: true,
|
|
53
|
-
title: "Fullscreen",
|
|
54
|
-
}),
|
|
55
|
-
},
|
|
56
|
-
component: YouTubeVideoComponent,
|
|
57
|
-
toMarkdown: (c) => [c.url],
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
function extractVideoId(url: string): string | null {
|
|
61
|
-
const shortMatch = url.match(/youtu\.be\/([^?&]+)/);
|
|
62
|
-
if (shortMatch) return shortMatch[1];
|
|
63
|
-
|
|
64
|
-
const shortsMatch = url.match(/youtube\.com\/shorts\/([^?&]+)/);
|
|
65
|
-
if (shortsMatch) return shortsMatch[1];
|
|
66
|
-
|
|
67
|
-
const watchMatch = url.match(/[?&]v=([^&]+)/);
|
|
68
|
-
if (watchMatch) return watchMatch[1];
|
|
69
|
-
|
|
70
|
-
const embedMatch = url.match(/youtube\.com\/embed\/([^?&]+)/);
|
|
71
|
-
if (embedMatch) return embedMatch[1];
|
|
72
|
-
|
|
73
|
-
return null;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
interface YouTubeParams {
|
|
77
|
-
autoplay: boolean;
|
|
78
|
-
mute: boolean;
|
|
79
|
-
controls: boolean;
|
|
80
|
-
showCaptions: boolean;
|
|
81
|
-
rel: boolean;
|
|
82
|
-
fullscreen: boolean;
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
function getYouTubeEmbedUrl(url: string, params: YouTubeParams): string {
|
|
86
|
-
const videoId = extractVideoId(url);
|
|
87
|
-
if (!videoId) return url;
|
|
88
|
-
|
|
89
|
-
const searchParams = new URLSearchParams();
|
|
90
|
-
|
|
91
|
-
if (params.autoplay) searchParams.set("autoplay", "1");
|
|
92
|
-
if (params.mute) searchParams.set("mute", "1");
|
|
93
|
-
if (!params.controls) searchParams.set("controls", "0");
|
|
94
|
-
if (params.showCaptions) searchParams.set("cc_load_policy", "1");
|
|
95
|
-
if (!params.rel) searchParams.set("rel", "0");
|
|
96
|
-
if (!params.fullscreen) searchParams.set("fs", "0");
|
|
97
|
-
searchParams.set("disablekb", "1");
|
|
98
|
-
|
|
99
|
-
const query = searchParams.toString();
|
|
100
|
-
return `https://www.youtube.com/embed/${videoId}${query ? `?${query}` : ""}`;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
function YouTubeVideoComponent() {
|
|
104
|
-
const fullWidth = youtubeVideo.useSetting("fullWidth");
|
|
105
|
-
const theme = youtubeVideo.useSetting("theme");
|
|
106
|
-
const autoplay = youtubeVideo.useSetting("autoplay");
|
|
107
|
-
const mute = youtubeVideo.useSetting("mute");
|
|
108
|
-
const controls = youtubeVideo.useSetting("controls");
|
|
109
|
-
const showCaptions = youtubeVideo.useSetting("showCaptions");
|
|
110
|
-
const rel = youtubeVideo.useSetting("rel");
|
|
111
|
-
const fullscreen = youtubeVideo.useSetting("fullscreen");
|
|
112
|
-
|
|
113
|
-
const params: YouTubeParams = {
|
|
114
|
-
autoplay,
|
|
115
|
-
mute,
|
|
116
|
-
controls,
|
|
117
|
-
showCaptions,
|
|
118
|
-
rel,
|
|
119
|
-
fullscreen,
|
|
120
|
-
};
|
|
121
|
-
|
|
122
|
-
return (
|
|
123
|
-
<section className={cn(theme === "dark" ? "dark" : "light")}>
|
|
124
|
-
<div className={cn("bg-background", !fullWidth && "py-12")}>
|
|
125
|
-
<div className={cn(!fullWidth && "container mx-auto px-4")}>
|
|
126
|
-
<youtubeVideo.Embed name="url">
|
|
127
|
-
{(_props, { url }) => (
|
|
128
|
-
<div
|
|
129
|
-
className={cn(
|
|
130
|
-
"relative w-full",
|
|
131
|
-
!fullWidth && "overflow-hidden rounded-lg shadow-lg",
|
|
132
|
-
)}
|
|
133
|
-
style={{ paddingBottom: "56.25%" }}
|
|
134
|
-
>
|
|
135
|
-
<iframe
|
|
136
|
-
src={getYouTubeEmbedUrl(url, params)}
|
|
137
|
-
title="YouTube video"
|
|
138
|
-
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
|
|
139
|
-
allowFullScreen={fullscreen}
|
|
140
|
-
style={{
|
|
141
|
-
position: "absolute",
|
|
142
|
-
top: 0,
|
|
143
|
-
left: 0,
|
|
144
|
-
width: "100%",
|
|
145
|
-
height: "100%",
|
|
146
|
-
border: 0,
|
|
147
|
-
}}
|
|
148
|
-
/>
|
|
149
|
-
</div>
|
|
150
|
-
)}
|
|
151
|
-
</youtubeVideo.Embed>
|
|
152
|
-
</div>
|
|
153
|
-
</div>
|
|
154
|
-
</section>
|
|
155
|
-
);
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export { youtubeVideo as block };
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { Accordion as AccordionPrimitive } from "@base-ui/react/accordion";
|
|
2
|
-
import { ChevronDownIcon, ChevronUpIcon } from "lucide-react";
|
|
3
|
-
|
|
4
|
-
import { cn } from "@/lib/utils";
|
|
5
|
-
|
|
6
|
-
function Accordion({ className, ...props }: AccordionPrimitive.Root.Props) {
|
|
7
|
-
return (
|
|
8
|
-
<AccordionPrimitive.Root
|
|
9
|
-
data-slot="accordion"
|
|
10
|
-
className={cn("flex w-full flex-col", className)}
|
|
11
|
-
{...props}
|
|
12
|
-
/>
|
|
13
|
-
);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function AccordionItem({ className, ...props }: AccordionPrimitive.Item.Props) {
|
|
17
|
-
return (
|
|
18
|
-
<AccordionPrimitive.Item
|
|
19
|
-
data-slot="accordion-item"
|
|
20
|
-
className={cn("not-last:border-b", className)}
|
|
21
|
-
{...props}
|
|
22
|
-
/>
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function AccordionTrigger({ className, children, ...props }: AccordionPrimitive.Trigger.Props) {
|
|
27
|
-
return (
|
|
28
|
-
<AccordionPrimitive.Header className="flex">
|
|
29
|
-
<AccordionPrimitive.Trigger
|
|
30
|
-
data-slot="accordion-trigger"
|
|
31
|
-
className={cn(
|
|
32
|
-
"group/accordion-trigger relative flex flex-1 items-start justify-between rounded-md border border-transparent py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:after:border-ring aria-disabled:pointer-events-none aria-disabled:opacity-50 **:data-[slot=accordion-trigger-icon]:ml-auto **:data-[slot=accordion-trigger-icon]:size-4 **:data-[slot=accordion-trigger-icon]:text-muted-foreground",
|
|
33
|
-
className,
|
|
34
|
-
)}
|
|
35
|
-
{...props}
|
|
36
|
-
>
|
|
37
|
-
{children}
|
|
38
|
-
<ChevronDownIcon
|
|
39
|
-
data-slot="accordion-trigger-icon"
|
|
40
|
-
className="pointer-events-none shrink-0 group-aria-expanded/accordion-trigger:hidden"
|
|
41
|
-
/>
|
|
42
|
-
<ChevronUpIcon
|
|
43
|
-
data-slot="accordion-trigger-icon"
|
|
44
|
-
className="pointer-events-none hidden shrink-0 group-aria-expanded/accordion-trigger:inline"
|
|
45
|
-
/>
|
|
46
|
-
</AccordionPrimitive.Trigger>
|
|
47
|
-
</AccordionPrimitive.Header>
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
function AccordionContent({ className, children, ...props }: AccordionPrimitive.Panel.Props) {
|
|
52
|
-
return (
|
|
53
|
-
<AccordionPrimitive.Panel
|
|
54
|
-
data-slot="accordion-content"
|
|
55
|
-
className="data-open:animate-accordion-down data-closed:animate-accordion-up overflow-hidden text-sm"
|
|
56
|
-
{...props}
|
|
57
|
-
>
|
|
58
|
-
<div
|
|
59
|
-
className={cn(
|
|
60
|
-
"h-(--accordion-panel-height) pt-0 pb-4 data-ending-style:h-0 data-starting-style:h-0 [&_a]:underline [&_a]:underline-offset-3 [&_a]:hover:text-foreground [&_p:not(:last-child)]:mb-4",
|
|
61
|
-
className,
|
|
62
|
-
)}
|
|
63
|
-
>
|
|
64
|
-
{children}
|
|
65
|
-
</div>
|
|
66
|
-
</AccordionPrimitive.Panel>
|
|
67
|
-
);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { Button as ButtonPrimitive } from "@base-ui/react/button";
|
|
2
|
-
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
-
|
|
4
|
-
import { cn } from "@/lib/utils";
|
|
5
|
-
|
|
6
|
-
const buttonVariants = cva(
|
|
7
|
-
"group/button inline-flex shrink-0 items-center justify-center rounded-md border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 active:not-aria-[haspopup]:translate-y-px disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
8
|
-
{
|
|
9
|
-
variants: {
|
|
10
|
-
variant: {
|
|
11
|
-
default: "bg-primary text-primary-foreground hover:bg-primary/80",
|
|
12
|
-
outline:
|
|
13
|
-
"border-border bg-background text-foreground shadow-xs hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:border-input dark:bg-input/30 dark:hover:bg-input/50",
|
|
14
|
-
secondary:
|
|
15
|
-
"bg-secondary text-secondary-foreground hover:bg-secondary/80 aria-expanded:bg-secondary aria-expanded:text-secondary-foreground",
|
|
16
|
-
ghost:
|
|
17
|
-
"hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50",
|
|
18
|
-
destructive:
|
|
19
|
-
"bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40",
|
|
20
|
-
link: "text-primary underline-offset-4 hover:underline",
|
|
21
|
-
},
|
|
22
|
-
size: {
|
|
23
|
-
default:
|
|
24
|
-
"h-9 gap-1.5 px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
|
25
|
-
xs: "h-6 gap-1 rounded-[min(var(--radius-md),8px)] px-2 text-xs in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5 [&_svg:not([class*='size-'])]:size-3",
|
|
26
|
-
sm: "h-8 gap-1 rounded-[min(var(--radius-md),10px)] px-2.5 in-data-[slot=button-group]:rounded-md has-data-[icon=inline-end]:pr-1.5 has-data-[icon=inline-start]:pl-1.5",
|
|
27
|
-
lg: "h-10 gap-1.5 px-2.5 has-data-[icon=inline-end]:pr-2 has-data-[icon=inline-start]:pl-2",
|
|
28
|
-
icon: "size-9",
|
|
29
|
-
"icon-xs":
|
|
30
|
-
"size-6 rounded-[min(var(--radius-md),8px)] in-data-[slot=button-group]:rounded-md [&_svg:not([class*='size-'])]:size-3",
|
|
31
|
-
"icon-sm":
|
|
32
|
-
"size-8 rounded-[min(var(--radius-md),10px)] in-data-[slot=button-group]:rounded-md",
|
|
33
|
-
"icon-lg": "size-10",
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
defaultVariants: {
|
|
37
|
-
variant: "default",
|
|
38
|
-
size: "default",
|
|
39
|
-
},
|
|
40
|
-
},
|
|
41
|
-
);
|
|
42
|
-
|
|
43
|
-
function Button({
|
|
44
|
-
className,
|
|
45
|
-
variant = "default",
|
|
46
|
-
size = "default",
|
|
47
|
-
...props
|
|
48
|
-
}: ButtonPrimitive.Props & VariantProps<typeof buttonVariants>) {
|
|
49
|
-
return (
|
|
50
|
-
<ButtonPrimitive
|
|
51
|
-
data-slot="button"
|
|
52
|
-
className={cn(buttonVariants({ variant, size, className }))}
|
|
53
|
-
{...props}
|
|
54
|
-
/>
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export { Button, buttonVariants };
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { createLayout } from "camox/createLayout";
|
|
2
|
-
|
|
3
|
-
import { block as faqBlock } from "../blocks/faq";
|
|
4
|
-
import { block as footerBlock } from "../blocks/footer";
|
|
5
|
-
import { block as heroBlock } from "../blocks/hero";
|
|
6
|
-
import { block as navbarBlock } from "../blocks/navbar";
|
|
7
|
-
|
|
8
|
-
const defaultLayout = createLayout({
|
|
9
|
-
id: "default",
|
|
10
|
-
title: "Default",
|
|
11
|
-
description: "Default page layout with a navbar and footer",
|
|
12
|
-
blocks: {
|
|
13
|
-
before: [navbarBlock],
|
|
14
|
-
after: [footerBlock],
|
|
15
|
-
initial: [heroBlock, faqBlock],
|
|
16
|
-
},
|
|
17
|
-
component: DefaultLayout,
|
|
18
|
-
buildMetaTitle: ({ pageMetaTitle, projectName }) => `${pageMetaTitle} | ${projectName}`,
|
|
19
|
-
buildOgImage: ({ title, description, projectName }) => (
|
|
20
|
-
<div
|
|
21
|
-
style={{
|
|
22
|
-
display: "flex",
|
|
23
|
-
flexDirection: "column",
|
|
24
|
-
justifyContent: "center",
|
|
25
|
-
alignItems: "flex-start",
|
|
26
|
-
width: "100%",
|
|
27
|
-
height: "100%",
|
|
28
|
-
backgroundColor: "#09090b",
|
|
29
|
-
padding: "60px 80px",
|
|
30
|
-
fontFamily: "sans-serif",
|
|
31
|
-
}}
|
|
32
|
-
>
|
|
33
|
-
{projectName && (
|
|
34
|
-
<div
|
|
35
|
-
style={{
|
|
36
|
-
fontSize: 24,
|
|
37
|
-
color: "#a1a1aa",
|
|
38
|
-
marginBottom: 24,
|
|
39
|
-
textTransform: "uppercase",
|
|
40
|
-
letterSpacing: "0.1em",
|
|
41
|
-
}}
|
|
42
|
-
>
|
|
43
|
-
{projectName}
|
|
44
|
-
</div>
|
|
45
|
-
)}
|
|
46
|
-
<div
|
|
47
|
-
style={{
|
|
48
|
-
fontSize: 64,
|
|
49
|
-
fontWeight: 700,
|
|
50
|
-
color: "#fafafa",
|
|
51
|
-
lineHeight: 1.2,
|
|
52
|
-
marginBottom: 24,
|
|
53
|
-
maxWidth: "100%",
|
|
54
|
-
overflow: "hidden",
|
|
55
|
-
textOverflow: "ellipsis",
|
|
56
|
-
}}
|
|
57
|
-
>
|
|
58
|
-
{title}
|
|
59
|
-
</div>
|
|
60
|
-
{description && (
|
|
61
|
-
<div
|
|
62
|
-
style={{
|
|
63
|
-
fontSize: 28,
|
|
64
|
-
color: "#a1a1aa",
|
|
65
|
-
lineHeight: 1.5,
|
|
66
|
-
maxWidth: "80%",
|
|
67
|
-
overflow: "hidden",
|
|
68
|
-
textOverflow: "ellipsis",
|
|
69
|
-
}}
|
|
70
|
-
>
|
|
71
|
-
{description}
|
|
72
|
-
</div>
|
|
73
|
-
)}
|
|
74
|
-
</div>
|
|
75
|
-
),
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
function DefaultLayout({ children }: { children: React.ReactNode }) {
|
|
79
|
-
return (
|
|
80
|
-
<main className="flex min-h-screen flex-col">
|
|
81
|
-
<defaultLayout.BeforeBlocks />
|
|
82
|
-
<div className="flex-1">{children}</div>
|
|
83
|
-
<defaultLayout.AfterBlocks />
|
|
84
|
-
</main>
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export { defaultLayout as layout };
|
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
@import "tailwindcss";
|
|
2
|
-
@import "tw-animate-css";
|
|
3
|
-
@import "shadcn/tailwind.css";
|
|
4
|
-
@import "@fontsource-variable/inter";
|
|
5
|
-
@import "@fontsource-variable/noto-serif";
|
|
6
|
-
|
|
7
|
-
@custom-variant dark (&:is(.dark *));
|
|
8
|
-
|
|
9
|
-
body {
|
|
10
|
-
@apply m-0;
|
|
11
|
-
-webkit-font-smoothing: antialiased;
|
|
12
|
-
-moz-osx-font-smoothing: grayscale;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
:root {
|
|
16
|
-
--background: oklch(0.99 0.01 260);
|
|
17
|
-
--foreground: oklch(0 0 0);
|
|
18
|
-
--card: oklch(1 0 0);
|
|
19
|
-
--card-foreground: oklch(0 0 0);
|
|
20
|
-
--popover: oklch(1 0 0);
|
|
21
|
-
--popover-foreground: oklch(0 0 0);
|
|
22
|
-
--primary: oklch(0.623 0.214 259.815);
|
|
23
|
-
--primary-foreground: oklch(0.97 0.014 254.604);
|
|
24
|
-
--secondary: oklch(0.96 0.02 260);
|
|
25
|
-
--secondary-foreground: oklch(0.22 0.05 260);
|
|
26
|
-
--muted: oklch(0.96 0.02 260);
|
|
27
|
-
--muted-foreground: oklch(0.55 0.05 260);
|
|
28
|
-
--accent: oklch(0.96 0.02 260);
|
|
29
|
-
--accent-foreground: oklch(0.22 0.05 260);
|
|
30
|
-
--destructive: oklch(0.577 0.245 27.325);
|
|
31
|
-
--destructive-foreground: oklch(0.577 0.245 27.325);
|
|
32
|
-
--border: oklch(0.92 0.02 260);
|
|
33
|
-
--input: oklch(0.92 0.02 260);
|
|
34
|
-
--ring: oklch(0.7 0.05 260);
|
|
35
|
-
--chart-1: oklch(0.871 0.02 260);
|
|
36
|
-
--chart-2: oklch(0.62 0.19 260);
|
|
37
|
-
--chart-3: oklch(0.5 0.12 260);
|
|
38
|
-
--chart-4: oklch(0.4 0.08 260);
|
|
39
|
-
--chart-5: oklch(0.3 0.05 260);
|
|
40
|
-
--radius: 0.625rem;
|
|
41
|
-
--sidebar: oklch(0.99 0.01 260);
|
|
42
|
-
--sidebar-foreground: oklch(0 0 0);
|
|
43
|
-
--sidebar-primary: oklch(0.62 0.19 260);
|
|
44
|
-
--sidebar-primary-foreground: oklch(0.984 0.019 200.873);
|
|
45
|
-
--sidebar-accent: oklch(0.96 0.02 260);
|
|
46
|
-
--sidebar-accent-foreground: oklch(0.22 0.05 260);
|
|
47
|
-
--sidebar-border: oklch(0.92 0.02 260);
|
|
48
|
-
--sidebar-ring: oklch(0.7 0.05 260);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
.dark {
|
|
52
|
-
--background: oklch(0.17 0.05 260);
|
|
53
|
-
--foreground: oklch(0.985 0 0);
|
|
54
|
-
--card: oklch(0.22 0.05 260);
|
|
55
|
-
--card-foreground: oklch(0.985 0 0);
|
|
56
|
-
--popover: oklch(0.22 0.05 260);
|
|
57
|
-
--popover-foreground: oklch(0.985 0 0);
|
|
58
|
-
--primary: oklch(0.623 0.214 259.815);
|
|
59
|
-
--primary-foreground: oklch(0.97 0.014 254.604);
|
|
60
|
-
--secondary: oklch(0.3 0.05 260);
|
|
61
|
-
--secondary-foreground: oklch(0.985 0 0);
|
|
62
|
-
--muted: oklch(0.3 0.05 260);
|
|
63
|
-
--muted-foreground: oklch(0.72 0.03 260);
|
|
64
|
-
--accent: oklch(0.3 0.05 260);
|
|
65
|
-
--accent-foreground: oklch(0.985 0 0);
|
|
66
|
-
--destructive: oklch(0.704 0.191 22.216);
|
|
67
|
-
--destructive-foreground: oklch(0.637 0.237 25.331);
|
|
68
|
-
--border: oklch(1 0 0 / 10%);
|
|
69
|
-
--input: oklch(1 0 0 / 15%);
|
|
70
|
-
--ring: oklch(0.55 0.05 260);
|
|
71
|
-
--chart-1: oklch(0.871 0.02 260);
|
|
72
|
-
--chart-2: oklch(0.62 0.19 260);
|
|
73
|
-
--chart-3: oklch(0.5 0.12 260);
|
|
74
|
-
--chart-4: oklch(0.4 0.08 260);
|
|
75
|
-
--chart-5: oklch(0.3 0.05 260);
|
|
76
|
-
--sidebar: oklch(0.22 0.05 260);
|
|
77
|
-
--sidebar-foreground: oklch(0.985 0 0);
|
|
78
|
-
--sidebar-primary: oklch(0.62 0.19 260);
|
|
79
|
-
--sidebar-primary-foreground: oklch(0.984 0.019 200.873);
|
|
80
|
-
--sidebar-accent: oklch(0.3 0.05 260);
|
|
81
|
-
--sidebar-accent-foreground: oklch(0.985 0 0);
|
|
82
|
-
--sidebar-border: oklch(1 0 0 / 10%);
|
|
83
|
-
--sidebar-ring: oklch(0.55 0.05 260);
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
@theme inline {
|
|
87
|
-
--color-background: var(--background);
|
|
88
|
-
--color-foreground: var(--foreground);
|
|
89
|
-
--color-card: var(--card);
|
|
90
|
-
--color-card-foreground: var(--card-foreground);
|
|
91
|
-
--color-popover: var(--popover);
|
|
92
|
-
--color-popover-foreground: var(--popover-foreground);
|
|
93
|
-
--color-primary: var(--primary);
|
|
94
|
-
--color-primary-foreground: var(--primary-foreground);
|
|
95
|
-
--color-secondary: var(--secondary);
|
|
96
|
-
--color-secondary-foreground: var(--secondary-foreground);
|
|
97
|
-
--color-muted: var(--muted);
|
|
98
|
-
--color-muted-foreground: var(--muted-foreground);
|
|
99
|
-
--color-accent: var(--accent);
|
|
100
|
-
--color-accent-foreground: var(--accent-foreground);
|
|
101
|
-
--color-destructive: var(--destructive);
|
|
102
|
-
--color-destructive-foreground: var(--destructive-foreground);
|
|
103
|
-
--color-border: var(--border);
|
|
104
|
-
--color-input: var(--input);
|
|
105
|
-
--color-ring: var(--ring);
|
|
106
|
-
--color-chart-1: var(--chart-1);
|
|
107
|
-
--color-chart-2: var(--chart-2);
|
|
108
|
-
--color-chart-3: var(--chart-3);
|
|
109
|
-
--color-chart-4: var(--chart-4);
|
|
110
|
-
--color-chart-5: var(--chart-5);
|
|
111
|
-
--radius-sm: calc(var(--radius) - 4px);
|
|
112
|
-
--radius-md: calc(var(--radius) - 2px);
|
|
113
|
-
--radius-lg: var(--radius);
|
|
114
|
-
--radius-xl: calc(var(--radius) + 4px);
|
|
115
|
-
--color-sidebar: var(--sidebar);
|
|
116
|
-
--color-sidebar-foreground: var(--sidebar-foreground);
|
|
117
|
-
--color-sidebar-primary: var(--sidebar-primary);
|
|
118
|
-
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
|
119
|
-
--color-sidebar-accent: var(--sidebar-accent);
|
|
120
|
-
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
|
121
|
-
--color-sidebar-border: var(--sidebar-border);
|
|
122
|
-
--color-sidebar-ring: var(--sidebar-ring);
|
|
123
|
-
--font-sans: "Inter Variable", sans-serif;
|
|
124
|
-
--font-heading: "Inter Variable", sans-serif;
|
|
125
|
-
--radius-2xl: calc(var(--radius) * 1.8);
|
|
126
|
-
--radius-3xl: calc(var(--radius) * 2.2);
|
|
127
|
-
--radius-4xl: calc(var(--radius) * 2.6);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
@layer base {
|
|
131
|
-
* {
|
|
132
|
-
@apply border-border outline-ring/50;
|
|
133
|
-
}
|
|
134
|
-
body {
|
|
135
|
-
@apply bg-background text-foreground;
|
|
136
|
-
}
|
|
137
|
-
a:focus-visible {
|
|
138
|
-
@apply border-ring ring-ring/50 rounded-md ring-3 outline-none;
|
|
139
|
-
}
|
|
140
|
-
html {
|
|
141
|
-
@apply font-sans;
|
|
142
|
-
font-size: 14px;
|
|
143
|
-
@media (width >= theme(--breakpoint-sm)) {
|
|
144
|
-
font-size: 15px;
|
|
145
|
-
}
|
|
146
|
-
@media (width >= theme(--breakpoint-md)) {
|
|
147
|
-
font-size: 16px;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
@utility container {
|
|
153
|
-
margin-inline: auto;
|
|
154
|
-
padding-inline: 0.5rem;
|
|
155
|
-
max-width: 80rem;
|
|
156
|
-
@media (width >= theme(--breakpoint-sm)) {
|
|
157
|
-
padding-inline: 1rem;
|
|
158
|
-
}
|
|
159
|
-
@media (width >= theme(--breakpoint-md)) {
|
|
160
|
-
padding-inline: 2rem;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"include": ["./**/*.ts", "./**/*.tsx"],
|
|
3
|
-
"exclude": ["node_modules", "dist"],
|
|
4
|
-
"compilerOptions": {
|
|
5
|
-
"target": "ES2022",
|
|
6
|
-
"jsx": "react-jsx",
|
|
7
|
-
"module": "ESNext",
|
|
8
|
-
"lib": ["ES2022", "DOM", "DOM.Iterable"],
|
|
9
|
-
"types": ["vite-plus/client"],
|
|
10
|
-
"moduleResolution": "bundler",
|
|
11
|
-
"allowImportingTsExtensions": true,
|
|
12
|
-
"verbatimModuleSyntax": false,
|
|
13
|
-
"noEmit": true,
|
|
14
|
-
"allowJs": true,
|
|
15
|
-
"skipLibCheck": true,
|
|
16
|
-
"strict": true,
|
|
17
|
-
"noUnusedLocals": true,
|
|
18
|
-
"noUnusedParameters": true,
|
|
19
|
-
"noFallthroughCasesInSwitch": true,
|
|
20
|
-
"noUncheckedSideEffectImports": true,
|
|
21
|
-
"paths": {
|
|
22
|
-
"@/*": ["./src/*"]
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|