@trackunit/react-components 0.1.68 → 0.1.70

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/index.cjs CHANGED
@@ -12,7 +12,6 @@ var dateFns = require('date-fns');
12
12
  var react = require('@floating-ui/react');
13
13
  var reactDayPicker = require('react-day-picker');
14
14
  var locale = require('date-fns/locale');
15
- var reactBrowserHooks = require('react-browser-hooks');
16
15
  var usePortal = require('react-useportal');
17
16
  var ReactSelect = require('react-select');
18
17
  var ReactAsyncCreatableSelect = require('react-select/async-creatable');
@@ -998,7 +997,7 @@ const PopoverContent = React__default["default"].forwardRef(function PopoverCont
998
997
  var { className, dataTestId, children } = _a, props = __rest(_a, ["className", "dataTestId", "children"]);
999
998
  const _f = usePopoverContext(), { context: floatingContext, customProps } = _f, context = __rest(_f, ["context", "customProps"]);
1000
999
  const ref = react.useMergeRefs([context.refs.setFloating, propRef]);
1001
- return (jsxRuntime.jsx(react.FloatingPortal, Object.assign({ id: "tu-floating-ui" }, { children: context.isOpen && (jsxRuntime.jsx(react.FloatingFocusManager, Object.assign({ guards: false, context: floatingContext, modal: context.isModal, order: ["reference", "content"] }, { children: jsxRuntime.jsx("div", Object.assign({ ref: ref, className: `tu-popover-container animate-fade-in-fast ${(_b = className !== null && className !== void 0 ? className : customProps.className) !== null && _b !== void 0 ? _b : ""}`, "data-testid": (_c = dataTestId !== null && dataTestId !== void 0 ? dataTestId : customProps.dataTestId) !== null && _c !== void 0 ? _c : "popover-content", style: Object.assign({ position: context.strategy, top: (_d = context.y) !== null && _d !== void 0 ? _d : 0, left: (_e = context.x) !== null && _e !== void 0 ? _e : 0, width: "max-content" }, props.style), "aria-labelledby": context.labelId, "aria-describedby": context.descriptionId }, context.getFloatingProps(props), { children: typeof children === "function" ? children(() => context.setIsOpen(false)) : children })) }))) })));
1000
+ return (jsxRuntime.jsx(react.FloatingPortal, Object.assign({ id: "tu-floating-ui" }, { children: context.isOpen && (jsxRuntime.jsx(react.FloatingFocusManager, Object.assign({ guards: false, context: floatingContext, modal: context.isModal, order: ["reference", "content"], returnFocus: false }, { children: jsxRuntime.jsx("div", Object.assign({ ref: ref, className: `tu-popover-container animate-fade-in-fast ${(_b = className !== null && className !== void 0 ? className : customProps.className) !== null && _b !== void 0 ? _b : ""}`, "data-testid": (_c = dataTestId !== null && dataTestId !== void 0 ? dataTestId : customProps.dataTestId) !== null && _c !== void 0 ? _c : "popover-content", style: Object.assign({ position: context.strategy, top: (_d = context.y) !== null && _d !== void 0 ? _d : 0, left: (_e = context.x) !== null && _e !== void 0 ? _e : 0, width: "max-content" }, props.style), "aria-labelledby": context.labelId, "aria-describedby": context.descriptionId }, context.getFloatingProps(props), { children: typeof children === "function" ? children(() => context.setIsOpen(false)) : children })) }))) })));
1002
1001
  });
1003
1002
 
