@jant/core 0.3.31 → 0.3.33

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 (95) hide show
  1. package/dist/client/client.css +1 -1
  2. package/dist/client/client.js +1442 -989
  3. package/dist/index.js +1429 -1055
  4. package/package.json +2 -2
  5. package/src/__tests__/helpers/app.ts +6 -3
  6. package/src/__tests__/helpers/db.ts +3 -0
  7. package/src/client.ts +2 -1
  8. package/src/db/migrations/0011_add_path_registry.sql +23 -0
  9. package/src/db/schema.ts +12 -1
  10. package/src/i18n/locales/en.po +225 -91
  11. package/src/i18n/locales/en.ts +1 -1
  12. package/src/i18n/locales/zh-Hans.po +201 -152
  13. package/src/i18n/locales/zh-Hans.ts +1 -1
  14. package/src/i18n/locales/zh-Hant.po +201 -152
  15. package/src/i18n/locales/zh-Hant.ts +1 -1
  16. package/src/lib/__tests__/excerpt.test.ts +25 -0
  17. package/src/lib/__tests__/resolve-config.test.ts +26 -2
  18. package/src/lib/__tests__/timeline.test.ts +2 -1
  19. package/src/lib/compose-bridge.ts +30 -1
  20. package/src/lib/excerpt.ts +16 -7
  21. package/src/lib/nav-manager-bridge.ts +54 -0
  22. package/src/lib/navigation.ts +7 -4
  23. package/src/lib/render.tsx +5 -2
  24. package/src/lib/resolve-config.ts +7 -0
  25. package/src/lib/view.ts +42 -10
  26. package/src/middleware/error-handler.ts +16 -0
  27. package/src/routes/api/__tests__/posts.test.ts +80 -0
  28. package/src/routes/api/__tests__/settings.test.ts +1 -1
  29. package/src/routes/api/posts.ts +6 -29
  30. package/src/routes/api/upload.ts +2 -14
  31. package/src/routes/auth/__tests__/setup.test.ts +2 -1
  32. package/src/routes/compose.tsx +13 -5
  33. package/src/routes/dash/__tests__/pages.test.ts +2 -1
  34. package/src/routes/dash/__tests__/settings-avatar.test.ts +151 -33
  35. package/src/routes/dash/appearance.tsx +71 -4
  36. package/src/routes/dash/collections.tsx +15 -21
  37. package/src/routes/dash/media.tsx +1 -13
  38. package/src/routes/dash/pages.tsx +5 -150
  39. package/src/routes/dash/posts.tsx +25 -32
  40. package/src/routes/dash/redirects.tsx +9 -11
  41. package/src/routes/dash/settings.tsx +29 -111
  42. package/src/routes/feed/__tests__/rss.test.ts +5 -1
  43. package/src/routes/pages/__tests__/collections.test.ts +2 -1
  44. package/src/routes/pages/__tests__/featured.test.ts +2 -1
  45. package/src/routes/pages/page.tsx +20 -25
  46. package/src/services/__tests__/collection.test.ts +2 -1
  47. package/src/services/__tests__/media.test.ts +78 -1
  48. package/src/services/__tests__/navigation.test.ts +2 -1
  49. package/src/services/__tests__/page.test.ts +78 -1
  50. package/src/services/__tests__/path-registry.test.ts +165 -0
  51. package/src/services/__tests__/post-timeline.test.ts +2 -1
  52. package/src/services/__tests__/post.test.ts +103 -1
  53. package/src/services/__tests__/redirect.test.ts +53 -4
  54. package/src/services/__tests__/search.test.ts +2 -1
  55. package/src/services/__tests__/settings.test.ts +153 -0
  56. package/src/services/index.ts +12 -4
  57. package/src/services/media.ts +72 -4
  58. package/src/services/page.ts +64 -17
  59. package/src/services/path-registry.ts +160 -0
  60. package/src/services/post.ts +119 -24
  61. package/src/services/redirect.ts +23 -3
  62. package/src/services/settings.ts +181 -0
  63. package/src/styles/components.css +135 -0
  64. package/src/styles/tokens.css +6 -1
  65. package/src/styles/ui.css +70 -26
  66. package/src/types/bindings.ts +1 -0
  67. package/src/types/config.ts +7 -2
  68. package/src/types/constants.ts +9 -1
  69. package/src/types/sortablejs.d.ts +8 -2
  70. package/src/types/views.ts +1 -1
  71. package/src/ui/color-themes.ts +31 -31
  72. package/src/ui/components/__tests__/jant-settings-avatar.test.ts +0 -3
  73. package/src/ui/components/__tests__/jant-settings-general.test.ts +2 -6
  74. package/src/ui/components/jant-compose-dialog.ts +3 -2
  75. package/src/ui/components/jant-compose-editor.ts +17 -2
  76. package/src/ui/components/jant-nav-manager.ts +1067 -0
  77. package/src/ui/components/jant-settings-general.ts +2 -35
  78. package/src/ui/components/nav-manager-types.ts +72 -0
  79. package/src/ui/components/settings-types.ts +0 -3
  80. package/src/ui/compose/ComposePrompt.tsx +3 -11
  81. package/src/ui/dash/appearance/AdvancedContent.tsx +0 -3
  82. package/src/ui/dash/appearance/AppearanceNav.tsx +12 -8
  83. package/src/ui/dash/appearance/ColorThemeContent.tsx +1 -4
  84. package/src/ui/dash/appearance/FontThemeContent.tsx +0 -3
  85. package/src/ui/dash/appearance/NavigationContent.tsx +302 -0
  86. package/src/ui/dash/pages/PagesContent.tsx +74 -0
  87. package/src/ui/dash/settings/AccountContent.tsx +0 -3
  88. package/src/ui/dash/settings/GeneralContent.tsx +1 -19
  89. package/src/ui/dash/settings/SettingsNav.tsx +2 -6
  90. package/src/ui/feed/NoteCard.tsx +2 -2
  91. package/src/ui/layouts/DashLayout.tsx +83 -86
  92. package/src/ui/layouts/SiteLayout.tsx +82 -21
  93. package/src/lib/nav-reorder.ts +0 -26
  94. package/src/ui/dash/pages/LinkFormContent.tsx +0 -119
  95. package/src/ui/dash/pages/UnifiedPagesContent.tsx +0 -203
