@trackunit/react-components 0.1.68 → 0.1.69
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 +240 -168
- package/index.js +238 -168
- package/package.json +1 -2
- package/src/hooks/index.d.ts +2 -0
- package/src/hooks/useClickOutside.d.ts +12 -0
- package/src/hooks/useResize.d.ts +10 -0
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
|
-
|
|
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.
|
|
3
|
+
"version": "0.1.69",
|
|
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",
|
package/src/hooks/index.d.ts
CHANGED
|
@@ -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;
|