@mantine/hooks 9.2.0 → 9.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cjs/use-click-outside/use-click-outside.cjs.map +1 -1
- package/cjs/use-clipboard/use-clipboard.cjs.map +1 -1
- package/cjs/use-collapse/use-collapse.cjs.map +1 -1
- package/cjs/use-collapse/use-horizontal-collapse.cjs.map +1 -1
- package/cjs/use-color-scheme/use-color-scheme.cjs.map +1 -1
- package/cjs/use-counter/use-counter.cjs.map +1 -1
- package/cjs/use-debounced-callback/use-debounced-callback.cjs.map +1 -1
- package/cjs/use-debounced-state/use-debounced-state.cjs.map +1 -1
- package/cjs/use-debounced-value/use-debounced-value.cjs +3 -0
- package/cjs/use-debounced-value/use-debounced-value.cjs.map +1 -1
- package/cjs/use-did-update/use-did-update.cjs.map +1 -1
- package/cjs/use-disclosure/use-disclosure.cjs.map +1 -1
- package/cjs/use-document-title/use-document-title.cjs.map +1 -1
- package/cjs/use-document-visibility/use-document-visibility.cjs.map +1 -1
- package/cjs/use-drag/use-drag.cjs.map +1 -1
- package/cjs/use-event-listener/use-event-listener.cjs.map +1 -1
- package/cjs/use-eye-dropper/use-eye-dropper.cjs.map +1 -1
- package/cjs/use-favicon/use-favicon.cjs.map +1 -1
- package/cjs/use-fetch/use-fetch.cjs.map +1 -1
- package/cjs/use-file-dialog/use-file-dialog.cjs.map +1 -1
- package/cjs/use-floating-window/use-floating-window.cjs.map +1 -1
- package/cjs/use-focus-return/use-focus-return.cjs.map +1 -1
- package/cjs/use-focus-trap/scope-tab.cjs.map +1 -1
- package/cjs/use-focus-trap/tabbable.cjs.map +1 -1
- package/cjs/use-focus-trap/use-focus-trap.cjs.map +1 -1
- package/cjs/use-focus-within/use-focus-within.cjs.map +1 -1
- package/cjs/use-force-update/use-force-update.cjs.map +1 -1
- package/cjs/use-fullscreen/use-fullscreen.cjs.map +1 -1
- package/cjs/use-hash/use-hash.cjs.map +1 -1
- package/cjs/use-headroom/use-headroom.cjs.map +1 -1
- package/cjs/use-hotkeys/parse-hotkey.cjs.map +1 -1
- package/cjs/use-hotkeys/use-hotkeys.cjs.map +1 -1
- package/cjs/use-hover/use-hover.cjs.map +1 -1
- package/cjs/use-id/use-id.cjs.map +1 -1
- package/cjs/use-idle/use-idle.cjs.map +1 -1
- package/cjs/use-in-viewport/use-in-viewport.cjs.map +1 -1
- package/cjs/use-input-state/use-input-state.cjs.map +1 -1
- package/cjs/use-intersection/use-intersection.cjs.map +1 -1
- package/cjs/use-interval/use-interval.cjs.map +1 -1
- package/cjs/use-is-first-render/use-is-first-render.cjs.map +1 -1
- package/cjs/use-list-state/use-list-state.cjs.map +1 -1
- package/cjs/use-local-storage/create-storage.cjs.map +1 -1
- package/cjs/use-local-storage/use-local-storage.cjs.map +1 -1
- package/cjs/use-logger/use-logger.cjs.map +1 -1
- package/cjs/use-long-press/use-long-press.cjs.map +1 -1
- package/cjs/use-map/use-map.cjs.map +1 -1
- package/cjs/use-mask/use-mask.cjs.map +1 -1
- package/cjs/use-media-query/use-media-query.cjs.map +1 -1
- package/cjs/use-merged-ref/use-merged-ref.cjs.map +1 -1
- package/cjs/use-mounted/use-mounted.cjs.map +1 -1
- package/cjs/use-mouse/use-mouse.cjs.map +1 -1
- package/cjs/use-move/use-move.cjs.map +1 -1
- package/cjs/use-mutation-observer/use-mutation-observer.cjs.map +1 -1
- package/cjs/use-network/use-network.cjs.map +1 -1
- package/cjs/use-orientation/use-orientation.cjs.map +1 -1
- package/cjs/use-os/use-os.cjs.map +1 -1
- package/cjs/use-page-leave/use-page-leave.cjs.map +1 -1
- package/cjs/use-pagination/use-pagination.cjs.map +1 -1
- package/cjs/use-previous/use-previous.cjs.map +1 -1
- package/cjs/use-queue/use-queue.cjs.map +1 -1
- package/cjs/use-radial-move/use-radial-move.cjs.map +1 -1
- package/cjs/use-reduced-motion/use-reduced-motion.cjs.map +1 -1
- package/cjs/use-resize-observer/use-resize-observer.cjs.map +1 -1
- package/cjs/use-roving-index/use-roving-index.cjs.map +1 -1
- package/cjs/use-scroll-direction/use-scroll-direction.cjs.map +1 -1
- package/cjs/use-scroll-into-view/use-scroll-into-view.cjs.map +1 -1
- package/cjs/use-scroll-spy/use-scroll-spy.cjs.map +1 -1
- package/cjs/use-scroller/use-scroller.cjs.map +1 -1
- package/cjs/use-selection/use-selection.cjs.map +1 -1
- package/cjs/use-session-storage/use-session-storage.cjs.map +1 -1
- package/cjs/use-set/use-set.cjs.map +1 -1
- package/cjs/use-set-state/use-set-state.cjs.map +1 -1
- package/cjs/use-shallow-effect/use-shallow-effect.cjs.map +1 -1
- package/cjs/use-state-history/use-state-history.cjs.map +1 -1
- package/cjs/use-text-selection/use-text-selection.cjs.map +1 -1
- package/cjs/use-throttled-callback/use-throttled-callback.cjs.map +1 -1
- package/cjs/use-throttled-state/use-throttled-state.cjs.map +1 -1
- package/cjs/use-throttled-value/use-throttled-value.cjs.map +1 -1
- package/cjs/use-timeout/use-timeout.cjs.map +1 -1
- package/cjs/use-toggle/use-toggle.cjs.map +1 -1
- package/cjs/use-uncontrolled/use-uncontrolled.cjs.map +1 -1
- package/cjs/use-validated-state/use-validated-state.cjs.map +1 -1
- package/cjs/use-viewport-size/use-viewport-size.cjs.map +1 -1
- package/cjs/use-window-event/use-window-event.cjs.map +1 -1
- package/cjs/use-window-scroll/use-window-scroll.cjs.map +1 -1
- package/cjs/utils/clamp/clamp.cjs.map +1 -1
- package/cjs/utils/lower-first/lower-first.cjs.map +1 -1
- package/cjs/utils/random-id/random-id.cjs.map +1 -1
- package/cjs/utils/range/range.cjs.map +1 -1
- package/cjs/utils/shallow-equal/shallow-equal.cjs.map +1 -1
- package/cjs/utils/upper-first/upper-first.cjs.map +1 -1
- package/cjs/utils/use-callback-ref/use-callback-ref.cjs.map +1 -1
- package/esm/use-click-outside/use-click-outside.mjs.map +1 -1
- package/esm/use-clipboard/use-clipboard.mjs.map +1 -1
- package/esm/use-collapse/use-collapse.mjs.map +1 -1
- package/esm/use-collapse/use-horizontal-collapse.mjs.map +1 -1
- package/esm/use-color-scheme/use-color-scheme.mjs.map +1 -1
- package/esm/use-counter/use-counter.mjs.map +1 -1
- package/esm/use-debounced-callback/use-debounced-callback.mjs.map +1 -1
- package/esm/use-debounced-state/use-debounced-state.mjs.map +1 -1
- package/esm/use-debounced-value/use-debounced-value.mjs +3 -0
- package/esm/use-debounced-value/use-debounced-value.mjs.map +1 -1
- package/esm/use-did-update/use-did-update.mjs.map +1 -1
- package/esm/use-disclosure/use-disclosure.mjs.map +1 -1
- package/esm/use-document-title/use-document-title.mjs.map +1 -1
- package/esm/use-document-visibility/use-document-visibility.mjs.map +1 -1
- package/esm/use-drag/use-drag.mjs.map +1 -1
- package/esm/use-event-listener/use-event-listener.mjs.map +1 -1
- package/esm/use-eye-dropper/use-eye-dropper.mjs.map +1 -1
- package/esm/use-favicon/use-favicon.mjs.map +1 -1
- package/esm/use-fetch/use-fetch.mjs.map +1 -1
- package/esm/use-file-dialog/use-file-dialog.mjs.map +1 -1
- package/esm/use-floating-window/use-floating-window.mjs.map +1 -1
- package/esm/use-focus-return/use-focus-return.mjs.map +1 -1
- package/esm/use-focus-trap/scope-tab.mjs.map +1 -1
- package/esm/use-focus-trap/tabbable.mjs.map +1 -1
- package/esm/use-focus-trap/use-focus-trap.mjs.map +1 -1
- package/esm/use-focus-within/use-focus-within.mjs.map +1 -1
- package/esm/use-force-update/use-force-update.mjs.map +1 -1
- package/esm/use-fullscreen/use-fullscreen.mjs.map +1 -1
- package/esm/use-hash/use-hash.mjs.map +1 -1
- package/esm/use-headroom/use-headroom.mjs.map +1 -1
- package/esm/use-hotkeys/parse-hotkey.mjs.map +1 -1
- package/esm/use-hotkeys/use-hotkeys.mjs.map +1 -1
- package/esm/use-hover/use-hover.mjs.map +1 -1
- package/esm/use-id/use-id.mjs.map +1 -1
- package/esm/use-idle/use-idle.mjs.map +1 -1
- package/esm/use-in-viewport/use-in-viewport.mjs.map +1 -1
- package/esm/use-input-state/use-input-state.mjs.map +1 -1
- package/esm/use-intersection/use-intersection.mjs.map +1 -1
- package/esm/use-interval/use-interval.mjs.map +1 -1
- package/esm/use-is-first-render/use-is-first-render.mjs.map +1 -1
- package/esm/use-list-state/use-list-state.mjs.map +1 -1
- package/esm/use-local-storage/create-storage.mjs.map +1 -1
- package/esm/use-local-storage/use-local-storage.mjs.map +1 -1
- package/esm/use-logger/use-logger.mjs.map +1 -1
- package/esm/use-long-press/use-long-press.mjs.map +1 -1
- package/esm/use-map/use-map.mjs.map +1 -1
- package/esm/use-mask/use-mask.mjs.map +1 -1
- package/esm/use-media-query/use-media-query.mjs.map +1 -1
- package/esm/use-merged-ref/use-merged-ref.mjs.map +1 -1
- package/esm/use-mounted/use-mounted.mjs.map +1 -1
- package/esm/use-mouse/use-mouse.mjs.map +1 -1
- package/esm/use-move/use-move.mjs.map +1 -1
- package/esm/use-mutation-observer/use-mutation-observer.mjs.map +1 -1
- package/esm/use-network/use-network.mjs.map +1 -1
- package/esm/use-orientation/use-orientation.mjs.map +1 -1
- package/esm/use-os/use-os.mjs.map +1 -1
- package/esm/use-page-leave/use-page-leave.mjs.map +1 -1
- package/esm/use-pagination/use-pagination.mjs.map +1 -1
- package/esm/use-previous/use-previous.mjs.map +1 -1
- package/esm/use-queue/use-queue.mjs.map +1 -1
- package/esm/use-radial-move/use-radial-move.mjs.map +1 -1
- package/esm/use-reduced-motion/use-reduced-motion.mjs.map +1 -1
- package/esm/use-resize-observer/use-resize-observer.mjs.map +1 -1
- package/esm/use-roving-index/use-roving-index.mjs.map +1 -1
- package/esm/use-scroll-direction/use-scroll-direction.mjs.map +1 -1
- package/esm/use-scroll-into-view/use-scroll-into-view.mjs.map +1 -1
- package/esm/use-scroll-spy/use-scroll-spy.mjs.map +1 -1
- package/esm/use-scroller/use-scroller.mjs.map +1 -1
- package/esm/use-selection/use-selection.mjs.map +1 -1
- package/esm/use-session-storage/use-session-storage.mjs.map +1 -1
- package/esm/use-set/use-set.mjs.map +1 -1
- package/esm/use-set-state/use-set-state.mjs.map +1 -1
- package/esm/use-shallow-effect/use-shallow-effect.mjs.map +1 -1
- package/esm/use-state-history/use-state-history.mjs.map +1 -1
- package/esm/use-text-selection/use-text-selection.mjs.map +1 -1
- package/esm/use-throttled-callback/use-throttled-callback.mjs.map +1 -1
- package/esm/use-throttled-state/use-throttled-state.mjs.map +1 -1
- package/esm/use-throttled-value/use-throttled-value.mjs.map +1 -1
- package/esm/use-timeout/use-timeout.mjs.map +1 -1
- package/esm/use-toggle/use-toggle.mjs.map +1 -1
- package/esm/use-uncontrolled/use-uncontrolled.mjs.map +1 -1
- package/esm/use-validated-state/use-validated-state.mjs.map +1 -1
- package/esm/use-viewport-size/use-viewport-size.mjs.map +1 -1
- package/esm/use-window-event/use-window-event.mjs.map +1 -1
- package/esm/use-window-scroll/use-window-scroll.mjs.map +1 -1
- package/esm/utils/clamp/clamp.mjs.map +1 -1
- package/esm/utils/lower-first/lower-first.mjs.map +1 -1
- package/esm/utils/random-id/random-id.mjs.map +1 -1
- package/esm/utils/range/range.mjs.map +1 -1
- package/esm/utils/shallow-equal/shallow-equal.mjs.map +1 -1
- package/esm/utils/upper-first/upper-first.mjs.map +1 -1
- package/esm/utils/use-callback-ref/use-callback-ref.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-roving-index.mjs","names":[],"sources":["../../src/use-roving-index/use-roving-index.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nimport { useUncontrolled } from '../use-uncontrolled/use-uncontrolled';\n\nexport interface UseRovingIndexInput {\n /** Total number of items in the group */\n total: number;\n\n /** Which arrow keys navigate, `'horizontal'` by default */\n orientation?: 'horizontal' | 'vertical' | 'both';\n\n /** Whether navigation wraps at boundaries, `true` by default */\n loop?: boolean;\n\n /** Text direction, `'ltr'` by default */\n dir?: 'rtl' | 'ltr';\n\n /** Whether to click element when it receives focus via keyboard, `false` by default */\n activateOnFocus?: boolean;\n\n /** Number of columns for grid (2D) navigation. When set, enables grid mode */\n columns?: number;\n\n /** Controlled focused index */\n focusedIndex?: number;\n\n /** Initial focused index for uncontrolled mode, first non-disabled item by default */\n initialIndex?: number;\n\n /** Called when focused index changes */\n onFocusChange?: (index: number) => void;\n\n /** Function to check if item at given index is disabled, `() => false` by default */\n isItemDisabled?: (index: number) => boolean;\n}\n\nexport interface UseRovingIndexGetItemPropsInput {\n /** Index of the item in the group */\n index: number;\n\n /** Called when item is clicked */\n onClick?: React.MouseEventHandler;\n\n /** Called when keydown event fires on item */\n onKeyDown?: React.KeyboardEventHandler;\n}\n\nexport interface UseRovingIndexReturnValue {\n /** Get props to spread on each navigable item */\n getItemProps: (options: UseRovingIndexGetItemPropsInput) => {\n tabIndex: 0 | -1;\n onKeyDown: React.KeyboardEventHandler;\n onClick: React.MouseEventHandler;\n ref: React.RefCallback<HTMLElement>;\n };\n\n /** Currently focused index */\n focusedIndex: number;\n\n /** Programmatically set focused index */\n setFocusedIndex: (index: number) => void;\n}\n\nfunction findNextEnabled(\n current: number,\n total: number,\n isItemDisabled: (index: number) => boolean,\n loop: boolean\n): number {\n for (let i = current + 1; i < total; i += 1) {\n if (!isItemDisabled(i)) {\n return i;\n }\n }\n\n if (loop) {\n for (let i = 0; i < current; i += 1) {\n if (!isItemDisabled(i)) {\n return i;\n }\n }\n }\n\n return current;\n}\n\nfunction findPreviousEnabled(\n current: number,\n total: number,\n isItemDisabled: (index: number) => boolean,\n loop: boolean\n): number {\n for (let i = current - 1; i >= 0; i -= 1) {\n if (!isItemDisabled(i)) {\n return i;\n }\n }\n\n if (loop) {\n for (let i = total - 1; i > current; i -= 1) {\n if (!isItemDisabled(i)) {\n return i;\n }\n }\n }\n\n return current;\n}\n\nfunction findFirstEnabled(total: number, isItemDisabled: (index: number) => boolean): number {\n for (let i = 0; i < total; i += 1) {\n if (!isItemDisabled(i)) {\n return i;\n }\n }\n\n return 0;\n}\n\nfunction findLastEnabled(total: number, isItemDisabled: (index: number) => boolean): number {\n for (let i = total - 1; i >= 0; i -= 1) {\n if (!isItemDisabled(i)) {\n return i;\n }\n }\n\n return 0;\n}\n\nconst defaultIsItemDisabled = () => false;\n\nexport function useRovingIndex(input: UseRovingIndexInput): UseRovingIndexReturnValue {\n const {\n total,\n orientation = 'horizontal',\n loop = true,\n dir = 'ltr',\n activateOnFocus = false,\n columns,\n focusedIndex,\n initialIndex,\n onFocusChange,\n isItemDisabled = defaultIsItemDisabled,\n } = input;\n\n const itemRefs = useRef<Map<number, HTMLElement>>(new Map());\n const isGrid = typeof columns === 'number' && columns > 0;\n\n const resolvedInitialIndex =\n initialIndex !== undefined ? initialIndex : findFirstEnabled(total, isItemDisabled);\n\n const [activeIndex, setActiveIndex] = useUncontrolled({\n value: focusedIndex,\n defaultValue: resolvedInitialIndex,\n finalValue: 0,\n onChange: onFocusChange,\n });\n\n useEffect(() => {\n if (total === 0) {\n return;\n }\n\n if (activeIndex >= total) {\n setActiveIndex(findLastEnabled(total, isItemDisabled));\n } else if (isItemDisabled(activeIndex)) {\n setActiveIndex(findFirstEnabled(total, isItemDisabled));\n }\n }, [total, activeIndex, isItemDisabled]);\n\n const focusItem = useCallback(\n (index: number) => {\n setActiveIndex(index);\n const element = itemRefs.current.get(index);\n if (element) {\n element.focus();\n if (activateOnFocus) {\n element.click();\n }\n }\n },\n [activateOnFocus, setActiveIndex]\n );\n\n const handleGridKeyDown = useCallback(\n (event: React.KeyboardEvent, currentIndex: number) => {\n const row = Math.floor(currentIndex / columns!);\n const col = currentIndex % columns!;\n const totalRows = Math.ceil(total / columns!);\n let nextIndex: number | null = null;\n\n const isRtl = dir === 'rtl';\n\n switch (event.key) {\n case 'ArrowRight': {\n const targetCol = isRtl ? col - 1 : col + 1;\n if (targetCol >= 0 && targetCol < columns! && row * columns! + targetCol < total) {\n const candidate = row * columns! + targetCol;\n if (!isItemDisabled(candidate)) {\n nextIndex = candidate;\n }\n }\n break;\n }\n\n case 'ArrowLeft': {\n const targetCol = isRtl ? col + 1 : col - 1;\n if (targetCol >= 0 && targetCol < columns! && row * columns! + targetCol < total) {\n const candidate = row * columns! + targetCol;\n if (!isItemDisabled(candidate)) {\n nextIndex = candidate;\n }\n }\n break;\n }\n\n case 'ArrowDown': {\n for (let r = row + 1; r < totalRows; r += 1) {\n const candidate = r * columns! + col;\n if (candidate < total && !isItemDisabled(candidate)) {\n nextIndex = candidate;\n break;\n }\n }\n break;\n }\n\n case 'ArrowUp': {\n for (let r = row - 1; r >= 0; r -= 1) {\n const candidate = r * columns! + col;\n if (candidate < total && !isItemDisabled(candidate)) {\n nextIndex = candidate;\n break;\n }\n }\n break;\n }\n\n case 'Home': {\n if (event.ctrlKey) {\n nextIndex = findFirstEnabled(total, isItemDisabled);\n } else {\n const rowStart = row * columns!;\n for (let i = rowStart; i < rowStart + columns! && i < total; i += 1) {\n if (!isItemDisabled(i)) {\n nextIndex = i;\n break;\n }\n }\n }\n break;\n }\n\n case 'End': {\n if (event.ctrlKey) {\n nextIndex = findLastEnabled(total, isItemDisabled);\n } else {\n const rowStart = row * columns!;\n const rowEnd = Math.min(rowStart + columns!, total) - 1;\n for (let i = rowEnd; i >= rowStart; i -= 1) {\n if (!isItemDisabled(i)) {\n nextIndex = i;\n break;\n }\n }\n }\n break;\n }\n }\n\n if (nextIndex !== null && nextIndex !== currentIndex) {\n event.preventDefault();\n event.stopPropagation();\n focusItem(nextIndex);\n }\n },\n [total, columns, dir, isItemDisabled, focusItem]\n );\n\n const handleListKeyDown = useCallback(\n (event: React.KeyboardEvent, currentIndex: number) => {\n const isRtl = dir === 'rtl';\n let nextIndex: number | null = null;\n\n switch (event.key) {\n case 'ArrowRight': {\n if (orientation === 'horizontal' || orientation === 'both') {\n nextIndex = isRtl\n ? findPreviousEnabled(currentIndex, total, isItemDisabled, loop)\n : findNextEnabled(currentIndex, total, isItemDisabled, loop);\n }\n break;\n }\n\n case 'ArrowLeft': {\n if (orientation === 'horizontal' || orientation === 'both') {\n nextIndex = isRtl\n ? findNextEnabled(currentIndex, total, isItemDisabled, loop)\n : findPreviousEnabled(currentIndex, total, isItemDisabled, loop);\n }\n break;\n }\n\n case 'ArrowDown': {\n if (orientation === 'vertical' || orientation === 'both') {\n nextIndex = findNextEnabled(currentIndex, total, isItemDisabled, loop);\n }\n break;\n }\n\n case 'ArrowUp': {\n if (orientation === 'vertical' || orientation === 'both') {\n nextIndex = findPreviousEnabled(currentIndex, total, isItemDisabled, loop);\n }\n break;\n }\n\n case 'Home': {\n nextIndex = findFirstEnabled(total, isItemDisabled);\n break;\n }\n\n case 'End': {\n nextIndex = findLastEnabled(total, isItemDisabled);\n break;\n }\n }\n\n if (nextIndex !== null && nextIndex !== currentIndex) {\n event.preventDefault();\n event.stopPropagation();\n focusItem(nextIndex);\n }\n },\n [total, orientation, loop, dir, isItemDisabled, focusItem]\n );\n\n const getItemProps = useCallback(\n (options: UseRovingIndexGetItemPropsInput) => {\n const { index, onClick, onKeyDown } = options;\n\n return {\n tabIndex: (index === activeIndex ? 0 : -1) as 0 | -1,\n\n ref: (node: HTMLElement | null) => {\n if (node) {\n itemRefs.current.set(index, node);\n } else {\n itemRefs.current.delete(index);\n }\n },\n\n onKeyDown: (event: React.KeyboardEvent) => {\n onKeyDown?.(event);\n\n if (event.defaultPrevented) {\n return;\n }\n\n if (isGrid) {\n handleGridKeyDown(event, index);\n } else {\n handleListKeyDown(event, index);\n }\n },\n\n onClick: (event: React.MouseEvent) => {\n onClick?.(event);\n setActiveIndex(index);\n },\n };\n },\n [activeIndex, isGrid, handleGridKeyDown, handleListKeyDown, setActiveIndex]\n );\n\n return {\n getItemProps,\n focusedIndex: activeIndex,\n setFocusedIndex: setActiveIndex,\n };\n}\n\nexport namespace useRovingIndex {\n export type Input = UseRovingIndexInput;\n export type GetItemPropsInput = UseRovingIndexGetItemPropsInput;\n export type ReturnValue = UseRovingIndexReturnValue;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-roving-index.mjs","names":[],"sources":["../../src/use-roving-index/use-roving-index.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nimport { useUncontrolled } from '../use-uncontrolled/use-uncontrolled';\n\nexport interface UseRovingIndexInput {\n /** Total number of items in the group */\n total: number;\n\n /** Which arrow keys navigate, `'horizontal'` by default */\n orientation?: 'horizontal' | 'vertical' | 'both';\n\n /** Whether navigation wraps at boundaries, `true` by default */\n loop?: boolean;\n\n /** Text direction, `'ltr'` by default */\n dir?: 'rtl' | 'ltr';\n\n /** Whether to click element when it receives focus via keyboard, `false` by default */\n activateOnFocus?: boolean;\n\n /** Number of columns for grid (2D) navigation. When set, enables grid mode */\n columns?: number;\n\n /** Controlled focused index */\n focusedIndex?: number;\n\n /** Initial focused index for uncontrolled mode, first non-disabled item by default */\n initialIndex?: number;\n\n /** Called when focused index changes */\n onFocusChange?: (index: number) => void;\n\n /** Function to check if item at given index is disabled, `() => false` by default */\n isItemDisabled?: (index: number) => boolean;\n}\n\nexport interface UseRovingIndexGetItemPropsInput {\n /** Index of the item in the group */\n index: number;\n\n /** Called when item is clicked */\n onClick?: React.MouseEventHandler;\n\n /** Called when keydown event fires on item */\n onKeyDown?: React.KeyboardEventHandler;\n}\n\nexport interface UseRovingIndexReturnValue {\n /** Get props to spread on each navigable item */\n getItemProps: (options: UseRovingIndexGetItemPropsInput) => {\n tabIndex: 0 | -1;\n onKeyDown: React.KeyboardEventHandler;\n onClick: React.MouseEventHandler;\n ref: React.RefCallback<HTMLElement>;\n };\n\n /** Currently focused index */\n focusedIndex: number;\n\n /** Programmatically set focused index */\n setFocusedIndex: (index: number) => void;\n}\n\nfunction findNextEnabled(\n current: number,\n total: number,\n isItemDisabled: (index: number) => boolean,\n loop: boolean\n): number {\n for (let i = current + 1; i < total; i += 1) {\n if (!isItemDisabled(i)) {\n return i;\n }\n }\n\n if (loop) {\n for (let i = 0; i < current; i += 1) {\n if (!isItemDisabled(i)) {\n return i;\n }\n }\n }\n\n return current;\n}\n\nfunction findPreviousEnabled(\n current: number,\n total: number,\n isItemDisabled: (index: number) => boolean,\n loop: boolean\n): number {\n for (let i = current - 1; i >= 0; i -= 1) {\n if (!isItemDisabled(i)) {\n return i;\n }\n }\n\n if (loop) {\n for (let i = total - 1; i > current; i -= 1) {\n if (!isItemDisabled(i)) {\n return i;\n }\n }\n }\n\n return current;\n}\n\nfunction findFirstEnabled(total: number, isItemDisabled: (index: number) => boolean): number {\n for (let i = 0; i < total; i += 1) {\n if (!isItemDisabled(i)) {\n return i;\n }\n }\n\n return 0;\n}\n\nfunction findLastEnabled(total: number, isItemDisabled: (index: number) => boolean): number {\n for (let i = total - 1; i >= 0; i -= 1) {\n if (!isItemDisabled(i)) {\n return i;\n }\n }\n\n return 0;\n}\n\nconst defaultIsItemDisabled = () => false;\n\nexport function useRovingIndex(input: UseRovingIndexInput): UseRovingIndexReturnValue {\n const {\n total,\n orientation = 'horizontal',\n loop = true,\n dir = 'ltr',\n activateOnFocus = false,\n columns,\n focusedIndex,\n initialIndex,\n onFocusChange,\n isItemDisabled = defaultIsItemDisabled,\n } = input;\n\n const itemRefs = useRef<Map<number, HTMLElement>>(new Map());\n const isGrid = typeof columns === 'number' && columns > 0;\n\n const resolvedInitialIndex =\n initialIndex !== undefined ? initialIndex : findFirstEnabled(total, isItemDisabled);\n\n const [activeIndex, setActiveIndex] = useUncontrolled({\n value: focusedIndex,\n defaultValue: resolvedInitialIndex,\n finalValue: 0,\n onChange: onFocusChange,\n });\n\n useEffect(() => {\n if (total === 0) {\n return;\n }\n\n if (activeIndex >= total) {\n setActiveIndex(findLastEnabled(total, isItemDisabled));\n } else if (isItemDisabled(activeIndex)) {\n setActiveIndex(findFirstEnabled(total, isItemDisabled));\n }\n }, [total, activeIndex, isItemDisabled]);\n\n const focusItem = useCallback(\n (index: number) => {\n setActiveIndex(index);\n const element = itemRefs.current.get(index);\n if (element) {\n element.focus();\n if (activateOnFocus) {\n element.click();\n }\n }\n },\n [activateOnFocus, setActiveIndex]\n );\n\n const handleGridKeyDown = useCallback(\n (event: React.KeyboardEvent, currentIndex: number) => {\n const row = Math.floor(currentIndex / columns!);\n const col = currentIndex % columns!;\n const totalRows = Math.ceil(total / columns!);\n let nextIndex: number | null = null;\n\n const isRtl = dir === 'rtl';\n\n switch (event.key) {\n case 'ArrowRight': {\n const targetCol = isRtl ? col - 1 : col + 1;\n if (targetCol >= 0 && targetCol < columns! && row * columns! + targetCol < total) {\n const candidate = row * columns! + targetCol;\n if (!isItemDisabled(candidate)) {\n nextIndex = candidate;\n }\n }\n break;\n }\n\n case 'ArrowLeft': {\n const targetCol = isRtl ? col + 1 : col - 1;\n if (targetCol >= 0 && targetCol < columns! && row * columns! + targetCol < total) {\n const candidate = row * columns! + targetCol;\n if (!isItemDisabled(candidate)) {\n nextIndex = candidate;\n }\n }\n break;\n }\n\n case 'ArrowDown': {\n for (let r = row + 1; r < totalRows; r += 1) {\n const candidate = r * columns! + col;\n if (candidate < total && !isItemDisabled(candidate)) {\n nextIndex = candidate;\n break;\n }\n }\n break;\n }\n\n case 'ArrowUp': {\n for (let r = row - 1; r >= 0; r -= 1) {\n const candidate = r * columns! + col;\n if (candidate < total && !isItemDisabled(candidate)) {\n nextIndex = candidate;\n break;\n }\n }\n break;\n }\n\n case 'Home': {\n if (event.ctrlKey) {\n nextIndex = findFirstEnabled(total, isItemDisabled);\n } else {\n const rowStart = row * columns!;\n for (let i = rowStart; i < rowStart + columns! && i < total; i += 1) {\n if (!isItemDisabled(i)) {\n nextIndex = i;\n break;\n }\n }\n }\n break;\n }\n\n case 'End': {\n if (event.ctrlKey) {\n nextIndex = findLastEnabled(total, isItemDisabled);\n } else {\n const rowStart = row * columns!;\n const rowEnd = Math.min(rowStart + columns!, total) - 1;\n for (let i = rowEnd; i >= rowStart; i -= 1) {\n if (!isItemDisabled(i)) {\n nextIndex = i;\n break;\n }\n }\n }\n break;\n }\n }\n\n if (nextIndex !== null && nextIndex !== currentIndex) {\n event.preventDefault();\n event.stopPropagation();\n focusItem(nextIndex);\n }\n },\n [total, columns, dir, isItemDisabled, focusItem]\n );\n\n const handleListKeyDown = useCallback(\n (event: React.KeyboardEvent, currentIndex: number) => {\n const isRtl = dir === 'rtl';\n let nextIndex: number | null = null;\n\n switch (event.key) {\n case 'ArrowRight': {\n if (orientation === 'horizontal' || orientation === 'both') {\n nextIndex = isRtl\n ? findPreviousEnabled(currentIndex, total, isItemDisabled, loop)\n : findNextEnabled(currentIndex, total, isItemDisabled, loop);\n }\n break;\n }\n\n case 'ArrowLeft': {\n if (orientation === 'horizontal' || orientation === 'both') {\n nextIndex = isRtl\n ? findNextEnabled(currentIndex, total, isItemDisabled, loop)\n : findPreviousEnabled(currentIndex, total, isItemDisabled, loop);\n }\n break;\n }\n\n case 'ArrowDown': {\n if (orientation === 'vertical' || orientation === 'both') {\n nextIndex = findNextEnabled(currentIndex, total, isItemDisabled, loop);\n }\n break;\n }\n\n case 'ArrowUp': {\n if (orientation === 'vertical' || orientation === 'both') {\n nextIndex = findPreviousEnabled(currentIndex, total, isItemDisabled, loop);\n }\n break;\n }\n\n case 'Home': {\n nextIndex = findFirstEnabled(total, isItemDisabled);\n break;\n }\n\n case 'End': {\n nextIndex = findLastEnabled(total, isItemDisabled);\n break;\n }\n }\n\n if (nextIndex !== null && nextIndex !== currentIndex) {\n event.preventDefault();\n event.stopPropagation();\n focusItem(nextIndex);\n }\n },\n [total, orientation, loop, dir, isItemDisabled, focusItem]\n );\n\n const getItemProps = useCallback(\n (options: UseRovingIndexGetItemPropsInput) => {\n const { index, onClick, onKeyDown } = options;\n\n return {\n tabIndex: (index === activeIndex ? 0 : -1) as 0 | -1,\n\n ref: (node: HTMLElement | null) => {\n if (node) {\n itemRefs.current.set(index, node);\n } else {\n itemRefs.current.delete(index);\n }\n },\n\n onKeyDown: (event: React.KeyboardEvent) => {\n onKeyDown?.(event);\n\n if (event.defaultPrevented) {\n return;\n }\n\n if (isGrid) {\n handleGridKeyDown(event, index);\n } else {\n handleListKeyDown(event, index);\n }\n },\n\n onClick: (event: React.MouseEvent) => {\n onClick?.(event);\n setActiveIndex(index);\n },\n };\n },\n [activeIndex, isGrid, handleGridKeyDown, handleListKeyDown, setActiveIndex]\n );\n\n return {\n getItemProps,\n focusedIndex: activeIndex,\n setFocusedIndex: setActiveIndex,\n };\n}\n\nexport namespace useRovingIndex {\n export type Input = UseRovingIndexInput;\n export type GetItemPropsInput = UseRovingIndexGetItemPropsInput;\n export type ReturnValue = UseRovingIndexReturnValue;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-scroll-direction.mjs","names":[],"sources":["../../src/use-scroll-direction/use-scroll-direction.ts"],"sourcesContent":["import { useEffect, useEffectEvent, useRef, useState } from 'react';\n\nexport type ScrollDirection = 'up' | 'down' | 'unknown';\n\nexport function useScrollDirection(): ScrollDirection {\n const lastScrollTopRef = useRef(0);\n const [scrollDirection, setScrollDirection] = useState<ScrollDirection>('unknown');\n const isResizingRef = useRef(false);\n const resizeTimerRef = useRef<number | undefined>(undefined);\n\n const handleScroll = useEffectEvent(() => {\n if (isResizingRef.current) {\n return;\n }\n\n const currentScrollTop = window.scrollY || document.documentElement.scrollTop;\n setScrollDirection(currentScrollTop < lastScrollTopRef.current ? 'up' : 'down');\n lastScrollTopRef.current = currentScrollTop;\n });\n\n useEffect(() => {\n const handleResize = () => {\n isResizingRef.current = true;\n window.clearTimeout(resizeTimerRef.current);\n resizeTimerRef.current = window.setTimeout(() => {\n isResizingRef.current = false;\n }, 300);\n };\n\n window.addEventListener('scroll', handleScroll);\n window.addEventListener('resize', handleResize);\n\n return () => {\n window.removeEventListener('scroll', handleScroll);\n window.removeEventListener('resize', handleResize);\n clearTimeout(resizeTimerRef.current);\n };\n }, []);\n\n return scrollDirection;\n}\n"],"mappings":";;;AAIA,SAAgB,qBAAsC;CACpD,MAAM,mBAAmB,OAAO,
|
|
1
|
+
{"version":3,"file":"use-scroll-direction.mjs","names":[],"sources":["../../src/use-scroll-direction/use-scroll-direction.ts"],"sourcesContent":["import { useEffect, useEffectEvent, useRef, useState } from 'react';\n\nexport type ScrollDirection = 'up' | 'down' | 'unknown';\n\nexport function useScrollDirection(): ScrollDirection {\n const lastScrollTopRef = useRef(0);\n const [scrollDirection, setScrollDirection] = useState<ScrollDirection>('unknown');\n const isResizingRef = useRef(false);\n const resizeTimerRef = useRef<number | undefined>(undefined);\n\n const handleScroll = useEffectEvent(() => {\n if (isResizingRef.current) {\n return;\n }\n\n const currentScrollTop = window.scrollY || document.documentElement.scrollTop;\n setScrollDirection(currentScrollTop < lastScrollTopRef.current ? 'up' : 'down');\n lastScrollTopRef.current = currentScrollTop;\n });\n\n useEffect(() => {\n const handleResize = () => {\n isResizingRef.current = true;\n window.clearTimeout(resizeTimerRef.current);\n resizeTimerRef.current = window.setTimeout(() => {\n isResizingRef.current = false;\n }, 300);\n };\n\n window.addEventListener('scroll', handleScroll);\n window.addEventListener('resize', handleResize);\n\n return () => {\n window.removeEventListener('scroll', handleScroll);\n window.removeEventListener('resize', handleResize);\n clearTimeout(resizeTimerRef.current);\n };\n }, []);\n\n return scrollDirection;\n}\n"],"mappings":";;;AAIA,SAAgB,qBAAsC;CACpD,MAAM,mBAAmB,OAAO,CAAC;CACjC,MAAM,CAAC,iBAAiB,sBAAsB,SAA0B,SAAS;CACjF,MAAM,gBAAgB,OAAO,KAAK;CAClC,MAAM,iBAAiB,OAA2B,KAAA,CAAS;CAE3D,MAAM,eAAe,qBAAqB;EACxC,IAAI,cAAc,SAChB;EAGF,MAAM,mBAAmB,OAAO,WAAW,SAAS,gBAAgB;EACpE,mBAAmB,mBAAmB,iBAAiB,UAAU,OAAO,MAAM;EAC9E,iBAAiB,UAAU;CAC7B,CAAC;CAED,gBAAgB;EACd,MAAM,qBAAqB;GACzB,cAAc,UAAU;GACxB,OAAO,aAAa,eAAe,OAAO;GAC1C,eAAe,UAAU,OAAO,iBAAiB;IAC/C,cAAc,UAAU;GAC1B,GAAG,GAAG;EACR;EAEA,OAAO,iBAAiB,UAAU,YAAY;EAC9C,OAAO,iBAAiB,UAAU,YAAY;EAE9C,aAAa;GACX,OAAO,oBAAoB,UAAU,YAAY;GACjD,OAAO,oBAAoB,UAAU,YAAY;GACjD,aAAa,eAAe,OAAO;EACrC;CACF,GAAG,CAAC,CAAC;CAEL,OAAO;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-scroll-into-view.mjs","names":[],"sources":["../../src/use-scroll-into-view/use-scroll-into-view.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\nimport { useReducedMotion } from '../use-reduced-motion/use-reduced-motion';\nimport { useWindowEvent } from '../use-window-event/use-window-event';\n\ninterface UseScrollIntoViewAnimation {\n /** Target element alignment relatively to parent based on current axis */\n alignment?: 'start' | 'end' | 'center';\n}\n\nexport interface UseScrollIntoViewOptions {\n /** Callback fired after scroll */\n onScrollFinish?: () => void;\n\n /** Callback fired when scroll animation is canceled by user interaction */\n onScrollCancel?: () => void;\n\n /** Duration of scroll in milliseconds */\n duration?: number;\n\n /** Axis of scroll */\n axis?: 'x' | 'y';\n\n /** Custom mathematical easing function */\n easing?: (t: number) => number;\n\n /** Additional distance between nearest edge and element */\n offset?: number;\n\n /** Indicator if animation may be interrupted by user scrolling */\n cancelable?: boolean;\n\n /** Prevents content jumping in scrolling lists with multiple targets */\n isList?: boolean;\n}\n\nexport interface UseScrollIntoViewReturnValue<\n Target extends HTMLElement = any,\n Parent extends HTMLElement | null = null,\n> {\n scrollableRef: React.RefObject<Parent | null>;\n targetRef: React.RefObject<Target | null>;\n scrollIntoView: (params?: UseScrollIntoViewAnimation) => void;\n cancel: () => void;\n scrolling: boolean;\n}\n\nexport function useScrollIntoView<\n Target extends HTMLElement = any,\n Parent extends HTMLElement | null = null,\n>({\n duration = 1250,\n axis = 'y',\n onScrollFinish,\n onScrollCancel,\n easing = easeInOutQuad,\n offset = 0,\n cancelable = true,\n isList = false,\n}: UseScrollIntoViewOptions = {}): UseScrollIntoViewReturnValue<Target, Parent> {\n const frameID = useRef(0);\n const startTime = useRef(0);\n const shouldStop = useRef(false);\n const [scrolling, setScrolling] = useState(false);\n\n const scrollableRef = useRef<Parent | null>(null);\n const targetRef = useRef<Target | null>(null);\n\n const reducedMotion = useReducedMotion();\n\n const cancel = (): void => {\n if (frameID.current) {\n cancelAnimationFrame(frameID.current);\n frameID.current = 0;\n setScrolling(false);\n }\n };\n\n const scrollIntoView = useCallback(\n ({ alignment = 'start' }: UseScrollIntoViewAnimation = {}) => {\n shouldStop.current = false;\n\n if (frameID.current) {\n cancel();\n }\n\n const start = getScrollStart({ parent: scrollableRef.current, axis }) ?? 0;\n\n const change =\n getRelativePosition({\n parent: scrollableRef.current,\n target: targetRef.current,\n axis,\n alignment,\n offset,\n isList,\n }) - (scrollableRef.current ? 0 : start);\n\n setScrolling(true);\n\n function animateScroll() {\n if (startTime.current === 0) {\n startTime.current = performance.now();\n }\n\n const now = performance.now();\n const elapsed = now - startTime.current;\n\n // Easing timing progress\n const t = reducedMotion || duration === 0 ? 1 : elapsed / duration;\n\n const distance = start + change * easing(t);\n\n setScrollParam({\n parent: scrollableRef.current,\n axis,\n distance,\n });\n\n if (!shouldStop.current && t < 1) {\n frameID.current = requestAnimationFrame(animateScroll);\n } else {\n if (shouldStop.current) {\n typeof onScrollCancel === 'function' && onScrollCancel();\n } else {\n typeof onScrollFinish === 'function' && onScrollFinish();\n }\n startTime.current = 0;\n frameID.current = 0;\n setScrolling(false);\n cancel();\n }\n }\n animateScroll();\n },\n [axis, duration, easing, isList, offset, onScrollFinish, onScrollCancel, reducedMotion]\n );\n\n const handleStop = () => {\n if (cancelable) {\n shouldStop.current = true;\n }\n };\n\n /**\n * Detection of one of these events stops scroll animation\n * wheel - mouse wheel / touch pad\n * touchmove - any touchable device\n */\n\n useWindowEvent('wheel', handleStop, {\n passive: true,\n });\n\n useWindowEvent('touchmove', handleStop, {\n passive: true,\n });\n\n // Cleanup requestAnimationFrame\n useEffect(() => cancel, []);\n\n return {\n scrollableRef,\n targetRef,\n scrollIntoView,\n cancel,\n scrolling,\n };\n}\n\n// ---------------------------------------------------\n// Helpers\n// ---------------------------------------------------\n\nfunction easeInOutQuad(t: number) {\n return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;\n}\n\nfunction getRelativePosition({ axis, target, parent, alignment, offset, isList }: any): number {\n if (!target || (!parent && typeof document === 'undefined')) {\n return 0;\n }\n const isCustomParent = !!parent;\n const parentElement = parent || document.body;\n const parentPosition = parentElement.getBoundingClientRect();\n const targetPosition = target.getBoundingClientRect();\n\n const getDiff = (property: 'top' | 'left'): number =>\n targetPosition[property] - parentPosition[property];\n\n if (axis === 'y') {\n const diff = getDiff('top');\n\n if (diff === 0) {\n return 0;\n }\n\n if (alignment === 'start') {\n const distance = diff - offset;\n const shouldScroll = distance <= targetPosition.height * (isList ? 0 : 1) || !isList;\n\n return shouldScroll ? distance : 0;\n }\n\n const parentHeight = isCustomParent ? parentPosition.height : window.innerHeight;\n\n if (alignment === 'end') {\n const distance = diff + offset - parentHeight + targetPosition.height;\n const shouldScroll = distance >= -targetPosition.height * (isList ? 0 : 1) || !isList;\n\n return shouldScroll ? distance : 0;\n }\n\n if (alignment === 'center') {\n return diff - parentHeight / 2 + targetPosition.height / 2;\n }\n\n return 0;\n }\n\n if (axis === 'x') {\n const diff = getDiff('left');\n\n if (diff === 0) {\n return 0;\n }\n\n if (alignment === 'start') {\n const distance = diff - offset;\n const shouldScroll = distance <= targetPosition.width || !isList;\n\n return shouldScroll ? distance : 0;\n }\n\n const parentWidth = isCustomParent ? parentPosition.width : window.innerWidth;\n\n if (alignment === 'end') {\n const distance = diff + offset - parentWidth + targetPosition.width;\n const shouldScroll = distance >= -targetPosition.width || !isList;\n\n return shouldScroll ? distance : 0;\n }\n\n if (alignment === 'center') {\n return diff - parentWidth / 2 + targetPosition.width / 2;\n }\n\n return 0;\n }\n\n return 0;\n}\n\nfunction getScrollStart({ axis, parent }: any) {\n if (!parent && typeof document === 'undefined') {\n return 0;\n }\n\n const method = axis === 'y' ? 'scrollTop' : 'scrollLeft';\n\n if (parent) {\n return parent[method];\n }\n\n const { body, documentElement } = document;\n\n // While one of it has a value the second is equal 0\n return body[method] + documentElement[method];\n}\n\nfunction setScrollParam({ axis, parent, distance }: any) {\n if (!parent && typeof document === 'undefined') {\n return;\n }\n\n const method = axis === 'y' ? 'scrollTop' : 'scrollLeft';\n\n if (parent) {\n parent[method] = distance;\n } else {\n const { body, documentElement } = document;\n body[method] = distance;\n documentElement[method] = distance;\n }\n}\n\nexport namespace useScrollIntoView {\n export type Options = UseScrollIntoViewOptions;\n export type ReturnValue<\n Target extends HTMLElement,\n Parent extends HTMLElement | null,\n > = UseScrollIntoViewReturnValue<Target, Parent>;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-scroll-into-view.mjs","names":[],"sources":["../../src/use-scroll-into-view/use-scroll-into-view.ts"],"sourcesContent":["import { useCallback, useEffect, useRef, useState } from 'react';\nimport { useReducedMotion } from '../use-reduced-motion/use-reduced-motion';\nimport { useWindowEvent } from '../use-window-event/use-window-event';\n\ninterface UseScrollIntoViewAnimation {\n /** Target element alignment relatively to parent based on current axis */\n alignment?: 'start' | 'end' | 'center';\n}\n\nexport interface UseScrollIntoViewOptions {\n /** Callback fired after scroll */\n onScrollFinish?: () => void;\n\n /** Callback fired when scroll animation is canceled by user interaction */\n onScrollCancel?: () => void;\n\n /** Duration of scroll in milliseconds */\n duration?: number;\n\n /** Axis of scroll */\n axis?: 'x' | 'y';\n\n /** Custom mathematical easing function */\n easing?: (t: number) => number;\n\n /** Additional distance between nearest edge and element */\n offset?: number;\n\n /** Indicator if animation may be interrupted by user scrolling */\n cancelable?: boolean;\n\n /** Prevents content jumping in scrolling lists with multiple targets */\n isList?: boolean;\n}\n\nexport interface UseScrollIntoViewReturnValue<\n Target extends HTMLElement = any,\n Parent extends HTMLElement | null = null,\n> {\n scrollableRef: React.RefObject<Parent | null>;\n targetRef: React.RefObject<Target | null>;\n scrollIntoView: (params?: UseScrollIntoViewAnimation) => void;\n cancel: () => void;\n scrolling: boolean;\n}\n\nexport function useScrollIntoView<\n Target extends HTMLElement = any,\n Parent extends HTMLElement | null = null,\n>({\n duration = 1250,\n axis = 'y',\n onScrollFinish,\n onScrollCancel,\n easing = easeInOutQuad,\n offset = 0,\n cancelable = true,\n isList = false,\n}: UseScrollIntoViewOptions = {}): UseScrollIntoViewReturnValue<Target, Parent> {\n const frameID = useRef(0);\n const startTime = useRef(0);\n const shouldStop = useRef(false);\n const [scrolling, setScrolling] = useState(false);\n\n const scrollableRef = useRef<Parent | null>(null);\n const targetRef = useRef<Target | null>(null);\n\n const reducedMotion = useReducedMotion();\n\n const cancel = (): void => {\n if (frameID.current) {\n cancelAnimationFrame(frameID.current);\n frameID.current = 0;\n setScrolling(false);\n }\n };\n\n const scrollIntoView = useCallback(\n ({ alignment = 'start' }: UseScrollIntoViewAnimation = {}) => {\n shouldStop.current = false;\n\n if (frameID.current) {\n cancel();\n }\n\n const start = getScrollStart({ parent: scrollableRef.current, axis }) ?? 0;\n\n const change =\n getRelativePosition({\n parent: scrollableRef.current,\n target: targetRef.current,\n axis,\n alignment,\n offset,\n isList,\n }) - (scrollableRef.current ? 0 : start);\n\n setScrolling(true);\n\n function animateScroll() {\n if (startTime.current === 0) {\n startTime.current = performance.now();\n }\n\n const now = performance.now();\n const elapsed = now - startTime.current;\n\n // Easing timing progress\n const t = reducedMotion || duration === 0 ? 1 : elapsed / duration;\n\n const distance = start + change * easing(t);\n\n setScrollParam({\n parent: scrollableRef.current,\n axis,\n distance,\n });\n\n if (!shouldStop.current && t < 1) {\n frameID.current = requestAnimationFrame(animateScroll);\n } else {\n if (shouldStop.current) {\n typeof onScrollCancel === 'function' && onScrollCancel();\n } else {\n typeof onScrollFinish === 'function' && onScrollFinish();\n }\n startTime.current = 0;\n frameID.current = 0;\n setScrolling(false);\n cancel();\n }\n }\n animateScroll();\n },\n [axis, duration, easing, isList, offset, onScrollFinish, onScrollCancel, reducedMotion]\n );\n\n const handleStop = () => {\n if (cancelable) {\n shouldStop.current = true;\n }\n };\n\n /**\n * Detection of one of these events stops scroll animation\n * wheel - mouse wheel / touch pad\n * touchmove - any touchable device\n */\n\n useWindowEvent('wheel', handleStop, {\n passive: true,\n });\n\n useWindowEvent('touchmove', handleStop, {\n passive: true,\n });\n\n // Cleanup requestAnimationFrame\n useEffect(() => cancel, []);\n\n return {\n scrollableRef,\n targetRef,\n scrollIntoView,\n cancel,\n scrolling,\n };\n}\n\n// ---------------------------------------------------\n// Helpers\n// ---------------------------------------------------\n\nfunction easeInOutQuad(t: number) {\n return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;\n}\n\nfunction getRelativePosition({ axis, target, parent, alignment, offset, isList }: any): number {\n if (!target || (!parent && typeof document === 'undefined')) {\n return 0;\n }\n const isCustomParent = !!parent;\n const parentElement = parent || document.body;\n const parentPosition = parentElement.getBoundingClientRect();\n const targetPosition = target.getBoundingClientRect();\n\n const getDiff = (property: 'top' | 'left'): number =>\n targetPosition[property] - parentPosition[property];\n\n if (axis === 'y') {\n const diff = getDiff('top');\n\n if (diff === 0) {\n return 0;\n }\n\n if (alignment === 'start') {\n const distance = diff - offset;\n const shouldScroll = distance <= targetPosition.height * (isList ? 0 : 1) || !isList;\n\n return shouldScroll ? distance : 0;\n }\n\n const parentHeight = isCustomParent ? parentPosition.height : window.innerHeight;\n\n if (alignment === 'end') {\n const distance = diff + offset - parentHeight + targetPosition.height;\n const shouldScroll = distance >= -targetPosition.height * (isList ? 0 : 1) || !isList;\n\n return shouldScroll ? distance : 0;\n }\n\n if (alignment === 'center') {\n return diff - parentHeight / 2 + targetPosition.height / 2;\n }\n\n return 0;\n }\n\n if (axis === 'x') {\n const diff = getDiff('left');\n\n if (diff === 0) {\n return 0;\n }\n\n if (alignment === 'start') {\n const distance = diff - offset;\n const shouldScroll = distance <= targetPosition.width || !isList;\n\n return shouldScroll ? distance : 0;\n }\n\n const parentWidth = isCustomParent ? parentPosition.width : window.innerWidth;\n\n if (alignment === 'end') {\n const distance = diff + offset - parentWidth + targetPosition.width;\n const shouldScroll = distance >= -targetPosition.width || !isList;\n\n return shouldScroll ? distance : 0;\n }\n\n if (alignment === 'center') {\n return diff - parentWidth / 2 + targetPosition.width / 2;\n }\n\n return 0;\n }\n\n return 0;\n}\n\nfunction getScrollStart({ axis, parent }: any) {\n if (!parent && typeof document === 'undefined') {\n return 0;\n }\n\n const method = axis === 'y' ? 'scrollTop' : 'scrollLeft';\n\n if (parent) {\n return parent[method];\n }\n\n const { body, documentElement } = document;\n\n // While one of it has a value the second is equal 0\n return body[method] + documentElement[method];\n}\n\nfunction setScrollParam({ axis, parent, distance }: any) {\n if (!parent && typeof document === 'undefined') {\n return;\n }\n\n const method = axis === 'y' ? 'scrollTop' : 'scrollLeft';\n\n if (parent) {\n parent[method] = distance;\n } else {\n const { body, documentElement } = document;\n body[method] = distance;\n documentElement[method] = distance;\n }\n}\n\nexport namespace useScrollIntoView {\n export type Options = UseScrollIntoViewOptions;\n export type ReturnValue<\n Target extends HTMLElement,\n Parent extends HTMLElement | null,\n > = UseScrollIntoViewReturnValue<Target, Parent>;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-scroll-spy.mjs","names":[],"sources":["../../src/use-scroll-spy/use-scroll-spy.ts"],"sourcesContent":["import { useEffect, useEffectEvent, useRef, useState } from 'react';\nimport { randomId } from '../utils';\n\nfunction getHeadingsData(\n headings: HTMLElement[],\n getDepth: (element: HTMLElement) => number,\n getValue: (element: HTMLElement) => string\n): UseScrollSpyHeadingData[] {\n const result: UseScrollSpyHeadingData[] = [];\n\n for (let i = 0; i < headings.length; i += 1) {\n const heading = headings[i];\n result.push({\n depth: getDepth(heading),\n value: getValue(heading),\n id: heading.id || randomId(),\n getNode: () => (heading.id ? document.getElementById(heading.id)! : heading),\n });\n }\n\n return result;\n}\n\nfunction getActiveElement(rects: DOMRect[], offset: number = 0) {\n if (rects.length === 0) {\n return -1;\n }\n\n const closest = rects.reduce(\n (acc, item, index) => {\n if (Math.abs(acc.position - offset) < Math.abs(item.y - offset)) {\n return acc;\n }\n\n return {\n index,\n position: item.y,\n };\n },\n { index: 0, position: rects[0].y }\n );\n\n return closest.index;\n}\n\nfunction getDefaultDepth(element: HTMLElement) {\n return Number(element.tagName[1]);\n}\n\nfunction getDefaultValue(element: HTMLElement) {\n return element.textContent || '';\n}\n\nexport interface UseScrollSpyHeadingData {\n /** Heading depth, 1-6 */\n depth: number;\n\n /** Heading text content value */\n value: string;\n\n /** Heading id */\n id: string;\n\n /** Function to get heading node */\n getNode: () => HTMLElement;\n}\n\nexport interface UseScrollSpyOptions {\n /** Selector to get headings, `'h1, h2, h3, h4, h5, h6'` by default */\n selector?: string;\n\n /** A function to retrieve depth of heading, by default depth is calculated based on tag name */\n getDepth?: (element: HTMLElement) => number;\n\n /** A function to retrieve heading value, by default `element.textContent` is used */\n getValue?: (element: HTMLElement) => string;\n\n /** Host element to attach scroll event listener, if not provided, `window` is used */\n scrollHost?: HTMLElement;\n\n /** Offset from the top of the viewport to use when determining the active heading, `0` by default */\n offset?: number;\n}\n\nexport interface UseScrollSpyReturnValue {\n /** Index of the active heading in the `data` array */\n active: number;\n\n /** Headings data. If not initialize, data is represented by an empty array. */\n data: UseScrollSpyHeadingData[];\n\n /** True if headings value have been retrieved from the DOM. */\n initialized: boolean;\n\n /** Function to update headings values after the parent component has mounted. */\n reinitialize: () => void;\n}\n\nexport function useScrollSpy({\n selector = 'h1, h2, h3, h4, h5, h6',\n getDepth = getDefaultDepth,\n getValue = getDefaultValue,\n offset = 0,\n scrollHost,\n}: UseScrollSpyOptions = {}): UseScrollSpyReturnValue {\n const [active, setActive] = useState(-1);\n const [initialized, setInitialized] = useState(false);\n const [data, setData] = useState<UseScrollSpyHeadingData[]>([]);\n const headingsRef = useRef<UseScrollSpyHeadingData[]>([]);\n\n const handleScroll = useEffectEvent(() => {\n setActive(\n getActiveElement(\n headingsRef.current.map((d) => d.getNode().getBoundingClientRect()),\n offset\n )\n );\n });\n\n const initialize = () => {\n const headings = getHeadingsData(\n Array.from(document.querySelectorAll(selector)),\n getDepth,\n getValue\n );\n headingsRef.current = headings;\n setInitialized(true);\n setData(headings);\n setActive(\n getActiveElement(\n headings.map((d) => d.getNode().getBoundingClientRect()),\n offset\n )\n );\n };\n\n useEffect(() => {\n initialize();\n const _scrollHost = scrollHost || window;\n _scrollHost.addEventListener('scroll', handleScroll);\n return () => _scrollHost.removeEventListener('scroll', handleScroll);\n }, [scrollHost, selector, offset]);\n\n return {\n reinitialize: initialize,\n active,\n initialized,\n data,\n };\n}\n\nexport namespace useScrollSpy {\n export type Options = UseScrollSpyOptions;\n export type ReturnValue = UseScrollSpyReturnValue;\n}\n"],"mappings":";;;;AAGA,SAAS,gBACP,UACA,UACA,UAC2B;CAC3B,MAAM,SAAoC,
|
|
1
|
+
{"version":3,"file":"use-scroll-spy.mjs","names":[],"sources":["../../src/use-scroll-spy/use-scroll-spy.ts"],"sourcesContent":["import { useEffect, useEffectEvent, useRef, useState } from 'react';\nimport { randomId } from '../utils';\n\nfunction getHeadingsData(\n headings: HTMLElement[],\n getDepth: (element: HTMLElement) => number,\n getValue: (element: HTMLElement) => string\n): UseScrollSpyHeadingData[] {\n const result: UseScrollSpyHeadingData[] = [];\n\n for (let i = 0; i < headings.length; i += 1) {\n const heading = headings[i];\n result.push({\n depth: getDepth(heading),\n value: getValue(heading),\n id: heading.id || randomId(),\n getNode: () => (heading.id ? document.getElementById(heading.id)! : heading),\n });\n }\n\n return result;\n}\n\nfunction getActiveElement(rects: DOMRect[], offset: number = 0) {\n if (rects.length === 0) {\n return -1;\n }\n\n const closest = rects.reduce(\n (acc, item, index) => {\n if (Math.abs(acc.position - offset) < Math.abs(item.y - offset)) {\n return acc;\n }\n\n return {\n index,\n position: item.y,\n };\n },\n { index: 0, position: rects[0].y }\n );\n\n return closest.index;\n}\n\nfunction getDefaultDepth(element: HTMLElement) {\n return Number(element.tagName[1]);\n}\n\nfunction getDefaultValue(element: HTMLElement) {\n return element.textContent || '';\n}\n\nexport interface UseScrollSpyHeadingData {\n /** Heading depth, 1-6 */\n depth: number;\n\n /** Heading text content value */\n value: string;\n\n /** Heading id */\n id: string;\n\n /** Function to get heading node */\n getNode: () => HTMLElement;\n}\n\nexport interface UseScrollSpyOptions {\n /** Selector to get headings, `'h1, h2, h3, h4, h5, h6'` by default */\n selector?: string;\n\n /** A function to retrieve depth of heading, by default depth is calculated based on tag name */\n getDepth?: (element: HTMLElement) => number;\n\n /** A function to retrieve heading value, by default `element.textContent` is used */\n getValue?: (element: HTMLElement) => string;\n\n /** Host element to attach scroll event listener, if not provided, `window` is used */\n scrollHost?: HTMLElement;\n\n /** Offset from the top of the viewport to use when determining the active heading, `0` by default */\n offset?: number;\n}\n\nexport interface UseScrollSpyReturnValue {\n /** Index of the active heading in the `data` array */\n active: number;\n\n /** Headings data. If not initialize, data is represented by an empty array. */\n data: UseScrollSpyHeadingData[];\n\n /** True if headings value have been retrieved from the DOM. */\n initialized: boolean;\n\n /** Function to update headings values after the parent component has mounted. */\n reinitialize: () => void;\n}\n\nexport function useScrollSpy({\n selector = 'h1, h2, h3, h4, h5, h6',\n getDepth = getDefaultDepth,\n getValue = getDefaultValue,\n offset = 0,\n scrollHost,\n}: UseScrollSpyOptions = {}): UseScrollSpyReturnValue {\n const [active, setActive] = useState(-1);\n const [initialized, setInitialized] = useState(false);\n const [data, setData] = useState<UseScrollSpyHeadingData[]>([]);\n const headingsRef = useRef<UseScrollSpyHeadingData[]>([]);\n\n const handleScroll = useEffectEvent(() => {\n setActive(\n getActiveElement(\n headingsRef.current.map((d) => d.getNode().getBoundingClientRect()),\n offset\n )\n );\n });\n\n const initialize = () => {\n const headings = getHeadingsData(\n Array.from(document.querySelectorAll(selector)),\n getDepth,\n getValue\n );\n headingsRef.current = headings;\n setInitialized(true);\n setData(headings);\n setActive(\n getActiveElement(\n headings.map((d) => d.getNode().getBoundingClientRect()),\n offset\n )\n );\n };\n\n useEffect(() => {\n initialize();\n const _scrollHost = scrollHost || window;\n _scrollHost.addEventListener('scroll', handleScroll);\n return () => _scrollHost.removeEventListener('scroll', handleScroll);\n }, [scrollHost, selector, offset]);\n\n return {\n reinitialize: initialize,\n active,\n initialized,\n data,\n };\n}\n\nexport namespace useScrollSpy {\n export type Options = UseScrollSpyOptions;\n export type ReturnValue = UseScrollSpyReturnValue;\n}\n"],"mappings":";;;;AAGA,SAAS,gBACP,UACA,UACA,UAC2B;CAC3B,MAAM,SAAoC,CAAC;CAE3C,KAAK,IAAI,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK,GAAG;EAC3C,MAAM,UAAU,SAAS;EACzB,OAAO,KAAK;GACV,OAAO,SAAS,OAAO;GACvB,OAAO,SAAS,OAAO;GACvB,IAAI,QAAQ,MAAM,SAAS;GAC3B,eAAgB,QAAQ,KAAK,SAAS,eAAe,QAAQ,EAAE,IAAK;EACtE,CAAC;CACH;CAEA,OAAO;AACT;AAEA,SAAS,iBAAiB,OAAkB,SAAiB,GAAG;CAC9D,IAAI,MAAM,WAAW,GACnB,OAAO;CAiBT,OAdgB,MAAM,QACnB,KAAK,MAAM,UAAU;EACpB,IAAI,KAAK,IAAI,IAAI,WAAW,MAAM,IAAI,KAAK,IAAI,KAAK,IAAI,MAAM,GAC5D,OAAO;EAGT,OAAO;GACL;GACA,UAAU,KAAK;EACjB;CACF,GACA;EAAE,OAAO;EAAG,UAAU,MAAM,GAAG;CAAE,CAGtB,EAAE;AACjB;AAEA,SAAS,gBAAgB,SAAsB;CAC7C,OAAO,OAAO,QAAQ,QAAQ,EAAE;AAClC;AAEA,SAAS,gBAAgB,SAAsB;CAC7C,OAAO,QAAQ,eAAe;AAChC;AA+CA,SAAgB,aAAa,EAC3B,WAAW,0BACX,WAAW,iBACX,WAAW,iBACX,SAAS,GACT,eACuB,CAAC,GAA4B;CACpD,MAAM,CAAC,QAAQ,aAAa,SAAS,EAAE;CACvC,MAAM,CAAC,aAAa,kBAAkB,SAAS,KAAK;CACpD,MAAM,CAAC,MAAM,WAAW,SAAoC,CAAC,CAAC;CAC9D,MAAM,cAAc,OAAkC,CAAC,CAAC;CAExD,MAAM,eAAe,qBAAqB;EACxC,UACE,iBACE,YAAY,QAAQ,KAAK,MAAM,EAAE,QAAQ,EAAE,sBAAsB,CAAC,GAClE,MACF,CACF;CACF,CAAC;CAED,MAAM,mBAAmB;EACvB,MAAM,WAAW,gBACf,MAAM,KAAK,SAAS,iBAAiB,QAAQ,CAAC,GAC9C,UACA,QACF;EACA,YAAY,UAAU;EACtB,eAAe,IAAI;EACnB,QAAQ,QAAQ;EAChB,UACE,iBACE,SAAS,KAAK,MAAM,EAAE,QAAQ,EAAE,sBAAsB,CAAC,GACvD,MACF,CACF;CACF;CAEA,gBAAgB;EACd,WAAW;EACX,MAAM,cAAc,cAAc;EAClC,YAAY,iBAAiB,UAAU,YAAY;EACnD,aAAa,YAAY,oBAAoB,UAAU,YAAY;CACrE,GAAG;EAAC;EAAY;EAAU;CAAM,CAAC;CAEjC,OAAO;EACL,cAAc;EACd;EACA;EACA;CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-scroller.mjs","names":[],"sources":["../../src/use-scroller/use-scroller.ts"],"sourcesContent":["import { RefCallback, useCallback, useEffect, useRef, useState } from 'react';\n\nexport interface UseScrollerOptions {\n /** Amount of pixels to scroll when calling scroll functions, `200` by default */\n scrollAmount?: number;\n\n /** Determines whether content can be scrolled by dragging with mouse, `true` by default */\n draggable?: boolean;\n\n /** Called when scroll state changes (canScrollStart or canScrollEnd) */\n onScrollStateChange?: (state: UseScrollerScrollState) => void;\n}\n\nexport interface UseScrollerScrollState {\n /** Whether content can be scrolled towards the start (left in LTR, right in RTL) */\n canScrollStart: boolean;\n\n /** Whether content can be scrolled towards the end (right in LTR, left in RTL) */\n canScrollEnd: boolean;\n}\n\nexport interface UseScrollerReturnValue<T extends HTMLElement = HTMLDivElement> {\n /** Ref callback to attach to the scrollable container element */\n ref: RefCallback<T | null>;\n\n /** Whether content can be scrolled towards the start */\n canScrollStart: boolean;\n\n /** Whether content can be scrolled towards the end */\n canScrollEnd: boolean;\n\n /** Scrolls towards the start direction */\n scrollStart: () => void;\n\n /** Scrolls towards the end direction */\n scrollEnd: () => void;\n\n /** `true` if the user is currently dragging the content */\n isDragging: boolean;\n\n /** Props to spread on the scrollable container for drag functionality */\n dragHandlers: {\n onMouseDown: (e: React.MouseEvent) => void;\n onMouseMove: (e: React.MouseEvent) => void;\n onMouseUp: () => void;\n onMouseLeave: () => void;\n };\n}\n\nexport function useScroller<T extends HTMLElement = HTMLDivElement>(\n options: UseScrollerOptions = {}\n): UseScrollerReturnValue<T> {\n const { scrollAmount = 200, draggable = true, onScrollStateChange } = options;\n\n const containerRef = useRef<T | null>(null);\n\n const [canScrollStart, setCanScrollStart] = useState(false);\n const [canScrollEnd, setCanScrollEnd] = useState(false);\n const [isDragging, setIsDragging] = useState(false);\n\n const isDraggingRef = useRef(false);\n const hasDraggedRef = useRef(false);\n const startX = useRef(0);\n const scrollLeftStart = useRef(0);\n\n const onScrollStateChangeRef = useRef(onScrollStateChange);\n onScrollStateChangeRef.current = onScrollStateChange;\n\n const updateScrollState = useCallback(() => {\n const container = containerRef.current;\n if (container) {\n const { scrollLeft, scrollWidth, clientWidth } = container;\n const isRtl = getComputedStyle(container).direction === 'rtl';\n\n let newCanScrollStart: boolean;\n let newCanScrollEnd: boolean;\n\n if (isRtl) {\n newCanScrollStart = scrollLeft < -1;\n newCanScrollEnd = scrollLeft > -(scrollWidth - clientWidth) + 1;\n } else {\n newCanScrollStart = scrollLeft > 1;\n newCanScrollEnd = scrollLeft < scrollWidth - clientWidth - 1;\n }\n\n setCanScrollStart(newCanScrollStart);\n setCanScrollEnd(newCanScrollEnd);\n\n onScrollStateChangeRef.current?.({\n canScrollStart: newCanScrollStart,\n canScrollEnd: newCanScrollEnd,\n });\n }\n }, []);\n\n useEffect(() => {\n updateScrollState();\n const container = containerRef.current;\n if (container) {\n container.addEventListener('scroll', updateScrollState);\n const resizeObserver = new ResizeObserver(updateScrollState);\n resizeObserver.observe(container);\n return () => {\n container.removeEventListener('scroll', updateScrollState);\n resizeObserver.disconnect();\n };\n }\n return undefined;\n }, [updateScrollState]);\n\n const scroll = useCallback(\n (direction: 'start' | 'end') => {\n const container = containerRef.current;\n if (container) {\n const isRtl = getComputedStyle(container).direction === 'rtl';\n const amount = scrollAmount;\n const scrollBy = direction === 'end' ? amount : -amount;\n const adjustedScrollBy = isRtl ? -scrollBy : scrollBy;\n\n container.scrollBy({\n left: adjustedScrollBy,\n behavior: 'smooth',\n });\n }\n },\n [scrollAmount]\n );\n\n const scrollStart = useCallback(() => scroll('start'), [scroll]);\n const scrollEnd = useCallback(() => scroll('end'), [scroll]);\n\n const handleMouseDown = useCallback(\n (event: React.MouseEvent) => {\n if (!draggable) {\n return;\n }\n const container = containerRef.current;\n if (container) {\n isDraggingRef.current = true;\n hasDraggedRef.current = false;\n setIsDragging(true);\n startX.current = event.pageX - container.offsetLeft;\n scrollLeftStart.current = container.scrollLeft;\n container.style.cursor = 'grabbing';\n container.style.userSelect = 'none';\n }\n },\n [draggable]\n );\n\n const handleMouseMove = useCallback((event: React.MouseEvent) => {\n if (!isDraggingRef.current) {\n return;\n }\n event.preventDefault();\n const container = containerRef.current;\n if (container) {\n const x = event.pageX - container.offsetLeft;\n const walk = x - startX.current;\n if (Math.abs(walk) > 5) {\n hasDraggedRef.current = true;\n }\n container.scrollLeft = scrollLeftStart.current - walk;\n }\n }, []);\n\n const handleMouseUp = useCallback(() => {\n const wasDragged = hasDraggedRef.current;\n isDraggingRef.current = false;\n hasDraggedRef.current = false;\n setIsDragging(false);\n const container = containerRef.current;\n if (container) {\n container.style.cursor = '';\n container.style.userSelect = '';\n\n if (wasDragged) {\n const suppressClick = (event: MouseEvent) => {\n event.stopPropagation();\n event.preventDefault();\n container.removeEventListener('click', suppressClick, true);\n };\n container.addEventListener('click', suppressClick, true);\n }\n }\n }, []);\n\n const handleMouseLeave = useCallback(() => {\n if (isDraggingRef.current) {\n handleMouseUp();\n }\n }, [handleMouseUp]);\n\n const assignRef: RefCallback<T | null> = useCallback(\n (node) => {\n containerRef.current = node;\n if (node) {\n updateScrollState();\n }\n },\n [updateScrollState]\n );\n\n return {\n ref: assignRef,\n canScrollStart,\n canScrollEnd,\n scrollStart,\n scrollEnd,\n isDragging,\n dragHandlers: {\n onMouseDown: handleMouseDown,\n onMouseMove: handleMouseMove,\n onMouseUp: handleMouseUp,\n onMouseLeave: handleMouseLeave,\n },\n };\n}\n\nexport namespace useScroller {\n export type Options = UseScrollerOptions;\n export type ReturnValue<T extends HTMLElement = HTMLDivElement> = UseScrollerReturnValue<T>;\n export type ScrollState = UseScrollerScrollState;\n}\n"],"mappings":";;;AAiDA,SAAgB,YACd,UAA8B,
|
|
1
|
+
{"version":3,"file":"use-scroller.mjs","names":[],"sources":["../../src/use-scroller/use-scroller.ts"],"sourcesContent":["import { RefCallback, useCallback, useEffect, useRef, useState } from 'react';\n\nexport interface UseScrollerOptions {\n /** Amount of pixels to scroll when calling scroll functions, `200` by default */\n scrollAmount?: number;\n\n /** Determines whether content can be scrolled by dragging with mouse, `true` by default */\n draggable?: boolean;\n\n /** Called when scroll state changes (canScrollStart or canScrollEnd) */\n onScrollStateChange?: (state: UseScrollerScrollState) => void;\n}\n\nexport interface UseScrollerScrollState {\n /** Whether content can be scrolled towards the start (left in LTR, right in RTL) */\n canScrollStart: boolean;\n\n /** Whether content can be scrolled towards the end (right in LTR, left in RTL) */\n canScrollEnd: boolean;\n}\n\nexport interface UseScrollerReturnValue<T extends HTMLElement = HTMLDivElement> {\n /** Ref callback to attach to the scrollable container element */\n ref: RefCallback<T | null>;\n\n /** Whether content can be scrolled towards the start */\n canScrollStart: boolean;\n\n /** Whether content can be scrolled towards the end */\n canScrollEnd: boolean;\n\n /** Scrolls towards the start direction */\n scrollStart: () => void;\n\n /** Scrolls towards the end direction */\n scrollEnd: () => void;\n\n /** `true` if the user is currently dragging the content */\n isDragging: boolean;\n\n /** Props to spread on the scrollable container for drag functionality */\n dragHandlers: {\n onMouseDown: (e: React.MouseEvent) => void;\n onMouseMove: (e: React.MouseEvent) => void;\n onMouseUp: () => void;\n onMouseLeave: () => void;\n };\n}\n\nexport function useScroller<T extends HTMLElement = HTMLDivElement>(\n options: UseScrollerOptions = {}\n): UseScrollerReturnValue<T> {\n const { scrollAmount = 200, draggable = true, onScrollStateChange } = options;\n\n const containerRef = useRef<T | null>(null);\n\n const [canScrollStart, setCanScrollStart] = useState(false);\n const [canScrollEnd, setCanScrollEnd] = useState(false);\n const [isDragging, setIsDragging] = useState(false);\n\n const isDraggingRef = useRef(false);\n const hasDraggedRef = useRef(false);\n const startX = useRef(0);\n const scrollLeftStart = useRef(0);\n\n const onScrollStateChangeRef = useRef(onScrollStateChange);\n onScrollStateChangeRef.current = onScrollStateChange;\n\n const updateScrollState = useCallback(() => {\n const container = containerRef.current;\n if (container) {\n const { scrollLeft, scrollWidth, clientWidth } = container;\n const isRtl = getComputedStyle(container).direction === 'rtl';\n\n let newCanScrollStart: boolean;\n let newCanScrollEnd: boolean;\n\n if (isRtl) {\n newCanScrollStart = scrollLeft < -1;\n newCanScrollEnd = scrollLeft > -(scrollWidth - clientWidth) + 1;\n } else {\n newCanScrollStart = scrollLeft > 1;\n newCanScrollEnd = scrollLeft < scrollWidth - clientWidth - 1;\n }\n\n setCanScrollStart(newCanScrollStart);\n setCanScrollEnd(newCanScrollEnd);\n\n onScrollStateChangeRef.current?.({\n canScrollStart: newCanScrollStart,\n canScrollEnd: newCanScrollEnd,\n });\n }\n }, []);\n\n useEffect(() => {\n updateScrollState();\n const container = containerRef.current;\n if (container) {\n container.addEventListener('scroll', updateScrollState);\n const resizeObserver = new ResizeObserver(updateScrollState);\n resizeObserver.observe(container);\n return () => {\n container.removeEventListener('scroll', updateScrollState);\n resizeObserver.disconnect();\n };\n }\n return undefined;\n }, [updateScrollState]);\n\n const scroll = useCallback(\n (direction: 'start' | 'end') => {\n const container = containerRef.current;\n if (container) {\n const isRtl = getComputedStyle(container).direction === 'rtl';\n const amount = scrollAmount;\n const scrollBy = direction === 'end' ? amount : -amount;\n const adjustedScrollBy = isRtl ? -scrollBy : scrollBy;\n\n container.scrollBy({\n left: adjustedScrollBy,\n behavior: 'smooth',\n });\n }\n },\n [scrollAmount]\n );\n\n const scrollStart = useCallback(() => scroll('start'), [scroll]);\n const scrollEnd = useCallback(() => scroll('end'), [scroll]);\n\n const handleMouseDown = useCallback(\n (event: React.MouseEvent) => {\n if (!draggable) {\n return;\n }\n const container = containerRef.current;\n if (container) {\n isDraggingRef.current = true;\n hasDraggedRef.current = false;\n setIsDragging(true);\n startX.current = event.pageX - container.offsetLeft;\n scrollLeftStart.current = container.scrollLeft;\n container.style.cursor = 'grabbing';\n container.style.userSelect = 'none';\n }\n },\n [draggable]\n );\n\n const handleMouseMove = useCallback((event: React.MouseEvent) => {\n if (!isDraggingRef.current) {\n return;\n }\n event.preventDefault();\n const container = containerRef.current;\n if (container) {\n const x = event.pageX - container.offsetLeft;\n const walk = x - startX.current;\n if (Math.abs(walk) > 5) {\n hasDraggedRef.current = true;\n }\n container.scrollLeft = scrollLeftStart.current - walk;\n }\n }, []);\n\n const handleMouseUp = useCallback(() => {\n const wasDragged = hasDraggedRef.current;\n isDraggingRef.current = false;\n hasDraggedRef.current = false;\n setIsDragging(false);\n const container = containerRef.current;\n if (container) {\n container.style.cursor = '';\n container.style.userSelect = '';\n\n if (wasDragged) {\n const suppressClick = (event: MouseEvent) => {\n event.stopPropagation();\n event.preventDefault();\n container.removeEventListener('click', suppressClick, true);\n };\n container.addEventListener('click', suppressClick, true);\n }\n }\n }, []);\n\n const handleMouseLeave = useCallback(() => {\n if (isDraggingRef.current) {\n handleMouseUp();\n }\n }, [handleMouseUp]);\n\n const assignRef: RefCallback<T | null> = useCallback(\n (node) => {\n containerRef.current = node;\n if (node) {\n updateScrollState();\n }\n },\n [updateScrollState]\n );\n\n return {\n ref: assignRef,\n canScrollStart,\n canScrollEnd,\n scrollStart,\n scrollEnd,\n isDragging,\n dragHandlers: {\n onMouseDown: handleMouseDown,\n onMouseMove: handleMouseMove,\n onMouseUp: handleMouseUp,\n onMouseLeave: handleMouseLeave,\n },\n };\n}\n\nexport namespace useScroller {\n export type Options = UseScrollerOptions;\n export type ReturnValue<T extends HTMLElement = HTMLDivElement> = UseScrollerReturnValue<T>;\n export type ScrollState = UseScrollerScrollState;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-selection.mjs","names":[],"sources":["../../src/use-selection/use-selection.ts"],"sourcesContent":["import { useCallback, useState } from 'react';\nimport { useDidUpdate } from '../use-did-update/use-did-update';\n\nexport interface UseSelectionInput<T> {\n /** The array of items to select from */\n data: T[];\n\n /** The initial selection, empty array by default */\n defaultSelection?: T[];\n\n /** If true, selection is reset when data changes */\n resetSelectionOnDataChange?: boolean;\n}\n\nexport interface UseSelectionHandlers<T> {\n /** Add an item to the selection */\n select: (selected: T) => void;\n\n /** Remove an item from the selection */\n deselect: (deselected: T) => void;\n\n /** Toggle an item's selection state */\n toggle: (toggled: T) => void;\n\n /** Returns true if all items from the `data` are selected */\n isAllSelected: () => boolean;\n\n /** Returns true if at least one item from the `data` is selected */\n isSomeSelected: () => boolean;\n\n /** Set the selection to a specific array of items */\n setSelection: (selection: T[]) => void;\n\n /** Clear all selections */\n resetSelection: () => void;\n}\n\nexport type UseSelectionReturnValue<T> = readonly [T[], UseSelectionHandlers<T>];\n\nexport function useSelection<T>(input: UseSelectionInput<T>): UseSelectionReturnValue<T> {\n const [selectionSet, setSelectionSet] = useState<Set<T>>(new Set(input.defaultSelection || []));\n\n useDidUpdate(() => {\n if (input.resetSelectionOnDataChange) {\n setSelectionSet(new Set());\n }\n }, [input.data, input.resetSelectionOnDataChange]);\n\n const select = useCallback((selected: T) => {\n setSelectionSet((state) => {\n if (!state.has(selected)) {\n const newSet = new Set(state);\n newSet.add(selected);\n return newSet;\n }\n return state;\n });\n }, []);\n\n const deselect = useCallback((deselected: T) => {\n setSelectionSet((state) => {\n if (state.has(deselected)) {\n const newSet = new Set(state);\n newSet.delete(deselected);\n return newSet;\n }\n return state;\n });\n }, []);\n\n const toggle = useCallback((toggled: T) => {\n setSelectionSet((state) => {\n const newSet = new Set(state);\n if (state.has(toggled)) {\n newSet.delete(toggled);\n } else {\n newSet.add(toggled);\n }\n return newSet;\n });\n }, []);\n\n const resetSelection = useCallback(() => {\n setSelectionSet(new Set());\n }, []);\n\n const setSelection = useCallback((selection: T[]) => {\n setSelectionSet(new Set(selection));\n }, []);\n\n const isAllSelected = useCallback(() => {\n if (input.data.length === 0) {\n return false;\n }\n return input.data.every((item) => selectionSet.has(item));\n }, [selectionSet, input.data]);\n\n const isSomeSelected = useCallback(() => {\n return input.data.some((item) => selectionSet.has(item));\n }, [selectionSet, input.data]);\n\n return [\n Array.from(selectionSet),\n {\n select,\n deselect,\n toggle,\n isAllSelected,\n isSomeSelected,\n setSelection,\n resetSelection,\n },\n ];\n}\n\nexport namespace useSelection {\n export type Input<T> = UseSelectionInput<T>;\n export type Handlers<T> = UseSelectionHandlers<T>;\n export type ReturnValue<T> = UseSelectionReturnValue<T>;\n}\n"],"mappings":";;;;AAuCA,SAAgB,aAAgB,OAAyD;CACvF,MAAM,CAAC,cAAc,mBAAmB,SAAiB,IAAI,IAAI,MAAM,oBAAoB,
|
|
1
|
+
{"version":3,"file":"use-selection.mjs","names":[],"sources":["../../src/use-selection/use-selection.ts"],"sourcesContent":["import { useCallback, useState } from 'react';\nimport { useDidUpdate } from '../use-did-update/use-did-update';\n\nexport interface UseSelectionInput<T> {\n /** The array of items to select from */\n data: T[];\n\n /** The initial selection, empty array by default */\n defaultSelection?: T[];\n\n /** If true, selection is reset when data changes */\n resetSelectionOnDataChange?: boolean;\n}\n\nexport interface UseSelectionHandlers<T> {\n /** Add an item to the selection */\n select: (selected: T) => void;\n\n /** Remove an item from the selection */\n deselect: (deselected: T) => void;\n\n /** Toggle an item's selection state */\n toggle: (toggled: T) => void;\n\n /** Returns true if all items from the `data` are selected */\n isAllSelected: () => boolean;\n\n /** Returns true if at least one item from the `data` is selected */\n isSomeSelected: () => boolean;\n\n /** Set the selection to a specific array of items */\n setSelection: (selection: T[]) => void;\n\n /** Clear all selections */\n resetSelection: () => void;\n}\n\nexport type UseSelectionReturnValue<T> = readonly [T[], UseSelectionHandlers<T>];\n\nexport function useSelection<T>(input: UseSelectionInput<T>): UseSelectionReturnValue<T> {\n const [selectionSet, setSelectionSet] = useState<Set<T>>(new Set(input.defaultSelection || []));\n\n useDidUpdate(() => {\n if (input.resetSelectionOnDataChange) {\n setSelectionSet(new Set());\n }\n }, [input.data, input.resetSelectionOnDataChange]);\n\n const select = useCallback((selected: T) => {\n setSelectionSet((state) => {\n if (!state.has(selected)) {\n const newSet = new Set(state);\n newSet.add(selected);\n return newSet;\n }\n return state;\n });\n }, []);\n\n const deselect = useCallback((deselected: T) => {\n setSelectionSet((state) => {\n if (state.has(deselected)) {\n const newSet = new Set(state);\n newSet.delete(deselected);\n return newSet;\n }\n return state;\n });\n }, []);\n\n const toggle = useCallback((toggled: T) => {\n setSelectionSet((state) => {\n const newSet = new Set(state);\n if (state.has(toggled)) {\n newSet.delete(toggled);\n } else {\n newSet.add(toggled);\n }\n return newSet;\n });\n }, []);\n\n const resetSelection = useCallback(() => {\n setSelectionSet(new Set());\n }, []);\n\n const setSelection = useCallback((selection: T[]) => {\n setSelectionSet(new Set(selection));\n }, []);\n\n const isAllSelected = useCallback(() => {\n if (input.data.length === 0) {\n return false;\n }\n return input.data.every((item) => selectionSet.has(item));\n }, [selectionSet, input.data]);\n\n const isSomeSelected = useCallback(() => {\n return input.data.some((item) => selectionSet.has(item));\n }, [selectionSet, input.data]);\n\n return [\n Array.from(selectionSet),\n {\n select,\n deselect,\n toggle,\n isAllSelected,\n isSomeSelected,\n setSelection,\n resetSelection,\n },\n ];\n}\n\nexport namespace useSelection {\n export type Input<T> = UseSelectionInput<T>;\n export type Handlers<T> = UseSelectionHandlers<T>;\n export type ReturnValue<T> = UseSelectionReturnValue<T>;\n}\n"],"mappings":";;;;AAuCA,SAAgB,aAAgB,OAAyD;CACvF,MAAM,CAAC,cAAc,mBAAmB,SAAiB,IAAI,IAAI,MAAM,oBAAoB,CAAC,CAAC,CAAC;CAE9F,mBAAmB;EACjB,IAAI,MAAM,4BACR,gCAAgB,IAAI,IAAI,CAAC;CAE7B,GAAG,CAAC,MAAM,MAAM,MAAM,0BAA0B,CAAC;CAEjD,MAAM,SAAS,aAAa,aAAgB;EAC1C,iBAAiB,UAAU;GACzB,IAAI,CAAC,MAAM,IAAI,QAAQ,GAAG;IACxB,MAAM,SAAS,IAAI,IAAI,KAAK;IAC5B,OAAO,IAAI,QAAQ;IACnB,OAAO;GACT;GACA,OAAO;EACT,CAAC;CACH,GAAG,CAAC,CAAC;CAEL,MAAM,WAAW,aAAa,eAAkB;EAC9C,iBAAiB,UAAU;GACzB,IAAI,MAAM,IAAI,UAAU,GAAG;IACzB,MAAM,SAAS,IAAI,IAAI,KAAK;IAC5B,OAAO,OAAO,UAAU;IACxB,OAAO;GACT;GACA,OAAO;EACT,CAAC;CACH,GAAG,CAAC,CAAC;CAEL,MAAM,SAAS,aAAa,YAAe;EACzC,iBAAiB,UAAU;GACzB,MAAM,SAAS,IAAI,IAAI,KAAK;GAC5B,IAAI,MAAM,IAAI,OAAO,GACnB,OAAO,OAAO,OAAO;QAErB,OAAO,IAAI,OAAO;GAEpB,OAAO;EACT,CAAC;CACH,GAAG,CAAC,CAAC;CAEL,MAAM,iBAAiB,kBAAkB;EACvC,gCAAgB,IAAI,IAAI,CAAC;CAC3B,GAAG,CAAC,CAAC;CAEL,MAAM,eAAe,aAAa,cAAmB;EACnD,gBAAgB,IAAI,IAAI,SAAS,CAAC;CACpC,GAAG,CAAC,CAAC;CAEL,MAAM,gBAAgB,kBAAkB;EACtC,IAAI,MAAM,KAAK,WAAW,GACxB,OAAO;EAET,OAAO,MAAM,KAAK,OAAO,SAAS,aAAa,IAAI,IAAI,CAAC;CAC1D,GAAG,CAAC,cAAc,MAAM,IAAI,CAAC;CAE7B,MAAM,iBAAiB,kBAAkB;EACvC,OAAO,MAAM,KAAK,MAAM,SAAS,aAAa,IAAI,IAAI,CAAC;CACzD,GAAG,CAAC,cAAc,MAAM,IAAI,CAAC;CAE7B,OAAO,CACL,MAAM,KAAK,YAAY,GACvB;EACE;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-session-storage.mjs","names":[],"sources":["../../src/use-session-storage/use-session-storage.ts"],"sourcesContent":["import {\n createStorage,\n readValue,\n UseStorageOptions,\n UseStorageReturnValue,\n} from '../use-local-storage/create-storage';\n\nexport function useSessionStorage<T = string>(\n props: UseStorageOptions<T> & { defaultValue: T }\n): UseStorageReturnValue<T>;\nexport function useSessionStorage<T = string>(\n props: UseStorageOptions<T>\n): UseStorageReturnValue<T | undefined>;\nexport function useSessionStorage<T = string>(props: UseStorageOptions<T>) {\n return createStorage<T>('sessionStorage', 'use-session-storage')(props);\n}\n\ninterface ReadStorageValue {\n <T>(options: UseStorageOptions<T> & { defaultValue: T }): T;\n <T>(options: UseStorageOptions<T>): T | undefined;\n}\n\nexport const readSessionStorageValue: ReadStorageValue = readValue('sessionStorage');\n"],"mappings":";;;AAaA,SAAgB,kBAA8B,OAA6B;
|
|
1
|
+
{"version":3,"file":"use-session-storage.mjs","names":[],"sources":["../../src/use-session-storage/use-session-storage.ts"],"sourcesContent":["import {\n createStorage,\n readValue,\n UseStorageOptions,\n UseStorageReturnValue,\n} from '../use-local-storage/create-storage';\n\nexport function useSessionStorage<T = string>(\n props: UseStorageOptions<T> & { defaultValue: T }\n): UseStorageReturnValue<T>;\nexport function useSessionStorage<T = string>(\n props: UseStorageOptions<T>\n): UseStorageReturnValue<T | undefined>;\nexport function useSessionStorage<T = string>(props: UseStorageOptions<T>) {\n return createStorage<T>('sessionStorage', 'use-session-storage')(props);\n}\n\ninterface ReadStorageValue {\n <T>(options: UseStorageOptions<T> & { defaultValue: T }): T;\n <T>(options: UseStorageOptions<T>): T | undefined;\n}\n\nexport const readSessionStorageValue: ReadStorageValue = readValue('sessionStorage');\n"],"mappings":";;;AAaA,SAAgB,kBAA8B,OAA6B;CACzE,OAAO,cAAiB,kBAAkB,qBAAqB,EAAE,KAAK;AACxE;AAOA,MAAa,0BAA4C,UAAU,gBAAgB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-set.mjs","names":[],"sources":["../../src/use-set/use-set.ts"],"sourcesContent":["import { useRef } from 'react';\nimport { useForceUpdate } from '../use-force-update/use-force-update';\n\nexport function readonlySetLikeToSet<T>(input: ReadonlySetLike<T>): Set<T> {\n if (input instanceof Set) {\n return input;\n }\n const result = new Set<T>();\n const iterator = input.keys();\n let next = iterator.next();\n while (!next.done) {\n result.add(next.value);\n next = iterator.next();\n }\n return result;\n}\n\nexport function useSet<T>(values?: T[]): Set<T> {\n const setRef = useRef(new Set(values));\n const forceUpdate = useForceUpdate();\n\n setRef.current.add = (...args) => {\n const res = Set.prototype.add.apply(setRef.current, args);\n forceUpdate();\n return res;\n };\n\n setRef.current.clear = (...args) => {\n Set.prototype.clear.apply(setRef.current, args);\n forceUpdate();\n };\n\n setRef.current.delete = (...args) => {\n const res = Set.prototype.delete.apply(setRef.current, args);\n forceUpdate();\n return res;\n };\n\n setRef.current.union = <U>(other: ReadonlySetLike<U>): Set<T | U> => {\n const result = new Set<T | U>(setRef.current as Set<T>);\n readonlySetLikeToSet(other).forEach((item) => result.add(item));\n return result;\n };\n\n setRef.current.intersection = <U>(other: ReadonlySetLike<U>): Set<T & U> => {\n const result = new Set<T & U>();\n const otherSet = readonlySetLikeToSet(other);\n setRef.current.forEach((item) => {\n if (otherSet.has(item as any)) {\n result.add(item as T & U);\n }\n });\n return result;\n };\n\n setRef.current.difference = <U>(other: ReadonlySetLike<U>): Set<T> => {\n const result = new Set<T>();\n const otherSet = readonlySetLikeToSet(other);\n setRef.current.forEach((item) => {\n if (!otherSet.has(item as any)) {\n result.add(item);\n }\n });\n return result;\n };\n\n setRef.current.symmetricDifference = <U>(other: ReadonlySetLike<U>): Set<T | U> => {\n const result = new Set<T | U>();\n const otherSet = readonlySetLikeToSet(other);\n\n setRef.current.forEach((item) => {\n if (!otherSet.has(item as any)) {\n result.add(item);\n }\n });\n\n otherSet.forEach((item) => {\n if (!setRef.current.has(item as any)) {\n result.add(item);\n }\n });\n\n return result;\n };\n\n return setRef.current;\n}\n"],"mappings":";;;;AAGA,SAAgB,qBAAwB,OAAmC;
|
|
1
|
+
{"version":3,"file":"use-set.mjs","names":[],"sources":["../../src/use-set/use-set.ts"],"sourcesContent":["import { useRef } from 'react';\nimport { useForceUpdate } from '../use-force-update/use-force-update';\n\nexport function readonlySetLikeToSet<T>(input: ReadonlySetLike<T>): Set<T> {\n if (input instanceof Set) {\n return input;\n }\n const result = new Set<T>();\n const iterator = input.keys();\n let next = iterator.next();\n while (!next.done) {\n result.add(next.value);\n next = iterator.next();\n }\n return result;\n}\n\nexport function useSet<T>(values?: T[]): Set<T> {\n const setRef = useRef(new Set(values));\n const forceUpdate = useForceUpdate();\n\n setRef.current.add = (...args) => {\n const res = Set.prototype.add.apply(setRef.current, args);\n forceUpdate();\n return res;\n };\n\n setRef.current.clear = (...args) => {\n Set.prototype.clear.apply(setRef.current, args);\n forceUpdate();\n };\n\n setRef.current.delete = (...args) => {\n const res = Set.prototype.delete.apply(setRef.current, args);\n forceUpdate();\n return res;\n };\n\n setRef.current.union = <U>(other: ReadonlySetLike<U>): Set<T | U> => {\n const result = new Set<T | U>(setRef.current as Set<T>);\n readonlySetLikeToSet(other).forEach((item) => result.add(item));\n return result;\n };\n\n setRef.current.intersection = <U>(other: ReadonlySetLike<U>): Set<T & U> => {\n const result = new Set<T & U>();\n const otherSet = readonlySetLikeToSet(other);\n setRef.current.forEach((item) => {\n if (otherSet.has(item as any)) {\n result.add(item as T & U);\n }\n });\n return result;\n };\n\n setRef.current.difference = <U>(other: ReadonlySetLike<U>): Set<T> => {\n const result = new Set<T>();\n const otherSet = readonlySetLikeToSet(other);\n setRef.current.forEach((item) => {\n if (!otherSet.has(item as any)) {\n result.add(item);\n }\n });\n return result;\n };\n\n setRef.current.symmetricDifference = <U>(other: ReadonlySetLike<U>): Set<T | U> => {\n const result = new Set<T | U>();\n const otherSet = readonlySetLikeToSet(other);\n\n setRef.current.forEach((item) => {\n if (!otherSet.has(item as any)) {\n result.add(item);\n }\n });\n\n otherSet.forEach((item) => {\n if (!setRef.current.has(item as any)) {\n result.add(item);\n }\n });\n\n return result;\n };\n\n return setRef.current;\n}\n"],"mappings":";;;;AAGA,SAAgB,qBAAwB,OAAmC;CACzE,IAAI,iBAAiB,KACnB,OAAO;CAET,MAAM,yBAAS,IAAI,IAAO;CAC1B,MAAM,WAAW,MAAM,KAAK;CAC5B,IAAI,OAAO,SAAS,KAAK;CACzB,OAAO,CAAC,KAAK,MAAM;EACjB,OAAO,IAAI,KAAK,KAAK;EACrB,OAAO,SAAS,KAAK;CACvB;CACA,OAAO;AACT;AAEA,SAAgB,OAAU,QAAsB;CAC9C,MAAM,SAAS,OAAO,IAAI,IAAI,MAAM,CAAC;CACrC,MAAM,cAAc,eAAe;CAEnC,OAAO,QAAQ,OAAO,GAAG,SAAS;EAChC,MAAM,MAAM,IAAI,UAAU,IAAI,MAAM,OAAO,SAAS,IAAI;EACxD,YAAY;EACZ,OAAO;CACT;CAEA,OAAO,QAAQ,SAAS,GAAG,SAAS;EAClC,IAAI,UAAU,MAAM,MAAM,OAAO,SAAS,IAAI;EAC9C,YAAY;CACd;CAEA,OAAO,QAAQ,UAAU,GAAG,SAAS;EACnC,MAAM,MAAM,IAAI,UAAU,OAAO,MAAM,OAAO,SAAS,IAAI;EAC3D,YAAY;EACZ,OAAO;CACT;CAEA,OAAO,QAAQ,SAAY,UAA0C;EACnE,MAAM,SAAS,IAAI,IAAW,OAAO,OAAiB;EACtD,qBAAqB,KAAK,EAAE,SAAS,SAAS,OAAO,IAAI,IAAI,CAAC;EAC9D,OAAO;CACT;CAEA,OAAO,QAAQ,gBAAmB,UAA0C;EAC1E,MAAM,yBAAS,IAAI,IAAW;EAC9B,MAAM,WAAW,qBAAqB,KAAK;EAC3C,OAAO,QAAQ,SAAS,SAAS;GAC/B,IAAI,SAAS,IAAI,IAAW,GAC1B,OAAO,IAAI,IAAa;EAE5B,CAAC;EACD,OAAO;CACT;CAEA,OAAO,QAAQ,cAAiB,UAAsC;EACpE,MAAM,yBAAS,IAAI,IAAO;EAC1B,MAAM,WAAW,qBAAqB,KAAK;EAC3C,OAAO,QAAQ,SAAS,SAAS;GAC/B,IAAI,CAAC,SAAS,IAAI,IAAW,GAC3B,OAAO,IAAI,IAAI;EAEnB,CAAC;EACD,OAAO;CACT;CAEA,OAAO,QAAQ,uBAA0B,UAA0C;EACjF,MAAM,yBAAS,IAAI,IAAW;EAC9B,MAAM,WAAW,qBAAqB,KAAK;EAE3C,OAAO,QAAQ,SAAS,SAAS;GAC/B,IAAI,CAAC,SAAS,IAAI,IAAW,GAC3B,OAAO,IAAI,IAAI;EAEnB,CAAC;EAED,SAAS,SAAS,SAAS;GACzB,IAAI,CAAC,OAAO,QAAQ,IAAI,IAAW,GACjC,OAAO,IAAI,IAAI;EAEnB,CAAC;EAED,OAAO;CACT;CAEA,OAAO,OAAO;AAChB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-set-state.mjs","names":[],"sources":["../../src/use-set-state/use-set-state.ts"],"sourcesContent":["import { useCallback, useState } from 'react';\n\nexport type UseSetStateCallback<T> = (\n state: Partial<T> | ((currentState: T) => Partial<T>)\n) => void;\n\nexport type UseSetStateReturnValue<T> = [T, UseSetStateCallback<T>];\n\nexport function useSetState<T extends Record<string, any>>(\n initialState: T\n): UseSetStateReturnValue<T> {\n const [state, setState] = useState(initialState);\n\n const _setState: UseSetStateCallback<T> = useCallback(\n (statePartial) =>\n setState((current) => ({\n ...current,\n ...(typeof statePartial === 'function' ? statePartial(current) : statePartial),\n })),\n []\n );\n\n return [state, _setState];\n}\n\nexport namespace useSetState {\n export type Callback<T> = UseSetStateCallback<T>;\n export type ReturnValue<T> = UseSetStateReturnValue<T>;\n}\n"],"mappings":";;;AAQA,SAAgB,YACd,cAC2B;CAC3B,MAAM,CAAC,OAAO,YAAY,SAAS,
|
|
1
|
+
{"version":3,"file":"use-set-state.mjs","names":[],"sources":["../../src/use-set-state/use-set-state.ts"],"sourcesContent":["import { useCallback, useState } from 'react';\n\nexport type UseSetStateCallback<T> = (\n state: Partial<T> | ((currentState: T) => Partial<T>)\n) => void;\n\nexport type UseSetStateReturnValue<T> = [T, UseSetStateCallback<T>];\n\nexport function useSetState<T extends Record<string, any>>(\n initialState: T\n): UseSetStateReturnValue<T> {\n const [state, setState] = useState(initialState);\n\n const _setState: UseSetStateCallback<T> = useCallback(\n (statePartial) =>\n setState((current) => ({\n ...current,\n ...(typeof statePartial === 'function' ? statePartial(current) : statePartial),\n })),\n []\n );\n\n return [state, _setState];\n}\n\nexport namespace useSetState {\n export type Callback<T> = UseSetStateCallback<T>;\n export type ReturnValue<T> = UseSetStateReturnValue<T>;\n}\n"],"mappings":";;;AAQA,SAAgB,YACd,cAC2B;CAC3B,MAAM,CAAC,OAAO,YAAY,SAAS,YAAY;CAW/C,OAAO,CAAC,OATkC,aACvC,iBACC,UAAU,aAAa;EACrB,GAAG;EACH,GAAI,OAAO,iBAAiB,aAAa,aAAa,OAAO,IAAI;CACnE,EAAE,GACJ,CAAC,CAGoB,CAAC;AAC1B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-shallow-effect.mjs","names":[],"sources":["../../src/use-shallow-effect/use-shallow-effect.ts"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport { shallowEqual } from '../utils/shallow-equal/shallow-equal';\n\nfunction shallowCompare(prevValue?: React.DependencyList | null, currValue?: React.DependencyList) {\n if (!prevValue || !currValue) {\n return false;\n }\n\n if (prevValue === currValue) {\n return true;\n }\n\n if (prevValue.length !== currValue.length) {\n return false;\n }\n\n for (let i = 0; i < prevValue.length; i += 1) {\n if (!shallowEqual(prevValue[i], currValue[i])) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction useShallowCompare(dependencies?: React.DependencyList) {\n const ref = useRef<React.DependencyList | null | undefined>([]);\n const updateRef = useRef<number>(0);\n\n if (!shallowCompare(ref.current, dependencies)) {\n ref.current = dependencies;\n updateRef.current += 1;\n }\n\n return [updateRef.current];\n}\n\nexport function useShallowEffect(cb: () => void, dependencies?: React.DependencyList): void {\n useEffect(cb, useShallowCompare(dependencies));\n}\n"],"mappings":";;;;AAGA,SAAS,eAAe,WAAyC,WAAkC;
|
|
1
|
+
{"version":3,"file":"use-shallow-effect.mjs","names":[],"sources":["../../src/use-shallow-effect/use-shallow-effect.ts"],"sourcesContent":["import { useEffect, useRef } from 'react';\nimport { shallowEqual } from '../utils/shallow-equal/shallow-equal';\n\nfunction shallowCompare(prevValue?: React.DependencyList | null, currValue?: React.DependencyList) {\n if (!prevValue || !currValue) {\n return false;\n }\n\n if (prevValue === currValue) {\n return true;\n }\n\n if (prevValue.length !== currValue.length) {\n return false;\n }\n\n for (let i = 0; i < prevValue.length; i += 1) {\n if (!shallowEqual(prevValue[i], currValue[i])) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction useShallowCompare(dependencies?: React.DependencyList) {\n const ref = useRef<React.DependencyList | null | undefined>([]);\n const updateRef = useRef<number>(0);\n\n if (!shallowCompare(ref.current, dependencies)) {\n ref.current = dependencies;\n updateRef.current += 1;\n }\n\n return [updateRef.current];\n}\n\nexport function useShallowEffect(cb: () => void, dependencies?: React.DependencyList): void {\n useEffect(cb, useShallowCompare(dependencies));\n}\n"],"mappings":";;;;AAGA,SAAS,eAAe,WAAyC,WAAkC;CACjG,IAAI,CAAC,aAAa,CAAC,WACjB,OAAO;CAGT,IAAI,cAAc,WAChB,OAAO;CAGT,IAAI,UAAU,WAAW,UAAU,QACjC,OAAO;CAGT,KAAK,IAAI,IAAI,GAAG,IAAI,UAAU,QAAQ,KAAK,GACzC,IAAI,CAAC,aAAa,UAAU,IAAI,UAAU,EAAE,GAC1C,OAAO;CAIX,OAAO;AACT;AAEA,SAAS,kBAAkB,cAAqC;CAC9D,MAAM,MAAM,OAAgD,CAAC,CAAC;CAC9D,MAAM,YAAY,OAAe,CAAC;CAElC,IAAI,CAAC,eAAe,IAAI,SAAS,YAAY,GAAG;EAC9C,IAAI,UAAU;EACd,UAAU,WAAW;CACvB;CAEA,OAAO,CAAC,UAAU,OAAO;AAC3B;AAEA,SAAgB,iBAAiB,IAAgB,cAA2C;CAC1F,UAAU,IAAI,kBAAkB,YAAY,CAAC;AAC/C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-state-history.mjs","names":[],"sources":["../../src/use-state-history/use-state-history.ts"],"sourcesContent":["import { useCallback, useMemo, useState } from 'react';\n\nexport interface UseStateHistoryHandlers<T> {\n set: (value: T) => void;\n back: (steps?: number) => void;\n forward: (steps?: number) => void;\n reset: () => void;\n}\n\nexport interface UseStateHistoryValue<T> {\n history: T[];\n current: number;\n}\n\nexport type UseStateHistoryReturnValue<T> = [\n T,\n UseStateHistoryHandlers<T>,\n UseStateHistoryValue<T>,\n];\n\nexport function useStateHistory<T>(initialValue: T): UseStateHistoryReturnValue<T> {\n const [state, setState] = useState<UseStateHistoryValue<T>>({\n history: [initialValue],\n current: 0,\n });\n\n const set = useCallback(\n (val: T) =>\n setState((currentState) => {\n const nextState = [...currentState.history.slice(0, currentState.current + 1), val];\n return {\n history: nextState,\n current: nextState.length - 1,\n };\n }),\n []\n );\n\n const back = useCallback(\n (steps = 1) =>\n setState((currentState) => ({\n history: currentState.history,\n current: Math.max(0, currentState.current - steps),\n })),\n []\n );\n\n const forward = useCallback(\n (steps = 1) =>\n setState((currentState) => ({\n history: currentState.history,\n current: Math.min(currentState.history.length - 1, currentState.current + steps),\n })),\n []\n );\n\n const reset = useCallback(() => {\n setState({ history: [initialValue], current: 0 });\n }, [initialValue]);\n\n const handlers = useMemo(() => ({ back, forward, reset, set }), [back, forward, reset, set]);\n\n return [state.history[state.current], handlers, state];\n}\n\nexport namespace useStateHistory {\n export type Handlers<T> = UseStateHistoryHandlers<T>;\n export type Value<T> = UseStateHistoryValue<T>;\n export type ReturnValue<T> = UseStateHistoryReturnValue<T>;\n}\n"],"mappings":";;;AAoBA,SAAgB,gBAAmB,cAAgD;CACjF,MAAM,CAAC,OAAO,YAAY,SAAkC;EAC1D,SAAS,CAAC,
|
|
1
|
+
{"version":3,"file":"use-state-history.mjs","names":[],"sources":["../../src/use-state-history/use-state-history.ts"],"sourcesContent":["import { useCallback, useMemo, useState } from 'react';\n\nexport interface UseStateHistoryHandlers<T> {\n set: (value: T) => void;\n back: (steps?: number) => void;\n forward: (steps?: number) => void;\n reset: () => void;\n}\n\nexport interface UseStateHistoryValue<T> {\n history: T[];\n current: number;\n}\n\nexport type UseStateHistoryReturnValue<T> = [\n T,\n UseStateHistoryHandlers<T>,\n UseStateHistoryValue<T>,\n];\n\nexport function useStateHistory<T>(initialValue: T): UseStateHistoryReturnValue<T> {\n const [state, setState] = useState<UseStateHistoryValue<T>>({\n history: [initialValue],\n current: 0,\n });\n\n const set = useCallback(\n (val: T) =>\n setState((currentState) => {\n const nextState = [...currentState.history.slice(0, currentState.current + 1), val];\n return {\n history: nextState,\n current: nextState.length - 1,\n };\n }),\n []\n );\n\n const back = useCallback(\n (steps = 1) =>\n setState((currentState) => ({\n history: currentState.history,\n current: Math.max(0, currentState.current - steps),\n })),\n []\n );\n\n const forward = useCallback(\n (steps = 1) =>\n setState((currentState) => ({\n history: currentState.history,\n current: Math.min(currentState.history.length - 1, currentState.current + steps),\n })),\n []\n );\n\n const reset = useCallback(() => {\n setState({ history: [initialValue], current: 0 });\n }, [initialValue]);\n\n const handlers = useMemo(() => ({ back, forward, reset, set }), [back, forward, reset, set]);\n\n return [state.history[state.current], handlers, state];\n}\n\nexport namespace useStateHistory {\n export type Handlers<T> = UseStateHistoryHandlers<T>;\n export type Value<T> = UseStateHistoryValue<T>;\n export type ReturnValue<T> = UseStateHistoryReturnValue<T>;\n}\n"],"mappings":";;;AAoBA,SAAgB,gBAAmB,cAAgD;CACjF,MAAM,CAAC,OAAO,YAAY,SAAkC;EAC1D,SAAS,CAAC,YAAY;EACtB,SAAS;CACX,CAAC;CAED,MAAM,MAAM,aACT,QACC,UAAU,iBAAiB;EACzB,MAAM,YAAY,CAAC,GAAG,aAAa,QAAQ,MAAM,GAAG,aAAa,UAAU,CAAC,GAAG,GAAG;EAClF,OAAO;GACL,SAAS;GACT,SAAS,UAAU,SAAS;EAC9B;CACF,CAAC,GACH,CAAC,CACH;CAEA,MAAM,OAAO,aACV,QAAQ,MACP,UAAU,kBAAkB;EAC1B,SAAS,aAAa;EACtB,SAAS,KAAK,IAAI,GAAG,aAAa,UAAU,KAAK;CACnD,EAAE,GACJ,CAAC,CACH;CAEA,MAAM,UAAU,aACb,QAAQ,MACP,UAAU,kBAAkB;EAC1B,SAAS,aAAa;EACtB,SAAS,KAAK,IAAI,aAAa,QAAQ,SAAS,GAAG,aAAa,UAAU,KAAK;CACjF,EAAE,GACJ,CAAC,CACH;CAEA,MAAM,QAAQ,kBAAkB;EAC9B,SAAS;GAAE,SAAS,CAAC,YAAY;GAAG,SAAS;EAAE,CAAC;CAClD,GAAG,CAAC,YAAY,CAAC;CAEjB,MAAM,WAAW,eAAe;EAAE;EAAM;EAAS;EAAO;CAAI,IAAI;EAAC;EAAM;EAAS;EAAO;CAAG,CAAC;CAE3F,OAAO;EAAC,MAAM,QAAQ,MAAM;EAAU;EAAU;CAAK;AACvD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-text-selection.mjs","names":[],"sources":["../../src/use-text-selection/use-text-selection.ts"],"sourcesContent":["import { useEffect, useEffectEvent, useState } from 'react';\nimport { useForceUpdate } from '../use-force-update/use-force-update';\n\nexport function useTextSelection(): Selection | null {\n const forceUpdate = useForceUpdate();\n const [selection, setSelection] = useState<Selection | null>(null);\n\n const handleSelectionChange = useEffectEvent(() => {\n setSelection(document.getSelection());\n forceUpdate();\n });\n\n useEffect(() => {\n setSelection(document.getSelection());\n document.addEventListener('selectionchange', handleSelectionChange);\n return () => document.removeEventListener('selectionchange', handleSelectionChange);\n }, []);\n\n return selection;\n}\n"],"mappings":";;;;AAGA,SAAgB,mBAAqC;CACnD,MAAM,cAAc,
|
|
1
|
+
{"version":3,"file":"use-text-selection.mjs","names":[],"sources":["../../src/use-text-selection/use-text-selection.ts"],"sourcesContent":["import { useEffect, useEffectEvent, useState } from 'react';\nimport { useForceUpdate } from '../use-force-update/use-force-update';\n\nexport function useTextSelection(): Selection | null {\n const forceUpdate = useForceUpdate();\n const [selection, setSelection] = useState<Selection | null>(null);\n\n const handleSelectionChange = useEffectEvent(() => {\n setSelection(document.getSelection());\n forceUpdate();\n });\n\n useEffect(() => {\n setSelection(document.getSelection());\n document.addEventListener('selectionchange', handleSelectionChange);\n return () => document.removeEventListener('selectionchange', handleSelectionChange);\n }, []);\n\n return selection;\n}\n"],"mappings":";;;;AAGA,SAAgB,mBAAqC;CACnD,MAAM,cAAc,eAAe;CACnC,MAAM,CAAC,WAAW,gBAAgB,SAA2B,IAAI;CAEjE,MAAM,wBAAwB,qBAAqB;EACjD,aAAa,SAAS,aAAa,CAAC;EACpC,YAAY;CACd,CAAC;CAED,gBAAgB;EACd,aAAa,SAAS,aAAa,CAAC;EACpC,SAAS,iBAAiB,mBAAmB,qBAAqB;EAClE,aAAa,SAAS,oBAAoB,mBAAmB,qBAAqB;CACpF,GAAG,CAAC,CAAC;CAEL,OAAO;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-throttled-callback.mjs","names":[],"sources":["../../src/use-throttled-callback/use-throttled-callback.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nimport { useCallbackRef } from '../utils';\n\nexport function useThrottledCallbackWithClearTimeout<T extends (...args: any[]) => any>(\n callback: T,\n wait: number\n) {\n const handleCallback = useCallbackRef(callback);\n const latestInArgsRef = useRef<Parameters<T>>(null);\n const latestOutArgsRef = useRef<Parameters<T>>(null);\n const active = useRef(true);\n const waitRef = useRef(wait);\n const timeoutRef = useRef<number>(-1);\n\n const clearTimeout = () => window.clearTimeout(timeoutRef.current);\n\n const callThrottledCallback = useCallback(\n (...args: Parameters<T>) => {\n handleCallback(...args);\n latestInArgsRef.current = args;\n latestOutArgsRef.current = args;\n active.current = false;\n },\n [handleCallback]\n );\n\n const timerCallback = useCallback(() => {\n if (latestInArgsRef.current && latestInArgsRef.current !== latestOutArgsRef.current) {\n callThrottledCallback(...latestInArgsRef.current);\n\n timeoutRef.current = window.setTimeout(timerCallback, waitRef.current);\n } else {\n active.current = true;\n }\n }, [callThrottledCallback]);\n\n const throttled = useCallback(\n (...args: Parameters<T>) => {\n if (active.current) {\n callThrottledCallback(...args);\n timeoutRef.current = window.setTimeout(timerCallback, waitRef.current);\n } else {\n latestInArgsRef.current = args;\n }\n },\n [callThrottledCallback, timerCallback]\n );\n\n useEffect(() => {\n waitRef.current = wait;\n }, [wait]);\n\n return [throttled, clearTimeout] as const;\n}\n\nexport function useThrottledCallback<T extends (...args: any[]) => any>(callback: T, wait: number) {\n const [throttled, clearTimeout] = useThrottledCallbackWithClearTimeout(callback, wait);\n useEffect(() => clearTimeout, []);\n return throttled;\n}\n"],"mappings":";;;;AAGA,SAAgB,qCACd,UACA,MACA;CACA,MAAM,iBAAiB,eAAe,
|
|
1
|
+
{"version":3,"file":"use-throttled-callback.mjs","names":[],"sources":["../../src/use-throttled-callback/use-throttled-callback.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nimport { useCallbackRef } from '../utils';\n\nexport function useThrottledCallbackWithClearTimeout<T extends (...args: any[]) => any>(\n callback: T,\n wait: number\n) {\n const handleCallback = useCallbackRef(callback);\n const latestInArgsRef = useRef<Parameters<T>>(null);\n const latestOutArgsRef = useRef<Parameters<T>>(null);\n const active = useRef(true);\n const waitRef = useRef(wait);\n const timeoutRef = useRef<number>(-1);\n\n const clearTimeout = () => window.clearTimeout(timeoutRef.current);\n\n const callThrottledCallback = useCallback(\n (...args: Parameters<T>) => {\n handleCallback(...args);\n latestInArgsRef.current = args;\n latestOutArgsRef.current = args;\n active.current = false;\n },\n [handleCallback]\n );\n\n const timerCallback = useCallback(() => {\n if (latestInArgsRef.current && latestInArgsRef.current !== latestOutArgsRef.current) {\n callThrottledCallback(...latestInArgsRef.current);\n\n timeoutRef.current = window.setTimeout(timerCallback, waitRef.current);\n } else {\n active.current = true;\n }\n }, [callThrottledCallback]);\n\n const throttled = useCallback(\n (...args: Parameters<T>) => {\n if (active.current) {\n callThrottledCallback(...args);\n timeoutRef.current = window.setTimeout(timerCallback, waitRef.current);\n } else {\n latestInArgsRef.current = args;\n }\n },\n [callThrottledCallback, timerCallback]\n );\n\n useEffect(() => {\n waitRef.current = wait;\n }, [wait]);\n\n return [throttled, clearTimeout] as const;\n}\n\nexport function useThrottledCallback<T extends (...args: any[]) => any>(callback: T, wait: number) {\n const [throttled, clearTimeout] = useThrottledCallbackWithClearTimeout(callback, wait);\n useEffect(() => clearTimeout, []);\n return throttled;\n}\n"],"mappings":";;;;AAGA,SAAgB,qCACd,UACA,MACA;CACA,MAAM,iBAAiB,eAAe,QAAQ;CAC9C,MAAM,kBAAkB,OAAsB,IAAI;CAClD,MAAM,mBAAmB,OAAsB,IAAI;CACnD,MAAM,SAAS,OAAO,IAAI;CAC1B,MAAM,UAAU,OAAO,IAAI;CAC3B,MAAM,aAAa,OAAe,EAAE;CAEpC,MAAM,qBAAqB,OAAO,aAAa,WAAW,OAAO;CAEjE,MAAM,wBAAwB,aAC3B,GAAG,SAAwB;EAC1B,eAAe,GAAG,IAAI;EACtB,gBAAgB,UAAU;EAC1B,iBAAiB,UAAU;EAC3B,OAAO,UAAU;CACnB,GACA,CAAC,cAAc,CACjB;CAEA,MAAM,gBAAgB,kBAAkB;EACtC,IAAI,gBAAgB,WAAW,gBAAgB,YAAY,iBAAiB,SAAS;GACnF,sBAAsB,GAAG,gBAAgB,OAAO;GAEhD,WAAW,UAAU,OAAO,WAAW,eAAe,QAAQ,OAAO;EACvE,OACE,OAAO,UAAU;CAErB,GAAG,CAAC,qBAAqB,CAAC;CAE1B,MAAM,YAAY,aACf,GAAG,SAAwB;EAC1B,IAAI,OAAO,SAAS;GAClB,sBAAsB,GAAG,IAAI;GAC7B,WAAW,UAAU,OAAO,WAAW,eAAe,QAAQ,OAAO;EACvE,OACE,gBAAgB,UAAU;CAE9B,GACA,CAAC,uBAAuB,aAAa,CACvC;CAEA,gBAAgB;EACd,QAAQ,UAAU;CACpB,GAAG,CAAC,IAAI,CAAC;CAET,OAAO,CAAC,WAAW,YAAY;AACjC;AAEA,SAAgB,qBAAwD,UAAa,MAAc;CACjG,MAAM,CAAC,WAAW,gBAAgB,qCAAqC,UAAU,IAAI;CACrF,gBAAgB,cAAc,CAAC,CAAC;CAChC,OAAO;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-throttled-state.mjs","names":[],"sources":["../../src/use-throttled-state/use-throttled-state.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { useThrottledCallbackWithClearTimeout } from '../use-throttled-callback/use-throttled-callback';\n\nexport function useThrottledState<T = any>(defaultValue: T, wait: number) {\n const [value, setValue] = useState(defaultValue);\n\n const [setThrottledValue, clearTimeout] = useThrottledCallbackWithClearTimeout(setValue, wait);\n\n useEffect(() => clearTimeout, []);\n\n return [value, setThrottledValue] as const;\n}\n"],"mappings":";;;;AAGA,SAAgB,kBAA2B,cAAiB,MAAc;CACxE,MAAM,CAAC,OAAO,YAAY,SAAS,
|
|
1
|
+
{"version":3,"file":"use-throttled-state.mjs","names":[],"sources":["../../src/use-throttled-state/use-throttled-state.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { useThrottledCallbackWithClearTimeout } from '../use-throttled-callback/use-throttled-callback';\n\nexport function useThrottledState<T = any>(defaultValue: T, wait: number) {\n const [value, setValue] = useState(defaultValue);\n\n const [setThrottledValue, clearTimeout] = useThrottledCallbackWithClearTimeout(setValue, wait);\n\n useEffect(() => clearTimeout, []);\n\n return [value, setThrottledValue] as const;\n}\n"],"mappings":";;;;AAGA,SAAgB,kBAA2B,cAAiB,MAAc;CACxE,MAAM,CAAC,OAAO,YAAY,SAAS,YAAY;CAE/C,MAAM,CAAC,mBAAmB,gBAAgB,qCAAqC,UAAU,IAAI;CAE7F,gBAAgB,cAAc,CAAC,CAAC;CAEhC,OAAO,CAAC,OAAO,iBAAiB;AAClC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-throttled-value.mjs","names":[],"sources":["../../src/use-throttled-value/use-throttled-value.ts"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport { useThrottledCallbackWithClearTimeout } from '../use-throttled-callback/use-throttled-callback';\n\nexport function useThrottledValue<T>(value: T, wait: number) {\n const [throttledValue, setThrottledValue] = useState(value);\n const valueRef = useRef(value);\n\n const [throttledSetValue, clearTimeout] = useThrottledCallbackWithClearTimeout(\n setThrottledValue,\n wait\n );\n\n useEffect(() => {\n if (value !== valueRef.current) {\n valueRef.current = value;\n throttledSetValue(value);\n }\n }, [throttledSetValue, value]);\n\n useEffect(() => clearTimeout, []);\n\n return throttledValue;\n}\n"],"mappings":";;;;AAGA,SAAgB,kBAAqB,OAAU,MAAc;CAC3D,MAAM,CAAC,gBAAgB,qBAAqB,SAAS,
|
|
1
|
+
{"version":3,"file":"use-throttled-value.mjs","names":[],"sources":["../../src/use-throttled-value/use-throttled-value.ts"],"sourcesContent":["import { useEffect, useRef, useState } from 'react';\nimport { useThrottledCallbackWithClearTimeout } from '../use-throttled-callback/use-throttled-callback';\n\nexport function useThrottledValue<T>(value: T, wait: number) {\n const [throttledValue, setThrottledValue] = useState(value);\n const valueRef = useRef(value);\n\n const [throttledSetValue, clearTimeout] = useThrottledCallbackWithClearTimeout(\n setThrottledValue,\n wait\n );\n\n useEffect(() => {\n if (value !== valueRef.current) {\n valueRef.current = value;\n throttledSetValue(value);\n }\n }, [throttledSetValue, value]);\n\n useEffect(() => clearTimeout, []);\n\n return throttledValue;\n}\n"],"mappings":";;;;AAGA,SAAgB,kBAAqB,OAAU,MAAc;CAC3D,MAAM,CAAC,gBAAgB,qBAAqB,SAAS,KAAK;CAC1D,MAAM,WAAW,OAAO,KAAK;CAE7B,MAAM,CAAC,mBAAmB,gBAAgB,qCACxC,mBACA,IACF;CAEA,gBAAgB;EACd,IAAI,UAAU,SAAS,SAAS;GAC9B,SAAS,UAAU;GACnB,kBAAkB,KAAK;EACzB;CACF,GAAG,CAAC,mBAAmB,KAAK,CAAC;CAE7B,gBAAgB,cAAc,CAAC,CAAC;CAEhC,OAAO;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-timeout.mjs","names":[],"sources":["../../src/use-timeout/use-timeout.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nimport { useCallbackRef } from '../utils';\n\nexport interface UseTimeoutOptions {\n autoInvoke: boolean;\n}\n\nexport interface UseTimeoutReturnValue {\n start: (...args: any[]) => void;\n clear: () => void;\n}\n\nexport function useTimeout(\n callback: (...args: any[]) => void,\n delay: number,\n options: UseTimeoutOptions = { autoInvoke: false }\n): UseTimeoutReturnValue {\n const timeoutRef = useRef<number | null>(null);\n const handleCallback = useCallbackRef(callback);\n\n const start = useCallback(\n (...args: any[]) => {\n if (!timeoutRef.current) {\n timeoutRef.current = window.setTimeout(() => {\n handleCallback(...args);\n timeoutRef.current = null;\n }, delay);\n }\n },\n [delay]\n );\n\n const clear = useCallback(() => {\n if (timeoutRef.current) {\n window.clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n }, []);\n\n useEffect(() => {\n if (options.autoInvoke) {\n start();\n }\n\n return clear;\n }, [clear, start]);\n\n return { start, clear };\n}\n\nexport namespace useTimeout {\n export type Options = UseTimeoutOptions;\n export type ReturnValue = UseTimeoutReturnValue;\n}\n"],"mappings":";;;;AAYA,SAAgB,WACd,UACA,OACA,UAA6B,EAAE,YAAY,
|
|
1
|
+
{"version":3,"file":"use-timeout.mjs","names":[],"sources":["../../src/use-timeout/use-timeout.ts"],"sourcesContent":["import { useCallback, useEffect, useRef } from 'react';\nimport { useCallbackRef } from '../utils';\n\nexport interface UseTimeoutOptions {\n autoInvoke: boolean;\n}\n\nexport interface UseTimeoutReturnValue {\n start: (...args: any[]) => void;\n clear: () => void;\n}\n\nexport function useTimeout(\n callback: (...args: any[]) => void,\n delay: number,\n options: UseTimeoutOptions = { autoInvoke: false }\n): UseTimeoutReturnValue {\n const timeoutRef = useRef<number | null>(null);\n const handleCallback = useCallbackRef(callback);\n\n const start = useCallback(\n (...args: any[]) => {\n if (!timeoutRef.current) {\n timeoutRef.current = window.setTimeout(() => {\n handleCallback(...args);\n timeoutRef.current = null;\n }, delay);\n }\n },\n [delay]\n );\n\n const clear = useCallback(() => {\n if (timeoutRef.current) {\n window.clearTimeout(timeoutRef.current);\n timeoutRef.current = null;\n }\n }, []);\n\n useEffect(() => {\n if (options.autoInvoke) {\n start();\n }\n\n return clear;\n }, [clear, start]);\n\n return { start, clear };\n}\n\nexport namespace useTimeout {\n export type Options = UseTimeoutOptions;\n export type ReturnValue = UseTimeoutReturnValue;\n}\n"],"mappings":";;;;AAYA,SAAgB,WACd,UACA,OACA,UAA6B,EAAE,YAAY,MAAM,GAC1B;CACvB,MAAM,aAAa,OAAsB,IAAI;CAC7C,MAAM,iBAAiB,eAAe,QAAQ;CAE9C,MAAM,QAAQ,aACX,GAAG,SAAgB;EAClB,IAAI,CAAC,WAAW,SACd,WAAW,UAAU,OAAO,iBAAiB;GAC3C,eAAe,GAAG,IAAI;GACtB,WAAW,UAAU;EACvB,GAAG,KAAK;CAEZ,GACA,CAAC,KAAK,CACR;CAEA,MAAM,QAAQ,kBAAkB;EAC9B,IAAI,WAAW,SAAS;GACtB,OAAO,aAAa,WAAW,OAAO;GACtC,WAAW,UAAU;EACvB;CACF,GAAG,CAAC,CAAC;CAEL,gBAAgB;EACd,IAAI,QAAQ,YACV,MAAM;EAGR,OAAO;CACT,GAAG,CAAC,OAAO,KAAK,CAAC;CAEjB,OAAO;EAAE;EAAO;CAAM;AACxB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-toggle.mjs","names":[],"sources":["../../src/use-toggle/use-toggle.ts"],"sourcesContent":["import { useReducer } from 'react';\n\ntype UseToggleAction<T> = (value?: React.SetStateAction<T>) => void;\nexport type UseToggleReturnValue<T> = [T, UseToggleAction<T>];\n\nexport function useToggle<T = boolean>(\n options: readonly T[] = [false, true] as any\n): UseToggleReturnValue<T> {\n const [[option], toggle] = useReducer((state: T[], action: React.SetStateAction<T>) => {\n const value = action instanceof Function ? action(state[0]) : action;\n const index = Math.abs(state.indexOf(value));\n\n return state.slice(index).concat(state.slice(0, index));\n }, options as T[]);\n\n return [option, toggle as UseToggleAction<T>];\n}\n\nexport namespace useToggle {\n export type ReturnValue<T> = UseToggleReturnValue<T>;\n}\n"],"mappings":";;;AAKA,SAAgB,UACd,UAAwB,CAAC,OAAO,
|
|
1
|
+
{"version":3,"file":"use-toggle.mjs","names":[],"sources":["../../src/use-toggle/use-toggle.ts"],"sourcesContent":["import { useReducer } from 'react';\n\ntype UseToggleAction<T> = (value?: React.SetStateAction<T>) => void;\nexport type UseToggleReturnValue<T> = [T, UseToggleAction<T>];\n\nexport function useToggle<T = boolean>(\n options: readonly T[] = [false, true] as any\n): UseToggleReturnValue<T> {\n const [[option], toggle] = useReducer((state: T[], action: React.SetStateAction<T>) => {\n const value = action instanceof Function ? action(state[0]) : action;\n const index = Math.abs(state.indexOf(value));\n\n return state.slice(index).concat(state.slice(0, index));\n }, options as T[]);\n\n return [option, toggle as UseToggleAction<T>];\n}\n\nexport namespace useToggle {\n export type ReturnValue<T> = UseToggleReturnValue<T>;\n}\n"],"mappings":";;;AAKA,SAAgB,UACd,UAAwB,CAAC,OAAO,IAAI,GACX;CACzB,MAAM,CAAC,CAAC,SAAS,UAAU,YAAY,OAAY,WAAoC;EACrF,MAAM,QAAQ,kBAAkB,WAAW,OAAO,MAAM,EAAE,IAAI;EAC9D,MAAM,QAAQ,KAAK,IAAI,MAAM,QAAQ,KAAK,CAAC;EAE3C,OAAO,MAAM,MAAM,KAAK,EAAE,OAAO,MAAM,MAAM,GAAG,KAAK,CAAC;CACxD,GAAG,OAAc;CAEjB,OAAO,CAAC,QAAQ,MAA4B;AAC9C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-uncontrolled.mjs","names":[],"sources":["../../src/use-uncontrolled/use-uncontrolled.ts"],"sourcesContent":["import { useState } from 'react';\n\nexport interface UseUncontrolledOptions<T> {\n /** Value for controlled state */\n value?: T;\n\n /** Initial value for uncontrolled state */\n defaultValue?: T;\n\n /** Final value for uncontrolled state when value and defaultValue are not provided */\n finalValue?: T;\n\n /** Controlled state onChange handler */\n onChange?: (value: T, ...payload: any[]) => void;\n}\n\nexport type UseUncontrolledReturnValue<T> = [\n /** Current value */\n T,\n\n /** Handler to update the state, passes `value` and `payload` to `onChange` */\n (value: T, ...payload: any[]) => void,\n\n /** True if the state is controlled, false if uncontrolled */\n boolean,\n];\n\nexport function useUncontrolled<T>({\n value,\n defaultValue,\n finalValue,\n onChange = () => {},\n}: UseUncontrolledOptions<T>): UseUncontrolledReturnValue<T> {\n const [uncontrolledValue, setUncontrolledValue] = useState(\n defaultValue !== undefined ? defaultValue : finalValue\n );\n\n const handleUncontrolledChange = (val: T, ...payload: any[]) => {\n setUncontrolledValue(val);\n onChange?.(val, ...payload);\n };\n\n if (value !== undefined) {\n return [value as T, onChange, true];\n }\n\n return [uncontrolledValue as T, handleUncontrolledChange, false];\n}\n\nexport namespace useUncontrolled {\n export type Options<T> = UseUncontrolledOptions<T>;\n export type ReturnValue<T> = UseUncontrolledReturnValue<T>;\n}\n"],"mappings":";;;AA2BA,SAAgB,gBAAmB,EACjC,OACA,cACA,YACA,iBAAiB,
|
|
1
|
+
{"version":3,"file":"use-uncontrolled.mjs","names":[],"sources":["../../src/use-uncontrolled/use-uncontrolled.ts"],"sourcesContent":["import { useState } from 'react';\n\nexport interface UseUncontrolledOptions<T> {\n /** Value for controlled state */\n value?: T;\n\n /** Initial value for uncontrolled state */\n defaultValue?: T;\n\n /** Final value for uncontrolled state when value and defaultValue are not provided */\n finalValue?: T;\n\n /** Controlled state onChange handler */\n onChange?: (value: T, ...payload: any[]) => void;\n}\n\nexport type UseUncontrolledReturnValue<T> = [\n /** Current value */\n T,\n\n /** Handler to update the state, passes `value` and `payload` to `onChange` */\n (value: T, ...payload: any[]) => void,\n\n /** True if the state is controlled, false if uncontrolled */\n boolean,\n];\n\nexport function useUncontrolled<T>({\n value,\n defaultValue,\n finalValue,\n onChange = () => {},\n}: UseUncontrolledOptions<T>): UseUncontrolledReturnValue<T> {\n const [uncontrolledValue, setUncontrolledValue] = useState(\n defaultValue !== undefined ? defaultValue : finalValue\n );\n\n const handleUncontrolledChange = (val: T, ...payload: any[]) => {\n setUncontrolledValue(val);\n onChange?.(val, ...payload);\n };\n\n if (value !== undefined) {\n return [value as T, onChange, true];\n }\n\n return [uncontrolledValue as T, handleUncontrolledChange, false];\n}\n\nexport namespace useUncontrolled {\n export type Options<T> = UseUncontrolledOptions<T>;\n export type ReturnValue<T> = UseUncontrolledReturnValue<T>;\n}\n"],"mappings":";;;AA2BA,SAAgB,gBAAmB,EACjC,OACA,cACA,YACA,iBAAiB,CAAC,KACyC;CAC3D,MAAM,CAAC,mBAAmB,wBAAwB,SAChD,iBAAiB,KAAA,IAAY,eAAe,UAC9C;CAEA,MAAM,4BAA4B,KAAQ,GAAG,YAAmB;EAC9D,qBAAqB,GAAG;EACxB,WAAW,KAAK,GAAG,OAAO;CAC5B;CAEA,IAAI,UAAU,KAAA,GACZ,OAAO;EAAC;EAAY;EAAU;CAAI;CAGpC,OAAO;EAAC;EAAwB;EAA0B;CAAK;AACjE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-validated-state.mjs","names":[],"sources":["../../src/use-validated-state/use-validated-state.ts"],"sourcesContent":["import { useState } from 'react';\n\nexport interface UseValidatedStateValue<T> {\n /** Current value */\n value: T;\n\n /** Last valid value */\n lastValidValue: T | undefined;\n\n /** True if the current value is valid, false otherwise */\n valid: boolean;\n}\n\nexport type UseValidatedStateReturnValue<T> = [\n /** Current value */\n UseValidatedStateValue<T>,\n /** Handler to update the state, passes `value` and `payload` to `onChange` */\n (value: T) => void,\n];\n\nexport function useValidatedState<T>(\n initialValue: T,\n validate: (value: T) => boolean,\n initialValidationState?: boolean\n): UseValidatedStateReturnValue<T> {\n const [value, setValue] = useState<T>(initialValue);\n const [lastValidValue, setLastValidValue] = useState<T | undefined>(\n validate(initialValue) ? initialValue : undefined\n );\n const [valid, setValid] = useState<boolean>(\n typeof initialValidationState === 'boolean' ? initialValidationState : validate(initialValue)\n );\n\n const onChange = (val: T) => {\n if (validate(val)) {\n setLastValidValue(val);\n setValid(true);\n } else {\n setValid(false);\n }\n\n setValue(val);\n };\n\n return [{ value, lastValidValue, valid }, onChange] as const;\n}\n\nexport namespace useValidatedState {\n export type ReturnValue<T> = UseValidatedStateReturnValue<T>;\n}\n"],"mappings":";;;AAoBA,SAAgB,kBACd,cACA,UACA,wBACiC;CACjC,MAAM,CAAC,OAAO,YAAY,SAAY,
|
|
1
|
+
{"version":3,"file":"use-validated-state.mjs","names":[],"sources":["../../src/use-validated-state/use-validated-state.ts"],"sourcesContent":["import { useState } from 'react';\n\nexport interface UseValidatedStateValue<T> {\n /** Current value */\n value: T;\n\n /** Last valid value */\n lastValidValue: T | undefined;\n\n /** True if the current value is valid, false otherwise */\n valid: boolean;\n}\n\nexport type UseValidatedStateReturnValue<T> = [\n /** Current value */\n UseValidatedStateValue<T>,\n /** Handler to update the state, passes `value` and `payload` to `onChange` */\n (value: T) => void,\n];\n\nexport function useValidatedState<T>(\n initialValue: T,\n validate: (value: T) => boolean,\n initialValidationState?: boolean\n): UseValidatedStateReturnValue<T> {\n const [value, setValue] = useState<T>(initialValue);\n const [lastValidValue, setLastValidValue] = useState<T | undefined>(\n validate(initialValue) ? initialValue : undefined\n );\n const [valid, setValid] = useState<boolean>(\n typeof initialValidationState === 'boolean' ? initialValidationState : validate(initialValue)\n );\n\n const onChange = (val: T) => {\n if (validate(val)) {\n setLastValidValue(val);\n setValid(true);\n } else {\n setValid(false);\n }\n\n setValue(val);\n };\n\n return [{ value, lastValidValue, valid }, onChange] as const;\n}\n\nexport namespace useValidatedState {\n export type ReturnValue<T> = UseValidatedStateReturnValue<T>;\n}\n"],"mappings":";;;AAoBA,SAAgB,kBACd,cACA,UACA,wBACiC;CACjC,MAAM,CAAC,OAAO,YAAY,SAAY,YAAY;CAClD,MAAM,CAAC,gBAAgB,qBAAqB,SAC1C,SAAS,YAAY,IAAI,eAAe,KAAA,CAC1C;CACA,MAAM,CAAC,OAAO,YAAY,SACxB,OAAO,2BAA2B,YAAY,yBAAyB,SAAS,YAAY,CAC9F;CAEA,MAAM,YAAY,QAAW;EAC3B,IAAI,SAAS,GAAG,GAAG;GACjB,kBAAkB,GAAG;GACrB,SAAS,IAAI;EACf,OACE,SAAS,KAAK;EAGhB,SAAS,GAAG;CACd;CAEA,OAAO,CAAC;EAAE;EAAO;EAAgB;CAAM,GAAG,QAAQ;AACpD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-viewport-size.mjs","names":[],"sources":["../../src/use-viewport-size/use-viewport-size.ts"],"sourcesContent":["import { useCallback, useEffect, useState } from 'react';\nimport { useWindowEvent } from '../use-window-event/use-window-event';\n\nconst eventListenerOptions = {\n passive: true,\n};\n\nexport function useViewportSize() {\n const [windowSize, setWindowSize] = useState({\n width: 0,\n height: 0,\n });\n\n const setSize = useCallback(() => {\n setWindowSize({ width: window.innerWidth || 0, height: window.innerHeight || 0 });\n }, []);\n\n useWindowEvent('resize', setSize, eventListenerOptions);\n useWindowEvent('orientationchange', setSize, eventListenerOptions);\n useEffect(setSize, []);\n\n return windowSize;\n}\n"],"mappings":";;;;AAGA,MAAM,uBAAuB,EAC3B,SAAS,
|
|
1
|
+
{"version":3,"file":"use-viewport-size.mjs","names":[],"sources":["../../src/use-viewport-size/use-viewport-size.ts"],"sourcesContent":["import { useCallback, useEffect, useState } from 'react';\nimport { useWindowEvent } from '../use-window-event/use-window-event';\n\nconst eventListenerOptions = {\n passive: true,\n};\n\nexport function useViewportSize() {\n const [windowSize, setWindowSize] = useState({\n width: 0,\n height: 0,\n });\n\n const setSize = useCallback(() => {\n setWindowSize({ width: window.innerWidth || 0, height: window.innerHeight || 0 });\n }, []);\n\n useWindowEvent('resize', setSize, eventListenerOptions);\n useWindowEvent('orientationchange', setSize, eventListenerOptions);\n useEffect(setSize, []);\n\n return windowSize;\n}\n"],"mappings":";;;;AAGA,MAAM,uBAAuB,EAC3B,SAAS,KACX;AAEA,SAAgB,kBAAkB;CAChC,MAAM,CAAC,YAAY,iBAAiB,SAAS;EAC3C,OAAO;EACP,QAAQ;CACV,CAAC;CAED,MAAM,UAAU,kBAAkB;EAChC,cAAc;GAAE,OAAO,OAAO,cAAc;GAAG,QAAQ,OAAO,eAAe;EAAE,CAAC;CAClF,GAAG,CAAC,CAAC;CAEL,eAAe,UAAU,SAAS,oBAAoB;CACtD,eAAe,qBAAqB,SAAS,oBAAoB;CACjE,UAAU,SAAS,CAAC,CAAC;CAErB,OAAO;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-window-event.mjs","names":[],"sources":["../../src/use-window-event/use-window-event.ts"],"sourcesContent":["import { useEffect, useEffectEvent } from 'react';\n\nexport function useWindowEvent<K extends string>(\n type: K,\n listener: K extends keyof WindowEventMap\n ? (this: Window, ev: WindowEventMap[K]) => void\n : (this: Window, ev: CustomEvent) => void,\n options?: boolean | AddEventListenerOptions\n) {\n const stableListener = useEffectEvent(listener);\n\n useEffect(() => {\n window.addEventListener(type as any, stableListener, options);\n return () => window.removeEventListener(type as any, stableListener, options);\n }, [type]);\n}\n"],"mappings":";;;AAEA,SAAgB,eACd,MACA,UAGA,SACA;CACA,MAAM,iBAAiB,eAAe,
|
|
1
|
+
{"version":3,"file":"use-window-event.mjs","names":[],"sources":["../../src/use-window-event/use-window-event.ts"],"sourcesContent":["import { useEffect, useEffectEvent } from 'react';\n\nexport function useWindowEvent<K extends string>(\n type: K,\n listener: K extends keyof WindowEventMap\n ? (this: Window, ev: WindowEventMap[K]) => void\n : (this: Window, ev: CustomEvent) => void,\n options?: boolean | AddEventListenerOptions\n) {\n const stableListener = useEffectEvent(listener);\n\n useEffect(() => {\n window.addEventListener(type as any, stableListener, options);\n return () => window.removeEventListener(type as any, stableListener, options);\n }, [type]);\n}\n"],"mappings":";;;AAEA,SAAgB,eACd,MACA,UAGA,SACA;CACA,MAAM,iBAAiB,eAAe,QAAQ;CAE9C,gBAAgB;EACd,OAAO,iBAAiB,MAAa,gBAAgB,OAAO;EAC5D,aAAa,OAAO,oBAAoB,MAAa,gBAAgB,OAAO;CAC9E,GAAG,CAAC,IAAI,CAAC;AACX"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-window-scroll.mjs","names":[],"sources":["../../src/use-window-scroll/use-window-scroll.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { useWindowEvent } from '../use-window-event/use-window-event';\n\nexport interface UseWindowScrollPosition {\n x: number;\n y: number;\n}\n\nexport type UseWindowScrollTo = (position: Partial<UseWindowScrollPosition>) => void;\nexport type UseWindowScrollReturnValue = [UseWindowScrollPosition, UseWindowScrollTo];\n\nfunction getScrollPosition(): UseWindowScrollPosition {\n return typeof window !== 'undefined' ? { x: window.scrollX, y: window.scrollY } : { x: 0, y: 0 };\n}\n\nfunction scrollTo({ x, y }: Partial<UseWindowScrollPosition>) {\n if (typeof window !== 'undefined') {\n const scrollOptions: ScrollToOptions = { behavior: 'smooth' };\n\n if (typeof x === 'number') {\n scrollOptions.left = x;\n }\n\n if (typeof y === 'number') {\n scrollOptions.top = y;\n }\n\n window.scrollTo(scrollOptions);\n }\n}\n\nexport function useWindowScroll(): UseWindowScrollReturnValue {\n const [position, setPosition] = useState<UseWindowScrollPosition>({ x: 0, y: 0 });\n\n useWindowEvent('scroll', () => setPosition(getScrollPosition()), { passive: true });\n useWindowEvent('resize', () => setPosition(getScrollPosition()), { passive: true });\n\n useEffect(() => {\n setPosition(getScrollPosition());\n }, []);\n\n return [position, scrollTo] as const;\n}\n\nexport namespace useWindowScroll {\n export type Position = UseWindowScrollPosition;\n export type ScrollTo = UseWindowScrollTo;\n export type ReturnValue = UseWindowScrollReturnValue;\n}\n"],"mappings":";;;;AAWA,SAAS,oBAA6C;
|
|
1
|
+
{"version":3,"file":"use-window-scroll.mjs","names":[],"sources":["../../src/use-window-scroll/use-window-scroll.ts"],"sourcesContent":["import { useEffect, useState } from 'react';\nimport { useWindowEvent } from '../use-window-event/use-window-event';\n\nexport interface UseWindowScrollPosition {\n x: number;\n y: number;\n}\n\nexport type UseWindowScrollTo = (position: Partial<UseWindowScrollPosition>) => void;\nexport type UseWindowScrollReturnValue = [UseWindowScrollPosition, UseWindowScrollTo];\n\nfunction getScrollPosition(): UseWindowScrollPosition {\n return typeof window !== 'undefined' ? { x: window.scrollX, y: window.scrollY } : { x: 0, y: 0 };\n}\n\nfunction scrollTo({ x, y }: Partial<UseWindowScrollPosition>) {\n if (typeof window !== 'undefined') {\n const scrollOptions: ScrollToOptions = { behavior: 'smooth' };\n\n if (typeof x === 'number') {\n scrollOptions.left = x;\n }\n\n if (typeof y === 'number') {\n scrollOptions.top = y;\n }\n\n window.scrollTo(scrollOptions);\n }\n}\n\nexport function useWindowScroll(): UseWindowScrollReturnValue {\n const [position, setPosition] = useState<UseWindowScrollPosition>({ x: 0, y: 0 });\n\n useWindowEvent('scroll', () => setPosition(getScrollPosition()), { passive: true });\n useWindowEvent('resize', () => setPosition(getScrollPosition()), { passive: true });\n\n useEffect(() => {\n setPosition(getScrollPosition());\n }, []);\n\n return [position, scrollTo] as const;\n}\n\nexport namespace useWindowScroll {\n export type Position = UseWindowScrollPosition;\n export type ScrollTo = UseWindowScrollTo;\n export type ReturnValue = UseWindowScrollReturnValue;\n}\n"],"mappings":";;;;AAWA,SAAS,oBAA6C;CACpD,OAAO,OAAO,WAAW,cAAc;EAAE,GAAG,OAAO;EAAS,GAAG,OAAO;CAAQ,IAAI;EAAE,GAAG;EAAG,GAAG;CAAE;AACjG;AAEA,SAAS,SAAS,EAAE,GAAG,KAAuC;CAC5D,IAAI,OAAO,WAAW,aAAa;EACjC,MAAM,gBAAiC,EAAE,UAAU,SAAS;EAE5D,IAAI,OAAO,MAAM,UACf,cAAc,OAAO;EAGvB,IAAI,OAAO,MAAM,UACf,cAAc,MAAM;EAGtB,OAAO,SAAS,aAAa;CAC/B;AACF;AAEA,SAAgB,kBAA8C;CAC5D,MAAM,CAAC,UAAU,eAAe,SAAkC;EAAE,GAAG;EAAG,GAAG;CAAE,CAAC;CAEhF,eAAe,gBAAgB,YAAY,kBAAkB,CAAC,GAAG,EAAE,SAAS,KAAK,CAAC;CAClF,eAAe,gBAAgB,YAAY,kBAAkB,CAAC,GAAG,EAAE,SAAS,KAAK,CAAC;CAElF,gBAAgB;EACd,YAAY,kBAAkB,CAAC;CACjC,GAAG,CAAC,CAAC;CAEL,OAAO,CAAC,UAAU,QAAQ;AAC5B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clamp.mjs","names":[],"sources":["../../../src/utils/clamp/clamp.ts"],"sourcesContent":["export function clamp(value: number, min: number | undefined, max: number | undefined) {\n if (min === undefined && max === undefined) {\n return value;\n }\n\n if (min !== undefined && max === undefined) {\n return Math.max(value, min);\n }\n\n if (min === undefined && max !== undefined) {\n return Math.min(value, max);\n }\n\n return Math.min(Math.max(value, min!), max!);\n}\n"],"mappings":";;AAAA,SAAgB,MAAM,OAAe,KAAyB,KAAyB;
|
|
1
|
+
{"version":3,"file":"clamp.mjs","names":[],"sources":["../../../src/utils/clamp/clamp.ts"],"sourcesContent":["export function clamp(value: number, min: number | undefined, max: number | undefined) {\n if (min === undefined && max === undefined) {\n return value;\n }\n\n if (min !== undefined && max === undefined) {\n return Math.max(value, min);\n }\n\n if (min === undefined && max !== undefined) {\n return Math.min(value, max);\n }\n\n return Math.min(Math.max(value, min!), max!);\n}\n"],"mappings":";;AAAA,SAAgB,MAAM,OAAe,KAAyB,KAAyB;CACrF,IAAI,QAAQ,KAAA,KAAa,QAAQ,KAAA,GAC/B,OAAO;CAGT,IAAI,QAAQ,KAAA,KAAa,QAAQ,KAAA,GAC/B,OAAO,KAAK,IAAI,OAAO,GAAG;CAG5B,IAAI,QAAQ,KAAA,KAAa,QAAQ,KAAA,GAC/B,OAAO,KAAK,IAAI,OAAO,GAAG;CAG5B,OAAO,KAAK,IAAI,KAAK,IAAI,OAAO,GAAI,GAAG,GAAI;AAC7C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lower-first.mjs","names":[],"sources":["../../../src/utils/lower-first/lower-first.ts"],"sourcesContent":["export function lowerFirst(value: string) {\n return typeof value !== 'string' ? '' : value.charAt(0).toLowerCase() + value.slice(1);\n}\n"],"mappings":";;AAAA,SAAgB,WAAW,OAAe;
|
|
1
|
+
{"version":3,"file":"lower-first.mjs","names":[],"sources":["../../../src/utils/lower-first/lower-first.ts"],"sourcesContent":["export function lowerFirst(value: string) {\n return typeof value !== 'string' ? '' : value.charAt(0).toLowerCase() + value.slice(1);\n}\n"],"mappings":";;AAAA,SAAgB,WAAW,OAAe;CACxC,OAAO,OAAO,UAAU,WAAW,KAAK,MAAM,OAAO,CAAC,EAAE,YAAY,IAAI,MAAM,MAAM,CAAC;AACvF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"random-id.mjs","names":[],"sources":["../../../src/utils/random-id/random-id.ts"],"sourcesContent":["export function randomId(prefix = 'mantine-'): string {\n return `${prefix}${Math.random().toString(36).slice(2, 11)}`;\n}\n"],"mappings":";;AAAA,SAAgB,SAAS,SAAS,YAAoB;
|
|
1
|
+
{"version":3,"file":"random-id.mjs","names":[],"sources":["../../../src/utils/random-id/random-id.ts"],"sourcesContent":["export function randomId(prefix = 'mantine-'): string {\n return `${prefix}${Math.random().toString(36).slice(2, 11)}`;\n}\n"],"mappings":";;AAAA,SAAgB,SAAS,SAAS,YAAoB;CACpD,OAAO,GAAG,SAAS,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE;AAC3D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"range.mjs","names":[],"sources":["../../../src/utils/range/range.ts"],"sourcesContent":["export function range(start: number, end: number) {\n const length = Math.abs(end - start) + 1;\n const reversed = start > end;\n\n if (!reversed) {\n return Array.from({ length }, (_, index) => index + start);\n }\n\n return Array.from({ length }, (_, index) => start - index);\n}\n"],"mappings":";;AAAA,SAAgB,MAAM,OAAe,KAAa;CAChD,MAAM,SAAS,KAAK,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"range.mjs","names":[],"sources":["../../../src/utils/range/range.ts"],"sourcesContent":["export function range(start: number, end: number) {\n const length = Math.abs(end - start) + 1;\n const reversed = start > end;\n\n if (!reversed) {\n return Array.from({ length }, (_, index) => index + start);\n }\n\n return Array.from({ length }, (_, index) => start - index);\n}\n"],"mappings":";;AAAA,SAAgB,MAAM,OAAe,KAAa;CAChD,MAAM,SAAS,KAAK,IAAI,MAAM,KAAK,IAAI;CAGvC,IAAI,EAFa,QAAQ,MAGvB,OAAO,MAAM,KAAK,EAAE,OAAO,IAAI,GAAG,UAAU,QAAQ,KAAK;CAG3D,OAAO,MAAM,KAAK,EAAE,OAAO,IAAI,GAAG,UAAU,QAAQ,KAAK;AAC3D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shallow-equal.mjs","names":[],"sources":["../../../src/utils/shallow-equal/shallow-equal.ts"],"sourcesContent":["export function shallowEqual(a: any, b: any) {\n if (a === b) {\n return true;\n }\n\n if (Number.isNaN(a) && Number.isNaN(b)) {\n return true;\n }\n\n if (!(a instanceof Object) || !(b instanceof Object)) {\n return false;\n }\n\n const keys = Object.keys(a);\n const { length } = keys;\n\n if (length !== Object.keys(b).length) {\n return false;\n }\n\n for (let i = 0; i < length; i += 1) {\n const key = keys[i];\n\n if (!(key in b)) {\n return false;\n }\n\n if (a[key] !== b[key] && !(Number.isNaN(a[key]) && Number.isNaN(b[key]))) {\n return false;\n }\n }\n\n return true;\n}\n"],"mappings":";;AAAA,SAAgB,aAAa,GAAQ,GAAQ;
|
|
1
|
+
{"version":3,"file":"shallow-equal.mjs","names":[],"sources":["../../../src/utils/shallow-equal/shallow-equal.ts"],"sourcesContent":["export function shallowEqual(a: any, b: any) {\n if (a === b) {\n return true;\n }\n\n if (Number.isNaN(a) && Number.isNaN(b)) {\n return true;\n }\n\n if (!(a instanceof Object) || !(b instanceof Object)) {\n return false;\n }\n\n const keys = Object.keys(a);\n const { length } = keys;\n\n if (length !== Object.keys(b).length) {\n return false;\n }\n\n for (let i = 0; i < length; i += 1) {\n const key = keys[i];\n\n if (!(key in b)) {\n return false;\n }\n\n if (a[key] !== b[key] && !(Number.isNaN(a[key]) && Number.isNaN(b[key]))) {\n return false;\n }\n }\n\n return true;\n}\n"],"mappings":";;AAAA,SAAgB,aAAa,GAAQ,GAAQ;CAC3C,IAAI,MAAM,GACR,OAAO;CAGT,IAAI,OAAO,MAAM,CAAC,KAAK,OAAO,MAAM,CAAC,GACnC,OAAO;CAGT,IAAI,EAAE,aAAa,WAAW,EAAE,aAAa,SAC3C,OAAO;CAGT,MAAM,OAAO,OAAO,KAAK,CAAC;CAC1B,MAAM,EAAE,WAAW;CAEnB,IAAI,WAAW,OAAO,KAAK,CAAC,EAAE,QAC5B,OAAO;CAGT,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,KAAK,GAAG;EAClC,MAAM,MAAM,KAAK;EAEjB,IAAI,EAAE,OAAO,IACX,OAAO;EAGT,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,OAAO,MAAM,EAAE,IAAI,KAAK,OAAO,MAAM,EAAE,IAAI,IACpE,OAAO;CAEX;CAEA,OAAO;AACT"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"upper-first.mjs","names":[],"sources":["../../../src/utils/upper-first/upper-first.ts"],"sourcesContent":["export function upperFirst(value: string) {\n return typeof value !== 'string' ? '' : value.charAt(0).toUpperCase() + value.slice(1);\n}\n"],"mappings":";;AAAA,SAAgB,WAAW,OAAe;
|
|
1
|
+
{"version":3,"file":"upper-first.mjs","names":[],"sources":["../../../src/utils/upper-first/upper-first.ts"],"sourcesContent":["export function upperFirst(value: string) {\n return typeof value !== 'string' ? '' : value.charAt(0).toUpperCase() + value.slice(1);\n}\n"],"mappings":";;AAAA,SAAgB,WAAW,OAAe;CACxC,OAAO,OAAO,UAAU,WAAW,KAAK,MAAM,OAAO,CAAC,EAAE,YAAY,IAAI,MAAM,MAAM,CAAC;AACvF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-callback-ref.mjs","names":[],"sources":["../../../src/utils/use-callback-ref/use-callback-ref.ts"],"sourcesContent":["import { useEffect, useMemo, useRef } from 'react';\n\nexport function useCallbackRef<T extends (...args: any[]) => any>(callback: T | undefined): T {\n const callbackRef = useRef(callback);\n\n useEffect(() => {\n callbackRef.current = callback;\n });\n\n return useMemo(() => ((...args) => callbackRef.current?.(...args)) as T, []);\n}\n"],"mappings":";;;AAEA,SAAgB,eAAkD,UAA4B;CAC5F,MAAM,cAAc,OAAO,
|
|
1
|
+
{"version":3,"file":"use-callback-ref.mjs","names":[],"sources":["../../../src/utils/use-callback-ref/use-callback-ref.ts"],"sourcesContent":["import { useEffect, useMemo, useRef } from 'react';\n\nexport function useCallbackRef<T extends (...args: any[]) => any>(callback: T | undefined): T {\n const callbackRef = useRef(callback);\n\n useEffect(() => {\n callbackRef.current = callback;\n });\n\n return useMemo(() => ((...args) => callbackRef.current?.(...args)) as T, []);\n}\n"],"mappings":";;;AAEA,SAAgB,eAAkD,UAA4B;CAC5F,MAAM,cAAc,OAAO,QAAQ;CAEnC,gBAAgB;EACd,YAAY,UAAU;CACxB,CAAC;CAED,OAAO,gBAAgB,GAAG,SAAS,YAAY,UAAU,GAAG,IAAI,IAAS,CAAC,CAAC;AAC7E"}
|