@jant/core 0.3.25 → 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 (131) hide show
  1. package/dist/app.js +67 -562
  2. package/dist/client.js +1 -0
  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/lib/avatar-upload.js +134 -0
  7. package/dist/lib/config.js +39 -0
  8. package/dist/lib/constants.js +10 -10
  9. package/dist/lib/favicon.js +102 -0
  10. package/dist/lib/image.js +13 -17
  11. package/dist/lib/media-helpers.js +2 -2
  12. package/dist/lib/navigation.js +23 -3
  13. package/dist/lib/render.js +10 -1
  14. package/dist/lib/schemas.js +31 -0
  15. package/dist/lib/timezones.js +388 -0
  16. package/dist/lib/view.js +1 -1
  17. package/dist/routes/api/posts.js +1 -1
  18. package/dist/routes/api/upload.js +3 -3
  19. package/dist/routes/auth/reset.js +221 -0
  20. package/dist/routes/auth/setup.js +194 -0
  21. package/dist/routes/auth/signin.js +176 -0
  22. package/dist/routes/dash/collections.js +23 -415
  23. package/dist/routes/dash/media.js +12 -392
  24. package/dist/routes/dash/pages.js +7 -330
  25. package/dist/routes/dash/redirects.js +18 -12
  26. package/dist/routes/dash/settings.js +198 -577
  27. package/dist/routes/feed/rss.js +2 -1
  28. package/dist/routes/feed/sitemap.js +4 -2
  29. package/dist/routes/pages/featured.js +5 -1
  30. package/dist/routes/pages/home.js +26 -1
  31. package/dist/routes/pages/latest.js +45 -0
  32. package/dist/services/post.js +30 -50
  33. package/dist/types/bindings.js +3 -0
  34. package/dist/types/config.js +147 -0
  35. package/dist/types/constants.js +27 -0
  36. package/dist/types/entities.js +3 -0
  37. package/dist/types/operations.js +3 -0
  38. package/dist/types/props.js +3 -0
  39. package/dist/types/views.js +5 -0
  40. package/dist/types.js +8 -111
  41. package/dist/ui/color-themes.js +33 -33
  42. package/dist/ui/compose/ComposeDialog.js +36 -21
  43. package/dist/ui/dash/PageForm.js +21 -15
  44. package/dist/ui/dash/PostForm.js +22 -16
  45. package/dist/ui/dash/collections/CollectionForm.js +152 -0
  46. package/dist/ui/dash/collections/CollectionsListContent.js +68 -0
  47. package/dist/ui/dash/collections/ViewCollectionContent.js +96 -0
  48. package/dist/ui/dash/media/MediaListContent.js +166 -0
  49. package/dist/ui/dash/media/ViewMediaContent.js +212 -0
  50. package/dist/ui/dash/pages/LinkFormContent.js +130 -0
  51. package/dist/ui/dash/pages/UnifiedPagesContent.js +193 -0
  52. package/dist/ui/dash/settings/AccountContent.js +209 -0
  53. package/dist/ui/dash/settings/AppearanceContent.js +259 -0
  54. package/dist/ui/dash/settings/GeneralContent.js +536 -0
  55. package/dist/ui/dash/settings/SettingsNav.js +41 -0
  56. package/dist/ui/font-themes.js +36 -0
  57. package/dist/ui/layouts/BaseLayout.js +24 -2
  58. package/dist/ui/layouts/SiteLayout.js +47 -19
  59. package/package.json +1 -1
  60. package/src/app.tsx +93 -553
  61. package/src/client.ts +1 -0
  62. package/src/i18n/locales/en.po +240 -175
  63. package/src/i18n/locales/en.ts +1 -1
  64. package/src/i18n/locales/zh-Hans.po +240 -175
  65. package/src/i18n/locales/zh-Hans.ts +1 -1
  66. package/src/i18n/locales/zh-Hant.po +240 -175
  67. package/src/i18n/locales/zh-Hant.ts +1 -1
  68. package/src/lib/__tests__/config.test.ts +192 -0
  69. package/src/lib/__tests__/favicon.test.ts +151 -0
  70. package/src/lib/__tests__/image.test.ts +2 -6
  71. package/src/lib/__tests__/timezones.test.ts +61 -0
  72. package/src/lib/__tests__/view.test.ts +2 -2
  73. package/src/lib/avatar-upload.ts +165 -0
  74. package/src/lib/config.ts +47 -0
  75. package/src/lib/constants.ts +19 -11
  76. package/src/lib/favicon.ts +115 -0
  77. package/src/lib/image.ts +13 -21
  78. package/src/lib/media-helpers.ts +2 -2
  79. package/src/lib/navigation.ts +33 -2
  80. package/src/lib/render.tsx +15 -1
  81. package/src/lib/schemas.ts +39 -0
  82. package/src/lib/timezones.ts +325 -0
  83. package/src/lib/view.ts +1 -1
  84. package/src/routes/api/posts.ts +1 -1
  85. package/src/routes/api/upload.ts +2 -3
  86. package/src/routes/auth/reset.tsx +239 -0
  87. package/src/routes/auth/setup.tsx +189 -0
  88. package/src/routes/auth/signin.tsx +163 -0
  89. package/src/routes/dash/__tests__/settings-avatar.test.ts +89 -0
  90. package/src/routes/dash/collections.tsx +17 -366
  91. package/src/routes/dash/media.tsx +12 -414
  92. package/src/routes/dash/pages.tsx +8 -348
  93. package/src/routes/dash/redirects.tsx +20 -14
  94. package/src/routes/dash/settings.tsx +243 -534
  95. package/src/routes/feed/__tests__/rss.test.ts +141 -0
  96. package/src/routes/feed/rss.ts +3 -1
  97. package/src/routes/feed/sitemap.ts +4 -2
  98. package/src/routes/pages/featured.tsx +7 -1
  99. package/src/routes/pages/home.tsx +25 -2
  100. package/src/routes/pages/latest.tsx +59 -0
  101. package/src/services/post.ts +34 -66
  102. package/src/styles/components.css +0 -65
  103. package/src/styles/tokens.css +1 -1
  104. package/src/styles/ui.css +24 -40
  105. package/src/types/bindings.ts +30 -0
  106. package/src/types/config.ts +183 -0
  107. package/src/types/constants.ts +26 -0
  108. package/src/types/entities.ts +109 -0
  109. package/src/types/operations.ts +88 -0
  110. package/src/types/props.ts +115 -0
  111. package/src/types/views.ts +172 -0
  112. package/src/types.ts +8 -644
  113. package/src/ui/__tests__/font-themes.test.ts +34 -0
  114. package/src/ui/color-themes.ts +34 -34
  115. package/src/ui/compose/ComposeDialog.tsx +40 -21
  116. package/src/ui/dash/PageForm.tsx +25 -19
  117. package/src/ui/dash/PostForm.tsx +26 -20
  118. package/src/ui/dash/collections/CollectionForm.tsx +153 -0
  119. package/src/ui/dash/collections/CollectionsListContent.tsx +85 -0
  120. package/src/ui/dash/collections/ViewCollectionContent.tsx +92 -0
  121. package/src/ui/dash/media/MediaListContent.tsx +201 -0
  122. package/src/ui/dash/media/ViewMediaContent.tsx +208 -0
  123. package/src/ui/dash/pages/LinkFormContent.tsx +119 -0
  124. package/src/ui/dash/pages/UnifiedPagesContent.tsx +203 -0
  125. package/src/ui/dash/settings/AccountContent.tsx +176 -0
  126. package/src/ui/dash/settings/AppearanceContent.tsx +254 -0
  127. package/src/ui/dash/settings/GeneralContent.tsx +533 -0
  128. package/src/ui/dash/settings/SettingsNav.tsx +56 -0
  129. package/src/ui/font-themes.ts +54 -0
  130. package/src/ui/layouts/BaseLayout.tsx +17 -0
  131. package/src/ui/layouts/SiteLayout.tsx +45 -31
