<commit_before><template lang="pug">
.c-submenu(:class="{'is-open': isOpen}")
  .c-submenu__title.c-menu__item(
    @click="toggleSubmenu"
    @mouseenter="enterSubMenu"
    @mouseleave="leaveSubMenu"
  )
    slot(name="title") {{ title }}
  .c-submenu__popup(
    @mouseenter="enterSubMenu"
    @mouseleave="leaveSubMenu"
    @focusin="openSubMenu"
    @focusout="closeSubMenu"
    @click.capture="clickSubMenu"
  )
    slot
</template>

<script>

export default {
  name: 'c-submenu',
  props: {
    title: String,
    open: Boolean,
    delay: {
      type: Number,
      default: 200
    }
  },
  inject: ['$menu'],
  watch: {
    open: {
      immediate: true,
      handler: function () {
        if (this.open) this.isOpen = true
      }
    },
    '$menu.collapsed': function (collapsed) {
      if (collapsed) this.isOpen = false
    }
  },
  data () {
    return {
      isOpen: false,
      hideSubMenuTimer: null, // 隐藏子菜单时延时
      showSubMenuTimer: null // hover显示子菜单延时
    }
  },
  methods: {
    toggleSubmenu () {
      this.isOpen = !this.isOpen
    },
    enterSubMenu () {
      if (this.hideSubMenuTimer) clearTimeout(this.hideSubMenuTimer)
      const { isVertical, collapsed } = this.$menu
      if (isVertical && !collapsed) return
      this.showSubMenuTimer = setTimeout(_ => {
        this.openSubMenu()
      }, this.delay)
    },
    leaveSubMenu () {
      if (this.showSubMenuTimer) clearTimeout(this.showSubMenuTimer)
      const { isVertical, collapsed } = this.$menu
      if (isVertical && !collapsed) return
      this.hideSubMenuTimer = setTimeout(_ => {
        this.closeSubMenu()
      }, this.delay)
    },
    clickSubMenu () {
      if (this.$menu.isVertical && !this.$menu.collapsed) return
      this.closeSubMenu()
    },
    openSubMenu () {
      this.isOpen = true
    },
    closeSubMenu () {
      this.isOpen = false
    }
  }
}
</script><commit_msg>fix(submenu): seperate different trigger mode(hover and click); fix wrongly closing submenu when focusout<commit_after><template lang="pug">
.c-submenu(:class="{'is-open': isOpen}")
  .c-submenu__title.c-menu__item(
    @click="toggleSubmenu"
    @mouseenter="enterSubMenu"
    @mouseleave="leaveSubMenu"
  )
    slot(name="title") {{ title }}
  .c-submenu__popup(
    @mouseenter="enterPopup"
    @mouseleave="leavePopup"
    @focusin="focusIn"
    @focusout="focusOut"
    @click.capture="clickSubMenu"
  )
    slot
</template>

<script>
import VueTypes from 'vue-types'

export default {
  name: 'c-submenu',
  props: {
    title: String,
    open: Boolean,
    trigger: VueTypes.oneOf(['hover', 'click']),
    delay: {
      type: Number,
      default: 60
    }
  },
  inject: ['$menu'],
  watch: {
    open: {
      immediate: true,
      handler () {
        if (this.open) {
          this.isOpen = true
        }
      }
    },
    '$menu.collapsed' (collapsed) {
      if (collapsed) {
        this.isOpen = false
      }
    }
  },
  data () {
    return {
      isOpen: false,
      hideSubMenuTimer: null, // 隐藏子菜单时延时
      showSubMenuTimer: null // hover显示子菜单延时
    }
  },
  computed: {
    isVerticalExpanding () {
      const { isVertical, collapsed } = this.$menu
      return isVertical && !collapsed
    },
    innerTrigger () {
      if (this.isVerticalExpanding) {
        return 'click'
      }

      // if not specified in props,
      // use 'hover' for vertical cases
      // and 'click' for horizontal cases
      if (this.trigger == null) {
        const { isVertical } = this.$menu
        return isVertical ? 'hover' : 'click'
      }

      return this.trigger
    }
  },
  methods: {
    toggleSubmenu () {
      if (this.innerTrigger === 'click') {
        this.isOpen = !this.isOpen
      }
    },

    enterSubMenu () {
      if (this.innerTrigger === 'hover') {
        this.enterPopup()
      }
    },

    leaveSubMenu () {
      if (this.innerTrigger === 'hover') {
        this.leavePopup()
      }
    },

    enterPopup () {
      if (this.isVerticalExpanding) {
        return
      }

      clearTimeout(this.showSubMenuTimer)
      clearTimeout(this.hideSubMenuTimer)
      this.showSubMenuTimer = setTimeout(() => {
        this.openSubMenu()
      }, this.delay)
    },

    leavePopup () {
      if (this.isVerticalExpanding) {
        return
      }

      clearTimeout(this.showSubMenuTimer)
      clearTimeout(this.hideSubMenuTimer)
      this.hideSubMenuTimer = setTimeout(() => {
        this.closeSubMenu()
      }, this.delay)
    },

    clickSubMenu () {
      if (this.isVerticalExpanding) {
        return
      }
      this.closeSubMenu()
    },

    openSubMenu () {
      this.isOpen = true
    },

    closeSubMenu () {
      this.isOpen = false
    },

    focusIn () {
      this.openSubMenu()
    },

    focusOut () {
      // do not close submenu if menu is vertical and not collapsed
      if (this.isVerticalExpanding) {
        return
      }

      this.closeSubMenu()
    }
  }
}
</script>
{'fraction_non_alphanumeric': 0.13759065269943593, 'fraction_numerical': 0.001007252215954875, 'mean_word_length': 2.1847338037203334, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 15, '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': '3928839', 'n_tokens_mistral': 1643, 'n_tokens_neox': 1650, 'n_words': 297}