@dialpad/dialtone-vue
Version:
Vue component library for Dialpad's design system Dialtone
1 lines • 36 kB
Source Map (JSON)
{"version":3,"file":"editor.cjs","sources":["../../../recipes/conversation_view/editor/editor.vue"],"sourcesContent":["<template>\n <div\n\n class=\"d-recipe-editor\"\n data-qa=\"dt-recipe-editor\"\n role=\"presentation\"\n @click=\"$refs.richTextEditor.focusEditor()\"\n >\n <!-- Section for the top UI -->\n <dt-stack\n class=\"d-recipe-editor__top-bar\"\n direction=\"row\"\n gap=\"450\"\n >\n <dt-stack\n v-for=\"buttonGroup in buttonGroups\"\n :key=\"buttonGroup.key\"\n direction=\"row\"\n gap=\"300\"\n >\n <dt-tooltip\n v-for=\"button in buttonGroup.buttonGroup\"\n :key=\"getButtonKey(buttonGroup.key, button.selector)\"\n :message=\"button.tooltipMessage\"\n placement=\"top\"\n >\n <template #anchor>\n <dt-button\n :ref=\"getButtonRef(buttonGroup.key, button.selector)\"\n :active=\"$refs.richTextEditor?.editor?.isActive(button.selector)\"\n :aria-label=\"button.tooltipMessage\"\n :data-qa=\"button.dataQA\"\n :tabindex=\"canFocus(getButtonRef(buttonGroup.key, button.selector)) ? 0 : -1\"\n importance=\"clear\"\n kind=\"muted\"\n size=\"xs\"\n @click=\"button.onClick()\"\n @keydown.right.stop=\"shiftActionBarFocusRight\"\n @keydown.left.stop=\"shiftActionBarFocusLeft\"\n >\n <template #icon>\n <component\n :is=\"button.icon\"\n size=\"200\"\n />\n </template>\n <span v-if=\"button.label\">{{ button.label }}</span>\n </dt-button>\n </template>\n </dt-tooltip>\n <div class=\"d-recipe-editor__button-group-divider\" />\n </dt-stack>\n <dt-stack\n v-if=\"linkButton.showBtn\"\n direction=\"row\"\n gap=\"300\"\n >\n <dt-popover\n :open.sync=\"showLinkInput\"\n :show-close-button=\"false\"\n data-qa=\"dt-recipe-editor-link-input-popover\"\n padding=\"none\"\n placement=\"bottom-start\"\n @click=\"onInputFocus\"\n @opened=\"updateInput\"\n @click.native.stop=\"onInputFocus\"\n >\n <template #anchor>\n <dt-tooltip\n :key=\"linkButton.key\"\n :message=\"linkButton.tooltipMessage\"\n placement=\"top\"\n >\n <template #anchor>\n <dt-button\n :ref=\"getButtonRef('custom', 'link')\"\n :active=\"$refs.richTextEditor?.editor?.isActive(linkButton.selector)\"\n :aria-label=\"linkButton.tooltipMessage\"\n :data-qa=\"linkButton.dataQA\"\n :tabindex=\"canFocus(getButtonRef('custom', 'link')) ? 0 : -1\"\n importance=\"clear\"\n kind=\"muted\"\n size=\"xs\"\n @click=\"linkButton.onClick()\"\n @keydown.right.stop=\"shiftActionBarFocusRight\"\n @keydown.left.stop=\"shiftActionBarFocusLeft\"\n >\n <template #icon>\n <component\n :is=\"linkButton.icon\"\n size=\"200\"\n />\n </template>\n </dt-button>\n </template>\n </dt-tooltip>\n </template>\n\n <template #content>\n <div class=\"d-recipe-editor__popover-content\">\n <span>\n {{ showAddLinkButtonLabels.title }}\n </span>\n <dt-input\n v-model=\"linkInput\"\n :input-aria-label=\"showAddLinkButtonLabels['aria-label']\"\n :placeholder=\"setLinkPlaceholder\"\n data-qa=\"dt-recipe-editor-link-input\"\n input-wrapper-class=\"d-recipe-editor-link__input-wrapper\"\n @click=\"onInputFocus\"\n @focus=\"onInputFocus\"\n @click.native.stop=\"onInputFocus\"\n @keydown.enter=\"setLink\"\n />\n </div>\n </template>\n <template #footerContent>\n <dt-stack\n direction=\"row\"\n gap=\"300\"\n class=\"d-recipe-editor__popover-footer\"\n >\n <dt-button\n data-qa=\"dt-recipe-editor-remove-link-btn\"\n importance=\"clear\"\n kind=\"muted\"\n size=\"sm\"\n v-bind=\"removeLinkButtonLabels\"\n @click=\"removeLink\"\n >\n {{ removeLinkButtonLabels.title }}\n </dt-button>\n <dt-button\n data-qa=\"dt-recipe-editor-set-link-cancel-btn\"\n importance=\"clear\"\n kind=\"muted\"\n size=\"sm\"\n v-bind=\"cancelSetLinkButtonLabels\"\n @click=\"closeLinkInput\"\n >\n {{ cancelSetLinkButtonLabels.title }}\n </dt-button>\n <dt-button\n data-qa=\"dt-recipe-editor-set-link-confirm-btn\"\n size=\"sm\"\n v-bind=\"confirmSetLinkButtonLabels\"\n @click=\"setLink\"\n >\n {{ confirmSetLinkButtonLabels.title }}\n </dt-button>\n </dt-stack>\n </template>\n </dt-popover>\n </dt-stack>\n </dt-stack>\n\n <!-- Some wrapper to restrict the height and show the scrollbar -->\n <div\n :style=\"{ 'max-height': maxHeight }\"\n class=\"d-recipe-editor__content\"\n >\n <dt-rich-text-editor\n ref=\"richTextEditor\"\n v-model=\"internalInputValue\"\n :allow-font-color=\"true\"\n :allow-font-family=\"true\"\n :allow-inline-images=\"true\"\n :allow-line-breaks=\"true\"\n :hide-link-bubble-menu=\"true\"\n :auto-focus=\"autoFocus\"\n :editable=\"editable\"\n :input-aria-label=\"inputAriaLabel\"\n :input-class=\"`d-recipe-editor__content-input ${inputClass}`\"\n :link=\"true\"\n :output-format=\"htmlOutputFormat\"\n :placeholder=\"placeholder\"\n :use-div-tags=\"useDivTags\"\n data-qa=\"dt-rich-text-editor\"\n v-bind=\"$attrs\"\n @text-input=\"onTextInput\"\n @blur=\"onBlur\"\n @focus=\"onFocus\"\n @input=\"onInput($event)\"\n />\n </div>\n </div>\n</template>\n\n<script>\n/* eslint-disable max-lines */\nimport {\n DtRichTextEditor,\n RICH_TEXT_EDITOR_OUTPUT_FORMATS,\n RICH_TEXT_EDITOR_AUTOFOCUS_TYPES,\n} from '@/components/rich_text_editor';\nimport {\n EDITOR_SUPPORTED_LINK_PROTOCOLS,\n EDITOR_DEFAULT_LINK_PREFIX,\n} from './editor_constants.js';\nimport { DtButton } from '@/components/button';\nimport { DtPopover } from '@/components/popover';\nimport { DtStack } from '@/components/stack';\nimport { DtInput } from '@/components/input';\nimport { DtTooltip } from '@/components/tooltip';\nimport {\n DtIconAlignCenter,\n DtIconAlignJustify,\n DtIconAlignLeft,\n DtIconAlignRight,\n DtIconBold,\n DtIconCodeBlock,\n DtIconImage,\n DtIconItalic,\n DtIconQuickReply,\n DtIconLink2,\n DtIconListBullet,\n DtIconListOrdered,\n DtIconQuote,\n DtIconStrikethrough,\n DtIconUnderline,\n} from '@dialpad/dialtone-icons/vue2';\nimport { DialtoneLocalization } from '@/localization';\n\nexport default {\n name: 'DtRecipeEditor',\n\n components: {\n DtRichTextEditor,\n DtButton,\n DtPopover,\n DtStack,\n DtInput,\n DtTooltip,\n DtIconQuickReply,\n DtIconBold,\n DtIconItalic,\n DtIconUnderline,\n DtIconStrikethrough,\n DtIconListBullet,\n DtIconListOrdered,\n DtIconAlignLeft,\n DtIconAlignCenter,\n DtIconAlignRight,\n DtIconAlignJustify,\n DtIconQuote,\n DtIconCodeBlock,\n DtIconLink2,\n DtIconImage,\n },\n\n inheritAttrs: false,\n\n props: {\n /**\n * Value of the input. The object format should match TipTap's JSON\n * document structure: https://tiptap.dev/guide/output#option-1-json\n */\n value: {\n type: [Object, String],\n default: '',\n },\n\n /**\n * Whether the input is editable\n */\n editable: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Descriptive label for the input element\n */\n inputAriaLabel: {\n type: String,\n required: true,\n default: '',\n },\n\n /**\n * Additional class name for the input element. Only accepts a String value\n * because this is passed to the editor via options. For multiple classes,\n * join them into one string, e.g. \"d-p8 d-hmx96\"\n */\n inputClass: {\n type: String,\n default: '',\n },\n\n /**\n * Whether the input should receive focus after the component has been\n * mounted. Either one of `start`, `end`, `all` or a Boolean or a Number.\n * - `start` Sets the focus to the beginning of the input\n * - `end` Sets the focus to the end of the input\n * - `all` Selects the whole contents of the input\n * - `Number` Sets the focus to a specific position in the input\n * - `true` Defaults to `start`\n * - `false` Disables autofocus\n * @values true, false, start, end, all, number\n */\n autoFocus: {\n type: [Boolean, String, Number],\n default: false,\n validator (autoFocus) {\n if (typeof autoFocus === 'string') {\n return RICH_TEXT_EDITOR_AUTOFOCUS_TYPES.includes(autoFocus);\n }\n return true;\n },\n },\n\n /**\n * Placeholder text\n */\n placeholder: {\n type: String,\n default: '',\n },\n\n /**\n * Content area needs to dynamically adjust height based on the conversation area height.\n * can be vh|px|rem|em|%\n */\n maxHeight: {\n type: String,\n default: 'unset',\n },\n\n /**\n * Placeholder text for the set link input field\n */\n setLinkPlaceholder: {\n type: String,\n default: '',\n },\n\n /**\n * Show button to render text as bold\n */\n showBoldButton: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Show button to render text in italics\n */\n showItalicsButton: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Show button to underline text\n */\n showUnderlineButton: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Show button to strike text\n */\n showStrikeButton: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Show button to render list items\n */\n showListItemsButton: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Show button to render ordered list items\n */\n showOrderedListButton: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Show button to align text to the left\n */\n showAlignLeftButton: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Show button to align text to the center\n */\n showAlignCenterButton: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Show button to align text to the right\n */\n showAlignRightButton: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Show button to justify text\n */\n showAlignJustifyButton: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Show button to add quote format to text\n */\n showQuoteButton: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Show button to add code block\n */\n showCodeBlockButton: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Show button to handle quick replies\n */\n showQuickRepliesButton: {\n type: Boolean,\n default: true,\n },\n\n /**\n * Show button to add an inline image\n */\n showInlineImageButton: {\n type: Boolean,\n default: false,\n },\n\n /**\n * Show add link default config.\n */\n showAddLink: {\n type: Object,\n default: () => ({\n showAddLinkButton: true,\n }),\n },\n\n /**\n * Use div tags instead of paragraph tags to show text\n */\n useDivTags: {\n type: Boolean,\n default: false,\n },\n },\n\n emits: [\n /**\n * Native focus event\n * @event input\n * @type {String|JSON}\n */\n 'focus',\n\n /**\n * Native blur event\n * @event input\n * @type {String|JSON}\n */\n 'blur',\n\n /**\n * Native input event\n * @event input\n * @type {String|JSON}\n */\n 'input',\n\n /**\n * Quick replies button\n * pressed event\n * @event quick-replies-click\n */\n 'quick-replies-click',\n\n /**\n * Emit when inline image button is clicked\n * @event inline-image-click\n */\n 'inline-image-click',\n\n /**\n * Emit when text content changes (not raw html)\n */\n 'text-input',\n ],\n\n data () {\n return {\n internalInputValue: this.value, // internal input content\n hasFocus: false,\n\n linkOptions: {\n class: 'd-recipe-editor__link',\n },\n\n showLinkInput: false,\n linkInput: '',\n currentButtonRefIndex: 0,\n i18n: new DialtoneLocalization(),\n };\n },\n\n computed: {\n inputLength () {\n return this.internalInputValue.length;\n },\n\n htmlOutputFormat () {\n return RICH_TEXT_EDITOR_OUTPUT_FORMATS[2];\n },\n\n showingTextFormatButtons () {\n return this.showBoldButton || this.showItalicsButton || this.showStrikeButton || this.showUnderlineButton;\n },\n\n showingAlignmentButtons () {\n return this.showAlignLeftButton || this.showAlignCenterButton ||\n this.showAlignRightButton || this.showAlignJustifyButton;\n },\n\n showingListButtons () {\n return this.showListItemsButton || this.showOrderedListButton;\n },\n\n orderedRefs () {\n const refs = this.buttonGroups.reduce(function (acc, buttonData) {\n buttonData.buttonGroup.forEach(button => {\n acc.push(this.getButtonRef(buttonData.key, button.selector));\n }, this);\n return acc;\n }.bind(this), []);\n refs.push(this.getButtonRef('custom', 'link'));\n return refs;\n },\n\n buttonGroups () {\n const individualButtonStacks = this.individualButtons.map(buttonData => ({\n key: buttonData.selector,\n buttonGroup: [buttonData],\n }));\n return [\n { key: 'new', buttonGroup: this.newButtons },\n { key: 'format', buttonGroup: this.textFormatButtons },\n { key: 'alignment', buttonGroup: this.alignmentButtons },\n { key: 'list', buttonGroup: this.listButtons },\n ...individualButtonStacks,\n ].filter(buttonGroupData => buttonGroupData.buttonGroup.length > 0);\n },\n\n newButtons () {\n return [\n {\n showBtn: this.showQuickRepliesButton,\n label: this.i18n.$t('DIALTONE_EDITOR_QUICK_REPLY_BUTTON_LABEL'),\n selector: 'quickReplies',\n icon: DtIconQuickReply,\n dataQA: 'dt-recipe-editor-quick-replies-btn',\n tooltipMessage: this.i18n.$t('DIALTONE_EDITOR_QUICK_REPLY_BUTTON_LABEL'),\n onClick: this.onQuickRepliesClick,\n },\n ].filter(button => button.showBtn);\n },\n\n textFormatButtons () {\n return [\n {\n showBtn: this.showBoldButton,\n selector: 'bold',\n icon: DtIconBold,\n dataQA: 'dt-recipe-editor-bold-btn',\n tooltipMessage: this.i18n.$t('DIALTONE_EDITOR_BOLD_BUTTON_LABEL'),\n onClick: this.onBoldTextToggle,\n },\n {\n showBtn: this.showItalicsButton,\n selector: 'italic',\n icon: DtIconItalic,\n dataQA: 'dt-recipe-editor-italics-btn',\n tooltipMessage: this.i18n.$t('DIALTONE_EDITOR_ITALICS_BUTTON_LABEL'),\n onClick: this.onItalicTextToggle,\n },\n {\n showBtn: this.showUnderlineButton,\n selector: 'underline',\n icon: DtIconUnderline,\n dataQA: 'dt-recipe-editor-underline-btn',\n tooltipMessage: this.i18n.$t('DIALTONE_EDITOR_UNDERLINE_BUTTON_LABEL'),\n onClick: this.onUnderlineTextToggle,\n },\n {\n showBtn: this.showStrikeButton,\n selector: 'strike',\n icon: DtIconStrikethrough,\n dataQA: 'dt-recipe-editor-strike-btn',\n tooltipMessage: this.i18n.$t('DIALTONE_EDITOR_STRIKE_BUTTON_LABEL'),\n onClick: this.onStrikethroughTextToggle,\n },\n ].filter(button => button.showBtn);\n },\n\n alignmentButtons () {\n return [\n {\n showBtn: this.showAlignLeftButton,\n selector: { textAlign: 'left' },\n icon: DtIconAlignLeft,\n dataQA: 'dt-recipe-editor-align-left-btn',\n tooltipMessage: this.i18n.$t('DIALTONE_EDITOR_ALIGN_LEFT_BUTTON_LABEL'),\n onClick: () => this.onTextAlign('left'),\n },\n {\n showBtn: this.showAlignCenterButton,\n selector: { textAlign: 'center' },\n icon: DtIconAlignCenter,\n dataQA: 'dt-recipe-editor-align-center-btn',\n tooltipMessage: this.i18n.$t('DIALTONE_EDITOR_ALIGN_CENTER_BUTTON_LABEL'),\n onClick: () => this.onTextAlign('center'),\n },\n {\n showBtn: this.showAlignRightButton,\n selector: { textAlign: 'right' },\n icon: DtIconAlignRight,\n dataQA: 'dt-recipe-editor-align-right-btn',\n tooltipMessage: this.i18n.$t('DIALTONE_EDITOR_ALIGN_RIGHT_BUTTON_LABEL'),\n onClick: () => this.onTextAlign('right'),\n },\n {\n showBtn: this.showAlignJustifyButton,\n selector: { textAlign: 'justify' },\n icon: DtIconAlignJustify,\n dataQA: 'dt-recipe-editor-align-justify-btn',\n tooltipMessage: this.i18n.$t('DIALTONE_EDITOR_ALIGN_JUSTIFY_BUTTON_LABEL'),\n onClick: () => this.onTextAlign('justify'),\n },\n ].filter(button => button.showBtn);\n },\n\n listButtons () {\n return [\n {\n showBtn: this.showListItemsButton,\n selector: 'bulletList',\n icon: DtIconListBullet,\n dataQA: 'dt-recipe-editor-list-items-btn',\n tooltipMessage: this.i18n.$t('DIALTONE_EDITOR_BULLET_LIST_BUTTON_LABEL'),\n onClick: this.onBulletListToggle,\n },\n {\n showBtn: this.showOrderedListButton,\n selector: 'orderedList',\n icon: DtIconListOrdered,\n dataQA: 'dt-recipe-editor-ordered-list-items-btn',\n tooltipMessage: this.i18n.$t('DIALTONE_EDITOR_ORDERED_LIST_BUTTON_LABEL'),\n onClick: this.onOrderedListToggle,\n },\n ].filter(button => button.showBtn);\n },\n\n individualButtons () {\n return [\n {\n showBtn: this.showQuoteButton,\n selector: 'blockquote',\n icon: DtIconQuote,\n dataQA: 'dt-recipe-editor-blockquote-btn',\n tooltipMessage: this.i18n.$t('DIALTONE_EDITOR_QUOTE_BUTTON_LABEL'),\n onClick: this.onBlockquoteToggle,\n },\n {\n showBtn: this.showCodeBlockButton,\n selector: 'codeBlock',\n icon: DtIconCodeBlock,\n dataQA: 'dt-recipe-editor-code-block-btn',\n tooltipMessage: this.i18n.$t('DIALTONE_EDITOR_CODE_BUTTON_LABEL'),\n onClick: this.onCodeBlockToggle,\n },\n {\n showBtn: this.showInlineImageButton,\n selector: 'image',\n icon: DtIconImage,\n dataQA: 'dt-recipe-editor-inline-image-btn',\n tooltipMessage: this.i18n.$t('DIALTONE_EDITOR_IMAGE_BUTTON_LABEL'),\n onClick: this.onInsertInlineImageClick,\n },\n ].filter(button => button.showBtn);\n },\n\n linkButton () {\n return {\n showBtn: this.showAddLink.showAddLinkButton,\n selector: 'link',\n icon: DtIconLink2,\n dataQA: 'dt-recipe-editor-add-link-btn',\n tooltipMessage: this.i18n.$t('DIALTONE_EDITOR_LINK_BUTTON_LABEL'),\n onClick: this.openLinkInput,\n };\n },\n\n confirmSetLinkButtonLabels () {\n return this.i18n.$ta('DIALTONE_EDITOR_CONFIRM_SET_LINK_BUTTON');\n },\n\n cancelSetLinkButtonLabels () {\n return this.i18n.$ta('DIALTONE_EDITOR_CANCEL_SET_LINK_BUTTON');\n },\n\n removeLinkButtonLabels () {\n return this.i18n.$ta('DIALTONE_EDITOR_REMOVE_LINK_BUTTON');\n },\n\n showAddLinkButtonLabels () {\n return this.i18n.$ta('DIALTONE_EDITOR_ADD_LINK_BUTTON');\n },\n },\n\n watch: {\n value (newValue) {\n this.internalInputValue = newValue;\n },\n },\n\n methods: {\n onInputFocus (event) {\n event?.stopPropagation();\n },\n\n removeLink () {\n this.$refs.richTextEditor?.editor?.chain()?.focus()?.unsetLink()?.run();\n this.closeLinkInput();\n },\n\n setLink (event) {\n const editor = this.$refs.richTextEditor?.editor;\n event?.preventDefault();\n event?.stopPropagation();\n\n if (!this.linkInput) {\n // If link text is set to empty string,\n // remove any existing links.\n this.removeLink();\n return;\n }\n\n // Check if input matches any of the supported link formats\n const prefix = EDITOR_SUPPORTED_LINK_PROTOCOLS.find(prefixRegex => prefixRegex.test(this.linkInput));\n\n if (!prefix) {\n // If no matching pattern is found, prepend default prefix\n this.linkInput = `${EDITOR_DEFAULT_LINK_PREFIX}${this.linkInput}`;\n }\n\n const selection = editor?.view?.state?.selection;\n\n if (selection.anchor === selection.head) {\n // If no text has been selected, manually insert the link text.\n // Do not rely on link options set through DtRichTextEditor\n // component, because they clash with these and cause issues.\n editor\n .chain()\n .focus()\n .insertContentAt(\n selection.anchor,\n `<a class=\"${this.linkOptions.class}\" href=${this.linkInput}>${this.linkInput}</a>`,\n )\n .run();\n } else {\n // Set or edit the link\n editor\n .chain()\n .focus()\n .extendMarkRange('link')\n .setLink({ href: this.linkInput, class: this.linkOptions.class })\n .run();\n }\n\n this.closeLinkInput();\n },\n\n openLinkInput () {\n this.showLinkInput = true;\n },\n\n updateInput (openedInput) {\n if (!openedInput) {\n return this.closeLinkInput();\n }\n this.linkInput = this.$refs.richTextEditor?.editor?.getAttributes('link')?.href;\n },\n\n closeLinkInput () {\n this.showLinkInput = false;\n this.linkInput = '';\n this.$refs.richTextEditor.editor?.chain().focus();\n },\n\n onBoldTextToggle () {\n this.$refs.richTextEditor?.editor?.chain().focus().toggleBold().run();\n },\n\n onItalicTextToggle () {\n this.$refs.richTextEditor?.editor.chain().focus().toggleItalic().run();\n },\n\n onUnderlineTextToggle () {\n this.$refs.richTextEditor?.editor.chain().focus().toggleUnderline().run();\n },\n\n onStrikethroughTextToggle () {\n this.$refs.richTextEditor?.editor.chain().focus().toggleStrike().run();\n },\n\n onTextAlign (alignment) {\n if (this.$refs.richTextEditor?.editor?.isActive({ textAlign: alignment })) {\n // If this alignment type is already set here, unset it\n return this.$refs.richTextEditor?.editor.chain().focus().unsetTextAlign().run();\n }\n this.$refs.richTextEditor?.editor.chain().focus().setTextAlign(alignment).run();\n },\n\n onBulletListToggle () {\n this.$refs.richTextEditor?.editor.chain().focus().toggleBulletList().run();\n },\n\n onOrderedListToggle () {\n this.$refs.richTextEditor?.editor.chain().focus().toggleOrderedList().run();\n },\n\n onCodeBlockToggle () {\n this.$refs.richTextEditor?.editor.chain().focus().toggleCodeBlock().run();\n },\n\n onQuickRepliesClick () {\n this.$emit('quick-replies-click');\n },\n\n onInsertInlineImageClick () {\n this.$emit('inline-image-click');\n },\n\n insertInlineImage (imageUrl) {\n this.$refs.richTextEditor?.editor.chain().focus().setImage({ src: imageUrl }).run();\n },\n\n onBlockquoteToggle () {\n this.$refs.richTextEditor?.editor.chain().focus().toggleBlockquote().run();\n },\n\n insertInMessageBody (messageContent) {\n this.$refs.richTextEditor?.editor.chain().focus().insertContent(messageContent).run();\n },\n\n setCursorPosition (position = null) {\n this.$refs.richTextEditor?.editor.chain().focus(position).run();\n },\n\n onTextInput (event) {\n this.$emit('text-input', event);\n },\n\n onFocus (event) {\n this.hasFocus = true;\n this.$emit('focus', event);\n },\n\n onBlur (event) {\n this.hasFocus = false;\n this.$emit('blur', event);\n },\n\n onInput (event) {\n this.$emit('input', event);\n },\n\n getButtonKey (key, selector) {\n return `${key}-${JSON.stringify(selector)}`;\n },\n\n // Unique Button Ref Key to identify ref\n getButtonRef (key, selector) {\n return `${this.getButtonKey(key, selector)}-ref`;\n },\n\n /**\n * Determines if an element in the action bar button list is focusable with tab key\n * @param {string} refKey - unique identifier for the ref element in DOM\n */\n canFocus (refKey) {\n return refKey === this.orderedRefs[this.currentButtonRefIndex];\n },\n\n shiftActionBarFocusRight () {\n this.shiftButtonRefIndex(1);\n },\n\n shiftActionBarFocusLeft () {\n this.shiftButtonRefIndex(-1);\n },\n\n shiftButtonRefIndex (shiftAmount) {\n const previousRef = this.$refs[this.orderedRefs[this.currentButtonRefIndex]];\n const previousActionBarBtn = Array.isArray(previousRef) ? previousRef[0] : previousRef;\n const index = (this.currentButtonRefIndex + shiftAmount) % this.orderedRefs.length;\n this.currentButtonRefIndex = index >= 0 ? index : this.orderedRefs.length + index;\n const currentRef = this.$refs[this.orderedRefs[this.currentButtonRefIndex]];\n const currentActionBarBtn = Array.isArray(currentRef) ? currentRef[0] : currentRef;\n previousActionBarBtn.$el.blur();\n currentActionBarBtn.$el.focus();\n },\n },\n};\n</script>\n"],"names":["_sfc_main","DtRichTextEditor","DtButton","DtPopover","DtStack","DtInput","DtTooltip","DtIconQuickReply","DtIconBold","DtIconItalic","DtIconUnderline","DtIconStrikethrough","DtIconListBullet","DtIconListOrdered","DtIconAlignLeft","DtIconAlignCenter","DtIconAlignRight","DtIconAlignJustify","DtIconQuote","DtIconCodeBlock","DtIconLink2","DtIconImage","autoFocus","RICH_TEXT_EDITOR_AUTOFOCUS_TYPES","DialtoneLocalization","RICH_TEXT_EDITOR_OUTPUT_FORMATS","refs","acc","buttonData","button","individualButtonStacks","buttonGroupData","newValue","event","_e","_d","_c","_b","_a","editor","EDITOR_SUPPORTED_LINK_PROTOCOLS","prefixRegex","EDITOR_DEFAULT_LINK_PREFIX","selection","openedInput","alignment","imageUrl","messageContent","position","key","selector","refKey","shiftAmount","previousRef","previousActionBarBtn","index","currentRef","currentActionBarBtn"],"mappings":"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"}