@jant/core 0.3.24 → 0.3.25

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 (206) hide show
  1. package/dist/app.js +50 -25
  2. package/dist/db/schema.js +1 -1
  3. package/dist/i18n/locales/en.js +1 -1
  4. package/dist/i18n/locales/zh-Hans.js +1 -1
  5. package/dist/i18n/locales/zh-Hant.js +1 -1
  6. package/dist/index.js +3 -9
  7. package/dist/lib/constants.js +1 -0
  8. package/dist/lib/nav-reorder.js +1 -1
  9. package/dist/lib/navigation.js +26 -1
  10. package/dist/lib/pagination.js +44 -0
  11. package/dist/lib/render.js +7 -11
  12. package/dist/lib/schemas.js +3 -3
  13. package/dist/lib/theme.js +4 -4
  14. package/dist/lib/timeline.js +24 -48
  15. package/dist/lib/view.js +2 -2
  16. package/dist/routes/api/collections.js +124 -0
  17. package/dist/routes/api/nav-items.js +104 -0
  18. package/dist/routes/api/pages.js +91 -0
  19. package/dist/routes/api/posts.js +2 -2
  20. package/dist/routes/api/search.js +2 -2
  21. package/dist/routes/api/settings.js +68 -0
  22. package/dist/routes/compose.js +48 -0
  23. package/dist/routes/dash/collections.js +2 -2
  24. package/dist/routes/dash/index.js +1 -1
  25. package/dist/routes/dash/media.js +2 -2
  26. package/dist/routes/dash/pages.js +411 -62
  27. package/dist/routes/dash/posts.js +3 -5
  28. package/dist/routes/dash/redirects.js +2 -2
  29. package/dist/routes/dash/settings.js +79 -5
  30. package/dist/routes/feed/rss.js +2 -2
  31. package/dist/routes/feed/sitemap.js +1 -1
  32. package/dist/routes/pages/archive.js +3 -6
  33. package/dist/routes/pages/collection.js +3 -6
  34. package/dist/routes/pages/collections.js +28 -0
  35. package/dist/routes/pages/featured.js +32 -0
  36. package/dist/routes/pages/home.js +9 -50
  37. package/dist/routes/pages/page.js +29 -32
  38. package/dist/routes/pages/post.js +3 -6
  39. package/dist/routes/pages/search.js +3 -6
  40. package/dist/services/page.js +5 -1
  41. package/dist/services/post.js +40 -6
  42. package/dist/services/search.js +1 -1
  43. package/dist/ui/compose/ComposeDialog.js +452 -0
  44. package/dist/ui/compose/ComposePrompt.js +55 -0
  45. package/dist/{theme/components/TypeBadge.js → ui/dash/FormatBadge.js} +1 -2
  46. package/dist/{theme/components → ui/dash}/PostForm.js +0 -27
  47. package/dist/{theme/components → ui/dash}/PostList.js +6 -6
  48. package/dist/{theme/components/VisibilityBadge.js → ui/dash/StatusBadge.js} +1 -2
  49. package/dist/{theme/components → ui/dash}/index.js +3 -6
  50. package/dist/{themes/threads/timeline → ui/feed}/LinkCard.js +6 -2
  51. package/dist/{themes/threads/timeline → ui/feed}/NoteCard.js +11 -6
  52. package/dist/{themes/threads/timeline → ui/feed}/QuoteCard.js +10 -6
  53. package/dist/{themes/threads/timeline → ui/feed}/ThreadPreview.js +7 -9
  54. package/dist/ui/feed/TimelineFeed.js +41 -0
  55. package/dist/ui/feed/TimelineItem.js +27 -0
  56. package/dist/{theme → ui}/layouts/BaseLayout.js +10 -0
  57. package/dist/{theme → ui}/layouts/DashLayout.js +0 -8
  58. package/dist/ui/layouts/SiteLayout.js +141 -0
  59. package/dist/{themes/threads → ui}/pages/ArchivePage.js +16 -14
  60. package/dist/{themes/threads → ui}/pages/CollectionPage.js +6 -1
  61. package/dist/ui/pages/CollectionsPage.js +76 -0
  62. package/dist/ui/pages/FeaturedPage.js +24 -0
  63. package/dist/ui/pages/HomePage.js +24 -0
  64. package/dist/{themes/threads → ui}/pages/PostPage.js +13 -8
  65. package/dist/{themes/threads → ui}/pages/SearchPage.js +9 -7
  66. package/dist/{themes/threads → ui}/pages/SinglePage.js +3 -2
  67. package/dist/{theme/components → ui/shared}/MediaGallery.js +1 -1
  68. package/dist/{theme/components → ui/shared}/Pagination.js +41 -2
  69. package/dist/{theme/components → ui/shared}/ThreadView.js +2 -2
  70. package/dist/ui/shared/index.js +5 -0
  71. package/package.json +1 -9
  72. package/src/__tests__/helpers/db.ts +3 -0
  73. package/src/app.tsx +57 -27
  74. package/src/db/migrations/0006_rename_slug_to_path.sql +5 -0
  75. package/src/db/migrations/meta/_journal.json +7 -0
  76. package/src/db/schema.ts +1 -1
  77. package/src/i18n/locales/en.po +332 -181
  78. package/src/i18n/locales/en.ts +1 -1
  79. package/src/i18n/locales/zh-Hans.po +332 -181
  80. package/src/i18n/locales/zh-Hans.ts +1 -1
  81. package/src/i18n/locales/zh-Hant.po +332 -181
  82. package/src/i18n/locales/zh-Hant.ts +1 -1
  83. package/src/index.ts +7 -36
  84. package/src/lib/__tests__/schemas.test.ts +60 -19
  85. package/src/lib/__tests__/timeline.test.ts +45 -81
  86. package/src/lib/__tests__/view.test.ts +13 -7
  87. package/src/lib/constants.ts +1 -0
  88. package/src/lib/nav-reorder.ts +1 -1
  89. package/src/lib/navigation.ts +40 -2
  90. package/src/lib/pagination.ts +50 -0
  91. package/src/lib/render.tsx +7 -14
  92. package/src/lib/schemas.ts +8 -6
  93. package/src/lib/theme.ts +5 -5
  94. package/src/lib/timeline.ts +28 -57
  95. package/src/lib/view.ts +2 -2
  96. package/src/preset.css +2 -1
  97. package/src/routes/__tests__/compose.test.ts +199 -0
  98. package/src/routes/api/__tests__/collections.test.ts +249 -0
  99. package/src/routes/api/__tests__/nav-items.test.ts +222 -0
  100. package/src/routes/api/__tests__/pages.test.ts +218 -0
  101. package/src/routes/api/__tests__/settings.test.ts +132 -0
  102. package/src/routes/api/collections.ts +143 -0
  103. package/src/routes/api/nav-items.ts +115 -0
  104. package/src/routes/api/pages.ts +101 -0
  105. package/src/routes/api/posts.ts +2 -2
  106. package/src/routes/api/search.ts +2 -2
  107. package/src/routes/api/settings.ts +91 -0
  108. package/src/routes/compose.ts +63 -0
  109. package/src/routes/dash/__tests__/pages.test.ts +225 -0
  110. package/src/routes/dash/collections.tsx +2 -2
  111. package/src/routes/dash/index.tsx +1 -1
  112. package/src/routes/dash/media.tsx +2 -2
  113. package/src/routes/dash/pages.tsx +443 -70
  114. package/src/routes/dash/posts.tsx +3 -7
  115. package/src/routes/dash/redirects.tsx +2 -2
  116. package/src/routes/dash/settings.tsx +83 -5
  117. package/src/routes/feed/rss.ts +2 -2
  118. package/src/routes/feed/sitemap.ts +1 -1
  119. package/src/routes/pages/__tests__/collections.test.ts +94 -0
  120. package/src/routes/pages/__tests__/featured.test.ts +94 -0
  121. package/src/routes/pages/archive.tsx +2 -6
  122. package/src/routes/pages/collection.tsx +2 -6
  123. package/src/routes/pages/collections.tsx +36 -0
  124. package/src/routes/pages/featured.tsx +38 -0
  125. package/src/routes/pages/home.tsx +9 -55
  126. package/src/routes/pages/page.tsx +28 -30
  127. package/src/routes/pages/post.tsx +2 -5
  128. package/src/routes/pages/search.tsx +2 -6
  129. package/src/services/__tests__/page.test.ts +106 -0
  130. package/src/services/__tests__/post.test.ts +114 -15
  131. package/src/services/page.ts +13 -1
  132. package/src/services/post.ts +57 -7
  133. package/src/services/search.ts +2 -2
  134. package/src/styles/tokens.css +47 -0
  135. package/src/styles/ui.css +491 -0
  136. package/src/types.ts +29 -159
  137. package/src/ui/compose/ComposeDialog.tsx +395 -0
  138. package/src/ui/compose/ComposePrompt.tsx +55 -0
  139. package/src/{theme/components/TypeBadge.tsx → ui/dash/FormatBadge.tsx} +2 -3
  140. package/src/{theme/components → ui/dash}/PostForm.tsx +0 -25
  141. package/src/{theme/components → ui/dash}/PostList.tsx +7 -7
  142. package/src/{theme/components/VisibilityBadge.tsx → ui/dash/StatusBadge.tsx} +2 -3
  143. package/src/ui/dash/index.ts +10 -0
  144. package/src/{themes/threads/timeline → ui/feed}/LinkCard.tsx +9 -4
  145. package/src/{themes/threads/timeline → ui/feed}/NoteCard.tsx +13 -8
  146. package/src/{themes/threads/timeline → ui/feed}/QuoteCard.tsx +13 -8
  147. package/src/{themes/threads/timeline → ui/feed}/ThreadPreview.tsx +7 -8
  148. package/src/ui/feed/TimelineFeed.tsx +49 -0
  149. package/src/ui/feed/TimelineItem.tsx +45 -0
  150. package/src/{theme → ui}/layouts/BaseLayout.tsx +11 -1
  151. package/src/{theme → ui}/layouts/DashLayout.tsx +0 -10
  152. package/src/ui/layouts/SiteLayout.tsx +150 -0
  153. package/src/{themes/threads → ui}/pages/ArchivePage.tsx +22 -17
  154. package/src/{themes/threads → ui}/pages/CollectionPage.tsx +14 -5
  155. package/src/ui/pages/CollectionsPage.tsx +73 -0
  156. package/src/ui/pages/FeaturedPage.tsx +31 -0
  157. package/src/{themes/threads → ui}/pages/HomePage.tsx +11 -15
  158. package/src/{themes/threads → ui}/pages/PostPage.tsx +23 -14
  159. package/src/{themes/threads → ui}/pages/SearchPage.tsx +13 -11
  160. package/src/{themes/threads → ui}/pages/SinglePage.tsx +4 -4
  161. package/src/{theme/components → ui/shared}/MediaGallery.tsx +1 -1
  162. package/src/{theme/components → ui/shared}/Pagination.tsx +67 -4
  163. package/src/{theme/components → ui/shared}/ThreadView.tsx +2 -2
  164. package/src/ui/shared/__tests__/pagination.test.ts +46 -0
  165. package/src/ui/shared/index.ts +12 -0
  166. package/bin/jant.js +0 -185
  167. package/dist/lib/theme-components.js +0 -46
  168. package/dist/routes/dash/navigation.js +0 -289
  169. package/dist/theme/index.js +0 -18
  170. package/dist/theme/layouts/index.js +0 -2
  171. package/dist/themes/threads/ThreadsSiteLayout.js +0 -172
  172. package/dist/themes/threads/index.js +0 -81
  173. package/dist/themes/threads/pages/HomePage.js +0 -25
  174. package/dist/themes/threads/timeline/TimelineFeed.js +0 -58
  175. package/dist/themes/threads/timeline/TimelineItem.js +0 -36
  176. package/dist/themes/threads/timeline/TimelineLoadMore.js +0 -23
  177. package/dist/themes/threads/timeline/groupByDate.js +0 -22
  178. package/dist/themes/threads/timeline/timelineMore.js +0 -107
  179. package/src/lib/__tests__/theme-components.test.ts +0 -105
  180. package/src/lib/theme-components.ts +0 -65
  181. package/src/routes/dash/navigation.tsx +0 -317
  182. package/src/theme/components/index.ts +0 -23
  183. package/src/theme/index.ts +0 -22
  184. package/src/theme/layouts/index.ts +0 -7
  185. package/src/themes/threads/ThreadsSiteLayout.tsx +0 -194
  186. package/src/themes/threads/index.ts +0 -100
  187. package/src/themes/threads/style.css +0 -336
  188. package/src/themes/threads/timeline/TimelineFeed.tsx +0 -62
  189. package/src/themes/threads/timeline/TimelineItem.tsx +0 -67
  190. package/src/themes/threads/timeline/TimelineLoadMore.tsx +0 -35
  191. package/src/themes/threads/timeline/groupByDate.ts +0 -30
  192. package/src/themes/threads/timeline/timelineMore.tsx +0 -130
  193. /package/dist/{theme → ui}/color-themes.js +0 -0
  194. /package/dist/{theme/components → ui/dash}/ActionButtons.js +0 -0
  195. /package/dist/{theme/components → ui/dash}/CrudPageHeader.js +0 -0
  196. /package/dist/{theme/components → ui/dash}/DangerZone.js +0 -0
  197. /package/dist/{theme/components → ui/dash}/ListItemRow.js +0 -0
  198. /package/dist/{theme/components → ui/dash}/PageForm.js +0 -0
  199. /package/dist/{theme/components → ui/shared}/EmptyState.js +0 -0
  200. /package/src/{theme → ui}/color-themes.ts +0 -0
  201. /package/src/{theme/components → ui/dash}/ActionButtons.tsx +0 -0
  202. /package/src/{theme/components → ui/dash}/CrudPageHeader.tsx +0 -0
  203. /package/src/{theme/components → ui/dash}/DangerZone.tsx +0 -0
  204. /package/src/{theme/components → ui/dash}/ListItemRow.tsx +0 -0
  205. /package/src/{theme/components → ui/dash}/PageForm.tsx +0 -0
  206. /package/src/{theme/components → ui/shared}/EmptyState.tsx +0 -0
