extracting css

This commit is contained in:
yev
2017-12-27 20:34:51 +00:00
parent 9acd4ddcfc
commit 2be134436f
5 changed files with 549 additions and 513 deletions

5
.prettierrc Normal file
View File

@@ -0,0 +1,5 @@
{
"trailingComma": "none",
"singleQuote": true,
"semi": false
}

View File

@@ -0,0 +1,24 @@
const path = require('path')
const webpack = require('webpack')
const merge = require('webpack-merge')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const base = require('./webpack.srr.config')
module.exports = merge(base, {
plugins: [new ExtractTextPlugin('styles.css')],
output: {
filename: 'ssr.pure.js'
},
module: {
rules: [
{
test: /\.css$/,
use: ExtractTextPlugin.extract({
fallback: 'style-loader',
use: 'css-loader'
})
}
]
}
})

View File

@@ -19,10 +19,11 @@
}, },
"scripts": { "scripts": {
"build:client": "webpack --config ./build/webpack.client.config.js --progress --hide-modules", "build:client": "webpack --config ./build/webpack.client.config.js --progress --hide-modules",
"build:server": "webpack --config ./build/webpack.server.config.js --progress --hide-modules", "build:srr": "webpack --config ./build/webpack.srr.config.js --progress --hide-modules",
"build:srr-no-css": "webpack --config ./build/webpack.srr-no-css.config.js --progress --hide-modules",
"lint": "eslint --ext .js,.vue src test/unit/specs", "lint": "eslint --ext .js,.vue src test/unit/specs",
"unit": "./node_modules/karma/bin/karma start test/unit/karma.conf.js", "unit": "./node_modules/karma/bin/karma start test/unit/karma.conf.js",
"build": "npm run lint && npm run unit && npm run build:client && npm run build:server" "build": "npm run lint && npm run unit && npm run build:client && npm run build:srr"
}, },
"license": "MIT", "license": "MIT",
"devDependencies": { "devDependencies": {

View File

@@ -28,13 +28,13 @@
</transition> </transition>
</template> </template>
<script> <script>
import Modal from './index' import Modal from "./index";
import Resizer from './Resizer.vue' import Resizer from "./Resizer.vue";
import { inRange } from './util' import { inRange } from "./util";
import parseNumber from './parser' import parseNumber from "./parser";
export default { export default {
name: 'VueJsModal', name: "VueJsModal",
props: { props: {
name: { name: {
required: true, required: true,
@@ -73,71 +73,71 @@
}, },
classes: { classes: {
type: [String, Array], type: [String, Array],
default: 'v--modal' default: "v--modal"
}, },
minWidth: { minWidth: {
type: Number, type: Number,
default: 0, default: 0,
validator (value) { validator(value) {
return value >= 0 return value >= 0;
} }
}, },
minHeight: { minHeight: {
type: Number, type: Number,
default: 0, default: 0,
validator (value) { validator(value) {
return value >= 0 return value >= 0;
} }
}, },
width: { width: {
type: [Number, String], type: [Number, String],
default: 600, default: 600,
validator (value) { validator(value) {
if (typeof value === 'string') { if (typeof value === "string") {
let width = parseNumber(value) let width = parseNumber(value);
return (width.type === '%' || width.type === 'px') && return (width.type === "%" || width.type === "px") && width.value > 0;
width.value > 0
} }
return value >= 0 return value >= 0;
} }
}, },
height: { height: {
type: [Number, String], type: [Number, String],
default: 300, default: 300,
validator (value) { validator(value) {
if (typeof value === 'string') { if (typeof value === "string") {
if (value === 'auto') { if (value === "auto") {
return true return true;
} }
let height = parseNumber(value) let height = parseNumber(value);
return (height.type === '%' || height.type === 'px') && return (
height.value > 0 (height.type === "%" || height.type === "px") && height.value > 0
);
} }
return value >= 0 return value >= 0;
} }
}, },
pivotX: { pivotX: {
type: Number, type: Number,
default: 0.5, default: 0.5,
validator (value) { validator(value) {
return value >= 0 && value <= 1 return value >= 0 && value <= 1;
} }
}, },
pivotY: { pivotY: {
type: Number, type: Number,
default: 0.5, default: 0.5,
validator (value) { validator(value) {
return value >= 0 && value <= 1 return value >= 0 && value <= 1;
} }
} }
}, },
components: { components: {
Resizer Resizer
}, },
data () { data() {
return { return {
visible: false, visible: false,
@@ -153,9 +153,9 @@
modal: { modal: {
width: 0, width: 0,
widthType: 'px', widthType: "px",
height: 0, height: 0,
heightType: 'px', heightType: "px",
renderedHeight: 0 renderedHeight: 0
}, },
@@ -165,7 +165,7 @@
}, },
mutationObserver: null mutationObserver: null
} };
}, },
watch: { watch: {
/** /**
@@ -174,55 +174,57 @@
* inside `setTimeout` and `$nextTick`, after the DOM changes. * inside `setTimeout` and `$nextTick`, after the DOM changes.
* This fixes `$refs.modal` `undefined` bug (fixes #15) * This fixes `$refs.modal` `undefined` bug (fixes #15)
*/ */
visible (value) { visible(value) {
if (value) { if (value) {
this.visibility.overlay = true this.visibility.overlay = true;
setTimeout(() => { setTimeout(() => {
this.visibility.modal = true this.visibility.modal = true;
this.$nextTick(() => { this.$nextTick(() => {
this.addDraggableListeners() this.addDraggableListeners();
this.callAfterEvent(true) this.callAfterEvent(true);
}) });
}, this.delay) }, this.delay);
} else { } else {
this.visibility.modal = false this.visibility.modal = false;
setTimeout(() => { setTimeout(() => {
this.visibility.overlay = false this.visibility.overlay = false;
this.$nextTick(() => { this.$nextTick(() => {
this.removeDraggableListeners() this.removeDraggableListeners();
this.callAfterEvent(false) this.callAfterEvent(false);
}) });
}, this.delay) }, this.delay);
} }
} }
}, },
created () { created() {
this.setInitialSize() this.setInitialSize();
}, },
/** /**
* Sets global listeners * Sets global listeners
*/ */
beforeMount () { beforeMount() {
Modal.event.$on('toggle', (name, state, params) => { Modal.event.$on("toggle", (name, state, params) => {
if (name === this.name) { if (name === this.name) {
if (typeof state === 'undefined') { if (typeof state === "undefined") {
state = !this.visible state = !this.visible;
} }
this.toggle(state, params) this.toggle(state, params);
} }
}) });
window.addEventListener('resize', this.onWindowResize) window.addEventListener("resize", this.onWindowResize);
this.onWindowResize() this.onWindowResize();
/** /**
* Making sure that autoHeight is enabled when using "scrollable" * Making sure that autoHeight is enabled when using "scrollable"
*/ */
if (this.scrollable && !this.isAutoHeight) { if (this.scrollable && !this.isAutoHeight) {
console.warn(`Modal "${this.name}" has scrollable flag set to true ` + console.warn(
`but height is not "auto" (${this.height})`) `Modal "${this.name}" has scrollable flag set to true ` +
`but height is not "auto" (${this.height})`
);
} }
/** /**
* Only observe when using height: 'auto' * Only observe when using height: 'auto'
@@ -237,80 +239,85 @@
* simply stay at its initial height (won't crash). * simply stay at its initial height (won't crash).
* (Provide polyfill to support IE < 11) * (Provide polyfill to support IE < 11)
*/ */
const MutationObserver = (function () { const MutationObserver = (function() {
const prefixes = ['', 'WebKit', 'Moz', 'O', 'Ms'] const prefixes = ["", "WebKit", "Moz", "O", "Ms"];
for (let i = 0; i < prefixes.length; i++) { for (let i = 0; i < prefixes.length; i++) {
let name = prefixes[i] + 'MutationObserver' let name = prefixes[i] + "MutationObserver";
if (name in window) { if (name in window) {
return window[name] return window[name];
} }
} }
return false return false;
}()) })();
if (MutationObserver) { if (MutationObserver) {
this.mutationObserver = new MutationObserver(mutations => { this.mutationObserver = new MutationObserver(mutations => {
this.updateRenderedHeight() this.updateRenderedHeight();
}) });
} }
} }
if (this.clickToClose) { if (this.clickToClose) {
window.addEventListener('keyup', this.onEscapeKeyUp) window.addEventListener("keyup", this.onEscapeKeyUp);
} }
}, },
/** /**
* Removes "resize" window listener * Removes "resize" window listener
*/ */
beforeDestroy () { beforeDestroy() {
window.removeEventListener('resize', this.onWindowResize) window.removeEventListener("resize", this.onWindowResize);
if (this.clickToClose) { if (this.clickToClose) {
window.removeEventListener('keyup', this.onEscapeKeyUp) window.removeEventListener("keyup", this.onEscapeKeyUp);
} }
}, },
computed: { computed: {
/** /**
* Returns true if height is set to "auto" * Returns true if height is set to "auto"
*/ */
isAutoHeight () { isAutoHeight() {
return this.modal.heightType === 'auto' return this.modal.heightType === "auto";
}, },
/** /**
* Calculates and returns modal position based on the * Calculates and returns modal position based on the
* pivots, window size and modal size * pivots, window size and modal size
*/ */
position () { position() {
const { window, shift, pivotX, pivotY, const {
trueModalWidth, trueModalHeight } = this window,
shift,
pivotX,
pivotY,
trueModalWidth,
trueModalHeight
} = this;
const maxLeft = window.width - trueModalWidth const maxLeft = window.width - trueModalWidth;
const maxTop = window.height - trueModalHeight const maxTop = window.height - trueModalHeight;
const left = shift.left + pivotX * maxLeft const left = shift.left + pivotX * maxLeft;
const top = shift.top + pivotY * maxTop const top = shift.top + pivotY * maxTop;
return { return {
left: inRange(0, maxLeft, left), left: inRange(0, maxLeft, left),
top: inRange(0, maxTop, top) top: inRange(0, maxTop, top)
} };
}, },
/** /**
* Returns pixel width (if set with %) and makes sure that modal size * Returns pixel width (if set with %) and makes sure that modal size
* fits the window * fits the window
*/ */
trueModalWidth () { trueModalWidth() {
const { window, modal, adaptive, minWidth } = this const { window, modal, adaptive, minWidth } = this;
const value = modal.widthType === '%' const value =
modal.widthType === "%"
? window.width / 100 * modal.width ? window.width / 100 * modal.width
: modal.width : modal.width;
return adaptive return adaptive ? inRange(minWidth, window.width, value) : value;
? inRange(minWidth, window.width, value)
: value
}, },
/** /**
* Returns pixel height (if set with %) and makes sure that modal size * Returns pixel height (if set with %) and makes sure that modal size
@@ -318,49 +325,48 @@
* *
* Returns modal.renderedHeight if height set as "auto" * Returns modal.renderedHeight if height set as "auto"
*/ */
trueModalHeight () { trueModalHeight() {
const { window, modal, isAutoHeight, adaptive } = this const { window, modal, isAutoHeight, adaptive } = this;
const value = (modal.heightType === '%') const value =
modal.heightType === "%"
? window.height / 100 * modal.height ? window.height / 100 * modal.height
: modal.height : modal.height;
if (isAutoHeight) { if (isAutoHeight) {
// use renderedHeight when height 'auto' // use renderedHeight when height 'auto'
return this.modal.renderedHeight return this.modal.renderedHeight;
} }
return adaptive return adaptive
? inRange(this.minHeight, this.window.height, value) ? inRange(this.minHeight, this.window.height, value)
: value : value;
}, },
/** /**
* Returns class list for screen overlay (modal background) * Returns class list for screen overlay (modal background)
*/ */
overlayClass () { overlayClass() {
return { return {
'v--modal-overlay': true, "v--modal-overlay": true,
'scrollable': this.scrollable && this.isAutoHeight scrollable: this.scrollable && this.isAutoHeight
} };
}, },
/** /**
* Returns class list for modal itself * Returns class list for modal itself
*/ */
modalClass () { modalClass() {
return ['v--modal-box', this.classes] return ["v--modal-box", this.classes];
}, },
/** /**
* CSS styles for position and size of the modal * CSS styles for position and size of the modal
*/ */
modalStyle () { modalStyle() {
return { return {
top: this.position.top + 'px', top: this.position.top + "px",
left: this.position.left + 'px', left: this.position.left + "px",
width: this.trueModalWidth + 'px', width: this.trueModalWidth + "px",
height: this.isAutoHeight height: this.isAutoHeight ? "auto" : this.trueModalHeight + "px"
? 'auto' };
: (this.trueModalHeight + 'px')
}
} }
}, },
methods: { methods: {
@@ -369,196 +375,193 @@
* if "reset" flag is set to true - this function will be called * if "reset" flag is set to true - this function will be called
* every time "beforeOpen" is triggered * every time "beforeOpen" is triggered
*/ */
setInitialSize () { setInitialSize() {
let { modal } = this let { modal } = this;
let width = parseNumber(this.width) let width = parseNumber(this.width);
let height = parseNumber(this.height) let height = parseNumber(this.height);
modal.width = width.value modal.width = width.value;
modal.widthType = width.type modal.widthType = width.type;
modal.height = height.value modal.height = height.value;
modal.heightType = height.type modal.heightType = height.type;
}, },
onEscapeKeyUp (event) { onEscapeKeyUp(event) {
if (event.which === 27 && this.visible) { if (event.which === 27 && this.visible) {
this.$modal.hide(this.name) this.$modal.hide(this.name);
} }
}, },
onWindowResize () { onWindowResize() {
this.window.width = window.innerWidth this.window.width = window.innerWidth;
this.window.height = window.innerHeight this.window.height = window.innerHeight;
}, },
/** /**
* Generates event object * Generates event object
*/ */
genEventObject (params) { genEventObject(params) {
var eventData = { var eventData = {
name: this.name, name: this.name,
timestamp: Date.now(), timestamp: Date.now(),
canceled: false, canceled: false,
ref: this.$refs.modal ref: this.$refs.modal
} };
return Object.assign(eventData, params || {}) return Object.assign(eventData, params || {});
}, },
/** /**
* Event handler which is triggered on modal resize * Event handler which is triggered on modal resize
*/ */
onModalResize (event) { onModalResize(event) {
this.modal.widthType = 'px' this.modal.widthType = "px";
this.modal.width = event.size.width this.modal.width = event.size.width;
this.modal.heightType = 'px' this.modal.heightType = "px";
this.modal.height = event.size.height this.modal.height = event.size.height;
const { size } = this.modal const { size } = this.modal;
const resizeEvent = this.genEventObject({ size }) const resizeEvent = this.genEventObject({ size });
this.$emit('resize', resizeEvent) this.$emit("resize", resizeEvent);
}, },
/** /**
* Event handler which is triggered on $modal.show and $modal.hight * Event handler which is triggered on $modal.show and $modal.hight
* BeforeEvents: ('before-close' and 'before-open') are `$emit`ed here, * BeforeEvents: ('before-close' and 'before-open') are `$emit`ed here,
* but AfterEvents ('opened' and 'closed') are moved to `watch.visible`. * but AfterEvents ('opened' and 'closed') are moved to `watch.visible`.
*/ */
toggle (state, params) { toggle(state, params) {
const { reset, scrollable, visible } = this const { reset, scrollable, visible } = this;
const beforeEventName = visible const beforeEventName = visible ? "before-close" : "before-open";
? 'before-close'
: 'before-open'
if (beforeEventName === 'before-open') { if (beforeEventName === "before-open") {
/** /**
* Need to unfocus previously focused element, otherwise * Need to unfocus previously focused element, otherwise
* all keypress events (ESC press, for example) will trigger on that element. * all keypress events (ESC press, for example) will trigger on that element.
*/ */
if (document.activeElement) { if (document.activeElement) {
document.activeElement.blur() document.activeElement.blur();
} }
if (reset) { if (reset) {
this.setInitialSize() this.setInitialSize();
this.shift.left = 0 this.shift.left = 0;
this.shift.top = 0 this.shift.top = 0;
} }
if (scrollable) { if (scrollable) {
document.body.classList.add('v--modal-block-scroll') document.body.classList.add("v--modal-block-scroll");
} }
} else { } else {
if (scrollable) { if (scrollable) {
document.body.classList.remove('v--modal-block-scroll') document.body.classList.remove("v--modal-block-scroll");
} }
} }
let stopEventExecution = false let stopEventExecution = false;
const stop = () => { const stop = () => {
stopEventExecution = true stopEventExecution = true;
} };
const beforeEvent = this.genEventObject({ stop, state, params }) const beforeEvent = this.genEventObject({ stop, state, params });
this.$emit(beforeEventName, beforeEvent) this.$emit(beforeEventName, beforeEvent);
if (!stopEventExecution) { if (!stopEventExecution) {
this.visible = state this.visible = state;
// after events are called in `watch.visible` // after events are called in `watch.visible`
} }
}, },
getDraggableElement () { getDraggableElement() {
var selector = typeof this.draggable !== 'string' var selector =
? '.v--modal-box' typeof this.draggable !== "string" ? ".v--modal-box" : this.draggable;
: this.draggable
if (selector) { if (selector) {
var handler = this.$refs.overlay.querySelector(selector) var handler = this.$refs.overlay.querySelector(selector);
if (handler) { if (handler) {
return handler return handler;
} }
} }
}, },
/** /**
* Event handler that is triggered when background overlay is clicked * Event handler that is triggered when background overlay is clicked
*/ */
onBackgroundClick () { onBackgroundClick() {
if (this.clickToClose) { if (this.clickToClose) {
this.toggle(false) this.toggle(false);
} }
}, },
addDraggableListeners () { addDraggableListeners() {
if (!this.draggable) { if (!this.draggable) {
return return;
} }
let dragger = this.getDraggableElement() let dragger = this.getDraggableElement();
if (dragger) { if (dragger) {
let startX = 0 let startX = 0;
let startY = 0 let startY = 0;
let cachedShiftX = 0 let cachedShiftX = 0;
let cachedShiftY = 0 let cachedShiftY = 0;
let getPosition = (event) => { let getPosition = event => {
return event.touches && event.touches.length > 0 return event.touches && event.touches.length > 0
? event.touches[0] ? event.touches[0]
: event : event;
};
let mousedown = event => {
let target = event.target;
if (target && target.nodeName === "INPUT") {
return;
} }
let mousedown = (event) => { let { clientX, clientY } = getPosition(event);
let target = event.target
if (target && target.nodeName === 'INPUT') { document.addEventListener("mousemove", mousemove);
return document.addEventListener("mouseup", mouseup);
}
let { clientX, clientY } = getPosition(event) document.addEventListener("touchmove", mousemove);
document.addEventListener("touchend", mouseup);
document.addEventListener('mousemove', mousemove) startX = clientX;
document.addEventListener('mouseup', mouseup) startY = clientY;
cachedShiftX = this.shift.left;
document.addEventListener('touchmove', mousemove) cachedShiftY = this.shift.top;
document.addEventListener('touchend', mouseup)
startX = clientX
startY = clientY
cachedShiftX = this.shift.left
cachedShiftY = this.shift.top
// event.preventDefault() // event.preventDefault()
} };
let mousemove = (event) => { let mousemove = event => {
let { clientX, clientY } = getPosition(event) let { clientX, clientY } = getPosition(event);
this.shift.left = cachedShiftX + clientX - startX this.shift.left = cachedShiftX + clientX - startX;
this.shift.top = cachedShiftY + clientY - startY this.shift.top = cachedShiftY + clientY - startY;
event.preventDefault() event.preventDefault();
} };
let mouseup = (event) => { let mouseup = event => {
document.removeEventListener('mousemove', mousemove) document.removeEventListener("mousemove", mousemove);
document.removeEventListener('mouseup', mouseup) document.removeEventListener("mouseup", mouseup);
document.removeEventListener('touchmove', mousemove) document.removeEventListener("touchmove", mousemove);
document.removeEventListener('touchend', mouseup) document.removeEventListener("touchend", mouseup);
event.preventDefault() event.preventDefault();
} };
dragger.addEventListener('mousedown', mousedown) dragger.addEventListener("mousedown", mousedown);
dragger.addEventListener('touchstart', mousedown) dragger.addEventListener("touchstart", mousedown);
} }
}, },
removeDraggableListeners () { removeDraggableListeners() {
// console.log('removing draggable handlers') // console.log('removing draggable handlers')
}, },
@@ -569,17 +572,17 @@
* wrapping afterEvents in `$nextTick` fixes `$refs.modal` undefined bug. * wrapping afterEvents in `$nextTick` fixes `$refs.modal` undefined bug.
* (fixes #15) * (fixes #15)
*/ */
callAfterEvent (state) { callAfterEvent(state) {
if (state) { if (state) {
this.connectObserver() this.connectObserver();
} else { } else {
this.disconnectObserver() this.disconnectObserver();
} }
const eventName = state ? 'opened' : 'closed' const eventName = state ? "opened" : "closed";
const event = this.genEventObject({ state }) const event = this.genEventObject({ state });
this.$emit(eventName, event) this.$emit(eventName, event);
}, },
/** /**
@@ -588,10 +591,9 @@
* 1. modal opened * 1. modal opened
* 2. MutationObserver's observe callback * 2. MutationObserver's observe callback
*/ */
updateRenderedHeight () { updateRenderedHeight() {
if (this.$refs.modal) { if (this.$refs.modal) {
this.modal.renderedHeight = this.$refs.modal this.modal.renderedHeight = this.$refs.modal.getBoundingClientRect().height;
.getBoundingClientRect().height
} }
}, },
@@ -599,102 +601,106 @@
* Start observing modal's DOM, if childList or subtree changes, * Start observing modal's DOM, if childList or subtree changes,
* the callback (registered in beforeMount) will be called. * the callback (registered in beforeMount) will be called.
*/ */
connectObserver () { connectObserver() {
if (this.mutationObserver) { if (this.mutationObserver) {
this.mutationObserver.observe(this.$refs.modal, { this.mutationObserver.observe(this.$refs.modal, {
childList: true, childList: true,
attributes: true, attributes: true,
subtree: true subtree: true
}) });
} }
}, },
/** /**
* Disconnects MutationObserver * Disconnects MutationObserver
*/ */
disconnectObserver () { disconnectObserver() {
if (this.mutationObserver) { if (this.mutationObserver) {
this.mutationObserver.disconnect() this.mutationObserver.disconnect();
}
} }
} }
} }
};
</script> </script>
<style> <style>
.v--modal-block-scroll { .v--modal-block-scroll {
overflow: hidden; overflow: hidden;
position: fixed; position: fixed;
width: 100vw; width: 100vw;
} }
.v--modal-overlay { .v--modal-overlay {
position: fixed; position: fixed;
box-sizing: border-box; box-sizing: border-box;
left: 0; left: 0;
top: 0; top: 0;
width: 100vw; width: 100%;
height: 100vh; height: 100vh;
background: rgba(0, 0, 0, 0.2); background: rgba(0, 0, 0, 0.2);
z-index: 999; z-index: 999;
opacity: 1; opacity: 1;
} }
.v--modal-overlay.scrollable { .v--modal-overlay.scrollable {
height: 100%; height: 100%;
min-height: 100vh; min-height: 100vh;
overflow-y: auto; overflow-y: auto;
padding-bottom: 10px; padding-bottom: 10px;
-webkit-overflow-scrolling: touch; -webkit-overflow-scrolling: touch;
} }
.v--modal-overlay .v--modal-box { .v--modal-overlay .v--modal-box {
position: relative; position: relative;
overflow: hidden; overflow: hidden;
box-sizing: border-box; box-sizing: border-box;
} }
.v--modal-overlay.scrollable .v--modal-box { .v--modal-overlay.scrollable .v--modal-box {
margin-bottom: 2px; margin-bottom: 2px;
/* transition: top 0.2s ease; */ /* transition: top 0.2s ease; */
} }
.v--modal { .v--modal {
background-color: white; background-color: white;
text-align: left; text-align: left;
border-radius: 3px; border-radius: 3px;
box-shadow: 0 20px 60px -2px rgba(27, 33, 58, .4); box-shadow: 0 20px 60px -2px rgba(27, 33, 58, 0.4);
padding: 0; padding: 0;
} }
.v--modal.v--modal-fullscreen { .v--modal.v--modal-fullscreen {
width: 100vw; width: 100vw;
height: 100vh; height: 100vh;
margin: 0; margin: 0;
left: 0; left: 0;
top: 0; top: 0;
} }
.v--modal-top-right { .v--modal-top-right {
display: block; display: block;
position: absolute; position: absolute;
right: 0; right: 0;
top: 0; top: 0;
} }
.overlay-fade-enter-active, .overlay-fade-leave-active { .overlay-fade-enter-active,
.overlay-fade-leave-active {
transition: all 0.2s; transition: all 0.2s;
} }
.overlay-fade-enter, .overlay-fade-leave-active { .overlay-fade-enter,
.overlay-fade-leave-active {
opacity: 0; opacity: 0;
} }
.nice-modal-fade-enter-active, .nice-modal-fade-leave-active { .nice-modal-fade-enter-active,
.nice-modal-fade-leave-active {
transition: all 0.4s; transition: all 0.4s;
} }
.nice-modal-fade-enter, .nice-modal-fade-leave-active { .nice-modal-fade-enter,
.nice-modal-fade-leave-active {
opacity: 0; opacity: 0;
transform: translateY(-20px); transform: translateY(-20px);
} }
</style> </style>