@jant/core 0.3.35 → 0.3.36
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.
- package/dist/client/assets/module-RjUF93sV.js +716 -0
- package/dist/client/assets/native-48B9X9Wg.js +1 -0
- package/dist/client/assets/url-8Dj-5CLW.js +1 -0
- package/dist/client/client.css +1 -1
- package/dist/client/client.js +3109 -2294
- package/dist/index.js +3026 -2778
- package/package.json +13 -4
- package/src/__tests__/helpers/app.ts +1 -1
- package/src/__tests__/helpers/db.ts +6 -0
- package/src/app.tsx +1 -5
- package/src/{lib → client}/avatar-upload.ts +1 -1
- package/src/{lib → client}/collection-form-bridge.ts +2 -2
- package/src/{ui → client}/components/__tests__/jant-collection-form.test.ts +26 -9
- package/src/{ui → client}/components/__tests__/jant-compose-dialog.test.ts +46 -14
- package/src/{ui → client}/components/__tests__/jant-compose-editor.test.ts +64 -24
- package/src/{ui → client}/components/__tests__/jant-post-form.test.ts +24 -14
- package/src/{ui → client}/components/__tests__/jant-settings-general.test.ts +3 -3
- package/src/client/components/collection-sidebar-types.ts +45 -0
- package/src/{ui → client}/components/collection-types.ts +3 -4
- package/src/{ui → client}/components/compose-types.ts +3 -1
- package/src/{ui → client}/components/jant-collection-form.ts +301 -182
- package/src/client/components/jant-collection-sidebar.ts +801 -0
- package/src/{ui → client}/components/jant-compose-dialog.ts +231 -1
- package/src/client/components/jant-compose-editor.ts +1249 -0
- package/src/client/components/jant-compose-fullscreen.ts +338 -0
- package/src/client/components/jant-media-lightbox.ts +257 -0
- package/src/{ui → client}/components/jant-nav-manager.ts +143 -84
- package/src/{ui → client}/components/jant-post-form.ts +57 -8
- package/src/{ui → client}/components/jant-settings-general.ts +2 -2
- package/src/{ui → client}/components/nav-manager-types.ts +3 -0
- package/src/{ui → client}/components/post-form-template.ts +35 -31
- package/src/{ui → client}/components/post-form-types.ts +7 -3
- package/src/{lib → client}/compose-bridge.ts +9 -7
- package/src/client/lazy-slugify.ts +51 -0
- package/src/{lib → client}/media-upload.ts +16 -3
- package/src/{lib → client}/nav-manager-bridge.ts +1 -1
- package/src/client/page-slug-bridge.ts +42 -0
- package/src/{lib → client}/post-form-bridge.ts +2 -2
- package/src/{lib → client}/settings-bridge.ts +3 -3
- package/src/client/tiptap/bubble-menu.ts +205 -0
- package/src/client/tiptap/create-editor.ts +40 -0
- package/src/client/tiptap/exitable-marks.ts +73 -0
- package/src/client/tiptap/extensions.ts +60 -0
- package/src/client/tiptap/image-node.ts +488 -0
- package/src/client/tiptap/link-toolbar.ts +371 -0
- package/src/client/tiptap/more-break.ts +50 -0
- package/src/client/tiptap/paste-image.ts +140 -0
- package/src/client/tiptap/slash-commands.ts +328 -0
- package/src/{types → client/types}/sortablejs.d.ts +1 -1
- package/src/client.ts +24 -17
- package/src/db/migrations/0012_add_tiptap_columns.sql +2 -0
- package/src/db/migrations/0013_replace_featured_with_visibility.sql +8 -0
- package/src/db/schema.ts +6 -1
- package/src/i18n/locales/en.po +641 -215
- package/src/i18n/locales/en.ts +1 -1
- package/src/i18n/locales/zh-Hans.po +642 -204
- package/src/i18n/locales/zh-Hans.ts +1 -1
- package/src/i18n/locales/zh-Hant.po +642 -204
- package/src/i18n/locales/zh-Hant.ts +1 -1
- package/src/lib/__tests__/resolve-config.test.ts +2 -2
- package/src/lib/__tests__/schemas.test.ts +9 -6
- package/src/lib/__tests__/url.test.ts +2 -2
- package/src/lib/__tests__/view.test.ts +9 -9
- package/src/lib/emoji-catalog.ts +146 -0
- package/src/lib/feed.ts +1 -1
- package/src/lib/media-helpers.ts +10 -9
- package/src/lib/render.tsx +4 -3
- package/src/lib/resolve-config.ts +8 -1
- package/src/lib/schemas.ts +2 -3
- package/src/lib/summary.ts +92 -0
- package/src/lib/timeline.ts +2 -0
- package/src/lib/tiptap-render.ts +196 -0
- package/src/lib/upload.ts +97 -9
- package/src/lib/url.ts +7 -23
- package/src/lib/view.ts +33 -19
- package/src/middleware/error-handler.ts +3 -3
- package/src/preset.css +38 -0
- package/src/routes/api/collections.ts +20 -3
- package/src/routes/api/posts.ts +48 -33
- package/src/routes/api/upload.ts +7 -5
- package/src/routes/auth/reset.tsx +5 -4
- package/src/routes/auth/setup.tsx +26 -11
- package/src/routes/auth/signin.tsx +10 -7
- package/src/routes/compose.tsx +20 -11
- package/src/routes/dash/__tests__/settings-avatar.test.ts +43 -8
- package/src/routes/dash/index.tsx +7 -1
- package/src/routes/dash/media.tsx +3 -0
- package/src/routes/dash/pages.tsx +8 -2
- package/src/routes/dash/posts.tsx +6 -2
- package/src/routes/dash/redirects.tsx +15 -9
- package/src/routes/dash/settings.tsx +336 -32
- package/src/routes/feed/__tests__/rss.test.ts +7 -7
- package/src/routes/feed/rss.ts +8 -6
- package/src/routes/pages/__tests__/featured.test.ts +6 -7
- package/src/routes/pages/archive.tsx +11 -7
- package/src/routes/pages/collection.tsx +32 -15
- package/src/routes/pages/collections.tsx +11 -2
- package/src/routes/pages/featured.tsx +1 -1
- package/src/routes/pages/home.tsx +1 -1
- package/src/services/__tests__/post.test.ts +124 -33
- package/src/services/__tests__/settings.test.ts +3 -3
- package/src/services/page.ts +16 -3
- package/src/services/post.ts +96 -37
- package/src/services/search.ts +4 -2
- package/src/services/settings.ts +6 -2
- package/src/styles/components.css +240 -60
- package/src/styles/tokens.css +10 -0
- package/src/styles/ui.css +1157 -81
- package/src/types/bindings.ts +5 -0
- package/src/types/config.ts +23 -1
- package/src/types/constants.ts +3 -0
- package/src/types/entities.ts +9 -2
- package/src/types/operations.ts +9 -3
- package/src/types/props.ts +3 -3
- package/src/types/views.ts +3 -2
- package/src/ui/compose/ComposeDialog.tsx +24 -7
- package/src/ui/dash/PageForm.tsx +2 -0
- package/src/ui/dash/PostList.tsx +5 -5
- package/src/ui/dash/StatusBadge.tsx +13 -5
- package/src/ui/dash/appearance/AdvancedContent.tsx +52 -61
- package/src/ui/dash/appearance/ColorThemeContent.tsx +30 -35
- package/src/ui/dash/appearance/FontThemeContent.tsx +65 -73
- package/src/ui/dash/appearance/NavigationContent.tsx +107 -96
- package/src/ui/dash/media/MediaListContent.tsx +9 -4
- package/src/ui/dash/media/ViewMediaContent.tsx +2 -2
- package/src/ui/dash/pages/PagesContent.tsx +2 -1
- package/src/ui/dash/posts/PostForm.tsx +19 -7
- package/src/ui/dash/settings/AccountContent.tsx +133 -138
- package/src/ui/dash/settings/AvatarContent.tsx +70 -0
- package/src/ui/dash/settings/GeneralContent.tsx +3 -62
- package/src/ui/dash/settings/SettingsRootContent.tsx +236 -0
- package/src/ui/layouts/DashLayout.tsx +157 -75
- package/src/ui/layouts/SiteLayout.tsx +13 -13
- package/src/ui/pages/ArchivePage.tsx +10 -7
- package/src/ui/pages/CollectionPage.tsx +6 -35
- package/src/ui/pages/CollectionsPage.tsx +2 -1
- package/src/ui/pages/FeaturedPage.tsx +2 -1
- package/src/ui/pages/HomePage.tsx +1 -1
- package/src/ui/pages/SearchPage.tsx +1 -1
- package/src/ui/shared/CollectionsSidebar.tsx +228 -3
- package/src/ui/shared/MediaGallery.tsx +179 -41
- package/src/lib/collections-reorder.ts +0 -28
- package/src/routes/dash/appearance.tsx +0 -240
- package/src/routes/dash/collections.tsx +0 -211
- package/src/ui/components/jant-compose-editor.ts +0 -814
- package/src/ui/dash/appearance/AppearanceNav.tsx +0 -60
- package/src/ui/dash/collections/CollectionForm.tsx +0 -166
- package/src/ui/dash/collections/CollectionsListContent.tsx +0 -146
- package/src/ui/dash/collections/IconPickerGrid.tsx +0 -50
- package/src/ui/dash/collections/ViewCollectionContent.tsx +0 -103
- package/src/ui/dash/settings/SettingsNav.tsx +0 -52
- /package/src/{ui → client}/components/__tests__/jant-settings-avatar.test.ts +0 -0
- /package/src/{ui → client}/components/jant-settings-avatar.ts +0 -0
- /package/src/{ui → client}/components/settings-types.ts +0 -0
- /package/src/{lib → client}/image-processor.ts +0 -0
- /package/src/{lib → client}/toast.ts +0 -0
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
import { useLingui } from "@lingui/react/macro";
|
|
6
6
|
import type { FontTheme } from "../../font-themes.js";
|
|
7
|
-
import { AppearanceNav } from "./AppearanceNav.js";
|
|
8
7
|
|
|
9
8
|
export function FontThemeContent({
|
|
10
9
|
fontThemes,
|
|
@@ -16,80 +15,73 @@ export function FontThemeContent({
|
|
|
16
15
|
const { t } = useLingui();
|
|
17
16
|
|
|
18
17
|
return (
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class="
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
18
|
+
<div
|
|
19
|
+
data-signals={JSON.stringify({ fontTheme: currentFontThemeId }).replace(
|
|
20
|
+
/</g,
|
|
21
|
+
"\\u003c",
|
|
22
|
+
)}
|
|
23
|
+
data-on:change="@post('/dash/settings/font-theme')"
|
|
24
|
+
class="max-w-3xl"
|
|
25
|
+
>
|
|
26
|
+
<fieldset>
|
|
27
|
+
<legend class="text-lg font-semibold">
|
|
28
|
+
{t({
|
|
29
|
+
message: "Font theme",
|
|
30
|
+
comment: "@context: Appearance settings heading for font theme",
|
|
31
|
+
})}
|
|
32
|
+
</legend>
|
|
33
|
+
<p class="text-sm text-muted-foreground mb-4">
|
|
34
|
+
{t({
|
|
35
|
+
message:
|
|
36
|
+
"Choose a font pairing for your site. All options use system fonts for fast loading.",
|
|
37
|
+
comment: "@context: Font theme settings description",
|
|
38
|
+
})}
|
|
39
|
+
</p>
|
|
40
|
+
<div class="flex flex-col gap-2">
|
|
41
|
+
{fontThemes.map((ft) => (
|
|
42
|
+
<label
|
|
43
|
+
key={ft.id}
|
|
44
|
+
class={`flex items-start gap-3 p-3 rounded-lg border cursor-pointer transition-colors ${ft.id === currentFontThemeId ? "border-primary" : "border-border"}`}
|
|
45
|
+
data-class:border-primary={`$fontTheme === '${ft.id}'`}
|
|
46
|
+
data-class:border-border={`$fontTheme !== '${ft.id}'`}
|
|
47
|
+
>
|
|
48
|
+
<input
|
|
49
|
+
type="radio"
|
|
50
|
+
name="fontTheme"
|
|
51
|
+
value={ft.id}
|
|
52
|
+
data-bind="fontTheme"
|
|
53
|
+
checked={ft.id === currentFontThemeId || undefined}
|
|
54
|
+
class="mt-1"
|
|
55
|
+
/>
|
|
56
|
+
<div>
|
|
57
|
+
<div class="font-medium">{t(ft.name)}</div>
|
|
58
|
+
<div class="text-sm text-muted-foreground">
|
|
59
|
+
{t(ft.description)}
|
|
60
|
+
</div>
|
|
61
|
+
<div class="mt-1 text-sm leading-relaxed">
|
|
62
|
+
<div
|
|
63
|
+
class="font-semibold"
|
|
64
|
+
style={`font-family:${ft.headingFontFamily}`}
|
|
65
|
+
>
|
|
66
|
+
{t({
|
|
67
|
+
message: "The quick brown fox jumps over the lazy dog.",
|
|
68
|
+
comment:
|
|
69
|
+
"@context: Font theme preview sentence for headings",
|
|
70
|
+
})}
|
|
64
71
|
</div>
|
|
65
|
-
<div class="mt-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
message: "The quick brown fox jumps over the lazy dog.",
|
|
72
|
-
comment:
|
|
73
|
-
"@context: Font theme preview sentence for headings",
|
|
74
|
-
})}
|
|
75
|
-
</div>
|
|
76
|
-
<div
|
|
77
|
-
class="mt-2"
|
|
78
|
-
style={`font-family:${ft.bodyFontFamily}`}
|
|
79
|
-
>
|
|
80
|
-
{t({
|
|
81
|
-
message: "The quick brown fox jumps over the lazy dog.",
|
|
82
|
-
comment:
|
|
83
|
-
"@context: Font theme preview sentence for body text",
|
|
84
|
-
})}
|
|
85
|
-
</div>
|
|
72
|
+
<div class="mt-2" style={`font-family:${ft.bodyFontFamily}`}>
|
|
73
|
+
{t({
|
|
74
|
+
message: "The quick brown fox jumps over the lazy dog.",
|
|
75
|
+
comment:
|
|
76
|
+
"@context: Font theme preview sentence for body text",
|
|
77
|
+
})}
|
|
86
78
|
</div>
|
|
87
79
|
</div>
|
|
88
|
-
</
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
</
|
|
92
|
-
</
|
|
93
|
-
|
|
80
|
+
</div>
|
|
81
|
+
</label>
|
|
82
|
+
))}
|
|
83
|
+
</div>
|
|
84
|
+
</fieldset>
|
|
85
|
+
</div>
|
|
94
86
|
);
|
|
95
87
|
}
|
|
@@ -8,9 +8,7 @@ import { SYSTEM_NAV_KEYS } from "../../../types.js";
|
|
|
8
8
|
import type {
|
|
9
9
|
NavManagerLabels,
|
|
10
10
|
SystemNavConfig,
|
|
11
|
-
} from "
|
|
12
|
-
import { AppearanceNav } from "./AppearanceNav.js";
|
|
13
|
-
|
|
11
|
+
} from "../../../client/components/nav-manager-types.js";
|
|
14
12
|
// =============================================================================
|
|
15
13
|
// System descriptions (used to build the config passed to the Lit component)
|
|
16
14
|
// =============================================================================
|
|
@@ -69,7 +67,7 @@ export function NavigationContent({
|
|
|
69
67
|
|
|
70
68
|
const labels: NavManagerLabels = {
|
|
71
69
|
preview: t({
|
|
72
|
-
message: "Preview",
|
|
70
|
+
message: "Navigation Preview",
|
|
73
71
|
comment: "@context: Label for nav preview section",
|
|
74
72
|
}),
|
|
75
73
|
navigationItems: t({
|
|
@@ -121,11 +119,11 @@ export function NavigationContent({
|
|
|
121
119
|
comment: "@context: Error toast when nav label is empty",
|
|
122
120
|
}),
|
|
123
121
|
saveFailed: t({
|
|
124
|
-
message: "
|
|
122
|
+
message: "Couldn't save. Try again in a moment.",
|
|
125
123
|
comment: "@context: Error toast when nav save fails",
|
|
126
124
|
}),
|
|
127
125
|
deleteFailed: t({
|
|
128
|
-
message: "
|
|
126
|
+
message: "Couldn't delete. Try again in a moment.",
|
|
129
127
|
comment: "@context: Error toast when nav delete fails",
|
|
130
128
|
}),
|
|
131
129
|
systemLinks: t({
|
|
@@ -154,7 +152,7 @@ export function NavigationContent({
|
|
|
154
152
|
comment: "@context: Placeholder for page search input in combobox",
|
|
155
153
|
}),
|
|
156
154
|
noPagesFound: t({
|
|
157
|
-
message: "No pages
|
|
155
|
+
message: "No matching pages.",
|
|
158
156
|
comment: "@context: Empty state when page search has no results",
|
|
159
157
|
}),
|
|
160
158
|
addLink: t({
|
|
@@ -169,20 +167,34 @@ export function NavigationContent({
|
|
|
169
167
|
message: "All pages are already in navigation.",
|
|
170
168
|
comment: "@context: Message when no pages available to add",
|
|
171
169
|
}),
|
|
170
|
+
createPage: t({
|
|
171
|
+
message: "Create page",
|
|
172
|
+
comment: "@context: Link at bottom of page combobox to create a new page",
|
|
173
|
+
}),
|
|
172
174
|
urlPlaceholder: "/archive or https://...",
|
|
173
175
|
maxVisibleLinks: t({
|
|
174
|
-
message: "
|
|
176
|
+
message: "Links shown in header",
|
|
175
177
|
comment: "@context: Label for max visible nav links number input",
|
|
176
178
|
}),
|
|
179
|
+
maxVisibleLinksDescription: t({
|
|
180
|
+
message: "The rest will be tucked into a ··· menu",
|
|
181
|
+
comment:
|
|
182
|
+
"@context: Description for max visible nav links, explains overflow behavior",
|
|
183
|
+
}),
|
|
177
184
|
maxVisibleSaved: t({
|
|
178
185
|
message: "Max visible links saved",
|
|
179
186
|
comment: "@context: Toast after saving max visible nav links setting",
|
|
180
187
|
}),
|
|
181
188
|
useFeaturedAsDefault: t({
|
|
182
|
-
message: "
|
|
189
|
+
message: "Open with Featured posts",
|
|
183
190
|
comment:
|
|
184
191
|
"@context: Switch label for setting featured posts as default homepage",
|
|
185
192
|
}),
|
|
193
|
+
useFeaturedAsDefaultDescription: t({
|
|
194
|
+
message: "When off, visitors see your latest posts first",
|
|
195
|
+
comment:
|
|
196
|
+
"@context: Description for featured default toggle, explains what happens when off",
|
|
197
|
+
}),
|
|
186
198
|
homeViewSaved: t({
|
|
187
199
|
message: "Home view saved",
|
|
188
200
|
comment: "@context: Toast after saving home default view setting",
|
|
@@ -205,98 +217,97 @@ export function NavigationContent({
|
|
|
205
217
|
JSON.stringify(data).replace(/</g, "\\u003c");
|
|
206
218
|
|
|
207
219
|
return (
|
|
208
|
-
|
|
209
|
-
<
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
220
|
+
<div class="max-w-3xl flex flex-col gap-8">
|
|
221
|
+
<jant-nav-manager
|
|
222
|
+
items={escapeJson(itemsData)}
|
|
223
|
+
labels={escapeJson(labels)}
|
|
224
|
+
system-nav-items={escapeJson(systemNavData)}
|
|
225
|
+
available-pages={escapeJson(pagesData)}
|
|
226
|
+
site-name={siteName}
|
|
227
|
+
max-visible={headerNavMaxVisible}
|
|
228
|
+
home-default-view={homeDefaultView}
|
|
229
|
+
>
|
|
230
|
+
{/* SSR fallback: static preview until JS hydrates */}
|
|
231
|
+
<div class="nav-preview">
|
|
232
|
+
<div class="nav-preview-chrome">
|
|
233
|
+
<div class="nav-preview-dots">
|
|
234
|
+
<span />
|
|
235
|
+
<span />
|
|
236
|
+
<span />
|
|
237
|
+
</div>
|
|
238
|
+
<span class="nav-preview-label">
|
|
224
239
|
{t({
|
|
225
|
-
message: "Preview",
|
|
240
|
+
message: "Navigation Preview",
|
|
226
241
|
comment: "@context: Label for nav preview section",
|
|
227
242
|
})}
|
|
228
|
-
</
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
<circle cx="11" cy="11" r="8" />
|
|
264
|
-
<path d="m21 21-4.35-4.35" />
|
|
265
|
-
</svg>
|
|
266
|
-
</span>
|
|
267
|
-
</div>
|
|
268
|
-
</div>
|
|
269
|
-
<nav class="site-browse-nav">
|
|
270
|
-
<span class="site-browse-link site-browse-link-active">
|
|
271
|
-
{homeDefaultView === "featured"
|
|
272
|
-
? t({
|
|
273
|
-
message: "Featured",
|
|
274
|
-
comment: "@context: Browse filter label",
|
|
275
|
-
})
|
|
276
|
-
: t({
|
|
277
|
-
message: "Latest",
|
|
278
|
-
comment: "@context: Browse filter label",
|
|
279
|
-
})}
|
|
280
|
-
</span>
|
|
281
|
-
<span class="site-browse-sep" aria-hidden="true">
|
|
282
|
-
/
|
|
283
|
-
</span>
|
|
284
|
-
<span class="site-browse-link">
|
|
285
|
-
{homeDefaultView === "featured"
|
|
286
|
-
? t({
|
|
287
|
-
message: "Latest",
|
|
288
|
-
comment: "@context: Browse filter label",
|
|
289
|
-
})
|
|
290
|
-
: t({
|
|
291
|
-
message: "Featured",
|
|
292
|
-
comment: "@context: Browse filter label",
|
|
293
|
-
})}
|
|
243
|
+
</span>
|
|
244
|
+
</div>
|
|
245
|
+
<div class="nav-preview-content">
|
|
246
|
+
<div class="site-header-top">
|
|
247
|
+
<a href="/" class="site-logo">
|
|
248
|
+
{siteName}
|
|
249
|
+
</a>
|
|
250
|
+
<div class="site-header-right">
|
|
251
|
+
{navItems.length > 0 && (
|
|
252
|
+
<nav class="site-header-nav">
|
|
253
|
+
{navItems.slice(0, headerNavMaxVisible).map((item) => (
|
|
254
|
+
<a key={item.id} href={item.url} class="site-header-link">
|
|
255
|
+
{item.label}
|
|
256
|
+
</a>
|
|
257
|
+
))}
|
|
258
|
+
{navItems.length > headerNavMaxVisible && (
|
|
259
|
+
<span class="text-muted-foreground">…</span>
|
|
260
|
+
)}
|
|
261
|
+
</nav>
|
|
262
|
+
)}
|
|
263
|
+
<span class="site-header-search" aria-hidden="true">
|
|
264
|
+
<svg
|
|
265
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
266
|
+
width="16"
|
|
267
|
+
height="16"
|
|
268
|
+
viewBox="0 0 24 24"
|
|
269
|
+
fill="none"
|
|
270
|
+
stroke="currentColor"
|
|
271
|
+
stroke-width="2"
|
|
272
|
+
stroke-linecap="round"
|
|
273
|
+
stroke-linejoin="round"
|
|
274
|
+
>
|
|
275
|
+
<circle cx="11" cy="11" r="8" />
|
|
276
|
+
<path d="m21 21-4.35-4.35" />
|
|
277
|
+
</svg>
|
|
294
278
|
</span>
|
|
295
|
-
</
|
|
279
|
+
</div>
|
|
296
280
|
</div>
|
|
281
|
+
<nav class="site-browse-nav">
|
|
282
|
+
<span class="site-browse-link site-browse-link-active">
|
|
283
|
+
{homeDefaultView === "featured"
|
|
284
|
+
? t({
|
|
285
|
+
message: "Featured",
|
|
286
|
+
comment: "@context: Browse filter label",
|
|
287
|
+
})
|
|
288
|
+
: t({
|
|
289
|
+
message: "Latest",
|
|
290
|
+
comment: "@context: Browse filter label",
|
|
291
|
+
})}
|
|
292
|
+
</span>
|
|
293
|
+
<span class="site-browse-sep" aria-hidden="true">
|
|
294
|
+
/
|
|
295
|
+
</span>
|
|
296
|
+
<span class="site-browse-link">
|
|
297
|
+
{homeDefaultView === "featured"
|
|
298
|
+
? t({
|
|
299
|
+
message: "Latest",
|
|
300
|
+
comment: "@context: Browse filter label",
|
|
301
|
+
})
|
|
302
|
+
: t({
|
|
303
|
+
message: "Featured",
|
|
304
|
+
comment: "@context: Browse filter label",
|
|
305
|
+
})}
|
|
306
|
+
</span>
|
|
307
|
+
</nav>
|
|
297
308
|
</div>
|
|
298
|
-
</
|
|
299
|
-
</
|
|
300
|
-
|
|
309
|
+
</div>
|
|
310
|
+
</jant-nav-manager>
|
|
311
|
+
</div>
|
|
301
312
|
);
|
|
302
313
|
}
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
getImageUrl,
|
|
11
11
|
getPublicUrlForProvider,
|
|
12
12
|
} from "../../../lib/image.js";
|
|
13
|
+
import { UPLOAD_ACCEPT } from "../../../lib/upload.js";
|
|
13
14
|
|
|
14
15
|
function formatSize(bytes: number): string {
|
|
15
16
|
if (bytes < 1024) return `${bytes} B`;
|
|
@@ -84,11 +85,13 @@ export function MediaListContent({
|
|
|
84
85
|
r2PublicUrl,
|
|
85
86
|
imageTransformUrl,
|
|
86
87
|
s3PublicUrl,
|
|
88
|
+
uploadMaxFileSize,
|
|
87
89
|
}: {
|
|
88
90
|
mediaList: Media[];
|
|
89
91
|
r2PublicUrl?: string;
|
|
90
92
|
imageTransformUrl?: string;
|
|
91
93
|
s3PublicUrl?: string;
|
|
94
|
+
uploadMaxFileSize?: number;
|
|
92
95
|
}) {
|
|
93
96
|
const { t } = useLingui();
|
|
94
97
|
|
|
@@ -105,7 +108,7 @@ export function MediaListContent({
|
|
|
105
108
|
comment: "@context: Button to upload media file",
|
|
106
109
|
});
|
|
107
110
|
const errorText = t({
|
|
108
|
-
message: "Upload
|
|
111
|
+
message: "Upload didn't go through. Try again in a moment.",
|
|
109
112
|
comment: "@context: Upload error message",
|
|
110
113
|
});
|
|
111
114
|
|
|
@@ -131,8 +134,9 @@ export function MediaListContent({
|
|
|
131
134
|
<input
|
|
132
135
|
type="file"
|
|
133
136
|
class="hidden"
|
|
134
|
-
accept=
|
|
137
|
+
accept={UPLOAD_ACCEPT}
|
|
135
138
|
data-media-upload
|
|
139
|
+
data-max-file-size={uploadMaxFileSize ?? 500}
|
|
136
140
|
data-text-processing={processingText}
|
|
137
141
|
data-text-uploading={uploadingText}
|
|
138
142
|
data-text-error={errorText}
|
|
@@ -146,7 +150,7 @@ export function MediaListContent({
|
|
|
146
150
|
<p>
|
|
147
151
|
{t({
|
|
148
152
|
message:
|
|
149
|
-
"Images are automatically optimized
|
|
153
|
+
"Images are automatically optimized (resized, converted to WebP). Video, audio, and PDF files are uploaded as-is (max 200MB).",
|
|
150
154
|
comment:
|
|
151
155
|
"@context: Media upload instructions - auto optimization",
|
|
152
156
|
})}
|
|
@@ -160,7 +164,8 @@ export function MediaListContent({
|
|
|
160
164
|
<div id="empty-state">
|
|
161
165
|
<EmptyState
|
|
162
166
|
message={t({
|
|
163
|
-
message:
|
|
167
|
+
message:
|
|
168
|
+
"Your media library is empty. Upload your first file to get started.",
|
|
164
169
|
comment: "@context: Empty state message when no media exists",
|
|
165
170
|
})}
|
|
166
171
|
/>
|
|
@@ -178,10 +178,10 @@ export function ViewMediaContent({
|
|
|
178
178
|
comment: "@context: Button to delete media",
|
|
179
179
|
})}
|
|
180
180
|
formAction={`/dash/media/${media.id}/delete`}
|
|
181
|
-
confirmMessage="
|
|
181
|
+
confirmMessage="Delete this file permanently?"
|
|
182
182
|
description={t({
|
|
183
183
|
message:
|
|
184
|
-
"
|
|
184
|
+
"This file will be permanently removed from storage. Posts using it will show a broken link.",
|
|
185
185
|
comment: "@context: Warning message before deleting media",
|
|
186
186
|
})}
|
|
187
187
|
/>
|
|
@@ -28,7 +28,8 @@ export function PagesContent({ pages }: { pages: Page[] }) {
|
|
|
28
28
|
{pages.length === 0 ? (
|
|
29
29
|
<p class="text-sm text-muted-foreground py-4">
|
|
30
30
|
{t({
|
|
31
|
-
message:
|
|
31
|
+
message:
|
|
32
|
+
"No pages yet. Create one to add static content to your site.",
|
|
32
33
|
comment: "@context: Empty state for pages list",
|
|
33
34
|
})}
|
|
34
35
|
</p>
|
|
@@ -100,7 +100,7 @@ export const PostForm: FC<PostFormProps> = ({
|
|
|
100
100
|
comment: "@context: Remove media attachment button",
|
|
101
101
|
}),
|
|
102
102
|
mediaEmptyLabel: t({
|
|
103
|
-
message: "No media
|
|
103
|
+
message: "No media attached.",
|
|
104
104
|
comment: "@context: Post form media empty state",
|
|
105
105
|
}),
|
|
106
106
|
statusLabel: t({
|
|
@@ -115,9 +115,21 @@ export const PostForm: FC<PostFormProps> = ({
|
|
|
115
115
|
message: "Draft",
|
|
116
116
|
comment: "@context: Post status option",
|
|
117
117
|
}),
|
|
118
|
-
|
|
118
|
+
visibilityLabel: t({
|
|
119
|
+
message: "Visibility",
|
|
120
|
+
comment: "@context: Post form field - post visibility",
|
|
121
|
+
}),
|
|
122
|
+
visibilityListed: t({
|
|
123
|
+
message: "Listed",
|
|
124
|
+
comment: "@context: Visibility option - appears everywhere",
|
|
125
|
+
}),
|
|
126
|
+
visibilityFeatured: t({
|
|
119
127
|
message: "Featured",
|
|
120
|
-
comment: "@context:
|
|
128
|
+
comment: "@context: Visibility option - highlighted on featured page",
|
|
129
|
+
}),
|
|
130
|
+
visibilityUnlisted: t({
|
|
131
|
+
message: "Unlisted",
|
|
132
|
+
comment: "@context: Visibility option - hidden from feeds",
|
|
121
133
|
}),
|
|
122
134
|
pinnedLabel: t({
|
|
123
135
|
message: "Pinned",
|
|
@@ -154,15 +166,15 @@ export const PostForm: FC<PostFormProps> = ({
|
|
|
154
166
|
}),
|
|
155
167
|
submitSuccessMessage: isEdit
|
|
156
168
|
? t({
|
|
157
|
-
message: "Post updated
|
|
169
|
+
message: "Post updated.",
|
|
158
170
|
comment: "@context: Toast after editing post",
|
|
159
171
|
})
|
|
160
172
|
: t({
|
|
161
|
-
message: "Post published
|
|
173
|
+
message: "Post published.",
|
|
162
174
|
comment: "@context: Toast after creating post",
|
|
163
175
|
}),
|
|
164
176
|
submitErrorMessage: t({
|
|
165
|
-
message: "
|
|
177
|
+
message: "Couldn't save your post. Try again in a moment.",
|
|
166
178
|
comment: "@context: Toast when post save fails",
|
|
167
179
|
}),
|
|
168
180
|
}).replace(/</g, "\\u003c");
|
|
@@ -174,7 +186,7 @@ export const PostForm: FC<PostFormProps> = ({
|
|
|
174
186
|
url: post?.url ?? "",
|
|
175
187
|
quoteText: post?.quoteText ?? "",
|
|
176
188
|
status: post?.status ?? "published",
|
|
177
|
-
|
|
189
|
+
visibility: post?.visibility ?? "listed",
|
|
178
190
|
pinned: post?.pinned === 1,
|
|
179
191
|
rating: post?.rating ?? 0,
|
|
180
192
|
collectionIds: postCollectionIds,
|