@jant/core 0.6.14 → 0.6.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/commands/import-site.js +88 -13
- package/bin/commands/migrate.js +55 -0
- package/bin/commands/posts/rebuild-html.js +184 -0
- package/bin/commands/site/snapshot/import.js +14 -10
- package/bin/lib/d1-query.js +23 -5
- package/bin/lib/migration-runner.js +29 -7
- package/bin/lib/node-database.js +32 -0
- package/bin/lib/site-snapshot.js +347 -46
- package/bin/lib/sql-export.js +1 -1
- package/bin/lib/thread-collection-migration.js +326 -0
- package/dist/app-C75Zc8dD.js +6 -0
- package/dist/{app-2i7-WQHg.js → app-C7_4oab9.js} +7774 -6425
- package/dist/client/.vite/manifest.json +8 -8
- package/dist/client/_assets/chunks/{url-pLre2DM_.js → url-CU9pEbk5.js} +1 -1
- package/dist/client/_assets/{client-BvID5ucz.js → client-Bq0vre8Y.js} +59 -38
- package/dist/client/_assets/client-D3VZyG4L.css +2 -0
- package/dist/client/_assets/client-auth-F2rb9WfF.js +5571 -0
- package/dist/{env-OHRKGcMj.js → env-BPYViDJJ.js} +1 -1
- package/dist/{export-DWn149b7.js → export-Dl5KCiEs.js} +1348 -128
- package/dist/{github-api-BgSiE71w.js → github-api-BNF35Lkx.js} +1 -1
- package/dist/{github-app-BbklkFmU.js → github-app-DdiD-bC4.js} +1 -1
- package/dist/{github-sync-C0zyF6XS.js → github-sync-Bqg62IvV.js} +3 -3
- package/dist/{github-sync-Ckk0sJxK.js → github-sync-HdK2EgvJ.js} +3 -3
- package/dist/index.js +5 -5
- package/dist/node.js +7 -7
- package/dist/{url-BMYO-Zlt.js → url-CbLAtlZe.js} +517 -12
- package/package.json +11 -10
- package/src/__tests__/bin/posts-rebuild-html.test.ts +137 -0
- package/src/__tests__/dev-navigation-defaults.test.ts +22 -0
- package/src/__tests__/export-hugo-build.test.ts +63 -4
- package/src/__tests__/export-import-roundtrip.test.ts +6 -4
- package/src/__tests__/export-service.test.ts +142 -9
- package/src/__tests__/helpers/app.ts +3 -0
- package/src/__tests__/helpers/export-fixtures.ts +2 -0
- package/src/__tests__/import-site-command.test.ts +65 -0
- package/src/__tests__/mise-config.test.ts +22 -0
- package/src/__tests__/vite-config.test.ts +45 -0
- package/src/app.tsx +16 -3
- package/src/client/__tests__/collection-created-notice.test.ts +36 -0
- package/src/client/__tests__/collection-form-bridge.test.ts +10 -1
- package/src/client/__tests__/collection-page-actions.test.ts +71 -2
- package/src/client/__tests__/compose-bridge.test.ts +316 -2
- package/src/client/__tests__/compose-shortcuts.test.ts +20 -0
- package/src/client/__tests__/feed-video-player.test.ts +16 -1
- package/src/client/__tests__/footnote-rail.test.ts +472 -0
- package/src/client/__tests__/hydrate-partial.test.ts +3 -0
- package/src/client/__tests__/toast.test.ts +82 -1
- package/src/client/collection-created-notice.ts +66 -0
- package/src/client/collection-form-bridge.ts +17 -0
- package/src/client/collection-navigation.ts +44 -0
- package/src/client/collection-page-actions.ts +57 -1
- package/src/client/components/__tests__/compose-format-convert.test.ts +0 -19
- package/src/client/components/__tests__/jant-collection-directory.test.ts +155 -6
- package/src/client/components/__tests__/jant-command-palette.test.ts +51 -0
- package/src/client/components/__tests__/jant-compose-dialog.test.ts +2268 -206
- package/src/client/components/__tests__/jant-compose-editor.test.ts +147 -59
- package/src/client/components/__tests__/jant-compose-fullscreen.test.ts +114 -64
- package/src/client/components/__tests__/jant-config-editor.test.ts +405 -0
- package/src/client/components/__tests__/jant-media-lightbox.test.ts +121 -0
- package/src/client/components/__tests__/jant-nav-manager.test.ts +538 -2
- package/src/client/components/__tests__/jant-post-form.test.ts +2 -2
- package/src/client/components/__tests__/jant-post-menu.test.ts +47 -5
- package/src/client/components/__tests__/jant-settings-avatar.test.ts +2 -2
- package/src/client/components/__tests__/jant-settings-general.test.ts +3 -3
- package/src/client/components/collection-manager-types.ts +9 -3
- package/src/client/components/compose-format-convert.ts +5 -1
- package/src/client/components/compose-types.ts +55 -3
- package/src/client/components/jant-collection-directory.ts +165 -30
- package/src/client/components/jant-command-palette.ts +14 -7
- package/src/client/components/jant-compose-dialog.ts +1542 -694
- package/src/client/components/jant-compose-editor.ts +237 -99
- package/src/client/components/jant-compose-fullscreen.ts +27 -9
- package/src/client/components/jant-config-editor.ts +722 -0
- package/src/client/components/jant-media-lightbox.ts +100 -18
- package/src/client/components/jant-nav-manager.ts +1283 -54
- package/src/client/components/jant-post-form.ts +3 -3
- package/src/client/components/jant-post-menu.ts +177 -95
- package/src/client/components/nav-manager-types.ts +51 -2
- package/src/client/components/post-form-types.ts +1 -1
- package/src/client/compose-bridge.ts +147 -123
- package/src/client/compose-launch.ts +13 -0
- package/src/client/compose-shortcuts.ts +5 -1
- package/src/client/feed-video-player.ts +62 -2
- package/src/client/footnote-rail.ts +478 -0
- package/src/client/hydrate-partial.ts +2 -0
- package/src/client/media-lightbox-events.ts +63 -0
- package/src/client/post-refresh.ts +135 -0
- package/src/client/site-header-fragment.ts +38 -0
- package/src/client/tiptap/__tests__/blockquote-editing.test.ts +201 -0
- package/src/client/tiptap/__tests__/clear-formatting.test.ts +168 -0
- package/src/client/tiptap/__tests__/link-input-rules.test.ts +121 -0
- package/src/client/tiptap/__tests__/list-editing.test.ts +447 -0
- package/src/client/tiptap/__tests__/markdown-clipboard.test.ts +727 -4
- package/src/client/tiptap/__tests__/table-controls.test.ts +263 -0
- package/src/client/tiptap/__tests__/table-size-picker.test.ts +179 -0
- package/src/client/tiptap/bubble-menu.ts +88 -10
- package/src/client/tiptap/continuous-lists.ts +102 -0
- package/src/client/tiptap/create-editor.ts +3 -0
- package/src/client/tiptap/extensions.ts +14 -5
- package/src/client/tiptap/link-input-rules.ts +4 -4
- package/src/client/tiptap/markdown-clipboard.ts +608 -11
- package/src/client/tiptap/slash-commands.ts +8 -1
- package/src/client/tiptap/structural-keymap.ts +211 -0
- package/src/client/tiptap/tab-indent.ts +8 -22
- package/src/client/tiptap/table-control-labels.ts +30 -0
- package/src/client/tiptap/table-controls.ts +537 -0
- package/src/client/tiptap/table-size-picker.ts +254 -0
- package/src/client/toast.ts +133 -39
- package/src/client-auth.ts +1 -0
- package/src/client.ts +1 -0
- package/src/db/__tests__/backfill-thread-activity.test.ts +234 -0
- package/src/db/__tests__/d1-query.test.ts +43 -1
- package/src/db/__tests__/migration-runner.test.ts +63 -0
- package/src/db/__tests__/migrations.test.ts +469 -0
- package/src/db/__tests__/thread-activity.test.ts +113 -0
- package/src/db/__tests__/thread-collection-migration.test.ts +364 -0
- package/src/db/backfills/0005_split_thread_activity_from_quiet_replies.sql +68 -0
- package/src/db/migrations/0027_old_blue_blade.sql +39 -0
- package/src/db/migrations/0028_superb_post.sql +2 -0
- package/src/db/migrations/0029_boring_magma.sql +1 -0
- package/src/db/migrations/0030_typical_vivisector.sql +50 -0
- package/src/db/migrations/0031_many_ego.sql +3 -0
- package/src/db/migrations/meta/0027_snapshot.json +2511 -0
- package/src/db/migrations/meta/0028_snapshot.json +2511 -0
- package/src/db/migrations/meta/0029_snapshot.json +2519 -0
- package/src/db/migrations/meta/0030_snapshot.json +2541 -0
- package/src/db/migrations/meta/0031_snapshot.json +2562 -0
- package/src/db/migrations/meta/_journal.json +35 -0
- package/src/db/migrations/pg/0025_moaning_epoch.sql +39 -0
- package/src/db/migrations/pg/0026_talented_killer_shrike.sql +2 -0
- package/src/db/migrations/pg/0027_short_cannonball.sql +1 -0
- package/src/db/migrations/pg/0028_perfect_sharon_carter.sql +27 -0
- package/src/db/migrations/pg/0029_rare_hairball.sql +3 -0
- package/src/db/migrations/pg/meta/0025_snapshot.json +3204 -0
- package/src/db/migrations/pg/meta/0026_snapshot.json +3204 -0
- package/src/db/migrations/pg/meta/0027_snapshot.json +3211 -0
- package/src/db/migrations/pg/meta/0028_snapshot.json +3248 -0
- package/src/db/migrations/pg/meta/0029_snapshot.json +3289 -0
- package/src/db/migrations/pg/meta/_journal.json +35 -0
- package/src/db/pg/schema.ts +46 -20
- package/src/db/rehearsal-fixtures/demo-current.json +39 -4
- package/src/db/rehearsal-fixtures/demo-current.sql +121 -6
- package/src/db/schema.ts +48 -20
- package/src/db/thread-activity.ts +101 -0
- package/src/i18n/__tests__/detect.test.ts +8 -2
- package/src/i18n/detect.ts +14 -5
- package/src/i18n/locales/public/en.po +222 -51
- package/src/i18n/locales/public/en.ts +1 -1
- package/src/i18n/locales/public/zh-Hans.po +216 -45
- package/src/i18n/locales/public/zh-Hans.ts +1 -1
- package/src/i18n/locales/public/zh-Hant.po +216 -45
- package/src/i18n/locales/public/zh-Hant.ts +1 -1
- package/src/i18n/locales/settings/en.po +513 -10
- package/src/i18n/locales/settings/en.ts +1 -1
- package/src/i18n/locales/settings/zh-Hans.po +515 -12
- package/src/i18n/locales/settings/zh-Hans.ts +1 -1
- package/src/i18n/locales/settings/zh-Hant.po +515 -12
- package/src/i18n/locales/settings/zh-Hant.ts +1 -1
- package/src/lib/__tests__/api-settings.test.ts +299 -0
- package/src/lib/__tests__/constants.test.ts +5 -0
- package/src/lib/__tests__/feed-policy.test.ts +25 -0
- package/src/lib/__tests__/feed.test.ts +168 -0
- package/src/lib/__tests__/footnotes-upgrade.test.ts +181 -0
- package/src/lib/__tests__/markdown-roundtrip-embed.test.ts +61 -0
- package/src/lib/__tests__/markdown-to-tiptap.test.ts +32 -4
- package/src/lib/__tests__/markdown.test.ts +24 -6
- package/src/lib/__tests__/navigation.test.ts +59 -2
- package/src/lib/__tests__/post-body-html.test.ts +176 -0
- package/src/lib/__tests__/post-display.test.ts +64 -0
- package/src/lib/__tests__/resolve-config.test.ts +113 -1
- package/src/lib/__tests__/slug.test.ts +18 -0
- package/src/lib/__tests__/summary.test.ts +82 -0
- package/src/lib/__tests__/timeline.test.ts +109 -70
- package/src/lib/__tests__/timezones.test.ts +31 -3
- package/src/lib/__tests__/tiptap-render.test.ts +268 -9
- package/src/lib/__tests__/tiptap-to-markdown.test.ts +6 -0
- package/src/lib/__tests__/translit.test.ts +87 -0
- package/src/lib/__tests__/url.test.ts +53 -0
- package/src/lib/__tests__/view.test.ts +53 -0
- package/src/lib/__tests__/worker-response-cache.test.ts +18 -1
- package/src/lib/api-settings.ts +239 -12
- package/src/lib/collection-sort.ts +7 -5
- package/src/lib/constants.ts +2 -0
- package/src/lib/feed-path.ts +25 -0
- package/src/lib/feed-policy.ts +64 -0
- package/src/lib/feed.ts +113 -11
- package/src/lib/footnotes.ts +264 -0
- package/src/lib/github-sync-site-config.ts +2 -0
- package/src/lib/hugo-markdown.ts +15 -3
- package/src/lib/jant-branding.ts +1 -0
- package/src/lib/link-preview.ts +25 -0
- package/src/lib/markdown-manager.ts +193 -5
- package/src/lib/markdown.ts +10 -3
- package/src/lib/navigation.ts +16 -3
- package/src/lib/post-body-html.ts +131 -0
- package/src/lib/post-display.ts +47 -8
- package/src/lib/render.tsx +9 -2
- package/src/lib/resolve-config.ts +100 -16
- package/src/lib/schemas.ts +133 -1
- package/src/lib/settings-paths.ts +5 -0
- package/src/lib/site-skill.ts +78 -0
- package/src/lib/summary.ts +16 -5
- package/src/lib/timeline.ts +137 -131
- package/src/lib/timezones.ts +54 -14
- package/src/lib/tiptap-render.ts +359 -83
- package/src/lib/translit.ts +288 -0
- package/src/lib/url.ts +123 -12
- package/src/lib/view.ts +58 -20
- package/src/lib/worker-response-cache.ts +11 -18
- package/src/middleware/__tests__/public-content-access.test.ts +91 -0
- package/src/middleware/config.ts +2 -2
- package/src/middleware/public-content-access.ts +87 -0
- package/src/node/__tests__/cli-export.test.ts +14 -0
- package/src/node/__tests__/cli-migrate.test.ts +6 -0
- package/src/node/__tests__/cli-site-snapshot.test.ts +205 -2
- package/src/node/__tests__/cli-snapshot-meta.test.ts +100 -0
- package/src/node/index.ts +2 -1
- package/src/preset.css +16 -2
- package/src/routes/__tests__/compose.test.ts +51 -0
- package/src/routes/__tests__/site-skill.test.ts +112 -0
- package/src/routes/api/__tests__/collections.test.ts +91 -19
- package/src/routes/api/__tests__/mcp.test.ts +65 -1
- package/src/routes/api/__tests__/nav-items.test.ts +91 -0
- package/src/routes/api/__tests__/palette.test.ts +44 -0
- package/src/routes/api/__tests__/public-access.test.ts +81 -0
- package/src/routes/api/__tests__/settings.test.ts +217 -0
- package/src/routes/api/collections.ts +22 -26
- package/src/routes/api/export.ts +2 -0
- package/src/routes/api/internal/__tests__/post-body-html.test.ts +163 -0
- package/src/routes/api/internal/__tests__/sites.test.ts +35 -2
- package/src/routes/api/internal/post-body-html.ts +43 -0
- package/src/routes/api/internal/sites.ts +24 -0
- package/src/routes/api/nav-items.ts +24 -1
- package/src/routes/api/posts.ts +14 -10
- package/src/routes/api/public/__tests__/archive.test.ts +35 -0
- package/src/routes/api/public/__tests__/posts.test.ts +246 -0
- package/src/routes/api/public/archive.ts +4 -0
- package/src/routes/api/public/posts.ts +48 -24
- package/src/routes/api/search.ts +3 -0
- package/src/routes/api/settings.ts +33 -0
- package/src/routes/auth/__tests__/setup.test.ts +7 -4
- package/src/routes/compose.tsx +8 -3
- package/src/routes/dash/settings.tsx +45 -2
- package/src/routes/feed/__tests__/feed.test.ts +210 -6
- package/src/routes/feed/__tests__/sitemap.test.ts +68 -1
- package/src/routes/feed/feed.ts +23 -14
- package/src/routes/pages/__tests__/archive-params.test.ts +384 -3
- package/src/routes/pages/__tests__/collection-routing.test.ts +63 -5
- package/src/routes/pages/__tests__/collections.test.ts +9 -9
- package/src/routes/pages/__tests__/featured.test.ts +6 -2
- package/src/routes/pages/__tests__/preview.test.ts +176 -0
- package/src/routes/pages/__tests__/search.test.ts +69 -0
- package/src/routes/pages/archive.tsx +90 -22
- package/src/routes/pages/collection.tsx +32 -19
- package/src/routes/pages/collections.tsx +6 -1
- package/src/routes/pages/page.tsx +86 -11
- package/src/routes/site-skill.ts +18 -0
- package/src/services/__tests__/auth.test.ts +7 -5
- package/src/services/__tests__/collection.test.ts +190 -44
- package/src/services/__tests__/navigation.test.ts +229 -21
- package/src/services/__tests__/post-timeline.test.ts +249 -39
- package/src/services/__tests__/post.test.ts +844 -5
- package/src/services/__tests__/search.test.ts +48 -1
- package/src/services/__tests__/settings.test.ts +8 -0
- package/src/services/__tests__/site-admin.test.ts +121 -1
- package/src/services/auth.ts +2 -2
- package/src/services/bootstrap.ts +3 -2
- package/src/services/collection.ts +224 -167
- package/src/services/export-theme/assets/client-site.css +1 -1
- package/src/services/export-theme/assets/client-site.js +46 -25
- package/src/services/export-theme/layouts/_default/list.html +18 -4
- package/src/services/export-theme/layouts/_default/rss.xml +8 -12
- package/src/services/export-theme/layouts/featured/list.html +5 -4
- package/src/services/export-theme/layouts/partials/featured-thread.html +56 -0
- package/src/services/export-theme/layouts/partials/footer.html +1 -1
- package/src/services/export-theme/layouts/partials/media-gallery.html +1 -0
- package/src/services/export-theme/styles/main.css +30 -2
- package/src/services/export.ts +94 -85
- package/src/services/mcp.ts +37 -27
- package/src/services/media.ts +1 -1
- package/src/services/navigation.ts +185 -46
- package/src/services/path.ts +4 -1
- package/src/services/post.ts +1142 -342
- package/src/services/search.ts +17 -2
- package/src/services/settings.ts +2 -10
- package/src/services/site-admin.ts +63 -43
- package/src/style-cjk-jp.css +1 -1
- package/src/style-cjk-kr.css +1 -1
- package/src/style-cjk-tc.css +1 -1
- package/src/style-cjk.css +1 -1
- package/src/styles/components.css +540 -14
- package/src/styles/site-media.css +111 -19
- package/src/styles/tokens.css +76 -10
- package/src/styles/ui.css +2227 -1347
- package/src/types/bindings.ts +3 -0
- package/src/types/config.ts +243 -12
- package/src/types/constants.ts +22 -1
- package/src/types/entities.ts +14 -8
- package/src/types/operations.ts +18 -10
- package/src/types/props.ts +20 -2
- package/src/types/raw-assets.d.ts +5 -0
- package/src/types/views.ts +22 -4
- package/src/ui/__tests__/font-themes.test.ts +42 -30
- package/src/ui/compose/ComposeDialog.tsx +109 -19
- package/src/ui/dash/appearance/NavigationContent.tsx +332 -4
- package/src/ui/dash/appearance/__tests__/NavigationContent.test.tsx +23 -0
- package/src/ui/dash/settings/ConfigEditorContent.tsx +578 -0
- package/src/ui/dash/settings/GeneralContent.tsx +15 -5
- package/src/ui/dash/settings/SettingsRootContent.tsx +21 -1
- package/src/ui/dash/settings/__tests__/ConfigEditorContent.test.tsx +98 -0
- package/src/ui/dash/settings/__tests__/SettingsRootContent.test.tsx +15 -0
- package/src/ui/feed/CuratedThreadPreview.tsx +16 -4
- package/src/ui/feed/LinkCard.tsx +2 -12
- package/src/ui/feed/LinkPreview.tsx +2 -7
- package/src/ui/feed/NoteCard.tsx +10 -20
- package/src/ui/feed/PostStatusBadges.tsx +42 -3
- package/src/ui/feed/QuoteCard.tsx +2 -12
- package/src/ui/feed/ThreadPreview.tsx +26 -34
- package/src/ui/feed/TimelineFeed.tsx +2 -2
- package/src/ui/feed/__tests__/thread-preview.test.ts +197 -56
- package/src/ui/feed/__tests__/timeline-cards.test.ts +178 -3
- package/src/ui/feed/thread-preview-state.ts +5 -7
- package/src/ui/font-themes.ts +74 -26
- package/src/ui/layouts/BaseLayout.tsx +22 -8
- package/src/ui/layouts/__tests__/BaseLayout.test.tsx +64 -1
- package/src/ui/pages/ArchivePage.tsx +131 -24
- package/src/ui/pages/CollectionPage.tsx +101 -22
- package/src/ui/pages/CollectionsPage.tsx +3 -1
- package/src/ui/pages/PostPage.tsx +39 -12
- package/src/ui/pages/SearchPage.tsx +6 -14
- package/src/ui/pages/__tests__/ArchivePage.test.tsx +70 -0
- package/src/ui/pages/__tests__/PostPage.test.tsx +88 -0
- package/src/ui/shared/CollectionDirectory.tsx +13 -9
- package/src/ui/shared/CollectionsManager.tsx +17 -7
- package/src/ui/shared/DraftPreviewBar.tsx +49 -0
- package/src/ui/shared/HomePageBranding.tsx +2 -2
- package/src/ui/shared/MediaGallery.tsx +1 -0
- package/src/ui/shared/PostFooter.tsx +38 -13
- package/src/ui/shared/__tests__/home-page-branding.test.tsx +1 -1
- package/src/ui/shared/__tests__/media-gallery.test.ts +1 -0
- package/src/ui/shared/__tests__/navigation-labels.test.ts +2 -2
- package/src/ui/shared/__tests__/post-footer.test.ts +15 -0
- package/src/ui/shared/collection-management-labels.ts +33 -2
- package/src/ui/shared/custom-icons.ts +5 -0
- package/src/ui/shared/navigation-labels.ts +2 -4
- package/src/ui/shared/post-article-attributes.ts +52 -0
- package/dist/app-DZDlmh7C.js +0 -6
- package/dist/client/_assets/client-Cevfpm8H.css +0 -2
- package/dist/client/_assets/client-auth-v3yvhbgZ.js +0 -4736
- package/src/client/tiptap/wrapping-input-rules.ts +0 -102
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
/** Accessible table-dimension picker opened by the compose slash command. */
|
|
2
|
+
|
|
3
|
+
import type { Editor, Range } from "@tiptap/core";
|
|
4
|
+
import {
|
|
5
|
+
getFixedFloatingContainerRect,
|
|
6
|
+
getFloatingPosition,
|
|
7
|
+
} from "./floating-position.js";
|
|
8
|
+
import type { TableControlLabels } from "./table-control-labels.js";
|
|
9
|
+
|
|
10
|
+
const MAX_ROWS = 8;
|
|
11
|
+
const MAX_COLUMNS = 8;
|
|
12
|
+
const DEFAULT_ROWS = 3;
|
|
13
|
+
const DEFAULT_COLUMNS = 3;
|
|
14
|
+
|
|
15
|
+
interface ActivePicker {
|
|
16
|
+
close: (restoreFocus?: boolean) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
let activePicker: ActivePicker | null = null;
|
|
20
|
+
|
|
21
|
+
function formatSizeLabel(
|
|
22
|
+
template: string,
|
|
23
|
+
rows: number,
|
|
24
|
+
columns: number,
|
|
25
|
+
): string {
|
|
26
|
+
return template
|
|
27
|
+
.replaceAll("%rows%", String(rows))
|
|
28
|
+
.replaceAll("%cols%", String(columns));
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Opens a bounded 8×8 table-size picker at the current slash-command range.
|
|
33
|
+
*
|
|
34
|
+
* @param editor - Editor receiving the selected table
|
|
35
|
+
* @param range - Slash query range to remove before opening the picker
|
|
36
|
+
* @param labels - Localized table UI labels
|
|
37
|
+
* @returns Nothing
|
|
38
|
+
*/
|
|
39
|
+
export function openTableSizePicker(
|
|
40
|
+
editor: Editor,
|
|
41
|
+
range: Range,
|
|
42
|
+
labels: TableControlLabels,
|
|
43
|
+
): void {
|
|
44
|
+
activePicker?.close(false);
|
|
45
|
+
|
|
46
|
+
editor.chain().focus().deleteRange(range).run();
|
|
47
|
+
const insertPosition = editor.state.selection.from;
|
|
48
|
+
const dialog = editor.view.dom.closest("dialog");
|
|
49
|
+
const container = dialog ?? document.body;
|
|
50
|
+
|
|
51
|
+
const picker = document.createElement("div");
|
|
52
|
+
picker.className = "tiptap-table-size-picker";
|
|
53
|
+
picker.dataset.editorFloatingUi = "true";
|
|
54
|
+
picker.style.position = "fixed";
|
|
55
|
+
picker.setAttribute("role", "dialog");
|
|
56
|
+
picker.setAttribute("aria-label", labels.sizePickerLabel);
|
|
57
|
+
|
|
58
|
+
const header = document.createElement("div");
|
|
59
|
+
header.className = "tiptap-table-size-picker-header";
|
|
60
|
+
const title = document.createElement("span");
|
|
61
|
+
title.textContent = labels.sizePickerLabel;
|
|
62
|
+
const dimensions = document.createElement("output");
|
|
63
|
+
dimensions.className = "tiptap-table-size-picker-dimensions";
|
|
64
|
+
dimensions.setAttribute("aria-live", "polite");
|
|
65
|
+
header.appendChild(title);
|
|
66
|
+
header.appendChild(dimensions);
|
|
67
|
+
picker.appendChild(header);
|
|
68
|
+
|
|
69
|
+
const grid = document.createElement("div");
|
|
70
|
+
grid.className = "tiptap-table-size-grid";
|
|
71
|
+
grid.setAttribute("role", "grid");
|
|
72
|
+
grid.setAttribute("aria-label", labels.sizePickerLabel);
|
|
73
|
+
picker.appendChild(grid);
|
|
74
|
+
|
|
75
|
+
let selectedRows = DEFAULT_ROWS;
|
|
76
|
+
let selectedColumns = DEFAULT_COLUMNS;
|
|
77
|
+
let closed = false;
|
|
78
|
+
const cells: HTMLButtonElement[][] = [];
|
|
79
|
+
|
|
80
|
+
function labelFor(rows: number, columns: number): string {
|
|
81
|
+
return formatSizeLabel(labels.insertTableSize, rows, columns);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function updateSelection(rows: number, columns: number): void {
|
|
85
|
+
selectedRows = Math.min(Math.max(rows, 1), MAX_ROWS);
|
|
86
|
+
selectedColumns = Math.min(Math.max(columns, 1), MAX_COLUMNS);
|
|
87
|
+
dimensions.textContent = `${selectedRows} × ${selectedColumns}`;
|
|
88
|
+
picker.setAttribute(
|
|
89
|
+
"aria-label",
|
|
90
|
+
`${labels.sizePickerLabel}: ${labelFor(selectedRows, selectedColumns)}`,
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
for (let row = 1; row <= MAX_ROWS; row += 1) {
|
|
94
|
+
for (let column = 1; column <= MAX_COLUMNS; column += 1) {
|
|
95
|
+
const cell = cells[row - 1]?.[column - 1];
|
|
96
|
+
if (!cell) continue;
|
|
97
|
+
const isCurrent = row === selectedRows && column === selectedColumns;
|
|
98
|
+
cell.classList.toggle(
|
|
99
|
+
"is-selected",
|
|
100
|
+
row <= selectedRows && column <= selectedColumns,
|
|
101
|
+
);
|
|
102
|
+
cell.classList.toggle("is-current", isCurrent);
|
|
103
|
+
cell.tabIndex = isCurrent ? 0 : -1;
|
|
104
|
+
cell.setAttribute("aria-selected", String(isCurrent));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function focusSelection(): void {
|
|
110
|
+
cells[selectedRows - 1]?.[selectedColumns - 1]?.focus();
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function insertTable(): void {
|
|
114
|
+
if (closed) return;
|
|
115
|
+
close(false);
|
|
116
|
+
editor
|
|
117
|
+
.chain()
|
|
118
|
+
.focus()
|
|
119
|
+
.setTextSelection(insertPosition)
|
|
120
|
+
.insertTable({
|
|
121
|
+
rows: selectedRows,
|
|
122
|
+
cols: selectedColumns,
|
|
123
|
+
withHeaderRow: true,
|
|
124
|
+
})
|
|
125
|
+
.run();
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function onKeydown(event: KeyboardEvent): void {
|
|
129
|
+
let nextRows = selectedRows;
|
|
130
|
+
let nextColumns = selectedColumns;
|
|
131
|
+
if (event.key === "ArrowUp") nextRows -= 1;
|
|
132
|
+
else if (event.key === "ArrowDown") nextRows += 1;
|
|
133
|
+
else if (event.key === "ArrowLeft") nextColumns -= 1;
|
|
134
|
+
else if (event.key === "ArrowRight") nextColumns += 1;
|
|
135
|
+
else if (event.key === "Enter" || event.key === " ") {
|
|
136
|
+
event.preventDefault();
|
|
137
|
+
event.stopPropagation();
|
|
138
|
+
insertTable();
|
|
139
|
+
return;
|
|
140
|
+
} else if (event.key === "Escape") {
|
|
141
|
+
event.preventDefault();
|
|
142
|
+
event.stopPropagation();
|
|
143
|
+
close(true);
|
|
144
|
+
return;
|
|
145
|
+
} else {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
event.preventDefault();
|
|
150
|
+
event.stopPropagation();
|
|
151
|
+
updateSelection(nextRows, nextColumns);
|
|
152
|
+
focusSelection();
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
for (let row = 1; row <= MAX_ROWS; row += 1) {
|
|
156
|
+
const rowElement = document.createElement("div");
|
|
157
|
+
rowElement.className = "tiptap-table-size-grid-row";
|
|
158
|
+
rowElement.setAttribute("role", "row");
|
|
159
|
+
const rowCells: HTMLButtonElement[] = [];
|
|
160
|
+
for (let column = 1; column <= MAX_COLUMNS; column += 1) {
|
|
161
|
+
const cell = document.createElement("button");
|
|
162
|
+
cell.type = "button";
|
|
163
|
+
cell.className = "tiptap-table-size-cell";
|
|
164
|
+
cell.dataset.row = String(row);
|
|
165
|
+
cell.dataset.column = String(column);
|
|
166
|
+
cell.setAttribute("role", "gridcell");
|
|
167
|
+
cell.setAttribute("aria-label", labelFor(row, column));
|
|
168
|
+
cell.addEventListener("pointerenter", () => {
|
|
169
|
+
updateSelection(row, column);
|
|
170
|
+
});
|
|
171
|
+
cell.addEventListener("focus", () => {
|
|
172
|
+
updateSelection(row, column);
|
|
173
|
+
});
|
|
174
|
+
cell.addEventListener("keydown", onKeydown);
|
|
175
|
+
cell.addEventListener("click", insertTable);
|
|
176
|
+
rowElement.appendChild(cell);
|
|
177
|
+
rowCells.push(cell);
|
|
178
|
+
}
|
|
179
|
+
cells.push(rowCells);
|
|
180
|
+
grid.appendChild(rowElement);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function positionPicker(): void {
|
|
184
|
+
if (closed) return;
|
|
185
|
+
const coords = editor.view.coordsAtPos(insertPosition);
|
|
186
|
+
const rect = picker.getBoundingClientRect();
|
|
187
|
+
const layout = getFloatingPosition({
|
|
188
|
+
anchorRect: {
|
|
189
|
+
left: coords.left,
|
|
190
|
+
right: coords.right,
|
|
191
|
+
top: coords.top,
|
|
192
|
+
bottom: coords.bottom,
|
|
193
|
+
},
|
|
194
|
+
containerRect: getFixedFloatingContainerRect(dialog),
|
|
195
|
+
floatingWidth: rect.width,
|
|
196
|
+
floatingHeight: rect.height,
|
|
197
|
+
preferredPlacement: "bottom",
|
|
198
|
+
fallbackPlacement: "top",
|
|
199
|
+
align: "start",
|
|
200
|
+
});
|
|
201
|
+
picker.style.left = `${layout.left}px`;
|
|
202
|
+
picker.style.top = `${layout.top}px`;
|
|
203
|
+
picker.dataset.placement = layout.placement;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
function onOutsidePointer(event: MouseEvent): void {
|
|
207
|
+
const target = event.target;
|
|
208
|
+
if (target instanceof Node && !picker.contains(target)) {
|
|
209
|
+
close(false);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
function onOutsideFocus(event: globalThis.FocusEvent): void {
|
|
214
|
+
const target = event.target;
|
|
215
|
+
if (
|
|
216
|
+
target instanceof Node &&
|
|
217
|
+
!picker.contains(target) &&
|
|
218
|
+
!editor.view.dom.contains(target)
|
|
219
|
+
) {
|
|
220
|
+
close(false);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function onEditorDestroy(): void {
|
|
225
|
+
close(false);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function close(restoreFocus = false): void {
|
|
229
|
+
if (closed) return;
|
|
230
|
+
closed = true;
|
|
231
|
+
document.removeEventListener("mousedown", onOutsidePointer, true);
|
|
232
|
+
document.removeEventListener("focusin", onOutsideFocus, true);
|
|
233
|
+
window.removeEventListener("resize", positionPicker);
|
|
234
|
+
window.removeEventListener("scroll", positionPicker, true);
|
|
235
|
+
editor.off("destroy", onEditorDestroy);
|
|
236
|
+
picker.remove();
|
|
237
|
+
if (activePicker?.close === close) activePicker = null;
|
|
238
|
+
if (restoreFocus && !editor.isDestroyed) editor.view.focus();
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
activePicker = { close };
|
|
242
|
+
container.appendChild(picker);
|
|
243
|
+
updateSelection(DEFAULT_ROWS, DEFAULT_COLUMNS);
|
|
244
|
+
positionPicker();
|
|
245
|
+
window.addEventListener("resize", positionPicker);
|
|
246
|
+
window.addEventListener("scroll", positionPicker, true);
|
|
247
|
+
editor.on("destroy", onEditorDestroy);
|
|
248
|
+
setTimeout(() => {
|
|
249
|
+
if (closed) return;
|
|
250
|
+
document.addEventListener("mousedown", onOutsidePointer, true);
|
|
251
|
+
document.addEventListener("focusin", onOutsideFocus, true);
|
|
252
|
+
focusSelection();
|
|
253
|
+
}, 0);
|
|
254
|
+
}
|
package/src/client/toast.ts
CHANGED
|
@@ -20,8 +20,40 @@ interface QueuedToast {
|
|
|
20
20
|
|
|
21
21
|
export const QUEUED_TOAST_STORAGE_KEY = "jant.pendingToast";
|
|
22
22
|
|
|
23
|
-
|
|
23
|
+
function openModalDialogs(): HTMLDialogElement[] {
|
|
24
|
+
const open = [
|
|
25
|
+
...document.querySelectorAll<HTMLDialogElement>("dialog[open]"),
|
|
26
|
+
];
|
|
27
|
+
try {
|
|
28
|
+
const modal = open.filter((dialog) => dialog.matches(":modal"));
|
|
29
|
+
if (modal.length > 0) return modal;
|
|
30
|
+
} catch {
|
|
31
|
+
// ":modal" unsupported — treat every open dialog as potentially modal.
|
|
32
|
+
}
|
|
33
|
+
// Engines without working ":modal" (happy-dom) match nothing above; Jant
|
|
34
|
+
// only opens dialogs via showModal(), so open dialogs are the right proxy.
|
|
35
|
+
return open;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* A modal <dialog> makes everything outside its subtree inert: the popover
|
|
40
|
+
* promotion keeps toasts *painted* above the dialog, but clicks and text
|
|
41
|
+
* selection would still fall through to the dialog. Mounting the container
|
|
42
|
+
* inside the topmost open modal dialog escapes the inert tree; the close
|
|
43
|
+
* watcher moves it back out when that dialog closes.
|
|
44
|
+
*/
|
|
45
|
+
function mountOutsideInertTree(container: HTMLElement): void {
|
|
46
|
+
const dialogs = openModalDialogs();
|
|
47
|
+
// Top-layer order isn't queryable; document order matches Jant's dialog
|
|
48
|
+
// nesting (confirm dialogs are descendants of the dialog that opened them).
|
|
49
|
+
const host = dialogs.at(-1) ?? document.body;
|
|
50
|
+
if (container.parentElement !== host) host.appendChild(container);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Ensure the toast container is interactive and in the top layer (above <dialog> etc.) */
|
|
24
54
|
function ensureTopLayer(container: HTMLElement): void {
|
|
55
|
+
mountOutsideInertTree(container);
|
|
56
|
+
|
|
25
57
|
if (typeof container.showPopover !== "function") return;
|
|
26
58
|
|
|
27
59
|
// Re-promote above any modal dialog that was opened after the toast container.
|
|
@@ -38,7 +70,21 @@ function ensureTopLayer(container: HTMLElement): void {
|
|
|
38
70
|
}
|
|
39
71
|
|
|
40
72
|
function getToastContainer(): HTMLElement | null {
|
|
41
|
-
|
|
73
|
+
const existing = document.getElementById("toast-container");
|
|
74
|
+
if (existing) return existing;
|
|
75
|
+
if (!document.body) return null;
|
|
76
|
+
|
|
77
|
+
// The container can vanish with a modal dialog it was mounted into if that
|
|
78
|
+
// dialog is removed from the DOM while open. Recreate it so toasts keep
|
|
79
|
+
// working for the rest of the page's lifetime.
|
|
80
|
+
const container = document.createElement("div");
|
|
81
|
+
container.id = "toast-container";
|
|
82
|
+
container.className = "toast-container";
|
|
83
|
+
container.setAttribute("popover", "manual");
|
|
84
|
+
container.setAttribute("aria-live", "polite");
|
|
85
|
+
container.setAttribute("aria-relevant", "additions text");
|
|
86
|
+
document.body.appendChild(container);
|
|
87
|
+
return container;
|
|
42
88
|
}
|
|
43
89
|
|
|
44
90
|
function canUseSessionStorage(): boolean {
|
|
@@ -92,10 +138,9 @@ const TOAST_ICONS = {
|
|
|
92
138
|
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><circle cx="12" cy="12" r="10"/><path d="m15 9-6 6M9 9l6 6"/></svg>',
|
|
93
139
|
};
|
|
94
140
|
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
const
|
|
98
|
-
'<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor"><path d="M20 6 9 17l-5-5"/></svg>';
|
|
141
|
+
const TOAST_DURATION_MS = 3000;
|
|
142
|
+
const ACTION_TOAST_DURATION_MS = 5000;
|
|
143
|
+
const MIN_RESUME_MS = 1000;
|
|
99
144
|
|
|
100
145
|
/** Build toast inner content using safe DOM APIs (icon is trusted, text uses textContent). */
|
|
101
146
|
function setToastContent(
|
|
@@ -115,21 +160,62 @@ function setToastContent(
|
|
|
115
160
|
a.textContent = action.label;
|
|
116
161
|
toast.appendChild(a);
|
|
117
162
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Auto-dismiss a toast after `duration`, pausing while the pointer hovers it
|
|
167
|
+
* or focus is inside it — so the message can be read, selected, and copied.
|
|
168
|
+
* On leave, the remaining time resumes (at least MIN_RESUME_MS).
|
|
169
|
+
*/
|
|
170
|
+
function scheduleAutoDismiss(toast: HTMLElement, duration: number): void {
|
|
171
|
+
let remaining = duration;
|
|
172
|
+
let startedAt = 0;
|
|
173
|
+
let timer: ReturnType<typeof setTimeout> | null = null;
|
|
174
|
+
let hovered = false;
|
|
175
|
+
let focused = false;
|
|
176
|
+
|
|
177
|
+
const pause = () => {
|
|
178
|
+
if (timer === null) return;
|
|
179
|
+
clearTimeout(timer);
|
|
180
|
+
timer = null;
|
|
181
|
+
remaining = Math.max(remaining - (Date.now() - startedAt), MIN_RESUME_MS);
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
const resume = () => {
|
|
185
|
+
if (timer !== null) return;
|
|
186
|
+
startedAt = Date.now();
|
|
187
|
+
timer = setTimeout(() => {
|
|
188
|
+
toast.classList.add("toast-out");
|
|
189
|
+
toast.addEventListener("animationend", () => toast.remove());
|
|
190
|
+
}, remaining);
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
const sync = () => {
|
|
194
|
+
if (hovered || focused) {
|
|
195
|
+
pause();
|
|
196
|
+
} else {
|
|
197
|
+
resume();
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
toast.addEventListener("pointerenter", () => {
|
|
202
|
+
hovered = true;
|
|
203
|
+
sync();
|
|
204
|
+
});
|
|
205
|
+
toast.addEventListener("pointerleave", () => {
|
|
206
|
+
hovered = false;
|
|
207
|
+
sync();
|
|
208
|
+
});
|
|
209
|
+
toast.addEventListener("focusin", () => {
|
|
210
|
+
focused = true;
|
|
211
|
+
sync();
|
|
212
|
+
});
|
|
213
|
+
toast.addEventListener("focusout", () => {
|
|
214
|
+
focused = false;
|
|
215
|
+
sync();
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
resume();
|
|
133
219
|
}
|
|
134
220
|
|
|
135
221
|
/**
|
|
@@ -155,17 +241,14 @@ export function showToast(message: string, type: ToastType = "success"): void {
|
|
|
155
241
|
setToastContent(toast, type, message);
|
|
156
242
|
container.appendChild(toast);
|
|
157
243
|
|
|
158
|
-
|
|
159
|
-
toast.classList.add("toast-out");
|
|
160
|
-
toast.addEventListener("animationend", () => toast.remove());
|
|
161
|
-
}, 3000);
|
|
244
|
+
scheduleAutoDismiss(toast, TOAST_DURATION_MS);
|
|
162
245
|
}
|
|
163
246
|
|
|
164
247
|
/**
|
|
165
248
|
* Show a toast with an action link.
|
|
166
249
|
*
|
|
167
250
|
* @param message - Text to display
|
|
168
|
-
* @param action - Action link
|
|
251
|
+
* @param action - Action link rendered beside the message
|
|
169
252
|
* @param type - Visual style: "success" (default) or "error"
|
|
170
253
|
*
|
|
171
254
|
* @example
|
|
@@ -188,10 +271,7 @@ export function showToastWithAction(
|
|
|
188
271
|
setToastContent(toast, type, message, action);
|
|
189
272
|
container.appendChild(toast);
|
|
190
273
|
|
|
191
|
-
|
|
192
|
-
toast.classList.add("toast-out");
|
|
193
|
-
toast.addEventListener("animationend", () => toast.remove());
|
|
194
|
-
}, 3000);
|
|
274
|
+
scheduleAutoDismiss(toast, ACTION_TOAST_DURATION_MS);
|
|
195
275
|
}
|
|
196
276
|
|
|
197
277
|
/**
|
|
@@ -282,10 +362,7 @@ export function replaceWithAutoClose(
|
|
|
282
362
|
toast.replaceChildren();
|
|
283
363
|
setToastContent(toast, type, message);
|
|
284
364
|
|
|
285
|
-
|
|
286
|
-
toast.classList.add("toast-out");
|
|
287
|
-
toast.addEventListener("animationend", () => toast.remove());
|
|
288
|
-
}, 3000);
|
|
365
|
+
scheduleAutoDismiss(toast, TOAST_DURATION_MS);
|
|
289
366
|
}
|
|
290
367
|
|
|
291
368
|
/**
|
|
@@ -293,7 +370,7 @@ export function replaceWithAutoClose(
|
|
|
293
370
|
*
|
|
294
371
|
* @param id - The toast identifier
|
|
295
372
|
* @param message - New message text
|
|
296
|
-
* @param action - Action link
|
|
373
|
+
* @param action - Action link rendered beside the message
|
|
297
374
|
* @param type - Visual style: "success" (default) or "error"
|
|
298
375
|
*
|
|
299
376
|
* @example
|
|
@@ -315,10 +392,7 @@ export function replaceWithAutoCloseAction(
|
|
|
315
392
|
toast.replaceChildren();
|
|
316
393
|
setToastContent(toast, type, message, action);
|
|
317
394
|
|
|
318
|
-
|
|
319
|
-
toast.classList.add("toast-out");
|
|
320
|
-
toast.addEventListener("animationend", () => toast.remove());
|
|
321
|
-
}, 3000);
|
|
395
|
+
scheduleAutoDismiss(toast, ACTION_TOAST_DURATION_MS);
|
|
322
396
|
}
|
|
323
397
|
|
|
324
398
|
/**
|
|
@@ -361,6 +435,25 @@ export function consumeQueuedToast(): boolean {
|
|
|
361
435
|
return true;
|
|
362
436
|
}
|
|
363
437
|
|
|
438
|
+
function initDialogCloseWatcher(): void {
|
|
439
|
+
// "close" doesn't bubble; capture reaches it from the document anyway.
|
|
440
|
+
document.addEventListener(
|
|
441
|
+
"close",
|
|
442
|
+
(event) => {
|
|
443
|
+
const dialog = event.target;
|
|
444
|
+
if (!(dialog instanceof HTMLDialogElement)) return;
|
|
445
|
+
|
|
446
|
+
const container = document.getElementById("toast-container");
|
|
447
|
+
if (!container || !dialog.contains(container)) return;
|
|
448
|
+
|
|
449
|
+
// The closed dialog is display:none — move the container back out
|
|
450
|
+
// (into the next open modal dialog, if any) so live toasts stay visible.
|
|
451
|
+
ensureTopLayer(container);
|
|
452
|
+
},
|
|
453
|
+
true,
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
|
|
364
457
|
function initQueuedToastConsumer(): void {
|
|
365
458
|
const showQueuedToast = () => {
|
|
366
459
|
consumeQueuedToast();
|
|
@@ -376,4 +469,5 @@ function initQueuedToastConsumer(): void {
|
|
|
376
469
|
showQueuedToast();
|
|
377
470
|
}
|
|
378
471
|
|
|
472
|
+
initDialogCloseWatcher();
|
|
379
473
|
initQueuedToastConsumer();
|
package/src/client-auth.ts
CHANGED
|
@@ -18,6 +18,7 @@ import "./client/slash-discovery-bridge.js";
|
|
|
18
18
|
import "./client/compose-shortcuts.js";
|
|
19
19
|
import "./client/components/jant-settings-general.js";
|
|
20
20
|
import "./client/components/jant-settings-avatar.js";
|
|
21
|
+
import "./client/components/jant-config-editor.js";
|
|
21
22
|
import "./client/settings-bridge.js";
|
|
22
23
|
import "./client/components/jant-repo-picker.js";
|
|
23
24
|
import "./client/components/jant-collection-form.js";
|
package/src/client.ts
CHANGED