Skip to content

Commit

Permalink
Merge branch 'feature/migrate-base-events-modal-component-to-composit…
Browse files Browse the repository at this point in the history
…ion-api' of https://github.com/empathyco/x into feature/migrate-base-events-modal-component-to-composition-api
  • Loading branch information
lauramargar committed Jun 4, 2024
2 parents ddb0175 + d77af6f commit 870a02d
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 65 deletions.
1 change: 1 addition & 0 deletions packages/_vue3-migration-test/src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ export { default as TestBaseResultImages } from './result/test-base-result-image
export { default as TestBasePanel } from './panels/test-base-panel.vue';
export { default as TestBaseKeyboardNavigation } from './test-base-keyboard-navigation.vue';
export { default as TestBaseEventsModal } from './modals/test-base-events-modal.vue';
export { default as TestBaseIdModal } from './modals/test-base-id-modal.vue';
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<template>
<div class="base-id-modal">
<BaseIdModalOpen modalId="myModal">Open</BaseIdModalOpen>
<BaseIdModal :animation="Fade" modalId="myModal" contentClass="content" overlayClass="overlay">
<h1>Hello</h1>
<p>The base id modal is working</p>
<BaseIdModalClose modalId="myModal">Close</BaseIdModalClose>
</BaseIdModal>
</div>
</template>

<script setup lang="ts">
import BaseIdModal from '../../../../x-components/src/components/modals/base-id-modal.vue';
import BaseIdModalOpen from '../../../../x-components/src/components/modals/base-id-modal-open.vue';
import BaseIdModalClose from '../../../../x-components/src/components/modals/base-id-modal-close.vue';
import Fade from '../../../../x-components/src/components/animations/fade.vue';
</script>

<style>
.base-id-modal {
.content {
background: white;
margin: auto;
width: 50%;
border: 3px solid green;
padding: 10px;
}
.overlay {
background-color: red;
}
}
</style>
8 changes: 7 additions & 1 deletion packages/_vue3-migration-test/src/router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ import {
TestBaseResultImages,
TestBasePanel,
TestBaseKeyboardNavigation,
TestBaseEventsModal
TestBaseEventsModal,
TestBaseIdModal
} from './';

const routes = [
Expand Down Expand Up @@ -170,6 +171,11 @@ const routes = [
path: '/base-events-modal',
name: 'BaseEventsModal',
component: TestBaseEventsModal
},
{
path: '/test-base-id-modal',
name: 'TestBaseIdModal',
component: TestBaseIdModal
}
];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,8 @@
<script lang="ts">
import { computed, defineComponent, ref } from 'vue';
import { animateTranslate } from '../animations/animate-translate/animate-translate.factory';
import BaseIdModal from '../modals/base-id-modal.vue';
import Scroll from '../../x-modules/scroll/components/scroll.vue';
import BaseIdModal from '../modals/base-id-modal.vue';
import MainScroll from '../../x-modules/scroll/components/main-scroll.vue';
import { useLayouts } from './use-layouts';
Expand Down
151 changes: 88 additions & 63 deletions packages/x-components/src/components/modals/base-id-modal.vue
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
<template>
<BaseModal
v-bind="$attrs"
:ref="el"
@click:overlay="emitClickOutOfModal"
@focusin:body="emitClickOutOfModal"
:animation="animation"
:open="isOpen"
v-bind="$attrs"
>
<slot />
</BaseModal>
</template>

