@dialpad/dialtone
Version:
Dialpad's Dialtone design system monorepo
950 lines (949 loc) • 36 kB
JavaScript
;
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