singularity-components 0.1.196 → 0.1.197
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/blocks/cards/blogpost-card.js +1 -1
- package/dist/components/blocks/cards/blogpost-card.js.map +1 -1
- package/dist/components/blocks/directory/category-card.js +3 -2
- package/dist/components/blocks/directory/category-card.js.map +1 -1
- package/dist/components/blocks/extras/extras-hub-card.js +4 -3
- package/dist/components/blocks/extras/extras-hub-card.js.map +1 -1
- package/dist/components/blocks/login/login.js +76 -47
- package/dist/components/blocks/login/login.js.map +1 -1
- package/dist/components/blocks/marketing/timeline.js +2 -1
- package/dist/components/blocks/marketing/timeline.js.map +1 -1
- package/dist/components/blocks/post-list/post-list-with-filters.js +4 -4
- package/dist/components/blocks/post-list/post-list-with-filters.js.map +1 -1
- package/dist/components/pages/about/about-page.js +2 -2
- package/dist/components/pages/about/about-page.js.map +1 -1
- package/dist/components/pages/admin/admin-page.js +159 -105
- package/dist/components/pages/admin/admin-page.js.map +1 -1
- package/dist/components/pages/author/author-page.js +1 -1
- package/dist/components/pages/author/author-page.js.map +1 -1
- package/dist/components/pages/authors/authors-page.js +1 -1
- package/dist/components/pages/authors/authors-page.js.map +1 -1
- package/dist/components/pages/blogpost/blogpost.js +72 -44
- package/dist/components/pages/blogpost/blogpost.js.map +1 -1
- package/dist/components/pages/categories/categories-page.js +1 -1
- package/dist/components/pages/categories/categories-page.js.map +1 -1
- package/dist/components/pages/category/category-page.js +1 -1
- package/dist/components/pages/category/category-page.js.map +1 -1
- package/dist/components/pages/chat/chat-page.js +4 -4
- package/dist/components/pages/chat/chat-page.js.map +1 -1
- package/dist/components/pages/contact/contact-page.js +104 -97
- package/dist/components/pages/contact/contact-page.js.map +1 -1
- package/dist/components/pages/content-blocks/content-blocks-page.js +3 -2
- package/dist/components/pages/content-blocks/content-blocks-page.js.map +1 -1
- package/dist/components/pages/extras/extras-hub-page.js +1 -1
- package/dist/components/pages/extras/extras-hub-page.js.map +1 -1
- package/dist/components/pages/maintenance/maintenance-page.js +1 -1
- package/dist/components/pages/maintenance/maintenance-page.js.map +1 -1
- package/dist/components/pages/membership/membership-page.js +1 -1
- package/dist/components/pages/membership/membership-page.js.map +1 -1
- package/dist/components/pages/mosaic/mosaic-page.js +1 -1
- package/dist/components/pages/mosaic/mosaic-page.js.map +1 -1
- package/dist/components/pages/newsletter/newsletter-page.js +56 -39
- package/dist/components/pages/newsletter/newsletter-page.js.map +1 -1
- package/dist/components/pages/not-found/not-found.js +2 -2
- package/dist/components/pages/not-found/not-found.js.map +1 -1
- package/dist/components/pages/privacy/privacy-page.js +2 -2
- package/dist/components/pages/privacy/privacy-page.js.map +1 -1
- package/dist/components/pages/resources/resources-page.js +1 -1
- package/dist/components/pages/resources/resources-page.js.map +1 -1
- package/dist/components/pages/terms/terms-page.js +2 -2
- package/dist/components/pages/terms/terms-page.js.map +1 -1
- package/dist/components/primitives/forms/form.d.ts +1 -1
- package/dist/components/primitives/forms/form.js.map +1 -1
- package/dist/components/templates/form/form.d.ts +2 -2
- package/dist/components/templates/form/form.js +133 -87
- package/dist/components/templates/form/form.js.map +1 -1
- package/dist/components/templates/hero/hero.js +1 -0
- package/dist/components/templates/hero/hero.js.map +1 -1
- package/dist/components/templates/loading-screen/loading-screen.js +1 -1
- package/dist/components/templates/loading-screen/loading-screen.js.map +1 -1
- package/dist/css/variables.css +4 -3
- package/dist/css/variables.css.map +1 -1
- package/dist/data/posts.js +4 -4
- package/dist/data/posts.js.map +1 -1
- package/dist/lib/forms/index.d.ts +1 -1
- package/dist/lib/forms/tanstack-field.d.ts +26 -11
- package/dist/lib/forms/tanstack-field.js +13 -6
- package/dist/lib/forms/tanstack-field.js.map +1 -1
- package/dist/lib/index.d.ts +1 -1
- package/dist/main.css +16 -22
- package/dist/main.css.map +1 -1
- package/package.json +25 -30
|
@@ -38,7 +38,7 @@ function BlogPostCard({
|
|
|
38
38
|
loading: "lazy"
|
|
39
39
|
}
|
|
40
40
|
) }),
|
|
41
|
-
/* @__PURE__ */ jsxs(CardContent, { className: "sg:p-5 sg:flex sg:flex-col sg:grow", children: [
|
|
41
|
+
/* @__PURE__ */ jsxs(CardContent, { className: "sg:p-5 sg:flex sg:flex-col sg:grow sg:text-card-foreground", children: [
|
|
42
42
|
categories && categories.length > 0 && /* @__PURE__ */ jsx(Badges, { className: "sg:mb-2", children: categories.map(
|
|
43
43
|
(cat) => clickableCategories ? /* @__PURE__ */ jsx(CategoryBadge, { category: cat, clickable: true }, cat) : /* @__PURE__ */ jsx(CategoryBadge, { category: cat }, cat)
|
|
44
44
|
) }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/blocks/cards/blogpost-card.tsx"],"sourcesContent":["import { Card, CardContent } from \"./card\";\r\nimport { Link } from \"../../primitives/link/link\";\r\nimport {\r\n TextTime,\r\n Heading,\r\n Text,\r\n TextSpan,\r\n Badges,\r\n Icon,\r\n UiImage,\r\n} from \"../../primitives/index\";\r\nimport CategoryBadge from \"../badges/category-badge\";\r\n\r\ninterface Props {\r\n id: number;\r\n slug?: string;\r\n image: string;\r\n categories: string[];\r\n date: string;\r\n title: string;\r\n excerpt: string;\r\n clickableCategories?: boolean;\r\n}\r\n\r\nexport default function BlogPostCard({\r\n id,\r\n slug,\r\n image,\r\n title,\r\n categories,\r\n date,\r\n excerpt,\r\n clickableCategories = false,\r\n}: Props) {\r\n const postPath = slug ? `/posts/${slug}` : `/posts/${id}`;\r\n\r\n return (\r\n <Link\r\n to={postPath}\r\n variant=\"no-decoration\"\r\n className=\"sg:group sg:block sg:h-full\"\r\n >\r\n <Card className=\"sg:overflow-hidden sg:transition-shadow sg:hover:shadow-lg sg:h-full sg:flex sg:flex-col\">\r\n <div className=\"sg:aspect-16/10 sg:overflow-hidden\">\r\n <UiImage\r\n src={image}\r\n alt={title}\r\n className=\"sg:h-full sg:w-full sg:object-cover sg:transition-transform sg:duration-300 sg:group-hover:scale-105\"\r\n loading=\"lazy\"\r\n />\r\n </div>\r\n <CardContent className=\"sg:p-5 sg:flex sg:flex-col sg:grow\">\r\n {categories && categories.length > 0 && (\r\n <Badges className=\"sg:mb-2\">\r\n {categories.map((cat) =>\r\n clickableCategories ? (\r\n <CategoryBadge key={cat} category={cat} clickable />\r\n ) : (\r\n <CategoryBadge key={cat} category={cat} />\r\n ),\r\n )}\r\n </Badges>\r\n )}\r\n <TextTime size=\"xs\" foreground=\"muted-foreground\">\r\n {date}\r\n </TextTime>\r\n <Heading\r\n variant=\"h6\"\r\n as=\"h3\"\r\n className=\"sg:mt-1 sg:group-hover:text-primary sg:transition-colors\"\r\n >\r\n {title}\r\n </Heading>\r\n <Text\r\n size=\"sm\"\r\n foreground=\"muted-foreground\"\r\n className=\"sg:mt-2 sg:line-clamp-2\"\r\n >\r\n {excerpt}\r\n </Text>\r\n <TextSpan\r\n size=\"sm\"\r\n foreground=\"primary\"\r\n className=\"sg:mt-auto sg:pt-3 sg:inline-flex sg:items-center sg:gap-1\"\r\n >\r\n Read more <Icon icon=\"ArrowRight\" size=\"xs\" />\r\n </TextSpan>\r\n </CardContent>\r\n </Card>\r\n </Link>\r\n );\r\n}\r\n"],"mappings":"AA4CU,cAoCA,YApCA;AA5CV,SAAS,MAAM,mBAAmB;AAClC,SAAS,YAAY;AACrB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,OAAO,mBAAmB;AAaX,SAAR,aAA8B;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,sBAAsB;AACxB,GAAU;AACR,QAAM,WAAW,OAAO,UAAU,IAAI,KAAK,UAAU,EAAE;AAEvD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,IAAI;AAAA,MACJ,SAAQ;AAAA,MACR,WAAU;AAAA,MAEV,+BAAC,QAAK,WAAU,4FACd;AAAA,4BAAC,SAAI,WAAU,sCACb;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,KAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAQ;AAAA;AAAA,QACV,GACF;AAAA,QACA,qBAAC,eAAY,WAAU,
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/blocks/cards/blogpost-card.tsx"],"sourcesContent":["import { Card, CardContent } from \"./card\";\r\nimport { Link } from \"../../primitives/link/link\";\r\nimport {\r\n TextTime,\r\n Heading,\r\n Text,\r\n TextSpan,\r\n Badges,\r\n Icon,\r\n UiImage,\r\n} from \"../../primitives/index\";\r\nimport CategoryBadge from \"../badges/category-badge\";\r\n\r\ninterface Props {\r\n id: number;\r\n slug?: string;\r\n image: string;\r\n categories: string[];\r\n date: string;\r\n title: string;\r\n excerpt: string;\r\n clickableCategories?: boolean;\r\n}\r\n\r\nexport default function BlogPostCard({\r\n id,\r\n slug,\r\n image,\r\n title,\r\n categories,\r\n date,\r\n excerpt,\r\n clickableCategories = false,\r\n}: Props) {\r\n const postPath = slug ? `/posts/${slug}` : `/posts/${id}`;\r\n\r\n return (\r\n <Link\r\n to={postPath}\r\n variant=\"no-decoration\"\r\n className=\"sg:group sg:block sg:h-full\"\r\n >\r\n <Card className=\"sg:overflow-hidden sg:transition-shadow sg:hover:shadow-lg sg:h-full sg:flex sg:flex-col\">\r\n <div className=\"sg:aspect-16/10 sg:overflow-hidden\">\r\n <UiImage\r\n src={image}\r\n alt={title}\r\n className=\"sg:h-full sg:w-full sg:object-cover sg:transition-transform sg:duration-300 sg:group-hover:scale-105\"\r\n loading=\"lazy\"\r\n />\r\n </div>\r\n <CardContent className=\"sg:p-5 sg:flex sg:flex-col sg:grow sg:text-card-foreground\">\r\n {categories && categories.length > 0 && (\r\n <Badges className=\"sg:mb-2\">\r\n {categories.map((cat) =>\r\n clickableCategories ? (\r\n <CategoryBadge key={cat} category={cat} clickable />\r\n ) : (\r\n <CategoryBadge key={cat} category={cat} />\r\n ),\r\n )}\r\n </Badges>\r\n )}\r\n <TextTime size=\"xs\" foreground=\"muted-foreground\">\r\n {date}\r\n </TextTime>\r\n <Heading\r\n variant=\"h6\"\r\n as=\"h3\"\r\n className=\"sg:mt-1 sg:group-hover:text-primary sg:transition-colors\"\r\n >\r\n {title}\r\n </Heading>\r\n <Text\r\n size=\"sm\"\r\n foreground=\"muted-foreground\"\r\n className=\"sg:mt-2 sg:line-clamp-2\"\r\n >\r\n {excerpt}\r\n </Text>\r\n <TextSpan\r\n size=\"sm\"\r\n foreground=\"primary\"\r\n className=\"sg:mt-auto sg:pt-3 sg:inline-flex sg:items-center sg:gap-1\"\r\n >\r\n Read more <Icon icon=\"ArrowRight\" size=\"xs\" />\r\n </TextSpan>\r\n </CardContent>\r\n </Card>\r\n </Link>\r\n );\r\n}\r\n"],"mappings":"AA4CU,cAoCA,YApCA;AA5CV,SAAS,MAAM,mBAAmB;AAClC,SAAS,YAAY;AACrB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,OAAO,mBAAmB;AAaX,SAAR,aAA8B;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,sBAAsB;AACxB,GAAU;AACR,QAAM,WAAW,OAAO,UAAU,IAAI,KAAK,UAAU,EAAE;AAEvD,SACE;AAAA,IAAC;AAAA;AAAA,MACC,IAAI;AAAA,MACJ,SAAQ;AAAA,MACR,WAAU;AAAA,MAEV,+BAAC,QAAK,WAAU,4FACd;AAAA,4BAAC,SAAI,WAAU,sCACb;AAAA,UAAC;AAAA;AAAA,YACC,KAAK;AAAA,YACL,KAAK;AAAA,YACL,WAAU;AAAA,YACV,SAAQ;AAAA;AAAA,QACV,GACF;AAAA,QACA,qBAAC,eAAY,WAAU,8DACpB;AAAA,wBAAc,WAAW,SAAS,KACjC,oBAAC,UAAO,WAAU,WACf,qBAAW;AAAA,YAAI,CAAC,QACf,sBACE,oBAAC,iBAAwB,UAAU,KAAK,WAAS,QAA7B,GAA8B,IAElD,oBAAC,iBAAwB,UAAU,OAAf,GAAoB;AAAA,UAE5C,GACF;AAAA,UAEF,oBAAC,YAAS,MAAK,MAAK,YAAW,oBAC5B,gBACH;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,SAAQ;AAAA,cACR,IAAG;AAAA,cACH,WAAU;AAAA,cAET;AAAA;AAAA,UACH;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,YAAW;AAAA,cACX,WAAU;AAAA,cAET;AAAA;AAAA,UACH;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,MAAK;AAAA,cACL,YAAW;AAAA,cACX,WAAU;AAAA,cACX;AAAA;AAAA,gBACW,oBAAC,QAAK,MAAK,cAAa,MAAK,MAAK;AAAA;AAAA;AAAA,UAC9C;AAAA,WACF;AAAA,SACF;AAAA;AAAA,EACF;AAEJ;","names":[]}
|
|
@@ -2,6 +2,7 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Card, CardContent, CardTitle, CardDescription } from "../cards/card.js";
|
|
3
3
|
import { Badge } from "../../primitives/badge/badge.js";
|
|
4
4
|
import { Link } from "../../primitives/link/link.js";
|
|
5
|
+
import { Stack } from "../../primitives/stack/stack.js";
|
|
5
6
|
function CategoryCard({ name, count }) {
|
|
6
7
|
return /* @__PURE__ */ jsx(
|
|
7
8
|
Link,
|
|
@@ -9,14 +10,14 @@ function CategoryCard({ name, count }) {
|
|
|
9
10
|
to: `/category/${encodeURIComponent(name)}`,
|
|
10
11
|
variant: "no-decoration",
|
|
11
12
|
className: "sg:group sg:block",
|
|
12
|
-
children: /* @__PURE__ */ jsx(Card, { className: "sg:transition-shadow sg:hover:shadow-lg sg:hover:border-primary/40", children: /* @__PURE__ */
|
|
13
|
+
children: /* @__PURE__ */ jsx(Card, { className: "sg:transition-shadow sg:hover:shadow-lg sg:hover:border-primary/40", children: /* @__PURE__ */ jsx(CardContent, { className: "sg:p-6", children: /* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
|
|
13
14
|
/* @__PURE__ */ jsx(CardTitle, { className: "sg:text-xl sg:group-hover:text-primary sg:transition-colors", children: name }),
|
|
14
15
|
/* @__PURE__ */ jsx(CardDescription, { children: /* @__PURE__ */ jsxs(Badge, { variant: "secondary", children: [
|
|
15
16
|
count,
|
|
16
17
|
" post",
|
|
17
18
|
count !== 1 ? "s" : ""
|
|
18
19
|
] }) })
|
|
19
|
-
] }) })
|
|
20
|
+
] }) }) })
|
|
20
21
|
}
|
|
21
22
|
);
|
|
22
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/blocks/directory/category-card.tsx"],"sourcesContent":["import { Card, CardContent, CardTitle, CardDescription } from \"../cards/card\";\r\nimport { Badge } from \"../../primitives/badge/badge\";\r\nimport { Link } from \"../../primitives/link/link\";\r\n\r\ntype Props = {\r\n\tname: string;\r\n\tcount: number;\r\n};\r\n\r\n/** Category index card linking to category page. */\r\nexport function CategoryCard({ name, count }: Props) {\r\n\treturn (\r\n\t\t<Link\r\n\t\t\tto={`/category/${encodeURIComponent(name)}`}\r\n\t\t\tvariant=\"no-decoration\"\r\n\t\t\tclassName=\"sg:group sg:block\"\r\n\t\t>\r\n\t\t\t<Card className=\"sg:transition-shadow sg:hover:shadow-lg sg:hover:border-primary/40\">\r\n\t\t\t\t<CardContent className=\"sg:p-6\">\r\n\t\t\t\t\t<CardTitle className=\"sg:text-xl sg:group-hover:text-primary sg:transition-colors\">\r\n\t\t\t\t\t\t{name}\r\n\t\t\t\t\t</CardTitle>\r\n\t\t\t\t\t<CardDescription>\r\n\t\t\t\t\t\t<Badge variant=\"secondary\">\r\n\t\t\t\t\t\t\t{count} post{count !== 1 ? \"s\" : \"\"}\r\n\t\t\t\t\t\t</Badge>\r\n\t\t\t\t\t</CardDescription>\r\n\t\t\t\t</CardContent>\r\n\t\t\t</Card>\r\n\t\t</Link>\r\n\t);\r\n}\r\n"],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/blocks/directory/category-card.tsx"],"sourcesContent":["import { Card, CardContent, CardTitle, CardDescription } from \"../cards/card\";\r\nimport { Badge } from \"../../primitives/badge/badge\";\r\nimport { Link } from \"../../primitives/link/link\";\r\nimport { Stack } from \"../../primitives/stack/stack\";\r\n\r\ntype Props = {\r\n\tname: string;\r\n\tcount: number;\r\n};\r\n\r\n/** Category index card linking to category page. */\r\nexport function CategoryCard({ name, count }: Props) {\r\n\treturn (\r\n\t\t<Link\r\n\t\t\tto={`/category/${encodeURIComponent(name)}`}\r\n\t\t\tvariant=\"no-decoration\"\r\n\t\t\tclassName=\"sg:group sg:block\"\r\n\t\t>\r\n\t\t\t<Card className=\"sg:transition-shadow sg:hover:shadow-lg sg:hover:border-primary/40\">\r\n\t\t\t\t<CardContent className=\"sg:p-6\">\r\n\t\t\t\t\t<Stack gap={2}>\r\n\t\t\t\t\t\t<CardTitle className=\"sg:text-xl sg:group-hover:text-primary sg:transition-colors\">\r\n\t\t\t\t\t\t\t{name}\r\n\t\t\t\t\t\t</CardTitle>\r\n\t\t\t\t\t\t<CardDescription>\r\n\t\t\t\t\t\t\t<Badge variant=\"secondary\">\r\n\t\t\t\t\t\t\t\t{count} post{count !== 1 ? \"s\" : \"\"}\r\n\t\t\t\t\t\t\t</Badge>\r\n\t\t\t\t\t\t</CardDescription>\r\n\t\t\t\t\t</Stack>\r\n\t\t\t\t</CardContent>\r\n\t\t\t</Card>\r\n\t\t</Link>\r\n\t);\r\n}\r\n"],"mappings":"AAqBM,cAIC,YAJD;AArBN,SAAS,MAAM,aAAa,WAAW,uBAAuB;AAC9D,SAAS,aAAa;AACtB,SAAS,YAAY;AACrB,SAAS,aAAa;AAQf,SAAS,aAAa,EAAE,MAAM,MAAM,GAAU;AACpD,SACC;AAAA,IAAC;AAAA;AAAA,MACA,IAAI,aAAa,mBAAmB,IAAI,CAAC;AAAA,MACzC,SAAQ;AAAA,MACR,WAAU;AAAA,MAEV,8BAAC,QAAK,WAAU,sEACf,8BAAC,eAAY,WAAU,UACtB,+BAAC,SAAM,KAAK,GACX;AAAA,4BAAC,aAAU,WAAU,+DACnB,gBACF;AAAA,QACA,oBAAC,mBACA,+BAAC,SAAM,SAAQ,aACb;AAAA;AAAA,UAAM;AAAA,UAAM,UAAU,IAAI,MAAM;AAAA,WAClC,GACD;AAAA,SACD,GACD,GACD;AAAA;AAAA,EACD;AAEF;","names":[]}
|
|
@@ -2,18 +2,19 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { Card, CardContent, CardTitle, CardDescription } from "../cards/card.js";
|
|
3
3
|
import { Icon } from "../../primitives/icon/icon.js";
|
|
4
4
|
import { Link } from "../../primitives/link/link.js";
|
|
5
|
+
import { Stack } from "../../primitives/stack/stack.js";
|
|
5
6
|
function ExtrasHubCard({ item }) {
|
|
6
|
-
return /* @__PURE__ */ jsx(Link, { to: item.to, variant: "no-decoration", className: "sg:group sg:block", children: /* @__PURE__ */ jsx(Card, { className: "sg:transition-shadow sg:hover:shadow-lg sg:hover:border-primary/40", children: /* @__PURE__ */
|
|
7
|
+
return /* @__PURE__ */ jsx(Link, { to: item.to, variant: "no-decoration", className: "sg:group sg:block", children: /* @__PURE__ */ jsx(Card, { className: "sg:transition-shadow sg:hover:shadow-lg sg:hover:border-primary/40", children: /* @__PURE__ */ jsx(CardContent, { className: "sg:p-6", children: /* @__PURE__ */ jsxs(Stack, { gap: 2, children: [
|
|
7
8
|
/* @__PURE__ */ jsx(
|
|
8
9
|
Icon,
|
|
9
10
|
{
|
|
10
11
|
icon: item.icon,
|
|
11
|
-
className: "sg:h-6 sg:w-6 sg:text-primary
|
|
12
|
+
className: "sg:h-6 sg:w-6 sg:text-primary"
|
|
12
13
|
}
|
|
13
14
|
),
|
|
14
15
|
/* @__PURE__ */ jsx(CardTitle, { className: "sg:group-hover:text-primary sg:transition-colors", children: item.title }),
|
|
15
16
|
/* @__PURE__ */ jsx(CardDescription, { children: item.description })
|
|
16
|
-
] }) }) });
|
|
17
|
+
] }) }) }) });
|
|
17
18
|
}
|
|
18
19
|
export {
|
|
19
20
|
ExtrasHubCard
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/blocks/extras/extras-hub-card.tsx"],"sourcesContent":["import type { icons } from \"lucide-react\";\r\nimport { Card, CardContent, CardTitle, CardDescription } from \"../cards/card\";\r\nimport { Icon } from \"../../primitives/icon/icon\";\r\nimport { Link } from \"../../primitives/link/link\";\r\n\r\nexport type ExtrasHubItem = {\r\n\ttitle: string;\r\n\tdescription: string;\r\n\tto: string;\r\n\ticon: keyof typeof icons;\r\n};\r\n\r\ntype Props = {\r\n\titem: ExtrasHubItem;\r\n};\r\n\r\n/** Linked card for the extras hub index page. */\r\nexport function ExtrasHubCard({ item }: Props) {\r\n\treturn (\r\n\t\t<Link to={item.to} variant=\"no-decoration\" className=\"sg:group sg:block\">\r\n\t\t\t<Card className=\"sg:transition-shadow sg:hover:shadow-lg sg:hover:border-primary/40\">\r\n\t\t\t\t<CardContent className=\"sg:p-6\">\r\n\t\t\t\t\t<Icon\r\n\t\t\t\t\t\ticon={item.icon}\r\n\t\t\t\t\t\tclassName=\"sg:h-6 sg:w-6 sg:text-primary
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/blocks/extras/extras-hub-card.tsx"],"sourcesContent":["import type { icons } from \"lucide-react\";\r\nimport { Card, CardContent, CardTitle, CardDescription } from \"../cards/card\";\r\nimport { Icon } from \"../../primitives/icon/icon\";\r\nimport { Link } from \"../../primitives/link/link\";\r\nimport { Stack } from \"../../primitives/stack/stack\";\r\n\r\nexport type ExtrasHubItem = {\r\n\ttitle: string;\r\n\tdescription: string;\r\n\tto: string;\r\n\ticon: keyof typeof icons;\r\n};\r\n\r\ntype Props = {\r\n\titem: ExtrasHubItem;\r\n};\r\n\r\n/** Linked card for the extras hub index page. */\r\nexport function ExtrasHubCard({ item }: Props) {\r\n\treturn (\r\n\t\t<Link to={item.to} variant=\"no-decoration\" className=\"sg:group sg:block\">\r\n\t\t\t<Card className=\"sg:transition-shadow sg:hover:shadow-lg sg:hover:border-primary/40\">\r\n\t\t\t\t<CardContent className=\"sg:p-6\">\r\n\t\t\t\t\t<Stack gap={2}>\r\n\t\t\t\t\t\t<Icon\r\n\t\t\t\t\t\t\ticon={item.icon}\r\n\t\t\t\t\t\t\tclassName=\"sg:h-6 sg:w-6 sg:text-primary\"\r\n\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t<CardTitle className=\"sg:group-hover:text-primary sg:transition-colors\">\r\n\t\t\t\t\t\t\t{item.title}\r\n\t\t\t\t\t\t</CardTitle>\r\n\t\t\t\t\t\t<CardDescription>{item.description}</CardDescription>\r\n\t\t\t\t\t</Stack>\r\n\t\t\t\t</CardContent>\r\n\t\t\t</Card>\r\n\t\t</Link>\r\n\t);\r\n}\r\n"],"mappings":"AAuBK,SACC,KADD;AAtBL,SAAS,MAAM,aAAa,WAAW,uBAAuB;AAC9D,SAAS,YAAY;AACrB,SAAS,YAAY;AACrB,SAAS,aAAa;AAcf,SAAS,cAAc,EAAE,KAAK,GAAU;AAC9C,SACC,oBAAC,QAAK,IAAI,KAAK,IAAI,SAAQ,iBAAgB,WAAU,qBACpD,8BAAC,QAAK,WAAU,sEACf,8BAAC,eAAY,WAAU,UACtB,+BAAC,SAAM,KAAK,GACX;AAAA;AAAA,MAAC;AAAA;AAAA,QACA,MAAM,KAAK;AAAA,QACX,WAAU;AAAA;AAAA,IACX;AAAA,IACA,oBAAC,aAAU,WAAU,oDACnB,eAAK,OACP;AAAA,IACA,oBAAC,mBAAiB,eAAK,aAAY;AAAA,KACpC,GACD,GACD,GACD;AAEF;","names":[]}
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
3
|
+
import { useForm } from "@tanstack/react-form";
|
|
4
|
+
import { useId } from "react";
|
|
5
|
+
import { TanStackInputField } from "../../../lib/forms/tanstack-field.js";
|
|
4
6
|
import { Button } from "../../primitives/buttons/button.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
+
import { FieldGroup } from "../../primitives/forms/field.js";
|
|
8
|
+
import { Form, FormActions } from "../../primitives/forms/form.js";
|
|
7
9
|
import { Heading, Link, Text } from "../../primitives/index.js";
|
|
8
10
|
import { cn } from "../../../utils/index.js";
|
|
9
11
|
function Login({
|
|
@@ -25,56 +27,83 @@ function Login({
|
|
|
25
27
|
autoFocus = false
|
|
26
28
|
}) {
|
|
27
29
|
const id = useId();
|
|
28
|
-
const usernameId = `${id}-username`;
|
|
29
|
-
const passwordId = `${id}-password`;
|
|
30
30
|
const titleId = `${id}-title`;
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
31
|
+
const form = useForm({
|
|
32
|
+
defaultValues: {
|
|
33
|
+
username: "",
|
|
34
|
+
password: ""
|
|
35
|
+
},
|
|
36
|
+
onSubmit: async ({ value }) => {
|
|
37
|
+
await onSubmit?.(value);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
37
40
|
return /* @__PURE__ */ jsxs("div", { className: cn("sg:w-full sg:max-w-sm sg:space-y-6", className), children: [
|
|
38
41
|
/* @__PURE__ */ jsxs("div", { className: "sg:text-center", children: [
|
|
39
42
|
/* @__PURE__ */ jsx(Heading, { variant: titleVariant, id: titleId, children: title }),
|
|
40
43
|
description && /* @__PURE__ */ jsx(Text, { className: "sg:mt-2", foreground: "muted-foreground", children: description })
|
|
41
44
|
] }),
|
|
42
|
-
/* @__PURE__ */ jsxs(
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
45
|
+
/* @__PURE__ */ jsxs(
|
|
46
|
+
Form,
|
|
47
|
+
{
|
|
48
|
+
className: "sg:gap-4",
|
|
49
|
+
"aria-labelledby": titleId,
|
|
50
|
+
onSubmit: (event) => {
|
|
51
|
+
event.preventDefault();
|
|
52
|
+
event.stopPropagation();
|
|
53
|
+
void form.handleSubmit();
|
|
54
|
+
},
|
|
55
|
+
children: [
|
|
56
|
+
/* @__PURE__ */ jsxs(FieldGroup, { children: [
|
|
57
|
+
/* @__PURE__ */ jsx(
|
|
58
|
+
TanStackInputField,
|
|
59
|
+
{
|
|
60
|
+
formApi: form,
|
|
61
|
+
name: "username",
|
|
62
|
+
label: usernameLabel,
|
|
63
|
+
type: usernameType,
|
|
64
|
+
placeholder: usernamePlaceholder,
|
|
65
|
+
autoFocus,
|
|
66
|
+
disabled: loading,
|
|
67
|
+
autoComplete: "username",
|
|
68
|
+
validators: {
|
|
69
|
+
onChange: ({ value }) => value.trim() ? void 0 : `${usernameLabel} is required.`
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
),
|
|
73
|
+
/* @__PURE__ */ jsx(
|
|
74
|
+
TanStackInputField,
|
|
75
|
+
{
|
|
76
|
+
formApi: form,
|
|
77
|
+
name: "password",
|
|
78
|
+
label: passwordLabel,
|
|
79
|
+
type: "password",
|
|
80
|
+
placeholder: passwordPlaceholder,
|
|
81
|
+
disabled: loading,
|
|
82
|
+
autoComplete: "current-password",
|
|
83
|
+
validators: {
|
|
84
|
+
onChange: ({ value }) => value.trim() ? void 0 : `${passwordLabel} is required.`
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
] }),
|
|
89
|
+
/* @__PURE__ */ jsx(FormActions, { children: /* @__PURE__ */ jsx(
|
|
90
|
+
form.Subscribe,
|
|
91
|
+
{
|
|
92
|
+
selector: (state) => [state.canSubmit, state.isSubmitting],
|
|
93
|
+
children: ([canSubmit, isSubmitting]) => /* @__PURE__ */ jsx(
|
|
94
|
+
Button,
|
|
95
|
+
{
|
|
96
|
+
type: "submit",
|
|
97
|
+
className: "sg:w-full",
|
|
98
|
+
disabled: loading || !canSubmit || isSubmitting,
|
|
99
|
+
children: loading || isSubmitting ? loadingLabel : submitLabel
|
|
100
|
+
}
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
) })
|
|
104
|
+
]
|
|
105
|
+
}
|
|
106
|
+
),
|
|
78
107
|
signUpLabel && signUpHref && /* @__PURE__ */ jsxs(
|
|
79
108
|
Text,
|
|
80
109
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/blocks/login/login.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport { useId
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/blocks/login/login.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport { useForm } from \"@tanstack/react-form\";\r\nimport { useId } from \"react\";\r\nimport { TanStackInputField } from \"../../../lib/forms/tanstack-field\";\r\nimport { Button } from \"../../primitives/buttons/button\";\r\nimport { FieldGroup } from \"../../primitives/forms/field\";\r\nimport { Form, FormActions } from \"../../primitives/forms/form\";\r\nimport { Heading, Link, Text } from \"../../primitives/index\";\r\nimport { cn } from \"../../../utils/index\";\r\n\r\nexport type LoginCredentials = {\r\n username: string;\r\n password: string;\r\n};\r\n\r\nexport type LoginProps = {\r\n /**\r\n * Form heading text.\r\n */\r\n title?: string;\r\n /**\r\n * Supporting text shown below the heading.\r\n */\r\n description?: string;\r\n /**\r\n * Label for the username or email field.\r\n */\r\n usernameLabel?: string;\r\n /**\r\n * Input type for the identifier field.\r\n */\r\n usernameType?: \"text\" | \"email\";\r\n /**\r\n * Placeholder for the identifier field.\r\n */\r\n usernamePlaceholder?: string;\r\n /**\r\n * Label for the password field.\r\n */\r\n passwordLabel?: string;\r\n /**\r\n * Placeholder for the password field.\r\n */\r\n passwordPlaceholder?: string;\r\n /**\r\n * Submit button label when not loading.\r\n */\r\n submitLabel?: string;\r\n /**\r\n * Submit button label while loading.\r\n */\r\n loadingLabel?: string;\r\n /**\r\n * Disables the form and shows the loading label on submit.\r\n */\r\n loading?: boolean;\r\n /**\r\n * Label for the optional sign-up link.\r\n */\r\n signUpLabel?: string;\r\n /**\r\n * Destination for the optional sign-up link.\r\n */\r\n signUpHref?: string;\r\n /**\r\n * Heading level for the title.\r\n */\r\n titleVariant?: \"h1\" | \"h2\" | \"h3\" | \"h4\";\r\n /**\r\n * Called when the form is submitted with valid credentials.\r\n */\r\n onSubmit?: (credentials: LoginCredentials) => void | Promise<void>;\r\n /**\r\n * Additional classes for the root wrapper.\r\n */\r\n className?: string;\r\n /**\r\n * Focuses the identifier field on mount.\r\n */\r\n autoFocus?: boolean;\r\n};\r\n\r\n/**\r\n * Reusable login form with username/email and password fields.\r\n */\r\nexport function Login({\r\n title = \"Log in\",\r\n description,\r\n usernameLabel = \"Username\",\r\n usernameType = \"text\",\r\n usernamePlaceholder = \"johndoe\",\r\n passwordLabel = \"Password\",\r\n passwordPlaceholder = \"••••••••\",\r\n submitLabel = \"Log in\",\r\n loadingLabel = \"Logging in...\",\r\n loading = false,\r\n signUpLabel,\r\n signUpHref,\r\n titleVariant = \"h1\",\r\n onSubmit,\r\n className,\r\n autoFocus = false,\r\n}: LoginProps) {\r\n const id = useId();\r\n const titleId = `${id}-title`;\r\n\r\n const form = useForm({\r\n defaultValues: {\r\n username: \"\",\r\n password: \"\",\r\n } satisfies LoginCredentials,\r\n onSubmit: async ({ value }) => {\r\n await onSubmit?.(value);\r\n },\r\n });\r\n\r\n return (\r\n <div className={cn(\"sg:w-full sg:max-w-sm sg:space-y-6\", className)}>\r\n <div className=\"sg:text-center\">\r\n <Heading variant={titleVariant} id={titleId}>\r\n {title}\r\n </Heading>\r\n {description && (\r\n <Text className=\"sg:mt-2\" foreground=\"muted-foreground\">\r\n {description}\r\n </Text>\r\n )}\r\n </div>\r\n\r\n <Form\r\n className=\"sg:gap-4\"\r\n aria-labelledby={titleId}\r\n onSubmit={(event) => {\r\n event.preventDefault();\r\n event.stopPropagation();\r\n void form.handleSubmit();\r\n }}\r\n >\r\n <FieldGroup>\r\n <TanStackInputField\r\n formApi={form}\r\n name=\"username\"\r\n label={usernameLabel}\r\n type={usernameType}\r\n placeholder={usernamePlaceholder}\r\n autoFocus={autoFocus}\r\n disabled={loading}\r\n autoComplete=\"username\"\r\n validators={{\r\n onChange: ({ value }: { value: string }) =>\r\n value.trim() ? undefined : `${usernameLabel} is required.`,\r\n }}\r\n />\r\n <TanStackInputField\r\n formApi={form}\r\n name=\"password\"\r\n label={passwordLabel}\r\n type=\"password\"\r\n placeholder={passwordPlaceholder}\r\n disabled={loading}\r\n autoComplete=\"current-password\"\r\n validators={{\r\n onChange: ({ value }: { value: string }) =>\r\n value.trim() ? undefined : `${passwordLabel} is required.`,\r\n }}\r\n />\r\n </FieldGroup>\r\n <FormActions>\r\n <form.Subscribe\r\n selector={(state) => [state.canSubmit, state.isSubmitting]}\r\n >\r\n {([canSubmit, isSubmitting]) => (\r\n <Button\r\n type=\"submit\"\r\n className=\"sg:w-full\"\r\n disabled={loading || !canSubmit || isSubmitting}\r\n >\r\n {loading || isSubmitting ? loadingLabel : submitLabel}\r\n </Button>\r\n )}\r\n </form.Subscribe>\r\n </FormActions>\r\n </Form>\r\n\r\n {signUpLabel && signUpHref && (\r\n <Text\r\n size=\"sm\"\r\n foreground=\"muted-foreground\"\r\n className=\"sg:text-center\"\r\n >\r\n Don't have an account? <Link to={signUpHref}>{signUpLabel}</Link>\r\n </Text>\r\n )}\r\n </div>\r\n );\r\n}\r\n"],"mappings":";AAuHM,SACE,KADF;AArHN,SAAS,eAAe;AACxB,SAAS,aAAa;AACtB,SAAS,0BAA0B;AACnC,SAAS,cAAc;AACvB,SAAS,kBAAkB;AAC3B,SAAS,MAAM,mBAAmB;AAClC,SAAS,SAAS,MAAM,YAAY;AACpC,SAAS,UAAU;AA6EZ,SAAS,MAAM;AAAA,EACpB,QAAQ;AAAA,EACR;AAAA,EACA,gBAAgB;AAAA,EAChB,eAAe;AAAA,EACf,sBAAsB;AAAA,EACtB,gBAAgB;AAAA,EAChB,sBAAsB;AAAA,EACtB,cAAc;AAAA,EACd,eAAe;AAAA,EACf,UAAU;AAAA,EACV;AAAA,EACA;AAAA,EACA,eAAe;AAAA,EACf;AAAA,EACA;AAAA,EACA,YAAY;AACd,GAAe;AACb,QAAM,KAAK,MAAM;AACjB,QAAM,UAAU,GAAG,EAAE;AAErB,QAAM,OAAO,QAAQ;AAAA,IACnB,eAAe;AAAA,MACb,UAAU;AAAA,MACV,UAAU;AAAA,IACZ;AAAA,IACA,UAAU,OAAO,EAAE,MAAM,MAAM;AAC7B,YAAM,WAAW,KAAK;AAAA,IACxB;AAAA,EACF,CAAC;AAED,SACE,qBAAC,SAAI,WAAW,GAAG,sCAAsC,SAAS,GAChE;AAAA,yBAAC,SAAI,WAAU,kBACb;AAAA,0BAAC,WAAQ,SAAS,cAAc,IAAI,SACjC,iBACH;AAAA,MACC,eACC,oBAAC,QAAK,WAAU,WAAU,YAAW,oBAClC,uBACH;AAAA,OAEJ;AAAA,IAEA;AAAA,MAAC;AAAA;AAAA,QACC,WAAU;AAAA,QACV,mBAAiB;AAAA,QACjB,UAAU,CAAC,UAAU;AACnB,gBAAM,eAAe;AACrB,gBAAM,gBAAgB;AACtB,eAAK,KAAK,aAAa;AAAA,QACzB;AAAA,QAEA;AAAA,+BAAC,cACC;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAS;AAAA,gBACT,MAAK;AAAA,gBACL,OAAO;AAAA,gBACP,MAAM;AAAA,gBACN,aAAa;AAAA,gBACb;AAAA,gBACA,UAAU;AAAA,gBACV,cAAa;AAAA,gBACb,YAAY;AAAA,kBACV,UAAU,CAAC,EAAE,MAAM,MACjB,MAAM,KAAK,IAAI,SAAY,GAAG,aAAa;AAAA,gBAC/C;AAAA;AAAA,YACF;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAS;AAAA,gBACT,MAAK;AAAA,gBACL,OAAO;AAAA,gBACP,MAAK;AAAA,gBACL,aAAa;AAAA,gBACb,UAAU;AAAA,gBACV,cAAa;AAAA,gBACb,YAAY;AAAA,kBACV,UAAU,CAAC,EAAE,MAAM,MACjB,MAAM,KAAK,IAAI,SAAY,GAAG,aAAa;AAAA,gBAC/C;AAAA;AAAA,YACF;AAAA,aACF;AAAA,UACA,oBAAC,eACC;AAAA,YAAC,KAAK;AAAA,YAAL;AAAA,cACC,UAAU,CAAC,UAAU,CAAC,MAAM,WAAW,MAAM,YAAY;AAAA,cAExD,WAAC,CAAC,WAAW,YAAY,MACxB;AAAA,gBAAC;AAAA;AAAA,kBACC,MAAK;AAAA,kBACL,WAAU;AAAA,kBACV,UAAU,WAAW,CAAC,aAAa;AAAA,kBAElC,qBAAW,eAAe,eAAe;AAAA;AAAA,cAC5C;AAAA;AAAA,UAEJ,GACF;AAAA;AAAA;AAAA,IACF;AAAA,IAEC,eAAe,cACd;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,YAAW;AAAA,QACX,WAAU;AAAA,QACX;AAAA;AAAA,UAC6B,oBAAC,QAAK,IAAI,YAAa,uBAAY;AAAA;AAAA;AAAA,IACjE;AAAA,KAEJ;AAEJ;","names":[]}
|
|
@@ -29,7 +29,8 @@ function Timeline({
|
|
|
29
29
|
Text,
|
|
30
30
|
{
|
|
31
31
|
size: "xs",
|
|
32
|
-
|
|
32
|
+
foreground: "muted-foreground",
|
|
33
|
+
className: "sg:font-mono sg:uppercase sg:tracking-wider",
|
|
33
34
|
children: item.year
|
|
34
35
|
}
|
|
35
36
|
),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/blocks/marketing/timeline.tsx"],"sourcesContent":["import { Heading, Text } from \"../../primitives/index\";\r\n\r\nexport type TimelineItem = {\r\n\tyear: string;\r\n\ttitle: string;\r\n\tdescription: string;\r\n};\r\n\r\ntype Props = {\r\n\titems: TimelineItem[];\r\n\ttitle?: string;\r\n\tdescription?: string;\r\n\tclassName?: string;\r\n};\r\n\r\n/** Vertical timeline with year, title, and description entries. */\r\nexport function Timeline({\r\n\titems,\r\n\ttitle = \"Our Journey\",\r\n\tdescription,\r\n\tclassName,\r\n}: Props) {\r\n\treturn (\r\n\t\t<div className={className}>\r\n\t\t\t<Heading variant=\"h2\" className=\"sg:mb-2\">\r\n\t\t\t\t{title}\r\n\t\t\t</Heading>\r\n\t\t\t{description && (\r\n\t\t\t\t<Text foreground=\"muted-foreground\" className=\"sg:mb-10\">\r\n\t\t\t\t\t{description}\r\n\t\t\t\t</Text>\r\n\t\t\t)}\r\n\t\t\t<div className=\"sg:relative\">\r\n\t\t\t\t<div\r\n\t\t\t\t\tclassName=\"sg:absolute sg:left-4 md:sg:left-6 sg:top-0 sg:bottom-0 sg:w-px sg:bg-border\"\r\n\t\t\t\t\taria-hidden=\"true\"\r\n\t\t\t\t/>\r\n\t\t\t\t<div className=\"sg:space-y-10\">\r\n\t\t\t\t\t{items.map((item, i) => (\r\n\t\t\t\t\t\t<div key={i} className=\"sg:relative sg:pl-12 md:sg:pl-16\">\r\n\t\t\t\t\t\t\t<div\r\n\t\t\t\t\t\t\t\tclassName=\"sg:absolute sg:left-2.5 md:sg:left-4.5 sg:top-1 sg:h-3 sg:w-3 sg:rounded-full sg:bg-primary sg:ring-4 sg:ring-background\"\r\n\t\t\t\t\t\t\t\taria-hidden=\"true\"\r\n\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t<Text\r\n\t\t\t\t\t\t\t\tsize=\"xs\"\r\n\t\t\t\t\t\t\t\tclassName=\"sg:font-mono sg:
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/blocks/marketing/timeline.tsx"],"sourcesContent":["import { Heading, Text } from \"../../primitives/index\";\r\n\r\nexport type TimelineItem = {\r\n\tyear: string;\r\n\ttitle: string;\r\n\tdescription: string;\r\n};\r\n\r\ntype Props = {\r\n\titems: TimelineItem[];\r\n\ttitle?: string;\r\n\tdescription?: string;\r\n\tclassName?: string;\r\n};\r\n\r\n/** Vertical timeline with year, title, and description entries. */\r\nexport function Timeline({\r\n\titems,\r\n\ttitle = \"Our Journey\",\r\n\tdescription,\r\n\tclassName,\r\n}: Props) {\r\n\treturn (\r\n\t\t<div className={className}>\r\n\t\t\t<Heading variant=\"h2\" className=\"sg:mb-2\">\r\n\t\t\t\t{title}\r\n\t\t\t</Heading>\r\n\t\t\t{description && (\r\n\t\t\t\t<Text foreground=\"muted-foreground\" className=\"sg:mb-10\">\r\n\t\t\t\t\t{description}\r\n\t\t\t\t</Text>\r\n\t\t\t)}\r\n\t\t\t<div className=\"sg:relative\">\r\n\t\t\t\t<div\r\n\t\t\t\t\tclassName=\"sg:absolute sg:left-4 md:sg:left-6 sg:top-0 sg:bottom-0 sg:w-px sg:bg-border\"\r\n\t\t\t\t\taria-hidden=\"true\"\r\n\t\t\t\t/>\r\n\t\t\t\t<div className=\"sg:space-y-10\">\r\n\t\t\t\t\t{items.map((item, i) => (\r\n\t\t\t\t\t\t<div key={i} className=\"sg:relative sg:pl-12 md:sg:pl-16\">\r\n\t\t\t\t\t\t\t<div\r\n\t\t\t\t\t\t\t\tclassName=\"sg:absolute sg:left-2.5 md:sg:left-4.5 sg:top-1 sg:h-3 sg:w-3 sg:rounded-full sg:bg-primary sg:ring-4 sg:ring-background\"\r\n\t\t\t\t\t\t\t\taria-hidden=\"true\"\r\n\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t<Text\r\n\t\t\t\t\t\t\t\tsize=\"xs\"\r\n\t\t\t\t\t\t\t\tforeground=\"muted-foreground\"\r\n\t\t\t\t\t\t\t\tclassName=\"sg:font-mono sg:uppercase sg:tracking-wider\"\r\n\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t{item.year}\r\n\t\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t\t\t<Heading variant=\"h4\" className=\"sg:mt-0.5\">\r\n\t\t\t\t\t\t\t\t{item.title}\r\n\t\t\t\t\t\t\t</Heading>\r\n\t\t\t\t\t\t\t<Text size=\"sm\" foreground=\"muted-foreground\" className=\"sg:mt-1\">\r\n\t\t\t\t\t\t\t\t{item.description}\r\n\t\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t\t</div>\r\n\t\t\t\t\t))}\r\n\t\t\t\t</div>\r\n\t\t\t</div>\r\n\t\t</div>\r\n\t);\r\n}\r\n"],"mappings":"AAwBG,cAeG,YAfH;AAxBH,SAAS,SAAS,YAAY;AAgBvB,SAAS,SAAS;AAAA,EACxB;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AACD,GAAU;AACT,SACC,qBAAC,SAAI,WACJ;AAAA,wBAAC,WAAQ,SAAQ,MAAK,WAAU,WAC9B,iBACF;AAAA,IACC,eACA,oBAAC,QAAK,YAAW,oBAAmB,WAAU,YAC5C,uBACF;AAAA,IAED,qBAAC,SAAI,WAAU,eACd;AAAA;AAAA,QAAC;AAAA;AAAA,UACA,WAAU;AAAA,UACV,eAAY;AAAA;AAAA,MACb;AAAA,MACA,oBAAC,SAAI,WAAU,iBACb,gBAAM,IAAI,CAAC,MAAM,MACjB,qBAAC,SAAY,WAAU,oCACtB;AAAA;AAAA,UAAC;AAAA;AAAA,YACA,WAAU;AAAA,YACV,eAAY;AAAA;AAAA,QACb;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACA,MAAK;AAAA,YACL,YAAW;AAAA,YACX,WAAU;AAAA,YAET,eAAK;AAAA;AAAA,QACP;AAAA,QACA,oBAAC,WAAQ,SAAQ,MAAK,WAAU,aAC9B,eAAK,OACP;AAAA,QACA,oBAAC,QAAK,MAAK,MAAK,YAAW,oBAAmB,WAAU,WACtD,eAAK,aACP;AAAA,WAjBS,CAkBV,CACA,GACF;AAAA,OACD;AAAA,KACD;AAEF;","names":[]}
|
|
@@ -193,9 +193,9 @@ function PostListWithFilters({
|
|
|
193
193
|
/* @__PURE__ */ jsx(AnimatePresence, { children: isFiltersOpen && /* @__PURE__ */ jsxs(
|
|
194
194
|
motion.div,
|
|
195
195
|
{
|
|
196
|
-
initial: { height: 0, opacity:
|
|
196
|
+
initial: { height: 0, opacity: 1 },
|
|
197
197
|
animate: { height: "auto", opacity: 1 },
|
|
198
|
-
exit: { height: 0, opacity:
|
|
198
|
+
exit: { height: 0, opacity: 1 },
|
|
199
199
|
className: "sg:overflow-hidden sg:border sg:rounded-xl sg:p-6 sg:bg-card sg:mb-8 sg:shadow-sm",
|
|
200
200
|
children: [
|
|
201
201
|
/* @__PURE__ */ jsxs("div", { className: "sg:flex sg:justify-between sg:items-center sg:mb-6", children: [
|
|
@@ -312,9 +312,9 @@ function PostListWithFilters({
|
|
|
312
312
|
/* @__PURE__ */ jsx(AnimatePresence, { mode: "wait", children: /* @__PURE__ */ jsx(
|
|
313
313
|
motion.div,
|
|
314
314
|
{
|
|
315
|
-
initial: { opacity:
|
|
315
|
+
initial: { opacity: 1, y: 10 },
|
|
316
316
|
animate: { opacity: 1, y: 0 },
|
|
317
|
-
exit: { opacity:
|
|
317
|
+
exit: { opacity: 1, y: -10 },
|
|
318
318
|
transition: { duration: 0.2 },
|
|
319
319
|
className: viewMode === "grid" ? "sg:grid sg:grid-cols-[repeat(auto-fill,minmax(210px,1fr))] sg:gap-8" : "sg:flex sg:flex-col sg:gap-4",
|
|
320
320
|
children: displayed.map(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/blocks/post-list/post-list-with-filters.tsx"],"sourcesContent":["\"use client\";\nimport { useState, useMemo } from \"react\";\nimport { motion, AnimatePresence } from \"framer-motion\";\nimport type { BlogPost } from \"../../../data/posts\";\nimport BlogPostCard from \"../cards/blogpost-card\";\nimport EmptyState from \"../empty-state/EmptyState\";\nimport { Input } from \"../../primitives/forms/input\";\nimport { Button } from \"../../primitives/buttons/button\";\nimport { Badge } from \"../../primitives/badge/badge\";\nimport { Link } from \"../../primitives/link/link\";\nimport { Icon } from \"../../primitives/icon/icon\";\nimport {\n Heading,\n IconButton,\n Text,\n TextSpan,\n TextTime,\n UiImage,\n} from \"../../primitives/index\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../primitives/forms/select\";\nimport { FilterControls } from \"./post-filters\";\nimport { cn } from \"../../../utils/index\";\n\nconst PAGE_SIZE = 6;\n\ntype SortOption = \"newest\" | \"oldest\" | \"a-z\" | \"z-a\";\ntype ViewMode = \"grid\" | \"list\";\ntype LoadMode = \"pagination\" | \"load-more\";\n\ntype FilterMode = \"sidebar\" | \"drawer\";\n\ninterface PostListWithFiltersProps {\n posts: BlogPost[];\n /** Hide the search bar */\n hideSearch?: boolean;\n /** Hide the author filter badges */\n hideAuthorFilter?: boolean;\n /** \"sidebar\" = inline on desktop, sheet on mobile (default). \"drawer\" = always behind a button/sheet. */\n filterMode?: FilterMode;\n /** Default load mode. \"load-more\" (default) or \"pagination\". User can still toggle. */\n defaultLoadMode?: LoadMode;\n}\n\nexport function PostListWithFilters({\n posts: sourcePosts,\n hideSearch = false,\n hideAuthorFilter = false,\n filterMode = \"sidebar\",\n defaultLoadMode = \"load-more\",\n}: PostListWithFiltersProps) {\n const [query, setQuery] = useState(\"\");\n const [selectedCategories, setSelectedCategories] = useState<string[]>([]);\n const [selectedAuthors, setSelectedAuthors] = useState<string[]>([]);\n const [sortBy, setSortBy] = useState<SortOption>(\"newest\");\n const [loadMode, setLoadMode] = useState<LoadMode>(defaultLoadMode);\n const [viewMode, setViewMode] = useState<ViewMode>(\"grid\");\n const [currentPage, setCurrentPage] = useState(1);\n const [loadMoreCount, setLoadMoreCount] = useState(PAGE_SIZE);\n const [isFiltersOpen, setIsFiltersOpen] = useState(false);\n\n const allCategories = useMemo(\n () => Array.from(new Set(sourcePosts.flatMap((p) => p.categories))).sort(),\n [sourcePosts],\n );\n const allAuthors = useMemo(\n () => Array.from(new Set(sourcePosts.map((p) => p.author))).sort(),\n [sourcePosts],\n );\n\n const resetPaging = () => {\n setCurrentPage(1);\n setLoadMoreCount(PAGE_SIZE);\n };\n\n const toggleCategory = (cat: string) => {\n setSelectedCategories((prev) =>\n prev.includes(cat) ? prev.filter((c) => c !== cat) : [...prev, cat],\n );\n resetPaging();\n };\n\n const toggleAuthor = (author: string) => {\n setSelectedAuthors((prev) =>\n prev.includes(author)\n ? prev.filter((a) => a !== author)\n : [...prev, author],\n );\n resetPaging();\n };\n\n const clearFilters = () => {\n setSelectedCategories([]);\n setSelectedAuthors([]);\n setQuery(\"\");\n resetPaging();\n };\n\n const activeCount = selectedCategories.length + selectedAuthors.length;\n\n const filtered = useMemo(() => {\n let result = [...sourcePosts];\n\n if (selectedCategories.length > 0) {\n result = result.filter((p) =>\n selectedCategories.some((cat) => p.categories?.includes(cat)),\n );\n }\n if (selectedAuthors.length > 0) {\n result = result.filter(\n (p) => p.author && selectedAuthors.includes(p.author),\n );\n }\n if (query.trim()) {\n const q = query.toLowerCase();\n result = result.filter(\n (p) =>\n p.title.toLowerCase().includes(q) ||\n p.excerpt.toLowerCase().includes(q) ||\n p.author.toLowerCase().includes(q) ||\n p.categories?.some((c) => c.toLowerCase().includes(q)),\n );\n }\n\n result.sort((a, b) => {\n switch (sortBy) {\n case \"newest\":\n return new Date(b.date).getTime() - new Date(a.date).getTime();\n case \"oldest\":\n return new Date(a.date).getTime() - new Date(b.date).getTime();\n case \"a-z\":\n return a.title.localeCompare(b.title);\n case \"z-a\":\n return b.title.localeCompare(a.title);\n default:\n return 0;\n }\n });\n\n return result;\n }, [query, selectedCategories, selectedAuthors, sortBy, sourcePosts]);\n\n const totalPages = Math.ceil(filtered.length / PAGE_SIZE);\n const displayed =\n loadMode === \"pagination\"\n ? filtered.slice((currentPage - 1) * PAGE_SIZE, currentPage * PAGE_SIZE)\n : filtered.slice(0, loadMoreCount);\n const hasMore = loadMode === \"load-more\" && loadMoreCount < filtered.length;\n\n const filterProps = {\n categories: allCategories,\n authors: allAuthors,\n selectedCategories,\n selectedAuthors,\n toggleCategory,\n toggleAuthor,\n clearFilters,\n activeCount,\n sortBy,\n setSortBy,\n hideAuthorFilter,\n };\n\n return (\n <div className=\"sg:w-full\">\n {/* Search bar */}\n {!hideSearch && (\n <div className=\"sg:relative sg:mb-8 sg:max-w-lg\">\n <div className=\"sg:absolute sg:left-3 sg:top-1/2 sg:-translate-y-1/2 sg:pointer-events-none\">\n <Icon icon=\"Search\" size=\"xs\" color=\"muted-foreground\" />\n </div>\n <Input\n placeholder=\"Search posts...\"\n value={query}\n onChange={(e) => {\n setQuery(e.target.value);\n resetPaging();\n }}\n className=\"sg:pl-9\"\n />\n </div>\n )}\n\n {/* Toolbar */}\n <div className=\"sg:flex sg:flex-wrap sg:items-center sg:gap-3 sg:mb-6\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n className={cn(\n \"sg:relative\",\n filterMode === \"sidebar\" && \"sg:md:hidden\",\n )}\n onClick={() => setIsFiltersOpen(!isFiltersOpen)}\n iconStart=\"ListFilter\"\n >\n Filters\n {activeCount > 0 && (\n <>\n <TextSpan\n size=\"xs\"\n foreground=\"primary-foreground\"\n className=\"sg:absolute sg:-top-1.5 sg:-right-1.5 sg:h-4 sg:w-4 sg:rounded-full sg:bg-primary sg:flex sg:items-center sg:justify-center\"\n >\n {activeCount}\n </TextSpan>\n </>\n )}\n </Button>\n\n <div className=\"sg:flex-1\" />\n\n <div className=\"sg:flex sg:gap-1 sg:bg-muted/50 sg:p-1 sg:rounded-lg sg:border\">\n <Button\n variant={viewMode === \"grid\" ? \"secondary\" : \"ghost\"}\n size=\"sm\"\n onClick={() => setViewMode(\"grid\")}\n aria-label=\"Grid view\"\n >\n <Icon icon=\"LayoutGrid\" size=\"xs\" />\n </Button>\n <Button\n variant={viewMode === \"list\" ? \"secondary\" : \"ghost\"}\n size=\"sm\"\n onClick={() => setViewMode(\"list\")}\n aria-label=\"List view\"\n >\n <Icon icon=\"List\" size=\"xs\" />\n </Button>\n </div>\n </div>\n\n {/* Mobile Filters Collapsible */}\n <AnimatePresence>\n {isFiltersOpen && (\n <motion.div\n initial={{ height: 0, opacity: 0 }}\n animate={{ height: \"auto\", opacity: 1 }}\n exit={{ height: 0, opacity: 0 }}\n className=\"sg:overflow-hidden sg:border sg:rounded-xl sg:p-6 sg:bg-card sg:mb-8 sg:shadow-sm\"\n >\n <div className=\"sg:flex sg:justify-between sg:items-center sg:mb-6\">\n <Heading variant=\"h4\">Filters</Heading>\n <IconButton\n variant=\"ghost\"\n icon=\"X\"\n size=\"sm\"\n aria-label=\"Close filters\"\n onClick={() => setIsFiltersOpen(false)}\n />\n </div>\n <FilterControls {...filterProps} />\n </motion.div>\n )}\n </AnimatePresence>\n\n <div className=\"sg:flex sg:gap-8\">\n {/* Desktop sidebar filters */}\n {filterMode === \"sidebar\" && (\n <aside className=\"sg:hidden sg:md:block sg:w-64 sg:shrink-0\">\n <div className=\"sg:sticky sg:top-24 sg:space-y-8\">\n <FilterControls {...filterProps} />\n </div>\n </aside>\n )}\n\n {/* Results */}\n <div className=\"sg:flex-1 sg:min-w-0\">\n {activeCount > 0 && (\n <div\n className={cn(\n \"sg:flex sg:flex-wrap sg:items-center sg:gap-2 sg:mb-6\",\n filterMode === \"sidebar\" && \"sg:md:hidden\",\n )}\n >\n {selectedCategories.map((cat) => (\n <Badge\n key={cat}\n variant=\"default\"\n className=\"sg:cursor-pointer sg:pr-1\"\n onClick={() => toggleCategory(cat)}\n >\n {cat} <Icon icon=\"X\" size=\"xs\" className=\"sg:ml-1\" />\n </Badge>\n ))}\n {!hideAuthorFilter &&\n selectedAuthors.map((author) => (\n <Badge\n key={author}\n variant=\"default\"\n className=\"sg:cursor-pointer sg:pr-1\"\n onClick={() => toggleAuthor(author)}\n >\n {author} <Icon icon=\"X\" size=\"xs\" className=\"sg:ml-1\" />\n </Badge>\n ))}\n </div>\n )}\n\n <div className=\"sg:flex sg:flex-wrap sg:gap-2 sg:items-center sg:justify-between sg:mb-6\">\n <Text size=\"sm\" foreground=\"muted-foreground\">\n Showing <TextSpan fontweight=\"medium\">{filtered.length}</TextSpan>{\" \"}\n result{filtered.length !== 1 ? \"s\" : \"\"}\n </Text>\n <div className=\"sg:flex sg:items-center sg:gap-2 sg:flex-wrap\">\n <Text\n id=\"loadmode_dropdown\"\n size=\"xs\"\n foreground=\"muted-foreground\"\n >\n Load mode:\n </Text>\n <Select\n value={loadMode}\n onValueChange={(v) => setLoadMode(v as LoadMode)}\n >\n <SelectTrigger\n className=\"sg:h-8 sg:w-32 sg:text-[12px]\"\n aria-labelledby=\"loadmode_dropdown\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"load-more\">Load more</SelectItem>\n <SelectItem value=\"pagination\">Pagination</SelectItem>\n </SelectContent>\n </Select>\n </div>\n </div>\n\n {filtered.length === 0 ? (\n <EmptyState\n icon=\"Search\"\n title=\"No posts found\"\n description={\n query.trim()\n ? `No results for \"${query}\". Try different keywords.`\n : \"No posts match the selected filters.\"\n }\n actionLabel=\"Clear all filters\"\n onAction={clearFilters}\n className=\"sg:bg-muted/30 sg:rounded-2xl\"\n />\n ) : (\n <>\n <AnimatePresence mode=\"wait\">\n <motion.div\n key={`${displayed.map((p) => p.id).join(\",\")}-${viewMode}`}\n initial={{ opacity: 0, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 0, y: -10 }}\n transition={{ duration: 0.2 }}\n className={\n viewMode === \"grid\"\n ? \"sg:grid sg:grid-cols-[repeat(auto-fill,minmax(210px,1fr))] sg:gap-8\"\n : \"sg:flex sg:flex-col sg:gap-4\"\n }\n >\n {displayed.map((post) =>\n viewMode === \"grid\" ? (\n <BlogPostCard\n key={post.id}\n id={post.id}\n image={post.primaryImage}\n categories={post.categories}\n date={post.date}\n title={post.title}\n excerpt={post.excerpt}\n />\n ) : (\n <Link\n key={post.id}\n to={`/posts/${post.id}`}\n variant=\"no-decoration\"\n className=\"sg:group sg:flex sg:gap-5 sg:rounded-xl sg:border sg:bg-card sg:p-4 sg:hover:shadow-lg sg:hover:border-primary/20 sg:transition-all\"\n >\n <div className=\"sg:w-32 sg:h-32 sg:rounded-lg sg:overflow-hidden sg:shrink-0\">\n <UiImage\n src={post.primaryImage}\n alt={post.title}\n className=\"sg:w-full sg:h-full sg:object-cover sg:transition-transform sg:duration-500 sg:group-hover:scale-110\"\n loading=\"lazy\"\n />\n </div>\n <div className=\"sg:min-w-0 sg:flex sg:flex-col sg:justify-center\">\n <Heading\n variant=\"h6\"\n as=\"h5\"\n className=\"sg:group-hover:text-primary sg:transition-colors sg:line-clamp-1\"\n >\n {post.title}\n </Heading>\n <Text\n size=\"sm\"\n foreground=\"muted-foreground\"\n className=\"sg:line-clamp-2 sg:mt-1.5\"\n >\n {post.excerpt}\n </Text>\n <div className=\"sg:flex sg:items-center sg:gap-3 sg:mt-3 \">\n <TextSpan size=\"xs\" foreground=\"muted-foreground\">\n {post.author}\n </TextSpan>\n <span className=\"sg:h-1 sg:w-1 sg:rounded-full sg:bg-border\" />\n <TextTime size=\"xs\" foreground=\"muted-foreground\">\n {new Date(post.date).toLocaleDateString(\n undefined,\n {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n },\n )}\n </TextTime>\n </div>\n </div>\n </Link>\n ),\n )}\n </motion.div>\n </AnimatePresence>\n\n {loadMode === \"load-more\" && hasMore && (\n <div className=\"sg:mt-12 sg:text-center\">\n <Button\n variant=\"outline\"\n size=\"lg\"\n onClick={() => setLoadMoreCount((c) => c + PAGE_SIZE)}\n >\n Load more stories\n </Button>\n </div>\n )}\n\n {loadMode === \"pagination\" && totalPages > 1 && (\n <div className=\"sg:mt-12 sg:flex sg:items-center sg:justify-center sg:gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={currentPage <= 1}\n onClick={() => setCurrentPage((p) => p - 1)}\n >\n Previous\n </Button>\n <div className=\"sg:flex sg:gap-1.5\">\n {Array.from({ length: totalPages }, (_, i) => i + 1).map(\n (page) => (\n <Button\n key={page}\n variant={page === currentPage ? \"default\" : \"ghost\"}\n size=\"sm\"\n onClick={() => setCurrentPage(page)}\n >\n {page}\n </Button>\n ),\n )}\n </div>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={currentPage >= totalPages}\n onClick={() => setCurrentPage((p) => p + 1)}\n >\n Next\n </Button>\n </div>\n )}\n </>\n )}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/blocks/post-list/post-list-with-filters.tsx"],"sourcesContent":["\"use client\";\nimport { useState, useMemo } from \"react\";\nimport { motion, AnimatePresence } from \"framer-motion\";\nimport type { BlogPost } from \"../../../data/posts\";\nimport BlogPostCard from \"../cards/blogpost-card\";\nimport EmptyState from \"../empty-state/EmptyState\";\nimport { Input } from \"../../primitives/forms/input\";\nimport { Button } from \"../../primitives/buttons/button\";\nimport { Badge } from \"../../primitives/badge/badge\";\nimport { Link } from \"../../primitives/link/link\";\nimport { Icon } from \"../../primitives/icon/icon\";\nimport {\n Heading,\n IconButton,\n Text,\n TextSpan,\n TextTime,\n UiImage,\n} from \"../../primitives/index\";\nimport {\n Select,\n SelectContent,\n SelectItem,\n SelectTrigger,\n SelectValue,\n} from \"../../primitives/forms/select\";\nimport { FilterControls } from \"./post-filters\";\nimport { cn } from \"../../../utils/index\";\n\nconst PAGE_SIZE = 6;\n\ntype SortOption = \"newest\" | \"oldest\" | \"a-z\" | \"z-a\";\ntype ViewMode = \"grid\" | \"list\";\ntype LoadMode = \"pagination\" | \"load-more\";\n\ntype FilterMode = \"sidebar\" | \"drawer\";\n\ninterface PostListWithFiltersProps {\n posts: BlogPost[];\n /** Hide the search bar */\n hideSearch?: boolean;\n /** Hide the author filter badges */\n hideAuthorFilter?: boolean;\n /** \"sidebar\" = inline on desktop, sheet on mobile (default). \"drawer\" = always behind a button/sheet. */\n filterMode?: FilterMode;\n /** Default load mode. \"load-more\" (default) or \"pagination\". User can still toggle. */\n defaultLoadMode?: LoadMode;\n}\n\nexport function PostListWithFilters({\n posts: sourcePosts,\n hideSearch = false,\n hideAuthorFilter = false,\n filterMode = \"sidebar\",\n defaultLoadMode = \"load-more\",\n}: PostListWithFiltersProps) {\n const [query, setQuery] = useState(\"\");\n const [selectedCategories, setSelectedCategories] = useState<string[]>([]);\n const [selectedAuthors, setSelectedAuthors] = useState<string[]>([]);\n const [sortBy, setSortBy] = useState<SortOption>(\"newest\");\n const [loadMode, setLoadMode] = useState<LoadMode>(defaultLoadMode);\n const [viewMode, setViewMode] = useState<ViewMode>(\"grid\");\n const [currentPage, setCurrentPage] = useState(1);\n const [loadMoreCount, setLoadMoreCount] = useState(PAGE_SIZE);\n const [isFiltersOpen, setIsFiltersOpen] = useState(false);\n\n const allCategories = useMemo(\n () => Array.from(new Set(sourcePosts.flatMap((p) => p.categories))).sort(),\n [sourcePosts],\n );\n const allAuthors = useMemo(\n () => Array.from(new Set(sourcePosts.map((p) => p.author))).sort(),\n [sourcePosts],\n );\n\n const resetPaging = () => {\n setCurrentPage(1);\n setLoadMoreCount(PAGE_SIZE);\n };\n\n const toggleCategory = (cat: string) => {\n setSelectedCategories((prev) =>\n prev.includes(cat) ? prev.filter((c) => c !== cat) : [...prev, cat],\n );\n resetPaging();\n };\n\n const toggleAuthor = (author: string) => {\n setSelectedAuthors((prev) =>\n prev.includes(author)\n ? prev.filter((a) => a !== author)\n : [...prev, author],\n );\n resetPaging();\n };\n\n const clearFilters = () => {\n setSelectedCategories([]);\n setSelectedAuthors([]);\n setQuery(\"\");\n resetPaging();\n };\n\n const activeCount = selectedCategories.length + selectedAuthors.length;\n\n const filtered = useMemo(() => {\n let result = [...sourcePosts];\n\n if (selectedCategories.length > 0) {\n result = result.filter((p) =>\n selectedCategories.some((cat) => p.categories?.includes(cat)),\n );\n }\n if (selectedAuthors.length > 0) {\n result = result.filter(\n (p) => p.author && selectedAuthors.includes(p.author),\n );\n }\n if (query.trim()) {\n const q = query.toLowerCase();\n result = result.filter(\n (p) =>\n p.title.toLowerCase().includes(q) ||\n p.excerpt.toLowerCase().includes(q) ||\n p.author.toLowerCase().includes(q) ||\n p.categories?.some((c) => c.toLowerCase().includes(q)),\n );\n }\n\n result.sort((a, b) => {\n switch (sortBy) {\n case \"newest\":\n return new Date(b.date).getTime() - new Date(a.date).getTime();\n case \"oldest\":\n return new Date(a.date).getTime() - new Date(b.date).getTime();\n case \"a-z\":\n return a.title.localeCompare(b.title);\n case \"z-a\":\n return b.title.localeCompare(a.title);\n default:\n return 0;\n }\n });\n\n return result;\n }, [query, selectedCategories, selectedAuthors, sortBy, sourcePosts]);\n\n const totalPages = Math.ceil(filtered.length / PAGE_SIZE);\n const displayed =\n loadMode === \"pagination\"\n ? filtered.slice((currentPage - 1) * PAGE_SIZE, currentPage * PAGE_SIZE)\n : filtered.slice(0, loadMoreCount);\n const hasMore = loadMode === \"load-more\" && loadMoreCount < filtered.length;\n\n const filterProps = {\n categories: allCategories,\n authors: allAuthors,\n selectedCategories,\n selectedAuthors,\n toggleCategory,\n toggleAuthor,\n clearFilters,\n activeCount,\n sortBy,\n setSortBy,\n hideAuthorFilter,\n };\n\n return (\n <div className=\"sg:w-full\">\n {/* Search bar */}\n {!hideSearch && (\n <div className=\"sg:relative sg:mb-8 sg:max-w-lg\">\n <div className=\"sg:absolute sg:left-3 sg:top-1/2 sg:-translate-y-1/2 sg:pointer-events-none\">\n <Icon icon=\"Search\" size=\"xs\" color=\"muted-foreground\" />\n </div>\n <Input\n placeholder=\"Search posts...\"\n value={query}\n onChange={(e) => {\n setQuery(e.target.value);\n resetPaging();\n }}\n className=\"sg:pl-9\"\n />\n </div>\n )}\n\n {/* Toolbar */}\n <div className=\"sg:flex sg:flex-wrap sg:items-center sg:gap-3 sg:mb-6\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n className={cn(\n \"sg:relative\",\n filterMode === \"sidebar\" && \"sg:md:hidden\",\n )}\n onClick={() => setIsFiltersOpen(!isFiltersOpen)}\n iconStart=\"ListFilter\"\n >\n Filters\n {activeCount > 0 && (\n <>\n <TextSpan\n size=\"xs\"\n foreground=\"primary-foreground\"\n className=\"sg:absolute sg:-top-1.5 sg:-right-1.5 sg:h-4 sg:w-4 sg:rounded-full sg:bg-primary sg:flex sg:items-center sg:justify-center\"\n >\n {activeCount}\n </TextSpan>\n </>\n )}\n </Button>\n\n <div className=\"sg:flex-1\" />\n\n <div className=\"sg:flex sg:gap-1 sg:bg-muted/50 sg:p-1 sg:rounded-lg sg:border\">\n <Button\n variant={viewMode === \"grid\" ? \"secondary\" : \"ghost\"}\n size=\"sm\"\n onClick={() => setViewMode(\"grid\")}\n aria-label=\"Grid view\"\n >\n <Icon icon=\"LayoutGrid\" size=\"xs\" />\n </Button>\n <Button\n variant={viewMode === \"list\" ? \"secondary\" : \"ghost\"}\n size=\"sm\"\n onClick={() => setViewMode(\"list\")}\n aria-label=\"List view\"\n >\n <Icon icon=\"List\" size=\"xs\" />\n </Button>\n </div>\n </div>\n\n {/* Mobile Filters Collapsible */}\n <AnimatePresence>\n {isFiltersOpen && (\n <motion.div\n initial={{ height: 0, opacity: 1 }}\n animate={{ height: \"auto\", opacity: 1 }}\n exit={{ height: 0, opacity: 1 }}\n className=\"sg:overflow-hidden sg:border sg:rounded-xl sg:p-6 sg:bg-card sg:mb-8 sg:shadow-sm\"\n >\n <div className=\"sg:flex sg:justify-between sg:items-center sg:mb-6\">\n <Heading variant=\"h4\">Filters</Heading>\n <IconButton\n variant=\"ghost\"\n icon=\"X\"\n size=\"sm\"\n aria-label=\"Close filters\"\n onClick={() => setIsFiltersOpen(false)}\n />\n </div>\n <FilterControls {...filterProps} />\n </motion.div>\n )}\n </AnimatePresence>\n\n <div className=\"sg:flex sg:gap-8\">\n {/* Desktop sidebar filters */}\n {filterMode === \"sidebar\" && (\n <aside className=\"sg:hidden sg:md:block sg:w-64 sg:shrink-0\">\n <div className=\"sg:sticky sg:top-24 sg:space-y-8\">\n <FilterControls {...filterProps} />\n </div>\n </aside>\n )}\n\n {/* Results */}\n <div className=\"sg:flex-1 sg:min-w-0\">\n {activeCount > 0 && (\n <div\n className={cn(\n \"sg:flex sg:flex-wrap sg:items-center sg:gap-2 sg:mb-6\",\n filterMode === \"sidebar\" && \"sg:md:hidden\",\n )}\n >\n {selectedCategories.map((cat) => (\n <Badge\n key={cat}\n variant=\"default\"\n className=\"sg:cursor-pointer sg:pr-1\"\n onClick={() => toggleCategory(cat)}\n >\n {cat} <Icon icon=\"X\" size=\"xs\" className=\"sg:ml-1\" />\n </Badge>\n ))}\n {!hideAuthorFilter &&\n selectedAuthors.map((author) => (\n <Badge\n key={author}\n variant=\"default\"\n className=\"sg:cursor-pointer sg:pr-1\"\n onClick={() => toggleAuthor(author)}\n >\n {author} <Icon icon=\"X\" size=\"xs\" className=\"sg:ml-1\" />\n </Badge>\n ))}\n </div>\n )}\n\n <div className=\"sg:flex sg:flex-wrap sg:gap-2 sg:items-center sg:justify-between sg:mb-6\">\n <Text size=\"sm\" foreground=\"muted-foreground\">\n Showing <TextSpan fontweight=\"medium\">{filtered.length}</TextSpan>{\" \"}\n result{filtered.length !== 1 ? \"s\" : \"\"}\n </Text>\n <div className=\"sg:flex sg:items-center sg:gap-2 sg:flex-wrap\">\n <Text\n id=\"loadmode_dropdown\"\n size=\"xs\"\n foreground=\"muted-foreground\"\n >\n Load mode:\n </Text>\n <Select\n value={loadMode}\n onValueChange={(v) => setLoadMode(v as LoadMode)}\n >\n <SelectTrigger\n className=\"sg:h-8 sg:w-32 sg:text-[12px]\"\n aria-labelledby=\"loadmode_dropdown\"\n >\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"load-more\">Load more</SelectItem>\n <SelectItem value=\"pagination\">Pagination</SelectItem>\n </SelectContent>\n </Select>\n </div>\n </div>\n\n {filtered.length === 0 ? (\n <EmptyState\n icon=\"Search\"\n title=\"No posts found\"\n description={\n query.trim()\n ? `No results for \"${query}\". Try different keywords.`\n : \"No posts match the selected filters.\"\n }\n actionLabel=\"Clear all filters\"\n onAction={clearFilters}\n className=\"sg:bg-muted/30 sg:rounded-2xl\"\n />\n ) : (\n <>\n <AnimatePresence mode=\"wait\">\n <motion.div\n key={`${displayed.map((p) => p.id).join(\",\")}-${viewMode}`}\n initial={{ opacity: 1, y: 10 }}\n animate={{ opacity: 1, y: 0 }}\n exit={{ opacity: 1, y: -10 }}\n transition={{ duration: 0.2 }}\n className={\n viewMode === \"grid\"\n ? \"sg:grid sg:grid-cols-[repeat(auto-fill,minmax(210px,1fr))] sg:gap-8\"\n : \"sg:flex sg:flex-col sg:gap-4\"\n }\n >\n {displayed.map((post) =>\n viewMode === \"grid\" ? (\n <BlogPostCard\n key={post.id}\n id={post.id}\n image={post.primaryImage}\n categories={post.categories}\n date={post.date}\n title={post.title}\n excerpt={post.excerpt}\n />\n ) : (\n <Link\n key={post.id}\n to={`/posts/${post.id}`}\n variant=\"no-decoration\"\n className=\"sg:group sg:flex sg:gap-5 sg:rounded-xl sg:border sg:bg-card sg:p-4 sg:hover:shadow-lg sg:hover:border-primary/20 sg:transition-all\"\n >\n <div className=\"sg:w-32 sg:h-32 sg:rounded-lg sg:overflow-hidden sg:shrink-0\">\n <UiImage\n src={post.primaryImage}\n alt={post.title}\n className=\"sg:w-full sg:h-full sg:object-cover sg:transition-transform sg:duration-500 sg:group-hover:scale-110\"\n loading=\"lazy\"\n />\n </div>\n <div className=\"sg:min-w-0 sg:flex sg:flex-col sg:justify-center\">\n <Heading\n variant=\"h6\"\n as=\"h5\"\n className=\"sg:group-hover:text-primary sg:transition-colors sg:line-clamp-1\"\n >\n {post.title}\n </Heading>\n <Text\n size=\"sm\"\n foreground=\"muted-foreground\"\n className=\"sg:line-clamp-2 sg:mt-1.5\"\n >\n {post.excerpt}\n </Text>\n <div className=\"sg:flex sg:items-center sg:gap-3 sg:mt-3 \">\n <TextSpan size=\"xs\" foreground=\"muted-foreground\">\n {post.author}\n </TextSpan>\n <span className=\"sg:h-1 sg:w-1 sg:rounded-full sg:bg-border\" />\n <TextTime size=\"xs\" foreground=\"muted-foreground\">\n {new Date(post.date).toLocaleDateString(\n undefined,\n {\n month: \"short\",\n day: \"numeric\",\n year: \"numeric\",\n },\n )}\n </TextTime>\n </div>\n </div>\n </Link>\n ),\n )}\n </motion.div>\n </AnimatePresence>\n\n {loadMode === \"load-more\" && hasMore && (\n <div className=\"sg:mt-12 sg:text-center\">\n <Button\n variant=\"outline\"\n size=\"lg\"\n onClick={() => setLoadMoreCount((c) => c + PAGE_SIZE)}\n >\n Load more stories\n </Button>\n </div>\n )}\n\n {loadMode === \"pagination\" && totalPages > 1 && (\n <div className=\"sg:mt-12 sg:flex sg:items-center sg:justify-center sg:gap-2\">\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={currentPage <= 1}\n onClick={() => setCurrentPage((p) => p - 1)}\n >\n Previous\n </Button>\n <div className=\"sg:flex sg:gap-1.5\">\n {Array.from({ length: totalPages }, (_, i) => i + 1).map(\n (page) => (\n <Button\n key={page}\n variant={page === currentPage ? \"default\" : \"ghost\"}\n size=\"sm\"\n onClick={() => setCurrentPage(page)}\n >\n {page}\n </Button>\n ),\n )}\n </div>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={currentPage >= totalPages}\n onClick={() => setCurrentPage((p) => p + 1)}\n >\n Next\n </Button>\n </div>\n )}\n </>\n )}\n </div>\n </div>\n </div>\n );\n}\n"],"mappings":";AA4KQ,SA8BI,UA5BA,KAFJ;AA3KR,SAAS,UAAU,eAAe;AAClC,SAAS,QAAQ,uBAAuB;AAExC,OAAO,kBAAkB;AACzB,OAAO,gBAAgB;AACvB,SAAS,aAAa;AACtB,SAAS,cAAc;AACvB,SAAS,aAAa;AACtB,SAAS,YAAY;AACrB,SAAS,YAAY;AACrB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,sBAAsB;AAC/B,SAAS,UAAU;AAEnB,MAAM,YAAY;AAoBX,SAAS,oBAAoB;AAAA,EAClC,OAAO;AAAA,EACP,aAAa;AAAA,EACb,mBAAmB;AAAA,EACnB,aAAa;AAAA,EACb,kBAAkB;AACpB,GAA6B;AAC3B,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,EAAE;AACrC,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,SAAmB,CAAC,CAAC;AACzE,QAAM,CAAC,iBAAiB,kBAAkB,IAAI,SAAmB,CAAC,CAAC;AACnE,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAqB,QAAQ;AACzD,QAAM,CAAC,UAAU,WAAW,IAAI,SAAmB,eAAe;AAClE,QAAM,CAAC,UAAU,WAAW,IAAI,SAAmB,MAAM;AACzD,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,CAAC;AAChD,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,SAAS;AAC5D,QAAM,CAAC,eAAe,gBAAgB,IAAI,SAAS,KAAK;AAExD,QAAM,gBAAgB;AAAA,IACpB,MAAM,MAAM,KAAK,IAAI,IAAI,YAAY,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,EAAE,KAAK;AAAA,IACzE,CAAC,WAAW;AAAA,EACd;AACA,QAAM,aAAa;AAAA,IACjB,MAAM,MAAM,KAAK,IAAI,IAAI,YAAY,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,KAAK;AAAA,IACjE,CAAC,WAAW;AAAA,EACd;AAEA,QAAM,cAAc,MAAM;AACxB,mBAAe,CAAC;AAChB,qBAAiB,SAAS;AAAA,EAC5B;AAEA,QAAM,iBAAiB,CAAC,QAAgB;AACtC;AAAA,MAAsB,CAAC,SACrB,KAAK,SAAS,GAAG,IAAI,KAAK,OAAO,CAAC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,MAAM,GAAG;AAAA,IACpE;AACA,gBAAY;AAAA,EACd;AAEA,QAAM,eAAe,CAAC,WAAmB;AACvC;AAAA,MAAmB,CAAC,SAClB,KAAK,SAAS,MAAM,IAChB,KAAK,OAAO,CAAC,MAAM,MAAM,MAAM,IAC/B,CAAC,GAAG,MAAM,MAAM;AAAA,IACtB;AACA,gBAAY;AAAA,EACd;AAEA,QAAM,eAAe,MAAM;AACzB,0BAAsB,CAAC,CAAC;AACxB,uBAAmB,CAAC,CAAC;AACrB,aAAS,EAAE;AACX,gBAAY;AAAA,EACd;AAEA,QAAM,cAAc,mBAAmB,SAAS,gBAAgB;AAEhE,QAAM,WAAW,QAAQ,MAAM;AAC7B,QAAI,SAAS,CAAC,GAAG,WAAW;AAE5B,QAAI,mBAAmB,SAAS,GAAG;AACjC,eAAS,OAAO;AAAA,QAAO,CAAC,MACtB,mBAAmB,KAAK,CAAC,QAAQ,EAAE,YAAY,SAAS,GAAG,CAAC;AAAA,MAC9D;AAAA,IACF;AACA,QAAI,gBAAgB,SAAS,GAAG;AAC9B,eAAS,OAAO;AAAA,QACd,CAAC,MAAM,EAAE,UAAU,gBAAgB,SAAS,EAAE,MAAM;AAAA,MACtD;AAAA,IACF;AACA,QAAI,MAAM,KAAK,GAAG;AAChB,YAAM,IAAI,MAAM,YAAY;AAC5B,eAAS,OAAO;AAAA,QACd,CAAC,MACC,EAAE,MAAM,YAAY,EAAE,SAAS,CAAC,KAChC,EAAE,QAAQ,YAAY,EAAE,SAAS,CAAC,KAClC,EAAE,OAAO,YAAY,EAAE,SAAS,CAAC,KACjC,EAAE,YAAY,KAAK,CAAC,MAAM,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;AAAA,MACzD;AAAA,IACF;AAEA,WAAO,KAAK,CAAC,GAAG,MAAM;AACpB,cAAQ,QAAQ;AAAA,QACd,KAAK;AACH,iBAAO,IAAI,KAAK,EAAE,IAAI,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,IAAI,EAAE,QAAQ;AAAA,QAC/D,KAAK;AACH,iBAAO,IAAI,KAAK,EAAE,IAAI,EAAE,QAAQ,IAAI,IAAI,KAAK,EAAE,IAAI,EAAE,QAAQ;AAAA,QAC/D,KAAK;AACH,iBAAO,EAAE,MAAM,cAAc,EAAE,KAAK;AAAA,QACtC,KAAK;AACH,iBAAO,EAAE,MAAM,cAAc,EAAE,KAAK;AAAA,QACtC;AACE,iBAAO;AAAA,MACX;AAAA,IACF,CAAC;AAED,WAAO;AAAA,EACT,GAAG,CAAC,OAAO,oBAAoB,iBAAiB,QAAQ,WAAW,CAAC;AAEpE,QAAM,aAAa,KAAK,KAAK,SAAS,SAAS,SAAS;AACxD,QAAM,YACJ,aAAa,eACT,SAAS,OAAO,cAAc,KAAK,WAAW,cAAc,SAAS,IACrE,SAAS,MAAM,GAAG,aAAa;AACrC,QAAM,UAAU,aAAa,eAAe,gBAAgB,SAAS;AAErE,QAAM,cAAc;AAAA,IAClB,YAAY;AAAA,IACZ,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SACE,qBAAC,SAAI,WAAU,aAEZ;AAAA,KAAC,cACA,qBAAC,SAAI,WAAU,mCACb;AAAA,0BAAC,SAAI,WAAU,+EACb,8BAAC,QAAK,MAAK,UAAS,MAAK,MAAK,OAAM,oBAAmB,GACzD;AAAA,MACA;AAAA,QAAC;AAAA;AAAA,UACC,aAAY;AAAA,UACZ,OAAO;AAAA,UACP,UAAU,CAAC,MAAM;AACf,qBAAS,EAAE,OAAO,KAAK;AACvB,wBAAY;AAAA,UACd;AAAA,UACA,WAAU;AAAA;AAAA,MACZ;AAAA,OACF;AAAA,IAIF,qBAAC,SAAI,WAAU,yDACb;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,SAAQ;AAAA,UACR,MAAK;AAAA,UACL,WAAW;AAAA,YACT;AAAA,YACA,eAAe,aAAa;AAAA,UAC9B;AAAA,UACA,SAAS,MAAM,iBAAiB,CAAC,aAAa;AAAA,UAC9C,WAAU;AAAA,UACX;AAAA;AAAA,YAEE,cAAc,KACb,gCACE;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,YAAW;AAAA,gBACX,WAAU;AAAA,gBAET;AAAA;AAAA,YACH,GACF;AAAA;AAAA;AAAA,MAEJ;AAAA,MAEA,oBAAC,SAAI,WAAU,aAAY;AAAA,MAE3B,qBAAC,SAAI,WAAU,kEACb;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,aAAa,SAAS,cAAc;AAAA,YAC7C,MAAK;AAAA,YACL,SAAS,MAAM,YAAY,MAAM;AAAA,YACjC,cAAW;AAAA,YAEX,8BAAC,QAAK,MAAK,cAAa,MAAK,MAAK;AAAA;AAAA,QACpC;AAAA,QACA;AAAA,UAAC;AAAA;AAAA,YACC,SAAS,aAAa,SAAS,cAAc;AAAA,YAC7C,MAAK;AAAA,YACL,SAAS,MAAM,YAAY,MAAM;AAAA,YACjC,cAAW;AAAA,YAEX,8BAAC,QAAK,MAAK,QAAO,MAAK,MAAK;AAAA;AAAA,QAC9B;AAAA,SACF;AAAA,OACF;AAAA,IAGA,oBAAC,mBACE,2BACC;AAAA,MAAC,OAAO;AAAA,MAAP;AAAA,QACC,SAAS,EAAE,QAAQ,GAAG,SAAS,EAAE;AAAA,QACjC,SAAS,EAAE,QAAQ,QAAQ,SAAS,EAAE;AAAA,QACtC,MAAM,EAAE,QAAQ,GAAG,SAAS,EAAE;AAAA,QAC9B,WAAU;AAAA,QAEV;AAAA,+BAAC,SAAI,WAAU,sDACb;AAAA,gCAAC,WAAQ,SAAQ,MAAK,qBAAO;AAAA,YAC7B;AAAA,cAAC;AAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,MAAK;AAAA,gBACL,MAAK;AAAA,gBACL,cAAW;AAAA,gBACX,SAAS,MAAM,iBAAiB,KAAK;AAAA;AAAA,YACvC;AAAA,aACF;AAAA,UACA,oBAAC,kBAAgB,GAAG,aAAa;AAAA;AAAA;AAAA,IACnC,GAEJ;AAAA,IAEA,qBAAC,SAAI,WAAU,oBAEZ;AAAA,qBAAe,aACd,oBAAC,WAAM,WAAU,6CACf,8BAAC,SAAI,WAAU,oCACb,8BAAC,kBAAgB,GAAG,aAAa,GACnC,GACF;AAAA,MAIF,qBAAC,SAAI,WAAU,wBACZ;AAAA,sBAAc,KACb;AAAA,UAAC;AAAA;AAAA,YACC,WAAW;AAAA,cACT;AAAA,cACA,eAAe,aAAa;AAAA,YAC9B;AAAA,YAEC;AAAA,iCAAmB,IAAI,CAAC,QACvB;AAAA,gBAAC;AAAA;AAAA,kBAEC,SAAQ;AAAA,kBACR,WAAU;AAAA,kBACV,SAAS,MAAM,eAAe,GAAG;AAAA,kBAEhC;AAAA;AAAA,oBAAI;AAAA,oBAAC,oBAAC,QAAK,MAAK,KAAI,MAAK,MAAK,WAAU,WAAU;AAAA;AAAA;AAAA,gBAL9C;AAAA,cAMP,CACD;AAAA,cACA,CAAC,oBACA,gBAAgB,IAAI,CAAC,WACnB;AAAA,gBAAC;AAAA;AAAA,kBAEC,SAAQ;AAAA,kBACR,WAAU;AAAA,kBACV,SAAS,MAAM,aAAa,MAAM;AAAA,kBAEjC;AAAA;AAAA,oBAAO;AAAA,oBAAC,oBAAC,QAAK,MAAK,KAAI,MAAK,MAAK,WAAU,WAAU;AAAA;AAAA;AAAA,gBALjD;AAAA,cAMP,CACD;AAAA;AAAA;AAAA,QACL;AAAA,QAGF,qBAAC,SAAI,WAAU,4EACb;AAAA,+BAAC,QAAK,MAAK,MAAK,YAAW,oBAAmB;AAAA;AAAA,YACpC,oBAAC,YAAS,YAAW,UAAU,mBAAS,QAAO;AAAA,YAAY;AAAA,YAAI;AAAA,YAChE,SAAS,WAAW,IAAI,MAAM;AAAA,aACvC;AAAA,UACA,qBAAC,SAAI,WAAU,iDACb;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,IAAG;AAAA,gBACH,MAAK;AAAA,gBACL,YAAW;AAAA,gBACZ;AAAA;AAAA,YAED;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,OAAO;AAAA,gBACP,eAAe,CAAC,MAAM,YAAY,CAAa;AAAA,gBAE/C;AAAA;AAAA,oBAAC;AAAA;AAAA,sBACC,WAAU;AAAA,sBACV,mBAAgB;AAAA,sBAEhB,8BAAC,eAAY;AAAA;AAAA,kBACf;AAAA,kBACA,qBAAC,iBACC;AAAA,wCAAC,cAAW,OAAM,aAAY,uBAAS;AAAA,oBACvC,oBAAC,cAAW,OAAM,cAAa,wBAAU;AAAA,qBAC3C;AAAA;AAAA;AAAA,YACF;AAAA,aACF;AAAA,WACF;AAAA,QAEC,SAAS,WAAW,IACnB;AAAA,UAAC;AAAA;AAAA,YACC,MAAK;AAAA,YACL,OAAM;AAAA,YACN,aACE,MAAM,KAAK,IACP,mBAAmB,KAAK,+BACxB;AAAA,YAEN,aAAY;AAAA,YACZ,UAAU;AAAA,YACV,WAAU;AAAA;AAAA,QACZ,IAEA,iCACE;AAAA,8BAAC,mBAAgB,MAAK,QACpB;AAAA,YAAC,OAAO;AAAA,YAAP;AAAA,cAEC,SAAS,EAAE,SAAS,GAAG,GAAG,GAAG;AAAA,cAC7B,SAAS,EAAE,SAAS,GAAG,GAAG,EAAE;AAAA,cAC5B,MAAM,EAAE,SAAS,GAAG,GAAG,IAAI;AAAA,cAC3B,YAAY,EAAE,UAAU,IAAI;AAAA,cAC5B,WACE,aAAa,SACT,wEACA;AAAA,cAGL,oBAAU;AAAA,gBAAI,CAAC,SACd,aAAa,SACX;AAAA,kBAAC;AAAA;AAAA,oBAEC,IAAI,KAAK;AAAA,oBACT,OAAO,KAAK;AAAA,oBACZ,YAAY,KAAK;AAAA,oBACjB,MAAM,KAAK;AAAA,oBACX,OAAO,KAAK;AAAA,oBACZ,SAAS,KAAK;AAAA;AAAA,kBANT,KAAK;AAAA,gBAOZ,IAEA;AAAA,kBAAC;AAAA;AAAA,oBAEC,IAAI,UAAU,KAAK,EAAE;AAAA,oBACrB,SAAQ;AAAA,oBACR,WAAU;AAAA,oBAEV;AAAA,0CAAC,SAAI,WAAU,gEACb;AAAA,wBAAC;AAAA;AAAA,0BACC,KAAK,KAAK;AAAA,0BACV,KAAK,KAAK;AAAA,0BACV,WAAU;AAAA,0BACV,SAAQ;AAAA;AAAA,sBACV,GACF;AAAA,sBACA,qBAAC,SAAI,WAAU,oDACb;AAAA;AAAA,0BAAC;AAAA;AAAA,4BACC,SAAQ;AAAA,4BACR,IAAG;AAAA,4BACH,WAAU;AAAA,4BAET,eAAK;AAAA;AAAA,wBACR;AAAA,wBACA;AAAA,0BAAC;AAAA;AAAA,4BACC,MAAK;AAAA,4BACL,YAAW;AAAA,4BACX,WAAU;AAAA,4BAET,eAAK;AAAA;AAAA,wBACR;AAAA,wBACA,qBAAC,SAAI,WAAU,6CACb;AAAA,8CAAC,YAAS,MAAK,MAAK,YAAW,oBAC5B,eAAK,QACR;AAAA,0BACA,oBAAC,UAAK,WAAU,8CAA6C;AAAA,0BAC7D,oBAAC,YAAS,MAAK,MAAK,YAAW,oBAC5B,cAAI,KAAK,KAAK,IAAI,EAAE;AAAA,4BACnB;AAAA,4BACA;AAAA,8BACE,OAAO;AAAA,8BACP,KAAK;AAAA,8BACL,MAAM;AAAA,4BACR;AAAA,0BACF,GACF;AAAA,2BACF;AAAA,yBACF;AAAA;AAAA;AAAA,kBA5CK,KAAK;AAAA,gBA6CZ;AAAA,cAEJ;AAAA;AAAA,YAvEK,GAAG,UAAU,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,KAAK,GAAG,CAAC,IAAI,QAAQ;AAAA,UAwE1D,GACF;AAAA,UAEC,aAAa,eAAe,WAC3B,oBAAC,SAAI,WAAU,2BACb;AAAA,YAAC;AAAA;AAAA,cACC,SAAQ;AAAA,cACR,MAAK;AAAA,cACL,SAAS,MAAM,iBAAiB,CAAC,MAAM,IAAI,SAAS;AAAA,cACrD;AAAA;AAAA,UAED,GACF;AAAA,UAGD,aAAa,gBAAgB,aAAa,KACzC,qBAAC,SAAI,WAAU,+DACb;AAAA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,MAAK;AAAA,gBACL,UAAU,eAAe;AAAA,gBACzB,SAAS,MAAM,eAAe,CAAC,MAAM,IAAI,CAAC;AAAA,gBAC3C;AAAA;AAAA,YAED;AAAA,YACA,oBAAC,SAAI,WAAU,sBACZ,gBAAM,KAAK,EAAE,QAAQ,WAAW,GAAG,CAAC,GAAG,MAAM,IAAI,CAAC,EAAE;AAAA,cACnD,CAAC,SACC;AAAA,gBAAC;AAAA;AAAA,kBAEC,SAAS,SAAS,cAAc,YAAY;AAAA,kBAC5C,MAAK;AAAA,kBACL,SAAS,MAAM,eAAe,IAAI;AAAA,kBAEjC;AAAA;AAAA,gBALI;AAAA,cAMP;AAAA,YAEJ,GACF;AAAA,YACA;AAAA,cAAC;AAAA;AAAA,gBACC,SAAQ;AAAA,gBACR,MAAK;AAAA,gBACL,UAAU,eAAe;AAAA,gBACzB,SAAS,MAAM,eAAe,CAAC,MAAM,IAAI,CAAC;AAAA,gBAC3C;AAAA;AAAA,YAED;AAAA,aACF;AAAA,WAEJ;AAAA,SAEJ;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
|
|
@@ -73,7 +73,7 @@ function AboutPage() {
|
|
|
73
73
|
return /* @__PURE__ */ jsxs(
|
|
74
74
|
motion.div,
|
|
75
75
|
{
|
|
76
|
-
initial: { opacity:
|
|
76
|
+
initial: { opacity: 1, y: 20 },
|
|
77
77
|
animate: { opacity: 1, y: 0 },
|
|
78
78
|
transition: { duration: 0.3 },
|
|
79
79
|
children: [
|
|
@@ -115,7 +115,7 @@ function AboutPage() {
|
|
|
115
115
|
children: author.name
|
|
116
116
|
}
|
|
117
117
|
),
|
|
118
|
-
/* @__PURE__ */ jsx(Text, { size: "sm",
|
|
118
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", foreground: "muted-foreground", className: "sg:mb-2", children: author.role }),
|
|
119
119
|
/* @__PURE__ */ jsx(
|
|
120
120
|
Text,
|
|
121
121
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/components/pages/about/about-page.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport { motion } from \"framer-motion\";\r\nimport { Layout, Heading, Text, Icon, Separator } from \"../../primitives/index\";\r\nimport { PageHero } from \"../../blocks/marketing/page-hero\";\r\nimport { StatsGrid } from \"../../blocks/marketing/stats-grid\";\r\nimport { Timeline } from \"../../blocks/marketing/timeline\";\r\nimport { ValuesGrid } from \"../../blocks/marketing/values-grid\";\r\nimport { Card, CardContent } from \"../../blocks/cards/card\";\r\nimport {\r\n\tAvatar,\r\n\tAvatarFallback,\r\n\tAvatarImage,\r\n} from \"../../primitives/avatar/avatar\";\r\nimport { Link } from \"../../primitives/link/link\";\r\nimport { authors } from \"../../../data/authors\";\r\nimport { posts } from \"../../../data/posts\";\r\n\r\nconst stats = [\r\n\t{\r\n\t\tlabel: \"Articles Published\",\r\n\t\tvalue: posts.length.toString(),\r\n\t\ticon: \"BookOpen\" as const,\r\n\t},\r\n\t{\r\n\t\tlabel: \"Contributing Writers\",\r\n\t\tvalue: authors.length.toString(),\r\n\t\ticon: \"Users\" as const,\r\n\t},\r\n\t{\r\n\t\tlabel: \"Categories Covered\",\r\n\t\tvalue: [...new Set(posts.flatMap((p) => p.categories))].length.toString(),\r\n\t\ticon: \"TrendingUp\" as const,\r\n\t},\r\n\t{ label: \"Years Running\", value: \"3\", icon: \"Calendar\" as const },\r\n];\r\n\r\nconst timeline = [\r\n\t{\r\n\t\tyear: \"2023\",\r\n\t\ttitle: \"The Beginning\",\r\n\t\tdescription:\r\n\t\t\t\"Launched as a personal blog about slow living and intentional design.\",\r\n\t},\r\n\t{\r\n\t\tyear: \"2023\",\r\n\t\ttitle: \"Growing the Team\",\r\n\t\tdescription:\r\n\t\t\t\"New contributing writers expanded coverage into culture and design.\",\r\n\t},\r\n\t{\r\n\t\tyear: \"2024\",\r\n\t\ttitle: \"Community & Resources\",\r\n\t\tdescription:\r\n\t\t\t\"Introduced the Resources hub and Mosaic gallery. Readership doubled.\",\r\n\t},\r\n\t{\r\n\t\tyear: \"2025\",\r\n\t\ttitle: \"New Horizons\",\r\n\t\tdescription:\r\n\t\t\t\"Expanded categories, launched chat, and hit a milestone of regular readers.\",\r\n\t},\r\n];\r\n\r\nconst values = [\r\n\t{\r\n\t\ttitle: \"Depth over speed\",\r\n\t\tdescription:\r\n\t\t\t\"We take time to research, write, and edit. Every piece earns its place.\",\r\n\t},\r\n\t{\r\n\t\ttitle: \"Beauty in simplicity\",\r\n\t\tdescription: \"Clean design, honest words, and images that breathe.\",\r\n\t},\r\n\t{\r\n\t\ttitle: \"Community first\",\r\n\t\tdescription:\r\n\t\t\t\"We write for curious minds who value connection and craft.\",\r\n\t},\r\n];\r\n\r\nexport function AboutPage() {\r\n\treturn (\r\n\t\t<motion.div\r\n\t\t\tinitial={{ opacity: 0, y: 20 }}\r\n\t\t\tanimate={{ opacity: 1, y: 0 }}\r\n\t\t\ttransition={{ duration: 0.3 }}\r\n\t\t>\r\n\t\t\t<PageHero\r\n\t\t\t\ticon=\"Heart\"\r\n\t\t\t\ttitle=\"About filion\"\r\n\t\t\t\tdescription=\"We believe in the power of slow, intentional storytelling — depth over speed, beauty over noise, and presence over productivity.\"\r\n\t\t\t/>\r\n\r\n\t\t\t<Layout type=\"col\" className=\"sg:py-16\">\r\n\t\t\t\t<Layout.Col1 hideDiv className=\"sg:max-w-4xl\">\r\n\t\t\t\t\t<StatsGrid items={stats} />\r\n\t\t\t\t</Layout.Col1>\r\n\t\t\t</Layout>\r\n\r\n\t\t\t<section className=\"sg:bg-muted/40 sg:border-y sg:border-border\">\r\n\t\t\t\t<Layout type=\"col\" className=\"sg:py-16\">\r\n\t\t\t\t\t<Layout.Col1 hideDiv className=\"sg:max-w-3xl\">\r\n\t\t\t\t\t\t<Heading variant=\"h2\" className=\"sg:mb-6\">\r\n\t\t\t\t\t\t\tOur Story\r\n\t\t\t\t\t\t</Heading>\r\n\t\t\t\t\t\t<div className=\"sg:space-y-4\">\r\n\t\t\t\t\t\t\t<Text foreground=\"muted-foreground\" className=\"sg:leading-relaxed\">\r\n\t\t\t\t\t\t\t\tWhat began as one writer's reflections on slow mornings and\r\n\t\t\t\t\t\t\t\thandwritten letters grew into a collective of voices united by\r\n\t\t\t\t\t\t\t\tcuriosity and care.\r\n\t\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t\t\t<Text foreground=\"muted-foreground\" className=\"sg:leading-relaxed\">\r\n\t\t\t\t\t\t\t\tToday, our team explores everything from minimalist design to\r\n\t\t\t\t\t\t\t\tglobal traditions, always with the same ethos: take your time,\r\n\t\t\t\t\t\t\t\tpay attention, and tell the story honestly.\r\n\t\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t\t</div>\r\n\t\t\t\t\t</Layout.Col1>\r\n\t\t\t\t</Layout>\r\n\t\t\t</section>\r\n\r\n\t\t\t<Layout type=\"col\" className=\"sg:py-16\">\r\n\t\t\t\t<Layout.Col1 hideDiv className=\"sg:max-w-4xl\">\r\n\t\t\t\t\t<Heading variant=\"h2\" className=\"sg:mb-2\">\r\n\t\t\t\t\t\tThe Team\r\n\t\t\t\t\t</Heading>\r\n\t\t\t\t\t<Text foreground=\"muted-foreground\" className=\"sg:mb-8\">\r\n\t\t\t\t\t\tThe writers behind the words.\r\n\t\t\t\t\t</Text>\r\n\t\t\t\t\t<div className=\"sg:grid sg:gap-6 sm:sg:grid-cols-3\">\r\n\t\t\t\t\t\t{authors.map((author) => (\r\n\t\t\t\t\t\t\t<Link\r\n\t\t\t\t\t\t\t\tkey={author.slug}\r\n\t\t\t\t\t\t\t\tto={`/extras/authors/${author.slug}`}\r\n\t\t\t\t\t\t\t\tvariant=\"no-decoration\"\r\n\t\t\t\t\t\t\t\tclassName=\"sg:group\"\r\n\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t<Card className=\"sg:h-full sg:transition-shadow sg:hover:shadow-lg sg:hover:border-primary/40\">\r\n\t\t\t\t\t\t\t\t\t<CardContent className=\"sg:pt-6 sg:text-center\">\r\n\t\t\t\t\t\t\t\t\t\t<Avatar className=\"sg:h-20 sg:w-20 sg:mx-auto sg:mb-3\">\r\n\t\t\t\t\t\t\t\t\t\t\t<AvatarImage src={author.avatar} alt={author.name} />\r\n\t\t\t\t\t\t\t\t\t\t\t<AvatarFallback>{author.name[0]}</AvatarFallback>\r\n\t\t\t\t\t\t\t\t\t\t</Avatar>\r\n\t\t\t\t\t\t\t\t\t\t<Heading\r\n\t\t\t\t\t\t\t\t\t\t\tvariant=\"h5\"\r\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"sg:group-hover:text-primary sg:transition-colors\"\r\n\t\t\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\t\t\t{author.name}\r\n\t\t\t\t\t\t\t\t\t\t</Heading>\r\n\t\t\t\t\t\t\t\t\t\t<Text size=\"sm\" className=\"sg:text-primary/80 sg:mb-2\">\r\n\t\t\t\t\t\t\t\t\t\t\t{author.role}\r\n\t\t\t\t\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t\t\t\t\t\t<Text\r\n\t\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\r\n\t\t\t\t\t\t\t\t\t\t\tforeground=\"muted-foreground\"\r\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"sg:line-clamp-3 sg:leading-relaxed\"\r\n\t\t\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\t\t\t{author.bio}\r\n\t\t\t\t\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t\t\t\t\t</CardContent>\r\n\t\t\t\t\t\t\t\t</Card>\r\n\t\t\t\t\t\t\t</Link>\r\n\t\t\t\t\t\t))}\r\n\t\t\t\t\t</div>\r\n\t\t\t\t</Layout.Col1>\r\n\t\t\t</Layout>\r\n\r\n\t\t\t<Separator className=\"sg:max-w-3xl sg:mx-auto\" />\r\n\r\n\t\t\t<Layout type=\"col\" className=\"sg:py-16\">\r\n\t\t\t\t<Layout.Col1 hideDiv className=\"sg:max-w-3xl\">\r\n\t\t\t\t\t<Timeline\r\n\t\t\t\t\t\titems={timeline}\r\n\t\t\t\t\t\tdescription=\"Key moments that shaped our journey.\"\r\n\t\t\t\t\t/>\r\n\t\t\t\t</Layout.Col1>\r\n\t\t\t</Layout>\r\n\r\n\t\t\t<section className=\"sg:bg-primary/5 sg:border-t sg:border-border\">\r\n\t\t\t\t<Layout type=\"col\" className=\"sg:py-16\">\r\n\t\t\t\t\t<Layout.Col1 hideDiv className=\"sg:max-w-3xl\">\r\n\t\t\t\t\t\t<ValuesGrid\r\n\t\t\t\t\t\t\titems={values}\r\n\t\t\t\t\t\t\ticon={\r\n\t\t\t\t\t\t\t\t<Icon\r\n\t\t\t\t\t\t\t\t\ticon=\"Award\"\r\n\t\t\t\t\t\t\t\t\tclassName=\"sg:h-8 sg:w-8 sg:text-primary sg:mx-auto sg:mb-4\"\r\n\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t/>\r\n\t\t\t\t\t</Layout.Col1>\r\n\t\t\t\t</Layout>\r\n\t\t\t</section>\r\n\t\t</motion.div>\r\n\t);\r\n}\r\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/components/pages/about/about-page.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport { motion } from \"framer-motion\";\r\nimport { Layout, Heading, Text, Icon, Separator } from \"../../primitives/index\";\r\nimport { PageHero } from \"../../blocks/marketing/page-hero\";\r\nimport { StatsGrid } from \"../../blocks/marketing/stats-grid\";\r\nimport { Timeline } from \"../../blocks/marketing/timeline\";\r\nimport { ValuesGrid } from \"../../blocks/marketing/values-grid\";\r\nimport { Card, CardContent } from \"../../blocks/cards/card\";\r\nimport {\r\n\tAvatar,\r\n\tAvatarFallback,\r\n\tAvatarImage,\r\n} from \"../../primitives/avatar/avatar\";\r\nimport { Link } from \"../../primitives/link/link\";\r\nimport { authors } from \"../../../data/authors\";\r\nimport { posts } from \"../../../data/posts\";\r\n\r\nconst stats = [\r\n\t{\r\n\t\tlabel: \"Articles Published\",\r\n\t\tvalue: posts.length.toString(),\r\n\t\ticon: \"BookOpen\" as const,\r\n\t},\r\n\t{\r\n\t\tlabel: \"Contributing Writers\",\r\n\t\tvalue: authors.length.toString(),\r\n\t\ticon: \"Users\" as const,\r\n\t},\r\n\t{\r\n\t\tlabel: \"Categories Covered\",\r\n\t\tvalue: [...new Set(posts.flatMap((p) => p.categories))].length.toString(),\r\n\t\ticon: \"TrendingUp\" as const,\r\n\t},\r\n\t{ label: \"Years Running\", value: \"3\", icon: \"Calendar\" as const },\r\n];\r\n\r\nconst timeline = [\r\n\t{\r\n\t\tyear: \"2023\",\r\n\t\ttitle: \"The Beginning\",\r\n\t\tdescription:\r\n\t\t\t\"Launched as a personal blog about slow living and intentional design.\",\r\n\t},\r\n\t{\r\n\t\tyear: \"2023\",\r\n\t\ttitle: \"Growing the Team\",\r\n\t\tdescription:\r\n\t\t\t\"New contributing writers expanded coverage into culture and design.\",\r\n\t},\r\n\t{\r\n\t\tyear: \"2024\",\r\n\t\ttitle: \"Community & Resources\",\r\n\t\tdescription:\r\n\t\t\t\"Introduced the Resources hub and Mosaic gallery. Readership doubled.\",\r\n\t},\r\n\t{\r\n\t\tyear: \"2025\",\r\n\t\ttitle: \"New Horizons\",\r\n\t\tdescription:\r\n\t\t\t\"Expanded categories, launched chat, and hit a milestone of regular readers.\",\r\n\t},\r\n];\r\n\r\nconst values = [\r\n\t{\r\n\t\ttitle: \"Depth over speed\",\r\n\t\tdescription:\r\n\t\t\t\"We take time to research, write, and edit. Every piece earns its place.\",\r\n\t},\r\n\t{\r\n\t\ttitle: \"Beauty in simplicity\",\r\n\t\tdescription: \"Clean design, honest words, and images that breathe.\",\r\n\t},\r\n\t{\r\n\t\ttitle: \"Community first\",\r\n\t\tdescription:\r\n\t\t\t\"We write for curious minds who value connection and craft.\",\r\n\t},\r\n];\r\n\r\nexport function AboutPage() {\r\n\treturn (\r\n\t\t<motion.div\r\n\t\t\tinitial={{ opacity: 1, y: 20 }}\r\n\t\t\tanimate={{ opacity: 1, y: 0 }}\r\n\t\t\ttransition={{ duration: 0.3 }}\r\n\t\t>\r\n\t\t\t<PageHero\r\n\t\t\t\ticon=\"Heart\"\r\n\t\t\t\ttitle=\"About filion\"\r\n\t\t\t\tdescription=\"We believe in the power of slow, intentional storytelling — depth over speed, beauty over noise, and presence over productivity.\"\r\n\t\t\t/>\r\n\r\n\t\t\t<Layout type=\"col\" className=\"sg:py-16\">\r\n\t\t\t\t<Layout.Col1 hideDiv className=\"sg:max-w-4xl\">\r\n\t\t\t\t\t<StatsGrid items={stats} />\r\n\t\t\t\t</Layout.Col1>\r\n\t\t\t</Layout>\r\n\r\n\t\t\t<section className=\"sg:bg-muted/40 sg:border-y sg:border-border\">\r\n\t\t\t\t<Layout type=\"col\" className=\"sg:py-16\">\r\n\t\t\t\t\t<Layout.Col1 hideDiv className=\"sg:max-w-3xl\">\r\n\t\t\t\t\t\t<Heading variant=\"h2\" className=\"sg:mb-6\">\r\n\t\t\t\t\t\t\tOur Story\r\n\t\t\t\t\t\t</Heading>\r\n\t\t\t\t\t\t<div className=\"sg:space-y-4\">\r\n\t\t\t\t\t\t\t<Text foreground=\"muted-foreground\" className=\"sg:leading-relaxed\">\r\n\t\t\t\t\t\t\t\tWhat began as one writer's reflections on slow mornings and\r\n\t\t\t\t\t\t\t\thandwritten letters grew into a collective of voices united by\r\n\t\t\t\t\t\t\t\tcuriosity and care.\r\n\t\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t\t\t<Text foreground=\"muted-foreground\" className=\"sg:leading-relaxed\">\r\n\t\t\t\t\t\t\t\tToday, our team explores everything from minimalist design to\r\n\t\t\t\t\t\t\t\tglobal traditions, always with the same ethos: take your time,\r\n\t\t\t\t\t\t\t\tpay attention, and tell the story honestly.\r\n\t\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t\t</div>\r\n\t\t\t\t\t</Layout.Col1>\r\n\t\t\t\t</Layout>\r\n\t\t\t</section>\r\n\r\n\t\t\t<Layout type=\"col\" className=\"sg:py-16\">\r\n\t\t\t\t<Layout.Col1 hideDiv className=\"sg:max-w-4xl\">\r\n\t\t\t\t\t<Heading variant=\"h2\" className=\"sg:mb-2\">\r\n\t\t\t\t\t\tThe Team\r\n\t\t\t\t\t</Heading>\r\n\t\t\t\t\t<Text foreground=\"muted-foreground\" className=\"sg:mb-8\">\r\n\t\t\t\t\t\tThe writers behind the words.\r\n\t\t\t\t\t</Text>\r\n\t\t\t\t\t<div className=\"sg:grid sg:gap-6 sm:sg:grid-cols-3\">\r\n\t\t\t\t\t\t{authors.map((author) => (\r\n\t\t\t\t\t\t\t<Link\r\n\t\t\t\t\t\t\t\tkey={author.slug}\r\n\t\t\t\t\t\t\t\tto={`/extras/authors/${author.slug}`}\r\n\t\t\t\t\t\t\t\tvariant=\"no-decoration\"\r\n\t\t\t\t\t\t\t\tclassName=\"sg:group\"\r\n\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t<Card className=\"sg:h-full sg:transition-shadow sg:hover:shadow-lg sg:hover:border-primary/40\">\r\n\t\t\t\t\t\t\t\t\t<CardContent className=\"sg:pt-6 sg:text-center\">\r\n\t\t\t\t\t\t\t\t\t\t<Avatar className=\"sg:h-20 sg:w-20 sg:mx-auto sg:mb-3\">\r\n\t\t\t\t\t\t\t\t\t\t\t<AvatarImage src={author.avatar} alt={author.name} />\r\n\t\t\t\t\t\t\t\t\t\t\t<AvatarFallback>{author.name[0]}</AvatarFallback>\r\n\t\t\t\t\t\t\t\t\t\t</Avatar>\r\n\t\t\t\t\t\t\t\t\t\t<Heading\r\n\t\t\t\t\t\t\t\t\t\t\tvariant=\"h5\"\r\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"sg:group-hover:text-primary sg:transition-colors\"\r\n\t\t\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\t\t\t{author.name}\r\n\t\t\t\t\t\t\t\t\t\t</Heading>\r\n\t\t\t\t\t\t\t\t\t\t<Text size=\"sm\" foreground=\"muted-foreground\" className=\"sg:mb-2\">\r\n\t\t\t\t\t\t\t\t\t\t\t{author.role}\r\n\t\t\t\t\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t\t\t\t\t\t<Text\r\n\t\t\t\t\t\t\t\t\t\t\tsize=\"sm\"\r\n\t\t\t\t\t\t\t\t\t\t\tforeground=\"muted-foreground\"\r\n\t\t\t\t\t\t\t\t\t\t\tclassName=\"sg:line-clamp-3 sg:leading-relaxed\"\r\n\t\t\t\t\t\t\t\t\t\t>\r\n\t\t\t\t\t\t\t\t\t\t\t{author.bio}\r\n\t\t\t\t\t\t\t\t\t\t</Text>\r\n\t\t\t\t\t\t\t\t\t</CardContent>\r\n\t\t\t\t\t\t\t\t</Card>\r\n\t\t\t\t\t\t\t</Link>\r\n\t\t\t\t\t\t))}\r\n\t\t\t\t\t</div>\r\n\t\t\t\t</Layout.Col1>\r\n\t\t\t</Layout>\r\n\r\n\t\t\t<Separator className=\"sg:max-w-3xl sg:mx-auto\" />\r\n\r\n\t\t\t<Layout type=\"col\" className=\"sg:py-16\">\r\n\t\t\t\t<Layout.Col1 hideDiv className=\"sg:max-w-3xl\">\r\n\t\t\t\t\t<Timeline\r\n\t\t\t\t\t\titems={timeline}\r\n\t\t\t\t\t\tdescription=\"Key moments that shaped our journey.\"\r\n\t\t\t\t\t/>\r\n\t\t\t\t</Layout.Col1>\r\n\t\t\t</Layout>\r\n\r\n\t\t\t<section className=\"sg:bg-primary/5 sg:border-t sg:border-border\">\r\n\t\t\t\t<Layout type=\"col\" className=\"sg:py-16\">\r\n\t\t\t\t\t<Layout.Col1 hideDiv className=\"sg:max-w-3xl\">\r\n\t\t\t\t\t\t<ValuesGrid\r\n\t\t\t\t\t\t\titems={values}\r\n\t\t\t\t\t\t\ticon={\r\n\t\t\t\t\t\t\t\t<Icon\r\n\t\t\t\t\t\t\t\t\ticon=\"Award\"\r\n\t\t\t\t\t\t\t\t\tclassName=\"sg:h-8 sg:w-8 sg:text-primary sg:mx-auto sg:mb-4\"\r\n\t\t\t\t\t\t\t\t/>\r\n\t\t\t\t\t\t\t}\r\n\t\t\t\t\t\t/>\r\n\t\t\t\t\t</Layout.Col1>\r\n\t\t\t\t</Layout>\r\n\t\t\t</section>\r\n\t\t</motion.div>\r\n\t);\r\n}\r\n"],"mappings":"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","names":[]}
|