@inkline/inkline
Version:
Inkline is the Vue.js UI/UX Library built for creating your next design system
221 lines (207 loc) • 5.58 kB
text/typescript
import { defineComponent } from 'vue';
import { addClass, removeClass, uid } from '@inkline/inkline/helpers';
import { OverlayController } from '@inkline/inkline/controllers';
import {
defaultPropValue,
colorVariantClass,
sizePropValidator
} from '@inkline/inkline/mixins';
import { ClickOutside } from '@inkline/inkline/directives';
import { Classes } from '@inkline/inkline/types';
/**
* Event emitted for setting the modelValue
* @event update:modelValue
*/
/**
* Slot for modal body content
* @name default
* @kind slot
*/
/**
* Slot for modal header content
* @name header
* @kind slot
*/
/**
* Slot for modal footer content
* @name footer
* @kind slot
*/
const componentName = 'IModal';
export default defineComponent({
name: componentName,
directives: {
ClickOutside
},
props: {
/**
* Determines if the modal should close when pressing escape
* @type Boolean
* @default true
* @name closeOnPressEscape
*/
closeOnPressEscape: {
type: Boolean,
default: true
},
/**
* The aria-label attribute of the close button
* @type String
* @default Close
* @name closeAriaLabel
*/
closeAriaLabel: {
type: String,
default: 'Close'
},
/**
* The color variant of the modal
* @type primary | success | light | dark | info | success | warning | danger
* @default light
* @name color
*/
color: {
type: String,
default: defaultPropValue<string>(componentName, 'color')
},
/**
* The disabled state of the modal
* @type Boolean
* @default false
* @name disabled
*/
disabled: {
type: Boolean,
default: false
},
/**
* Determines if the modal should close when clicking the overlay
* @type Boolean
* @default true
* @name hideOnClickOutside
*/
hideOnClickOutside: {
type: Boolean,
default: true
},
/**
* The identifier of the modal
* @type String
* @default uid()
* @name name
*/
name: {
type: String,
default (): string {
return uid('modal');
}
},
/**
* Determines if the close icon should be visible in the modal header
* @type Boolean
* @default false
* @name showClose
*/
showClose: {
type: Boolean,
default: true
},
/**
* The size variant of the modal
* @type sm | md | lg
* @default md
* @name size
*/
size: {
type: String,
default: defaultPropValue<string>(componentName, 'size'),
validator: sizePropValidator
},
/**
* Used to determine if modal is visible or not
* @type Boolean
* @default false
* @name modelValue
*/
modelValue: {
type: Boolean,
default: false
},
/**
* The modal opening and closing animation
* @type fade-in-transition | fade-in-linear-transition | zoom-in-top-transition | zoom-in-bottom-transition | zoom-in-center-transition | zoom-in-left-transition | zoom-in-right-transition
* @default zoom-in-center-transition
* @name transition
*/
transition: {
type: String,
default: 'zoom-in-center-transition'
}
},
emits: [
/**
* Event emitted for setting the modelValue
* @event update:modelValue
*/
'update:modelValue'
],
data (): { visible: boolean } {
return {
visible: (this as any).modelValue as boolean
};
},
computed: {
classes (): Classes {
return {
'-disabled': (this as any).disabled,
...colorVariantClass(this),
[`-${(this as any).size}`]: Boolean((this as any).size)
};
}
},
watch: {
modelValue (value) {
if (value) {
this.show();
} else {
this.hide();
}
}
},
mounted () {
OverlayController.register(this as any);
},
unmounted () {
OverlayController.unregister(this as any);
},
methods: {
show (): void {
if ((this as any).disabled) {
return;
}
this.visible = true;
this.$emit('update:modelValue', true);
OverlayController.open((this as any).name);
if (typeof window !== 'undefined') {
addClass(window.document.body, '-modal');
}
},
hide (): void {
if ((this as any).disabled) {
return;
}
this.visible = false;
this.$emit('update:modelValue', false);
OverlayController.close((this as any).name);
if (typeof window !== 'undefined') {
removeClass(window.document.body, '-modal');
}
},
onClickOutside (): void {
if (!(this as any).hideOnClickOutside) {
return;
}
this.hide();
}
}
});