123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143 |
- <script>
- const popoverCloseQueue = [];
- const popoverCloseAll = () => popoverCloseQueue.forEach(callback => callback());
- const triggerEvents = {
- hover(el) {},
- focus(el) {
- el.addEventListener("focus", e => {
- this.changeVisible();
- });
- el.addEventListener("blur", e => {
- this.changeVisible();
- });
- },
- click(el) {
- el.addEventListener("click", e => {
- e.stopPropagation();
- this.changeVisible();
- });
- },
- contextmenu(el) {
- el.addEventListener("contextmenu", e => {
- e.preventDefault();
- this.changeVisible();
- });
- }
- };
- export default {
- name: "LemonPopover",
- props: {
- trigger: {
- type: String,
- default: "click",
- validator(val) {
- return Object.keys(triggerEvents).includes(val);
- }
- }
- },
- data() {
- return {
- popoverStyle: {},
- visible: false
- };
- },
- created() {
- document.addEventListener("click", this._documentClickEvent);
- popoverCloseQueue.push(this.close);
- },
- mounted() {
- triggerEvents[this.trigger].call(this, this.$slots.default[0].elm);
- },
- render() {
- return (
- <span style="position:relative">
- <transition name="slide-top">
- {this.visible && (
- <div
- class="lemon-popover"
- ref="popover"
- style={this.popoverStyle}
- on-click={e => e.stopPropagation()}
- >
- <div class="lemon-popover__title" />
- <div class="lemon-popover__content">{this.$slots.content}</div>
- <div class="lemon-popover__arrow" />
- </div>
- )}
- </transition>
- {this.$slots.default}
- </span>
- );
- },
- destroyed() {
- document.removeEventListener("click", this._documentClickEvent);
- },
- computed: {},
- watch: {
- async visible(val) {
- if (val) {
- await this.$nextTick();
- const defaultEl = this.$slots.default[0].elm;
- const contentEl = this.$refs.popover;
- this.popoverStyle = {
- top: `-${contentEl.offsetHeight + 10}px`,
- left: `${defaultEl.offsetWidth / 2 - contentEl.offsetWidth / 2}px`
- };
- }
- }
- },
- methods: {
- _documentClickEvent(e) {
- e.stopPropagation();
- if (this.visible) this.close();
- },
- changeVisible() {
- this.visible ? this.close() : this.open();
- },
- open() {
- popoverCloseAll();
- this.visible = true;
- },
- close() {
- this.visible = false;
- }
- }
- };
- </script>
- <style lang="stylus">
- @import '~styles/utils/index'
- +b(lemon-popover)
- border 1px solid #eee
- border-radius 4px
- font-size 14px
- font-variant tabular-nums
- line-height 1.5
- color rgba(0, 0, 0, 0.65)
- z-index 10
- background-color #fff
- border-radius 4px
- box-shadow 0 2px 8px rgba(0, 0, 0, 0.15)
- position absolute
- transform-origin 50% 150%
- +e(content)
- padding 15px
- box-sizing border-box
- position relative
- z-index 1
- +e(arrow)
- left 50%
- transform translateX(-50%) rotate(45deg)
- position absolute
- z-index 0
- bottom -4px
- box-shadow 3px 3px 7px rgba(0, 0, 0, 0.07)
- width 8px
- height 8px
- background #fff
- .slide-top-leave-active ,.slide-top-enter-active
- transition all .3s cubic-bezier(0.645, 0.045, 0.355, 1)
- .slide-top-enter, .slide-top-leave-to
- transform translateY(-10px) scale(.8)
- opacity 0
- </style>
|