singularity-components 0.1.151 → 0.1.193

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.
Files changed (244) hide show
  1. package/README.md +29 -12
  2. package/dist/components/blocks/cards/blogpost-card.d.ts +9 -4
  3. package/dist/components/blocks/cards/blogpost-card.js +37 -23
  4. package/dist/components/blocks/cards/blogpost-card.js.map +1 -1
  5. package/dist/components/blocks/cards/card.js +1 -1
  6. package/dist/components/blocks/cards/card.js.map +1 -1
  7. package/dist/components/blocks/empty-state/EmptyState.d.ts +15 -0
  8. package/dist/components/blocks/empty-state/EmptyState.js +36 -0
  9. package/dist/components/blocks/empty-state/EmptyState.js.map +1 -0
  10. package/dist/components/blocks/index.d.ts +2 -0
  11. package/dist/components/blocks/index.js +4 -2
  12. package/dist/components/blocks/index.js.map +1 -1
  13. package/dist/components/blocks/post-list/post-filters.d.ts +19 -0
  14. package/dist/components/blocks/post-list/post-filters.js +99 -0
  15. package/dist/components/blocks/post-list/post-filters.js.map +1 -0
  16. package/dist/components/blocks/post-list/post-list-with-filters.d.ts +19 -0
  17. package/dist/components/blocks/post-list/post-list-with-filters.js +439 -0
  18. package/dist/components/blocks/post-list/post-list-with-filters.js.map +1 -0
  19. package/dist/components/index.d.ts +42 -12
  20. package/dist/components/index.js +5 -6
  21. package/dist/components/index.js.map +1 -1
  22. package/dist/components/pages/admin/admin-page.d.ts +8 -0
  23. package/dist/components/pages/admin/admin-page.js +299 -0
  24. package/dist/components/pages/admin/admin-page.js.map +1 -0
  25. package/dist/components/pages/blogpost/blogpost.js +440 -0
  26. package/dist/components/pages/blogpost/blogpost.js.map +1 -0
  27. package/dist/components/pages/category/category-page.d.ts +8 -0
  28. package/dist/components/pages/category/category-page.js +69 -0
  29. package/dist/components/pages/category/category-page.js.map +1 -0
  30. package/dist/components/pages/chat/chat-page.d.ts +5 -0
  31. package/dist/components/pages/chat/chat-page.js +209 -0
  32. package/dist/components/pages/chat/chat-page.js.map +1 -0
  33. package/dist/components/pages/index.d.ts +11 -0
  34. package/dist/components/pages/index.js +11 -0
  35. package/dist/components/pages/index.js.map +1 -0
  36. package/dist/components/pages/login/login-page.d.ts +19 -0
  37. package/dist/components/pages/login/login-page.js +108 -0
  38. package/dist/components/pages/login/login-page.js.map +1 -0
  39. package/dist/components/pages/maintenance/maintenance-page.d.ts +5 -0
  40. package/dist/components/pages/maintenance/maintenance-page.js +50 -0
  41. package/dist/components/pages/maintenance/maintenance-page.js.map +1 -0
  42. package/dist/components/pages/not-found/not-found.d.ts +10 -0
  43. package/dist/components/pages/not-found/not-found.js +64 -0
  44. package/dist/components/pages/not-found/not-found.js.map +1 -0
  45. package/dist/components/pages/privacy/privacy-page.d.ts +15 -0
  46. package/dist/components/pages/privacy/privacy-page.js +98 -0
  47. package/dist/components/pages/privacy/privacy-page.js.map +1 -0
  48. package/dist/components/pages/search/search-page.d.ts +5 -0
  49. package/dist/components/pages/search/search-page.js +18 -0
  50. package/dist/components/pages/search/search-page.js.map +1 -0
  51. package/dist/components/pages/startpage/startpage.js +50 -0
  52. package/dist/components/pages/startpage/startpage.js.map +1 -0
  53. package/dist/components/pages/terms/terms-page.d.ts +15 -0
  54. package/dist/components/pages/terms/terms-page.js +98 -0
  55. package/dist/components/pages/terms/terms-page.js.map +1 -0
  56. package/dist/components/primitives/accordion/accordion.js +1 -1
  57. package/dist/components/primitives/accordion/accordion.js.map +1 -1
  58. package/dist/components/primitives/alert/alert.js +1 -1
  59. package/dist/components/primitives/alert/alert.js.map +1 -1
  60. package/dist/components/primitives/avatar/avatar.d.ts +14 -0
  61. package/dist/components/primitives/avatar/avatar.js +103 -0
  62. package/dist/components/primitives/avatar/avatar.js.map +1 -0
  63. package/dist/components/primitives/badge/badge.d.ts +1 -1
  64. package/dist/components/primitives/badge/badge.js +5 -5
  65. package/dist/components/primitives/badge/badge.js.map +1 -1
  66. package/dist/components/primitives/badge/badges.js +1 -1
  67. package/dist/components/primitives/badge/badges.js.map +1 -1
  68. package/dist/components/primitives/{button → buttons}/button.d.ts +8 -7
  69. package/dist/components/primitives/{button → buttons}/button.js +19 -14
  70. package/dist/components/primitives/buttons/button.js.map +1 -0
  71. package/dist/components/primitives/buttons/icon-button.d.ts +33 -0
  72. package/dist/components/primitives/buttons/icon-button.js +61 -0
  73. package/dist/components/primitives/buttons/icon-button.js.map +1 -0
  74. package/dist/components/primitives/{link → buttons}/link-button.d.ts +7 -4
  75. package/dist/components/primitives/buttons/link-button.js +35 -0
  76. package/dist/components/primitives/buttons/link-button.js.map +1 -0
  77. package/dist/components/primitives/collapsible/collapsible.d.ts +9 -0
  78. package/dist/components/primitives/collapsible/collapsible.js +53 -0
  79. package/dist/components/primitives/collapsible/collapsible.js.map +1 -0
  80. package/dist/components/primitives/dropdown-menu/dropdown-menu.d.ts +30 -0
  81. package/dist/components/primitives/dropdown-menu/dropdown-menu.js +164 -0
  82. package/dist/components/primitives/dropdown-menu/dropdown-menu.js.map +1 -0
  83. package/dist/components/primitives/forms/checkbox.d.ts +6 -0
  84. package/dist/components/primitives/forms/checkbox.js +30 -0
  85. package/dist/components/primitives/forms/checkbox.js.map +1 -0
  86. package/dist/components/primitives/forms/field.d.ts +29 -0
  87. package/dist/components/primitives/forms/field.js +218 -0
  88. package/dist/components/primitives/forms/field.js.map +1 -0
  89. package/dist/components/primitives/forms/input.d.ts +6 -0
  90. package/dist/components/primitives/forms/input.js +22 -0
  91. package/dist/components/primitives/forms/input.js.map +1 -0
  92. package/dist/components/primitives/forms/select.d.ts +22 -0
  93. package/dist/components/primitives/forms/select.js +169 -0
  94. package/dist/components/primitives/forms/select.js.map +1 -0
  95. package/dist/components/primitives/forms/textarea.d.ts +6 -0
  96. package/dist/components/primitives/forms/textarea.js +20 -0
  97. package/dist/components/primitives/forms/textarea.js.map +1 -0
  98. package/dist/components/primitives/icon/icon.d.ts +9 -2
  99. package/dist/components/primitives/icon/icon.js +10 -3
  100. package/dist/components/primitives/icon/icon.js.map +1 -1
  101. package/dist/components/primitives/index.d.ts +23 -7
  102. package/dist/components/primitives/index.js +31 -20
  103. package/dist/components/primitives/index.js.map +1 -1
  104. package/dist/components/primitives/label/label.d.ts +6 -0
  105. package/dist/components/primitives/label/label.js +22 -0
  106. package/dist/components/primitives/label/label.js.map +1 -0
  107. package/dist/components/primitives/layout/layout.d.ts +6 -3
  108. package/dist/components/primitives/layout/layout.js +28 -11
  109. package/dist/components/primitives/layout/layout.js.map +1 -1
  110. package/dist/components/primitives/link/link.d.ts +11 -5
  111. package/dist/components/primitives/link/link.js +38 -11
  112. package/dist/components/primitives/link/link.js.map +1 -1
  113. package/dist/components/primitives/separator/separator.js +1 -1
  114. package/dist/components/primitives/separator/separator.js.map +1 -1
  115. package/dist/components/primitives/sheet/sheet.d.ts +29 -0
  116. package/dist/components/primitives/sheet/sheet.js +117 -0
  117. package/dist/components/primitives/sheet/sheet.js.map +1 -0
  118. package/dist/components/primitives/skeleton/skeleton.js +1 -1
  119. package/dist/components/primitives/skeleton/skeleton.js.map +1 -1
  120. package/dist/components/primitives/sonner/sonner.d.ts +7 -0
  121. package/dist/components/primitives/sonner/sonner.js +42 -0
  122. package/dist/components/primitives/sonner/sonner.js.map +1 -0
  123. package/dist/components/primitives/sonner/use-toast.d.ts +24 -0
  124. package/dist/components/primitives/sonner/use-toast.js +21 -0
  125. package/dist/components/primitives/sonner/use-toast.js.map +1 -0
  126. package/dist/components/primitives/spinner/spinner.js +1 -1
  127. package/dist/components/primitives/spinner/spinner.js.map +1 -1
  128. package/dist/components/primitives/stack/stack.d.ts +3 -0
  129. package/dist/components/primitives/stack/stack.js +34 -4
  130. package/dist/components/primitives/stack/stack.js.map +1 -1
  131. package/dist/components/primitives/text/{text-heading.d.ts → heading.d.ts} +5 -5
  132. package/dist/components/primitives/text/{text-heading.js → heading.js} +11 -11
  133. package/dist/components/primitives/text/heading.js.map +1 -0
  134. package/dist/components/primitives/text/internal/text-element.d.ts +7 -3
  135. package/dist/components/primitives/text/internal/text-element.js +4 -2
  136. package/dist/components/primitives/text/internal/text-element.js.map +1 -1
  137. package/dist/components/primitives/text/text-code.d.ts +26 -0
  138. package/dist/components/primitives/text/text-code.js +44 -0
  139. package/dist/components/primitives/text/text-code.js.map +1 -0
  140. package/dist/components/primitives/text/text-div.js +2 -2
  141. package/dist/components/primitives/text/text-div.js.map +1 -1
  142. package/dist/components/primitives/text/text-span.js +2 -2
  143. package/dist/components/primitives/text/text-span.js.map +1 -1
  144. package/dist/components/primitives/text/text-time.js +2 -2
  145. package/dist/components/primitives/text/text-time.js.map +1 -1
  146. package/dist/components/primitives/text/{text-paragraph.d.ts → text.d.ts} +4 -4
  147. package/dist/components/primitives/text/{text-paragraph.js → text.js} +11 -11
  148. package/dist/components/primitives/text/text.js.map +1 -0
  149. package/dist/components/primitives/{ui-image.d.ts → ui-image/ui-image.d.ts} +1 -1
  150. package/dist/components/primitives/{ui-image.js → ui-image/ui-image.js} +3 -3
  151. package/dist/components/primitives/ui-image/ui-image.js.map +1 -0
  152. package/dist/components/primitives/ui-link/ui-link.d.ts +8 -0
  153. package/dist/components/primitives/ui-link/ui-link.js +19 -0
  154. package/dist/components/primitives/ui-link/ui-link.js.map +1 -0
  155. package/dist/components/providers/LinkContext.d.ts +1 -1
  156. package/dist/components/providers/LinkContext.js +1 -1
  157. package/dist/components/providers/LinkContext.js.map +1 -1
  158. package/dist/components/providers/SingularityContext.d.ts +4 -1
  159. package/dist/components/providers/SingularityContext.js +7 -3
  160. package/dist/components/providers/SingularityContext.js.map +1 -1
  161. package/dist/components/providers/auth-provider.d.ts +15 -0
  162. package/dist/components/providers/auth-provider.js +30 -0
  163. package/dist/components/providers/auth-provider.js.map +1 -0
  164. package/dist/components/providers/index.d.ts +3 -0
  165. package/dist/components/providers/index.js +5 -3
  166. package/dist/components/providers/index.js.map +1 -1
  167. package/dist/components/providers/theme-provider.d.ts +27 -0
  168. package/dist/components/providers/theme-provider.js +75 -0
  169. package/dist/components/providers/theme-provider.js.map +1 -0
  170. package/dist/components/templates/container/container.d.ts +20 -0
  171. package/dist/components/templates/container/container.js +58 -0
  172. package/dist/components/templates/container/container.js.map +1 -0
  173. package/dist/components/templates/footer/footer.d.ts +5 -0
  174. package/dist/components/templates/footer/footer.js +12 -0
  175. package/dist/components/templates/footer/footer.js.map +1 -0
  176. package/dist/components/templates/form/form.d.ts +5 -0
  177. package/dist/components/templates/form/form.js +141 -0
  178. package/dist/components/templates/form/form.js.map +1 -0
  179. package/dist/components/templates/hero/hero.d.ts +18 -0
  180. package/dist/components/{sections → templates}/hero/hero.js +52 -22
  181. package/dist/components/templates/hero/hero.js.map +1 -0
  182. package/dist/components/templates/index.d.ts +4 -2
  183. package/dist/components/templates/index.js +4 -2
  184. package/dist/components/templates/index.js.map +1 -1
  185. package/dist/components/templates/navigation/header.d.ts +19 -0
  186. package/dist/components/templates/navigation/header.js +222 -0
  187. package/dist/components/templates/navigation/header.js.map +1 -0
  188. package/dist/components/templates/navigation/index.d.ts +3 -0
  189. package/dist/components/templates/navigation/index.js +2 -0
  190. package/dist/components/templates/navigation/index.js.map +1 -0
  191. package/dist/css/variables.css +2 -2
  192. package/dist/css/variables.css.map +1 -1
  193. package/dist/data/authors.d.ts +12 -0
  194. package/dist/data/authors.js +33 -0
  195. package/dist/data/authors.js.map +1 -0
  196. package/dist/data/posts.d.ts +5 -3
  197. package/dist/data/posts.js +66 -47
  198. package/dist/data/posts.js.map +1 -1
  199. package/dist/index.d.ts +42 -12
  200. package/dist/index.js +1 -1
  201. package/dist/index.js.map +1 -1
  202. package/dist/lib/helpers/index.js +1 -1
  203. package/dist/lib/helpers/index.js.map +1 -1
  204. package/dist/lib/index.js +2 -2
  205. package/dist/lib/index.js.map +1 -1
  206. package/dist/lib/types.d.ts +4 -8
  207. package/dist/main.css +1528 -85
  208. package/dist/main.css.map +1 -1
  209. package/dist/{utils.js → utils/index.js} +1 -1
  210. package/dist/utils/index.js.map +1 -0
  211. package/dist/utils/index.test.js +37 -0
  212. package/dist/utils/index.test.js.map +1 -0
  213. package/package.json +69 -44
  214. package/dist/components/primitives/button/button.js.map +0 -1
  215. package/dist/components/primitives/link/link-button.js +0 -21
  216. package/dist/components/primitives/link/link-button.js.map +0 -1
  217. package/dist/components/primitives/text/text-heading.js.map +0 -1
  218. package/dist/components/primitives/text/text-paragraph.js.map +0 -1
  219. package/dist/components/primitives/ui-image.js.map +0 -1
  220. package/dist/components/primitives/ui-link.d.ts +0 -8
  221. package/dist/components/primitives/ui-link.js +0 -16
  222. package/dist/components/primitives/ui-link.js.map +0 -1
  223. package/dist/components/sections/body/body.d.ts +0 -19
  224. package/dist/components/sections/body/body.js +0 -49
  225. package/dist/components/sections/body/body.js.map +0 -1
  226. package/dist/components/sections/footer/footer.d.ts +0 -12
  227. package/dist/components/sections/footer/footer.js +0 -59
  228. package/dist/components/sections/footer/footer.js.map +0 -1
  229. package/dist/components/sections/hero/hero.d.ts +0 -6
  230. package/dist/components/sections/hero/hero.js.map +0 -1
  231. package/dist/components/sections/index.d.ts +0 -3
  232. package/dist/components/sections/index.js +0 -4
  233. package/dist/components/sections/index.js.map +0 -1
  234. package/dist/components/templates/blogpost/blogpost.js +0 -173
  235. package/dist/components/templates/blogpost/blogpost.js.map +0 -1
  236. package/dist/components/templates/startpage/startpage.js +0 -48
  237. package/dist/components/templates/startpage/startpage.js.map +0 -1
  238. package/dist/components/units/index.js +0 -1
  239. package/dist/components/units/index.js.map +0 -1
  240. package/dist/utils.js.map +0 -1
  241. /package/dist/components/{templates → pages}/blogpost/blogpost.d.ts +0 -0
  242. /package/dist/components/{templates → pages}/startpage/startpage.d.ts +0 -0
  243. /package/dist/{utils.d.ts → utils/index.d.ts} +0 -0
  244. /package/dist/{components/units/index.d.ts → utils/index.test.d.ts} +0 -0
