@dialpad/dialtone
Version:
Dialpad's Dialtone design system monorepo
242 lines (241 loc) • 7.28 kB
JavaScript
import { TAB_LIST_SIZES, TAB_LIST_SIZE_MODIFIERS, TAB_LIST_KIND_MODIFIERS, TAB_LIST_IMPORTANCE_MODIFIERS } from "./tabs_constants.js";
import normalizeComponent from "../../_virtual/_plugin-vue2_normalizer.js";
const _sfc_main = {
name: "DtTabGroup",
provide() {
return {
groupContext: this.provideObj,
setFocus: this.setFocus
};
},
props: {
/**
* Identifies the tab group
*/
label: {
type: String,
default: ""
},
/**
* The id of the selected tab panel which should be displayed
*/
selected: {
type: String,
default: ""
},
/**
* If true, disables the tab group
* @values true, false
*/
disabled: {
type: Boolean,
default: false
},
/**
* If true, applies inverted styles to the tab group
* @values true, false
*/
inverted: {
type: Boolean,
default: false
},
/**
* If true, applies borderless styles to the tab group
* @values true, false
*/
borderless: {
type: Boolean,
default: false
},
/**
* If provided, applies size styles to the tab group
* @values default, sm
*/
size: {
type: String,
default: "default",
validate(size) {
return TAB_LIST_SIZES.includes(size);
}
},
/**
* Pass through classes, used to customize the tab list
*/
tabListClass: {
type: [String, Array, Object],
default: ""
},
/**
* Pass through props, used to customize the tab list
*/
tabListChildProps: {
type: Object,
default: () => ({})
}
},
emits: [
/**
* Change tab event with the arguments: selected id of the current tab and disabled value
*
* @event change
* @type {Object}
*/
"change",
/**
* Before change tab event with the event argument, useful to perform validations and prevent changing tabs if neccessary.
*
* @event before-change
* @type {Event}
*/
"before-change"
],
data() {
return {
provideObj: {
selected: "",
// the currently displayed tab id
disabled: false
// disable group
},
focusId: null,
tabs: [],
TAB_LIST_SIZE_MODIFIERS,
TAB_LIST_KIND_MODIFIERS,
TAB_LIST_IMPORTANCE_MODIFIERS
};
},
watch: {
disabled: {
immediate: true,
handler() {
this.provideObj.disabled = this.disabled;
}
},
selected: {
immediate: true,
handler() {
this.provideObj.selected = this.selected;
}
}
},
mounted() {
this.updateSelected();
},
beforeUpdate() {
this.updateSelected();
},
methods: {
updateSelected() {
if (!this.provideObj.selected) {
this.provideObj.selected = this.selected;
}
this.tabs = this.getTabChildren();
},
setFocus(focusId) {
this.focusId = focusId;
},
getTabChildren() {
return Array.from(this.$el.querySelectorAll(".d-tab")).map((el) => {
var _a, _b;
return {
context: el,
panelId: (_a = el.getAttribute("aria-controls")) == null ? void 0 : _a.replace("dt-panel-", ""),
tabId: (_b = el.getAttribute("id")) == null ? void 0 : _b.replace("dt-tab-", ""),
isSelected: el.getAttribute("aria-selected") === "true"
};
});
},
onChange() {
this.$emit("change", { ...this.provideObj });
},
tabLeft() {
const index = this.getFocusedTabIndex();
if (index === -1) return;
const indexElement = index - 1 < 0 ? this.tabs.length - 1 : index - 1;
this.selectFocusOnTab(indexElement);
},
tabRight() {
const index = this.getFocusedTabIndex();
if (index === -1) return;
const indexElement = index + 1 > this.tabs.length - 1 ? 0 : index + 1;
this.selectFocusOnTab(indexElement);
},
selectFocusOnTab(index) {
const { context } = this.tabs[index];
context.focus();
},
selectTab(event) {
if (this.isSameTabClicked()) return;
this.$emit("before-change", event);
if (event.defaultPrevented) return;
const index = this.getFocusedTabIndex();
this.selectTabByIndex(index);
this.onChange();
},
selectTabByIndex(index) {
const { context, panelId } = this.tabs[index];
this.provideObj.selected = panelId;
context.focus();
},
getFocusedTabIndex() {
return this.tabs.findIndex((context) => this.focusId ? context.tabId === `${this.focusId}` : context.isSelected);
},
onHomeButton() {
var _a, _b;
if (this.tabs.length === 0) return;
(_b = (_a = this.tabs[0]) == null ? void 0 : _a.context) == null ? void 0 : _b.focus();
},
onEndButton() {
var _a, _b;
if (this.tabs.length === 0) return;
(_b = (_a = this.tabs[this.tabs.length - 1]) == null ? void 0 : _a.context) == null ? void 0 : _b.focus();
},
isSameTabClicked() {
const tab = this.tabs[this.getFocusedTabIndex()];
return this.provideObj.selected === tab.panelId;
}
}
};
var _sfc_render = function render() {
var _vm = this, _c = _vm._self._c;
return _c("div", { attrs: { "data-qa": "dt-tab-group" } }, [_c("div", _vm._b({ class: [
"d-tablist",
_vm.TAB_LIST_SIZE_MODIFIERS[_vm.size],
{
[_vm.TAB_LIST_KIND_MODIFIERS.inverted]: _vm.inverted,
[_vm.TAB_LIST_IMPORTANCE_MODIFIERS.borderless]: _vm.borderless
},
_vm.tabListClass
], attrs: { "role": "tablist", "aria-label": _vm.label }, on: { "keyup": [function($event) {
if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "left", 37, $event.key, ["Left", "ArrowLeft"])) return null;
if ("button" in $event && $event.button !== 0) return null;
return _vm.tabLeft.apply(null, arguments);
}, function($event) {
if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "right", 39, $event.key, ["Right", "ArrowRight"])) return null;
if ("button" in $event && $event.button !== 2) return null;
return _vm.tabRight.apply(null, arguments);
}, function($event) {
if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "enter", 13, $event.key, "Enter")) return null;
return _vm.selectTab.apply(null, arguments);
}, function($event) {
if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "space", 32, $event.key, [" ", "Spacebar"])) return null;
return _vm.selectTab.apply(null, arguments);
}], "click": _vm.selectTab, "keydown": [function($event) {
if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "home", void 0, $event.key, void 0)) return null;
return _vm.onHomeButton.apply(null, arguments);
}, function($event) {
if (!$event.type.indexOf("key") && _vm._k($event.keyCode, "end", void 0, $event.key, void 0)) return null;
return _vm.onEndButton.apply(null, arguments);
}] } }, "div", _vm.tabListChildProps, false), [_vm._t("tabs")], 2), _vm._t("default")], 2);
};
var _sfc_staticRenderFns = [];
var __component__ = /* @__PURE__ */ normalizeComponent(
_sfc_main,
_sfc_render,
_sfc_staticRenderFns
);
const DtTabGroup = __component__.exports;
export {
DtTabGroup as default
};
//# sourceMappingURL=tab_group.vue.js.map