@trackunit/react-components 0.1.67 → 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 +272 -192
- package/index.css +23 -24
- package/index.js +270 -192
- package/package.json +2 -2
- package/src/components/FormGroup/FormGroup.d.ts +2 -1
- 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
|
@@ -7,11 +7,11 @@ var tailwindStyledComponents = require('@trackunit/tailwind-styled-components');
|
|
|
7
7
|
var React = require('react');
|
|
8
8
|
var uiIcons = require('@trackunit/ui-icons');
|
|
9
9
|
var reactUse = require('react-use');
|
|
10
|
+
var uuid = require('uuid');
|
|
10
11
|
var dateFns = require('date-fns');
|
|
11
12
|
var react = require('@floating-ui/react');
|
|
12
13
|
var reactDayPicker = require('react-day-picker');
|
|
13
14
|
var locale = require('date-fns/locale');
|
|
14
|
-
var reactBrowserHooks = require('react-browser-hooks');
|
|
15
15
|
var usePortal = require('react-useportal');
|
|
16
16
|
var ReactSelect = require('react-select');
|
|
17
17
|
var ReactAsyncCreatableSelect = require('react-select/async-creatable');
|
|
@@ -825,7 +825,7 @@ const CheckboxWrapper = tailwindStyledComponents.tw.span `
|
|
|
825
825
|
? tailwindStyledComponents.tws `tu-checkbox--selected`
|
|
826
826
|
: tailwindStyledComponents.tws `tu-checkbox--deselected`;
|
|
827
827
|
}}
|
|
828
|
-
|
|
828
|
+
|
|
829
829
|
${({ $isInvalid }) => $isInvalid && tailwindStyledComponents.tws `tu-checkbox--invalid`}
|
|
830
830
|
`;
|
|
831
831
|
|
|
@@ -997,7 +997,7 @@ const PopoverContent = React__default["default"].forwardRef(function PopoverCont
|
|
|
997
997
|
var { className, dataTestId, children } = _a, props = __rest(_a, ["className", "dataTestId", "children"]);
|
|
998
998
|
const _f = usePopoverContext(), { context: floatingContext, customProps } = _f, context = __rest(_f, ["context", "customProps"]);
|
|
999
999
|
const ref = react.useMergeRefs([context.refs.setFloating, propRef]);
|
|
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"] }, { 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 })) }))) })));
|
|
1001
1001
|
});
|
|
1002
1002
|
|
|
1003
1003
|
/**
|
|
@@ -1079,13 +1079,13 @@ const TipContainer = tailwindStyledComponents.tw.text `
|
|
|
1079
1079
|
* @param {FormGroupProps} props - The props for the FormGroup component
|
|
1080
1080
|
* @returns {JSX.Element} FormGroup component
|
|
1081
1081
|
*/
|
|
1082
|
-
const FormGroup = ({ isInvalid, helpText, helpAddon, tip, className, dataTestId, label, children, disabled = false, }) => {
|
|
1083
|
-
return (jsxRuntime.jsxs(FormGroupRoot, Object.assign({ className: className, "data-testid": dataTestId, "$disabled": disabled }, { children: [jsxRuntime.jsxs(ContainerBefore, { children: [jsxRuntime.jsx(FormGroupLabel, Object.assign({ dataTestId: dataTestId && `${dataTestId}-label
|
|
1082
|
+
const FormGroup = ({ isInvalid, helpText, helpAddon, tip, className, dataTestId, label, htmlFor, children, disabled = false, }) => {
|
|
1083
|
+
return (jsxRuntime.jsxs(FormGroupRoot, Object.assign({ className: className, "data-testid": dataTestId, "$disabled": disabled }, { children: [jsxRuntime.jsxs(ContainerBefore, { children: [jsxRuntime.jsx(FormGroupLabel, Object.assign({ dataTestId: dataTestId && `${dataTestId}-label`, htmlFor: htmlFor, id: htmlFor + "-label" }, { children: label })), tip && jsxRuntime.jsx(Tip, Object.assign({ dataTestId: dataTestId && `${dataTestId}-tip` }, { children: tip }))] }), children, jsxRuntime.jsxs(ContainerAfter, Object.assign({ "$isInvalid": isInvalid }, { children: [helpText && jsxRuntime.jsx("span", Object.assign({ "data-testid": dataTestId && `${dataTestId}-helpText` }, { children: helpText })), helpAddon && jsxRuntime.jsx(HelpAddon, Object.assign({ "data-testid": dataTestId && `${dataTestId}-helpAddon` }, { children: helpAddon }))] }))] })));
|
|
1084
1084
|
};
|
|
1085
|
-
const FormGroupRoot = tailwindStyledComponents.tw.
|
|
1085
|
+
const FormGroupRoot = tailwindStyledComponents.tw.div `
|
|
1086
1086
|
tu-form-group
|
|
1087
1087
|
${({ $disabled }) => {
|
|
1088
|
-
return $disabled ? "pointer-events-none
|
|
1088
|
+
return $disabled ? "pointer-events-none" : null;
|
|
1089
1089
|
}}
|
|
1090
1090
|
`;
|
|
1091
1091
|
const ContainerBefore = tailwindStyledComponents.tw.div `
|
|
@@ -1099,7 +1099,7 @@ const ContainerAfter = tailwindStyledComponents.tw.div `
|
|
|
1099
1099
|
${({ $isInvalid }) => ($isInvalid ? tailwindStyledComponents.tws `tu-form-group__container-after--invalid` : null)}
|
|
1100
1100
|
`;
|
|
1101
1101
|
const HelpAddon = tailwindStyledComponents.tw.span `
|
|
1102
|
-
tu-form-group__help-addon
|
|
1102
|
+
tu-form-group__help-addon
|
|
1103
1103
|
`;
|
|
1104
1104
|
|
|
1105
1105
|
/**
|
|
@@ -1110,9 +1110,10 @@ const HelpAddon = tailwindStyledComponents.tw.span `
|
|
|
1110
1110
|
* _**Do not use**_ this fields for non-serialized dates. Use TextField instead.
|
|
1111
1111
|
*/
|
|
1112
1112
|
const DateField = React.forwardRef((_a, ref) => {
|
|
1113
|
-
var { label, tip, helpText, errorMessage, helpAddon, isInvalid, className, defaultValue, dataTestId } = _a, rest = __rest(_a, ["label", "tip", "helpText", "errorMessage", "helpAddon", "isInvalid", "className", "defaultValue", "dataTestId"]);
|
|
1113
|
+
var { label, id, tip, helpText, errorMessage, helpAddon, isInvalid, className, defaultValue, dataTestId } = _a, rest = __rest(_a, ["label", "id", "tip", "helpText", "errorMessage", "helpAddon", "isInvalid", "className", "defaultValue", "dataTestId"]);
|
|
1114
1114
|
const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
|
|
1115
|
-
|
|
1115
|
+
const htmlForId = id ? id : "dateField-" + uuid.v4();
|
|
1116
|
+
return (jsxRuntime.jsx(FormGroup, Object.assign({ htmlFor: htmlForId, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, helpAddon: helpAddon, disabled: rest.disabled, dataTestId: dataTestId && `${dataTestId}-FormGroup` }, { children: jsxRuntime.jsx(DateInput, Object.assign({ id: htmlForId, "aria-labelledby": htmlForId + "-label", ref: ref, defaultValue: defaultValue, isInvalid: renderAsInvalid }, rest, { className: className, dataTestId: dataTestId })) })));
|
|
1116
1117
|
});
|
|
1117
1118
|
|
|
1118
1119
|
const localeLookup = {
|
|
@@ -1326,15 +1327,16 @@ const EmailInput = React__namespace.forwardRef((_a, ref) => {
|
|
|
1326
1327
|
*
|
|
1327
1328
|
*/
|
|
1328
1329
|
const EmailField = React.forwardRef((_a, ref) => {
|
|
1329
|
-
var { label, tip, helpText, errorMessage, helpAddon, className, defaultValue, dataTestId } = _a, rest = __rest(_a, ["label", "tip", "helpText", "errorMessage", "helpAddon", "className", "defaultValue", "dataTestId"]);
|
|
1330
|
+
var { label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, dataTestId } = _a, rest = __rest(_a, ["label", "id", "tip", "helpText", "errorMessage", "helpAddon", "className", "defaultValue", "dataTestId"]);
|
|
1330
1331
|
const [value, setValue] = React.useState(defaultValue);
|
|
1332
|
+
const htmlForId = id ? id : "emailField-" + uuid.v4();
|
|
1331
1333
|
// Type guard to check if value is a string
|
|
1332
1334
|
function isString(inputValue) {
|
|
1333
1335
|
return typeof inputValue === "string";
|
|
1334
1336
|
}
|
|
1335
1337
|
// Check the regular expression only if value is a string
|
|
1336
1338
|
const renderAsInvalid = !!errorMessage || (isString(value) && !/^\S+@\S+\.\S+$/.test(value));
|
|
1337
|
-
return (jsxRuntime.jsx(FormGroup, Object.assign({ label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, helpAddon: helpAddon, disabled: rest.disabled, dataTestId: dataTestId && `${dataTestId}-FormGroup` }, { children: jsxRuntime.jsx(EmailInput, Object.assign({ ref: ref, value: value, onChange: e => setValue(e.target.value), isInvalid: renderAsInvalid, disabled: renderAsInvalid }, rest, { className: className, dataTestId: dataTestId })) })));
|
|
1339
|
+
return (jsxRuntime.jsx(FormGroup, Object.assign({ htmlFor: htmlForId, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, helpAddon: helpAddon, disabled: rest.disabled, dataTestId: dataTestId && `${dataTestId}-FormGroup` }, { children: jsxRuntime.jsx(EmailInput, Object.assign({ id: htmlForId, "aria-labelledby": htmlForId + "-label", ref: ref, value: value, onChange: e => setValue(e.target.value), isInvalid: renderAsInvalid, disabled: renderAsInvalid }, rest, { className: className, dataTestId: dataTestId })) })));
|
|
1338
1340
|
});
|
|
1339
1341
|
|
|
1340
1342
|
/**
|
|
@@ -1490,6 +1492,241 @@ const Divider = tailwindStyledComponents.tw.hr `
|
|
|
1490
1492
|
tu-menu-list__divider
|
|
1491
1493
|
`;
|
|
1492
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
|
+
|
|
1493
1730
|
/**
|
|
1494
1731
|
* A kebab menu component.
|
|
1495
1732
|
* Advice: fill it with MenuList
|
|
@@ -1508,12 +1745,12 @@ const MoreMenu = ({ className, dataTestId, dotsDirection = "horizontal", menuPla
|
|
|
1508
1745
|
const [actionMenuIsOpen, setActionMenuIsOpen] = React.useState(false);
|
|
1509
1746
|
const dotsName = dotsDirection === "horizontal" ? "EllipsisHorizontalIcon" : "EllipsisVerticalIcon";
|
|
1510
1747
|
const actionMenuRef = React.useRef(null);
|
|
1511
|
-
|
|
1748
|
+
useClickOutside(actionMenuRef, () => {
|
|
1512
1749
|
setActionMenuIsOpen(false);
|
|
1513
1750
|
});
|
|
1514
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: () => {
|
|
1515
1752
|
setActionMenuIsOpen(!actionMenuIsOpen);
|
|
1516
|
-
} })) }), jsxRuntime.jsx(PopoverContent, { children: children })] })) })));
|
|
1753
|
+
} })) }), jsxRuntime.jsx(PopoverContent, { children: close => (typeof children === "function" ? children(close) : children) })] })) })));
|
|
1517
1754
|
};
|
|
1518
1755
|
const Root$4 = tailwindStyledComponents.tw.div `
|
|
1519
1756
|
tu-more-menu
|
|
@@ -1609,9 +1846,10 @@ const NumberInput = React.forwardRef((props, ref) => (jsxRuntime.jsx(BaseInput,
|
|
|
1609
1846
|
* _**Do not use**_ this fields for non-serialized numbers. Use TextField instead.
|
|
1610
1847
|
*/
|
|
1611
1848
|
const NumberField = React.forwardRef((_a, ref) => {
|
|
1612
|
-
var { label, tip, helpText, errorMessage, helpAddon, isInvalid, maxLength, className, value, dataTestId } = _a, rest = __rest(_a, ["label", "tip", "helpText", "errorMessage", "helpAddon", "isInvalid", "maxLength", "className", "value", "dataTestId"]);
|
|
1849
|
+
var { label, id, tip, helpText, errorMessage, helpAddon, isInvalid, maxLength, className, value, dataTestId } = _a, rest = __rest(_a, ["label", "id", "tip", "helpText", "errorMessage", "helpAddon", "isInvalid", "maxLength", "className", "value", "dataTestId"]);
|
|
1613
1850
|
const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
|
|
1614
|
-
|
|
1851
|
+
const htmlForId = id ? id : "numberField-" + uuid.v4();
|
|
1852
|
+
return (jsxRuntime.jsx(FormGroup, Object.assign({ htmlFor: htmlForId, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, helpAddon: helpAddon, dataTestId: dataTestId && `${dataTestId}-FormGroup` }, { children: jsxRuntime.jsx(NumberInput, Object.assign({ id: htmlForId, "aria-labelledby": htmlForId + "-label", ref: ref, maxLength: maxLength, value: value, isInvalid: renderAsInvalid }, rest, { className: className, dataTestId: dataTestId })) })));
|
|
1615
1853
|
});
|
|
1616
1854
|
|
|
1617
1855
|
/**
|
|
@@ -2340,9 +2578,10 @@ const Container = tailwindStyledComponents.tw.div `
|
|
|
2340
2578
|
* @returns {JSX.Element} - The PhoneField component.
|
|
2341
2579
|
*/
|
|
2342
2580
|
const PhoneField = React.forwardRef((_a, ref) => {
|
|
2343
|
-
var { label, tip, helpText, isInvalid, errorMessage, value, helpAddon, className, defaultValue, dataTestId } = _a, rest = __rest(_a, ["label", "tip", "helpText", "isInvalid", "errorMessage", "value", "helpAddon", "className", "defaultValue", "dataTestId"]);
|
|
2581
|
+
var { label, id, tip, helpText, isInvalid, errorMessage, value, helpAddon, className, defaultValue, dataTestId } = _a, rest = __rest(_a, ["label", "id", "tip", "helpText", "isInvalid", "errorMessage", "value", "helpAddon", "className", "defaultValue", "dataTestId"]);
|
|
2344
2582
|
const renderAsInvalid = isInvalid || Boolean(errorMessage);
|
|
2345
|
-
|
|
2583
|
+
const htmlForId = id ? id : "phoneField-" + uuid.v4();
|
|
2584
|
+
return (jsxRuntime.jsx(FormGroup, Object.assign({ htmlFor: htmlForId, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, helpAddon: helpAddon, disabled: rest.disabled, className: className, dataTestId: dataTestId && `${dataTestId}-FormGroup` }, { children: jsxRuntime.jsx(PhoneInput, Object.assign({ id: htmlForId, "aria-labelledby": htmlForId + "-label", value: value || defaultValue, isInvalid: renderAsInvalid }, rest)) })));
|
|
2346
2585
|
});
|
|
2347
2586
|
|
|
2348
2587
|
function useConfirmExit(confirmExit, when = true) {
|
|
@@ -2436,7 +2675,7 @@ ${({ $inline }) => ($inline ? tailwindStyledComponents.tws `tu-radiogroup--inlin
|
|
|
2436
2675
|
const RadioItem = ({ label, value, dataTestId, className, description }) => {
|
|
2437
2676
|
const groupCtx = React__namespace.useContext(RadioGroupContext);
|
|
2438
2677
|
const isChecked = (groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.value) === value;
|
|
2439
|
-
return (jsxRuntime.jsxs(InputWrapper, Object.assign({ className: className, htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}
|
|
2678
|
+
return (jsxRuntime.jsxs(InputWrapper, Object.assign({ className: className, htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, "data-testid": dataTestId && `${dataTestId}-Wrapper` }, { children: [jsxRuntime.jsx(Input, { id: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, type: "radio", role: "radio", value: value, checked: isChecked, "$disabled": groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled, "$isInvalid": groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.isInvalid, onChange: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.onChange, "data-testid": dataTestId, "$checked": isChecked }), jsxRuntime.jsxs(LabelContainer$1, { children: [jsxRuntime.jsx(Label$2, Object.assign({ htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, dataTestId: dataTestId && `${dataTestId}-Label`, disabled: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled, isInvalid: groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.isInvalid }, { children: label })), description && (jsxRuntime.jsx(Description$1, Object.assign({ htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, "data-testid": dataTestId && `${dataTestId}-Description`, "$disabled": groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.disabled }, { children: description })))] })] })));
|
|
2440
2679
|
};
|
|
2441
2680
|
const InputWrapper = tailwindStyledComponents.tw.label `tu-radioitem__wrapper`;
|
|
2442
2681
|
const Input = tailwindStyledComponents.tw.input `
|
|
@@ -2631,7 +2870,7 @@ const ChildContainer = tailwindStyledComponents.tw.div `
|
|
|
2631
2870
|
*/
|
|
2632
2871
|
const TextArea = React__namespace.forwardRef((_a, ref) => {
|
|
2633
2872
|
var { id, name, value, rows, disabled, placeholder, readOnly, tabIndex, onChange, onFocus, onBlur, maxLength, resize = "vertical", defaultValue, className, required, dataTestId, isInvalid } = _a, rest = __rest(_a, ["id", "name", "value", "rows", "disabled", "placeholder", "readOnly", "tabIndex", "onChange", "onFocus", "onBlur", "maxLength", "resize", "defaultValue", "className", "required", "dataTestId", "isInvalid"]);
|
|
2634
|
-
return (jsxRuntime.jsx(StyledTextArea, Object.assign({ name: name, value: value, rows: rows, disabled: disabled, placeholder: placeholder, readOnly: readOnly, tabIndex: tabIndex, onFocus: onFocus, onBlur: onBlur, maxLength: maxLength, "$resize": resize, "$invalid": isInvalid, ref: ref, defaultValue: defaultValue, required: required }, rest, { onChange: onChange, "data-testid": dataTestId })));
|
|
2873
|
+
return (jsxRuntime.jsx(StyledTextArea, Object.assign({ id: id, name: name, value: value, rows: rows, disabled: disabled, placeholder: placeholder, readOnly: readOnly, tabIndex: tabIndex, onFocus: onFocus, onBlur: onBlur, maxLength: maxLength, "$resize": resize, "$invalid": isInvalid, ref: ref, defaultValue: defaultValue, required: required }, rest, { onChange: onChange, "data-testid": dataTestId })));
|
|
2635
2874
|
});
|
|
2636
2875
|
const StyledTextArea = tailwindStyledComponents.tw.textarea `
|
|
2637
2876
|
tu-textarea
|
|
@@ -2668,17 +2907,18 @@ const Root$1 = tailwindStyledComponents.tw.span `
|
|
|
2668
2907
|
`;
|
|
2669
2908
|
|
|
2670
2909
|
const TextAreaField = React__namespace.forwardRef((_a, ref) => {
|
|
2671
|
-
var { label, tip, helpText, helpAddon, errorMessage, isInvalid, maxLength, onChange, className, value, dataTestId } = _a, rest = __rest(_a, ["label", "tip", "helpText", "helpAddon", "errorMessage", "isInvalid", "maxLength", "onChange", "className", "value", "dataTestId"]);
|
|
2910
|
+
var { id, label, tip, helpText, helpAddon, errorMessage, isInvalid, maxLength, onChange, className, value, dataTestId } = _a, rest = __rest(_a, ["id", "label", "tip", "helpText", "helpAddon", "errorMessage", "isInvalid", "maxLength", "onChange", "className", "value", "dataTestId"]);
|
|
2672
2911
|
const [valueLength, setValueLength] = React__namespace.useState(value ? `${value}`.length : 0);
|
|
2673
2912
|
const renderAsInvalid = isInvalid || Boolean(errorMessage);
|
|
2913
|
+
const htmlForId = id ? id : "textAreaField-" + uuid.v4();
|
|
2674
2914
|
const handleChange = React__namespace.useCallback((event) => {
|
|
2675
2915
|
setValueLength(event.target.value.length);
|
|
2676
2916
|
if (onChange) {
|
|
2677
2917
|
onChange(event);
|
|
2678
2918
|
}
|
|
2679
2919
|
}, [onChange]);
|
|
2680
|
-
return (jsxRuntime.jsx(FormGroup, Object.assign({ label: label, tip: tip, isInvalid: renderAsInvalid, helpText: errorMessage || helpText, helpAddon: helpAddon ||
|
|
2681
|
-
(maxLength !== null && maxLength !== undefined && (jsxRuntime.jsx(TextLengthIndicator, { length: valueLength, maxLength: maxLength }))), className: className, dataTestId: dataTestId && `${dataTestId}-FormGroup` }, { children: jsxRuntime.jsx(TextArea, Object.assign({ ref: ref, maxLength: maxLength, value: value, isInvalid: renderAsInvalid }, rest, { className: className, onChange: handleChange, dataTestId: dataTestId })) })));
|
|
2920
|
+
return (jsxRuntime.jsx(FormGroup, Object.assign({ htmlFor: htmlForId, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: errorMessage || helpText, helpAddon: helpAddon ||
|
|
2921
|
+
(maxLength !== null && maxLength !== undefined && (jsxRuntime.jsx(TextLengthIndicator, { length: valueLength, maxLength: maxLength }))), className: className, dataTestId: dataTestId && `${dataTestId}-FormGroup` }, { children: jsxRuntime.jsx(TextArea, Object.assign({ id: htmlForId, "aria-labelledby": htmlForId + "-label", ref: ref, maxLength: maxLength, value: value, isInvalid: renderAsInvalid }, rest, { className: className, onChange: handleChange, dataTestId: dataTestId })) })));
|
|
2682
2922
|
});
|
|
2683
2923
|
|
|
2684
2924
|
/**
|
|
@@ -2689,17 +2929,18 @@ const TextAreaField = React__namespace.forwardRef((_a, ref) => {
|
|
|
2689
2929
|
* _**Do not use** to confirm user actions, such as deleting. Use a checkbox for such flows._
|
|
2690
2930
|
*/
|
|
2691
2931
|
const TextField = React__namespace.forwardRef((_a, ref) => {
|
|
2692
|
-
var { label, tip, helpText, helpAddon, errorMessage, isInvalid, maxLength, onChange, className, value, dataTestId } = _a, rest = __rest(_a, ["label", "tip", "helpText", "helpAddon", "errorMessage", "isInvalid", "maxLength", "onChange", "className", "value", "dataTestId"]);
|
|
2932
|
+
var { id, label, tip, helpText, helpAddon, errorMessage, isInvalid, maxLength, onChange, className, value, dataTestId } = _a, rest = __rest(_a, ["id", "label", "tip", "helpText", "helpAddon", "errorMessage", "isInvalid", "maxLength", "onChange", "className", "value", "dataTestId"]);
|
|
2693
2933
|
const [valueLength, setValueLength] = React__namespace.useState(value ? `${value}`.length : 0);
|
|
2694
2934
|
const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
|
|
2935
|
+
const htmlFor = id ? id : "textField-" + uuid.v4();
|
|
2695
2936
|
const handleChange = React__namespace.useCallback((event) => {
|
|
2696
2937
|
setValueLength(event.target.value.length);
|
|
2697
2938
|
if (onChange) {
|
|
2698
2939
|
onChange(event);
|
|
2699
2940
|
}
|
|
2700
2941
|
}, [onChange]);
|
|
2701
|
-
return (jsxRuntime.jsx(FormGroup, Object.assign({ label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, helpAddon: helpAddon ||
|
|
2702
|
-
(maxLength !== null && maxLength !== undefined && (jsxRuntime.jsx(TextLengthIndicator, { length: valueLength, maxLength: maxLength }))), dataTestId: dataTestId && `${dataTestId}-FormGroup`, disabled: rest.readOnly }, { children: jsxRuntime.jsx(TextInput, Object.assign({ ref: ref, maxLength: maxLength, value: value, isInvalid: renderAsInvalid }, rest, { className: className, onChange: handleChange, dataTestId: dataTestId })) })));
|
|
2942
|
+
return (jsxRuntime.jsx(FormGroup, Object.assign({ htmlFor: htmlFor, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, helpAddon: helpAddon ||
|
|
2943
|
+
(maxLength !== null && maxLength !== undefined && (jsxRuntime.jsx(TextLengthIndicator, { length: valueLength, maxLength: maxLength }))), dataTestId: dataTestId && `${dataTestId}-FormGroup`, disabled: rest.readOnly }, { children: jsxRuntime.jsx(TextInput, Object.assign({ id: htmlFor, "aria-labelledby": htmlFor + "-label", ref: ref, maxLength: maxLength, value: value, isInvalid: renderAsInvalid }, rest, { className: className, onChange: handleChange, dataTestId: dataTestId })) })));
|
|
2703
2944
|
});
|
|
2704
2945
|
|
|
2705
2946
|
/**
|
|
@@ -2787,9 +3028,10 @@ tu-upload-input`;
|
|
|
2787
3028
|
* Upload fields enable the user to upload Files.
|
|
2788
3029
|
*/
|
|
2789
3030
|
const UploadField = React.forwardRef((_a, ref) => {
|
|
2790
|
-
var { label, tip, helpText, errorMessage, isInvalid, className, value, dataTestId } = _a, rest = __rest(_a, ["label", "tip", "helpText", "errorMessage", "isInvalid", "className", "value", "dataTestId"]);
|
|
3031
|
+
var { label, id, tip, helpText, errorMessage, isInvalid, className, value, dataTestId } = _a, rest = __rest(_a, ["label", "id", "tip", "helpText", "errorMessage", "isInvalid", "className", "value", "dataTestId"]);
|
|
2791
3032
|
const renderAsInvalid = isInvalid || Boolean(errorMessage);
|
|
2792
|
-
|
|
3033
|
+
const htmlForId = id ? id : "uploadField-" + uuid.v4();
|
|
3034
|
+
return (jsxRuntime.jsx(FormGroup, Object.assign({ htmlFor: htmlForId, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: errorMessage || helpText, dataTestId: `${dataTestId}-FormGroup` }, { children: jsxRuntime.jsx(UploadInput, Object.assign({ ref: ref, id: htmlForId, "aria-labelledby": htmlForId + "-label", isInvalid: renderAsInvalid }, rest, { className: className, dataTestId: dataTestId })) })));
|
|
2793
3035
|
});
|
|
2794
3036
|
|
|
2795
3037
|
/**
|
|
@@ -2882,170 +3124,6 @@ const Bar = tailwindStyledComponents.tw.rect `
|
|
|
2882
3124
|
tu-value-bar__bar
|
|
2883
3125
|
`;
|
|
2884
3126
|
|
|
2885
|
-
/**
|
|
2886
|
-
* The useDebounce hook works like useState, but adds a delay where previous values will be ignored.
|
|
2887
|
-
*
|
|
2888
|
-
* @param {any} value The value to set
|
|
2889
|
-
* @param {number} delay The debounce time
|
|
2890
|
-
* @returns {any} value The latest values received
|
|
2891
|
-
*/
|
|
2892
|
-
const useDebounce = (value, delay = 500) => {
|
|
2893
|
-
const [debouncedValue, setDebouncedValue] = React.useState(value);
|
|
2894
|
-
React.useEffect(() => {
|
|
2895
|
-
const handler = setTimeout(() => {
|
|
2896
|
-
setDebouncedValue(value);
|
|
2897
|
-
}, delay);
|
|
2898
|
-
return () => {
|
|
2899
|
-
clearTimeout(handler);
|
|
2900
|
-
};
|
|
2901
|
-
}, [value, delay]);
|
|
2902
|
-
return debouncedValue;
|
|
2903
|
-
};
|
|
2904
|
-
|
|
2905
|
-
// Copied from https://github.com/rexxars/use-device-pixel-ratio
|
|
2906
|
-
/**
|
|
2907
|
-
* Get the device pixel ratio, potentially rounded and capped.
|
|
2908
|
-
* Will emit new values if it changes.
|
|
2909
|
-
*
|
|
2910
|
-
* @param {DevicePixelRatioOptions} options the options object
|
|
2911
|
-
* @returns { number } The current device pixel ratio, or the default if none can be resolved
|
|
2912
|
-
*/
|
|
2913
|
-
function useDevicePixelRatio(options) {
|
|
2914
|
-
const dpr = getDevicePixelRatio(options);
|
|
2915
|
-
const [currentDpr, setCurrentDpr] = React.useState(dpr);
|
|
2916
|
-
const { defaultDpr, maxDpr, round } = options || {};
|
|
2917
|
-
React.useEffect(() => {
|
|
2918
|
-
const canListen = typeof window !== "undefined" && "matchMedia" in window;
|
|
2919
|
-
if (!canListen) {
|
|
2920
|
-
return;
|
|
2921
|
-
}
|
|
2922
|
-
const updateDpr = () => setCurrentDpr(getDevicePixelRatio({ defaultDpr, maxDpr, round }));
|
|
2923
|
-
const mediaMatcher = window.matchMedia(`screen and (resolution: ${currentDpr}dppx)`);
|
|
2924
|
-
// Safari 13.1 does not have `addEventListener`, but does have `addListener`
|
|
2925
|
-
if (mediaMatcher.addEventListener) {
|
|
2926
|
-
mediaMatcher.addEventListener("change", updateDpr);
|
|
2927
|
-
}
|
|
2928
|
-
else {
|
|
2929
|
-
mediaMatcher.addListener(updateDpr);
|
|
2930
|
-
}
|
|
2931
|
-
return () => {
|
|
2932
|
-
if (mediaMatcher.removeEventListener) {
|
|
2933
|
-
mediaMatcher.removeEventListener("change", updateDpr);
|
|
2934
|
-
}
|
|
2935
|
-
else {
|
|
2936
|
-
mediaMatcher.removeListener(updateDpr);
|
|
2937
|
-
}
|
|
2938
|
-
};
|
|
2939
|
-
}, [currentDpr, defaultDpr, maxDpr, round]);
|
|
2940
|
-
return currentDpr;
|
|
2941
|
-
}
|
|
2942
|
-
/**
|
|
2943
|
-
* Returns the current device pixel ratio (DPR) given the passed options
|
|
2944
|
-
*
|
|
2945
|
-
* @param { DevicePixelRatioOptions } options the options object
|
|
2946
|
-
* @returns { number } current device pixel ratio
|
|
2947
|
-
*/
|
|
2948
|
-
function getDevicePixelRatio(options) {
|
|
2949
|
-
const { defaultDpr = 1, maxDpr = 3, round = true } = options || {};
|
|
2950
|
-
const hasDprProp = typeof window !== "undefined" && typeof window.devicePixelRatio === "number";
|
|
2951
|
-
const dpr = hasDprProp ? window.devicePixelRatio : defaultDpr;
|
|
2952
|
-
const rounded = Math.min(Math.max(1, round ? Math.floor(dpr) : dpr), maxDpr);
|
|
2953
|
-
return rounded;
|
|
2954
|
-
}
|
|
2955
|
-
|
|
2956
|
-
/**
|
|
2957
|
-
* The useLocalStorage hook works like useState, but saves to localstorage.
|
|
2958
|
-
*
|
|
2959
|
-
* @param {string} key - The key the values is saved under.
|
|
2960
|
-
* @param {string | null | undefined} initialValue - The initial value for the state/local storage item
|
|
2961
|
-
* @returns {string | null | undefined} value
|
|
2962
|
-
*/
|
|
2963
|
-
const useLocalStorage = (key, initialValue) => {
|
|
2964
|
-
if (!key) {
|
|
2965
|
-
throw new Error("useLocalStorage key may not be falsy");
|
|
2966
|
-
}
|
|
2967
|
-
const setLocalStorageItem = React.useCallback((value) => window.localStorage.setItem(key, typeof value === "object" ? JSON.stringify(value) : `${value}`), [key]);
|
|
2968
|
-
const removeLocalStorageItem = React.useCallback(() => window.localStorage.removeItem(key), [key]);
|
|
2969
|
-
const [item, setValue] = React.useState(() => {
|
|
2970
|
-
const value = window.localStorage.getItem(key);
|
|
2971
|
-
if (value !== undefined && value !== null) {
|
|
2972
|
-
const parsedValue = tryParse(value);
|
|
2973
|
-
return parsedValue;
|
|
2974
|
-
}
|
|
2975
|
-
return initialValue !== null && initialValue !== void 0 ? initialValue : null;
|
|
2976
|
-
});
|
|
2977
|
-
React.useEffect(() => {
|
|
2978
|
-
if (item !== undefined && item !== null) {
|
|
2979
|
-
setLocalStorageItem(item);
|
|
2980
|
-
}
|
|
2981
|
-
else {
|
|
2982
|
-
removeLocalStorageItem();
|
|
2983
|
-
}
|
|
2984
|
-
}, [item, setLocalStorageItem, removeLocalStorageItem, key]);
|
|
2985
|
-
/*
|
|
2986
|
-
// Sync local storage between tabs / windows
|
|
2987
|
-
useEffect(() => {
|
|
2988
|
-
const handleStorageChange = (e: StorageEvent) => {
|
|
2989
|
-
if (e.key === key) {
|
|
2990
|
-
setValue(tryParse(e.newValue));
|
|
2991
|
-
}
|
|
2992
|
-
};
|
|
2993
|
-
|
|
2994
|
-
window.addEventListener("storage", handleStorageChange);
|
|
2995
|
-
|
|
2996
|
-
return () => {
|
|
2997
|
-
window.removeEventListener("storage", handleStorageChange);
|
|
2998
|
-
};
|
|
2999
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
3000
|
-
}, []);
|
|
3001
|
-
*/
|
|
3002
|
-
const removeItem = () => {
|
|
3003
|
-
setValue(null);
|
|
3004
|
-
};
|
|
3005
|
-
return [item, setValue, removeItem];
|
|
3006
|
-
};
|
|
3007
|
-
function tryParse(value) {
|
|
3008
|
-
try {
|
|
3009
|
-
return JSON.parse(value);
|
|
3010
|
-
}
|
|
3011
|
-
catch (_a) {
|
|
3012
|
-
return value;
|
|
3013
|
-
}
|
|
3014
|
-
}
|
|
3015
|
-
|
|
3016
|
-
/**
|
|
3017
|
-
* @param {UseTimeoutProps} props The props
|
|
3018
|
-
* @returns {{ startTimeout: () => void; stopTimeout: () => void; isReady: boolean | null}} return
|
|
3019
|
-
*/
|
|
3020
|
-
const useTimeout = ({ onTimeout, duration }) => {
|
|
3021
|
-
const ready = React.useRef(false);
|
|
3022
|
-
const timeout = React.useRef();
|
|
3023
|
-
const callback = React.useRef(onTimeout);
|
|
3024
|
-
const isReady = React.useCallback(() => ready.current, []);
|
|
3025
|
-
const startTimeout = React.useCallback(() => {
|
|
3026
|
-
ready.current = false;
|
|
3027
|
-
timeout.current && clearTimeout(timeout.current);
|
|
3028
|
-
timeout.current = setTimeout(() => {
|
|
3029
|
-
ready.current = true;
|
|
3030
|
-
callback.current();
|
|
3031
|
-
}, duration);
|
|
3032
|
-
}, [duration]);
|
|
3033
|
-
const stopTimeout = React.useCallback(() => {
|
|
3034
|
-
ready.current = null;
|
|
3035
|
-
timeout.current && clearTimeout(timeout.current);
|
|
3036
|
-
}, []);
|
|
3037
|
-
// update ref when function changes
|
|
3038
|
-
React.useEffect(() => {
|
|
3039
|
-
callback.current = onTimeout;
|
|
3040
|
-
}, [onTimeout]);
|
|
3041
|
-
// startTimeout on mount, stopTimeout on unmount
|
|
3042
|
-
React.useEffect(() => {
|
|
3043
|
-
startTimeout();
|
|
3044
|
-
return stopTimeout;
|
|
3045
|
-
}, [duration, startTimeout, stopTimeout]);
|
|
3046
|
-
return [isReady, stopTimeout, startTimeout];
|
|
3047
|
-
};
|
|
3048
|
-
|
|
3049
3127
|
/**
|
|
3050
3128
|
* The MinTopFullContentLayout component.
|
|
3051
3129
|
*
|
|
@@ -3323,6 +3401,7 @@ exports.getDevicePixelRatio = getDevicePixelRatio;
|
|
|
3323
3401
|
exports.getOrderedOptions = getOrderedOptions;
|
|
3324
3402
|
exports.getValueBarColorByValue = getValueBarColorByValue;
|
|
3325
3403
|
exports.isMultiValue = isMultiValue;
|
|
3404
|
+
exports.useClickOutside = useClickOutside;
|
|
3326
3405
|
exports.useContainerProps = useContainerProps;
|
|
3327
3406
|
exports.useCustomComponents = useCustomComponents;
|
|
3328
3407
|
exports.useDebounce = useDebounce;
|
|
@@ -3331,4 +3410,5 @@ exports.useLocalStorage = useLocalStorage;
|
|
|
3331
3410
|
exports.useModal = useModal;
|
|
3332
3411
|
exports.usePopoverContext = usePopoverContext;
|
|
3333
3412
|
exports.usePrompt = usePrompt;
|
|
3413
|
+
exports.useResize = useResize;
|
|
3334
3414
|
exports.useTimeout = useTimeout;
|