@@ -0,0 +1,440 @@
1
+ "use client";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import { useMemo, useState } from "react";
4
+ import DOMPurify from "isomorphic-dompurify";
5
+ import { mockComments, posts } from "../../../data/posts.js";
6
+ import {
7
+ Button,
8
+ Layout,
9
+ Link,
10
+ TextTime,
11
+ UiImage,
12
+ Badge,
13
+ Badges,
14
+ Icon,
15
+ Textarea,
16
+ Input,
17
+ Heading,
18
+ Text,
19
+ TextSpan
20
+ } from "../../primitives/index.js";
21
+ import { ArrowLeft, ArrowRight } from "lucide-react";
22
+ import EmptyState from "../../blocks/empty-state/EmptyState.js";
23
+ import { useToast } from "../../primitives/sonner/use-toast.js";
24
+ import { authors } from "../../../data/authors.js";
25
+ import {
26
+ Avatar,
27
+ AvatarFallback,
28
+ AvatarImage
29
+ } from "../../primitives/avatar/avatar.js";
30
+ import BlogPostCard from "../../blocks/cards/blogpost-card.js";
31
+ function BlogPost() {
32
+ const postId = 1;
33
+ const post = posts.find((p) => p.id === postId);
34
+ const postIndex = posts.findIndex((p) => p.id === postId);
35
+ const prevPost = postIndex > 0 ? posts[postIndex - 1] : null;
36
+ const nextPost = postIndex < posts.length - 1 ? posts[postIndex + 1] : null;
37
+ const isLoggedIn = true;
38
+ const { toast } = useToast();
39
+ const [comments, setComments] = useState(mockComments);
40
+ const [name, setName] = useState("");
41
+ const [text, setText] = useState("");
42
+ const [hasLiked, setHasLiked] = useState(false);
43
+ const [likes, setLikes] = useState(0);
44
+ const [isGenerating, setIsGenerating] = useState(false);
45
+ const [isValidate, setIsValidate] = useState(false);
46
+ const relatedPosts = useMemo(() => {
47
+ if (!post) return [];
48
+ return posts.filter(
49
+ (p) => p.id !== post.id && p.categories.some((c) => post.categories.includes(c))
50
+ ).slice(0, 3);
51
+ }, [post]);
52
+ if (!post) {
53
+ return /* @__PURE__ */ jsx(Layout, { children: /* @__PURE__ */ jsx(Layout.Col1, { hideDiv: true, children: /* @__PURE__ */ jsx(
54
+ EmptyState,
55
+ {
56
+ icon: "BookOpen",
57
+ title: "Post not found",
58
+ description: "This post may have been removed or the link is incorrect.",
59
+ actionLabel: "Browse all posts",
60
+ actionTo: "/posts",
61
+ className: "min-h-[60vh]"
62
+ }
63
+ ) }) });
64
+ }
65
+ const handleLike = () => {
66
+ if (!isLoggedIn) return;
67
+ if (hasLiked) {
68
+ setLikes((l) => l - 1);
69
+ setHasLiked(false);
70
+ } else {
71
+ setLikes((l) => l + 1);
72
+ setHasLiked(true);
73
+ }
74
+ };
75
+ const handleGenerateImage = () => {
76
+ setIsGenerating(true);
77
+ setTimeout(() => {
78
+ setIsGenerating(false);
79
+ }, 1e3);
80
+ toast.message("Generating image\u2026", {
81
+ description: "A new AI image is being created for this post.",
82
+ dismissible: true,
83
+ icon: /* @__PURE__ */ jsx(Icon, { icon: "ImagePlus" })
84
+ });
85
+ };
86
+ const handleValidate = () => {
87
+ setIsValidate(true);
88
+ setTimeout(() => {
89
+ setIsValidate(false);
90
+ }, 1e3);
91
+ toast.message("Post validated", {
92
+ description: "Content has been reviewed.",
93
+ icon: /* @__PURE__ */ jsx(Icon, { icon: "Check" })
94
+ });
95
+ };
96
+ const handleSubmit = (e) => {
97
+ e.preventDefault();
98
+ if (!name.trim() || !text.trim()) return;
99
+ setComments((prev) => [
100
+ ...prev,
101
+ {
102
+ id: Date.now().toString(),
103
+ author: name,
104
+ text,
105
+ date: (/* @__PURE__ */ new Date()).toISOString().slice(0, 10)
106
+ }
107
+ ]);
108
+ setName("");
109
+ setText("");
110
+ };
111
+ const renderBody = (body) => {
112
+ return body.split("\n\n").map((block, i) => {
113
+ if (block.startsWith("## ")) {
114
+ return /* @__PURE__ */ jsx(Heading, { variant: "h2", className: "sg:mt-8 sg:mb-4", children: block.replace("## ", "") }, i);
115
+ }
116
+ if (block.startsWith("1. ") || block.startsWith("- ")) {
117
+ const items = block.split("\n").map((line) => line.replace(/^(\d+\.\s|-\s)/, ""));
118
+ const isOrdered = block.startsWith("1.");
119
+ const Tag = isOrdered ? "ol" : "ul";
120
+ return /* @__PURE__ */ jsx(
121
+ Tag,
122
+ {
123
+ className: `sg:my-4 sg:ml-6 sg:space-y-2 ${isOrdered ? "sg:list-decimal" : "sg:list-disc"}`,
124
+ children: items.map((item, j) => /* @__PURE__ */ jsx(
125
+ "li",
126
+ {
127
+ className: "sg:text-muted-foreground",
128
+ dangerouslySetInnerHTML: {
129
+ __html: DOMPurify.sanitize(
130
+ item.replace(
131
+ /\*\*(.*?)\*\*/g,
132
+ '<strong class="text-foreground">$1</strong>'
133
+ )
134
+ )
135
+ }
136
+ },
137
+ j
138
+ ))
139
+ },
140
+ i
141
+ );
142
+ }
143
+ return /* @__PURE__ */ jsx(
144
+ Text,
145
+ {
146
+ className: "sg:my-4",
147
+ foreground: "muted-foreground",
148
+ dangerouslySetInnerHTML: {
149
+ __html: DOMPurify.sanitize(
150
+ block.replace(
151
+ /\*\*(.*?)\*\*/g,
152
+ '<strong class="sg:text-foreground">$1</strong>'
153
+ )
154
+ )
155
+ }
156
+ },
157
+ i
158
+ );
159
+ });
160
+ };
161
+ const mockedAuthor = authors[0];
162
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
163
+ /* @__PURE__ */ jsx(Layout, { type: "container", children: /* @__PURE__ */ jsx(Layout.Col1, { className: "sg:w-full sg:h-64 sg:md:h-96 sg:overflow-hidden", children: /* @__PURE__ */ jsx(
164
+ UiImage,
165
+ {
166
+ src: post.primaryImage || post.originalImage || "",
167
+ alt: post.title,
168
+ className: "sg:w-full sg:h-full sg:object-cover"
169
+ }
170
+ ) }) }),
171
+ /* @__PURE__ */ jsx(Layout, { type: "col", className: "sg:py-12", as: "article", children: /* @__PURE__ */ jsxs(Layout.Col1, { hideDiv: true, children: [
172
+ /* @__PURE__ */ jsxs("div", { className: "sg:flex sg:flex-col sg:gap-6 sg:items-start", children: [
173
+ /* @__PURE__ */ jsx(Link, { to: "/posts", iconStart: "ArrowLeft", children: "Back to all posts" }),
174
+ /* @__PURE__ */ jsxs(TextTime, { size: "sm", foreground: "muted-foreground", children: [
175
+ post.date,
176
+ " \xB7 ",
177
+ post.author
178
+ ] })
179
+ ] }),
180
+ /* @__PURE__ */ jsx(Heading, { variant: "h1", className: "sg:mt-2", children: post.title }),
181
+ post.categories.length > 0 && /* @__PURE__ */ jsx(Badges, { className: "sg:mt-4", children: post.categories.map((cat) => /* @__PURE__ */ jsx(Badge, { variant: "secondary", children: cat }, cat)) }),
182
+ /* @__PURE__ */ jsx(
183
+ Text,
184
+ {
185
+ size: "lg",
186
+ foreground: "muted-foreground",
187
+ className: "sg:mt-4 sg:italic",
188
+ children: post.excerpt
189
+ }
190
+ ),
191
+ /* @__PURE__ */ jsxs("div", { className: "sg:mt-6 sg:flex sg:items-center sg:gap-3 sg:flex-wrap", children: [
192
+ /* @__PURE__ */ jsx(
193
+ Button,
194
+ {
195
+ onClick: handleLike,
196
+ disabled: !isLoggedIn,
197
+ variant: "outline",
198
+ size: "sm",
199
+ iconStart: "Heart",
200
+ iconStartFill: hasLiked,
201
+ title: isLoggedIn ? hasLiked ? "Unlike" : "Like this post" : "Log in to like",
202
+ children: likes
203
+ }
204
+ ),
205
+ isLoggedIn && /* @__PURE__ */ jsxs(Fragment, { children: [
206
+ /* @__PURE__ */ jsx(
207
+ Button,
208
+ {
209
+ variant: "outline",
210
+ iconStart: "ImagePlus",
211
+ size: "sm",
212
+ onClick: handleGenerateImage,
213
+ loading: isGenerating,
214
+ children: "Generate image"
215
+ }
216
+ ),
217
+ /* @__PURE__ */ jsx(
218
+ Button,
219
+ {
220
+ variant: "outline",
221
+ iconStart: "ShieldCheck",
222
+ size: "sm",
223
+ onClick: handleValidate,
224
+ loading: isValidate,
225
+ children: "Validate"
226
+ }
227
+ )
228
+ ] })
229
+ ] }),
230
+ /* @__PURE__ */ jsx("div", { className: "sg:mt-8 sg:border-t sg:pt-8", children: renderBody(post.content || "") }),
231
+ /* @__PURE__ */ jsx("div", { className: "sg:mt-12 sg:-mx-4 sg:md:-mx-8 sg:rounded-lg sg:overflow-hidden", children: /* @__PURE__ */ jsx(
232
+ UiImage,
233
+ {
234
+ src: (post.originalImage || "") + "&q=80&crop=entropy",
235
+ alt: `Visual for ${post.title}`,
236
+ className: "sg:w-full sg:h-56 sg:md:h-72 sg:object-cover",
237
+ loading: "lazy"
238
+ }
239
+ ) }),
240
+ (() => {
241
+ const authorData = mockedAuthor;
242
+ return /* @__PURE__ */ jsx("div", { className: "sg:mt-12 sg:border-t sg:pt-8", children: /* @__PURE__ */ jsxs(
243
+ Link,
244
+ {
245
+ variant: "no-decoration",
246
+ to: `/extras/authors/${authorData.slug}`,
247
+ className: "sg:group sg:flex sg:items-start sg:gap-4 sg:rounded-lg sg:border sg:bg-card sg:p-5 sg:hover:shadow-md sg:hover:border-primary/40 sg:transition-all",
248
+ children: [
249
+ /* @__PURE__ */ jsxs(Avatar, { className: "sg:h-14 sg:w-14 sg:mt-0.5", children: [
250
+ /* @__PURE__ */ jsx(
251
+ AvatarImage,
252
+ {
253
+ src: authorData.avatar,
254
+ alt: authorData.name
255
+ }
256
+ ),
257
+ /* @__PURE__ */ jsx(AvatarFallback, { children: authorData.name.split(" ").map((n) => n[0]).join("") })
258
+ ] }),
259
+ /* @__PURE__ */ jsxs("div", { className: "sg:min-w-0", children: [
260
+ /* @__PURE__ */ jsx(
261
+ TextSpan,
262
+ {
263
+ size: "xs",
264
+ foreground: "muted-foreground",
265
+ className: "sg:uppercase sg:tracking-wider sg:mb-1",
266
+ children: "Written by"
267
+ }
268
+ ),
269
+ /* @__PURE__ */ jsx(
270
+ Text,
271
+ {
272
+ size: "sm",
273
+ fontweight: "semibold",
274
+ className: "sg:font-display sg:group-hover:text-primary sg:transition-colors",
275
+ children: authorData.name
276
+ }
277
+ ),
278
+ /* @__PURE__ */ jsxs(
279
+ Text,
280
+ {
281
+ size: "sm",
282
+ foreground: "muted-foreground",
283
+ className: "sg:mt-0.5",
284
+ children: [
285
+ authorData.role,
286
+ " \xB7 ",
287
+ authorData.location
288
+ ]
289
+ }
290
+ ),
291
+ /* @__PURE__ */ jsx(
292
+ Text,
293
+ {
294
+ size: "sm",
295
+ foreground: "muted-foreground",
296
+ className: "sg:mt-2 sg:line-clamp-2",
297
+ children: authorData.bio
298
+ }
299
+ )
300
+ ] })
301
+ ]
302
+ }
303
+ ) });
304
+ })(),
305
+ /* @__PURE__ */ jsxs("nav", { className: "sg:mt-12 sg:border-t sg:pt-8 sg:grid sg:grid-cols-2 sg:gap-4", children: [
306
+ prevPost ? /* @__PURE__ */ jsxs(
307
+ Link,
308
+ {
309
+ variant: "no-decoration",
310
+ to: `/posts/${prevPost.id}`,
311
+ className: "sg:group sg:flex sg:flex-col sg:items-start sg:gap-1 sg:rounded-lg sg:border sg:border-border sg:p-4 sg:hover:border-primary sg:transition-colors sg:text-right",
312
+ "aria-label": `Previous post: ${prevPost.title}`,
313
+ title: `Previous post: ${prevPost.title}`,
314
+ children: [
315
+ /* @__PURE__ */ jsxs(
316
+ TextSpan,
317
+ {
318
+ size: "xs",
319
+ foreground: "muted-foreground",
320
+ className: "sg:flex sg:items-center sg:gap-1",
321
+ children: [
322
+ /* @__PURE__ */ jsx(ArrowLeft, { className: "h-3 w-3" }),
323
+ " Previous"
324
+ ]
325
+ }
326
+ ),
327
+ /* @__PURE__ */ jsx(
328
+ TextSpan,
329
+ {
330
+ size: "sm",
331
+ fontweight: "medium",
332
+ className: "sg:group-hover:text-primary sg:transition-colors sg:line-clamp-1 sg:text-start",
333
+ children: prevPost.title
334
+ }
335
+ )
336
+ ]
337
+ }
338
+ ) : /* @__PURE__ */ jsx("div", {}),
339
+ nextPost ? /* @__PURE__ */ jsxs(
340
+ Link,
341
+ {
342
+ variant: "no-decoration",
343
+ to: `/posts/${nextPost.id}`,
344
+ className: "sg:group sg:flex sg:flex-col sg:items-end sg:gap-1 sg:rounded-lg sg:border sg:border-border sg:p-4 sg:hover:border-primary sg:transition-colors sg:text-right",
345
+ "aria-label": `Next post: ${nextPost.title}`,
346
+ title: `Next post: ${nextPost.title}`,
347
+ children: [
348
+ /* @__PURE__ */ jsxs(
349
+ TextSpan,
350
+ {
351
+ size: "xs",
352
+ foreground: "muted-foreground",
353
+ className: "sg:flex sg:items-center sg:gap-1",
354
+ children: [
355
+ "Next ",
356
+ /* @__PURE__ */ jsx(ArrowRight, { className: "h-3 w-3" })
357
+ ]
358
+ }
359
+ ),
360
+ /* @__PURE__ */ jsx(
361
+ TextSpan,
362
+ {
363
+ size: "sm",
364
+ fontweight: "medium",
365
+ className: "sg:group-hover:text-primary sg:transition-colors sg:line-clamp-1",
366
+ children: nextPost.title
367
+ }
368
+ )
369
+ ]
370
+ }
371
+ ) : /* @__PURE__ */ jsx("div", {})
372
+ ] }),
373
+ /* @__PURE__ */ jsxs("section", { className: "sg:mt-16 sg:border-t sg:pt-8", children: [
374
+ /* @__PURE__ */ jsxs(Heading, { variant: "h3", className: "sg:mb-6", children: [
375
+ "Comments (",
376
+ comments.length,
377
+ ")"
378
+ ] }),
379
+ /* @__PURE__ */ jsx("div", { className: "sg:space-y-4 sg:mb-8", children: comments.map((c) => /* @__PURE__ */ jsxs("div", { className: "sg:rounded-lg sg:bg-accent sg:p-4", children: [
380
+ /* @__PURE__ */ jsxs("div", { className: "sg:flex sg:items-center sg:gap-2 sg:mb-1", children: [
381
+ /* @__PURE__ */ jsx(TextSpan, { fontweight: "medium", size: "sm", children: c.author }),
382
+ /* @__PURE__ */ jsx(
383
+ TextSpan,
384
+ {
385
+ fontweight: "medium",
386
+ size: "xs",
387
+ foreground: "muted-foreground",
388
+ children: c.date
389
+ }
390
+ )
391
+ ] }),
392
+ /* @__PURE__ */ jsx(Text, { size: "sm", foreground: "muted-foreground", children: c.text })
393
+ ] }, c.id)) }),
394
+ /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "sg:space-y-4", children: [
395
+ /* @__PURE__ */ jsx(Heading, { variant: "h4", children: "Leave a comment" }),
396
+ /* @__PURE__ */ jsx(
397
+ Input,
398
+ {
399
+ placeholder: "Your name",
400
+ value: name,
401
+ onChange: (e) => setName(e.target.value),
402
+ required: true,
403
+ "aria-label": "Your name"
404
+ }
405
+ ),
406
+ /* @__PURE__ */ jsx(
407
+ Textarea,
408
+ {
409
+ placeholder: "Write your comment...",
410
+ value: text,
411
+ onChange: (e) => setText(e.target.value),
412
+ required: true,
413
+ "aria-label": "Your comment"
414
+ }
415
+ ),
416
+ /* @__PURE__ */ jsx(Button, { type: "submit", children: "Post comment" })
417
+ ] })
418
+ ] }),
419
+ relatedPosts.length > 0 && /* @__PURE__ */ jsxs("section", { className: "sg:mt-16 sg:border-t sg:pt-8", children: [
420
+ /* @__PURE__ */ jsx(Heading, { variant: "h3", className: "sg:mb-6", children: "Related Posts" }),
421
+ /* @__PURE__ */ jsx("div", { className: "sg:grid sg:gap-6 sg:sm:grid-cols-2 lg:grid-cols-3", children: relatedPosts.map((p) => /* @__PURE__ */ jsx(
422
+ BlogPostCard,
423
+ {
424
+ id: post.id,
425
+ image: post.primaryImage,
426
+ categories: post.categories,
427
+ date: post.date,
428
+ title: post.title,
429
+ excerpt: post.excerpt
430
+ },
431
+ p.id
432
+ )) })
433
+ ] })
434
+ ] }) })
435
+ ] });
436
+ }
437
+ export {
438
+ BlogPost
439
+ };
440
+ //# sourceMappingURL=blogpost.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/components/pages/blogpost/blogpost.tsx"],"sourcesContent":["\"use client\";\nimport { useMemo, useState } from \"react\";\nimport DOMPurify from \"isomorphic-dompurify\";\nimport { mockComments, posts, type Comment } from \"../../../data/posts\";\nimport {\n Button,\n Layout,\n Link,\n TextTime,\n UiImage,\n Badge,\n Badges,\n Icon,\n Textarea,\n Input,\n Heading,\n Text,\n TextSpan,\n} from \"../../primitives/index\";\nimport { ArrowLeft, ArrowRight } from \"lucide-react\";\nimport EmptyState from \"../../blocks/empty-state/EmptyState\";\nimport { useToast } from \"../../primitives/sonner/use-toast\";\nimport { authors } from \"../../../data/authors\";\nimport {\n Avatar,\n AvatarFallback,\n AvatarImage,\n} from \"../../primitives/avatar/avatar\";\nimport BlogPostCard from \"../../blocks/cards/blogpost-card\";\n\nfunction BlogPost() {\n const postId = 1; // In a real app, this would come from the URL params\n\n const post = posts.find((p) => p.id === postId);\n const postIndex = posts.findIndex((p) => p.id === postId);\n const prevPost = postIndex > 0 ? posts[postIndex - 1] : null;\n const nextPost = postIndex < posts.length - 1 ? posts[postIndex + 1] : null;\n\n const isLoggedIn = true;\n const { toast } = useToast();\n\n const [comments, setComments] = useState<Comment[]>(mockComments);\n const [name, setName] = useState(\"\");\n const [text, setText] = useState(\"\");\n\n const [hasLiked, setHasLiked] = useState(false);\n const [likes, setLikes] = useState(0);\n\n const [isGenerating, setIsGenerating] = useState(false);\n const [isValidate, setIsValidate] = useState(false);\n\n const relatedPosts = useMemo(() => {\n if (!post) return [];\n return posts\n .filter(\n (p) =>\n p.id !== post.id &&\n p.categories.some((c) => post.categories.includes(c)),\n )\n .slice(0, 3);\n }, [post]);\n\n if (!post) {\n return (\n <Layout>\n <Layout.Col1 hideDiv>\n <EmptyState\n icon=\"BookOpen\"\n title=\"Post not found\"\n description=\"This post may have been removed or the link is incorrect.\"\n actionLabel=\"Browse all posts\"\n actionTo=\"/posts\"\n className=\"min-h-[60vh]\"\n />\n </Layout.Col1>\n </Layout>\n );\n }\n\n const handleLike = () => {\n if (!isLoggedIn) return;\n if (hasLiked) {\n setLikes((l) => l - 1);\n setHasLiked(false);\n } else {\n setLikes((l) => l + 1);\n setHasLiked(true);\n }\n };\n\n const handleGenerateImage = () => {\n setIsGenerating(true);\n setTimeout(() => {\n setIsGenerating(false);\n }, 1000);\n toast.message(\"Generating image…\", {\n description: \"A new AI image is being created for this post.\",\n dismissible: true,\n icon: <Icon icon=\"ImagePlus\" />,\n });\n };\n\n const handleValidate = () => {\n setIsValidate(true);\n setTimeout(() => {\n setIsValidate(false);\n }, 1000);\n toast.message(\"Post validated\", {\n description: \"Content has been reviewed.\",\n icon: <Icon icon=\"Check\" />,\n });\n };\n\n const handleSubmit = (e: React.FormEvent) => {\n e.preventDefault();\n if (!name.trim() || !text.trim()) return;\n setComments((prev) => [\n ...prev,\n {\n id: Date.now().toString(),\n author: name,\n text,\n date: new Date().toISOString().slice(0, 10),\n },\n ]);\n setName(\"\");\n setText(\"\");\n };\n\n // Simple markdown-ish rendering for content\n const renderBody = (body: string) => {\n return body.split(\"\\n\\n\").map((block, i) => {\n if (block.startsWith(\"## \")) {\n return (\n <Heading variant=\"h2\" key={i} className=\"sg:mt-8 sg:mb-4\">\n {block.replace(\"## \", \"\")}\n </Heading>\n );\n }\n if (block.startsWith(\"1. \") || block.startsWith(\"- \")) {\n const items = block\n .split(\"\\n\")\n .map((line) => line.replace(/^(\\d+\\.\\s|-\\s)/, \"\"));\n const isOrdered = block.startsWith(\"1.\");\n const Tag = isOrdered ? \"ol\" : \"ul\";\n\n return (\n <Tag\n key={i}\n className={`sg:my-4 sg:ml-6 sg:space-y-2 ${isOrdered ? \"sg:list-decimal\" : \"sg:list-disc\"}`}\n >\n {items.map((item, j) => (\n <li\n key={j}\n className=\"sg:text-muted-foreground\"\n dangerouslySetInnerHTML={{\n __html: DOMPurify.sanitize(\n item.replace(\n /\\*\\*(.*?)\\*\\*/g,\n '<strong class=\"text-foreground\">$1</strong>',\n ),\n ),\n }}\n />\n ))}\n </Tag>\n );\n }\n\n return (\n <Text\n key={i}\n className=\"sg:my-4\"\n foreground=\"muted-foreground\"\n dangerouslySetInnerHTML={{\n __html: DOMPurify.sanitize(\n block.replace(\n /\\*\\*(.*?)\\*\\*/g,\n '<strong class=\"sg:text-foreground\">$1</strong>',\n ),\n ),\n }}\n />\n );\n });\n };\n\n // Using a mocked author for now as PostGetDto lacks author info\n const mockedAuthor = authors[0];\n\n return (\n <>\n <Layout type=\"container\">\n <Layout.Col1 className=\"sg:w-full sg:h-64 sg:md:h-96 sg:overflow-hidden\">\n <UiImage\n src={post.primaryImage || post.originalImage || \"\"}\n alt={post.title}\n className=\"sg:w-full sg:h-full sg:object-cover\"\n />\n </Layout.Col1>\n </Layout>\n <Layout type=\"col\" className=\"sg:py-12\" as=\"article\">\n <Layout.Col1 hideDiv>\n <div className=\"sg:flex sg:flex-col sg:gap-6 sg:items-start\">\n <Link to=\"/posts\" iconStart=\"ArrowLeft\">\n Back to all posts\n </Link>\n\n <TextTime size=\"sm\" foreground=\"muted-foreground\">\n {post.date} · {post.author}\n </TextTime>\n </div>\n\n <Heading variant=\"h1\" className=\"sg:mt-2\">\n {post.title}\n </Heading>\n\n {post.categories.length > 0 && (\n <Badges className=\"sg:mt-4\">\n {post.categories.map((cat) => (\n <Badge key={cat} variant=\"secondary\">\n {cat}\n </Badge>\n ))}\n </Badges>\n )}\n\n <Text\n size=\"lg\"\n foreground=\"muted-foreground\"\n className=\"sg:mt-4 sg:italic\"\n >\n {post.excerpt}\n </Text>\n\n {/* Like + admin actions bar */}\n <div className=\"sg:mt-6 sg:flex sg:items-center sg:gap-3 sg:flex-wrap\">\n <Button\n onClick={handleLike}\n disabled={!isLoggedIn}\n variant=\"outline\"\n size=\"sm\"\n iconStart=\"Heart\"\n iconStartFill={hasLiked}\n title={\n isLoggedIn\n ? hasLiked\n ? \"Unlike\"\n : \"Like this post\"\n : \"Log in to like\"\n }\n >\n {likes}\n </Button>\n\n {isLoggedIn && (\n <>\n <Button\n variant=\"outline\"\n iconStart=\"ImagePlus\"\n size=\"sm\"\n onClick={handleGenerateImage}\n loading={isGenerating}\n >\n Generate image\n </Button>\n <Button\n variant=\"outline\"\n iconStart=\"ShieldCheck\"\n size=\"sm\"\n onClick={handleValidate}\n loading={isValidate}\n >\n Validate\n </Button>\n </>\n )}\n </div>\n\n <div className=\"sg:mt-8 sg:border-t sg:pt-8\">\n {renderBody(post.content || \"\")}\n </div>\n\n {/* Secondary image */}\n <div className=\"sg:mt-12 sg:-mx-4 sg:md:-mx-8 sg:rounded-lg sg:overflow-hidden\">\n <UiImage\n src={(post.originalImage || \"\") + \"&q=80&crop=entropy\"}\n alt={`Visual for ${post.title}`}\n className=\"sg:w-full sg:h-56 sg:md:h-72 sg:object-cover\"\n loading=\"lazy\"\n />\n </div>\n\n {/* Author card */}\n {(() => {\n const authorData = mockedAuthor;\n return (\n <div className=\"sg:mt-12 sg:border-t sg:pt-8\">\n <Link\n variant=\"no-decoration\"\n to={`/extras/authors/${authorData.slug}`}\n className=\"sg:group sg:flex sg:items-start sg:gap-4 sg:rounded-lg sg:border sg:bg-card sg:p-5 sg:hover:shadow-md sg:hover:border-primary/40 sg:transition-all\"\n >\n <Avatar className=\"sg:h-14 sg:w-14 sg:mt-0.5\">\n <AvatarImage\n src={authorData.avatar}\n alt={authorData.name}\n />\n <AvatarFallback>\n {authorData.name\n .split(\" \")\n .map((n) => n[0])\n .join(\"\")}\n </AvatarFallback>\n </Avatar>\n <div className=\"sg:min-w-0\">\n <TextSpan\n size=\"xs\"\n foreground=\"muted-foreground\"\n className=\"sg:uppercase sg:tracking-wider sg:mb-1\"\n >\n Written by\n </TextSpan>\n <Text\n size=\"sm\"\n fontweight=\"semibold\"\n className=\"sg:font-display sg:group-hover:text-primary sg:transition-colors\"\n >\n {authorData.name}\n </Text>\n <Text\n size=\"sm\"\n foreground=\"muted-foreground\"\n className=\"sg:mt-0.5\"\n >\n {authorData.role} · {authorData.location}\n </Text>\n <Text\n size=\"sm\"\n foreground=\"muted-foreground\"\n className=\"sg:mt-2 sg:line-clamp-2\"\n >\n {authorData.bio}\n </Text>\n </div>\n </Link>\n </div>\n );\n })()}\n\n {/* Prev / Next navigation */}\n <nav className=\"sg:mt-12 sg:border-t sg:pt-8 sg:grid sg:grid-cols-2 sg:gap-4\">\n {prevPost ? (\n <Link\n variant=\"no-decoration\"\n to={`/posts/${prevPost.id}`}\n className=\"sg:group sg:flex sg:flex-col sg:items-start sg:gap-1 sg:rounded-lg sg:border sg:border-border sg:p-4 sg:hover:border-primary sg:transition-colors sg:text-right\"\n aria-label={`Previous post: ${prevPost.title}`}\n title={`Previous post: ${prevPost.title}`}\n >\n <TextSpan\n size=\"xs\"\n foreground=\"muted-foreground\"\n className=\"sg:flex sg:items-center sg:gap-1\"\n >\n <ArrowLeft className=\"h-3 w-3\" /> Previous\n </TextSpan>\n <TextSpan\n size=\"sm\"\n fontweight=\"medium\"\n className=\"sg:group-hover:text-primary sg:transition-colors sg:line-clamp-1 sg:text-start\"\n >\n {prevPost.title}\n </TextSpan>\n </Link>\n ) : (\n <div />\n )}\n {nextPost ? (\n <Link\n variant=\"no-decoration\"\n to={`/posts/${nextPost.id}`}\n className=\"sg:group sg:flex sg:flex-col sg:items-end sg:gap-1 sg:rounded-lg sg:border sg:border-border sg:p-4 sg:hover:border-primary sg:transition-colors sg:text-right\"\n aria-label={`Next post: ${nextPost.title}`}\n title={`Next post: ${nextPost.title}`}\n >\n <TextSpan\n size=\"xs\"\n foreground=\"muted-foreground\"\n className=\"sg:flex sg:items-center sg:gap-1\"\n >\n Next <ArrowRight className=\"h-3 w-3\" />\n </TextSpan>\n <TextSpan\n size=\"sm\"\n fontweight=\"medium\"\n className=\"sg:group-hover:text-primary sg:transition-colors sg:line-clamp-1\"\n >\n {nextPost.title}\n </TextSpan>\n </Link>\n ) : (\n <div />\n )}\n </nav>\n\n {/* Comments */}\n <section className=\"sg:mt-16 sg:border-t sg:pt-8\">\n <Heading variant=\"h3\" className=\"sg:mb-6\">\n Comments ({comments.length})\n </Heading>\n\n <div className=\"sg:space-y-4 sg:mb-8\">\n {comments.map((c) => (\n <div key={c.id} className=\"sg:rounded-lg sg:bg-accent sg:p-4\">\n <div className=\"sg:flex sg:items-center sg:gap-2 sg:mb-1\">\n <TextSpan fontweight=\"medium\" size=\"sm\">\n {c.author}\n </TextSpan>\n <TextSpan\n fontweight=\"medium\"\n size=\"xs\"\n foreground=\"muted-foreground\"\n >\n {c.date}\n </TextSpan>\n </div>\n <Text size=\"sm\" foreground=\"muted-foreground\">\n {c.text}\n </Text>\n </div>\n ))}\n </div>\n\n <form onSubmit={handleSubmit} className=\"sg:space-y-4\">\n <Heading variant=\"h4\">Leave a comment</Heading>\n <Input\n placeholder=\"Your name\"\n value={name}\n onChange={(e) => setName(e.target.value)}\n required\n aria-label=\"Your name\"\n />\n <Textarea\n placeholder=\"Write your comment...\"\n value={text}\n onChange={(e) => setText(e.target.value)}\n required\n aria-label=\"Your comment\"\n />\n <Button type=\"submit\">Post comment</Button>\n </form>\n </section>\n\n {/* Related Posts */}\n {relatedPosts.length > 0 && (\n <section className=\"sg:mt-16 sg:border-t sg:pt-8\">\n <Heading variant=\"h3\" className=\"sg:mb-6\">\n Related Posts\n </Heading>\n <div className=\"sg:grid sg:gap-6 sg:sm:grid-cols-2 lg:grid-cols-3\">\n {relatedPosts.map((p) => (\n <BlogPostCard\n key={p.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 </div>\n </section>\n )}\n </Layout.Col1>\n </Layout>\n </>\n );\n}\n\nexport { BlogPost };\n"],"mappings":"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","names":[]}
@@ -0,0 +1,8 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ interface Props {
4
+ category?: string;
5
+ }
6
+ declare function CategoryPage({ category: propCategory }: Props): react_jsx_runtime.JSX.Element;
7
+
8
+ export { CategoryPage };
@@ -0,0 +1,69 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import { useMemo } from "react";
4
+ import { motion } from "framer-motion";
5
+ import { Layout, Heading, Text } from "../../primitives/index.js";
6
+ import { LinkButton } from "../../primitives/buttons/link-button.js";
7
+ import { posts } from "../../../data/posts.js";
8
+ import { PostListWithFilters } from "../../blocks/post-list/post-list-with-filters.js";
9
+ import EmptyState from "../../blocks/empty-state/EmptyState.js";
10
+ function CategoryPage({ category: propCategory }) {
11
+ const category = propCategory || "Design";
12
+ const decodedCategory = decodeURIComponent(category);
13
+ const categoryPosts = useMemo(
14
+ () => posts.filter((p) => p.categories.includes(decodedCategory)),
15
+ [decodedCategory]
16
+ );
17
+ if (!decodedCategory || categoryPosts.length === 0) {
18
+ return /* @__PURE__ */ jsx(Layout, { type: "col", className: "sg:py-16", children: /* @__PURE__ */ jsx(Layout.Col1, { hideDiv: true, children: /* @__PURE__ */ jsx(
19
+ EmptyState,
20
+ {
21
+ icon: "Tag",
22
+ title: "Category not found",
23
+ description: decodedCategory ? `No posts found in "${decodedCategory}". It may have been removed or renamed.` : "This category doesn't exist.",
24
+ actionLabel: "Browse all posts",
25
+ actionTo: "/posts",
26
+ className: "sg:min-h-[60vh]"
27
+ }
28
+ ) }) });
29
+ }
30
+ return /* @__PURE__ */ jsx(Layout, { type: "col", className: "sg:py-16", as: "main", children: /* @__PURE__ */ jsx(Layout.Col1, { hideDiv: true, children: /* @__PURE__ */ jsxs(
31
+ motion.div,
32
+ {
33
+ initial: { opacity: 0, y: 20 },
34
+ animate: { opacity: 1, y: 0 },
35
+ transition: { duration: 0.3 },
36
+ children: [
37
+ /* @__PURE__ */ jsx(
38
+ LinkButton,
39
+ {
40
+ variant: "ghost",
41
+ size: "sm",
42
+ to: "/posts",
43
+ iconStart: "ArrowLeft",
44
+ className: "sg:mb-6",
45
+ children: "All Posts"
46
+ }
47
+ ),
48
+ /* @__PURE__ */ jsx(Heading, { variant: "h1", className: "sg:mb-2 sg:capitalize", children: decodedCategory }),
49
+ /* @__PURE__ */ jsxs(Text, { foreground: "muted-foreground", className: "sg:mb-12", children: [
50
+ "Explore ",
51
+ categoryPosts.length,
52
+ " story in this category."
53
+ ] }),
54
+ /* @__PURE__ */ jsx(
55
+ PostListWithFilters,
56
+ {
57
+ posts: categoryPosts,
58
+ hideSearch: true,
59
+ filterMode: "drawer"
60
+ }
61
+ )
62
+ ]
63
+ }
64
+ ) }) });
65
+ }
66
+ export {
67
+ CategoryPage
68
+ };
69
+ //# sourceMappingURL=category-page.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/components/pages/category/category-page.tsx"],"sourcesContent":["\"use client\";\nimport { useMemo } from \"react\";\nimport { motion } from \"framer-motion\";\nimport { Layout, Heading, Text } from \"../../primitives/index\";\nimport { LinkButton } from \"../../primitives/buttons/link-button\";\nimport { posts } from \"../../../data/posts\";\nimport { PostListWithFilters } from \"../../blocks/post-list/post-list-with-filters\";\nimport EmptyState from \"../../blocks/empty-state/EmptyState\";\n\ninterface Props {\n category?: string;\n}\n\nexport function CategoryPage({ category: propCategory }: Props) {\n // In a real app, this would come from useParams()\n // For the library/storybook, we allow passing it as a prop\n const category = propCategory || \"Design\";\n const decodedCategory = decodeURIComponent(category);\n\n const categoryPosts = useMemo(\n () => posts.filter((p) => p.categories.includes(decodedCategory)),\n [decodedCategory],\n );\n\n if (!decodedCategory || categoryPosts.length === 0) {\n return (\n <Layout type=\"col\" className=\"sg:py-16\">\n <Layout.Col1 hideDiv>\n <EmptyState\n icon=\"Tag\"\n title=\"Category not found\"\n description={\n decodedCategory\n ? `No posts found in \"${decodedCategory}\". It may have been removed or renamed.`\n : \"This category doesn't exist.\"\n }\n actionLabel=\"Browse all posts\"\n actionTo=\"/posts\"\n className=\"sg:min-h-[60vh]\"\n />\n </Layout.Col1>\n </Layout>\n );\n }\n\n return (\n <Layout type=\"col\" className=\"sg:py-16\" as=\"main\">\n <Layout.Col1 hideDiv>\n <motion.div\n initial={{ opacity: 0, y: 20 }}\n animate={{ opacity: 1, y: 0 }}\n transition={{ duration: 0.3 }}\n >\n <LinkButton\n variant=\"ghost\"\n size=\"sm\"\n to=\"/posts\"\n iconStart=\"ArrowLeft\"\n className=\"sg:mb-6\"\n >\n All Posts\n </LinkButton>\n\n <Heading variant=\"h1\" className=\"sg:mb-2 sg:capitalize\">\n {decodedCategory}\n </Heading>\n <Text foreground=\"muted-foreground\" className=\"sg:mb-12\">\n Explore {categoryPosts.length} story in this category.\n </Text>\n\n <PostListWithFilters\n posts={categoryPosts}\n hideSearch\n filterMode=\"drawer\"\n />\n </motion.div>\n </Layout.Col1>\n </Layout>\n );\n}\n"],"mappings":";AA4BU,cAsCA,YAtCA;AA3BV,SAAS,eAAe;AACxB,SAAS,cAAc;AACvB,SAAS,QAAQ,SAAS,YAAY;AACtC,SAAS,kBAAkB;AAC3B,SAAS,aAAa;AACtB,SAAS,2BAA2B;AACpC,OAAO,gBAAgB;AAMhB,SAAS,aAAa,EAAE,UAAU,aAAa,GAAU;AAG9D,QAAM,WAAW,gBAAgB;AACjC,QAAM,kBAAkB,mBAAmB,QAAQ;AAEnD,QAAM,gBAAgB;AAAA,IACpB,MAAM,MAAM,OAAO,CAAC,MAAM,EAAE,WAAW,SAAS,eAAe,CAAC;AAAA,IAChE,CAAC,eAAe;AAAA,EAClB;AAEA,MAAI,CAAC,mBAAmB,cAAc,WAAW,GAAG;AAClD,WACE,oBAAC,UAAO,MAAK,OAAM,WAAU,YAC3B,8BAAC,OAAO,MAAP,EAAY,SAAO,MAClB;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,OAAM;AAAA,QACN,aACE,kBACI,sBAAsB,eAAe,4CACrC;AAAA,QAEN,aAAY;AAAA,QACZ,UAAS;AAAA,QACT,WAAU;AAAA;AAAA,IACZ,GACF,GACF;AAAA,EAEJ;AAEA,SACE,oBAAC,UAAO,MAAK,OAAM,WAAU,YAAW,IAAG,QACzC,8BAAC,OAAO,MAAP,EAAY,SAAO,MAClB;AAAA,IAAC,OAAO;AAAA,IAAP;AAAA,MACC,SAAS,EAAE,SAAS,GAAG,GAAG,GAAG;AAAA,MAC7B,SAAS,EAAE,SAAS,GAAG,GAAG,EAAE;AAAA,MAC5B,YAAY,EAAE,UAAU,IAAI;AAAA,MAE5B;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,IAAG;AAAA,YACH,WAAU;AAAA,YACV,WAAU;AAAA,YACX;AAAA;AAAA,QAED;AAAA,QAEA,oBAAC,WAAQ,SAAQ,MAAK,WAAU,yBAC7B,2BACH;AAAA,QACA,qBAAC,QAAK,YAAW,oBAAmB,WAAU,YAAW;AAAA;AAAA,UAC9C,cAAc;AAAA,UAAO;AAAA,WAChC;AAAA,QAEA;AAAA,UAAC;AAAA;AAAA,YACC,OAAO;AAAA,YACP,YAAU;AAAA,YACV,YAAW;AAAA;AAAA,QACb;AAAA;AAAA;AAAA,EACF,GACF,GACF;AAEJ;","names":[]}
@@ -0,0 +1,5 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+
3
+ declare function ChatPage(): react_jsx_runtime.JSX.Element;
4
+
5
+ export { ChatPage };