package/src/styles/ui.css CHANGED
@@ -49,7 +49,7 @@
49
49
 
50
50
  .site-header-top-bordered {
51
51
  padding-bottom: 12px;
52
- border-bottom: 0.5px solid var(--site-divider);
52
+ /* border-bottom: 0.5px solid var(--site-divider); */
53
53
  }
54
54
 
55
55
  .site-header-right {
@@ -130,42 +130,73 @@
130
130
  color: var(--site-text-primary);
131
131
  }
132
132
 
133
- .site-description {
134
- font-size: var(--text-sm);
133
+ /* --- "More" overflow dropdown for > 4 nav links ----------------------- */
134
+
135
+ .site-header-more-btn {
136
+ display: flex;
137
+ align-items: center;
138
+ justify-content: center;
139
+ width: 32px;
140
+ height: 32px;
141
+ border-radius: 999px;
142
+ border: none;
143
+ background: none;
135
144
  color: var(--site-text-secondary);
136
- margin: 2px 0 0;
137
- line-height: var(--leading);
145
+ cursor: pointer;
146
+ transition:
147
+ color 0.15s,
148
+ background-color 0.15s;
149
+ }
150
+
151
+ .site-header-more-btn:hover {
152
+ color: var(--site-text-primary);
153
+ background-color: var(--site-nav-hover-bg);
154
+ }
155
+
156
+ .site-header-more [data-popover] {
157
+ min-width: 170px;
138
158
  }
139
159
 
140
160
  /* --- Browse filter tabs ------------------------------------------------- */
141
161
 
142
162
  .site-browse-nav {
143
163
  display: flex;
144
- align-items: center;
145
- gap: 8px;
146
- padding: 16px 0 var(--space-xl);
164
+ align-items: baseline;
165
+ gap: 10px;
166
+ padding: 16px 0;
147
167
  }
148
168
 
149
169
  .site-browse-sep {
150
- color: var(--site-divider);
151
170
  font-size: var(--text-sm);
171
+ color: var(--site-text-primary);
172
+ opacity: 0.15;
173
+ user-select: none;
152
174
  }
153
175
 
154
176
  .site-browse-link {
155
177
  font-size: var(--text-base);
156
- color: var(--site-text-secondary);
178
+ font-weight: 400;
179
+ color: var(--site-text-primary);
157
180
  text-decoration: none;
158
- font-weight: 500;
159
- transition: color 0.15s;
181
+ opacity: 0.28;
182
+ transition: opacity 0.2s ease;
160
183
  }
161
184
 
162
185
  .site-browse-link:hover {
163
- color: var(--site-text-primary);
186
+ opacity: 0.55;
164
187
  }
165
188
 
166
189
  .site-browse-link-active {
167
- color: var(--site-text-primary);
168
- font-weight: 700;
190
+ opacity: 1;
191
+ font-weight: 500;
192
+ }
193
+
194
+ /* --- Home header wrapper (compose-prompt + browse-nav) ------------------ */
195
+
196
+ .site-home-header {
197
+ display: flex;
198
+ flex-direction: column;
199
+ margin-bottom: var(--space-xl);
169
200
  }
170
201
 
171
202
  /* --- Main content area -------------------------------------------------- */
@@ -177,7 +208,7 @@
177
208
 
178
209
  .site-content {
179
210
  background-color: var(--site-elevated-bg);
180
- padding: 0 var(--site-padding);
211
+ padding: 0px var(--site-padding) var(--space-xl);
181
212
  }
182
213
 
183
214
  /* --- Sidebar layout (shared by dashboard and site sidebar pages) ------- */
@@ -311,7 +342,13 @@
311
342
  align-items: center;
312
343
  gap: 12px;
313
344
  padding: 16px 0;
314
- margin: -20px 0 12px;
345
+ margin: 10px 0;
346
+ border-bottom: 0.5px solid oklch(from var(--site-divider) l c h / 0.5);
347
+ transition: border-color 0.15s;
348
+ }
349
+
350
+ .compose-prompt:hover {
351
+ border-bottom-color: var(--site-divider);
315
352
  }
