veslx 0.1.22 → 0.1.24
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/client/components/gallery/components/figure-caption.js +1 -1
- package/dist/client/components/gallery/components/figure-caption.js.map +1 -1
- package/dist/client/components/gallery/components/figure-header.js +1 -1
- package/dist/client/components/gallery/components/figure-header.js.map +1 -1
- package/dist/client/components/gallery/components/lightbox.js +1 -1
- package/dist/client/components/gallery/components/lightbox.js.map +1 -1
- package/dist/client/components/gallery/index.js +37 -7
- package/dist/client/components/gallery/index.js.map +1 -1
- package/dist/client/components/header.js +45 -21
- package/dist/client/components/header.js.map +1 -1
- package/dist/client/components/mdx-components.js +8 -0
- package/dist/client/components/mdx-components.js.map +1 -1
- package/dist/client/components/post-list.js +13 -11
- package/dist/client/components/post-list.js.map +1 -1
- package/dist/client/components/slides/figure-slide.js +14 -0
- package/dist/client/components/slides/figure-slide.js.map +1 -0
- package/dist/client/components/slides/hero-slide.js +21 -0
- package/dist/client/components/slides/hero-slide.js.map +1 -0
- package/dist/client/components/slides/slide-outline.js +28 -0
- package/dist/client/components/slides/slide-outline.js.map +1 -0
- package/dist/client/components/slides/text-slide.js +18 -0
- package/dist/client/components/slides/text-slide.js.map +1 -0
- package/dist/client/components/slides-renderer.js.map +1 -1
- package/dist/client/pages/home.js +2 -6
- package/dist/client/pages/home.js.map +1 -1
- package/dist/client/pages/slides.js +7 -11
- package/dist/client/pages/slides.js.map +1 -1
- package/index.html +27 -0
- package/package.json +1 -1
- package/plugin/src/plugin.ts +65 -0
- package/plugin/src/types.ts +3 -0
- package/src/components/content-tabs.tsx +4 -4
- package/src/components/gallery/components/figure-caption.tsx +1 -1
- package/src/components/gallery/components/figure-header.tsx +1 -1
- package/src/components/gallery/components/lightbox.tsx +1 -1
- package/src/components/gallery/index.tsx +68 -29
- package/src/components/header.tsx +44 -25
- package/src/components/mdx-components.tsx +12 -0
- package/src/components/post-list.tsx +14 -10
- package/src/components/slides/figure-slide.tsx +16 -0
- package/src/components/slides/hero-slide.tsx +34 -0
- package/src/components/slides/slide-outline.tsx +38 -0
- package/src/components/slides/text-slide.tsx +35 -0
- package/src/components/slides-renderer.tsx +1 -1
- package/src/index.css +5 -0
- package/src/pages/home.tsx +3 -3
- package/src/pages/slides.tsx +7 -12
- package/dist/client/components/content-tabs.js +0 -50
- package/dist/client/components/content-tabs.js.map +0 -1
|
@@ -2,7 +2,7 @@ import { Link } from "react-router-dom";
|
|
|
2
2
|
import { cn } from "@/lib/utils";
|
|
3
3
|
import type { DirectoryEntry } from "../../plugin/src/lib";
|
|
4
4
|
import { formatDate } from "@/lib/format-date";
|
|
5
|
-
import { ArrowRight } from "lucide-react";
|
|
5
|
+
import { ArrowRight, Presentation } from "lucide-react";
|
|
6
6
|
import {
|
|
7
7
|
type ContentView,
|
|
8
8
|
type PostEntry,
|
|
@@ -117,6 +117,8 @@ export default function PostList({ directory, view = 'all' }: PostListProps) {
|
|
|
117
117
|
linkPath = `/${post.path}`;
|
|
118
118
|
}
|
|
119
119
|
|
|
120
|
+
const isSlides = linkPath.endsWith('SLIDES.mdx');
|
|
121
|
+
|
|
120
122
|
return (
|
|
121
123
|
<Link
|
|
122
124
|
key={post.path}
|
|
@@ -126,15 +128,7 @@ export default function PostList({ directory, view = 'all' }: PostListProps) {
|
|
|
126
128
|
"transition-colors duration-150",
|
|
127
129
|
)}
|
|
128
130
|
>
|
|
129
|
-
<article className="flex items-
|
|
130
|
-
{/* Date - left side, fixed width */}
|
|
131
|
-
<time
|
|
132
|
-
dateTime={date?.toISOString()}
|
|
133
|
-
className="font-mono text-xs text-muted-foreground tabular-nums w-20 flex-shrink-0 pt-0.5"
|
|
134
|
-
>
|
|
135
|
-
{date ? formatDate(date) : <span className="text-muted-foreground/30">—</span>}
|
|
136
|
-
</time>
|
|
137
|
-
|
|
131
|
+
<article className="flex items-center gap-4">
|
|
138
132
|
{/* Main content */}
|
|
139
133
|
<div className="flex-1 min-w-0">
|
|
140
134
|
<h3 className={cn(
|
|
@@ -152,6 +146,16 @@ export default function PostList({ directory, view = 'all' }: PostListProps) {
|
|
|
152
146
|
</p>
|
|
153
147
|
)}
|
|
154
148
|
</div>
|
|
149
|
+
|
|
150
|
+
{isSlides && (
|
|
151
|
+
<Presentation className="h-3 w-3 text-muted-foreground" />
|
|
152
|
+
)}
|
|
153
|
+
<time
|
|
154
|
+
dateTime={date?.toISOString()}
|
|
155
|
+
className="font-mono text-xs text-muted-foreground tabular-nums w-20 flex-shrink-0"
|
|
156
|
+
>
|
|
157
|
+
{date && formatDate(date)}
|
|
158
|
+
</time>
|
|
155
159
|
</article>
|
|
156
160
|
</Link>
|
|
157
161
|
);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
|
|
2
|
+
export function HeroSlide({
|
|
3
|
+
title,
|
|
4
|
+
subtitle,
|
|
5
|
+
author,
|
|
6
|
+
date,
|
|
7
|
+
}: {
|
|
8
|
+
title: string;
|
|
9
|
+
subtitle?: string;
|
|
10
|
+
author?: string;
|
|
11
|
+
date?: string;
|
|
12
|
+
}) {
|
|
13
|
+
return (
|
|
14
|
+
<div>
|
|
15
|
+
<h1 className="text-[clamp(2.5rem,6vw,5rem)] font-semibold leading-[1.1] tracking-[-0.02em] text-foreground text-balance">
|
|
16
|
+
{title}
|
|
17
|
+
</h1>
|
|
18
|
+
|
|
19
|
+
{subtitle && (
|
|
20
|
+
<p className="text-[clamp(1rem,2vw,1.5rem)] text-muted-foreground max-w-[50ch] leading-relaxed">
|
|
21
|
+
{subtitle}
|
|
22
|
+
</p>
|
|
23
|
+
)}
|
|
24
|
+
|
|
25
|
+
{(author || date) && (
|
|
26
|
+
<div className="flex flex-wrap gap-x-4 gap-y-1 text-sm text-muted-foreground mt-4">
|
|
27
|
+
{author && <span>{author}</span>}
|
|
28
|
+
{author && date && <span className="text-border">·</span>}
|
|
29
|
+
{date && <span>{date}</span>}
|
|
30
|
+
</div>
|
|
31
|
+
)}
|
|
32
|
+
</div>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
export function SlideOutline({
|
|
4
|
+
children,
|
|
5
|
+
className,
|
|
6
|
+
size="md"
|
|
7
|
+
}: {
|
|
8
|
+
children?: React.ReactNode;
|
|
9
|
+
className?: string;
|
|
10
|
+
size?: "sm" | "md" | "lg" | "xl" | "2xl" | "3xl" | "full";
|
|
11
|
+
}) {
|
|
12
|
+
|
|
13
|
+
const wClasses: Record<string, string> = {
|
|
14
|
+
sm: "max-w-lg",
|
|
15
|
+
md: "max-w-2xl",
|
|
16
|
+
lg: "max-w-5xl",
|
|
17
|
+
xl: "max-w-7xl",
|
|
18
|
+
full: "max-w-full",
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const wClassName = `${wClasses[size]} ${className ?? ""}`;
|
|
22
|
+
|
|
23
|
+
const hClasses: Record<string, string> = {
|
|
24
|
+
sm: "min-h-[300px]",
|
|
25
|
+
md: "min-h-[400px]",
|
|
26
|
+
lg: "min-h-[500px]",
|
|
27
|
+
xl: "min-h-[600px]",
|
|
28
|
+
full: "min-h-[600px]",
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
const hClassName = `${hClasses[size]} ${className ?? ""}`;
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<div className={`border rounded relative left-1/2 -translate-x-1/2 w-screen ${wClassName} ${hClassName} ${className}`}>
|
|
35
|
+
{children}
|
|
36
|
+
</div>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
|
|
2
|
+
export function TextSlide({
|
|
3
|
+
title,
|
|
4
|
+
subtitle,
|
|
5
|
+
children,
|
|
6
|
+
}: {
|
|
7
|
+
title?: string;
|
|
8
|
+
subtitle?: string;
|
|
9
|
+
children?: React.ReactNode;
|
|
10
|
+
}) {
|
|
11
|
+
return (
|
|
12
|
+
<div>
|
|
13
|
+
{(title || subtitle) && (
|
|
14
|
+
<header className="flex flex-col gap-2">
|
|
15
|
+
{title && (
|
|
16
|
+
<h2 className="text-[clamp(1.75rem,4vw,3rem)] font-semibold leading-tight tracking-[-0.02em] text-foreground">
|
|
17
|
+
{title}
|
|
18
|
+
</h2>
|
|
19
|
+
)}
|
|
20
|
+
{subtitle && (
|
|
21
|
+
<p className="text-[clamp(0.95rem,1.5vw,1.25rem)] text-muted-foreground">
|
|
22
|
+
{subtitle}
|
|
23
|
+
</p>
|
|
24
|
+
)}
|
|
25
|
+
</header>
|
|
26
|
+
)}
|
|
27
|
+
|
|
28
|
+
{children && (
|
|
29
|
+
<div className="text-[clamp(1rem,1.8vw,1.35rem)] leading-[1.6] text-foreground/90 space-y-4 [&>ul]:space-y-2 [&>ul]:list-disc [&>ul]:pl-6 [&>ol]:space-y-2 [&>ol]:list-decimal [&>ol]:pl-6">
|
|
30
|
+
{children}
|
|
31
|
+
</div>
|
|
32
|
+
)}
|
|
33
|
+
</div>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
@@ -15,7 +15,7 @@ export const slidesMdxComponents = {
|
|
|
15
15
|
*/
|
|
16
16
|
export function SlideContent({ children }: { children: ReactNode }) {
|
|
17
17
|
return (
|
|
18
|
-
<div className="slide-content prose dark:prose-invert prose-headings:tracking-tight prose-p:leading-relaxed
|
|
18
|
+
<div className="slide-content prose dark:prose-invert prose-headings:tracking-tight prose-p:leading-relaxed">
|
|
19
19
|
{children}
|
|
20
20
|
</div>
|
|
21
21
|
)
|
package/src/index.css
CHANGED
package/src/pages/home.tsx
CHANGED
|
@@ -68,12 +68,12 @@ export function Home({ view }: HomeProps) {
|
|
|
68
68
|
</div>
|
|
69
69
|
)}
|
|
70
70
|
|
|
71
|
-
<div className="">
|
|
72
|
-
{isRoot && directory && (
|
|
71
|
+
<div className="flex flex-col gap-2">
|
|
72
|
+
{/* {isRoot && directory && (
|
|
73
73
|
<div className="animate-fade-in">
|
|
74
74
|
<ContentTabs value={activeView} counts={counts} />
|
|
75
75
|
</div>
|
|
76
|
-
)}
|
|
76
|
+
)} */}
|
|
77
77
|
{directory && (
|
|
78
78
|
<div className="animate-fade-in">
|
|
79
79
|
<PostList directory={directory} view={isRoot ? activeView : 'all'} />
|
package/src/pages/slides.tsx
CHANGED
|
@@ -19,8 +19,7 @@ export function SlidesPage() {
|
|
|
19
19
|
// Load the compiled MDX module (now includes slideCount export)
|
|
20
20
|
const { Content, frontmatter, slideCount, loading, error } = useMDXSlides(mdxPath);
|
|
21
21
|
|
|
22
|
-
|
|
23
|
-
const totalSlides = (slideCount || 0) + 1;
|
|
22
|
+
const totalSlides = slideCount || 0;
|
|
24
23
|
|
|
25
24
|
const [currentSlide, setCurrentSlide] = useState(0);
|
|
26
25
|
const titleSlideRef = useRef<HTMLDivElement>(null);
|
|
@@ -30,7 +29,7 @@ export function SlidesPage() {
|
|
|
30
29
|
useEffect(() => {
|
|
31
30
|
const slideParam = parseInt(searchParams.get("slide") || "0", 10);
|
|
32
31
|
if (slideParam > 0 && contentRef.current) {
|
|
33
|
-
const slideEl = contentRef.current.querySelector(`[data-slide-index="${slideParam
|
|
32
|
+
const slideEl = contentRef.current.querySelector(`[data-slide-index="${slideParam}"]`);
|
|
34
33
|
if (slideEl) {
|
|
35
34
|
slideEl.scrollIntoView({ behavior: "auto" });
|
|
36
35
|
}
|
|
@@ -45,7 +44,7 @@ export function SlidesPage() {
|
|
|
45
44
|
if (entry.isIntersecting) {
|
|
46
45
|
const index = entry.target.getAttribute("data-slide-index");
|
|
47
46
|
if (index !== null) {
|
|
48
|
-
const slideNum = index === "title" ? 0 : parseInt(index, 10)
|
|
47
|
+
const slideNum = index === "title" ? 0 : parseInt(index, 10);
|
|
49
48
|
setCurrentSlide(slideNum);
|
|
50
49
|
setSearchParams(slideNum > 0 ? { slide: String(slideNum) } : {}, { replace: true });
|
|
51
50
|
}
|
|
@@ -72,20 +71,16 @@ export function SlidesPage() {
|
|
|
72
71
|
// Keyboard/scroll navigation helpers
|
|
73
72
|
const goToPrevious = useCallback(() => {
|
|
74
73
|
const prev = Math.max(0, currentSlide - 1);
|
|
75
|
-
if (
|
|
76
|
-
|
|
77
|
-
} else if (contentRef.current) {
|
|
78
|
-
const slideEl = contentRef.current.querySelector(`[data-slide-index="${prev - 1}"]`);
|
|
74
|
+
if (contentRef.current) {
|
|
75
|
+
const slideEl = contentRef.current.querySelector(`[data-slide-index="${prev}"]`);
|
|
79
76
|
slideEl?.scrollIntoView({ behavior: "smooth" });
|
|
80
77
|
}
|
|
81
78
|
}, [currentSlide]);
|
|
82
79
|
|
|
83
80
|
const goToNext = useCallback(() => {
|
|
84
81
|
const next = Math.min(totalSlides - 1, currentSlide + 1);
|
|
85
|
-
if (
|
|
86
|
-
|
|
87
|
-
} else if (contentRef.current) {
|
|
88
|
-
const slideEl = contentRef.current.querySelector(`[data-slide-index="${next - 1}"]`);
|
|
82
|
+
if (contentRef.current) {
|
|
83
|
+
const slideEl = contentRef.current.querySelector(`[data-slide-index="${next}"]`);
|
|
89
84
|
slideEl?.scrollIntoView({ behavior: "smooth" });
|
|
90
85
|
}
|
|
91
86
|
}, [currentSlide, totalSlides]);
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Link } from "react-router-dom";
|
|
3
|
-
import { cn } from "../lib/utils.js";
|
|
4
|
-
const views = [
|
|
5
|
-
{ key: "posts", label: "posts", path: "/posts" },
|
|
6
|
-
{ key: "docs", label: "docs", path: "/docs" },
|
|
7
|
-
{ key: "all", label: "all", path: "/all" }
|
|
8
|
-
];
|
|
9
|
-
function ContentTabs({ value, counts }) {
|
|
10
|
-
const hasOnlyPosts = counts.posts > 0 && counts.docs === 0;
|
|
11
|
-
const hasOnlyDocs = counts.docs > 0 && counts.posts === 0;
|
|
12
|
-
if (hasOnlyPosts || hasOnlyDocs) {
|
|
13
|
-
return null;
|
|
14
|
-
}
|
|
15
|
-
const isDisabled = (key) => {
|
|
16
|
-
if (key === "posts") return counts.posts === 0;
|
|
17
|
-
if (key === "docs") return counts.docs === 0;
|
|
18
|
-
return false;
|
|
19
|
-
};
|
|
20
|
-
return /* @__PURE__ */ jsx("nav", { className: "flex justify-end items-center gap-3 font-mono font-medium text-xs text-muted-foreground", children: views.map((view) => {
|
|
21
|
-
const disabled = isDisabled(view.key);
|
|
22
|
-
if (disabled) {
|
|
23
|
-
return /* @__PURE__ */ jsx(
|
|
24
|
-
"span",
|
|
25
|
-
{
|
|
26
|
-
className: "opacity-30 cursor-not-allowed",
|
|
27
|
-
children: view.label
|
|
28
|
-
},
|
|
29
|
-
view.key
|
|
30
|
-
);
|
|
31
|
-
}
|
|
32
|
-
return /* @__PURE__ */ jsx(
|
|
33
|
-
Link,
|
|
34
|
-
{
|
|
35
|
-
to: view.path,
|
|
36
|
-
className: cn(
|
|
37
|
-
"transition-colors duration-150",
|
|
38
|
-
"hover:text-foreground hover:underline hover:underline-offset-4 hover:decoration-primary/60",
|
|
39
|
-
value === view.key ? "text-foreground underline-offset-4 decoration-primary/60" : ""
|
|
40
|
-
),
|
|
41
|
-
children: view.label
|
|
42
|
-
},
|
|
43
|
-
view.key
|
|
44
|
-
);
|
|
45
|
-
}) });
|
|
46
|
-
}
|
|
47
|
-
export {
|
|
48
|
-
ContentTabs
|
|
49
|
-
};
|
|
50
|
-
//# sourceMappingURL=content-tabs.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"content-tabs.js","sources":["../../../src/components/content-tabs.tsx"],"sourcesContent":["import { Link } from \"react-router-dom\";\nimport { cn } from \"@/lib/utils\";\nimport type { ContentView } from \"@/lib/content-classification\";\n\ninterface ContentTabsProps {\n value: ContentView;\n counts: { posts: number; docs: number; all: number };\n}\n\nconst views: { key: ContentView; label: string; path: string }[] = [\n { key: \"posts\", label: \"posts\", path: \"/posts\" },\n { key: \"docs\", label: \"docs\", path: \"/docs\" },\n { key: \"all\", label: \"all\", path: \"/all\" },\n];\n\nexport function ContentTabs({ value, counts }: ContentTabsProps) {\n const hasOnlyPosts = counts.posts > 0 && counts.docs === 0;\n const hasOnlyDocs = counts.docs > 0 && counts.posts === 0;\n\n if (hasOnlyPosts || hasOnlyDocs) {\n return null;\n }\n\n const isDisabled = (key: ContentView) => {\n if (key === \"posts\") return counts.posts === 0;\n if (key === \"docs\") return counts.docs === 0;\n return false;\n };\n\n return (\n <nav className=\"flex justify-end items-center gap-3 font-mono font-medium text-xs text-muted-foreground\">\n {views.map((view) => {\n const disabled = isDisabled(view.key);\n\n if (disabled) {\n return (\n <span\n key={view.key}\n className=\"opacity-30 cursor-not-allowed\"\n >\n {view.label}\n </span>\n );\n }\n\n return (\n <Link\n key={view.key}\n to={view.path}\n className={cn(\n \"transition-colors duration-150\",\n \"hover:text-foreground hover:underline hover:underline-offset-4 hover:decoration-primary/60\",\n value === view.key\n ? \"text-foreground underline-offset-4 decoration-primary/60\"\n : \"\"\n )}\n >\n {view.label}\n </Link>\n );\n })}\n </nav>\n );\n}\n"],"names":[],"mappings":";;;AASA,MAAM,QAA6D;AAAA,EACjE,EAAE,KAAK,SAAS,OAAO,SAAS,MAAM,SAAA;AAAA,EACtC,EAAE,KAAK,QAAQ,OAAO,QAAQ,MAAM,QAAA;AAAA,EACpC,EAAE,KAAK,OAAO,OAAO,OAAO,MAAM,OAAA;AACpC;AAEO,SAAS,YAAY,EAAE,OAAO,UAA4B;AAC/D,QAAM,eAAe,OAAO,QAAQ,KAAK,OAAO,SAAS;AACzD,QAAM,cAAc,OAAO,OAAO,KAAK,OAAO,UAAU;AAExD,MAAI,gBAAgB,aAAa;AAC/B,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,CAAC,QAAqB;AACvC,QAAI,QAAQ,QAAS,QAAO,OAAO,UAAU;AAC7C,QAAI,QAAQ,OAAQ,QAAO,OAAO,SAAS;AAC3C,WAAO;AAAA,EACT;AAEA,6BACG,OAAA,EAAI,WAAU,2FACZ,UAAA,MAAM,IAAI,CAAC,SAAS;AACnB,UAAM,WAAW,WAAW,KAAK,GAAG;AAEpC,QAAI,UAAU;AACZ,aACE;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,WAAU;AAAA,UAET,UAAA,KAAK;AAAA,QAAA;AAAA,QAHD,KAAK;AAAA,MAAA;AAAA,IAMhB;AAEA,WACE;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,IAAI,KAAK;AAAA,QACT,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA,UAAU,KAAK,MACX,6DACA;AAAA,QAAA;AAAA,QAGL,UAAA,KAAK;AAAA,MAAA;AAAA,MAVD,KAAK;AAAA,IAAA;AAAA,EAahB,CAAC,EAAA,CACH;AAEJ;"}
|