@koobiq/react-core 0.2.1 → 0.3.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.
@@ -13,3 +13,5 @@ export * from './useResizeObserver';
13
13
  export * from './useElementSize';
14
14
  export * from './useRefs';
15
15
  export * from './useDebounceCallback';
16
+ export * from './useResizeObserverRefs';
17
+ export * from './useHideOverflowItems';
@@ -0,0 +1 @@
1
+ export * from './useHideOverflowItems';
@@ -0,0 +1,27 @@
1
+ export type UseHideOverflowItemsProps = {
2
+ /** Total number of items in the line (including the "more" item). */
3
+ length: number;
4
+ /**
5
+ * Index of the "more" item (defaults to the last one).
6
+ * @default (length - 1)
7
+ */
8
+ moreIndex?: number;
9
+ /**
10
+ * Reserved space in pixels to exclude.
11
+ * @default 0
12
+ */
13
+ busy?: number;
14
+ /**
15
+ * Dependencies that trigger recalculation when changed.
16
+ * @default []
17
+ */
18
+ deps?: unknown[];
19
+ /** Index that should always remain visible. */
20
+ pinnedIndex?: number;
21
+ };
22
+ export declare function useHideOverflowItems<Item extends HTMLElement = HTMLDivElement, Parent extends HTMLElement = HTMLDivElement>({ length, moreIndex, busy, deps, pinnedIndex, }: UseHideOverflowItemsProps): {
23
+ visibleMap: boolean[];
24
+ itemsRefs: import("react").RefObject<Item>[];
25
+ parentRef: import("react").RefObject<Parent>;
26
+ parentSize: number;
27
+ };
@@ -0,0 +1,58 @@
1
+ import { useElementSize } from "../useElementSize/useElementSize.js";
2
+ import { useRefs } from "../useRefs/useRefs.js";
3
+ import { useResizeObserverRefs } from "../useResizeObserverRefs/useResizeObserverRefs.js";
4
+ const createMap = (length, moreIndex, pinnedIndex) => {
5
+ const map = new Array(length).fill(null).map((_, i) => i !== moreIndex);
6
+ if (typeof pinnedIndex === "number" && pinnedIndex >= 0 && pinnedIndex < length) {
7
+ map[pinnedIndex] = true;
8
+ }
9
+ return map;
10
+ };
11
+ const calcItemsVisibleSize = (itemsSizes, map) => {
12
+ let sum = 0;
13
+ for (let index = 0; index < map.length; index++) {
14
+ sum += map[index] ? itemsSizes[index] : 0;
15
+ }
16
+ return sum;
17
+ };
18
+ function useHideOverflowItems({
19
+ length,
20
+ moreIndex = length - 1,
21
+ busy = 0,
22
+ deps = [],
23
+ pinnedIndex
24
+ }) {
25
+ const { ref: parentRef, width: parentSize } = useElementSize();
26
+ const itemsRefs = useRefs(length, deps);
27
+ const itemsSizes = useResizeObserverRefs(itemsRefs, (el) => {
28
+ if (el) {
29
+ const { marginInlineStart, marginInlineEnd } = getComputedStyle(el);
30
+ return parseInt(marginInlineStart, 10) + parseInt(marginInlineEnd, 10) + el.getBoundingClientRect().width;
31
+ }
32
+ return 0;
33
+ });
34
+ const map = createMap(length, moreIndex, pinnedIndex);
35
+ const hideByIndex = (index) => {
36
+ if (!itemsSizes[index] || index === moreIndex || index === pinnedIndex) {
37
+ return;
38
+ }
39
+ const itemsSize = calcItemsVisibleSize(itemsSizes, map);
40
+ if (itemsSize + busy > parentSize) {
41
+ map[index] = false;
42
+ map[moreIndex] = true;
43
+ }
44
+ };
45
+ for (let index = 0; index < itemsSizes.length; index++) {
46
+ hideByIndex(moreIndex - index);
47
+ hideByIndex(moreIndex + index);
48
+ }
49
+ return {
50
+ visibleMap: map,
51
+ itemsRefs,
52
+ parentRef,
53
+ parentSize
54
+ };
55
+ }
56
+ export {
57
+ useHideOverflowItems
58
+ };
@@ -0,0 +1 @@
1
+ export * from './useResizeObserverRefs';
@@ -0,0 +1,2 @@
1
+ import type { RefObject } from 'react';
2
+ export declare const useResizeObserverRefs: <Element extends HTMLElement | SVGGraphicsElement, ReturnType>(refs: Array<RefObject<Element>>, mapper: (el: Element | null) => ReturnType) => ReturnType[];
@@ -0,0 +1,28 @@
1
+ import { useState, useLayoutEffect } from "react";
2
+ import { useMutableRef } from "../useMutableRef/useMutableRef.js";
3
+ const useResizeObserverRefs = (refs, mapper) => {
4
+ const calculateDimensionsRef = useMutableRef(
5
+ () => refs.map((ref) => mapper(ref.current))
6
+ );
7
+ const [dimensions, setDimensions] = useState(
8
+ calculateDimensionsRef.current
9
+ );
10
+ useLayoutEffect(() => {
11
+ setDimensions(calculateDimensionsRef.current);
12
+ }, [refs]);
13
+ useLayoutEffect(() => {
14
+ const resizeObserver = new ResizeObserver(() => {
15
+ setDimensions(calculateDimensionsRef.current);
16
+ });
17
+ for (const ref of refs) {
18
+ if (ref.current) resizeObserver.observe(ref.current);
19
+ }
20
+ return () => {
21
+ resizeObserver.disconnect();
22
+ };
23
+ }, [refs]);
24
+ return dimensions;
25
+ };
26
+ export {
27
+ useResizeObserverRefs
28
+ };
package/dist/index.js CHANGED
@@ -18,6 +18,8 @@ import { useResizeObserver } from "./hooks/useResizeObserver/useResizeObserver.j
18
18
  import { useElementSize } from "./hooks/useElementSize/useElementSize.js";
19
19
  import { useRefs } from "./hooks/useRefs/useRefs.js";
20
20
  import { useDebounceCallback } from "./hooks/useDebounceCallback/useDebounceCallback.js";
21
+ import { useResizeObserverRefs } from "./hooks/useResizeObserverRefs/useResizeObserverRefs.js";
22
+ import { useHideOverflowItems } from "./hooks/useHideOverflowItems/useHideOverflowItems.js";
21
23
  import { polymorphicForwardRef } from "./utils/polymorphicForwardRef.js";
22
24
  import { isNotNil } from "./utils/typeGuards/isNotNil.js";
23
25
  import { isString } from "./utils/typeGuards/isString.js";
@@ -45,6 +47,7 @@ export {
45
47
  useDebounceCallback,
46
48
  useElementSize,
47
49
  useEventListener,
50
+ useHideOverflowItems,
48
51
  useInterval,
49
52
  useIsFirstRender,
50
53
  useIsomorphicEffect,
@@ -54,6 +57,7 @@ export {
54
57
  usePrevious,
55
58
  useRefs,
56
59
  useResizeObserver,
60
+ useResizeObserverRefs,
57
61
  useRouter,
58
62
  useSsr
59
63
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@koobiq/react-core",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "license": "MIT",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",