316
353
 
317
354
  .compose-prompt-trigger {
@@ -322,26 +359,28 @@
322
359
  min-width: 0;
323
360
  padding: 0;
324
361
  border: none;
362
+ outline: none;
325
363
  background: none;
326
364
  cursor: pointer;
327
365
  text-align: left;
366
+ color: var(--site-text-primary);
367
+ opacity: 0.5;
368
+ transition: opacity 0.15s;
369
+ }
370
+
371
+ .compose-prompt-trigger:hover {
372
+ opacity: 0.7;
328
373
  }
329
374
 
330
375
  .compose-prompt-avatar {
331
376
  display: flex;
332
377
  align-items: center;
333
378
  justify-content: center;
334
- width: var(--avatar-size);
335
- height: var(--avatar-size);
336
379
  flex-shrink: 0;
337
- border-radius: var(--avatar-radius);
338
- border: 1.5px solid var(--site-column-outline);
339
- color: var(--site-text-secondary);
340
380
  }
341
381
 
342
382
  .compose-prompt-text {
343
383
  font-size: var(--text-base);
344
- color: var(--site-text-secondary);
345
384
  }
346
385
 
347
386
  .compose-prompt-post-btn {
@@ -396,8 +435,9 @@
396
435
  --compose-margin-top: max(80px, 10vh);
397
436
 
398
437
  padding: 0;
438
+ outline: none;
399
439
  border: none;
400
- border-radius: 20px;
440
+ border-radius: 10px;
401
441
  width: calc(100% - 20px);
402
442
  max-width: calc(var(--site-width) - var(--site-padding) * 2 - 20px);
403
443
  max-height: calc(100dvh - var(--compose-margin-top) - 20px);
@@ -1296,9 +1336,13 @@
1296
1336
  .site-footer {
1297
1337
  max-width: var(--site-width);
1298
1338
  margin: var(--space-xl) auto 0;
1299
- padding: var(--content-gap) var(--site-padding) var(--space-xl);
1300
- border-top: 0.5px solid var(--site-divider);
1339
+ padding: 0 var(--site-padding) var(--space-xl);
1301
1340
  color: var(--site-text-secondary);
1302
1341
  font-size: var(--text-sm);
1303
1342
  }
1343
+
1344
+ .site-footer > .site-container {
1345
+ border-top: 0.5px solid var(--site-divider);
1346
+ padding-top: var(--content-gap);
1347
+ }
1304
1348
  }
