@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.
Files changed (156) hide show
  1. package/dist/client/assets/module-RjUF93sV.js +716 -0
  2. package/dist/client/assets/native-48B9X9Wg.js +1 -0
  3. package/dist/client/assets/url-8Dj-5CLW.js +1 -0
  4. package/dist/client/client.css +1 -1
  5. package/dist/client/client.js +3109 -2294
  6. package/dist/index.js +3026 -2778
  7. package/package.json +13 -4
  8. package/src/__tests__/helpers/app.ts +1 -1
  9. package/src/__tests__/helpers/db.ts +6 -0
  10. package/src/app.tsx +1 -5
  11. package/src/{lib → client}/avatar-upload.ts +1 -1
  12. package/src/{lib → client}/collection-form-bridge.ts +2 -2
  13. package/src/{ui → client}/components/__tests__/jant-collection-form.test.ts +26 -9
  14. package/src/{ui → client}/components/__tests__/jant-compose-dialog.test.ts +46 -14
  15. package/src/{ui → client}/components/__tests__/jant-compose-editor.test.ts +64 -24
  16. package/src/{ui → client}/components/__tests__/jant-post-form.test.ts +24 -14
  17. package/src/{ui → client}/components/__tests__/jant-settings-general.test.ts +3 -3
  18. package/src/client/components/collection-sidebar-types.ts +45 -0
  19. package/src/{ui → client}/components/collection-types.ts +3 -4
  20. package/src/{ui → client}/components/compose-types.ts +3 -1
  21. package/src/{ui → client}/components/jant-collection-form.ts +301 -182
  22. package/src/client/components/jant-collection-sidebar.ts +801 -0
  23. package/src/{ui → client}/components/jant-compose-dialog.ts +231 -1
  24. package/src/client/components/jant-compose-editor.ts +1249 -0
  25. package/src/client/components/jant-compose-fullscreen.ts +338 -0
  26. package/src/client/components/jant-media-lightbox.ts +257 -0
  27. package/src/{ui → client}/components/jant-nav-manager.ts +143 -84
  28. package/src/{ui → client}/components/jant-post-form.ts +57 -8
  29. package/src/{ui → client}/components/jant-settings-general.ts +2 -2
  30. package/src/{ui → client}/components/nav-manager-types.ts +3 -0
  31. package/src/{ui → client}/components/post-form-template.ts +35 -31
  32. package/src/{ui → client}/components/post-form-types.ts +7 -3
  33. package/src/{lib → client}/compose-bridge.ts +9 -7
  34. package/src/client/lazy-slugify.ts +51 -0
  35. package/src/{lib → client}/media-upload.ts +16 -3
  36. package/src/{lib → client}/nav-manager-bridge.ts +1 -1
  37. package/src/client/page-slug-bridge.ts +42 -0
  38. package/src/{lib → client}/post-form-bridge.ts +2 -2
  39. package/src/{lib → client}/settings-bridge.ts +3 -3
  40. package/src/client/tiptap/bubble-menu.ts +205 -0
  41. package/src/client/tiptap/create-editor.ts +40 -0
  42. package/src/client/tiptap/exitable-marks.ts +73 -0
  43. package/src/client/tiptap/extensions.ts +60 -0
  44. package/src/client/tiptap/image-node.ts +488 -0
  45. package/src/client/tiptap/link-toolbar.ts +371 -0
  46. package/src/client/tiptap/more-break.ts +50 -0
  47. package/src/client/tiptap/paste-image.ts +140 -0
  48. package/src/client/tiptap/slash-commands.ts +328 -0
  49. package/src/{types → client/types}/sortablejs.d.ts +1 -1
  50. package/src/client.ts +24 -17
  51. package/src/db/migrations/0012_add_tiptap_columns.sql +2 -0
  52. package/src/db/migrations/0013_replace_featured_with_visibility.sql +8 -0
  53. package/src/db/schema.ts +6 -1
  54. package/src/i18n/locales/en.po +641 -215
  55. package/src/i18n/locales/en.ts +1 -1
  56. package/src/i18n/locales/zh-Hans.po +642 -204
  57. package/src/i18n/locales/zh-Hans.ts +1 -1
  58. package/src/i18n/locales/zh-Hant.po +642 -204
  59. package/src/i18n/locales/zh-Hant.ts +1 -1
  60. package/src/lib/__tests__/resolve-config.test.ts +2 -2
  61. package/src/lib/__tests__/schemas.test.ts +9 -6
  62. package/src/lib/__tests__/url.test.ts +2 -2
  63. package/src/lib/__tests__/view.test.ts +9 -9
  64. package/src/lib/emoji-catalog.ts +146 -0
  65. package/src/lib/feed.ts +1 -1
  66. package/src/lib/media-helpers.ts +10 -9
  67. package/src/lib/render.tsx +4 -3
  68. package/src/lib/resolve-config.ts +8 -1
  69. package/src/lib/schemas.ts +2 -3
  70. package/src/lib/summary.ts +92 -0
  71. package/src/lib/timeline.ts +2 -0
  72. package/src/lib/tiptap-render.ts +196 -0
  73. package/src/lib/upload.ts +97 -9
  74. package/src/lib/url.ts +7 -23
  75. package/src/lib/view.ts +33 -19
  76. package/src/middleware/error-handler.ts +3 -3
  77. package/src/preset.css +38 -0
  78. package/src/routes/api/collections.ts +20 -3
  79. package/src/routes/api/posts.ts +48 -33
  80. package/src/routes/api/upload.ts +7 -5
  81. package/src/routes/auth/reset.tsx +5 -4
  82. package/src/routes/auth/setup.tsx +26 -11
  83. package/src/routes/auth/signin.tsx +10 -7
  84. package/src/routes/compose.tsx +20 -11
  85. package/src/routes/dash/__tests__/settings-avatar.test.ts +43 -8
  86. package/src/routes/dash/index.tsx +7 -1
  87. package/src/routes/dash/media.tsx +3 -0
  88. package/src/routes/dash/pages.tsx +8 -2
  89. package/src/routes/dash/posts.tsx +6 -2
  90. package/src/routes/dash/redirects.tsx +15 -9
  91. package/src/routes/dash/settings.tsx +336 -32
  92. package/src/routes/feed/__tests__/rss.test.ts +7 -7
  93. package/src/routes/feed/rss.ts +8 -6
  94. package/src/routes/pages/__tests__/featured.test.ts +6 -7
  95. package/src/routes/pages/archive.tsx +11 -7
  96. package/src/routes/pages/collection.tsx +32 -15
  97. package/src/routes/pages/collections.tsx +11 -2
  98. package/src/routes/pages/featured.tsx +1 -1
  99. package/src/routes/pages/home.tsx +1 -1
  100. package/src/services/__tests__/post.test.ts +124 -33
  101. package/src/services/__tests__/settings.test.ts +3 -3
  102. package/src/services/page.ts +16 -3
  103. package/src/services/post.ts +96 -37
  104. package/src/services/search.ts +4 -2
  105. package/src/services/settings.ts +6 -2
  106. package/src/styles/components.css +240 -60
  107. package/src/styles/tokens.css +10 -0
  108. package/src/styles/ui.css +1157 -81
  109. package/src/types/bindings.ts +5 -0
  110. package/src/types/config.ts +23 -1
  111. package/src/types/constants.ts +3 -0
  112. package/src/types/entities.ts +9 -2
  113. package/src/types/operations.ts +9 -3
  114. package/src/types/props.ts +3 -3
  115. package/src/types/views.ts +3 -2
  116. package/src/ui/compose/ComposeDialog.tsx +24 -7
  117. package/src/ui/dash/PageForm.tsx +2 -0
  118. package/src/ui/dash/PostList.tsx +5 -5
  119. package/src/ui/dash/StatusBadge.tsx +13 -5
  120. package/src/ui/dash/appearance/AdvancedContent.tsx +52 -61
  121. package/src/ui/dash/appearance/ColorThemeContent.tsx +30 -35
  122. package/src/ui/dash/appearance/FontThemeContent.tsx +65 -73
  123. package/src/ui/dash/appearance/NavigationContent.tsx +107 -96
  124. package/src/ui/dash/media/MediaListContent.tsx +9 -4
  125. package/src/ui/dash/media/ViewMediaContent.tsx +2 -2
  126. package/src/ui/dash/pages/PagesContent.tsx +2 -1
  127. package/src/ui/dash/posts/PostForm.tsx +19 -7
  128. package/src/ui/dash/settings/AccountContent.tsx +133 -138
  129. package/src/ui/dash/settings/AvatarContent.tsx +70 -0
  130. package/src/ui/dash/settings/GeneralContent.tsx +3 -62
  131. package/src/ui/dash/settings/SettingsRootContent.tsx +236 -0
  132. package/src/ui/layouts/DashLayout.tsx +157 -75
  133. package/src/ui/layouts/SiteLayout.tsx +13 -13
  134. package/src/ui/pages/ArchivePage.tsx +10 -7
  135. package/src/ui/pages/CollectionPage.tsx +6 -35
  136. package/src/ui/pages/CollectionsPage.tsx +2 -1
  137. package/src/ui/pages/FeaturedPage.tsx +2 -1
  138. package/src/ui/pages/HomePage.tsx +1 -1
  139. package/src/ui/pages/SearchPage.tsx +1 -1
  140. package/src/ui/shared/CollectionsSidebar.tsx +228 -3
  141. package/src/ui/shared/MediaGallery.tsx +179 -41
  142. package/src/lib/collections-reorder.ts +0 -28
  143. package/src/routes/dash/appearance.tsx +0 -240
  144. package/src/routes/dash/collections.tsx +0 -211
  145. package/src/ui/components/jant-compose-editor.ts +0 -814
  146. package/src/ui/dash/appearance/AppearanceNav.tsx +0 -60
  147. package/src/ui/dash/collections/CollectionForm.tsx +0 -166
  148. package/src/ui/dash/collections/CollectionsListContent.tsx +0 -146
  149. package/src/ui/dash/collections/IconPickerGrid.tsx +0 -50
  150. package/src/ui/dash/collections/ViewCollectionContent.tsx +0 -103
  151. package/src/ui/dash/settings/SettingsNav.tsx +0 -52
  152. /package/src/{ui → client}/components/__tests__/jant-settings-avatar.test.ts +0 -0
  153. /package/src/{ui → client}/components/jant-settings-avatar.ts +0 -0
  154. /package/src/{ui → client}/components/settings-types.ts +0 -0
  155. /package/src/{lib → client}/image-processor.ts +0 -0
  156. /package/src/{lib → client}/toast.ts +0 -0
