@jant/core 0.6.16 → 0.7.0

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 (508) hide show
  1. package/README.md +11 -11
  2. package/bin/commands/assets/upload.js +192 -15
  3. package/bin/commands/import-site.js +60 -4
  4. package/bin/commands/reset-password.js +21 -8
  5. package/bin/commands/site/snapshot/export.js +1 -1
  6. package/bin/commands/site/snapshot/import.js +1 -1
  7. package/bin/lib/d1-query.js +5 -16
  8. package/bin/lib/node-env.js +40 -4
  9. package/bin/lib/site-selection.js +85 -29
  10. package/bin/lib/wrangler-cli.js +28 -2
  11. package/bin/lib/wrangler-json.js +35 -0
  12. package/dist/{app-C7_4oab9.js → app-K_Aa1MMn.js} +52476 -13330
  13. package/dist/client/.vite/manifest.json +255 -90
  14. package/dist/client/_assets/chunks/confirm-D7GrwsCN.js +45 -0
  15. package/dist/client/_assets/chunks/create-editor-CD3FhrOB.js +257 -0
  16. package/dist/client/_assets/chunks/{native-DpcrFAPh.js → emoji-mart-C4RpRKcU.js} +716 -1
  17. package/dist/client/_assets/chunks/footnote-rail-CmeoVtnU.js +1 -0
  18. package/dist/client/_assets/chunks/heic-to-CuP2Qlsw.js +1 -0
  19. package/dist/client/_assets/chunks/jant-locale-picker-DL6mIOT5.js +69 -0
  20. package/dist/client/_assets/chunks/lit-DW8VmJAT.js +2 -0
  21. package/dist/client/_assets/chunks/mediabunny-DRaCQ1r-.js +31 -0
  22. package/dist/client/_assets/chunks/rolldown-runtime-hePW80VL.js +1 -0
  23. package/dist/client/_assets/chunks/settings-paths-BcdySNx6.js +84 -0
  24. package/dist/client/_assets/chunks/site-header-nav-DzXsFk05.js +1 -0
  25. package/dist/client/_assets/chunks/slug-format-CRXO1AL5.js +1 -0
  26. package/dist/client/_assets/chunks/slugify-373citbs.js +1 -0
  27. package/dist/client/_assets/chunks/sortable-list-CgaL2jCs.js +2 -0
  28. package/dist/client/_assets/chunks/types-D5iF3H1a.js +1 -0
  29. package/dist/client/_assets/chunks/unsafe-html-B5ZEXaxg.js +1 -0
  30. package/dist/client/_assets/chunks/unsafe-svg-0QCkP0vZ.js +2 -0
  31. package/dist/client/_assets/client-GiYENVw8.css +2 -0
  32. package/dist/client/_assets/client-VnFxJN7G.js +295 -0
  33. package/dist/client/_assets/client-auth-k8gJ6QJj.js +828 -0
  34. package/dist/client/_assets/client-author-DQ8R-8KR.css +2 -0
  35. package/dist/client/_assets/client-compose-B_kDtWkW.js +2004 -0
  36. package/dist/client/_assets/client-manage-M90aSTOk.js +2170 -0
  37. package/dist/client/_assets/client-settings-DfYs9n1F.js +1112 -0
  38. package/dist/{export-Dl5KCiEs.js → github-sync-BPAvT999.js} +2254 -107
  39. package/dist/index.js +2 -5
  40. package/dist/node.js +5 -7
  41. package/package.json +3 -3
  42. package/src/__tests__/auth-session-freshness.test.ts +57 -0
  43. package/src/__tests__/basecoat-variants.test.ts +121 -0
  44. package/src/__tests__/bin/assets-upload.test.ts +68 -0
  45. package/src/__tests__/export-hugo-build.test.ts +260 -0
  46. package/src/__tests__/export-service.test.ts +231 -0
  47. package/src/__tests__/helpers/component-css.ts +91 -0
  48. package/src/__tests__/helpers/db.ts +33 -0
  49. package/src/__tests__/helpers/export-fixtures.ts +3 -0
  50. package/src/__tests__/stylesheet-audience.test.ts +159 -0
  51. package/src/__tests__/stylesheet-breakpoints.test.ts +183 -0
  52. package/src/app.tsx +71 -16
  53. package/src/auth.ts +18 -1
  54. package/src/client/__tests__/collection-page-actions.test.ts +51 -2
  55. package/src/client/__tests__/compose-bridge-image-upload.test.ts +196 -0
  56. package/src/client/__tests__/compose-bridge-video-poster.test.ts +159 -0
  57. package/src/client/__tests__/compose-bridge.test.ts +272 -0
  58. package/src/client/__tests__/compose-launch.test.ts +62 -1
  59. package/src/client/__tests__/compose-shortcuts.test.ts +38 -9
  60. package/src/client/__tests__/compose-triggers.test.ts +90 -0
  61. package/src/client/__tests__/copy-field.test.ts +162 -0
  62. package/src/client/__tests__/custom-url-menu.test.ts +127 -6
  63. package/src/client/__tests__/image-processor.test.ts +324 -2
  64. package/src/client/__tests__/lazy-entries.test.ts +92 -0
  65. package/src/client/__tests__/media-scroll-hint.test.ts +155 -0
  66. package/src/client/__tests__/runtime-paths.test.ts +84 -0
  67. package/src/client/__tests__/smart-collection-page-actions.test.ts +158 -0
  68. package/src/client/__tests__/toast.test.ts +23 -0
  69. package/src/client/__tests__/video-processor-probe.test.ts +175 -0
  70. package/src/client/__tests__/video-processor.test.ts +181 -0
  71. package/src/client/audio-processor.ts +24 -15
  72. package/src/client/audio-waveform.ts +49 -0
  73. package/src/client/collection-dialog-host.ts +72 -0
  74. package/src/client/collection-navigation.ts +51 -16
  75. package/src/client/collection-page-actions.ts +26 -0
  76. package/src/client/components/__tests__/jant-collection-dialog.test.ts +329 -0
  77. package/src/client/components/__tests__/jant-collection-directory.test.ts +274 -10
  78. package/src/client/components/__tests__/jant-collection-form.test.ts +59 -178
  79. package/src/client/components/__tests__/jant-command-palette.test.ts +28 -0
  80. package/src/client/components/__tests__/jant-compose-dialog-draft-storage.test.ts +340 -0
  81. package/src/client/components/__tests__/jant-compose-dialog.test.ts +1250 -53
  82. package/src/client/components/__tests__/jant-compose-editor.test.ts +544 -40
  83. package/src/client/components/__tests__/jant-compose-fullscreen.test.ts +0 -1
  84. package/src/client/components/__tests__/jant-locale-picker.test.ts +207 -0
  85. package/src/client/components/__tests__/jant-nav-manager.test.ts +234 -15
  86. package/src/client/components/__tests__/jant-post-menu.test.ts +413 -2
  87. package/src/client/components/__tests__/jant-post-picker.test.ts +197 -0
  88. package/src/client/components/__tests__/jant-settings-avatar.test.ts +15 -12
  89. package/src/client/components/__tests__/jant-settings-general.test.ts +541 -172
  90. package/src/client/components/__tests__/jant-settings-language.test.ts +851 -0
  91. package/src/client/components/__tests__/jant-smart-collection-dialog.test.ts +665 -0
  92. package/src/client/components/collection-dialog-types.ts +49 -0
  93. package/src/client/components/collection-manager-types.ts +32 -1
  94. package/src/client/components/collection-types.ts +1 -15
  95. package/src/client/components/compose-types.ts +75 -1
  96. package/src/client/components/jant-collection-dialog.ts +722 -0
  97. package/src/client/components/jant-collection-directory.ts +567 -182
  98. package/src/client/components/jant-collection-form.ts +53 -232
  99. package/src/client/components/jant-command-palette.ts +100 -49
  100. package/src/client/components/jant-compose-dialog.ts +1486 -707
  101. package/src/client/components/jant-compose-editor.ts +673 -336
  102. package/src/client/components/jant-compose-fullscreen.ts +51 -43
  103. package/src/client/components/jant-config-editor.ts +65 -53
  104. package/src/client/components/jant-confirm-dialog.ts +13 -11
  105. package/src/client/components/jant-locale-picker.ts +418 -0
  106. package/src/client/components/jant-media-lightbox.ts +146 -136
  107. package/src/client/components/jant-nav-manager.ts +690 -366
  108. package/src/client/components/jant-post-menu.ts +1086 -282
  109. package/src/client/components/jant-post-picker.ts +324 -0
  110. package/src/client/components/jant-repo-picker.ts +138 -106
  111. package/src/client/components/jant-settings-avatar.ts +31 -27
  112. package/src/client/components/jant-settings-general.ts +617 -543
  113. package/src/client/components/jant-settings-language.ts +1087 -0
  114. package/src/client/components/jant-smart-collection-dialog.ts +1021 -0
  115. package/src/client/components/jant-text-preview.ts +94 -86
  116. package/src/client/components/nav-manager-types.ts +62 -1
  117. package/src/client/components/settings-types.ts +14 -29
  118. package/src/client/components/smart-collection-conditions.ts +285 -0
  119. package/src/client/components/smart-collection-dialog-types.ts +68 -0
  120. package/src/client/compose-bridge.ts +214 -141
  121. package/src/client/compose-launch.ts +76 -2
  122. package/src/client/compose-shortcuts.ts +6 -8
  123. package/src/client/compose-triggers.ts +50 -0
  124. package/src/client/copy-field.ts +108 -0
  125. package/src/client/custom-url-menu.ts +60 -4
  126. package/src/client/icons.ts +14 -0
  127. package/src/client/image-plan.ts +165 -0
  128. package/src/client/image-processor.ts +195 -117
  129. package/src/client/image-worker-client.ts +45 -0
  130. package/src/client/image-worker.ts +135 -0
  131. package/src/client/lazy-entries.ts +95 -0
  132. package/src/client/lazy-slugify.ts +2 -2
  133. package/src/client/media-scroll-hint.ts +43 -2
  134. package/src/client/mediabunny.ts +29 -0
  135. package/src/client/post-picker.ts +41 -0
  136. package/src/client/runtime-paths.ts +74 -1
  137. package/src/client/settings-bridge.ts +4 -10
  138. package/src/client/site-header-nav.js +18 -6
  139. package/src/client/smart-collection-dialog-host.ts +116 -0
  140. package/src/client/smart-collection-page-actions.ts +208 -0
  141. package/src/client/tiptap/__tests__/bubble-menu.test.ts +110 -0
  142. package/src/client/tiptap/__tests__/floating-position.test.ts +136 -1
  143. package/src/client/tiptap/__tests__/inline-image-upload.test.ts +37 -0
  144. package/src/client/tiptap/bubble-menu.ts +47 -16
  145. package/src/client/tiptap/floating-position.ts +216 -2
  146. package/src/client/tiptap/inline-image-upload.ts +7 -3
  147. package/src/client/tiptap/link-toolbar.ts +22 -9
  148. package/src/client/toast.ts +13 -0
  149. package/src/client/types/vite-worker.d.ts +12 -0
  150. package/src/client/upload-with-metadata.ts +3 -13
  151. package/src/client/video-processor.ts +351 -107
  152. package/src/client-auth.ts +14 -31
  153. package/src/client-compose.ts +19 -0
  154. package/src/client-manage.ts +13 -0
  155. package/src/client-settings.ts +14 -0
  156. package/src/client-site.ts +10 -3
  157. package/src/client.ts +4 -0
  158. package/src/db/__tests__/backfill-nav-label-mirrors.test.ts +149 -0
  159. package/src/db/__tests__/schema-enum-sources.test.ts +33 -0
  160. package/src/db/__tests__/smart-collection-placement.test.ts +402 -0
  161. package/src/db/backfills/0006_clear_mirrored_page_nav_labels.sql +31 -0
  162. package/src/db/migrations/0032_married_tomas.sql +3 -0
  163. package/src/db/migrations/0033_busy_johnny_storm.sql +198 -0
  164. package/src/db/migrations/0034_cheerful_rumiko_fujikawa.sql +35 -0
  165. package/src/db/migrations/meta/0032_snapshot.json +2582 -0
  166. package/src/db/migrations/meta/0033_snapshot.json +2816 -0
  167. package/src/db/migrations/meta/0034_snapshot.json +2816 -0
  168. package/src/db/migrations/meta/_journal.json +21 -0
  169. package/src/db/migrations/pg/0030_abandoned_nighthawk.sql +3 -0
  170. package/src/db/migrations/pg/0031_strong_ultimatum.sql +128 -0
  171. package/src/db/migrations/pg/0032_furry_multiple_man.sql +6 -0
  172. package/src/db/migrations/pg/meta/0030_snapshot.json +3329 -0
  173. package/src/db/migrations/pg/meta/0031_snapshot.json +3660 -0
  174. package/src/db/migrations/pg/meta/0032_snapshot.json +3660 -0
  175. package/src/db/migrations/pg/meta/_journal.json +21 -0
  176. package/src/db/pg/schema.ts +195 -27
  177. package/src/db/post-visibility.ts +117 -0
  178. package/src/db/schema.ts +222 -27
  179. package/src/i18n/__tests__/detect.test.ts +26 -81
  180. package/src/i18n/__tests__/supported-locales.test.ts +83 -0
  181. package/src/i18n/context.tsx +12 -2
  182. package/src/i18n/detect.ts +7 -66
  183. package/src/i18n/locales/glossary.zh-Hans.yml +44 -4
  184. package/src/i18n/locales/glossary.zh-Hant.yml +44 -4
  185. package/src/i18n/locales/public/en.po +490 -158
  186. package/src/i18n/locales/public/en.ts +1 -1
  187. package/src/i18n/locales/public/zh-Hans.po +487 -155
  188. package/src/i18n/locales/public/zh-Hans.ts +1 -1
  189. package/src/i18n/locales/public/zh-Hant.po +487 -155
  190. package/src/i18n/locales/public/zh-Hant.ts +1 -1
  191. package/src/i18n/locales/settings/en.po +551 -69
  192. package/src/i18n/locales/settings/en.ts +1 -1
  193. package/src/i18n/locales/settings/zh-Hans.po +597 -115
  194. package/src/i18n/locales/settings/zh-Hans.ts +1 -1
  195. package/src/i18n/locales/settings/zh-Hant.po +610 -128
  196. package/src/i18n/locales/settings/zh-Hant.ts +1 -1
  197. package/src/i18n/locales.ts +94 -0
  198. package/src/i18n/middleware.ts +12 -2
  199. package/src/i18n/supported-locales.ts +80 -0
  200. package/src/lib/__tests__/api-settings.test.ts +11 -2
  201. package/src/lib/__tests__/asset-path.test.ts +92 -0
  202. package/src/lib/__tests__/deferred.test.ts +90 -0
  203. package/src/lib/__tests__/discover-ping.test.ts +89 -0
  204. package/src/lib/__tests__/discover.test.ts +410 -0
  205. package/src/lib/__tests__/feed-policy.test.ts +26 -0
  206. package/src/lib/__tests__/feed.test.ts +1526 -15
  207. package/src/lib/__tests__/filter-dimensions.test.ts +341 -0
  208. package/src/lib/__tests__/hosted-signin.test.ts +1 -1
  209. package/src/lib/__tests__/http-cache.test.ts +162 -0
  210. package/src/lib/__tests__/jant-docs-dev.test.ts +21 -0
  211. package/src/lib/__tests__/jant-docs.test.ts +23 -0
  212. package/src/lib/__tests__/lang-detect.test.ts +231 -0
  213. package/src/lib/__tests__/media-helpers.test.ts +81 -0
  214. package/src/lib/__tests__/navigation.test.ts +135 -1
  215. package/src/lib/__tests__/resolve-config.test.ts +64 -3
  216. package/src/lib/__tests__/schemas.test.ts +42 -4
  217. package/src/lib/__tests__/site-unavailable-page.test.ts +25 -0
  218. package/src/lib/__tests__/slug.test.ts +70 -0
  219. package/src/lib/__tests__/slugify.test.ts +85 -0
  220. package/src/lib/__tests__/storage.test.ts +32 -0
  221. package/src/lib/__tests__/thread-fold.test.ts +113 -0
  222. package/src/lib/__tests__/upload-sideload.test.ts +14 -0
  223. package/src/lib/__tests__/url-fetch.test.ts +1 -2
  224. package/src/lib/__tests__/url.test.ts +78 -72
  225. package/src/lib/__tests__/view-language.test.ts +413 -0
  226. package/src/lib/__tests__/worker-response-cache.test.ts +90 -0
  227. package/src/lib/address.ts +57 -0
  228. package/src/lib/api-posts.ts +12 -0
  229. package/src/lib/asset-path.ts +98 -1
  230. package/src/lib/build-env.ts +16 -0
  231. package/src/lib/collection-groups.ts +5 -1
  232. package/src/lib/collection-paths.ts +3 -10
  233. package/src/lib/constants.ts +28 -3
  234. package/src/lib/copy-field.ts +36 -0
  235. package/src/lib/crypto.ts +40 -0
  236. package/src/lib/csp-builder.ts +2 -1
  237. package/src/lib/deferred.ts +79 -0
  238. package/src/lib/discover-ping.ts +141 -0
  239. package/src/lib/discover.ts +437 -0
  240. package/src/lib/env.ts +134 -0
  241. package/src/lib/errors.ts +33 -0
  242. package/src/lib/feed-policy.ts +236 -2
  243. package/src/lib/feed.ts +926 -73
  244. package/src/lib/filter-dimensions.ts +1349 -0
  245. package/src/lib/github-sync-site-config.ts +3 -0
  246. package/src/lib/hosted-signin.ts +1 -1
  247. package/src/lib/http-cache.ts +148 -0
  248. package/src/lib/hugo-markdown.ts +16 -0
  249. package/src/lib/icons.ts +9 -2
  250. package/src/lib/ids.ts +3 -0
  251. package/src/lib/jant-docs.ts +42 -0
  252. package/src/lib/lang-detect.ts +308 -0
  253. package/src/lib/media-helpers.ts +13 -1
  254. package/src/lib/navigation.ts +78 -11
  255. package/src/lib/pagination.ts +28 -24
  256. package/src/lib/per-language-surfaces.ts +67 -0
  257. package/src/lib/post-meta.ts +19 -0
  258. package/src/lib/render.tsx +55 -7
  259. package/src/lib/resolve-config.ts +53 -5
  260. package/src/lib/schemas.ts +201 -10
  261. package/src/lib/site-header-fragment.tsx +2 -1
  262. package/src/lib/site-unavailable-page.ts +47 -0
  263. package/src/lib/slug.ts +51 -7
  264. package/src/lib/slugify.ts +113 -0
  265. package/src/lib/startup-config.ts +4 -6
  266. package/src/lib/storage.ts +7 -0
  267. package/src/lib/summary.ts +50 -0
  268. package/src/lib/thread-fold.ts +161 -0
  269. package/src/lib/time.ts +32 -0
  270. package/src/lib/timeline.ts +42 -1
  271. package/src/lib/tiptap-render.ts +1 -2
  272. package/src/lib/upload.ts +16 -13
  273. package/src/lib/url.ts +139 -86
  274. package/src/lib/version.ts +10 -8
  275. package/src/lib/view-language.ts +436 -0
  276. package/src/lib/view.ts +51 -23
  277. package/src/lib/viewer-context.ts +62 -0
  278. package/src/middleware/__tests__/auth.test.ts +70 -2
  279. package/src/middleware/__tests__/cache-control.test.ts +71 -3
  280. package/src/middleware/__tests__/onboarding.test.ts +76 -5
  281. package/src/middleware/__tests__/secure-headers.test.ts +1 -1
  282. package/src/middleware/__tests__/session.test.ts +181 -33
  283. package/src/middleware/auth.ts +50 -31
  284. package/src/middleware/cache-control.ts +75 -10
  285. package/src/middleware/config.ts +6 -6
  286. package/src/middleware/error-handler.ts +12 -0
  287. package/src/middleware/onboarding.ts +32 -10
  288. package/src/middleware/secure-headers.ts +1 -1
  289. package/src/middleware/session.ts +96 -8
  290. package/src/node/__tests__/cli-migrate.test.ts +21 -19
  291. package/src/node/__tests__/cli-reset-password.test.ts +81 -8
  292. package/src/node/__tests__/cli-runtime-target.test.ts +48 -1
  293. package/src/node/__tests__/cli-site-selection.test.ts +128 -38
  294. package/src/node/__tests__/runtime.test.ts +37 -0
  295. package/src/node/index.ts +1 -0
  296. package/src/preset.css +76 -22
  297. package/src/routes/__tests__/feed-validator.test.ts +156 -0
  298. package/src/routes/api/__tests__/collections.test.ts +114 -0
  299. package/src/routes/api/__tests__/discover.test.ts +222 -0
  300. package/src/routes/api/__tests__/nav-items.test.ts +212 -2
  301. package/src/routes/api/__tests__/post-translations.test.ts +829 -0
  302. package/src/routes/api/__tests__/settings.test.ts +24 -3
  303. package/src/routes/api/__tests__/telegram.test.ts +6 -5
  304. package/src/routes/api/collections.ts +49 -6
  305. package/src/routes/api/custom-urls.ts +0 -1
  306. package/src/routes/api/discover.ts +95 -0
  307. package/src/routes/api/export.ts +3 -0
  308. package/src/routes/api/internal/__tests__/sites.test.ts +42 -2
  309. package/src/routes/api/nav-items.ts +55 -8
  310. package/src/routes/api/posts.ts +159 -0
  311. package/src/routes/api/public/__tests__/archive.test.ts +111 -0
  312. package/src/routes/api/public/archive.ts +77 -81
  313. package/src/routes/api/public/posts.ts +23 -6
  314. package/src/routes/api/smart-collections.ts +132 -0
  315. package/src/routes/api/telegram.ts +2 -40
  316. package/src/routes/api/uploads.ts +1 -2
  317. package/src/routes/auth/__tests__/setup-auth.test.ts +137 -0
  318. package/src/routes/auth/__tests__/setup-discover.test.ts +204 -0
  319. package/src/routes/auth/__tests__/setup-flow.test.ts +270 -0
  320. package/src/routes/auth/__tests__/setup-page.test.tsx +329 -0
  321. package/src/routes/auth/__tests__/setup-steps.test.ts +310 -0
  322. package/src/routes/auth/__tests__/setup.test.ts +278 -26
  323. package/src/routes/auth/__tests__/signin.test.ts +135 -0
  324. package/src/routes/auth/setup.tsx +934 -186
  325. package/src/routes/auth/signin.tsx +10 -8
  326. package/src/routes/compose.tsx +5 -0
  327. package/src/routes/dash/__tests__/custom-urls-archive.test.ts +44 -0
  328. package/src/routes/dash/__tests__/custom-urls-page.test.ts +49 -0
  329. package/src/routes/dash/__tests__/delete-account.test.ts +106 -0
  330. package/src/routes/dash/__tests__/settings-discover.test.ts +213 -0
  331. package/src/routes/dash/custom-urls.tsx +1 -37
  332. package/src/routes/dash/settings.tsx +502 -41
  333. package/src/routes/discover-announce.ts +96 -0
  334. package/src/routes/feed/__tests__/feed.test.ts +165 -2
  335. package/src/routes/feed/feed.ts +69 -40
  336. package/src/routes/feed/sitemap.ts +95 -11
  337. package/src/routes/pages/__tests__/archive-indexing.test.ts +200 -0
  338. package/src/routes/pages/__tests__/archive-params.test.ts +370 -6
  339. package/src/routes/pages/__tests__/collection-routing.test.ts +16 -0
  340. package/src/routes/pages/__tests__/collections-feed-links.test.ts +72 -0
  341. package/src/routes/pages/__tests__/collections.test.ts +9 -3
  342. package/src/routes/pages/__tests__/custom-archive-url.test.ts +119 -0
  343. package/src/routes/pages/__tests__/feed-autodiscovery.test.ts +148 -0
  344. package/src/routes/pages/__tests__/language-routing.test.ts +679 -0
  345. package/src/routes/pages/__tests__/post-preview-partial.test.ts +96 -0
  346. package/src/routes/pages/__tests__/smart-collection.test.ts +298 -0
  347. package/src/routes/pages/__tests__/subscribe.test.ts +248 -0
  348. package/src/routes/pages/archive.tsx +471 -369
  349. package/src/routes/pages/collection.tsx +94 -96
  350. package/src/routes/pages/collections.tsx +38 -50
  351. package/src/routes/pages/featured.tsx +32 -13
  352. package/src/routes/pages/home.tsx +25 -6
  353. package/src/routes/pages/language.tsx +113 -0
  354. package/src/routes/pages/latest.tsx +26 -16
  355. package/src/routes/pages/new.tsx +3 -0
  356. package/src/routes/pages/page.tsx +178 -17
  357. package/src/routes/pages/partials.tsx +41 -0
  358. package/src/routes/pages/search.tsx +18 -3
  359. package/src/routes/pages/smart-collection.tsx +340 -0
  360. package/src/routes/pages/subscribe.tsx +182 -0
  361. package/src/runtime/__tests__/index.test.ts +19 -0
  362. package/src/runtime/__tests__/node.test.ts +129 -4
  363. package/src/runtime/cloudflare.ts +21 -2
  364. package/src/runtime/index.ts +27 -1
  365. package/src/runtime/node.ts +18 -1
  366. package/src/runtime/site.ts +95 -24
  367. package/src/services/__tests__/auth.test.ts +116 -7
  368. package/src/services/__tests__/collection.test.ts +108 -4
  369. package/src/services/__tests__/language.test.ts +495 -0
  370. package/src/services/__tests__/navigation.test.ts +213 -10
  371. package/src/services/__tests__/path.test.ts +180 -0
  372. package/src/services/__tests__/post-language.test.ts +830 -0
  373. package/src/services/__tests__/post.test.ts +46 -9
  374. package/src/services/__tests__/settings.test.ts +228 -17
  375. package/src/services/__tests__/site-admin.test.ts +5 -5
  376. package/src/services/__tests__/smart-collection.test.ts +651 -0
  377. package/src/services/about-page.ts +22 -1
  378. package/src/services/auth.ts +51 -49
  379. package/src/services/bootstrap.ts +188 -38
  380. package/src/services/collection-directory-position.ts +76 -0
  381. package/src/services/collection.ts +331 -46
  382. package/src/services/custom-url.ts +27 -22
  383. package/src/services/export-theme/assets/client-site.css +1 -1
  384. package/src/services/export-theme/assets/client-site.js +123 -123
  385. package/src/services/export-theme/layouts/_default/rss.xml +77 -1
  386. package/src/services/export-theme/layouts/partials/feed-post-content.xml +105 -2
  387. package/src/services/export-theme/layouts/partials/media-gallery.html +35 -21
  388. package/src/services/export-theme/layouts/partials/pagination.html +14 -13
  389. package/src/services/export-theme/layouts/partials/post-card.html +8 -4
  390. package/src/services/export-theme/layouts/partials/reply.html +2 -1
  391. package/src/services/export-theme/layouts/partials/thread-preview.html +40 -30
  392. package/src/services/export-theme/styles/main.css +13 -1
  393. package/src/services/export.ts +278 -19
  394. package/src/services/index.ts +34 -3
  395. package/src/services/language.ts +412 -0
  396. package/src/services/mcp.ts +3 -1
  397. package/src/services/media.ts +14 -6
  398. package/src/services/navigation.ts +429 -67
  399. package/src/services/path.ts +221 -6
  400. package/src/services/post.ts +1021 -152
  401. package/src/services/search.ts +39 -2
  402. package/src/services/settings.ts +238 -43
  403. package/src/services/site-admin.ts +24 -7
  404. package/src/services/site.ts +77 -1
  405. package/src/services/smart-collection.ts +636 -0
  406. package/src/services/telegram.ts +20 -22
  407. package/src/services/upload-session.ts +1 -3
  408. package/src/style-author.css +27 -0
  409. package/src/styles/components-author.css +1622 -0
  410. package/src/styles/components.css +24 -1571
  411. package/src/styles/site-media.css +16 -2
  412. package/src/styles/tokens.css +82 -12
  413. package/src/styles/ui-author.css +7602 -0
  414. package/src/styles/ui.css +1087 -7219
  415. package/src/types/app-context.ts +7 -0
  416. package/src/types/bindings.ts +3 -0
  417. package/src/types/config.ts +94 -15
  418. package/src/types/constants.ts +188 -16
  419. package/src/types/entities.ts +87 -1
  420. package/src/types/operations.ts +64 -2
  421. package/src/types/props.ts +157 -31
  422. package/src/types/views.ts +55 -1
  423. package/src/ui/__tests__/font-themes.test.ts +52 -12
  424. package/src/ui/compose/ComposeDialog.tsx +201 -7
  425. package/src/ui/compose/ComposePrompt.tsx +1 -5
  426. package/src/ui/compose/__tests__/ComposeDialog.test.tsx +125 -0
  427. package/src/ui/dash/appearance/AdvancedContent.tsx +2 -2
  428. package/src/ui/dash/appearance/CodeInjectionContent.tsx +12 -16
  429. package/src/ui/dash/appearance/NavigationContent.tsx +117 -16
  430. package/src/ui/dash/appearance/__tests__/NavigationContent.test.tsx +33 -11
  431. package/src/ui/dash/appearance/__tests__/system-nav-descriptions.test.ts +44 -0
  432. package/src/ui/dash/appearance/system-nav-descriptions.ts +75 -0
  433. package/src/ui/dash/settings/AccountMenuContent.tsx +2 -2
  434. package/src/ui/dash/settings/ApiTokensContent.tsx +2 -1
  435. package/src/ui/dash/settings/ConfigEditorContent.tsx +35 -16
  436. package/src/ui/dash/settings/GeneralContent.tsx +275 -113
  437. package/src/ui/dash/settings/LanguageContent.tsx +409 -0
  438. package/src/ui/dash/settings/SettingsRootContent.tsx +19 -1
  439. package/src/ui/dash/settings/__tests__/GeneralContent.test.tsx +324 -4
  440. package/src/ui/dash/settings/__tests__/LanguageContent.test.tsx +144 -0
  441. package/src/ui/dash/settings/__tests__/discover-copy.test.ts +66 -0
  442. package/src/ui/dash/settings/discover-copy.ts +116 -0
  443. package/src/ui/feed/LinkCard.tsx +55 -45
  444. package/src/ui/feed/NoteCard.tsx +9 -4
  445. package/src/ui/feed/PostStatusBadges.tsx +90 -43
  446. package/src/ui/feed/QuoteCard.tsx +55 -30
  447. package/src/ui/feed/ThreadPreview.tsx +6 -2
  448. package/src/ui/feed/__tests__/thread-preview.test.ts +13 -16
  449. package/src/ui/feed/__tests__/timeline-cards.test.ts +314 -49
  450. package/src/ui/feed/thread-preview-state.ts +20 -6
  451. package/src/ui/font-themes.ts +39 -29
  452. package/src/ui/layouts/BaseLayout.tsx +155 -10
  453. package/src/ui/layouts/SiteLayout.tsx +192 -34
  454. package/src/ui/layouts/__tests__/BaseLayout.test.tsx +196 -17
  455. package/src/ui/layouts/__tests__/SiteLayout.test.tsx +109 -85
  456. package/src/ui/pages/ArchivePage.tsx +282 -289
  457. package/src/ui/pages/CollectionPage.tsx +86 -76
  458. package/src/ui/pages/CollectionsPage.tsx +5 -0
  459. package/src/ui/pages/ComposePage.tsx +8 -0
  460. package/src/ui/pages/PostPage.tsx +47 -0
  461. package/src/ui/pages/SearchPage.tsx +3 -3
  462. package/src/ui/pages/SmartCollectionPage.tsx +434 -0
  463. package/src/ui/pages/SubscribePage.tsx +236 -0
  464. package/src/ui/pages/__tests__/ArchivePage.test.tsx +65 -9
  465. package/src/ui/pages/__tests__/collections-directory-rows.test.tsx +92 -0
  466. package/src/ui/pages/__tests__/collections-view-links.test.tsx +81 -0
  467. package/src/ui/shared/CollectionDirectory.tsx +178 -3
  468. package/src/ui/shared/CollectionsManager.tsx +70 -17
  469. package/src/ui/shared/CopyField.tsx +127 -0
  470. package/src/ui/shared/EmptyPostContent.tsx +23 -0
  471. package/src/ui/shared/MediaGallery.tsx +125 -46
  472. package/src/ui/shared/Pagination.tsx +20 -5
  473. package/src/ui/shared/PostFooter.tsx +20 -11
  474. package/src/ui/shared/__tests__/archive-labels.test.ts +100 -0
  475. package/src/ui/shared/__tests__/media-gallery.test.ts +210 -2
  476. package/src/ui/shared/__tests__/navigation-labels.test.ts +16 -22
  477. package/src/ui/shared/__tests__/pagination.test.ts +38 -24
  478. package/src/ui/shared/__tests__/post-footer.test.ts +32 -0
  479. package/src/ui/shared/archive-labels.ts +98 -0
  480. package/src/ui/shared/collection-management-labels.ts +94 -16
  481. package/src/ui/shared/navigation-labels.ts +45 -71
  482. package/src/ui/shared/post-article-attributes.ts +2 -0
  483. package/src/ui/shared/smart-collection-labels.ts +343 -0
  484. package/dist/app-C75Zc8dD.js +0 -6
  485. package/dist/client/_assets/chunks/heic-to-DUUaO23q.js +0 -1
  486. package/dist/client/_assets/chunks/module-DcsAZQZ_.js +0 -716
  487. package/dist/client/_assets/chunks/url-CU9pEbk5.js +0 -1
  488. package/dist/client/_assets/client-Bq0vre8Y.js +0 -296
  489. package/dist/client/_assets/client-D3VZyG4L.css +0 -2
  490. package/dist/client/_assets/client-auth-F2rb9WfF.js +0 -5571
  491. package/dist/env-BPYViDJJ.js +0 -281
  492. package/dist/github-api-BNF35Lkx.js +0 -176
  493. package/dist/github-app-DdiD-bC4.js +0 -275
  494. package/dist/github-sync-Bqg62IvV.js +0 -4
  495. package/dist/github-sync-HdK2EgvJ.js +0 -431
  496. package/dist/url-CbLAtlZe.js +0 -900
  497. package/src/client/__tests__/collection-created-notice.test.ts +0 -36
  498. package/src/client/__tests__/collection-form-bridge.test.ts +0 -216
  499. package/src/client/__tests__/post-form-bridge.test.ts +0 -82
  500. package/src/client/collection-created-notice.ts +0 -66
  501. package/src/client/collection-form-bridge.ts +0 -191
  502. package/src/client/components/__tests__/jant-post-form.test.ts +0 -193
  503. package/src/client/components/jant-post-form.ts +0 -422
  504. package/src/client/components/post-form-template.ts +0 -352
  505. package/src/client/components/post-form-types.ts +0 -96
  506. package/src/client/media-metadata.ts +0 -247
  507. package/src/client/post-form-bridge.ts +0 -193
  508. package/src/ui/pages/CollectionEditorPage.tsx +0 -175
