diff --git a/.changeset/heavy-falcons-act.md b/.changeset/heavy-falcons-act.md new file mode 100644 index 000000000..c1b9d01ff --- /dev/null +++ b/.changeset/heavy-falcons-act.md @@ -0,0 +1,7 @@ +--- +"@shopware-ag/meteor-component-library": major +--- + +Removed locale control from mt-theme-provider. + +Controlling the local will still happen via vue-i18n diff --git a/.changeset/neat-pumpkins-juggle.md b/.changeset/neat-pumpkins-juggle.md new file mode 100644 index 000000000..21c5a3dcd --- /dev/null +++ b/.changeset/neat-pumpkins-juggle.md @@ -0,0 +1,6 @@ +--- +"@shopware-ag/meteor-component-library": patch +--- + +Fixes a issue in the mt-modal that the toggling does not work when it is triggered outside the modal. +Fixes a issue in the mt-modal that it does not work inside transformed elements. This was fixed by moving the modal to the body element using the native Teleport feature of Vue 3. diff --git a/.changeset/wise-melons-smash.md b/.changeset/wise-melons-smash.md new file mode 100644 index 000000000..a7400e456 --- /dev/null +++ b/.changeset/wise-melons-smash.md @@ -0,0 +1,11 @@ +--- +"@shopware-ag/meteor-component-library": major +--- + +# Add new Text Editor component + +This change introduces a new Text Editor component to the Meteor Component Library. + +# Updated i18n configuration + +We change the 'legacy' mode of i18n to 'false' in the Meteor Component Library configuration to use the new i18n composable. \ No newline at end of file diff --git a/examples/nuxt-app/package.json b/examples/nuxt-app/package.json index e5634f9bb..6b064c160 100644 --- a/examples/nuxt-app/package.json +++ b/examples/nuxt-app/package.json @@ -16,7 +16,8 @@ "@shopware-ag/meteor-component-library": "workspace:*", "nuxt": "^3.10.3", "vue": "^3.5.0", - "vue-router": "^4.3.0" + "vue-router": "^4.3.0", + "vue-i18n": "^9.9.1" }, "devDependencies": { "@playwright/test": "^1.45.0", diff --git a/examples/nuxt-app/plugins/i18n.ts b/examples/nuxt-app/plugins/i18n.ts new file mode 100644 index 000000000..4f139f473 --- /dev/null +++ b/examples/nuxt-app/plugins/i18n.ts @@ -0,0 +1,11 @@ +import { createI18n } from "vue-i18n"; + +export default defineNuxtPlugin(({ vueApp }) => { + const i18n = createI18n({ + legacy: false, + globalInjection: true, + locale: "en", + }); + + vueApp.use(i18n); +}); diff --git a/examples/nuxt-app/tests/smoke.spec.ts-snapshots/renders-an-example-page-1-chromium-linux.png b/examples/nuxt-app/tests/smoke.spec.ts-snapshots/renders-an-example-page-1-chromium-linux.png index 3a346250f..dcad20f7e 100644 Binary files a/examples/nuxt-app/tests/smoke.spec.ts-snapshots/renders-an-example-page-1-chromium-linux.png and b/examples/nuxt-app/tests/smoke.spec.ts-snapshots/renders-an-example-page-1-chromium-linux.png differ diff --git a/packages/component-library/.storybook/preview.ts b/packages/component-library/.storybook/preview.ts index 65203d77a..0457e4741 100644 --- a/packages/component-library/.storybook/preview.ts +++ b/packages/component-library/.storybook/preview.ts @@ -18,6 +18,7 @@ import "@shopware-ag/meteor-tokens/administration/dark.css"; const i18n = createI18n({ // something vue-i18n options here ... + legacy: false, globalInjection: true, locale: "en", fallbackLocale: "en", diff --git a/packages/component-library/__snapshots__/interaction-tests-form-mt-colorpicker--visual-test-open-colorpicker-with-apply-mode-snap.png b/packages/component-library/__snapshots__/interaction-tests-form-mt-colorpicker--visual-test-open-colorpicker-with-apply-mode-snap.png new file mode 100644 index 000000000..78ed6fa6b Binary files /dev/null and b/packages/component-library/__snapshots__/interaction-tests-form-mt-colorpicker--visual-test-open-colorpicker-with-apply-mode-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-form-mt-select--visual-test-ensure-correct-multi-selection-wrapping-snap.png b/packages/component-library/__snapshots__/interaction-tests-form-mt-select--visual-test-ensure-correct-multi-selection-wrapping-snap.png index 4dbc6481c..fdfc67652 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-form-mt-select--visual-test-ensure-correct-multi-selection-wrapping-snap.png and b/packages/component-library/__snapshots__/interaction-tests-form-mt-select--visual-test-ensure-correct-multi-selection-wrapping-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-code-view-snap.png b/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-code-view-snap.png new file mode 100644 index 000000000..05258a583 Binary files /dev/null and b/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-code-view-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-disabled-editor-snap.png b/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-disabled-editor-snap.png new file mode 100644 index 000000000..902e0868c Binary files /dev/null and b/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-disabled-editor-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-editor-inline-mode-selected-snap.png b/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-editor-inline-mode-selected-snap.png new file mode 100644 index 000000000..0a71126af Binary files /dev/null and b/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-editor-inline-mode-selected-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-editor-inline-mode-snap.png b/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-editor-inline-mode-snap.png new file mode 100644 index 000000000..b6357bba1 Binary files /dev/null and b/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-editor-inline-mode-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-editor-snap.png b/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-editor-snap.png new file mode 100644 index 000000000..a5a93624b Binary files /dev/null and b/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-editor-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-error-snap.png b/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-error-snap.png new file mode 100644 index 000000000..d79911605 Binary files /dev/null and b/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-error-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-placeholder-snap.png b/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-placeholder-snap.png new file mode 100644 index 000000000..9cfbcc989 Binary files /dev/null and b/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-render-placeholder-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-show-contextual-buttons-snap.png b/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-show-contextual-buttons-snap.png new file mode 100644 index 000000000..14d4b199b Binary files /dev/null and b/packages/component-library/__snapshots__/interaction-tests-form-mt-text-editor--visual-test-show-contextual-buttons-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-snap.png b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-snap.png index c74ccbdec..5ae81c977 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-snap.png and b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-with-opened-context-actions-snap.png b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-with-opened-context-actions-snap.png index 3191900c5..1bf1d9a3d 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-with-opened-context-actions-snap.png and b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-with-opened-context-actions-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-avatar-snap.png b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-avatar-snap.png index b28baf010..e726c2105 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-avatar-snap.png and b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-avatar-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-context-actions-snap.png b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-context-actions-snap.png index 082dc4681..5aed4785c 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-context-actions-snap.png and b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-context-actions-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-footer-snap.png b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-footer-snap.png index 2eabb6352..a9bdf47af 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-footer-snap.png and b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-footer-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-header-right-snap.png b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-header-right-snap.png index 225cfe6ef..d3c426f1a 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-header-right-snap.png and b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-header-right-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-tabs-snap.png b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-tabs-snap.png index e225ca888..9fa277e01 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-tabs-snap.png and b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-tabs-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-toolbar-snap.png b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-toolbar-snap.png index 15b575d81..4ad9a760f 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-toolbar-snap.png and b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-extended-page-without-toolbar-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-minimal-page-snap.png b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-minimal-page-snap.png index 962d4ca49..c26d6c6a2 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-minimal-page-snap.png and b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-minimal-page-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-minimal-page-with-custom-footer-snap.png b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-minimal-page-with-custom-footer-snap.png index c43f844e7..05a236a53 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-minimal-page-with-custom-footer-snap.png and b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-minimal-page-with-custom-footer-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-minimal-page-with-linked-inheritance-snap.png b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-minimal-page-with-linked-inheritance-snap.png index 4cb2db133..a287f6e20 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-minimal-page-with-linked-inheritance-snap.png and b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-minimal-page-with-linked-inheritance-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-minimal-page-with-unlinked-inheritance-snap.png b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-minimal-page-with-unlinked-inheritance-snap.png index 13dbf8c94..7d3576202 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-minimal-page-with-unlinked-inheritance-snap.png and b/packages/component-library/__snapshots__/interaction-tests-layout-mt-card--visual-test-minimal-page-with-unlinked-inheritance-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-layout-mt-empty-state--visual-test-extended-page-snap.png b/packages/component-library/__snapshots__/interaction-tests-layout-mt-empty-state--visual-test-extended-page-snap.png index b04364c10..dc5c0c279 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-layout-mt-empty-state--visual-test-extended-page-snap.png and b/packages/component-library/__snapshots__/interaction-tests-layout-mt-empty-state--visual-test-extended-page-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-navigation-mt-tabs--visual-test-render-tabs-with-context-menu-badge-snap.png b/packages/component-library/__snapshots__/interaction-tests-navigation-mt-tabs--visual-test-render-tabs-with-context-menu-badge-snap.png index 66fe8a042..224edc400 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-navigation-mt-tabs--visual-test-render-tabs-with-context-menu-badge-snap.png and b/packages/component-library/__snapshots__/interaction-tests-navigation-mt-tabs--visual-test-render-tabs-with-context-menu-badge-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-overlay-mt-modal--visual-test-teleport-feature-snap.png b/packages/component-library/__snapshots__/interaction-tests-overlay-mt-modal--visual-test-teleport-feature-snap.png new file mode 100644 index 000000000..af23db7cc Binary files /dev/null and b/packages/component-library/__snapshots__/interaction-tests-overlay-mt-modal--visual-test-teleport-feature-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-overlay-mt-popover--visual-test-render-popover-snap.png b/packages/component-library/__snapshots__/interaction-tests-overlay-mt-popover--visual-test-render-popover-snap.png index 45f38644a..b796948bf 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-overlay-mt-popover--visual-test-render-popover-snap.png and b/packages/component-library/__snapshots__/interaction-tests-overlay-mt-popover--visual-test-render-popover-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-overlay-mt-popover--visual-test-render-without-float-snap.png b/packages/component-library/__snapshots__/interaction-tests-overlay-mt-popover--visual-test-render-without-float-snap.png index 847f229f0..f99e2ca03 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-overlay-mt-popover--visual-test-render-without-float-snap.png and b/packages/component-library/__snapshots__/interaction-tests-overlay-mt-popover--visual-test-render-without-float-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-table-and-list-mt-data-table--visual-test-add-filter-via-filter-menu-snap.png b/packages/component-library/__snapshots__/interaction-tests-table-and-list-mt-data-table--visual-test-add-filter-via-filter-menu-snap.png index 9cc004e78..446ab5e73 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-table-and-list-mt-data-table--visual-test-add-filter-via-filter-menu-snap.png and b/packages/component-library/__snapshots__/interaction-tests-table-and-list-mt-data-table--visual-test-add-filter-via-filter-menu-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-table-and-list-mt-data-table--visual-test-add-filter-via-icon-button-snap.png b/packages/component-library/__snapshots__/interaction-tests-table-and-list-mt-data-table--visual-test-add-filter-via-icon-button-snap.png index 1095b6370..6d74d9898 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-table-and-list-mt-data-table--visual-test-add-filter-via-icon-button-snap.png and b/packages/component-library/__snapshots__/interaction-tests-table-and-list-mt-data-table--visual-test-add-filter-via-icon-button-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-table-and-list-mt-data-table--visual-test-remove-filter-via-filter-menu-snap.png b/packages/component-library/__snapshots__/interaction-tests-table-and-list-mt-data-table--visual-test-remove-filter-via-filter-menu-snap.png index fb0a8818f..5f05dc2cc 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-table-and-list-mt-data-table--visual-test-remove-filter-via-filter-menu-snap.png and b/packages/component-library/__snapshots__/interaction-tests-table-and-list-mt-data-table--visual-test-remove-filter-via-filter-menu-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-table-and-list-mt-data-table--visual-test-render-table-with-an-image-in-cell-table-snap.png b/packages/component-library/__snapshots__/interaction-tests-table-and-list-mt-data-table--visual-test-render-table-with-an-image-in-cell-table-snap.png index 85807b62a..6526d86bd 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-table-and-list-mt-data-table--visual-test-render-table-with-an-image-in-cell-table-snap.png and b/packages/component-library/__snapshots__/interaction-tests-table-and-list-mt-data-table--visual-test-render-table-with-an-image-in-cell-table-snap.png differ diff --git a/packages/component-library/__snapshots__/interaction-tests-table-and-list-mt-data-table--visual-test-should-hide-the-last-column-with-via-disable-context-menu-and-settings-table-snap.png b/packages/component-library/__snapshots__/interaction-tests-table-and-list-mt-data-table--visual-test-should-hide-the-last-column-with-via-disable-context-menu-and-settings-table-snap.png index 5ab04d884..b80e1457b 100644 Binary files a/packages/component-library/__snapshots__/interaction-tests-table-and-list-mt-data-table--visual-test-should-hide-the-last-column-with-via-disable-context-menu-and-settings-table-snap.png and b/packages/component-library/__snapshots__/interaction-tests-table-and-list-mt-data-table--visual-test-should-hide-the-last-column-with-via-disable-context-menu-and-settings-table-snap.png differ diff --git a/packages/component-library/package.json b/packages/component-library/package.json index a10abd081..cb1644561 100644 --- a/packages/component-library/package.json +++ b/packages/component-library/package.json @@ -39,6 +39,7 @@ "test:storybook": "test-storybook" }, "dependencies": { + "@codemirror/lang-html": "^6.4.9", "@floating-ui/dom": "^1.4.3", "@floating-ui/vue": "^1.1.5", "@shopware-ag/meteor-icon-kit": "workspace:*", @@ -46,15 +47,38 @@ "@storybook/addon-a11y": "^8.4.5", "@testing-library/jest-dom": "^6.4.6", "@testing-library/vue": "^8.1.0", + "@tiptap/extension-bubble-menu": "^2.10.0", + "@tiptap/extension-bullet-list": "^2.10.0", + "@tiptap/extension-character-count": "^2.10.0", + "@tiptap/extension-color": "^2.9.1", + "@tiptap/extension-highlight": "^2.10.3", + "@tiptap/extension-link": "^2.10.0", + "@tiptap/extension-list-item": "^2.10.0", + "@tiptap/extension-ordered-list": "^2.10.0", + "@tiptap/extension-placeholder": "^2.10.4", + "@tiptap/extension-subscript": "^2.9.1", + "@tiptap/extension-superscript": "^2.9.1", + "@tiptap/extension-table": "^2.10.3", + "@tiptap/extension-table-cell": "^2.10.3", + "@tiptap/extension-table-header": "^2.10.3", + "@tiptap/extension-table-row": "^2.10.3", + "@tiptap/extension-text-align": "^2.9.1", + "@tiptap/extension-text-style": "^2.9.1", + "@tiptap/extension-underline": "^2.9.1", + "@tiptap/pm": "^2.9.1", + "@tiptap/starter-kit": "^2.9.1", + "@tiptap/vue-3": "^2.9.1", "@vuepic/vue-datepicker": "^10.0.0", "@vueuse/components": "^10.7.2", "@vueuse/core": "^10.7.2", + "codemirror": "^6.0.1", "date-fns": "^2.30.0", "date-fns-tz": "^2.0.0", "focus-trap": "^7.5.4", "inter-ui": "^3.19.3", "lodash-es": "^4.17.21", "nanoid": "^5.0.7", + "vue-codemirror6": "^1.3.8", "vue-i18n": "^9.9.1", "vue-smooth-reflow": "^0.1.12" }, @@ -109,8 +133,5 @@ "vite-plugin-svgstring": "^1.0.0", "vitest": "^1.1.3", "vue-tsc": "^2.0.21" - }, - "peerDependencies": { - "vue": ">= 3.5.0" } } diff --git a/packages/component-library/src/components/_internal/mt-label.vue b/packages/component-library/src/components/_internal/mt-label.vue index ebcf25e56..e4f594a80 100644 --- a/packages/component-library/src/components/_internal/mt-label.vue +++ b/packages/component-library/src/components/_internal/mt-label.vue @@ -24,7 +24,7 @@ import { computed, useAttrs } from "vue"; import MtIcon from "../icons-media/mt-icon/mt-icon.vue"; import MtColorBadge from "../feedback-indicator/mt-color-badge/mt-color-badge.vue"; -import { useI18n } from "@/composables/useI18n"; +import { useI18n } from "vue-i18n"; const props = withDefaults( defineProps<{ diff --git a/packages/component-library/src/components/feedback-indicator/mt-banner/mt-banner.vue b/packages/component-library/src/components/feedback-indicator/mt-banner/mt-banner.vue index 666285f8d..c93121fc5 100644 --- a/packages/component-library/src/components/feedback-indicator/mt-banner/mt-banner.vue +++ b/packages/component-library/src/components/feedback-indicator/mt-banner/mt-banner.vue @@ -36,7 +36,7 @@ import { computed } from "vue"; import MtIcon from "../../icons-media/mt-icon/mt-icon.vue"; import MtText from "@/components/content/mt-text/mt-text.vue"; import { useFutureFlags } from "@/composables/useFutureFlags"; -import { useI18n } from "@/composables/useI18n"; +import { useI18n } from "vue-i18n"; const { t } = useI18n({ messages: { diff --git a/packages/component-library/src/components/form/_internal/mt-base-field/mt-base-field.vue b/packages/component-library/src/components/form/_internal/mt-base-field/mt-base-field.vue index 3afc57f8f..4954149a3 100644 --- a/packages/component-library/src/components/form/_internal/mt-base-field/mt-base-field.vue +++ b/packages/component-library/src/components/form/_internal/mt-base-field/mt-base-field.vue @@ -262,6 +262,10 @@ $mt-field-transition: margin-bottom: var(--scale-size-12); } + &.is--disabled { + cursor: not-allowed; + } + &__hint-wrapper { display: flex; justify-content: space-between; diff --git a/packages/component-library/src/components/form/_internal/mt-field-copyable/mt-field-copyable.vue b/packages/component-library/src/components/form/_internal/mt-field-copyable/mt-field-copyable.vue index 9e09abb9a..3c3dd7113 100644 --- a/packages/component-library/src/components/form/_internal/mt-field-copyable/mt-field-copyable.vue +++ b/packages/component-library/src/components/form/_internal/mt-field-copyable/mt-field-copyable.vue @@ -22,7 +22,7 @@ import MtIcon from "../../../icons-media/mt-icon/mt-icon.vue"; import MtTooltipDirective from "../../../../directives/tooltip.directive"; import MtNotificationMixin from "../../../../mixins/notification.mixin"; import { copyToClipboard as copyToClipboardUtil } from "../../../../utils/dom"; -import { useI18n } from "@/composables/useI18n"; +import { useI18n } from "vue-i18n"; export default defineComponent({ name: "MtFieldCopyable", diff --git a/packages/component-library/src/components/form/_internal/mt-field-error/mt-field-error.vue b/packages/component-library/src/components/form/_internal/mt-field-error/mt-field-error.vue index f15742730..303264d0b 100644 --- a/packages/component-library/src/components/form/_internal/mt-field-error/mt-field-error.vue +++ b/packages/component-library/src/components/form/_internal/mt-field-error/mt-field-error.vue @@ -16,7 +16,7 @@ import { computed } from "vue"; import MtIcon from "../../../icons-media/mt-icon/mt-icon.vue"; import MtText from "@/components/content/mt-text/mt-text.vue"; -import { useI18n } from "@/composables/useI18n"; +import { useI18n } from "vue-i18n"; const props = defineProps<{ error?: Record | null; @@ -25,8 +25,12 @@ const props = defineProps<{ const errorMessage = computed(() => { if (!props.error) return ""; + if (!props.error.code) { + return t(props.error.detail); + } + const translation = t(props.error.code, props.error.parameters || {}); - const noTranslationFound = translation === props.error.code; + const noTranslationFound = translation === props.error.code.toString(); return noTranslationFound ? props.error.detail : translation; }); diff --git a/packages/component-library/src/components/form/_internal/mt-field-label/mt-field-label.vue b/packages/component-library/src/components/form/_internal/mt-field-label/mt-field-label.vue index cfdf95880..e4cdf5335 100644 --- a/packages/component-library/src/components/form/_internal/mt-field-label/mt-field-label.vue +++ b/packages/component-library/src/components/form/_internal/mt-field-label/mt-field-label.vue @@ -22,7 +22,7 @@ + + + + diff --git a/packages/component-library/src/components/form/mt-text-editor/_internal/mt-text-editor-toolbar-button-link.vue b/packages/component-library/src/components/form/mt-text-editor/_internal/mt-text-editor-toolbar-button-link.vue new file mode 100644 index 000000000..ffbc6b1cb --- /dev/null +++ b/packages/component-library/src/components/form/mt-text-editor/_internal/mt-text-editor-toolbar-button-link.vue @@ -0,0 +1,142 @@ + + + + + + + diff --git a/packages/component-library/src/components/form/mt-text-editor/_internal/mt-text-editor-toolbar-button-table.vue b/packages/component-library/src/components/form/mt-text-editor/_internal/mt-text-editor-toolbar-button-table.vue new file mode 100644 index 000000000..5254fb0a1 --- /dev/null +++ b/packages/component-library/src/components/form/mt-text-editor/_internal/mt-text-editor-toolbar-button-table.vue @@ -0,0 +1,229 @@ + + + + + + + diff --git a/packages/component-library/src/components/form/mt-text-editor/_internal/mt-text-editor-toolbar-button.vue b/packages/component-library/src/components/form/mt-text-editor/_internal/mt-text-editor-toolbar-button.vue new file mode 100644 index 000000000..e9c76008a --- /dev/null +++ b/packages/component-library/src/components/form/mt-text-editor/_internal/mt-text-editor-toolbar-button.vue @@ -0,0 +1,91 @@ + + + + + diff --git a/packages/component-library/src/components/form/mt-text-editor/_internal/mt-text-editor-toolbar.vue b/packages/component-library/src/components/form/mt-text-editor/_internal/mt-text-editor-toolbar.vue new file mode 100644 index 000000000..ec01b3b37 --- /dev/null +++ b/packages/component-library/src/components/form/mt-text-editor/_internal/mt-text-editor-toolbar.vue @@ -0,0 +1,483 @@ + + + + + diff --git a/packages/component-library/src/components/form/mt-text-editor/mt-text-editor.interactive.stories.ts b/packages/component-library/src/components/form/mt-text-editor/mt-text-editor.interactive.stories.ts new file mode 100644 index 000000000..a6428a658 --- /dev/null +++ b/packages/component-library/src/components/form/mt-text-editor/mt-text-editor.interactive.stories.ts @@ -0,0 +1,836 @@ +import { within, userEvent } from "@storybook/test"; +import { expect } from "@storybook/test"; +import { waitUntil } from "../../../_internal/test-helper"; + +import meta, { type MtTextEditorMeta, type MtTextEditorStory } from "./mt-text-editor.stories"; +import { defineStory } from "@/_internal/story-helper"; + +export default { + ...meta, + title: "Interaction Tests/Form/mt-text-editor", +} as MtTextEditorMeta; + +/** + * Selects the text of an element. It is important to + * click on the element before calling this function + * to ensure that the element is focused. Because + * Storybook throws manual events, the element is not + * focused by default. + */ +function selectText(element: HTMLElement) { + const selection = window.getSelection(); + const range = document.createRange(); + range.selectNodeContents(element); + selection?.removeAllRanges(); + selection?.addRange(range); +} + +export const VisualTestRenderEditor: MtTextEditorStory = defineStory({ + name: "Should render the text editor", + args: {}, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("82 characters")).toBeDefined(); + }, +}); + +export const VisualTestRenderEditorInlineMode: MtTextEditorStory = defineStory({ + name: "Should render the text editor in inline mode", + args: { + isInlineEdit: true, + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("82 characters")).toBeDefined(); + }, +}); + +export const VisualTestRenderDisabledEditor: MtTextEditorStory = defineStory({ + name: "Should render the disabled text editor", + args: { + disabled: true, + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("82 characters")).toBeDefined(); + }, +}); + +export const VisualTestRenderPlaceholder: MtTextEditorStory = defineStory({ + name: "Should render the placeholder inside text editor", + args: { + placeholder: "Type something...", + modelValue: "", + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("0 characters")).toBeDefined(); + }, +}); + +export const VisualTestRenderError: MtTextEditorStory = defineStory({ + name: "Should render a error in text editor", + args: { + error: { + code: 500, + detail: "Error while saving!", + }, + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("82 characters")).toBeDefined(); + }, +}); + +export const VisualTestRenderEditorInlineModeSelected: MtTextEditorStory = defineStory({ + name: "Should render the bubble menu in inline mode when text is selected", + args: { + isInlineEdit: true, + modelValue: `

