Componentize modal (#5386)

This commit is contained in:
Aya Morisawa 2019-10-29 09:51:19 +09:00 committed by syuilo
parent 34c82776fc
commit bf654c6f42
6 changed files with 188 additions and 223 deletions

View file

@ -1,6 +1,12 @@
<template> <template>
<div class="felqjxyj" :class="{ splash }"> <ui-modal
<div class="bg" ref="bg" @click="onBgClick"></div> ref="modal"
class="modal"
:class="{ splash }"
:close-anime-duration="300"
:close-on-bg-click="false"
@bg-click="onBgClick"
@before-close="onBeforeClose">
<div class="main" ref="main" :class="{ round: $store.state.device.roundedCorners }"> <div class="main" ref="main" :class="{ round: $store.state.device.roundedCorners }">
<template v-if="type == 'signin'"> <template v-if="type == 'signin'">
<mk-signin/> <mk-signin/>
@ -38,7 +44,7 @@
</ui-horizon-group> </ui-horizon-group>
</template> </template>
</div> </div>
</div> </ui-modal>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -120,14 +126,6 @@ export default Vue.extend({
if (this.user) this.canOk = false; if (this.user) this.canOk = false;
this.$nextTick(() => { this.$nextTick(() => {
(this.$refs.bg as any).style.pointerEvents = 'auto';
anime({
targets: this.$refs.bg,
opacity: 1,
duration: 100,
easing: 'linear'
});
anime({ anime({
targets: this.$refs.main, targets: this.$refs.main,
opacity: 1, opacity: 1,
@ -170,33 +168,27 @@ export default Vue.extend({
this.close(); this.close();
}, },
onBgClick() {
if (this.cancelableByBgClick) this.cancel();
}
close() { close() {
this.$refs.modal.close();
},
onBeforeClose() {
this.$el.style.pointerEvents = 'none'; this.$el.style.pointerEvents = 'none';
(this.$refs.bg as any).style.pointerEvents = 'none';
(this.$refs.main as any).style.pointerEvents = 'none'; (this.$refs.main as any).style.pointerEvents = 'none';
anime({
targets: this.$refs.bg,
opacity: 0,
duration: 300,
easing: 'linear'
});
anime({ anime({
targets: this.$refs.main, targets: this.$refs.main,
opacity: 0, opacity: 0,
scale: 0.8, scale: 0.8,
duration: 300, duration: 300,
easing: 'cubicBezier(0, 0.5, 0.5, 1)', easing: 'cubicBezier(0, 0.5, 0.5, 1)',
complete: () => this.destroyDom()
}); });
}, },
onBgClick() {
if (this.cancelableByBgClick) {
this.cancel();
}
},
onInputKeydown(e) { onInputKeydown(e) {
if (e.which == 13) { // Enter if (e.which == 13) { // Enter
e.preventDefault(); e.preventDefault();
@ -209,34 +201,17 @@ export default Vue.extend({
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.felqjxyj .modal
display flex display flex
align-items center align-items center
justify-content center justify-content center
position fixed
z-index 30000
top 0
left 0
width 100%
height 100%
&.splash &.splash
> .main > .main
min-width 0 min-width 0
width initial width initial
> .bg .main
display block
position fixed
top 0
left 0
width 100%
height 100%
background rgba(#000, 0.7)
opacity 0
pointer-events none
> .main
display block display block
position fixed position fixed
margin auto margin auto

View file

@ -1,24 +1,14 @@
<template> <template>
<div class="dkjvrdxtkvqrwmhfickhndpmnncsgacq" v-hotkey.global="keymap"> <ui-modal ref="modal" v-hotkey.global="keymap">
<div class="bg" @click="close"></div>
<img :src="image.url" :alt="image.name" :title="image.name" @click="close" /> <img :src="image.url" :alt="image.name" :title="image.name" @click="close" />
</div> </ui-modal>
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
import anime from 'animejs';
export default Vue.extend({ export default Vue.extend({
props: ['image'], props: ['image'],
mounted() {
anime({
targets: this.$el,
opacity: 1,
duration: 100,
easing: 'linear'
});
},
computed: { computed: {
keymap(): any { keymap(): any {
return { return {
@ -28,40 +18,14 @@ export default Vue.extend({
}, },
methods: { methods: {
close() { close() {
anime({ (this.$refs.modal as any).close();
targets: this.$el,
opacity: 0,
duration: 100,
easing: 'linear',
complete: () => this.destroyDom()
});
} }
} }
}); });
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.dkjvrdxtkvqrwmhfickhndpmnncsgacq img
display block
position fixed
z-index 2048
top 0
left 0
width 100%
height 100%
opacity 0
> .bg
display block
position fixed
z-index 1
top 0
left 0
width 100%
height 100%
background rgba(#000, 0.7)
> img
position fixed position fixed
z-index 2 z-index 2
top 0 top 0

View file

@ -47,6 +47,7 @@ import uiInfo from './ui/info.vue';
import uiMargin from './ui/margin.vue'; import uiMargin from './ui/margin.vue';
import uiHr from './ui/hr.vue'; import uiHr from './ui/hr.vue';
import uiPagination from './ui/pagination.vue'; import uiPagination from './ui/pagination.vue';
import uiModal from './ui/modal.vue';
import formButton from './ui/form/button.vue'; import formButton from './ui/form/button.vue';
import formRadio from './ui/form/radio.vue'; import formRadio from './ui/form/radio.vue';
@ -97,5 +98,6 @@ Vue.component('ui-info', uiInfo);
Vue.component('ui-margin', uiMargin); Vue.component('ui-margin', uiMargin);
Vue.component('ui-hr', uiHr); Vue.component('ui-hr', uiHr);
Vue.component('ui-pagination', uiPagination); Vue.component('ui-pagination', uiPagination);
Vue.component('ui-modal', uiModal);
Vue.component('form-button', formButton); Vue.component('form-button', formButton);
Vue.component('form-radio', formRadio); Vue.component('form-radio', formRadio);

View file

@ -0,0 +1,80 @@
<template>
<div class="modal">
<div class="bg" ref="bg" @click="onBgClick" />
<slot class="main" />
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import anime from 'animejs';
export default Vue.extend({
props: {
closeOnBgClick: {
type: Boolean,
required: false,
default: true
},
openAnimeDuration: {
type: Number,
required: false,
default: 100
},
closeAnimeDuration: {
type: Number,
required: false,
default: 100
}
},
mounted() {
anime({
targets: this.$refs.bg,
opacity: 1,
duration: this.openAnimeDuration,
easing: 'linear'
});
},
methods: {
onBgClick() {
this.$emit('bg-click');
if (this.closeOnBgClick) this.close();
},
close() {
this.$emit('before-close');
anime({
targets: this.$refs.bg,
opacity: 0,
duration: this.closeAnimeDuration,
easing: 'linear',
complete: () => (this as any).destroyDom()
});
}
}
});
</script>
<style lang="stylus" scoped>
.modal
position fixed
z-index 2048
top 0
left 0
width 100%
height 100%
.bg
display block
position fixed
z-index 1
top 0
left 0
width 100%
height 100%
background rgba(#000, 0.7)
opacity 0
.main
z-index 1
</style>

View file

@ -1,23 +1,15 @@
<template> <template>
<div class="mk-media-video-dialog" v-hotkey.global="keymap"> <ui-modal v-hotkey.global="keymap">
<div class="bg" @click="close"></div>
<video :src="video.url" :title="video.name" controls autoplay ref="video" @volumechange="volumechange" /> <video :src="video.url" :title="video.name" controls autoplay ref="video" @volumechange="volumechange" />
</div> </ui-modal>
</template> </template>
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
import anime from 'animejs';
export default Vue.extend({ export default Vue.extend({
props: ['video', 'start'], props: ['video', 'start'],
mounted() { mounted() {
anime({
targets: this.$el,
opacity: 1,
duration: 100,
easing: 'linear'
});
const videoTag = this.$refs.video as HTMLVideoElement; const videoTag = this.$refs.video as HTMLVideoElement;
if (this.start) videoTag.currentTime = this.start if (this.start) videoTag.currentTime = this.start
videoTag.volume = this.$store.state.device.mediaVolume; videoTag.volume = this.$store.state.device.mediaVolume;
@ -31,13 +23,6 @@ export default Vue.extend({
}, },
methods: { methods: {
close() { close() {
anime({
targets: this.$el,
opacity: 0,
duration: 100,
easing: 'linear',
complete: () => this.destroyDom()
});
}, },
volumechange() { volumechange() {
const videoTag = this.$refs.video as HTMLVideoElement; const videoTag = this.$refs.video as HTMLVideoElement;
@ -48,27 +33,7 @@ export default Vue.extend({
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.mk-media-video-dialog video
display block
position fixed
z-index 2048
top 0
left 0
width 100%
height 100%
opacity 0
> .bg
display block
position fixed
z-index 1
top 0
left 0
width 100%
height 100%
background rgba(#000, 0.7)
> video
position fixed position fixed
z-index 2 z-index 2
top 0 top 0

View file

@ -1,6 +1,9 @@
<template> <template>
<div class="ulveipglmagnxfgvitaxyszerjwiqmwl"> <ui-modal
<div class="bg" ref="bg"></div> ref="modal"
:close-on-bg-click="false"
:close-anime-duration="300"
@before-close="onBeforeClose">
<div class="main" ref="main"> <div class="main" ref="main">
<x-post-form ref="form" <x-post-form ref="form"
:reply="reply" :reply="reply"
@ -12,7 +15,7 @@
@posted="onPosted" @posted="onPosted"
@cancel="onCanceled"/> @cancel="onCanceled"/>
</div> </div>
</div> </ui-modal>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -55,14 +58,6 @@ export default Vue.extend({
mounted() { mounted() {
this.$nextTick(() => { this.$nextTick(() => {
(this.$refs.bg as any).style.pointerEvents = 'auto';
anime({
targets: this.$refs.bg,
opacity: 1,
duration: 100,
easing: 'linear'
});
anime({ anime({
targets: this.$refs.main, targets: this.$refs.main,
opacity: 1, opacity: 1,
@ -78,26 +73,22 @@ export default Vue.extend({
this.$refs.form.focus(); this.$refs.form.focus();
}, },
close() { onBeforeClose() {
(this.$refs.bg as any).style.pointerEvents = 'none';
anime({
targets: this.$refs.bg,
opacity: 0,
duration: 300,
easing: 'linear'
});
(this.$refs.main as any).style.pointerEvents = 'none'; (this.$refs.main as any).style.pointerEvents = 'none';
anime({ anime({
targets: this.$refs.main, targets: this.$refs.main,
opacity: 0, opacity: 0,
translateY: 16, translateY: 16,
duration: 300, duration: 300,
easing: 'easeOutQuad', easing: 'easeOutQuad'
complete: () => this.destroyDom()
}); });
}, },
close() {
(this.$refs.modal as any).close();
},
onPosted() { onPosted() {
this.$emit('posted'); this.$emit('posted');
this.close(); this.close();
@ -112,20 +103,8 @@ export default Vue.extend({
</script> </script>
<style lang="stylus" scoped> <style lang="stylus" scoped>
.ulveipglmagnxfgvitaxyszerjwiqmwl
> .bg
display block
position fixed
z-index 10000
top 0
left 0
width 100%
height 100%
background rgba(#000, 0.7)
opacity 0
pointer-events none
> .main .main
display block display block
position fixed position fixed
z-index 10000 z-index 10000