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