Refactored, added es5 build

This commit is contained in:
euvl
2017-04-05 11:34:38 +01:00
parent 5109f89848
commit 3d9c97722f
15 changed files with 10570 additions and 117 deletions

257
src/Modal.vue Normal file
View File

@@ -0,0 +1,257 @@
<template>
<transition name="overlay-fade">
<div v-if="visibility.overlay"
class="nice-modal-overlay"
@mousedown.stop="toggle(false)">
<transition :name="transition">
<div v-if="visibility.modal"
ref="modal"
:class="modalClass"
:style="modalStyle"
@mousedown.stop>
<slot></slot>
<resizer v-if="resizable"
:min-width="minWidth"
:min-height="minHeight"
@resize="resize"/>
</div>
</transition>
</div>
</transition>
</template>
<script>
import Vue from 'vue'
import Modal from './index'
import Resizer from './Resizer.vue'
export default {
name: 'Modal',
props: {
name: {
required: true,
type: [String, Number],
},
delay: {
type: Number,
default: 0,
},
resizable: {
type: Boolean,
default: false
},
adaptive: {
type: Boolean,
default: false
},
transition: {
type: String,
},
classes: {
type: [String, Array],
default: 'nice-modal',
},
width: {
type: Number,
default: 600
},
height: {
type: Number,
default: 300
},
minWidth: {
type: Number,
default: 0
},
minHeight: {
type: Number,
default: 0
}
},
components: {
Resizer
},
data() {
return {
visible: false,
visibility: {
modal: false,
overlay: false
},
modal: {
width: this.width,
height: this.height
},
window: {
width: window.innerWidth,
height: window.innerWidth
}
};
},
watch: {
visible(value) {
if (this.delay > 0) {
if (value) {
this.visibility.overlay = true
setTimeout(() => this.visibility.modal = true, this.delay)
} else {
this.visibility.modal = false
setTimeout(() => this.visibility.overlay = false, this.delay)
}
} else {
this.visibility.overlay = value
Vue.nextTick(() => this.visibility.modal = value)
}
},
},
created() {
Modal.event.$on('toggle', (name, state, params) => {
if (name === this.name) {
this.toggle(!this.visible, params)
}
});
window.addEventListener('resize', this.onWindowResize)
},
beforeMount() {
this.onWindowResize();
},
computed: {
position() {
return {
left: Math.max(0.5 * (this.window.width - this.modal.width), 0),
top: Math.max(0.5 * (this.window.height - this.modal.height), 0)
}
},
modalClass() {
return ['modal', this.classes]
},
modalStyle() {
return {
top: this.position.top + 'px',
left: this.position.left + 'px',
width: this.modal.width + 'px',
height: this.modal.height + 'px'
}
}
},
methods: {
onWindowResize() {
this.window.width = window.innerWidth
this.window.height = window.innerHeight
if (this.adaptive) {
var width = this.window.width > this.modal.width
? this.modal.width
: this.window.width
var height = this.window.height > this.modal.height
? this.modal.height
: this.window.height
this.modal.width = width // Math.max(width, this.minWidth);
this.modal.height = height // Math.max(height, this.minHeight);
}
},
genEventObject(params) {
return Vue.util.extend(
{
name: this.name,
ref: this.$refs.modal,
timestamp: Date.now()
},
params || {});
},
resize(event) {
this.modal.width = event.size.width
this.modal.height = event.size.height
let resizeEvent = this.genEventObject({
size: this.modal
});
this.$emit('resize', resizeEvent)
},
toggle(state, params) {
const beforeEventName = this.visible ? 'before-close' : 'before-open'
const afterEventName = this.visible ? 'closed' : 'opened'
let stopEventExecution = false
const beforeEvent = this.genEventObject({
stop: () => stopEventExecution = false,
state,
params
})
this.$emit(beforeEventName, beforeEvent)
if (!stopEventExecution) {
this.visible = !!state
const afterEvent = this.genEventObject({
state,
params
})
this.$emit(afterEventName, afterEvent)
}
},
},
};
</script>
<style lang="scss" scoped>
.nice-modal-overlay {
position: fixed;
left: 0;
top: 0;
width: 100vw;
height: 100vh;
background: rgba(0, 0, 0, 0.2);
z-index: 999;
opacity: 1;
.modal {
position: relative;
overflow: hidden;
box-sizing: border-box;
background-color: white;
}
}
.overlay-fade-enter-active, .overlay-fade-leave-active {
transition: all 0.2s;
}
.overlay-fade-enter, .overlay-fade-leave-active {
opacity: 0;
}
.nice-modal-fade-enter-active, .nice-modal-fade-leave-active {
transition: all 0.4s;
}
.nice-modal-fade-enter, .nice-modal-fade-leave-active {
opacity: 0;
transform: translateY(-20px);
}
.nice-modal {
background: white;
text-align: left;
border-radius: 3px;
box-shadow: 0 20px 60px -2px rgba(27, 33, 58, .4);
padding: 0;
&.nice-modal-fullscreen {
width: 100vw;
height: 100vh;
margin: 0;
left: 0;
top: 0;
}
}
</style>

