@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
@@ -1,46 +0,0 @@
1
- /**
2
- * Theme Component Resolution
3
- *
4
- * Resolves theme-overridable components, falling back to defaults.
5
- */ const THEME_KEY_MAP = {
6
- note: "NoteCard",
7
- link: "LinkCard",
8
- quote: "QuoteCard"
9
- };
10
- /**
11
- * Generic component resolver.
12
- *
13
- * Looks up a component by key in `ThemeComponents` and falls back to the
14
- * provided default component.
15
- *
16
- * @param key - ThemeComponents key to look up
17
- * @param defaultComponent - Fallback component
18
- * @param themeComponents - Optional theme component overrides
19
- * @returns The resolved component
20
- *
21
- * @example
22
- * ```ts
23
- * const Gallery = resolveComponent("MediaGallery", DefaultMediaGallery, theme);
24
- * ```
25
- */ export function resolveComponent(key, defaultComponent, themeComponents) {
26
- return themeComponents?.[key] ?? defaultComponent;
27
- }
28
- /**
29
- * Resolves the card component for a given post format.
30
- *
31
- * Checks theme overrides first, then falls back to the provided default card component.
32
- *
33
- * @param format - The post format to resolve a card for
34
- * @param defaults - Map of format to default card component
35
- * @param themeComponents - Optional theme component overrides
36
- * @returns The resolved card component
37
- *
38
- * @example
39
- * ```ts
40
- * const Card = resolveCardComponent("note", DEFAULT_CARD_MAP, c.var.config.theme?.components);
41
- * ```
42
- */ export function resolveCardComponent(format, defaults, themeComponents) {
43
- const key = THEME_KEY_MAP[format];
44
- const override = themeComponents?.[key];
45
- return override ?? defaults[format];
46
- }
@@ -1,289 +0,0 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
2
- import { getSiteName } from "../../lib/config.js";
3
- /**
4
- * Dashboard Navigation Items Routes
5
- */ import { Hono } from "hono";
6
- import { useLingui as $_useLingui } from "@jant/core/i18n";
7
- import { DashLayout } from "../../theme/layouts/index.js";
8
- import { EmptyState, ListItemRow, ActionButtons, CrudPageHeader } from "../../theme/components/index.js";
9
- import { dsRedirect, dsToast } from "../../lib/sse.js";
10
- export const navigationRoutes = new Hono();
11
- function NavigationListContent({ items }) {
12
- const { i18n: $__i18n, _: $__ } = $_useLingui();
13
- return /*#__PURE__*/ _jsxs(_Fragment, {
14
- children: [
15
- /*#__PURE__*/ _jsx(CrudPageHeader, {
16
- title: $__i18n._({
17
- id: "UxKoFf",
18
- message: "Navigation"
19
- }),
20
- ctaLabel: $__i18n._({
21
- id: "aaGV/9",
22
- message: "New Link"
23
- }),
24
- ctaHref: "/dash/navigation/new"
25
- }),
26
- items.length === 0 ? /*#__PURE__*/ _jsx(EmptyState, {
27
- message: $__i18n._({
28
- id: "wdGjkd",
29
- message: "No navigation links configured."
30
- }),
31
- ctaText: $__i18n._({
32
- id: "aaGV/9",
33
- message: "New Link"
34
- }),
35
- ctaHref: "/dash/navigation/new"
36
- }) : /*#__PURE__*/ _jsx(_Fragment, {
37
- children: /*#__PURE__*/ _jsx("div", {
38
- id: "nav-links-list",
39
- class: "flex flex-col divide-y",
40
- children: items.map((item)=>/*#__PURE__*/ _jsx(ListItemRow, {
41
- actions: /*#__PURE__*/ _jsx(ActionButtons, {
42
- editHref: `/dash/navigation/${item.id}/edit`,
43
- editLabel: $__i18n._({
44
- id: "ePK91l",
45
- message: "Edit"
46
- }),
47
- deleteAction: `/dash/navigation/${item.id}/delete`,
48
- deleteLabel: $__i18n._({
49
- id: "cnGeoo",
50
- message: "Delete"
51
- })
52
- }),
53
- children: /*#__PURE__*/ _jsxs("div", {
54
- class: "flex items-center gap-3 cursor-grab",
55
- "data-id": item.id,
56
- children: [
57
- /*#__PURE__*/ _jsx("span", {
58
- class: "text-muted-foreground select-none",
59
- children: "⠿"
60
- }),
61
- /*#__PURE__*/ _jsxs("div", {
62
- class: "flex items-center gap-2",
63
- children: [
64
- /*#__PURE__*/ _jsx("span", {
65
- class: "font-medium",
66
- children: item.label
67
- }),
68
- /*#__PURE__*/ _jsx("code", {
69
- class: "text-sm text-muted-foreground bg-muted px-1 rounded",
70
- children: item.url
71
- })
72
- ]
73
- })
74
- ]
75
- })
76
- }, item.id))
77
- })
78
- })
79
- ]
80
- });
81
- }
82
- function NavigationFormContent({ item, isEdit }) {
83
- const { i18n: $__i18n, _: $__ } = $_useLingui();
84
- const title = isEdit ? $__i18n._({
85
- id: "gDx5MG",
86
- message: "Edit Link"
87
- }) : $__i18n._({
88
- id: "aaGV/9",
89
- message: "New Link"
90
- });
91
- const signals = JSON.stringify({
92
- label: item?.label ?? "",
93
- url: item?.url ?? ""
94
- }).replace(/</g, "\\u003c");
95
- const action = isEdit ? `/dash/navigation/${item?.id}` : "/dash/navigation";
96
- return /*#__PURE__*/ _jsxs(_Fragment, {
97
- children: [
98
- /*#__PURE__*/ _jsx("h1", {
99
- class: "text-2xl font-semibold mb-6",
100
- children: title
101
- }),
102
- /*#__PURE__*/ _jsxs("form", {
103
- "data-signals": signals,
104
- "data-on:submit__prevent": `@post('${action}')`,
105
- "data-indicator": "_loading",
106
- class: "flex flex-col gap-4 max-w-lg",
107
- children: [
108
- /*#__PURE__*/ _jsxs("div", {
109
- class: "field",
110
- children: [
111
- /*#__PURE__*/ _jsx("label", {
112
- class: "label",
113
- children: $__i18n._({
114
- id: "87a/t/",
115
- message: "Label"
116
- })
117
- }),
118
- /*#__PURE__*/ _jsx("input", {
119
- type: "text",
120
- "data-bind": "label",
121
- class: "input",
122
- placeholder: "Home",
123
- required: true
124
- }),
125
- /*#__PURE__*/ _jsx("p", {
126
- class: "text-xs text-muted-foreground mt-1",
127
- children: $__i18n._({
128
- id: "+bHzpy",
129
- message: "Display text for the link"
130
- })
131
- })
132
- ]
133
- }),
134
- /*#__PURE__*/ _jsxs("div", {
135
- class: "field",
136
- children: [
137
- /*#__PURE__*/ _jsx("label", {
138
- class: "label",
139
- children: $__i18n._({
140
- id: "IagCbF",
141
- message: "URL"
142
- })
143
- }),
144
- /*#__PURE__*/ _jsx("input", {
145
- type: "text",
146
- "data-bind": "url",
147
- class: "input",
148
- placeholder: "/archive or https://...",
149
- required: true
150
- }),
151
- /*#__PURE__*/ _jsx("p", {
152
- class: "text-xs text-muted-foreground mt-1",
153
- children: $__i18n._({
154
- id: "QEbNBb",
155
- message: "Path (e.g. /archive) or full URL (e.g. https://example.com)"
156
- })
157
- })
158
- ]
159
- }),
160
- /*#__PURE__*/ _jsxs("div", {
161
- class: "flex gap-2",
162
- children: [
163
- /*#__PURE__*/ _jsxs("button", {
164
- type: "submit",
165
- class: "btn",
166
- "data-attr-disabled": "$_loading",
167
- children: [
168
- /*#__PURE__*/ _jsx("span", {
169
- "data-show": "!$_loading",
170
- children: isEdit ? $__i18n._({
171
- id: "IUwGEM",
172
- message: "Save Changes"
173
- }) : $__i18n._({
174
- id: "kd7eBB",
175
- message: "Create Link"
176
- })
177
- }),
178
- /*#__PURE__*/ _jsx("span", {
179
- "data-show": "$_loading",
180
- children: $__i18n._({
181
- id: "k1ifdL",
182
- message: "Processing..."
183
- })
184
- })
185
- ]
186
- }),
187
- /*#__PURE__*/ _jsx("a", {
188
- href: "/dash/navigation",
189
- class: "btn-outline",
190
- children: $__i18n._({
191
- id: "dEgA5A",
192
- message: "Cancel"
193
- })
194
- })
195
- ]
196
- })
197
- ]
198
- })
199
- ]
200
- });
201
- }
202
- // List navigation items
203
- navigationRoutes.get("/", async (c)=>{
204
- const siteName = await getSiteName(c);
205
- const items = await c.var.services.navItems.list();
206
- return c.html(/*#__PURE__*/ _jsx(DashLayout, {
207
- c: c,
208
- title: "Navigation",
209
- siteName: siteName,
210
- currentPath: "/dash/navigation",
211
- children: /*#__PURE__*/ _jsx(NavigationListContent, {
212
- items: items
213
- })
214
- }));
215
- });
216
- // New link form
217
- navigationRoutes.get("/new", async (c)=>{
218
- const siteName = await getSiteName(c);
219
- return c.html(/*#__PURE__*/ _jsx(DashLayout, {
220
- c: c,
221
- title: "New Link",
222
- siteName: siteName,
223
- currentPath: "/dash/navigation",
224
- children: /*#__PURE__*/ _jsx(NavigationFormContent, {})
225
- }));
226
- });
227
- // Create link
228
- navigationRoutes.post("/", async (c)=>{
229
- const body = await c.req.json();
230
- if (!body.label || !body.url) {
231
- return dsToast("Label and URL are required", "error");
232
- }
233
- await c.var.services.navItems.create({
234
- type: "link",
235
- label: body.label,
236
- url: body.url
237
- });
238
- return dsRedirect("/dash/navigation");
239
- });
240
- // Reorder links (must be before /:id to avoid "reorder" matching as :id)
241
- navigationRoutes.post("/reorder", async (c)=>{
242
- const body = await c.req.json();
243
- if (!Array.isArray(body.ids)) {
244
- return dsToast("Invalid request", "error");
245
- }
246
- await c.var.services.navItems.reorder(body.ids);
247
- return dsToast("Order saved");
248
- });
249
- // Edit link form
250
- navigationRoutes.get("/:id/edit", async (c)=>{
251
- const id = parseInt(c.req.param("id"), 10);
252
- if (isNaN(id)) return c.notFound();
253
- const item = await c.var.services.navItems.getById(id);
254
- if (!item) return c.notFound();
255
- const siteName = await getSiteName(c);
256
- return c.html(/*#__PURE__*/ _jsx(DashLayout, {
257
- c: c,
258
- title: "Edit Link",
259
- siteName: siteName,
260
- currentPath: "/dash/navigation",
261
- children: /*#__PURE__*/ _jsx(NavigationFormContent, {
262
- item: item,
263
- isEdit: true
264
- })
265
- }));
266
- });
267
- // Update link
268
- navigationRoutes.post("/:id", async (c)=>{
269
- const id = parseInt(c.req.param("id"), 10);
270
- if (isNaN(id)) return c.notFound();
271
- const body = await c.req.json();
272
- if (!body.label || !body.url) {
273
- return dsToast("Label and URL are required", "error");
274
- }
275
- const updated = await c.var.services.navItems.update(id, {
276
- label: body.label,
277
- url: body.url
278
- });
279
- if (!updated) return c.notFound();
280
- return dsRedirect("/dash/navigation");
281
- });
282
- // Delete link
283
- navigationRoutes.post("/:id/delete", async (c)=>{
284
- const id = parseInt(c.req.param("id"), 10);
285
- if (!isNaN(id)) {
286
- await c.var.services.navItems.delete(id);
287
- }
288
- return dsRedirect("/dash/navigation");
289
- });
@@ -1,18 +0,0 @@
1
- /**
2
- * Jant Theme - Shared Infrastructure
3
- *
4
- * Exports shared layouts, components, and color themes used by all themes.
5
- * Individual theme packages (minimal, card, etc.) import from here.
6
- *
7
- * @example
8
- * ```typescript
9
- * // In a theme package:
10
- * import { MediaGallery, Pagination } from "@jant/core/theme";
11
- * import type { ColorTheme } from "@jant/core/theme";
12
- * ```
13
- */ // Layout components (BaseLayout, DashLayout)
14
- export * from "./layouts/index.js";
15
- // Shared UI components (MediaGallery, Pagination, EmptyState, etc.)
16
- export * from "./components/index.js";
17
- // Color themes
18
- export * from "./color-themes.js";
@@ -1,2 +0,0 @@
1
- export { BaseLayout } from "./BaseLayout.js";
2
- export { DashLayout } from "./DashLayout.js";
@@ -1,172 +0,0 @@
1
- /**
2
- * Threads Theme - Site Layout
3
- *
4
- * Left icon sidebar (76px) on desktop, bottom tab bar (60px) on mobile.
5
- * Gray page background (#fafafa) with white rounded content container.
6
- * All dimensions match threads.com's --barcelona-* design tokens.
7
- */ import { jsx as _jsx, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
8
- /** Map known URL paths to SVG icons. Size 26x26 matching Threads' nav icons. */ function NavIcon({ url, isActive }) {
9
- const stroke = "currentColor";
10
- const sw = isActive ? "2.25" : "1.75";
11
- const cls = "size-[26px]";
12
- // Home
13
- if (url === "/") {
14
- return /*#__PURE__*/ _jsx("svg", {
15
- class: cls,
16
- fill: "none",
17
- viewBox: "0 0 24 24",
18
- "stroke-width": sw,
19
- stroke: stroke,
20
- children: /*#__PURE__*/ _jsx("path", {
21
- "stroke-linecap": "round",
22
- "stroke-linejoin": "round",
23
- d: "m2.25 12 8.954-8.955a1.126 1.126 0 0 1 1.591 0L21.75 12M4.5 9.75v10.125c0 .621.504 1.125 1.125 1.125H9.75v-4.875c0-.621.504-1.125 1.125-1.125h2.25c.621 0 1.125.504 1.125 1.125V21h4.125c.621 0 1.125-.504 1.125-1.125V9.75M8.25 21h8.25"
24
- })
25
- });
26
- }
27
- // Search
28
- if (url === "/search") {
29
- return /*#__PURE__*/ _jsx("svg", {
30
- class: cls,
31
- fill: "none",
32
- viewBox: "0 0 24 24",
33
- "stroke-width": sw,
34
- stroke: stroke,
35
- children: /*#__PURE__*/ _jsx("path", {
36
- "stroke-linecap": "round",
37
- "stroke-linejoin": "round",
38
- d: "m21 21-5.197-5.197m0 0A7.5 7.5 0 1 0 5.196 5.196a7.5 7.5 0 0 0 10.607 10.607Z"
39
- })
40
- });
41
- }
42
- // Archive
43
- if (url === "/archive") {
44
- return /*#__PURE__*/ _jsx("svg", {
45
- class: cls,
46
- fill: "none",
47
- viewBox: "0 0 24 24",
48
- "stroke-width": sw,
49
- stroke: stroke,
50
- children: /*#__PURE__*/ _jsx("path", {
51
- "stroke-linecap": "round",
52
- "stroke-linejoin": "round",
53
- d: "M12 6.042A8.967 8.967 0 0 0 6 3.75c-1.052 0-2.062.18-3 .512v14.25A8.987 8.987 0 0 1 6 18c2.305 0 4.408.867 6 2.292m0-14.25a8.966 8.966 0 0 1 6-2.292c1.052 0 2.062.18 3 .512v14.25A8.987 8.987 0 0 0 18 18a8.967 8.967 0 0 0-6 2.292m0-14.25v14.25"
54
- })
55
- });
56
- }
57
- // RSS — common for /feed, /rss, /atom
58
- if (url.match(/\/(feed|rss|atom)/)) {
59
- return /*#__PURE__*/ _jsx("svg", {
60
- class: cls,
61
- fill: "none",
62
- viewBox: "0 0 24 24",
63
- "stroke-width": sw,
64
- stroke: stroke,
65
- children: /*#__PURE__*/ _jsx("path", {
66
- "stroke-linecap": "round",
67
- "stroke-linejoin": "round",
68
- d: "M12.75 19.5v-.75a7.5 7.5 0 0 0-7.5-7.5H4.5m0-6.75h.75c7.87 0 14.25 6.38 14.25 14.25v.75M4.5 19.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5Z"
69
- })
70
- });
71
- }
72
- // External link
73
- if (url.startsWith("http")) {
74
- return /*#__PURE__*/ _jsx("svg", {
75
- class: cls,
76
- fill: "none",
77
- viewBox: "0 0 24 24",
78
- "stroke-width": sw,
79
- stroke: stroke,
80
- children: /*#__PURE__*/ _jsx("path", {
81
- "stroke-linecap": "round",
82
- "stroke-linejoin": "round",
83
- d: "M13.5 6H5.25A2.25 2.25 0 0 0 3 8.25v10.5A2.25 2.25 0 0 0 5.25 21h10.5A2.25 2.25 0 0 0 18 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"
84
- })
85
- });
86
- }
87
- // Default: generic page icon
88
- return /*#__PURE__*/ _jsx("svg", {
89
- class: cls,
90
- fill: "none",
91
- viewBox: "0 0 24 24",
92
- "stroke-width": sw,
93
- stroke: stroke,
94
- children: /*#__PURE__*/ _jsx("path", {
95
- "stroke-linecap": "round",
96
- "stroke-linejoin": "round",
97
- d: "M19.5 14.25v-2.625a3.375 3.375 0 0 0-3.375-3.375h-1.5A1.125 1.125 0 0 1 13.5 7.125v-1.5a3.375 3.375 0 0 0-3.375-3.375H8.25m2.25 0H5.625c-.621 0-1.125.504-1.125 1.125v17.25c0 .621.504 1.125 1.125 1.125h12.75c.621 0 1.125-.504 1.125-1.125V11.25a9 9 0 0 0-9-9Z"
98
- })
99
- });
100
- }
101
- function SidebarLink({ link }) {
102
- return /*#__PURE__*/ _jsx("a", {
103
- href: link.url,
104
- class: `threads-sidebar-link ${link.isActive ? "threads-sidebar-link-active" : ""}`,
105
- title: link.label,
106
- ...link.isExternal ? {
107
- target: "_blank",
108
- rel: "noopener noreferrer"
109
- } : {},
110
- children: /*#__PURE__*/ _jsx(NavIcon, {
111
- url: link.url,
112
- isActive: link.isActive
113
- })
114
- });
115
- }
116
- function MobileTabLink({ link }) {
117
- return /*#__PURE__*/ _jsx("a", {
118
- href: link.url,
119
- class: `threads-mobile-tab ${link.isActive ? "threads-mobile-tab-active" : ""}`,
120
- ...link.isExternal ? {
121
- target: "_blank",
122
- rel: "noopener noreferrer"
123
- } : {},
124
- children: /*#__PURE__*/ _jsx(NavIcon, {
125
- url: link.url,
126
- isActive: link.isActive
127
- })
128
- });
129
- }
130
- export const ThreadsSiteLayout = ({ siteName, links, children })=>{
131
- return /*#__PURE__*/ _jsxs("div", {
132
- class: "threads-page",
133
- children: [
134
- /*#__PURE__*/ _jsxs("aside", {
135
- class: "threads-sidebar",
136
- children: [
137
- /*#__PURE__*/ _jsx("a", {
138
- href: "/",
139
- class: "threads-logo",
140
- title: siteName,
141
- children: /*#__PURE__*/ _jsx("span", {
142
- class: "text-2xl font-black leading-none",
143
- children: "@"
144
- })
145
- }),
146
- /*#__PURE__*/ _jsx("nav", {
147
- class: "flex flex-1 flex-col items-center gap-1",
148
- children: links.map((link)=>/*#__PURE__*/ _jsx(SidebarLink, {
149
- link: link
150
- }, link.id))
151
- })
152
- ]
153
- }),
154
- /*#__PURE__*/ _jsx("main", {
155
- class: "threads-main",
156
- children: /*#__PURE__*/ _jsx("div", {
157
- class: "threads-container",
158
- children: /*#__PURE__*/ _jsx("div", {
159
- class: "threads-content",
160
- children: children
161
- })
162
- })
163
- }),
164
- /*#__PURE__*/ _jsx("nav", {
165
- class: "threads-mobile-tabs",
166
- children: links.map((link)=>/*#__PURE__*/ _jsx(MobileTabLink, {
167
- link: link
168
- }, link.id))
169
- })
170
- ]
171
- });
172
- };
@@ -1,81 +0,0 @@
1
- /**
2
- * Threads Theme
3
- *
4
- * A clean, centered timeline theme inspired by Threads.net.
5
- * Posts separated by thin dividers, no cards, with thread connector lines.
6
- *
7
- * This is the default theme for Jant.
8
- */ // Layout
9
- import { ThreadsSiteLayout } from "./ThreadsSiteLayout.js";
10
- // Pages
11
- import { HomePage } from "./pages/HomePage.js";
12
- import { PostPage } from "./pages/PostPage.js";
13
- import { SinglePage } from "./pages/SinglePage.js";
14
- import { ArchivePage } from "./pages/ArchivePage.js";
15
- import { SearchPage } from "./pages/SearchPage.js";
16
- import { CollectionPage } from "./pages/CollectionPage.js";
17
- // Timeline
18
- import { NoteCard } from "./timeline/NoteCard.js";
19
- import { LinkCard } from "./timeline/LinkCard.js";
20
- import { QuoteCard } from "./timeline/QuoteCard.js";
21
- import { ThreadPreview } from "./timeline/ThreadPreview.js";
22
- import { TimelineFeed } from "./timeline/TimelineFeed.js";
23
- import { TimelineLoadMore } from "./timeline/TimelineLoadMore.js";
24
- import { timelineMore } from "./timeline/timelineMore.js";
25
- /**
26
- * Create the threads theme configuration.
27
- *
28
- * @param options - Optional overrides for components, CSS variables, or color themes
29
- * @returns A JantTheme configuration object
30
- *
31
- * @example
32
- * ```typescript
33
- * import { createApp } from "@jant/core";
34
- * import { threadsTheme } from "@jant/core";
35
- *
36
- * export default createApp({
37
- * theme: threadsTheme(),
38
- * });
39
- * ```
40
- */ export function theme(options) {
41
- return {
42
- name: "threads",
43
- components: {
44
- SiteLayout: ThreadsSiteLayout,
45
- HomePage,
46
- PostPage,
47
- SinglePage,
48
- ArchivePage,
49
- SearchPage,
50
- CollectionPage,
51
- NoteCard,
52
- LinkCard,
53
- QuoteCard,
54
- ThreadPreview,
55
- TimelineFeed,
56
- TimelineLoadMore,
57
- ...options?.components
58
- },
59
- timelineMore,
60
- cssVariables: {
61
- ...options?.cssVariables
62
- },
63
- colorThemes: options?.colorThemes
64
- };
65
- }
66
- // Re-export individual components for wrapping/extending
67
- export { ThreadsSiteLayout } from "./ThreadsSiteLayout.js";
68
- export { HomePage } from "./pages/HomePage.js";
69
- export { PostPage } from "./pages/PostPage.js";
70
- export { SinglePage } from "./pages/SinglePage.js";
71
- export { ArchivePage } from "./pages/ArchivePage.js";
72
- export { SearchPage } from "./pages/SearchPage.js";
73
- export { CollectionPage } from "./pages/CollectionPage.js";
74
- export { NoteCard } from "./timeline/NoteCard.js";
75
- export { LinkCard } from "./timeline/LinkCard.js";
76
- export { QuoteCard } from "./timeline/QuoteCard.js";
77
- export { ThreadPreview } from "./timeline/ThreadPreview.js";
78
- export { TimelineFeed } from "./timeline/TimelineFeed.js";
79
- export { TimelineLoadMore } from "./timeline/TimelineLoadMore.js";
80
- export { TimelineItem, TimelineItemFromPost } from "./timeline/TimelineItem.js";
81
- export { timelineMore } from "./timeline/timelineMore.js";
@@ -1,25 +0,0 @@
1
- /**
2
- * Threads Theme - Home Page
3
- *
4
- * Clean feed of posts separated by dividers.
5
- */ import { jsx as _jsx, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
6
- import { useLingui as $_useLingui } from "@jant/core/i18n";
7
- import { TimelineFeed as DefaultTimelineFeed } from "../timeline/TimelineFeed.js";
8
- export const HomePage = ({ items, hasMore, nextCursor, theme })=>{
9
- const { i18n: $__i18n, _: $__ } = $_useLingui();
10
- const Feed = theme?.TimelineFeed ?? DefaultTimelineFeed;
11
- return /*#__PURE__*/ _jsx(_Fragment, {
12
- children: items.length === 0 ? /*#__PURE__*/ _jsx("p", {
13
- class: "py-12 text-center text-muted-foreground",
14
- children: $__i18n._({
15
- id: "ODiSoW",
16
- message: "No posts yet."
17
- })
18
- }) : /*#__PURE__*/ _jsx(Feed, {
19
- items: items,
20
- hasMore: hasMore,
21
- nextCursor: nextCursor,
22
- theme: theme
23
- })
24
- });
25
- };