Hello World

`, + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // Click inside the editor + await userEvent.click(canvas.getByText("Hello World")); + + // Wait until the counter is rendered + await waitUntil(() => canvas.getByText("11 characters")); + + // Select "Hello World" text + selectText(canvas.getByText("Hello World")); + + // Wait until the bubble menu is rendered + await waitUntil(() => document.querySelector(".mt-text-editor-toolbar") !== null); + + // Expect the bubble menu to be rendered + expect(canvas.getByLabelText("Format")).toBeDefined(); + expect(canvas.getByLabelText("Bold")).toBeDefined(); + expect(canvas.getByLabelText("Italic")).toBeDefined(); + + // Expect the contextual buttons to be rendered + expect(canvas.getByLabelText("Insert row before")).toBeDefined(); + expect(canvas.getByLabelText("Insert row after")).toBeDefined(); + expect(canvas.getByLabelText("Delete row")).toBeDefined(); + }, +}); + +export const SetParagraph: MtTextEditorStory = defineStory({ + name: "Should set paragraph", + args: { + modelValue: `

Hello World

`, + }, + play: async ({ canvasElement, args, screen }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("11 characters")).toBeDefined(); + + // Click on button with aria-label "Format" + await userEvent.click(canvas.getByLabelText("Format")); + + // Click on menuitem with text "Paragraph" + await userEvent.click(screen.getByText("Paragraph")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue.mock.calls.length > 0); + + // Check if args was triggered with new content + expect(args.updateModelValue).toHaveBeenCalledWith("

Hello World

"); + }, +}); + +export const SetHeadlineH1: MtTextEditorStory = defineStory({ + name: "Should set h1 headline", + args: { + modelValue: `

Hello World

