@trackunit/react-components 1.21.8 → 1.21.12
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.js +119 -16
- package/index.esm.js +119 -17
- package/package.json +5 -5
- package/src/hooks/useOverflowBorder.d.ts +33 -0
- package/src/index.d.ts +2 -0
- package/src/overlay-dismissible/types.d.ts +52 -0
package/index.cjs.js
CHANGED
|
@@ -1341,6 +1341,15 @@ const createBreakpointState = ({ width }) => {
|
|
|
1341
1341
|
}), { ...defaultBreakpointState });
|
|
1342
1342
|
};
|
|
1343
1343
|
|
|
1344
|
+
const canUseMatchMedia = () => typeof window !== "undefined" && typeof window.matchMedia === "function";
|
|
1345
|
+
const getViewportBreakpointState = () => {
|
|
1346
|
+
if (!canUseMatchMedia())
|
|
1347
|
+
return { ...defaultBreakpointState };
|
|
1348
|
+
return sharedUtils.objectEntries(uiDesignTokens.themeScreenSizeAsNumber).reduce((acc, [size, minWidth]) => ({
|
|
1349
|
+
...acc,
|
|
1350
|
+
[breakpointPropsMap[size]]: window.matchMedia(`(min-width: ${minWidth}px)`).matches,
|
|
1351
|
+
}), { ...defaultBreakpointState });
|
|
1352
|
+
};
|
|
1344
1353
|
/**
|
|
1345
1354
|
* A custom React hook that provides real-time information about the current viewport size.
|
|
1346
1355
|
* ! Consider using `useContainerBreakpoints` instead, and only use this when you need to actually react to the viewport size, not the container size.
|
|
@@ -1364,36 +1373,23 @@ const createBreakpointState = ({ width }) => {
|
|
|
1364
1373
|
*/
|
|
1365
1374
|
const useViewportBreakpoints = (options = {}) => {
|
|
1366
1375
|
const { skip = false } = options;
|
|
1367
|
-
const [viewportSize, setViewportSize] = react.useState(
|
|
1368
|
-
const newViewportSize = sharedUtils.objectEntries(uiDesignTokens.themeScreenSizeAsNumber).reduce((acc, [size, minWidth]) => ({
|
|
1369
|
-
...acc,
|
|
1370
|
-
[breakpointPropsMap[size]]: window.matchMedia(`(min-width: ${minWidth}px)`).matches,
|
|
1371
|
-
}), { ...defaultBreakpointState });
|
|
1372
|
-
return newViewportSize;
|
|
1373
|
-
});
|
|
1376
|
+
const [viewportSize, setViewportSize] = react.useState(getViewportBreakpointState);
|
|
1374
1377
|
const updateViewportSize = react.useCallback(() => {
|
|
1375
|
-
|
|
1376
|
-
...acc,
|
|
1377
|
-
[breakpointPropsMap[size]]: window.matchMedia(`(min-width: ${minWidth}px)`).matches,
|
|
1378
|
-
}), { ...defaultBreakpointState });
|
|
1379
|
-
setViewportSize(newViewportSize);
|
|
1378
|
+
setViewportSize(getViewportBreakpointState());
|
|
1380
1379
|
}, []);
|
|
1381
1380
|
const updateViewportSizeRef = react.useRef(updateViewportSize);
|
|
1382
1381
|
react.useEffect(() => {
|
|
1383
1382
|
updateViewportSizeRef.current = updateViewportSize;
|
|
1384
1383
|
}, [updateViewportSize]);
|
|
1385
1384
|
react.useEffect(() => {
|
|
1386
|
-
if (skip) {
|
|
1385
|
+
if (skip || !canUseMatchMedia()) {
|
|
1387
1386
|
return;
|
|
1388
1387
|
}
|
|
1389
|
-
// Initial check
|
|
1390
1388
|
updateViewportSizeRef.current();
|
|
1391
|
-
// Set up listeners for each breakpoint
|
|
1392
1389
|
const mediaQueryLists = sharedUtils.objectEntries(uiDesignTokens.themeScreenSizeAsNumber).map(([_, minWidth]) => window.matchMedia(`(min-width: ${minWidth}px)`));
|
|
1393
1390
|
mediaQueryLists.forEach(mql => {
|
|
1394
1391
|
mql.addEventListener("change", updateViewportSizeRef.current);
|
|
1395
1392
|
});
|
|
1396
|
-
// Cleanup
|
|
1397
1393
|
return () => {
|
|
1398
1394
|
mediaQueryLists.forEach(mql => {
|
|
1399
1395
|
mql.removeEventListener("change", updateViewportSizeRef.current);
|
|
@@ -9812,6 +9808,112 @@ const useModifierKey = ({ exclude = [] } = {}) => {
|
|
|
9812
9808
|
return isModifierPressed;
|
|
9813
9809
|
};
|
|
9814
9810
|
|
|
9811
|
+
const resolveRootEl = (refLike) => {
|
|
9812
|
+
if (refLike && typeof refLike === "object" && "current" in refLike) {
|
|
9813
|
+
return refLike.current;
|
|
9814
|
+
}
|
|
9815
|
+
return refLike;
|
|
9816
|
+
};
|
|
9817
|
+
/**
|
|
9818
|
+
* Observes a scroll area within the given root element and toggles CSS
|
|
9819
|
+
* class(es) on a target element when the scroll area overflows vertically.
|
|
9820
|
+
*
|
|
9821
|
+
* Behavior:
|
|
9822
|
+
* - Locates elements via CSS selectors within the root.
|
|
9823
|
+
* - Recomputes on resize, DOM mutations within the scroll area, scroll
|
|
9824
|
+
* events, and image load/error events.
|
|
9825
|
+
* - Cleans up all observers/listeners on unmount or dependency change.
|
|
9826
|
+
*
|
|
9827
|
+
* Edge cases:
|
|
9828
|
+
* - If either element is missing, retries via requestAnimationFrame
|
|
9829
|
+
* (up to 20 attempts) to handle deferred DOM mounting (e.g. portals).
|
|
9830
|
+
* - No DOM mutations occur when `enabled` is false.
|
|
9831
|
+
*
|
|
9832
|
+
* @param rootRef Root element that contains both the scroll area and the target.
|
|
9833
|
+
* @param options Configuration.
|
|
9834
|
+
* @param options.scrollAreaSelector CSS selector to locate the scrollable element.
|
|
9835
|
+
* @param options.targetSelector CSS selector to locate the element that receives the class toggle.
|
|
9836
|
+
* @param options.toggleClass CSS class(es) toggled on the target when the scroll area overflows. Accepts string or string[].
|
|
9837
|
+
* @param options.enabled Whether the hook is active. Defaults to true.
|
|
9838
|
+
*/
|
|
9839
|
+
const useOverflowBorder = (rootRef, { scrollAreaSelector, targetSelector, toggleClass, enabled = true }) => {
|
|
9840
|
+
react.useLayoutEffect(() => {
|
|
9841
|
+
if (!enabled)
|
|
9842
|
+
return;
|
|
9843
|
+
let cleanup;
|
|
9844
|
+
let cancelled = false;
|
|
9845
|
+
const classes = Array.isArray(toggleClass)
|
|
9846
|
+
? toggleClass.filter(Boolean)
|
|
9847
|
+
: String(toggleClass).split(/\s+/).filter(Boolean);
|
|
9848
|
+
let attempts = 0;
|
|
9849
|
+
const MAX_ATTEMPTS = 20;
|
|
9850
|
+
const tryInit = () => {
|
|
9851
|
+
if (cancelled)
|
|
9852
|
+
return;
|
|
9853
|
+
const root = resolveRootEl(rootRef);
|
|
9854
|
+
if (!root) {
|
|
9855
|
+
if (attempts++ < MAX_ATTEMPTS)
|
|
9856
|
+
requestAnimationFrame(tryInit);
|
|
9857
|
+
return;
|
|
9858
|
+
}
|
|
9859
|
+
const scrollAreaEl = root.querySelector(scrollAreaSelector);
|
|
9860
|
+
const targetEl = root.querySelector(targetSelector);
|
|
9861
|
+
if (!scrollAreaEl || !targetEl) {
|
|
9862
|
+
if (attempts++ < MAX_ATTEMPTS)
|
|
9863
|
+
requestAnimationFrame(tryInit);
|
|
9864
|
+
return;
|
|
9865
|
+
}
|
|
9866
|
+
const update = () => {
|
|
9867
|
+
const hasOverflow = scrollAreaEl.scrollHeight > scrollAreaEl.clientHeight;
|
|
9868
|
+
classes.forEach(cls => targetEl.classList.toggle(cls, hasOverflow));
|
|
9869
|
+
};
|
|
9870
|
+
update();
|
|
9871
|
+
const ro = new ResizeObserver(update);
|
|
9872
|
+
ro.observe(scrollAreaEl);
|
|
9873
|
+
const attachImgListeners = (node) => {
|
|
9874
|
+
node.querySelectorAll("img").forEach(img => {
|
|
9875
|
+
if (!img.complete) {
|
|
9876
|
+
const once = () => update();
|
|
9877
|
+
img.addEventListener("load", once, { once: true });
|
|
9878
|
+
img.addEventListener("error", once, { once: true });
|
|
9879
|
+
}
|
|
9880
|
+
});
|
|
9881
|
+
};
|
|
9882
|
+
attachImgListeners(scrollAreaEl);
|
|
9883
|
+
const mo = new MutationObserver(muts => {
|
|
9884
|
+
update();
|
|
9885
|
+
for (const m of muts) {
|
|
9886
|
+
m.addedNodes.forEach(n => {
|
|
9887
|
+
if (n instanceof HTMLImageElement) {
|
|
9888
|
+
if (!n.complete) {
|
|
9889
|
+
const once = () => update();
|
|
9890
|
+
n.addEventListener("load", once, { once: true });
|
|
9891
|
+
n.addEventListener("error", once, { once: true });
|
|
9892
|
+
}
|
|
9893
|
+
}
|
|
9894
|
+
else if (n instanceof HTMLElement) {
|
|
9895
|
+
attachImgListeners(n);
|
|
9896
|
+
}
|
|
9897
|
+
});
|
|
9898
|
+
}
|
|
9899
|
+
});
|
|
9900
|
+
mo.observe(scrollAreaEl, { childList: true, subtree: true, characterData: true });
|
|
9901
|
+
scrollAreaEl.addEventListener("scroll", update, { passive: true });
|
|
9902
|
+
cleanup = () => {
|
|
9903
|
+
ro.disconnect();
|
|
9904
|
+
mo.disconnect();
|
|
9905
|
+
scrollAreaEl.removeEventListener("scroll", update);
|
|
9906
|
+
classes.forEach(cls => targetEl.classList.remove(cls));
|
|
9907
|
+
};
|
|
9908
|
+
};
|
|
9909
|
+
requestAnimationFrame(tryInit);
|
|
9910
|
+
return () => {
|
|
9911
|
+
cancelled = true;
|
|
9912
|
+
cleanup?.();
|
|
9913
|
+
};
|
|
9914
|
+
}, [enabled, toggleClass, scrollAreaSelector, targetSelector, rootRef]);
|
|
9915
|
+
};
|
|
9916
|
+
|
|
9815
9917
|
/**
|
|
9816
9918
|
* The usePrevious hook is a useful tool for tracking the previous value of a variable in a functional component. This can be particularly handy in scenarios where it is necessary to compare the current value with the previous one, such as triggering actions or rendering based on changes.
|
|
9817
9919
|
*
|
|
@@ -10329,6 +10431,7 @@ exports.useLocalStorageReducer = useLocalStorageReducer;
|
|
|
10329
10431
|
exports.useMeasure = useMeasure;
|
|
10330
10432
|
exports.useMergeRefs = useMergeRefs;
|
|
10331
10433
|
exports.useModifierKey = useModifierKey;
|
|
10434
|
+
exports.useOverflowBorder = useOverflowBorder;
|
|
10332
10435
|
exports.useOverflowItems = useOverflowItems;
|
|
10333
10436
|
exports.usePopoverContext = usePopoverContext;
|
|
10334
10437
|
exports.usePrevious = usePrevious;
|
package/index.esm.js
CHANGED
|
@@ -1339,6 +1339,15 @@ const createBreakpointState = ({ width }) => {
|
|
|
1339
1339
|
}), { ...defaultBreakpointState });
|
|
1340
1340
|
};
|
|
1341
1341
|
|
|
1342
|
+
const canUseMatchMedia = () => typeof window !== "undefined" && typeof window.matchMedia === "function";
|
|
1343
|
+
const getViewportBreakpointState = () => {
|
|
1344
|
+
if (!canUseMatchMedia())
|
|
1345
|
+
return { ...defaultBreakpointState };
|
|
1346
|
+
return objectEntries(themeScreenSizeAsNumber).reduce((acc, [size, minWidth]) => ({
|
|
1347
|
+
...acc,
|
|
1348
|
+
[breakpointPropsMap[size]]: window.matchMedia(`(min-width: ${minWidth}px)`).matches,
|
|
1349
|
+
}), { ...defaultBreakpointState });
|
|
1350
|
+
};
|
|
1342
1351
|
/**
|
|
1343
1352
|
* A custom React hook that provides real-time information about the current viewport size.
|
|
1344
1353
|
* ! Consider using `useContainerBreakpoints` instead, and only use this when you need to actually react to the viewport size, not the container size.
|
|
@@ -1362,36 +1371,23 @@ const createBreakpointState = ({ width }) => {
|
|
|
1362
1371
|
*/
|
|
1363
1372
|
const useViewportBreakpoints = (options = {}) => {
|
|
1364
1373
|
const { skip = false } = options;
|
|
1365
|
-
const [viewportSize, setViewportSize] = useState(
|
|
1366
|
-
const newViewportSize = objectEntries(themeScreenSizeAsNumber).reduce((acc, [size, minWidth]) => ({
|
|
1367
|
-
...acc,
|
|
1368
|
-
[breakpointPropsMap[size]]: window.matchMedia(`(min-width: ${minWidth}px)`).matches,
|
|
1369
|
-
}), { ...defaultBreakpointState });
|
|
1370
|
-
return newViewportSize;
|
|
1371
|
-
});
|
|
1374
|
+
const [viewportSize, setViewportSize] = useState(getViewportBreakpointState);
|
|
1372
1375
|
const updateViewportSize = useCallback(() => {
|
|
1373
|
-
|
|
1374
|
-
...acc,
|
|
1375
|
-
[breakpointPropsMap[size]]: window.matchMedia(`(min-width: ${minWidth}px)`).matches,
|
|
1376
|
-
}), { ...defaultBreakpointState });
|
|
1377
|
-
setViewportSize(newViewportSize);
|
|
1376
|
+
setViewportSize(getViewportBreakpointState());
|
|
1378
1377
|
}, []);
|
|
1379
1378
|
const updateViewportSizeRef = useRef(updateViewportSize);
|
|
1380
1379
|
useEffect(() => {
|
|
1381
1380
|
updateViewportSizeRef.current = updateViewportSize;
|
|
1382
1381
|
}, [updateViewportSize]);
|
|
1383
1382
|
useEffect(() => {
|
|
1384
|
-
if (skip) {
|
|
1383
|
+
if (skip || !canUseMatchMedia()) {
|
|
1385
1384
|
return;
|
|
1386
1385
|
}
|
|
1387
|
-
// Initial check
|
|
1388
1386
|
updateViewportSizeRef.current();
|
|
1389
|
-
// Set up listeners for each breakpoint
|
|
1390
1387
|
const mediaQueryLists = objectEntries(themeScreenSizeAsNumber).map(([_, minWidth]) => window.matchMedia(`(min-width: ${minWidth}px)`));
|
|
1391
1388
|
mediaQueryLists.forEach(mql => {
|
|
1392
1389
|
mql.addEventListener("change", updateViewportSizeRef.current);
|
|
1393
1390
|
});
|
|
1394
|
-
// Cleanup
|
|
1395
1391
|
return () => {
|
|
1396
1392
|
mediaQueryLists.forEach(mql => {
|
|
1397
1393
|
mql.removeEventListener("change", updateViewportSizeRef.current);
|
|
@@ -9810,6 +9806,112 @@ const useModifierKey = ({ exclude = [] } = {}) => {
|
|
|
9810
9806
|
return isModifierPressed;
|
|
9811
9807
|
};
|
|
9812
9808
|
|
|
9809
|
+
const resolveRootEl = (refLike) => {
|
|
9810
|
+
if (refLike && typeof refLike === "object" && "current" in refLike) {
|
|
9811
|
+
return refLike.current;
|
|
9812
|
+
}
|
|
9813
|
+
return refLike;
|
|
9814
|
+
};
|
|
9815
|
+
/**
|
|
9816
|
+
* Observes a scroll area within the given root element and toggles CSS
|
|
9817
|
+
* class(es) on a target element when the scroll area overflows vertically.
|
|
9818
|
+
*
|
|
9819
|
+
* Behavior:
|
|
9820
|
+
* - Locates elements via CSS selectors within the root.
|
|
9821
|
+
* - Recomputes on resize, DOM mutations within the scroll area, scroll
|
|
9822
|
+
* events, and image load/error events.
|
|
9823
|
+
* - Cleans up all observers/listeners on unmount or dependency change.
|
|
9824
|
+
*
|
|
9825
|
+
* Edge cases:
|
|
9826
|
+
* - If either element is missing, retries via requestAnimationFrame
|
|
9827
|
+
* (up to 20 attempts) to handle deferred DOM mounting (e.g. portals).
|
|
9828
|
+
* - No DOM mutations occur when `enabled` is false.
|
|
9829
|
+
*
|
|
9830
|
+
* @param rootRef Root element that contains both the scroll area and the target.
|
|
9831
|
+
* @param options Configuration.
|
|
9832
|
+
* @param options.scrollAreaSelector CSS selector to locate the scrollable element.
|
|
9833
|
+
* @param options.targetSelector CSS selector to locate the element that receives the class toggle.
|
|
9834
|
+
* @param options.toggleClass CSS class(es) toggled on the target when the scroll area overflows. Accepts string or string[].
|
|
9835
|
+
* @param options.enabled Whether the hook is active. Defaults to true.
|
|
9836
|
+
*/
|
|
9837
|
+
const useOverflowBorder = (rootRef, { scrollAreaSelector, targetSelector, toggleClass, enabled = true }) => {
|
|
9838
|
+
useLayoutEffect(() => {
|
|
9839
|
+
if (!enabled)
|
|
9840
|
+
return;
|
|
9841
|
+
let cleanup;
|
|
9842
|
+
let cancelled = false;
|
|
9843
|
+
const classes = Array.isArray(toggleClass)
|
|
9844
|
+
? toggleClass.filter(Boolean)
|
|
9845
|
+
: String(toggleClass).split(/\s+/).filter(Boolean);
|
|
9846
|
+
let attempts = 0;
|
|
9847
|
+
const MAX_ATTEMPTS = 20;
|
|
9848
|
+
const tryInit = () => {
|
|
9849
|
+
if (cancelled)
|
|
9850
|
+
return;
|
|
9851
|
+
const root = resolveRootEl(rootRef);
|
|
9852
|
+
if (!root) {
|
|
9853
|
+
if (attempts++ < MAX_ATTEMPTS)
|
|
9854
|
+
requestAnimationFrame(tryInit);
|
|
9855
|
+
return;
|
|
9856
|
+
}
|
|
9857
|
+
const scrollAreaEl = root.querySelector(scrollAreaSelector);
|
|
9858
|
+
const targetEl = root.querySelector(targetSelector);
|
|
9859
|
+
if (!scrollAreaEl || !targetEl) {
|
|
9860
|
+
if (attempts++ < MAX_ATTEMPTS)
|
|
9861
|
+
requestAnimationFrame(tryInit);
|
|
9862
|
+
return;
|
|
9863
|
+
}
|
|
9864
|
+
const update = () => {
|
|
9865
|
+
const hasOverflow = scrollAreaEl.scrollHeight > scrollAreaEl.clientHeight;
|
|
9866
|
+
classes.forEach(cls => targetEl.classList.toggle(cls, hasOverflow));
|
|
9867
|
+
};
|
|
9868
|
+
update();
|
|
9869
|
+
const ro = new ResizeObserver(update);
|
|
9870
|
+
ro.observe(scrollAreaEl);
|
|
9871
|
+
const attachImgListeners = (node) => {
|
|
9872
|
+
node.querySelectorAll("img").forEach(img => {
|
|
9873
|
+
if (!img.complete) {
|
|
9874
|
+
const once = () => update();
|
|
9875
|
+
img.addEventListener("load", once, { once: true });
|
|
9876
|
+
img.addEventListener("error", once, { once: true });
|
|
9877
|
+
}
|
|
9878
|
+
});
|
|
9879
|
+
};
|
|
9880
|
+
attachImgListeners(scrollAreaEl);
|
|
9881
|
+
const mo = new MutationObserver(muts => {
|
|
9882
|
+
update();
|
|
9883
|
+
for (const m of muts) {
|
|
9884
|
+
m.addedNodes.forEach(n => {
|
|
9885
|
+
if (n instanceof HTMLImageElement) {
|
|
9886
|
+
if (!n.complete) {
|
|
9887
|
+
const once = () => update();
|
|
9888
|
+
n.addEventListener("load", once, { once: true });
|
|
9889
|
+
n.addEventListener("error", once, { once: true });
|
|
9890
|
+
}
|
|
9891
|
+
}
|
|
9892
|
+
else if (n instanceof HTMLElement) {
|
|
9893
|
+
attachImgListeners(n);
|
|
9894
|
+
}
|
|
9895
|
+
});
|
|
9896
|
+
}
|
|
9897
|
+
});
|
|
9898
|
+
mo.observe(scrollAreaEl, { childList: true, subtree: true, characterData: true });
|
|
9899
|
+
scrollAreaEl.addEventListener("scroll", update, { passive: true });
|
|
9900
|
+
cleanup = () => {
|
|
9901
|
+
ro.disconnect();
|
|
9902
|
+
mo.disconnect();
|
|
9903
|
+
scrollAreaEl.removeEventListener("scroll", update);
|
|
9904
|
+
classes.forEach(cls => targetEl.classList.remove(cls));
|
|
9905
|
+
};
|
|
9906
|
+
};
|
|
9907
|
+
requestAnimationFrame(tryInit);
|
|
9908
|
+
return () => {
|
|
9909
|
+
cancelled = true;
|
|
9910
|
+
cleanup?.();
|
|
9911
|
+
};
|
|
9912
|
+
}, [enabled, toggleClass, scrollAreaSelector, targetSelector, rootRef]);
|
|
9913
|
+
};
|
|
9914
|
+
|
|
9813
9915
|
/**
|
|
9814
9916
|
* The usePrevious hook is a useful tool for tracking the previous value of a variable in a functional component. This can be particularly handy in scenarios where it is necessary to compare the current value with the previous one, such as triggering actions or rendering based on changes.
|
|
9815
9917
|
*
|
|
@@ -10174,4 +10276,4 @@ const useWindowActivity = ({ onFocus, onBlur, skip = false } = { onBlur: undefin
|
|
|
10174
10276
|
return useMemo(() => ({ focused }), [focused]);
|
|
10175
10277
|
};
|
|
10176
10278
|
|
|
10177
|
-
export { ActionRenderer, Alert, Badge, Breadcrumb, BreadcrumbContainer, Button, Card, CardBody, CardFooter, CardHeader, Collapse, CompletionStatusIndicator, CopyableText, DEFAULT_SKELETON_PREFERENCE_CARD_PROPS, DetailsList, EmptyState, EmptyValue, ExternalLink, GridAreas, Heading, Highlight, HorizontalOverflowScroller, Icon, IconButton, Indicator, KPI, KPICard, KPICardSkeleton, KPISkeleton, List, ListItem, MenuDivider, MenuItem, MenuList, MoreMenu, Notice, PackageNameStoryComponent, Page, PageContent, PageHeader, PageHeaderKpiMetrics, PageHeaderSecondaryActions, PageHeaderTitle, Pagination, Polygon, Popover, PopoverContent, PopoverTitle, PopoverTrigger, Portal, PreferenceCard, PreferenceCardSkeleton, Prompt, ROLE_CARD, SectionHeader, SegmentedValueBar, Sidebar, SkeletonBlock, SkeletonLabel, SkeletonLines, Spacer, Spinner, StarButton, Tab, TabContent, TabList, Tabs, Tag, Text, ToggleGroup, Tooltip, TrendIndicator, TrendIndicators, ValueBar, ZStack, createGrid, cvaButton, cvaButtonPrefixSuffix, cvaButtonSpinner, cvaButtonSpinnerContainer, cvaClickable, cvaContainerStyles, cvaContentContainer, cvaContentWrapper, cvaDescriptionCard, cvaIconBackground, cvaIconButton, cvaImgStyles, cvaIndicator, cvaIndicatorIcon, cvaIndicatorIconBackground, cvaIndicatorLabel, cvaIndicatorPing, cvaInputContainer, cvaInteractableItem, cvaList, cvaListContainer, cvaListItem$1 as cvaListItem, cvaMenu, cvaMenuItem, cvaMenuItemLabel, cvaMenuItemPrefix, cvaMenuItemStyle, cvaMenuItemSuffix, cvaMenuList, cvaMenuListDivider, cvaMenuListItem, cvaMenuListMultiSelect, cvaPageHeader, cvaPageHeaderContainer, cvaPageHeaderHeading, cvaPreferenceCard, cvaTitleCard, cvaToggleGroup, cvaToggleGroupWithSlidingBackground, cvaToggleItem, cvaToggleItemContent, cvaToggleItemText, cvaZStackContainer, cvaZStackItem, defaultPageSize, docs, getDevicePixelRatio, getValueBarColorByValue, iconColorNames, iconPalette, noPagination, preferenceCardGrid, useBidirectionalScroll, useClickOutside, useContainerBreakpoints, useContinuousTimeout, useCopyToClipboard, useCursorUrlSync, useCustomEncoding, useDebounce, useDevicePixelRatio, useElevatedReducer, useElevatedState, useGridAreas, useHover, useInfiniteScroll, useIsFirstRender, useIsFullscreen, useIsTextTruncated, useKeyboardShortcut, useList, useListItemHeight, useLocalStorage, useLocalStorageReducer, useMeasure, useMergeRefs, useModifierKey, useOverflowItems, usePopoverContext, usePrevious, usePrompt, useRandomCSSLengths, useRelayPagination, useResize, useScrollBlock, useScrollDetection, useSelfUpdatingRef, useSessionStorage, useSessionStorageReducer, useTextSearch, useTimeout, useViewportBreakpoints, useWatch, useWindowActivity };
|
|
10279
|
+
export { ActionRenderer, Alert, Badge, Breadcrumb, BreadcrumbContainer, Button, Card, CardBody, CardFooter, CardHeader, Collapse, CompletionStatusIndicator, CopyableText, DEFAULT_SKELETON_PREFERENCE_CARD_PROPS, DetailsList, EmptyState, EmptyValue, ExternalLink, GridAreas, Heading, Highlight, HorizontalOverflowScroller, Icon, IconButton, Indicator, KPI, KPICard, KPICardSkeleton, KPISkeleton, List, ListItem, MenuDivider, MenuItem, MenuList, MoreMenu, Notice, PackageNameStoryComponent, Page, PageContent, PageHeader, PageHeaderKpiMetrics, PageHeaderSecondaryActions, PageHeaderTitle, Pagination, Polygon, Popover, PopoverContent, PopoverTitle, PopoverTrigger, Portal, PreferenceCard, PreferenceCardSkeleton, Prompt, ROLE_CARD, SectionHeader, SegmentedValueBar, Sidebar, SkeletonBlock, SkeletonLabel, SkeletonLines, Spacer, Spinner, StarButton, Tab, TabContent, TabList, Tabs, Tag, Text, ToggleGroup, Tooltip, TrendIndicator, TrendIndicators, ValueBar, ZStack, createGrid, cvaButton, cvaButtonPrefixSuffix, cvaButtonSpinner, cvaButtonSpinnerContainer, cvaClickable, cvaContainerStyles, cvaContentContainer, cvaContentWrapper, cvaDescriptionCard, cvaIconBackground, cvaIconButton, cvaImgStyles, cvaIndicator, cvaIndicatorIcon, cvaIndicatorIconBackground, cvaIndicatorLabel, cvaIndicatorPing, cvaInputContainer, cvaInteractableItem, cvaList, cvaListContainer, cvaListItem$1 as cvaListItem, cvaMenu, cvaMenuItem, cvaMenuItemLabel, cvaMenuItemPrefix, cvaMenuItemStyle, cvaMenuItemSuffix, cvaMenuList, cvaMenuListDivider, cvaMenuListItem, cvaMenuListMultiSelect, cvaPageHeader, cvaPageHeaderContainer, cvaPageHeaderHeading, cvaPreferenceCard, cvaTitleCard, cvaToggleGroup, cvaToggleGroupWithSlidingBackground, cvaToggleItem, cvaToggleItemContent, cvaToggleItemText, cvaZStackContainer, cvaZStackItem, defaultPageSize, docs, getDevicePixelRatio, getValueBarColorByValue, iconColorNames, iconPalette, noPagination, preferenceCardGrid, useBidirectionalScroll, useClickOutside, useContainerBreakpoints, useContinuousTimeout, useCopyToClipboard, useCursorUrlSync, useCustomEncoding, useDebounce, useDevicePixelRatio, useElevatedReducer, useElevatedState, useGridAreas, useHover, useInfiniteScroll, useIsFirstRender, useIsFullscreen, useIsTextTruncated, useKeyboardShortcut, useList, useListItemHeight, useLocalStorage, useLocalStorageReducer, useMeasure, useMergeRefs, useModifierKey, useOverflowBorder, useOverflowItems, usePopoverContext, usePrevious, usePrompt, useRandomCSSLengths, useRelayPagination, useResize, useScrollBlock, useScrollDetection, useSelfUpdatingRef, useSessionStorage, useSessionStorageReducer, useTextSearch, useTimeout, useViewportBreakpoints, useWatch, useWindowActivity };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-components",
|
|
3
|
-
"version": "1.21.
|
|
3
|
+
"version": "1.21.12",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"engines": {
|
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
"@floating-ui/react": "^0.26.25",
|
|
14
14
|
"string-ts": "^2.0.0",
|
|
15
15
|
"tailwind-merge": "^2.0.0",
|
|
16
|
-
"@trackunit/ui-design-tokens": "1.11.
|
|
17
|
-
"@trackunit/css-class-variance-utilities": "1.11.
|
|
18
|
-
"@trackunit/shared-utils": "1.13.
|
|
19
|
-
"@trackunit/ui-icons": "1.11.
|
|
16
|
+
"@trackunit/ui-design-tokens": "1.11.92",
|
|
17
|
+
"@trackunit/css-class-variance-utilities": "1.11.95",
|
|
18
|
+
"@trackunit/shared-utils": "1.13.95",
|
|
19
|
+
"@trackunit/ui-icons": "1.11.91",
|
|
20
20
|
"es-toolkit": "^1.39.10",
|
|
21
21
|
"@tanstack/react-virtual": "3.13.12",
|
|
22
22
|
"fflate": "^0.8.2",
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { type RefObject } from "react";
|
|
2
|
+
type OverflowBorderOptions = {
|
|
3
|
+
readonly scrollAreaSelector: string;
|
|
4
|
+
readonly targetSelector: string;
|
|
5
|
+
readonly toggleClass: string | Array<string>;
|
|
6
|
+
readonly enabled?: boolean;
|
|
7
|
+
};
|
|
8
|
+
type ElementRef = HTMLElement | null;
|
|
9
|
+
type ElementRefLike = ElementRef | RefObject<ElementRef>;
|
|
10
|
+
/**
|
|
11
|
+
* Observes a scroll area within the given root element and toggles CSS
|
|
12
|
+
* class(es) on a target element when the scroll area overflows vertically.
|
|
13
|
+
*
|
|
14
|
+
* Behavior:
|
|
15
|
+
* - Locates elements via CSS selectors within the root.
|
|
16
|
+
* - Recomputes on resize, DOM mutations within the scroll area, scroll
|
|
17
|
+
* events, and image load/error events.
|
|
18
|
+
* - Cleans up all observers/listeners on unmount or dependency change.
|
|
19
|
+
*
|
|
20
|
+
* Edge cases:
|
|
21
|
+
* - If either element is missing, retries via requestAnimationFrame
|
|
22
|
+
* (up to 20 attempts) to handle deferred DOM mounting (e.g. portals).
|
|
23
|
+
* - No DOM mutations occur when `enabled` is false.
|
|
24
|
+
*
|
|
25
|
+
* @param rootRef Root element that contains both the scroll area and the target.
|
|
26
|
+
* @param options Configuration.
|
|
27
|
+
* @param options.scrollAreaSelector CSS selector to locate the scrollable element.
|
|
28
|
+
* @param options.targetSelector CSS selector to locate the element that receives the class toggle.
|
|
29
|
+
* @param options.toggleClass CSS class(es) toggled on the target when the scroll area overflows. Accepts string or string[].
|
|
30
|
+
* @param options.enabled Whether the hook is active. Defaults to true.
|
|
31
|
+
*/
|
|
32
|
+
export declare const useOverflowBorder: (rootRef: ElementRefLike, { scrollAreaSelector, targetSelector, toggleClass, enabled }: OverflowBorderOptions) => void;
|
|
33
|
+
export {};
|
package/src/index.d.ts
CHANGED
|
@@ -130,6 +130,7 @@ export { useKeyboardShortcut } from "./hooks/useKeyboardShortcut/useKeyboardShor
|
|
|
130
130
|
export * from "./hooks/useMeasure";
|
|
131
131
|
export * from "./hooks/useMergeRefs";
|
|
132
132
|
export * from "./hooks/useModifierKey";
|
|
133
|
+
export * from "./hooks/useOverflowBorder";
|
|
133
134
|
export * from "./hooks/usePrevious";
|
|
134
135
|
export * from "./hooks/useRelayPagination";
|
|
135
136
|
export * from "./hooks/useResize";
|
|
@@ -141,3 +142,4 @@ export * from "./hooks/useTimeout";
|
|
|
141
142
|
export * from "./hooks/useViewportBreakpoints";
|
|
142
143
|
export * from "./hooks/useWatch";
|
|
143
144
|
export * from "./hooks/useWindowActivity";
|
|
145
|
+
export type { CloseReason, DismissOptions, OnBeforeCloseFn, OnCloseFn, OnOpenChangeFn, OnOpenFn, UseOverlayDismissibleProps, UseOverlayDismissibleReturn, } from "./overlay-dismissible/types";
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { RefObject } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Reasons why an overlay (Modal/Sheet) closed.
|
|
4
|
+
* - `escape-key`: User pressed the ESC key
|
|
5
|
+
* - `outside-press`: User clicked outside / on overlay
|
|
6
|
+
* - `programmatic`: The close() function was called (e.g., from a close button)
|
|
7
|
+
* - `gesture`: User swiped down to close (Sheet only; Modal-in-sheet-mode)
|
|
8
|
+
*/
|
|
9
|
+
export type CloseReason = "escape-key" | "outside-press" | "programmatic" | "gesture";
|
|
10
|
+
/**
|
|
11
|
+
* Config for which user gestures trigger close.
|
|
12
|
+
* Shared by Modal and Sheet.
|
|
13
|
+
*/
|
|
14
|
+
export type DismissOptions = {
|
|
15
|
+
/** Whether ESC key closes. @default true */
|
|
16
|
+
readonly escapeKey?: boolean;
|
|
17
|
+
/** Whether overlay/outside click closes. @default true */
|
|
18
|
+
readonly outsidePress?: boolean;
|
|
19
|
+
/** Whether swipe-down gesture closes (Sheet only; Modal-in-sheet-mode). @default true */
|
|
20
|
+
readonly gesture?: boolean;
|
|
21
|
+
};
|
|
22
|
+
/** Callback fired when the overlay closes. */
|
|
23
|
+
export type OnCloseFn = (event?: Event, reason?: CloseReason) => void;
|
|
24
|
+
/** Callback fired when the overlay opens. */
|
|
25
|
+
export type OnOpenFn = (event?: Event) => void;
|
|
26
|
+
/** Callback fired when the overlay open state changes. */
|
|
27
|
+
export type OnOpenChangeFn = (open: boolean, event?: Event, reason?: CloseReason) => void;
|
|
28
|
+
/** Callback fired BEFORE the overlay closes. Return false to prevent closing. */
|
|
29
|
+
export type OnBeforeCloseFn = (event?: Event, reason?: CloseReason) => boolean | Promise<boolean>;
|
|
30
|
+
/** Base props shared by useModal and useSheet. */
|
|
31
|
+
export type UseOverlayDismissibleProps = {
|
|
32
|
+
readonly isOpen?: boolean;
|
|
33
|
+
readonly defaultOpen?: boolean;
|
|
34
|
+
readonly onClose?: OnCloseFn;
|
|
35
|
+
readonly onOpen?: OnOpenFn;
|
|
36
|
+
readonly onOpenChange?: OnOpenChangeFn;
|
|
37
|
+
readonly onBeforeClose?: OnBeforeCloseFn;
|
|
38
|
+
/** Config for which user gestures trigger close. Defaults: all true. */
|
|
39
|
+
readonly dismiss?: DismissOptions;
|
|
40
|
+
};
|
|
41
|
+
/** Base return value shared by useModal and useSheet. */
|
|
42
|
+
export type UseOverlayDismissibleReturn = {
|
|
43
|
+
readonly isOpen: boolean;
|
|
44
|
+
readonly open: () => void;
|
|
45
|
+
readonly close: () => void;
|
|
46
|
+
readonly toggle: () => void;
|
|
47
|
+
readonly ref: RefObject<HTMLDivElement | null>;
|
|
48
|
+
};
|
|
49
|
+
/** Resolves DismissOptions with defaults (all true when omitted). */
|
|
50
|
+
export declare const DEFAULT_DISMISS_OPTIONS: Required<DismissOptions>;
|
|
51
|
+
/** Merges caller-supplied DismissOptions with defaults, returning a fully-resolved options object. */
|
|
52
|
+
export declare function resolveDismissOptions(dismiss?: DismissOptions): Required<DismissOptions>;
|