@jant/core 0.3.24 → 0.3.26

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 (277) hide show
  1. package/dist/app.js +101 -571
  2. package/dist/client.js +1 -0
  3. package/dist/db/schema.js +1 -1
  4. package/dist/i18n/locales/en.js +1 -1
  5. package/dist/i18n/locales/zh-Hans.js +1 -1
  6. package/dist/i18n/locales/zh-Hant.js +1 -1
  7. package/dist/index.js +3 -9
  8. package/dist/lib/avatar-upload.js +134 -0
  9. package/dist/lib/config.js +39 -0
  10. package/dist/lib/constants.js +10 -9
  11. package/dist/lib/favicon.js +102 -0
  12. package/dist/lib/image.js +13 -17
  13. package/dist/lib/media-helpers.js +2 -2
  14. package/dist/lib/nav-reorder.js +1 -1
  15. package/dist/lib/navigation.js +48 -3
  16. package/dist/lib/pagination.js +44 -0
  17. package/dist/lib/render.js +16 -11
  18. package/dist/lib/schemas.js +34 -3
  19. package/dist/lib/theme.js +4 -4
  20. package/dist/lib/timeline.js +24 -48
  21. package/dist/lib/timezones.js +388 -0
  22. package/dist/lib/view.js +3 -3
  23. package/dist/routes/api/collections.js +124 -0
  24. package/dist/routes/api/nav-items.js +104 -0
  25. package/dist/routes/api/pages.js +91 -0
  26. package/dist/routes/api/posts.js +3 -3
  27. package/dist/routes/api/search.js +2 -2
  28. package/dist/routes/api/settings.js +68 -0
  29. package/dist/routes/api/upload.js +3 -3
  30. package/dist/routes/auth/reset.js +221 -0
  31. package/dist/routes/auth/setup.js +194 -0
  32. package/dist/routes/auth/signin.js +176 -0
  33. package/dist/routes/compose.js +48 -0
  34. package/dist/routes/dash/collections.js +24 -416
  35. package/dist/routes/dash/index.js +1 -1
  36. package/dist/routes/dash/media.js +13 -393
  37. package/dist/routes/dash/pages.js +112 -86
  38. package/dist/routes/dash/posts.js +3 -5
  39. package/dist/routes/dash/redirects.js +20 -14
  40. package/dist/routes/dash/settings.js +213 -518
  41. package/dist/routes/feed/rss.js +4 -3
  42. package/dist/routes/feed/sitemap.js +5 -3
  43. package/dist/routes/pages/archive.js +3 -6
  44. package/dist/routes/pages/collection.js +3 -6
  45. package/dist/routes/pages/collections.js +28 -0
  46. package/dist/routes/pages/featured.js +36 -0
  47. package/dist/routes/pages/home.js +33 -49
  48. package/dist/routes/pages/latest.js +45 -0
  49. package/dist/routes/pages/page.js +29 -32
  50. package/dist/routes/pages/post.js +3 -6
  51. package/dist/routes/pages/search.js +3 -6
  52. package/dist/services/page.js +5 -1
  53. package/dist/services/post.js +45 -31
  54. package/dist/services/search.js +1 -1
  55. package/dist/types/bindings.js +3 -0
  56. package/dist/types/config.js +147 -0
  57. package/dist/types/constants.js +27 -0
  58. package/dist/types/entities.js +3 -0
  59. package/dist/types/operations.js +3 -0
  60. package/dist/types/props.js +3 -0
  61. package/dist/types/views.js +5 -0
  62. package/dist/types.js +8 -111
  63. package/dist/{theme → ui}/color-themes.js +33 -33
  64. package/dist/ui/compose/ComposeDialog.js +467 -0
  65. package/dist/ui/compose/ComposePrompt.js +55 -0
  66. package/dist/{theme/components/TypeBadge.js → ui/dash/FormatBadge.js} +1 -2
  67. package/dist/{theme/components → ui/dash}/PageForm.js +21 -15
  68. package/dist/{theme/components → ui/dash}/PostForm.js +22 -43
  69. package/dist/{theme/components → ui/dash}/PostList.js +6 -6
  70. package/dist/{theme/components/VisibilityBadge.js → ui/dash/StatusBadge.js} +1 -2
  71. package/dist/ui/dash/collections/CollectionForm.js +152 -0
  72. package/dist/ui/dash/collections/CollectionsListContent.js +68 -0
  73. package/dist/ui/dash/collections/ViewCollectionContent.js +96 -0
  74. package/dist/{theme/components → ui/dash}/index.js +3 -6
  75. package/dist/ui/dash/media/MediaListContent.js +166 -0
  76. package/dist/ui/dash/media/ViewMediaContent.js +212 -0
  77. package/dist/ui/dash/pages/LinkFormContent.js +130 -0
  78. package/dist/ui/dash/pages/UnifiedPagesContent.js +193 -0
  79. package/dist/ui/dash/settings/AccountContent.js +209 -0
  80. package/dist/ui/dash/settings/AppearanceContent.js +259 -0
  81. package/dist/ui/dash/settings/GeneralContent.js +536 -0
  82. package/dist/ui/dash/settings/SettingsNav.js +41 -0
  83. package/dist/{themes/threads/timeline → ui/feed}/LinkCard.js +6 -2
  84. package/dist/{themes/threads/timeline → ui/feed}/NoteCard.js +11 -6
  85. package/dist/{themes/threads/timeline → ui/feed}/QuoteCard.js +10 -6
  86. package/dist/{themes/threads/timeline → ui/feed}/ThreadPreview.js +7 -9
  87. package/dist/ui/feed/TimelineFeed.js +41 -0
  88. package/dist/ui/feed/TimelineItem.js +27 -0
  89. package/dist/ui/font-themes.js +36 -0
  90. package/dist/{theme → ui}/layouts/BaseLayout.js +34 -2
  91. package/dist/{theme → ui}/layouts/DashLayout.js +0 -8
  92. package/dist/ui/layouts/SiteLayout.js +169 -0
  93. package/dist/{themes/threads → ui}/pages/ArchivePage.js +16 -14
  94. package/dist/{themes/threads → ui}/pages/CollectionPage.js +6 -1
  95. package/dist/ui/pages/CollectionsPage.js +76 -0
  96. package/dist/ui/pages/FeaturedPage.js +24 -0
  97. package/dist/ui/pages/HomePage.js +24 -0
  98. package/dist/{themes/threads → ui}/pages/PostPage.js +13 -8
  99. package/dist/{themes/threads → ui}/pages/SearchPage.js +9 -7
  100. package/dist/{themes/threads → ui}/pages/SinglePage.js +3 -2
  101. package/dist/{theme/components → ui/shared}/MediaGallery.js +1 -1
  102. package/dist/{theme/components → ui/shared}/Pagination.js +41 -2
  103. package/dist/{theme/components → ui/shared}/ThreadView.js +2 -2
  104. package/dist/ui/shared/index.js +5 -0
  105. package/package.json +1 -9
  106. package/src/__tests__/helpers/db.ts +3 -0
  107. package/src/app.tsx +131 -561
  108. package/src/client.ts +1 -0
  109. package/src/db/migrations/0006_rename_slug_to_path.sql +5 -0
  110. package/src/db/migrations/meta/_journal.json +7 -0
  111. package/src/db/schema.ts +1 -1
  112. package/src/i18n/locales/en.po +477 -261
  113. package/src/i18n/locales/en.ts +1 -1
  114. package/src/i18n/locales/zh-Hans.po +477 -261
  115. package/src/i18n/locales/zh-Hans.ts +1 -1
  116. package/src/i18n/locales/zh-Hant.po +477 -261
  117. package/src/i18n/locales/zh-Hant.ts +1 -1
  118. package/src/index.ts +7 -36
  119. package/src/lib/__tests__/config.test.ts +192 -0
  120. package/src/lib/__tests__/favicon.test.ts +151 -0
  121. package/src/lib/__tests__/image.test.ts +2 -6
  122. package/src/lib/__tests__/schemas.test.ts +60 -19
  123. package/src/lib/__tests__/timeline.test.ts +45 -81
  124. package/src/lib/__tests__/timezones.test.ts +61 -0
  125. package/src/lib/__tests__/view.test.ts +15 -9
  126. package/src/lib/avatar-upload.ts +165 -0
  127. package/src/lib/config.ts +47 -0
  128. package/src/lib/constants.ts +19 -10
  129. package/src/lib/favicon.ts +115 -0
  130. package/src/lib/image.ts +13 -21
  131. package/src/lib/media-helpers.ts +2 -2
  132. package/src/lib/nav-reorder.ts +1 -1
  133. package/src/lib/navigation.ts +73 -4
  134. package/src/lib/pagination.ts +50 -0
  135. package/src/lib/render.tsx +22 -15
  136. package/src/lib/schemas.ts +47 -6
  137. package/src/lib/theme.ts +5 -5
  138. package/src/lib/timeline.ts +28 -57
  139. package/src/lib/timezones.ts +325 -0
  140. package/src/lib/view.ts +3 -3
  141. package/src/preset.css +2 -1
  142. package/src/routes/__tests__/compose.test.ts +199 -0
  143. package/src/routes/api/__tests__/collections.test.ts +249 -0
  144. package/src/routes/api/__tests__/nav-items.test.ts +222 -0
  145. package/src/routes/api/__tests__/pages.test.ts +218 -0
  146. package/src/routes/api/__tests__/settings.test.ts +132 -0
  147. package/src/routes/api/collections.ts +143 -0
  148. package/src/routes/api/nav-items.ts +115 -0
  149. package/src/routes/api/pages.ts +101 -0
  150. package/src/routes/api/posts.ts +3 -3
  151. package/src/routes/api/search.ts +2 -2
  152. package/src/routes/api/settings.ts +91 -0
  153. package/src/routes/api/upload.ts +2 -3
  154. package/src/routes/auth/reset.tsx +239 -0
  155. package/src/routes/auth/setup.tsx +189 -0
  156. package/src/routes/auth/signin.tsx +163 -0
  157. package/src/routes/compose.ts +63 -0
  158. package/src/routes/dash/__tests__/pages.test.ts +225 -0
  159. package/src/routes/dash/__tests__/settings-avatar.test.ts +89 -0
  160. package/src/routes/dash/collections.tsx +18 -367
  161. package/src/routes/dash/index.tsx +1 -1
  162. package/src/routes/dash/media.tsx +13 -415
  163. package/src/routes/dash/pages.tsx +131 -98
  164. package/src/routes/dash/posts.tsx +3 -7
  165. package/src/routes/dash/redirects.tsx +22 -16
  166. package/src/routes/dash/settings.tsx +265 -478
  167. package/src/routes/feed/__tests__/rss.test.ts +141 -0
  168. package/src/routes/feed/rss.ts +5 -3
  169. package/src/routes/feed/sitemap.ts +5 -3
  170. package/src/routes/pages/__tests__/collections.test.ts +94 -0
  171. package/src/routes/pages/__tests__/featured.test.ts +94 -0
  172. package/src/routes/pages/archive.tsx +2 -6
  173. package/src/routes/pages/collection.tsx +2 -6
  174. package/src/routes/pages/collections.tsx +36 -0
  175. package/src/routes/pages/featured.tsx +44 -0
  176. package/src/routes/pages/home.tsx +30 -53
  177. package/src/routes/pages/latest.tsx +59 -0
  178. package/src/routes/pages/page.tsx +28 -30
  179. package/src/routes/pages/post.tsx +2 -5
  180. package/src/routes/pages/search.tsx +2 -6
  181. package/src/services/__tests__/page.test.ts +106 -0
  182. package/src/services/__tests__/post.test.ts +114 -15
  183. package/src/services/page.ts +13 -1
  184. package/src/services/post.ts +58 -40
  185. package/src/services/search.ts +2 -2
  186. package/src/styles/components.css +0 -65
  187. package/src/styles/tokens.css +47 -0
  188. package/src/styles/ui.css +475 -0
  189. package/src/types/bindings.ts +30 -0
  190. package/src/types/config.ts +183 -0
  191. package/src/types/constants.ts +26 -0
  192. package/src/types/entities.ts +109 -0
  193. package/src/types/operations.ts +88 -0
  194. package/src/types/props.ts +115 -0
  195. package/src/types/views.ts +172 -0
  196. package/src/types.ts +8 -774
  197. package/src/ui/__tests__/font-themes.test.ts +34 -0
  198. package/src/{theme → ui}/color-themes.ts +34 -34
  199. package/src/ui/compose/ComposeDialog.tsx +414 -0
  200. package/src/ui/compose/ComposePrompt.tsx +55 -0
  201. package/src/{theme/components/TypeBadge.tsx → ui/dash/FormatBadge.tsx} +2 -3
  202. package/src/{theme/components → ui/dash}/PageForm.tsx +25 -19
  203. package/src/{theme/components → ui/dash}/PostForm.tsx +26 -45
  204. package/src/{theme/components → ui/dash}/PostList.tsx +7 -7
  205. package/src/{theme/components/VisibilityBadge.tsx → ui/dash/StatusBadge.tsx} +2 -3
  206. package/src/ui/dash/collections/CollectionForm.tsx +153 -0
  207. package/src/ui/dash/collections/CollectionsListContent.tsx +85 -0
  208. package/src/ui/dash/collections/ViewCollectionContent.tsx +92 -0
  209. package/src/ui/dash/index.ts +10 -0
  210. package/src/ui/dash/media/MediaListContent.tsx +201 -0
  211. package/src/ui/dash/media/ViewMediaContent.tsx +208 -0
  212. package/src/ui/dash/pages/LinkFormContent.tsx +119 -0
  213. package/src/ui/dash/pages/UnifiedPagesContent.tsx +203 -0
  214. package/src/ui/dash/settings/AccountContent.tsx +176 -0
  215. package/src/ui/dash/settings/AppearanceContent.tsx +254 -0
  216. package/src/ui/dash/settings/GeneralContent.tsx +533 -0
  217. package/src/ui/dash/settings/SettingsNav.tsx +56 -0
  218. package/src/{themes/threads/timeline → ui/feed}/LinkCard.tsx +9 -4
  219. package/src/{themes/threads/timeline → ui/feed}/NoteCard.tsx +13 -8
  220. package/src/{themes/threads/timeline → ui/feed}/QuoteCard.tsx +13 -8
  221. package/src/{themes/threads/timeline → ui/feed}/ThreadPreview.tsx +7 -8
  222. package/src/ui/feed/TimelineFeed.tsx +49 -0
  223. package/src/ui/feed/TimelineItem.tsx +45 -0
  224. package/src/ui/font-themes.ts +54 -0
  225. package/src/{theme → ui}/layouts/BaseLayout.tsx +28 -1
  226. package/src/{theme → ui}/layouts/DashLayout.tsx +0 -10
  227. package/src/ui/layouts/SiteLayout.tsx +164 -0
  228. package/src/{themes/threads → ui}/pages/ArchivePage.tsx +22 -17
  229. package/src/{themes/threads → ui}/pages/CollectionPage.tsx +14 -5
  230. package/src/ui/pages/CollectionsPage.tsx +73 -0
  231. package/src/ui/pages/FeaturedPage.tsx +31 -0
  232. package/src/{themes/threads → ui}/pages/HomePage.tsx +11 -15
  233. package/src/{themes/threads → ui}/pages/PostPage.tsx +23 -14
  234. package/src/{themes/threads → ui}/pages/SearchPage.tsx +13 -11
  235. package/src/{themes/threads → ui}/pages/SinglePage.tsx +4 -4
  236. package/src/{theme/components → ui/shared}/MediaGallery.tsx +1 -1
  237. package/src/{theme/components → ui/shared}/Pagination.tsx +67 -4
  238. package/src/{theme/components → ui/shared}/ThreadView.tsx +2 -2
  239. package/src/ui/shared/__tests__/pagination.test.ts +46 -0
  240. package/src/ui/shared/index.ts +12 -0
  241. package/bin/jant.js +0 -185
  242. package/dist/lib/theme-components.js +0 -46
  243. package/dist/routes/dash/navigation.js +0 -289
  244. package/dist/theme/index.js +0 -18
  245. package/dist/theme/layouts/index.js +0 -2
  246. package/dist/themes/threads/ThreadsSiteLayout.js +0 -172
  247. package/dist/themes/threads/index.js +0 -81
  248. package/dist/themes/threads/pages/HomePage.js +0 -25
  249. package/dist/themes/threads/timeline/TimelineFeed.js +0 -58
  250. package/dist/themes/threads/timeline/TimelineItem.js +0 -36
  251. package/dist/themes/threads/timeline/TimelineLoadMore.js +0 -23
  252. package/dist/themes/threads/timeline/groupByDate.js +0 -22
  253. package/dist/themes/threads/timeline/timelineMore.js +0 -107
  254. package/src/lib/__tests__/theme-components.test.ts +0 -105
  255. package/src/lib/theme-components.ts +0 -65
  256. package/src/routes/dash/navigation.tsx +0 -317
  257. package/src/theme/components/index.ts +0 -23
  258. package/src/theme/index.ts +0 -22
  259. package/src/theme/layouts/index.ts +0 -7
  260. package/src/themes/threads/ThreadsSiteLayout.tsx +0 -194
  261. package/src/themes/threads/index.ts +0 -100
  262. package/src/themes/threads/style.css +0 -336
  263. package/src/themes/threads/timeline/TimelineFeed.tsx +0 -62
  264. package/src/themes/threads/timeline/TimelineItem.tsx +0 -67
  265. package/src/themes/threads/timeline/TimelineLoadMore.tsx +0 -35
  266. package/src/themes/threads/timeline/groupByDate.ts +0 -30
  267. package/src/themes/threads/timeline/timelineMore.tsx +0 -130
  268. /package/dist/{theme/components → ui/dash}/ActionButtons.js +0 -0
  269. /package/dist/{theme/components → ui/dash}/CrudPageHeader.js +0 -0
  270. /package/dist/{theme/components → ui/dash}/DangerZone.js +0 -0
  271. /package/dist/{theme/components → ui/dash}/ListItemRow.js +0 -0
  272. /package/dist/{theme/components → ui/shared}/EmptyState.js +0 -0
  273. /package/src/{theme/components → ui/dash}/ActionButtons.tsx +0 -0
  274. /package/src/{theme/components → ui/dash}/CrudPageHeader.tsx +0 -0
  275. /package/src/{theme/components → ui/dash}/DangerZone.tsx +0 -0
  276. /package/src/{theme/components → ui/dash}/ListItemRow.tsx +0 -0
  277. /package/src/{theme/components → ui/shared}/EmptyState.tsx +0 -0
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Entity Types (database-level models)
3
+ */
4
+
5
+ import type { Format, Status, SortOrder, NavItemType } from "./constants.js";
6
+
7
+ export interface Post {
8
+ id: number;
9
+ format: Format;
10
+ status: Status;
11
+ featured: number; // 0 | 1
12
+ pinned: number; // 0 | 1
13
+ path: string | null;
14
+ title: string | null;
15
+ url: string | null;
16
+ body: string | null;
17
+ bodyHtml: string | null;
18
+ quoteText: string | null;
19
+ rating: number | null;
20
+ collectionId: number | null;
21
+ replyToId: number | null;
22
+ threadId: number | null;
23
+ deletedAt: number | null;
24
+ publishedAt: number;
25
+ createdAt: number;
26
+ updatedAt: number;
27
+ }
28
+
29
+ export interface Page {
30
+ id: number;
31
+ slug: string;
32
+ title: string | null;
33
+ body: string | null;
34
+ bodyHtml: string | null;
35
+ status: Status;
36
+ createdAt: number;
37
+ updatedAt: number;
38
+ }
39
+
40
+ export interface Media {
41
+ id: string; // UUIDv7
42
+ postId: number | null;
43
+ filename: string;
44
+ originalName: string;
45
+ mimeType: string;
46
+ size: number;
47
+ storageKey: string;
48
+ provider: string;
49
+ width: number | null;
50
+ height: number | null;
51
+ alt: string | null;
52
+ position: number;
53
+ blurhash: string | null;
54
+ createdAt: number;
55
+ }
56
+
57
+ export interface MediaAttachment {
58
+ id: string;
59
+ url: string;
60
+ previewUrl: string;
61
+ alt: string | null;
62
+ blurhash: string | null;
63
+ width: number | null;
64
+ height: number | null;
65
+ position: number;
66
+ mimeType: string;
67
+ }
68
+
69
+ export interface PostWithMedia extends Post {
70
+ mediaAttachments: MediaAttachment[];
71
+ }
72
+
73
+ export interface Collection {
74
+ id: number;
75
+ slug: string;
76
+ title: string;
77
+ description: string | null;
78
+ icon: string | null;
79
+ sortOrder: SortOrder;
80
+ position: number;
81
+ showDivider: number; // 0 | 1
82
+ createdAt: number;
83
+ updatedAt: number;
84
+ }
85
+
86
+ export interface NavItem {
87
+ id: number;
88
+ type: NavItemType;
89
+ label: string;
90
+ url: string;
91
+ pageId: number | null;
92
+ position: number;
93
+ createdAt: number;
94
+ updatedAt: number;
95
+ }
96
+
97
+ export interface Redirect {
98
+ id: number;
99
+ fromPath: string;
100
+ toPath: string;
101
+ type: 301 | 302;
102
+ createdAt: number;
103
+ }
104
+
105
+ export interface Setting {
106
+ key: string;
107
+ value: string;
108
+ updatedAt: number;
109
+ }
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Operation Types (create/update DTOs)
3
+ */
4
+
5
+ import type { Format, Status, SortOrder, NavItemType } from "./constants.js";
6
+
7
+ export interface CreatePost {
8
+ format: Format;
9
+ status?: Status;
10
+ featured?: boolean;
11
+ pinned?: boolean;
12
+ path?: string;
13
+ title?: string;
14
+ url?: string;
15
+ body?: string;
16
+ quoteText?: string;
17
+ rating?: number;
18
+ collectionId?: number;
19
+ replyToId?: number;
20
+ publishedAt?: number;
21
+ mediaIds?: string[];
22
+ }
23
+
24
+ export interface UpdatePost {
25
+ format?: Format;
26
+ status?: Status;
27
+ featured?: boolean;
28
+ pinned?: boolean;
29
+ path?: string | null;
30
+ title?: string | null;
31
+ url?: string | null;
32
+ body?: string | null;
33
+ quoteText?: string | null;
34
+ rating?: number | null;
35
+ collectionId?: number | null;
36
+ publishedAt?: number;
37
+ mediaIds?: string[];
38
+ }
39
+
40
+ export interface CreatePage {
41
+ slug: string;
42
+ title?: string;
43
+ body?: string;
44
+ status?: Status;
45
+ }
46
+
47
+ export interface UpdatePage {
48
+ slug?: string;
49
+ title?: string | null;
50
+ body?: string | null;
51
+ status?: Status;
52
+ }
53
+
54
+ export interface CreateNavItem {
55
+ type: NavItemType;
56
+ label: string;
57
+ url: string;
58
+ pageId?: number;
59
+ position?: number;
60
+ }
61
+
62
+ export interface UpdateNavItem {
63
+ type?: NavItemType;
64
+ label?: string;
65
+ url?: string;
66
+ pageId?: number | null;
67
+ position?: number;
68
+ }
69
+
70
+ export interface CreateCollection {
71
+ slug: string;
72
+ title: string;
73
+ description?: string;
74
+ icon?: string;
75
+ sortOrder?: SortOrder;
76
+ position?: number;
77
+ showDivider?: boolean;
78
+ }
79
+
80
+ export interface UpdateCollection {
81
+ slug?: string;
82
+ title?: string;
83
+ description?: string | null;
84
+ icon?: string | null;
85
+ sortOrder?: SortOrder;
86
+ position?: number;
87
+ showDivider?: boolean;
88
+ }
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Page-Level Props & Feed Data Types
3
+ */
4
+
5
+ import type { Format } from "./constants.js";
6
+ import type { Collection } from "./entities.js";
7
+ import type {
8
+ PostView,
9
+ PageView,
10
+ TimelineItemView,
11
+ SearchResultView,
12
+ ArchiveGroup,
13
+ } from "./views.js";
14
+
15
+ // =============================================================================
16
+ // Page-Level Props
17
+ // =============================================================================
18
+
19
+ /** Props for the home page component */
20
+ export interface HomePageProps {
21
+ items: TimelineItemView[];
22
+ pinnedItems: PostView[];
23
+ currentPage: number;
24
+ totalPages: number;
25
+ }
26
+
27
+ /** Props for the single post page component */
28
+ export interface PostPageProps {
29
+ post: PostView;
30
+ }
31
+
32
+ /** Props for the custom page component */
33
+ export interface SinglePageProps {
34
+ page: PageView;
35
+ }
36
+
37
+ /** Props for the featured page component */
38
+ export interface FeaturedPageProps {
39
+ items: TimelineItemView[];
40
+ }
41
+
42
+ /** Props for the archive page component */
43
+ export interface ArchivePageProps {
44
+ groups: ArchiveGroup[];
45
+ hasMore: boolean;
46
+ nextCursor?: number;
47
+ format?: Format;
48
+ featured?: boolean;
49
+ }
50
+
51
+ /** Props for the search page component */
52
+ export interface SearchPageProps {
53
+ query: string;
54
+ results: SearchResultView[];
55
+ error?: string;
56
+ hasMore: boolean;
57
+ page: number;
58
+ }
59
+
60
+ /** Props for the single collection page component */
61
+ export interface CollectionPageProps {
62
+ collection: Collection;
63
+ posts: PostView[];
64
+ hasMore: boolean;
65
+ nextCursor?: number;
66
+ }
67
+
68
+ /** Props for the collections list page component */
69
+ export interface CollectionsPageProps {
70
+ collections: (Collection & { postCount: number })[];
71
+ }
72
+
73
+ // =============================================================================
74
+ // Feed Data Types
75
+ // =============================================================================
76
+
77
+ /** Data passed to RSS/Atom feed renderers */
78
+ export interface FeedData {
79
+ siteName: string;
80
+ siteDescription: string;
81
+ siteUrl: string;
82
+ siteLanguage: string;
83
+ posts: PostView[];
84
+ }
85
+
86
+ /** Data passed to sitemap renderers */
87
+ export interface SitemapData {
88
+ siteUrl: string;
89
+ posts: PostView[];
90
+ pages: PageView[];
91
+ }
92
+
93
+ // =============================================================================
94
+ // Timeline Types
95
+ // =============================================================================
96
+
97
+ /** Props for per-type timeline cards */
98
+ export interface TimelineCardProps {
99
+ post: PostView;
100
+ compact?: boolean;
101
+ }
102
+
103
+ /** Props for thread inline preview */
104
+ export interface ThreadPreviewProps {
105
+ rootPost: PostView;
106
+ previewReplies: PostView[];
107
+ totalReplyCount: number;
108
+ }
109
+
110
+ /** Props for the timeline feed wrapper */
111
+ export interface TimelineFeedProps {
112
+ items: TimelineItemView[];
113
+ currentPage?: number;
114
+ totalPages?: number;
115
+ }
@@ -0,0 +1,172 @@
1
+ /**
2
+ * View Model Types (render-ready, for theme components)
3
+ */
4
+
5
+ import type { Format, Status, NavItemType } from "./constants.js";
6
+ import type { Post, Collection } from "./entities.js";
7
+
8
+ /**
9
+ * Render-ready post data for theme components.
10
+ * All fields are pre-computed -- no lib/ imports needed.
11
+ */
12
+ export interface PostView {
13
+ // Identity
14
+ id: number;
15
+ /** Pre-computed permalink: "/{path}" if path set, otherwise "/p/{sqid}" */
16
+ permalink: string;
17
+ /** Custom URL path, if set. Supports multi-level paths (e.g. "2024/my-post") */
18
+ path?: string;
19
+
20
+ // Content
21
+ title?: string;
22
+ /** Pre-sanitized HTML */
23
+ bodyHtml?: string;
24
+ /** Pre-computed excerpt, max 160 chars */
25
+ excerpt?: string;
26
+ /** HTML excerpt for article previews (paragraph-aware, ~500 chars) */
27
+ summaryHtml?: string;
28
+ /** Whether summaryHtml was truncated (content continues beyond excerpt) */
29
+ summaryHasMore?: boolean;
30
+ /** URL for link/quote formats */
31
+ url?: string;
32
+ /** Quoted text for quote format */
33
+ quoteText?: string;
34
+
35
+ // Metadata
36
+ format: Format;
37
+ status: Status;
38
+ featured: boolean;
39
+ pinned: boolean;
40
+ rating?: number;
41
+
42
+ // Collection
43
+ collectionId?: number;
44
+
45
+ // Time -- pre-formatted
46
+ /** ISO 8601 string */
47
+ publishedAt: string;
48
+ /** Human-readable, e.g. "Feb 1, 2024" */
49
+ publishedAtFormatted: string;
50
+ /** 24-hour time, e.g. "23:05" */
51
+ publishedAtTime: string;
52
+ /** Short relative time, e.g. "5m", "3h", "2d", "Feb 1" */
53
+ publishedAtRelative: string;
54
+ /** ISO 8601 string */
55
+ updatedAt: string;
56
+
57
+ // Media -- URLs pre-computed
58
+ media: MediaView[];
59
+
60
+ // Thread context
61
+ replyToId?: number;
62
+ threadRootId?: number;
63
+
64
+ // Raw content (for forms/editing, not typical theme use)
65
+ body?: string;
66
+ }
67
+
68
+ /**
69
+ * Render-ready page data for theme components.
70
+ */
71
+ export interface PageView {
72
+ id: number;
73
+ slug: string;
74
+ title?: string;
75
+ bodyHtml?: string;
76
+ status: Status;
77
+ createdAt: string;
78
+ updatedAt: string;
79
+ }
80
+
81
+ /**
82
+ * Render-ready media data for theme components.
83
+ * URLs are pre-computed -- no lib/ imports needed.
84
+ */
85
+ export interface MediaView {
86
+ id: string;
87
+ /** Full-size URL, pre-computed */
88
+ url: string;
89
+ /** Thumbnail URL, pre-computed */
90
+ thumbnailUrl: string;
91
+ mimeType: string;
92
+ altText?: string;
93
+ width?: number;
94
+ height?: number;
95
+ size?: number;
96
+ }
97
+
98
+ /**
99
+ * Render-ready navigation item for theme components.
100
+ * Active/external state pre-computed.
101
+ */
102
+ export interface NavItemView {
103
+ id: number;
104
+ type: NavItemType;
105
+ label: string;
106
+ url: string;
107
+ pageId?: number;
108
+ /** Pre-computed based on currentPath */
109
+ isActive: boolean;
110
+ /** Pre-computed: starts with http(s):// */
111
+ isExternal: boolean;
112
+ }
113
+
114
+ /**
115
+ * Search result from FTS5
116
+ */
117
+ export interface SearchResult {
118
+ post: Post;
119
+ /** FTS5 rank score (lower is better) */
120
+ rank: number;
121
+ /** Highlighted snippet from content */
122
+ snippet?: string;
123
+ }
124
+
125
+ /**
126
+ * Render-ready search result for theme components.
127
+ */
128
+ export interface SearchResultView {
129
+ post: PostView;
130
+ rank: number;
131
+ snippet?: string;
132
+ }
133
+
134
+ /**
135
+ * Render-ready timeline item for theme components.
136
+ */
137
+ export interface TimelineItemView {
138
+ post: PostView;
139
+ threadPreview?: {
140
+ replies: PostView[];
141
+ totalReplyCount: number;
142
+ };
143
+ }
144
+
145
+ /**
146
+ * Typed archive group with pre-formatted label.
147
+ */
148
+ export interface ArchiveGroup {
149
+ /** e.g. "2024" */
150
+ year: string;
151
+ /** e.g. "02" */
152
+ month: string;
153
+ /** Pre-formatted, e.g. "February 2024" */
154
+ label: string;
155
+ posts: PostView[];
156
+ }
157
+
158
+ /**
159
+ * Site Layout Props
160
+ */
161
+ export interface SiteLayoutProps {
162
+ siteName: string;
163
+ siteDescription?: string;
164
+ links: NavItemView[];
165
+ currentPath: string;
166
+ isAuthenticated?: boolean;
167
+ collections?: Collection[];
168
+ homeDefaultView?: string;
169
+ siteAvatarUrl?: string;
170
+ showHeaderAvatar?: boolean;
171
+ siteFooterHtml?: string;
172
+ }