`, + }, + play: async ({ canvasElement, args, screen }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("11 characters")).toBeDefined(); + + // Click on button with aria-label "Format" + await userEvent.click(canvas.getByLabelText("Format")); + + // Click on menuitem with text "Headline 1" + await userEvent.click(screen.getByText("Headline 1")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue.mock.calls.length > 0); + + // Check if args was triggered with new content + expect(args.updateModelValue).toHaveBeenCalledWith("

Hello World

"); + }, +}); + +export const SetHeadlineH2: MtTextEditorStory = defineStory({ + name: "Should set h2 headline", + args: { + modelValue: "

Hello World

", + }, + play: async ({ canvasElement, args, screen }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("11 characters")).toBeDefined(); + + // Click on button with aria-label "Format" + await userEvent.click(canvas.getByLabelText("Format")); + + // Click on menuitem with text "Headline 2" + await userEvent.click(screen.getByText("Headline 2")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue.mock.calls.length > 0); + + // Check if args was triggered with new content + expect(args.updateModelValue).toHaveBeenCalledWith("

Hello World

"); + }, +}); + +export const SetHeadlineH3: MtTextEditorStory = defineStory({ + name: "Should set h3 headline", + args: { + modelValue: "

Hello World

", + }, + play: async ({ canvasElement, args, screen }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("11 characters")).toBeDefined(); + + // Click on button with aria-label "Format" + await userEvent.click(canvas.getByLabelText("Format")); + + // Click on menuitem with text "Headline 3" + await userEvent.click(screen.getByText("Headline 3")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue.mock.calls.length > 0); + + // Check if args was triggered with new content + expect(args.updateModelValue).toHaveBeenCalledWith("

Hello World

"); + }, +}); + +export const SetHeadlineH4: MtTextEditorStory = defineStory({ + name: "Should set h4 headline", + args: { + modelValue: "

Hello World

", + }, + play: async ({ canvasElement, args, screen }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("11 characters")).toBeDefined(); + + // Click on button with aria-label "Format" + await userEvent.click(canvas.getByLabelText("Format")); + + // Click on menuitem with text "Headline 4" + await userEvent.click(screen.getByText("Headline 4")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue.mock.calls.length > 0); + + // Check if args was triggered with new content + expect(args.updateModelValue).toHaveBeenCalledWith("

Hello World

"); + }, +}); + +export const SetHeadlineH5: MtTextEditorStory = defineStory({ + name: "Should set h5 headline", + args: { + modelValue: "

Hello World

", + }, + play: async ({ canvasElement, args, screen }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("11 characters")).toBeDefined(); + + // Click on button with aria-label "Format" + await userEvent.click(canvas.getByLabelText("Format")); + + // Click on menuitem with text "Headline 5" + await userEvent.click(screen.getByText("Headline 5")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue.mock.calls.length > 0); + + // Check if args was triggered with new content + expect(args.updateModelValue).toHaveBeenCalledWith("
Hello World
"); + }, +}); + +export const SetHeadlineH6: MtTextEditorStory = defineStory({ + name: "Should set h6 headline", + args: { + modelValue: "

Hello World

", + }, + play: async ({ canvasElement, args, screen }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("11 characters")).toBeDefined(); + + // Click on button with aria-label "Format" + await userEvent.click(canvas.getByLabelText("Format")); + + // Click on menuitem with text "Headline 6" + await userEvent.click(screen.getByText("Headline 6")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue.mock.calls.length > 0); + + // Check if args was triggered with new content + expect(args.updateModelValue).toHaveBeenCalledWith("
Hello World
"); + }, +}); + +export const SetTextColor: MtTextEditorStory = defineStory({ + name: "Should set text color", + args: { + modelValue: "

Hello World

Some text

", + }, + play: async ({ canvasElement, args, screen }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("20 characters")).toBeDefined(); + + // Click inside the editor + await userEvent.click(canvas.getByText("Hello World")); + + // Select "Hello World" text + selectText(canvas.getByText("Hello World")); + + // Click on button with aria-label "colorpicker-toggle" + await userEvent.click(canvas.getByLabelText("colorpicker-toggle")); + + // Set new color value + await waitUntil(() => document.querySelector("[aria-label='colorpicker-apply-color']")); + + const redInput = screen.getByLabelText("red-value") as HTMLInputElement; + const greenInput = screen.getByLabelText("green-value") as HTMLInputElement; + const blueInput = screen.getByLabelText("blue-value") as HTMLInputElement; + + await userEvent.clear(redInput); + await userEvent.type(redInput, "255"); + + await userEvent.clear(greenInput); + await userEvent.type(greenInput, "0"); + + await userEvent.clear(blueInput); + await userEvent.type(blueInput, "0"); + + // Click on button with aria-label "Apply" + await userEvent.click(screen.getByLabelText("colorpicker-apply-color")); + + // Expect the color to be applied + await waitUntil(() => args.updateModelValue?.mock?.calls?.length > 0); + expect(args.updateModelValue).toHaveBeenCalledWith( + '

Hello World

Some text

', + ); + }, +}); + +export const MakeFontBold: MtTextEditorStory = defineStory({ + name: "Should make font bold", + args: { + modelValue: "

Hello World

Some text

", + }, + play: async ({ canvasElement, args }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("20 characters")).toBeDefined(); + + // Click inside the editor + await userEvent.click(canvas.getByText("Hello World")); + + // Select "Hello World" text + selectText(canvas.getByText("Hello World")); + + // Click on button with aria-label "bold" + await userEvent.click(canvas.getByLabelText("Bold")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue?.mock?.calls?.length > 0); + + // Check if args was triggered with new content + expect(args.updateModelValue).toHaveBeenCalledWith( + "

Hello World

Some text

", + ); + }, +}); + +export const MakeFontItalic: MtTextEditorStory = defineStory({ + name: "Should make font italic", + args: { + modelValue: "

Hello World

Some text

", + }, + play: async ({ canvasElement, args }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("20 characters")).toBeDefined(); + + // Click inside the editor + await userEvent.click(canvas.getByText("Hello World")); + + // Select "Hello World" text + selectText(canvas.getByText("Hello World")); + + // Click on button with aria-label "italic" + await userEvent.click(canvas.getByLabelText("Italic")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue?.mock?.calls?.length > 0); + + // Check if args was triggered with new content + expect(args.updateModelValue).toHaveBeenCalledWith( + "

Hello World

Some text

", + ); + }, +}); + +export const MakeFontUnderline: MtTextEditorStory = defineStory({ + name: "Should make font underline", + args: { + modelValue: "

Hello World

Some text

", + }, + play: async ({ canvasElement, args }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("20 characters")).toBeDefined(); + + // Click inside the editor + await userEvent.click(canvas.getByText("Hello World")); + + // Select "Hello World" text + selectText(canvas.getByText("Hello World")); + + // Click on button with aria-label "underline" + await userEvent.click(canvas.getByLabelText("Underline")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue?.mock?.calls?.length > 0); + + // Check if args was triggered with new content + expect(args.updateModelValue).toHaveBeenCalledWith( + "

Hello World

Some text

", + ); + }, +}); + +export const MakeFontStrikeThrough: MtTextEditorStory = defineStory({ + name: "Should make font strike through", + args: { + modelValue: "

Hello World

Some text

", + }, + play: async ({ canvasElement, args }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("20 characters")).toBeDefined(); + + // Click inside the editor + await userEvent.click(canvas.getByText("Hello World")); + + // Select "Hello World" text + selectText(canvas.getByText("Hello World")); + + // Click on button with aria-label "strike-through" + await userEvent.click(canvas.getByLabelText("Strikethrough")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue?.mock?.calls?.length > 0); + + // Check if args was triggered with new content + expect(args.updateModelValue).toHaveBeenCalledWith( + "

Hello World

Some text

", + ); + }, +}); + +export const MakeFontSuperScript: MtTextEditorStory = defineStory({ + name: "Should make font super script", + args: { + modelValue: "

Hello World

Some text

", + }, + play: async ({ canvasElement, args }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("20 characters")).toBeDefined(); + + // Click inside the editor + await userEvent.click(canvas.getByText("Hello World")); + + // Select "Hello World" text + selectText(canvas.getByText("Hello World")); + + // Click on button with aria-label "superscript" + await userEvent.click(canvas.getByLabelText("Superscript")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue?.mock?.calls?.length > 0); + + // Check if args was triggered with new content + expect(args.updateModelValue).toHaveBeenCalledWith( + "

Hello World

Some text

", + ); + }, +}); + +export const MakeFontSubScript: MtTextEditorStory = defineStory({ + name: "Should make font sub script", + args: { + modelValue: "

Hello World

Some text

", + }, + play: async ({ canvasElement, args }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("20 characters")).toBeDefined(); + + // Click inside the editor + await userEvent.click(canvas.getByText("Hello World")); + + // Select "Hello World" text + selectText(canvas.getByText("Hello World")); + + // Click on button with aria-label "subscript" + await userEvent.click(canvas.getByLabelText("Subscript")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue?.mock?.calls?.length > 0); + + // Check if args was triggered with new content + expect(args.updateModelValue).toHaveBeenCalledWith( + "

Hello World

Some text

", + ); + }, +}); + +export const SetTextAlignmentLeft: MtTextEditorStory = defineStory({ + name: "Should set text alignment left", + args: { + modelValue: "

Hello World

Some text

", + }, + play: async ({ canvasElement, args, screen }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("20 characters")).toBeDefined(); + + // Click inside the editor + await userEvent.click(canvas.getByText("Hello World")); + + // Select "Hello World" text + selectText(canvas.getByText("Hello World")); + + // Click on button with aria-label "Text Alignment" + await userEvent.click(canvas.getByLabelText("Text Alignment")); + + // Click on menuitem with text "Align left" + await userEvent.click(screen.getByText("Align left")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue?.mock?.calls?.length > 0); + + // Check if args was triggered with new content (no change expected because left is default) + expect(args.updateModelValue).toHaveBeenCalledWith("

Hello World

Some text

"); + }, +}); + +export const SetTextAlignmentCenter: MtTextEditorStory = defineStory({ + name: "Should set text alignment center", + args: { + modelValue: "

Hello World

Some text

", + }, + play: async ({ canvasElement, args, screen }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("20 characters")).toBeDefined(); + + // Click inside the editor + await userEvent.click(canvas.getByText("Hello World")); + + // Select "Hello World" text + selectText(canvas.getByText("Hello World")); + + // Click on button with aria-label "Text Alignment" + await userEvent.click(canvas.getByLabelText("Text Alignment")); + + // Click on menuitem with text "Align center" + await userEvent.click(screen.getByText("Align center")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue?.mock?.calls?.length > 0); + + // Check if args was triggered with new content + expect(args.updateModelValue).toHaveBeenCalledWith( + '

Hello World

Some text

', + ); + }, +}); + +export const SetTextAlignmentRight: MtTextEditorStory = defineStory({ + name: "Should set text alignment right", + args: { + modelValue: "

Hello World

Some text

", + }, + play: async ({ canvasElement, args, screen }) => { + const canvas = within(canvasElement); + + expect(canvas.getByText("20 characters")).toBeDefined(); + + // Click inside the editor + await userEvent.click(canvas.getByText("Hello World")); + + // Select "Hello World" text + selectText(canvas.getByText("Hello World")); + + // Click on button with aria-label "Text Alignment" + await userEvent.click(canvas.getByLabelText("Text Alignment")); + + // Click on menuitem with text "Align right" + await userEvent.click(screen.getByText("Align right")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue?.mock?.calls?.length > 0); + + // Check if args was triggered with new content + expect(args.updateModelValue).toHaveBeenCalledWith( + '

Hello World

Some text

', + ); + }, +}); + +export const SetTextAlignmentJustify: MtTextEditorStory = defineStory({ + name: "Should set text alignment justify", + args: { + modelValue: "

Hello World

Some text

", + }, + play: async ({ canvasElement, args, screen }) => { + const canvas = within(canvasElement); + + // Click inside the editor + await userEvent.click(canvas.getByText("Hello World")); + + // Select "Hello World" text + selectText(canvas.getByText("Hello World")); + + // Click on button with aria-label "Text Alignment" + await userEvent.click(canvas.getByLabelText("Text Alignment")); + + // Click on menuitem with text "Align justify" + await userEvent.click(screen.getByText("Justify")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue?.mock?.calls?.length > 0); + + // Check if args was triggered with new content + expect(args.updateModelValue).toHaveBeenCalledWith( + '

Hello World

Some text

', + ); + }, +}); + +export const SetUnorderedList: MtTextEditorStory = defineStory({ + name: "Should set unordered list", + args: { + modelValue: "

Hello World

Some text

", + }, + play: async ({ canvasElement, args }) => { + const canvas = within(canvasElement); + + // Click inside the editor + await userEvent.click(canvas.getByText("Hello World")); + + // Select "Hello World" text + selectText(canvas.getByText("Hello World")); + + // Click on button with aria-label "Unordered list" + await userEvent.click(canvas.getByLabelText("Insert Unordered List")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue?.mock?.calls?.length > 0); + + // Check if args was triggered with new content + expect(args.updateModelValue).toHaveBeenCalledWith( + "

Some text

", + ); + }, +}); + +export const SetOrderedList: MtTextEditorStory = defineStory({ + name: "Should set ordered list", + args: { + modelValue: "

Hello World

Some text

", + }, + play: async ({ canvasElement, args }) => { + const canvas = within(canvasElement); + + // Click inside the editor + await userEvent.click(canvas.getByText("Hello World")); + + // Select "Hello World" text + selectText(canvas.getByText("Hello World")); + + // Click on button with aria-label "Ordered list" + await userEvent.click(canvas.getByLabelText("Insert Ordered List")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue?.mock?.calls?.length > 0); + + // Check if args was triggered with new content + expect(args.updateModelValue).toHaveBeenCalledWith( + "
  1. Hello World

Some text

", + ); + }, +}); + +export const SetLink: MtTextEditorStory = defineStory({ + name: "Should set link", + args: { + modelValue: "

Hello World

Some text

", + }, + play: async ({ canvasElement, args }) => { + const canvas = within(canvasElement); + + // Click inside the editor + await userEvent.click(canvas.getByText("Hello World")); + + // Select "Hello World" text + selectText(canvas.getByText("Hello World")); + + // Click on button with aria-label "Link" + await userEvent.click(canvas.getByLabelText("Link")); + + // Get body + const body = within(document.body); + + // Set link url + const linkInput = body.getByLabelText("Link URL"); + await userEvent.clear(linkInput); + await userEvent.type(linkInput, "https://www.shopware.com"); + + // Toggle link target + const targetCheckbox = document.querySelector( + "div[aria-label='Open in new tab'] input[type='checkbox'", + ) as HTMLInputElement; + await userEvent.click(targetCheckbox); + + // Click on button with text "Apply link" + await userEvent.click(body.getByText("Apply link")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue?.mock?.calls?.length > 0); + + // Check if args was triggered with new content + expect(args.updateModelValue).toHaveBeenCalledWith( + '

Hello World

Some text

', + ); + }, +}); + +export const InsertTable: MtTextEditorStory = defineStory({ + name: "Should insert table", + args: { + modelValue: "

Hello World

Some text

", + }, + play: async ({ canvasElement, args }) => { + const canvas = within(canvasElement); + + // Click on button with aria-label "Table" + await userEvent.click(canvas.getByLabelText("Table")); + + // Get body + const body = within(document.body); + + // Set table columns + const columnsInput = body.getByLabelText("Columns"); + await userEvent.type(columnsInput, "{selectall}{backspace}4"); + + // Set table rows + const rowsInput = body.getByLabelText("Rows"); + await userEvent.type(rowsInput, "{selectall}{backspace}2"); + + // Click on button with text "Insert table" + await userEvent.click(body.getByText("Insert table")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue?.mock?.calls?.length > 0); + + // Check if args was triggered with new content + expect(args.updateModelValue).toHaveBeenCalledWith( + '

Hello World

Some text

', + ); + }, +}); + +export const VisualTestShowContextualButtons: MtTextEditorStory = defineStory({ + name: "Should show contextual buttons when inside a table", + args: { + modelValue: "

Hello World

Some text

", + }, + play: async ({ canvasElement, args }) => { + const canvas = within(canvasElement); + + // Click on button with aria-label "Table" + await userEvent.click(canvas.getByLabelText("Table")); + + // Get body + const body = within(document.body); + + // Wait until modal transition is finished + await waitUntil(() => document.body.querySelector("div[role='dialog']")); + await waitUntil(() => !document.body.querySelector(".modal-enter-active")); + + // Set table columns + const columnsInput = body.getByLabelText("Columns"); + await userEvent.type(columnsInput, "{selectall}{backspace}4"); + + // Set table rows + const rowsInput = body.getByLabelText("Rows"); + await userEvent.type(rowsInput, "{selectall}{backspace}2"); + + // Click on button with text "Insert table" + await userEvent.click(body.getByText("Insert table")); + + // Wait until modal is closed + await waitUntil(() => !document.body.querySelector("div[role='dialog']")); + + // Wait until args was triggered with new content + await waitUntil(() => args.updateModelValue?.mock?.calls?.length > 0); + + // Click inside a table cell + const tableCell = document.querySelector( + ".mt-text-editor__content-editor table td", + ) as HTMLElement; + await userEvent.click(tableCell); + + // Expect the contextual buttons to be rendered + expect(canvas.getByLabelText("Insert row before")).toBeDefined(); + expect(canvas.getByLabelText("Insert row after")).toBeDefined(); + expect(canvas.getByLabelText("Delete row")).toBeDefined(); + expect(canvas.getByLabelText("Insert column before")).toBeDefined(); + expect(canvas.getByLabelText("Insert column after")).toBeDefined(); + expect(canvas.getByLabelText("Delete column")).toBeDefined(); + expect(canvas.getByLabelText("Remove table")).toBeDefined(); + }, +}); + +export const VisualTestRenderCodeView: MtTextEditorStory = defineStory({ + name: "Should render the code view", + args: { + modelValue: "

Hello World

Some text

", + }, + play: async ({ canvasElement }) => { + const canvas = within(canvasElement); + + // Click on button with aria-label "Toggle code" + await userEvent.click(canvas.getByLabelText("Toggle code")); + + // Expect the code view to be rendered + const codeEditor = canvas.getByRole("textbox"); + expect(codeEditor).toBeDefined(); + expect(codeEditor.innerText).toBe("

Hello World

Some text

"); + }, +}); diff --git a/packages/component-library/src/components/form/mt-text-editor/mt-text-editor.mdx b/packages/component-library/src/components/form/mt-text-editor/mt-text-editor.mdx new file mode 100644 index 000000000..48e8d06c5 --- /dev/null +++ b/packages/component-library/src/components/form/mt-text-editor/mt-text-editor.mdx @@ -0,0 +1,445 @@ +import { Canvas, Meta, Markdown } from "@storybook/blocks"; + +import * as TextEditorStories from "./mt-text-editor.stories"; + + + +# Text Editor + +The `mt-text-editor` component is a powerful and flexible rich text editor built with [tiptap](https://tiptap.dev/). It is designed to handle a variety of use cases, such as adding rich text editing to your application. This component is highly customizable and can be extended with additional buttons, features, or configurations to suit your needs. + +## Features + +- **Rich Text Editing**: Includes common formatting options like bold, italic, underline, and more, with support for text alignment, bullet lists, ordered lists, and more. +- **Customizable Toolbar**: Add or exclude toolbar buttons as per your requirements. +- **Code Editor Mode**: Toggle between WYSIWYG editing and raw HTML editing with CodeMirror integration. +- **Character Count**: Displays a live character count at the bottom. +- **Inline Editing**: Option to enable inline editing with a floating toolbar. +- **Contextual Buttons**: Provides custom buttons for the footer of the editor that change contextually based on the current cursor position. + +--- + +## Usage + +To use the `mt-text-editor` component in your project, import it and provide the required props. + +### Minimal Example + +```html + + + +``` + + + +### Inline Editing + +```html + + + +``` + + + +### Custom Toolbar Buttons + +```html + + + +``` + + + +### Props + + + {` +| Prop Name | Type | Default | Description | +| --------------- | ------- | ------- | ----------------------------------------------------------------------- | +| modelValue | String | '' | The HTML content of the editor. Use 'v-model' to bind it to a variable. | +| isInlineEdit | Boolean | 'false' | Enables inline editing with a floating toolbar. | +| tipTapConfig | Object | {} | Custom configuration for the tiptap editor. | +| customButtons | Array | [] | Array of custom buttons to add to the toolbar. | +| excludedButtons | Array | [] | Array of button names to exclude from the toolbar. | +`} + + +--- + +## Slots + +The `mt-text-editor` component provides several slots for customization: + +### `button_` + +Allows you to override or customize specific buttons in the toolbar. For example, to customize the `text-color` button: + +```html + + + +``` + +### `contextual-buttons` + +Provides custom buttons for the footer of the editor. These buttons can change contextually based on the editor's state. + +### `footer-left` and `footer-right` + +Customize the left or right sections of the editor's footer. + +--- + +## Toolbar Buttons + +The `mt-text-editor` includes the following built-in buttons by default: + + + {` +| Button Name | Description | Alignment | Position | +| -------------- | -------------------------------------------------- | --------- | -------- | +| format | Opens a popover with formatting options. | 'left' | 1000 | +| text-color | Allows the user to pick a text color. | 'left' | 2000 | +| bold | Toggles bold text. | 'left' | 3000 | +| italic | Toggles italic text. | 'left' | 4000 | +| underline | Toggles underlined text. | 'left' | 5000 | +| strikethrough | Toggles strikethrough text. | 'left' | 6000 | +| superscript | Toggles superscript text. | 'left' | 7000 | +| subscript | Toggles subscript text. | 'left' | 8000 | +| text-alignment | Opens a popover to set text alignment. | 'left' | 9000 | +| unordered-list | Toggles an unordered list. | 'left' | 10000 | +| numbered-list | Toggles an numbered list. | 'left' | 11000 | +| link | Opens a modal to insert or edit links. | 'left' | 12000 | +| table | Opens a modal to insert or modify tables. | 'left' | 13000 | +| undo | Undoes the last action. | 'right' | 1000 | +| redo | Redoes the last undone action. | 'right' | 2000 | +| toggle-code | Toggles between WYSIWYG mode and raw HTML editing. | 'right' | 3000 | +`} + + +You can exclude or add custom buttons using the `excludedButtons` and `customButtons` props. + +--- + +## Customizing with TipTap Extensions + +The editor uses [tiptap extensions](https://tiptap.dev/guide/extensions) for its features. +You can include custom extensions by passing them through the `tipTapConfig` prop except the hardcoded properties `content`, `editorProps` and `onUpdate`. +For example: + +```html + + + +``` + +--- + +## Customizing with Custom Buttons + +The `mt-text-editor` supports adding custom buttons to the toolbar by passing an array of `CustomButton` objects to the `customButtons` prop. + +### Key Properties of `CustomButton` + +- **`name`** (required): A unique identifier for the button. +- **`label`** (required): The visible label for the button, can be the direct text or a translation key. +- **`icon`**: An optional icon to display instead of the label. You can use an icon name from the Meteor icon set. +- **`isActive`**: A function that determines whether the button is currently active (e.g., for toggling bold or italic formatting). +- **`action`**: A function that executes when the button is clicked. This is where you can apply an editor command. +- **`children`**: An array of child buttons to create a dropdown or multi-level menu. +- **`alignment`**: Specifies whether the button should appear on the left or right side of the toolbar. +- **`position`**: Defines the order of the button in the toolbar. Buttons with lower `position` values appear first. See the table with existing buttons to see their positions. +- **`disabled`**: A function that determines whether the button should be disabled. +- **`contextualButtons`**: A function that returns additional buttons to display in the footer based on the editor's state. + +--- + +### Example: Adding a Simple Custom Button + +Here’s how you can add a simple custom button to toggle bold formatting: + +```html + + + +``` + +### Example: Adding a Dropdown Menu + +You can create a dropdown menu by using the `children` property. Each child button is defined as another `CustomButton` object. + +```html + + + +``` + +--- + +### Example: Adding Contextual Buttons in the Footer + +Contextual buttons are buttons that appear in the editor's footer and can change depending on the editor's current state. Use the `contextualButtons` property to define these. + +```html + + + +``` + +--- + +### Example: Disabling a Button Based on Editor State + +You can disable a button dynamically by providing a `disabled` function. For example, disabling the "Bold" button if the editor is empty: + +```html + + + +``` + +--- + +### Example: Using a complete custom button with the dynamic slot + +For each button a dynamic slot is rendered: `button_${name}`. You can use this slot to replace the automatic rendered button defined in the button object with your own component: + +```html + + + +``` + +--- + +### Positioning Custom Buttons in the Toolbar + +By default, buttons are sorted in the toolbar based on their `position` value. Buttons with lower `position` values appear earlier. The default buttons have predefined positions in increments of `1000`, leaving space for you to insert custom buttons at specific positions. + +For example: + +- Default buttons (like `bold`, `italic`, etc.) have `position` values starting at `1000`. +- You can insert your custom buttons between or after them by specifying values like `1500`, `3500`, or `8500`. + +```js +const customButtons = [ + { + name: "custom-highlight", + label: "Highlight", + icon: "circle-xs", + position: 3500, // Places this button between "Bold" (3000) and "Italic" (4000) + action: (editor) => editor.chain().focus().toggleHighlight().run(), + }, +]; +``` + +--- + +## Code Editor Mode + +The `mt-text-editor` includes a code editor mode for editing raw HTML. This mode is powered by [CodeMirror](https://codemirror.net/). Use the `toggle-code` button to switch between WYSIWYG mode and code mode. diff --git a/packages/component-library/src/components/form/mt-text-editor/mt-text-editor.stories.ts b/packages/component-library/src/components/form/mt-text-editor/mt-text-editor.stories.ts new file mode 100644 index 000000000..0d3cb6e6e --- /dev/null +++ b/packages/component-library/src/components/form/mt-text-editor/mt-text-editor.stories.ts @@ -0,0 +1,81 @@ +import type { StoryObj } from "@storybook/vue3"; +import MtTextEditor from "./mt-text-editor.vue"; +import type { SlottedMeta } from "@/_internal/story-helper"; +import MtTextEditorToolbarButtonColor from "./_internal/mt-text-editor-toolbar-button-color.vue"; +import { ref } from "vue"; +import Highlight from "@tiptap/extension-highlight"; +import { fn } from "@storybook/test"; + +export type MtTextEditorMeta = SlottedMeta< + typeof MtTextEditor, + "default" | "click" | "updateModelValue" +>; + +export default { + title: "Components/Form/mt-text-editor", + component: MtTextEditor, + args: { + modelValue: `

Hello World

Some text

  1. Lorem

  2. Ipsum

First

Second

Third

Lorem

Ipsum

non

dolor

sit

amet

After table

`, + updateModelValue: fn(), + label: "My Text editor", + }, + render: (args) => ({ + components: { MtTextEditor, MtTextEditorToolbarButtonColor }, + setup() { + const currentModelValue = ref(args.modelValue); + const onUpdateModelValue = (value: string) => { + currentModelValue.value = value; + args.updateModelValue(value); + }; + + return { + args, + currentModelValue, + onUpdateModelValue, + }; + }, + template: ` +
+ + + +
`, + }), +} as MtTextEditorMeta; + +export type MtTextEditorStory = StoryObj; + +export const DefaultStory: MtTextEditorStory = { + name: "mt-text-editor", +}; + +export const InlineEditStory: MtTextEditorStory = { + name: "mt-text-editor (inline edit)", + args: { + isInlineEdit: true, + }, +}; + +export const CustomButtonsStory: MtTextEditorStory = { + name: "mt-text-editor (custom buttons)", + args: { + modelValue: `

Hello World

In the toolbar you see now a new highlight button.

`, + tipTapConfig: { + extensions: [Highlight], + }, + customButtons: [ + { + name: "highlight", + label: "Highlight", + icon: "regular-circle-xs", + action: (editor) => { + editor.chain().focus().toggleMark("highlight").run(); + }, + }, + ], + }, +}; diff --git a/packages/component-library/src/components/form/mt-text-editor/mt-text-editor.vue b/packages/component-library/src/components/form/mt-text-editor/mt-text-editor.vue new file mode 100644 index 000000000..c20582b40 --- /dev/null +++ b/packages/component-library/src/components/form/mt-text-editor/mt-text-editor.vue @@ -0,0 +1,690 @@ + + + + + diff --git a/packages/component-library/src/components/form/mt-text-field/mt-text-field.vue b/packages/component-library/src/components/form/mt-text-field/mt-text-field.vue index 861293e9d..733e474cd 100644 --- a/packages/component-library/src/components/form/mt-text-field/mt-text-field.vue +++ b/packages/component-library/src/components/form/mt-text-field/mt-text-field.vue @@ -8,7 +8,7 @@ :disable-inheritance-toggle="disableInheritanceToggle" :copyable="copyable" :copyable-tooltip="copyableTooltip" - :copyable-text="currentValue" + :copyable-text="String(currentValue)" :has-focus="hasFocus" :help-text="helpText" :name="name" @@ -33,6 +33,7 @@ :value="currentValue" :placeholder="placeholder" :maxlength="maxLength" + :aria-label="label" @input="onInput" @change.stop="onChange" @focus="setFocusClass" @@ -53,13 +54,13 @@ diff --git a/packages/component-library/src/composables/useI18n.spec.ts b/packages/component-library/src/composables/useI18n.spec.ts deleted file mode 100644 index cf97ea431..000000000 --- a/packages/component-library/src/composables/useI18n.spec.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { render, screen } from "@testing-library/vue"; -import { useI18n } from "./useI18n"; - -describe("useI18n", () => { - it("returns the translation for the given path", () => { - render({ - setup() { - const { t } = useI18n({ - messages: { en: { greeting: "Hello!" } }, - }); - - return { t }; - }, - template: "{{ t('greeting') }}", - }); - - expect(screen.getByText("Hello!")).toBeInTheDocument(); - }); - - it("returns the path to the translation if no translation is found", () => { - render({ - setup() { - const { t } = useI18n({ - messages: { en: { greeting: "Hello!" } }, - }); - - return { t }; - }, - template: "{{ t('path.to.translation') }}", - }); - - expect(screen.getByText("path.to.translation")).toBeInTheDocument(); - }); - - it("translates the snippet with custom values", () => { - render({ - setup() { - const { t } = useI18n({ - messages: { en: { greeting: "Hello, {name}!" } }, - }); - - return { t }; - }, - template: "{{ t('greeting', { name: 'World' }) }}", - }); - - expect(screen.getByText("Hello, World!")).toBeInTheDocument(); - }); - - it("keeps the custom value syntax when no custom value is provided", () => { - render({ - setup() { - const { t } = useI18n({ - messages: { en: { greeting: "Hello, {name}!" } }, - }); - - return { t }; - }, - template: "{{ t('greeting') }}", - }); - - expect(screen.getByText("Hello, {name}!")).toBeInTheDocument(); - }); - - it("translates the singular version", () => { - render({ - setup() { - const { t } = useI18n({ - messages: { en: { apple: "apple | apples" } }, - }); - - return { t }; - }, - template: "{{ t('apple', { n: 1 }) }}", - }); - - expect(screen.getByText("apple")).toBeInTheDocument(); - }); - - it("translates the pluralized version", () => { - render({ - setup() { - const { t } = useI18n({ - messages: { en: { apple: "apple | apples" } }, - }); - - return { t }; - }, - template: "{{ t('apple', { n: 2 }) }}", - }); - - expect(screen.getByText("apples")).toBeInTheDocument; - }); - - it("translates the 'none' version", () => { - render({ - setup() { - const { t } = useI18n({ - messages: { en: { apple: "no apple | apple | apples" } }, - }); - - return { t }; - }, - template: "{{ t('apple', { n: 0 }) }}", - }); - - expect(screen.getByText("no apple")).toBeInTheDocument(); - }); - - it("translates the pluralized version with custom values", () => { - render({ - setup() { - const { t } = useI18n({ - messages: { en: { apple: "no apple | apple | {n} apples" } }, - }); - - return { t }; - }, - template: "{{ t('apple', { n: 3 }) }}", - }); - - expect(screen.getByText("3 apples")).toBeInTheDocument(); - }); -}); diff --git a/packages/component-library/src/composables/useI18n.ts b/packages/component-library/src/composables/useI18n.ts deleted file mode 100644 index d94b57cfd..000000000 --- a/packages/component-library/src/composables/useI18n.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { provide, inject } from "vue"; - -function get(obj: Record, path: string): string | undefined { - if (typeof obj !== "object" || obj === null) return undefined; - - const keys = path.split("."); - let result = obj; - - for (const key of keys) { - if (result === undefined || result === null) return undefined; - - // @ts-ignore - result = result[key]; - } - - // @ts-ignore - return result; -} - -interface TranslationDictionary { - [key: string]: string | TranslationDictionary; -} - -type Options = { messages: TranslationDictionary }; - -const defaultI18nState = { - locale: "en", - defaultLocale: "en", -}; - -const i18nInjectionKey = Symbol("mt-i18n"); - -function limit(value: number, max: number) { - return Math.min(value, max); -} - -export function provideI18n(locale: string = "en") { - const state = { - ...defaultI18nState, - locale: locale, - }; - - provide(i18nInjectionKey, state); -} - -const CUSTOM_VALUE_REGEX = /{([^}]*)}/g; - -export function useI18n({ messages }: Options) { - const i18n = inject(i18nInjectionKey, defaultI18nState); - - function translate(path: string, customValues: Record = {}): string { - function resolveCustomKeys(translation: string) { - return translation.replace(CUSTOM_VALUE_REGEX, (match: string, key: string) => { - return Object.prototype.hasOwnProperty.call(customValues, key) - ? customValues[key].toString() - : match; - }); - } - - const translation = - get(messages, `${i18n.locale}.${path}`) || get(messages, `${i18n.defaultLocale}.${path}`); - - if (!translation) return path; - - const canBePluralized = /\|/.test(translation); - if (canBePluralized) { - if (typeof customValues.n !== "number") - throw new Error('The "n" key is required for pluralization'); - - const versions = translation.split("|"); - - // "no apple | apple | apples"; The first version is the zero form - const includesZeroForm = versions.length === 3; - - const index = limit(includesZeroForm ? customValues.n : customValues.n - 1, 2); - const resolvedTranslation = versions.at(index); - if (!resolvedTranslation) return path; - - return resolveCustomKeys(resolvedTranslation); - } - - return resolveCustomKeys(translation); - } - - return { t: translate }; -} diff --git a/packages/component-library/src/index.ts b/packages/component-library/src/index.ts index 727ab29ec..aa8815c7e 100644 --- a/packages/component-library/src/index.ts +++ b/packages/component-library/src/index.ts @@ -37,6 +37,8 @@ import MtThemeProvider from "./components/theme/mt-theme-provider.vue"; import TooltipDirective from "./directives/tooltip.directive"; import DeviceHelperPlugin from "./plugin/device-helper.plugin"; import MtTooltip from "./components/overlay/mt-tooltip/mt-tooltip.vue"; +import MtTextEditor from "./components/form/mt-text-editor/mt-text-editor.vue"; +import MtTextEditorToolbarButton from "./components/form/mt-text-editor/_internal/mt-text-editor-toolbar-button.vue"; // Import SCSS for styling import "./components/assets/scss/all.scss"; @@ -64,6 +66,8 @@ export { MtSwitch, MtTextField, MtTextarea, + MtTextEditor, + MtTextEditorToolbarButton, MtIcon, MtCard, MtEmptyState, diff --git a/packages/component-library/vitest.setup.ts b/packages/component-library/vitest.setup.ts index f149f27ae..fed514b02 100644 --- a/packages/component-library/vitest.setup.ts +++ b/packages/component-library/vitest.setup.ts @@ -1 +1,11 @@ import "@testing-library/jest-dom/vitest"; +import { config } from "@vue/test-utils"; +import { createI18n } from "vue-i18n"; + +const i18n = createI18n({ + legacy: false, + locale: "en", +}); + +// Install a plugin onto VueWrapper +config.global.plugins = [...(config.global.plugins || []), i18n]; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 24b52478f..efdcdcd40 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -184,6 +184,9 @@ importers: vue: specifier: ^3.5.0 version: 3.5.0(typescript@5.6.2) + vue-i18n: + specifier: ^9.9.1 + version: 9.13.1(vue@3.5.0(typescript@5.6.2)) vue-router: specifier: ^4.3.0 version: 4.3.3(vue@3.5.0(typescript@5.6.2)) @@ -279,6 +282,9 @@ importers: packages/component-library: dependencies: + '@codemirror/lang-html': + specifier: ^6.4.9 + version: 6.4.9 '@floating-ui/dom': specifier: ^1.4.3 version: 1.6.5 @@ -300,6 +306,69 @@ importers: '@testing-library/vue': specifier: ^8.1.0 version: 8.1.0(@vue/compiler-sfc@3.5.13)(vue@3.5.13(typescript@5.2.2)) + '@tiptap/extension-bubble-menu': + specifier: ^2.10.0 + version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3) + '@tiptap/extension-bullet-list': + specifier: ^2.10.0 + version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-character-count': + specifier: ^2.10.0 + version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3) + '@tiptap/extension-color': + specifier: ^2.9.1 + version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/extension-text-style@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))) + '@tiptap/extension-highlight': + specifier: ^2.10.3 + version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-link': + specifier: ^2.10.0 + version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3) + '@tiptap/extension-list-item': + specifier: ^2.10.0 + version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-ordered-list': + specifier: ^2.10.0 + version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-placeholder': + specifier: ^2.10.4 + version: 2.10.4(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3) + '@tiptap/extension-subscript': + specifier: ^2.9.1 + version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-superscript': + specifier: ^2.9.1 + version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-table': + specifier: ^2.10.3 + version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3) + '@tiptap/extension-table-cell': + specifier: ^2.10.3 + version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-table-header': + specifier: ^2.10.3 + version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-table-row': + specifier: ^2.10.3 + version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-text-align': + specifier: ^2.9.1 + version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-text-style': + specifier: ^2.9.1 + version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-underline': + specifier: ^2.9.1 + version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/pm': + specifier: ^2.9.1 + version: 2.10.3 + '@tiptap/starter-kit': + specifier: ^2.9.1 + version: 2.10.3 + '@tiptap/vue-3': + specifier: ^2.9.1 + version: 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3)(vue@3.5.13(typescript@5.2.2)) '@vuepic/vue-datepicker': specifier: ^10.0.0 version: 10.0.0(vue@3.5.13(typescript@5.2.2)) @@ -309,6 +378,9 @@ importers: '@vueuse/core': specifier: ^10.7.2 version: 10.11.0(vue@3.5.13(typescript@5.2.2)) + codemirror: + specifier: ^6.0.1 + version: 6.0.1(@lezer/common@1.2.3) date-fns: specifier: ^2.30.0 version: 2.30.0 @@ -327,9 +399,9 @@ importers: nanoid: specifier: ^5.0.7 version: 5.0.7 - vue: - specifier: '>= 3.5.0' - version: 3.5.13(typescript@5.2.2) + vue-codemirror6: + specifier: ^1.3.8 + version: 1.3.8(@lezer/common@1.2.3)(vue@3.5.13(typescript@5.2.2)) vue-i18n: specifier: ^9.9.1 version: 9.13.1(vue@3.5.13(typescript@5.2.2)) @@ -1479,6 +1551,41 @@ packages: resolution: {integrity: sha512-EeEjMobfuJrwoctj7FA1y1KEbM0+Q1xSjobIEyie9k4haVEBB7vkDvsasw1pM3rO39mL2akxIAzLMUAtrMHZhA==} engines: {node: '>=16.13'} + '@codemirror/autocomplete@6.18.3': + resolution: {integrity: sha512-1dNIOmiM0z4BIBwxmxEfA1yoxh1MF/6KPBbh20a5vphGV0ictKlgQsbJs6D6SkR6iJpGbpwRsa6PFMNlg9T9pQ==} + peerDependencies: + '@codemirror/language': ^6.0.0 + '@codemirror/state': ^6.0.0 + '@codemirror/view': ^6.0.0 + '@lezer/common': ^1.0.0 + + '@codemirror/commands@6.7.1': + resolution: {integrity: sha512-llTrboQYw5H4THfhN4U3qCnSZ1SOJ60ohhz+SzU0ADGtwlc533DtklQP0vSFaQuCPDn3BPpOd1GbbnUtwNjsrw==} + + '@codemirror/lang-css@6.3.1': + resolution: {integrity: sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==} + + '@codemirror/lang-html@6.4.9': + resolution: {integrity: sha512-aQv37pIMSlueybId/2PVSP6NPnmurFDVmZwzc7jszd2KAF8qd4VBbvNYPXWQq90WIARjsdVkPbw29pszmHws3Q==} + + '@codemirror/lang-javascript@6.2.2': + resolution: {integrity: sha512-VGQfY+FCc285AhWuwjYxQyUQcYurWlxdKYT4bqwr3Twnd5wP5WSeu52t4tvvuWmljT4EmgEgZCqSieokhtY8hg==} + + '@codemirror/language@6.10.6': + resolution: {integrity: sha512-KrsbdCnxEztLVbB5PycWXFxas4EOyk/fPAfruSOnDDppevQgid2XZ+KbJ9u+fDikP/e7MW7HPBTvTb8JlZK9vA==} + + '@codemirror/lint@6.8.4': + resolution: {integrity: sha512-u4q7PnZlJUojeRe8FJa/njJcMctISGgPQ4PnWsd9268R4ZTtU+tfFYmwkBvgcrK2+QQ8tYFVALVb5fVJykKc5A==} + + '@codemirror/search@6.5.8': + resolution: {integrity: sha512-PoWtZvo7c1XFeZWmmyaOp2G0XVbOnm+fJzvghqGAktBW3cufwJUWvSCcNG0ppXiBEM05mZu6RhMtXPv2hpllig==} + + '@codemirror/state@6.5.0': + resolution: {integrity: sha512-MwBHVK60IiIHDcoMet78lxt6iw5gJOGSbNbOIVBHWVXIH4/Nq1+GQgLLGgI1KlnN86WDXsPudVaqYHKBIx7Eyw==} + + '@codemirror/view@6.35.3': + resolution: {integrity: sha512-ScY7L8+EGdPl4QtoBiOzE4FELp7JmNUsBvgBcCakXWM2uiv/K89VAzU3BMDscf0DsACLvTKePbd5+cFDTcei6g==} + '@colors/colors@1.5.0': resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} engines: {node: '>=0.1.90'} @@ -2543,6 +2650,24 @@ packages: '@leichtgewicht/ip-codec@2.0.5': resolution: {integrity: sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==} + '@lezer/common@1.2.3': + resolution: {integrity: sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA==} + + '@lezer/css@1.1.9': + resolution: {integrity: sha512-TYwgljcDv+YrV0MZFFvYFQHCfGgbPMR6nuqLabBdmZoFH3EP1gvw8t0vae326Ne3PszQkbXfVBjCnf3ZVCr0bA==} + + '@lezer/highlight@1.2.1': + resolution: {integrity: sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA==} + + '@lezer/html@1.3.10': + resolution: {integrity: sha512-dqpT8nISx/p9Do3AchvYGV3qYc4/rKr3IBZxlHmpIKam56P47RSHkSF5f13Vu9hebS1jM0HmtJIwLbWz1VIY6w==} + + '@lezer/javascript@1.4.21': + resolution: {integrity: sha512-lL+1fcuxWYPURMM/oFZLEDm0XuLN128QPV+VuGtKpeaOGdcl9F2LYC3nh1S9LkPqx9M0mndZFdXCipNAZpzIkQ==} + + '@lezer/lr@1.4.2': + resolution: {integrity: sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA==} + '@manypkg/find-root@1.1.0': resolution: {integrity: sha512-mki5uBvhHzO8kYYix/WRy2WX8S3B5wdVSc9D6KcU5lQNglP2yt58/VfLuAK49glRXChosY8ap2oJ1qgma3GUVA==} @@ -2553,6 +2678,9 @@ packages: resolution: {integrity: sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==} hasBin: true + '@marijn/find-cluster-break@1.0.2': + resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==} + '@mdx-js/mdx@1.6.22': resolution: {integrity: sha512-AMxuLxPz2j5/6TpF/XSdKpQP1NlG0z11dFOlq+2IP/lSgl11GY8ji6S/rgsViN/L0BDvHvUMruRb7ub+24LUYA==} @@ -2867,6 +2995,12 @@ packages: '@polka/url@1.0.0-next.25': resolution: {integrity: sha512-j7P6Rgr3mmtdkeDGTe0E/aYyWEWVtc5yFXtHCRHs28/jptDEWfaVOc5T7cblqy1XKPPfCxJc/8DwQ5YgLOZOVQ==} + '@popperjs/core@2.11.8': + resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} + + '@remirror/core-constants@3.0.0': + resolution: {integrity: sha512-42aWfPrimMfDKDi4YegyS7x+/0tlzaqwPQCULLanv3DMIlu96KTJR0fM5isWX2UViOqlGnX6YFgqWepcX+XMNg==} + '@rollup/plugin-alias@5.1.0': resolution: {integrity: sha512-lpA3RZ9PdIG7qqhEfv79tBffNaoDuukFDrmhLqg9ifv99u/ehn+lOg30x2zmhf8AQqQUZaMk/B9fZraQ6/acDQ==} engines: {node: '>=14.0.0'} @@ -3590,6 +3724,206 @@ packages: '@vue/compiler-sfc': optional: true + '@tiptap/core@2.10.3': + resolution: {integrity: sha512-wAG/0/UsLeZLmshWb6rtWNXKJftcmnned91/HLccHVQAuQZ1UWH+wXeQKu/mtodxEO7JcU2mVPR9mLGQkK0McQ==} + peerDependencies: + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-blockquote@2.10.3': + resolution: {integrity: sha512-u9Mq4r8KzoeGVT8ms6FQDIMN95dTh3TYcT7fZpwcVM96mIl2Oyt+Bk66mL8z4zuFptfRI57Cu9QdnHEeILd//w==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-bold@2.10.3': + resolution: {integrity: sha512-xnF1tS2BsORenr11qyybW120gHaeHKiKq+ZOP14cGA0MsriKvWDnaCSocXP/xMEYHy7+2uUhJ0MsKkHVj4bPzQ==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-bubble-menu@2.10.3': + resolution: {integrity: sha512-e9a4yMjQezuKy0rtyyzxbV2IAE1bm1PY3yoZEFrcaY0o47g1CMUn2Hwe+9As2HdntEjQpWR7NO1mZeKxHlBPYA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-bullet-list@2.10.3': + resolution: {integrity: sha512-PTkwJOVlHi4RR4Wrs044tKMceweXwNmWA6EoQ93hPUVtQcwQL990Es5Izp+i88twTPLuGD9dH+o9QDyH9SkWdA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-character-count@2.10.3': + resolution: {integrity: sha512-7L3VS9+SZqwK94/Yk4c+NEpI6kDUAYW3tYGuxCRiKHDlUy3fkXkVkPlxsoNUpAA4O05KGAwD0YW5rvAkNXdi8w==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-code-block@2.10.3': + resolution: {integrity: sha512-yiDVNg22fYkzsFk5kBlDSHcjwVJgajvO/M5fDXA+Hfxwo2oNcG6aJyyHXFe+UaXTVjdkPej0J6kcMKrTMCiFug==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-code@2.10.3': + resolution: {integrity: sha512-JyLbfyY3cPctq9sVdpcRWTcoUOoq3/MnGE1eP6eBNyMTHyBPcM9TPhOkgj+xkD1zW/884jfelB+wa70RT/AMxQ==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-color@2.10.3': + resolution: {integrity: sha512-FC2hPMSQ4w9UmO9kJCAdoU7gHpDbJ6MeJAmikB9EPp16dbGwFLrZm9TZ/4pv74fGfVm0lv720316ALOEgPEDjQ==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/extension-text-style': ^2.7.0 + + '@tiptap/extension-document@2.10.3': + resolution: {integrity: sha512-6i8+xbS2zB6t8iFzli1O/QB01MmwyI5Hqiiv4m5lOxqavmJwLss2sRhoMC2hB3CyFg5UmeODy/f/RnI6q5Vixg==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-dropcursor@2.10.3': + resolution: {integrity: sha512-wzWf82ixWzZQr0hxcf/A0ul8NNxgy1N63O+c56st6OomoLuKUJWOXF+cs9O7V+/5rZKWdbdYYoRB5QLvnDBAlQ==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-floating-menu@2.10.3': + resolution: {integrity: sha512-Prg8rYLxeyzHxfzVu1mDkkUWMnD9ZN3y370O/1qy55e+XKVw9jFkTSuz0y0+OhMJG6bulYpDUMtb+N3+2xOWlQ==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-gapcursor@2.10.3': + resolution: {integrity: sha512-FskZi2DqDSTH1WkgLF2OLy0xU7qj3AgHsKhVsryeAtld4jAK5EsonneWgaipbz0e/MxuIvc1oyacfZKABpLaNg==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-hard-break@2.10.3': + resolution: {integrity: sha512-2rFlimUKAgKDwT6nqAMtPBjkrknQY8S7oBNyIcDOUGyFkvbDUl3Jd0PiC929S5F3XStJRppnMqhpNDAlWmvBLA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-heading@2.10.3': + resolution: {integrity: sha512-AlxXXPCWIvw8hQUDFRskasj32iMNB8Sb19VgyFWqwvntGs2/UffNu8VdsVqxD2HpZ0g5rLYCYtSW4wigs9R3og==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-highlight@2.10.3': + resolution: {integrity: sha512-srMOdpUTcp1yPGmUqgKOkbmTpCYOF6Q/8CnquDkhrvK7Gyphj+n8TocrKiloaRYZKcoQWtmb+kcVPaHhHMzsWQ==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-history@2.10.3': + resolution: {integrity: sha512-HaSiMdx9Im9Pb9qGlVud7W8bweRDRMez33Uzs5a2x0n1RWkelfH7TwYs41Y3wus8Ujs7kw6qh7jyhvPpQBKaSA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-horizontal-rule@2.10.3': + resolution: {integrity: sha512-1a2IWhD00tgUNg/91RLnBvfENL7DLCui5L245+smcaLu+OXOOEpoBHawx59/M4hEpsjqvRRM79TzO9YXfopsPw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-italic@2.10.3': + resolution: {integrity: sha512-wAiO6ZxoHx2H90phnKttLWGPjPZXrfKxhOCsqYrK8BpRByhr48godOFRuGwYnKaiwoVjpxc63t+kDJDWvqmgMw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-link@2.10.3': + resolution: {integrity: sha512-8esKlkZBzEiNcpt7I8Cd6l1mWmCc/66pPbUq9LfnIniDXE3U+ahBf4m3TJltYFBGbiiTR/xqMtJyVHOpuLDtAw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-list-item@2.10.3': + resolution: {integrity: sha512-9sok81gvZfSta2K1Dwrq5/HSz1jk4zHBpFqCx0oydzodGslx6X1bNxdca+eXJpXZmQIWALK7zEr4X8kg3WZsgw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-ordered-list@2.10.3': + resolution: {integrity: sha512-/SFuEDnbJxy3jvi72LeyiPHWkV+uFc0LUHTUHSh20vwyy+tLrzncJfXohGbTIv5YxYhzExQYZDRD4VbSghKdlw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-paragraph@2.10.3': + resolution: {integrity: sha512-sNkTX/iN+YoleDiTJsrWSBw9D7c4vsYwnW5y/G5ydfuJMIRQMF78pWSIWZFDRNOMkgK5UHkhu9anrbCFYgBfaA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-placeholder@2.10.4': + resolution: {integrity: sha512-leWG4xP7cvddR6alGZS7yojOh9941bxehgAeQDLlEisaJcNa2Od5Vbap2zipjc5sXMxZakQVChL27oH1wWhHkQ==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-strike@2.10.3': + resolution: {integrity: sha512-jYoPy6F6njYp3txF3u23bgdRy/S5ATcWDO9LPZLHSeikwQfJ47nqb+EUNo5M8jIOgFBTn4MEbhuZ6OGyhnxopA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-subscript@2.10.3': + resolution: {integrity: sha512-GkOwXIruM7QksmlfqLTKTC6JBpWSBDN2eeoPwggxXuqetqYs4sIx1ul3LEGDQy0vglcFKGkbbO2IiHCO/0fSWA==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-superscript@2.10.3': + resolution: {integrity: sha512-4bXDPyT10ByVCLXFR8A70TcpFJ0H3PicRsxKJcQ+KZIauNUo5BBUpkF2cK+IOUp4UZ1W5ZBeuMQG5HWMuV9T1A==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-table-cell@2.10.3': + resolution: {integrity: sha512-EYzBrnq7KUAcRhshIoTmC4ED8YoF4Ei5m8ZMPOctKX+QMAagKdcrw2UxuOf4tP2xgBYx+qDsKCautepZXQiL2g==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-table-header@2.10.3': + resolution: {integrity: sha512-zJqzivz+VITYIFXNH09leBbkwAPuvp504rCAFL2PMa1uaME6+oiiRqZvXQrOiRkjNpOWEXH4dqvVLwkSMZoWaw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-table-row@2.10.3': + resolution: {integrity: sha512-l6P6BAE4SuIFdPmsRd+zGP2Ks9AhLAua7nfDlHFMWDnfOeaJu7g/t4oG++9xTojDcVDHhcIe8TJYUXfhOt2anw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-table@2.10.3': + resolution: {integrity: sha512-XAvq0ptpHfuN7lQhTeew4Sqo8aKYHTqroa7cHL8I+gWJqYqKJSTGb4FAqdGIFEzHvnSsMCFbTL//kAHXvTdsHg==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + + '@tiptap/extension-text-align@2.10.3': + resolution: {integrity: sha512-g75sNl73gtgjP3XIcl06kvv1qw3c0rGEUD848rUU1bvlBpU3IxjkcQLgYvHmv3vpuUp9cKUkA2wa7Sv6R3fjvw==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-text-style@2.10.3': + resolution: {integrity: sha512-TalYIdlF7vBA4afFhmido7AORdBbu3sV+HCByda0FiNbM6cjng3Nr9oxHOCVJy+ChqrcgF4m54zDfLmamdyu5Q==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-text@2.10.3': + resolution: {integrity: sha512-7p9XiRprsRZm8y9jvF/sS929FCELJ5N9FQnbzikOiyGNUx5mdI+exVZlfvBr9xOD5s7fBLg6jj9Vs0fXPNRkPg==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/extension-underline@2.10.3': + resolution: {integrity: sha512-VeGs0jeNiTnXddHHJEgOc/sKljZiyTEgSSuqMmsBACrr9aGFXbLTgKTvNjkZ9WzSnu7LwgJuBrwEhg8yYixUyQ==} + peerDependencies: + '@tiptap/core': ^2.7.0 + + '@tiptap/pm@2.10.3': + resolution: {integrity: sha512-771p53aU0KFvujvKpngvq2uAxThlEsjYaXcVVmwrhf0vxSSg+psKQEvqvWvHv/3BwkPVCGwmEKNVJZjaXFKu4g==} + + '@tiptap/starter-kit@2.10.3': + resolution: {integrity: sha512-oq8xdVIMqohSs91ofHSr7i5dCp2F56Lb9aYIAI25lZmwNwQJL2geGOYjMSfL0IC4cQHPylIuSKYCg7vRFdZmAA==} + + '@tiptap/vue-3@2.10.3': + resolution: {integrity: sha512-eJLUpuKq3Yei3+XHba25eFvjAH6q275r+Dkz/ulStOWGwchlN8OSbcn0kBWfhr14RG8yoNvL4rZncxXvqXzvhQ==} + peerDependencies: + '@tiptap/core': ^2.7.0 + '@tiptap/pm': ^2.7.0 + vue: ^3.0.0 + '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} @@ -3743,15 +4077,24 @@ packages: '@types/keyv@3.1.4': resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} + '@types/linkify-it@5.0.0': + resolution: {integrity: sha512-sVDA58zAw4eWAffKOaQH5/5j3XeayukzDk+ewSsnv3p4yJEZHCCzMDiZM8e0OUrRvmpGZ85jf4yDHkHsgBNr9Q==} + '@types/lodash-es@4.17.12': resolution: {integrity: sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==} '@types/lodash@4.17.5': resolution: {integrity: sha512-MBIOHVZqVqgfro1euRDWX7OO0fBVUUMrN6Pwm8LQsz8cWhEpihlvR70ENj3f40j58TNxZaWv2ndSkInykNBBJw==} + '@types/markdown-it@14.1.2': + resolution: {integrity: sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog==} + '@types/mdast@3.0.15': resolution: {integrity: sha512-LnwD+mUEfxWMa1QpDraczIn6k0Ee3SMicuYSSzS6ZYl2gKS09EClnJYGd8Du6rfc5r/GZEk5o1mRb8TaTj03sQ==} + '@types/mdurl@2.0.0': + resolution: {integrity: sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg==} + '@types/mdx@2.0.13': resolution: {integrity: sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==} @@ -5360,6 +5703,9 @@ packages: code-block-writer@12.0.0: resolution: {integrity: sha512-q4dMFMlXtKR3XNBHyMHt/3pwYNA69EDk00lloMOaaUMKPUXBw6lpXtbu3MMVG6/uOihGnRDOlkyqsONEUj60+w==} + codemirror@6.0.1: + resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==} + collapse-white-space@1.0.6: resolution: {integrity: sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ==} @@ -5590,6 +5936,9 @@ packages: create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + crelt@1.0.6: + resolution: {integrity: sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==} + croner@8.0.2: resolution: {integrity: sha512-HgSdlSUX8mIgDTTiQpWUP4qY4IFRMsduPCYdca34Pelt8MVdxdaDOzreFtCscA6R+cRZd7UbD1CD3uyx6J3X1A==} engines: {node: '>=18.0'} @@ -8579,6 +8928,12 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + linkify-it@5.0.0: + resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} + + linkifyjs@4.2.0: + resolution: {integrity: sha512-pCj3PrQyATaoTYKHrgWRF3SJwsm61udVh+vuls/Rl6SptiDhgE7ziUIudAedRY9QEfynmM7/RmLEfPUyw1HPCw==} + listhen@1.7.2: resolution: {integrity: sha512-7/HamOm5YD9Wb7CFgAZkKgVPA96WwhcTQoqtm2VTZGVbVVn3IWKRBTgrU7cchA3Q8k9iCsG8Osoi9GX4JsGM9g==} hasBin: true @@ -8778,6 +9133,10 @@ packages: markdown-escapes@1.0.4: resolution: {integrity: sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg==} + markdown-it@14.1.0: + resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} + hasBin: true + mathml-tag-names@2.1.3: resolution: {integrity: sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==} @@ -8814,6 +9173,9 @@ packages: mdurl@1.0.1: resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==} + mdurl@2.0.0: + resolution: {integrity: sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==} + media-typer@0.3.0: resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} engines: {node: '>= 0.6'} @@ -9480,6 +9842,9 @@ packages: resolution: {integrity: sha512-ANIvzobt1rls2BDny5fWZ3ZVKyD6nscLvfFRpQgfWsythlcsVUC9kL0zq6j2Z5z9wwp1kd7wpsD/T9qNPVLCaQ==} engines: {node: '>=18'} + orderedmap@2.1.1: + resolution: {integrity: sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==} + os-homedir@1.0.2: resolution: {integrity: sha512-B5JU3cabzk8c67mRRd3ECmROafjYMXbuzlwtqdM8IbS8ktlTix8aFGb2bAGKrSRIlnfKwovGUUr72JUPyOb6kQ==} engines: {node: '>=0.10.0'} @@ -10360,6 +10725,64 @@ packages: property-information@5.6.0: resolution: {integrity: sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA==} + prosemirror-changeset@2.2.1: + resolution: {integrity: sha512-J7msc6wbxB4ekDFj+n9gTW/jav/p53kdlivvuppHsrZXCaQdVgRghoZbSS3kwrRyAstRVQ4/+u5k7YfLgkkQvQ==} + + prosemirror-collab@1.3.1: + resolution: {integrity: sha512-4SnynYR9TTYaQVXd/ieUvsVV4PDMBzrq2xPUWutHivDuOshZXqQ5rGbZM84HEaXKbLdItse7weMGOUdDVcLKEQ==} + + prosemirror-commands@1.6.2: + resolution: {integrity: sha512-0nDHH++qcf/BuPLYvmqZTUUsPJUCPBUXt0J1ErTcDIS369CTp773itzLGIgIXG4LJXOlwYCr44+Mh4ii6MP1QA==} + + prosemirror-dropcursor@1.8.1: + resolution: {integrity: sha512-M30WJdJZLyXHi3N8vxN6Zh5O8ZBbQCz0gURTfPmTIBNQ5pxrdU7A58QkNqfa98YEjSAL1HUyyU34f6Pm5xBSGw==} + + prosemirror-gapcursor@1.3.2: + resolution: {integrity: sha512-wtjswVBd2vaQRrnYZaBCbyDqr232Ed4p2QPtRIUK5FuqHYKGWkEwl08oQM4Tw7DOR0FsasARV5uJFvMZWxdNxQ==} + + prosemirror-history@1.4.1: + resolution: {integrity: sha512-2JZD8z2JviJrboD9cPuX/Sv/1ChFng+xh2tChQ2X4bB2HeK+rra/bmJ3xGntCcjhOqIzSDG6Id7e8RJ9QPXLEQ==} + + prosemirror-inputrules@1.4.0: + resolution: {integrity: sha512-6ygpPRuTJ2lcOXs9JkefieMst63wVJBgHZGl5QOytN7oSZs3Co/BYbc3Yx9zm9H37Bxw8kVzCnDsihsVsL4yEg==} + + prosemirror-keymap@1.2.2: + resolution: {integrity: sha512-EAlXoksqC6Vbocqc0GtzCruZEzYgrn+iiGnNjsJsH4mrnIGex4qbLdWWNza3AW5W36ZRrlBID0eM6bdKH4OStQ==} + + prosemirror-markdown@1.13.1: + resolution: {integrity: sha512-Sl+oMfMtAjWtlcZoj/5L/Q39MpEnVZ840Xo330WJWUvgyhNmLBLN7MsHn07s53nG/KImevWHSE6fEj4q/GihHw==} + + prosemirror-menu@1.2.4: + resolution: {integrity: sha512-S/bXlc0ODQup6aiBbWVsX/eM+xJgCTAfMq/nLqaO5ID/am4wS0tTCIkzwytmao7ypEtjj39i7YbJjAgO20mIqA==} + + prosemirror-model@1.24.1: + resolution: {integrity: sha512-YM053N+vTThzlWJ/AtPtF1j0ebO36nvbmDy4U7qA2XQB8JVaQp1FmB9Jhrps8s+z+uxhhVTny4m20ptUvhk0Mg==} + + prosemirror-schema-basic@1.2.3: + resolution: {integrity: sha512-h+H0OQwZVqMon1PNn0AG9cTfx513zgIG2DY00eJ00Yvgb3UD+GQ/VlWW5rcaxacpCGT1Yx8nuhwXk4+QbXUfJA==} + + prosemirror-schema-list@1.5.0: + resolution: {integrity: sha512-gg1tAfH1sqpECdhIHOA/aLg2VH3ROKBWQ4m8Qp9mBKrOxQRW61zc+gMCI8nh22gnBzd1t2u1/NPLmO3nAa3ssg==} + + prosemirror-state@1.4.3: + resolution: {integrity: sha512-goFKORVbvPuAQaXhpbemJFRKJ2aixr+AZMGiquiqKxaucC6hlpHNZHWgz5R7dS4roHiwq9vDctE//CZ++o0W1Q==} + + prosemirror-tables@1.6.1: + resolution: {integrity: sha512-p8WRJNA96jaNQjhJolmbxTzd6M4huRE5xQ8OxjvMhQUP0Nzpo4zz6TztEiwk6aoqGBhz9lxRWR1yRZLlpQN98w==} + + prosemirror-trailing-node@3.0.0: + resolution: {integrity: sha512-xiun5/3q0w5eRnGYfNlW1uU9W6x5MoFKWwq/0TIRgt09lv7Hcser2QYV8t4muXbEr+Fwo0geYn79Xs4GKywrRQ==} + peerDependencies: + prosemirror-model: ^1.22.1 + prosemirror-state: ^1.4.2 + prosemirror-view: ^1.33.8 + + prosemirror-transform@1.10.2: + resolution: {integrity: sha512-2iUq0wv2iRoJO/zj5mv8uDUriOHWzXRnOTVgCzSXnktS/2iQRa3UUQwVlkBlYZFtygw6Nh1+X4mGqoYBINn5KQ==} + + prosemirror-view@1.37.0: + resolution: {integrity: sha512-z2nkKI1sJzyi7T47Ji/ewBPuIma1RNvQCCYVdV+MqWBV7o4Sa1n94UJCJJ1aQRF/xRkFfyqLGlGFWitIcCOtbg==} + proto-list@1.2.4: resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} @@ -10421,6 +10844,10 @@ packages: pump@3.0.0: resolution: {integrity: sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==} + punycode.js@2.3.1: + resolution: {integrity: sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==} + engines: {node: '>=6'} + punycode@1.4.1: resolution: {integrity: sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==} @@ -10878,6 +11305,9 @@ packages: engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true + rope-sequence@1.3.4: + resolution: {integrity: sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==} + rrweb-cssom@0.6.0: resolution: {integrity: sha512-APM0Gt1KoXBz0iIkkdB/kfvGOwC4UuJFeG/c+yV7wSc7q96cG/kJ0HiYCnzivD9SB53cLV1MlHFNfOuPaadYSw==} @@ -11412,6 +11842,9 @@ packages: engines: {node: '>=12.0.0'} hasBin: true + style-mod@4.1.2: + resolution: {integrity: sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw==} + style-to-object@0.3.0: resolution: {integrity: sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA==} @@ -11698,6 +12131,9 @@ packages: resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==} engines: {node: '>=14.0.0'} + tippy.js@6.3.7: + resolution: {integrity: sha512-E1d3oP2emgJ9dRQZdf3Kkn0qJgI6ZLpyS5z6ZkY1DF3kaQaBsGZsndEpHwx+eC+tYM41HaSNvNtLx8tU57FzTQ==} + tmp@0.0.33: resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} engines: {node: '>=0.6.0'} @@ -12004,6 +12440,9 @@ packages: ua-parser-js@1.0.38: resolution: {integrity: sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ==} + uc.micro@2.1.0: + resolution: {integrity: sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==} + ufo@1.5.3: resolution: {integrity: sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==} @@ -12579,6 +13018,12 @@ packages: vue-bundle-renderer@2.1.0: resolution: {integrity: sha512-uZ+5ZJdZ/b43gMblWtcpikY6spJd0nERaM/1RtgioXNfWFbjKlUwrS8HlrddN6T2xtptmOouWclxLUkpgcVX3Q==} + vue-codemirror6@1.3.8: + resolution: {integrity: sha512-pCOzKzBBSFKi/SjUg+XGranV1vt+8S22z56BES/OeZtmyuj2M0CE0aczYS8qbTWNnKcuJcI5FRDHzVXy2v2Htg==} + engines: {pnpm: '>=9.14.2'} + peerDependencies: + vue: ^2.7.14 || ^3.4 + vue-component-meta@2.0.21: resolution: {integrity: sha512-K7B/wu1nrtYnrDkCkrqqllIe2bxbKNtQG/kc/cquMNw0PYt5xbnAItXZLhC2tHtiIlw6DPYFKpAhnFDi2NGqeA==} peerDependencies: @@ -12590,8 +13035,19 @@ packages: vue-component-type-helpers@2.0.21: resolution: {integrity: sha512-3NaicyZ7N4B6cft4bfb7dOnPbE9CjLcx+6wZWAg5zwszfO4qXRh+U52dN5r5ZZfc6iMaxKCEcoH9CmxxoFZHLg==} - vue-component-type-helpers@2.1.10: - resolution: {integrity: sha512-lfgdSLQKrUmADiSV6PbBvYgQ33KF3Ztv6gP85MfGaGaSGMTXORVaHT1EHfsqCgzRNBstPKYDmvAV9Do5CmJ07A==} + vue-component-type-helpers@2.2.0: + resolution: {integrity: sha512-cYrAnv2me7bPDcg9kIcGwjJiSB6Qyi08+jLDo9yuvoFQjzHiPTzML7RnkJB1+3P6KMsX/KbCD4QE3Tv/knEllw==} + + vue-demi@0.14.10: + resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} + engines: {node: '>=12'} + hasBin: true + peerDependencies: + '@vue/composition-api': ^1.0.0-rc.1 + vue: ^3.0.0-0 || ^2.6.0 + peerDependenciesMeta: + '@vue/composition-api': + optional: true vue-demi@0.14.8: resolution: {integrity: sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==} @@ -12698,6 +13154,9 @@ packages: resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==} deprecated: Use your platform's native performance.now() and performance.timeOrigin. + w3c-keyname@2.2.8: + resolution: {integrity: sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==} + w3c-xmlserializer@2.0.0: resolution: {integrity: sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==} engines: {node: '>=10'} @@ -14361,6 +14820,83 @@ snapshots: dependencies: mime: 3.0.0 + '@codemirror/autocomplete@6.18.3(@codemirror/language@6.10.6)(@codemirror/state@6.5.0)(@codemirror/view@6.35.3)(@lezer/common@1.2.3)': + dependencies: + '@codemirror/language': 6.10.6 + '@codemirror/state': 6.5.0 + '@codemirror/view': 6.35.3 + '@lezer/common': 1.2.3 + + '@codemirror/commands@6.7.1': + dependencies: + '@codemirror/language': 6.10.6 + '@codemirror/state': 6.5.0 + '@codemirror/view': 6.35.3 + '@lezer/common': 1.2.3 + + '@codemirror/lang-css@6.3.1(@codemirror/view@6.35.3)': + dependencies: + '@codemirror/autocomplete': 6.18.3(@codemirror/language@6.10.6)(@codemirror/state@6.5.0)(@codemirror/view@6.35.3)(@lezer/common@1.2.3) + '@codemirror/language': 6.10.6 + '@codemirror/state': 6.5.0 + '@lezer/common': 1.2.3 + '@lezer/css': 1.1.9 + transitivePeerDependencies: + - '@codemirror/view' + + '@codemirror/lang-html@6.4.9': + dependencies: + '@codemirror/autocomplete': 6.18.3(@codemirror/language@6.10.6)(@codemirror/state@6.5.0)(@codemirror/view@6.35.3)(@lezer/common@1.2.3) + '@codemirror/lang-css': 6.3.1(@codemirror/view@6.35.3) + '@codemirror/lang-javascript': 6.2.2 + '@codemirror/language': 6.10.6 + '@codemirror/state': 6.5.0 + '@codemirror/view': 6.35.3 + '@lezer/common': 1.2.3 + '@lezer/css': 1.1.9 + '@lezer/html': 1.3.10 + + '@codemirror/lang-javascript@6.2.2': + dependencies: + '@codemirror/autocomplete': 6.18.3(@codemirror/language@6.10.6)(@codemirror/state@6.5.0)(@codemirror/view@6.35.3)(@lezer/common@1.2.3) + '@codemirror/language': 6.10.6 + '@codemirror/lint': 6.8.4 + '@codemirror/state': 6.5.0 + '@codemirror/view': 6.35.3 + '@lezer/common': 1.2.3 + '@lezer/javascript': 1.4.21 + + '@codemirror/language@6.10.6': + dependencies: + '@codemirror/state': 6.5.0 + '@codemirror/view': 6.35.3 + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + style-mod: 4.1.2 + + '@codemirror/lint@6.8.4': + dependencies: + '@codemirror/state': 6.5.0 + '@codemirror/view': 6.35.3 + crelt: 1.0.6 + + '@codemirror/search@6.5.8': + dependencies: + '@codemirror/state': 6.5.0 + '@codemirror/view': 6.35.3 + crelt: 1.0.6 + + '@codemirror/state@6.5.0': + dependencies: + '@marijn/find-cluster-break': 1.0.2 + + '@codemirror/view@6.35.3': + dependencies: + '@codemirror/state': 6.5.0 + style-mod: 4.1.2 + w3c-keyname: 2.2.8 + '@colors/colors@1.5.0': optional: true @@ -15993,6 +16529,34 @@ snapshots: '@leichtgewicht/ip-codec@2.0.5': {} + '@lezer/common@1.2.3': {} + + '@lezer/css@1.1.9': + dependencies: + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + + '@lezer/highlight@1.2.1': + dependencies: + '@lezer/common': 1.2.3 + + '@lezer/html@1.3.10': + dependencies: + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + + '@lezer/javascript@1.4.21': + dependencies: + '@lezer/common': 1.2.3 + '@lezer/highlight': 1.2.1 + '@lezer/lr': 1.4.2 + + '@lezer/lr@1.4.2': + dependencies: + '@lezer/common': 1.2.3 + '@manypkg/find-root@1.1.0': dependencies: '@babel/runtime': 7.24.7 @@ -16024,6 +16588,8 @@ snapshots: - encoding - supports-color + '@marijn/find-cluster-break@1.0.2': {} + '@mdx-js/mdx@1.6.22': dependencies: '@babel/core': 7.12.9 @@ -16572,6 +17138,10 @@ snapshots: '@polka/url@1.0.0-next.25': {} + '@popperjs/core@2.11.8': {} + + '@remirror/core-constants@3.0.0': {} + '@rollup/plugin-alias@5.1.0(rollup@4.18.0)': dependencies: slash: 4.0.0 @@ -16971,7 +17541,7 @@ snapshots: node-fetch: 2.7.0(encoding@0.1.13) picomatch: 2.3.1 pkg-dir: 5.0.0 - prettier-fallback: prettier@3.2.5 + prettier-fallback: prettier@3.3.3 pretty-hrtime: 1.0.3 resolve-from: 5.0.0 semver: 7.6.2 @@ -17146,7 +17716,7 @@ snapshots: ts-dedent: 2.2.0 type-fest: 2.19.0 vue: 3.5.13(typescript@5.2.2) - vue-component-type-helpers: 2.1.10 + vue-component-type-helpers: 2.2.0 '@supercharge/promise-pool@2.4.0': {} @@ -17433,6 +18003,214 @@ snapshots: optionalDependencies: '@vue/compiler-sfc': 3.5.13 + '@tiptap/core@2.10.3(@tiptap/pm@2.10.3)': + dependencies: + '@tiptap/pm': 2.10.3 + + '@tiptap/extension-blockquote@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-bold@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-bubble-menu@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3)': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + '@tiptap/pm': 2.10.3 + tippy.js: 6.3.7 + + '@tiptap/extension-bullet-list@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-character-count@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3)': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + '@tiptap/pm': 2.10.3 + + '@tiptap/extension-code-block@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3)': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + '@tiptap/pm': 2.10.3 + + '@tiptap/extension-code@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-color@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/extension-text-style@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + '@tiptap/extension-text-style': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + + '@tiptap/extension-document@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-dropcursor@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3)': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + '@tiptap/pm': 2.10.3 + + '@tiptap/extension-floating-menu@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3)': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + '@tiptap/pm': 2.10.3 + tippy.js: 6.3.7 + + '@tiptap/extension-gapcursor@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3)': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + '@tiptap/pm': 2.10.3 + + '@tiptap/extension-hard-break@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-heading@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-highlight@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-history@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3)': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + '@tiptap/pm': 2.10.3 + + '@tiptap/extension-horizontal-rule@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3)': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + '@tiptap/pm': 2.10.3 + + '@tiptap/extension-italic@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-link@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3)': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + '@tiptap/pm': 2.10.3 + linkifyjs: 4.2.0 + + '@tiptap/extension-list-item@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-ordered-list@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-paragraph@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-placeholder@2.10.4(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3)': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + '@tiptap/pm': 2.10.3 + + '@tiptap/extension-strike@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-subscript@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-superscript@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-table-cell@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-table-header@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-table-row@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-table@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3)': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + '@tiptap/pm': 2.10.3 + + '@tiptap/extension-text-align@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-text-style@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-text@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/extension-underline@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + + '@tiptap/pm@2.10.3': + dependencies: + prosemirror-changeset: 2.2.1 + prosemirror-collab: 1.3.1 + prosemirror-commands: 1.6.2 + prosemirror-dropcursor: 1.8.1 + prosemirror-gapcursor: 1.3.2 + prosemirror-history: 1.4.1 + prosemirror-inputrules: 1.4.0 + prosemirror-keymap: 1.2.2 + prosemirror-markdown: 1.13.1 + prosemirror-menu: 1.2.4 + prosemirror-model: 1.24.1 + prosemirror-schema-basic: 1.2.3 + prosemirror-schema-list: 1.5.0 + prosemirror-state: 1.4.3 + prosemirror-tables: 1.6.1 + prosemirror-trailing-node: 3.0.0(prosemirror-model@1.24.1)(prosemirror-state@1.4.3)(prosemirror-view@1.37.0) + prosemirror-transform: 1.10.2 + prosemirror-view: 1.37.0 + + '@tiptap/starter-kit@2.10.3': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + '@tiptap/extension-blockquote': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-bold': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-bullet-list': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-code': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-code-block': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3) + '@tiptap/extension-document': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-dropcursor': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3) + '@tiptap/extension-gapcursor': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3) + '@tiptap/extension-hard-break': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-heading': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-history': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3) + '@tiptap/extension-horizontal-rule': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3) + '@tiptap/extension-italic': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-list-item': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-ordered-list': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-paragraph': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-strike': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-text': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/extension-text-style': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3)) + '@tiptap/pm': 2.10.3 + + '@tiptap/vue-3@2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3)(vue@3.5.13(typescript@5.2.2))': + dependencies: + '@tiptap/core': 2.10.3(@tiptap/pm@2.10.3) + '@tiptap/extension-bubble-menu': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3) + '@tiptap/extension-floating-menu': 2.10.3(@tiptap/core@2.10.3(@tiptap/pm@2.10.3))(@tiptap/pm@2.10.3) + '@tiptap/pm': 2.10.3 + vue: 3.5.13(typescript@5.2.2) + '@tokenizer/token@0.3.0': {} '@tootallnate/once@1.1.2': {} @@ -17610,16 +18388,25 @@ snapshots: dependencies: '@types/node': 18.19.36 + '@types/linkify-it@5.0.0': {} + '@types/lodash-es@4.17.12': dependencies: '@types/lodash': 4.17.5 '@types/lodash@4.17.5': {} + '@types/markdown-it@14.1.2': + dependencies: + '@types/linkify-it': 5.0.0 + '@types/mdurl': 2.0.0 + '@types/mdast@3.0.15': dependencies: '@types/unist': 2.0.10 + '@types/mdurl@2.0.0': {} + '@types/mdx@2.0.13': {} '@types/mime@1.3.5': {} @@ -18973,7 +19760,7 @@ snapshots: dependencies: '@vueuse/core': 10.11.0(vue@3.5.13(typescript@5.6.2)) '@vueuse/shared': 10.11.0(vue@3.5.13(typescript@5.6.2)) - vue-demi: 0.14.8(vue@3.5.13(typescript@5.6.2)) + vue-demi: 0.14.10(vue@3.5.13(typescript@5.6.2)) optionalDependencies: axios: 1.7.2 change-case: 4.1.2 @@ -20067,6 +20854,18 @@ snapshots: code-block-writer@12.0.0: {} + codemirror@6.0.1(@lezer/common@1.2.3): + dependencies: + '@codemirror/autocomplete': 6.18.3(@codemirror/language@6.10.6)(@codemirror/state@6.5.0)(@codemirror/view@6.35.3)(@lezer/common@1.2.3) + '@codemirror/commands': 6.7.1 + '@codemirror/language': 6.10.6 + '@codemirror/lint': 6.8.4 + '@codemirror/search': 6.5.8 + '@codemirror/state': 6.5.0 + '@codemirror/view': 6.35.3 + transitivePeerDependencies: + - '@lezer/common' + collapse-white-space@1.0.6: {} collect-v8-coverage@1.0.2: {} @@ -20304,6 +21103,8 @@ snapshots: create-require@1.1.1: {} + crelt@1.0.6: {} + croner@8.0.2: {} cronstrue@2.50.0: {} @@ -20663,10 +21464,6 @@ snapshots: dependencies: ms: 2.0.0 - debug@3.2.7: - dependencies: - ms: 2.1.3 - debug@3.2.7(supports-color@5.5.0): dependencies: ms: 2.1.3 @@ -24128,6 +24925,12 @@ snapshots: lines-and-columns@1.2.4: {} + linkify-it@5.0.0: + dependencies: + uc.micro: 2.1.0 + + linkifyjs@4.2.0: {} + listhen@1.7.2: dependencies: '@parcel/watcher': 2.4.1 @@ -24368,6 +25171,15 @@ snapshots: markdown-escapes@1.0.4: {} + markdown-it@14.1.0: + dependencies: + argparse: 2.0.1 + entities: 4.5.0 + linkify-it: 5.0.0 + mdurl: 2.0.0 + punycode.js: 2.3.1 + uc.micro: 2.1.0 + mathml-tag-names@2.1.3: {} mdast-squeeze-paragraphs@4.0.0: @@ -24405,6 +25217,8 @@ snapshots: mdurl@1.0.1: {} + mdurl@2.0.0: {} + media-typer@0.3.0: {} median-quickselect@1.0.1: {} @@ -25363,6 +26177,8 @@ snapshots: string-width: 7.1.0 strip-ansi: 7.1.0 + orderedmap@2.1.1: {} + os-homedir@1.0.2: {} os-tmpdir@1.0.2: {} @@ -25654,7 +26470,7 @@ snapshots: portfinder@1.0.32: dependencies: async: 2.6.4 - debug: 3.2.7 + debug: 3.2.7(supports-color@5.5.0) mkdirp: 0.5.6 transitivePeerDependencies: - supports-color @@ -26333,6 +27149,109 @@ snapshots: dependencies: xtend: 4.0.2 + prosemirror-changeset@2.2.1: + dependencies: + prosemirror-transform: 1.10.2 + + prosemirror-collab@1.3.1: + dependencies: + prosemirror-state: 1.4.3 + + prosemirror-commands@1.6.2: + dependencies: + prosemirror-model: 1.24.1 + prosemirror-state: 1.4.3 + prosemirror-transform: 1.10.2 + + prosemirror-dropcursor@1.8.1: + dependencies: + prosemirror-state: 1.4.3 + prosemirror-transform: 1.10.2 + prosemirror-view: 1.37.0 + + prosemirror-gapcursor@1.3.2: + dependencies: + prosemirror-keymap: 1.2.2 + prosemirror-model: 1.24.1 + prosemirror-state: 1.4.3 + prosemirror-view: 1.37.0 + + prosemirror-history@1.4.1: + dependencies: + prosemirror-state: 1.4.3 + prosemirror-transform: 1.10.2 + prosemirror-view: 1.37.0 + rope-sequence: 1.3.4 + + prosemirror-inputrules@1.4.0: + dependencies: + prosemirror-state: 1.4.3 + prosemirror-transform: 1.10.2 + + prosemirror-keymap@1.2.2: + dependencies: + prosemirror-state: 1.4.3 + w3c-keyname: 2.2.8 + + prosemirror-markdown@1.13.1: + dependencies: + '@types/markdown-it': 14.1.2 + markdown-it: 14.1.0 + prosemirror-model: 1.24.1 + + prosemirror-menu@1.2.4: + dependencies: + crelt: 1.0.6 + prosemirror-commands: 1.6.2 + prosemirror-history: 1.4.1 + prosemirror-state: 1.4.3 + + prosemirror-model@1.24.1: + dependencies: + orderedmap: 2.1.1 + + prosemirror-schema-basic@1.2.3: + dependencies: + prosemirror-model: 1.24.1 + + prosemirror-schema-list@1.5.0: + dependencies: + prosemirror-model: 1.24.1 + prosemirror-state: 1.4.3 + prosemirror-transform: 1.10.2 + + prosemirror-state@1.4.3: + dependencies: + prosemirror-model: 1.24.1 + prosemirror-transform: 1.10.2 + prosemirror-view: 1.37.0 + + prosemirror-tables@1.6.1: + dependencies: + prosemirror-keymap: 1.2.2 + prosemirror-model: 1.24.1 + prosemirror-state: 1.4.3 + prosemirror-transform: 1.10.2 + prosemirror-view: 1.37.0 + + prosemirror-trailing-node@3.0.0(prosemirror-model@1.24.1)(prosemirror-state@1.4.3)(prosemirror-view@1.37.0): + dependencies: + '@remirror/core-constants': 3.0.0 + escape-string-regexp: 4.0.0 + prosemirror-model: 1.24.1 + prosemirror-state: 1.4.3 + prosemirror-view: 1.37.0 + + prosemirror-transform@1.10.2: + dependencies: + prosemirror-model: 1.24.1 + + prosemirror-view@1.37.0: + dependencies: + prosemirror-model: 1.24.1 + prosemirror-state: 1.4.3 + prosemirror-transform: 1.10.2 + proto-list@1.2.4: {} protocols@2.0.1: {} @@ -26422,6 +27341,8 @@ snapshots: end-of-stream: 1.4.4 once: 1.4.0 + punycode.js@2.3.1: {} + punycode@1.4.1: {} punycode@2.3.1: {} @@ -26997,6 +27918,8 @@ snapshots: '@rollup/rollup-win32-x64-msvc': 4.18.0 fsevents: 2.3.3 + rope-sequence@1.3.4: {} + rrweb-cssom@0.6.0: {} rtl-detect@1.1.2: {} @@ -27624,6 +28547,8 @@ snapshots: lodash: 4.17.21 tinycolor2: 1.6.0 + style-mod@4.1.2: {} + style-to-object@0.3.0: dependencies: inline-style-parser: 0.1.1 @@ -28024,6 +28949,10 @@ snapshots: tinyspy@3.0.2: {} + tippy.js@6.3.7: + dependencies: + '@popperjs/core': 2.11.8 + tmp@0.0.33: dependencies: os-tmpdir: 1.0.2 @@ -28366,6 +29295,8 @@ snapshots: ua-parser-js@1.0.38: {} + uc.micro@2.1.0: {} + ufo@1.5.3: {} uglify-js@3.18.0: @@ -29071,6 +30002,21 @@ snapshots: dependencies: ufo: 1.5.3 + vue-codemirror6@1.3.8(@lezer/common@1.2.3)(vue@3.5.13(typescript@5.2.2)): + dependencies: + '@codemirror/commands': 6.7.1 + '@codemirror/language': 6.10.6 + '@codemirror/lint': 6.8.4 + '@codemirror/state': 6.5.0 + '@codemirror/view': 6.35.3 + codemirror: 6.0.1(@lezer/common@1.2.3) + style-mod: 4.1.2 + vue: 3.5.13(typescript@5.2.2) + vue-demi: 0.14.10(vue@3.5.13(typescript@5.2.2)) + transitivePeerDependencies: + - '@lezer/common' + - '@vue/composition-api' + vue-component-meta@2.0.21(typescript@5.6.2): dependencies: '@volar/typescript': 2.3.0 @@ -29082,7 +30028,15 @@ snapshots: vue-component-type-helpers@2.0.21: {} - vue-component-type-helpers@2.1.10: {} + vue-component-type-helpers@2.2.0: {} + + vue-demi@0.14.10(vue@3.5.13(typescript@5.2.2)): + dependencies: + vue: 3.5.13(typescript@5.2.2) + + vue-demi@0.14.10(vue@3.5.13(typescript@5.6.2)): + dependencies: + vue: 3.5.13(typescript@5.6.2) vue-demi@0.14.8(vue@3.5.13(typescript@5.2.2)): dependencies: @@ -29123,6 +30077,13 @@ snapshots: transitivePeerDependencies: - supports-color + vue-i18n@9.13.1(vue@3.5.0(typescript@5.6.2)): + dependencies: + '@intlify/core-base': 9.13.1 + '@intlify/shared': 9.13.1 + '@vue/devtools-api': 6.6.3 + vue: 3.5.0(typescript@5.6.2) + vue-i18n@9.13.1(vue@3.5.13(typescript@5.2.2)): dependencies: '@intlify/core-base': 9.13.1 @@ -29255,6 +30216,8 @@ snapshots: dependencies: browser-process-hrtime: 1.0.0 + w3c-keyname@2.2.8: {} + w3c-xmlserializer@2.0.0: dependencies: xml-name-validator: 3.0.0