singularity-components 0.1.195 → 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/badges/category-badge.d.ts +11 -0
- package/dist/components/blocks/badges/category-badge.js +34 -0
- package/dist/components/blocks/badges/category-badge.js.map +1 -0
- package/dist/components/blocks/cards/blogpost-card.d.ts +3 -1
- package/dist/components/blocks/cards/blogpost-card.js +10 -5
- package/dist/components/blocks/cards/blogpost-card.js.map +1 -1
- package/dist/components/blocks/directory/author-card.d.ts +10 -0
- package/dist/components/blocks/directory/author-card.js +50 -0
- package/dist/components/blocks/directory/author-card.js.map +1 -0
- package/dist/components/blocks/directory/category-card.d.ts +10 -0
- package/dist/components/blocks/directory/category-card.js +27 -0
- package/dist/components/blocks/directory/category-card.js.map +1 -0
- package/dist/components/blocks/extras/extras-hub-card.d.ts +16 -0
- package/dist/components/blocks/extras/extras-hub-card.js +22 -0
- package/dist/components/blocks/extras/extras-hub-card.js.map +1 -0
- package/dist/components/blocks/gallery/image-gallery.d.ts +14 -0
- package/dist/components/blocks/gallery/image-gallery.js +211 -0
- package/dist/components/blocks/gallery/image-gallery.js.map +1 -0
- package/dist/components/blocks/index.d.ts +11 -0
- package/dist/components/blocks/index.js +10 -0
- package/dist/components/blocks/index.js.map +1 -1
- package/dist/components/blocks/loading/loading-skeletons.d.ts +15 -0
- package/dist/components/blocks/loading/loading-skeletons.js +78 -0
- package/dist/components/blocks/loading/loading-skeletons.js.map +1 -0
- package/dist/components/blocks/login/login.js +76 -47
- package/dist/components/blocks/login/login.js.map +1 -1
- package/dist/components/blocks/marketing/page-hero.d.ts +13 -0
- package/dist/components/blocks/marketing/page-hero.js +37 -0
- package/dist/components/blocks/marketing/page-hero.js.map +1 -0
- package/dist/components/blocks/marketing/stats-grid.d.ts +16 -0
- package/dist/components/blocks/marketing/stats-grid.js +30 -0
- package/dist/components/blocks/marketing/stats-grid.js.map +1 -0
- package/dist/components/blocks/marketing/timeline.d.ts +17 -0
- package/dist/components/blocks/marketing/timeline.js +46 -0
- package/dist/components/blocks/marketing/timeline.js.map +1 -0
- package/dist/components/blocks/marketing/values-grid.d.ts +16 -0
- package/dist/components/blocks/marketing/values-grid.js +29 -0
- package/dist/components/blocks/marketing/values-grid.js.map +1 -0
- 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/index.d.ts +28 -1
- package/dist/components/pages/about/about-page.d.ts +5 -0
- package/dist/components/pages/about/about-page.js +161 -0
- package/dist/components/pages/about/about-page.js.map +1 -0
- package/dist/components/pages/admin/admin-page.js +160 -103
- package/dist/components/pages/admin/admin-page.js.map +1 -1
- package/dist/components/pages/author/author-page.d.ts +8 -0
- package/dist/components/pages/author/author-page.js +107 -0
- package/dist/components/pages/author/author-page.js.map +1 -0
- package/dist/components/pages/authors/authors-page.d.ts +5 -0
- package/dist/components/pages/authors/authors-page.js +25 -0
- package/dist/components/pages/authors/authors-page.js.map +1 -0
- package/dist/components/pages/blogpost/blogpost.d.ts +4 -1
- package/dist/components/pages/blogpost/blogpost.js +110 -62
- package/dist/components/pages/blogpost/blogpost.js.map +1 -1
- package/dist/components/pages/categories/categories-page.d.ts +5 -0
- package/dist/components/pages/categories/categories-page.js +33 -0
- package/dist/components/pages/categories/categories-page.js.map +1 -0
- package/dist/components/pages/category/category-page.js +4 -2
- 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.d.ts +5 -0
- package/dist/components/pages/contact/contact-page.js +180 -0
- package/dist/components/pages/contact/contact-page.js.map +1 -0
- package/dist/components/pages/content-blocks/content-blocks-page.d.ts +5 -0
- package/dist/components/pages/content-blocks/content-blocks-page.js +87 -0
- package/dist/components/pages/content-blocks/content-blocks-page.js.map +1 -0
- package/dist/components/pages/extras/extras-hub-page.d.ts +10 -0
- package/dist/components/pages/extras/extras-hub-page.js +110 -0
- package/dist/components/pages/extras/extras-hub-page.js.map +1 -0
- package/dist/components/pages/index.d.ts +14 -0
- package/dist/components/pages/index.js +12 -0
- package/dist/components/pages/index.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.d.ts +5 -0
- package/dist/components/pages/membership/membership-page.js +131 -0
- package/dist/components/pages/membership/membership-page.js.map +1 -0
- package/dist/components/pages/mosaic/mosaic-page.d.ts +5 -0
- package/dist/components/pages/mosaic/mosaic-page.js +81 -0
- package/dist/components/pages/mosaic/mosaic-page.js.map +1 -0
- package/dist/components/pages/newsletter/newsletter-page.d.ts +5 -0
- package/dist/components/pages/newsletter/newsletter-page.js +165 -0
- package/dist/components/pages/newsletter/newsletter-page.js.map +1 -0
- 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.d.ts +5 -0
- package/dist/components/pages/resources/resources-page.js +24 -0
- package/dist/components/pages/resources/resources-page.js.map +1 -0
- package/dist/components/pages/startpage/startpage.js +6 -4
- package/dist/components/pages/startpage/startpage.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/accordion/accordion.js +14 -16
- package/dist/components/primitives/accordion/accordion.js.map +1 -1
- package/dist/components/primitives/badge/badge.js +1 -1
- package/dist/components/primitives/badge/badge.js.map +1 -1
- package/dist/components/primitives/buttons/button.d.ts +2 -2
- package/dist/components/primitives/buttons/icon-button.d.ts +1 -1
- package/dist/components/primitives/collapsible/collapsible.js +4 -1
- package/dist/components/primitives/collapsible/collapsible.js.map +1 -1
- package/dist/components/primitives/dropdown-menu/dropdown-menu.js +6 -1
- package/dist/components/primitives/dropdown-menu/dropdown-menu.js.map +1 -1
- package/dist/components/primitives/forms/checkbox.js +1 -1
- package/dist/components/primitives/forms/checkbox.js.map +1 -1
- package/dist/components/primitives/forms/field.d.ts +4 -2
- package/dist/components/primitives/forms/field.js +4 -2
- package/dist/components/primitives/forms/field.js.map +1 -1
- package/dist/components/primitives/forms/form-control.d.ts +28 -0
- package/dist/components/primitives/forms/form-control.js +40 -0
- package/dist/components/primitives/forms/form-control.js.map +1 -0
- package/dist/components/primitives/forms/form.d.ts +12 -0
- package/dist/components/primitives/forms/form.js +30 -0
- package/dist/components/primitives/forms/form.js.map +1 -0
- package/dist/components/primitives/forms/select.js +12 -12
- package/dist/components/primitives/forms/select.js.map +1 -1
- package/dist/components/primitives/icon/icon.d.ts +3 -2
- package/dist/components/primitives/icon/icon.js +2 -1
- package/dist/components/primitives/icon/icon.js.map +1 -1
- package/dist/components/primitives/index.d.ts +4 -0
- package/dist/components/primitives/index.js +3 -0
- package/dist/components/primitives/index.js.map +1 -1
- package/dist/components/primitives/layout/layout.d.ts +1 -1
- package/dist/components/primitives/link/link.d.ts +2 -2
- package/dist/components/primitives/sheet/sheet.js +1 -1
- package/dist/components/primitives/sheet/sheet.js.map +1 -1
- package/dist/components/primitives/stack/stack.d.ts +2 -2
- package/dist/components/primitives/text/internal/text-element.d.ts +8 -2
- package/dist/components/primitives/text/internal/text-element.js +3 -0
- package/dist/components/primitives/text/internal/text-element.js.map +1 -1
- package/dist/components/primitives/text/text-code.d.ts +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/index.d.ts +1 -0
- package/dist/components/templates/index.js +1 -0
- package/dist/components/templates/index.js.map +1 -1
- package/dist/components/templates/loading-screen/loading-screen.d.ts +10 -0
- package/dist/components/templates/loading-screen/loading-screen.js +39 -0
- package/dist/components/templates/loading-screen/loading-screen.js.map +1 -0
- package/dist/css/variables.css +6 -3
- package/dist/css/variables.css.map +1 -1
- package/dist/data/posts.d.ts +5 -0
- package/dist/data/posts.js +41 -8
- package/dist/data/posts.js.map +1 -1
- package/dist/index.d.ts +28 -1
- package/dist/lib/forms/field-props.d.ts +60 -0
- package/dist/lib/forms/field-props.js +60 -0
- package/dist/lib/forms/field-props.js.map +1 -0
- package/dist/lib/forms/index.d.ts +11 -0
- package/dist/lib/forms/index.js +3 -0
- package/dist/lib/forms/index.js.map +1 -0
- package/dist/lib/forms/tanstack-field.d.ts +71 -0
- package/dist/lib/forms/tanstack-field.js +121 -0
- package/dist/lib/forms/tanstack-field.js.map +1 -0
- package/dist/lib/index.d.ts +11 -0
- package/dist/lib/index.js +1 -0
- package/dist/lib/index.js.map +1 -1
- package/dist/main.css +393 -90
- package/dist/main.css.map +1 -1
- package/package.json +30 -23
|
@@ -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":"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","names":[]}
|
|
@@ -1,13 +1,34 @@
|
|
|
1
1
|
export { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from './blocks/cards/card.js';
|
|
2
|
+
export { AuthorCard } from './blocks/directory/author-card.js';
|
|
3
|
+
export { CategoryCard } from './blocks/directory/category-card.js';
|
|
4
|
+
export { ExtrasHubCard, ExtrasHubItem } from './blocks/extras/extras-hub-card.js';
|
|
5
|
+
export { GalleryImage } from './blocks/gallery/image-gallery.js';
|
|
6
|
+
export { CommentSkeleton, PostCardSkeleton, PostListRowSkeleton, PostListSkeleton, SinglePostSkeleton } from './blocks/loading/loading-skeletons.js';
|
|
2
7
|
export { Login, LoginCredentials, LoginProps } from './blocks/login/login.js';
|
|
8
|
+
export { PageHero } from './blocks/marketing/page-hero.js';
|
|
9
|
+
export { StatItem, StatsGrid } from './blocks/marketing/stats-grid.js';
|
|
10
|
+
export { Timeline, TimelineItem } from './blocks/marketing/timeline.js';
|
|
11
|
+
export { ValueItem, ValuesGrid } from './blocks/marketing/values-grid.js';
|
|
3
12
|
export { PostListWithFilters } from './blocks/post-list/post-list-with-filters.js';
|
|
13
|
+
export { AboutPage } from './pages/about/about-page.js';
|
|
4
14
|
export { AdminPage, AdminPageProps } from './pages/admin/admin-page.js';
|
|
15
|
+
export { AuthorPage } from './pages/author/author-page.js';
|
|
16
|
+
export { AuthorsPage } from './pages/authors/authors-page.js';
|
|
5
17
|
export { BlogPost } from './pages/blogpost/blogpost.js';
|
|
18
|
+
export { CategoriesPage } from './pages/categories/categories-page.js';
|
|
6
19
|
export { CategoryPage } from './pages/category/category-page.js';
|
|
20
|
+
export { ChatPage } from './pages/chat/chat-page.js';
|
|
21
|
+
export { ContactPage } from './pages/contact/contact-page.js';
|
|
22
|
+
export { ContentBlocksPage } from './pages/content-blocks/content-blocks-page.js';
|
|
23
|
+
export { ExtrasHubPage } from './pages/extras/extras-hub-page.js';
|
|
7
24
|
export { LoginPage } from './pages/login/login-page.js';
|
|
8
25
|
export { MaintenancePage } from './pages/maintenance/maintenance-page.js';
|
|
26
|
+
export { MembershipPage } from './pages/membership/membership-page.js';
|
|
27
|
+
export { MosaicPage } from './pages/mosaic/mosaic-page.js';
|
|
28
|
+
export { NewsletterPage } from './pages/newsletter/newsletter-page.js';
|
|
9
29
|
export { NotFound } from './pages/not-found/not-found.js';
|
|
10
30
|
export { PrivacyPage } from './pages/privacy/privacy-page.js';
|
|
31
|
+
export { ResourcesPage } from './pages/resources/resources-page.js';
|
|
11
32
|
export { SearchPage } from './pages/search/search-page.js';
|
|
12
33
|
export { StartPage } from './pages/startpage/startpage.js';
|
|
13
34
|
export { TermsPage } from './pages/terms/terms-page.js';
|
|
@@ -21,6 +42,9 @@ export { LinkButton } from './primitives/buttons/link-button.js';
|
|
|
21
42
|
export { Collapsible, CollapsibleContent, CollapsibleTrigger } from './primitives/collapsible/collapsible.js';
|
|
22
43
|
export { DropdownMenu, DropdownMenuCheckboxItem, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuPortal, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuSub, DropdownMenuSubContent, DropdownMenuSubTrigger, DropdownMenuTrigger } from './primitives/dropdown-menu/dropdown-menu.js';
|
|
23
44
|
export { Checkbox } from './primitives/forms/checkbox.js';
|
|
45
|
+
export { Field, FieldContent, FieldDescription, FieldError, FieldGroup, FieldLabel, FieldLegend, FieldSeparator, FieldSet, FieldTitle } from './primitives/forms/field.js';
|
|
46
|
+
export { Form, FormActions } from './primitives/forms/form.js';
|
|
47
|
+
export { FormControl } from './primitives/forms/form-control.js';
|
|
24
48
|
export { Input } from './primitives/forms/input.js';
|
|
25
49
|
export { Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue } from './primitives/forms/select.js';
|
|
26
50
|
export { Textarea } from './primitives/forms/textarea.js';
|
|
@@ -49,19 +73,22 @@ export { AuthProvider, useAuth } from './providers/auth-provider.js';
|
|
|
49
73
|
export { Theme, ThemeProvider, ThemeProviderProps, ThemeProviderState, useTheme } from './providers/theme-provider.js';
|
|
50
74
|
export { Container } from './templates/container/container.js';
|
|
51
75
|
export { Footer } from './templates/footer/footer.js';
|
|
76
|
+
export { LoadingScreen } from './templates/loading-screen/loading-screen.js';
|
|
52
77
|
export { Header, HeaderProps, NavLink } from './templates/navigation/header.js';
|
|
53
78
|
export { toast } from 'sonner';
|
|
54
79
|
import 'react';
|
|
80
|
+
import '../data/authors.js';
|
|
81
|
+
import 'lucide-react';
|
|
55
82
|
import '../data/posts.js';
|
|
56
83
|
import '@base-ui/react/accordion';
|
|
57
84
|
import 'class-variance-authority/types';
|
|
58
85
|
import 'class-variance-authority';
|
|
59
86
|
import '@base-ui/react/use-render';
|
|
60
87
|
import '@base-ui/react/button';
|
|
61
|
-
import 'lucide-react';
|
|
62
88
|
import '@radix-ui/react-collapsible';
|
|
63
89
|
import '@radix-ui/react-dropdown-menu';
|
|
64
90
|
import '@base-ui/react';
|
|
91
|
+
import '../lib/forms/field-props.js';
|
|
65
92
|
import '@base-ui/react/separator';
|
|
66
93
|
import '@radix-ui/react-dialog';
|
|
67
94
|
import './primitives/text/internal/text-element.js';
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { motion } from "framer-motion";
|
|
4
|
+
import { Layout, Heading, Text, Icon, Separator } from "../../primitives/index.js";
|
|
5
|
+
import { PageHero } from "../../blocks/marketing/page-hero.js";
|
|
6
|
+
import { StatsGrid } from "../../blocks/marketing/stats-grid.js";
|
|
7
|
+
import { Timeline } from "../../blocks/marketing/timeline.js";
|
|
8
|
+
import { ValuesGrid } from "../../blocks/marketing/values-grid.js";
|
|
9
|
+
import { Card, CardContent } from "../../blocks/cards/card.js";
|
|
10
|
+
import {
|
|
11
|
+
Avatar,
|
|
12
|
+
AvatarFallback,
|
|
13
|
+
AvatarImage
|
|
14
|
+
} from "../../primitives/avatar/avatar.js";
|
|
15
|
+
import { Link } from "../../primitives/link/link.js";
|
|
16
|
+
import { authors } from "../../../data/authors.js";
|
|
17
|
+
import { posts } from "../../../data/posts.js";
|
|
18
|
+
const stats = [
|
|
19
|
+
{
|
|
20
|
+
label: "Articles Published",
|
|
21
|
+
value: posts.length.toString(),
|
|
22
|
+
icon: "BookOpen"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
label: "Contributing Writers",
|
|
26
|
+
value: authors.length.toString(),
|
|
27
|
+
icon: "Users"
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
label: "Categories Covered",
|
|
31
|
+
value: [...new Set(posts.flatMap((p) => p.categories))].length.toString(),
|
|
32
|
+
icon: "TrendingUp"
|
|
33
|
+
},
|
|
34
|
+
{ label: "Years Running", value: "3", icon: "Calendar" }
|
|
35
|
+
];
|
|
36
|
+
const timeline = [
|
|
37
|
+
{
|
|
38
|
+
year: "2023",
|
|
39
|
+
title: "The Beginning",
|
|
40
|
+
description: "Launched as a personal blog about slow living and intentional design."
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
year: "2023",
|
|
44
|
+
title: "Growing the Team",
|
|
45
|
+
description: "New contributing writers expanded coverage into culture and design."
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
year: "2024",
|
|
49
|
+
title: "Community & Resources",
|
|
50
|
+
description: "Introduced the Resources hub and Mosaic gallery. Readership doubled."
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
year: "2025",
|
|
54
|
+
title: "New Horizons",
|
|
55
|
+
description: "Expanded categories, launched chat, and hit a milestone of regular readers."
|
|
56
|
+
}
|
|
57
|
+
];
|
|
58
|
+
const values = [
|
|
59
|
+
{
|
|
60
|
+
title: "Depth over speed",
|
|
61
|
+
description: "We take time to research, write, and edit. Every piece earns its place."
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
title: "Beauty in simplicity",
|
|
65
|
+
description: "Clean design, honest words, and images that breathe."
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
title: "Community first",
|
|
69
|
+
description: "We write for curious minds who value connection and craft."
|
|
70
|
+
}
|
|
71
|
+
];
|
|
72
|
+
function AboutPage() {
|
|
73
|
+
return /* @__PURE__ */ jsxs(
|
|
74
|
+
motion.div,
|
|
75
|
+
{
|
|
76
|
+
initial: { opacity: 1, y: 20 },
|
|
77
|
+
animate: { opacity: 1, y: 0 },
|
|
78
|
+
transition: { duration: 0.3 },
|
|
79
|
+
children: [
|
|
80
|
+
/* @__PURE__ */ jsx(
|
|
81
|
+
PageHero,
|
|
82
|
+
{
|
|
83
|
+
icon: "Heart",
|
|
84
|
+
title: "About filion",
|
|
85
|
+
description: "We believe in the power of slow, intentional storytelling \u2014 depth over speed, beauty over noise, and presence over productivity."
|
|
86
|
+
}
|
|
87
|
+
),
|
|
88
|
+
/* @__PURE__ */ jsx(Layout, { type: "col", className: "sg:py-16", children: /* @__PURE__ */ jsx(Layout.Col1, { hideDiv: true, className: "sg:max-w-4xl", children: /* @__PURE__ */ jsx(StatsGrid, { items: stats }) }) }),
|
|
89
|
+
/* @__PURE__ */ jsx("section", { className: "sg:bg-muted/40 sg:border-y sg:border-border", children: /* @__PURE__ */ jsx(Layout, { type: "col", className: "sg:py-16", children: /* @__PURE__ */ jsxs(Layout.Col1, { hideDiv: true, className: "sg:max-w-3xl", children: [
|
|
90
|
+
/* @__PURE__ */ jsx(Heading, { variant: "h2", className: "sg:mb-6", children: "Our Story" }),
|
|
91
|
+
/* @__PURE__ */ jsxs("div", { className: "sg:space-y-4", children: [
|
|
92
|
+
/* @__PURE__ */ jsx(Text, { foreground: "muted-foreground", className: "sg:leading-relaxed", children: "What began as one writer's reflections on slow mornings and handwritten letters grew into a collective of voices united by curiosity and care." }),
|
|
93
|
+
/* @__PURE__ */ jsx(Text, { foreground: "muted-foreground", className: "sg:leading-relaxed", children: "Today, our team explores everything from minimalist design to global traditions, always with the same ethos: take your time, pay attention, and tell the story honestly." })
|
|
94
|
+
] })
|
|
95
|
+
] }) }) }),
|
|
96
|
+
/* @__PURE__ */ jsx(Layout, { type: "col", className: "sg:py-16", children: /* @__PURE__ */ jsxs(Layout.Col1, { hideDiv: true, className: "sg:max-w-4xl", children: [
|
|
97
|
+
/* @__PURE__ */ jsx(Heading, { variant: "h2", className: "sg:mb-2", children: "The Team" }),
|
|
98
|
+
/* @__PURE__ */ jsx(Text, { foreground: "muted-foreground", className: "sg:mb-8", children: "The writers behind the words." }),
|
|
99
|
+
/* @__PURE__ */ jsx("div", { className: "sg:grid sg:gap-6 sm:sg:grid-cols-3", children: authors.map((author) => /* @__PURE__ */ jsx(
|
|
100
|
+
Link,
|
|
101
|
+
{
|
|
102
|
+
to: `/extras/authors/${author.slug}`,
|
|
103
|
+
variant: "no-decoration",
|
|
104
|
+
className: "sg:group",
|
|
105
|
+
children: /* @__PURE__ */ jsx(Card, { className: "sg:h-full sg:transition-shadow sg:hover:shadow-lg sg:hover:border-primary/40", children: /* @__PURE__ */ jsxs(CardContent, { className: "sg:pt-6 sg:text-center", children: [
|
|
106
|
+
/* @__PURE__ */ jsxs(Avatar, { className: "sg:h-20 sg:w-20 sg:mx-auto sg:mb-3", children: [
|
|
107
|
+
/* @__PURE__ */ jsx(AvatarImage, { src: author.avatar, alt: author.name }),
|
|
108
|
+
/* @__PURE__ */ jsx(AvatarFallback, { children: author.name[0] })
|
|
109
|
+
] }),
|
|
110
|
+
/* @__PURE__ */ jsx(
|
|
111
|
+
Heading,
|
|
112
|
+
{
|
|
113
|
+
variant: "h5",
|
|
114
|
+
className: "sg:group-hover:text-primary sg:transition-colors",
|
|
115
|
+
children: author.name
|
|
116
|
+
}
|
|
117
|
+
),
|
|
118
|
+
/* @__PURE__ */ jsx(Text, { size: "sm", foreground: "muted-foreground", className: "sg:mb-2", children: author.role }),
|
|
119
|
+
/* @__PURE__ */ jsx(
|
|
120
|
+
Text,
|
|
121
|
+
{
|
|
122
|
+
size: "sm",
|
|
123
|
+
foreground: "muted-foreground",
|
|
124
|
+
className: "sg:line-clamp-3 sg:leading-relaxed",
|
|
125
|
+
children: author.bio
|
|
126
|
+
}
|
|
127
|
+
)
|
|
128
|
+
] }) })
|
|
129
|
+
},
|
|
130
|
+
author.slug
|
|
131
|
+
)) })
|
|
132
|
+
] }) }),
|
|
133
|
+
/* @__PURE__ */ jsx(Separator, { className: "sg:max-w-3xl sg:mx-auto" }),
|
|
134
|
+
/* @__PURE__ */ jsx(Layout, { type: "col", className: "sg:py-16", children: /* @__PURE__ */ jsx(Layout.Col1, { hideDiv: true, className: "sg:max-w-3xl", children: /* @__PURE__ */ jsx(
|
|
135
|
+
Timeline,
|
|
136
|
+
{
|
|
137
|
+
items: timeline,
|
|
138
|
+
description: "Key moments that shaped our journey."
|
|
139
|
+
}
|
|
140
|
+
) }) }),
|
|
141
|
+
/* @__PURE__ */ jsx("section", { className: "sg:bg-primary/5 sg:border-t sg:border-border", children: /* @__PURE__ */ jsx(Layout, { type: "col", className: "sg:py-16", children: /* @__PURE__ */ jsx(Layout.Col1, { hideDiv: true, className: "sg:max-w-3xl", children: /* @__PURE__ */ jsx(
|
|
142
|
+
ValuesGrid,
|
|
143
|
+
{
|
|
144
|
+
items: values,
|
|
145
|
+
icon: /* @__PURE__ */ jsx(
|
|
146
|
+
Icon,
|
|
147
|
+
{
|
|
148
|
+
icon: "Award",
|
|
149
|
+
className: "sg:h-8 sg:w-8 sg:text-primary sg:mx-auto sg:mb-4"
|
|
150
|
+
}
|
|
151
|
+
)
|
|
152
|
+
}
|
|
153
|
+
) }) }) })
|
|
154
|
+
]
|
|
155
|
+
}
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
export {
|
|
159
|
+
AboutPage
|
|
160
|
+
};
|
|
161
|
+
//# sourceMappingURL=about-page.js.map
|
|
@@ -0,0 +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: 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":[]}
|