<commit_before>import { defineComponent } from 'vue';
import { on, off, focusFirstDescendant } from '@inkline/inkline/helpers';

export default defineComponent({
    props: {
        disabled: {
            type: Boolean,
            default: false
        },
        modelValue: {
            type: Boolean,
            default: undefined
        },
        trigger: {
            type: Array,
            default: () => ['hover', 'click', 'focus']
        },
        interactable: {
            type: Boolean,
            default: true
        },
        hoverHideDelay: {
            type: Number,
            default: 300
        }
    },
    emits: ['update:modelValue', 'click-outside'],
    data () {
        return {
            visible: this.modelValue,
            triggerStack: 0,
            hoverHideTransition: false
        };
    },
    watch: {
        modelValue (value) {
            if (value) {
                this.show();
            } else {
                this.hide();
            }
        }
    },
    mounted () {
        if (!(this as any).$slots.default) {
            throw new Error(
                'Popup components require one child element to be used as trigger.'
            );
        }

        this.addEventListeners();
    },
    beforeUnmount () {
        this.removeEventListeners();
    },
    methods: {
        show () {
            if (this.disabled || this.visible) {
                return;
            }

            this.triggerStack += 1;
            this.visible = true;

            (this as any).createPopper();
            this.$emit('update:modelValue', true);
        },
        hide () {
            if (this.disabled || !this.visible) {
                return;
            }

            this.triggerStack -= 1;

            if (this.triggerStack <= 0) {
                this.triggerStack = 0;
                this.visible = false;

                // Destroyed by <transition> component after transition is finished
                // this.destroyPopper();
                this.$emit('update:modelValue', false);
            }
        },
        hoverShow () {
            this.hoverHideTransition = false;
            this.show();
        },
        hoverHide () {
            this.hoverHideTransition = true;
            setTimeout(() => {
                if (this.hoverHideTransition) {
                    this.hide();
                }
            }, this.hoverHideDelay);
        },
        onClick () {
            if (this.visible) {
                this.hide();
            } else {
                this.show();
            }
        },
        onClickOutside () {
            if (this.modelValue) return;

            this.hide();
            this.$emit('click-outside');
        },
        addEventListeners () {
            [].concat((this as any).trigger).forEach((trigger) => {
                switch (trigger) {
                case 'hover':
                    on(
                            this.$refs.trigger as HTMLElement,
                            'mouseenter',
                            this.interactable ? this.hoverShow : this.show
                    );
                    on(
                            this.$refs.trigger as HTMLElement,
                            'mouseleave',
                            this.interactable ? this.hoverHide : this.hide
                    );

                    if (this.interactable) {
                        on(<commit_msg>fix: emit click-outside only when dropdown is visible<commit_after>import { defineComponent } from 'vue';
import { on, off, focusFirstDescendant } from '@inkline/inkline/helpers';

export default defineComponent({
    props: {
        disabled: {
            type: Boolean,
            default: false
        },
        modelValue: {
            type: Boolean,
            default: undefined
        },
        trigger: {
            type: Array,
            default: () => ['hover', 'click', 'focus']
        },
        interactable: {
            type: Boolean,
            default: true
        },
        hoverHideDelay: {
            type: Number,
            default: 300
        }
    },
    emits: ['update:modelValue', 'click-outside'],
    data () {
        return {
            visible: this.modelValue,
            triggerStack: 0,
            hoverHideTransition: false
        };
    },
    watch: {
        modelValue (value) {
            if (value) {
                this.show();
            } else {
                this.hide();
            }
        }
    },
    mounted () {
        if (!(this as any).$slots.default) {
            throw new Error(
                'Popup components require one child element to be used as trigger.'
            );
        }

        this.addEventListeners();
    },
    beforeUnmount () {
        this.removeEventListeners();
    },
    methods: {
        show () {
            if (this.disabled || this.visible) {
                return;
            }

            this.triggerStack += 1;
            this.visible = true;

            (this as any).createPopper();
            this.$emit('update:modelValue', true);
        },
        hide () {
            if (this.disabled || !this.visible) {
                return;
            }

            this.triggerStack -= 1;

            if (this.triggerStack <= 0) {
                this.triggerStack = 0;
                this.visible = false;

                // Destroyed by <transition> component after transition is finished
                // this.destroyPopper();
                this.$emit('update:modelValue', false);
            }
        },
        hoverShow () {
            this.hoverHideTransition = false;
            this.show();
        },
        hoverHide () {
            this.hoverHideTransition = true;
            setTimeout(() => {
                if (this.hoverHideTransition) {
                    this.hide();
                }
            }, this.hoverHideDelay);
        },
        onClick () {
            if (this.visible) {
                this.hide();
            } else {
                this.show();
            }
        },
        onClickOutside (event: MouseEvent) {
            if (this.visible) {
                this.$emit('click-outside', event);
            }

            if (this.modelValue) return;

            this.hide();
        },
        addEventListeners () {
            [].concat((this as any).trigger).forEach((trigger) => {
                switch (trigger) {
                case 'hover':
                    on(
                            this.$refs.trigger as HTMLElement,
                            'mouseenter',
                            this.interactable ? this.hoverShow : this.show
                    );
                    on(
                            this.$refs.trigger as HTMLElement,
                            'mouseleave',
                            this.interactable ? this.hoverHide : this.hide
                    );

                    if (this.interactable) {
                        on(
{'fraction_non_alphanumeric': 0.10994168681553122, 'fraction_numerical': 0.002275636467074385, 'mean_word_length': 1.0507436570428696, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4206635', 'n_tokens_mistral': 1748, 'n_tokens_neox': 1674, 'n_words': 357}