UNPKG

@dialpad/dialtone

Version:

Dialpad's Dialtone design system monorepo

196 lines (195 loc) 5.96 kB
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