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 { jsx, jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { renderMathInText } from "../lib/render-math-in-text.js";
|
|
3
3
|
function FigureCaption({ caption, label }) {
|
|
4
4
|
if (!caption && !label) return null;
|
|
5
|
-
return /* @__PURE__ */ jsx("figcaption", { className: "
|
|
5
|
+
return /* @__PURE__ */ jsx("figcaption", { className: "mt-4", children: /* @__PURE__ */ jsxs("p", { className: "text-[13px] leading-[1.6] text-muted-foreground", children: [
|
|
6
6
|
label && /* @__PURE__ */ jsxs("span", { className: "font-semibold text-foreground tracking-tight", children: [
|
|
7
7
|
label,
|
|
8
8
|
caption && /* @__PURE__ */ jsx("span", { className: "font-normal mx-1.5", children: "·" })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"figure-caption.js","sources":["../../../../../src/components/gallery/components/figure-caption.tsx"],"sourcesContent":["import { renderMathInText } from \"../lib/render-math-in-text\";\n\nexport function FigureCaption({ caption, label }: { caption?: string; label?: string }) {\n if (!caption && !label) return null;\n\n return (\n <figcaption className=\"
|
|
1
|
+
{"version":3,"file":"figure-caption.js","sources":["../../../../../src/components/gallery/components/figure-caption.tsx"],"sourcesContent":["import { renderMathInText } from \"../lib/render-math-in-text\";\n\nexport function FigureCaption({ caption, label }: { caption?: string; label?: string }) {\n if (!caption && !label) return null;\n\n return (\n <figcaption className=\"mt-4\">\n <p className=\"text-[13px] leading-[1.6] text-muted-foreground\">\n {label && (\n <span className=\"font-semibold text-foreground tracking-tight\">\n {label}\n {caption && <span className=\"font-normal mx-1.5\">·</span>}\n </span>\n )}\n {caption && (\n <span className=\"text-muted-foreground/90\">\n {renderMathInText(caption)}\n </span>\n )}\n </p>\n </figcaption>\n );\n}\n"],"names":[],"mappings":";;AAEO,SAAS,cAAc,EAAE,SAAS,SAA+C;AACtF,MAAI,CAAC,WAAW,CAAC,MAAO,QAAO;AAE/B,6BACG,cAAA,EAAW,WAAU,QACpB,UAAA,qBAAC,KAAA,EAAE,WAAU,mDACV,UAAA;AAAA,IAAA,SACC,qBAAC,QAAA,EAAK,WAAU,gDACb,UAAA;AAAA,MAAA;AAAA,MACA,WAAW,oBAAC,QAAA,EAAK,WAAU,sBAAqB,UAAA,IAAA,CAAC;AAAA,IAAA,GACpD;AAAA,IAED,WACC,oBAAC,QAAA,EAAK,WAAU,4BACb,UAAA,iBAAiB,OAAO,EAAA,CAC3B;AAAA,EAAA,EAAA,CAEJ,EAAA,CACF;AAEJ;"}
|
|
@@ -2,7 +2,7 @@ import { jsxs, jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { renderMathInText } from "../lib/render-math-in-text.js";
|
|
3
3
|
function FigureHeader({ title, subtitle }) {
|
|
4
4
|
if (!title && !subtitle) return null;
|
|
5
|
-
return /* @__PURE__ */ jsxs("div", { className: "
|
|
5
|
+
return /* @__PURE__ */ jsxs("div", { className: "mb-4", children: [
|
|
6
6
|
title && /* @__PURE__ */ jsx("h3", { className: "text-[15px] font-medium tracking-[-0.01em] text-foreground", children: renderMathInText(title) }),
|
|
7
7
|
subtitle && /* @__PURE__ */ jsx("p", { className: "text-[13px] text-muted-foreground/80 leading-relaxed mt-1", children: renderMathInText(subtitle) })
|
|
8
8
|
] });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"figure-header.js","sources":["../../../../../src/components/gallery/components/figure-header.tsx"],"sourcesContent":["import { renderMathInText } from \"../lib/render-math-in-text\";\n\nexport function FigureHeader({ title, subtitle }: { title?: string; subtitle?: string }) {\n if (!title && !subtitle) return null;\n\n return (\n <div className=\"
|
|
1
|
+
{"version":3,"file":"figure-header.js","sources":["../../../../../src/components/gallery/components/figure-header.tsx"],"sourcesContent":["import { renderMathInText } from \"../lib/render-math-in-text\";\n\nexport function FigureHeader({ title, subtitle }: { title?: string; subtitle?: string }) {\n if (!title && !subtitle) return null;\n\n return (\n <div className=\"mb-4\">\n {title && (\n <h3 className=\"text-[15px] font-medium tracking-[-0.01em] text-foreground\">\n {renderMathInText(title)}\n </h3>\n )}\n {subtitle && (\n <p className=\"text-[13px] text-muted-foreground/80 leading-relaxed mt-1\">\n {renderMathInText(subtitle)}\n </p>\n )}\n </div>\n );\n}\n"],"names":[],"mappings":";;AAEO,SAAS,aAAa,EAAE,OAAO,YAAmD;AACvF,MAAI,CAAC,SAAS,CAAC,SAAU,QAAO;AAEhC,SACE,qBAAC,OAAA,EAAI,WAAU,QACZ,UAAA;AAAA,IAAA,6BACE,MAAA,EAAG,WAAU,8DACX,UAAA,iBAAiB,KAAK,GACzB;AAAA,IAED,YACC,oBAAC,KAAA,EAAE,WAAU,6DACV,UAAA,iBAAiB,QAAQ,EAAA,CAC5B;AAAA,EAAA,GAEJ;AAEJ;"}
|
|
@@ -15,7 +15,7 @@ function Lightbox({
|
|
|
15
15
|
/* @__PURE__ */ jsxs(
|
|
16
16
|
"div",
|
|
17
17
|
{
|
|
18
|
-
className: "fixed inset-0 z-[9999] bg-background/98 backdrop-blur-md animate-fade-
|
|
18
|
+
className: "fixed inset-0 z-[9999] bg-background/98 backdrop-blur-md animate-[fade-in_150ms_ease-out]",
|
|
19
19
|
onClick: onClose,
|
|
20
20
|
...{ [FULLSCREEN_DATA_ATTR]: "true" },
|
|
21
21
|
style: { top: 0, left: 0, right: 0, bottom: 0 },
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lightbox.js","sources":["../../../../../src/components/gallery/components/lightbox.tsx"],"sourcesContent":["import { createPortal } from \"react-dom\";\nimport { X, ChevronLeft, ChevronRight } from \"lucide-react\";\nimport { FULLSCREEN_DATA_ATTR } from \"@/lib/constants\";\n\nexport interface LightboxImage {\n src: string;\n label: string;\n}\n\nexport interface LightboxProps {\n images: LightboxImage[];\n selectedIndex: number;\n onClose: () => void;\n onPrevious: () => void;\n onNext: () => void;\n showNavigation?: boolean;\n}\n\n/**\n * Fullscreen lightbox component for viewing images\n */\nexport function Lightbox({\n images,\n selectedIndex,\n onClose,\n onPrevious,\n onNext,\n showNavigation = true,\n}: LightboxProps) {\n const current = images[selectedIndex];\n\n return createPortal(\n <div\n className=\"fixed inset-0 z-[9999] bg-background/98 backdrop-blur-md animate-fade-
|
|
1
|
+
{"version":3,"file":"lightbox.js","sources":["../../../../../src/components/gallery/components/lightbox.tsx"],"sourcesContent":["import { createPortal } from \"react-dom\";\nimport { X, ChevronLeft, ChevronRight } from \"lucide-react\";\nimport { FULLSCREEN_DATA_ATTR } from \"@/lib/constants\";\n\nexport interface LightboxImage {\n src: string;\n label: string;\n}\n\nexport interface LightboxProps {\n images: LightboxImage[];\n selectedIndex: number;\n onClose: () => void;\n onPrevious: () => void;\n onNext: () => void;\n showNavigation?: boolean;\n}\n\n/**\n * Fullscreen lightbox component for viewing images\n */\nexport function Lightbox({\n images,\n selectedIndex,\n onClose,\n onPrevious,\n onNext,\n showNavigation = true,\n}: LightboxProps) {\n const current = images[selectedIndex];\n\n return createPortal(\n <div\n className=\"fixed inset-0 z-[9999] bg-background/98 backdrop-blur-md animate-[fade-in_150ms_ease-out]\"\n onClick={onClose}\n {...{ [FULLSCREEN_DATA_ATTR]: \"true\" }}\n style={{ top: 0, left: 0, right: 0, bottom: 0 }}\n >\n {/* Top bar */}\n <div\n className=\"fixed top-0 left-0 right-0 z-10 flex items-center justify-between px-6 py-4\"\n onClick={(e) => e.stopPropagation()}\n >\n <div className=\"font-mono text-[11px] text-muted-foreground/60 tabular-nums tracking-wider uppercase\">\n {String(selectedIndex + 1).padStart(2, '0')}\n <span className=\"mx-1.5 text-muted-foreground/30\">/</span>\n {String(images.length).padStart(2, '0')}\n </div>\n <button\n onClick={onClose}\n className=\"p-2 -m-2 text-muted-foreground/50 hover:text-foreground transition-colors duration-200\"\n aria-label=\"Close\"\n >\n <X className=\"h-4 w-4\" strokeWidth={1.5} />\n </button>\n </div>\n\n {/* Navigation: Previous */}\n {showNavigation && selectedIndex > 0 && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n onPrevious();\n }}\n className=\"fixed left-6 top-1/2 -translate-y-1/2 z-10 p-3 -m-3 text-muted-foreground/40 hover:text-foreground transition-colors duration-200\"\n aria-label=\"Previous image\"\n >\n <ChevronLeft className=\"h-6 w-6\" strokeWidth={1.5} />\n </button>\n )}\n\n {/* Navigation: Next */}\n {showNavigation && selectedIndex < images.length - 1 && (\n <button\n onClick={(e) => {\n e.stopPropagation();\n onNext();\n }}\n className=\"fixed right-6 top-1/2 -translate-y-1/2 z-10 p-3 -m-3 text-muted-foreground/40 hover:text-foreground transition-colors duration-200\"\n aria-label=\"Next image\"\n >\n <ChevronRight className=\"h-6 w-6\" strokeWidth={1.5} />\n </button>\n )}\n\n {/* Main image */}\n <div className=\"fixed inset-0 flex items-center justify-center p-16\">\n <img\n src={current.src}\n alt={current.label}\n className=\"max-w-full max-h-full object-contain rounded-sm shadow-2xl\"\n onClick={(e) => e.stopPropagation()}\n />\n </div>\n\n {/* Caption */}\n <div\n className=\"fixed bottom-0 left-0 right-0 z-10 px-6 py-5 text-center\"\n onClick={(e) => e.stopPropagation()}\n >\n <span className=\"font-mono text-[11px] text-muted-foreground/50 tracking-wide\">\n {current.label}\n </span>\n </div>\n </div>,\n document.body\n );\n}\n"],"names":[],"mappings":";;;;AAqBO,SAAS,SAAS;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AACnB,GAAkB;AAChB,QAAM,UAAU,OAAO,aAAa;AAEpC,SAAO;AAAA,IACL;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,SAAS;AAAA,QACR,GAAG,EAAE,CAAC,oBAAoB,GAAG,OAAA;AAAA,QAC9B,OAAO,EAAE,KAAK,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,EAAA;AAAA,QAG5C,UAAA;AAAA,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,SAAS,CAAC,MAAM,EAAE,gBAAA;AAAA,cAElB,UAAA;AAAA,gBAAA,qBAAC,OAAA,EAAI,WAAU,wFACZ,UAAA;AAAA,kBAAA,OAAO,gBAAgB,CAAC,EAAE,SAAS,GAAG,GAAG;AAAA,kBAC1C,oBAAC,QAAA,EAAK,WAAU,mCAAkC,UAAA,KAAC;AAAA,kBAClD,OAAO,OAAO,MAAM,EAAE,SAAS,GAAG,GAAG;AAAA,gBAAA,GACxC;AAAA,gBACA;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,SAAS;AAAA,oBACT,WAAU;AAAA,oBACV,cAAW;AAAA,oBAEX,UAAA,oBAAC,GAAA,EAAE,WAAU,WAAU,aAAa,IAAA,CAAK;AAAA,kBAAA;AAAA,gBAAA;AAAA,cAC3C;AAAA,YAAA;AAAA,UAAA;AAAA,UAID,kBAAkB,gBAAgB,KACjC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAAS,CAAC,MAAM;AACd,kBAAE,gBAAA;AACF,2BAAA;AAAA,cACF;AAAA,cACA,WAAU;AAAA,cACV,cAAW;AAAA,cAEX,UAAA,oBAAC,aAAA,EAAY,WAAU,WAAU,aAAa,IAAA,CAAK;AAAA,YAAA;AAAA,UAAA;AAAA,UAKtD,kBAAkB,gBAAgB,OAAO,SAAS,KACjD;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,SAAS,CAAC,MAAM;AACd,kBAAE,gBAAA;AACF,uBAAA;AAAA,cACF;AAAA,cACA,WAAU;AAAA,cACV,cAAW;AAAA,cAEX,UAAA,oBAAC,cAAA,EAAa,WAAU,WAAU,aAAa,IAAA,CAAK;AAAA,YAAA;AAAA,UAAA;AAAA,UAKxD,oBAAC,OAAA,EAAI,WAAU,uDACb,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,KAAK,QAAQ;AAAA,cACb,KAAK,QAAQ;AAAA,cACb,WAAU;AAAA,cACV,SAAS,CAAC,MAAM,EAAE,gBAAA;AAAA,YAAgB;AAAA,UAAA,GAEtC;AAAA,UAGA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,WAAU;AAAA,cACV,SAAS,CAAC,MAAM,EAAE,gBAAA;AAAA,cAElB,UAAA,oBAAC,QAAA,EAAK,WAAU,gEACb,kBAAQ,MAAA,CACX;AAAA,YAAA;AAAA,UAAA;AAAA,QACF;AAAA,MAAA;AAAA,IAAA;AAAA,IAEF,SAAS;AAAA,EAAA;AAEb;"}
|
|
@@ -23,7 +23,9 @@ function Gallery({
|
|
|
23
23
|
title,
|
|
24
24
|
subtitle,
|
|
25
25
|
limit = null,
|
|
26
|
-
page = 0
|
|
26
|
+
page = 0,
|
|
27
|
+
children,
|
|
28
|
+
childAlign = "right"
|
|
27
29
|
}) {
|
|
28
30
|
const { paths, isLoading, isEmpty } = useGalleryImages({
|
|
29
31
|
path,
|
|
@@ -58,14 +60,42 @@ function Gallery({
|
|
|
58
60
|
/* @__PURE__ */ jsx("span", { className: "font-mono text-xs uppercase tracking-widest", children: "No images" })
|
|
59
61
|
] }) });
|
|
60
62
|
}
|
|
63
|
+
const isCompact = images.length <= 3;
|
|
64
|
+
const isSingleWithChildren = images.length === 1 && children;
|
|
65
|
+
const imageElement = (index, img, className) => /* @__PURE__ */ jsx(
|
|
66
|
+
"div",
|
|
67
|
+
{
|
|
68
|
+
className: `aspect-square overflow-hidden rounded-sm bg-muted/10 cursor-pointer group ${className || ""}`,
|
|
69
|
+
onClick: () => lightbox.open(index),
|
|
70
|
+
children: /* @__PURE__ */ jsx(
|
|
71
|
+
LoadingImage,
|
|
72
|
+
{
|
|
73
|
+
src: img.src,
|
|
74
|
+
alt: img.label,
|
|
75
|
+
className: "object-contain transition-transform duration-500 ease-out group-hover:scale-[1.02]"
|
|
76
|
+
}
|
|
77
|
+
)
|
|
78
|
+
},
|
|
79
|
+
index
|
|
80
|
+
);
|
|
61
81
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
62
|
-
/* @__PURE__ */ jsxs("figure", { className:
|
|
63
|
-
/* @__PURE__ */ jsx(FigureHeader, { title, subtitle }),
|
|
64
|
-
/* @__PURE__ */ jsxs(
|
|
65
|
-
/* @__PURE__ */
|
|
82
|
+
/* @__PURE__ */ jsxs("figure", { className: `not-prose relative py-6 md:py-8 ${isCompact ? "" : "-mx-[calc((var(--gallery-width)-var(--content-width))/2+var(--page-padding))] px-[calc((var(--gallery-width)-var(--content-width))/2)]"}`, children: [
|
|
83
|
+
!isSingleWithChildren && /* @__PURE__ */ jsx(FigureHeader, { title, subtitle }),
|
|
84
|
+
isSingleWithChildren ? /* @__PURE__ */ jsxs("div", { className: `flex gap-6 ${childAlign === "left" ? "" : "flex-row-reverse"}`, children: [
|
|
85
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1 text-sm leading-relaxed text-foreground/90 space-y-3 [&>ul]:space-y-1.5 [&>ul]:list-disc [&>ul]:pl-5 [&>ol]:space-y-1.5 [&>ol]:list-decimal [&>ol]:pl-5 flex flex-col", children: [
|
|
86
|
+
(title || subtitle) && /* @__PURE__ */ jsx("div", { className: "invisible", children: /* @__PURE__ */ jsx(FigureHeader, { title, subtitle }) }),
|
|
87
|
+
/* @__PURE__ */ jsx("div", { children })
|
|
88
|
+
] }),
|
|
89
|
+
/* @__PURE__ */ jsxs("div", { className: "w-3/5 flex-shrink-0", children: [
|
|
90
|
+
/* @__PURE__ */ jsx(FigureHeader, { title, subtitle }),
|
|
91
|
+
imageElement(0, images[0]),
|
|
92
|
+
/* @__PURE__ */ jsx(FigureCaption, { caption, label: captionLabel })
|
|
93
|
+
] })
|
|
94
|
+
] }) : isCompact ? /* @__PURE__ */ jsx("div", { className: "flex gap-3", children: images.map((img, index) => imageElement(index, img, "flex-1")) }) : /* @__PURE__ */ jsxs(Carousel, { className: "w-full", children: [
|
|
95
|
+
/* @__PURE__ */ jsx(CarouselContent, { className: "-ml-2 md:-ml-3", children: images.map((img, index) => /* @__PURE__ */ jsx(
|
|
66
96
|
CarouselItem,
|
|
67
97
|
{
|
|
68
|
-
className:
|
|
98
|
+
className: "pl-2 md:pl-3 md:basis-1/2 lg:basis-1/3 cursor-pointer group",
|
|
69
99
|
onClick: () => lightbox.open(index),
|
|
70
100
|
children: /* @__PURE__ */ jsx("div", { className: "aspect-square overflow-hidden rounded-sm bg-muted/10", children: /* @__PURE__ */ jsx(
|
|
71
101
|
LoadingImage,
|
|
@@ -83,7 +113,7 @@ function Gallery({
|
|
|
83
113
|
/* @__PURE__ */ jsx(CarouselNext, { className: "right-4 bg-background/80 backdrop-blur-sm border-border/50 hover:bg-background hover:border-border" })
|
|
84
114
|
] })
|
|
85
115
|
] }),
|
|
86
|
-
/* @__PURE__ */ jsx(FigureCaption, { caption, label: captionLabel })
|
|
116
|
+
!isSingleWithChildren && /* @__PURE__ */ jsx(FigureCaption, { caption, label: captionLabel })
|
|
87
117
|
] }),
|
|
88
118
|
lightbox.isOpen && lightbox.selectedIndex !== null && /* @__PURE__ */ jsx(
|
|
89
119
|
Lightbox,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../../src/components/gallery/index.tsx"],"sourcesContent":["import { useMemo } from \"react\";\nimport { Image } from \"lucide-react\";\nimport { Lightbox, LightboxImage } from \"@/components/gallery/components/lightbox\";\nimport { useGalleryImages } from \"./hooks/use-gallery-images\";\nimport { useLightbox } from \"./hooks/use-lightbox\";\nimport { LoadingImage } from \"./components/loading-image\";\nimport { FigureHeader } from \"./components/figure-header\";\nimport { FigureCaption } from \"./components/figure-caption\";\nimport {\n Carousel,\n CarouselContent,\n CarouselItem,\n CarouselNext,\n CarouselPrevious,\n} from \"@/components/ui/carousel\"\n\nfunction getImageLabel(path: string): string {\n const filename = path.split('/').pop() || path;\n return filename\n .replace(/\\.(png|jpg|jpeg|gif|svg|webp)$/i, '')\n .replace(/[_-]/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\nfunction getImageUrl(path: string): string {\n return `/raw/${path}`;\n}\n\nexport default function Gallery({\n path,\n globs = null
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/components/gallery/index.tsx"],"sourcesContent":["import { useMemo } from \"react\";\nimport { Image } from \"lucide-react\";\nimport { Lightbox, LightboxImage } from \"@/components/gallery/components/lightbox\";\nimport { useGalleryImages } from \"./hooks/use-gallery-images\";\nimport { useLightbox } from \"./hooks/use-lightbox\";\nimport { LoadingImage } from \"./components/loading-image\";\nimport { FigureHeader } from \"./components/figure-header\";\nimport { FigureCaption } from \"./components/figure-caption\";\nimport {\n Carousel,\n CarouselContent,\n CarouselItem,\n CarouselNext,\n CarouselPrevious,\n} from \"@/components/ui/carousel\"\n\nfunction getImageLabel(path: string): string {\n const filename = path.split('/').pop() || path;\n return filename\n .replace(/\\.(png|jpg|jpeg|gif|svg|webp)$/i, '')\n .replace(/[_-]/g, ' ')\n .replace(/\\s+/g, ' ')\n .trim();\n}\n\nfunction getImageUrl(path: string): string {\n return `/raw/${path}`;\n}\n\nexport default function Gallery({\n path,\n globs = null,\n caption,\n captionLabel,\n title,\n subtitle,\n limit = null,\n page = 0,\n children,\n childAlign = \"right\",\n}: {\n path?: string;\n globs?: string[] | null;\n caption?: string;\n captionLabel?: string;\n title?: string;\n subtitle?: string;\n limit?: number | null;\n page?: number;\n children?: React.ReactNode;\n childAlign?: \"left\" | \"right\";\n}) {\n const { paths, isLoading, isEmpty } = useGalleryImages({\n path,\n globs,\n limit,\n page: page,\n });\n\n const lightbox = useLightbox(paths.length);\n\n const images: LightboxImage[] = useMemo(() =>\n paths.map(p => ({ src: getImageUrl(p), label: getImageLabel(p) })),\n [paths]\n );\n\n if (isLoading) {\n return (\n <figure className=\"not-prose py-6 md:py-8\">\n <div className=\"grid grid-cols-3 gap-3 max-w-[var(--gallery-width)] mx-auto\">\n {[...Array(3)].map((_, i) => (\n <div\n key={i}\n className=\"aspect-square rounded-sm bg-muted/20 relative overflow-hidden\"\n >\n <div\n className=\"absolute inset-0 bg-gradient-to-r from-transparent via-muted/30 to-transparent animate-shimmer\"\n style={{ animationDelay: `${i * 150}ms` }}\n />\n </div>\n ))}\n </div>\n </figure>\n );\n }\n\n if (isEmpty) {\n return (\n <figure className=\"not-prose py-12 text-center\">\n <div className=\"inline-flex items-center gap-2.5 text-muted-foreground/40\">\n <Image className=\"h-3.5 w-3.5\" strokeWidth={1.5} />\n <span className=\"font-mono text-xs uppercase tracking-widest\">No images</span>\n </div>\n </figure>\n );\n }\n\n const isCompact = images.length <= 3;\n const isSingleWithChildren = images.length === 1 && children;\n\n const imageElement = (index: number, img: LightboxImage, className?: string) => (\n <div\n key={index}\n className={`aspect-square overflow-hidden rounded-sm bg-muted/10 cursor-pointer group ${className || ''}`}\n onClick={() => lightbox.open(index)}\n >\n <LoadingImage\n src={img.src}\n alt={img.label}\n className=\"object-contain transition-transform duration-500 ease-out group-hover:scale-[1.02]\"\n />\n </div>\n );\n\n return (\n <>\n <figure className={`not-prose relative py-6 md:py-8 ${isCompact ? '' : '-mx-[calc((var(--gallery-width)-var(--content-width))/2+var(--page-padding))] px-[calc((var(--gallery-width)-var(--content-width))/2)]'}`}>\n {!isSingleWithChildren && <FigureHeader title={title} subtitle={subtitle} />}\n\n {isSingleWithChildren ? (\n <div className={`flex gap-6 ${childAlign === 'left' ? '' : 'flex-row-reverse'}`}>\n <div className=\"flex-1 text-sm leading-relaxed text-foreground/90 space-y-3 [&>ul]:space-y-1.5 [&>ul]:list-disc [&>ul]:pl-5 [&>ol]:space-y-1.5 [&>ol]:list-decimal [&>ol]:pl-5 flex flex-col\">\n {(title || subtitle) && <div className=\"invisible\"><FigureHeader title={title} subtitle={subtitle} /></div>}\n <div>{children}</div>\n </div>\n <div className=\"w-3/5 flex-shrink-0\">\n <FigureHeader title={title} subtitle={subtitle} />\n {imageElement(0, images[0])}\n <FigureCaption caption={caption} label={captionLabel} />\n </div>\n </div>\n ) : isCompact ? (\n <div className=\"flex gap-3\">\n {images.map((img, index) => imageElement(index, img, 'flex-1'))}\n </div>\n ) : (\n <Carousel className=\"w-full\">\n <CarouselContent className=\"-ml-2 md:-ml-3\">\n {images.map((img, index) => (\n <CarouselItem\n key={index}\n className=\"pl-2 md:pl-3 md:basis-1/2 lg:basis-1/3 cursor-pointer group\"\n onClick={() => lightbox.open(index)}\n >\n <div className=\"aspect-square overflow-hidden rounded-sm bg-muted/10\">\n <LoadingImage\n src={img.src}\n alt={img.label}\n className=\"object-contain transition-transform duration-500 ease-out group-hover:scale-[1.02]\"\n />\n </div>\n </CarouselItem>\n ))}\n </CarouselContent>\n\n {images.length > 3 && (\n <>\n <CarouselPrevious className=\"left-4 bg-background/80 backdrop-blur-sm border-border/50 hover:bg-background hover:border-border\" />\n <CarouselNext className=\"right-4 bg-background/80 backdrop-blur-sm border-border/50 hover:bg-background hover:border-border\" />\n </>\n )}\n </Carousel>\n )}\n\n {!isSingleWithChildren && <FigureCaption caption={caption} label={captionLabel} />}\n </figure>\n\n {lightbox.isOpen && lightbox.selectedIndex !== null && (\n <Lightbox\n images={images}\n selectedIndex={lightbox.selectedIndex}\n onClose={lightbox.close}\n onPrevious={lightbox.goToPrevious}\n onNext={lightbox.goToNext}\n />\n )}\n </>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Link } from "react-router-dom";
|
|
1
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useParams, Link } from "react-router-dom";
|
|
3
3
|
import { ModeToggle } from "./mode-toggle.js";
|
|
4
4
|
import { SiGithub } from "@icons-pack/react-simple-icons";
|
|
5
5
|
import { ChevronUp, ChevronDown } from "lucide-react";
|
|
6
6
|
import siteConfig from "virtual:veslx-config";
|
|
7
|
+
import { cn } from "../lib/utils.js";
|
|
7
8
|
function Header({ slideControls } = {}) {
|
|
8
9
|
const config = siteConfig;
|
|
10
|
+
const { "*": path } = useParams();
|
|
9
11
|
return /* @__PURE__ */ jsx("header", { className: "print:hidden fixed top-0 left-0 right-0 z-40", children: /* @__PURE__ */ jsxs("div", { className: "mx-auto w-full px-[var(--page-padding)] flex items-center gap-8 py-4", children: [
|
|
10
12
|
/* @__PURE__ */ jsx("nav", { className: "flex items-center gap-1", children: /* @__PURE__ */ jsx(
|
|
11
13
|
Link,
|
|
@@ -16,32 +18,54 @@ function Header({ slideControls } = {}) {
|
|
|
16
18
|
}
|
|
17
19
|
) }),
|
|
18
20
|
/* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
19
|
-
|
|
21
|
+
/* @__PURE__ */ jsxs("nav", { className: "flex items-center gap-4", children: [
|
|
22
|
+
slideControls && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
23
|
+
/* @__PURE__ */ jsx(
|
|
24
|
+
"button",
|
|
25
|
+
{
|
|
26
|
+
onClick: slideControls.onPrevious,
|
|
27
|
+
className: "p-1.5 text-muted-foreground/70 hover:text-foreground transition-colors duration-200",
|
|
28
|
+
title: "Previous slide (↑)",
|
|
29
|
+
children: /* @__PURE__ */ jsx(ChevronUp, { className: "h-4 w-4" })
|
|
30
|
+
}
|
|
31
|
+
),
|
|
32
|
+
/* @__PURE__ */ jsxs("span", { className: "font-mono text-xs text-muted-foreground/70 tabular-nums min-w-[3ch] text-center", children: [
|
|
33
|
+
slideControls.current + 1,
|
|
34
|
+
"/",
|
|
35
|
+
slideControls.total
|
|
36
|
+
] }),
|
|
37
|
+
/* @__PURE__ */ jsx(
|
|
38
|
+
"button",
|
|
39
|
+
{
|
|
40
|
+
onClick: slideControls.onNext,
|
|
41
|
+
className: "p-1.5 text-muted-foreground/70 hover:text-foreground transition-colors duration-200",
|
|
42
|
+
title: "Next slide (↓)",
|
|
43
|
+
children: /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4" })
|
|
44
|
+
}
|
|
45
|
+
)
|
|
46
|
+
] }),
|
|
20
47
|
/* @__PURE__ */ jsx(
|
|
21
|
-
|
|
48
|
+
Link,
|
|
22
49
|
{
|
|
23
|
-
|
|
24
|
-
className:
|
|
25
|
-
|
|
26
|
-
|
|
50
|
+
to: `/posts`,
|
|
51
|
+
className: cn(
|
|
52
|
+
"font-medium text-muted-foreground/70 hover:text-foreground transition-colors duration-300",
|
|
53
|
+
(path == null ? void 0 : path.startsWith("posts")) && "font-semibold text-foreground"
|
|
54
|
+
),
|
|
55
|
+
children: "Posts"
|
|
27
56
|
}
|
|
28
57
|
),
|
|
29
|
-
/* @__PURE__ */ jsxs("span", { className: "font-mono text-xs text-muted-foreground/70 tabular-nums min-w-[3ch] text-center", children: [
|
|
30
|
-
slideControls.current + 1,
|
|
31
|
-
"/",
|
|
32
|
-
slideControls.total
|
|
33
|
-
] }),
|
|
34
58
|
/* @__PURE__ */ jsx(
|
|
35
|
-
|
|
59
|
+
Link,
|
|
36
60
|
{
|
|
37
|
-
|
|
38
|
-
className:
|
|
39
|
-
|
|
40
|
-
|
|
61
|
+
to: `/docs`,
|
|
62
|
+
className: cn(
|
|
63
|
+
"font-medium text-muted-foreground/70 hover:text-foreground transition-colors duration-300",
|
|
64
|
+
(path == null ? void 0 : path.startsWith("docs")) && "font-semibold text-foreground"
|
|
65
|
+
),
|
|
66
|
+
children: "Docs"
|
|
41
67
|
}
|
|
42
|
-
)
|
|
43
|
-
] }),
|
|
44
|
-
/* @__PURE__ */ jsxs("nav", { className: "flex items-center gap-2", children: [
|
|
68
|
+
),
|
|
45
69
|
config.github && /* @__PURE__ */ jsx(
|
|
46
70
|
Link,
|
|
47
71
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"header.js","sources":["../../../src/components/header.tsx"],"sourcesContent":["import { Link } from \"react-router-dom\";\nimport { ModeToggle } from \"./mode-toggle\";\nimport { SiGithub } from \"@icons-pack/react-simple-icons\";\nimport { ChevronUp, ChevronDown } from \"lucide-react\";\nimport siteConfig from \"virtual:veslx-config\";\n\ninterface HeaderProps {\n slideControls?: {\n current: number;\n total: number;\n onPrevious: () => void;\n onNext: () => void;\n };\n}\n\nexport function Header({ slideControls }: HeaderProps = {}) {\n const config = siteConfig;\n\n return (\n <header className=\"print:hidden fixed top-0 left-0 right-0 z-40\">\n <div className=\"mx-auto w-full px-[var(--page-padding)] flex items-center gap-8 py-4\">\n <nav className=\"flex items-center gap-1\">\n <Link\n to=\"/\"\n className=\"rounded-lg font-mono py-1.5 text-sm font-medium text-muted-foreground hover:underline\"\n >\n {config.name}\n </Link>\n </nav>\n\n <div className=\"flex-1\" />\n\n {/*
|
|
1
|
+
{"version":3,"file":"header.js","sources":["../../../src/components/header.tsx"],"sourcesContent":["import { Link, useParams } from \"react-router-dom\";\nimport { ModeToggle } from \"./mode-toggle\";\nimport { SiGithub } from \"@icons-pack/react-simple-icons\";\nimport { ChevronUp, ChevronDown } from \"lucide-react\";\nimport siteConfig from \"virtual:veslx-config\";\nimport { cn } from \"@/lib/utils\";\n\ninterface HeaderProps {\n slideControls?: {\n current: number;\n total: number;\n onPrevious: () => void;\n onNext: () => void;\n };\n}\n\nexport function Header({ slideControls }: HeaderProps = {}) {\n const config = siteConfig;\n\n const { \"*\": path } = useParams()\n\n return (\n <header className=\"print:hidden fixed top-0 left-0 right-0 z-40\">\n <div className=\"mx-auto w-full px-[var(--page-padding)] flex items-center gap-8 py-4\">\n <nav className=\"flex items-center gap-1\">\n <Link\n to=\"/\"\n className=\"rounded-lg font-mono py-1.5 text-sm font-medium text-muted-foreground hover:underline\"\n >\n {config.name}\n </Link>\n </nav>\n\n <div className=\"flex-1\" />\n\n {/* Navigation */}\n <nav className=\"flex items-center gap-4\">\n {slideControls && (\n <>\n <button\n onClick={slideControls.onPrevious}\n className=\"p-1.5 text-muted-foreground/70 hover:text-foreground transition-colors duration-200\"\n title=\"Previous slide (↑)\"\n >\n <ChevronUp className=\"h-4 w-4\" />\n </button>\n <span className=\"font-mono text-xs text-muted-foreground/70 tabular-nums min-w-[3ch] text-center\">\n {slideControls.current + 1}/{slideControls.total}\n </span>\n <button\n onClick={slideControls.onNext}\n className=\"p-1.5 text-muted-foreground/70 hover:text-foreground transition-colors duration-200\"\n title=\"Next slide (↓)\"\n >\n <ChevronDown className=\"h-4 w-4\" />\n </button>\n </>\n )}\n <Link\n to={`/posts`}\n className={cn(\n \"font-medium text-muted-foreground/70 hover:text-foreground transition-colors duration-300\",\n path?.startsWith(\"posts\") && \"font-semibold text-foreground\",\n )}\n >\n Posts\n </Link>\n <Link\n to={`/docs`}\n className={cn(\n \"font-medium text-muted-foreground/70 hover:text-foreground transition-colors duration-300\",\n path?.startsWith(\"docs\") && \"font-semibold text-foreground\",\n )}\n >\n Docs\n </Link>\n {config.github && (\n <Link\n to={`https://github.com/${config.github}`}\n target=\"_blank\"\n className=\"text-muted-foreground/70 hover:text-foreground transition-colors duration-300\"\n aria-label=\"GitHub\"\n >\n <SiGithub className=\"h-4 w-4\" />\n </Link>\n )}\n <ModeToggle />\n </nav>\n </div>\n </header>\n );\n}\n"],"names":[],"mappings":";;;;;;;AAgBO,SAAS,OAAO,EAAE,cAAA,IAA+B,IAAI;AAC1D,QAAM,SAAS;AAEf,QAAM,EAAE,KAAK,KAAA,IAAS,UAAA;AAEtB,6BACG,UAAA,EAAO,WAAU,gDAChB,UAAA,qBAAC,OAAA,EAAI,WAAU,wEACb,UAAA;AAAA,IAAA,oBAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,IAAG;AAAA,QACH,WAAU;AAAA,QAET,UAAA,OAAO;AAAA,MAAA;AAAA,IAAA,GAEZ;AAAA,IAEA,oBAAC,OAAA,EAAI,WAAU,SAAA,CAAS;AAAA,IAGxB,qBAAC,OAAA,EAAI,WAAU,2BACZ,UAAA;AAAA,MAAA,iBACC,qBAAA,UAAA,EACE,UAAA;AAAA,QAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS,cAAc;AAAA,YACvB,WAAU;AAAA,YACV,OAAM;AAAA,YAEN,UAAA,oBAAC,WAAA,EAAU,WAAU,UAAA,CAAU;AAAA,UAAA;AAAA,QAAA;AAAA,QAEjC,qBAAC,QAAA,EAAK,WAAU,mFACb,UAAA;AAAA,UAAA,cAAc,UAAU;AAAA,UAAE;AAAA,UAAE,cAAc;AAAA,QAAA,GAC7C;AAAA,QACA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,SAAS,cAAc;AAAA,YACvB,WAAU;AAAA,YACV,OAAM;AAAA,YAEN,UAAA,oBAAC,aAAA,EAAY,WAAU,UAAA,CAAU;AAAA,UAAA;AAAA,QAAA;AAAA,MACnC,GACF;AAAA,MAEF;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,IAAI;AAAA,UACJ,WAAW;AAAA,YACT;AAAA,aACA,6BAAM,WAAW,aAAY;AAAA,UAAA;AAAA,UAEhC,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAGD;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,IAAI;AAAA,UACJ,WAAW;AAAA,YACT;AAAA,aACA,6BAAM,WAAW,YAAW;AAAA,UAAA;AAAA,UAE/B,UAAA;AAAA,QAAA;AAAA,MAAA;AAAA,MAGA,OAAO,UACN;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,IAAI,sBAAsB,OAAO,MAAM;AAAA,UACvC,QAAO;AAAA,UACP,WAAU;AAAA,UACV,cAAW;AAAA,UAEX,UAAA,oBAAC,UAAA,EAAS,WAAU,UAAA,CAAU;AAAA,QAAA;AAAA,MAAA;AAAA,0BAGjC,YAAA,CAAA,CAAW;AAAA,IAAA,EAAA,CACd;AAAA,EAAA,EAAA,CACF,EAAA,CACF;AAEJ;"}
|
|
@@ -4,6 +4,10 @@ import Gallery from "./gallery/index.js";
|
|
|
4
4
|
import { ParameterTable } from "./parameter-table.js";
|
|
5
5
|
import { ParameterBadge } from "./parameter-badge.js";
|
|
6
6
|
import { FrontMatter } from "./front-matter.js";
|
|
7
|
+
import { HeroSlide } from "./slides/hero-slide.js";
|
|
8
|
+
import { FigureSlide } from "./slides/figure-slide.js";
|
|
9
|
+
import { TextSlide } from "./slides/text-slide.js";
|
|
10
|
+
import { SlideOutline } from "./slides/slide-outline.js";
|
|
7
11
|
function SmartLink({ href, children, ...props }) {
|
|
8
12
|
const location = useLocation();
|
|
9
13
|
const isExternal = (href == null ? void 0 : href.startsWith("http")) || (href == null ? void 0 : href.startsWith("mailto:")) || (href == null ? void 0 : href.startsWith("tel:"));
|
|
@@ -49,6 +53,10 @@ const mdxComponents = {
|
|
|
49
53
|
Gallery,
|
|
50
54
|
ParameterTable,
|
|
51
55
|
ParameterBadge,
|
|
56
|
+
HeroSlide,
|
|
57
|
+
FigureSlide,
|
|
58
|
+
TextSlide,
|
|
59
|
+
SlideOutline,
|
|
52
60
|
// Headings - clean sans-serif
|
|
53
61
|
h1: (props) => {
|
|
54
62
|
const id = generateId(props.children);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mdx-components.js","sources":["../../../src/components/mdx-components.tsx"],"sourcesContent":["import { Link, useLocation } from 'react-router-dom'\nimport Gallery from '@/components/gallery'\nimport { ParameterTable } from '@/components/parameter-table'\nimport { ParameterBadge } from '@/components/parameter-badge'\nimport { FrontMatter } from './front-matter'\n\n/**\n * Smart link component that uses React Router for internal links\n * and regular anchor tags for external links.\n */\nfunction SmartLink({ href, children, ...props }: React.AnchorHTMLAttributes<HTMLAnchorElement>) {\n const location = useLocation()\n\n // External links: absolute URLs, mailto, tel, etc.\n const isExternal = href?.startsWith('http') || href?.startsWith('mailto:') || href?.startsWith('tel:')\n\n // Hash-only links stay as anchors for in-page navigation\n const isHashOnly = href?.startsWith('#')\n\n if (isExternal || isHashOnly || !href) {\n return (\n <a\n href={href}\n className=\"text-primary hover:underline underline-offset-2\"\n {...(isExternal ? { target: '_blank', rel: 'noopener noreferrer' } : {})}\n {...props}\n >\n {children}\n </a>\n )\n }\n\n // Resolve relative paths (./foo.mdx, ../bar.mdx) against current location\n let resolvedHref = href\n if (href.startsWith('./') || href.startsWith('../')) {\n // Get current directory from pathname\n const currentPath = location.pathname\n const currentDir = currentPath.replace(/\\/[^/]+\\.mdx$/, '') || currentPath.replace(/\\/[^/]*$/, '') || '/'\n\n // Simple relative path resolution\n if (href.startsWith('./')) {\n resolvedHref = `${currentDir}/${href.slice(2)}`.replace(/\\/+/g, '/')\n } else if (href.startsWith('../')) {\n const parentDir = currentDir.replace(/\\/[^/]+$/, '') || '/'\n resolvedHref = `${parentDir}/${href.slice(3)}`.replace(/\\/+/g, '/')\n }\n }\n\n // Internal link - use React Router Link\n return (\n <Link\n to={resolvedHref}\n className=\"text-primary hover:underline underline-offset-2\"\n {...props}\n >\n {children}\n </Link>\n )\n}\n\nfunction generateId(children: unknown): string {\n return children\n ?.toString()\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, '')\n .replace(/\\s+/g, '-') ?? ''\n}\n\n// Shared MDX components - lab notebook / coder aesthetic\nexport const mdxComponents = {\n\n FrontMatter,\n\n Gallery,\n\n ParameterTable,\n\n ParameterBadge,\n\n // Headings - clean sans-serif\n h1: (props: React.HTMLAttributes<HTMLHeadingElement>) => {\n const id = generateId(props.children)\n return (\n <h1\n id={id}\n className=\"text-2xl font-semibold tracking-tight mt-12 mb-4 first:mt-0\"\n {...props}\n />\n )\n },\n h2: (props: React.HTMLAttributes<HTMLHeadingElement>) => {\n const id = generateId(props.children)\n return (\n <h2\n id={id}\n className=\"text-xl font-semibold tracking-tight mt-10 mb-3 pb-2 border-b border-border\"\n {...props}\n />\n )\n },\n h3: (props: React.HTMLAttributes<HTMLHeadingElement>) => {\n const id = generateId(props.children)\n return (\n <h3\n id={id}\n className=\"text-lg font-medium tracking-tight mt-8 mb-2\"\n {...props}\n />\n )\n },\n h4: (props: React.HTMLAttributes<HTMLHeadingElement>) => {\n const id = generateId(props.children)\n return (\n <h4\n id={id}\n className=\"text-base font-medium mt-6 mb-2\"\n {...props}\n />\n )\n },\n h5: (props: React.HTMLAttributes<HTMLHeadingElement>) => {\n const id = generateId(props.children)\n return (\n <h5\n id={id}\n className=\"text-sm font-medium mt-4 mb-1\"\n {...props}\n />\n )\n },\n\n // Code blocks - IDE/terminal style\n pre: (props: React.HTMLAttributes<HTMLPreElement>) => (\n <pre\n className=\"not-prose w-full overflow-x-auto p-4 text-sm bg-muted/50 border border-border rounded-md font-mono my-6\"\n {...props}\n />\n ),\n code: (props: React.HTMLAttributes<HTMLElement> & { className?: string }) => {\n const isInline = !props.className?.includes('language-')\n if (isInline) {\n return (\n <code\n className=\"font-mono text-[0.85em] bg-muted px-1.5 py-0.5 rounded text-primary\"\n {...props}\n />\n )\n }\n return <code {...props} />\n },\n\n // Blockquote\n blockquote: (props: React.HTMLAttributes<HTMLQuoteElement>) => (\n <blockquote\n className=\"border-l-2 border-primary pl-4 my-6 text-muted-foreground\"\n {...props}\n />\n ),\n\n // Lists\n ul: (props: React.HTMLAttributes<HTMLUListElement>) => (\n <ul className=\"my-4 ml-6 list-disc marker:text-muted-foreground\" {...props} />\n ),\n ol: (props: React.HTMLAttributes<HTMLOListElement>) => (\n <ol className=\"my-4 ml-6 list-decimal marker:text-muted-foreground\" {...props} />\n ),\n li: (props: React.HTMLAttributes<HTMLLIElement>) => (\n <li className=\"mt-1.5\" {...props} />\n ),\n\n // Links - uses React Router for internal navigation\n a: SmartLink,\n\n // Tables\n table: (props: React.TableHTMLAttributes<HTMLTableElement>) => (\n <div className=\"not-prose my-6 overflow-x-auto border border-border rounded-md\">\n <table className=\"w-full text-sm border-collapse\" {...props} />\n </div>\n ),\n thead: (props: React.HTMLAttributes<HTMLTableSectionElement>) => (\n <thead className=\"bg-muted/50\" {...props} />\n ),\n tbody: (props: React.HTMLAttributes<HTMLTableSectionElement>) => (\n <tbody {...props} />\n ),\n tr: (props: React.HTMLAttributes<HTMLTableRowElement>) => (\n <tr className=\"border-b border-border last:border-b-0\" {...props} />\n ),\n th: (props: React.ThHTMLAttributes<HTMLTableCellElement>) => (\n <th\n className=\"px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider\"\n {...props}\n />\n ),\n td: (props: React.TdHTMLAttributes<HTMLTableCellElement>) => (\n <td className=\"px-4 py-3 align-top\" {...props} />\n ),\n\n // Horizontal rule\n hr: (props: React.HTMLAttributes<HTMLHRElement>) => (\n <hr className=\"my-8 border-t border-border\" {...props} />\n ),\n\n // Paragraph\n p: (props: React.HTMLAttributes<HTMLParagraphElement>) => (\n <p className=\"leading-relaxed mb-4 last:mb-0\" {...props} />\n ),\n\n // Strong/emphasis\n strong: (props: React.HTMLAttributes<HTMLElement>) => (\n <strong className=\"font-semibold\" {...props} />\n ),\n em: (props: React.HTMLAttributes<HTMLElement>) => (\n <em className=\"italic\" {...props} />\n ),\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"mdx-components.js","sources":["../../../src/components/mdx-components.tsx"],"sourcesContent":["import { Link, useLocation } from 'react-router-dom'\nimport Gallery from '@/components/gallery'\nimport { ParameterTable } from '@/components/parameter-table'\nimport { ParameterBadge } from '@/components/parameter-badge'\nimport { FrontMatter } from './front-matter'\nimport { HeroSlide } from './slides/hero-slide'\nimport { FigureSlide } from './slides/figure-slide'\nimport { TextSlide } from './slides/text-slide'\nimport { SlideOutline } from './slides/slide-outline'\n\n/**\n * Smart link component that uses React Router for internal links\n * and regular anchor tags for external links.\n */\nfunction SmartLink({ href, children, ...props }: React.AnchorHTMLAttributes<HTMLAnchorElement>) {\n const location = useLocation()\n\n // External links: absolute URLs, mailto, tel, etc.\n const isExternal = href?.startsWith('http') || href?.startsWith('mailto:') || href?.startsWith('tel:')\n\n // Hash-only links stay as anchors for in-page navigation\n const isHashOnly = href?.startsWith('#')\n\n if (isExternal || isHashOnly || !href) {\n return (\n <a\n href={href}\n className=\"text-primary hover:underline underline-offset-2\"\n {...(isExternal ? { target: '_blank', rel: 'noopener noreferrer' } : {})}\n {...props}\n >\n {children}\n </a>\n )\n }\n\n // Resolve relative paths (./foo.mdx, ../bar.mdx) against current location\n let resolvedHref = href\n if (href.startsWith('./') || href.startsWith('../')) {\n // Get current directory from pathname\n const currentPath = location.pathname\n const currentDir = currentPath.replace(/\\/[^/]+\\.mdx$/, '') || currentPath.replace(/\\/[^/]*$/, '') || '/'\n\n // Simple relative path resolution\n if (href.startsWith('./')) {\n resolvedHref = `${currentDir}/${href.slice(2)}`.replace(/\\/+/g, '/')\n } else if (href.startsWith('../')) {\n const parentDir = currentDir.replace(/\\/[^/]+$/, '') || '/'\n resolvedHref = `${parentDir}/${href.slice(3)}`.replace(/\\/+/g, '/')\n }\n }\n\n // Internal link - use React Router Link\n return (\n <Link\n to={resolvedHref}\n className=\"text-primary hover:underline underline-offset-2\"\n {...props}\n >\n {children}\n </Link>\n )\n}\n\nfunction generateId(children: unknown): string {\n return children\n ?.toString()\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, '')\n .replace(/\\s+/g, '-') ?? ''\n}\n\n// Shared MDX components - lab notebook / coder aesthetic\nexport const mdxComponents = {\n\n FrontMatter,\n\n Gallery,\n\n ParameterTable,\n\n ParameterBadge,\n\n HeroSlide,\n\n FigureSlide,\n\n TextSlide,\n\n SlideOutline,\n\n // Headings - clean sans-serif\n h1: (props: React.HTMLAttributes<HTMLHeadingElement>) => {\n const id = generateId(props.children)\n return (\n <h1\n id={id}\n className=\"text-2xl font-semibold tracking-tight mt-12 mb-4 first:mt-0\"\n {...props}\n />\n )\n },\n h2: (props: React.HTMLAttributes<HTMLHeadingElement>) => {\n const id = generateId(props.children)\n return (\n <h2\n id={id}\n className=\"text-xl font-semibold tracking-tight mt-10 mb-3 pb-2 border-b border-border\"\n {...props}\n />\n )\n },\n h3: (props: React.HTMLAttributes<HTMLHeadingElement>) => {\n const id = generateId(props.children)\n return (\n <h3\n id={id}\n className=\"text-lg font-medium tracking-tight mt-8 mb-2\"\n {...props}\n />\n )\n },\n h4: (props: React.HTMLAttributes<HTMLHeadingElement>) => {\n const id = generateId(props.children)\n return (\n <h4\n id={id}\n className=\"text-base font-medium mt-6 mb-2\"\n {...props}\n />\n )\n },\n h5: (props: React.HTMLAttributes<HTMLHeadingElement>) => {\n const id = generateId(props.children)\n return (\n <h5\n id={id}\n className=\"text-sm font-medium mt-4 mb-1\"\n {...props}\n />\n )\n },\n\n // Code blocks - IDE/terminal style\n pre: (props: React.HTMLAttributes<HTMLPreElement>) => (\n <pre\n className=\"not-prose w-full overflow-x-auto p-4 text-sm bg-muted/50 border border-border rounded-md font-mono my-6\"\n {...props}\n />\n ),\n code: (props: React.HTMLAttributes<HTMLElement> & { className?: string }) => {\n const isInline = !props.className?.includes('language-')\n if (isInline) {\n return (\n <code\n className=\"font-mono text-[0.85em] bg-muted px-1.5 py-0.5 rounded text-primary\"\n {...props}\n />\n )\n }\n return <code {...props} />\n },\n\n // Blockquote\n blockquote: (props: React.HTMLAttributes<HTMLQuoteElement>) => (\n <blockquote\n className=\"border-l-2 border-primary pl-4 my-6 text-muted-foreground\"\n {...props}\n />\n ),\n\n // Lists\n ul: (props: React.HTMLAttributes<HTMLUListElement>) => (\n <ul className=\"my-4 ml-6 list-disc marker:text-muted-foreground\" {...props} />\n ),\n ol: (props: React.HTMLAttributes<HTMLOListElement>) => (\n <ol className=\"my-4 ml-6 list-decimal marker:text-muted-foreground\" {...props} />\n ),\n li: (props: React.HTMLAttributes<HTMLLIElement>) => (\n <li className=\"mt-1.5\" {...props} />\n ),\n\n // Links - uses React Router for internal navigation\n a: SmartLink,\n\n // Tables\n table: (props: React.TableHTMLAttributes<HTMLTableElement>) => (\n <div className=\"not-prose my-6 overflow-x-auto border border-border rounded-md\">\n <table className=\"w-full text-sm border-collapse\" {...props} />\n </div>\n ),\n thead: (props: React.HTMLAttributes<HTMLTableSectionElement>) => (\n <thead className=\"bg-muted/50\" {...props} />\n ),\n tbody: (props: React.HTMLAttributes<HTMLTableSectionElement>) => (\n <tbody {...props} />\n ),\n tr: (props: React.HTMLAttributes<HTMLTableRowElement>) => (\n <tr className=\"border-b border-border last:border-b-0\" {...props} />\n ),\n th: (props: React.ThHTMLAttributes<HTMLTableCellElement>) => (\n <th\n className=\"px-4 py-3 text-left text-xs font-medium text-muted-foreground uppercase tracking-wider\"\n {...props}\n />\n ),\n td: (props: React.TdHTMLAttributes<HTMLTableCellElement>) => (\n <td className=\"px-4 py-3 align-top\" {...props} />\n ),\n\n // Horizontal rule\n hr: (props: React.HTMLAttributes<HTMLHRElement>) => (\n <hr className=\"my-8 border-t border-border\" {...props} />\n ),\n\n // Paragraph\n p: (props: React.HTMLAttributes<HTMLParagraphElement>) => (\n <p className=\"leading-relaxed mb-4 last:mb-0\" {...props} />\n ),\n\n // Strong/emphasis\n strong: (props: React.HTMLAttributes<HTMLElement>) => (\n <strong className=\"font-semibold\" {...props} />\n ),\n em: (props: React.HTMLAttributes<HTMLElement>) => (\n <em className=\"italic\" {...props} />\n ),\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Link } from "react-router-dom";
|
|
3
3
|
import { cn } from "../lib/utils.js";
|
|
4
4
|
import { formatDate } from "../lib/format-date.js";
|
|
5
|
-
import { ArrowRight } from "lucide-react";
|
|
5
|
+
import { ArrowRight, Presentation } from "lucide-react";
|
|
6
6
|
import { directoryToPostEntries, filterVisiblePosts, filterByView, getFrontmatter } from "../lib/content-classification.js";
|
|
7
7
|
function extractOrder(name) {
|
|
8
8
|
const match = name.match(/^(\d+)-/);
|
|
@@ -60,6 +60,7 @@ function PostList({ directory, view = "all" }) {
|
|
|
60
60
|
} else {
|
|
61
61
|
linkPath = `/${post.path}`;
|
|
62
62
|
}
|
|
63
|
+
const isSlides = linkPath.endsWith("SLIDES.mdx");
|
|
63
64
|
return /* @__PURE__ */ jsx(
|
|
64
65
|
Link,
|
|
65
66
|
{
|
|
@@ -68,15 +69,7 @@ function PostList({ directory, view = "all" }) {
|
|
|
68
69
|
"group block py-3 px-3 -mx-3 rounded-md",
|
|
69
70
|
"transition-colors duration-150"
|
|
70
71
|
),
|
|
71
|
-
children: /* @__PURE__ */ jsxs("article", { className: "flex items-
|
|
72
|
-
/* @__PURE__ */ jsx(
|
|
73
|
-
"time",
|
|
74
|
-
{
|
|
75
|
-
dateTime: date == null ? void 0 : date.toISOString(),
|
|
76
|
-
className: "font-mono text-xs text-muted-foreground tabular-nums w-20 flex-shrink-0 pt-0.5",
|
|
77
|
-
children: date ? formatDate(date) : /* @__PURE__ */ jsx("span", { className: "text-muted-foreground/30", children: "—" })
|
|
78
|
-
}
|
|
79
|
-
),
|
|
72
|
+
children: /* @__PURE__ */ jsxs("article", { className: "flex items-center gap-4", children: [
|
|
80
73
|
/* @__PURE__ */ jsxs("div", { className: "flex-1 min-w-0", children: [
|
|
81
74
|
/* @__PURE__ */ jsxs("h3", { className: cn(
|
|
82
75
|
"text-sm font-medium text-foreground",
|
|
@@ -87,7 +80,16 @@ function PostList({ directory, view = "all" }) {
|
|
|
87
80
|
/* @__PURE__ */ jsx(ArrowRight, { className: "h-3 w-3 opacity-0 -translate-x-1 group-hover:opacity-100 group-hover:translate-x-0 transition-all duration-200 text-primary" })
|
|
88
81
|
] }),
|
|
89
82
|
description && /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground line-clamp-1 mt-0.5", children: description })
|
|
90
|
-
] })
|
|
83
|
+
] }),
|
|
84
|
+
isSlides && /* @__PURE__ */ jsx(Presentation, { className: "h-3 w-3 text-muted-foreground" }),
|
|
85
|
+
/* @__PURE__ */ jsx(
|
|
86
|
+
"time",
|
|
87
|
+
{
|
|
88
|
+
dateTime: date == null ? void 0 : date.toISOString(),
|
|
89
|
+
className: "font-mono text-xs text-muted-foreground tabular-nums w-20 flex-shrink-0",
|
|
90
|
+
children: date && formatDate(date)
|
|
91
|
+
}
|
|
92
|
+
)
|
|
91
93
|
] })
|
|
92
94
|
},
|
|
93
95
|
post.path
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post-list.js","sources":["../../../src/components/post-list.tsx"],"sourcesContent":["import { Link } from \"react-router-dom\";\nimport { cn } from \"@/lib/utils\";\nimport type { DirectoryEntry } from \"../../plugin/src/lib\";\nimport { formatDate } from \"@/lib/format-date\";\nimport { ArrowRight } from \"lucide-react\";\nimport {\n type ContentView,\n type PostEntry,\n directoryToPostEntries,\n filterVisiblePosts,\n filterByView,\n getFrontmatter,\n} from \"@/lib/content-classification\";\n\n// Helper to extract numeric prefix from filename (e.g., \"01-intro\" → 1)\nfunction extractOrder(name: string): number | null {\n const match = name.match(/^(\\d+)-/);\n return match ? parseInt(match[1], 10) : null;\n}\n\n// Helper to strip numeric prefix for display (e.g., \"01-getting-started\" → \"Getting Started\")\nfunction stripNumericPrefix(name: string): string {\n return name\n .replace(/^\\d+-/, '')\n .replace(/-/g, ' ')\n .replace(/\\b\\w/g, c => c.toUpperCase());\n}\n\ninterface PostListProps {\n directory: DirectoryEntry;\n view?: ContentView;\n}\n\nexport default function PostList({ directory, view = 'all' }: PostListProps) {\n let posts = directoryToPostEntries(directory);\n\n if (posts.length === 0) {\n return (\n <div className=\"py-24 text-center\">\n <p className=\"text-muted-foreground font-mono text-sm tracking-wide\">no entries</p>\n </div>\n );\n }\n\n // Filter out hidden and draft posts\n posts = filterVisiblePosts(posts);\n\n // Apply view filter\n posts = filterByView(posts, view);\n\n if (posts.length === 0) {\n return (\n <div className=\"py-24 text-center\">\n <p className=\"text-muted-foreground font-mono text-sm tracking-wide\">no entries</p>\n </div>\n );\n }\n\n // Helper to get date from post\n const getPostDate = (post: PostEntry): Date | null => {\n const frontmatter = getFrontmatter(post);\n return frontmatter?.date ? new Date(frontmatter.date as string) : null;\n };\n\n // Smart sorting: numeric prefix → date → alphabetical\n posts = posts.sort((a, b) => {\n const aOrder = extractOrder(a.name);\n const bOrder = extractOrder(b.name);\n const aDate = getPostDate(a);\n const bDate = getPostDate(b);\n\n // Both have numeric prefix → sort by number\n if (aOrder !== null && bOrder !== null) {\n return aOrder - bOrder;\n }\n // One has prefix, one doesn't → prefixed comes first\n if (aOrder !== null) return -1;\n if (bOrder !== null) return 1;\n\n // Both have dates → sort by date (newest first)\n if (aDate && bDate) {\n return bDate.getTime() - aDate.getTime();\n }\n // One has date → dated comes first\n if (aDate) return -1;\n if (bDate) return 1;\n\n // Neither → alphabetical by title\n const aTitle = (getFrontmatter(a)?.title as string) || a.name;\n const bTitle = (getFrontmatter(b)?.title as string) || b.name;\n return aTitle.localeCompare(bTitle);\n });\n\n return (\n <div className=\"space-y-1\">\n {posts.map((post) => {\n const frontmatter = getFrontmatter(post);\n\n // Title: explicit frontmatter > stripped numeric prefix > raw name\n const title = (frontmatter?.title as string) || stripNumericPrefix(post.name);\n const description = frontmatter?.description as string | undefined;\n const date = frontmatter?.date ? new Date(frontmatter.date as string) : null;\n\n // Determine the link path\n let linkPath: string;\n if (post.file) {\n // Standalone MDX file\n linkPath = `/${post.file.path}`;\n } else if (post.slides && !post.readme) {\n // Folder with only slides\n linkPath = `/${post.slides.path}`;\n } else if (post.readme) {\n // Folder with readme\n linkPath = `/${post.readme.path}`;\n } else {\n // Fallback to folder path\n linkPath = `/${post.path}`;\n }\n\n return (\n <Link\n key={post.path}\n to={linkPath}\n className={cn(\n \"group block py-3 px-3 -mx-3 rounded-md\",\n \"transition-colors duration-150\",\n )}\n >\n <article className=\"flex items-
|
|
1
|
+
{"version":3,"file":"post-list.js","sources":["../../../src/components/post-list.tsx"],"sourcesContent":["import { Link } from \"react-router-dom\";\nimport { cn } from \"@/lib/utils\";\nimport type { DirectoryEntry } from \"../../plugin/src/lib\";\nimport { formatDate } from \"@/lib/format-date\";\nimport { ArrowRight, Presentation } from \"lucide-react\";\nimport {\n type ContentView,\n type PostEntry,\n directoryToPostEntries,\n filterVisiblePosts,\n filterByView,\n getFrontmatter,\n} from \"@/lib/content-classification\";\n\n// Helper to extract numeric prefix from filename (e.g., \"01-intro\" → 1)\nfunction extractOrder(name: string): number | null {\n const match = name.match(/^(\\d+)-/);\n return match ? parseInt(match[1], 10) : null;\n}\n\n// Helper to strip numeric prefix for display (e.g., \"01-getting-started\" → \"Getting Started\")\nfunction stripNumericPrefix(name: string): string {\n return name\n .replace(/^\\d+-/, '')\n .replace(/-/g, ' ')\n .replace(/\\b\\w/g, c => c.toUpperCase());\n}\n\ninterface PostListProps {\n directory: DirectoryEntry;\n view?: ContentView;\n}\n\nexport default function PostList({ directory, view = 'all' }: PostListProps) {\n let posts = directoryToPostEntries(directory);\n\n if (posts.length === 0) {\n return (\n <div className=\"py-24 text-center\">\n <p className=\"text-muted-foreground font-mono text-sm tracking-wide\">no entries</p>\n </div>\n );\n }\n\n // Filter out hidden and draft posts\n posts = filterVisiblePosts(posts);\n\n // Apply view filter\n posts = filterByView(posts, view);\n\n if (posts.length === 0) {\n return (\n <div className=\"py-24 text-center\">\n <p className=\"text-muted-foreground font-mono text-sm tracking-wide\">no entries</p>\n </div>\n );\n }\n\n // Helper to get date from post\n const getPostDate = (post: PostEntry): Date | null => {\n const frontmatter = getFrontmatter(post);\n return frontmatter?.date ? new Date(frontmatter.date as string) : null;\n };\n\n // Smart sorting: numeric prefix → date → alphabetical\n posts = posts.sort((a, b) => {\n const aOrder = extractOrder(a.name);\n const bOrder = extractOrder(b.name);\n const aDate = getPostDate(a);\n const bDate = getPostDate(b);\n\n // Both have numeric prefix → sort by number\n if (aOrder !== null && bOrder !== null) {\n return aOrder - bOrder;\n }\n // One has prefix, one doesn't → prefixed comes first\n if (aOrder !== null) return -1;\n if (bOrder !== null) return 1;\n\n // Both have dates → sort by date (newest first)\n if (aDate && bDate) {\n return bDate.getTime() - aDate.getTime();\n }\n // One has date → dated comes first\n if (aDate) return -1;\n if (bDate) return 1;\n\n // Neither → alphabetical by title\n const aTitle = (getFrontmatter(a)?.title as string) || a.name;\n const bTitle = (getFrontmatter(b)?.title as string) || b.name;\n return aTitle.localeCompare(bTitle);\n });\n\n return (\n <div className=\"space-y-1\">\n {posts.map((post) => {\n const frontmatter = getFrontmatter(post);\n\n // Title: explicit frontmatter > stripped numeric prefix > raw name\n const title = (frontmatter?.title as string) || stripNumericPrefix(post.name);\n const description = frontmatter?.description as string | undefined;\n const date = frontmatter?.date ? new Date(frontmatter.date as string) : null;\n\n // Determine the link path\n let linkPath: string;\n if (post.file) {\n // Standalone MDX file\n linkPath = `/${post.file.path}`;\n } else if (post.slides && !post.readme) {\n // Folder with only slides\n linkPath = `/${post.slides.path}`;\n } else if (post.readme) {\n // Folder with readme\n linkPath = `/${post.readme.path}`;\n } else {\n // Fallback to folder path\n linkPath = `/${post.path}`;\n }\n\n const isSlides = linkPath.endsWith('SLIDES.mdx');\n\n return (\n <Link\n key={post.path}\n to={linkPath}\n className={cn(\n \"group block py-3 px-3 -mx-3 rounded-md\",\n \"transition-colors duration-150\",\n )}\n >\n <article className=\"flex items-center gap-4\">\n {/* Main content */}\n <div className=\"flex-1 min-w-0\">\n <h3 className={cn(\n \"text-sm font-medium text-foreground\",\n \"group-hover:underline\",\n \"flex items-center gap-2\"\n )}>\n <span>{title}</span>\n <ArrowRight className=\"h-3 w-3 opacity-0 -translate-x-1 group-hover:opacity-100 group-hover:translate-x-0 transition-all duration-200 text-primary\" />\n </h3>\n\n {description && (\n <p className=\"text-sm text-muted-foreground line-clamp-1 mt-0.5\">\n {description}\n </p>\n )}\n </div>\n\n {isSlides && (\n <Presentation className=\"h-3 w-3 text-muted-foreground\" />\n )}\n <time\n dateTime={date?.toISOString()}\n className=\"font-mono text-xs text-muted-foreground tabular-nums w-20 flex-shrink-0\"\n >\n {date && formatDate(date)}\n </time>\n </article>\n </Link>\n );\n })}\n </div>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
function FigureSlide({
|
|
3
|
+
title,
|
|
4
|
+
src
|
|
5
|
+
}) {
|
|
6
|
+
return /* @__PURE__ */ jsxs("div", { className: "figure-slide", children: [
|
|
7
|
+
/* @__PURE__ */ jsx("h2", { children: title }),
|
|
8
|
+
/* @__PURE__ */ jsx("img", { src, alt: title })
|
|
9
|
+
] });
|
|
10
|
+
}
|
|
11
|
+
export {
|
|
12
|
+
FigureSlide
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=figure-slide.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"figure-slide.js","sources":["../../../../src/components/slides/figure-slide.tsx"],"sourcesContent":["\n\nexport function FigureSlide({\n title,\n src,\n}: {\n title: string;\n src: string;\n}) {\n return (\n <div className=\"figure-slide\">\n <h2>{title}</h2>\n <img src={src} alt={title} />\n </div>\n );\n}"],"names":[],"mappings":";AAEO,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AACF,GAGG;AACD,SACE,qBAAC,OAAA,EAAI,WAAU,gBACb,UAAA;AAAA,IAAA,oBAAC,QAAI,UAAA,MAAA,CAAM;AAAA,IACX,oBAAC,OAAA,EAAI,KAAU,KAAK,MAAA,CAAO;AAAA,EAAA,GAC7B;AAEJ;"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
function HeroSlide({
|
|
3
|
+
title,
|
|
4
|
+
subtitle,
|
|
5
|
+
author,
|
|
6
|
+
date
|
|
7
|
+
}) {
|
|
8
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
9
|
+
/* @__PURE__ */ jsx("h1", { className: "text-[clamp(2.5rem,6vw,5rem)] font-semibold leading-[1.1] tracking-[-0.02em] text-foreground text-balance", children: title }),
|
|
10
|
+
subtitle && /* @__PURE__ */ jsx("p", { className: "text-[clamp(1rem,2vw,1.5rem)] text-muted-foreground max-w-[50ch] leading-relaxed", children: subtitle }),
|
|
11
|
+
(author || date) && /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-x-4 gap-y-1 text-sm text-muted-foreground mt-4", children: [
|
|
12
|
+
author && /* @__PURE__ */ jsx("span", { children: author }),
|
|
13
|
+
author && date && /* @__PURE__ */ jsx("span", { className: "text-border", children: "·" }),
|
|
14
|
+
date && /* @__PURE__ */ jsx("span", { children: date })
|
|
15
|
+
] })
|
|
16
|
+
] });
|
|
17
|
+
}
|
|
18
|
+
export {
|
|
19
|
+
HeroSlide
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=hero-slide.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hero-slide.js","sources":["../../../../src/components/slides/hero-slide.tsx"],"sourcesContent":["\nexport function HeroSlide({\n title,\n subtitle,\n author,\n date,\n}: {\n title: string;\n subtitle?: string;\n author?: string;\n date?: string;\n}) {\n return (\n <div>\n <h1 className=\"text-[clamp(2.5rem,6vw,5rem)] font-semibold leading-[1.1] tracking-[-0.02em] text-foreground text-balance\">\n {title}\n </h1>\n\n {subtitle && (\n <p className=\"text-[clamp(1rem,2vw,1.5rem)] text-muted-foreground max-w-[50ch] leading-relaxed\">\n {subtitle}\n </p>\n )}\n\n {(author || date) && (\n <div className=\"flex flex-wrap gap-x-4 gap-y-1 text-sm text-muted-foreground mt-4\">\n {author && <span>{author}</span>}\n {author && date && <span className=\"text-border\">·</span>}\n {date && <span>{date}</span>}\n </div>\n )}\n </div>\n );\n}\n"],"names":[],"mappings":";AACO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKG;AACD,8BACG,OAAA,EACC,UAAA;AAAA,IAAA,oBAAC,MAAA,EAAG,WAAU,6GACX,UAAA,OACH;AAAA,IAEC,YACC,oBAAC,KAAA,EAAE,WAAU,oFACV,UAAA,UACH;AAAA,KAGA,UAAU,SACV,qBAAC,OAAA,EAAI,WAAU,qEACZ,UAAA;AAAA,MAAA,UAAU,oBAAC,UAAM,UAAA,OAAA,CAAO;AAAA,MACxB,UAAU,QAAQ,oBAAC,QAAA,EAAK,WAAU,eAAc,UAAA,KAAC;AAAA,MACjD,QAAQ,oBAAC,QAAA,EAAM,UAAA,KAAA,CAAK;AAAA,IAAA,EAAA,CACvB;AAAA,EAAA,GAEJ;AAEJ;"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx } from "react/jsx-runtime";
|
|
2
|
+
function SlideOutline({
|
|
3
|
+
children,
|
|
4
|
+
className,
|
|
5
|
+
size = "md"
|
|
6
|
+
}) {
|
|
7
|
+
const wClasses = {
|
|
8
|
+
sm: "max-w-lg",
|
|
9
|
+
md: "max-w-2xl",
|
|
10
|
+
lg: "max-w-5xl",
|
|
11
|
+
xl: "max-w-7xl",
|
|
12
|
+
full: "max-w-full"
|
|
13
|
+
};
|
|
14
|
+
const wClassName = `${wClasses[size]} ${className ?? ""}`;
|
|
15
|
+
const hClasses = {
|
|
16
|
+
sm: "min-h-[300px]",
|
|
17
|
+
md: "min-h-[400px]",
|
|
18
|
+
lg: "min-h-[500px]",
|
|
19
|
+
xl: "min-h-[600px]",
|
|
20
|
+
full: "min-h-[600px]"
|
|
21
|
+
};
|
|
22
|
+
const hClassName = `${hClasses[size]} ${className ?? ""}`;
|
|
23
|
+
return /* @__PURE__ */ jsx("div", { className: `border rounded relative left-1/2 -translate-x-1/2 w-screen ${wClassName} ${hClassName} ${className}`, children });
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
SlideOutline
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=slide-outline.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slide-outline.js","sources":["../../../../src/components/slides/slide-outline.tsx"],"sourcesContent":["\n\nexport function SlideOutline({\n children,\n className,\n size=\"md\"\n}: {\n children?: React.ReactNode;\n className?: string;\n size?: \"sm\" | \"md\" | \"lg\" | \"xl\" | \"2xl\" | \"3xl\" | \"full\";\n}) {\n\n const wClasses: Record<string, string> = {\n sm: \"max-w-lg\",\n md: \"max-w-2xl\",\n lg: \"max-w-5xl\",\n xl: \"max-w-7xl\",\n full: \"max-w-full\",\n };\n\n const wClassName = `${wClasses[size]} ${className ?? \"\"}`;\n\n const hClasses: Record<string, string> = {\n sm: \"min-h-[300px]\",\n md: \"min-h-[400px]\",\n lg: \"min-h-[500px]\",\n xl: \"min-h-[600px]\",\n full: \"min-h-[600px]\",\n };\n\n const hClassName = `${hClasses[size]} ${className ?? \"\"}`;\n\n return (\n <div className={`border rounded relative left-1/2 -translate-x-1/2 w-screen ${wClassName} ${hClassName} ${className}`}>\n {children}\n </div>\n );\n}"],"names":[],"mappings":";AAEO,SAAS,aAAa;AAAA,EAC3B;AAAA,EACA;AAAA,EACA,OAAK;AACP,GAIG;AAED,QAAM,WAAmC;AAAA,IACvC,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,MAAM;AAAA,EAAA;AAGR,QAAM,aAAa,GAAG,SAAS,IAAI,CAAC,IAAI,aAAa,EAAE;AAEvD,QAAM,WAAmC;AAAA,IACvC,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,MAAM;AAAA,EAAA;AAGR,QAAM,aAAa,GAAG,SAAS,IAAI,CAAC,IAAI,aAAa,EAAE;AAEvD,SACE,oBAAC,OAAA,EAAI,WAAW,8DAA8D,UAAU,IAAI,UAAU,IAAI,SAAS,IAChH,SAAA,CACH;AAEJ;"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsxs, jsx } from "react/jsx-runtime";
|
|
2
|
+
function TextSlide({
|
|
3
|
+
title,
|
|
4
|
+
subtitle,
|
|
5
|
+
children
|
|
6
|
+
}) {
|
|
7
|
+
return /* @__PURE__ */ jsxs("div", { children: [
|
|
8
|
+
(title || subtitle) && /* @__PURE__ */ jsxs("header", { className: "flex flex-col gap-2", children: [
|
|
9
|
+
title && /* @__PURE__ */ jsx("h2", { className: "text-[clamp(1.75rem,4vw,3rem)] font-semibold leading-tight tracking-[-0.02em] text-foreground", children: title }),
|
|
10
|
+
subtitle && /* @__PURE__ */ jsx("p", { className: "text-[clamp(0.95rem,1.5vw,1.25rem)] text-muted-foreground", children: subtitle })
|
|
11
|
+
] }),
|
|
12
|
+
children && /* @__PURE__ */ jsx("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", children })
|
|
13
|
+
] });
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
TextSlide
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=text-slide.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"text-slide.js","sources":["../../../../src/components/slides/text-slide.tsx"],"sourcesContent":["\nexport function TextSlide({\n title,\n subtitle,\n children,\n}: {\n title?: string;\n subtitle?: string;\n children?: React.ReactNode;\n}) {\n return (\n <div>\n {(title || subtitle) && (\n <header className=\"flex flex-col gap-2\">\n {title && (\n <h2 className=\"text-[clamp(1.75rem,4vw,3rem)] font-semibold leading-tight tracking-[-0.02em] text-foreground\">\n {title}\n </h2>\n )}\n {subtitle && (\n <p className=\"text-[clamp(0.95rem,1.5vw,1.25rem)] text-muted-foreground\">\n {subtitle}\n </p>\n )}\n </header>\n )}\n\n {children && (\n <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\">\n {children}\n </div>\n )}\n </div>\n );\n}\n"],"names":[],"mappings":";AACO,SAAS,UAAU;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AACF,GAIG;AACD,8BACG,OAAA,EACG,UAAA;AAAA,KAAA,SAAS,aACT,qBAAC,UAAA,EAAO,WAAU,uBACf,UAAA;AAAA,MAAA,SACC,oBAAC,MAAA,EAAG,WAAU,iGACX,UAAA,OACH;AAAA,MAED,YACC,oBAAC,KAAA,EAAE,WAAU,6DACV,UAAA,SAAA,CACH;AAAA,IAAA,GAEJ;AAAA,IAGD,YACC,oBAAC,OAAA,EAAI,WAAU,8KACZ,SAAA,CACH;AAAA,EAAA,GAEJ;AAEJ;"}
|