@dialpad/dialtone
Version:
Dialpad's Dialtone design system monorepo
193 lines (192 loc) • 5.5 kB
JavaScript
import { LIST_ITEM_TYPES, LIST_ITEM_NAVIGATION_TYPES } from "./list_item_constants.js";
import utils from "../../common/utils.js";
import { DtIconCheck } from "@dialpad/dialtone-icons/vue2";
import normalizeComponent from "../../_virtual/_plugin-vue2_normalizer.js";
import DtItemLayout from "../item_layout/item_layout.vue.js";
const ROLES = ["listitem", "menuitem", "option"];
const _sfc_main = {
name: "DtListItem",
components: {
DtItemLayout,
DtIconCheck
},
/**
* Value provided from keyboard_list_navigation.js using id prop.
*/
inject: {
highlightId: { default: null }
},
props: {
/**
* Id for the item.
*/
id: {
type: String,
default() {
return utils.getUniqueString();
}
},
/**
* String to use for the item's role.
*/
role: {
type: String,
default: "listitem",
validator: (role) => ROLES.includes(role)
},
/**
* HTML element type (tag name) of the content wrapper element.
*/
elementType: {
type: String,
default: "li"
},
/**
* The type of child list item to use.
* @values default, custom
*/
type: {
type: String,
default: LIST_ITEM_TYPES.DEFAULT,
validator: (t) => Object.values(LIST_ITEM_TYPES).includes(t)
},
/**
* The type of navigation that this component should support.
* - "arrow-keys" for items that are navigated with UP/DOWN keys.
* - "tab" for items that are navigated using the TAB key.
* - "none" for static items that are not interactive.
* @values arrow-keys, tab, none
*/
navigationType: {
type: String,
default: LIST_ITEM_NAVIGATION_TYPES.NONE,
validator: (t) => Object.values(LIST_ITEM_NAVIGATION_TYPES).includes(t)
},
/**
* Applies selected styles to the list item
*/
selected: {
type: Boolean,
default: false
}
},
emits: [
/**
* Native click event
*
* @event click
* @type {PointerEvent | KeyboardEvent}
*/
"click",
/**
* Key down event
*
* @event keydown
* @type {KeyboardEvent}
*/
"keydown",
/**
* Native mouse move event
*
* @event mousemove
* @type {MouseEvent}
*/
"mousemove",
/**
* Native mouse leave event
*
* @event mouseleave
* @type {MouseEvent}
*/
"mouseleave"
],
data() {
return {
injected: false,
mouseHighlighted: false
};
},
computed: {
isDefaultType() {
if (this.type === LIST_ITEM_TYPES.DEFAULT) return true;
return false;
},
listItemListeners() {
return {
...this.$listeners,
keydown: (event) => {
if (["enter", "space"].includes(event.code.toLowerCase())) {
this.onClick(event);
}
this.$emit("keydown", event);
},
mousemove: (event) => {
this.onMouseHover(event);
this.$emit("mousemove", event);
},
mouseleave: (event) => {
this.onMouseLeave(event);
this.$emit("mouseleave", event);
}
};
},
/**
* For keyboard navigation, whether this item is currently highlighted.
* An injected highlightId will override the default mouseover highlight.
*/
isHighlighted() {
if (this.isHoverable) {
return this.highlightId && this.highlightId() ? this.id === this.highlightId() : this.mouseHighlighted;
}
return false;
},
isFocusable() {
return this.navigationType === LIST_ITEM_NAVIGATION_TYPES.TAB;
},
/**
* Whether to apply hover styles.
*/
isHoverable() {
return this.navigationType !== LIST_ITEM_NAVIGATION_TYPES.NONE;
}
},
methods: {
onClick(e) {
this.$emit("click", e);
},
onMouseHover() {
this.mouseHighlighted = true;
},
onMouseLeave() {
this.mouseHighlighted = false;
}
}
};
var _sfc_render = function render() {
var _vm = this, _c = _vm._self._c;
return _c(_vm.elementType, _vm._g({ tag: "component", class: [
"d-list-item",
{
"d-list-item--focusable": _vm.isFocusable,
"d-list-item--highlighted": _vm.isHighlighted,
"d-list-item--static": !_vm.isHoverable
}
], attrs: { "id": _vm.id, "tabindex": _vm.isFocusable ? 0 : -1, "role": _vm.role, "aria-selected": _vm.role === "listitem" ? void 0 : _vm.isHighlighted } }, _vm.listItemListeners), [_vm.isDefaultType ? _c("dt-item-layout", { staticClass: "d-list-item__wrapper", attrs: { "unstyled": "", "left-class": "d-list-item__left", "content-class": "d-list-item__content", "title-class": "d-list-item__title", "subtitle-class": "d-list-item__subtitle", "bottom-class": "d-list-item__bottom", "right-class": "d-list-item__right", "selected-class": "d-list-item__selected" }, scopedSlots: _vm._u([_vm._l(_vm.$slots, function(_, slotName) {
return { key: slotName, fn: function() {
return [_vm._t(slotName)];
}, proxy: true };
}), _vm.selected ? { key: "selected", fn: function() {
return [_c("dt-icon-check", { attrs: { "size": "400" } })];
}, proxy: true } : null], null, true) }) : _vm._t("default")], 2);
};
var _sfc_staticRenderFns = [];
var __component__ = /* @__PURE__ */ normalizeComponent(
_sfc_main,
_sfc_render,
_sfc_staticRenderFns
);
const DtListItem = __component__.exports;
export {
DtListItem as default
};
//# sourceMappingURL=list_item.vue.js.map