@dialpad/dialtone
Version:
Dialpad's Dialtone design system monorepo
251 lines (250 loc) • 7.39 kB
JavaScript
;
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
const modal = require("../../common/mixins/modal.cjs");
const common_utils = require("../../common/utils.cjs");
const common_constants = require("../../common/constants.cjs");
const vue3 = require("@dialpad/dialtone-icons/vue3");
const vue = require("vue");
const _pluginVue_exportHelper = require("../../_virtual/_plugin-vue_export-helper.cjs");
const button = require("../button/button.vue.cjs");
const _sfc_main = {
compatConfig: { MODE: 3 },
name: "DtImageViewer",
components: {
DtButton: button.default,
DtIconClose: vue3.DtIconClose
},
mixins: [modal.default],
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 common_constants.EVENT_KEYNAMES.esc:
case common_constants.EVENT_KEYNAMES.escape:
this.close();
break;
case common_constants.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 = common_utils.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 = vue.resolveComponent("dt-button");
const _component_dt_icon_close = vue.resolveComponent("dt-icon-close");
return vue.openBlock(), vue.createElementBlock("div", null, [
vue.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: vue.withCtx(() => [
vue.createElementVNode("img", {
class: vue.normalizeClass($props.imageButtonClass),
src: $props.imageSrc,
alt: $props.imageAlt
}, null, 10, _hoisted_1)
]),
_: 1
}, 8, ["aria-label", "onClick"]),
$data.isOpen ? (vue.openBlock(), vue.createBlock(vue.Teleport, {
key: 0,
to: $props.appendTo
}, [
vue.createElementVNode("div", vue.mergeProps({
"aria-hidden": !$data.isOpen ? "true" : "false",
class: "d-modal",
"data-qa": "dt-modal"
}, vue.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)
}), [
vue.createElementVNode("div", _hoisted_3, [
vue.createElementVNode("img", {
class: "d-image-viewer__full__image",
src: $props.imageSrc,
alt: $props.imageAlt
}, null, 8, _hoisted_4)
]),
vue.createVNode(vue.Transition, { name: "fade" }, {
default: vue.withCtx(() => [
$data.showCloseButton ? (vue.openBlock(), vue.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: vue.withCtx(() => [
vue.createVNode(_component_dt_icon_close, {
class: "d-image-viewer__close-button",
size: "400"
})
]),
_: 1
}, 8, ["aria-label", "onClick"])) : vue.createCommentVNode("", true)
]),
_: 1
})
], 16, _hoisted_2)
], 8, ["to"])) : vue.createCommentVNode("", true)
]);
}
const DtImageViewer = /* @__PURE__ */ _pluginVue_exportHelper.default(_sfc_main, [["render", _sfc_render]]);
exports.default = DtImageViewer;
//# sourceMappingURL=image_viewer.vue.cjs.map