@jant/core 0.3.35 → 0.3.37
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/bin/commands/export.js +1 -1
- package/bin/commands/import-site.js +529 -0
- package/bin/commands/reset-password.js +3 -2
- package/dist/client/assets/heic-to-DIRPI3VF.js +1 -0
- package/dist/client/assets/module-RjUF93sV.js +716 -0
- package/dist/client/assets/native-48B9X9Wg.js +1 -0
- package/dist/client/assets/url-FWFqPJPb.js +1 -0
- package/dist/client/client.css +1 -1
- package/dist/client/client.js +4564 -3013
- package/dist/index.js +12885 -8161
- package/package.json +23 -6
- package/src/__tests__/helpers/app.ts +10 -10
- package/src/__tests__/helpers/db.ts +91 -87
- package/src/app.tsx +157 -31
- package/src/auth.ts +20 -2
- package/src/client/archive-nav.js +187 -0
- package/src/client/audio-player.ts +478 -0
- package/src/client/audio-processor.ts +84 -0
- package/src/{lib → client}/avatar-upload.ts +4 -3
- 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/client/components/__tests__/jant-compose-dialog.test.ts +1140 -0
- package/src/client/components/__tests__/jant-compose-editor.test.ts +504 -0
- package/src/{ui → client}/components/__tests__/jant-post-form.test.ts +37 -17
- package/src/{ui → client}/components/__tests__/jant-settings-avatar.test.ts +2 -2
- package/src/{ui → client}/components/__tests__/jant-settings-general.test.ts +3 -3
- package/src/client/components/collection-sidebar-types.ts +43 -0
- package/src/{ui → client}/components/collection-types.ts +3 -4
- package/src/client/components/compose-types.ts +174 -0
- package/src/client/components/jant-collection-form.ts +667 -0
- package/src/client/components/jant-collection-sidebar.ts +805 -0
- package/src/client/components/jant-compose-dialog.ts +2161 -0
- package/src/client/components/jant-compose-editor.ts +1813 -0
- package/src/client/components/jant-compose-fullscreen.ts +283 -0
- package/src/client/components/jant-media-lightbox.ts +259 -0
- package/src/{ui → client}/components/jant-nav-manager.ts +97 -298
- package/src/{ui → client}/components/jant-post-form.ts +141 -12
- package/src/client/components/jant-post-menu.ts +1019 -0
- package/src/{ui → client}/components/jant-settings-avatar.ts +3 -3
- package/src/{ui → client}/components/jant-settings-general.ts +38 -4
- package/src/client/components/jant-text-preview.ts +232 -0
- package/src/{ui → client}/components/nav-manager-types.ts +6 -18
- package/src/{ui → client}/components/post-form-template.ts +137 -38
- package/src/{ui → client}/components/post-form-types.ts +15 -4
- package/src/client/compose-bridge.ts +583 -0
- package/src/{lib → client}/image-processor.ts +26 -8
- package/src/client/lazy-slugify.ts +51 -0
- package/src/client/media-metadata.ts +247 -0
- package/src/client/multipart-upload.ts +160 -0
- package/src/{lib → client}/nav-manager-bridge.ts +1 -1
- package/src/{lib → client}/post-form-bridge.ts +53 -2
- package/src/{lib → client}/settings-bridge.ts +3 -15
- package/src/client/thread-context.ts +140 -0
- package/src/client/tiptap/bubble-menu.ts +205 -0
- package/src/client/tiptap/create-editor.ts +86 -0
- package/src/client/tiptap/exitable-marks.ts +73 -0
- package/src/client/tiptap/extensions.ts +65 -0
- package/src/client/tiptap/image-node.ts +482 -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 +129 -0
- package/src/client/tiptap/slash-commands.ts +438 -0
- package/src/{lib → client}/toast.ts +101 -3
- package/src/client/types/sortablejs.d.ts +44 -0
- package/src/client/upload-with-metadata.ts +54 -0
- package/src/client/video-processor.ts +207 -0
- package/src/client.ts +27 -17
- package/src/db/__tests__/migrations.test.ts +118 -0
- package/src/db/index.ts +52 -0
- package/src/db/migrations/0000_baseline.sql +269 -0
- package/src/db/migrations/0001_fts_setup.sql +31 -0
- package/src/db/migrations/meta/0000_snapshot.json +703 -119
- package/src/db/migrations/meta/0001_snapshot.json +1337 -0
- package/src/db/migrations/meta/_journal.json +4 -39
- package/src/db/schema.ts +409 -140
- package/src/i18n/__tests__/detect.test.ts +115 -0
- package/src/i18n/context.tsx +2 -2
- package/src/i18n/detect.ts +85 -1
- package/src/i18n/i18n.ts +1 -1
- package/src/i18n/index.ts +2 -1
- package/src/i18n/locales/en.po +783 -1087
- package/src/i18n/locales/en.ts +1 -1
- package/src/i18n/locales/zh-Hans.po +867 -812
- package/src/i18n/locales/zh-Hans.ts +1 -1
- package/src/i18n/locales/zh-Hant.po +878 -823
- package/src/i18n/locales/zh-Hant.ts +1 -1
- package/src/i18n/middleware.ts +6 -0
- package/src/index.ts +5 -7
- package/src/lib/__tests__/blurhash-placeholder.test.ts +75 -0
- package/src/lib/__tests__/constants.test.ts +0 -1
- package/src/lib/__tests__/markdown-to-tiptap.test.ts +358 -0
- package/src/lib/__tests__/nanoid.test.ts +26 -0
- package/src/lib/__tests__/resolve-config.test.ts +2 -2
- package/src/lib/__tests__/schemas.test.ts +186 -65
- package/src/lib/__tests__/slug.test.ts +126 -0
- package/src/lib/__tests__/sse.test.ts +6 -6
- package/src/lib/__tests__/summary.test.ts +264 -0
- package/src/lib/__tests__/theme.test.ts +1 -1
- package/src/lib/__tests__/timeline.test.ts +33 -30
- package/src/lib/__tests__/tiptap-to-markdown.test.ts +346 -0
- package/src/lib/__tests__/url.test.ts +2 -2
- package/src/lib/__tests__/view.test.ts +140 -65
- package/src/lib/blurhash-placeholder.ts +102 -0
- package/src/lib/constants.ts +3 -1
- package/src/lib/emoji-catalog.ts +963 -0
- package/src/lib/errors.ts +11 -8
- package/src/lib/feed.ts +77 -31
- package/src/lib/html.ts +2 -1
- package/src/lib/icon-catalog.ts +5033 -1
- package/src/lib/icons.ts +3 -2
- package/src/lib/index.ts +0 -1
- package/src/lib/markdown-to-tiptap.ts +286 -0
- package/src/lib/media-helpers.ts +22 -12
- package/src/lib/nanoid.ts +29 -0
- package/src/lib/navigation.ts +1 -1
- package/src/lib/render.tsx +24 -5
- package/src/lib/resolve-config.ts +13 -2
- package/src/lib/schemas.ts +226 -58
- package/src/lib/search-snippet.ts +34 -0
- package/src/lib/slug.ts +96 -0
- package/src/lib/sse.ts +6 -6
- package/src/lib/storage.ts +115 -7
- package/src/lib/summary.ts +158 -0
- package/src/lib/theme.ts +11 -8
- package/src/lib/timeline.ts +76 -34
- package/src/lib/tiptap-render.ts +191 -0
- package/src/lib/tiptap-to-markdown.ts +305 -0
- package/src/lib/upload.ts +263 -14
- package/src/lib/url.ts +37 -22
- package/src/lib/view.ts +236 -55
- package/src/middleware/__tests__/auth.test.ts +191 -11
- package/src/middleware/__tests__/onboarding.test.ts +12 -10
- package/src/middleware/auth.ts +63 -9
- package/src/middleware/error-handler.ts +3 -3
- package/src/middleware/onboarding.ts +1 -1
- package/src/middleware/secure-headers.ts +40 -0
- package/src/preset.css +83 -2
- package/src/routes/__tests__/compose.test.ts +17 -24
- package/src/routes/api/__tests__/collections.test.ts +109 -61
- package/src/routes/api/__tests__/nav-items.test.ts +46 -29
- package/src/routes/api/__tests__/posts.test.ts +132 -68
- package/src/routes/api/__tests__/search.test.ts +15 -2
- package/src/routes/api/__tests__/upload-multipart.test.ts +534 -0
- package/src/routes/api/collections.ts +57 -31
- package/src/routes/api/custom-urls.ts +80 -0
- package/src/routes/api/export.ts +31 -0
- package/src/routes/api/nav-items.ts +23 -19
- package/src/routes/api/posts.ts +81 -62
- package/src/routes/api/search.ts +3 -4
- package/src/routes/api/upload-multipart.ts +245 -0
- package/src/routes/api/upload.ts +92 -24
- package/src/routes/auth/__tests__/setup.test.ts +20 -60
- package/src/routes/auth/reset.tsx +5 -4
- package/src/routes/auth/setup.tsx +39 -31
- package/src/routes/auth/signin.tsx +13 -14
- package/src/routes/compose.tsx +27 -63
- package/src/routes/dash/__tests__/settings-avatar.test.ts +44 -9
- package/src/routes/dash/custom-urls.tsx +414 -0
- package/src/routes/dash/settings.tsx +475 -99
- package/src/routes/feed/__tests__/rss.test.ts +22 -23
- package/src/routes/feed/rss.ts +6 -2
- package/src/routes/feed/sitemap.ts +2 -12
- package/src/routes/pages/__tests__/collections.test.ts +5 -6
- package/src/routes/pages/__tests__/featured.test.ts +36 -18
- package/src/routes/pages/archive.tsx +177 -37
- package/src/routes/pages/collection.tsx +43 -14
- package/src/routes/pages/collections.tsx +11 -2
- package/src/routes/pages/featured.tsx +27 -3
- package/src/routes/pages/home.tsx +15 -14
- package/src/routes/pages/latest.tsx +1 -11
- package/src/routes/pages/new.tsx +39 -0
- package/src/routes/pages/page.tsx +95 -49
- package/src/routes/pages/search.tsx +1 -1
- package/src/services/__tests__/api-token.test.ts +135 -0
- package/src/services/__tests__/collection.test.ts +275 -227
- package/src/services/__tests__/custom-url.test.ts +213 -0
- package/src/services/__tests__/media.test.ts +162 -22
- package/src/services/__tests__/navigation.test.ts +109 -68
- package/src/services/__tests__/post-timeline.test.ts +205 -32
- package/src/services/__tests__/post.test.ts +800 -230
- package/src/services/__tests__/search.test.ts +67 -10
- package/src/services/__tests__/settings.test.ts +3 -3
- package/src/services/api-token.ts +166 -0
- package/src/services/auth.ts +17 -2
- package/src/services/collection.ts +397 -131
- package/src/services/custom-url.ts +188 -0
- package/src/services/export.ts +802 -0
- package/src/services/index.ts +26 -19
- package/src/services/media.ts +100 -22
- package/src/services/navigation.ts +158 -47
- package/src/services/path.ts +339 -0
- package/src/services/post.ts +764 -172
- package/src/services/search.ts +161 -74
- package/src/services/settings.ts +6 -2
- package/src/styles/components.css +293 -62
- package/src/styles/tokens.css +93 -5
- package/src/styles/ui.css +4349 -766
- package/src/types/bindings.ts +8 -0
- package/src/types/config.ts +34 -4
- package/src/types/constants.ts +17 -2
- package/src/types/entities.ts +83 -37
- package/src/types/operations.ts +20 -27
- package/src/types/props.ts +52 -17
- package/src/types/views.ts +48 -24
- package/src/ui/color-themes.ts +133 -23
- package/src/ui/compose/ComposeDialog.tsx +255 -16
- package/src/ui/compose/ComposePrompt.tsx +1 -1
- package/src/ui/dash/CrudPageHeader.tsx +1 -1
- package/src/ui/dash/ListItemRow.tsx +1 -1
- package/src/ui/dash/StatusBadge.tsx +12 -2
- package/src/ui/dash/appearance/AdvancedContent.tsx +71 -59
- package/src/ui/dash/appearance/ColorThemeContent.tsx +48 -33
- package/src/ui/dash/appearance/FontThemeContent.tsx +65 -73
- package/src/ui/dash/appearance/NavigationContent.tsx +106 -135
- package/src/ui/dash/index.ts +0 -3
- package/src/ui/dash/settings/AccountContent.tsx +87 -146
- package/src/ui/dash/settings/AccountMenuContent.tsx +147 -0
- package/src/ui/dash/settings/ApiTokensContent.tsx +232 -0
- package/src/ui/dash/settings/AvatarContent.tsx +78 -0
- package/src/ui/dash/settings/GeneralContent.tsx +3 -62
- package/src/ui/dash/settings/SessionsContent.tsx +159 -0
- package/src/ui/dash/settings/SettingsRootContent.tsx +266 -0
- package/src/ui/feed/LinkCard.tsx +89 -40
- package/src/ui/feed/NoteCard.tsx +39 -25
- package/src/ui/feed/PostStatusBadges.tsx +67 -0
- package/src/ui/feed/QuoteCard.tsx +38 -23
- package/src/ui/feed/ThreadPreview.tsx +90 -26
- package/src/ui/feed/TimelineFeed.tsx +3 -2
- package/src/ui/feed/TimelineItem.tsx +15 -6
- package/src/ui/feed/__tests__/thread-preview.test.ts +107 -0
- package/src/ui/feed/thread-preview-state.ts +61 -0
- package/src/ui/font-themes.ts +2 -2
- package/src/ui/layouts/BaseLayout.tsx +2 -2
- package/src/ui/layouts/SiteLayout.tsx +116 -103
- package/src/ui/pages/ArchivePage.tsx +923 -95
- package/src/ui/pages/CollectionPage.tsx +6 -35
- package/src/ui/pages/CollectionsPage.tsx +2 -1
- package/src/ui/pages/ComposePage.tsx +54 -0
- package/src/ui/pages/FeaturedPage.tsx +2 -1
- package/src/ui/pages/HomePage.tsx +1 -1
- package/src/ui/pages/PostPage.tsx +30 -45
- package/src/ui/pages/SearchPage.tsx +182 -38
- package/src/ui/shared/AdminBreadcrumb.tsx +29 -0
- package/src/ui/shared/CollectionsSidebar.tsx +239 -4
- package/src/ui/shared/MediaGallery.tsx +475 -41
- package/src/ui/shared/PostFooter.tsx +204 -0
- package/src/ui/shared/StarRating.tsx +27 -0
- package/src/ui/shared/__tests__/format-chars.test.ts +35 -0
- package/src/ui/shared/index.ts +0 -1
- package/src/db/migrations/0000_square_wallflower.sql +0 -118
- package/src/db/migrations/0001_add_search_fts.sql +0 -34
- package/src/db/migrations/0002_add_media_attachments.sql +0 -3
- package/src/db/migrations/0003_add_navigation_links.sql +0 -8
- package/src/db/migrations/0004_add_storage_provider.sql +0 -3
- package/src/db/migrations/0005_v2_schema_migration.sql +0 -268
- package/src/db/migrations/0006_rename_slug_to_path.sql +0 -5
- package/src/db/migrations/0007_post_collections_m2m.sql +0 -94
- package/src/db/migrations/0008_add_collection_dividers.sql +0 -8
- package/src/db/migrations/0009_drop_collection_show_divider.sql +0 -2
- package/src/db/migrations/0010_add_performance_indexes.sql +0 -16
- package/src/db/migrations/0011_add_path_registry.sql +0 -23
- package/src/db/migrations/meta/0003_snapshot.json +0 -821
- package/src/lib/__tests__/sqid.test.ts +0 -65
- package/src/lib/collections-reorder.ts +0 -28
- package/src/lib/compose-bridge.ts +0 -280
- package/src/lib/media-upload.ts +0 -148
- package/src/lib/sqid.ts +0 -79
- package/src/routes/api/__tests__/pages.test.ts +0 -218
- package/src/routes/api/pages.ts +0 -73
- package/src/routes/dash/__tests__/pages.test.ts +0 -226
- package/src/routes/dash/appearance.tsx +0 -240
- package/src/routes/dash/collections.tsx +0 -211
- package/src/routes/dash/index.tsx +0 -103
- package/src/routes/dash/media.tsx +0 -132
- package/src/routes/dash/pages.tsx +0 -239
- package/src/routes/dash/posts.tsx +0 -334
- package/src/routes/dash/redirects.tsx +0 -257
- package/src/routes/pages/post.tsx +0 -59
- package/src/services/__tests__/page.test.ts +0 -298
- package/src/services/__tests__/path-registry.test.ts +0 -165
- package/src/services/__tests__/redirect.test.ts +0 -159
- package/src/services/page.ts +0 -203
- package/src/services/path-registry.ts +0 -160
- package/src/services/redirect.ts +0 -97
- package/src/types/sortablejs.d.ts +0 -29
- package/src/ui/components/__tests__/jant-compose-dialog.test.ts +0 -512
- package/src/ui/components/__tests__/jant-compose-editor.test.ts +0 -272
- package/src/ui/components/compose-types.ts +0 -75
- package/src/ui/components/jant-collection-form.ts +0 -512
- package/src/ui/components/jant-compose-dialog.ts +0 -495
- package/src/ui/components/jant-compose-editor.ts +0 -814
- package/src/ui/dash/PageForm.tsx +0 -185
- package/src/ui/dash/PostList.tsx +0 -95
- 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/media/MediaListContent.tsx +0 -201
- package/src/ui/dash/media/ViewMediaContent.tsx +0 -208
- package/src/ui/dash/pages/PagesContent.tsx +0 -74
- package/src/ui/dash/posts/PostForm.tsx +0 -248
- package/src/ui/dash/settings/SettingsNav.tsx +0 -52
- package/src/ui/layouts/DashLayout.tsx +0 -165
- package/src/ui/pages/SinglePage.tsx +0 -23
- package/src/ui/shared/ThreadView.tsx +0 -136
- /package/src/{ui → client}/components/settings-types.ts +0 -0
|
@@ -15,9 +15,22 @@ import { useLingui } from "@lingui/react/macro";
|
|
|
15
15
|
|
|
16
16
|
export interface ComposeDialogProps {
|
|
17
17
|
collections?: Collection[];
|
|
18
|
+
uploadMaxFileSize?: number;
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
export
|
|
21
|
+
export interface ComposeFormProps extends ComposeDialogProps {
|
|
22
|
+
pageMode?: boolean;
|
|
23
|
+
closeHref?: string;
|
|
24
|
+
autoRestoreDraft?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export const ComposeForm: FC<ComposeFormProps> = ({
|
|
28
|
+
collections,
|
|
29
|
+
uploadMaxFileSize,
|
|
30
|
+
pageMode = false,
|
|
31
|
+
closeHref,
|
|
32
|
+
autoRestoreDraft = false,
|
|
33
|
+
}) => {
|
|
21
34
|
const { t } = useLingui();
|
|
22
35
|
|
|
23
36
|
const labels = JSON.stringify({
|
|
@@ -70,7 +83,7 @@ export const ComposeDialog: FC<ComposeDialogProps> = ({ collections }) => {
|
|
|
70
83
|
comment: "@context: Compose quote source link placeholder",
|
|
71
84
|
}),
|
|
72
85
|
attachedText: t({
|
|
73
|
-
message: "
|
|
86
|
+
message: "Text attachment",
|
|
74
87
|
comment: "@context: Attached text panel title",
|
|
75
88
|
}),
|
|
76
89
|
attachedTextPlaceholder: t({
|
|
@@ -90,9 +103,13 @@ export const ComposeDialog: FC<ComposeDialogProps> = ({ collections }) => {
|
|
|
90
103
|
message: "Media",
|
|
91
104
|
comment: "@context: Compose toolbar - media tooltip",
|
|
92
105
|
}),
|
|
93
|
-
|
|
94
|
-
message: "
|
|
95
|
-
comment: "@context: Compose toolbar -
|
|
106
|
+
rate: t({
|
|
107
|
+
message: "Rate",
|
|
108
|
+
comment: "@context: Compose toolbar - rate tooltip",
|
|
109
|
+
}),
|
|
110
|
+
emoji: t({
|
|
111
|
+
message: "Emoji",
|
|
112
|
+
comment: "@context: Compose toolbar - emoji picker tooltip",
|
|
96
113
|
}),
|
|
97
114
|
title: t({
|
|
98
115
|
message: "Title",
|
|
@@ -107,8 +124,14 @@ export const ComposeDialog: FC<ComposeDialogProps> = ({ collections }) => {
|
|
|
107
124
|
comment: "@context: Compose collection combobox search placeholder",
|
|
108
125
|
}),
|
|
109
126
|
noCollections: t({
|
|
110
|
-
message: "No collections
|
|
111
|
-
comment:
|
|
127
|
+
message: "No matching collections.",
|
|
128
|
+
comment:
|
|
129
|
+
"@context: Compose collection combobox empty state when search has no results",
|
|
130
|
+
}),
|
|
131
|
+
emptyCollections: t({
|
|
132
|
+
message: "Create a collection to get started.",
|
|
133
|
+
comment:
|
|
134
|
+
"@context: Compose collection combobox empty state when no collections exist",
|
|
112
135
|
}),
|
|
113
136
|
post: t({
|
|
114
137
|
message: "Post",
|
|
@@ -127,7 +150,7 @@ export const ComposeDialog: FC<ComposeDialogProps> = ({ collections }) => {
|
|
|
127
150
|
comment: "@context: Alt text textarea placeholder",
|
|
128
151
|
}),
|
|
129
152
|
altHint: t({
|
|
130
|
-
message: "
|
|
153
|
+
message: "Helps screen readers describe the image",
|
|
131
154
|
comment: "@context: Hint text in alt text panel",
|
|
132
155
|
}),
|
|
133
156
|
addMore: t({
|
|
@@ -142,6 +165,203 @@ export const ComposeDialog: FC<ComposeDialogProps> = ({ collections }) => {
|
|
|
142
165
|
message: "Published!",
|
|
143
166
|
comment: "@context: Toast shown after successful deferred publish",
|
|
144
167
|
}),
|
|
168
|
+
view: t({
|
|
169
|
+
message: "View",
|
|
170
|
+
comment: "@context: Toast action button to view the published post",
|
|
171
|
+
}),
|
|
172
|
+
retryAll: t({
|
|
173
|
+
message: "Tap to retry",
|
|
174
|
+
comment:
|
|
175
|
+
"@context: Label on failed upload overlay button, tells user tapping retries the upload",
|
|
176
|
+
}),
|
|
177
|
+
editPost: t({
|
|
178
|
+
message: "Edit post",
|
|
179
|
+
comment: "@context: Compose dialog header title in edit mode",
|
|
180
|
+
}),
|
|
181
|
+
update: t({
|
|
182
|
+
message: "Done",
|
|
183
|
+
comment: "@context: Compose button - update existing post",
|
|
184
|
+
}),
|
|
185
|
+
confirmCloseTitle: t({
|
|
186
|
+
message: "Save to drafts?",
|
|
187
|
+
comment: "@context: Confirm close action sheet title",
|
|
188
|
+
}),
|
|
189
|
+
confirmCloseSubtitle: t({
|
|
190
|
+
message: "Save to drafts to edit and post at a later time.",
|
|
191
|
+
comment: "@context: Confirm close action sheet subtitle",
|
|
192
|
+
}),
|
|
193
|
+
confirmCloseSave: t({
|
|
194
|
+
message: "Save",
|
|
195
|
+
comment: "@context: Confirm close action sheet - save draft button",
|
|
196
|
+
}),
|
|
197
|
+
confirmCloseCancel: t({
|
|
198
|
+
message: "Cancel",
|
|
199
|
+
comment:
|
|
200
|
+
"@context: Confirm close action sheet - cancel and return to editor",
|
|
201
|
+
}),
|
|
202
|
+
confirmCloseDiscard: t({
|
|
203
|
+
message: "Don't save",
|
|
204
|
+
comment: "@context: Confirm close action sheet - discard button",
|
|
205
|
+
}),
|
|
206
|
+
confirmEditTitle: t({
|
|
207
|
+
message: "You have unsaved changes",
|
|
208
|
+
comment:
|
|
209
|
+
"@context: Confirm close action sheet title when editing a published post",
|
|
210
|
+
}),
|
|
211
|
+
confirmEditSubtitle: t({
|
|
212
|
+
message: "Do you want to publish your changes or discard them?",
|
|
213
|
+
comment:
|
|
214
|
+
"@context: Confirm close action sheet subtitle when editing a published post",
|
|
215
|
+
}),
|
|
216
|
+
confirmEditPublish: t({
|
|
217
|
+
message: "Publish",
|
|
218
|
+
comment:
|
|
219
|
+
"@context: Confirm close action sheet - publish update button for editing published post",
|
|
220
|
+
}),
|
|
221
|
+
confirmEditDiscard: t({
|
|
222
|
+
message: "Discard",
|
|
223
|
+
comment:
|
|
224
|
+
"@context: Confirm close action sheet - discard changes button for editing published post",
|
|
225
|
+
}),
|
|
226
|
+
drafts: t({ message: "Drafts", comment: "@context: Drafts panel title" }),
|
|
227
|
+
draftsEmpty: t({
|
|
228
|
+
message: "No drafts yet. Save a draft to find it here.",
|
|
229
|
+
comment: "@context: Drafts panel empty state",
|
|
230
|
+
}),
|
|
231
|
+
deleteDraft: t({
|
|
232
|
+
message: "Delete Draft",
|
|
233
|
+
comment: "@context: Draft item action",
|
|
234
|
+
}),
|
|
235
|
+
draftDeleted: t({
|
|
236
|
+
message: "Draft deleted.",
|
|
237
|
+
comment: "@context: Toast after draft deletion",
|
|
238
|
+
}),
|
|
239
|
+
publishFailedDraft: t({
|
|
240
|
+
message: "Couldn't publish. Saved as draft.",
|
|
241
|
+
comment:
|
|
242
|
+
"@context: Toast when publish fails and post is auto-saved as draft",
|
|
243
|
+
}),
|
|
244
|
+
uploadFailedDraft: t({
|
|
245
|
+
message: "Some uploads failed. Saved as draft.",
|
|
246
|
+
comment:
|
|
247
|
+
"@context: Toast when uploads fail and post is auto-saved as draft",
|
|
248
|
+
}),
|
|
249
|
+
reply: t({
|
|
250
|
+
message: "Reply",
|
|
251
|
+
comment: "@context: Compose button - reply to post",
|
|
252
|
+
}),
|
|
253
|
+
publishFeatured: t({
|
|
254
|
+
message: "Post as Featured",
|
|
255
|
+
comment:
|
|
256
|
+
"@context: Compose dropdown option - publish post and mark it as featured",
|
|
257
|
+
}),
|
|
258
|
+
publishUnlisted: t({
|
|
259
|
+
message: "Post Unlisted",
|
|
260
|
+
comment:
|
|
261
|
+
"@context: Compose dropdown option - publish post with unlisted visibility, hidden from main feed",
|
|
262
|
+
}),
|
|
263
|
+
publishPrivate: t({
|
|
264
|
+
message: "Post as Private",
|
|
265
|
+
comment:
|
|
266
|
+
"@context: Compose dropdown option - publish post visible only when logged in",
|
|
267
|
+
}),
|
|
268
|
+
showMore: t({
|
|
269
|
+
message: "Show more",
|
|
270
|
+
comment: "@context: Expand reply context",
|
|
271
|
+
}),
|
|
272
|
+
showLess: t({
|
|
273
|
+
message: "Show less",
|
|
274
|
+
comment: "@context: Collapse reply context",
|
|
275
|
+
}),
|
|
276
|
+
addCollection: t({
|
|
277
|
+
message: "Add Collection",
|
|
278
|
+
comment: "@context: Action to create a new collection from compose",
|
|
279
|
+
}),
|
|
280
|
+
collectionCountLabel: t({
|
|
281
|
+
message: "%name% + %count% more",
|
|
282
|
+
comment:
|
|
283
|
+
"@context: Compose collection trigger label when multiple collections selected. %name% is the first collection name, %count% is how many more",
|
|
284
|
+
}),
|
|
285
|
+
draftRestored: t({
|
|
286
|
+
message: "Draft restored.",
|
|
287
|
+
comment:
|
|
288
|
+
"@context: Toast shown when a local draft is restored on compose open",
|
|
289
|
+
}),
|
|
290
|
+
collectionFormLabels: {
|
|
291
|
+
titleLabel: t({
|
|
292
|
+
message: "Title",
|
|
293
|
+
comment: "@context: Collection form field",
|
|
294
|
+
}),
|
|
295
|
+
titlePlaceholder: t({
|
|
296
|
+
message: "My Collection",
|
|
297
|
+
comment: "@context: Collection title placeholder",
|
|
298
|
+
}),
|
|
299
|
+
slugLabel: t({
|
|
300
|
+
message: "Slug",
|
|
301
|
+
comment: "@context: Collection form field",
|
|
302
|
+
}),
|
|
303
|
+
slugHelp: t({
|
|
304
|
+
message:
|
|
305
|
+
"URL-safe identifier (lowercase, numbers, hyphens). For CJK titles, slug will be auto-generated on the server.",
|
|
306
|
+
comment: "@context: Collection path help text",
|
|
307
|
+
}),
|
|
308
|
+
descriptionLabel: t({
|
|
309
|
+
message: "Description (optional)",
|
|
310
|
+
comment: "@context: Collection form field",
|
|
311
|
+
}),
|
|
312
|
+
descriptionPlaceholder: t({
|
|
313
|
+
message: "What's this collection about?",
|
|
314
|
+
comment: "@context: Collection description placeholder",
|
|
315
|
+
}),
|
|
316
|
+
removeIcon: t({
|
|
317
|
+
message: "Remove",
|
|
318
|
+
comment: "@context: Button to remove icon",
|
|
319
|
+
}),
|
|
320
|
+
iconsTab: t({
|
|
321
|
+
message: "Icons",
|
|
322
|
+
comment: "@context: Icon picker tab label",
|
|
323
|
+
}),
|
|
324
|
+
emojisTab: t({
|
|
325
|
+
message: "Emojis",
|
|
326
|
+
comment: "@context: Emoji picker tab label",
|
|
327
|
+
}),
|
|
328
|
+
searchIconsPlaceholder: t({
|
|
329
|
+
message: "Search icons...",
|
|
330
|
+
comment: "@context: Icon picker search placeholder",
|
|
331
|
+
}),
|
|
332
|
+
searchEmojisPlaceholder: t({
|
|
333
|
+
message: "Search emojis...",
|
|
334
|
+
comment: "@context: Emoji picker search placeholder",
|
|
335
|
+
}),
|
|
336
|
+
sortOrderLabel: t({
|
|
337
|
+
message: "Sort Order",
|
|
338
|
+
comment: "@context: Collection form field",
|
|
339
|
+
}),
|
|
340
|
+
sortNewest: t({
|
|
341
|
+
message: "Newest first",
|
|
342
|
+
comment: "@context: Collection sort order option",
|
|
343
|
+
}),
|
|
344
|
+
sortOldest: t({
|
|
345
|
+
message: "Oldest first",
|
|
346
|
+
comment: "@context: Collection sort order option",
|
|
347
|
+
}),
|
|
348
|
+
sortRatingDesc: t({
|
|
349
|
+
message: "Highest rated",
|
|
350
|
+
comment: "@context: Collection sort order option",
|
|
351
|
+
}),
|
|
352
|
+
sortRatingAsc: t({
|
|
353
|
+
message: "Lowest rated",
|
|
354
|
+
comment: "@context: Collection sort order option",
|
|
355
|
+
}),
|
|
356
|
+
submitLabel: t({
|
|
357
|
+
message: "Save",
|
|
358
|
+
comment: "@context: Button to save collection",
|
|
359
|
+
}),
|
|
360
|
+
cancelLabel: t({
|
|
361
|
+
message: "Cancel",
|
|
362
|
+
comment: "@context: Button to cancel form",
|
|
363
|
+
}),
|
|
364
|
+
},
|
|
145
365
|
}).replace(/</g, "\\u003c");
|
|
146
366
|
|
|
147
367
|
const collectionsJson = JSON.stringify(
|
|
@@ -152,19 +372,38 @@ export const ComposeDialog: FC<ComposeDialogProps> = ({ collections }) => {
|
|
|
152
372
|
})),
|
|
153
373
|
).replace(/</g, "\\u003c");
|
|
154
374
|
|
|
375
|
+
return (
|
|
376
|
+
<jant-compose-dialog
|
|
377
|
+
collections={collectionsJson}
|
|
378
|
+
labels={labels}
|
|
379
|
+
upload-max-file-size={uploadMaxFileSize ?? 500}
|
|
380
|
+
{...(pageMode ? { "page-mode": "" } : {})}
|
|
381
|
+
{...(closeHref ? { "close-href": closeHref } : {})}
|
|
382
|
+
{...(autoRestoreDraft ? { "auto-restore-draft": "" } : {})}
|
|
383
|
+
>
|
|
384
|
+
{/* SSR fallback skeleton */}
|
|
385
|
+
<div class="compose-dialog-inner">
|
|
386
|
+
<div class="compose-dialog-header" />
|
|
387
|
+
<div class="compose-body skel-section-md" />
|
|
388
|
+
</div>
|
|
389
|
+
</jant-compose-dialog>
|
|
390
|
+
);
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
export const ComposeDialog: FC<ComposeDialogProps> = ({
|
|
394
|
+
collections,
|
|
395
|
+
uploadMaxFileSize,
|
|
396
|
+
}) => {
|
|
155
397
|
return (
|
|
156
398
|
<dialog
|
|
157
399
|
id="compose-dialog"
|
|
158
400
|
class="compose-dialog"
|
|
159
|
-
|
|
401
|
+
data-on:click="evt.target === el && el.querySelector('jant-compose-dialog')?.requestClose()"
|
|
160
402
|
>
|
|
161
|
-
<
|
|
162
|
-
{
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
<div class="compose-body skel-section-md" />
|
|
166
|
-
</div>
|
|
167
|
-
</jant-compose-dialog>
|
|
403
|
+
<ComposeForm
|
|
404
|
+
collections={collections}
|
|
405
|
+
uploadMaxFileSize={uploadMaxFileSize}
|
|
406
|
+
/>
|
|
168
407
|
</dialog>
|
|
169
408
|
);
|
|
170
409
|
};
|
|
@@ -16,7 +16,7 @@ export const ComposePrompt: FC = () => {
|
|
|
16
16
|
<button
|
|
17
17
|
type="button"
|
|
18
18
|
class="compose-prompt-trigger"
|
|
19
|
-
|
|
19
|
+
data-on:click="document.getElementById('compose-dialog').querySelector('jant-compose-dialog')?.restoreLocalDraft(); document.getElementById('compose-dialog').showModal(); document.getElementById('compose-dialog').querySelector('jant-compose-editor')?.focusInput()"
|
|
20
20
|
>
|
|
21
21
|
<span class="compose-prompt-avatar">
|
|
22
22
|
<svg
|
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Status Badge Component
|
|
3
3
|
*
|
|
4
|
-
* Displays badges for post status,
|
|
4
|
+
* Displays badges for post status, visibility, and pinned state.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import type { FC } from "hono/jsx";
|
|
8
8
|
import { useLingui } from "@lingui/react/macro";
|
|
9
|
-
import type { Status } from "../../types.js";
|
|
9
|
+
import type { Status, Visibility } from "../../types.js";
|
|
10
10
|
|
|
11
11
|
export interface StatusBadgeProps {
|
|
12
12
|
status: Status;
|
|
13
|
+
visibility?: Visibility;
|
|
13
14
|
featured?: boolean;
|
|
14
15
|
pinned?: boolean;
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
export const StatusBadge: FC<StatusBadgeProps> = ({
|
|
18
19
|
status,
|
|
20
|
+
visibility,
|
|
19
21
|
featured,
|
|
20
22
|
pinned,
|
|
21
23
|
}) => {
|
|
@@ -48,6 +50,14 @@ export const StatusBadge: FC<StatusBadgeProps> = ({
|
|
|
48
50
|
})}
|
|
49
51
|
</span>
|
|
50
52
|
)}
|
|
53
|
+
{visibility === "unlisted" && (
|
|
54
|
+
<span class="badge-outline">
|
|
55
|
+
{t({
|
|
56
|
+
message: "Unlisted",
|
|
57
|
+
comment: "@context: Post badge - unlisted",
|
|
58
|
+
})}
|
|
59
|
+
</span>
|
|
60
|
+
)}
|
|
51
61
|
{pinned && (
|
|
52
62
|
<span class="badge-outline">
|
|
53
63
|
{t({
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { useLingui } from "@lingui/react/macro";
|
|
6
|
-
|
|
6
|
+
|
|
7
|
+
const THEMING_DOCS_URL =
|
|
8
|
+
"https://github.com/jant-me/jant/blob/main/docs/theming.md";
|
|
7
9
|
|
|
8
10
|
export function AdvancedContent({ customCSS }: { customCSS: string }) {
|
|
9
11
|
const { t } = useLingui();
|
|
@@ -11,67 +13,77 @@ export function AdvancedContent({ customCSS }: { customCSS: string }) {
|
|
|
11
13
|
const cssSignals = JSON.stringify({ customCSS }).replace(/</g, "\\u003c");
|
|
12
14
|
|
|
13
15
|
return (
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
class="
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
16
|
+
<form
|
|
17
|
+
data-signals={cssSignals}
|
|
18
|
+
data-on:submit__prevent="@post('/settings/custom-css')"
|
|
19
|
+
data-indicator="_cssLoading"
|
|
20
|
+
class="max-w-3xl"
|
|
21
|
+
>
|
|
22
|
+
<fieldset>
|
|
23
|
+
<legend class="text-lg font-semibold">
|
|
24
|
+
{t({
|
|
25
|
+
message: "Custom CSS",
|
|
26
|
+
comment: "@context: Appearance settings heading for custom CSS",
|
|
27
|
+
})}
|
|
28
|
+
</legend>
|
|
29
|
+
<p class="text-sm text-muted-foreground mb-4">
|
|
30
|
+
{t({
|
|
31
|
+
message:
|
|
32
|
+
"Add custom CSS to override any styles. Use data attributes like [data-page], [data-post], [data-format] to target specific elements.",
|
|
33
|
+
comment: "@context: Custom CSS settings description",
|
|
34
|
+
})}{" "}
|
|
35
|
+
<a
|
|
36
|
+
href={THEMING_DOCS_URL}
|
|
37
|
+
target="_blank"
|
|
38
|
+
rel="noopener noreferrer"
|
|
39
|
+
class="underline hover:text-foreground transition-colors"
|
|
40
|
+
>
|
|
31
41
|
{t({
|
|
32
|
-
message:
|
|
33
|
-
|
|
34
|
-
|
|
42
|
+
message: "Theming guide",
|
|
43
|
+
comment:
|
|
44
|
+
"@context: Link to theming documentation on Custom CSS page",
|
|
35
45
|
})}
|
|
36
|
-
</
|
|
37
|
-
|
|
38
|
-
data-bind="customCSS"
|
|
39
|
-
class="textarea font-mono text-sm min-h-32"
|
|
40
|
-
rows={8}
|
|
41
|
-
placeholder={t({
|
|
42
|
-
message: "/* Your custom CSS here */",
|
|
43
|
-
comment: "@context: Custom CSS textarea placeholder",
|
|
44
|
-
})}
|
|
45
|
-
>
|
|
46
|
-
{customCSS}
|
|
47
|
-
</textarea>
|
|
48
|
-
</fieldset>
|
|
49
|
-
<button
|
|
50
|
-
type="submit"
|
|
51
|
-
class="btn mt-4"
|
|
52
|
-
data-attr:disabled="$_cssLoading"
|
|
53
|
-
>
|
|
54
|
-
<svg
|
|
55
|
-
data-show="$_cssLoading"
|
|
56
|
-
style="display:none"
|
|
57
|
-
class="animate-spin size-4"
|
|
58
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
59
|
-
viewBox="0 0 24 24"
|
|
60
|
-
fill="none"
|
|
61
|
-
stroke="currentColor"
|
|
62
|
-
stroke-width="2"
|
|
63
|
-
stroke-linecap="round"
|
|
64
|
-
stroke-linejoin="round"
|
|
65
|
-
role="status"
|
|
66
|
-
>
|
|
67
|
-
<path d="M21 12a9 9 0 1 1-6.219-8.56" />
|
|
68
|
-
</svg>
|
|
46
|
+
</a>
|
|
47
|
+
{" — "}
|
|
69
48
|
{t({
|
|
70
|
-
message: "
|
|
71
|
-
comment:
|
|
49
|
+
message: "available CSS variables, data attributes, and examples.",
|
|
50
|
+
comment:
|
|
51
|
+
"@context: Description after theming guide link on Custom CSS page",
|
|
72
52
|
})}
|
|
73
|
-
</
|
|
74
|
-
|
|
75
|
-
|
|
53
|
+
</p>
|
|
54
|
+
<textarea
|
|
55
|
+
data-bind="customCSS"
|
|
56
|
+
class="textarea font-mono text-sm min-h-32"
|
|
57
|
+
rows={8}
|
|
58
|
+
placeholder={t({
|
|
59
|
+
message: "/* Your custom CSS here */",
|
|
60
|
+
comment: "@context: Custom CSS textarea placeholder",
|
|
61
|
+
})}
|
|
62
|
+
>
|
|
63
|
+
{customCSS}
|
|
64
|
+
</textarea>
|
|
65
|
+
</fieldset>
|
|
66
|
+
<button type="submit" class="btn mt-4" data-attr:disabled="$_cssLoading">
|
|
67
|
+
<svg
|
|
68
|
+
data-show="$_cssLoading"
|
|
69
|
+
style="display:none"
|
|
70
|
+
class="animate-spin size-4"
|
|
71
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
72
|
+
viewBox="0 0 24 24"
|
|
73
|
+
fill="none"
|
|
74
|
+
stroke="currentColor"
|
|
75
|
+
stroke-width="2"
|
|
76
|
+
stroke-linecap="round"
|
|
77
|
+
stroke-linejoin="round"
|
|
78
|
+
role="status"
|
|
79
|
+
>
|
|
80
|
+
<path d="M21 12a9 9 0 1 1-6.219-8.56" />
|
|
81
|
+
</svg>
|
|
82
|
+
{t({
|
|
83
|
+
message: "Save CSS",
|
|
84
|
+
comment: "@context: Button to save custom CSS",
|
|
85
|
+
})}
|
|
86
|
+
</button>
|
|
87
|
+
</form>
|
|
76
88
|
);
|
|
77
89
|
}
|
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
|
|
5
5
|
import { useLingui } from "@lingui/react/macro";
|
|
6
6
|
import type { ColorTheme } from "../../color-themes.js";
|
|
7
|
-
import { AppearanceNav } from "./AppearanceNav.js";
|
|
8
7
|
|
|
9
8
|
function ThemeCard({
|
|
10
9
|
theme,
|
|
@@ -87,40 +86,56 @@ export function ColorThemeContent({
|
|
|
87
86
|
);
|
|
88
87
|
|
|
89
88
|
return (
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
class="
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
89
|
+
<div
|
|
90
|
+
data-signals={themeSignals}
|
|
91
|
+
data-on:change="@post('/settings/color-theme')"
|
|
92
|
+
class="max-w-3xl"
|
|
93
|
+
>
|
|
94
|
+
<fieldset>
|
|
95
|
+
<legend class="text-lg font-semibold">
|
|
96
|
+
{t({
|
|
97
|
+
message: "Color theme",
|
|
98
|
+
comment: "@context: Appearance settings heading",
|
|
99
|
+
})}
|
|
100
|
+
</legend>
|
|
101
|
+
<p class="text-sm text-muted-foreground mb-4">
|
|
102
|
+
{t({
|
|
103
|
+
message:
|
|
104
|
+
"Applies to your entire site, including admin pages. All themes support dark mode.",
|
|
105
|
+
comment: "@context: Appearance settings description",
|
|
106
|
+
})}{" "}
|
|
107
|
+
{t({
|
|
108
|
+
message: "Want more control?",
|
|
109
|
+
comment:
|
|
110
|
+
"@context: Prefix before Custom CSS link on color theme page",
|
|
111
|
+
})}{" "}
|
|
112
|
+
<a
|
|
113
|
+
href="/settings/custom-css"
|
|
114
|
+
class="underline hover:text-foreground transition-colors"
|
|
115
|
+
>
|
|
106
116
|
{t({
|
|
107
|
-
message:
|
|
108
|
-
|
|
109
|
-
|
|
117
|
+
message: "Custom CSS",
|
|
118
|
+
comment:
|
|
119
|
+
"@context: Link to Custom CSS settings from color theme page",
|
|
110
120
|
})}
|
|
111
|
-
</
|
|
121
|
+
</a>{" "}
|
|
122
|
+
{t({
|
|
123
|
+
message: "lets you override any theme variable.",
|
|
124
|
+
comment:
|
|
125
|
+
"@context: Suffix after Custom CSS link on color theme page",
|
|
126
|
+
})}
|
|
127
|
+
</p>
|
|
112
128
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
</>
|
|
129
|
+
<div class="flex flex-col gap-4">
|
|
130
|
+
{themes.map((theme) => (
|
|
131
|
+
<ThemeCard
|
|
132
|
+
key={theme.id}
|
|
133
|
+
theme={theme}
|
|
134
|
+
selected={theme.id === currentThemeId}
|
|
135
|
+
/>
|
|
136
|
+
))}
|
|
137
|
+
</div>
|
|
138
|
+
</fieldset>
|
|
139
|
+
</div>
|
|
125
140
|
);
|
|
126
141
|
}
|