120
src/Resizer.vue Normal file
View File

@@ -0,0 +1,120 @@
<template>
<div :class="className"></div>
</template>
<script>
export default {
name: 'Resizer',
props: {
minHeight: {
type: Number,
default: 0
},
minWidth: {
type: Number,
default: 0
}},
data() {
return {
clicked: false,
size: {}
}
},
mounted() {
this.$el.addEventListener('mousedown', this.start, false)
},
computed: {
className () {
return {'vue-modal-resizer': true, 'clicked': this.clicked}
}
},
methods: {
start(event) {
this.clicked = true
window.addEventListener('mousemove', this.mousemove, false)
window.addEventListener('mouseup', this.stop, false)
event.stopPropagation()
event.preventDefault()
},
stop() {
this.clicked = false
window.removeEventListener('mousemove', this.mousemove, false)
window.removeEventListener('mouseup', this.stop, false)
this.$emit('resize-stop', {
element: this.$el.parentElement,
size: this.size
});
},
mousemove(event) {
this.resize(event)
},
resize(event) {
var el = this.$el.parentElement
if (el) {
var width = event.clientX - el.offsetLeft
var height = event.clientY - el.offsetTop
if (width < this.minWidth) {
width = this.minWidth
}
if (width > window.innerWidth) {
width = window.innerWidth
}
if (height < this.minHeight) {
height = this.minHeight
}
if (height > window.innerHeight) {
height = window.innerHeight
}
this.size = {width, height}
el.style.width = width + 'px'
el.style.height = height + 'px'
this.$emit('resize', {
element: el,
size: this.size
})
}
}
}
}
</script>
<style lang="scss">
.vue-modal-resizer {
display: block;
overflow: hidden;
position: absolute;
width: 12px;
height: 12px;
right: 0;
bottom: 0;
z-index: 9999999;
background: transparent;
cursor: se-resize;
&:after {
display: block;
position: absolute;
content: '';
background: transparent;
left: 0;
top: 0;
width: 0;
height: 0;
border-bottom: 10px solid #ddd;
border-left: 10px solid transparent;
}
&.clicked:after {
border-bottom: 10px solid #369BE9;
}
}
</style>

28
src/index.js Normal file
View File

@@ -0,0 +1,28 @@
import Vue from 'vue'
import Modal from './Modal.vue'
const ModalPlugin = {
install(Vue, options = {}) {
if (!this.hasOwnProperty("event")) {
this.event = new Vue()
}
const $modal = {
show(name, params) {
ModalPlugin.event.$emit('toggle', name, true, params)
},
hide(name, params) {
ModalPlugin.event.$emit('toggle', name, false, params)
}
}
Object.defineProperty(Vue.prototype, '$modal', {
get: () => $modal
})
Vue.component('modal', Modal)
return null
},
}
export default ModalPlugin