@@ -3,7 +3,6 @@
3
3
  */
4
4
 
5
5
  import { useLingui } from "@lingui/react/macro";
6
- import { SettingsNav } from "./SettingsNav.js";
7
6
 
8
7
  export function AccountContent({ userName }: { userName: string }) {
9
8
  const { t } = useLingui();
@@ -11,152 +10,148 @@ export function AccountContent({ userName }: { userName: string }) {
11
10
  const profileSignals = JSON.stringify({ userName }).replace(/</g, "\\u003c");
12
11
 
13
12
  return (
14
- <>
15
- <SettingsNav currentTab="account" />
16
-
17
- <div class="flex flex-col max-w-lg">
18
- <form
19
- data-signals={profileSignals}
20
- data-on:submit__prevent="@post('/dash/settings/account')"
21
- data-indicator="_profileLoading"
22
- >
23
- <h2 class="text-lg font-semibold mb-4">
24
- {t({
25
- message: "Profile",
26
- comment: "@context: Account settings section heading",
27
- })}
28
- </h2>
29
- <div class="flex flex-col gap-4">
30
- <div class="field">
31
- <label class="label">
32
- {t({
33
- message: "Name",
34
- comment: "@context: Account settings form field",
35
- })}
36
- </label>
37
- <input type="text" data-bind="userName" class="input" required />
38
- </div>
13
+ <div class="flex flex-col max-w-lg">
14
+ <form
15
+ data-signals={profileSignals}
16
+ data-on:submit__prevent="@post('/dash/settings/account')"
17
+ data-indicator="_profileLoading"
18
+ >
19
+ <h2 class="text-lg font-semibold mb-4">
20
+ {t({
21
+ message: "Profile",
22
+ comment: "@context: Account settings section heading",
23
+ })}
24
+ </h2>
25
+ <div class="flex flex-col gap-4">
26
+ <div class="field">
27
+ <label class="label">
28
+ {t({
29
+ message: "Name",
30
+ comment: "@context: Account settings form field",
31
+ })}
32
+ </label>
33
+ <input type="text" data-bind="userName" class="input" required />
39
34
  </div>
35
+ </div>
40
36
 
41
- <button
42
- type="submit"
43
- class="btn mt-4"
44
- data-attr:disabled="$_profileLoading"
37
+ <button
38
+ type="submit"
39
+ class="btn mt-4"
40
+ data-attr:disabled="$_profileLoading"
41
+ >
42
+ <svg
43
+ data-show="$_profileLoading"
44
+ style="display:none"
45
+ class="animate-spin size-4"
46
+ xmlns="http://www.w3.org/2000/svg"
47
+ viewBox="0 0 24 24"
48
+ fill="none"
49
+ stroke="currentColor"
50
+ stroke-width="2"
51
+ stroke-linecap="round"
52
+ stroke-linejoin="round"
53
+ role="status"
45
54
  >
46
- <svg
47
- data-show="$_profileLoading"
48
- style="display:none"
49
- class="animate-spin size-4"
50
- xmlns="http://www.w3.org/2000/svg"
51
- viewBox="0 0 24 24"
52
- fill="none"
53
- stroke="currentColor"
54
- stroke-width="2"
55
- stroke-linecap="round"
56
- stroke-linejoin="round"
57
- role="status"
58
- >
59
- <path d="M21 12a9 9 0 1 1-6.219-8.56" />
60
- </svg>
61
- {t({
62
- message: "Save Profile",
63
- comment: "@context: Button to save profile",
64
- })}
65
- </button>
66
- </form>
55
+ <path d="M21 12a9 9 0 1 1-6.219-8.56" />
56
+ </svg>
57
+ {t({
58
+ message: "Save Profile",
59
+ comment: "@context: Button to save profile",
60
+ })}
61
+ </button>
62
+ </form>
67
63
 
68
- <hr class="my-8" />
64
+ <hr class="my-8" />
69
65
 
70
- <form
71
- data-signals="{currentPassword: '', newPassword: '', confirmPassword: ''}"
72
- data-on:submit__prevent="@post('/dash/settings/password')"
73
- data-indicator="_passwordLoading"
74
- >
75
- <h2 class="text-lg font-semibold mb-4">
76
- {t({
77
- message: "Change Password",
78
- comment: "@context: Settings section heading",
79
- })}
80
- </h2>
81
- <div class="flex flex-col gap-4">
82
- <div class="field">
83
- <label class="label">
84
- {t({
85
- message: "Current Password",
86
- comment: "@context: Password form field",
87
- })}
88
- </label>
89
- <input
90
- type="password"
91
- data-bind="currentPassword"
92
- class="input"
93
- required
94
- autocomplete="current-password"
95
- />
96
- </div>
66
+ <form
67
+ data-signals="{currentPassword: '', newPassword: '', confirmPassword: ''}"
68
+ data-on:submit__prevent="@post('/dash/settings/password')"
69
+ data-indicator="_passwordLoading"
70
+ >
71
+ <h2 class="text-lg font-semibold mb-4">
72
+ {t({
73
+ message: "Change Password",
74
+ comment: "@context: Settings section heading",
75
+ })}
76
+ </h2>
77
+ <div class="flex flex-col gap-4">
78
+ <div class="field">
79
+ <label class="label">
80
+ {t({
81
+ message: "Current Password",
82
+ comment: "@context: Password form field",
83
+ })}
84
+ </label>
85
+ <input
86
+ type="password"
87
+ data-bind="currentPassword"
88
+ class="input"
89
+ required
90
+ autocomplete="current-password"
91
+ />
92
+ </div>
97
93
 
98
- <div class="field">
99
- <label class="label">
100
- {t({
101
- message: "New Password",
102
- comment: "@context: Password form field",
103
- })}
104
- </label>
105
- <input
106
- type="password"
107
- data-bind="newPassword"
108
- class="input"
109
- required
110
- minlength={8}
111
- autocomplete="new-password"
112
- />
113
- </div>
94
+ <div class="field">
95
+ <label class="label">
96
+ {t({
97
+ message: "New Password",
98
+ comment: "@context: Password form field",
99
+ })}
100
+ </label>
101
+ <input
102
+ type="password"
103
+ data-bind="newPassword"
104
+ class="input"
105
+ required
106
+ minlength={8}
107
+ autocomplete="new-password"
108
+ />
109
+ </div>
114
110
 
115
- <div class="field">
116
- <label class="label">
117
- {t({
118
- message: "Confirm New Password",
119
- comment: "@context: Password form field",
120
- })}
121
- </label>
122
- <input
123
- type="password"
124
- data-bind="confirmPassword"
125
- class="input"
126
- required
127
- minlength={8}
128
- autocomplete="new-password"
129
- />
130
- </div>
111
+ <div class="field">
112
+ <label class="label">
113
+ {t({
114
+ message: "Confirm New Password",
115
+ comment: "@context: Password form field",
116
+ })}
117
+ </label>
118
+ <input
119
+ type="password"
120
+ data-bind="confirmPassword"
121
+ class="input"
122
+ required
123
+ minlength={8}
124
+ autocomplete="new-password"
125
+ />
131
126
  </div>
127
+ </div>
132
128
 
133
- <button
134
- type="submit"
135
- class="btn mt-4"
136
- data-attr:disabled="$_passwordLoading"
129
+ <button
130
+ type="submit"
131
+ class="btn mt-4"
132
+ data-attr:disabled="$_passwordLoading"
133
+ >
134
+ <svg
135
+ data-show="$_passwordLoading"
136
+ style="display:none"
137
+ class="animate-spin size-4"
138
+ xmlns="http://www.w3.org/2000/svg"
139
+ viewBox="0 0 24 24"
140
+ fill="none"
141
+ stroke="currentColor"
142
+ stroke-width="2"
143
+ stroke-linecap="round"
144
+ stroke-linejoin="round"
145
+ role="status"
137
146
  >
138
- <svg
139
- data-show="$_passwordLoading"
140
- style="display:none"
141
- class="animate-spin size-4"
142
- xmlns="http://www.w3.org/2000/svg"
143
- viewBox="0 0 24 24"
144
- fill="none"
145
- stroke="currentColor"
146
- stroke-width="2"
147
- stroke-linecap="round"
148
- stroke-linejoin="round"
149
- role="status"
150
- >
151
- <path d="M21 12a9 9 0 1 1-6.219-8.56" />
152
- </svg>
153
- {t({
154
- message: "Change Password",
155
- comment: "@context: Button to change password",
156
- })}
157
- </button>
158
- </form>
159
- </div>
160
- </>
147
+ <path d="M21 12a9 9 0 1 1-6.219-8.56" />
148
+ </svg>
149
+ {t({
150
+ message: "Change Password",
151
+ comment: "@context: Button to change password",
152
+ })}
153
+ </button>
154
+ </form>
155
+ </div>
161
156
  );
162
157
  }
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Avatar settings page — extracted from GeneralContent
3
+ *
4
+ * Wraps the <jant-settings-avatar> Lit component with translated labels.
5
+ */
6
+
7
+ import { useLingui } from "@lingui/react/macro";
8
+
9
+ export function AvatarContent({
10
+ siteAvatarUrl,
11
+ showHeaderAvatar,
12
+ }: {
13
+ siteAvatarUrl: string;
14
+ showHeaderAvatar: boolean;
15
+ }) {
16
+ const { t } = useLingui();
17
+
18
+ const labels = JSON.stringify({
19
+ blogAvatar: t({
20
+ message: "Blog Avatar",
21
+ comment: "@context: Settings section heading for avatar",
22
+ }),
23
+ uploadAvatar: t({
24
+ message: "Upload Avatar",
25
+ comment: "@context: Button to upload avatar image",
26
+ }),
27
+ remove: t({
28
+ message: "Remove",
29
+ comment: "@context: Button to remove the blog avatar",
30
+ }),
31
+ avatarHelp: t({
32
+ message:
33
+ "This is used for your favicon and apple-touch-icon. For best results, upload a square image at least 180x180 pixels.",
34
+ comment: "@context: Help text for avatar upload",
35
+ }),
36
+ displayInHeader: t({
37
+ message: "Display avatar in my site header",
38
+ comment: "@context: Checkbox to show avatar in the site header",
39
+ }),
40
+ processing: t({
41
+ message: "Processing...",
42
+ comment:
43
+ "@context: Avatar upload button text while generating favicon variants",
44
+ }),
45
+ uploading: t({
46
+ message: "Uploading...",
47
+ comment: "@context: Avatar upload button text while uploading",
48
+ }),
49
+ uploadError: t({
50
+ message: "Upload failed. Please try again.",
51
+ comment: "@context: Error message when avatar upload fails",
52
+ }),
53
+ }).replace(/</g, "\\u003c");
54
+
55
+ return (
56
+ <div class="flex flex-col max-w-lg">
57
+ <jant-settings-avatar
58
+ avatar-url={siteAvatarUrl}
59
+ show-in-header={showHeaderAvatar || undefined}
60
+ labels={labels}
61
+ >
62
+ {/* SSR fallback skeleton */}
63
+ <div>
64
+ <h2 class="skel-label" />
65
+ <div class="skel-section-sm" />
66
+ </div>
67
+ </jant-settings-avatar>
68
+ </div>
69
+ );
70
+ }
@@ -1,18 +1,13 @@
1
1
  /**
2
2
  * General settings form
3
3
  *
4
- * Server-side template that renders Lit Web Components for the
5
- * settings page. Provides translated labels, initial data, and
6
- * timezone/language options as JSON attributes.
7
- *
8
- * The Lit components <jant-settings-avatar> and <jant-settings-general>
9
- * handle all form state and rendering. The settings-bridge.ts script
10
- * handles server communication.
4
+ * Server-side template that renders the <jant-settings-general> Lit
5
+ * component for site name, description, language, timezone, footer, and SEO.
6
+ * The settings-bridge.ts script handles server communication.
11
7
  */
12
8
 
13
9
  import { useLingui } from "@lingui/react/macro";
14
10
  import type { TimezoneEntry } from "../../../lib/timezones.js";
15
- import { SettingsNav } from "./SettingsNav.js";
16
11
 
17
12
  export function GeneralContent({
18
13
  siteName,
@@ -20,8 +15,6 @@ export function GeneralContent({
20
15
  siteLanguage,
21
16
  siteNameFallback,
22
17
  siteDescriptionFallback,
23
- siteAvatarUrl,
24
- showHeaderAvatar,
25
18
  timeZone,
26
19
  siteFooter,
27
20
  noindex,
@@ -32,8 +25,6 @@ export function GeneralContent({
32
25
  siteLanguage: string;
33
26
  siteNameFallback: string;
34
27
  siteDescriptionFallback: string;
35
- siteAvatarUrl: string;
36
- showHeaderAvatar: boolean;
37
28
  timeZone: string;
38
29
  siteFooter: string;
39
30
  noindex: boolean;
@@ -42,40 +33,6 @@ export function GeneralContent({
42
33
  const { t } = useLingui();
43
34
 
44
35
  const labels = JSON.stringify({
45
- blogAvatar: t({
46
- message: "Blog Avatar",
47
- comment: "@context: Settings section heading for avatar",
48
- }),
49
- uploadAvatar: t({
50
- message: "Upload Avatar",
51
- comment: "@context: Button to upload avatar image",
52
- }),
53
- remove: t({
54
- message: "Remove",
55
- comment: "@context: Button to remove the blog avatar",
56
- }),
57
- avatarHelp: t({
58
- message:
59
- "This is used for your favicon and apple-touch-icon. For best results, upload a square image at least 180x180 pixels.",
60
- comment: "@context: Help text for avatar upload",
61
- }),
62
- displayInHeader: t({
63
- message: "Display avatar in my site header",
64
- comment: "@context: Checkbox to show avatar in the site header",
65
- }),
66
- processing: t({
67
- message: "Processing...",
68
- comment:
69
- "@context: Avatar upload button text while generating favicon variants",
70
- }),
71
- uploading: t({
72
- message: "Uploading...",
73
- comment: "@context: Avatar upload button text while uploading",
74
- }),
75
- uploadError: t({
76
- message: "Upload failed. Please try again.",
77
- comment: "@context: Error message when avatar upload fails",
78
- }),
79
36
  general: t({
80
37
  message: "General",
81
38
  comment: "@context: Settings section heading",
@@ -154,23 +111,7 @@ export function GeneralContent({
154
111
 
155
112
  return (
156
113
  <>
157
- <SettingsNav currentTab="general" />
158
-
159
114
  <div class="flex flex-col max-w-lg">
160
- <jant-settings-avatar
161
- avatar-url={siteAvatarUrl}
162
- show-in-header={showHeaderAvatar || undefined}
163
- labels={labels}
164
- >
165
- {/* SSR fallback skeleton */}
166
- <div>
167
- <h2 class="skel-label" />
168
- <div class="skel-section-sm" />
169
- </div>
170
- </jant-settings-avatar>
171
-
172
- <hr class="my-8" />
173
-
174
115
  <jant-settings-general
175
116
  labels={labels}
176
117
  timezones={timezonesJson}