diff --git a/src/_internal/scrollbar/src/Scrollbar.tsx b/src/_internal/scrollbar/src/Scrollbar.tsx index 86e5fa00015..0f327ff9d27 100644 --- a/src/_internal/scrollbar/src/Scrollbar.tsx +++ b/src/_internal/scrollbar/src/Scrollbar.tsx @@ -22,7 +22,7 @@ import { } from 'vue' import { VResizeObserver } from 'vueuc' import { useConfig, useRtl, useTheme, useThemeClass } from '../../../_mixins' -import { rtlInset, useReactivated, Wrapper } from '../../../_utils' +import { clampValue, rtlInset, useReactivated, Wrapper } from '../../../_utils' import { scrollbarLight } from '../styles' import style from './styles/index.cssr' @@ -568,8 +568,7 @@ const Scrollbar = defineComponent({ = (dX * (contentWidth - containerWidth)) / (containerWidth - xBarSize) const toScrollLeftUpperBound = contentWidth - containerWidth let toScrollLeft = memoXLeft + dScrollLeft - toScrollLeft = Math.min(toScrollLeftUpperBound, toScrollLeft) - toScrollLeft = Math.max(toScrollLeft, 0) + toScrollLeft = clampValue(toScrollLeft, 0, toScrollLeftUpperBound) const { value: container } = mergedContainerRef if (container) { container.scrollLeft = toScrollLeft * (rtlEnabledRef?.value ? -1 : 1) @@ -617,8 +616,7 @@ const Scrollbar = defineComponent({ = (dY * (contentHeight - containerHeight)) / (containerHeight - yBarSize) const toScrollTopUpperBound = contentHeight - containerHeight let toScrollTop = memoYTop + dScrollTop - toScrollTop = Math.min(toScrollTopUpperBound, toScrollTop) - toScrollTop = Math.max(toScrollTop, 0) + toScrollTop = clampValue(toScrollTop, 0, toScrollTopUpperBound) const { value: container } = mergedContainerRef if (container) { container.scrollTop = toScrollTop diff --git a/src/_utils/format/index.ts b/src/_utils/format/index.ts new file mode 100644 index 00000000000..c68a157ff2e --- /dev/null +++ b/src/_utils/format/index.ts @@ -0,0 +1,4 @@ +// TODO: remove this after https://github.com/07akioni/seemly/pull/88 merged +export function clampValue(value: number, min: number, max: number): number { + return Math.min(max, Math.max(min, value)) +} diff --git a/src/_utils/index.ts b/src/_utils/index.ts index 5d13813dab8..3e1395d8940 100644 --- a/src/_utils/index.ts +++ b/src/_utils/index.ts @@ -5,6 +5,7 @@ export * from './dom' export { isBrowser } from './env/is-browser' export { isJsdom } from './env/is-jsdom' export { eventEffectNotPerformed, markEventEffectPerformed } from './event' +export { clampValue } from './format' export { getTitleAttribute, isArrayShallowEqual, diff --git a/src/carousel/src/Carousel.tsx b/src/carousel/src/Carousel.tsx index ef578d5f67f..9e954ce3047 100644 --- a/src/carousel/src/Carousel.tsx +++ b/src/carousel/src/Carousel.tsx @@ -41,7 +41,12 @@ import { } from 'vue' import { VResizeObserver } from 'vueuc' import { useConfig, useTheme, useThemeClass } from '../../_mixins' -import { flatten, keep, resolveSlotWithTypedProps } from '../../_utils' +import { + clampValue, + flatten, + keep, + resolveSlotWithTypedProps +} from '../../_utils' import { carouselLight } from '../styles' import NCarouselArrow from './CarouselArrow' import { provideCarouselContext } from './CarouselContext' @@ -51,7 +56,6 @@ import style from './styles/index.cssr' import { addDuplicateSlides, calculateSize, - clampValue, getDisplayIndex, getDisplayTotalView, getNextIndex, diff --git a/src/carousel/src/utils/index.ts b/src/carousel/src/utils/index.ts index 204fd166d61..d7fada52fd5 100644 --- a/src/carousel/src/utils/index.ts +++ b/src/carousel/src/utils/index.ts @@ -19,10 +19,6 @@ export function calculateSize(element: HTMLElement, innerOnly?: boolean): Size { return { width, height } } -export function clampValue(value: number, min: number, max: number): number { - return value < min ? min : value > max ? max : value -} - export function resolveSpeed(value?: string | number): number { if (value === undefined) return 0 diff --git a/src/color-picker/src/ColorInputUnit.tsx b/src/color-picker/src/ColorInputUnit.tsx index 5f17b7dda32..5022e601b75 100644 --- a/src/color-picker/src/ColorInputUnit.tsx +++ b/src/color-picker/src/ColorInputUnit.tsx @@ -1,12 +1,13 @@ import type { PropType } from 'vue' import { defineComponent, h, inject, ref, watchEffect } from 'vue' +import { clampValue } from '../../_utils' import { NInput } from '../../input' import { colorPickerInjectionKey } from './context' // 0 - 255 function normalizeRgbUnit(value: string): number | false { if (/^\d{1,3}\.?\d*$/.test(value.trim())) { - return Math.max(0, Math.min(Number.parseInt(value), 255)) + return clampValue(Number.parseInt(value), 0, 255) } return false } @@ -14,7 +15,7 @@ function normalizeRgbUnit(value: string): number | false { // 0 - 360 function normalizeHueUnit(value: string): number | false { if (/^\d{1,3}\.?\d*$/.test(value.trim())) { - return Math.max(0, Math.min(Number.parseInt(value), 360)) + return clampValue(Number.parseInt(value), 0, 360) } return false } @@ -22,7 +23,7 @@ function normalizeHueUnit(value: string): number | false { // 0 - 100 function normalizeSlvUnit(value: string): number | false { if (/^\d{1,3}\.?\d*$/.test(value.trim())) { - return Math.max(0, Math.min(Number.parseInt(value), 100)) + return clampValue(Number.parseInt(value), 0, 100) } return false } @@ -38,7 +39,7 @@ function normalizeHexaUnit(value: string): boolean { // 0 - 100% function normalizeAlphaUnit(value: string): number | false { if (/^\d{1,3}\.?\d*%$/.test(value.trim())) { - return Math.max(0, Math.min(Number.parseInt(value) / 100, 100)) + return clampValue(Number.parseInt(value) / 100, 0, 100) } return false } diff --git a/src/data-table/src/use-table-data.ts b/src/data-table/src/use-table-data.ts index a377b4fb593..86a3b8d5ff4 100644 --- a/src/data-table/src/use-table-data.ts +++ b/src/data-table/src/use-table-data.ts @@ -16,7 +16,7 @@ import type { import { createTreeMate } from 'treemate' import { useMemo, useMergedState } from 'vooks' import { computed, ref } from 'vue' -import { call, warn } from '../../_utils' +import { call, clampValue, warn } from '../../_utils' import { getDefaultPageSize } from '../../pagination/src/utils' import { useSorter } from './use-sorter' import { createShallowClonedObject } from './utils' @@ -241,12 +241,10 @@ export function useTableData( const page = _mergedCurrentPageRef.value return props.remote ? page - : Math.max( + : clampValue( + Math.ceil(filteredDataRef.value.length / mergedPageSizeRef.value), 1, - Math.min( - Math.ceil(filteredDataRef.value.length / mergedPageSizeRef.value), - page - ) + page ) }) diff --git a/src/pagination/src/Pagination.tsx b/src/pagination/src/Pagination.tsx index d3138a03574..4d9e72806f3 100644 --- a/src/pagination/src/Pagination.tsx +++ b/src/pagination/src/Pagination.tsx @@ -41,6 +41,7 @@ import { useConfig, useLocale, useTheme, useThemeClass } from '../../_mixins' import { useRtl } from '../../_mixins/use-rtl' import { call, + clampValue, createKey, resolveSlot, smallerSize, @@ -384,7 +385,7 @@ export default defineComponent({ const page = Number.parseInt(jumperValueRef.value) if (Number.isNaN(page)) return - doUpdatePage(Math.max(1, Math.min(page, mergedPageCountRef.value))) + doUpdatePage(clampValue(page, 1, mergedPageCountRef.value)) if (!props.simple) { jumperValueRef.value = '' } diff --git a/src/pagination/src/utils.ts b/src/pagination/src/utils.ts index 1735d6f1c58..b2561006618 100644 --- a/src/pagination/src/utils.ts +++ b/src/pagination/src/utils.ts @@ -1,4 +1,5 @@ import type { PaginationProps } from './Pagination' +import { clampValue } from '../../_utils' export function getDefaultPageSize( paginationProps: PaginationProps | false @@ -77,15 +78,9 @@ function createPageItemsInfo( let middleEnd = currentPage const middleDelta = (pageSlot - 5) / 2 middleEnd += Math.ceil(middleDelta) - middleEnd = Math.min( - Math.max(middleEnd, firstPage + pageSlot - 3), - lastPage - 2 - ) + middleEnd = clampValue(middleEnd, firstPage + pageSlot - 3, lastPage - 2) middleStart -= Math.floor(middleDelta) - middleStart = Math.max( - Math.min(middleStart, lastPage - pageSlot + 3), - firstPage + 2 - ) + middleStart = clampValue(middleStart, firstPage + 2, lastPage - pageSlot + 3) let leftSplit = false let rightSplit = false if (middleStart > firstPage + 2) diff --git a/src/slider/src/Slider.tsx b/src/slider/src/Slider.tsx index 01f4ddc023e..c49a691c967 100644 --- a/src/slider/src/Slider.tsx +++ b/src/slider/src/Slider.tsx @@ -26,7 +26,7 @@ import { } from 'vue' import { VBinder, VFollower, VTarget } from 'vueuc' import { useConfig, useFormItem, useTheme, useThemeClass } from '../../_mixins' -import { call, resolveSlot, useAdjustedTo } from '../../_utils' +import { call, clampValue, resolveSlot, useAdjustedTo } from '../../_utils' import { sliderLight } from '../styles' import style from './styles/index.cssr' import { isTouchEvent, useRefs } from './utils' @@ -146,7 +146,7 @@ export default defineComponent({ const arrifiedValueRef = computed(() => { const { value: mergedValue } = mergedValueRef return ((props.range ? mergedValue : [mergedValue]) as number[]).map( - clampValue + v => clampValue(v, props.min, props.max) ) }) const handleCountExceeds2Ref = computed( @@ -353,10 +353,9 @@ export default defineComponent({ const roundValue = getRoundValue(value) closestMark = getClosestMark(value, [...markValues, roundValue]) } - return closestMark ? clampValue(closestMark.value) : currentValue - } - function clampValue(value: number): number { - return Math.min(props.max, Math.max(props.min, value)) + return closestMark + ? clampValue(closestMark.value, props.min, props.max) + : currentValue } function valueToPercentage(value: number): number { const { max, min } = props