@mantine/hooks 9.3.2 → 9.4.0
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-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.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-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-splitter/use-splitter.cjs +226 -55
- package/cjs/use-splitter/use-splitter.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/lower-first/lower-first.cjs.map +1 -1
- package/cjs/utils/random-id/random-id.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-clipboard/use-clipboard.mjs.map +1 -1
- package/esm/use-document-title/use-document-title.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-floating-window/use-floating-window.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-hotkeys/parse-hotkey.mjs.map +1 -1
- package/esm/use-hotkeys/use-hotkeys.mjs.map +1 -1
- package/esm/use-id/use-id.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-mask/use-mask.mjs.map +1 -1
- package/esm/use-media-query/use-media-query.mjs.map +1 -1
- package/esm/use-move/use-move.mjs.map +1 -1
- package/esm/use-radial-move/use-radial-move.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-session-storage/use-session-storage.mjs.map +1 -1
- package/esm/use-set/use-set.mjs.map +1 -1
- package/esm/use-splitter/use-splitter.mjs +226 -55
- package/esm/use-splitter/use-splitter.mjs.map +1 -1
- package/esm/use-toggle/use-toggle.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/shallow-equal/shallow-equal.mjs.map +1 -1
- package/esm/utils/upper-first/upper-first.mjs.map +1 -1
- package/lib/index.d.mts +1 -1
- package/lib/index.d.ts +1 -1
- package/lib/use-splitter/use-splitter.d.ts +48 -22
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-roving-index.cjs","names":["useUncontrolled"],"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":";;;;AA8DA,SAAS,gBACP,SACA,OACA,gBACA,MACQ;CACR,KAAK,IAAI,IAAI,UAAU,GAAG,IAAI,OAAO,KAAK,GACxC,IAAI,CAAC,eAAe,CAAC,GACnB,OAAO;CAIX,IAAI;OACG,IAAI,IAAI,GAAG,IAAI,SAAS,KAAK,GAChC,IAAI,CAAC,eAAe,CAAC,GACnB,OAAO;CAAA;CAKb,OAAO;AACT;AAEA,SAAS,oBACP,SACA,OACA,gBACA,MACQ;CACR,KAAK,IAAI,IAAI,UAAU,GAAG,KAAK,GAAG,KAAK,GACrC,IAAI,CAAC,eAAe,CAAC,GACnB,OAAO;CAIX,IAAI;OACG,IAAI,IAAI,QAAQ,GAAG,IAAI,SAAS,KAAK,GACxC,IAAI,CAAC,eAAe,CAAC,GACnB,OAAO;CAAA;CAKb,OAAO;AACT;AAEA,SAAS,iBAAiB,OAAe,gBAAoD;CAC3F,KAAK,IAAI,IAAI,GAAG,IAAI,OAAO,KAAK,GAC9B,IAAI,CAAC,eAAe,CAAC,GACnB,OAAO;CAIX,OAAO;AACT;AAEA,SAAS,gBAAgB,OAAe,gBAAoD;CAC1F,KAAK,IAAI,IAAI,QAAQ,GAAG,KAAK,GAAG,KAAK,GACnC,IAAI,CAAC,eAAe,CAAC,GACnB,OAAO;CAIX,OAAO;AACT;AAEA,MAAM,8BAA8B;AAEpC,SAAgB,eAAe,OAAuD;CACpF,MAAM,EACJ,OACA,cAAc,cACd,OAAO,MACP,MAAM,OACN,kBAAkB,OAClB,SACA,cACA,cACA,eACA,iBAAiB,0BACf;CAEJ,MAAM,YAAA,GAAA,MAAA,wBAA4C,IAAI,IAAI,CAAC;CAC3D,MAAM,SAAS,OAAO,YAAY,YAAY,UAAU;CAKxD,MAAM,CAAC,aAAa,kBAAkBA,yBAAAA,gBAAgB;EACpD,OAAO;EACP,cAJA,iBAAiB,KAAA,IAAY,eAAe,iBAAiB,OAAO,cAAc;EAKlF,YAAY;EACZ,UAAU;CACZ,CAAC;CAED,CAAA,GAAA,MAAA,iBAAgB;EACd,IAAI,UAAU,GACZ;EAGF,IAAI,eAAe,OACjB,eAAe,gBAAgB,OAAO,cAAc,CAAC;OAChD,IAAI,eAAe,WAAW,GACnC,eAAe,iBAAiB,OAAO,cAAc,CAAC;CAE1D,GAAG;EAAC;EAAO;EAAa;CAAc,CAAC;CAEvC,MAAM,aAAA,GAAA,MAAA,cACH,UAAkB;EACjB,eAAe,KAAK;EACpB,MAAM,UAAU,SAAS,QAAQ,IAAI,KAAK;EAC1C,IAAI,SAAS;GACX,QAAQ,MAAM;GACd,IAAI,iBACF,QAAQ,MAAM;EAElB;CACF,GACA,CAAC,iBAAiB,cAAc,CAClC;CAEA,MAAM,qBAAA,GAAA,MAAA,cACH,OAA4B,iBAAyB;EACpD,MAAM,MAAM,KAAK,MAAM,eAAe,OAAQ;EAC9C,MAAM,MAAM,eAAe;EAC3B,MAAM,YAAY,KAAK,KAAK,QAAQ,OAAQ;EAC5C,IAAI,YAA2B;EAE/B,MAAM,QAAQ,QAAQ;EAEtB,QAAQ,MAAM,KAAd;GACE,KAAK,cAAc;IACjB,MAAM,YAAY,QAAQ,MAAM,IAAI,MAAM;IAC1C,IAAI,aAAa,KAAK,YAAY,WAAY,MAAM,UAAW,YAAY,OAAO;KAChF,MAAM,YAAY,MAAM,UAAW;KACnC,IAAI,CAAC,eAAe,SAAS,GAC3B,YAAY;IAEhB;IACA;GACF;GAEA,KAAK,aAAa;IAChB,MAAM,YAAY,QAAQ,MAAM,IAAI,MAAM;IAC1C,IAAI,aAAa,KAAK,YAAY,WAAY,MAAM,UAAW,YAAY,OAAO;KAChF,MAAM,YAAY,MAAM,UAAW;KACnC,IAAI,CAAC,eAAe,SAAS,GAC3B,YAAY;IAEhB;IACA;GACF;GAEA,KAAK;IACH,KAAK,IAAI,IAAI,MAAM,GAAG,IAAI,WAAW,KAAK,GAAG;KAC3C,MAAM,YAAY,IAAI,UAAW;KACjC,IAAI,YAAY,SAAS,CAAC,eAAe,SAAS,GAAG;MACnD,YAAY;MACZ;KACF;IACF;IACA;GAGF,KAAK;IACH,KAAK,IAAI,IAAI,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG;KACpC,MAAM,YAAY,IAAI,UAAW;KACjC,IAAI,YAAY,SAAS,CAAC,eAAe,SAAS,GAAG;MACnD,YAAY;MACZ;KACF;IACF;IACA;GAGF,KAAK;IACH,IAAI,MAAM,SACR,YAAY,iBAAiB,OAAO,cAAc;SAC7C;KACL,MAAM,WAAW,MAAM;KACvB,KAAK,IAAI,IAAI,UAAU,IAAI,WAAW,WAAY,IAAI,OAAO,KAAK,GAChE,IAAI,CAAC,eAAe,CAAC,GAAG;MACtB,YAAY;MACZ;KACF;IAEJ;IACA;GAGF,KAAK;IACH,IAAI,MAAM,SACR,YAAY,gBAAgB,OAAO,cAAc;SAC5C;KACL,MAAM,WAAW,MAAM;KACvB,MAAM,SAAS,KAAK,IAAI,WAAW,SAAU,KAAK,IAAI;KACtD,KAAK,IAAI,IAAI,QAAQ,KAAK,UAAU,KAAK,GACvC,IAAI,CAAC,eAAe,CAAC,GAAG;MACtB,YAAY;MACZ;KACF;IAEJ;IACA;EAEJ;EAEA,IAAI,cAAc,QAAQ,cAAc,cAAc;GACpD,MAAM,eAAe;GACrB,MAAM,gBAAgB;GACtB,UAAU,SAAS;EACrB;CACF,GACA;EAAC;EAAO;EAAS;EAAK;EAAgB;CAAS,CACjD;CAEA,MAAM,qBAAA,GAAA,MAAA,cACH,OAA4B,iBAAyB;EACpD,MAAM,QAAQ,QAAQ;EACtB,IAAI,YAA2B;EAE/B,QAAQ,MAAM,KAAd;GACE,KAAK;IACH,IAAI,gBAAgB,gBAAgB,gBAAgB,QAClD,YAAY,QACR,oBAAoB,cAAc,OAAO,gBAAgB,IAAI,IAC7D,gBAAgB,cAAc,OAAO,gBAAgB,IAAI;IAE/D;GAGF,KAAK;IACH,IAAI,gBAAgB,gBAAgB,gBAAgB,QAClD,YAAY,QACR,gBAAgB,cAAc,OAAO,gBAAgB,IAAI,IACzD,oBAAoB,cAAc,OAAO,gBAAgB,IAAI;IAEnE;GAGF,KAAK;IACH,IAAI,gBAAgB,cAAc,gBAAgB,QAChD,YAAY,gBAAgB,cAAc,OAAO,gBAAgB,IAAI;IAEvE;GAGF,KAAK;IACH,IAAI,gBAAgB,cAAc,gBAAgB,QAChD,YAAY,oBAAoB,cAAc,OAAO,gBAAgB,IAAI;IAE3E;GAGF,KAAK;IACH,YAAY,iBAAiB,OAAO,cAAc;IAClD;GAGF,KAAK;IACH,YAAY,gBAAgB,OAAO,cAAc;IACjD;EAEJ;EAEA,IAAI,cAAc,QAAQ,cAAc,cAAc;GACpD,MAAM,eAAe;GACrB,MAAM,gBAAgB;GACtB,UAAU,SAAS;EACrB;CACF,GACA;EAAC;EAAO;EAAa;EAAM;EAAK;EAAgB;CAAS,CAC3D;CAwCA,OAAO;EACL,eAAA,GAAA,MAAA,cAtCC,YAA6C;GAC5C,MAAM,EAAE,OAAO,SAAS,cAAc;GAEtC,OAAO;IACL,UAAW,UAAU,cAAc,IAAI;IAEvC,MAAM,SAA6B;KACjC,IAAI,MACF,SAAS,QAAQ,IAAI,OAAO,IAAI;UAEhC,SAAS,QAAQ,OAAO,KAAK;IAEjC;IAEA,YAAY,UAA+B;KACzC,YAAY,KAAK;KAEjB,IAAI,MAAM,kBACR;KAGF,IAAI,QACF,kBAAkB,OAAO,KAAK;UAE9B,kBAAkB,OAAO,KAAK;IAElC;IAEA,UAAU,UAA4B;KACpC,UAAU,KAAK;KACf,eAAe,KAAK;IACtB;GACF;EACF,GACA;GAAC;GAAa;GAAQ;GAAmB;GAAmB;EAAc,CAI/D;EACX,cAAc;EACd,iBAAiB;CACnB;AACF"}
|
|
1
|
+
{"version":3,"file":"use-roving-index.cjs","names":["useUncontrolled"],"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.cjs","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,oBAAA,GAAA,MAAA,
|
|
1
|
+
{"version":3,"file":"use-scroll-direction.cjs","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,oBAAA,GAAA,MAAA,OAAA,CAA0B,CAAC;CACjC,MAAM,CAAC,iBAAiB,uBAAA,GAAA,MAAA,SAAA,CAAgD,SAAS;CACjF,MAAM,iBAAA,GAAA,MAAA,OAAA,CAAuB,KAAK;CAClC,MAAM,kBAAA,GAAA,MAAA,OAAA,CAA4C,KAAA,CAAS;CAE3D,MAAM,gBAAA,GAAA,MAAA,eAAA,OAAoC;EACxC,IAAI,cAAc,SAChB;EAGF,MAAM,mBAAmB,OAAO,WAAW,SAAS,gBAAgB;EACpE,mBAAmB,mBAAmB,iBAAiB,UAAU,OAAO,MAAM;EAC9E,iBAAiB,UAAU;CAC7B,CAAC;CAED,CAAA,GAAA,MAAA,UAAA,OAAgB;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.cjs","names":["useReducedMotion"],"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.cjs","names":["useReducedMotion"],"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.cjs","names":["randomId"],"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,MAAMA,kBAAAA,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,
|
|
1
|
+
{"version":3,"file":"use-scroll-spy.cjs","names":["randomId"],"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,MAAMA,kBAAAA,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,EAAE,CAAC;CAAE,CAGtB,CAAC,CAAC;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,cAAA,GAAA,MAAA,SAAA,CAAsB,EAAE;CACvC,MAAM,CAAC,aAAa,mBAAA,GAAA,MAAA,SAAA,CAA2B,KAAK;CACpD,MAAM,CAAC,MAAM,YAAA,GAAA,MAAA,SAAA,CAA+C,CAAC,CAAC;CAC9D,MAAM,eAAA,GAAA,MAAA,OAAA,CAAgD,CAAC,CAAC;CAExD,MAAM,gBAAA,GAAA,MAAA,eAAA,OAAoC;EACxC,UACE,iBACE,YAAY,QAAQ,KAAK,MAAM,EAAE,QAAQ,CAAC,CAAC,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,CAAC,CAAC,sBAAsB,CAAC,GACvD,MACF,CACF;CACF;CAEA,CAAA,GAAA,MAAA,UAAA,OAAgB;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.cjs","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,CAAC,GACJ;CAC3B,MAAM,EAAE,eAAe,KAAK,YAAY,MAAM,wBAAwB;CAEtE,MAAM,gBAAA,GAAA,MAAA,
|
|
1
|
+
{"version":3,"file":"use-scroller.cjs","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.cjs","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,oBAAA,GAAA,MAAA,
|
|
1
|
+
{"version":3,"file":"use-selection.cjs","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,oBAAA,GAAA,MAAA,SAAA,CAAoC,IAAI,IAAI,MAAM,oBAAoB,CAAC,CAAC,CAAC;CAE9F,uBAAA,mBAAmB;EACjB,IAAI,MAAM,4BACR,gCAAgB,IAAI,IAAI,CAAC;CAE7B,GAAG,CAAC,MAAM,MAAM,MAAM,0BAA0B,CAAC;CAEjD,MAAM,UAAA,GAAA,MAAA,YAAA,EAAsB,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,YAAA,GAAA,MAAA,YAAA,EAAwB,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,UAAA,GAAA,MAAA,YAAA,EAAsB,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,kBAAA,GAAA,MAAA,YAAA,OAAmC;EACvC,gCAAgB,IAAI,IAAI,CAAC;CAC3B,GAAG,CAAC,CAAC;CAEL,MAAM,gBAAA,GAAA,MAAA,YAAA,EAA4B,cAAmB;EACnD,gBAAgB,IAAI,IAAI,SAAS,CAAC;CACpC,GAAG,CAAC,CAAC;CAEL,MAAM,iBAAA,GAAA,MAAA,YAAA,OAAkC;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,kBAAA,GAAA,MAAA,YAAA,OAAmC;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.cjs","names":["createStorage","readValue"],"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,OAAOA,uBAAAA,cAAiB,kBAAkB,qBAAqB,
|
|
1
|
+
{"version":3,"file":"use-session-storage.cjs","names":["createStorage","readValue"],"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,OAAOA,uBAAAA,cAAiB,kBAAkB,qBAAqB,CAAC,CAAC,KAAK;AACxE;AAOA,MAAa,0BAA4CC,uBAAAA,UAAU,gBAAgB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-set.cjs","names":["useForceUpdate"],"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,UAAA,GAAA,MAAA,
|
|
1
|
+
{"version":3,"file":"use-set.cjs","names":["useForceUpdate"],"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,UAAA,GAAA,MAAA,OAAA,CAAgB,IAAI,IAAI,MAAM,CAAC;CACrC,MAAM,cAAcA,yBAAAA,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,CAAC,CAAC,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.cjs","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,aAAA,GAAA,MAAA,
|
|
1
|
+
{"version":3,"file":"use-set-state.cjs","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,aAAA,GAAA,MAAA,SAAA,CAAqB,YAAY;CAW/C,OAAO,CAAC,QAAA,GAAA,MAAA,YAAA,EARL,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.cjs","names":["shallowEqual"],"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,CAACA,sBAAAA,aAAa,UAAU,IAAI,UAAU,EAAE,GAC1C,OAAO;CAIX,OAAO;AACT;AAEA,SAAS,kBAAkB,cAAqC;CAC9D,MAAM,OAAA,GAAA,MAAA,
|
|
1
|
+
{"version":3,"file":"use-shallow-effect.cjs","names":["shallowEqual"],"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,CAACA,sBAAAA,aAAa,UAAU,IAAI,UAAU,EAAE,GAC1C,OAAO;CAIX,OAAO;AACT;AAEA,SAAS,kBAAkB,cAAqC;CAC9D,MAAM,OAAA,GAAA,MAAA,OAAA,CAAsD,CAAC,CAAC;CAC9D,MAAM,aAAA,GAAA,MAAA,OAAA,CAA2B,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,CAAA,GAAA,MAAA,UAAA,CAAU,IAAI,kBAAkB,YAAY,CAAC;AAC/C"}
|