@jant/core 0.3.34 → 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 +3327 -3031
  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 +245 -6
  93. package/src/routes/feed/rss.ts +70 -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
@@ -23,16 +23,6 @@ svg[stroke-width].icon-fine {
23
23
  padding-left: var(--site-padding);
24
24
  padding-right: var(--site-padding);
25
25
  }
26
-
27
- .container-sidebar {
28
- max-width: calc(
29
- var(--sidebar-width) + var(--sidebar-gap) + var(--site-width)
30
- );
31
- margin-left: auto;
32
- margin-right: auto;
33
- padding-left: var(--site-padding);
34
- padding-right: var(--site-padding);
35
- }
36
26
  }
37
27
 
38
28
  /* Toast notifications */
@@ -121,29 +111,50 @@ svg[stroke-width].icon-fine {
121
111
  padding-bottom: 12px;
122
112
  }
123
113
 
124
- .dash-header-left {
114
+ .dash-header-avatar-link {
115
+ flex-shrink: 0;
116
+ line-height: 0;
117
+ }
118
+
119
+ .dash-header-avatar {
120
+ width: 22px;
121
+ height: 22px;
122
+ border-radius: 5px;
123
+ }
124
+
125
+ .dash-header-avatar:is(img) {
126
+ object-fit: cover;
127
+ }
128
+
129
+ .dash-header-avatar-fallback {
125
130
  display: flex;
126
131
  align-items: center;
127
- gap: 6px;
132
+ justify-content: center;
133
+ color: white;
134
+ font-size: 0.625rem;
135
+ font-weight: 600;
136
+ line-height: 1;
128
137
  }
129
138
 
130
139
  .dash-header-nav {
131
140
  display: flex;
132
141
  align-items: center;
133
- justify-content: center;
134
- gap: 4px;
135
- flex: 1;
142
+ gap: 16px;
136
143
  }
137
144
 
138
- .dash-header-logo {
139
- font-size: 1.125rem;
140
- font-weight: 800;
141
- line-height: 1;
142
- color: var(--color-foreground);
145
+ .dash-header-nav-sep {
146
+ display: none;
143
147
  }
144
148
 
145
- .dash-header-site-link {
146
- @apply flex items-center justify-center;
149
+ .dash-header-right {
150
+ display: flex;
151
+ align-items: center;
152
+ gap: 8px;
153
+ margin-left: auto;
154
+ }
155
+
156
+ .dash-header-link {
157
+ font-size: 0.8125rem;
147
158
  color: var(--color-muted-foreground);
148
159
  transition: color 0.15s;
149
160
 
@@ -152,33 +163,41 @@ svg[stroke-width].icon-fine {
152
163
  }
153
164
  }
154
165
 
155
- .dash-header-link {
156
- position: relative;
166
+ .dash-header-link-active {
167
+ color: var(--color-foreground);
168
+ font-weight: 500;
169
+ }
170
+
171
+ .dash-header-visit {
172
+ @apply flex items-center gap-3;
157
173
  font-size: 0.875rem;
158
- padding: 6px 10px;
159
- border-radius: var(--radius);
160
174
  color: var(--color-muted-foreground);
161
- transition:
162
- color 0.15s,
163
- background-color 0.15s;
175
+ transition: color 0.15s;
164
176
 
165
177
  &:hover {
166
178
  color: var(--color-foreground);
167
- background-color: var(--color-accent);
168
179
  }
169
180
  }
170
181
 
171
- .dash-header-link-active {
172
- color: var(--color-foreground);
173
- font-weight: 600;
174
- background-color: var(--color-accent);
182
+ .dash-header-visit-text {
183
+ display: none;
184
+ }
185
+
186
+ @media (min-width: 700px) {
187
+ .dash-header-visit-text {
188
+ display: inline;
189
+ }
190
+
191
+ .dash-header-visit-icon {
192
+ display: none;
193
+ }
175
194
  }
176
195
 
177
196
  .dash-header-menu-btn {
178
197
  @apply flex items-center justify-center;
179
198
  width: 32px;
180
199
  height: 32px;
181
- border-radius: 999px;
200
+ border-radius: var(--radius);
182
201
  border: none;
183
202
  background: transparent;
184
203
  color: var(--color-muted-foreground);
@@ -198,33 +217,194 @@ svg[stroke-width].icon-fine {
198
217
  }
199
218
  }
200
219
 
201
- /* Sub-navigationunderline style for secondary tabs (Settings, Appearance) */
220
+ /* Breadcrumbsecond row below header on settings sub-pages */
221
+ @layer components {
222
+ .dash-breadcrumb {
223
+ display: flex;
224
+ align-items: center;
225
+ gap: 8px;
226
+ padding: 8px 0;
227
+ font-size: 0.8125rem;
228
+ }
229
+
230
+ .dash-breadcrumb-parent {
231
+ color: var(--color-muted-foreground);
232
+ transition: color 0.15s;
233
+
234
+ &:hover {
235
+ color: var(--color-foreground);
236
+ }
237
+ }
238
+
239
+ .dash-breadcrumb-sep {
240
+ color: var(--color-muted-foreground);
241
+ opacity: 0.5;
242
+ }
243
+
244
+ .dash-breadcrumb-current {
245
+ color: var(--color-foreground);
246
+ font-weight: 500;
247
+ }
248
+ }
249
+
250
+ /* Settings root — iOS-style grouped list */
202
251
  @layer components {
203
- .dash-subnav {
204
- @apply flex gap-4 mb-6;
205
-
206
- > a {
207
- position: relative;
208
- font-size: 0.8125rem;
209
- padding-bottom: 8px;
210
- color: var(--color-muted-foreground);
211
- transition: color 0.15s;
212
-
213
- &:hover {
214
- color: var(--color-foreground);
215
- }
216
-
217
- &.active {
218
- color: var(--color-foreground);
219
- font-weight: 500;
220
-
221
- &::after {
222
- content: "";
223
- @apply absolute inset-x-0 bottom-0 h-0.5 rounded-full;
224
- background-color: var(--color-foreground);
225
- }
226
- }
252
+ .settings-root {
253
+ @apply flex flex-col gap-6;
254
+ }
255
+
256
+ .settings-group-label {
257
+ @apply text-xs font-medium uppercase tracking-wider mb-2 px-1;
258
+ color: var(--color-muted-foreground);
259
+ }
260
+
261
+ .settings-group {
262
+ @apply border rounded-xl overflow-hidden;
263
+ border-radius: var(--dash-card-radius);
264
+ }
265
+
266
+ .settings-item {
267
+ @apply flex items-center gap-3 px-4 py-3;
268
+ transition: background-color 0.15s;
269
+ border-bottom: 1px solid var(--color-border);
270
+
271
+ &:last-child {
272
+ border-bottom: none;
227
273
  }
274
+
275
+ &:hover {
276
+ background-color: var(--color-accent);
277
+ }
278
+ }
279
+
280
+ .settings-item-icon {
281
+ @apply flex items-center justify-center shrink-0;
282
+ width: 28px;
283
+ height: 28px;
284
+ border-radius: 6px;
285
+ color: white;
286
+ }
287
+
288
+ .settings-item-text {
289
+ @apply flex flex-col flex-1 min-w-0;
290
+ }
291
+
292
+ .settings-item-name {
293
+ @apply text-sm font-medium;
294
+ color: var(--color-foreground);
295
+ }
296
+
297
+ .settings-item-desc {
298
+ @apply text-xs;
299
+ color: var(--color-muted-foreground);
300
+ }
301
+
302
+ .settings-item-chevron {
303
+ @apply shrink-0;
304
+ color: var(--color-muted-foreground);
305
+ opacity: 0.5;
306
+ }
307
+ }
308
+
309
+ /* Dashboard scoped font rules */
310
+ @layer components {
311
+ .dash-heading {
312
+ font-family: Georgia, "Times New Roman", serif;
313
+ }
314
+ }
315
+
316
+ /* Navigation preview — browser-chrome frame for nav preview */
317
+ @layer components {
318
+ .nav-preview {
319
+ @apply border rounded-lg overflow-hidden;
320
+ background-color: var(--color-card);
321
+ }
322
+
323
+ .nav-preview-chrome {
324
+ @apply flex items-center gap-3 px-4 py-2.5 border-b;
325
+ background-color: var(--color-muted);
326
+ }
327
+
328
+ .nav-preview-dots {
329
+ @apply flex gap-1.5;
330
+
331
+ > span {
332
+ @apply block size-2.5 rounded-full;
333
+ background-color: var(--color-muted-foreground);
334
+ opacity: 0.3;
335
+ }
336
+ }
337
+
338
+ .nav-preview-label {
339
+ @apply text-xs;
340
+ color: var(--color-muted-foreground);
341
+ }
342
+
343
+ .nav-preview-content {
344
+ @apply px-5 py-3;
345
+ }
346
+ }
347
+
348
+ /* Navigation items list — card-style draggable nav items */
349
+ @layer components {
350
+ .nav-items-list {
351
+ @apply flex flex-col gap-2;
352
+ }
353
+
354
+ .nav-item {
355
+ @apply border rounded-lg transition-shadow;
356
+
357
+ &:hover {
358
+ @apply shadow-xs;
359
+ }
360
+ }
361
+
362
+ .nav-item-editing {
363
+ @apply ring-1 ring-ring;
364
+ }
365
+
366
+ .nav-item-row {
367
+ @apply flex items-center gap-1 px-1 py-1;
368
+ }
369
+
370
+ .nav-item-handle {
371
+ @apply flex items-center justify-center w-8 h-8 shrink-0 cursor-grab rounded;
372
+ transition: background-color 0.15s;
373
+
374
+ &:hover {
375
+ background-color: var(--color-accent);
376
+ }
377
+
378
+ &:active {
379
+ cursor: grabbing;
380
+ }
381
+ }
382
+
383
+ .nav-item-info {
384
+ @apply flex flex-col flex-1 min-w-0 py-1.5 px-1.5 rounded cursor-pointer;
385
+ transition: background-color 0.15s;
386
+
387
+ &:hover {
388
+ background-color: var(--color-accent);
389
+ }
390
+ }
391
+
392
+ .nav-item-toggle {
393
+ @apply flex items-center justify-center w-8 h-8 shrink-0 rounded border-0 bg-transparent cursor-pointer;
394
+ color: var(--color-muted-foreground);
395
+ transition:
396
+ color 0.15s,
397
+ background-color 0.15s;
398
+
399
+ &:hover {
400
+ color: var(--color-foreground);
401
+ background-color: var(--color-accent);
402
+ }
403
+ }
404
+
405
+ .nav-item-edit {
406
+ @apply flex flex-col gap-3 px-4 pb-3 pt-3 border-t mx-1 mb-1;
407
+ border-color: var(--color-border);
228
408
  }
229
409
  }
230
410
 
@@ -53,4 +53,14 @@
53
53
  --site-text-placeholder: oklch(from var(--muted-foreground) l c h / 0.5);
54
54
  --site-media-outline: var(--border);
55
55
  --site-divider: var(--border);
56
+
57
+ /* Dashboard */
58
+ --dash-bg: oklch(0.97 0.005 80);
59
+ --dash-card-radius: 10px;
60
+ }
61
+
62
+ @media (prefers-color-scheme: dark) {
63
+ :root {
64
+ --dash-bg: oklch(0.2 0.005 80);
65
+ }
56
66
  }