UNPKG

@dialpad/dialtone

Version:

Dialpad's Dialtone design system monorepo

950 lines (949 loc) 36 kB
"use strict"; Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } }); const last_active_nodes = require("./last_active_nodes.cjs"); const common_utils = require("../../../common/utils.cjs"); const meeting_pill = require("./extensions/meeting_pill/meeting_pill.cjs"); const vue3 = require("@dialpad/dialtone-icons/vue3"); const message_input_topbar = require("./message_input_topbar.vue.cjs"); const message_input_link = require("./message_input_link.vue.cjs"); const editor_constants = require("../editor/editor_constants.cjs"); const vue = require("vue"); const _pluginVue_exportHelper = require("../../../_virtual/_plugin-vue_export-helper.cjs"); const button = require("../../../components/button/button.vue.cjs"); const emoji_picker = require("../../../components/emoji_picker/emoji_picker.vue.cjs"); const input = require("../../../components/input/input.vue.cjs"); const popover = require("../../../components/popover/popover.vue.cjs"); const rich_text_editor = require("../../../components/rich_text_editor/rich_text_editor.vue.cjs"); const tooltip = require("../../../components/tooltip/tooltip.vue.cjs"); const stack = require("../../../components/stack/stack.vue.cjs"); const rich_text_editor_constants = require("../../../components/rich_text_editor/rich_text_editor_constants.cjs"); const _sfc_main = { compatConfig: { MODE: 3 }, name: "DtRecipeMessageInput", components: { DtButton: button.default, DtEmojiPicker: emoji_picker.default, DtInput: input.default, DtPopover: popover.default, DtRecipeMessageInputTopbar: message_input_topbar.default, DtRecipeMessageInputLink: message_input_link.default, DtRichTextEditor: rich_text_editor.default, DtTooltip: tooltip.default, DtStack: stack.default, DtIconImage: vue3.DtIconImage, DtIconVerySatisfied: vue3.DtIconVerySatisfied, DtIconSatisfied: vue3.DtIconSatisfied, DtIconSend: vue3.DtIconSend }, mixins: [], inheritAttrs: false, props: { /** * Displays all the buttons for rich text formatting above the message input, and enables it within the editor. * Rich text formatting for the purposes of this component is defined as: * * bold, italic, strikethrough, lists, blockquotes, inline code tags, and code blocks. * * If you are sending a message to a phone rather than a Dialpad to Dialpad message, you should have this as false. */ richText: { type: Boolean, default: true }, /** * Value of the input. The object format should match TipTap's JSON * document structure: https://tiptap.dev/guide/output#option-1-json */ modelValue: { type: [Object, String], default: "" }, /** * Whether the input is editable */ editable: { type: Boolean, default: true }, /** * Descriptive label for the input element */ inputAriaLabel: { type: String, required: true, default: "" }, /** * Prevents the user from typing any further. Deleting text will still work. */ preventTyping: { type: Boolean, default: false }, /** * Additional class name for the input element. Only accepts a String value * because this is passed to the editor via options. For multiple classes, * join them into one string, e.g. "d-p8 d-hmx96" */ inputClass: { type: String, default: "" }, /** * Whether the input should receive focus after the component has been * mounted. Either one of `start`, `end`, `all` or a Boolean or a Number. * - `start` Sets the focus to the beginning of the input * - `end` Sets the focus to the end of the input * - `all` Selects the whole contents of the input * - `Number` Sets the focus to a specific position in the input * - `true` Defaults to `start` * - `false` Disables autofocus * @values true, false, start, end, all, number */ autoFocus: { type: [Boolean, String, Number], default: false, validator(autoFocus) { if (typeof autoFocus === "string") { return rich_text_editor_constants.RICH_TEXT_EDITOR_AUTOFOCUS_TYPES.includes(autoFocus); } return true; } }, /** * The output format that the editor uses when emitting the "@input" event. * One of `text`, `json`, `html`. See https://tiptap.dev/guide/output for * examples. * @values text, json, html */ outputFormat: { type: String, default: "json", validator(outputFormat) { return rich_text_editor_constants.RICH_TEXT_EDITOR_OUTPUT_FORMATS.includes(outputFormat); } }, /** * Placeholder text */ placeholder: { type: String, default: "" }, /** * Disable Send Button */ disableSend: { type: Boolean, default: false }, /** * Content area needs to dynamically adjust height based on the conversation area height. * can be vh|px|rem|em|% */ maxHeight: { type: String, default: "unset" }, // Emoji picker props showEmojiPicker: { type: Boolean, default: true }, /** * Props to pass into the emoji picker. */ emojiPickerProps: { type: Object, default: () => ({}), validate(emojiPickerProps) { return [ "searchNoResultsLabel", "searchResultsLabel", "searchPlaceholderLabel", "skinSelectorButtonTooltipLabel", "tabSetLabels" ].every((prop) => emojiPickerProps[prop] != null); } }, /** * Emoji button tooltip label */ emojiTooltipMessage: { type: String, default: "Emoji" }, // Aria label for buttons /** * Emoji button aria label */ emojiButtonAriaLabel: { type: String, default: "emoji button" }, /** * Enable character Limit warning */ showCharacterLimit: { type: [Boolean, Object], default: () => ({ count: 1500, warning: 500, message: "" }) }, showImagePicker: { type: [Boolean, Object], default: () => ({ tooltipLabel: "Attach Image", ariaLabel: "image button" }) }, /** * Send button defaults. */ showSend: { type: [Boolean, Object], default: () => ({}) }, /** * Cancel button defaults. */ showCancel: { type: [Boolean, Object], default: () => ({ text: "Cancel" }) }, /** * suggestion object containing the items query function. * The valid keys passed into this object can be found here: https://tiptap.dev/api/utilities/suggestion * * The only required key is the items function which is used to query the contacts for suggestion. * items({ query }) => { return [ContactObject]; } * ContactObject format: * { name: string, avatarSrc: string, id: string } * * When null, it does not add the plugin. */ mentionSuggestion: { type: Object, default: null }, /** * suggestion object containing the items query function. * The valid keys passed into this object can be found here: https://tiptap.dev/api/utilities/suggestion * * The only required key is the items function which is used to query the channels for suggestion. * items({ query }) => { return [ChannelObject]; } * ChannelObject format: * { name: string, id: string, locked: boolean } * * When null, it does not add the plugin. Setting locked to true will display a lock rather than hash. */ channelSuggestion: { type: Object, default: null }, /** * suggestion object containing the items query function. * The valid keys passed into this object can be found here: https://tiptap.dev/api/utilities/suggestion * * The only required key is the items function which is used to query the slash commands for suggestion. * items({ query }) => { return [SlashCommandObject]; } * SlashCommandObject format: * { command: string, description: string, parametersExample?: string } * The "parametersExample" parameter is optional, and describes an example * of the parameters that command can take. * * When null, it does not add the plugin. */ slashCommandSuggestion: { type: Object, default: null }, /** * descriptive text fields for the bold button * * object format: * { ariaLabel: string, tooltipText: string, keyboardShortcutText: string } */ boldButtonOptions: { type: Object, default: () => ({ ariaLabel: "Toggle bold on selected text", tooltipText: "Bold", keyboardShortcutText: "Mod + B" }) }, /** * descriptive text fields for the italic button * * object format: * { ariaLabel: string, tooltipText: string, keyboardShortcutText: string } */ italicButtonOptions: { type: Object, default: () => ({ ariaLabel: "Toggle italic on selected text", tooltipText: "Italic", keyboardShortcutText: "Mod + I" }) }, /** * descriptive text fields for the strikethrough button * * object format: * { ariaLabel: string, tooltipText: string, keyboardShortcutText: string } */ strikeButtonOptions: { type: Object, default: () => ({ ariaLabel: "Toggle strikethrough on selected text", tooltipText: "Strikethrough", keyboardShortcutText: "Mod + Shift + S" }) }, /** * descriptive text fields for the link button * * object format: * { ariaLabel: string, tooltipText: string, keyboardShortcutText: string } */ linkButtonOptions: { type: Object, default: () => ({ ariaLabel: "Create or edit link on selected text", tooltipText: "Link", // TODO: implement mod k keyboardShortcutText: "Mod + K", dialogTitle: "Add a link", textLabel: "Text to display (optional)", linkLabel: "Link", linkPlaceholder: "e.g. https://www.dialpad.com", removeLabel: "Remove", cancelLabel: "Cancel", confirmLabel: "Done", visuallyHiddenCloseText: "Close link dialog" }) }, /** * descriptive text fields for the bullet list button * * object format: * { ariaLabel: string, tooltipText: string, keyboardShortcutText: string } */ bulletListButtonOptions: { type: Object, default: () => ({ ariaLabel: "Toggle bullet list on selected text", tooltipText: "Bullet list", keyboardShortcutText: "Mod + Shift + 8" }) }, /** * descriptive text fields for the ordered list button * * object format: * { ariaLabel: string, tooltipText: string, keyboardShortcutText: string } */ orderedListButtonOptions: { type: Object, default: () => ({ ariaLabel: "Toggle ordered list on selected text", tooltipText: "Ordered list", keyboardShortcutText: "Mod + Shift + 7" }) }, /** * descriptive text fields for the italic button * * object format: * { ariaLabel: string, tooltipText: string, keyboardShortcutText: string } */ blockQuoteButtonOptions: { type: Object, default: () => ({ ariaLabel: "Toggle Blockquote on selected text", tooltipText: "Blockquote", keyboardShortcutText: "Mod + Shift + B" }) }, /** * descriptive text fields for the code button * * object format: * { ariaLabel: string, tooltipText: string, keyboardShortcutText: string } */ codeButtonOptions: { type: Object, default: () => ({ ariaLabel: "Toggle code tag on selected text", tooltipText: "Code", keyboardShortcutText: "Mod + E" }) }, /** * descriptive text fields for the code block button * * object format: * { ariaLabel: string, tooltipText: string, keyboardShortcutText: string } */ codeBlockButtonOptions: { type: Object, default: () => ({ ariaLabel: "Toggle code block on selected text", tooltipText: "Code block", keyboardShortcutText: "Mod + Alt + C" }) } }, emits: [ /** * Fires when send button is clicked * * @event submit * @type {String} */ "submit", /** * Fires when media is selected from image button * * @event select-media * @type {Array} */ "select-media", /** * Fires when media is dropped into the message input * * @event add-media * @type {Array} */ "add-media", /** * Fires when media is pasted into the message input * * @event paste-media * @type {Array} */ "paste-media", /** * Fires when cancel button is pressed (only on edit mode) * * @event cancel * @type {Boolean} */ "cancel", /** * Fires when skin tone is selected from the emoji picker * * @event skin-tone * @type {String} */ "skin-tone", /** * Fires when emoji is selected from the emoji picker * * @event selected-emoji * @type {String} */ "selected-emoji", /** * Fires when a slash command is selected * * @event selected-command * @type {String} */ "selected-command", /** * Fires when meeting pill is closed * * @event meeting-pill-close * @type {String} */ "meeting-pill-close", /** * Event to sync the value with the parent * @event update:modelValue * @type {String|JSON} */ "update:modelValue", /** * Emitted when input changes, returns text content only * @event text-input * @type {String} */ "text-input" ], data() { return { // If an ordered list is nested within an unordered list, we only want to show the currently selected list as // active. This function performs the logic to determine the farthest active node from the root. lastActiveNodes: last_active_nodes.default, additionalExtensions: [meeting_pill.default], internalInputValue: this.modelValue, // internal input content imagePickerFocus: false, emojiPickerFocus: false, emojiPickerOpened: false, isFocused: false, linkOptions: { class: "d-link d-c-text d-d-inline-block" }, linkDialogOpen: false, selectedText: "", text: "", hideLinkBubbleMenu: false }; }, computed: { showSendIcon() { return !this.showSend.text; }, inputLength() { return this.text.length; }, displayCharacterLimitWarning() { return Boolean(this.showCharacterLimit) && this.showCharacterLimit.count - this.inputLength <= this.showCharacterLimit.warning; }, characterLimitTooltipEnabled() { return this.showCharacterLimit.message && this.showCharacterLimit.count - this.inputLength < 0; }, isSendDisabled() { return this.disableSend || this.showCharacterLimit && this.inputLength > this.showCharacterLimit.count; }, computedCloseButtonProps() { return { ariaLabel: "Close" }; }, emojiPickerHovered() { return this.emojiPickerFocus || this.emojiPickerOpened; }, sendIconSize() { return "300"; } }, watch: { modelValue(newValue) { this.internalInputValue = newValue; }, emojiPickerOpened(newValue) { var _a; if (!newValue) { (_a = this.$refs.richTextEditor) == null ? void 0 : _a.focusEditor(); } } }, created() { if (this.modelValue && this.outputFormat === "text") { this.internalInputValue = this.modelValue.replace(/\n/g, "<br>"); } else { this.internalInputValue = this.modelValue; } }, methods: { removeClassStyleAttrs: common_utils.removeClassStyleAttrs, addClassStyleAttrs: common_utils.addClassStyleAttrs, linkDialogOpened(value) { var _a; this.linkDialogOpen = value; if (value === true) { this.initLinkDialog(); } else { this.hideLinkBubbleMenu = false; (_a = this.$refs.richTextEditor) == null ? void 0 : _a.focusEditor(); } }, // eslint-disable-next-line complexity handleTopbarClick(type) { var _a; const editor = (_a = this.$refs.richTextEditor) == null ? void 0 : _a.editor; const typeToCommandMap = { bold: () => editor == null ? void 0 : editor.chain().focus().toggleBold().run(), italic: () => editor == null ? void 0 : editor.chain().focus().toggleItalic().run(), strike: () => editor == null ? void 0 : editor.chain().focus().toggleStrike().run(), bulletList: () => editor == null ? void 0 : editor.chain().focus().toggleBulletList().run(), orderedList: () => editor == null ? void 0 : editor.chain().focus().toggleOrderedList().run(), blockquote: () => editor == null ? void 0 : editor.chain().focus().toggleBlockquote().run(), code: () => editor == null ? void 0 : editor.chain().focus().toggleCode().run(), codeBlock: () => editor == null ? void 0 : editor.chain().focus().toggleCodeBlock().run() }; if (editor && typeToCommandMap[type]) { typeToCommandMap[type](); } }, // Checks if the node currently selected is active ex/ the bold button is active if the selected text is bold isSelectionActive(type) { var _a, _b, _c, _d; if (["bulletList", "orderedList"].includes(type)) { return this.lastActiveNodes((_b = (_a = this.$refs.richTextEditor) == null ? void 0 : _a.editor) == null ? void 0 : _b.state, [{ type: "bulletList" }, { type: "orderedList" }]).includes(type) && this.isFocused; } return ((_d = (_c = this.$refs.richTextEditor) == null ? void 0 : _c.editor) == null ? void 0 : _d.isActive(type)) && this.isFocused; }, initLinkDialog() { var _a, _b, _c; this.$refs.link.setInitialValues(this.selectedText, (_c = (_b = (_a = this.$refs.richTextEditor) == null ? void 0 : _a.editor) == null ? void 0 : _b.getAttributes("link")) == null ? void 0 : _c.href); this.hideLinkBubbleMenu = true; this.linkDialogOpen = true; }, removeLink() { var _a; (_a = this.$refs.richTextEditor) == null ? void 0 : _a.removeLink(); this.linkDialogOpen = false; }, setLink(linkText, linkInput) { this.$refs.richTextEditor.setLink( linkInput, linkText, this.linkOptions, editor_constants.EDITOR_SUPPORTED_LINK_PROTOCOLS, editor_constants.EDITOR_DEFAULT_LINK_PREFIX ); this.linkDialogOpen = false; }, // Mousedown instead of click because it fires before the blur event. onMousedown(e) { const isWithinInput = common_utils.returnFirstEl(this.$refs.richTextEditor.$el).querySelector(".tiptap").contains(e.target); if (!isWithinInput) { e.preventDefault(); this.$refs.richTextEditor.focusEditor(); } }, onDrop(e) { const dt = e.dataTransfer; const files = Array.from(dt.files); this.$emit("add-media", files); }, onPaste(e) { if (e.clipboardData.files.length) { e.stopPropagation(); e.preventDefault(); const files = [...e.clipboardData.files]; this.$emit("paste-media", files); } }, onSkinTone(skinTone) { this.$emit("skin-tone", skinTone); }, onSelectEmoji(emoji, close) { if (!emoji) { return; } if (!emoji.shift_key) { close(); } this.$refs.richTextEditor.editor.commands.insertContent({ type: "emoji", attrs: { code: emoji.shortname } }); this.$emit("selected-emoji", emoji); }, onSelectImage() { this.$refs.messageInputImageUpload.$refs.input.click(); }, onImageUpload() { this.$emit( "select-media", this.$refs.messageInputImageUpload.$refs.input.files ); }, toggleEmojiPicker() { this.emojiPickerOpened = !this.emojiPickerOpened; }, onSend() { if (this.isSendDisabled) { return; } this.$emit("submit", this.internalInputValue); }, onCancel() { this.$emit("cancel"); }, onInput(event) { this.$emit("update:modelValue", event); }, onTextInput(event) { this.text = event; this.$emit("text-input", event); } } }; const _hoisted_1 = { class: "d-recipe-message-input__bottom-section" }; const _hoisted_2 = { class: "d-recipe-message-input__bottom-section-left" }; const _hoisted_3 = { class: "d-recipe-message-input__bottom-section-right" }; const _hoisted_4 = { class: "d-recipe-message-input__sms-count" }; const _hoisted_5 = { key: 0 }; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { const _component_dt_recipe_message_input_link = vue.resolveComponent("dt-recipe-message-input-link"); const _component_dt_recipe_message_input_topbar = vue.resolveComponent("dt-recipe-message-input-topbar"); const _component_dt_rich_text_editor = vue.resolveComponent("dt-rich-text-editor"); const _component_dt_icon_image = vue.resolveComponent("dt-icon-image"); const _component_dt_button = vue.resolveComponent("dt-button"); const _component_dt_input = vue.resolveComponent("dt-input"); const _component_dt_icon_very_satisfied = vue.resolveComponent("dt-icon-very-satisfied"); const _component_dt_icon_satisfied = vue.resolveComponent("dt-icon-satisfied"); const _component_dt_emoji_picker = vue.resolveComponent("dt-emoji-picker"); const _component_dt_popover = vue.resolveComponent("dt-popover"); const _component_dt_stack = vue.resolveComponent("dt-stack"); const _component_dt_tooltip = vue.resolveComponent("dt-tooltip"); const _component_dt_icon_send = vue.resolveComponent("dt-icon-send"); const _directive_dt_scrollbar = vue.resolveDirective("dt-scrollbar"); const _directive_dt_tooltip = vue.resolveDirective("dt-tooltip"); return vue.openBlock(), vue.createElementBlock("div", vue.mergeProps({ "data-qa": "dt-recipe-message-input", role: "presentation", class: "d-recipe-message-input" }, $options.addClassStyleAttrs(_ctx.$attrs), { onDragover: _cache[12] || (_cache[12] = vue.withModifiers(() => { }, ["prevent"])), onDrop: _cache[13] || (_cache[13] = vue.withModifiers((...args) => $options.onDrop && $options.onDrop(...args), ["prevent"])), onPaste: _cache[14] || (_cache[14] = (...args) => $options.onPaste && $options.onPaste(...args)), onMousedown: _cache[15] || (_cache[15] = (...args) => $options.onMousedown && $options.onMousedown(...args)) }), [ vue.renderSlot(_ctx.$slots, "top"), $props.richText ? (vue.openBlock(), vue.createBlock(_component_dt_recipe_message_input_topbar, { key: $data.selectedText, "bold-button-options": $props.boldButtonOptions, "italic-button-options": $props.italicButtonOptions, "strike-button-options": $props.strikeButtonOptions, "bullet-list-button-options": $props.bulletListButtonOptions, "ordered-list-button-options": $props.orderedListButtonOptions, "block-quote-button-options": $props.blockQuoteButtonOptions, "code-button-options": $props.codeButtonOptions, "code-block-button-options": $props.codeBlockButtonOptions, "is-selection-active": $options.isSelectionActive, onClick: $options.handleTopbarClick }, { link: vue.withCtx(() => [ vue.createVNode(_component_dt_recipe_message_input_link, { ref: "link", open: $data.linkDialogOpen, "link-button-options": $props.linkButtonOptions, "is-selection-active": $options.isSelectionActive, onOpened: $options.linkDialogOpened, onSetLink: $options.setLink, onRemoveLink: $options.removeLink }, null, 8, ["open", "link-button-options", "is-selection-active", "onOpened", "onSetLink", "onRemoveLink"]) ]), _: 1 }, 8, ["bold-button-options", "italic-button-options", "strike-button-options", "bullet-list-button-options", "ordered-list-button-options", "block-quote-button-options", "code-button-options", "code-block-button-options", "is-selection-active", "onClick"])) : vue.createCommentVNode("", true), vue.withDirectives((vue.openBlock(), vue.createElementBlock("div", { class: "d-recipe-message-input__editor-wrapper", style: vue.normalizeStyle({ "max-height": $props.maxHeight }) }, [ vue.createVNode(_component_dt_rich_text_editor, vue.mergeProps({ ref: "richTextEditor", modelValue: $data.internalInputValue, "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => $data.internalInputValue = $event), "allow-blockquote": $props.richText, "allow-bold": $props.richText, "allow-bullet-list": $props.richText, "allow-code": $props.richText, "allow-codeblock": $props.richText, "allow-italic": $props.richText, "allow-strike": $props.richText, "allow-underline": $props.richText, editable: $props.editable, "input-aria-label": $props.inputAriaLabel, "input-class": $props.inputClass, "output-format": $props.outputFormat, "auto-focus": $props.autoFocus, link: $props.richText, placeholder: $props.placeholder, "prevent-typing": $props.preventTyping, "mention-suggestion": $props.mentionSuggestion, "channel-suggestion": $props.channelSuggestion, "slash-command-suggestion": $props.slashCommandSuggestion, "additional-extensions": $data.additionalExtensions, "hide-link-bubble-menu": $data.hideLinkBubbleMenu }, $options.removeClassStyleAttrs(_ctx.$attrs), { onInput: $options.onInput, onTextInput: $options.onTextInput, onEnter: $options.onSend, onSelected: _cache[1] || (_cache[1] = ($event) => $data.selectedText = $event), onEditLink: $options.initLinkDialog, onFocus: _cache[2] || (_cache[2] = ($event) => $data.isFocused = true), onBlur: _cache[3] || (_cache[3] = ($event) => $data.isFocused = false) }), null, 16, ["modelValue", "allow-blockquote", "allow-bold", "allow-bullet-list", "allow-code", "allow-codeblock", "allow-italic", "allow-strike", "allow-underline", "editable", "input-aria-label", "input-class", "output-format", "auto-focus", "link", "placeholder", "prevent-typing", "mention-suggestion", "channel-suggestion", "slash-command-suggestion", "additional-extensions", "hide-link-bubble-menu", "onInput", "onTextInput", "onEnter", "onEditLink"]) ], 4)), [ [_directive_dt_scrollbar] ]), vue.renderSlot(_ctx.$slots, "middle"), vue.createElementVNode("section", _hoisted_1, [ vue.createElementVNode("div", _hoisted_2, [ vue.createVNode(_component_dt_stack, { gap: "200", direction: "row" }, { default: vue.withCtx(() => { var _a; return [ $props.showImagePicker ? vue.withDirectives((vue.openBlock(), vue.createBlock(_component_dt_button, { key: 0, "data-qa": "dt-recipe-message-input-image-btn", size: "sm", class: "d-recipe-message-input__button", kind: "muted", importance: "clear", "aria-label": $props.showImagePicker.ariaLabel, onClick: $options.onSelectImage, onMouseenter: _cache[4] || (_cache[4] = ($event) => $data.imagePickerFocus = true), onMouseleave: _cache[5] || (_cache[5] = ($event) => $data.imagePickerFocus = false), onFocus: _cache[6] || (_cache[6] = ($event) => $data.imagePickerFocus = true), onBlur: _cache[7] || (_cache[7] = ($event) => $data.imagePickerFocus = false) }, { icon: vue.withCtx(() => [ vue.createVNode(_component_dt_icon_image, { size: "300" }) ]), _: 1 }, 8, ["aria-label", "onClick"])), [ [_directive_dt_tooltip, (_a = $props.showImagePicker) == null ? void 0 : _a.tooltipLabel, "top-start"] ]) : vue.createCommentVNode("", true), vue.createVNode(_component_dt_input, { ref: "messageInputImageUpload", "data-qa": "dt-recipe-message-input-image-input", accept: "image/*, video/*", type: "file", class: "d-recipe-message-input__image-input", multiple: "", hidden: "", onInput: $options.onImageUpload }, null, 8, ["onInput"]), $props.showEmojiPicker ? (vue.openBlock(), vue.createBlock(_component_dt_popover, { key: 1, "open.sync": "emojiPickerOpened", "data-qa": "dt-recipe-message-input-emoji-picker-popover", "initial-focus-element": "#searchInput", padding: "none" }, { anchor: vue.withCtx(({ attrs }) => [ vue.withDirectives((vue.openBlock(), vue.createBlock(_component_dt_button, vue.mergeProps(attrs, { "data-qa": "dt-recipe-message-input-emoji-picker-btn", size: "sm", class: "d-recipe-message-input__button", kind: "muted", importance: "clear", "aria-label": $props.emojiButtonAriaLabel, onClick: $options.toggleEmojiPicker, onMouseenter: _cache[8] || (_cache[8] = ($event) => $data.emojiPickerFocus = true), onMouseleave: _cache[9] || (_cache[9] = ($event) => $data.emojiPickerFocus = false), onFocus: _cache[10] || (_cache[10] = ($event) => $data.emojiPickerFocus = true), onBlur: _cache[11] || (_cache[11] = ($event) => $data.emojiPickerFocus = false) }), { icon: vue.withCtx(() => [ $options.emojiPickerHovered ? (vue.openBlock(), vue.createBlock(_component_dt_icon_very_satisfied, { key: 0, size: "300" })) : (vue.openBlock(), vue.createBlock(_component_dt_icon_satisfied, { key: 1, size: "300" })) ]), _: 2 }, 1040, ["aria-label", "onClick"])), [ [_directive_dt_tooltip, $props.emojiTooltipMessage] ]) ]), content: vue.withCtx(({ close }) => [ vue.createVNode(_component_dt_emoji_picker, vue.mergeProps($props.emojiPickerProps, { onSkinTone: $options.onSkinTone, onSelectedEmoji: (emoji) => $options.onSelectEmoji(emoji, close) }), null, 16, ["onSkinTone", "onSelectedEmoji"]) ]), _: 1 })) : vue.createCommentVNode("", true), vue.renderSlot(_ctx.$slots, "emojiGiphyPicker"), vue.renderSlot(_ctx.$slots, "customActionIcons") ]; }), _: 3 }) ]), vue.createElementVNode("div", _hoisted_3, [ vue.createVNode(_component_dt_stack, { direction: "row", gap: "300" }, { default: vue.withCtx(() => [ vue.createElementVNode("div", _hoisted_4, [ vue.renderSlot(_ctx.$slots, "smsCount") ]), Boolean($props.showCharacterLimit) ? (vue.openBlock(), vue.createBlock(_component_dt_tooltip, { key: 0, class: "d-recipe-message-input__remaining-char-tooltip", placement: "top-end", enabled: $options.characterLimitTooltipEnabled, message: $props.showCharacterLimit.message, offset: [10, 8] }, { anchor: vue.withCtx(() => [ vue.withDirectives(vue.createElementVNode("p", { class: "d-recipe-message-input__remaining-char", "data-qa": "dt-recipe-message-input-character-limit" }, vue.toDisplayString($props.showCharacterLimit.count - $options.inputLength), 513), [ [vue.vShow, $options.displayCharacterLimitWarning] ]) ]), _: 1 }, 8, ["enabled", "message"])) : vue.createCommentVNode("", true), $props.showCancel ? (vue.openBlock(), vue.createBlock(_component_dt_button, { key: 1, "data-qa": "dt-recipe-message-input-cancel-button", class: "d-recipe-message-input__button d-recipe-message-input__cancel-button", size: "sm", kind: "muted", importance: "clear", "aria-label": $props.showCancel.ariaLabel, onClick: $options.onCancel }, { default: vue.withCtx(() => [ vue.createElementVNode("p", null, vue.toDisplayString($props.showCancel.text), 1) ]), _: 1 }, 8, ["aria-label", "onClick"])) : vue.createCommentVNode("", true), vue.renderSlot(_ctx.$slots, "sendButton", {}, () => { var _a; return [ $props.showSend ? vue.withDirectives((vue.openBlock(), vue.createBlock(_component_dt_button, { key: 0, "data-qa": "dt-recipe-message-input-send-btn", size: "sm", kind: "default", importance: "primary", class: vue.normalizeClass([ "d-recipe-message-input__button d-recipe-message-input__send-button", { "d-recipe-message-input__send-button--disabled": $options.isSendDisabled, "d-btn--icon-only": $options.showSendIcon } ]), "aria-label": $props.showSend.ariaLabel, "aria-disabled": $options.isSendDisabled, onClick: $options.onSend }, vue.createSlots({ default: vue.withCtx(() => [ $props.showSend.text ? (vue.openBlock(), vue.createElementBlock("p", _hoisted_5, vue.toDisplayString($props.showSend.text), 1)) : vue.createCommentVNode("", true) ]), _: 2 }, [ $options.showSendIcon ? { name: "icon", fn: vue.withCtx(() => [ vue.renderSlot(_ctx.$slots, "sendIcon", { iconSize: $options.sendIconSize }, () => [ vue.createVNode(_component_dt_icon_send, { size: $options.sendIconSize }, null, 8, ["size"]) ]) ]), key: "0" } : void 0 ]), 1032, ["class", "aria-label", "aria-disabled", "onClick"])), [ [_directive_dt_tooltip, (_a = $props.showSend) == null ? void 0 : _a.tooltipLabel, "top-end"] ]) : vue.createCommentVNode("", true) ]; }) ]), _: 3 }) ]) ]) ], 16); } const message_input = /* @__PURE__ */ _pluginVue_exportHelper.default(_sfc_main, [["render", _sfc_render]]); exports.default = message_input; //# sourceMappingURL=message_input.vue.cjs.map