UNPKG

@dialpad/dialtone

Version:

Dialpad's Dialtone design system monorepo

251 lines (250 loc) 7.2 kB
import Modal from "../../common/mixins/modal.js"; import { returnFirstEl } from "../../common/utils.js"; import { EVENT_KEYNAMES } from "../../common/constants.js"; import { DtIconClose } from "@dialpad/dialtone-icons/vue3"; import { resolveComponent, openBlock, createElementBlock, createVNode, withCtx, createElementVNode, normalizeClass, createBlock, Teleport, mergeProps, toHandlers, Transition, createCommentVNode } from "vue"; import _export_sfc from "../../_virtual/_plugin-vue_export-helper.js"; import DtButton from "../button/button.vue.js"; const _sfc_main = { compatConfig: { MODE: 3 }, name: "DtImageViewer", components: { DtButton, DtIconClose }, mixins: [Modal], props: { /** * By default the portal appends to the body of the root parent. We can modify * this behaviour by passing an appendTo prop that points to an id or an html tag from the root of the parent. * The appendTo prop expects a CSS selector string or an actual DOM node. * type: string | HTMLElement, default: 'body' */ appendTo: { type: String, default: "body" }, /** * Controls whether the image modal is shown. Leaving this null will have the image modal * 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 }, /** * URL of the image to be shown */ imageSrc: { type: String, required: true }, /** * Alt text of image */ imageAlt: { type: String, required: true }, /** * Image Class */ imageButtonClass: { type: String, required: false, default: "" }, /** * Aria label */ ariaLabel: { type: String, required: true }, /** * Aria label for close button */ closeAriaLabel: { type: String, required: true } }, emits: [ /** * Emitted when popover is shown or hidden * * @event opened * @type {Boolean} */ "opened", /** * Event fired to sync the open prop with the parent component * @event update:open */ "update:open" ], data() { return { showCloseButton: true, isOpen: false }; }, computed: { modalListeners() { return { click: (event) => { event.target === event.currentTarget && this.close(); }, keydown: (event) => { switch (event.code) { case EVENT_KEYNAMES.esc: case EVENT_KEYNAMES.escape: this.close(); break; case EVENT_KEYNAMES.tab: this.trapFocus(event); break; } } }; } }, watch: { isOpen: { immediate: true, handler(isShowing) { var _a; if (isShowing) { this.previousActiveElement = document.activeElement; } else { (_a = this.previousActiveElement) == null ? void 0 : _a.focus(); this.previousActiveElement = null; } } }, open: { handler: function(open) { if (open !== null) { this.isOpen = open; } }, immediate: true } }, methods: { openModal() { if (this.open !== null) { return; } this.isOpen = true; this.showCloseButton = true; this.$emit("opened", true); setTimeout(() => { this.focusAfterOpen(); }); }, close() { this.isOpen = false; this.$emit("opened", false); if (this.open !== null) { this.$emit("update:open", false); } }, focusAfterOpen() { var _a, _b; (_b = returnFirstEl((_a = this.$refs.closeImage) == null ? void 0 : _a.$el)) == null ? void 0 : _b.focus(); }, trapFocus(e) { if (this.isOpen) { this.focusTrappedTabPress(e); } } } }; const _hoisted_1 = ["src", "alt"]; const _hoisted_2 = ["aria-hidden"]; const _hoisted_3 = { "data-qa": "dt-image-viewer-full", class: "d-image-viewer__full", role: "dialog", "aria-modal": "true" }; const _hoisted_4 = ["src", "alt"]; function _sfc_render(_ctx, _cache, $props, $setup, $data, $options) { const _component_dt_button = resolveComponent("dt-button"); const _component_dt_icon_close = resolveComponent("dt-icon-close"); return openBlock(), createElementBlock("div", null, [ createVNode(_component_dt_button, { "data-qa": "dt-image-viewer-preview", class: "d-image-viewer__preview-button", "aria-label": $props.ariaLabel, importance: "clear", onClick: $options.openModal }, { default: withCtx(() => [ createElementVNode("img", { class: normalizeClass($props.imageButtonClass), src: $props.imageSrc, alt: $props.imageAlt }, null, 10, _hoisted_1) ]), _: 1 }, 8, ["aria-label", "onClick"]), $data.isOpen ? (openBlock(), createBlock(Teleport, { key: 0, to: $props.appendTo }, [ createElementVNode("div", mergeProps({ "aria-hidden": !$data.isOpen ? "true" : "false", class: "d-modal", "data-qa": "dt-modal" }, toHandlers($options.modalListeners, true), { onMouseover: _cache[0] || (_cache[0] = ($event) => $data.showCloseButton = true), onMouseleave: _cache[1] || (_cache[1] = ($event) => $data.showCloseButton = false), onFocusin: _cache[2] || (_cache[2] = ($event) => $data.showCloseButton = true), onFocusout: _cache[3] || (_cache[3] = ($event) => $data.showCloseButton = false) }), [ createElementVNode("div", _hoisted_3, [ createElementVNode("img", { class: "d-image-viewer__full__image", src: $props.imageSrc, alt: $props.imageAlt }, null, 8, _hoisted_4) ]), createVNode(Transition, { name: "fade" }, { default: withCtx(() => [ $data.showCloseButton ? (openBlock(), createBlock(_component_dt_button, { key: 0, ref: "closeImage", "data-qa": "dt-image-viewer-close-btn", class: "d-modal__close", circle: "", size: "lg", importance: "clear", kind: "inverted", "aria-label": $props.closeAriaLabel, onClick: $options.close }, { icon: withCtx(() => [ createVNode(_component_dt_icon_close, { class: "d-image-viewer__close-button", size: "400" }) ]), _: 1 }, 8, ["aria-label", "onClick"])) : createCommentVNode("", true) ]), _: 1 }) ], 16, _hoisted_2) ], 8, ["to"])) : createCommentVNode("", true) ]); } const DtImageViewer = /* @__PURE__ */ _export_sfc(_sfc_main, [["render", _sfc_render]]); export { DtImageViewer as default }; //# sourceMappingURL=image_viewer.vue.js.map