UNPKG

@dialpad/dialtone

Version:

Dialpad's Dialtone design system monorepo

437 lines (436 loc) 15.6 kB
import { LEFTBAR_GENERAL_ROW_TYPES, LEFTBAR_GENERAL_ROW_CONTACT_CENTER_COLORS, LEFTBAR_GENERAL_ROW_ICON_SIZES, LEFTBAR_GENERAL_ROW_CONTACT_CENTER_VALIDATION_ERROR } from "./general_row_constants.js"; import { DtIconPhone, DtIconWaveform } from "@dialpad/dialtone-icons/vue3"; import DtEmojiTextWrapper from "../../../components/emoji_text_wrapper/emoji_text_wrapper.vue.js"; import DtRecipeLeftbarGeneralRowIcon from "./leftbar_general_row_icon.vue.js"; import { extractVueListeners, safeConcatStrings, returnFirstEl, removeClassStyleAttrs, addClassStyleAttrs } from "../../../common/utils.js"; import { resolveComponent, openBlock, createElementBlock, mergeProps, createElementVNode, toHandlers, renderSlot, createVNode, normalizeStyle, withCtx, createTextVNode, toDisplayString, createBlock, createCommentVNode, normalizeClass, withModifiers } from "vue"; import _export_sfc from "../../../_virtual/_plugin-vue_export-helper.js"; import DtBadge from "../../../components/badge/badge.vue.js"; import DtButton from "../../../components/button/button.vue.js"; import DtTooltip from "../../../components/tooltip/tooltip.vue.js"; const _sfc_main = { compatConfig: { MODE: 3 }, name: "DtRecipeGeneralRow", components: { DtEmojiTextWrapper, DtBadge, DtButton, DtTooltip, DtIconPhone, DtIconWaveform, DtRecipeLeftbarGeneralRowIcon }, inheritAttrs: false, props: { /** * Determines the icon to show. * If type is contact center, the color prop must be provided and will determine the color of the icon */ type: { type: String, default: "inbox", validator: (type) => { return Object.values(LEFTBAR_GENERAL_ROW_TYPES).includes(type); } }, /** * Will be read out by a screen reader upon focus of this row. If not defined "description" will be read. */ ariaLabel: { type: String, default: "" }, /** * Text displayed next to the icon. Required. Even if you are overriding this field using the label slot * you still must input this as it will be displayed as the "title" attribute for the row. */ description: { type: String, required: true }, /** * Determines the color of the contact center icon */ color: { type: String, default: null, validator: (color) => { return Object.keys(LEFTBAR_GENERAL_ROW_CONTACT_CENTER_COLORS).includes(color); } }, /** * The channel setting, either 'mention' or 'always'. * @values 'mention', 'always', null. */ channelSetting: { type: String, default: null }, /** * Styles the row with an increased font weight to convey it has unreads. This must be true to see * the unread count badge. */ hasUnreads: { type: Boolean, default: false }, /** * Number of unread messages */ unreadCount: { type: String, default: null }, /** * Number of unread mention messages */ unreadMentionCount: { type: String, default: null }, /** * Text shown when the unread count is hovered. */ unreadCountTooltip: { type: String, default: "" }, /** * Determines if the row is selected */ selected: { type: Boolean, default: false }, /** * Gives a faded style to be used when muted */ muted: { type: Boolean, default: false }, /** * Shows styling to represent an active voice chat. This will display over unreadCount. */ activeVoiceChat: { type: Boolean, default: false }, /** * Acronym used to represent "Do not Disturb" state. If entered will display the entered text alongside * unreadCount. */ dndText: { type: String, default: "" }, /** * Text shown in tooltip when you hover the dndText */ dndTextTooltip: { type: String, default: "" }, /** * Whether the row should have a call button. Usually only applicable to individual contact rows. */ hasCallButton: { type: Boolean, default: false }, /** * Text shown when the call button is hovered. */ callButtonTooltip: { type: String, default: "" }, /** * Shows an "is typing" animation over the avatar when true. */ isTyping: { type: Boolean, default: false }, /** * Sets the size of the icon. */ iconSize: { type: String, default: "300", validator: (size) => { return LEFTBAR_GENERAL_ROW_ICON_SIZES.includes(size); } } }, emits: [ /** * Call button clicked * * @event call * @type {PointerEvent | KeyboardEvent} */ "call" ], data() { return { actionFocused: false, labelWidth: "100%" }; }, computed: { leftbarGeneralRowClasses() { return [ "d-recipe-leftbar-row", { "d-recipe-leftbar-row--no-action": !this.hasCallButton, "d-recipe-leftbar-row--has-unread": this.hasUnreads, "d-recipe-leftbar-row__unread-count": this.showUnreadCount || this.showUnreadMentionCount, "d-recipe-leftbar-row--selected": this.selected, "d-recipe-leftbar-row--muted": this.muted, "d-recipe-leftbar-row--action-focused": this.actionFocused } ]; }, getIcon() { switch (this.type) { case LEFTBAR_GENERAL_ROW_TYPES.CHANNELS: if (this.hasUnreads) return "channel unread"; break; case LEFTBAR_GENERAL_ROW_TYPES.LOCKED_CHANNEL: if (this.hasUnreads) return "locked channel unread"; break; } return this.type; }, generalRowListeners() { return extractVueListeners(this.$attrs); }, getAriaLabel() { return this.ariaLabel ? this.ariaLabel : safeConcatStrings([this.description, this.unreadCountTooltip, this.dndTextTooltip]); }, hasActions() { return this.dndText || this.activeVoiceChat || this.showUnreadCount || this.hasCallButton || this.showUnreadMentionCount; }, showUnreadCount() { return !!this.unreadCount && this.hasUnreads; }, showUnreadMentionCount() { return !!this.unreadMentionCount && this.hasUnreads; }, hasUnreadCount() { return this.unreadCount !== null; }, hasUnreadMentionCount() { return this.unreadMentionCount !== null; }, shouldApplyCustomStyleForCountBadge() { return this.hasUnreadCount && this.hasUnreadMentionCount; }, /** * When a channel in 'always' setting, meaning the user should see both unread count and unread mention count, * if there are only mention messages, we should apply the theme design tokens var(--dt-theme-mention-color-[background||foreground]-strong). * @returns {boolean} */ shouldApplyCustomStyleForMentionOnly() { return this.channelSetting === "always" && !this.hasUnreadCount && this.hasUnreadMentionCount; } }, watch: { $props: { immediate: true, deep: true, async handler() { this.validateProps(); await this.$nextTick(); this.adjustLabelWidth(); } } }, mounted() { this.resizeObserver = new ResizeObserver(this.adjustLabelWidth); this.resizeObserver.observe(returnFirstEl(this.$el)); this.adjustLabelWidth(); }, beforeUnmount: function() { this.resizeObserver.disconnect(); }, methods: { removeClassStyleAttrs, addClassStyleAttrs, validateProps() { if (this.type === LEFTBAR_GENERAL_ROW_TYPES.CONTACT_CENTER && !Object.keys(LEFTBAR_GENERAL_ROW_CONTACT_CENTER_COLORS).includes(this.color)) { console.error(LEFTBAR_GENERAL_ROW_CONTACT_CENTER_VALIDATION_ERROR); } }, adjustLabelWidth() { var _a, _b, _c, _d, _e, _f; const labelWidth = ((_b = (_a = returnFirstEl(this.$el)) == null ? void 0 : _a.querySelector(".d-recipe-leftbar-row__primary")) == null ? void 0 : _b.clientWidth) || 0; const omegaWidth = ((_d = (_c = returnFirstEl(this.$el)) == null ? void 0 : _c.querySelector(".d-recipe-leftbar-row__omega")) == null ? void 0 : _d.clientWidth) || 0; const alphaWidth = ((_f = (_e = returnFirstEl(this.$el)) == null ? void 0 : _e.querySelector(".d-recipe-leftbar-row__alpha")) == null ? void 0 : _f.clientWidth) || 0; const paddings = 16; this.labelWidth = labelWidth - (omegaWidth + alphaWidth + paddings) + "px"; } } }; const _hoisted_1 = ["data-qa", "aria-label", "title", "href"]; const _hoisted_2 = { class: "d-recipe-leftbar-row__alpha" }; const _hoisted_3 = { key: 0, class: "d-recipe-leftbar-row__is-typing" }; const _hoisted_4 = /* @__PURE__ */ createElementVNode("span", null, null, -1); const _hoisted_5 = /* @__PURE__ */ createElementVNode("span", null, null, -1); const _hoisted_6 = /* @__PURE__ */ createElementVNode("span", null, null, -1); const _hoisted_7 = [ _hoisted_4, _hoisted_5, _hoisted_6 ]; const _hoisted_8 = { key: 0, class: "d-recipe-leftbar-row__omega" }; const _hoisted_9 = { key: 1, class: "d-recipe-leftbar-row__active-voice" }; const _hoisted_10 = { key: 3, class: "d-recipe-leftbar-row__action", "data-qa": "dt-recipe-leftbar-row-action" }; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { const _component_dt_recipe_leftbar_general_row_icon = resolveComponent("dt-recipe-leftbar-general-row-icon"); const _component_dt_emoji_text_wrapper = resolveComponent("dt-emoji-text-wrapper"); const _component_dt_tooltip = resolveComponent("dt-tooltip"); const _component_dt_icon_waveform = resolveComponent("dt-icon-waveform"); const _component_dt_badge = resolveComponent("dt-badge"); const _component_dt_icon_phone = resolveComponent("dt-icon-phone"); const _component_dt_button = resolveComponent("dt-button"); return openBlock(), createElementBlock("div", mergeProps({ class: $options.leftbarGeneralRowClasses }, $options.addClassStyleAttrs(_ctx.$attrs), { "data-qa": "dt-recipe-leftbar-row" }), [ createElementVNode("a", mergeProps({ class: "d-recipe-leftbar-row__primary", "data-qa": "data-qa" in _ctx.$attrs ? _ctx.$attrs["data-qa"] : "d-recipe-leftbar-row-link", "aria-label": $options.getAriaLabel, title: $props.description, href: "href" in _ctx.$attrs ? _ctx.$attrs.href : "javascript:void(0)" }, $options.removeClassStyleAttrs(_ctx.$attrs), toHandlers($options.generalRowListeners, true)), [ createElementVNode("div", _hoisted_2, [ $props.isTyping ? (openBlock(), createElementBlock("div", _hoisted_3, _hoisted_7)) : renderSlot(_ctx.$slots, "left", { key: 1 }, () => [ createVNode(_component_dt_recipe_leftbar_general_row_icon, { type: $options.getIcon, color: $props.color, "icon-size": $props.iconSize, "data-qa": "dt-recipe-leftbar-row-icon" }, null, 8, ["type", "color", "icon-size"]) ]) ]), createElementVNode("div", { class: "d-recipe-leftbar-row__label", style: normalizeStyle(`flex-basis: ${$data.labelWidth}`) }, [ renderSlot(_ctx.$slots, "label", {}, () => [ createVNode(_component_dt_emoji_text_wrapper, { class: "d-recipe-leftbar-row__description", "data-qa": "dt-recipe-leftbar-row-description", size: "200" }, { default: withCtx(() => [ createTextVNode(toDisplayString($props.description), 1) ]), _: 1 }) ]) ], 4) ], 16, _hoisted_1), $options.hasActions ? (openBlock(), createElementBlock("div", _hoisted_8, [ $props.dndText ? (openBlock(), createBlock(_component_dt_tooltip, { key: 0, placement: "top", message: $props.dndTextTooltip }, { anchor: withCtx(() => [ createElementVNode("div", { ref: "d-recipe-leftbar-row-dnd", class: "d-recipe-leftbar-row__dnd", "data-qa": "dt-recipe-leftbar-row-dnd" }, toDisplayString($props.dndText), 513) ]), _: 1 }, 8, ["message"])) : createCommentVNode("", true), $props.activeVoiceChat ? (openBlock(), createElementBlock("div", _hoisted_9, [ createVNode(_component_dt_icon_waveform, { size: "300" }) ])) : $options.showUnreadCount || $options.showUnreadMentionCount ? (openBlock(), createBlock(_component_dt_tooltip, { key: 2, message: $props.unreadCountTooltip, placement: "top" }, { anchor: withCtx(() => [ $options.showUnreadCount ? (openBlock(), createBlock(_component_dt_badge, { key: 0, kind: "count", type: "bulletin", "data-qa": "dt-recipe-leftbar-row-unread-badge", class: normalizeClass(["d-recipe-leftbar-row__unread-badge", { "d-recipe-leftbar-row__unread-count-badge": $options.shouldApplyCustomStyleForCountBadge }]) }, { default: withCtx(() => [ createTextVNode(toDisplayString($props.unreadCount), 1) ]), _: 1 }, 8, ["class"])) : createCommentVNode("", true), $options.showUnreadMentionCount ? (openBlock(), createBlock(_component_dt_badge, { key: 1, kind: "count", type: "bulletin", "data-qa": "dt-recipe-leftbar-row-unread-mention-badge", class: normalizeClass([ "d-recipe-leftbar-row__unread-badge", { "d-recipe-leftbar-row__unread-mention-count-badge": $options.shouldApplyCustomStyleForCountBadge }, { "d-recipe-leftbar-row__unread-mention-only-count-badge": $options.shouldApplyCustomStyleForMentionOnly } ]) }, { default: withCtx(() => [ createTextVNode(toDisplayString($props.unreadMentionCount), 1) ]), _: 1 }, 8, ["class"])) : createCommentVNode("", true) ]), _: 1 }, 8, ["message"])) : createCommentVNode("", true), $props.hasCallButton ? (openBlock(), createElementBlock("div", _hoisted_10, [ createVNode(_component_dt_tooltip, { message: $props.callButtonTooltip, placement: "top" }, { anchor: withCtx(() => [ createVNode(_component_dt_button, { class: "d-recipe-leftbar-row__action-button", "data-qa": "dt-recipe-leftbar-row-action-call-button", circle: true, size: "xs", kind: "inverted", "aria-label": $props.callButtonTooltip, onFocus: _cache[0] || (_cache[0] = ($event) => $data.actionFocused = true), onBlur: _cache[1] || (_cache[1] = ($event) => $data.actionFocused = false), onClick: _cache[2] || (_cache[2] = withModifiers(($event) => _ctx.$emit("call", $event), ["stop"])) }, { icon: withCtx(() => [ createVNode(_component_dt_icon_phone, { size: "200" }) ]), _: 1 }, 8, ["aria-label"]) ]), _: 1 }, 8, ["message"]) ])) : createCommentVNode("", true) ])) : createCommentVNode("", true) ], 16); } const DtRecipeGeneralRow = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]); export { DtRecipeGeneralRow as default }; //# sourceMappingURL=general_row.vue.js.map