@dialpad/dialtone
Version:
Dialpad's Dialtone design system monorepo
192 lines (191 loc) • 5.84 kB
JavaScript
import Modal from "../../common/mixins/modal.js";
import { EVENT_KEYNAMES } from "../../common/constants.js";
import { DtIconClose } from "@dialpad/dialtone-icons/vue2";
import { Portal } from "@linusborg/vue-simple-portal";
import normalizeComponent from "../../_virtual/_plugin-vue2_normalizer.js";
import DtButton from "../button/button.vue.js";
const _sfc_main = {
name: "DtImageViewer",
components: {
Portal,
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 {
...this.$listeners,
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;
(_a = this.$refs.closeImage) == null ? void 0 : _a.$el.focus();
},
trapFocus(e) {
if (this.isOpen) {
this.focusTrappedTabPress(e);
}
}
}
};
var _sfc_render = function render() {
var _vm = this, _c = _vm._self._c;
return _c("div", [_c("dt-button", { staticClass: "d-image-viewer__preview-button", attrs: { "data-qa": "dt-image-viewer-preview", "aria-label": _vm.ariaLabel, "importance": "clear" }, on: { "click": _vm.openModal } }, [_c("img", { class: _vm.imageButtonClass, attrs: { "src": _vm.imageSrc, "alt": _vm.imageAlt } })]), _vm.isOpen ? _c("portal", { attrs: { "selector": _vm.appendTo } }, [_c("div", _vm._g({ staticClass: "d-modal", attrs: { "aria-hidden": !_vm.isOpen ? "true" : "false", "data-qa": "dt-modal" }, on: { "mouseover": function($event) {
_vm.showCloseButton = true;
}, "mouseleave": function($event) {
_vm.showCloseButton = false;
}, "focusin": function($event) {
_vm.showCloseButton = true;
}, "focusout": function($event) {
_vm.showCloseButton = false;
} } }, _vm.modalListeners), [_c("div", { staticClass: "d-image-viewer__full", attrs: { "data-qa": "dt-image-viewer-full", "role": "dialog", "aria-modal": "true" } }, [_c("img", { staticClass: "d-image-viewer__full__image", attrs: { "src": _vm.imageSrc, "alt": _vm.imageAlt } })]), _c("transition", { attrs: { "name": "fade" } }, [_vm.showCloseButton ? _c("dt-button", { ref: "closeImage", staticClass: "d-modal__close", attrs: { "data-qa": "dt-image-viewer-close-btn", "circle": "", "size": "lg", "importance": "clear", "kind": "inverted", "aria-label": _vm.closeAriaLabel }, on: { "click": _vm.close }, scopedSlots: _vm._u([{ key: "icon", fn: function() {
return [_c("dt-icon-close", { staticClass: "d-image-viewer__close-button", attrs: { "size": "400" } })];
}, proxy: true }], null, false, 3317018023) }) : _vm._e()], 1)], 1)]) : _vm._e()], 1);
};
var _sfc_staticRenderFns = [];
var __component__ = /* @__PURE__ */ normalizeComponent(
_sfc_main,
_sfc_render,
_sfc_staticRenderFns
);
const DtImageViewer = __component__.exports;
export {
DtImageViewer as default
};
//# sourceMappingURL=image_viewer.vue.js.map