UNPKG

@dialpad/dialtone

Version:

Dialpad's Dialtone design system monorepo

259 lines (258 loc) 7.83 kB
import { getUniqueString, extractVueListeners, hasSlotContent } from "../../common/utils.js"; import DtCollapsibleLazyShow from "./collapsible_lazy_show.vue.js"; import { DtIconChevronDown, DtIconChevronRight } from "@dialpad/dialtone-icons/vue3"; import { resolveComponent, openBlock, createBlock, resolveDynamicComponent, mergeProps, toHandlers, withCtx, createElementVNode, normalizeClass, renderSlot, createVNode, normalizeStyle, toDisplayString } from "vue"; import _export_sfc from "../../_virtual/_plugin-vue_export-helper.js"; import DtButton from "../button/button.vue.js"; import DtLazyShow from "../lazy_show/lazy_show.vue.js"; const _sfc_main = { compatConfig: { MODE: 3 }, 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"); }, collapsibleListeners() { return extractVueListeners(this.$attrs); } }, watch: { open: { handler: function(open) { if (open !== null) { this.isOpen = open; } }, immediate: true } }, created() { 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 && !hasSlotContent(this.$slots.anchor)) { console.error("anchor text and anchor slot content cannot both be falsy"); } } } }; const _hoisted_1 = ["id"]; const _hoisted_2 = ["title"]; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { const _component_dt_icon_chevron_down = resolveComponent("dt-icon-chevron-down"); const _component_dt_icon_chevron_right = resolveComponent("dt-icon-chevron-right"); const _component_dt_button = resolveComponent("dt-button"); const _component_dt_collapsible_lazy_show = resolveComponent("dt-collapsible-lazy-show"); return openBlock(), createBlock(resolveDynamicComponent($props.elementType), mergeProps({ ref: "collapsible" }, toHandlers($options.collapsibleListeners)), { default: withCtx(() => [ createElementVNode("div", { id: !$props.ariaLabelledBy && $options.labelledBy, ref: "anchor", class: normalizeClass($props.anchorClass) }, [ renderSlot(_ctx.$slots, "anchor", { attrs: { "aria-controls": $props.id, "aria-expanded": $data.isOpen.toString(), "role": "button" } }, () => [ createVNode(_component_dt_button, { importance: "clear", kind: "muted", "aria-controls": $props.id, "aria-expanded": `${$data.isOpen}`, style: normalizeStyle({ "width": $props.maxWidth }), onClick: $options.defaultToggleOpen }, { default: withCtx(() => [ $data.isOpen ? (openBlock(), createBlock(_component_dt_icon_chevron_down, { key: 0, class: "d-collapsible__icon", size: "300" })) : (openBlock(), createBlock(_component_dt_icon_chevron_right, { key: 1, class: "d-collapsible__icon", size: "300" })), createElementVNode("span", { class: "d-collapsible__anchor-text", title: $props.anchorText }, toDisplayString($props.anchorText), 9, _hoisted_2) ]), _: 1 }, 8, ["aria-controls", "aria-expanded", "style", "onClick"]) ]) ], 10, _hoisted_1), createVNode(_component_dt_collapsible_lazy_show, mergeProps({ id: $props.id, ref: "contentWrapper", "aria-hidden": `${!$data.isOpen}`, "aria-labelledby": $options.labelledBy, "aria-label": $props.ariaLabel, show: $data.isOpen, "element-type": $props.contentElementType, class: $props.contentClass, style: { "max-height": $props.maxHeight, "max-width": $props.maxWidth }, "data-qa": "dt-collapsible--content", tabindex: "-1", appear: "" }, toHandlers($options.collapsibleListeners), { onAfterLeave: $options.onLeaveTransitionComplete, onAfterEnter: $options.onEnterTransitionComplete }), { default: withCtx(() => [ renderSlot(_ctx.$slots, "content") ]), _: 3 }, 16, ["id", "aria-hidden", "aria-labelledby", "aria-label", "show", "element-type", "class", "style", "onAfterLeave", "onAfterEnter"]) ]), _: 3 }, 16); } const DtCollapsible = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]); export { DtCollapsible as default }; //# sourceMappingURL=collapsible.vue.js.map