@@ -362,40 +362,55 @@ export const ComposeDialog = ({ collections })=>{
362
362
  /*#__PURE__*/ _jsxs("button", {
363
363
  type: "button",
364
364
  class: "btn-outline text-sm",
365
- "data-attr-disabled": "$_composeLoading",
365
+ "data-attr:disabled": "$_composeLoading",
366
366
  "data-on:click": "$status = 'draft'; document.querySelector('#compose-dialog form').requestSubmit()",
367
367
  children: [
368
- /*#__PURE__*/ _jsx("span", {
369
- "data-show": "!$_composeLoading",
370
- children: $__i18n._({
371
- id: "eneWvv",
372
- message: "Draft"
368
+ /*#__PURE__*/ _jsx("svg", {
369
+ "data-show": "$_composeLoading",
370
+ style: "display:none",
371
+ class: "animate-spin size-4",
372
+ xmlns: "http://www.w3.org/2000/svg",
373
+ viewBox: "0 0 24 24",
374
+ fill: "none",
375
+ stroke: "currentColor",
376
+ "stroke-width": "2",
377
+ "stroke-linecap": "round",
378
+ "stroke-linejoin": "round",
379
+ role: "status",
380
+ children: /*#__PURE__*/ _jsx("path", {
381
+ d: "M21 12a9 9 0 1 1-6.219-8.56"
373
382
  })
374
383
  }),
375
- /*#__PURE__*/ _jsx("span", {
376
- "data-show": "$_composeLoading",
377
- children: "..."
384
+ $__i18n._({
385
+ id: "eneWvv",
386
+ message: "Draft"
378
387
  })
379
388
  ]
380
389
  }),
381
390
  /*#__PURE__*/ _jsxs("button", {
382
391
  type: "submit",
383
392
  class: "btn text-sm",
384
- "data-attr-disabled": "$_composeLoading",
393
+ "data-attr:disabled": "$_composeLoading",
385
394
  children: [
386
- /*#__PURE__*/ _jsx("span", {
387
- "data-show": "!$_composeLoading",
388
- children: $__i18n._({
389
- id: "y28hnO",
390
- message: "Post"
391
- })
392
- }),
393
- /*#__PURE__*/ _jsx("span", {
395
+ /*#__PURE__*/ _jsx("svg", {
394
396
  "data-show": "$_composeLoading",
395
- children: $__i18n._({
396
- id: "iPHeYN",
397
- message: "Posting..."
397
+ style: "display:none",
398
+ class: "animate-spin size-4",
399
+ xmlns: "http://www.w3.org/2000/svg",
400
+ viewBox: "0 0 24 24",
401
+ fill: "none",
402
+ stroke: "currentColor",
403
+ "stroke-width": "2",
404
+ "stroke-linecap": "round",
405
+ "stroke-linejoin": "round",
406
+ role: "status",
407
+ children: /*#__PURE__*/ _jsx("path", {
408
+ d: "M21 12a9 9 0 1 1-6.219-8.56"
398
409
  })
410
+ }),
411
+ $__i18n._({
412
+ id: "y28hnO",
413
+ message: "Post"
399
414
  })
400
415
  ]
401
416
  })
@@ -153,24 +153,30 @@ export const PageForm = ({ page, action, cancelUrl = "/dash/pages" })=>{
153
153
  /*#__PURE__*/ _jsxs("button", {
154
154
  type: "submit",
155
155
  class: "btn",
156
- "data-attr-disabled": "$_loading",
156
+ "data-attr:disabled": "$_loading",
157
157
  children: [
158
- /*#__PURE__*/ _jsx("span", {
159
- "data-show": "!$_loading",
160
- children: isEdit ? $__i18n._({
161
- id: "oYPBa0",
162
- message: "Update Page"
163
- }) : $__i18n._({
164
- id: "Y+7JGK",
165
- message: "Create Page"
166
- })
167
- }),
168
- /*#__PURE__*/ _jsx("span", {
158
+ /*#__PURE__*/ _jsx("svg", {
169
159
  "data-show": "$_loading",
170
- children: $__i18n._({
171
- id: "k1ifdL",
172
- message: "Processing..."
160
+ style: "display:none",
161
+ class: "animate-spin size-4",
162
+ xmlns: "http://www.w3.org/2000/svg",
163
+ viewBox: "0 0 24 24",
164
+ fill: "none",
165
+ stroke: "currentColor",
166
+ "stroke-width": "2",
167
+ "stroke-linecap": "round",
168
+ "stroke-linejoin": "round",
169
+ role: "status",
170
+ children: /*#__PURE__*/ _jsx("path", {
171
+ d: "M21 12a9 9 0 1 1-6.219-8.56"
173
172
  })
173
+ }),
174
+ isEdit ? $__i18n._({
175
+ id: "oYPBa0",
176
+ message: "Update Page"
177
+ }) : $__i18n._({
178
+ id: "Y+7JGK",
179
+ message: "Create Page"
174
180
  })
175
181
  ]
176
182
  }),
@@ -169,7 +169,7 @@ export const PostForm = ({ post, action, mediaAttachments, r2PublicUrl, imageTra
169
169
  class: "grid grid-cols-4 sm:grid-cols-6 gap-2 mb-2",
170
170
  children: mediaAttachments.map((m)=>{
171
171
  const pUrl = getPublicUrlForProvider(m.provider, r2PublicUrl, s3PublicUrl);
172
- const mUrl = getMediaUrl(m.id, m.storageKey, pUrl);
172
+ const mUrl = getMediaUrl(m.storageKey, pUrl);
173
173
  const thumbUrl = getImageUrl(mUrl, imageTransformUrl, {
174
174
  width: 150,
175
175
  quality: 80,
@@ -314,24 +314,30 @@ export const PostForm = ({ post, action, mediaAttachments, r2PublicUrl, imageTra
314
314
  /*#__PURE__*/ _jsxs("button", {
315
315
  type: "submit",
316
316
  class: "btn",
317
- "data-attr-disabled": "$_loading",
317
+ "data-attr:disabled": "$_loading",
318
318
  children: [
319
- /*#__PURE__*/ _jsx("span", {
320
- "data-show": "!$_loading",
321
- children: isEdit ? $__i18n._({
322
- id: "EkH9pt",
323
- message: "Update"
324
- }) : $__i18n._({
325
- id: "EEYbdt",
326
- message: "Publish"
327
- })
328
- }),
329
- /*#__PURE__*/ _jsx("span", {
319
+ /*#__PURE__*/ _jsx("svg", {
330
320
  "data-show": "$_loading",
331
- children: $__i18n._({
332
- id: "k1ifdL",
333
- message: "Processing..."
321
+ style: "display:none",
322
+ class: "animate-spin size-4",
323
+ xmlns: "http://www.w3.org/2000/svg",
324
+ viewBox: "0 0 24 24",
325
+ fill: "none",
326
+ stroke: "currentColor",
327
+ "stroke-width": "2",
328
+ "stroke-linecap": "round",
329
+ "stroke-linejoin": "round",
330
+ role: "status",
331
+ children: /*#__PURE__*/ _jsx("path", {
332
+ d: "M21 12a9 9 0 1 1-6.219-8.56"
334
333
  })
334
+ }),
335
+ isEdit ? $__i18n._({
336
+ id: "EkH9pt",
337
+ message: "Update"
338
+ }) : $__i18n._({
339
+ id: "EEYbdt",
340
+ message: "Publish"
335
341
  })
336
342
  ]
337
343
  }),
@@ -0,0 +1,152 @@
1
+ /**
2
+ * Shared collection form (new + edit)
3
+ */ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
4
+ import { useLingui as $_useLingui } from "@jant/core/i18n";
5
+ export function CollectionForm({ collection, isEdit }) {
6
+ const { i18n: $__i18n, _: $__ } = $_useLingui();
7
+ const signals = JSON.stringify({
8
+ title: collection?.title ?? "",
9
+ slug: collection?.slug ?? "",
10
+ description: collection?.description ?? ""
11
+ }).replace(/</g, "\\u003c");
12
+ const action = isEdit ? `/dash/collections/${collection?.id}` : "/dash/collections";
13
+ const heading = isEdit ? $__i18n._({
14
+ id: "/0D1Xp",
15
+ message: "Edit Collection"
16
+ }) : $__i18n._({
17
+ id: "vzU4k9",
18
+ message: "New Collection"
19
+ });
20
+ const submitLabel = isEdit ? $__i18n._({
21
+ id: "7Mk+/h",
22
+ message: "Update Collection"
23
+ }) : $__i18n._({
24
+ id: "Pbm2/N",
25
+ message: "Create Collection"
26
+ });
27
+ const cancelHref = isEdit ? `/dash/collections/${collection?.id}` : "/dash/collections";
28
+ return /*#__PURE__*/ _jsxs(_Fragment, {
29
+ children: [
30
+ /*#__PURE__*/ _jsx("h1", {
31
+ class: "text-2xl font-semibold mb-6",
32
+ children: heading
33
+ }),
34
+ /*#__PURE__*/ _jsxs("form", {
35
+ "data-signals": signals,
36
+ "data-on:submit__prevent": `@post('${action}')`,
37
+ "data-indicator": "_loading",
38
+ class: "flex flex-col gap-4 max-w-lg",
39
+ children: [
40
+ /*#__PURE__*/ _jsxs("div", {
41
+ class: "field",
42
+ children: [
43
+ /*#__PURE__*/ _jsx("label", {
44
+ class: "label",
45
+ children: $__i18n._({
46
+ id: "MHrjPM",
47
+ message: "Title"
48
+ })
49
+ }),
50
+ /*#__PURE__*/ _jsx("input", {
51
+ type: "text",
52
+ "data-bind": "title",
53
+ class: "input",
54
+ required: true,
55
+ placeholder: isEdit ? undefined : $__i18n._({
56
+ id: "fttd2R",
57
+ message: "My Collection"
58
+ })
59
+ })
60
+ ]
61
+ }),
62
+ /*#__PURE__*/ _jsxs("div", {
63
+ class: "field",
64
+ children: [
65
+ /*#__PURE__*/ _jsx("label", {
66
+ class: "label",
67
+ children: $__i18n._({
68
+ id: "L85WcV",
69
+ message: "Slug"
70
+ })
71
+ }),
72
+ /*#__PURE__*/ _jsx("input", {
73
+ type: "text",
74
+ "data-bind": "slug",
75
+ class: "input",
76
+ required: true,
77
+ pattern: "[a-z0-9-]+",
78
+ placeholder: isEdit ? undefined : "my-collection"
79
+ }),
80
+ !isEdit && /*#__PURE__*/ _jsx("p", {
81
+ class: "text-xs text-muted-foreground mt-1",
82
+ children: $__i18n._({
83
+ id: "1CU1Td",
84
+ message: "URL-safe identifier (lowercase, numbers, hyphens)"
85
+ })
86
+ })
87
+ ]
88
+ }),
89
+ /*#__PURE__*/ _jsxs("div", {
90
+ class: "field",
91
+ children: [
92
+ /*#__PURE__*/ _jsx("label", {
93
+ class: "label",
94
+ children: $__i18n._({
95
+ id: "Fxf4jq",
96
+ message: "Description (optional)"
97
+ })
98
+ }),
99
+ /*#__PURE__*/ _jsx("textarea", {
100
+ "data-bind": "description",
101
+ class: "textarea",
102
+ rows: 3,
103
+ placeholder: isEdit ? undefined : $__i18n._({
104
+ id: "AyHO4m",
105
+ message: "What's this collection about?"
106
+ }),
107
+ children: collection?.description ?? ""
108
+ })
109
+ ]
110
+ }),
111
+ /*#__PURE__*/ _jsxs("div", {
112
+ class: "flex gap-2",
113
+ children: [
114
+ /*#__PURE__*/ _jsxs("button", {
115
+ type: "submit",
116
+ class: "btn",
117
+ "data-attr:disabled": "$_loading",
118
+ children: [
119
+ /*#__PURE__*/ _jsx("svg", {
120
+ "data-show": "$_loading",
121
+ style: "display:none",
122
+ class: "animate-spin size-4",
123
+ xmlns: "http://www.w3.org/2000/svg",
124
+ viewBox: "0 0 24 24",
125
+ fill: "none",
126
+ stroke: "currentColor",
127
+ "stroke-width": "2",
128
+ "stroke-linecap": "round",
129
+ "stroke-linejoin": "round",
130
+ role: "status",
131
+ children: /*#__PURE__*/ _jsx("path", {
132
+ d: "M21 12a9 9 0 1 1-6.219-8.56"
133
+ })
134
+ }),
135
+ submitLabel
136
+ ]
137
+ }),
138
+ /*#__PURE__*/ _jsx("a", {
139
+ href: cancelHref,
140
+ class: "btn-outline",
141
+ children: $__i18n._({
142
+ id: "dEgA5A",
143
+ message: "Cancel"
144
+ })
145
+ })
146
+ ]
147
+ })
148
+ ]
149
+ })
150
+ ]
151
+ });
152
+ }
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Collections list view
3
+ */ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
4
+ import { useLingui as $_useLingui } from "@jant/core/i18n";
5
+ import { EmptyState, ListItemRow, ActionButtons, CrudPageHeader } from "../index.js";
6
+ export function CollectionsListContent({ collections }) {
7
+ const { i18n: $__i18n, _: $__ } = $_useLingui();
8
+ return /*#__PURE__*/ _jsxs(_Fragment, {
9
+ children: [
10
+ /*#__PURE__*/ _jsx(CrudPageHeader, {
11
+ title: $__i18n._({
12
+ id: "DoJzLz",
13
+ message: "Collections"
14
+ }),
15
+ ctaLabel: $__i18n._({
16
+ id: "vzU4k9",
17
+ message: "New Collection"
18
+ }),
19
+ ctaHref: "/dash/collections/new"
20
+ }),
21
+ collections.length === 0 ? /*#__PURE__*/ _jsx(EmptyState, {
22
+ message: $__i18n._({
23
+ id: "+MACwa",
24
+ message: "No collections yet."
25
+ }),
26
+ ctaText: $__i18n._({
27
+ id: "vzU4k9",
28
+ message: "New Collection"
29
+ }),
30
+ ctaHref: "/dash/collections/new"
31
+ }) : /*#__PURE__*/ _jsx("div", {
32
+ class: "flex flex-col divide-y",
33
+ children: collections.map((col)=>/*#__PURE__*/ _jsxs(ListItemRow, {
34
+ actions: /*#__PURE__*/ _jsx(ActionButtons, {
35
+ editHref: `/dash/collections/${col.id}/edit`,
36
+ editLabel: $__i18n._({
37
+ id: "ePK91l",
38
+ message: "Edit"
39
+ }),
40
+ viewHref: `/c/${col.slug}`,
41
+ viewLabel: $__i18n._({
42
+ id: "jpctdh",
43
+ message: "View"
44
+ })
45
+ }),
46
+ children: [
47
+ /*#__PURE__*/ _jsx("a", {
48
+ href: `/dash/collections/${col.id}`,
49
+ class: "font-medium hover:underline",
50
+ children: col.title
51
+ }),
52
+ /*#__PURE__*/ _jsxs("p", {
53
+ class: "text-sm text-muted-foreground",
54
+ children: [
55
+ "/",
56
+ col.slug
57
+ ]
58
+ }),
59
+ col.description && /*#__PURE__*/ _jsx("p", {
60
+ class: "text-sm text-muted-foreground mt-1",
61
+ children: col.description
62
+ })
63
+ ]
64
+ }, col.id))
65
+ })
66
+ ]
67
+ });
68
+ }
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Single collection detail view
3
+ */ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "hono/jsx/jsx-runtime";
4
+ import { useLingui as $_useLingui } from "@jant/core/i18n";
5
+ import { ActionButtons } from "../index.js";
6
+ import { encode } from "../../../lib/sqid.js";
7
+ export function ViewCollectionContent({ collection, posts }) {
8
+ const { i18n: $__i18n, _: $__ } = $_useLingui();
9
+ const postsHeader = $__i18n._({
10
+ id: "pRhYH2",
11
+ message: "Posts in Collection ({count})"
12
+ });
13
+ return /*#__PURE__*/ _jsxs(_Fragment, {
14
+ children: [
15
+ /*#__PURE__*/ _jsxs("div", {
16
+ class: "flex items-center justify-between mb-6",
17
+ children: [
18
+ /*#__PURE__*/ _jsxs("div", {
19
+ children: [
20
+ /*#__PURE__*/ _jsx("h1", {
21
+ class: "text-2xl font-semibold",
22
+ children: collection.title
23
+ }),
24
+ /*#__PURE__*/ _jsxs("p", {
25
+ class: "text-sm text-muted-foreground",
26
+ children: [
27
+ "/",
28
+ collection.slug
29
+ ]
30
+ })
31
+ ]
32
+ }),
33
+ /*#__PURE__*/ _jsx(ActionButtons, {
34
+ editHref: `/dash/collections/${collection.id}/edit`,
35
+ editLabel: $__i18n._({
36
+ id: "ePK91l",
37
+ message: "Edit"
38
+ }),
39
+ viewHref: `/c/${collection.slug}`,
40
+ viewLabel: $__i18n._({
41
+ id: "jpctdh",
42
+ message: "View"
43
+ })
44
+ })
45
+ ]
46
+ }),
47
+ collection.description && /*#__PURE__*/ _jsx("p", {
48
+ class: "text-muted-foreground mb-6",
49
+ children: collection.description
50
+ }),
51
+ /*#__PURE__*/ _jsxs("div", {
52
+ class: "card",
53
+ children: [
54
+ /*#__PURE__*/ _jsx("header", {
55
+ children: /*#__PURE__*/ _jsx("h2", {
56
+ children: postsHeader
57
+ })
58
+ }),
59
+ /*#__PURE__*/ _jsx("section", {
60
+ children: posts.length === 0 ? /*#__PURE__*/ _jsx("p", {
61
+ class: "text-muted-foreground",
62
+ children: $__i18n._({
63
+ id: "J4FNfC",
64
+ message: "No posts in this collection."
65
+ })
66
+ }) : /*#__PURE__*/ _jsx("div", {
67
+ class: "flex flex-col divide-y",
68
+ children: posts.map((post)=>/*#__PURE__*/ _jsx("div", {
69
+ class: "py-3 flex items-center gap-4",
70
+ children: /*#__PURE__*/ _jsx("div", {
71
+ class: "flex-1 min-w-0",
72
+ children: /*#__PURE__*/ _jsx("a", {
73
+ href: `/dash/posts/${encode(post.id)}`,
74
+ class: "font-medium hover:underline",
75
+ children: post.title || post.excerpt?.slice(0, 50) || `Post #${post.id}`
76
+ })
77
+ })
78
+ }, post.id))
79
+ })
80
+ })
81
+ ]
82
+ }),
83
+ /*#__PURE__*/ _jsx("div", {
84
+ class: "mt-6",
85
+ children: /*#__PURE__*/ _jsx("a", {
86
+ href: "/dash/collections",
87
+ class: "text-sm hover:underline",
88
+ children: $__i18n._({
89
+ id: "e6Jr7Q",
90
+ message: "← Back to Collections"
91
+ })
92
+ })
93
+ })
94
+ ]
95
+ });
96
+ }