@@ -0,0 +1,2170 @@
1
+ import{S as e,T as t,_ as n,d as r,g as i,h as a,i as o,n as s,t as c,u as l,v as u,x as d}from"./chunks/lit-DW8VmJAT.js";import{n as f}from"./chunks/unsafe-html-B5ZEXaxg.js";import{n as p,t as m}from"./chunks/site-header-nav-DzXsFk05.js";import{n as h}from"./chunks/confirm-D7GrwsCN.js";import{n as g,r as _,t as v}from"./chunks/slug-format-CRXO1AL5.js";import{_ as ee,a as te,c as ne,i as y,n as re,o as b,p as x,r as ie,s as ae}from"./chunks/types-D5iF3H1a.js";import{a as S,i as oe,n as se,r as C,t as w}from"./chunks/settings-paths-BcdySNx6.js";import{a as ce,c as le,d as ue,f as T,i as de,l as fe,n as pe,o as E,r as D,s as O,t as k}from"./chunks/sortable-list-CgaL2jCs.js";import{_ as me,r as A,t as j}from"./chunks/create-editor-CD3FhrOB.js";function M(e){if(!e)return;let t=document.createElement(`template`);t.innerHTML=e.trim();let n=[`[data-site-header-fragment="header"]`,`[data-site-header-fragment="drawer-backdrop"]`,`[data-site-header-fragment="drawer"]`],r=!1;m(document);for(let e of n){let n=document.querySelector(e),i=t.content.querySelector(e);n&&i&&(n.replaceWith(i),r=!0)}r&&p(document)}var he=`<svg class="lucide lucide-funnel icon-fine" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M10 20a1 1 0 0 0 .553.895l2 1A1 1 0 0 0 14 21v-7a2 2 0 0 1 .517-1.341L21.74 4.67A1 1 0 0 0 21 3H3a1 1 0 0 0-.742 1.67l7.225 7.989A2 2 0 0 1 10 14z"/></svg>`,ge=250,_e=o`<svg
2
+ viewBox="0 0 24 24"
3
+ fill="none"
4
+ stroke="currentColor"
5
+ stroke-width="2"
6
+ stroke-linecap="round"
7
+ stroke-linejoin="round"
8
+ aria-hidden="true"
9
+ >
10
+ <circle cx="12" cy="12" r="10" />
11
+ <line x1="12" x2="12" y1="8" y2="12" />
12
+ <line x1="12" x2="12.01" y1="16" y2="16" />
13
+ </svg>`,ve=class extends c{static properties={labels:{type:Object},_open:{state:!0},_mode:{state:!0},_id:{state:!0},_title:{state:!0},_slug:{state:!0},_slugEdited:{state:!0},_slugState:{state:!0},_slugOpen:{state:!0},_sortOrder:{state:!0},_saving:{state:!0},_error:{state:!0}};#e=``;#t=``;#n=``;#r=null;#i=null;#a=null;createRenderRoot(){return this.innerHTML=``,this}constructor(){super(),this.labels={},this._open=!1,this._mode=`create`,this._id=null,this._title=``,this._slug=``,this._slugEdited=!1,this._slugState=`unknown`,this._slugOpen=!1,this._sortOrder=`newest`,this._saving=!1,this._error=``}async open(e){return this.#o(),e.collectionId&&!await this.#s(e.collectionId)?{changed:!1}:(this._open=!0,await this.updateComplete,this.#u(),this.#c(),new Promise(e=>{this.#r=e}))}#o(){this._mode=`create`,this._id=null,this._title=``,this._slug=``,this._slugEdited=!1,this._slugState=`unknown`,this._slugOpen=!1,this._sortOrder=`newest`,this._saving=!1,this._error=``,this.#e=``,this.#t=``,this.#n=``}async#s(e){try{let t=await fetch(a(`/api/collections/${e}`));if(!t.ok)throw Error(`HTTP ${t.status}`);let n=await t.json();return this._mode=`edit`,this._id=n.id,this._title=n.title??``,this._slug=n.slug??``,this.#t=n.slug??``,this._slugEdited=!0,this.#e=n.description??``,this._sortOrder=n.sortOrder??`newest`,!0}catch{return l(this.labels.loadFailed,`error`),!1}}#c(){let e=this.querySelector(`.collection-dialog`);e&&(e.open||e.showModal(),this.querySelector(`[data-field='title']`)?.focus())}#l(e){let t=this.querySelector(`.collection-dialog`);t?.open&&t.close(),this._open=!1,this.#i&&clearTimeout(this.#i),this.#d();let n=this.#r;this.#r=null,n?.(e)}#u(){let e=this.querySelector(`[data-collection-description]`);!e||this.#a||(this.#a=j({element:e,placeholder:this.labels.descriptionPlaceholder,content:this.#e||void 0,onUpdate:e=>{this.#e=e,this._error&&=``}}),this.#e=A(this.#a.getJSON()))}#d(){this.#a?.destroy(),this.#a=null}#f(e){this._title=e,!this._slugEdited&&this.#p()}async#p(){let e=this._title.trim();if(!e){this.#n=``,this._slug=``,this._slugState=`unknown`;return}let t=g(await se(e),200);this._slugEdited||this._title.trim()!==e||(this.#n=t,this._slug=t,this.#h())}#m(e){this._slugEdited=!0,this._slug=e.trim().toLowerCase(),this.#h()}#h(){this.#i&&clearTimeout(this.#i),this._slugState=`checking`,this.#i=setTimeout(()=>void this.#g(),ge)}async#g(){let e=this._slug;if(!e){this._slugState=`unknown`;return}if(this.#_()!==null){this._slugState=`taken`;return}try{let t=new URLSearchParams({mode:`check`,slug:e});this._id&&t.set(`collectionId`,this._id);let n=await fetch(a(`/api/collections/slug?${t.toString()}`));if(!n.ok)throw Error(`HTTP ${n.status}`);let r=await n.json();if(e!==this._slug)return;this._slugState=r.available?`available`:`taken`}catch{if(e!==this._slug)return;this._slugState=`unknown`}}#_(){return v(this._slug,{maxLength:200})}#v(){let e=this.#_();return e===`invalid`?this.labels.linkInvalid:e===`reserved`?this.labels.linkReserved:e===`too_long`?this.labels.linkTooLong:this._slugState===`taken`?this.labels.linkTaken:null}#y(){let e=a(C(this._slug)),t=globalThis.location?.origin&&globalThis.location.origin!==`null`?globalThis.location.origin:`http://localhost`;return new URL(e,`${t}/`).toString()}#b(){this._slugOpen||(this._slugOpen=!0,this.updateComplete.then(()=>{let e=this.querySelector(`[data-field='slug']`);e?.focus(),e?.select()}))}#x(){this.#n&&(this._slug=this.#n,this._slugEdited=!1,this.#h())}#S(){if(!this._slug&&!this._slugOpen)return s;let e=this.#v(),t=this._mode===`edit`&&this._slug!==this.#t;if(!this._slugOpen)return o`
14
+ <div class="collection-quick-link-box">
15
+ <div class="collection-quick-link-row">
16
+ <p
17
+ class="collection-quick-link-preview text-xs text-muted-foreground"
18
+ aria-live="polite"
19
+ >
20
+ ${this.#y()}
21
+ </p>
22
+ <button
23
+ type="button"
24
+ class="collection-quick-link-action"
25
+ @click=${()=>this.#b()}
26
+ >
27
+ ${this.labels.editLink}
28
+ </button>
29
+ </div>
30
+ ${e?o`<p class="collection-dialog-link-problem">${e}</p>`:s}
31
+ ${t?o`<p class="collection-dialog-link-problem">
32
+ ${this.labels.linkMovesWarning}
33
+ </p>`:s}
34
+ </div>
35
+ `;let n=!!this.#n&&this._slug!==this.#n;return o`
36
+ <div class="collection-quick-link-editor">
37
+ <div class="field">
38
+ <div class="collection-quick-link-row">
39
+ <label class="label mb-0" for="collection-dialog-slug"
40
+ >${this.labels.link}</label
41
+ >
42
+ ${n?o`
43
+ <button
44
+ type="button"
45
+ class="collection-quick-link-action"
46
+ @click=${()=>this.#x()}
47
+ >
48
+ ${this.labels.resetLink}
49
+ </button>
50
+ `:s}
51
+ </div>
52
+ <input
53
+ id="collection-dialog-slug"
54
+ class="input"
55
+ type="text"
56
+ data-field="slug"
57
+ required
58
+ maxlength=${200}
59
+ autocomplete="off"
60
+ autocapitalize="off"
61
+ spellcheck="false"
62
+ aria-invalid=${e?`true`:`false`}
63
+ .value=${this._slug}
64
+ @input=${e=>this.#m(e.target.value)}
65
+ />
66
+ ${e?o`<p class="collection-dialog-link-problem">${e}</p>`:this._slug?o`<p class="collection-dialog-link-preview">
67
+ ${this.#y()}
68
+ </p>`:o`<p class="collection-dialog-link-help">
69
+ ${this.labels.linkHelp}
70
+ </p>`}
71
+ ${t?o`<p class="collection-dialog-link-problem">
72
+ ${this.labels.linkMovesWarning}
73
+ </p>`:s}
74
+ </div>
75
+ </div>
76
+ `}#C(){return!this._title.trim()||!this._slug?this.labels.titleAndLinkRequired:this.#v()}async#w(){if(this._saving)return;let e=this.#C();if(e){this._error=e;return}this._saving=!0,this._error=``;let t=this._title.trim(),n=this.#e.trim(),r={slug:this._slug,title:t,sortOrder:this._sortOrder};n?r.description=n:this._id&&(r.description=null);try{let e=await fetch(a(this._id?`/api/collections/${this._id}`:`/api/collections`),{method:this._id?`PUT`:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(r)}),n=await e.json().catch(()=>null);if(!e.ok){this._error=n?.error??this.labels.saveFailed;return}l(this.labels.saved),this.#l({changed:!0,collection:{id:n?.id??this._id??``,slug:n?.slug??this._slug,title:n?.title??t}})}catch{this._error=this.labels.saveFailed}finally{this._saving=!1}}#T=e=>{if(this._open){if(e.key===`Escape`){e.preventDefault(),e.stopPropagation(),this.#l({changed:!1});return}if(e.key===`Enter`){let t=e.target;if(t?.isContentEditable||t?.tagName===`TEXTAREA`)return;e.preventDefault(),this.#w()}}};connectedCallback(){super.connectedCallback(),this.addEventListener(`keydown`,this.#T)}disconnectedCallback(){super.disconnectedCallback(),this.removeEventListener(`keydown`,this.#T),this.#i&&clearTimeout(this.#i),this.#d()}render(){if(!this._open)return s;let e=this._mode===`edit`?this.labels.editHeading:this.labels.createHeading;return o`
77
+ <dialog
78
+ class="dialog collection-dialog"
79
+ @cancel=${e=>{e.preventDefault(),this.#l({changed:!1})}}
80
+ @click=${e=>{e.target===e.currentTarget&&this.#l({changed:!1})}}
81
+ >
82
+ <div
83
+ class="collection-dialog-panel"
84
+ role="dialog"
85
+ aria-modal="true"
86
+ aria-labelledby="collection-dialog-title"
87
+ @click=${e=>e.stopPropagation()}
88
+ >
89
+ <header class="collection-dialog-header">
90
+ <h2 id="collection-dialog-title" class="collection-dialog-title">
91
+ ${e}
92
+ </h2>
93
+ </header>
94
+
95
+ <div
96
+ class="collection-dialog-body"
97
+ @input=${()=>{this._error=``}}
98
+ @change=${()=>{this._error=``}}
99
+ >
100
+ <div class="field">
101
+ <label for="collection-dialog-title-field"
102
+ >${this.labels.title}</label
103
+ >
104
+ <input
105
+ id="collection-dialog-title-field"
106
+ class="input"
107
+ type="text"
108
+ data-field="title"
109
+ required
110
+ maxlength=${120}
111
+ placeholder=${this._mode===`edit`?s:this.labels.titlePlaceholder}
112
+ .value=${this._title}
113
+ @input=${e=>this.#f(e.target.value)}
114
+ />
115
+ </div>
116
+
117
+ ${this.#S()}
118
+
119
+ <div class="field">
120
+ <!-- The label carries no "for": the editor is a contenteditable
121
+ region, not a labelable control. -->
122
+ <label>${this.labels.description}</label>
123
+ <div
124
+ class="settings-tiptap-editor"
125
+ data-collection-description
126
+ ></div>
127
+ </div>
128
+
129
+ <div class="field">
130
+ <label for="collection-dialog-sort">${this.labels.orderBy}</label>
131
+ <select
132
+ id="collection-dialog-sort"
133
+ class="select"
134
+ data-field="sort"
135
+ .value=${this._sortOrder}
136
+ @change=${e=>{this._sortOrder=e.target.value}}
137
+ >
138
+ ${re.map(e=>o`<option
139
+ value=${e}
140
+ ?selected=${e===this._sortOrder}
141
+ >
142
+ ${this.labels.sortOptions[e]}
143
+ </option>`)}
144
+ </select>
145
+ </div>
146
+
147
+ ${this._error?o`<div class="alert-destructive" role="alert">
148
+ ${_e}
149
+ <section><p>${this._error}</p></section>
150
+ </div>`:s}
151
+ </div>
152
+
153
+ <footer class="collection-dialog-actions">
154
+ <button
155
+ type="button"
156
+ class="btn-outline"
157
+ @click=${()=>this.#l({changed:!1})}
158
+ >
159
+ ${this.labels.cancel}
160
+ </button>
161
+ <button
162
+ type="button"
163
+ class="btn"
164
+ ?disabled=${this._saving||this.#C()!==null}
165
+ @click=${()=>void this.#w()}
166
+ >
167
+ ${this.labels.save}
168
+ </button>
169
+ </footer>
170
+ </div>
171
+ </dialog>
172
+ `}};customElements.get(`jant-collection-dialog`)||customElements.define(`jant-collection-dialog`,ve);var ye=`data-collection-dialog-labels`,N=null,P=null;function be(){if(N)return N;let e=document.querySelector(`[${ye}]`)?.getAttribute(ye);if(!e)return null;try{return N=JSON.parse(e),N}catch{return null}}function xe(e){return P?.isConnected?(P.labels=e,P):(P=document.createElement(`jant-collection-dialog`),P.labels=e,document.body.appendChild(P),P)}async function F(e={}){let t=be();return t?xe(t).open(e):{changed:!1}}var I=`X-Jant-Site-Header`,L=`include`,Se=class extends c{static properties={items:{type:Array},labels:{type:Object},systemNavItems:{type:Array,attribute:`system-nav-items`},collections:{type:Array},suggestedLinks:{type:Array,attribute:`suggested-links`},siteName:{type:String,attribute:`site-name`},rssFeedsEnabled:{type:Boolean,attribute:`rss-feeds-enabled`},_items:{state:!0},_editingId:{state:!0},_editLabel:{state:!0},_editUrl:{state:!0},_togglingKeys:{state:!0},_showLinkForm:{state:!0},_newLinkLabel:{state:!0},_newLinkUrl:{state:!0},_addingLink:{state:!0},_showPreviewMore:{state:!0},_addingCollectionId:{state:!0},_showCollectionPicker:{state:!0},_collectionDialogOpen:{state:!0},_collectionDialogView:{state:!0},_creatingCollection:{state:!0},_createCollectionError:{state:!0},_createdCollection:{state:!0},_addingSuggestedKey:{state:!0},_pageDialogOpen:{state:!0},_pageDialogView:{state:!0},_pageQuery:{state:!0},_pages:{state:!0},_pageAddress:{state:!0},_pageSearchLoading:{state:!0},_pageSearchError:{state:!0},_selectedPageIndex:{state:!0},_addingPageId:{state:!0},_newPageTitle:{state:!0},_newPageSlug:{state:!0},_slugEdited:{state:!0},_slugCheckLoading:{state:!0},_slugTaken:{state:!0},_creatingPage:{state:!0},_createPageError:{state:!0},_createdPage:{state:!0}};#e=null;#t=null;#n=!1;#r=null;#i=null;#a=0;#o=null;#s=0;#c=null;#l=0;#u=()=>{this._showLinkForm=!1,document.removeEventListener(`click`,this.#u)};#d=()=>{this._showCollectionPicker=!1,document.removeEventListener(`click`,this.#d)};#f=e=>{e.target instanceof Node&&(this.querySelector(`[data-preview-more]`)?.contains(e.target)||this.#se())};#p=e=>{if(!(`key`in e)||e.key!==`Escape`||!this._showPreviewMore)return;let t=e;t.isComposing||t.keyCode===229||(e.preventDefault(),this.#se(),this.querySelector(`[data-preview-more-trigger]`)?.focus())};#m=e=>{e.key===`Escape`&&!e.isComposing&&e.keyCode!==229&&this._showCollectionPicker&&(e.preventDefault(),e.stopPropagation(),this.#d(),this.querySelector(`[data-add-collection-trigger]`)?.focus())};createRenderRoot(){return this.innerHTML=``,this}constructor(){super(),this.items=[],this.labels={},this.systemNavItems=[],this.collections=[],this.suggestedLinks=[],this.siteName=``,this.rssFeedsEnabled=!1,this._items=[],this._editingId=null,this._editLabel=``,this._editUrl=``,this._togglingKeys=new Set,this._showLinkForm=!1,this._newLinkLabel=``,this._newLinkUrl=``,this._addingLink=!1,this._showPreviewMore=!1,this._addingCollectionId=null,this._showCollectionPicker=!1,this._collectionDialogOpen=!1,this._collectionDialogView=`create`,this._creatingCollection=!1,this._createCollectionError=``,this._createdCollection=null,this._addingSuggestedKey=null,this._pageDialogOpen=!1,this._pageDialogView=`picker`,this._pageQuery=``,this._pages=[],this._pageAddress=null,this._pageSearchLoading=!1,this._pageSearchError=!1,this._selectedPageIndex=0,this._addingPageId=null,this._newPageTitle=``,this._newPageSlug=``,this._slugEdited=!1,this._slugCheckLoading=!1,this._slugTaken=!1,this._creatingPage=!1,this._createPageError=``,this._createdPage=null}update(e){(!this.#n||e.has(`items`))&&(this._items=[...this.items??[]],this.#n=!0),super.update(e)}updated(){this._showPreviewMore&&this.#oe.length===0&&this.#se(),this.#H()}disconnectedCallback(){super.disconnectedCallback(),this.#e?.destroy(),this.#e=null,this.#t?.destroy(),this.#t=null,document.removeEventListener(`click`,this.#u),document.removeEventListener(`click`,this.#d),this.#se(),this.#y()}#h(){return{"Content-Type":`application/json`,Accept:`application/json`,[I]:L}}#g(){return{Accept:`application/json`,[I]:L}}#_(e){let t={...e};return delete t.headerHtml,t}#v(e){let t=e.type===`system`?this.systemNavItems.find(t=>t.key===e.systemKey)?.label:void 0,n=e.label.trim()||t||e.displayLabel||e.targetTitle?.trim()||e.label;return{...e,displayLabel:n}}#y(){this.#i!==null&&(clearTimeout(this.#i),this.#i=null),this.#o!==null&&(clearTimeout(this.#o),this.#o=null),this.#c!==null&&(clearTimeout(this.#c),this.#c=null),this.#a+=1,this.#s+=1,this.#l+=1}async#b(){if(this._pageDialogOpen)return;this.#y(),this._pageDialogOpen=!0,this._pageDialogView=`picker`,this._pageQuery=``,this._pages=[],this._pageAddress=null,this._pageSearchError=!1,this._selectedPageIndex=0,this._addingPageId=null,this._newPageTitle=``,this._newPageSlug=``,this._slugEdited=!1,this._slugCheckLoading=!1,this._slugTaken=!1,this._creatingPage=!1,this._createPageError=``,this._createdPage=null,await this.updateComplete;let e=this.querySelector(`#nav-page-dialog`);e&&!e.open&&e.showModal(),this.querySelector(`#nav-page-search`)?.focus(),this.#C()}#x(){let e=this.querySelector(`[data-add-page-trigger]`),t=this.querySelector(`#nav-page-dialog`);t?.open&&t.close(),this.#y(),this._pageDialogOpen=!1,this.updateComplete.then(()=>e?.focus())}async#S(e){let t=++this.#a,n=new URLSearchParams({url:e});this._pageSearchLoading=!0,this._pageSearchError=!1;try{let e=await fetch(`/api/nav-items/resolve?${n.toString()}`,{headers:{Accept:`application/json`}});if(!e.ok)throw Error(`HTTP ${e.status}`);let r=await e.json();if(t!==this.#a)return;this._pages=[],this._pageAddress=r.resolution??null,this._selectedPageIndex=0}catch{t===this.#a&&(this._pages=[],this._pageAddress=null,this._pageSearchError=!0)}finally{t===this.#a&&(this._pageSearchLoading=!1)}}async#C(){let e=++this.#a,t=new URLSearchParams({limit:`20`}),n=this._pageQuery.trim();n&&t.set(`q`,n),this._pageSearchLoading=!0,this._pageSearchError=!1,this._pageAddress=null;try{let n=await fetch(`/api/nav-items/pages?${t.toString()}`,{headers:{Accept:`application/json`}});if(!n.ok)throw Error(`HTTP ${n.status}`);let r=await n.json();if(e!==this.#a)return;let i=new Set(this._items.flatMap(e=>e.type===`page`&&e.postId?[e.postId]:[]));this._pages=(r.pages??[]).filter(e=>!i.has(e.id)),this._selectedPageIndex=0}catch{e===this.#a&&(this._pages=[],this._pageSearchError=!0)}finally{e===this.#a&&(this._pageSearchLoading=!1)}}#w(){this.#i!==null&&clearTimeout(this.#i),this.#i=setTimeout(()=>{this.#i=null;let e=this._pageQuery.trim();d(e)?this.#S(e):this.#C()},200)}async#T(e){if(!this._addingPageId){this._addingPageId=e.id;try{let t=await fetch(`/api/nav-items`,{method:`POST`,headers:this.#h(),body:JSON.stringify({type:`page`,postId:e.id,placement:`header`})});if(!t.ok)throw Error(`HTTP ${t.status}`);let n=await t.json(),r=this.#v(this.#_(n));this.#V(),this._items=[...this._items,r],this._pages=this._pages.filter(t=>t.id!==e.id),M(n.headerHtml),l(this.labels.pageAdded),this.#x()}catch{l(this.labels.saveFailed,`error`)}finally{this._addingPageId=null}}}#E(){this.#a+=1,this._pageDialogView=`create`,this._newPageTitle=``,this._newPageSlug=``,this._slugEdited=!1,this._slugCheckLoading=!1,this._slugTaken=!1,this._createPageError=``,this.updateComplete.then(()=>{this.querySelector(`#nav-new-page-title`)?.focus()})}#D(){this.#s+=1,this.#l+=1,this._pageDialogView=`picker`,this._createPageError=``,this.updateComplete.then(()=>{this.querySelector(`#nav-page-search`)?.focus()})}#O(){if(this._slugEdited)return;this.#o!==null&&clearTimeout(this.#o);let e=this._newPageTitle.trim();if(!e){this._newPageSlug=``;return}this.#o=setTimeout(()=>{this.#o=null,this.#k(e)},250)}async#k(e){let t=++this.#s,n=new URLSearchParams({mode:`suggest`,title:e});try{let e=await fetch(`/api/posts/slug?${n.toString()}`,{headers:{Accept:`application/json`}});if(!e.ok)return;let r=await e.json();if(t!==this.#s||this._slugEdited||this._pageDialogView!==`create`)return;this._newPageSlug=r.slug?.trim()??``,this._slugTaken=!1}catch{}}#A(){this.#c!==null&&clearTimeout(this.#c),this._slugTaken=!1;let e=this._newPageSlug.trim();if(!e||v(e,{maxLength:200})){this._slugCheckLoading=!1;return}this._slugCheckLoading=!0,this.#c=setTimeout(()=>{this.#c=null,this.#j(e)},250)}async#j(e){let t=++this.#l,n=new URLSearchParams({mode:`check`,slug:e});try{let r=await fetch(`/api/posts/slug?${n.toString()}`,{headers:{Accept:`application/json`}});if(!r.ok)return;let i=await r.json();if(t!==this.#l||this._newPageSlug.trim()!==e)return;this._slugTaken=i.available===!1}catch{}finally{t===this.#l&&(this._slugCheckLoading=!1)}}#M(){let e=v(this._newPageSlug,{maxLength:200});return e===`invalid`?this.labels.slugInvalid:e===`reserved`?this.labels.slugReserved:e===`too_long`?this.labels.slugTooLong:this._slugTaken?this.labels.slugUnavailable:``}async#N(){let e=this._newPageTitle.trim(),t=this._newPageSlug.trim();if(!e){this._createPageError=this.labels.titleRequired;return}let n=this.#M();if(n){this._createPageError=n;return}if(!this._slugCheckLoading){this._creatingPage=!0,this._createPageError=``;try{let n=await fetch(`/api/posts`,{method:`POST`,headers:{"Content-Type":`application/json`,Accept:`application/json`},body:JSON.stringify({format:`note`,title:e,...t&&{slug:t},status:`published`,visibility:`latest_hidden`})});if(!n.ok){if(n.status===409){this._slugTaken=!0,this._createPageError=this.labels.slugUnavailable;return}throw Error(`HTTP ${n.status}`)}let r=await n.json();this._createdPage={id:r.id,title:r.title||e,slug:r.slug},this._pageDialogView=`created`}catch{this._createPageError=this.labels.createPageFailed}finally{this._creatingPage=!1}}}#P(e){if(!(e.isComposing||e.keyCode===229)){if(e.key===`Escape`){e.preventDefault(),this.#x();return}if(this._pageDialogView===`picker`&&e.target===this.querySelector(`#nav-page-search`)){if(e.key===`ArrowDown`)e.preventDefault(),this._selectedPageIndex=this._pages.length>0?(this._selectedPageIndex+1)%this._pages.length:0,this.#F();else if(e.key===`ArrowUp`)e.preventDefault(),this._selectedPageIndex=this._pages.length>0?(this._selectedPageIndex-1+this._pages.length)%this._pages.length:0,this.#F();else if(e.key===`Enter`&&this._pages.length>0){e.preventDefault();let t=this._pages[this._selectedPageIndex];t&&this.#T(t)}}}}#F(){requestAnimationFrame(()=>{this.querySelector(`.nav-page-result-selected`)?.scrollIntoView({block:`nearest`})})}async#I(){if(this._collectionDialogOpen)return;this.#d(),this._collectionDialogOpen=!0,this._collectionDialogView=`create`,this._creatingCollection=!1,this._createCollectionError=``,this._createdCollection=null,await this.updateComplete;let e=this.querySelector(`#nav-collection-dialog`);e&&!e.open&&e.showModal();let t=this.querySelector(`#nav-collection-dialog [data-collection-title-input]`);t?.focus(),t?.select()}#L(){let e=this.querySelector(`[data-add-collection-trigger]`),t=this.querySelector(`#nav-collection-dialog`);t?.open&&t.close(),this._collectionDialogOpen=!1,this._creatingCollection=!1,this._createCollectionError=``,this.updateComplete.then(()=>e?.focus())}#R(e){e.isComposing||e.keyCode===229||e.key===`Escape`&&(e.preventDefault(),this.#L())}#z(){this.querySelector(`#nav-collection-dialog jant-collection-form form`)?.requestSubmit()}async#B(e){let t=e;if(t.stopPropagation(),!t.detail||this._creatingCollection)return;let n=this.querySelector(`#nav-collection-dialog jant-collection-form`);this._creatingCollection=!0,this._createCollectionError=``,n&&(n.loading=!0);try{let e=await fetch(`/api/collections`,{method:`POST`,headers:{"Content-Type":`application/json`,Accept:`application/json`},body:JSON.stringify(t.detail.data)}),n=await e.json().catch(()=>null);if(!e.ok||!n?.id||!n.title||!n.slug)throw Error(`Invalid collection response`);let r={id:n.id,title:n.title,slug:n.slug,group:null};this.collections.some(e=>e.id===n.id)||(this.collections=[...this.collections,r]),this._createdCollection=n,this._collectionDialogView=`created`}catch{this._createCollectionError=this.labels.createCollectionFailed}finally{this._creatingCollection=!1,n&&(n.loading=!1)}}#V(){this.#e?.destroy(),this.#e=null,this.#t?.destroy(),this.#t=null}#H(){let e=this.querySelector(`#nav-items-header`),t=this.querySelector(`#nav-items-more`);e&&!this.#e&&(this.#e=O.create(e,this.#U())),t&&!this.#t&&(this.#t=O.create(t,this.#U()))}#U(){return{...de,animation:150,handle:`[data-drag-handle]`,draggable:`[data-nav-id]`,group:`nav-items`,onStart:e=>{this.#r=k(e)},onEnd:e=>{this.#W(e)}}}async#W(e){let t=e.to,n=e.from,r=n!==t,i=t.id===`nav-items-header`?`header`:`more`,a=this.querySelector(`#nav-items-header`),o=this.querySelector(`#nav-items-more`),s=this._items.map(e=>({...e})),c=e.item?.dataset?.navId;if(!c||!a||!o){this.#r=null;return}let u=D(a,`[data-nav-id]`,`navId`),d=D(o,`[data-nav-id]`,`navId`);r?(e.item.parentNode?.removeChild(e.item),this.#r?n.insertBefore(e.item,this.#r):e.oldIndex!=null&&e.oldIndex<n.children.length?n.insertBefore(e.item,n.children[e.oldIndex]??null):n.appendChild(e.item)):ce(t,e,this.#r),this.#r=null,this.#V();let f=[...new Set([...u,...d])],p=new Map(this._items.map(e=>[e.id,e.id===c?{...e,placement:i}:{...e}])),m=f.map(e=>p.get(e)).filter(e=>e!==void 0),h=this._items.filter(e=>!f.includes(e.id)).map(e=>e.id===c?{...e,placement:i}:{...e});this._items=[...m,...h];let{movedId:g,afterId:_,beforeId:v}=pe(i===`header`?u:d,e.newIndex);if(g)try{if(r){let e=await fetch(`/api/nav-items/${c}`,{method:`PUT`,headers:{"Content-Type":`application/json`,Accept:`application/json`},body:JSON.stringify({placement:i})});if(!e.ok)throw Error(`HTTP ${e.status}`)}let e=await fetch(`/api/nav-items/${g}/move`,{method:`PUT`,headers:this.#h(),body:JSON.stringify({after:_??null,before:v??null})});if(!e.ok)throw Error(`HTTP ${e.status}`);M((await e.json()).headerHtml),l(r?this.labels.placementSaved:this.labels.orderSaved)}catch{this.#V(),this._items=s,l(this.labels.saveFailed,`error`)}}#G(e){this._editingId===e.id?this._editingId=null:(this._editingId=e.id,this._editLabel=e.label,this._editUrl=e.url)}async#K(e){let t=this._editLabel.trim();if(!t&&e.type===`link`){l(this.labels.labelRequired,`error`);return}try{let n=await fetch(`/api/nav-items/${e.id}`,{method:`PUT`,headers:this.#h(),body:JSON.stringify({label:t,...e.type===`link`&&{url:this._editUrl.trim()}})});if(!n.ok)throw Error(`HTTP ${n.status}`);let r=await n.json(),i=this.#v(this.#_(r));this.#V(),this._items=this._items.map(e=>e.id===i.id?i:e),this._editingId=null,M(r.headerHtml)}catch{l(this.labels.saveFailed,`error`)}}async#q(e){let t=e.type===`collection`?this.labels.confirmDeleteCollection:e.type===`page`?this.labels.confirmDeletePage:this.labels.confirmDeleteLink,n=e.type===`collection`||e.type===`page`?this.labels.remove:this.labels.delete;if(await h({message:t,confirmLabel:n,cancelLabel:this.labels.cancel,tone:`danger`}))try{let t=await fetch(`/api/nav-items/${e.id}`,{method:`DELETE`,headers:this.#g()});if(!t.ok)throw Error(`HTTP ${t.status}`);let n=await t.json();this.#V(),this._items=this._items.filter(t=>t.id!==e.id),this._editingId=null,M(n.headerHtml)}catch{l(this.labels.deleteFailed,`error`)}}async#J(){let e=this._newLinkLabel.trim(),t=this._newLinkUrl.trim();if(!e||!t){l(this.labels.labelAndUrlRequired,`error`);return}this._addingLink=!0;try{let n=await fetch(`/api/nav-items`,{method:`POST`,headers:this.#h(),body:JSON.stringify({type:`link`,label:e,url:t,placement:`header`})});if(!n.ok)throw Error(`HTTP ${n.status}`);let r=await n.json(),i=this.#v(this.#_(r));this.#V(),this._items=[...this._items,i],this._newLinkLabel=``,this._newLinkUrl=``,this._showLinkForm=!1,document.removeEventListener(`click`,this.#u),M(r.headerHtml)}catch{l(this.labels.saveFailed,`error`)}finally{this._addingLink=!1}}async#Y(e,t=!1){if(e&&!this._addingCollectionId){this._addingCollectionId=e;try{let n=await fetch(`/api/nav-items`,{method:`POST`,headers:this.#h(),body:JSON.stringify(t?{type:`smart_collection`,smartCollectionId:e,placement:`header`}:{type:`collection`,collectionId:e,placement:`header`})});if(!n.ok)throw Error(`HTTP ${n.status}`);let r=await n.json(),i=this.#v(this.#_(r));this.#V(),this._items=[...this._items,i],this.#d(),M(r.headerHtml),l(this.labels.collectionAdded),this._collectionDialogOpen&&this.#L()}catch{l(this.labels.saveFailed,`error`)}finally{this._addingCollectionId=null}}}#X(n){let r=t(n,{siteOrigins:[window.location.origin],sitePathPrefix:i()});if(r===null)return null;let a=e(r);return a?`/${a}`:`/`}#Z(e){let t=this.#X(e.url);return t!==null&&this._items.some(e=>this.#X(e.url)===t)?!0:!!(e.collectionId&&this._items.some(t=>t.type===`collection`&&t.collectionId===e.collectionId)||e.postId&&this._items.some(t=>t.type===`page`&&t.postId===e.postId))}get#Q(){return(this.suggestedLinks??[]).filter(e=>!this.#Z(e))}async#$(e){if(!this._addingSuggestedKey){this._addingSuggestedKey=e.key;try{let t=e.navItemType===`page`&&e.postId?{type:`page`,postId:e.postId,placement:`header`}:e.navItemType===`collection`&&e.collectionId?{type:`collection`,collectionId:e.collectionId,placement:`header`}:{type:`link`,label:e.label,url:e.url,placement:`header`},n=await fetch(`/api/nav-items`,{method:`POST`,headers:this.#h(),body:JSON.stringify(t)});if(!n.ok)throw Error(`HTTP ${n.status}`);let r=await n.json(),i=this.#v(this.#_(r));this.#V(),this._items=[...this._items,i],M(r.headerHtml),l(this.labels.suggestedLinkAdded)}catch{l(this.labels.saveFailed,`error`)}finally{this._addingSuggestedKey=null}}}#ee(e){return this._items.some(t=>t.type===`system`&&t.systemKey===e.key)}async#te(e,t){this._togglingKeys=new Set([...this._togglingKeys,e.key]);try{if(t){let t=await fetch(`/api/nav-items`,{method:`POST`,headers:this.#h(),body:JSON.stringify({type:`system`,systemKey:e.key})});if(!t.ok)throw Error(`HTTP ${t.status}`);let n=await t.json(),r=this.#v(this.#_(n));this.#V(),this._items=[...this._items,r],M(n.headerHtml)}else{let t=this._items.find(t=>t.type===`system`&&t.systemKey===e.key);if(t){let e=await fetch(`/api/nav-items/${t.id}`,{method:`DELETE`,headers:this.#g()});if(!e.ok)throw Error(`HTTP ${e.status}`);let n=await e.json();this.#V(),this._items=this._items.filter(e=>e.id!==t.id),M(n.headerHtml)}}}catch{l(this.labels.saveFailed,`error`),this.requestUpdate()}finally{let t=new Set(this._togglingKeys);t.delete(e.key),this._togglingKeys=t}}get#ne(){return this._items.filter(e=>(e.placement??`header`)===`header`)}get#re(){return this._items.filter(e=>e.placement===`more`)}#ie(e){return this.rssFeedsEnabled||e.type!==`system`||!ne(e.systemKey)}get#ae(){return this.#ne.filter(e=>this.#ie(e))}get#oe(){return this.#re.filter(e=>this.#ie(e))}#se(){this._showPreviewMore=!1,document.removeEventListener(`click`,this.#f),document.removeEventListener(`keydown`,this.#p)}#ce(e){if(e.preventDefault(),e.stopPropagation(),this._showPreviewMore){this.#se();return}this._showPreviewMore=!0,document.addEventListener(`keydown`,this.#p),setTimeout(()=>{document.addEventListener(`click`,this.#f)})}#le(){let e=this.#ae,t=this.#oe;return o`
173
+ <div class="nav-preview">
174
+ <div class="nav-preview-chrome">
175
+ <div class="nav-preview-dots">
176
+ <span></span><span></span><span></span>
177
+ </div>
178
+ <span class="nav-preview-label">${this.labels.preview}</span>
179
+ </div>
180
+ <div class="nav-preview-content">
181
+ <div class="site-header-top">
182
+ <a href=${a(`/`)} class="site-logo">${this.siteName}</a>
183
+ <nav class="site-header-nav">
184
+ ${T(e,e=>e.id,(e,t)=>o`<a
185
+ class=${t===0?`site-header-link site-header-link-active`:`site-header-link`}
186
+ >
187
+ ${e.displayLabel??e.label}
188
+ </a>`)}
189
+ ${t.length>0?o`
190
+ <div class="site-header-more" data-preview-more>
191
+ <button
192
+ type="button"
193
+ class="site-header-more-btn"
194
+ data-preview-more-trigger
195
+ aria-haspopup="menu"
196
+ aria-expanded=${this._showPreviewMore?`true`:`false`}
197
+ @click=${this.#ce}
198
+ >
199
+ ${this.labels.previewMore}
200
+ <svg
201
+ xmlns="http://www.w3.org/2000/svg"
202
+ width="12"
203
+ height="12"
204
+ viewBox="0 0 24 24"
205
+ fill="none"
206
+ stroke="currentColor"
207
+ stroke-width="2.5"
208
+ stroke-linecap="round"
209
+ stroke-linejoin="round"
210
+ aria-hidden="true"
211
+ >
212
+ <path d="m6 9 6 6 6-6" />
213
+ </svg>
214
+ </button>
215
+ <div
216
+ class="site-header-more-popover"
217
+ aria-hidden=${this._showPreviewMore?`false`:`true`}
218
+ @click=${e=>e.stopPropagation()}
219
+ >
220
+ ${T(t,e=>e.id,e=>o`
221
+ <span class="site-header-more-link">
222
+ ${e.displayLabel??e.label}
223
+ </span>
224
+ `)}
225
+ </div>
226
+ </div>
227
+ `:s}
228
+ </nav>
229
+ </div>
230
+ </div>
231
+ </div>
232
+ `}#ue(e){let t=e===`system`?this.labels.system:e===`collection`?this.labels.collection:e===`page`?this.labels.page:this.labels.link;return o`<span class="badge-secondary">${t}</span>`}#de(e){if(this._editingId!==e.id)return s;if(e.type===`system`)return o`
233
+ <div class="nav-item-edit">
234
+ <div class="field">
235
+ <label class="label">${this.labels.label}</label>
236
+ <input
237
+ type="text"
238
+ class="input"
239
+ placeholder=${e.displayLabel??``}
240
+ .value=${this._editLabel}
241
+ @input=${e=>{this._editLabel=e.target.value}}
242
+ />
243
+ </div>
244
+ <div class="flex items-center justify-between">
245
+ <button
246
+ type="button"
247
+ class="btn-sm-ghost text-destructive"
248
+ @click=${()=>{let t=this.systemNavItems.find(t=>t.key===e.systemKey);t&&(this._editingId=null,this.#te(t,!1))}}
249
+ >
250
+ ${this.labels.remove}
251
+ </button>
252
+ <button
253
+ type="button"
254
+ class="btn-sm"
255
+ @click=${()=>this.#K(e)}
256
+ >
257
+ ${this.labels.save}
258
+ </button>
259
+ </div>
260
+ </div>
261
+ `;if(e.type===`collection`)return o`
262
+ <div class="nav-item-edit">
263
+ <div class="field">
264
+ <label class="label">${this.labels.label}</label>
265
+ <input
266
+ type="text"
267
+ class="input"
268
+ maxlength="100"
269
+ placeholder=${e.displayLabel??``}
270
+ .value=${this._editLabel}
271
+ @input=${e=>{this._editLabel=e.target.value}}
272
+ />
273
+ </div>
274
+ <div class="flex items-center justify-between">
275
+ <button
276
+ type="button"
277
+ class="btn-sm-ghost text-destructive"
278
+ @click=${()=>void this.#q(e)}
279
+ >
280
+ ${this.labels.remove}
281
+ </button>
282
+ <button
283
+ type="button"
284
+ class="btn-sm"
285
+ @click=${()=>this.#K(e)}
286
+ >
287
+ ${this.labels.save}
288
+ </button>
289
+ </div>
290
+ </div>
291
+ `;if(e.type===`page`){let t=`${a(e.url)}?edit=1`;return o`
292
+ <div class="nav-item-edit">
293
+ <div class="field">
294
+ <label class="label">${this.labels.label}</label>
295
+ <input
296
+ type="text"
297
+ class="input"
298
+ maxlength="100"
299
+ placeholder=${e.displayLabel??``}
300
+ .value=${this._editLabel}
301
+ @input=${e=>{this._editLabel=e.target.value}}
302
+ />
303
+ </div>
304
+ <div class="flex items-center justify-between gap-3">
305
+ <button
306
+ type="button"
307
+ class="btn-sm-ghost text-destructive"
308
+ @click=${()=>void this.#q(e)}
309
+ >
310
+ ${this.labels.remove}
311
+ </button>
312
+ <div class="flex items-center gap-2">
313
+ <a
314
+ class="btn-sm-outline"
315
+ href=${t}
316
+ target="_blank"
317
+ rel="noopener noreferrer"
318
+ >
319
+ ${this.labels.editPage}
320
+ <span aria-hidden="true">↗</span>
321
+ </a>
322
+ <button
323
+ type="button"
324
+ class="btn-sm"
325
+ @click=${()=>this.#K(e)}
326
+ >
327
+ ${this.labels.save}
328
+ </button>
329
+ </div>
330
+ </div>
331
+ </div>
332
+ `}return e.type===`link`?o`
333
+ <div class="nav-item-edit">
334
+ <div class="field">
335
+ <label class="label">${this.labels.label}</label>
336
+ <input
337
+ type="text"
338
+ class="input"
339
+ required
340
+ .value=${this._editLabel}
341
+ @input=${e=>{this._editLabel=e.target.value}}
342
+ />
343
+ </div>
344
+ <div class="field">
345
+ <label class="label">${this.labels.url}</label>
346
+ <input
347
+ type="text"
348
+ class="input"
349
+ required
350
+ .value=${this._editUrl}
351
+ @input=${e=>{this._editUrl=e.target.value}}
352
+ />
353
+ </div>
354
+ <div class="flex items-center justify-between">
355
+ <button
356
+ type="button"
357
+ class="btn-sm-ghost text-destructive"
358
+ @click=${()=>void this.#q(e)}
359
+ >
360
+ ${this.labels.delete}
361
+ </button>
362
+ <button
363
+ type="button"
364
+ class="btn-sm"
365
+ @click=${()=>this.#K(e)}
366
+ >
367
+ ${this.labels.save}
368
+ </button>
369
+ </div>
370
+ </div>
371
+ `:s}#fe(e){let t=this._editingId===e.id;return o`
372
+ <div
373
+ data-nav-id=${e.id}
374
+ class="nav-item${t?` nav-item-editing`:``}"
375
+ >
376
+ <div class="nav-item-row">
377
+ <div class="nav-item-handle" data-drag-handle>
378
+ <svg
379
+ xmlns="http://www.w3.org/2000/svg"
380
+ width="14"
381
+ height="14"
382
+ viewBox="0 0 24 24"
383
+ fill="none"
384
+ stroke="currentColor"
385
+ stroke-width="2"
386
+ stroke-linecap="round"
387
+ stroke-linejoin="round"
388
+ class="text-muted-foreground shrink-0"
389
+ >
390
+ <circle cx="9" cy="12" r="1" />
391
+ <circle cx="9" cy="5" r="1" />
392
+ <circle cx="9" cy="19" r="1" />
393
+ <circle cx="15" cy="12" r="1" />
394
+ <circle cx="15" cy="5" r="1" />
395
+ <circle cx="15" cy="19" r="1" />
396
+ </svg>
397
+ </div>
398
+ <div class="nav-item-info" @click=${()=>this.#G(e)}>
399
+ <div class="flex items-center gap-2 min-w-0">
400
+ <span class="text-sm font-medium truncate"
401
+ >${e.displayLabel??e.label}</span
402
+ >
403
+ ${this.#ue(e.type)}
404
+ </div>
405
+ <span class="text-xs text-muted-foreground truncate"
406
+ >${e.url}</span
407
+ >
408
+ </div>
409
+ <button
410
+ type="button"
411
+ class="nav-item-toggle"
412
+ @click=${()=>this.#G(e)}
413
+ aria-label=${this.labels.toggleEdit}
414
+ >
415
+ <svg
416
+ xmlns="http://www.w3.org/2000/svg"
417
+ width="14"
418
+ height="14"
419
+ viewBox="0 0 24 24"
420
+ fill="none"
421
+ stroke="currentColor"
422
+ stroke-width="2"
423
+ stroke-linecap="round"
424
+ stroke-linejoin="round"
425
+ style="transition: transform 0.15s; ${t?`transform: rotate(180deg);`:``}"
426
+ >
427
+ <path d="m6 9 6 6 6-6" />
428
+ </svg>
429
+ </button>
430
+ </div>
431
+ ${this.#de(e)}
432
+ </div>
433
+ `}#pe(){let e=this.#Q;return e.length===0?s:o`
434
+ <section class="mt-8">
435
+ <h2 class="text-lg font-semibold mb-1">
436
+ ${this.labels.suggestedLinks}
437
+ </h2>
438
+ <p class="text-sm text-muted-foreground mb-3">
439
+ ${this.labels.suggestedLinksDescription}
440
+ </p>
441
+ <div class="nav-suggestions-list">
442
+ ${e.map(e=>{let t=this._addingSuggestedKey===e.key;return o`
443
+ <div class="nav-suggestion-item">
444
+ <div class="nav-suggestion-info">
445
+ <span class="nav-suggestion-title">${e.label}</span>
446
+ <span class="nav-suggestion-meta">
447
+ ${e.url} · ${e.targetLabel}
448
+ </span>
449
+ </div>
450
+ <button
451
+ type="button"
452
+ class="btn-sm"
453
+ ?disabled=${t||this._addingSuggestedKey!==null}
454
+ @click=${()=>this.#$(e)}
455
+ >
456
+ ${this.labels.addSuggestedLink}
457
+ </button>
458
+ </div>
459
+ `})}
460
+ </div>
461
+ </section>
462
+ `}#me(){return o`
463
+ <section class="mt-8">
464
+ <h2 class="text-lg font-semibold mb-1">
465
+ ${this.labels.addPageToNavigation}
466
+ </h2>
467
+ <p class="text-sm text-muted-foreground mb-3">
468
+ ${this.labels.addPageDescription}
469
+ </p>
470
+ <button
471
+ type="button"
472
+ class="btn-outline"
473
+ data-add-page-trigger
474
+ @click=${()=>void this.#b()}
475
+ >
476
+ ${this.labels.addPage}
477
+ </button>
478
+ </section>
479
+ `}#he(e){return e.kind===`page`?this._items.some(t=>t.postId===e.page.id):e.kind===`collection`?this._items.some(t=>t.collectionId===e.collection.id):e.kind===`smart_collection`&&this._items.some(t=>t.smartCollectionId===e.smartCollection.id)}#ge(e){if(this.#he(e))return this.labels.addressAlreadyAdded;switch(e.kind){case`not_found`:return this.labels.addressNotFound.replace(`{address}`,e.address);case`unpublished`:return this.labels.addressUnpublished;case`private`:return this.labels.addressPrivate;case`untitled`:return this.labels.addressUntitled;case`external`:return this.labels.addressExternal;case`link_only`:return this.labels.addressLinkOnly;default:return``}}#_e(e){this._newLinkUrl=e,this.#x(),this._showLinkForm=!0,setTimeout(()=>{document.addEventListener(`click`,this.#u)}),this.updateComplete.then(()=>{this.querySelector(`#nav-link-label`)?.focus()})}#ve(e){let t=this.#he(e);if(e.kind===`page`&&!t){let t=e.page;return this.#ye(t.title,a(`/${t.slug}`),this._addingPageId===t.id,()=>void this.#T(t))}if(e.kind===`collection`&&!t){let t=e.collection;return this.#ye(t.title,a(C(t.slug)),this._addingCollectionId===t.id,()=>{this.#Y(t.id).then(()=>{this.#x()})})}if(e.kind===`smart_collection`&&!t){let t=e.smartCollection;return this.#ye(t.title,a(C(t.slug)),this._addingCollectionId===t.id,()=>{this.#Y(t.id,!0).then(()=>{this.#x()})})}let n=this.#ge(e),r=e.kind===`external`||e.kind===`link_only`;return o`
480
+ <p class="nav-page-status" role="status">${n}</p>
481
+ ${r?o`
482
+ <button
483
+ type="button"
484
+ class="btn-outline nav-page-address-link"
485
+ @click=${()=>this.#_e(e.address)}
486
+ >
487
+ ${this.labels.addressAddAsLink}
488
+ </button>
489
+ `:s}
490
+ `}#ye(e,t,n,r){return o`
491
+ <p class="nav-page-results-label">${this.labels.addressMatch}</p>
492
+ <div class="nav-page-results" role="listbox">
493
+ <button
494
+ type="button"
495
+ role="option"
496
+ aria-selected="true"
497
+ class="nav-page-result nav-page-result-selected"
498
+ ?disabled=${n}
499
+ @click=${r}
500
+ >
501
+ <span class="nav-page-result-copy">
502
+ <span class="nav-page-result-title">${e}</span>
503
+ <span class="nav-page-result-path">${t}</span>
504
+ </span>
505
+ ${n?o`<span class="nav-page-spinner" aria-hidden="true"></span>`:o`
506
+ <svg
507
+ xmlns="http://www.w3.org/2000/svg"
508
+ width="16"
509
+ height="16"
510
+ viewBox="0 0 24 24"
511
+ fill="none"
512
+ stroke="currentColor"
513
+ stroke-width="2"
514
+ stroke-linecap="round"
515
+ stroke-linejoin="round"
516
+ aria-hidden="true"
517
+ >
518
+ <path d="M12 5v14" />
519
+ <path d="M5 12h14" />
520
+ </svg>
521
+ `}
522
+ </button>
523
+ </div>
524
+ `}#be(){let e=this._pageSearchLoading?this.labels.searchingPages:this._pageSearchError?this.labels.pageSearchFailed:this._pages.length===0?this._pageQuery.trim()?this.labels.noMatchingPages:this.labels.noPages:``;return o`
525
+ <header>
526
+ <h2 id="nav-page-dialog-title">${this.labels.addPage}</h2>
527
+ <p>${this.labels.addPageDescription}</p>
528
+ </header>
529
+ <section class="nav-page-picker-section">
530
+ <div class="nav-page-search-wrap">
531
+ <svg
532
+ xmlns="http://www.w3.org/2000/svg"
533
+ width="16"
534
+ height="16"
535
+ viewBox="0 0 24 24"
536
+ fill="none"
537
+ stroke="currentColor"
538
+ stroke-width="2"
539
+ stroke-linecap="round"
540
+ stroke-linejoin="round"
541
+ aria-hidden="true"
542
+ >
543
+ <circle cx="11" cy="11" r="8" />
544
+ <path d="m21 21-4.3-4.3" />
545
+ </svg>
546
+ <input
547
+ id="nav-page-search"
548
+ type="search"
549
+ class="input nav-page-search-input"
550
+ placeholder=${this.labels.searchPagesHint}
551
+ autocomplete="off"
552
+ role="combobox"
553
+ aria-expanded="true"
554
+ aria-controls="nav-page-results"
555
+ aria-activedescendant=${this._pages.length>0?`nav-page-result-${this._selectedPageIndex}`:``}
556
+ .value=${this._pageQuery}
557
+ @input=${e=>{this._pageQuery=e.target.value,this._selectedPageIndex=0,this.#w()}}
558
+ />
559
+ </div>
560
+
561
+ ${this._pageSearchLoading||this._pageSearchError?o`<p class="nav-page-status" role="status">${e}</p>`:this._pageAddress?this.#ve(this._pageAddress):this._pages.length>0?o`
562
+ <p class="nav-page-results-label">
563
+ ${this._pageQuery.trim()?this.labels.searchPages:this.labels.recentPages}
564
+ </p>
565
+ <div
566
+ id="nav-page-results"
567
+ class="nav-page-results"
568
+ role="listbox"
569
+ >
570
+ ${this._pages.map((e,t)=>{let n=t===this._selectedPageIndex,r=this._addingPageId===e.id;return o`
571
+ <button
572
+ id=${`nav-page-result-${t}`}
573
+ type="button"
574
+ role="option"
575
+ aria-selected=${n?`true`:`false`}
576
+ class=${`nav-page-result${n?` nav-page-result-selected`:``}`}
577
+ ?disabled=${this._addingPageId!==null}
578
+ @mouseenter=${()=>{this._selectedPageIndex=t}}
579
+ @click=${()=>void this.#T(e)}
580
+ >
581
+ <span class="nav-page-result-copy">
582
+ <span class="nav-page-result-title"
583
+ >${e.title}</span
584
+ >
585
+ <span class="nav-page-result-path"
586
+ >${a(`/${e.slug}`)}</span
587
+ >
588
+ </span>
589
+ ${r?o`<span
590
+ class="nav-page-spinner"
591
+ aria-hidden="true"
592
+ ></span>`:o`
593
+ <svg
594
+ xmlns="http://www.w3.org/2000/svg"
595
+ width="16"
596
+ height="16"
597
+ viewBox="0 0 24 24"
598
+ fill="none"
599
+ stroke="currentColor"
600
+ stroke-width="2"
601
+ stroke-linecap="round"
602
+ stroke-linejoin="round"
603
+ aria-hidden="true"
604
+ >
605
+ <path d="M12 5v14" />
606
+ <path d="M5 12h14" />
607
+ </svg>
608
+ `}
609
+ </button>
610
+ `})}
611
+ </div>
612
+ `:o`<p class="nav-page-status" role="status">${e}</p>`}
613
+ </section>
614
+ <footer class="nav-page-dialog-footer">
615
+ <button
616
+ type="button"
617
+ class="btn-outline nav-page-create-link"
618
+ @click=${this.#E}
619
+ >
620
+ <svg
621
+ xmlns="http://www.w3.org/2000/svg"
622
+ width="16"
623
+ height="16"
624
+ viewBox="0 0 24 24"
625
+ fill="none"
626
+ stroke="currentColor"
627
+ stroke-width="2"
628
+ stroke-linecap="round"
629
+ stroke-linejoin="round"
630
+ aria-hidden="true"
631
+ >
632
+ <path d="M12 5v14" />
633
+ <path d="M5 12h14" />
634
+ </svg>
635
+ ${this.labels.createNewPage}
636
+ </button>
637
+ <button type="button" class="btn-ghost" @click=${this.#x}>
638
+ ${this.labels.cancel}
639
+ </button>
640
+ </footer>
641
+ `}#xe(){let e=this.#M(),t=this._newPageSlug.trim()?a(`/${this._newPageSlug.trim()}`):a(`/`);return o`
642
+ <header>
643
+ <h2 id="nav-page-dialog-title">${this.labels.createPage}</h2>
644
+ <p>${this.labels.createPageDescription}</p>
645
+ </header>
646
+ <section>
647
+ <form
648
+ id="nav-create-page-form"
649
+ class="form grid gap-4"
650
+ @submit=${e=>{e.preventDefault(),this.#N()}}
651
+ >
652
+ <div class="field">
653
+ <label class="label" for="nav-new-page-title"
654
+ >${this.labels.pageTitle}</label
655
+ >
656
+ <input
657
+ id="nav-new-page-title"
658
+ type="text"
659
+ class="input"
660
+ required
661
+ maxlength="300"
662
+ autocomplete="off"
663
+ .value=${this._newPageTitle}
664
+ @input=${e=>{this._newPageTitle=e.target.value,this._createPageError=``,this.#O()}}
665
+ />
666
+ </div>
667
+ <div class="field">
668
+ <label class="label" for="nav-new-page-slug"
669
+ >${this.labels.pageAddress}</label
670
+ >
671
+ <div class="nav-page-slug-field">
672
+ <span class="nav-page-slug-prefix" aria-hidden="true"
673
+ >${a(`/`)}</span
674
+ >
675
+ <input
676
+ id="nav-new-page-slug"
677
+ type="text"
678
+ class="input nav-page-slug-input"
679
+ maxlength="200"
680
+ autocomplete="off"
681
+ spellcheck="false"
682
+ .value=${this._newPageSlug}
683
+ @input=${e=>{this._newPageSlug=e.target.value.toLowerCase(),this._slugEdited=!0,this._createPageError=``,this.#A()}}
684
+ aria-invalid=${e?`true`:`false`}
685
+ aria-describedby="nav-new-page-slug-help"
686
+ />
687
+ </div>
688
+ <p
689
+ id="nav-new-page-slug-help"
690
+ class=${e?`text-xs text-destructive`:`text-xs text-muted-foreground`}
691
+ >
692
+ ${e||(this._slugCheckLoading?this.labels.checkingAddress:t)}
693
+ </p>
694
+ </div>
695
+ <p class="nav-page-visibility-note">
696
+ <svg
697
+ xmlns="http://www.w3.org/2000/svg"
698
+ width="15"
699
+ height="15"
700
+ viewBox="0 0 24 24"
701
+ fill="none"
702
+ stroke="currentColor"
703
+ stroke-width="2"
704
+ stroke-linecap="round"
705
+ stroke-linejoin="round"
706
+ aria-hidden="true"
707
+ >
708
+ <circle cx="12" cy="12" r="10" />
709
+ <path d="M12 16v-4" />
710
+ <path d="M12 8h.01" />
711
+ </svg>
712
+ ${this.labels.pageVisibilityHint}
713
+ </p>
714
+ ${this._createPageError?o`<p class="text-sm text-destructive" role="alert">
715
+ ${this._createPageError}
716
+ </p>`:s}
717
+ </form>
718
+ </section>
719
+ <footer>
720
+ <button
721
+ type="button"
722
+ class="btn-ghost"
723
+ ?disabled=${this._creatingPage}
724
+ @click=${this.#D}
725
+ >
726
+ ${this.labels.back}
727
+ </button>
728
+ <button
729
+ type="submit"
730
+ class="btn"
731
+ form="nav-create-page-form"
732
+ ?disabled=${this._creatingPage||this._slugCheckLoading||!!e}
733
+ >
734
+ ${this._creatingPage?this.labels.creatingPage:this.labels.createPage}
735
+ </button>
736
+ </footer>
737
+ `}#Se(){let e=this._createdPage;if(!e)return s;let t=`${a(`/${e.slug}`)}?edit=1`;return o`
738
+ <header class="nav-create-success-header">
739
+ <span class="nav-create-success-icon" aria-hidden="true">
740
+ <svg
741
+ xmlns="http://www.w3.org/2000/svg"
742
+ width="22"
743
+ height="22"
744
+ viewBox="0 0 24 24"
745
+ fill="none"
746
+ stroke="currentColor"
747
+ stroke-width="2"
748
+ stroke-linecap="round"
749
+ stroke-linejoin="round"
750
+ >
751
+ <path d="M20 6 9 17l-5-5" />
752
+ </svg>
753
+ </span>
754
+ <h2 id="nav-page-dialog-title">${this.labels.pageCreated}</h2>
755
+ <p>${this.labels.pageCreatedDescription}</p>
756
+ </header>
757
+ <section>
758
+ <div class="nav-create-success-card">
759
+ <span class="nav-page-result-title">${e.title}</span>
760
+ <span class="nav-page-result-path"
761
+ >${a(`/${e.slug}`)}</span
762
+ >
763
+ </div>
764
+ </section>
765
+ <footer>
766
+ <a
767
+ class="btn-outline"
768
+ href=${t}
769
+ target="_blank"
770
+ rel="noopener noreferrer"
771
+ >
772
+ ${this.labels.editPage}
773
+ <span aria-hidden="true">↗</span>
774
+ </a>
775
+ <button
776
+ type="button"
777
+ class="btn"
778
+ ?disabled=${this._addingPageId!==null}
779
+ @click=${()=>void this.#T(e)}
780
+ >
781
+ ${this.labels.addToNavigation}
782
+ </button>
783
+ </footer>
784
+ `}#Ce(){return this._pageDialogOpen?o`
785
+ <dialog
786
+ id="nav-page-dialog"
787
+ class="dialog nav-page-dialog"
788
+ aria-labelledby="nav-page-dialog-title"
789
+ @cancel=${e=>{e.preventDefault(),this.#x()}}
790
+ @click=${e=>{e.target===e.currentTarget&&this.#x()}}
791
+ @keydown=${this.#P}
792
+ >
793
+ <div
794
+ class="nav-page-dialog-panel"
795
+ @click=${e=>e.stopPropagation()}
796
+ >
797
+ <button
798
+ type="button"
799
+ aria-label=${this.labels.cancel}
800
+ @click=${this.#x}
801
+ >
802
+ <svg
803
+ xmlns="http://www.w3.org/2000/svg"
804
+ width="18"
805
+ height="18"
806
+ viewBox="0 0 24 24"
807
+ fill="none"
808
+ stroke="currentColor"
809
+ stroke-width="2"
810
+ stroke-linecap="round"
811
+ stroke-linejoin="round"
812
+ aria-hidden="true"
813
+ >
814
+ <path d="M18 6 6 18" />
815
+ <path d="m6 6 12 12" />
816
+ </svg>
817
+ </button>
818
+ ${this._pageDialogView===`picker`?this.#be():this._pageDialogView===`create`?this.#xe():this.#Se()}
819
+ </div>
820
+ </dialog>
821
+ `:s}#we(){return o`
822
+ <section class="mt-8">
823
+ <h2 class="text-lg font-semibold mb-3">
824
+ ${this.labels.addCustomLinkToNavigation}
825
+ </h2>
826
+ <div id="nav-link-popover" class="popover">
827
+ <button
828
+ id="nav-link-popover-trigger"
829
+ type="button"
830
+ aria-expanded=${this._showLinkForm}
831
+ aria-controls="nav-link-popover-content"
832
+ class="btn-outline"
833
+ @click=${e=>{e.stopPropagation(),this._showLinkForm=!this._showLinkForm,this._showLinkForm?setTimeout(()=>{document.addEventListener(`click`,this.#u)}):document.removeEventListener(`click`,this.#u)}}
834
+ >
835
+ ${this.labels.addLink}
836
+ </button>
837
+ ${this._showLinkForm?o`
838
+ <div
839
+ id="nav-link-popover-content"
840
+ data-popover
841
+ data-side="top"
842
+ aria-hidden="false"
843
+ class="w-80"
844
+ style="bottom: 100%; margin-bottom: 0.5rem;"
845
+ @click=${e=>e.stopPropagation()}
846
+ >
847
+ <div class="grid gap-4">
848
+ <header class="grid gap-1.5">
849
+ <h4 class="leading-none font-medium">
850
+ ${this.labels.addLink}
851
+ </h4>
852
+ <p class="text-muted-foreground text-sm">
853
+ ${this.labels.addLinkDescription}
854
+ </p>
855
+ </header>
856
+ <form
857
+ class="form grid gap-2"
858
+ @submit=${e=>{e.preventDefault(),this.#J()}}
859
+ >
860
+ <div class="grid grid-cols-3 items-center gap-4">
861
+ <label for="nav-link-label"
862
+ >${this.labels.label}</label
863
+ >
864
+ <input
865
+ type="text"
866
+ id="nav-link-label"
867
+ class="col-span-2 h-8"
868
+ placeholder="Home"
869
+ required
870
+ .value=${this._newLinkLabel}
871
+ @input=${e=>{this._newLinkLabel=e.target.value}}
872
+ autofocus
873
+ />
874
+ </div>
875
+ <div class="grid grid-cols-3 items-center gap-4">
876
+ <label for="nav-link-url">${this.labels.url}</label>
877
+ <input
878
+ type="text"
879
+ id="nav-link-url"
880
+ class="col-span-2 h-8"
881
+ placeholder=${this.labels.urlPlaceholder}
882
+ required
883
+ .value=${this._newLinkUrl}
884
+ @input=${e=>{this._newLinkUrl=e.target.value}}
885
+ />
886
+ </div>
887
+ <button
888
+ type="submit"
889
+ class="btn-sm mt-2"
890
+ ?disabled=${this._addingLink}
891
+ >
892
+ ${this.labels.addLink}
893
+ </button>
894
+ </form>
895
+ </div>
896
+ </div>
897
+ `:s}
898
+ </div>
899
+ </section>
900
+ `}#Te(){if(!this.collections?.length)return o`
901
+ <section class="mt-8">
902
+ <h2 class="text-lg font-semibold mb-1">
903
+ ${this.labels.addCollectionToNavigation}
904
+ </h2>
905
+ <p class="text-sm text-muted-foreground mb-3">
906
+ ${this.labels.noCollections}
907
+ </p>
908
+ <button
909
+ type="button"
910
+ class="btn-outline"
911
+ data-add-collection-trigger
912
+ @click=${()=>void this.#I()}
913
+ >
914
+ ${this.labels.createCollection}
915
+ </button>
916
+ </section>
917
+ `;let e=new Set(this._items.flatMap(e=>e.type===`collection`&&e.collectionId?[e.collectionId]:e.type===`smart_collection`&&e.smartCollectionId?[e.smartCollectionId]:[])),t=this.collections.filter(t=>!e.has(t.id));if(t.length===0)return o`
918
+ <section class="mt-8">
919
+ <h2 class="text-lg font-semibold mb-1">
920
+ ${this.labels.addCollectionToNavigation}
921
+ </h2>
922
+ <p class="text-sm text-muted-foreground mb-3">
923
+ ${this.labels.allCollectionsAdded}
924
+ </p>
925
+ <button
926
+ type="button"
927
+ class="btn-outline"
928
+ data-add-collection-trigger
929
+ @click=${()=>void this.#I()}
930
+ >
931
+ ${this.labels.createCollection}
932
+ </button>
933
+ </section>
934
+ `;let n=[],r=null;for(let e of t){let t=e.group??null;(!r||r.label!==t)&&(r={label:t,items:[]},n.push(r)),r.items.push(e)}return o`
935
+ <section class="mt-8">
936
+ <h2 class="text-lg font-semibold mb-1">
937
+ ${this.labels.addCollectionToNavigation}
938
+ </h2>
939
+ <p class="text-sm text-muted-foreground mb-3">
940
+ ${this.labels.addCollectionDescription}
941
+ </p>
942
+ <div
943
+ class="relative inline-block"
944
+ @keydown=${this.#m}
945
+ >
946
+ <button
947
+ type="button"
948
+ aria-expanded=${this._showCollectionPicker}
949
+ aria-haspopup="menu"
950
+ class="btn-outline"
951
+ data-add-collection-trigger
952
+ @click=${e=>{e.stopPropagation();let t=!this._showCollectionPicker;t&&this.#u(),this._showCollectionPicker=t,this._showCollectionPicker?setTimeout(()=>{document.addEventListener(`click`,this.#d)}):document.removeEventListener(`click`,this.#d)}}
953
+ >
954
+ ${this.labels.addCollection}
955
+ <svg
956
+ xmlns="http://www.w3.org/2000/svg"
957
+ width="14"
958
+ height="14"
959
+ viewBox="0 0 24 24"
960
+ fill="none"
961
+ stroke="currentColor"
962
+ stroke-width="2"
963
+ stroke-linecap="round"
964
+ stroke-linejoin="round"
965
+ class="ml-1.5 -mr-0.5"
966
+ aria-hidden="true"
967
+ style="transition: transform 0.15s; ${this._showCollectionPicker?`transform: rotate(180deg);`:``}"
968
+ >
969
+ <path d="m6 9 6 6 6-6" />
970
+ </svg>
971
+ </button>
972
+ ${this._showCollectionPicker?o`
973
+ <div
974
+ class="collection-picker"
975
+ role="menu"
976
+ @click=${e=>e.stopPropagation()}
977
+ >
978
+ ${n.map(e=>o`
979
+ ${e.label?o`<div class="collection-picker-group">
980
+ ${e.label}
981
+ </div>`:s}
982
+ ${e.items.map(e=>{let t=this._addingCollectionId===e.id;return o`
983
+ <button
984
+ type="button"
985
+ role="menuitem"
986
+ class="collection-picker-item"
987
+ ?disabled=${t||this._addingCollectionId!==null}
988
+ @click=${()=>this.#Y(e.id,e.isSmart)}
989
+ >
990
+ <span class="collection-picker-title">
991
+ ${e.title}
992
+ </span>
993
+ ${e.isSmart?o`<span
994
+ class="collection-directory-smart-icon"
995
+ role="img"
996
+ aria-label=${this.labels.smartCollectionLabel??``}
997
+ title=${this.labels.smartCollectionLabel??``}
998
+ >${f(he)}</span
999
+ >`:s}
1000
+ ${t?o`<svg
1001
+ xmlns="http://www.w3.org/2000/svg"
1002
+ width="14"
1003
+ height="14"
1004
+ viewBox="0 0 24 24"
1005
+ fill="none"
1006
+ stroke="currentColor"
1007
+ stroke-width="2"
1008
+ stroke-linecap="round"
1009
+ stroke-linejoin="round"
1010
+ class="animate-spin shrink-0 text-muted-foreground"
1011
+ >
1012
+ <path d="M21 12a9 9 0 1 1-6.219-8.56" />
1013
+ </svg>`:s}
1014
+ </button>
1015
+ `})}
1016
+ `)}
1017
+ <div class="collection-picker-footer">
1018
+ <button
1019
+ type="button"
1020
+ role="menuitem"
1021
+ class="collection-picker-create"
1022
+ data-create-collection-trigger
1023
+ @click=${()=>void this.#I()}
1024
+ >
1025
+ ${this.labels.createNewCollection}
1026
+ <span aria-hidden="true">+</span>
1027
+ </button>
1028
+ </div>
1029
+ </div>
1030
+ `:s}
1031
+ </div>
1032
+ </section>
1033
+ `}#Ee(){return o`
1034
+ <header>
1035
+ <h2 id="nav-collection-dialog-title">
1036
+ ${this.labels.createCollection}
1037
+ </h2>
1038
+ <p>${this.labels.collectionFormLabels.quickHint}</p>
1039
+ </header>
1040
+ <section>
1041
+ <jant-collection-form
1042
+ .labels=${this.labels.collectionFormLabels}
1043
+ .initial=${{title:``,slug:``}}
1044
+ action=${a(`/api/collections`)}
1045
+ @jant:collection-submit=${e=>void this.#B(e)}
1046
+ ></jant-collection-form>
1047
+ ${this._createCollectionError?o`<p class="mt-3 text-sm text-destructive" role="alert">
1048
+ ${this._createCollectionError}
1049
+ </p>`:s}
1050
+ </section>
1051
+ <footer>
1052
+ <button
1053
+ type="button"
1054
+ class="btn-ghost"
1055
+ ?disabled=${this._creatingCollection}
1056
+ @click=${this.#L}
1057
+ >
1058
+ ${this.labels.cancel}
1059
+ </button>
1060
+ <button
1061
+ type="button"
1062
+ class="btn"
1063
+ ?disabled=${this._creatingCollection}
1064
+ @click=${this.#z}
1065
+ >
1066
+ ${this._creatingCollection?this.labels.creatingCollection:this.labels.createCollection}
1067
+ </button>
1068
+ </footer>
1069
+ `}async#De(e){let{changed:t,collection:n}=await F({collectionId:e});t&&n&&(this._createdCollection=n,this.collections=this.collections.map(e=>e.id===n.id?{...e,title:n.title,slug:n.slug}:e))}#Oe(){let e=this._createdCollection;return e?o`
1070
+ <header class="nav-create-success-header">
1071
+ <span class="nav-create-success-icon" aria-hidden="true">
1072
+ <svg
1073
+ xmlns="http://www.w3.org/2000/svg"
1074
+ width="22"
1075
+ height="22"
1076
+ viewBox="0 0 24 24"
1077
+ fill="none"
1078
+ stroke="currentColor"
1079
+ stroke-width="2"
1080
+ stroke-linecap="round"
1081
+ stroke-linejoin="round"
1082
+ >
1083
+ <path d="M20 6 9 17l-5-5" />
1084
+ </svg>
1085
+ </span>
1086
+ <h2 id="nav-collection-dialog-title">
1087
+ ${this.labels.collectionFormLabels.createdLabel}
1088
+ </h2>
1089
+ <p>${this.labels.collectionCreatedDescription}</p>
1090
+ </header>
1091
+ <section>
1092
+ <div class="nav-create-success-card">
1093
+ <span class="nav-page-result-title">${e.title}</span>
1094
+ <span class="nav-page-result-path">
1095
+ ${a(C(e.slug))}
1096
+ </span>
1097
+ </div>
1098
+ </section>
1099
+ <footer>
1100
+ <!-- The collection dialog opens on top of this one rather than in a
1101
+ new tab: there is no editor page to send the author to, and the
1102
+ navigation step they came for is still waiting underneath. -->
1103
+ <button
1104
+ type="button"
1105
+ class="btn-outline"
1106
+ @click=${()=>void this.#De(e.id)}
1107
+ >
1108
+ ${this.labels.editCollection}
1109
+ </button>
1110
+ <button
1111
+ type="button"
1112
+ class="btn"
1113
+ ?disabled=${this._addingCollectionId!==null}
1114
+ @click=${()=>void this.#Y(e.id)}
1115
+ >
1116
+ ${this.labels.addToNavigation}
1117
+ </button>
1118
+ </footer>
1119
+ `:s}#ke(){return this._collectionDialogOpen?o`
1120
+ <dialog
1121
+ id="nav-collection-dialog"
1122
+ class="dialog nav-collection-dialog"
1123
+ aria-labelledby="nav-collection-dialog-title"
1124
+ @cancel=${e=>{e.preventDefault(),this.#L()}}
1125
+ @click=${e=>{e.target===e.currentTarget&&this.#L()}}
1126
+ @keydown=${this.#R}
1127
+ >
1128
+ <div
1129
+ class="nav-collection-dialog-panel"
1130
+ @click=${e=>e.stopPropagation()}
1131
+ >
1132
+ <button
1133
+ type="button"
1134
+ aria-label=${this.labels.cancel}
1135
+ @click=${this.#L}
1136
+ >
1137
+ <svg
1138
+ xmlns="http://www.w3.org/2000/svg"
1139
+ width="18"
1140
+ height="18"
1141
+ viewBox="0 0 24 24"
1142
+ fill="none"
1143
+ stroke="currentColor"
1144
+ stroke-width="2"
1145
+ stroke-linecap="round"
1146
+ stroke-linejoin="round"
1147
+ aria-hidden="true"
1148
+ >
1149
+ <path d="M18 6 6 18" />
1150
+ <path d="m6 6 12 12" />
1151
+ </svg>
1152
+ </button>
1153
+ ${this._collectionDialogView===`create`?this.#Ee():this.#Oe()}
1154
+ </div>
1155
+ </dialog>
1156
+ `:s}#Ae(){return this.systemNavItems?.length?o`
1157
+ <section class="mt-8">
1158
+ <h2 class="text-lg font-semibold mb-1">${this.labels.systemLinks}</h2>
1159
+ <p class="text-sm text-muted-foreground mb-3">
1160
+ ${this.labels.systemLinksDescription}
1161
+ </p>
1162
+ <div class="flex flex-col divide-y">
1163
+ ${this.systemNavItems.map(e=>{let t=this.#ee(e),n=this._togglingKeys.has(e.key);return o`
1164
+ <label class=${n?`flex items-center justify-between gap-4 py-3 opacity-60 cursor-not-allowed`:`flex items-center justify-between gap-4 py-3 cursor-pointer`}>
1165
+ <div>
1166
+ <p class="font-medium">${e.label}</p>
1167
+ <p class="text-sm text-muted-foreground">
1168
+ ${e.description}
1169
+ </p>
1170
+ </div>
1171
+ <input
1172
+ type="checkbox"
1173
+ role="switch"
1174
+ class="input"
1175
+ .checked=${t}
1176
+ ?disabled=${n}
1177
+ @change=${t=>{let n=t.target.checked;this.#te(e,n)}}
1178
+ />
1179
+ </label>
1180
+ `})}
1181
+ </div>
1182
+ </section>
1183
+ `:s}render(){return o`
1184
+ ${this.#le()}
1185
+
1186
+ <section class="mt-8">
1187
+ <h2 class="text-lg font-semibold mb-3">${this.labels.headerSection}</h2>
1188
+ ${this.#ne.length===0?o`<p class="text-sm text-muted-foreground py-4">
1189
+ ${this.labels.emptyState}
1190
+ </p>`:s}
1191
+ <div id="nav-items-header" class="nav-items-list">
1192
+ ${T(this.#ne,e=>e.id,e=>this.#fe(e))}
1193
+ </div>
1194
+ </section>
1195
+
1196
+ <section class="mt-8">
1197
+ <h2 class="text-lg font-semibold mb-3">${this.labels.moreSection}</h2>
1198
+ <div id="nav-items-more" class="nav-items-list nav-items-list-drop">
1199
+ ${this.#re.length>0?T(this.#re,e=>e.id,e=>this.#fe(e)):o`<p class="nav-items-empty-hint">
1200
+ ${this.labels.moreEmptyHint}
1201
+ </p>`}
1202
+ </div>
1203
+ </section>
1204
+
1205
+ ${this.#pe()} ${this.#me()}
1206
+ ${this.#Te()} ${this.#we()}
1207
+ ${this.#Ae()} ${this.#Ce()}
1208
+ ${this.#ke()}
1209
+ `}};customElements.define(`jant-nav-manager`,Se);var Ce=`X-Jant-Site-Header`,we=`include`;async function R(e){let t=await fetch(`/api/nav-items`,{method:`POST`,headers:{"Content-Type":`application/json`,Accept:`application/json`,[Ce]:we},body:JSON.stringify(e)}),n=await ee(t);if(!t.ok)throw Error(x(n,`error`)??`HTTP ${t.status}`);return M(x(n,`headerHtml`)),x(n,`id`)}async function z(e){return R({type:`collection`,collectionId:e,placement:`header`})}async function B(e){return R({type:`smart_collection`,smartCollectionId:e,placement:`header`})}function Te(e,t){let n=e[t];if(!n||n.type!==`divider`||!n.label)return null;let r=[];for(let n=t+1;n<e.length;n+=1){let t=e[n];if(!t||t.type===`divider`)break;let i=t.collection?.slug;i&&r.push(i)}return r.length<2?null:{slugExpression:r.join(`+`),collectionCount:r.length}}function V(e,t={}){return e.trim()?ue(me(e),t):``}function Ee(){return Math.floor(Date.now()/1e3)}function H(e){return new Date(e*1e3).toISOString()}function De(e,t=`UTC`){let n=Ee()-e;if(n<60)return`1m`;let r=Math.floor(n/60);if(r<60)return`${r}m`;let i=Math.floor(n/3600);if(i<24)return`${i}h`;let a=Math.floor(n/86400);return a<=7?`${a}d`:new Date(e*1e3).toLocaleDateString(`en-US`,{month:`short`,day:`numeric`,timeZone:t})}function U(e,t=`UTC`){let n=De(e,t);return/^[0-9]+[mhd]$/.test(n)?`${n} ago`:n}var W=[`collection`,`format`,`title`,`year`,`media`,`replies`,`visibility`];function Oe(e){return e===`any`||e===`none`||Array.isArray(e)&&e.length>0&&e.every(e=>b.includes(e))}function ke(e){return typeof e==`boolean`?e:e===1||e===0?e===1:null}function Ae(e){if(typeof e!=`string`||e===``)return null;if(e===`any`||e===`none`)return e;let t=e.split(`,`).map(e=>e.trim()).filter(e=>b.includes(e));return t.length>0?t:null}var je=/[,+\s]+/;function Me(e){let t=new Set;for(let n of e.split(je)){let e=n.trim();e&&t.add(e)}return[...t]}var Ne={key:`collection`,label:{id:`q+hNag`},url:{param:`collection`,parse(e,t){let n=e(`collection`);if(!n)return{state:`absent`};let r=Me(n);if(r.length===0)return{state:`absent`};let i=t.collections,a=[];for(let e of r){let t=i?.idBySlug.get(e);if(!t)return{state:`invalid`,message:`No collection named "${e}".`};a.push(t)}return{state:`value`,value:a}},serialize(e,t){let n=e.map(e=>t.collections?.slugById.get(e)).filter(e=>!!e);return n.length>0?n.join(`,`):null}},storage:{column:`collectionId`,isStorable(e){return Array.isArray(e)&&e.length===1&&typeof e[0]==`string`&&fe(e[0],le.collection)},toColumn(e){return e[0]},fromColumn(e){return typeof e==`string`&&e?[e]:null}},control:{kind:`collection`},toPostFilter(e){return{collectionIds:[...e]}},describe(e,t,n){let r=e.map(e=>n.collections?.titleById.get(e)).filter(e=>!!e);return r.length>0?r.join(`, `):null}},Pe={note:{id:`1DBGsz`},link:{id:`Rj01Fz`},quote:{id:`eWLklq`}},Fe={key:`format`,label:{id:`kI1qVD`},url:{param:`format`,parse(e){let t=e(`format`);return t?y.includes(t)?{state:`value`,value:t}:{state:`invalid`,message:`Invalid format value. Allowed: ${y.join(`, `)}`}:{state:`absent`}},serialize(e){return e}},storage:{column:`format`,isStorable(e){return typeof e==`string`&&y.includes(e)},toColumn(e){return e},fromColumn(e){return y.includes(e)?e:null}},control:{kind:`enum`,options:y,labelOf:e=>Pe[e]},toPostFilter(e){return{format:e}},describe(e,t){return t._(Pe[e])}},G={id:`q8RviX`},Ie={id:`wja8aL`};function Le(e,t){let n=e(t);return n===void 0?{state:`absent`}:n===`1`?{state:`value`,value:!0}:n===`0`?{state:`value`,value:!1}:{state:`invalid`,message:`Invalid ${t} value. Allowed: 0, 1`}}function Re(e,t,n){let r=e(t);return r!==void 0&&r!==``?r===`any`?{state:`value`,value:!0}:r===`none`?{state:`value`,value:!1}:{state:`invalid`,message:`Invalid ${t} value. Allowed: any, none`}:Le(e,n)}var ze={key:`title`,label:{id:`MHrjPM`},url:{param:`title`,legacy:[`hasTitle`],parse(e){return Re(e,`title`,`hasTitle`)},serialize(e){return e?`any`:`none`}},storage:{column:`hasTitle`,isStorable(e){return typeof e==`boolean`},toColumn(e){return e},fromColumn:ke},control:{kind:`presence`,yes:G,no:Ie},toPostFilter(e){return{hasTitle:e}},describe(e,t){return t._(e?G:Ie)}},Be={key:`year`,label:{id:`3PAU4M`},url:{param:`year`,parse(e){let t=e(`year`);if(!t)return{state:`absent`};let n=Number.parseInt(t,10);return!Number.isFinite(n)||n<1971||n>9999?{state:`invalid`,message:`Invalid year value. Allowed: ${ie} to ${te}`}:{state:`value`,value:n}},serialize(e){return String(e)}},storage:{column:`year`,isStorable(e){return typeof e==`number`&&Number.isInteger(e)&&e>=1971&&e<=9999},toColumn(e){return e},fromColumn(e){return typeof e==`number`&&Number.isInteger(e)?e:null}},control:{kind:`year`},toPostFilter(e,t){let n=Date.UTC(e,0,1)/1e3,r=Date.UTC(e+1,0,1)/1e3;return t.yearAxis===`sort`?{axisAfter:n,axisBefore:r}:{publishedAfter:n,publishedBefore:r}},describe(e){return String(e)}},Ve={image:{id:`an5hVd`},video:{id:`vSJd18`},audio:{id:`/rTz0M`},text:{id:`mKT7g0`},document:{id:`sER+bs`}},He={id:`QJAQiR`},Ue={id:`P5WtnY`},We={key:`media`,label:{id:`xYilR2`},url:{param:`media`,legacy:[`hasMedia`],parse(e){let t=e(`media`);if(t===void 0||t===``){let t=Le(e,`hasMedia`);return t.state===`value`?{state:`value`,value:t.value?`any`:`none`}:t}if(t===`any`||t===`none`)return{state:`value`,value:t};let n=t.split(`,`).map(e=>e.trim()).filter(e=>e.length>0),r=n.filter(e=>b.includes(e));return n.length===0||r.length!==n.length?{state:`invalid`,message:`Invalid media value. Allowed: any, none, or kinds: ${b.join(`, `)}`}:{state:`value`,value:r}},serialize(e){return typeof e==`string`?e:e.length>0?e.join(`,`):null}},storage:{column:`media`,isStorable:Oe,toColumn(e){return typeof e==`string`?e:e.join(`,`)},fromColumn:Ae},control:{kind:`media`},toPostFilter(e){return e===`any`?{hasMedia:!0}:e===`none`?{hasMedia:!1}:e.length>0?{mediaKinds:[...e]}:{}},describe(e,t){return e===`any`?t._(He):e===`none`?t._(Ue):e.length===1?t._(Ve[e[0]]):e.length>0?t._(He):null}},Ge={id:`FqCHF/`},Ke={id:`hqeXKW`},qe={key:`replies`,label:{id:`N8UzTV`},url:{param:`replies`,legacy:[`hasReplies`],parse(e){return Re(e,`replies`,`hasReplies`)},serialize(e){return e?`any`:`none`}},storage:{column:`hasReplies`,isStorable(e){return typeof e==`boolean`},toColumn(e){return e},fromColumn:ke},control:{kind:`presence`,yes:Ge,no:Ke},toPostFilter(e){return{hasReplies:e}},describe(e,t){return t._(e?Ge:Ke)}},K={public:`public`,featured:`featured`,latest_hidden:`hidden`,private:`private`},Je=Object.keys(K),Ye=new Map(Object.entries(K).map(([e,t])=>[t,e])),Xe=new Map([[`latest_hidden`,{state:`value`,value:`latest_hidden`}],[`all`,{state:`cleared`}]]),Ze={public:{id:`7d1a0d`},latest_hidden:{id:`dYKrp3`},private:{id:`zwBp5t`},featured:{id:`FkMol5`}},q={collection:Ne,format:Fe,title:ze,year:Be,media:We,replies:qe,visibility:{key:`visibility`,label:{id:`2q/Q7x`},url:{param:`visibility`,parse(e){let t=e(`visibility`);if(!t)return{state:`absent`};let n=Xe.get(t);if(n)return n;let r=Ye.get(t);return r?{state:`value`,value:r}:{state:`invalid`,message:`Invalid visibility value. Allowed: ${[...Ye.keys()].join(`, `)}`}},serialize(e){return K[e]}},storage:{column:`visibility`,isStorable(e){return typeof e==`string`&&ae.includes(e)},toColumn(e){return e},fromColumn(e){return Je.includes(e)?e:null}},control:{kind:`enum`,options:ae,labelOf:e=>Ze[e]},toPostFilter(e){return e===`featured`?{featured:!0}:{visibility:e}},describe(e,t){return t._(Ze[e])}}};W.flatMap(e=>[q[e].url.param,...q[e].url.legacy??[]]);function Qe(e,t){let n={},r=[];for(let i of W){let a=q[i],o=a.url.parse(e,t);o.state===`value`?n[i]=o.value:o.state===`invalid`&&r.push({param:a.url.param,message:o.message})}return{selection:n,issues:r}}function $e(e,t,n=new URLSearchParams){for(let r of W){let i=e[r];if(i===void 0)continue;let a=q[r],o=et(r,i,t);o!==null&&n.set(a.url.param,o)}return n}function et(e,t,n){let r=q[e].url.serialize;return r(t,n)}function J(e,t){return(n,r,i)=>o`
1210
+ <select
1211
+ class="select smart-condition-select"
1212
+ .value=${n}
1213
+ @change=${e=>r(e.target.value)}
1214
+ >
1215
+ ${t.map(t=>o`
1216
+ <option value=${t} ?selected=${t===n}>
1217
+ ${i.values[`${e}.${t}`]??t}
1218
+ </option>
1219
+ `)}
1220
+ </select>
1221
+ `}function tt(e){return J(e,[`any`,`none`])}var Y={collection:{defaultValue:``,render:(e,t,n)=>{let r=Object.entries(n.values).filter(([e])=>e.startsWith(`collection.`)).map(([e,t])=>[e.slice(11),t]);return o`
1222
+ <select
1223
+ class="select smart-condition-select"
1224
+ .value=${e}
1225
+ @change=${e=>t(e.target.value)}
1226
+ >
1227
+ ${r.map(([t,n])=>o`
1228
+ <option value=${t} ?selected=${t===e}>${n}</option>
1229
+ `)}
1230
+ </select>
1231
+ `}},format:{defaultValue:y[0],render:J(`format`,y)},title:{defaultValue:`any`,render:tt(`title`)},year:{defaultValue:String(new Date().getUTCFullYear()),render:(e,t)=>o`
1232
+ <input
1233
+ class="input smart-condition-year"
1234
+ type="number"
1235
+ min="1971"
1236
+ step="1"
1237
+ .value=${e}
1238
+ @input=${e=>t(e.target.value)}
1239
+ />
1240
+ `},media:{defaultValue:`any`,render:(e,t,n)=>{let r=e===`any`||e===`none`?[]:e.split(`,`),i=(e,n)=>{let i=n?[...r,e]:r.filter(t=>t!==e);t(i.length>0?i.join(`,`):`any`)};return o`
1241
+ <div class="smart-condition-media">
1242
+ <select
1243
+ class="select smart-condition-select"
1244
+ .value=${e===`none`?`none`:`any`}
1245
+ @change=${e=>t(e.target.value)}
1246
+ >
1247
+ <option value="any" ?selected=${e!==`none`}>
1248
+ ${n.values[`media.any`]??`any`}
1249
+ </option>
1250
+ <option value="none" ?selected=${e===`none`}>
1251
+ ${n.values[`media.none`]??`none`}
1252
+ </option>
1253
+ </select>
1254
+ ${e===`none`?null:o`
1255
+ <div class="smart-condition-media-kinds">
1256
+ ${b.map(e=>o`
1257
+ <label class="smart-condition-kind">
1258
+ <input
1259
+ class="input"
1260
+ type="checkbox"
1261
+ .checked=${r.includes(e)}
1262
+ @change=${t=>i(e,t.target.checked)}
1263
+ />
1264
+ <span>${n.values[`media.${e}`]??e}</span>
1265
+ </label>
1266
+ `)}
1267
+ </div>
1268
+ `}
1269
+ </div>
1270
+ `}},replies:{defaultValue:`any`,render:tt(`replies`)},visibility:{defaultValue:`public`,render:J(`visibility`,[`public`,`featured`,`hidden`])}};function nt(e){let t=$e(e,{collections:ot()}),n=[];for(let e of W){let r=t.get(q[e].url.param);r!==null&&n.push({key:e,value:r})}return n}function rt(e){let t=new URLSearchParams;for(let n of e){if(!n.value)continue;let e=q[n.key];e&&t.set(e.url.param,n.value)}let{selection:n}=Qe(e=>t.get(e)??void 0,{collections:ot()});return n}var it={idBySlug:new Map,slugById:new Map,titleById:new Map};function at(e){let t=new Map,n=new Map,r=new Map;for(let i of e)t.set(i.slug,i.id),n.set(i.id,i.slug),r.set(i.id,i.title);it={idBySlug:t,slugById:n,titleById:r}}function ot(){return it}var st=250,ct=o`<svg
1271
+ viewBox="0 0 24 24"
1272
+ fill="none"
1273
+ stroke="currentColor"
1274
+ stroke-width="2"
1275
+ stroke-linecap="round"
1276
+ stroke-linejoin="round"
1277
+ aria-hidden="true"
1278
+ >
1279
+ <path d="M5 12h14" />
1280
+ <path d="M12 5v14" />
1281
+ </svg>`,lt=o`<svg
1282
+ viewBox="0 0 24 24"
1283
+ fill="none"
1284
+ stroke="currentColor"
1285
+ stroke-width="2"
1286
+ stroke-linecap="round"
1287
+ stroke-linejoin="round"
1288
+ aria-hidden="true"
1289
+ >
1290
+ <circle cx="12" cy="12" r="10" />
1291
+ <line x1="12" x2="12" y1="8" y2="12" />
1292
+ <line x1="12" x2="12.01" y1="16" y2="16" />
1293
+ </svg>`,ut=o`<svg
1294
+ viewBox="0 0 24 24"
1295
+ fill="none"
1296
+ stroke="currentColor"
1297
+ stroke-width="2"
1298
+ stroke-linecap="round"
1299
+ stroke-linejoin="round"
1300
+ aria-hidden="true"
1301
+ >
1302
+ <path d="M18 6 6 18" />
1303
+ <path d="m6 6 12 12" />
1304
+ </svg>`,dt=class extends c{static properties={labels:{type:Object},_open:{state:!0},_mode:{state:!0},_id:{state:!0},_title:{state:!0},_slug:{state:!0},_slugEdited:{state:!0},_slugState:{state:!0},_slugOpen:{state:!0},_description:{state:!0},_rows:{state:!0},_sort:{state:!0},_layout:{state:!0},_preview:{state:!0},_addMenuOpen:{state:!0},_saving:{state:!0},_error:{state:!0}};#e=``;#t=``;#n=null;#r=null;#i=null;#a=0;createRenderRoot(){return this.innerHTML=``,this}constructor(){super(),this.labels={},this._open=!1,this._mode=`create`,this._id=null,this._title=``,this._slug=``,this._slugEdited=!1,this._slugState=`unknown`,this._slugOpen=!1,this._description=``,this._rows=[],this._sort=`newest`,this._layout=``,this._preview=null,this._addMenuOpen=!1,this._saving=!1,this._error=``}async open(e){if(this.#o(),e.smartCollectionId){if(!await this.#s(e.smartCollectionId))return!1}else e.prefill&&(this._title=e.prefill.title??``,this._description=e.prefill.description??``,this._rows=nt(e.prefill.selection??{}),this._sort=e.prefill.sort??`newest`,this._layout=e.prefill.layout??``,this._title&&await this.#S());return this._open=!0,await this.updateComplete,this.#c(),this.#y(),new Promise(e=>{this.#n=e})}#o(){this._mode=`create`,this._id=null,this._title=``,this._slug=``,this._slugEdited=!1,this._slugState=`unknown`,this._slugOpen=!1,this._description=``,this._rows=[],this._sort=`newest`,this._layout=``,this._preview=null,this._addMenuOpen=!1,this._saving=!1,this._error=``,this.#e=``}async#s(e){try{let t=await fetch(a(`/api/smart-collections/${e}`));if(!t.ok)throw Error(`HTTP ${t.status}`);let n=(await t.json()).smartCollection;return this._mode=`edit`,this._id=n.id,this._title=n.title??``,this._slug=n.slug??``,this.#e=n.slug??``,this._slugEdited=!0,this._description=n.description??``,this._rows=nt(n.selection??{}),this._sort=n.sort??`newest`,this._layout=n.layout??``,!0}catch{return l(this.labels.loadFailed,`error`),!1}}#c(){let e=this.querySelector(`.collection-dialog`);e&&(e.open||e.showModal(),this.querySelector(`[data-field='title']`)?.focus())}#l(e){let t=this.querySelector(`.collection-dialog`);t?.open&&t.close(),this._open=!1,this._addMenuOpen=!1,this.#r&&clearTimeout(this.#r),this.#i&&clearTimeout(this.#i);let n=this.#n;this.#n=null,n?.(e)}#u(){let e=new Set(this._rows.map(e=>e.key));return Object.keys(Y).filter(t=>!e.has(t))}#d(e){this._addMenuOpen=!1,this._rows=[...this._rows,{key:e,value:Y[e].defaultValue}],this.#y()}#f(){this._addMenuOpen=!this._addMenuOpen,this._addMenuOpen&&this.updateComplete.then(()=>{this.#m()?.scrollIntoView?.({block:`nearest`}),this.#h()[0]?.focus()})}#p(e){this._addMenuOpen&&(this._addMenuOpen=!1,e&&this.updateComplete.then(()=>{this.querySelector(`[data-add-trigger]`)?.focus()}))}#m(){return this.querySelector(`[data-add-menu]`)}#h(){return[...this.querySelectorAll(`[data-add-menu] [role='menuitem']`)]}#g(e){let t=this.#h();if(t.length===0)return;let n=t.indexOf(document.activeElement);t[n<0?e>0?0:t.length-1:(n+e+t.length)%t.length]?.focus()}#_(e){this._rows=this._rows.filter(t=>t.key!==e),this.#y()}#v(e,t){this._rows=this._rows.map(n=>n.key===e?{...n,value:t}:n),this.#y()}#y(){this.#r&&clearTimeout(this.#r),this.#r=setTimeout(()=>void this.#b(),st)}async#b(){let e=++this.#a;try{let t=await fetch(a(`/api/smart-collections/preview`),{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({selection:rt(this._rows)})});if(!t.ok)throw Error(`HTTP ${t.status}`);let n=await t.json();if(e!==this.#a)return;this._preview=n}catch{if(e!==this.#a)return;this._preview=null}}#x(e){this._title=e,!this._slugEdited&&this.#S()}async#S(){let e=this._title.trim();if(!e){this.#t=``,this._slug=``,this._slugState=`unknown`;return}this.#t=g(await se(e),200),this._slug=this.#t,this.#w()}#C(e){this._slugEdited=!0,this._slug=e.trim().toLowerCase(),this.#w()}#w(){this.#i&&clearTimeout(this.#i),this._slugState=`checking`,this.#i=setTimeout(()=>void this.#T(),st)}async#T(){let e=this._slug;if(!e){this._slugState=`unknown`;return}if(this.#E()!==null){this._slugState=`taken`;return}try{let t=new URLSearchParams({mode:`check`,slug:e});this._id&&t.set(`smartCollectionId`,this._id);let n=await fetch(a(`/api/smart-collections/slug?${t.toString()}`));if(!n.ok)throw Error(`HTTP ${n.status}`);let r=await n.json();if(e!==this._slug)return;this._slugState=r.available?`available`:`taken`}catch{if(e!==this._slug)return;this._slugState=`unknown`}}#E(){return v(this._slug,{maxLength:200})}#D(){let e=this.#E();return e===`invalid`?this.labels.linkInvalid:e===`reserved`?this.labels.linkReserved:e===`too_long`?this.labels.linkTooLong:this._slugState===`taken`?this.labels.linkTaken:null}#O(){let e=a(C(this._slug)),t=globalThis.location?.origin&&globalThis.location.origin!==`null`?globalThis.location.origin:`http://localhost`;return new URL(e,`${t}/`).toString()}#k(){this._slugOpen||(this._slugOpen=!0,this.updateComplete.then(()=>{let e=this.querySelector(`[data-field='slug']`);e?.focus(),e?.select()}))}#A(){this.#t&&(this._slug=this.#t,this._slugEdited=!1,this.#w())}#j(){if(!this._slug&&!this._slugOpen)return s;let e=this.#D(),t=this._mode===`edit`&&this._slug!==this.#e;if(!this._slugOpen)return o`
1305
+ <div class="collection-quick-link-box">
1306
+ <div class="collection-quick-link-row">
1307
+ <p
1308
+ class="collection-quick-link-preview text-xs text-muted-foreground"
1309
+ aria-live="polite"
1310
+ >
1311
+ ${this.#O()}
1312
+ </p>
1313
+ <button
1314
+ type="button"
1315
+ class="collection-quick-link-action"
1316
+ @click=${()=>this.#k()}
1317
+ >
1318
+ ${this.labels.editLink}
1319
+ </button>
1320
+ </div>
1321
+ ${e?o`<p class="collection-dialog-link-problem">${e}</p>`:s}
1322
+ </div>
1323
+ `;let n=!!this.#t&&this._slug!==this.#t;return o`
1324
+ <div class="collection-quick-link-editor">
1325
+ <div class="field">
1326
+ <div class="collection-quick-link-row">
1327
+ <label class="label mb-0" for="smart-collection-slug"
1328
+ >${this.labels.link}</label
1329
+ >
1330
+ ${n?o`
1331
+ <button
1332
+ type="button"
1333
+ class="collection-quick-link-action"
1334
+ @click=${()=>this.#A()}
1335
+ >
1336
+ ${this.labels.resetLink}
1337
+ </button>
1338
+ `:s}
1339
+ </div>
1340
+ <input
1341
+ id="smart-collection-slug"
1342
+ class="input"
1343
+ type="text"
1344
+ data-field="slug"
1345
+ required
1346
+ maxlength=${200}
1347
+ autocomplete="off"
1348
+ autocapitalize="off"
1349
+ spellcheck="false"
1350
+ aria-invalid=${e?`true`:`false`}
1351
+ .value=${this._slug}
1352
+ @input=${e=>this.#C(e.target.value)}
1353
+ />
1354
+ ${e?o`<p class="collection-dialog-link-problem">${e}</p>`:this._slug?o`<p class="collection-dialog-link-preview">
1355
+ ${this.#O()}
1356
+ </p>`:o`<p class="collection-dialog-link-help">
1357
+ ${this.labels.linkHelp}
1358
+ </p>`}
1359
+ ${t?o`<p class="collection-dialog-link-problem">
1360
+ ${this.labels.linkMovesWarning}
1361
+ </p>`:s}
1362
+ </div>
1363
+ </div>
1364
+ `}#M(){return!this._title.trim()||!this._slug?this.labels.titleAndLinkRequired:this.#D()}async#N(){if(this._saving)return;let e=this.#M();if(e){this._error=e;return}let t=this._title.trim();this._saving=!0,this._error=``;let n={slug:this._slug,title:t,description:this._description.trim()||null,selection:rt(this._rows),sort:this._sort,layout:this._layout||null};try{let e=await fetch(a(this._id?`/api/smart-collections/${this._id}`:`/api/smart-collections`),{method:this._id?`PUT`:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify(n)});if(!e.ok){let t=await e.json().catch(()=>null);this._error=t?.error??this.labels.saveFailed;return}l(this.labels.saved),this.#l(!0)}catch{this._error=this.labels.saveFailed}finally{this._saving=!1}}#P=e=>{if(this._open){if(e.key===`Escape`){if(e.preventDefault(),e.stopPropagation(),this._addMenuOpen){this.#p(!0);return}this.#l(!1);return}if(this._addMenuOpen&&(e.key===`ArrowDown`||e.key===`ArrowUp`)){e.preventDefault(),this.#g(e.key===`ArrowDown`?1:-1);return}if(e.key===`Enter`){let t=e.target;if(t?.tagName===`TEXTAREA`||t?.getAttribute(`role`)===`menuitem`)return;e.preventDefault(),this.#N()}}};connectedCallback(){super.connectedCallback(),this.addEventListener(`keydown`,this.#P)}disconnectedCallback(){super.disconnectedCallback(),this.removeEventListener(`keydown`,this.#P),this.#r&&clearTimeout(this.#r),this.#i&&clearTimeout(this.#i)}#F(e){let t=Y[e.key],n=this.labels.dimensions[e.key]??e.key;return o`
1365
+ <div class="smart-condition-row" data-condition=${e.key}>
1366
+ <span class="smart-condition-label">${n}</span>
1367
+ <div class="smart-condition-control">
1368
+ ${t.render(e.value,t=>this.#v(e.key,t),this.labels)}
1369
+ </div>
1370
+ <button
1371
+ type="button"
1372
+ class="btn-sm-icon-ghost smart-condition-remove"
1373
+ aria-label=${this.labels.removeCondition}
1374
+ title=${this.labels.removeCondition}
1375
+ @click=${()=>this.#_(e.key)}
1376
+ >
1377
+ ${ut}
1378
+ </button>
1379
+ </div>
1380
+ `}#I(){let e=this.#u(),t=this._rows.length>0;return o`
1381
+ <section class="smart-collection-section">
1382
+ <div class="smart-collection-section-head">
1383
+ <h3 class="smart-collection-section-title">
1384
+ ${this.labels.conditionsHeading}
1385
+ </h3>
1386
+ <!-- The count belongs to the whole section, not to the last row:
1387
+ it answers "what did that just do" from a fixed place. -->
1388
+ <p class="smart-collection-count" aria-live="polite">
1389
+ ${this._preview?this.labels.countSummary.replace(`{count}`,String(this._preview.count)).replace(`{total}`,String(this._preview.baseline)):this.labels.counting}
1390
+ </p>
1391
+ </div>
1392
+
1393
+ <p class="smart-collection-section-hint">
1394
+ ${t?this.labels.matchAllHint:this.labels.noConditions}
1395
+ </p>
1396
+
1397
+ ${t?o`
1398
+ <div class="smart-condition-rows">
1399
+ ${this._rows.map(e=>this.#F(e))}
1400
+ </div>
1401
+ `:s}
1402
+
1403
+ <div class="smart-condition-add">
1404
+ <button
1405
+ type="button"
1406
+ class="btn-sm-outline smart-condition-add-trigger"
1407
+ data-add-trigger
1408
+ ?disabled=${e.length===0}
1409
+ aria-haspopup="menu"
1410
+ aria-expanded=${String(this._addMenuOpen)}
1411
+ @click=${e=>{e.stopPropagation(),this.#f()}}
1412
+ >
1413
+ ${ct}${this.labels.addCondition}
1414
+ </button>
1415
+ ${this._addMenuOpen?o`
1416
+ <div
1417
+ class="collections-page-menu smart-condition-menu"
1418
+ data-add-menu
1419
+ role="menu"
1420
+ @click=${e=>e.stopPropagation()}
1421
+ >
1422
+ ${e.map(e=>o`
1423
+ <button
1424
+ type="button"
1425
+ class="collections-page-menu-item"
1426
+ role="menuitem"
1427
+ @click=${()=>this.#d(e)}
1428
+ >
1429
+ ${this.labels.dimensions[e]??e}
1430
+ </button>
1431
+ `)}
1432
+ </div>
1433
+ `:s}
1434
+ </div>
1435
+ </section>
1436
+ `}render(){if(!this._open)return s;let e=this._mode===`edit`?this.labels.editHeading:this.labels.createHeading;return o`
1437
+ <dialog
1438
+ class="dialog collection-dialog"
1439
+ @cancel=${e=>{e.preventDefault(),this.#l(!1)}}
1440
+ @click=${e=>{e.target===e.currentTarget&&this.#l(!1),this.#p(!1)}}
1441
+ >
1442
+ <div
1443
+ class="collection-dialog-panel"
1444
+ role="dialog"
1445
+ aria-modal="true"
1446
+ aria-labelledby="collection-dialog-title"
1447
+ @click=${e=>{e.stopPropagation(),this.#p(!1)}}
1448
+ >
1449
+ <header class="collection-dialog-header">
1450
+ <h2 id="collection-dialog-title" class="collection-dialog-title">
1451
+ ${e}
1452
+ </h2>
1453
+ <!-- Said once, where it is needed: by the time anyone edits one
1454
+ they know what it is. -->
1455
+ ${this._mode===`create`?o`<p class="collection-dialog-note">
1456
+ ${this.labels.whatItIs}
1457
+ </p>`:s}
1458
+ </header>
1459
+
1460
+ <div
1461
+ class="collection-dialog-body"
1462
+ @input=${()=>{this._error=``}}
1463
+ @change=${()=>{this._error=``}}
1464
+ >
1465
+ <div class="field">
1466
+ <label for="smart-collection-title">${this.labels.title}</label>
1467
+ <input
1468
+ id="smart-collection-title"
1469
+ class="input"
1470
+ type="text"
1471
+ data-field="title"
1472
+ required
1473
+ .value=${this._title}
1474
+ @input=${e=>this.#x(e.target.value)}
1475
+ />
1476
+ </div>
1477
+
1478
+ ${this.#j()}
1479
+
1480
+ <div class="field">
1481
+ <label for="smart-collection-description"
1482
+ >${this.labels.description}</label
1483
+ >
1484
+ <textarea
1485
+ id="smart-collection-description"
1486
+ class="textarea"
1487
+ rows="2"
1488
+ .value=${this._description}
1489
+ @input=${e=>{this._description=e.target.value}}
1490
+ ></textarea>
1491
+ </div>
1492
+
1493
+ ${this.#I()}
1494
+
1495
+ <section class="smart-collection-section">
1496
+ <div class="smart-collection-section-head">
1497
+ <h3 class="smart-collection-section-title">
1498
+ ${this.labels.displayHeading}
1499
+ </h3>
1500
+ </div>
1501
+ <div class="smart-collection-display">
1502
+ <div class="field">
1503
+ <label for="smart-collection-sort"
1504
+ >${this.labels.orderBy}</label
1505
+ >
1506
+ <select
1507
+ id="smart-collection-sort"
1508
+ class="select"
1509
+ .value=${this._sort}
1510
+ @change=${e=>{this._sort=e.target.value}}
1511
+ >
1512
+ ${Object.entries(this.labels.sortOptions).map(([e,t])=>o`<option
1513
+ value=${e}
1514
+ ?selected=${e===this._sort}
1515
+ >
1516
+ ${t}
1517
+ </option>`)}
1518
+ </select>
1519
+ </div>
1520
+ <div class="field">
1521
+ <label for="smart-collection-layout"
1522
+ >${this.labels.layout}</label
1523
+ >
1524
+ <select
1525
+ id="smart-collection-layout"
1526
+ class="select"
1527
+ .value=${this._layout}
1528
+ @change=${e=>{this._layout=e.target.value}}
1529
+ >
1530
+ ${Object.entries(this.labels.layoutOptions).map(([e,t])=>o`<option
1531
+ value=${e}
1532
+ ?selected=${e===this._layout}
1533
+ >
1534
+ ${t}
1535
+ </option>`)}
1536
+ </select>
1537
+ </div>
1538
+ </div>
1539
+ </section>
1540
+
1541
+ ${this._error?o`<div class="alert-destructive" role="alert">
1542
+ ${lt}
1543
+ <section><p>${this._error}</p></section>
1544
+ </div>`:s}
1545
+ </div>
1546
+
1547
+ <footer class="collection-dialog-actions">
1548
+ <button
1549
+ type="button"
1550
+ class="btn-outline"
1551
+ @click=${()=>this.#l(!1)}
1552
+ >
1553
+ ${this.labels.cancel}
1554
+ </button>
1555
+ <button
1556
+ type="button"
1557
+ class="btn"
1558
+ ?disabled=${this._saving||this.#M()!==null}
1559
+ @click=${()=>void this.#N()}
1560
+ >
1561
+ ${this.labels.save}
1562
+ </button>
1563
+ </footer>
1564
+ </div>
1565
+ </dialog>
1566
+ `}};customElements.get(`jant-smart-collection-dialog`)||customElements.define(`jant-smart-collection-dialog`,dt);var ft=`data-smart-collection-dialog-labels`,X=null,Z=null,pt=null;function mt(){if(X)return X;let e=document.querySelector(`[${ft}]`)?.getAttribute(ft);if(!e)return null;try{return X=JSON.parse(e),X}catch{return null}}async function ht(e){pt??=gt();let t=await pt;at(t);for(let n of t)e.values[`collection.${n.slug}`]=n.title}async function gt(){try{let e=await fetch(a(`/api/collections`));return e.ok?(await e.json()).collections??[]:[]}catch{return[]}}function _t(e){return Z?.isConnected?(Z.labels=e,Z):(Z=document.createElement(`jant-smart-collection-dialog`),Z.labels=e,document.body.appendChild(Z),Z)}async function Q(e){let t=mt();return t?(await ht(t),_t(t).open(e)):!1}var vt=class extends c{static properties={items:{type:Array},labels:{type:Object},navigationCollectionIds:{type:Array,attribute:`navigation-collection-ids`},_items:{state:!0},_reorderMode:{state:!0},_editingDividerId:{state:!0},_editingLinkId:{state:!0},_editLinkLabel:{state:!0},_editLinkUrl:{state:!0},_editLinkDescription:{state:!0},_showMoreMenu:{state:!0},_showLinkForm:{state:!0},_newLinkLabel:{state:!0},_newLinkUrl:{state:!0},_newLinkDescription:{state:!0},_addingLink:{state:!0},_showItemMenuId:{state:!0},_addingToNavigationId:{state:!0},_createdCollectionId:{state:!0}};#e=null;#t=!1;#n=null;#r=null;#i=null;#a=null;#o=()=>{this._showMoreMenu=!1,document.removeEventListener(`click`,this.#o)};#s=()=>{this._showItemMenuId=null,document.removeEventListener(`click`,this.#s)};#c=e=>{let t=e.target;if(!t)return;t.closest(`[data-collections-more-menu]`)&&e.stopPropagation();let n=t.closest(`[data-collections-action]`);if(!n||!this.#r?.contains(n))return;let r=n.dataset.collectionsAction;if(r)switch(e.preventDefault(),e.stopPropagation(),r!==`toggle-menu`&&this._showMoreMenu&&(this._showMoreMenu=!1,document.removeEventListener(`click`,this.#o)),r){case`done`:this.#x();break;case`toggle-menu`:this._showMoreMenu=!this._showMoreMenu,this._showMoreMenu?setTimeout(()=>{document.addEventListener(`click`,this.#o)}):document.removeEventListener(`click`,this.#o);break;case`organize`:this.#b();break;case`divider`:this.#w();break;case`link`:this.#T();break;case`collection`:this.#l();break;case`smart-collection`:Q({}).then(e=>{e&&this.#v()})}};createRenderRoot(){return this.innerHTML=``,this}connectedCallback(){super.connectedCallback(),this.#p()}async#l(){let e=await F();e.changed&&(await this.#v(),e.collection&&(this._createdCollectionId=e.collection.id))}async#u(e){this._showItemMenuId=null,document.removeEventListener(`click`,this.#s);let{changed:t}=await F({collectionId:e});t&&await this.#v()}constructor(){super(),this.items=[],this.labels={},this.navigationCollectionIds=[],this._items=[],this._reorderMode=!1,this._editingDividerId=null,this._editingLinkId=null,this._editLinkLabel=``,this._editLinkUrl=``,this._editLinkDescription=``,this._showMoreMenu=!1,this._showLinkForm=!1,this._newLinkLabel=``,this._newLinkUrl=``,this._newLinkDescription=``,this._addingLink=!1,this._showItemMenuId=null,this._addingToNavigationId=null,this._createdCollectionId=null}update(e){(!this.#t||e.has(`items`))&&(this._items=[...this.items??[]],this.#t=!0),super.update(e)}disconnectedCallback(){super.disconnectedCallback(),this.#e?.destroy(),this.#e=null,this.#r?.removeEventListener(`click`,this.#c),this.#r=null,this.#i?.destroy(),this.#i=null,this.#a?.destroy(),this.#a=null,document.removeEventListener(`click`,this.#o),document.removeEventListener(`click`,this.#s)}#d(){return this._items.some(e=>e.type===`collection`&&e.collection||e.type===`smart_collection`&&e.smartCollection||e.type===`link`&&e.label&&e.url)}#f(e){return`${e} ${e===1?this.labels.threadSingular:this.labels.threadPlural}`}#p(){let e=this.closest(`[data-collections-manager-root]`);e!==this.#r&&(this.#r?.removeEventListener(`click`,this.#c),this.#r=e,this.#r?.addEventListener(`click`,this.#c))}#m(e){return this.#r?.querySelector(e)??null}#h(){let e=this.#m(`[data-collections-action="done"]`);e&&(e.hidden=!this._reorderMode);let t=this.#m(`[data-collections-reorder-actions]`);t&&(t.hidden=!this._reorderMode);let n=this.#m(`[data-collections-toolbar]`);n&&(n.hidden=this._reorderMode);let r=this.#m(`[data-collections-hint]`);r&&(r.hidden=!this._reorderMode);let i=this.#m(`[data-collections-more-menu]`);i&&(i.hidden=!this._showMoreMenu||this._reorderMode);let a=this.#m(`[data-collections-action="toggle-menu"]`);a&&a.setAttribute(`aria-expanded`,String(this._showMoreMenu&&!this._reorderMode))}#g(){at(this._items.flatMap(e=>e.collection?[{id:e.collection.id,slug:e.collection.slug,title:e.collection.title}]:[]))}#_(e){let t=e.collections??[],n=e.directoryItems??[],r=new Map;for(let e of t)r.set(e.id,{id:e.id,slug:e.slug,title:e.title,description:e.description,sortOrder:e.sortOrder,threadCount:e.threadCount??0,recentActivityAt:e.recentActivityAt});let i=e.smartCollections??[],a=new Map;for(let e of i)a.set(e.id,{id:e.id,slug:e.slug,title:e.title,description:e.description,selection:e.selection??{},sort:e.sort,layout:e.layout,threadCount:e.threadCount??0,recentActivityAt:e.recentActivityAt});let o=new Set,s=new Set,c=[];for(let e of n){let t=e.collectionId==null?void 0:r.get(e.collectionId),n=e.smartCollectionId==null?void 0:a.get(e.smartCollectionId);(e.type!==`collection`||t)&&(e.type!==`smart_collection`||n)&&(t&&o.add(t.id),n&&s.add(n.id),c.push({id:e.id,type:e.type,collectionId:e.collectionId,smartCollectionId:e.smartCollectionId,label:e.label,url:e.url,description:e.description,position:e.position,collection:t,smartCollection:n}))}for(let e of t)o.has(e.id)||c.push({id:e.id,type:`collection`,collectionId:e.id,label:null,url:null,position:``,collection:r.get(e.id)});for(let e of i)s.has(e.id)||c.push({id:e.id,type:`smart_collection`,smartCollectionId:e.id,label:null,url:null,position:``,smartCollection:a.get(e.id)});return c}async#v(){try{let e=n(),t=await fetch(e?`/api/collections?lang=${encodeURIComponent(e)}`:`/api/collections`);if(!t.ok)return;let r=await t.json();this._items=this.#_(r)}catch{}}#y(){let e=this.querySelector(`#collections-manager-list`);!e||this.#e||(this.#e=O.create(e,{...de,chosenClass:`collection-directory-chosen`,dragClass:`collection-directory-drag`,ghostClass:`collection-directory-ghost`,handle:`[data-drag-handle]`,scroll:!0,onChoose:()=>{E(e,!0)},onStart:e=>{this.#n=k(e)},onUnchoose:()=>{E(e,!1)},onEnd:t=>{let n=D(e,`[data-directory-item]`,`directoryItem`);ce(e,t,this.#n),this.#n=null,E(e,!1),this.#e?.destroy(),this.#e=null;let{movedId:r,afterId:i,beforeId:a}=pe(n,t.newIndex);if(!r)return;let o=new Map(this._items.map(e=>[e.id,e]));this._items=n.map(e=>o.get(e)).filter(e=>e!==void 0),fetch(`/api/collections/directory-items/${r}/move`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({after:i??null,before:a??null})}).then(e=>{e.ok?l(this.labels.orderSaved):l(this.labels.saveFailed,`error`)})}}))}#b(){this._reorderMode=!0,this._showLinkForm=!1,this._editingLinkId=null,this._showMoreMenu=!1,document.removeEventListener(`click`,this.#o)}#x(){this._reorderMode=!1,this._editingDividerId=null,this.#e?.destroy(),this.#e=null}updated(e){if(this.#p(),this.#h(),this.#g(),this._reorderMode&&this.#y(),this._editingDividerId){let e=this.querySelector(`[data-divider-input-for="${this._editingDividerId}"]`);e&&(e.focus(),e.select(),e.scrollIntoView({block:`nearest`}),this._editingDividerId=null)}if(e.has(`_showLinkForm`)&&this._showLinkForm){let e=this.querySelector(`[data-link-form-input="label"]`);e&&this.ownerDocument.activeElement!==e&&e.focus(),this.#S()}e.has(`_editingLinkId`)&&this._editingLinkId&&this.#C()}#S(){let e=this.querySelector(`[data-new-link-desc-editor]`);!e||this.#i||(this.#i=j({element:e,placeholder:this.labels.linkDescriptionPlaceholder,content:this._newLinkDescription||void 0,onUpdate:e=>{this._newLinkDescription=e}}),this._newLinkDescription=A(this.#i.getJSON()))}#C(){let e=this.querySelector(`[data-edit-link-desc-editor]`);!e||this.#a||(this.#a=j({element:e,placeholder:this.labels.linkDescriptionPlaceholder,content:this._editLinkDescription||void 0,onUpdate:e=>{this._editLinkDescription=e}}),this._editLinkDescription=A(this.#a.getJSON()))}async#w(){this._showMoreMenu=!1,document.removeEventListener(`click`,this.#o);try{let e=await fetch(`/api/collections/directory-items`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({type:`divider`})});if(!e.ok)throw Error(`HTTP ${e.status}`);let t=await e.json();this._reorderMode=!0,await this.#v(),this._editingDividerId=t.id}catch{l(this.labels.saveFailed,`error`)}}#T(){this._showMoreMenu=!1,this._showLinkForm=!0,this._newLinkLabel=``,this._newLinkUrl=``,this._newLinkDescription=``,this.#i?.destroy(),this.#i=null,document.removeEventListener(`click`,this.#o)}async#E(){let e=this._newLinkLabel.trim(),t=this._newLinkUrl.trim();if(!e||!t){l(this.labels.labelAndUrlRequired,`error`);return}this._addingLink=!0;try{let n=this._newLinkDescription.trim()||null,r=await fetch(`/api/collections/directory-items`,{method:`POST`,headers:{"Content-Type":`application/json`},body:JSON.stringify({type:`link`,label:e,url:t,description:n})});if(!r.ok)throw Error(`HTTP ${r.status}`);this._showLinkForm=!1,this._newLinkLabel=``,this._newLinkUrl=``,this._newLinkDescription=``,this.#i?.destroy(),this.#i=null,l(this.labels.linkCreated),await this.#v()}catch{l(this.labels.saveFailed,`error`)}finally{this._addingLink=!1}}async#D(e){try{let t=await fetch(`/api/collections/directory-items/${e}`,{method:`DELETE`});if(!t.ok)throw Error(`HTTP ${t.status}`);this._items=this._items.filter(t=>t.id!==e)}catch{l(this.labels.saveFailed,`error`)}}async#O(e,t){let n=t.trim();if(n!==(this._items.find(t=>t.id===e)?.label??``))try{let t=await fetch(`/api/collections/directory-items/${e}`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({label:n||null})});if(!t.ok)throw Error(`HTTP ${t.status}`);let r=await t.json();this._items=this._items.map(t=>t.id===e?{...t,label:r.label??null}:t)}catch{l(this.labels.saveFailed,`error`),await this.#v()}}async#k(e){if(await h({message:this.labels.confirmDelete,confirmLabel:this.labels.deleteCollection,cancelLabel:this.labels.cancel,tone:`danger`})){this._showItemMenuId=null,document.removeEventListener(`click`,this.#s);try{let t=await fetch(`/api/collections/${e.id}`,{method:`DELETE`});if(!t.ok)throw Error(`HTTP ${t.status}`);l(this.labels.deleted),await this.#v()}catch{l(this.labels.saveFailed,`error`)}}}async#A(e,t){if(!e||this._addingToNavigationId)return;let n=this._createdCollectionId===e;this._showItemMenuId=null,this._addingToNavigationId=e,document.removeEventListener(`click`,this.#s);try{await t(e),this.navigationCollectionIds=[...new Set([...this.navigationCollectionIds,e])],n||r(this.labels.addedToNavigation,{label:this.labels.editNavigation,href:a(w)})}catch{l(this.labels.addToNavigationFailed,`error`)}finally{this._addingToNavigationId=null}}#j(e){if(e.type===`link`){if(this._editingLinkId===e.id){this._editingLinkId=null,this._editLinkLabel=``,this._editLinkUrl=``,this._editLinkDescription=``,this.#a?.destroy(),this.#a=null;return}this._editingLinkId=e.id,this._editLinkLabel=e.label??``,this._editLinkUrl=e.url??``,this._editLinkDescription=e.description??``,this.#a?.destroy(),this.#a=null}}async#M(e){let t=this._editLinkLabel.trim(),n=this._editLinkUrl.trim();if(!t||!n){l(this.labels.labelAndUrlRequired,`error`);return}try{let r=this._editLinkDescription.trim()||null,i=await fetch(`/api/collections/directory-items/${e.id}`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify({label:t,url:n,description:r})});if(!i.ok)throw Error(`HTTP ${i.status}`);let a=await i.json();this._items=this._items.map(r=>r.id===e.id?{...r,label:a.label??t,url:a.url??n,description:a.description??null}:r),this._editingLinkId=null,this._editLinkLabel=``,this._editLinkUrl=``,this._editLinkDescription=``,this.#a?.destroy(),this.#a=null,l(this.labels.linkSaved)}catch{l(this.labels.saveFailed,`error`),await this.#v()}}async#N(e){if(await h({message:this.labels.confirmDeleteLink,confirmLabel:this.labels.deleteLink,cancelLabel:this.labels.cancel,tone:`danger`})){this._showItemMenuId=null,document.removeEventListener(`click`,this.#s);try{let t=await fetch(`/api/collections/directory-items/${e.id}`,{method:`DELETE`});if(!t.ok)throw Error(`HTTP ${t.status}`);this._editingLinkId=null,this._editLinkLabel=``,this._editLinkUrl=``,this._editLinkDescription=``,this.#a?.destroy(),this.#a=null,l(this.labels.linkDeleted),this._items=this._items.filter(t=>t.id!==e.id)}catch{l(this.labels.saveFailed,`error`)}}}#P(){let e=e=>e.type===`collection`&&e.collection||e.type===`smart_collection`&&e.smartCollection||e.type===`link`&&e.label&&e.url,t=[],n=!1,r=0;for(let i of this._items)i.type===`divider`?(n=!0,t.push(0)):e(i)&&(n?t[t.length-1]+=1:r+=1);let i=t.length>0,a=Math.max(0,t.length-1),o=i?Math.max(1,a.toString(36).length):0,s=Math.max(2,String(Math.max(0,r-1)).length),c=[],l=-1,u=0;for(let t of this._items)if(t.type===`divider`)l+=1,u=0,c.push(``);else if(e(t)){if(i){let e=Math.max(0,l).toString(36).padStart(o,`0`),t=u.toString(36);c.push(e+t)}else c.push(String(u).padStart(s,`0`));u+=1}else c.push(``);return c}#F(e,t){let n=e.collection;if(!n)return s;let r=u(oe(n.slug)),i=o`
1567
+ <div class="collection-directory-main">
1568
+ <span class="collection-directory-sequence" aria-hidden="true">
1569
+ ${t}
1570
+ </span>
1571
+ <div class="collection-directory-title-row">
1572
+ <a href=${r} class="collection-directory-title-link">
1573
+ <span class="collection-directory-title">${n.title}</span>
1574
+ </a>
1575
+ </div>
1576
+ ${n.description?o`
1577
+ <div class="collection-directory-description prose">
1578
+ ${f(V(n.description,{namespace:n.id}))}
1579
+ </div>
1580
+ `:s}
1581
+ <p class="collection-directory-summary">
1582
+ <span class="collection-directory-meta"
1583
+ >${this.#f(n.threadCount)}</span
1584
+ >
1585
+ <span class="collection-directory-meta-separator" aria-hidden="true"
1586
+ >/</span
1587
+ >
1588
+ <time
1589
+ class="collection-directory-updated"
1590
+ datetime=${H(n.recentActivityAt)}
1591
+ >
1592
+ ${U(n.recentActivityAt)}
1593
+ </time>
1594
+ </p>
1595
+ </div>
1596
+ `;return this._reorderMode?o`
1597
+ <div
1598
+ data-directory-item=${e.id}
1599
+ class="collection-directory-item collection-directory-item-reorder"
1600
+ >
1601
+ <div class="collection-directory-handle" data-drag-handle>
1602
+ <svg
1603
+ xmlns="http://www.w3.org/2000/svg"
1604
+ width="16"
1605
+ height="16"
1606
+ viewBox="0 0 24 24"
1607
+ fill="none"
1608
+ stroke="currentColor"
1609
+ stroke-width="2"
1610
+ stroke-linecap="round"
1611
+ stroke-linejoin="round"
1612
+ >
1613
+ <circle cx="9" cy="12" r="1" />
1614
+ <circle cx="9" cy="5" r="1" />
1615
+ <circle cx="9" cy="19" r="1" />
1616
+ <circle cx="15" cy="12" r="1" />
1617
+ <circle cx="15" cy="5" r="1" />
1618
+ <circle cx="15" cy="19" r="1" />
1619
+ </svg>
1620
+ </div>
1621
+ <div class="collection-directory-reorder-main">${i}</div>
1622
+ </div>
1623
+ `:o`
1624
+ <div
1625
+ class=${_({"group relative":!0,"collection-directory-managed-row":!0,"z-50":this._showItemMenuId===e.id||this._editingLinkId===e.id})}
1626
+ >
1627
+ <div
1628
+ class="collection-directory-item collection-directory-item-manageable"
1629
+ >
1630
+ ${i}
1631
+ </div>
1632
+ ${this.#B(e)}
1633
+ </div>
1634
+ `}#I(e,t){let n=e.smartCollection;if(!n)return s;let r=u(C(n.slug)),i=o`
1635
+ <div class="collection-directory-main">
1636
+ <span class="collection-directory-sequence" aria-hidden="true"
1637
+ >${t}</span
1638
+ >
1639
+ <div class="collection-directory-title-row">
1640
+ <a href=${a(r)} class="collection-directory-title-link">
1641
+ <span class="collection-directory-title"
1642
+ >${n.title}
1643
+ <span
1644
+ class="collection-directory-smart-icon"
1645
+ role="img"
1646
+ aria-label=${this.labels.smartCollectionNoun}
1647
+ title=${this.labels.smartCollectionNoun}
1648
+ >${f(he)}</span
1649
+ ></span
1650
+ >
1651
+ </a>
1652
+ </div>
1653
+ ${n.description?o`
1654
+ <div class="collection-directory-description prose">
1655
+ ${f(V(n.description,{namespace:n.id}))}
1656
+ </div>
1657
+ `:s}
1658
+ <p class="collection-directory-summary">
1659
+ <span class="collection-directory-meta"
1660
+ >${this.#f(n.threadCount)}</span
1661
+ >
1662
+ <span class="collection-directory-meta-separator" aria-hidden="true"
1663
+ >/</span
1664
+ >
1665
+ <time
1666
+ class="collection-directory-updated"
1667
+ datetime=${H(n.recentActivityAt)}
1668
+ >
1669
+ ${U(n.recentActivityAt)}
1670
+ </time>
1671
+ </p>
1672
+ </div>
1673
+ `;return this._reorderMode?o`
1674
+ <div
1675
+ data-directory-item=${e.id}
1676
+ class="collection-directory-item collection-directory-item-reorder"
1677
+ >
1678
+ <div class="collection-directory-handle" data-drag-handle>
1679
+ <svg
1680
+ xmlns="http://www.w3.org/2000/svg"
1681
+ width="16"
1682
+ height="16"
1683
+ viewBox="0 0 24 24"
1684
+ fill="none"
1685
+ stroke="currentColor"
1686
+ stroke-width="2"
1687
+ stroke-linecap="round"
1688
+ stroke-linejoin="round"
1689
+ >
1690
+ <circle cx="9" cy="12" r="1" />
1691
+ <circle cx="9" cy="5" r="1" />
1692
+ <circle cx="9" cy="19" r="1" />
1693
+ <circle cx="15" cy="12" r="1" />
1694
+ <circle cx="15" cy="5" r="1" />
1695
+ <circle cx="15" cy="19" r="1" />
1696
+ </svg>
1697
+ </div>
1698
+ <div class="collection-directory-reorder-main">${i}</div>
1699
+ </div>
1700
+ `:o`
1701
+ <div
1702
+ class=${_({"group relative":!0,"collection-directory-managed-row":!0,"z-50":this._showItemMenuId===e.id})}
1703
+ >
1704
+ <div
1705
+ class="collection-directory-item collection-directory-item-manageable"
1706
+ >
1707
+ ${i}
1708
+ </div>
1709
+ ${this.#B(e)}
1710
+ </div>
1711
+ `}async#L(e){if(this._showItemMenuId=null,document.removeEventListener(`click`,this.#s),await h({message:this.labels.confirmDeleteSmartCollection,confirmLabel:this.labels.deleteSmartCollection,cancelLabel:this.labels.cancel,tone:`danger`}))try{let t=await fetch(`/api/smart-collections/${e.id}`,{method:`DELETE`});if(!t.ok)throw Error(`HTTP ${t.status}`);l(this.labels.smartCollectionDeleted),await this.#v()}catch{l(this.labels.saveFailed,`error`)}}#R(e){return this._editingLinkId===e.id?o`
1712
+ <div
1713
+ class="collections-link-edit card"
1714
+ @click=${e=>e.stopPropagation()}
1715
+ >
1716
+ <form
1717
+ class="grid gap-4"
1718
+ @submit=${t=>{t.preventDefault(),this.#M(e)}}
1719
+ >
1720
+ <div class="field">
1721
+ <label class="label" for=${`collections-link-label-${e.id}`}>
1722
+ ${this.labels.label}
1723
+ </label>
1724
+ <input
1725
+ id=${`collections-link-label-${e.id}`}
1726
+ type="text"
1727
+ class="input"
1728
+ .value=${this._editLinkLabel}
1729
+ @input=${e=>{this._editLinkLabel=e.currentTarget.value}}
1730
+ />
1731
+ </div>
1732
+ <div class="field">
1733
+ <label class="label" for=${`collections-link-url-${e.id}`}>
1734
+ ${this.labels.url}
1735
+ </label>
1736
+ <input
1737
+ id=${`collections-link-url-${e.id}`}
1738
+ type="text"
1739
+ class="input"
1740
+ .value=${this._editLinkUrl}
1741
+ @input=${e=>{this._editLinkUrl=e.currentTarget.value}}
1742
+ />
1743
+ </div>
1744
+ <div class="field">
1745
+ <label class="label"> ${this.labels.linkDescriptionLabel} </label>
1746
+ <div
1747
+ class="settings-tiptap-editor"
1748
+ data-edit-link-desc-editor
1749
+ ></div>
1750
+ </div>
1751
+ <div class="collections-link-edit-actions">
1752
+ <button
1753
+ type="button"
1754
+ class="btn-outline"
1755
+ @click=${()=>this.#j(e)}
1756
+ >
1757
+ ${this.labels.cancel}
1758
+ </button>
1759
+ <button type="submit" class="btn-sm">${this.labels.save}</button>
1760
+ </div>
1761
+ </form>
1762
+ </div>
1763
+ `:s}#z(e,t){if(!e.label||!e.url)return s;let n=a(e.url),r=e.url.startsWith(`http://`)||e.url.startsWith(`https://`),i=o`
1764
+ <div class="collection-directory-main">
1765
+ <span class="collection-directory-sequence" aria-hidden="true">
1766
+ ${t}
1767
+ </span>
1768
+ <div class="collection-directory-title-row">
1769
+ <a
1770
+ href=${n}
1771
+ class="collection-directory-title-link"
1772
+ target=${r?`_blank`:s}
1773
+ rel=${r?`noopener noreferrer`:s}
1774
+ >
1775
+ <span class="collection-directory-title">
1776
+ ${e.label}
1777
+ <span
1778
+ class="collection-directory-title-marker"
1779
+ aria-hidden="true"
1780
+ >
1781
+ <svg
1782
+ xmlns="http://www.w3.org/2000/svg"
1783
+ width="14"
1784
+ height="14"
1785
+ viewBox="0 0 24 24"
1786
+ fill="none"
1787
+ stroke="currentColor"
1788
+ stroke-width="2"
1789
+ stroke-linecap="round"
1790
+ stroke-linejoin="round"
1791
+ >
1792
+ <path
1793
+ d="M10 13a5 5 0 0 0 7.54.54l2.92-2.92a5 5 0 0 0-7.07-7.08L11.7 5.24"
1794
+ />
1795
+ <path
1796
+ d="M14 11a5 5 0 0 0-7.54-.54l-2.92 2.92a5 5 0 0 0 7.07 7.08l1.69-1.7"
1797
+ />
1798
+ </svg>
1799
+ </span>
1800
+ </span>
1801
+ </a>
1802
+ </div>
1803
+ ${e.description?o`
1804
+ <div class="collection-directory-description prose">
1805
+ ${f(V(e.description,{namespace:e.id}))}
1806
+ </div>
1807
+ `:o`
1808
+ <p class="collection-directory-summary">
1809
+ <span class="collection-directory-meta"
1810
+ >${this.labels.linkDescriptionPlaceholder}</span
1811
+ >
1812
+ </p>
1813
+ `}
1814
+ </div>
1815
+ `;return this._reorderMode?o`
1816
+ <div
1817
+ data-directory-item=${e.id}
1818
+ class="collection-directory-item collection-directory-item-reorder"
1819
+ >
1820
+ <div class="collection-directory-handle" data-drag-handle>
1821
+ <svg
1822
+ xmlns="http://www.w3.org/2000/svg"
1823
+ width="16"
1824
+ height="16"
1825
+ viewBox="0 0 24 24"
1826
+ fill="none"
1827
+ stroke="currentColor"
1828
+ stroke-width="2"
1829
+ stroke-linecap="round"
1830
+ stroke-linejoin="round"
1831
+ >
1832
+ <circle cx="9" cy="12" r="1" />
1833
+ <circle cx="9" cy="5" r="1" />
1834
+ <circle cx="9" cy="19" r="1" />
1835
+ <circle cx="15" cy="12" r="1" />
1836
+ <circle cx="15" cy="5" r="1" />
1837
+ <circle cx="15" cy="19" r="1" />
1838
+ </svg>
1839
+ </div>
1840
+ <div class="collection-directory-reorder-main">${i}</div>
1841
+ </div>
1842
+ `:o`
1843
+ <div
1844
+ class=${_({"group relative":!0,"collection-directory-managed-row":!0,"z-50":this._showItemMenuId===e.id||this._editingLinkId===e.id})}
1845
+ >
1846
+ <div
1847
+ class="collection-directory-item collection-directory-item-link collection-directory-item-manageable"
1848
+ >
1849
+ ${i}
1850
+ </div>
1851
+ ${this.#B(e)} ${this.#R(e)}
1852
+ </div>
1853
+ `}#B(e){let t=e.collection,n=e.smartCollection,r=e.type===`link`&&!!e.label&&!!e.url;if(!t&&!n&&!r)return s;let i=this._showItemMenuId===e.id;return o`
1854
+ <div class="collection-directory-item-menu">
1855
+ <button
1856
+ type="button"
1857
+ class="collections-page-icon-button"
1858
+ aria-label=${this.labels.moreActions}
1859
+ @click=${t=>{t.preventDefault(),t.stopPropagation(),i?(this._showItemMenuId=null,document.removeEventListener(`click`,this.#s)):(this._showItemMenuId=e.id,setTimeout(()=>{document.addEventListener(`click`,this.#s)}))}}
1860
+ >
1861
+ <svg
1862
+ xmlns="http://www.w3.org/2000/svg"
1863
+ width="14"
1864
+ height="14"
1865
+ viewBox="0 0 24 24"
1866
+ fill="currentColor"
1867
+ >
1868
+ <circle cx="5" cy="12" r="2" />
1869
+ <circle cx="12" cy="12" r="2" />
1870
+ <circle cx="19" cy="12" r="2" />
1871
+ </svg>
1872
+ </button>
1873
+ ${i?o`
1874
+ <div
1875
+ class="collections-page-menu"
1876
+ @click=${e=>e.stopPropagation()}
1877
+ >
1878
+ ${n?o`
1879
+ <!-- Opens the dialog, not an editor page: creating and
1880
+ editing a smart collection are one surface. There is
1881
+ deliberately no "Remove from Collections" — a
1882
+ directory row is only a position, and deleting it
1883
+ would move the entry to the end rather than hide it,
1884
+ so the menu item would not do what it says. -->
1885
+ <button
1886
+ type="button"
1887
+ class="collections-page-menu-item"
1888
+ @click=${()=>{this._showItemMenuId=null,document.removeEventListener(`click`,this.#s),Q({smartCollectionId:n.id}).then(e=>{e&&this.#v()})}}
1889
+ >
1890
+ ${this.labels.edit}
1891
+ </button>
1892
+ ${this.navigationCollectionIds.includes(n.id)?o`
1893
+ <a
1894
+ href=${a(w)}
1895
+ class="collections-page-menu-item"
1896
+ >
1897
+ ${this.labels.editNavigation}
1898
+ </a>
1899
+ `:o`
1900
+ <button
1901
+ type="button"
1902
+ class="collections-page-menu-item"
1903
+ ?disabled=${this._addingToNavigationId===n.id}
1904
+ @click=${()=>void this.#A(n.id,B)}
1905
+ >
1906
+ ${this._addingToNavigationId===n.id?this.labels.addingToNavigation:this.labels.addToNavigation}
1907
+ </button>
1908
+ `}
1909
+ <button
1910
+ type="button"
1911
+ class="collections-page-menu-item collections-page-menu-item-danger"
1912
+ @click=${()=>void this.#L(n)}
1913
+ >
1914
+ ${this.labels.deleteSmartCollection}
1915
+ </button>
1916
+ `:t?o`
1917
+ <button
1918
+ type="button"
1919
+ class="collections-page-menu-item"
1920
+ @click=${()=>void this.#u(t.id)}
1921
+ >
1922
+ ${this.labels.edit}
1923
+ </button>
1924
+ ${this.navigationCollectionIds.includes(t.id)?o`
1925
+ <a
1926
+ href=${a(w)}
1927
+ class="collections-page-menu-item"
1928
+ >
1929
+ ${this.labels.editNavigation}
1930
+ </a>
1931
+ `:o`
1932
+ <button
1933
+ type="button"
1934
+ class="collections-page-menu-item"
1935
+ ?disabled=${this._addingToNavigationId===t.id}
1936
+ @click=${()=>void this.#A(t.id,z)}
1937
+ >
1938
+ ${this._addingToNavigationId===t.id?this.labels.addingToNavigation:this.labels.addToNavigation}
1939
+ </button>
1940
+ `}
1941
+ <button
1942
+ type="button"
1943
+ class="collections-page-menu-item collections-page-menu-item-danger"
1944
+ @click=${()=>this.#k(t)}
1945
+ >
1946
+ ${this.labels.deleteCollection}
1947
+ </button>
1948
+ `:o`
1949
+ <button
1950
+ type="button"
1951
+ class="collections-page-menu-item"
1952
+ @click=${()=>{this._showItemMenuId=null,document.removeEventListener(`click`,this.#s),this.#j(e)}}
1953
+ >
1954
+ ${this.labels.edit}
1955
+ </button>
1956
+ <button
1957
+ type="button"
1958
+ class="collections-page-menu-item collections-page-menu-item-danger"
1959
+ @click=${()=>this.#N(e)}
1960
+ >
1961
+ ${this.labels.deleteLink}
1962
+ </button>
1963
+ `}
1964
+ </div>
1965
+ `:s}
1966
+ </div>
1967
+ `}#V(e,t){if(this._reorderMode)return o`
1968
+ <div
1969
+ data-directory-item=${e.id}
1970
+ class="collection-directory-divider-row"
1971
+ >
1972
+ <div class="collection-directory-handle" data-drag-handle>
1973
+ <svg
1974
+ xmlns="http://www.w3.org/2000/svg"
1975
+ width="16"
1976
+ height="16"
1977
+ viewBox="0 0 24 24"
1978
+ fill="none"
1979
+ stroke="currentColor"
1980
+ stroke-width="2"
1981
+ stroke-linecap="round"
1982
+ stroke-linejoin="round"
1983
+ >
1984
+ <circle cx="9" cy="12" r="1" />
1985
+ <circle cx="9" cy="5" r="1" />
1986
+ <circle cx="9" cy="19" r="1" />
1987
+ <circle cx="15" cy="12" r="1" />
1988
+ <circle cx="15" cy="5" r="1" />
1989
+ <circle cx="15" cy="19" r="1" />
1990
+ </svg>
1991
+ </div>
1992
+ <div class="collection-directory-divider-body">
1993
+ <input
1994
+ type="text"
1995
+ class="collection-directory-divider-input"
1996
+ data-divider-input-for=${e.id}
1997
+ placeholder=${this.labels.dividerLabelPlaceholder}
1998
+ .value=${e.label??``}
1999
+ aria-label=${this.labels.dividerLabelPlaceholder}
2000
+ @blur=${t=>this.#O(e.id,t.currentTarget.value)}
2001
+ @keydown=${t=>{if(t.isComposing||t.keyCode===229)return;let n=t.currentTarget;t.key===`Enter`&&(t.preventDefault(),n.blur()),t.key===`Escape`&&(n.value=e.label??``,n.blur())}}
2002
+ />
2003
+ <hr class="collection-directory-divider-line" />
2004
+ </div>
2005
+ <button
2006
+ type="button"
2007
+ class="collections-page-icon-button"
2008
+ title=${this.labels.deleteDivider}
2009
+ aria-label=${this.labels.deleteDivider}
2010
+ @click=${()=>this.#D(e.id)}
2011
+ >
2012
+ <svg
2013
+ xmlns="http://www.w3.org/2000/svg"
2014
+ width="12"
2015
+ height="12"
2016
+ viewBox="0 0 24 24"
2017
+ fill="none"
2018
+ stroke="currentColor"
2019
+ stroke-width="2"
2020
+ stroke-linecap="round"
2021
+ stroke-linejoin="round"
2022
+ >
2023
+ <path d="M18 6 6 18" />
2024
+ <path d="m6 6 12 12" />
2025
+ </svg>
2026
+ </button>
2027
+ </div>
2028
+ `;let n=!!e.label,r=Te(this._items,t);return o`
2029
+ <div class="collection-directory-divider">
2030
+ <div
2031
+ class="collection-directory-divider-row"
2032
+ aria-hidden=${n?s:`true`}
2033
+ >
2034
+ ${n?o`
2035
+ ${r?o`
2036
+ <a
2037
+ href=${u(oe(r.slugExpression))}
2038
+ class="collection-directory-divider-link collection-directory-divider-text"
2039
+ >
2040
+ ${e.label}
2041
+ </a>
2042
+ `:o`
2043
+ <span class="collection-directory-divider-text">
2044
+ ${e.label}
2045
+ </span>
2046
+ `}
2047
+ <hr class="collection-directory-divider-line" />
2048
+ `:o`<hr class="collection-directory-divider-line" />`}
2049
+ </div>
2050
+ </div>
2051
+ `}#H(){return this._showLinkForm?o`
2052
+ <div class="collections-link-create card">
2053
+ <form
2054
+ class="grid gap-4"
2055
+ @submit=${e=>{e.preventDefault(),this.#E()}}
2056
+ >
2057
+ <header class="grid gap-1">
2058
+ <h2 class="text-base font-semibold">${this.labels.newLink}</h2>
2059
+ <p class="text-sm text-muted-foreground">
2060
+ ${this.labels.addLinkDescription}
2061
+ </p>
2062
+ </header>
2063
+ <div class="field">
2064
+ <label class="label" for="collections-new-link-label">
2065
+ ${this.labels.label}
2066
+ </label>
2067
+ <input
2068
+ id="collections-new-link-label"
2069
+ type="text"
2070
+ class="input"
2071
+ data-link-form-input="label"
2072
+ placeholder=${this.labels.linkLabelPlaceholder}
2073
+ .value=${this._newLinkLabel}
2074
+ @input=${e=>{this._newLinkLabel=e.currentTarget.value}}
2075
+ />
2076
+ </div>
2077
+ <div class="field">
2078
+ <label class="label" for="collections-new-link-url">
2079
+ ${this.labels.url}
2080
+ </label>
2081
+ <input
2082
+ id="collections-new-link-url"
2083
+ type="text"
2084
+ class="input"
2085
+ placeholder=${this.labels.linkUrlPlaceholder}
2086
+ .value=${this._newLinkUrl}
2087
+ @input=${e=>{this._newLinkUrl=e.currentTarget.value}}
2088
+ />
2089
+ </div>
2090
+ <div class="field">
2091
+ <label class="label"> ${this.labels.linkDescriptionLabel} </label>
2092
+ <div class="settings-tiptap-editor" data-new-link-desc-editor></div>
2093
+ </div>
2094
+ <div class="collections-link-edit-actions">
2095
+ <button
2096
+ type="button"
2097
+ class="btn-outline"
2098
+ @click=${()=>{this._showLinkForm=!1,this._newLinkLabel=``,this._newLinkUrl=``,this._newLinkDescription=``,this.#i?.destroy(),this.#i=null}}
2099
+ >
2100
+ ${this.labels.cancel}
2101
+ </button>
2102
+ <button type="submit" class="btn-sm" ?disabled=${this._addingLink}>
2103
+ ${this.labels.addLink}
2104
+ </button>
2105
+ </div>
2106
+ </form>
2107
+ </div>
2108
+ `:s}#U(){if(!this._createdCollectionId)return s;let e=this._items.find(e=>e.collection?.id===this._createdCollectionId)?.collection;if(!e)return s;let t=this.navigationCollectionIds.includes(e.id);return o`
2109
+ <section
2110
+ class="collection-created-notice"
2111
+ role="status"
2112
+ aria-labelledby="collection-created-notice-title"
2113
+ >
2114
+ <p
2115
+ id="collection-created-notice-title"
2116
+ class="collection-created-notice-message"
2117
+ >
2118
+ ${t?this.labels.addedToNavigation:this.labels.formLabels.createdLabel}
2119
+ </p>
2120
+ <div class="collection-created-notice-actions">
2121
+ ${t?o`
2122
+ <a
2123
+ href=${a(w)}
2124
+ class="collection-created-notice-action collection-created-notice-action-primary"
2125
+ >
2126
+ ${this.labels.editNavigation}
2127
+ </a>
2128
+ `:o`
2129
+ <button
2130
+ type="button"
2131
+ class="collection-created-notice-action collection-created-notice-action-primary"
2132
+ ?disabled=${this._addingToNavigationId===e.id}
2133
+ @click=${()=>void this.#A(e.id,z)}
2134
+ >
2135
+ ${this._addingToNavigationId===e.id?this.labels.addingToNavigation:this.labels.addToNavigation}
2136
+ </button>
2137
+ `}
2138
+ <button
2139
+ type="button"
2140
+ class="collection-created-notice-dismiss"
2141
+ aria-label=${this.labels.notNow}
2142
+ title=${this.labels.notNow}
2143
+ @click=${()=>{this._createdCollectionId=null}}
2144
+ >
2145
+ <svg
2146
+ xmlns="http://www.w3.org/2000/svg"
2147
+ width="14"
2148
+ height="14"
2149
+ viewBox="0 0 24 24"
2150
+ fill="none"
2151
+ stroke="currentColor"
2152
+ stroke-width="2"
2153
+ stroke-linecap="round"
2154
+ stroke-linejoin="round"
2155
+ aria-hidden="true"
2156
+ >
2157
+ <path d="M18 6 6 18" />
2158
+ <path d="m6 6 12 12" />
2159
+ </svg>
2160
+ </button>
2161
+ </div>
2162
+ </section>
2163
+ `}render(){return o`
2164
+ ${this.#U()} ${this.#H()}
2165
+ ${this.#d()?o`
2166
+ <div id="collections-manager-list" class="collection-directory">
2167
+ ${(()=>{let e=this.#P();return this._items.map((t,n)=>t.type===`collection`?this.#F(t,e[n]):t.type===`smart_collection`?this.#I(t,e[n]):t.type===`link`?this.#z(t,e[n]):this.#V(t,n))})()}
2168
+ </div>
2169
+ `:o`<p class="text-muted-foreground">${this.labels.emptyState}</p>`}
2170
+ `}};customElements.define(`jant-collections-manager`,vt);var yt=e=>{if(!e)return{edit:``,addToNavigation:``,addingToNavigation:``,addedToNavigation:``,editNavigation:``,addToNavigationFailed:``,moreActions:``,deleteCollection:``,confirmDelete:``,cancel:``,saveFailed:``,deleted:``};try{return JSON.parse(e)}catch{return{edit:``,addToNavigation:``,addingToNavigation:``,addedToNavigation:``,editNavigation:``,addToNavigationFailed:``,moreActions:``,deleteCollection:``,confirmDelete:``,cancel:``,saveFailed:``,deleted:``}}};document.querySelectorAll(`[data-collection-page-actions]`).forEach(e=>{if(e.dataset.collectionPageActionsInitialized===`true`)return;let t=yt(e.dataset.collectionPageLabels),n=e.dataset.collectionId,i=e.dataset.collectionPageRedirectUrl||S(),a=e.querySelector(`[data-collection-page-action='toggle-menu']`),o=e.querySelector(`[data-collection-page-menu]`),s=e.querySelector(`[data-collection-page-action='add-to-navigation']`),c=e.querySelector(`[data-collection-page-edit-navigation]`);if(!n||!a||!o)return;let u=(e=!1)=>{o.hidden||(o.hidden=!0,a.setAttribute(`aria-expanded`,`false`),e&&a.focus())},d=(e=!1)=>{o.hidden=!1,a.setAttribute(`aria-expanded`,`true`),e&&o.querySelector(`[role='menuitem']`)?.focus()},f=async()=>{u(!1);let{changed:e,collection:t}=await F({collectionId:n});if(!e)return;let r=t?.slug?window.location.pathname.replace(/[^/]*$/,t.slug):null;if(r&&r!==window.location.pathname){window.location.href=`${r}${window.location.search}`;return}window.location.reload()},p=async()=>{if(u(!1),await h({message:t.confirmDelete,confirmLabel:t.deleteCollection,cancelLabel:t.cancel,tone:`danger`}))try{let e=await fetch(`/api/collections/${n}`,{method:`DELETE`});if(!e.ok)throw Error(`HTTP ${e.status}`);l(t.deleted),window.location.href=i}catch{l(t.saveFailed,`error`)}},m=async()=>{if(!s||s.disabled)return;u(!1);let i=s.querySelector(`.collections-page-menu-item-label`);s.disabled=!0,i&&(i.textContent=t.addingToNavigation);try{await z(n),s.hidden=!0,c&&(c.hidden=!1),e.dataset.collectionInNavigation=`true`,r(t.addedToNavigation,{label:t.editNavigation,href:c?.getAttribute(`href`)??`/settings/navigation`})}catch{l(t.addToNavigationFailed,`error`)}finally{s.disabled=!1,i&&(i.textContent=t.addToNavigation)}};a.addEventListener(`click`,e=>{if(e.preventDefault(),e.stopPropagation(),o.hidden){d(!1);return}u(!1)}),a.addEventListener(`keydown`,e=>{(e.key===`Enter`||e.key===` `||e.key===`ArrowDown`)&&(e.preventDefault(),o.hidden?d(!0):u(!1)),e.key===`Escape`&&(e.preventDefault(),u(!0))}),o.addEventListener(`keydown`,e=>{e.key===`Escape`&&(e.preventDefault(),u(!0))}),e.addEventListener(`click`,t=>{let n=t.target;if(!n)return;let r=n.closest(`[data-collection-page-action]`);if(!r||!e.contains(r))return;let i=r.dataset.collectionPageAction;i===`edit`&&(t.preventDefault(),f()),i===`delete`&&(t.preventDefault(),p()),i===`add-to-navigation`&&(t.preventDefault(),m())}),document.addEventListener(`click`,t=>{t.target instanceof Node&&(e.contains(t.target)||u(!1))}),e.dataset.collectionPageActionsInitialized=`true`});var bt=e=>{let t={addToNavigation:``,addingToNavigation:``,addedToNavigation:``,editNavigation:``,addToNavigationFailed:``,confirmDelete:``,deleteCollection:``,cancel:``,saveFailed:``,deleted:``};if(!e)return t;try{return{...t,...JSON.parse(e)}}catch{return t}};document.querySelectorAll(`[data-smart-collection-page-actions]`).forEach(e=>{if(e.dataset.smartCollectionPageActionsInitialized===`true`)return;let t=bt(e.dataset.collectionPageLabels),n=e.dataset.smartCollectionId,i=e.dataset.collectionPageRedirectUrl||S(),a=e.querySelector(`[data-collection-page-action='toggle-menu']`),o=e.querySelector(`[data-collection-page-menu]`),s=e.querySelector(`[data-collection-page-action='add-to-navigation']`),c=e.querySelector(`[data-collection-page-edit-navigation]`);if(!n||!a||!o)return;let u=(e=!1)=>{o.hidden||(o.hidden=!0,a.setAttribute(`aria-expanded`,`false`),e&&a.focus())},d=(e=!1)=>{o.hidden=!1,a.setAttribute(`aria-expanded`,`true`),e&&o.querySelector(`[role='menuitem']`)?.focus()},f=async()=>{u(!1),await Q({smartCollectionId:n})&&window.location.reload()},p=async()=>{if(u(!1),await h({message:t.confirmDelete,confirmLabel:t.deleteCollection,cancelLabel:t.cancel,tone:`danger`}))try{let e=await fetch(`/api/smart-collections/${n}`,{method:`DELETE`});if(!e.ok)throw Error(`HTTP ${e.status}`);l(t.deleted),window.location.href=i}catch{l(t.saveFailed,`error`)}},m=async()=>{if(!s||s.disabled)return;u(!1);let i=s.querySelector(`.collections-page-menu-item-label`);s.disabled=!0,i&&(i.textContent=t.addingToNavigation);try{await B(n),s.hidden=!0,c&&(c.hidden=!1),e.dataset.collectionInNavigation=`true`,r(t.addedToNavigation,{label:t.editNavigation,href:c?.getAttribute(`href`)??`/settings/navigation`})}catch{l(t.addToNavigationFailed,`error`)}finally{s.disabled=!1,i&&(i.textContent=t.addToNavigation)}};a.addEventListener(`click`,e=>{e.preventDefault(),e.stopPropagation(),o.hidden?d(!1):u(!1)}),a.addEventListener(`keydown`,e=>{(e.key===`Enter`||e.key===` `||e.key===`ArrowDown`)&&(e.preventDefault(),o.hidden?d(!0):u(!1)),e.key===`Escape`&&(e.preventDefault(),u(!0))}),o.addEventListener(`keydown`,e=>{e.key===`Escape`&&(e.preventDefault(),u(!0))}),e.addEventListener(`click`,t=>{let n=t.target?.closest(`[data-collection-page-action]`);if(!n||!e.contains(n))return;let r=n.dataset.collectionPageAction;r===`edit`&&(t.preventDefault(),f()),r===`delete`&&(t.preventDefault(),p()),r===`add-to-navigation`&&(t.preventDefault(),m())}),document.addEventListener(`click`,t=>{t.target instanceof Node&&(e.contains(t.target)||u(!1))}),e.dataset.smartCollectionPageActionsInitialized=`true`});var xt=6,$=8;function St(e=document){e.querySelectorAll(`[data-custom-url-actions]`).forEach(e=>{if(e.dataset.customUrlActionsInitialized===`true`)return;let t=e.querySelector(`[data-custom-url-action='toggle-menu']`),n=e.querySelector(`[data-custom-url-menu]`);if(!(t instanceof HTMLButtonElement)||!n)return;let r=typeof n.showPopover==`function`&&n.hasAttribute(`popover`),i=()=>{let e=t.getBoundingClientRect(),{width:r,height:i}=n.getBoundingClientRect(),a=e.bottom+xt,o=e.top-xt-i,s=a+i<=window.innerHeight-$||o<$?a:o;n.style.top=`${s}px`,n.style.left=`${Math.max($,Math.min(e.right-r,window.innerWidth-$-r))}px`},a=(e=!1)=>{n.hidden||(r&&(window.removeEventListener(`resize`,i),window.removeEventListener(`scroll`,i,!0),n.matches(`:popover-open`)&&n.hidePopover()),n.hidden=!0,t.setAttribute(`aria-expanded`,`false`),e&&t.focus())},o=(a=!1)=>{document.dispatchEvent(new CustomEvent(`jant:custom-url-menu`,{detail:{source:e}})),n.hidden=!1,r&&(n.matches(`:popover-open`)||n.showPopover(),i(),window.addEventListener(`resize`,i),window.addEventListener(`scroll`,i,!0)),t.setAttribute(`aria-expanded`,`true`),a&&n.querySelector(`[role='menuitem']`)?.focus()};t.addEventListener(`click`,e=>{if(e.preventDefault(),e.stopPropagation(),n.hidden){o(!1);return}a(!1)}),t.addEventListener(`keydown`,e=>{if(e.key===`Enter`||e.key===` `||e.key===`ArrowDown`){e.preventDefault(),n.hidden?o(!0):a(!1);return}e.key===`Escape`&&(e.preventDefault(),a(!0))}),n.addEventListener(`keydown`,e=>{e.key===`Escape`&&(e.preventDefault(),a(!0))}),e.addEventListener(`click`,t=>{let n=t.target;if(!n)return;let r=n.closest(`[data-custom-url-action]`);r&&e.contains(r)&&r.dataset.customUrlAction===`delete`&&a(!1)}),document.addEventListener(`click`,e=>{e.target instanceof Node&&(t.contains(e.target)||n.contains(e.target)||a(!1))}),document.addEventListener(`jant:custom-url-menu`,t=>{t.detail?.source!==e&&a(!1)}),e.dataset.customUrlActionsInitialized=`true`})}St();