@dialpad/dialtone
Version:
Dialpad's Dialtone design system monorepo
196 lines (195 loc) • 5.96 kB
JavaScript
import { getUniqueString } from "../../common/utils.js";
import DtCollapsibleLazyShow from "./collapsible_lazy_show.vue.js";
import { DtIconChevronDown, DtIconChevronRight } from "@dialpad/dialtone-icons/vue2";
import normalizeComponent from "../../_virtual/_plugin-vue2_normalizer.js";
import DtButton from "../button/button.vue.js";
import DtLazyShow from "../lazy_show/lazy_show.vue.js";
const _sfc_main = {
name: "DtCollapsible",
components: {
DtButton,
DtCollapsibleLazyShow,
DtLazyShow,
DtIconChevronDown,
DtIconChevronRight
},
props: {
/**
* Text that is displayed on the anchor if nothing is passed in the slot.
* Ignored if the anchor slot is used.
*/
anchorText: {
type: String,
default: null
},
/**
* Controls whether the collapsible is shown. Leaving this null will have the collapsible start
* expanded and trigger on click by default. If you set this value, the default trigger
* behavior will be disabled, and you can control it as you need.
* Supports .sync modifier
* @values null, true, false
*/
open: {
type: Boolean,
default: null
},
/**
* The id of the content wrapper.
*/
id: {
type: String,
default() {
return getUniqueString();
}
},
/**
* HTML element type (tag name) of the root element of the component.
*/
elementType: {
type: String,
default: "div"
},
/**
* HTML element type (tag name) of the content wrapper element.
*/
contentElementType: {
type: String,
default: "div"
},
/**
* Additional class name for the anchor wrapper element.
*/
anchorClass: {
type: [String, Array, Object],
default: null
},
/**
* Additional class name for the content wrapper element.
*/
contentClass: {
type: [String, Array, Object],
default: null
},
/**
* The maximum width of the anchor and collapsible element.
* Possible units rem|px|%|em
*/
maxWidth: {
type: String,
default: null
},
/**
* The maximum height of the collapsible element.
* Possible units rem|px|%|em
*/
maxHeight: {
type: String,
default: null
},
/**
* Label on the collapsible content. Should provide this or ariaLabelledBy but not both.
*/
ariaLabel: {
type: String,
default: null
},
/**
* Id of the element that labels the collapsible content. Defaults to the anchor element.
* Should provide this or ariaLabel but not both.
*/
ariaLabelledBy: {
type: String,
default: null
}
},
emits: [
/**
* Event fired to sync the open prop with the parent component
* @event update:open
*/
"update:open",
/**
* Event fired when the content is shown or hidden
*
* @event opened
* @type {Boolean}
*/
"opened"
],
data() {
return {
isOpen: true
};
},
computed: {
labelledBy() {
return this.ariaLabelledBy || !this.ariaLabel && getUniqueString("DtCollapsible__anchor");
}
},
watch: {
open: {
handler: function(open) {
if (open !== null) {
this.isOpen = open;
}
},
immediate: true
}
},
mounted() {
this.validateProperAnchor();
},
methods: {
onLeaveTransitionComplete() {
this.$emit("opened", false);
if (this.open !== null) {
this.$emit("update:open", false);
}
},
onEnterTransitionComplete() {
this.$emit("opened", true, this.$refs.content);
if (this.open !== null) {
this.$emit("update:open", true);
}
},
defaultToggleOpen() {
if (this.open === null) {
this.toggleOpen();
}
},
toggleOpen() {
this.isOpen = !this.isOpen;
},
validateProperAnchor() {
if (!this.anchorText && !this.$scopedSlots.anchor) {
console.error("anchor text and anchor slot content cannot both be falsy");
}
}
}
};
var _sfc_render = function render() {
var _vm = this, _c = _vm._self._c;
return _c(_vm.elementType, _vm._g({ ref: "collapsible", tag: "component" }, _vm.$listeners), [_c("div", { ref: "anchor", class: _vm.anchorClass, attrs: { "id": !_vm.ariaLabelledBy && _vm.labelledBy } }, [_vm._t("anchor", function() {
return [_c("dt-button", { style: {
"width": _vm.maxWidth
}, attrs: { "importance": "clear", "kind": "muted", "aria-controls": _vm.id, "aria-expanded": `${_vm.isOpen}` }, on: { "click": _vm.defaultToggleOpen } }, [_vm.isOpen ? _c("dt-icon-chevron-down", { staticClass: "d-collapsible__icon", attrs: { "size": "300" } }) : _c("dt-icon-chevron-right", { staticClass: "d-collapsible__icon", attrs: { "size": "300" } }), _c("span", { staticClass: "d-collapsible__anchor-text", attrs: { "title": _vm.anchorText } }, [_vm._v(" " + _vm._s(_vm.anchorText) + " ")])], 1)];
}, { "attrs": {
"aria-controls": _vm.id,
"aria-expanded": _vm.isOpen.toString(),
"role": "button"
} })], 2), _c("dt-collapsible-lazy-show", _vm._g({ ref: "contentWrapper", class: _vm.contentClass, style: {
"max-height": _vm.maxHeight,
"max-width": _vm.maxWidth
}, attrs: { "id": _vm.id, "aria-hidden": `${!_vm.isOpen}`, "aria-labelledby": _vm.labelledBy, "aria-label": _vm.ariaLabel, "show": _vm.isOpen, "element-type": _vm.contentElementType, "data-qa": "dt-collapsible--content", "tabindex": "-1", "appear": "" }, on: { "after-leave": _vm.onLeaveTransitionComplete, "after-enter": _vm.onEnterTransitionComplete } }, _vm.$listeners), [_vm._t("content")], 2)], 1);
};
var _sfc_staticRenderFns = [];
var __component__ = /* @__PURE__ */ normalizeComponent(
_sfc_main,
_sfc_render,
_sfc_staticRenderFns
);
const DtCollapsible = __component__.exports;
export {
DtCollapsible as default
};
//# sourceMappingURL=collapsible.vue.js.map