@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.js
CHANGED
|
@@ -4,11 +4,11 @@ import * as React from 'react';
|
|
|
4
4
|
import React__default, { useState, forwardRef, useMemo, createContext, useContext, isValidElement, cloneElement, useCallback, useEffect, Children, useRef, memo } from 'react';
|
|
5
5
|
import { HeroIconsArray, heroIconLookup, TrackunitSolidIconsArray, TrackunitOutlineIconsArray, trackunitIconLookup } from '@trackunit/ui-icons';
|
|
6
6
|
import { useMeasure, useCopyToClipboard } from 'react-use';
|
|
7
|
+
import { v4 } from 'uuid';
|
|
7
8
|
import { format, formatDistance } from 'date-fns';
|
|
8
9
|
import { useFloating, autoUpdate, offset, flip, shift, size, useClick, useDismiss, useHover, useRole, useInteractions, useMergeRefs, FloatingPortal, FloatingFocusManager } from '@floating-ui/react';
|
|
9
10
|
import { DayPicker as DayPicker$1 } from 'react-day-picker';
|
|
10
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';
|
|
11
|
-
import { useClickOutside } from 'react-browser-hooks';
|
|
12
12
|
import usePortal from 'react-useportal';
|
|
13
13
|
import ReactSelect, { components } from 'react-select';
|
|
14
14
|
export { default as ValueType } from 'react-select';
|
|
@@ -795,7 +795,7 @@ const CheckboxWrapper = tw.span `
|
|
|
795
795
|
? tws `tu-checkbox--selected`
|
|
796
796
|
: tws `tu-checkbox--deselected`;
|
|
797
797
|
}}
|
|
798
|
-
|
|
798
|
+
|
|
799
799
|
${({ $isInvalid }) => $isInvalid && tws `tu-checkbox--invalid`}
|
|
800
800
|
`;
|
|
801
801
|
|
|
@@ -967,7 +967,7 @@ const PopoverContent = React__default.forwardRef(function PopoverContent(_a, pro
|
|
|
967
967
|
var { className, dataTestId, children } = _a, props = __rest(_a, ["className", "dataTestId", "children"]);
|
|
968
968
|
const _f = usePopoverContext(), { context: floatingContext, customProps } = _f, context = __rest(_f, ["context", "customProps"]);
|
|
969
969
|
const ref = useMergeRefs([context.refs.setFloating, propRef]);
|
|
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"] }, { 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 })) }))) })));
|
|
971
971
|
});
|
|
972
972
|
|
|
973
973
|
/**
|
|
@@ -1049,13 +1049,13 @@ const TipContainer = tw.text `
|
|
|
1049
1049
|
* @param {FormGroupProps} props - The props for the FormGroup component
|
|
1050
1050
|
* @returns {JSX.Element} FormGroup component
|
|
1051
1051
|
*/
|
|
1052
|
-
const FormGroup = ({ isInvalid, helpText, helpAddon, tip, className, dataTestId, label, children, disabled = false, }) => {
|
|
1053
|
-
return (jsxs(FormGroupRoot, Object.assign({ className: className, "data-testid": dataTestId, "$disabled": disabled }, { children: [jsxs(ContainerBefore, { children: [jsx(FormGroupLabel, Object.assign({ dataTestId: dataTestId && `${dataTestId}-label
|
|
1052
|
+
const FormGroup = ({ isInvalid, helpText, helpAddon, tip, className, dataTestId, label, htmlFor, children, disabled = false, }) => {
|
|
1053
|
+
return (jsxs(FormGroupRoot, Object.assign({ className: className, "data-testid": dataTestId, "$disabled": disabled }, { children: [jsxs(ContainerBefore, { children: [jsx(FormGroupLabel, Object.assign({ dataTestId: dataTestId && `${dataTestId}-label`, htmlFor: htmlFor, id: htmlFor + "-label" }, { children: label })), tip && jsx(Tip, Object.assign({ dataTestId: dataTestId && `${dataTestId}-tip` }, { children: tip }))] }), children, jsxs(ContainerAfter, Object.assign({ "$isInvalid": isInvalid }, { children: [helpText && jsx("span", Object.assign({ "data-testid": dataTestId && `${dataTestId}-helpText` }, { children: helpText })), helpAddon && jsx(HelpAddon, Object.assign({ "data-testid": dataTestId && `${dataTestId}-helpAddon` }, { children: helpAddon }))] }))] })));
|
|
1054
1054
|
};
|
|
1055
|
-
const FormGroupRoot = tw.
|
|
1055
|
+
const FormGroupRoot = tw.div `
|
|
1056
1056
|
tu-form-group
|
|
1057
1057
|
${({ $disabled }) => {
|
|
1058
|
-
return $disabled ? "pointer-events-none
|
|
1058
|
+
return $disabled ? "pointer-events-none" : null;
|
|
1059
1059
|
}}
|
|
1060
1060
|
`;
|
|
1061
1061
|
const ContainerBefore = tw.div `
|
|
@@ -1069,7 +1069,7 @@ const ContainerAfter = tw.div `
|
|
|
1069
1069
|
${({ $isInvalid }) => ($isInvalid ? tws `tu-form-group__container-after--invalid` : null)}
|
|
1070
1070
|
`;
|
|
1071
1071
|
const HelpAddon = tw.span `
|
|
1072
|
-
tu-form-group__help-addon
|
|
1072
|
+
tu-form-group__help-addon
|
|
1073
1073
|
`;
|
|
1074
1074
|
|
|
1075
1075
|
/**
|
|
@@ -1080,9 +1080,10 @@ const HelpAddon = tw.span `
|
|
|
1080
1080
|
* _**Do not use**_ this fields for non-serialized dates. Use TextField instead.
|
|
1081
1081
|
*/
|
|
1082
1082
|
const DateField = forwardRef((_a, ref) => {
|
|
1083
|
-
var { label, tip, helpText, errorMessage, helpAddon, isInvalid, className, defaultValue, dataTestId } = _a, rest = __rest(_a, ["label", "tip", "helpText", "errorMessage", "helpAddon", "isInvalid", "className", "defaultValue", "dataTestId"]);
|
|
1083
|
+
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"]);
|
|
1084
1084
|
const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
|
|
1085
|
-
|
|
1085
|
+
const htmlForId = id ? id : "dateField-" + v4();
|
|
1086
|
+
return (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: jsx(DateInput, Object.assign({ id: htmlForId, "aria-labelledby": htmlForId + "-label", ref: ref, defaultValue: defaultValue, isInvalid: renderAsInvalid }, rest, { className: className, dataTestId: dataTestId })) })));
|
|
1086
1087
|
});
|
|
1087
1088
|
|
|
1088
1089
|
const localeLookup = {
|
|
@@ -1296,15 +1297,16 @@ const EmailInput = React.forwardRef((_a, ref) => {
|
|
|
1296
1297
|
*
|
|
1297
1298
|
*/
|
|
1298
1299
|
const EmailField = forwardRef((_a, ref) => {
|
|
1299
|
-
var { label, tip, helpText, errorMessage, helpAddon, className, defaultValue, dataTestId } = _a, rest = __rest(_a, ["label", "tip", "helpText", "errorMessage", "helpAddon", "className", "defaultValue", "dataTestId"]);
|
|
1300
|
+
var { label, id, tip, helpText, errorMessage, helpAddon, className, defaultValue, dataTestId } = _a, rest = __rest(_a, ["label", "id", "tip", "helpText", "errorMessage", "helpAddon", "className", "defaultValue", "dataTestId"]);
|
|
1300
1301
|
const [value, setValue] = useState(defaultValue);
|
|
1302
|
+
const htmlForId = id ? id : "emailField-" + v4();
|
|
1301
1303
|
// Type guard to check if value is a string
|
|
1302
1304
|
function isString(inputValue) {
|
|
1303
1305
|
return typeof inputValue === "string";
|
|
1304
1306
|
}
|
|
1305
1307
|
// Check the regular expression only if value is a string
|
|
1306
1308
|
const renderAsInvalid = !!errorMessage || (isString(value) && !/^\S+@\S+\.\S+$/.test(value));
|
|
1307
|
-
return (jsx(FormGroup, Object.assign({ label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, helpAddon: helpAddon, disabled: rest.disabled, dataTestId: dataTestId && `${dataTestId}-FormGroup` }, { children: jsx(EmailInput, Object.assign({ ref: ref, value: value, onChange: e => setValue(e.target.value), isInvalid: renderAsInvalid, disabled: renderAsInvalid }, rest, { className: className, dataTestId: dataTestId })) })));
|
|
1309
|
+
return (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: 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 })) })));
|
|
1308
1310
|
});
|
|
1309
1311
|
|
|
1310
1312
|
/**
|
|
@@ -1460,6 +1462,241 @@ const Divider = tw.hr `
|
|
|
1460
1462
|
tu-menu-list__divider
|
|
1461
1463
|
`;
|
|
1462
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
|
+
|
|
1463
1700
|
/**
|
|
1464
1701
|
* A kebab menu component.
|
|
1465
1702
|
* Advice: fill it with MenuList
|
|
@@ -1483,7 +1720,7 @@ const MoreMenu = ({ className, dataTestId, dotsDirection = "horizontal", menuPla
|
|
|
1483
1720
|
});
|
|
1484
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: () => {
|
|
1485
1722
|
setActionMenuIsOpen(!actionMenuIsOpen);
|
|
1486
|
-
} })) }), jsx(PopoverContent, { children: children })] })) })));
|
|
1723
|
+
} })) }), jsx(PopoverContent, { children: close => (typeof children === "function" ? children(close) : children) })] })) })));
|
|
1487
1724
|
};
|
|
1488
1725
|
const Root$4 = tw.div `
|
|
1489
1726
|
tu-more-menu
|
|
@@ -1579,9 +1816,10 @@ const NumberInput = forwardRef((props, ref) => (jsx(BaseInput, Object.assign({ r
|
|
|
1579
1816
|
* _**Do not use**_ this fields for non-serialized numbers. Use TextField instead.
|
|
1580
1817
|
*/
|
|
1581
1818
|
const NumberField = forwardRef((_a, ref) => {
|
|
1582
|
-
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"]);
|
|
1819
|
+
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"]);
|
|
1583
1820
|
const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
|
|
1584
|
-
|
|
1821
|
+
const htmlForId = id ? id : "numberField-" + v4();
|
|
1822
|
+
return (jsx(FormGroup, Object.assign({ htmlFor: htmlForId, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, helpAddon: helpAddon, dataTestId: dataTestId && `${dataTestId}-FormGroup` }, { children: jsx(NumberInput, Object.assign({ id: htmlForId, "aria-labelledby": htmlForId + "-label", ref: ref, maxLength: maxLength, value: value, isInvalid: renderAsInvalid }, rest, { className: className, dataTestId: dataTestId })) })));
|
|
1585
1823
|
});
|
|
1586
1824
|
|
|
1587
1825
|
/**
|
|
@@ -2310,9 +2548,10 @@ const Container = tw.div `
|
|
|
2310
2548
|
* @returns {JSX.Element} - The PhoneField component.
|
|
2311
2549
|
*/
|
|
2312
2550
|
const PhoneField = forwardRef((_a, ref) => {
|
|
2313
|
-
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"]);
|
|
2551
|
+
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"]);
|
|
2314
2552
|
const renderAsInvalid = isInvalid || Boolean(errorMessage);
|
|
2315
|
-
|
|
2553
|
+
const htmlForId = id ? id : "phoneField-" + v4();
|
|
2554
|
+
return (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: jsx(PhoneInput, Object.assign({ id: htmlForId, "aria-labelledby": htmlForId + "-label", value: value || defaultValue, isInvalid: renderAsInvalid }, rest)) })));
|
|
2316
2555
|
});
|
|
2317
2556
|
|
|
2318
2557
|
function useConfirmExit(confirmExit, when = true) {
|
|
@@ -2406,7 +2645,7 @@ ${({ $inline }) => ($inline ? tws `tu-radiogroup--inline` : tws `tu-radiogroup`)
|
|
|
2406
2645
|
const RadioItem = ({ label, value, dataTestId, className, description }) => {
|
|
2407
2646
|
const groupCtx = React.useContext(RadioGroupContext);
|
|
2408
2647
|
const isChecked = (groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.value) === value;
|
|
2409
|
-
return (jsxs(InputWrapper, Object.assign({ className: className, htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}
|
|
2648
|
+
return (jsxs(InputWrapper, Object.assign({ className: className, htmlFor: `${groupCtx === null || groupCtx === void 0 ? void 0 : groupCtx.id}-${value}`, "data-testid": dataTestId && `${dataTestId}-Wrapper` }, { children: [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 }), jsxs(LabelContainer$1, { children: [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 && (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 })))] })] })));
|
|
2410
2649
|
};
|
|
2411
2650
|
const InputWrapper = tw.label `tu-radioitem__wrapper`;
|
|
2412
2651
|
const Input = tw.input `
|
|
@@ -2601,7 +2840,7 @@ const ChildContainer = tw.div `
|
|
|
2601
2840
|
*/
|
|
2602
2841
|
const TextArea = React.forwardRef((_a, ref) => {
|
|
2603
2842
|
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"]);
|
|
2604
|
-
return (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 })));
|
|
2843
|
+
return (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 })));
|
|
2605
2844
|
});
|
|
2606
2845
|
const StyledTextArea = tw.textarea `
|
|
2607
2846
|
tu-textarea
|
|
@@ -2638,17 +2877,18 @@ const Root$1 = tw.span `
|
|
|
2638
2877
|
`;
|
|
2639
2878
|
|
|
2640
2879
|
const TextAreaField = React.forwardRef((_a, ref) => {
|
|
2641
|
-
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"]);
|
|
2880
|
+
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"]);
|
|
2642
2881
|
const [valueLength, setValueLength] = React.useState(value ? `${value}`.length : 0);
|
|
2643
2882
|
const renderAsInvalid = isInvalid || Boolean(errorMessage);
|
|
2883
|
+
const htmlForId = id ? id : "textAreaField-" + v4();
|
|
2644
2884
|
const handleChange = React.useCallback((event) => {
|
|
2645
2885
|
setValueLength(event.target.value.length);
|
|
2646
2886
|
if (onChange) {
|
|
2647
2887
|
onChange(event);
|
|
2648
2888
|
}
|
|
2649
2889
|
}, [onChange]);
|
|
2650
|
-
return (jsx(FormGroup, Object.assign({ label: label, tip: tip, isInvalid: renderAsInvalid, helpText: errorMessage || helpText, helpAddon: helpAddon ||
|
|
2651
|
-
(maxLength !== null && maxLength !== undefined && (jsx(TextLengthIndicator, { length: valueLength, maxLength: maxLength }))), className: className, dataTestId: dataTestId && `${dataTestId}-FormGroup` }, { children: jsx(TextArea, Object.assign({ ref: ref, maxLength: maxLength, value: value, isInvalid: renderAsInvalid }, rest, { className: className, onChange: handleChange, dataTestId: dataTestId })) })));
|
|
2890
|
+
return (jsx(FormGroup, Object.assign({ htmlFor: htmlForId, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: errorMessage || helpText, helpAddon: helpAddon ||
|
|
2891
|
+
(maxLength !== null && maxLength !== undefined && (jsx(TextLengthIndicator, { length: valueLength, maxLength: maxLength }))), className: className, dataTestId: dataTestId && `${dataTestId}-FormGroup` }, { children: 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 })) })));
|
|
2652
2892
|
});
|
|
2653
2893
|
|
|
2654
2894
|
/**
|
|
@@ -2659,17 +2899,18 @@ const TextAreaField = React.forwardRef((_a, ref) => {
|
|
|
2659
2899
|
* _**Do not use** to confirm user actions, such as deleting. Use a checkbox for such flows._
|
|
2660
2900
|
*/
|
|
2661
2901
|
const TextField = React.forwardRef((_a, ref) => {
|
|
2662
|
-
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"]);
|
|
2902
|
+
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"]);
|
|
2663
2903
|
const [valueLength, setValueLength] = React.useState(value ? `${value}`.length : 0);
|
|
2664
2904
|
const renderAsInvalid = isInvalid === undefined ? Boolean(errorMessage) : isInvalid;
|
|
2905
|
+
const htmlFor = id ? id : "textField-" + v4();
|
|
2665
2906
|
const handleChange = React.useCallback((event) => {
|
|
2666
2907
|
setValueLength(event.target.value.length);
|
|
2667
2908
|
if (onChange) {
|
|
2668
2909
|
onChange(event);
|
|
2669
2910
|
}
|
|
2670
2911
|
}, [onChange]);
|
|
2671
|
-
return (jsx(FormGroup, Object.assign({ label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, helpAddon: helpAddon ||
|
|
2672
|
-
(maxLength !== null && maxLength !== undefined && (jsx(TextLengthIndicator, { length: valueLength, maxLength: maxLength }))), dataTestId: dataTestId && `${dataTestId}-FormGroup`, disabled: rest.readOnly }, { children: jsx(TextInput, Object.assign({ ref: ref, maxLength: maxLength, value: value, isInvalid: renderAsInvalid }, rest, { className: className, onChange: handleChange, dataTestId: dataTestId })) })));
|
|
2912
|
+
return (jsx(FormGroup, Object.assign({ htmlFor: htmlFor, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: (renderAsInvalid && errorMessage) || helpText, helpAddon: helpAddon ||
|
|
2913
|
+
(maxLength !== null && maxLength !== undefined && (jsx(TextLengthIndicator, { length: valueLength, maxLength: maxLength }))), dataTestId: dataTestId && `${dataTestId}-FormGroup`, disabled: rest.readOnly }, { children: 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 })) })));
|
|
2673
2914
|
});
|
|
2674
2915
|
|
|
2675
2916
|
/**
|
|
@@ -2757,9 +2998,10 @@ tu-upload-input`;
|
|
|
2757
2998
|
* Upload fields enable the user to upload Files.
|
|
2758
2999
|
*/
|
|
2759
3000
|
const UploadField = forwardRef((_a, ref) => {
|
|
2760
|
-
var { label, tip, helpText, errorMessage, isInvalid, className, value, dataTestId } = _a, rest = __rest(_a, ["label", "tip", "helpText", "errorMessage", "isInvalid", "className", "value", "dataTestId"]);
|
|
3001
|
+
var { label, id, tip, helpText, errorMessage, isInvalid, className, value, dataTestId } = _a, rest = __rest(_a, ["label", "id", "tip", "helpText", "errorMessage", "isInvalid", "className", "value", "dataTestId"]);
|
|
2761
3002
|
const renderAsInvalid = isInvalid || Boolean(errorMessage);
|
|
2762
|
-
|
|
3003
|
+
const htmlForId = id ? id : "uploadField-" + v4();
|
|
3004
|
+
return (jsx(FormGroup, Object.assign({ htmlFor: htmlForId, label: label, tip: tip, isInvalid: renderAsInvalid, helpText: errorMessage || helpText, dataTestId: `${dataTestId}-FormGroup` }, { children: jsx(UploadInput, Object.assign({ ref: ref, id: htmlForId, "aria-labelledby": htmlForId + "-label", isInvalid: renderAsInvalid }, rest, { className: className, dataTestId: dataTestId })) })));
|
|
2763
3005
|
});
|
|
2764
3006
|
|
|
2765
3007
|
/**
|
|
@@ -2852,170 +3094,6 @@ const Bar = tw.rect `
|
|
|
2852
3094
|
tu-value-bar__bar
|
|
2853
3095
|
`;
|
|
2854
3096
|
|
|
2855
|
-
/**
|
|
2856
|
-
* The useDebounce hook works like useState, but adds a delay where previous values will be ignored.
|
|
2857
|
-
*
|
|
2858
|
-
* @param {any} value The value to set
|
|
2859
|
-
* @param {number} delay The debounce time
|
|
2860
|
-
* @returns {any} value The latest values received
|
|
2861
|
-
*/
|
|
2862
|
-
const useDebounce = (value, delay = 500) => {
|
|
2863
|
-
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
2864
|
-
useEffect(() => {
|
|
2865
|
-
const handler = setTimeout(() => {
|
|
2866
|
-
setDebouncedValue(value);
|
|
2867
|
-
}, delay);
|
|
2868
|
-
return () => {
|
|
2869
|
-
clearTimeout(handler);
|
|
2870
|
-
};
|
|
2871
|
-
}, [value, delay]);
|
|
2872
|
-
return debouncedValue;
|
|
2873
|
-
};
|
|
2874
|
-
|
|
2875
|
-
// Copied from https://github.com/rexxars/use-device-pixel-ratio
|
|
2876
|
-
/**
|
|
2877
|
-
* Get the device pixel ratio, potentially rounded and capped.
|
|
2878
|
-
* Will emit new values if it changes.
|
|
2879
|
-
*
|
|
2880
|
-
* @param {DevicePixelRatioOptions} options the options object
|
|
2881
|
-
* @returns { number } The current device pixel ratio, or the default if none can be resolved
|
|
2882
|
-
*/
|
|
2883
|
-
function useDevicePixelRatio(options) {
|
|
2884
|
-
const dpr = getDevicePixelRatio(options);
|
|
2885
|
-
const [currentDpr, setCurrentDpr] = useState(dpr);
|
|
2886
|
-
const { defaultDpr, maxDpr, round } = options || {};
|
|
2887
|
-
useEffect(() => {
|
|
2888
|
-
const canListen = typeof window !== "undefined" && "matchMedia" in window;
|
|
2889
|
-
if (!canListen) {
|
|
2890
|
-
return;
|
|
2891
|
-
}
|
|
2892
|
-
const updateDpr = () => setCurrentDpr(getDevicePixelRatio({ defaultDpr, maxDpr, round }));
|
|
2893
|
-
const mediaMatcher = window.matchMedia(`screen and (resolution: ${currentDpr}dppx)`);
|
|
2894
|
-
// Safari 13.1 does not have `addEventListener`, but does have `addListener`
|
|
2895
|
-
if (mediaMatcher.addEventListener) {
|
|
2896
|
-
mediaMatcher.addEventListener("change", updateDpr);
|
|
2897
|
-
}
|
|
2898
|
-
else {
|
|
2899
|
-
mediaMatcher.addListener(updateDpr);
|
|
2900
|
-
}
|
|
2901
|
-
return () => {
|
|
2902
|
-
if (mediaMatcher.removeEventListener) {
|
|
2903
|
-
mediaMatcher.removeEventListener("change", updateDpr);
|
|
2904
|
-
}
|
|
2905
|
-
else {
|
|
2906
|
-
mediaMatcher.removeListener(updateDpr);
|
|
2907
|
-
}
|
|
2908
|
-
};
|
|
2909
|
-
}, [currentDpr, defaultDpr, maxDpr, round]);
|
|
2910
|
-
return currentDpr;
|
|
2911
|
-
}
|
|
2912
|
-
/**
|
|
2913
|
-
* Returns the current device pixel ratio (DPR) given the passed options
|
|
2914
|
-
*
|
|
2915
|
-
* @param { DevicePixelRatioOptions } options the options object
|
|
2916
|
-
* @returns { number } current device pixel ratio
|
|
2917
|
-
*/
|
|
2918
|
-
function getDevicePixelRatio(options) {
|
|
2919
|
-
const { defaultDpr = 1, maxDpr = 3, round = true } = options || {};
|
|
2920
|
-
const hasDprProp = typeof window !== "undefined" && typeof window.devicePixelRatio === "number";
|
|
2921
|
-
const dpr = hasDprProp ? window.devicePixelRatio : defaultDpr;
|
|
2922
|
-
const rounded = Math.min(Math.max(1, round ? Math.floor(dpr) : dpr), maxDpr);
|
|
2923
|
-
return rounded;
|
|
2924
|
-
}
|
|
2925
|
-
|
|
2926
|
-
/**
|
|
2927
|
-
* The useLocalStorage hook works like useState, but saves to localstorage.
|
|
2928
|
-
*
|
|
2929
|
-
* @param {string} key - The key the values is saved under.
|
|
2930
|
-
* @param {string | null | undefined} initialValue - The initial value for the state/local storage item
|
|
2931
|
-
* @returns {string | null | undefined} value
|
|
2932
|
-
*/
|
|
2933
|
-
const useLocalStorage = (key, initialValue) => {
|
|
2934
|
-
if (!key) {
|
|
2935
|
-
throw new Error("useLocalStorage key may not be falsy");
|
|
2936
|
-
}
|
|
2937
|
-
const setLocalStorageItem = useCallback((value) => window.localStorage.setItem(key, typeof value === "object" ? JSON.stringify(value) : `${value}`), [key]);
|
|
2938
|
-
const removeLocalStorageItem = useCallback(() => window.localStorage.removeItem(key), [key]);
|
|
2939
|
-
const [item, setValue] = useState(() => {
|
|
2940
|
-
const value = window.localStorage.getItem(key);
|
|
2941
|
-
if (value !== undefined && value !== null) {
|
|
2942
|
-
const parsedValue = tryParse(value);
|
|
2943
|
-
return parsedValue;
|
|
2944
|
-
}
|
|
2945
|
-
return initialValue !== null && initialValue !== void 0 ? initialValue : null;
|
|
2946
|
-
});
|
|
2947
|
-
useEffect(() => {
|
|
2948
|
-
if (item !== undefined && item !== null) {
|
|
2949
|
-
setLocalStorageItem(item);
|
|
2950
|
-
}
|
|
2951
|
-
else {
|
|
2952
|
-
removeLocalStorageItem();
|
|
2953
|
-
}
|
|
2954
|
-
}, [item, setLocalStorageItem, removeLocalStorageItem, key]);
|
|
2955
|
-
/*
|
|
2956
|
-
// Sync local storage between tabs / windows
|
|
2957
|
-
useEffect(() => {
|
|
2958
|
-
const handleStorageChange = (e: StorageEvent) => {
|
|
2959
|
-
if (e.key === key) {
|
|
2960
|
-
setValue(tryParse(e.newValue));
|
|
2961
|
-
}
|
|
2962
|
-
};
|
|
2963
|
-
|
|
2964
|
-
window.addEventListener("storage", handleStorageChange);
|
|
2965
|
-
|
|
2966
|
-
return () => {
|
|
2967
|
-
window.removeEventListener("storage", handleStorageChange);
|
|
2968
|
-
};
|
|
2969
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2970
|
-
}, []);
|
|
2971
|
-
*/
|
|
2972
|
-
const removeItem = () => {
|
|
2973
|
-
setValue(null);
|
|
2974
|
-
};
|
|
2975
|
-
return [item, setValue, removeItem];
|
|
2976
|
-
};
|
|
2977
|
-
function tryParse(value) {
|
|
2978
|
-
try {
|
|
2979
|
-
return JSON.parse(value);
|
|
2980
|
-
}
|
|
2981
|
-
catch (_a) {
|
|
2982
|
-
return value;
|
|
2983
|
-
}
|
|
2984
|
-
}
|
|
2985
|
-
|
|
2986
|
-
/**
|
|
2987
|
-
* @param {UseTimeoutProps} props The props
|
|
2988
|
-
* @returns {{ startTimeout: () => void; stopTimeout: () => void; isReady: boolean | null}} return
|
|
2989
|
-
*/
|
|
2990
|
-
const useTimeout = ({ onTimeout, duration }) => {
|
|
2991
|
-
const ready = useRef(false);
|
|
2992
|
-
const timeout = useRef();
|
|
2993
|
-
const callback = useRef(onTimeout);
|
|
2994
|
-
const isReady = useCallback(() => ready.current, []);
|
|
2995
|
-
const startTimeout = useCallback(() => {
|
|
2996
|
-
ready.current = false;
|
|
2997
|
-
timeout.current && clearTimeout(timeout.current);
|
|
2998
|
-
timeout.current = setTimeout(() => {
|
|
2999
|
-
ready.current = true;
|
|
3000
|
-
callback.current();
|
|
3001
|
-
}, duration);
|
|
3002
|
-
}, [duration]);
|
|
3003
|
-
const stopTimeout = useCallback(() => {
|
|
3004
|
-
ready.current = null;
|
|
3005
|
-
timeout.current && clearTimeout(timeout.current);
|
|
3006
|
-
}, []);
|
|
3007
|
-
// update ref when function changes
|
|
3008
|
-
useEffect(() => {
|
|
3009
|
-
callback.current = onTimeout;
|
|
3010
|
-
}, [onTimeout]);
|
|
3011
|
-
// startTimeout on mount, stopTimeout on unmount
|
|
3012
|
-
useEffect(() => {
|
|
3013
|
-
startTimeout();
|
|
3014
|
-
return stopTimeout;
|
|
3015
|
-
}, [duration, startTimeout, stopTimeout]);
|
|
3016
|
-
return [isReady, stopTimeout, startTimeout];
|
|
3017
|
-
};
|
|
3018
|
-
|
|
3019
3097
|
/**
|
|
3020
3098
|
* The MinTopFullContentLayout component.
|
|
3021
3099
|
*
|
|
@@ -3200,4 +3278,4 @@ const Layout = tw.div `
|
|
|
3200
3278
|
tu-layout-TwoColumnLayout
|
|
3201
3279
|
`;
|
|
3202
3280
|
|
|
3203
|
-
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": {
|
|
@@ -9,11 +9,11 @@
|
|
|
9
9
|
"@trackunit/ui-design-tokens": "0.0.61",
|
|
10
10
|
"react": "18.2.0",
|
|
11
11
|
"react-use": "17.4.0",
|
|
12
|
+
"uuid": "8.3.2",
|
|
12
13
|
"date-fns": "2.29.3",
|
|
13
14
|
"react-day-picker": "8.3.7",
|
|
14
15
|
"@floating-ui/react": "0.22.2",
|
|
15
16
|
"@trackunit/ui-icons": "0.0.61",
|
|
16
|
-
"react-browser-hooks": "2.2.4",
|
|
17
17
|
"react-useportal": "1.0.17",
|
|
18
18
|
"libphonenumber-js": "1.10.24",
|
|
19
19
|
"react-router-dom": "6.4.5",
|