@@ -15,6 +15,7 @@ export interface Bindings {
15
15
  // Timeline
16
16
  PAGE_SIZE?: string;
17
17
  // Site configuration (optional - can be overridden in DB)
18
+ HEADER_NAV_MAX_VISIBLE?: string;
18
19
  SITE_NAME?: string;
19
20
  SITE_DESCRIPTION?: string;
20
21
  SITE_LANGUAGE?: string;
@@ -21,7 +21,7 @@ export const CONFIG_FIELDS = {
21
21
  envOnly: false,
22
22
  },
23
23
  SITE_DESCRIPTION: {
24
- defaultValue: "A microblog powered by Jant",
24
+ defaultValue: "Thoughts, links, and quotes — one post at a time",
25
25
  envOnly: false,
26
26
  },
27
27
  SITE_LANGUAGE: {
@@ -32,10 +32,14 @@ export const CONFIG_FIELDS = {
32
32
  defaultValue: "latest",
33
33
  envOnly: false,
34
34
  },
35
+ HEADER_NAV_MAX_VISIBLE: {
36
+ defaultValue: "3",
37
+ envOnly: false,
38
+ },
35
39
 
36
40
  // Environment-only (deployment/infrastructure config)
37
41
  DEFAULT_THEME: {
38
- defaultValue: "halloween",
42
+ defaultValue: "notepad",
39
43
  envOnly: true,
40
44
  },
41
45
  SITE_URL: {
@@ -176,6 +180,7 @@ export interface AppConfig {
176
180
  siteDescriptionExplicit: boolean;
177
181
  siteLanguage: string;
178
182
  homeDefaultView: string;
183
+ headerNavMaxVisible: number;
179
184
  timeZone: string;
180
185
  siteFooter: string;
181
186
  noindex: boolean;
@@ -16,9 +16,17 @@ export const SORT_ORDERS = [
16
16
  ] as const;
17
17
  export type SortOrder = (typeof SORT_ORDERS)[number];
18
18
 
19
- export const NAV_ITEM_TYPES = ["page", "link"] as const;
19
+ export const NAV_ITEM_TYPES = ["page", "link", "system"] as const;
20
20
  export type NavItemType = (typeof NAV_ITEM_TYPES)[number];
21
21
 
22
+ export const SYSTEM_NAV_KEYS = {
23
+ rss: { defaultLabel: "RSS", url: "/feed" },
24
+ dashboard: { defaultLabel: "Dashboard", url: "/dash" },
25
+ collections: { defaultLabel: "Collections", url: "/collections" },
26
+ archive: { defaultLabel: "Archive", url: "/archive" },
27
+ } as const;
28
+ export type SystemNavKey = keyof typeof SYSTEM_NAV_KEYS;
29
+
22
30
  export const MAX_MEDIA_ATTACHMENTS = 20;
23
31
  export const MAX_PINNED_POSTS = 3;
24
32
 
@@ -1,14 +1,20 @@
1
1
  /**
2
2
  * Minimal type declarations for sortablejs
3
3
  *
4
- * Only covers the API surface used by nav-reorder.ts.
4
+ * Only covers the API surface used by jant-nav-manager and collections-reorder.
5
5
  */
6
6
 
7
7
  declare module "sortablejs" {
8
+ interface SortableEvent {
9
+ oldIndex?: number;
10
+ newIndex?: number;
11
+ item: HTMLElement;
12
+ }
13
+
8
14
  interface SortableOptions {
9
15
  animation?: number;
10
16
  handle?: string;
11
- onEnd?: (event: { oldIndex?: number; newIndex?: number }) => void;
17
+ onEnd?: (event: SortableEvent) => void;
12
18
  }
13
19
 
14
20
  interface SortableInstance {
@@ -157,12 +157,12 @@ export interface ArchiveGroup {
157
157
  */
158
158
  export interface SiteLayoutProps {
159
159
  siteName: string;
160
- siteDescription?: string;
161
160
  links: NavItemView[];
162
161
  currentPath: string;
163
162
  isAuthenticated?: boolean;
164
163
  collections?: Collection[];
165
164
  homeDefaultView?: string;
165
+ headerNavMaxVisible?: number;
166
166
  siteAvatarUrl?: string;
167
167
  showHeaderAvatar?: boolean;
168
168
  siteFooterHtml?: string;
@@ -118,6 +118,37 @@ function defineTheme(opts: {
118
118
  }
119
119
 
120
120
  export const BUILTIN_COLOR_THEMES: ColorTheme[] = [
121
+ defineTheme({
122
+ id: "notepad",
123
+ name: "Notepad",
124
+ preview: {
125
+ lightBg: "#fdfce8",
126
+ lightText: "#333333",
127
+ lightLink: "#2060b8",
128
+ darkBg: "#2a291a",
129
+ darkText: "#d2d2b8",
130
+ darkLink: "#6695cc",
131
+ },
132
+ light: {
133
+ bg: "oklch(0.985 0.018 95)",
134
+ fg: "oklch(0.27 0 0)",
135
+ primary: "oklch(0.5 0.17 260)",
136
+ primaryFg: "oklch(0.985 0.01 95)",
137
+ muted: "oklch(0.94 0.022 95)",
138
+ mutedFg: "oklch(0.52 0 0)",
139
+ border: "oklch(0.88 0.025 95)",
140
+ },
141
+ dark: {
142
+ bg: "oklch(0.2 0.02 90)",
143
+ fg: "oklch(0.87 0.015 95)",
144
+ primary: "oklch(0.65 0.14 260)",
145
+ primaryFg: "oklch(0.98 0.01 95)",
146
+ muted: "oklch(0.26 0.018 90)",
147
+ mutedFg: "oklch(0.62 0.012 95)",
148
+ border: "oklch(0.32 0.018 90)",
149
+ },
150
+ }),
151
+
121
152
  defineTheme({
122
153
  id: "halloween",
123
154
  name: "Halloween",
@@ -257,37 +288,6 @@ export const BUILTIN_COLOR_THEMES: ColorTheme[] = [
257
288
  },
258
289
  }),
259
290
 
260
- defineTheme({
261
- id: "notepad",
262
- name: "Notepad",
263
- preview: {
264
- lightBg: "#fdfce8",
265
- lightText: "#333333",
266
- lightLink: "#2060b8",
267
- darkBg: "#2a291a",
268
- darkText: "#d2d2b8",
269
- darkLink: "#6695cc",
270
- },
271
- light: {
272
- bg: "oklch(0.985 0.018 95)",
273
- fg: "oklch(0.27 0 0)",
274
- primary: "oklch(0.5 0.17 260)",
275
- primaryFg: "oklch(0.985 0.01 95)",
276
- muted: "oklch(0.94 0.022 95)",
277
- mutedFg: "oklch(0.52 0 0)",
278
- border: "oklch(0.88 0.025 95)",
279
- },
280
- dark: {
281
- bg: "oklch(0.2 0.02 90)",
282
- fg: "oklch(0.87 0.015 95)",
283
- primary: "oklch(0.65 0.14 260)",
284
- primaryFg: "oklch(0.98 0.01 95)",
285
- muted: "oklch(0.26 0.018 90)",
286
- mutedFg: "oklch(0.62 0.012 95)",
287
- border: "oklch(0.32 0.018 90)",
288
- },
289
- }),
290
-
291
291
  defineTheme({
292
292
  id: "sonnet",
293
293
  name: "Sonnet",
@@ -33,9 +33,6 @@ const labels: SettingsLabels = {
33
33
  aboutBlog: "About this blog",
34
34
  aboutBlogHelp: "Displayed above your blog posts.",
35
35
  language: "Language",
36
- defaultHomepageView: "Default Homepage View",
37
- latest: "Latest",
38
- featured: "Featured",
39
36
  timeZone: "Time Zone",
40
37
  siteFooter: "Site Footer",
41
38
  markdownSupported: "Markdown supported",
@@ -34,9 +34,6 @@ const labels: SettingsLabels = {
34
34
  aboutBlog: "About this blog",
35
35
  aboutBlogHelp: "Displayed above your blog posts.",
36
36
  language: "Language",
37
- defaultHomepageView: "Default Homepage View",
38
- latest: "Latest",
39
- featured: "Featured",
40
37
  timeZone: "Time Zone",
41
38
  siteFooter: "Site Footer",
42
39
  footerHelp: "Displayed at the bottom of posts.",
@@ -61,7 +58,6 @@ const initialData = {
61
58
  siteName: "My Blog",
62
59
  siteDescription: "A test blog",
63
60
  siteLanguage: "en",
64
- homeDefaultView: "latest",
65
61
  timeZone: "UTC",
66
62
  siteFooter: "Footer text",
67
63
  noindex: false,
@@ -112,8 +108,8 @@ describe("JantSettingsGeneral", () => {
112
108
  it("renders timezone options", async () => {
113
109
  const el = await createElement();
114
110
  const selects = el.querySelectorAll("select");
115
- // Third select is timezone (language, homepage view, timezone)
116
- const tzSelect = selects[2];
111
+ // Second select is timezone (language, timezone)
112
+ const tzSelect = selects[1];
117
113
  const options = tzSelect?.querySelectorAll("option");
118
114
  expect(options?.length).toBe(2);
119
115
  expect(options?.[0]?.value).toBe("UTC");
@@ -246,6 +246,7 @@ export class JantComposeDialog extends LitElement {
246
246
  @click=${() => this._submit("draft")}
247
247
  >
248
248
  <svg
249
+ class="icon-fine"
249
250
  width="18"
250
251
  height="18"
251
252
  viewBox="0 0 18 18"
@@ -363,7 +364,7 @@ export class JantComposeDialog extends LitElement {
363
364
  stroke-width="1.4"
364
365
  stroke-linecap="round"
365
366
  stroke-linejoin="round"
366
- class="shrink-0"
367
+ class="shrink-0 icon-fine"
367
368
  >
368
369
  <rect x="3" y="5" width="12" height="10" rx="2" />
369
370
  <path d="M6 5V4a1 1 0 011-1h4a1 1 0 011 1v1" />
@@ -382,7 +383,7 @@ export class JantComposeDialog extends LitElement {
382
383
  stroke-width="1.4"
383
384
  stroke-linecap="round"
384
385
  stroke-linejoin="round"
385
- class="shrink-0 opacity-50"
386
+ class="shrink-0 opacity-50 icon-fine"
386
387
  >
387
388
  <path d="M3 4l2 2 2-2" />
388
389
  </svg>
@@ -235,6 +235,15 @@ export class JantComposeEditor extends LitElement {
235
235
  const attachment = this._attachments[index];
236
236
  if (attachment) {
237
237
  URL.revokeObjectURL(attachment.previewUrl);
238
+ this.dispatchEvent(
239
+ new CustomEvent("jant:attachment-removed", {
240
+ bubbles: true,
241
+ detail: {
242
+ clientId: attachment.clientId,
243
+ mediaId: attachment.mediaId,
244
+ },
245
+ }),
246
+ );
238
247
  }
239
248
  this._attachments = this._attachments.filter((_, i) => i !== index);
240
249
  // Close alt panel if it was showing the removed item
@@ -420,7 +429,7 @@ export class JantComposeEditor extends LitElement {
420
429
  stroke="currentColor"
421
430
  stroke-width="1.3"
422
431
  stroke-linecap="round"
423
- class="text-muted-foreground"
432
+ class="text-muted-foreground icon-fine"
424
433
  >
425
434
  <rect x="3" y="2" width="12" height="14" rx="2" />
426
435
  <line x1="6" y1="6" x2="12" y2="6" />
@@ -461,6 +470,7 @@ export class JantComposeEditor extends LitElement {
461
470
  }}
462
471
  >
463
472
  <svg
473
+ class="icon-fine"
464
474
  width="16"
465
475
  height="16"
466
476
  viewBox="0 0 16 16"
@@ -527,6 +537,7 @@ export class JantComposeEditor extends LitElement {
527
537
  @click=${() => this._closeAltPanel()}
528
538
  >
529
539
  <svg
540
+ class="icon-fine"
530
541
  width="16"
531
542
  height="16"
532
543
  viewBox="0 0 16 16"
@@ -599,7 +610,7 @@ export class JantComposeEditor extends LitElement {
599
610
  viewBox="0 0 24 24"
600
611
  fill="none"
601
612
  stroke="currentColor"
602
- stroke-width="2.5"
613
+ style="stroke-width: 2.5"
603
614
  stroke-linecap="round"
604
615
  >
605
616
  <path d="M21 12a9 9 0 1 1-6.219-8.56" />
@@ -613,6 +624,7 @@ export class JantComposeEditor extends LitElement {
613
624
  class="compose-attachment-overlay compose-attachment-error"
614
625
  >
615
626
  <svg
627
+ class="icon-fine"
616
628
  width="16"
617
629
  height="16"
618
630
  viewBox="0 0 16 16"
@@ -666,6 +678,7 @@ export class JantComposeEditor extends LitElement {
666
678
  @click=${() => this._openFilePicker()}
667
679
  >
668
680
  <svg
681
+ class="icon-fine"
669
682
  width="18"
670
683
  height="18"
671
684
  viewBox="0 0 18 18"
@@ -697,6 +710,7 @@ export class JantComposeEditor extends LitElement {
697
710
  @click=${() => this._openAttachedText()}
698
711
  >
699
712
  <svg
713
+ class="icon-fine"
700
714
  width="18"
701
715
  height="18"
702
716
  viewBox="0 0 18 18"
@@ -725,6 +739,7 @@ export class JantComposeEditor extends LitElement {
725
739
  }}
726
740
  >
727
741
  <svg
742
+ class="icon-fine"
728
743
  width="18"
729
744
  height="18"
730
745
  viewBox="0 0 18 18"