1004
1003
  /**
@@ -1493,6 +1492,241 @@ const Divider = tailwindStyledComponents.tw.hr `
1493
1492
  tu-menu-list__divider
1494
1493
  `;
1495
1494
 
1495
+ /**
1496
+ * Custom hook to handle click outside events.
1497
+ *
1498
+ * @param {RefObject<HTMLElement> | Array<RefObject<HTMLElement>>} el - The reference(s) to the element(s) to watch for click outside events.
1499
+ * @param {Object | Function} [options={}] - Configuration options or the click event handler if options are not provided.
1500
+ * @param {boolean} [options.active=true] - Whether the click outside event listener should be active.
1501
+ * @param {Function} [onClick] - The event handler for the click outside event.
1502
+ */
1503
+ const useClickOutside = (el, options = {}, onClick) => {
1504
+ const els = Array.isArray(el) ? el : [el];
1505
+ let active = true;
1506
+ if (!onClick && typeof options === "function") {
1507
+ onClick = options;
1508
+ }
1509
+ else if (typeof options === "object") {
1510
+ active = options.active !== undefined ? options.active : active;
1511
+ }
1512
+ const handler = (ev) => {
1513
+ const target = ev.target;
1514
+ if (els.every(ref => !ref.current || !ref.current.contains(target))) {
1515
+ onClick && onClick(ev);
1516
+ }
1517
+ };
1518
+ const cleanup = () => window.removeEventListener("click", handler);
1519
+ React.useEffect(() => {
1520
+ if (active) {
1521
+ window.addEventListener("click", handler);
1522
+ }
1523
+ else {
1524
+ cleanup();
1525
+ }
1526
+ return cleanup;
1527
+ });
1528
+ };
1529
+
1530
+ /**
1531
+ * The useDebounce hook works like useState, but adds a delay where previous values will be ignored.
1532
+ *
1533
+ * @param {any} value The value to set
1534
+ * @param {number} delay The debounce time
1535
+ * @returns {any} value The latest values received
1536
+ */
1537
+ const useDebounce = (value, delay = 500) => {
1538
+ const [debouncedValue, setDebouncedValue] = React.useState(value);
1539
+ React.useEffect(() => {
1540
+ const handler = setTimeout(() => {
1541
+ setDebouncedValue(value);
1542
+ }, delay);
1543
+ return () => {
1544
+ clearTimeout(handler);
1545
+ };
1546
+ }, [value, delay]);
1547
+ return debouncedValue;
1548
+ };
1549
+
1550
+ // Copied from https://github.com/rexxars/use-device-pixel-ratio
1551
+ /**
1552
+ * Get the device pixel ratio, potentially rounded and capped.
1553
+ * Will emit new values if it changes.
1554
+ *
1555
+ * @param {DevicePixelRatioOptions} options the options object
1556
+ * @returns { number } The current device pixel ratio, or the default if none can be resolved
1557
+ */
1558
+ function useDevicePixelRatio(options) {
1559
+ const dpr = getDevicePixelRatio(options);
1560
+ const [currentDpr, setCurrentDpr] = React.useState(dpr);
1561
+ const { defaultDpr, maxDpr, round } = options || {};
1562
+ React.useEffect(() => {
1563
+ const canListen = typeof window !== "undefined" && "matchMedia" in window;
1564
+ if (!canListen) {
1565
+ return;
1566
+ }
1567
+ const updateDpr = () => setCurrentDpr(getDevicePixelRatio({ defaultDpr, maxDpr, round }));
1568
+ const mediaMatcher = window.matchMedia(`screen and (resolution: ${currentDpr}dppx)`);
1569
+ // Safari 13.1 does not have `addEventListener`, but does have `addListener`
1570
+ if (mediaMatcher.addEventListener) {
1571
+ mediaMatcher.addEventListener("change", updateDpr);
1572
+ }
1573
+ else {
1574
+ mediaMatcher.addListener(updateDpr);
1575
+ }
1576
+ return () => {
1577
+ if (mediaMatcher.removeEventListener) {
1578
+ mediaMatcher.removeEventListener("change", updateDpr);
1579
+ }
1580
+ else {
1581
+ mediaMatcher.removeListener(updateDpr);
1582
+ }
1583
+ };
1584
+ }, [currentDpr, defaultDpr, maxDpr, round]);
1585
+ return currentDpr;
1586
+ }
1587
+ /**
1588
+ * Returns the current device pixel ratio (DPR) given the passed options
1589
+ *
1590
+ * @param { DevicePixelRatioOptions } options the options object
1591
+ * @returns { number } current device pixel ratio
1592
+ */
1593
+ function getDevicePixelRatio(options) {
1594
+ const { defaultDpr = 1, maxDpr = 3, round = true } = options || {};
1595
+ const hasDprProp = typeof window !== "undefined" && typeof window.devicePixelRatio === "number";
1596
+ const dpr = hasDprProp ? window.devicePixelRatio : defaultDpr;
1597
+ const rounded = Math.min(Math.max(1, round ? Math.floor(dpr) : dpr), maxDpr);
1598
+ return rounded;
1599
+ }
1600
+
1601
+ /**
1602
+ * The useLocalStorage hook works like useState, but saves to localstorage.
1603
+ *
1604
+ * @param {string} key - The key the values is saved under.
1605
+ * @param {string | null | undefined} initialValue - The initial value for the state/local storage item
1606
+ * @returns {string | null | undefined} value
1607
+ */
1608
+ const useLocalStorage = (key, initialValue) => {
1609
+ if (!key) {
1610
+ throw new Error("useLocalStorage key may not be falsy");
1611
+ }
1612
+ const setLocalStorageItem = React.useCallback((value) => window.localStorage.setItem(key, typeof value === "object" ? JSON.stringify(value) : `${value}`), [key]);
1613
+ const removeLocalStorageItem = React.useCallback(() => window.localStorage.removeItem(key), [key]);
1614
+ const [item, setValue] = React.useState(() => {
1615
+ const value = window.localStorage.getItem(key);
1616
+ if (value !== undefined && value !== null) {
1617
+ const parsedValue = tryParse(value);
1618
+ return parsedValue;
1619
+ }
1620
+ return initialValue !== null && initialValue !== void 0 ? initialValue : null;
1621
+ });
1622
+ React.useEffect(() => {
1623
+ if (item !== undefined && item !== null) {
1624
+ setLocalStorageItem(item);
1625
+ }
1626
+ else {
1627
+ removeLocalStorageItem();
1628
+ }
1629
+ }, [item, setLocalStorageItem, removeLocalStorageItem, key]);
1630
+ /*
1631
+ // Sync local storage between tabs / windows
1632
+ useEffect(() => {
1633
+ const handleStorageChange = (e: StorageEvent) => {
1634
+ if (e.key === key) {
1635
+ setValue(tryParse(e.newValue));
1636
+ }
1637
+ };
1638
+
1639
+ window.addEventListener("storage", handleStorageChange);
1640
+
1641
+ return () => {
1642
+ window.removeEventListener("storage", handleStorageChange);
1643
+ };
1644
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1645
+ }, []);
1646
+ */
1647
+ const removeItem = () => {
1648
+ setValue(null);
1649
+ };
1650
+ return [item, setValue, removeItem];
1651
+ };
1652
+ function tryParse(value) {
1653
+ try {
1654
+ return JSON.parse(value);
1655
+ }
1656
+ catch (_a) {
1657
+ return value;
1658
+ }
1659
+ }
1660
+
1661
+ /**
1662
+ * Custom hook to handle window resize events and provide the current window size.
1663
+ *
1664
+ * @returns {WindowSize} An object containing the current window height and width.
1665
+ */
1666
+ const useResize = () => {
1667
+ const [size, setSize] = React.useState(getWindowSize());
1668
+ React.useEffect(() => {
1669
+ const handleResize = () => {
1670
+ setSize(getWindowSize());
1671
+ };
1672
+ window.addEventListener("resize", handleResize, false);
1673
+ return () => window.removeEventListener("resize", handleResize);
1674
+ }, [setSize]);
1675
+ return size;
1676
+ };
1677
+ /**
1678
+ * Get the current window size.
1679
+ *
1680
+ * @returns {WindowSize} An object containing the current window height and width.
1681
+ */
1682
+ const getWindowSize = () => {
1683
+ try {
1684
+ return {
1685
+ height: window.innerHeight,
1686
+ width: window.innerWidth,
1687
+ };
1688
+ }
1689
+ catch (err) {
1690
+ return {
1691
+ height: 0,
1692
+ width: 0,
1693
+ };
1694
+ }
1695
+ };
1696
+
1697
+ /**
1698
+ * @param {UseTimeoutProps} props The props
1699
+ * @returns {{ startTimeout: () => void; stopTimeout: () => void; isReady: boolean | null}} return
1700
+ */
1701
+ const useTimeout = ({ onTimeout, duration }) => {
1702
+ const ready = React.useRef(false);
1703
+ const timeout = React.useRef();
1704
+ const callback = React.useRef(onTimeout);
1705
+ const isReady = React.useCallback(() => ready.current, []);
1706
+ const startTimeout = React.useCallback(() => {
1707
+ ready.current = false;
1708
+ timeout.current && clearTimeout(timeout.current);
1709
+ timeout.current = setTimeout(() => {
1710
+ ready.current = true;
1711
+ callback.current();
1712
+ }, duration);
1713
+ }, [duration]);
1714
+ const stopTimeout = React.useCallback(() => {
1715
+ ready.current = null;
1716
+ timeout.current && clearTimeout(timeout.current);
1717
+ }, []);
1718
+ // update ref when function changes
1719
+ React.useEffect(() => {
1720
+ callback.current = onTimeout;
1721
+ }, [onTimeout]);
1722
+ // startTimeout on mount, stopTimeout on unmount
1723
+ React.useEffect(() => {
1724
+ startTimeout();
1725
+ return stopTimeout;
1726
+ }, [duration, startTimeout, stopTimeout]);
1727
+ return [isReady, stopTimeout, startTimeout];
1728
+ };
1729
+
1496
1730
  /**
1497
1731
  * A kebab menu component.
1498
1732
  * Advice: fill it with MenuList
@@ -1511,12 +1745,12 @@ const MoreMenu = ({ className, dataTestId, dotsDirection = "horizontal", menuPla
1511
1745
  const [actionMenuIsOpen, setActionMenuIsOpen] = React.useState(false);
1512
1746
  const dotsName = dotsDirection === "horizontal" ? "EllipsisHorizontalIcon" : "EllipsisVerticalIcon";
1513
1747
  const actionMenuRef = React.useRef(null);
1514
- reactBrowserHooks.useClickOutside(actionMenuRef, () => {
1748
+ useClickOutside(actionMenuRef, () => {
1515
1749
  setActionMenuIsOpen(false);
1516
1750
  });
1517
1751
  return (jsxRuntime.jsx(Root$4, Object.assign({ ref: actionMenuRef, className: className, "data-testid": dataTestId }, { children: jsxRuntime.jsxs(Popover, Object.assign({ placement: menuPlacement }, { children: [jsxRuntime.jsx(PopoverTrigger, { children: jsxRuntime.jsx(IconButton, Object.assign({}, iconButtonProps, { icon: jsxRuntime.jsx(Icon, Object.assign({ name: dotsName }, iconProps)), onClick: () => {
1518
1752
  setActionMenuIsOpen(!actionMenuIsOpen);
1519
- } })) }), jsxRuntime.jsx(PopoverContent, { children: children })] })) })));
1753
+ } })) }), jsxRuntime.jsx(PopoverContent, { children: close => (typeof children === "function" ? children(close) : children) })] })) })));
1520
1754
  };
1521
1755
  const Root$4 = tailwindStyledComponents.tw.div `
1522
1756
  tu-more-menu
@@ -2890,170 +3124,6 @@ const Bar = tailwindStyledComponents.tw.rect `
2890
3124
  tu-value-bar__bar
2891
3125
  `;
2892
3126
 
2893
- /**
2894
- * The useDebounce hook works like useState, but adds a delay where previous values will be ignored.
2895
- *
2896
- * @param {any} value The value to set
2897
- * @param {number} delay The debounce time
2898
- * @returns {any} value The latest values received
2899
- */
2900
- const useDebounce = (value, delay = 500) => {
2901
- const [debouncedValue, setDebouncedValue] = React.useState(value);
2902
- React.useEffect(() => {
2903
- const handler = setTimeout(() => {
2904
- setDebouncedValue(value);
2905
- }, delay);
2906
- return () => {
2907
- clearTimeout(handler);
2908
- };
2909
- }, [value, delay]);
2910
- return debouncedValue;
2911
- };
2912
-
2913
- // Copied from https://github.com/rexxars/use-device-pixel-ratio
2914
- /**
2915
- * Get the device pixel ratio, potentially rounded and capped.
2916
- * Will emit new values if it changes.
2917
- *
2918
- * @param {DevicePixelRatioOptions} options the options object
2919
- * @returns { number } The current device pixel ratio, or the default if none can be resolved
2920
- */
2921
- function useDevicePixelRatio(options) {
2922
- const dpr = getDevicePixelRatio(options);
2923
- const [currentDpr, setCurrentDpr] = React.useState(dpr);
2924
- const { defaultDpr, maxDpr, round } = options || {};
2925
- React.useEffect(() => {
2926
- const canListen = typeof window !== "undefined" && "matchMedia" in window;
2927
- if (!canListen) {
2928
- return;
2929
- }
2930
- const updateDpr = () => setCurrentDpr(getDevicePixelRatio({ defaultDpr, maxDpr, round }));
2931
- const mediaMatcher = window.matchMedia(`screen and (resolution: ${currentDpr}dppx)`);
2932
- // Safari 13.1 does not have `addEventListener`, but does have `addListener`
2933
- if (mediaMatcher.addEventListener) {
2934
- mediaMatcher.addEventListener("change", updateDpr);
2935
- }
2936
- else {
2937
- mediaMatcher.addListener(updateDpr);
2938
- }
2939
- return () => {
2940
- if (mediaMatcher.removeEventListener) {
2941
- mediaMatcher.removeEventListener("change", updateDpr);
2942
- }
2943
- else {
2944
- mediaMatcher.removeListener(updateDpr);
2945
- }
2946
- };
2947
- }, [currentDpr, defaultDpr, maxDpr, round]);
2948
- return currentDpr;
2949
- }
2950
- /**
2951
- * Returns the current device pixel ratio (DPR) given the passed options
2952
- *
2953
- * @param { DevicePixelRatioOptions } options the options object
2954
- * @returns { number } current device pixel ratio
2955
- */
2956
- function getDevicePixelRatio(options) {
2957
- const { defaultDpr = 1, maxDpr = 3, round = true } = options || {};
2958
- const hasDprProp = typeof window !== "undefined" && typeof window.devicePixelRatio === "number";
2959
- const dpr = hasDprProp ? window.devicePixelRatio : defaultDpr;
2960
- const rounded = Math.min(Math.max(1, round ? Math.floor(dpr) : dpr), maxDpr);
2961
- return rounded;
2962
- }
2963
-
2964
- /**
2965
- * The useLocalStorage hook works like useState, but saves to localstorage.
2966
- *
2967
- * @param {string} key - The key the values is saved under.
2968
- * @param {string | null | undefined} initialValue - The initial value for the state/local storage item
2969
- * @returns {string | null | undefined} value
2970
- */
2971
- const useLocalStorage = (key, initialValue) => {
2972
- if (!key) {
2973
- throw new Error("useLocalStorage key may not be falsy");
2974
- }
2975
- const setLocalStorageItem = React.useCallback((value) => window.localStorage.setItem(key, typeof value === "object" ? JSON.stringify(value) : `${value}`), [key]);
2976
- const removeLocalStorageItem = React.useCallback(() => window.localStorage.removeItem(key), [key]);
2977
- const [item, setValue] = React.useState(() => {
2978
- const value = window.localStorage.getItem(key);
2979
- if (value !== undefined && value !== null) {
2980
- const parsedValue = tryParse(value);
2981
- return parsedValue;
2982
- }
2983
- return initialValue !== null && initialValue !== void 0 ? initialValue : null;
2984
- });
2985
- React.useEffect(() => {
2986
- if (item !== undefined && item !== null) {
2987
- setLocalStorageItem(item);
2988
- }
2989
- else {
2990
- removeLocalStorageItem();
2991
- }
2992
- }, [item, setLocalStorageItem, removeLocalStorageItem, key]);
2993
- /*
2994
- // Sync local storage between tabs / windows
2995
- useEffect(() => {
2996
- const handleStorageChange = (e: StorageEvent) => {
2997
- if (e.key === key) {
2998
- setValue(tryParse(e.newValue));
2999
- }
3000
- };
3001
-
3002
- window.addEventListener("storage", handleStorageChange);
3003
-
3004
- return () => {
3005
- window.removeEventListener("storage", handleStorageChange);
3006
- };
3007
- // eslint-disable-next-line react-hooks/exhaustive-deps
3008
- }, []);
3009
- */
3010
- const removeItem = () => {
3011
- setValue(null);
3012
- };
3013
- return [item, setValue, removeItem];
3014
- };
3015
- function tryParse(value) {
3016
- try {
3017
- return JSON.parse(value);
3018
- }
3019
- catch (_a) {
3020
- return value;
3021
- }
3022
- }
3023
-
3024
- /**
3025
- * @param {UseTimeoutProps} props The props
3026
- * @returns {{ startTimeout: () => void; stopTimeout: () => void; isReady: boolean | null}} return
3027
- */
3028
- const useTimeout = ({ onTimeout, duration }) => {
3029
- const ready = React.useRef(false);
3030
- const timeout = React.useRef();
3031
- const callback = React.useRef(onTimeout);
3032
- const isReady = React.useCallback(() => ready.current, []);
3033
- const startTimeout = React.useCallback(() => {
3034
- ready.current = false;
3035
- timeout.current && clearTimeout(timeout.current);
3036
- timeout.current = setTimeout(() => {
3037
- ready.current = true;
3038
- callback.current();
3039
- }, duration);
3040
- }, [duration]);
3041
- const stopTimeout = React.useCallback(() => {
3042
- ready.current = null;
3043
- timeout.current && clearTimeout(timeout.current);
3044
- }, []);
3045
- // update ref when function changes
3046
- React.useEffect(() => {
3047
- callback.current = onTimeout;
3048
- }, [onTimeout]);
3049
- // startTimeout on mount, stopTimeout on unmount
3050
- React.useEffect(() => {
3051
- startTimeout();
3052
- return stopTimeout;
3053
- }, [duration, startTimeout, stopTimeout]);
3054
- return [isReady, stopTimeout, startTimeout];
3055
- };
3056
-
3057
3127
  /**
3058
3128
  * The MinTopFullContentLayout component.
3059
3129
  *
@@ -3331,6 +3401,7 @@ exports.getDevicePixelRatio = getDevicePixelRatio;
3331
3401
  exports.getOrderedOptions = getOrderedOptions;
3332
3402
  exports.getValueBarColorByValue = getValueBarColorByValue;
3333
3403
  exports.isMultiValue = isMultiValue;
3404
+ exports.useClickOutside = useClickOutside;
3334
3405
  exports.useContainerProps = useContainerProps;
3335
3406
  exports.useCustomComponents = useCustomComponents;
3336
3407
  exports.useDebounce = useDebounce;
@@ -3339,4 +3410,5 @@ exports.useLocalStorage = useLocalStorage;
3339
3410
  exports.useModal = useModal;
3340
3411
  exports.usePopoverContext = usePopoverContext;
3341
3412
  exports.usePrompt = usePrompt;
3413
+ exports.useResize = useResize;
3342
3414
  exports.useTimeout = useTimeout;
package/index.js CHANGED
@@ -9,7 +9,6 @@ import { format, formatDistance } from 'date-fns';
9
9
  import { useFloating, autoUpdate, offset, flip, shift, size, useClick, useDismiss, useHover, useRole, useInteractions, useMergeRefs, FloatingPortal, FloatingFocusManager } from '@floating-ui/react';
10
10
  import { DayPicker as DayPicker$1 } from 'react-day-picker';
11
11
  import { enGB, enUS, da, de, cs, nl, fr, fi, hu, it, nb, pl, pt, ru, ro, es, sv, ja, th } from 'date-fns/locale';
12
- import { useClickOutside } from 'react-browser-hooks';
13
12
  import usePortal from 'react-useportal';
14
13
  import ReactSelect, { components } from 'react-select';
15
14
  export { default as ValueType } from 'react-select';
@@ -968,7 +967,7 @@ const PopoverContent = React__default.forwardRef(function PopoverContent(_a, pro
968
967
  var { className, dataTestId, children } = _a, props = __rest(_a, ["className", "dataTestId", "children"]);
969
968
  const _f = usePopoverContext(), { context: floatingContext, customProps } = _f, context = __rest(_f, ["context", "customProps"]);
970
969
  const ref = useMergeRefs([context.refs.setFloating, propRef]);
971
- return (jsx(FloatingPortal, Object.assign({ id: "tu-floating-ui" }, { children: context.isOpen && (jsx(FloatingFocusManager, Object.assign({ guards: false, context: floatingContext, modal: context.isModal, order: ["reference", "content"] }, { children: jsx("div", Object.assign({ ref: ref, className: `tu-popover-container animate-fade-in-fast ${(_b = className !== null && className !== void 0 ? className : customProps.className) !== null && _b !== void 0 ? _b : ""}`, "data-testid": (_c = dataTestId !== null && dataTestId !== void 0 ? dataTestId : customProps.dataTestId) !== null && _c !== void 0 ? _c : "popover-content", style: Object.assign({ position: context.strategy, top: (_d = context.y) !== null && _d !== void 0 ? _d : 0, left: (_e = context.x) !== null && _e !== void 0 ? _e : 0, width: "max-content" }, props.style), "aria-labelledby": context.labelId, "aria-describedby": context.descriptionId }, context.getFloatingProps(props), { children: typeof children === "function" ? children(() => context.setIsOpen(false)) : children })) }))) })));
970
+ return (jsx(FloatingPortal, Object.assign({ id: "tu-floating-ui" }, { children: context.isOpen && (jsx(FloatingFocusManager, Object.assign({ guards: false, context: floatingContext, modal: context.isModal, order: ["reference", "content"], returnFocus: false }, { children: jsx("div", Object.assign({ ref: ref, className: `tu-popover-container animate-fade-in-fast ${(_b = className !== null && className !== void 0 ? className : customProps.className) !== null && _b !== void 0 ? _b : ""}`, "data-testid": (_c = dataTestId !== null && dataTestId !== void 0 ? dataTestId : customProps.dataTestId) !== null && _c !== void 0 ? _c : "popover-content", style: Object.assign({ position: context.strategy, top: (_d = context.y) !== null && _d !== void 0 ? _d : 0, left: (_e = context.x) !== null && _e !== void 0 ? _e : 0, width: "max-content" }, props.style), "aria-labelledby": context.labelId, "aria-describedby": context.descriptionId }, context.getFloatingProps(props), { children: typeof children === "function" ? children(() => context.setIsOpen(false)) : children })) }))) })));
972
971
  });
973
972
 
974
973
  /**
@@ -1463,6 +1462,241 @@ const Divider = tw.hr `
1463
1462
  tu-menu-list__divider
1464
1463
  `;
1465
1464
 
1465
+ /**
1466
+ * Custom hook to handle click outside events.
1467
+ *
1468
+ * @param {RefObject<HTMLElement> | Array<RefObject<HTMLElement>>} el - The reference(s) to the element(s) to watch for click outside events.
1469
+ * @param {Object | Function} [options={}] - Configuration options or the click event handler if options are not provided.
1470
+ * @param {boolean} [options.active=true] - Whether the click outside event listener should be active.
1471
+ * @param {Function} [onClick] - The event handler for the click outside event.
1472
+ */
1473
+ const useClickOutside = (el, options = {}, onClick) => {
1474
+ const els = Array.isArray(el) ? el : [el];
1475
+ let active = true;
1476
+ if (!onClick && typeof options === "function") {
1477
+ onClick = options;
1478
+ }
1479
+ else if (typeof options === "object") {
1480
+ active = options.active !== undefined ? options.active : active;
1481
+ }
1482
+ const handler = (ev) => {
1483
+ const target = ev.target;
1484
+ if (els.every(ref => !ref.current || !ref.current.contains(target))) {
1485
+ onClick && onClick(ev);
1486
+ }
1487
+ };
1488
+ const cleanup = () => window.removeEventListener("click", handler);
1489
+ useEffect(() => {
1490
+ if (active) {
1491
+ window.addEventListener("click", handler);
1492
+ }
1493
+ else {
1494
+ cleanup();
1495
+ }
1496
+ return cleanup;
1497
+ });
1498
+ };
1499
+
1500
+ /**
1501
+ * The useDebounce hook works like useState, but adds a delay where previous values will be ignored.
1502
+ *
1503
+ * @param {any} value The value to set
1504
+ * @param {number} delay The debounce time
1505
+ * @returns {any} value The latest values received
1506
+ */
1507
+ const useDebounce = (value, delay = 500) => {
1508
+ const [debouncedValue, setDebouncedValue] = useState(value);
1509
+ useEffect(() => {
1510
+ const handler = setTimeout(() => {
1511
+ setDebouncedValue(value);
1512
+ }, delay);
1513
+ return () => {
1514
+ clearTimeout(handler);
1515
+ };
1516
+ }, [value, delay]);
1517
+ return debouncedValue;
1518
+ };
1519
+
1520
+ // Copied from https://github.com/rexxars/use-device-pixel-ratio
1521
+ /**
1522
+ * Get the device pixel ratio, potentially rounded and capped.
1523
+ * Will emit new values if it changes.
1524
+ *
1525
+ * @param {DevicePixelRatioOptions} options the options object
1526
+ * @returns { number } The current device pixel ratio, or the default if none can be resolved
1527
+ */
1528
+ function useDevicePixelRatio(options) {
1529
+ const dpr = getDevicePixelRatio(options);
1530
+ const [currentDpr, setCurrentDpr] = useState(dpr);
1531
+ const { defaultDpr, maxDpr, round } = options || {};
1532
+ useEffect(() => {
1533
+ const canListen = typeof window !== "undefined" && "matchMedia" in window;
1534
+ if (!canListen) {
1535
+ return;
1536
+ }
1537
+ const updateDpr = () => setCurrentDpr(getDevicePixelRatio({ defaultDpr, maxDpr, round }));
1538
+ const mediaMatcher = window.matchMedia(`screen and (resolution: ${currentDpr}dppx)`);
1539
+ // Safari 13.1 does not have `addEventListener`, but does have `addListener`
1540
+ if (mediaMatcher.addEventListener) {
1541
+ mediaMatcher.addEventListener("change", updateDpr);
1542
+ }
1543
+ else {
1544
+ mediaMatcher.addListener(updateDpr);
1545
+ }
1546
+ return () => {
1547
+ if (mediaMatcher.removeEventListener) {
1548
+ mediaMatcher.removeEventListener("change", updateDpr);
1549
+ }
1550
+ else {
1551
+ mediaMatcher.removeListener(updateDpr);
1552
+ }
1553
+ };
1554
+ }, [currentDpr, defaultDpr, maxDpr, round]);
1555
+ return currentDpr;
1556
+ }
1557
+ /**
1558
+ * Returns the current device pixel ratio (DPR) given the passed options
1559
+ *
1560
+ * @param { DevicePixelRatioOptions } options the options object
1561
+ * @returns { number } current device pixel ratio
1562
+ */
1563
+ function getDevicePixelRatio(options) {
1564
+ const { defaultDpr = 1, maxDpr = 3, round = true } = options || {};
1565
+ const hasDprProp = typeof window !== "undefined" && typeof window.devicePixelRatio === "number";
1566
+ const dpr = hasDprProp ? window.devicePixelRatio : defaultDpr;
1567
+ const rounded = Math.min(Math.max(1, round ? Math.floor(dpr) : dpr), maxDpr);
1568
+ return rounded;
1569
+ }
1570
+
1571
+ /**
1572
+ * The useLocalStorage hook works like useState, but saves to localstorage.
1573
+ *
1574
+ * @param {string} key - The key the values is saved under.
1575
+ * @param {string | null | undefined} initialValue - The initial value for the state/local storage item
1576
+ * @returns {string | null | undefined} value
1577
+ */
1578
+ const useLocalStorage = (key, initialValue) => {
1579
+ if (!key) {
1580
+ throw new Error("useLocalStorage key may not be falsy");
1581
+ }
1582
+ const setLocalStorageItem = useCallback((value) => window.localStorage.setItem(key, typeof value === "object" ? JSON.stringify(value) : `${value}`), [key]);
1583
+ const removeLocalStorageItem = useCallback(() => window.localStorage.removeItem(key), [key]);
1584
+ const [item, setValue] = useState(() => {
1585
+ const value = window.localStorage.getItem(key);
1586
+ if (value !== undefined && value !== null) {
1587
+ const parsedValue = tryParse(value);
1588
+ return parsedValue;
1589
+ }
1590
+ return initialValue !== null && initialValue !== void 0 ? initialValue : null;
1591
+ });
1592
+ useEffect(() => {
1593
+ if (item !== undefined && item !== null) {
1594
+ setLocalStorageItem(item);
1595
+ }
1596
+ else {
1597
+ removeLocalStorageItem();
1598
+ }
1599
+ }, [item, setLocalStorageItem, removeLocalStorageItem, key]);
1600
+ /*
1601
+ // Sync local storage between tabs / windows
1602
+ useEffect(() => {
1603
+ const handleStorageChange = (e: StorageEvent) => {
1604
+ if (e.key === key) {
1605
+ setValue(tryParse(e.newValue));
1606
+ }
1607
+ };
1608
+
1609
+ window.addEventListener("storage", handleStorageChange);
1610
+
1611
+ return () => {
1612
+ window.removeEventListener("storage", handleStorageChange);
1613
+ };
1614
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1615
+ }, []);
1616
+ */
1617
+ const removeItem = () => {
1618
+ setValue(null);
1619
+ };
1620
+ return [item, setValue, removeItem];
1621
+ };
1622
+ function tryParse(value) {
1623
+ try {
1624
+ return JSON.parse(value);
1625
+ }
1626
+ catch (_a) {
1627
+ return value;
1628
+ }
1629
+ }
1630
+
1631
+ /**
1632
+ * Custom hook to handle window resize events and provide the current window size.
1633
+ *
1634
+ * @returns {WindowSize} An object containing the current window height and width.
1635
+ */
1636
+ const useResize = () => {
1637
+ const [size, setSize] = useState(getWindowSize());
1638
+ useEffect(() => {
1639
+ const handleResize = () => {
1640
+ setSize(getWindowSize());
1641
+ };
1642
+ window.addEventListener("resize", handleResize, false);
1643
+ return () => window.removeEventListener("resize", handleResize);
1644
+ }, [setSize]);
1645
+ return size;
1646
+ };
1647
+ /**
1648
+ * Get the current window size.
1649
+ *
1650
+ * @returns {WindowSize} An object containing the current window height and width.
1651
+ */
1652
+ const getWindowSize = () => {
1653
+ try {
1654
+ return {
1655
+ height: window.innerHeight,
1656
+ width: window.innerWidth,
1657
+ };
1658
+ }
1659
+ catch (err) {
1660
+ return {
1661
+ height: 0,
1662
+ width: 0,
1663
+ };
1664
+ }
1665
+ };
1666
+
1667
+ /**
1668
+ * @param {UseTimeoutProps} props The props
1669
+ * @returns {{ startTimeout: () => void; stopTimeout: () => void; isReady: boolean | null}} return
1670
+ */
1671
+ const useTimeout = ({ onTimeout, duration }) => {
1672
+ const ready = useRef(false);
1673
+ const timeout = useRef();
1674
+ const callback = useRef(onTimeout);
1675
+ const isReady = useCallback(() => ready.current, []);
1676
+ const startTimeout = useCallback(() => {
1677
+ ready.current = false;
1678
+ timeout.current && clearTimeout(timeout.current);
1679
+ timeout.current = setTimeout(() => {
1680
+ ready.current = true;
1681
+ callback.current();
1682
+ }, duration);
1683
+ }, [duration]);
1684
+ const stopTimeout = useCallback(() => {
1685
+ ready.current = null;
1686
+ timeout.current && clearTimeout(timeout.current);
1687
+ }, []);
1688
+ // update ref when function changes
1689
+ useEffect(() => {
1690
+ callback.current = onTimeout;
1691
+ }, [onTimeout]);
1692
+ // startTimeout on mount, stopTimeout on unmount
1693
+ useEffect(() => {
1694
+ startTimeout();
1695
+ return stopTimeout;
1696
+ }, [duration, startTimeout, stopTimeout]);
1697
+ return [isReady, stopTimeout, startTimeout];
1698
+ };
1699
+
1466
1700
  /**
1467
1701
  * A kebab menu component.
1468
1702
  * Advice: fill it with MenuList
@@ -1486,7 +1720,7 @@ const MoreMenu = ({ className, dataTestId, dotsDirection = "horizontal", menuPla
1486
1720
  });
1487
1721
  return (jsx(Root$4, Object.assign({ ref: actionMenuRef, className: className, "data-testid": dataTestId }, { children: jsxs(Popover, Object.assign({ placement: menuPlacement }, { children: [jsx(PopoverTrigger, { children: jsx(IconButton, Object.assign({}, iconButtonProps, { icon: jsx(Icon, Object.assign({ name: dotsName }, iconProps)), onClick: () => {
1488
1722
  setActionMenuIsOpen(!actionMenuIsOpen);
1489
- } })) }), jsx(PopoverContent, { children: children })] })) })));
1723
+ } })) }), jsx(PopoverContent, { children: close => (typeof children === "function" ? children(close) : children) })] })) })));
1490
1724
  };
1491
1725
  const Root$4 = tw.div `
1492
1726
  tu-more-menu
@@ -2860,170 +3094,6 @@ const Bar = tw.rect `
2860
3094
  tu-value-bar__bar
2861
3095
  `;
2862
3096
 
2863
- /**
2864
- * The useDebounce hook works like useState, but adds a delay where previous values will be ignored.
2865
- *
2866
- * @param {any} value The value to set
2867
- * @param {number} delay The debounce time
2868
- * @returns {any} value The latest values received
2869
- */
2870
- const useDebounce = (value, delay = 500) => {
2871
- const [debouncedValue, setDebouncedValue] = useState(value);
2872
- useEffect(() => {
2873
- const handler = setTimeout(() => {
2874
- setDebouncedValue(value);
2875
- }, delay);
2876
- return () => {
2877
- clearTimeout(handler);
2878
- };
2879
- }, [value, delay]);
2880
- return debouncedValue;
2881
- };
2882
-
2883
- // Copied from https://github.com/rexxars/use-device-pixel-ratio
2884
- /**
2885
- * Get the device pixel ratio, potentially rounded and capped.
2886
- * Will emit new values if it changes.
2887
- *
2888
- * @param {DevicePixelRatioOptions} options the options object
2889
- * @returns { number } The current device pixel ratio, or the default if none can be resolved
2890
- */
2891
- function useDevicePixelRatio(options) {
2892
- const dpr = getDevicePixelRatio(options);
2893
- const [currentDpr, setCurrentDpr] = useState(dpr);
2894
- const { defaultDpr, maxDpr, round } = options || {};
2895
- useEffect(() => {
2896
- const canListen = typeof window !== "undefined" && "matchMedia" in window;
2897
- if (!canListen) {
2898
- return;
2899
- }
2900
- const updateDpr = () => setCurrentDpr(getDevicePixelRatio({ defaultDpr, maxDpr, round }));
2901
- const mediaMatcher = window.matchMedia(`screen and (resolution: ${currentDpr}dppx)`);
2902
- // Safari 13.1 does not have `addEventListener`, but does have `addListener`
2903
- if (mediaMatcher.addEventListener) {
2904
- mediaMatcher.addEventListener("change", updateDpr);
2905
- }
2906
- else {
2907
- mediaMatcher.addListener(updateDpr);
2908
- }
2909
- return () => {
2910
- if (mediaMatcher.removeEventListener) {
2911
- mediaMatcher.removeEventListener("change", updateDpr);
2912
- }
2913
- else {
2914
- mediaMatcher.removeListener(updateDpr);
2915
- }
2916
- };
2917
- }, [currentDpr, defaultDpr, maxDpr, round]);
2918
- return currentDpr;
2919
- }
2920
- /**
2921
- * Returns the current device pixel ratio (DPR) given the passed options
2922
- *
2923
- * @param { DevicePixelRatioOptions } options the options object
2924
- * @returns { number } current device pixel ratio
2925
- */
2926
- function getDevicePixelRatio(options) {
2927
- const { defaultDpr = 1, maxDpr = 3, round = true } = options || {};
2928
- const hasDprProp = typeof window !== "undefined" && typeof window.devicePixelRatio === "number";
2929
- const dpr = hasDprProp ? window.devicePixelRatio : defaultDpr;
2930
- const rounded = Math.min(Math.max(1, round ? Math.floor(dpr) : dpr), maxDpr);
2931
- return rounded;
2932
- }
2933
-
2934
- /**
2935
- * The useLocalStorage hook works like useState, but saves to localstorage.
2936
- *
2937
- * @param {string} key - The key the values is saved under.
2938
- * @param {string | null | undefined} initialValue - The initial value for the state/local storage item
2939
- * @returns {string | null | undefined} value
2940
- */
2941
- const useLocalStorage = (key, initialValue) => {
2942
- if (!key) {
2943
- throw new Error("useLocalStorage key may not be falsy");
2944
- }
2945
- const setLocalStorageItem = useCallback((value) => window.localStorage.setItem(key, typeof value === "object" ? JSON.stringify(value) : `${value}`), [key]);
2946
- const removeLocalStorageItem = useCallback(() => window.localStorage.removeItem(key), [key]);
2947
- const [item, setValue] = useState(() => {
2948
- const value = window.localStorage.getItem(key);
2949
- if (value !== undefined && value !== null) {
2950
- const parsedValue = tryParse(value);
2951
- return parsedValue;
2952
- }
2953
- return initialValue !== null && initialValue !== void 0 ? initialValue : null;
2954
- });
2955
- useEffect(() => {
2956
- if (item !== undefined && item !== null) {
2957
- setLocalStorageItem(item);
2958
- }
2959
- else {
2960
- removeLocalStorageItem();
2961
- }
2962
- }, [item, setLocalStorageItem, removeLocalStorageItem, key]);
2963
- /*
2964
- // Sync local storage between tabs / windows
2965
- useEffect(() => {
2966
- const handleStorageChange = (e: StorageEvent) => {
2967
- if (e.key === key) {
2968
- setValue(tryParse(e.newValue));
2969
- }
2970
- };
2971
-
2972
- window.addEventListener("storage", handleStorageChange);
2973
-
2974
- return () => {
2975
- window.removeEventListener("storage", handleStorageChange);
2976
- };
2977
- // eslint-disable-next-line react-hooks/exhaustive-deps
2978
- }, []);
2979
- */
2980
- const removeItem = () => {
2981
- setValue(null);
2982
- };
2983
- return [item, setValue, removeItem];
2984
- };
2985
- function tryParse(value) {
2986
- try {
2987
- return JSON.parse(value);
2988
- }
2989
- catch (_a) {
2990
- return value;
2991
- }
2992
- }
2993
-
2994
- /**
2995
- * @param {UseTimeoutProps} props The props
2996
- * @returns {{ startTimeout: () => void; stopTimeout: () => void; isReady: boolean | null}} return
2997
- */
2998
- const useTimeout = ({ onTimeout, duration }) => {
2999
- const ready = useRef(false);
3000
- const timeout = useRef();
3001
- const callback = useRef(onTimeout);
3002
- const isReady = useCallback(() => ready.current, []);
3003
- const startTimeout = useCallback(() => {
3004
- ready.current = false;
3005
- timeout.current && clearTimeout(timeout.current);
3006
- timeout.current = setTimeout(() => {
3007
- ready.current = true;
3008
- callback.current();
3009
- }, duration);
3010
- }, [duration]);
3011
- const stopTimeout = useCallback(() => {
3012
- ready.current = null;
3013
- timeout.current && clearTimeout(timeout.current);
3014
- }, []);
3015
- // update ref when function changes
3016
- useEffect(() => {
3017
- callback.current = onTimeout;
3018
- }, [onTimeout]);
3019
- // startTimeout on mount, stopTimeout on unmount
3020
- useEffect(() => {
3021
- startTimeout();
3022
- return stopTimeout;
3023
- }, [duration, startTimeout, stopTimeout]);
3024
- return [isReady, stopTimeout, startTimeout];
3025
- };
3026
-
3027
3097
  /**
3028
3098
  * The MinTopFullContentLayout component.
3029
3099
  *
@@ -3208,4 +3278,4 @@ const Layout = tw.div `
3208
3278
  tu-layout-TwoColumnLayout
3209
3279
  `;
3210
3280
 
3211
- export { ActionButton, Alert, Badge, BaseInput, Button, Card, CardBody, CardFooter, CardHeader, Checkbox, Collapse, ContentGridArea, CopyableText, CreatableSelect, DateField, DateInput, DayPicker, DayPickerPopover, DayRangePicker, DensityContainer, Drawer, DropZone, EmailField, EmailInput, ExternalLink, FilterListMapLayout, FormGroup, FullWidthRepeatingLayout, GridArea, Heading$1 as Heading, Icon, IconButton, Indicator, IntrinsicallyResponsiveGrid, Label$2 as Label, MenuItem, MenuList, MinTopFullContentLayout, Modal, ModalBackdrop, MoreMenu, MultiSelectMenuItem, NavGridArea, NumberField, NumberInput, PageHeader, Pagination, PhoneField, PhoneInput, Popover, PopoverContent, PopoverTitle, PopoverTrigger, Prompt, ROLE_CARD, RadioGroup, RadioItem, Search, SectionHeader, Select, SelectPrefix, Sidebar, SingleSelectMenuItem, SkeletonLines, Spacer, Spinner, StarButton, Tag, Text$1 as Text, TextArea, TextAreaField, TextField, TextInput, Timeline, TimelineElement, Tip, TitleGridArea, TitleNavContentLayout, Toggle, Tooltip, TwoColumnLayout, UploadField, UploadInput, ValueBar, docs, getDevicePixelRatio, getOrderedOptions, getValueBarColorByValue, isMultiValue, useContainerProps, useCustomComponents, useDebounce, useDevicePixelRatio, useLocalStorage, useModal, usePopoverContext, usePrompt, useTimeout };
3281
+ export { ActionButton, Alert, Badge, BaseInput, Button, Card, CardBody, CardFooter, CardHeader, Checkbox, Collapse, ContentGridArea, CopyableText, CreatableSelect, DateField, DateInput, DayPicker, DayPickerPopover, DayRangePicker, DensityContainer, Drawer, DropZone, EmailField, EmailInput, ExternalLink, FilterListMapLayout, FormGroup, FullWidthRepeatingLayout, GridArea, Heading$1 as Heading, Icon, IconButton, Indicator, IntrinsicallyResponsiveGrid, Label$2 as Label, MenuItem, MenuList, MinTopFullContentLayout, Modal, ModalBackdrop, MoreMenu, MultiSelectMenuItem, NavGridArea, NumberField, NumberInput, PageHeader, Pagination, PhoneField, PhoneInput, Popover, PopoverContent, PopoverTitle, PopoverTrigger, Prompt, ROLE_CARD, RadioGroup, RadioItem, Search, SectionHeader, Select, SelectPrefix, Sidebar, SingleSelectMenuItem, SkeletonLines, Spacer, Spinner, StarButton, Tag, Text$1 as Text, TextArea, TextAreaField, TextField, TextInput, Timeline, TimelineElement, Tip, TitleGridArea, TitleNavContentLayout, Toggle, Tooltip, TwoColumnLayout, UploadField, UploadInput, ValueBar, docs, getDevicePixelRatio, getOrderedOptions, getValueBarColorByValue, isMultiValue, useClickOutside, useContainerProps, useCustomComponents, useDebounce, useDevicePixelRatio, useLocalStorage, useModal, usePopoverContext, usePrompt, useResize, useTimeout };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-components",
3
- "version": "0.1.68",
3
+ "version": "0.1.70",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "dependencies": {
@@ -14,7 +14,6 @@
14
14
  "react-day-picker": "8.3.7",
15
15
  "@floating-ui/react": "0.22.2",
16
16
  "@trackunit/ui-icons": "0.0.61",
17
- "react-browser-hooks": "2.2.4",
18
17
  "react-useportal": "1.0.17",
19
18
  "libphonenumber-js": "1.10.24",
20
19
  "react-router-dom": "6.4.5",
@@ -1,9 +1,9 @@
1
1
  /// <reference types="react" />
2
2
  import { GroupBase } from "react-select";
3
3
  import { SelectProps } from "./useSelect";
4
- export interface SelectOption {
4
+ export interface SelectOption<T extends string> {
5
5
  label: string;
6
- value: string;
6
+ value: T;
7
7
  disabled?: boolean;
8
8
  }
9
9
  /**
@@ -1,4 +1,6 @@
1
+ export * from "./useClickOutside";
1
2
  export * from "./useDebounce";
2
3
  export * from "./useDevicePixelRatio";
3
4
  export * from "./useLocalStorage";
5
+ export * from "./useResize";
4
6
  export * from "./useTimeout";
@@ -0,0 +1,12 @@
1
+ import { RefObject } from "react";
2
+ /**
3
+ * Custom hook to handle click outside events.
4
+ *
5
+ * @param {RefObject<HTMLElement> | Array<RefObject<HTMLElement>>} el - The reference(s) to the element(s) to watch for click outside events.
6
+ * @param {Object | Function} [options={}] - Configuration options or the click event handler if options are not provided.
7
+ * @param {boolean} [options.active=true] - Whether the click outside event listener should be active.
8
+ * @param {Function} [onClick] - The event handler for the click outside event.
9
+ */
10
+ export declare const useClickOutside: (el: RefObject<HTMLElement> | RefObject<HTMLElement>[], options?: {
11
+ active?: boolean | undefined;
12
+ } | ((ev: MouseEvent) => void), onClick?: ((ev: MouseEvent) => void) | undefined) => void;
@@ -0,0 +1,10 @@
1
+ export interface WindowSize {
2
+ height: number;
3
+ width: number;
4
+ }
5
+ /**
6
+ * Custom hook to handle window resize events and provide the current window size.
7
+ *
8
+ * @returns {WindowSize} An object containing the current window height and width.
9
+ */
10
+ export declare const useResize: () => WindowSize;