element-plus
Version:
A Component Library for Vue 3
1 lines • 13 kB
Source Map (JSON)
{"version":3,"file":"use-carousel.mjs","names":[],"sources":["../../../../../../packages/components/carousel/src/use-carousel.ts"],"sourcesContent":["import {\n computed,\n getCurrentInstance,\n isVNode,\n onBeforeUnmount,\n onMounted,\n provide,\n ref,\n shallowRef,\n unref,\n useSlots,\n watch,\n} from 'vue'\nimport { throttle } from 'lodash-unified'\nimport { useResizeObserver } from '@vueuse/core'\nimport { debugWarn, flattedChildren, isString } from '@element-plus/utils'\nimport { useOrderedChildren } from '@element-plus/hooks'\nimport { CHANGE_EVENT } from '@element-plus/constants'\nimport { CAROUSEL_ITEM_NAME, carouselContextKey } from './constants'\n\nimport type { SetupContext } from 'vue'\nimport type { CarouselItemContext } from './constants'\nimport type { CarouselEmits, CarouselProps } from './carousel'\n\nconst THROTTLE_TIME = 300\n\nexport const useCarousel = (\n props: Required<CarouselProps>,\n emit: SetupContext<CarouselEmits>['emit'],\n componentName: string\n) => {\n const {\n children: items,\n addChild: addItem,\n removeChild: removeItem,\n ChildrenSorter: ItemsSorter,\n } = useOrderedChildren<CarouselItemContext>(\n getCurrentInstance()!,\n CAROUSEL_ITEM_NAME\n )\n\n const slots = useSlots()\n\n // refs\n const activeIndex = ref(-1)\n const timer = ref<ReturnType<typeof setInterval> | null>(null)\n const hover = ref(false)\n const root = ref<HTMLDivElement>()\n const containerHeight = ref<number>(0)\n const isItemsTwoLength = ref(true)\n\n // computed\n const arrowDisplay = computed(\n () => props.arrow !== 'never' && !unref(isVertical)\n )\n\n const hasLabel = computed(() => {\n return items.value.some((item) => item.props.label.toString().length > 0)\n })\n\n const isCardType = computed(() => props.type === 'card')\n const isVertical = computed(() => props.direction === 'vertical')\n\n const containerStyle = computed(() => {\n if (props.height !== 'auto') {\n return {\n height: props.height,\n }\n }\n return {\n height: `${containerHeight.value}px`,\n overflow: 'hidden',\n }\n })\n\n // methods\n const throttledArrowClick = throttle(\n (index: number) => {\n setActiveItem(index)\n },\n THROTTLE_TIME,\n { trailing: true }\n )\n\n const throttledIndicatorHover = throttle((index: number) => {\n handleIndicatorHover(index)\n }, THROTTLE_TIME)\n\n const isTwoLengthShow = (index: number) => {\n if (!isItemsTwoLength.value) return true\n return activeIndex.value <= 1 ? index <= 1 : index > 1\n }\n\n function pauseTimer() {\n if (timer.value) {\n clearInterval(timer.value)\n timer.value = null\n }\n }\n\n function startTimer() {\n if (props.interval <= 0 || !props.autoplay || timer.value) return\n timer.value = setInterval(() => playSlides(), props.interval)\n }\n\n const playSlides = () => {\n if (activeIndex.value < items.value.length - 1) {\n activeIndex.value = activeIndex.value + 1\n } else if (props.loop) {\n activeIndex.value = 0\n }\n }\n\n function setActiveItem(index: number | string) {\n if (isString(index)) {\n const filteredItems = items.value.filter(\n (item) => item.props.name === index\n )\n if (filteredItems.length > 0) {\n index = items.value.indexOf(filteredItems[0])\n }\n }\n index = Number(index)\n if (Number.isNaN(index) || index !== Math.floor(index)) {\n debugWarn(componentName, 'index must be integer.')\n return\n }\n const itemCount = items.value.length\n const oldIndex = activeIndex.value\n if (index < 0) {\n activeIndex.value = props.loop ? itemCount - 1 : 0\n } else if (index >= itemCount) {\n activeIndex.value = props.loop ? 0 : itemCount - 1\n } else {\n activeIndex.value = index\n }\n if (oldIndex === activeIndex.value) {\n resetItemPosition(oldIndex)\n }\n resetTimer()\n }\n\n function resetItemPosition(oldIndex?: number) {\n items.value.forEach((item, index) => {\n item.translateItem(index, activeIndex.value, oldIndex)\n })\n }\n\n function itemInStage(item: CarouselItemContext, index: number) {\n const _items = unref(items)\n const itemCount = _items.length\n if (itemCount === 0 || !item.states.inStage) return false\n const nextItemIndex = index + 1\n const prevItemIndex = index - 1\n const lastItemIndex = itemCount - 1\n const isLastItemActive = _items[lastItemIndex].states.active\n const isFirstItemActive = _items[0].states.active\n const isNextItemActive = _items[nextItemIndex]?.states?.active\n const isPrevItemActive = _items[prevItemIndex]?.states?.active\n\n if ((index === lastItemIndex && isFirstItemActive) || isNextItemActive) {\n return 'left'\n } else if ((index === 0 && isLastItemActive) || isPrevItemActive) {\n return 'right'\n }\n return false\n }\n\n function handleMouseEnter() {\n hover.value = true\n if (props.pauseOnHover) {\n pauseTimer()\n }\n }\n\n function handleMouseLeave() {\n hover.value = false\n startTimer()\n }\n\n function handleButtonEnter(arrow: 'left' | 'right') {\n if (unref(isVertical)) return\n items.value.forEach((item, index) => {\n if (arrow === itemInStage(item, index)) {\n item.states.hover = true\n }\n })\n }\n\n function handleButtonLeave() {\n if (unref(isVertical)) return\n items.value.forEach((item) => {\n item.states.hover = false\n })\n }\n\n function handleIndicatorClick(index: number) {\n activeIndex.value = index\n }\n\n function handleIndicatorHover(index: number) {\n if (props.trigger === 'hover' && index !== activeIndex.value) {\n activeIndex.value = index\n }\n }\n\n function prev() {\n setActiveItem(activeIndex.value - 1)\n }\n\n function next() {\n setActiveItem(activeIndex.value + 1)\n }\n\n function resetTimer() {\n pauseTimer()\n if (!props.pauseOnHover || !hover.value) startTimer()\n }\n\n function setContainerHeight(height: number) {\n if (props.height !== 'auto') return\n containerHeight.value = height\n }\n\n function PlaceholderItem() {\n // fix: https://github.com/element-plus/element-plus/issues/12139\n const defaultSlots = slots.default?.()\n if (!defaultSlots) return null\n\n const flatSlots = flattedChildren(defaultSlots)\n\n const normalizeSlots = flatSlots.filter((slot) => {\n return isVNode(slot) && (slot.type as any).name === CAROUSEL_ITEM_NAME\n })\n\n if (normalizeSlots?.length === 2 && props.loop && !isCardType.value) {\n isItemsTwoLength.value = true\n return normalizeSlots\n }\n isItemsTwoLength.value = false\n return null\n }\n\n // watch\n watch(\n () => activeIndex.value,\n (current, prev) => {\n resetItemPosition(prev)\n if (isItemsTwoLength.value) {\n current = current % 2\n prev = prev % 2\n }\n if (prev > -1) {\n emit(CHANGE_EVENT, current, prev)\n }\n }\n )\n\n const exposeActiveIndex = computed({\n get: () => {\n return isItemsTwoLength.value ? activeIndex.value % 2 : activeIndex.value\n },\n set: (value) => (activeIndex.value = value),\n })\n\n watch(\n () => props.autoplay,\n (autoplay) => {\n autoplay ? startTimer() : pauseTimer()\n }\n )\n watch(\n () => props.loop,\n () => {\n setActiveItem(activeIndex.value)\n }\n )\n\n watch(\n () => props.interval,\n () => {\n resetTimer()\n }\n )\n\n const resizeObserver = shallowRef<ReturnType<typeof useResizeObserver>>()\n // lifecycle\n onMounted(() => {\n watch(\n () => items.value,\n () => {\n if (items.value.length > 0) setActiveItem(props.initialIndex)\n },\n {\n immediate: true,\n }\n )\n\n resizeObserver.value = useResizeObserver(root.value, () => {\n resetItemPosition()\n })\n startTimer()\n })\n\n onBeforeUnmount(() => {\n pauseTimer()\n if (root.value && resizeObserver.value) resizeObserver.value.stop()\n })\n\n // provide\n provide(carouselContextKey, {\n root,\n isCardType,\n isVertical,\n items,\n loop: props.loop,\n cardScale: props.cardScale,\n addItem,\n removeItem,\n setActiveItem,\n setContainerHeight,\n })\n\n return {\n root,\n activeIndex,\n exposeActiveIndex,\n arrowDisplay,\n hasLabel,\n hover,\n isCardType,\n items,\n isVertical,\n containerStyle,\n isItemsTwoLength,\n handleButtonEnter,\n handleButtonLeave,\n handleIndicatorClick,\n handleMouseEnter,\n handleMouseLeave,\n setActiveItem,\n prev,\n next,\n PlaceholderItem,\n isTwoLengthShow,\n ItemsSorter,\n throttledArrowClick,\n throttledIndicatorHover,\n }\n}\n"],"mappings":"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"}