<script lang="ts">
import Vue from 'vue';
import { Component, Prop } from 'vue-property-decorator';
import { XOn } from '../decorators/bus.decorators';
import { defineComponent, ref } from 'vue';
import { WireMetadata } from '../../wiring/wiring.types';
import { getTargetElement, isElementEqualOrContained } from '../../utils/html';
import { useXBus } from '../../composables';
import { AnimationProp } from '../../types/animation-prop';
import { XEvent } from '../../wiring/events.types';
import BaseModal from './base-modal.vue';
/**
Expand All @@ -26,71 +28,94 @@
*
* @public
*/
@Component({
components: { BaseModal }
})
export default class BaseIdModal extends Vue {
/** Animation to use for opening/closing the modal. */
@Prop()
public animation?: Vue | string;
/** The modalId to use for the open and close event listeners. */
@Prop({ required: true })
public modalId!: string;
/** Whether the modal is open or not. */
protected isOpen = false;
/** The element that opened the modal. */
protected openerElement?: HTMLElement;
/**
* Opens the modal.
*
* @param modalId - The payload of the {@link XEventsTypes.UserClickedOpenModal} event.
* @param metadata - The metadata of the emitted event.
* @public
*/
@XOn('UserClickedOpenModal')
openModal(modalId: string, metadata: WireMetadata): void {
if (!this.isOpen && this.modalId === modalId) {
this.openerElement = metadata.target;
this.isOpen = true;
export default defineComponent({
name: 'BaseIdModal',
components: { BaseModal },
props: {
/**
* Animation to use for opening/closing the modal.
*/
animation: {
type: AnimationProp
},
/**
* The modalId to use for the open and close event listeners.
*/
modalId: {
type: String,
required: true
}
},
setup(props) {
/** The element that opened the modal. */
let openerElement: HTMLElement | undefined;
/** Whether the modal is open or not. */
const isOpen = ref(false);
const el = ref<HTMLElement>();
const closeModalEvents: XEvent[] = ['UserClickedCloseModal', 'UserClickedOutOfModal'];
const xBus = useXBus();
/**
* Opens the modal.
*
* @param modalId - The payload of the {@link XEventsTypes.UserClickedOpenModal} event.
* @param metadata - The metadata of the emitted event.
* @public
*/
function openModal(modalId: string, metadata: WireMetadata): void {
if (!isOpen.value && props.modalId === modalId) {
openerElement = metadata.target;
isOpen.value = true;
}
}
}
/**
* Closes the modal.
*
* @param payload - The payload of the closing events:
* {@link XEventsTypes.UserClickedCloseModal} or {@link XEventsTypes.UserClickedOutOfModal}.
*
* @public
*/
@XOn(['UserClickedCloseModal', 'UserClickedOutOfModal'])
closeModal(payload: string): void {
if (this.isOpen && this.modalId === payload) {
this.isOpen = false;
/**
* Closes the modal.
*
* @param payload - The payload of the closing events:
* {@link XEventsTypes.UserClickedCloseModal} or {@link XEventsTypes.UserClickedOutOfModal}.
*
* @public
*/
function closeModal(payload: string): void {
if (isOpen.value && props.modalId === payload) {
isOpen.value = false;
}
}
}
/**
* Emits a {@link XEventsTypes.UserClickedOutOfModal} event unless the passed event target
* is the button that opened the modal.
*
* @param event - The event that triggered the close attempt.
* @public
*/
protected emitClickOutOfModal(event: MouseEvent | FocusEvent): void {
// Prevents clicking the open button when the panel is already open to close the panel.
if (
!this.openerElement ||
!isElementEqualOrContained(this.openerElement, getTargetElement(event))
) {
this.$x.emit('UserClickedOutOfModal', this.modalId, { target: this.$el as HTMLElement });
/**
* Emits a {@link XEventsTypes.UserClickedOutOfModal} event unless the passed event target
* is the button that opened the modal.
*
* @param event - The event that triggered the close attempt.
* @public
*/
function emitClickOutOfModal(event: MouseEvent | FocusEvent): void {
// Prevents clicking the open button when the panel is already open to close the panel.
if (!openerElement || !isElementEqualOrContained(openerElement, getTargetElement(event))) {
xBus.emit('UserClickedOutOfModal', props.modalId, { target: el.value as HTMLElement });
}
}
xBus
.on('UserClickedOpenModal', true)
.subscribe(({ eventPayload, metadata }) => openModal(eventPayload, metadata));
closeModalEvents.forEach(event => {
xBus.on(event, false).subscribe(eventPayload => closeModal(eventPayload as string));
});
return {
el,
isOpen,
emitClickOutOfModal
};
}
}
});
</script>

<docs lang="mdx">
Expand Down

0 comments on commit 870a02d

Please sign in to comment.