@dialpad/dialtone
Version:
Dialpad's Dialtone design system monorepo
952 lines (951 loc) • 33.2 kB
JavaScript
import { POPOVER_ROLES, POPOVER_PADDING_CLASSES, POPOVER_CONTENT_WIDTHS, POPOVER_STICKY_VALUES, POPOVER_INITIAL_FOCUS_STRINGS, POPOVER_APPEND_TO_VALUES, POPOVER_HEADER_FOOTER_PADDING_CLASSES } from "./popover_constants.js";
import { getUniqueString, hasSlotContent, warnIfUnmounted, returnFirstEl, isOutOfViewPort, disableRootScrolling, enableRootScrolling } from "../../common/utils.js";
import Modal from "../../common/mixins/modal.js";
import { getPopperOptions, createTippyPopover } from "./tippy_utils.js";
import PopoverHeaderFooter from "./popover_header_footer.vue.js";
import SrOnlyCloseButtonMixin from "../../common/mixins/sr_only_close_button.js";
import SrOnlyCloseButton from "../../common/sr_only_close_button.vue.js";
import { resolveComponent, openBlock, createElementBlock, createBlock, Teleport, createElementVNode, withModifiers, createCommentVNode, resolveDynamicComponent, normalizeClass, withCtx, withKeys, renderSlot, createVNode, mergeProps, toHandlers } from "vue";
import _export_sfc from "../../_virtual/_plugin-vue_export-helper.js";
import DtLazyShow from "../lazy_show/lazy_show.vue.js";
const _sfc_main = {
compatConfig: { MODE: 3 },
name: "DtPopover",
/********************
* CHILD COMPONENTS *
********************/
components: {
SrOnlyCloseButton,
DtLazyShow,
PopoverHeaderFooter
},
mixins: [Modal, SrOnlyCloseButtonMixin],
props: {
/**
* Controls whether the popover is shown. Leaving this null will have the popover 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 v-model
* @values null, true, false
*/
open: {
type: Boolean,
default: null
},
/**
* Opens the popover on right click (context menu). If you set this value to `true`,
* the default trigger behavior will be disabled.
* @values true, false
*/
openOnContext: {
type: Boolean,
default: false
},
/**
* Element type (tag name) of the root element of the component.
*/
elementType: {
type: String,
default: "div"
},
/**
* Named transition when the content display is toggled.
* @see DtLazyShow
*/
transition: {
type: String,
default: "fade"
},
/**
* ARIA role for the content of the popover. Defaults to "dialog".
* <a class="d-link" href="https://www.w3.org/TR/wai-aria/#aria-haspopup" target="_blank">aria-haspopup</a>
*/
role: {
type: String,
default: "dialog",
validator: (role) => {
return POPOVER_ROLES.includes(role);
}
},
/**
* ID of the element that serves as the label for the popover content.
* Defaults to the "anchor" element; this exists to provide a different
* ID of the label element if, for example, the anchor slot contains
* other items that do not serve as a label. You should provide this
* or ariaLabel, but not both.
*/
ariaLabelledby: {
type: String,
default: null
},
/**
* Descriptive label for the popover content. You should provide this
* or ariaLabelledby, but not both.
*/
ariaLabel: {
type: String,
default: null
},
/**
* A set of props to be passed into the popover's header close button.
* Requires an 'ariaLabel' property, when the header popover is visible
*/
closeButtonProps: {
type: Object,
default: () => ({})
},
/**
* Padding size class for the popover content.
* @values none, small, medium, large
*/
padding: {
type: String,
default: "large",
validator: (padding) => {
return Object.keys(POPOVER_PADDING_CLASSES).some((item) => item === padding);
}
},
/**
* Additional class name for the content wrapper element.
*/
contentClass: {
type: [String, Array, Object],
default: ""
},
/**
* Width configuration for the popover content. When its value is 'anchor',
* the popover content will have the same width as the anchor.
* @values null, anchor
*/
contentWidth: {
type: String,
default: "",
validator: (contentWidth) => POPOVER_CONTENT_WIDTHS.includes(contentWidth)
},
/**
* Whether to apply transition on initial render in the content lazy show component.
*/
contentAppear: {
type: Boolean,
default: null
},
/**
* Tabindex value for the content. Passing null, no tabindex attribute will be set.
*/
contentTabindex: {
type: Number || null,
default: -1
},
/**
* External anchor id to use in those cases the anchor can't be provided via the slot.
* For instance, using the combobox's input as the anchor for the popover.
*/
externalAnchor: {
type: String,
default: ""
},
/**
* The id of the tooltip
*/
id: {
type: String,
default() {
return getUniqueString();
}
},
/**
* Displaces the content box from its anchor element
* by the specified number of pixels.
* <a
* class="d-link"
* href="https://atomiks.github.io/tippyjs/v6/all-props/#offset"
* target="_blank"
* >
* Tippy.js docs
* </a>
*/
offset: {
type: Array,
default: () => [0, 4]
},
/**
* Determines if the popover hides upon clicking the
* anchor or outside the content box.
* @values true, false
*/
hideOnClick: {
type: Boolean,
default: true
},
/**
* Determines modal state. If enabled popover has a modal overlay
* preventing interaction with elements below it, but it is invisible.
* @values true, false
*/
modal: {
type: Boolean,
default: true
},
/**
* If the popover does not fit in the direction described by "placement",
* it will attempt to change its direction to the "fallbackPlacements".
* <a
* class="d-link"
* href="https://popper.js.org/docs/v2/modifiers/flip/#fallbackplacements"
* target="_blank"
* >
* Popper.js docs
* </a>
* */
fallbackPlacements: {
type: Array,
default: () => {
return ["auto"];
}
},
/**
* The direction the popover displays relative to the anchor.
* <a
* class="d-link"
* href="https://atomiks.github.io/tippyjs/v6/all-props/#placement"
* target="_blank"
* >
* Tippy.js docs
* </a>
* @values top, top-start, top-end,
* right, right-start, right-end,
* left, left-start, left-end,
* bottom, bottom-start, bottom-end,
* auto, auto-start, auto-end
*/
placement: {
type: String,
default: "bottom-end"
},
/**
* If set to false the dialog will display over top of the anchor when there is insufficient space.
* If set to true it will never move from its position relative to the anchor and will clip instead.
* <a
* class="d-link"
* href="https://popper.js.org/docs/v2/modifiers/prevent-overflow/#tether"
* target="_blank"
* >
* Popper.js docs
* </a>
* @values true, false
*/
tether: {
type: Boolean,
default: true
},
/**
* If the popover sticks to the anchor. This is usually not needed, but can be needed
* if the reference element's position is animating, or to automatically update the popover
* position in those cases the DOM layout changes the reference element's position.
* `true` enables it, `reference` only checks the "reference" rect for changes and `popper` only
* checks the "popper" rect for changes.
* <a
* class="d-link"
* href="https://atomiks.github.io/tippyjs/v6/all-props/#sticky"
* target="_blank"
* >
* Tippy.js docs
* </a>
* @values true, false, reference, popper
*/
sticky: {
type: [Boolean, String],
default: false,
validator: (sticky) => {
return POPOVER_STICKY_VALUES.includes(sticky);
}
},
/**
* Determines maximum height for the popover before overflow.
* Possible units rem|px|em
*/
maxHeight: {
type: String,
default: ""
},
/**
* Determines maximum width for the popover before overflow.
* Possible units rem|px|%|em
*/
maxWidth: {
type: String,
default: ""
},
/**
* Determines visibility for close button
* @values true, false
*/
showCloseButton: {
type: Boolean,
default: false
},
/**
* Additional class name for the header content wrapper element.
*/
headerClass: {
type: [String, Array, Object],
default: ""
},
/**
* Additional class name for the footer content wrapper element.
*/
footerClass: {
type: [String, Array, Object],
default: ""
},
/**
* Additional class name for the dialog element.
*/
dialogClass: {
type: [String, Array, Object],
default: ""
},
/**
* The element that is focused when the popover is opened. This can be an
* HTMLElement within the popover, a string starting with '#' which will
* find the element by ID. 'first' which will automatically focus
* the first element, or 'dialog' which will focus the dialog window itself.
* If the dialog is modal this prop cannot be 'none'.
* @values none, dialog, first
*/
initialFocusElement: {
type: [String, HTMLElement],
default: "first",
validator: (initialFocusElement) => {
return POPOVER_INITIAL_FOCUS_STRINGS.includes(initialFocusElement) || initialFocusElement instanceof HTMLElement || initialFocusElement.startsWith("#");
}
},
/**
* If the popover should open pressing up or down arrow key on the anchor element.
* This can be set when not passing open prop.
* @values true, false
*/
openWithArrowKeys: {
type: Boolean,
default: false
},
/**
* Sets the element to which the popover is going to append to.
* 'body' will append to the nearest body (supports shadow DOM).
* 'root' will try append to the iFrame's parent body if it is contained in an iFrame
* and has permissions to access it, else, it'd default to 'parent'.
* @values 'body', 'parent', 'root', HTMLElement
*/
appendTo: {
type: [HTMLElement, String],
default: "body",
validator: (appendTo) => {
return POPOVER_APPEND_TO_VALUES.includes(appendTo) || appendTo instanceof HTMLElement;
}
}
},
emits: [
/**
* Native keydown event
*
* @event keydown
* @type {KeyboardEvent}
*/
"keydown",
/**
* Event fired to sync the open prop with the parent component
* @event update:open
*/
"update:open",
/**
* Emitted when popover is shown or hidden
*
* @event opened
* @type {Boolean | Array}
*/
"opened",
/**
* Emitted when the mouse enters the popover
*
* @event mouseenter-popover
*/
"mouseenter-popover",
/**
* Emitted when the mouse leaves the popover
*
* @event mouseleave-popover
*/
"mouseleave-popover",
/**
* Emitted when the mouse enters the popover anchor
*
* @event mouseenter-popover-anchor
*/
"mouseenter-popover-anchor",
/**
* Emitted when the mouse leaves the popover anchor
*
* @event mouseleave-popover-anchor
*/
"mouseleave-popover-anchor"
],
data() {
return {
POPOVER_PADDING_CLASSES,
POPOVER_HEADER_FOOTER_PADDING_CLASSES,
intersectionObserver: null,
isOutsideViewport: false,
isOpen: false,
toAppear: false,
anchorEl: null,
popoverContentEl: null,
hasSlotContent
};
},
computed: {
popoverListeners() {
return {
keydown: (event) => {
this.onKeydown(event);
},
"after-leave": (event) => {
this.onLeaveTransitionComplete();
},
"after-enter": (event) => {
this.onEnterTransitionComplete();
}
};
},
calculatedMaxHeight() {
if (this.isOutsideViewport && this.modal) {
return `calc(100vh - var(--dt-space-300))`;
}
return this.maxHeight;
},
labelledBy() {
return this.ariaLabelledby || !this.ariaLabel && getUniqueString("DtPopover__anchor");
}
},
watch: {
$props: {
immediate: true,
deep: true,
handler() {
this.validateProps();
}
},
modal(modal) {
var _a;
(_a = this.tip) == null ? void 0 : _a.setProps({
zIndex: modal ? 650 : this.calculateAnchorZindex()
});
},
offset(offset) {
var _a;
(_a = this.tip) == null ? void 0 : _a.setProps({
offset
});
},
sticky(sticky) {
var _a;
(_a = this.tip) == null ? void 0 : _a.setProps({
sticky
});
},
fallbackPlacements() {
var _a;
(_a = this.tip) == null ? void 0 : _a.setProps({
popperOptions: this.popperOptions()
});
},
tether() {
var _a;
(_a = this.tip) == null ? void 0 : _a.setProps({
popperOptions: this.popperOptions()
});
},
placement(placement) {
var _a;
(_a = this.tip) == null ? void 0 : _a.setProps({
placement
});
},
open: {
handler: function(open) {
if (open !== null) {
this.isOpen = open;
}
if (open === true) {
this.toAppear = true;
}
},
immediate: true
},
contentAppear: {
handler: function(contentAppear) {
if (contentAppear !== null) {
this.toAppear = contentAppear;
}
}
},
isOpen(isOpen, isPrev) {
if (isOpen) {
this.initTippyInstance();
this.tip.show();
} else if (!isOpen && isPrev !== isOpen) {
this.removeEventListeners();
this.tip.hide();
}
}
},
mounted() {
var _a;
warnIfUnmounted(returnFirstEl(this.$el), this.$options.name);
const externalAnchorEl = this.externalAnchor ? this.$refs.anchor.getRootNode().querySelector(`#${this.externalAnchor}`) : null;
this.anchorEl = externalAnchorEl ?? this.$refs.anchor.children[0];
this.popoverContentEl = returnFirstEl((_a = this.$refs.content) == null ? void 0 : _a.$el);
if (this.isOpen) {
this.initTippyInstance();
this.tip.show();
}
this.intersectionObserver = new IntersectionObserver(this.hasIntersectedViewport);
this.intersectionObserver.observe(this.popoverContentEl);
},
beforeUnmount() {
var _a, _b;
(_a = this.tip) == null ? void 0 : _a.destroy();
(_b = this.intersectionObserver) == null ? void 0 : _b.disconnect();
this.removeReferences();
this.removeEventListeners();
},
/******************
* METHODS *
******************/
methods: {
hasIntersectedViewport(entries) {
var _a;
const dialog = (_a = entries == null ? void 0 : entries[0]) == null ? void 0 : _a.target;
if (!dialog) return;
const isOut = isOutOfViewPort(dialog);
this.isOutsideViewport = isOut.bottom || isOut.top;
},
popperOptions() {
return getPopperOptions({
fallbackPlacements: this.fallbackPlacements,
tether: this.tether,
hasHideModifierEnabled: true
});
},
validateProps() {
if (this.modal && this.initialFocusElement === "none") {
console.error('If the popover is modal you must set the initialFocusElement prop. Possible values: "dialog", "first", HTMLElement');
}
},
calculateAnchorZindex() {
var _a;
if (returnFirstEl(this.$el).getRootNode().querySelector('.d-modal[aria-hidden="false"], .d-modal--transparent[aria-hidden="false"]') || // Special case because we don't have any dialtone drawer component yet. Render at 650 when
// anchor of popover is within a drawer.
((_a = this.anchorEl) == null ? void 0 : _a.closest(".d-zi-drawer"))) {
return 650;
} else {
return 300;
}
},
defaultToggleOpen(e) {
var _a, _b, _c;
if (this.openOnContext) {
return;
}
if (this.open === null || this.open === void 0) {
if (!((_a = this.anchorEl) == null ? void 0 : _a.contains(e.target)) && !((_b = this.anchorEl) == null ? void 0 : _b.isEqualNode(e.target)) || ((_c = this.anchorEl) == null ? void 0 : _c.disabled)) {
return;
}
this.toggleOpen();
}
},
async onContext(event) {
if (!this.openOnContext) {
return;
}
event.preventDefault();
this.isOpen = true;
await this.$nextTick();
this.tip.setProps({
placement: "right-start",
getReferenceClientRect: () => ({
width: 0,
height: 0,
top: event.clientY,
bottom: event.clientY,
left: event.clientX,
right: event.clientX
})
});
},
toggleOpen() {
this.isOpen = !this.isOpen;
},
onArrowKeyPress(e) {
var _a;
if (this.open !== null) {
return;
}
if (this.openWithArrowKeys && ((_a = this.anchorEl) == null ? void 0 : _a.contains(e.target))) {
if (!this.isOpen) {
this.isOpen = true;
}
}
this.$emit("keydown", e);
},
addEventListeners() {
window.addEventListener("dt-popover-close", this.closePopover);
if (this.contentWidth === "anchor") {
window.addEventListener("resize", this.onResize);
}
},
removeEventListeners() {
window.removeEventListener("dt-popover-close", this.closePopover);
if (this.contentWidth === "anchor") {
window.removeEventListener("resize", this.onResize);
}
},
closePopover() {
this.isOpen = false;
},
/*
* Prevents scrolling outside of the currently opened modal popover by:
* - when anchor is not within another popover: setting the body to overflow: hidden
* - when anchor is within another popover: set the popover dialog container to it's non-modal z-index
* since it is no longer the active modal. This puts it underneath the overlay and prevents scrolling.
**/
preventScrolling() {
var _a, _b;
if (this.modal) {
const element = (_a = this.anchorEl) == null ? void 0 : _a.closest("body, .tippy-box");
if (!element) return;
if (((_b = element.tagName) == null ? void 0 : _b.toLowerCase()) === "body") {
disableRootScrolling(this.anchorEl.getRootNode().host);
this.tip.setProps({ offset: this.offset });
} else {
element.classList.add("d-zi-popover");
}
}
},
/*
* Resets the prevent scrolling properties set in preventScrolling() back to normal.
**/
enableScrolling() {
var _a, _b;
const element = (_a = this.anchorEl) == null ? void 0 : _a.closest("body, .tippy-box");
if (!element) return;
if (((_b = element.tagName) == null ? void 0 : _b.toLowerCase()) === "body") {
enableRootScrolling(this.anchorEl.getRootNode().host);
this.tip.setProps({ offset: this.offset });
} else {
element.classList.remove("d-zi-popover");
}
},
removeReferences() {
this.anchorEl = null;
this.popoverContentEl = null;
this.tip = null;
},
async onShow() {
if (this.contentWidth === "anchor") {
await this.setPopoverContentAnchorWidth();
}
if (this.contentWidth === null) {
this.popoverContentEl.style.width = "auto";
}
this.addEventListeners();
},
async onLeaveTransitionComplete() {
var _a;
if (this.modal) {
await this.focusFirstElement(this.$refs.anchor);
await this.$nextTick();
this.enableScrolling();
}
(_a = this.tip) == null ? void 0 : _a.unmount();
this.$emit("opened", false);
if (this.open !== null) {
this.$emit("update:open", false);
}
},
async onEnterTransitionComplete() {
this.focusInitialElement();
await this.$nextTick();
this.preventScrolling();
this.$emit("opened", true, this.$refs.popover__content);
if (this.open !== null) {
this.$emit("update:open", true);
}
},
focusInitialElement() {
var _a, _b;
if (this.initialFocusElement === "dialog") {
(_b = returnFirstEl((_a = this.$refs.content) == null ? void 0 : _a.$el)) == null ? void 0 : _b.focus();
}
if (this.initialFocusElement.startsWith("#")) {
this.focusInitialElementById();
}
if (this.initialFocusElement === "first") {
this.focusFirstElementIfNeeded(this.$refs.popover__content);
}
if (this.initialFocusElement instanceof HTMLElement) {
this.initialFocusElement.focus();
}
},
focusInitialElementById() {
var _a, _b, _c;
const result = (_b = returnFirstEl((_a = this.$refs.content) == null ? void 0 : _a.$el)) == null ? void 0 : _b.querySelector(this.initialFocusElement);
if (result) {
result.focus();
} else {
console.warn('Could not find the element specified in dt-popover prop "initialFocusElement". Defaulting to focusing the dialog.');
}
result ? result.focus() : returnFirstEl((_c = this.$refs.content) == null ? void 0 : _c.$el).focus();
},
onResize() {
this.closePopover();
},
onClickOutside() {
var _a;
if (!this.hideOnClick) return;
const innerModals = (_a = this.popoverContentEl) == null ? void 0 : _a.querySelector(".d-popover__anchor--opened");
if (!innerModals) {
this.closePopover();
}
},
onKeydown(e) {
if (e.key === "Tab") {
if (this.modal) {
this.focusTrappedTabPress(e, this.popoverContentEl);
}
}
if (e.key === "Escape") {
this.closePopover();
}
this.$emit("keydown", e);
},
async setPopoverContentAnchorWidth() {
var _a;
await this.$nextTick();
this.popoverContentEl.style.width = `${(_a = this.anchorEl) == null ? void 0 : _a.clientWidth}px`;
},
focusFirstElementIfNeeded(domEl) {
var _a, _b;
const focusableElements = this._getFocusableElements(domEl, true);
if (focusableElements.length !== 0) {
this.focusFirstElement(domEl);
} else if (this.showCloseButton) {
(_a = this.$refs.popover__header) == null ? void 0 : _a.focusCloseButton();
} else {
returnFirstEl((_b = this.$refs.content) == null ? void 0 : _b.$el).focus();
}
},
/**
* Return's the anchor ClientRect object relative to the window.
* Refer to: https://atomiks.github.io/tippyjs/v6/all-props/#getreferenceclientrect for more information
* @param error
*/
getReferenceClientRect(error) {
var _a, _b;
const anchorReferenceRect = (_a = this.anchorEl) == null ? void 0 : _a.getBoundingClientRect();
if (this.appendTo !== "root" || error) return anchorReferenceRect;
const anchorOwnerDocument = (_b = this.anchorEl) == null ? void 0 : _b.ownerDocument;
const anchorParentWindow = (anchorOwnerDocument == null ? void 0 : anchorOwnerDocument.defaultView) || (anchorOwnerDocument == null ? void 0 : anchorOwnerDocument.parentWindow);
const anchorIframe = anchorParentWindow == null ? void 0 : anchorParentWindow.frameElement;
if (!anchorIframe) return anchorReferenceRect;
const iframeReferenceRect = anchorIframe.getBoundingClientRect();
return {
width: anchorReferenceRect == null ? void 0 : anchorReferenceRect.width,
height: anchorReferenceRect == null ? void 0 : anchorReferenceRect.height,
top: (iframeReferenceRect == null ? void 0 : iframeReferenceRect.top) + (anchorReferenceRect == null ? void 0 : anchorReferenceRect.top),
left: (iframeReferenceRect == null ? void 0 : iframeReferenceRect.left) + (anchorReferenceRect == null ? void 0 : anchorReferenceRect.left),
right: (iframeReferenceRect == null ? void 0 : iframeReferenceRect.right) + (anchorReferenceRect == null ? void 0 : anchorReferenceRect.right),
bottom: (iframeReferenceRect == null ? void 0 : iframeReferenceRect.bottom) + (anchorReferenceRect == null ? void 0 : anchorReferenceRect.bottom)
};
},
initTippyInstance() {
var _a, _b;
let internalAppendTo = null;
let iFrameError = false;
switch (this.appendTo) {
case "body":
internalAppendTo = (_b = (_a = this.anchorEl) == null ? void 0 : _a.getRootNode()) == null ? void 0 : _b.querySelector("body");
break;
case "root":
try {
internalAppendTo = window.parent.document.body;
} catch (err) {
console.error("Could not attach the popover to iframe parent window: ", err);
internalAppendTo = "parent";
iFrameError = true;
}
break;
default:
internalAppendTo = this.appendTo;
break;
}
this.tip = createTippyPopover(this.anchorEl, {
popperOptions: this.popperOptions(),
contentElement: this.popoverContentEl,
placement: this.placement,
offset: this.offset,
sticky: this.sticky,
appendTo: internalAppendTo,
interactive: true,
trigger: "manual",
getReferenceClientRect: () => this.getReferenceClientRect(iFrameError),
// We have to manage hideOnClick functionality manually to handle
// popover within popover situations.
hideOnClick: false,
zIndex: this.modal ? 650 : this.calculateAnchorZindex(),
onClickOutside: this.onClickOutside,
onShow: this.onShow
});
},
onMouseEnter() {
this.$emit("mouseenter-popover");
},
onMouseLeave() {
this.$emit("mouseleave-popover");
},
onMouseEnterAnchor() {
this.$emit("mouseenter-popover-anchor");
},
onMouseLeaveAnchor() {
this.$emit("mouseleave-popover-anchor");
}
}
};
const _hoisted_1 = ["aria-hidden"];
const _hoisted_2 = ["id", "data-qa", "tabindex"];
const _hoisted_3 = ["data-qa"];
function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) {
const _component_popover_header_footer = resolveComponent("popover-header-footer");
const _component_sr_only_close_button = resolveComponent("sr-only-close-button");
const _component_dt_lazy_show = resolveComponent("dt-lazy-show");
return openBlock(), createElementBlock("div", null, [
$props.modal && $data.isOpen ? (openBlock(), createBlock(Teleport, {
key: 0,
to: "body"
}, [
createElementVNode("div", {
class: "d-modal--transparent",
"aria-hidden": $props.modal && $data.isOpen ? "false" : "true",
onClick: _cache[0] || (_cache[0] = withModifiers(() => {
}, ["prevent", "stop"]))
}, null, 8, _hoisted_1)
])) : createCommentVNode("", true),
(openBlock(), createBlock(resolveDynamicComponent($props.elementType), {
ref: "popover",
class: normalizeClass(["d-popover", { "d-popover__anchor--opened": $data.isOpen }]),
"data-qa": "dt-popover-container"
}, {
default: withCtx(() => [
createElementVNode("div", {
id: !$props.ariaLabelledby && $options.labelledBy,
ref: "anchor",
"data-qa": _ctx.$attrs["data-qa"] ? `${_ctx.$attrs["data-qa"]}-anchor` : "dt-popover-anchor",
tabindex: $props.openOnContext ? 0 : void 0,
onClickCapture: _cache[1] || (_cache[1] = (...args) => $options.defaultToggleOpen && $options.defaultToggleOpen(...args)),
onContextmenu: _cache[2] || (_cache[2] = (...args) => $options.onContext && $options.onContext(...args)),
onKeydown: [
_cache[3] || (_cache[3] = withKeys(withModifiers((...args) => $options.onArrowKeyPress && $options.onArrowKeyPress(...args), ["prevent"]), ["up"])),
_cache[4] || (_cache[4] = withKeys(withModifiers((...args) => $options.onArrowKeyPress && $options.onArrowKeyPress(...args), ["prevent"]), ["down"])),
_cache[6] || (_cache[6] = withKeys(($event) => _ctx.$emit("keydown", $event), ["enter"])),
_cache[7] || (_cache[7] = withKeys(($event) => _ctx.$emit("keydown", $event), ["space"]))
],
onKeydownCapture: _cache[5] || (_cache[5] = withKeys((...args) => $options.closePopover && $options.closePopover(...args), ["escape"])),
onMouseenter: _cache[8] || (_cache[8] = (...args) => $options.onMouseEnter && $options.onMouseEnter(...args)),
onMouseleave: _cache[9] || (_cache[9] = (...args) => $options.onMouseLeave && $options.onMouseLeave(...args))
}, [
renderSlot(_ctx.$slots, "anchor", {
attrs: {
"aria-expanded": $data.isOpen.toString(),
"aria-controls": $props.id,
"aria-haspopup": $props.role
}
})
], 40, _hoisted_2),
createVNode(_component_dt_lazy_show, mergeProps({
id: $props.id,
ref: "content",
role: $props.role,
"data-qa": _ctx.$attrs["data-qa"] ? `${_ctx.$attrs["data-qa"]}__dialog` : "dt-popover",
"aria-hidden": `${!$data.isOpen}`,
"aria-labelledby": $options.labelledBy,
"aria-label": $props.ariaLabel,
"aria-modal": `${!$props.modal}`,
transition: $props.transition,
show: $data.isOpen,
appear: $data.toAppear,
class: ["d-popover__dialog", { "d-popover__dialog--modal": $props.modal }, $props.dialogClass],
style: {
"max-height": $options.calculatedMaxHeight,
"max-width": $props.maxWidth
},
css: _ctx.$attrs.css,
tabindex: $props.contentTabindex
}, toHandlers($options.popoverListeners), {
onMouseenter: $options.onMouseEnterAnchor,
onMouseleave: $options.onMouseLeaveAnchor
}), {
default: withCtx(() => [
$data.hasSlotContent(_ctx.$slots.headerContent) || $props.showCloseButton ? (openBlock(), createBlock(_component_popover_header_footer, {
key: 0,
ref: "popover__header",
class: normalizeClass($data.POPOVER_HEADER_FOOTER_PADDING_CLASSES[$props.padding]),
"content-class": $props.headerClass,
type: "header",
"show-close-button": $props.showCloseButton,
"close-button-props": $props.closeButtonProps,
onClose: $options.closePopover
}, {
content: withCtx(() => [
renderSlot(_ctx.$slots, "headerContent", { close: $options.closePopover })
]),
_: 3
}, 8, ["class", "content-class", "show-close-button", "close-button-props", "onClose"])) : createCommentVNode("", true),
createElementVNode("div", {
ref: "popover__content",
"data-qa": _ctx.$attrs["data-qa"] ? `${_ctx.$attrs["data-qa"]}-content` : "dt-popover-content",
class: normalizeClass([
"d-popover__content",
$data.POPOVER_PADDING_CLASSES[$props.padding],
$props.contentClass
])
}, [
renderSlot(_ctx.$slots, "content", { close: $options.closePopover })
], 10, _hoisted_3),
$data.hasSlotContent(_ctx.$slots.footerContent) ? (openBlock(), createBlock(_component_popover_header_footer, {
key: 1,
ref: "popover__footer",
type: "footer",
class: normalizeClass($data.POPOVER_HEADER_FOOTER_PADDING_CLASSES[$props.padding]),
"content-class": $props.footerClass
}, {
content: withCtx(() => [
renderSlot(_ctx.$slots, "footerContent", { close: $options.closePopover })
]),
_: 3
}, 8, ["class", "content-class"])) : createCommentVNode("", true),
_ctx.showVisuallyHiddenClose ? (openBlock(), createBlock(_component_sr_only_close_button, {
key: 2,
"visually-hidden-close-label": _ctx.visuallyHiddenCloseLabel,
onClose: $options.closePopover
}, null, 8, ["visually-hidden-close-label", "onClose"])) : createCommentVNode("", true)
]),
_: 3
}, 16, ["id", "role", "data-qa", "aria-hidden", "aria-labelledby", "aria-label", "aria-modal", "transition", "show", "appear", "class", "style", "css", "tabindex", "onMouseenter", "onMouseleave"])
]),
_: 3
}, 8, ["class"]))
]);
}
const DtPopover = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]);
export {
DtPopover as default
};
//# sourceMappingURL=popover.vue.js.map