* Copyright (c) 2022 - present TinyVue Authors.
* Copyright (c) 2022 - present Huawei Cloud Computing Technologies Co., Ltd.
*
* Use of this source code is governed by an MIT-style license.
*
* THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
* BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
* A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
*
*/
import { REFRESH_INTERVAL } from '@opentiny/utils'
import { on, off } from '@opentiny/utils'
import { PopupManager } from '@opentiny/utils'
import { xss } from '@opentiny/utils'
import type { IFallMenuApi, IFallMenuState, IFallMenuProps, IPagerData } from '@/types'
export const arrowClick = (state: IFallMenuState) => (opt) => {
state.pager += opt
}
export const overContent = (state: IFallMenuState) => (on) => {
state.isActive = on
}
export const clickActive = (state: IFallMenuState) => (index) => {
state.active = index
}
export const mouseover =
({ fall, props, state }: { fall: any; props: IFallMenuProps; state: IFallMenuState }) =>
(index) => {
const popupBox = fall.value
state.activeNode = index
let level2Array = props.data[index].children || []
level2Array.forEach((level2) => {
let level3Array = level2.children || []
level3Array.forEach((level3) => {
level3.url = xss.filterUrl(level3.url)
})
})
state.level2data = level2Array
if (popupBox && state.level2data.length > 0) {
popupBox.style.zIndex = PopupManager.nextZIndex()
state.isActive = true
}
}
export const mouseout = (state: IFallMenuState) => () => {
state.isActive = false
state.activeNode = null
}
export const computePx =
({ props, refs, state }: { props: IFallMenuProps; refs: any; state: IFallMenuState }) =>
() => {
const list = refs.list
const width = list.parentElement.clientWidth
const arr = list.querySelectorAll('li') as NodeListOf<HTMLLIElement>
const set: IPagerData = {
data: [],
offset: [],
index: []
}
const liWidth: number[] = []
let innerwidth = 0
let start = 0
for (let i = 0, len = arr.length; i < len; i++) {
innerwidth += arr[i].clientWidth
liWidth.push(arr[i].clientWidth)
if (innerwidth > width || i === len - 1) {
set.data.push(props.data.slice(start, i) as any)
set.offset.push(`-${arr[start].offsetLeft}px`)
set.index.push(i)
innerwidth = arr[i].clientWidth
start = i
}
}
const pagers = set.index.length
const lastRange = set.data.length === 1 ? liWidth : liWidth.slice(set.index[pagers - 2], set.index[pagers])
if (lastRange.reduce((a, b) => a + b) > width) {
set.data.push(props.data[start])
set.offset.push(`-${arr[start].offsetLeft}px`)
}
set.size = set.data.length
state.pagerData = set
}
export const reRender =
({ api, state, timeout }: { api: IFallMenuApi; state: IFallMenuState; timeout?: NodeJS.Timeout }) =>
() => {
timeout && clearTimeout(timeout)
timeout = setTimeout(() => {
api.computePx()
}, REFRESH_INTERVAL)
state.pager = 1
}
export const mounted =
({ api }) =>
() => {
api.computePx()
on(window, 'resize', api.reRender)
}
export const beforeDestroy = (api) => () => off(window, 'resize', api.reRender)
export const computeLeft =
({ state }) =>
() =>
state.pagerData.offset[state.pager - 1]
export const computeData =
({ props }: { props: IFallMenuProps }) =>
() => {
if (Array.isArray(props.data) && props.data.length) {
props.data.forEach((level1) => {
level1.url = xss.filterUrl(level1.url)
})
}
return props.data
}