package/bin/jant.js DELETED
@@ -1,185 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Jant CLI
5
- *
6
- * Commands:
7
- * swizzle <component> [--wrap|--eject] - Override a theme component
8
- */
9
-
10
- import { writeFileSync, mkdirSync, existsSync } from "fs";
11
- import { resolve } from "path";
12
-
13
-
14
- // Available components that can be swizzled
15
- const SWIZZLABLE_COMPONENTS = {
16
- PostCard: {
17
- file: "PostCard.tsx",
18
- props: "PostCardProps",
19
- },
20
- PostList: {
21
- file: "PostList.tsx",
22
- props: "PostListProps",
23
- },
24
- Pagination: {
25
- file: "Pagination.tsx",
26
- props: "PaginationProps",
27
- },
28
- EmptyState: {
29
- file: "EmptyState.tsx",
30
- props: "EmptyStateProps",
31
- },
32
- BaseLayout: {
33
- file: "BaseLayout.tsx",
34
- props: "BaseLayoutProps",
35
- isLayout: true,
36
- },
37
- };
38
-
39
- function showHelp() {
40
- console.log(`
41
- Jant CLI
42
-
43
- Usage:
44
- jant swizzle <component> [options]
45
-
46
- Commands:
47
- swizzle <component> Override a theme component
48
-
49
- Options:
50
- --wrap Create a wrapper around the original component (default)
51
- --eject Copy the full component source for complete customization
52
- --list List available components
53
-
54
- Examples:
55
- jant swizzle PostCard # Wrap PostCard component
56
- jant swizzle PostCard --eject # Copy PostCard source
57
- jant swizzle --list # List all swizzlable components
58
- `);
59
- }
60
-
61
- function listComponents() {
62
- console.log("\nAvailable components to swizzle:\n");
63
- for (const [name, info] of Object.entries(SWIZZLABLE_COMPONENTS)) {
64
- const type = info.isLayout ? "[Layout]" : "[Component]";
65
- console.log(` ${name.padEnd(15)} ${type}`);
66
- }
67
- console.log("\nUsage: jant swizzle <component> [--wrap|--eject]\n");
68
- }
69
-
70
- function generateWrapperCode(componentName, info) {
71
- const importPath = info.isLayout
72
- ? "@jant/core/theme/layouts"
73
- : "@jant/core/theme/components";
74
-
75
- return `/**
76
- * Custom ${componentName} component
77
- *
78
- * This is a wrapper around the original ${componentName}.
79
- * You can customize the rendering while keeping the original functionality.
80
- */
81
-
82
- import type { ${info.props} } from "@jant/core";
83
- import { ${componentName} as Original${componentName} } from "${importPath}";
84
-
85
- export function ${componentName}(props: ${info.props}) {
86
- // Add your customizations here
87
- return (
88
- <div class="custom-${componentName.toLowerCase()}-wrapper">
89
- <Original${componentName} {...props} />
90
- </div>
91
- );
92
- }
93
- `;
94
- }
95
-
96
- function swizzle(componentName, mode) {
97
- const info = SWIZZLABLE_COMPONENTS[componentName];
98
- if (!info) {
99
- console.error(`Error: Unknown component "${componentName}"`);
100
- console.log("\nAvailable components:");
101
- listComponents();
102
- process.exit(1);
103
- }
104
-
105
- const targetDir = info.isLayout
106
- ? resolve(process.cwd(), "src/theme/layouts")
107
- : resolve(process.cwd(), "src/theme/components");
108
-
109
- const targetFile = resolve(targetDir, info.file);
110
-
111
- // Check if file already exists
112
- if (existsSync(targetFile)) {
113
- console.error(`Error: ${targetFile} already exists`);
114
- console.log("Remove it first if you want to re-swizzle.");
115
- process.exit(1);
116
- }
117
-
118
- // Create directory if needed
119
- mkdirSync(targetDir, { recursive: true });
120
-
121
- if (mode === "eject") {
122
- // For eject mode, we'd need to copy the actual source
123
- // For now, show a message about where to find it
124
- console.log(`
125
- To eject ${componentName}, copy the source from:
126
- node_modules/@jant/core/src/theme/${info.isLayout ? "layouts" : "components"}/${info.file}
127
-
128
- Then modify it as needed.
129
- `);
130
- return;
131
- }
132
-
133
- // Generate wrapper code
134
- const code = generateWrapperCode(componentName, info);
135
- writeFileSync(targetFile, code, "utf-8");
136
-
137
- console.log(`
138
- ✓ Created ${targetFile}
139
-
140
- Next steps:
141
- 1. Customize the component in the generated file
142
- 2. Import it in your src/index.ts:
143
-
144
- import { ${componentName} } from "./theme/${info.isLayout ? "layouts" : "components"}/${componentName}";
145
-
146
- export default createApp({
147
- theme: {
148
- components: {
149
- ${componentName},
150
- },
151
- },
152
- });
153
- `);
154
- }
155
-
156
- // Parse arguments
157
- const args = process.argv.slice(2);
158
-
159
- if (args.length === 0 || args[0] === "--help" || args[0] === "-h") {
160
- showHelp();
161
- process.exit(0);
162
- }
163
-
164
- const command = args[0];
165
-
166
- if (command === "swizzle") {
167
- if (args.includes("--list")) {
168
- listComponents();
169
- process.exit(0);
170
- }
171
-
172
- const componentName = args[1];
173
- if (!componentName) {
174
- console.error("Error: Component name required");
175
- console.log("Usage: jant swizzle <component> [--wrap|--eject]");
176
- process.exit(1);
177
- }
178
-
179
- const mode = args.includes("--eject") ? "eject" : "wrap";
180
- swizzle(componentName, mode);
181
- } else {
182
- console.error(`Unknown command: ${command}`);
183
- showHelp();
184
- process.exit(1);
185
- }
@@ -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";