@trackunit/react-components 0.4.34 → 0.5.1
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 +58 -328
- package/index.esm.js +58 -328
- package/package.json +1 -2
- package/src/components/index.d.ts +0 -2
- package/src/hooks/index.d.ts +1 -0
- package/src/hooks/useScrollDetection.d.ts +16 -0
- package/src/components/Drawer/Drawer.d.ts +0 -37
- package/src/components/Drawer/Drawer.variants.d.ts +0 -20
- package/src/components/Drawer/Overlay.d.ts +0 -14
- package/src/components/Drawer/ToogleButton.d.ts +0 -19
- package/src/components/Drawer/index.d.ts +0 -1
package/index.cjs.js
CHANGED
|
@@ -13,9 +13,8 @@ var stringTs = require('string-ts');
|
|
|
13
13
|
var cssClassVarianceUtilities = require('@trackunit/css-class-variance-utilities');
|
|
14
14
|
var reactSlot = require('@radix-ui/react-slot');
|
|
15
15
|
var isEqual = require('lodash/isEqual');
|
|
16
|
-
var reactRouter = require('@tanstack/react-router');
|
|
17
16
|
var usehooksTs = require('usehooks-ts');
|
|
18
|
-
var
|
|
17
|
+
var reactRouter = require('@tanstack/react-router');
|
|
19
18
|
var react = require('@floating-ui/react');
|
|
20
19
|
var omit = require('lodash/omit');
|
|
21
20
|
var tailwindMerge = require('tailwind-merge');
|
|
@@ -1310,6 +1309,62 @@ const getWindowSize = () => {
|
|
|
1310
1309
|
}
|
|
1311
1310
|
};
|
|
1312
1311
|
|
|
1312
|
+
const SCROLL_DEBOUNCE_TIME = 50;
|
|
1313
|
+
/**
|
|
1314
|
+
* Hook for getting detecting scroll values.
|
|
1315
|
+
*
|
|
1316
|
+
* @param {useRef} elementRef - Ref hook holding the element that needs to be observed during scrolling
|
|
1317
|
+
* @returns {object} An object containing if the element is scrollable, is at the top, is at the bottom, and its current scroll position.
|
|
1318
|
+
*/
|
|
1319
|
+
const useScrollDetection = (elementRef) => {
|
|
1320
|
+
const [isScrollable, setIsScrollable] = React.useState(false);
|
|
1321
|
+
const [isAtTop, setIsAtTop] = React.useState(true);
|
|
1322
|
+
const [isAtBottom, setIsAtBottom] = React.useState(false);
|
|
1323
|
+
const [scrollPosition, setScrollPosition] = React.useState({ top: 0, bottom: 0 });
|
|
1324
|
+
const observerRef = React.useRef();
|
|
1325
|
+
const checkScrollable = React.useCallback(() => {
|
|
1326
|
+
const element = elementRef.current;
|
|
1327
|
+
if (!element) {
|
|
1328
|
+
return;
|
|
1329
|
+
}
|
|
1330
|
+
const hasOverflow = element.scrollHeight > element.clientHeight;
|
|
1331
|
+
setIsScrollable(hasOverflow);
|
|
1332
|
+
}, [elementRef]);
|
|
1333
|
+
const checkScrollPosition = React.useCallback(() => {
|
|
1334
|
+
const element = elementRef.current;
|
|
1335
|
+
if (!element) {
|
|
1336
|
+
return;
|
|
1337
|
+
}
|
|
1338
|
+
const { scrollTop, scrollHeight, clientHeight } = element;
|
|
1339
|
+
setIsAtTop(scrollTop === 0);
|
|
1340
|
+
setIsAtBottom(Math.abs(scrollHeight - scrollTop - clientHeight) < 1);
|
|
1341
|
+
setScrollPosition(prev => ({ ...prev, top: scrollTop, bottom: clientHeight - scrollTop }));
|
|
1342
|
+
}, [elementRef]);
|
|
1343
|
+
const debouncedCheckScrollPosition = usehooksTs.useDebounceCallback(checkScrollPosition, SCROLL_DEBOUNCE_TIME);
|
|
1344
|
+
React.useEffect(() => {
|
|
1345
|
+
const element = elementRef.current;
|
|
1346
|
+
if (!element) {
|
|
1347
|
+
return;
|
|
1348
|
+
}
|
|
1349
|
+
// Initial checks
|
|
1350
|
+
checkScrollable();
|
|
1351
|
+
checkScrollPosition();
|
|
1352
|
+
observerRef.current = new ResizeObserver(() => {
|
|
1353
|
+
checkScrollable();
|
|
1354
|
+
checkScrollPosition();
|
|
1355
|
+
});
|
|
1356
|
+
observerRef.current.observe(element);
|
|
1357
|
+
element.addEventListener("scroll", debouncedCheckScrollPosition);
|
|
1358
|
+
return () => {
|
|
1359
|
+
if (observerRef.current) {
|
|
1360
|
+
observerRef.current.disconnect();
|
|
1361
|
+
}
|
|
1362
|
+
element.removeEventListener("scroll", debouncedCheckScrollPosition);
|
|
1363
|
+
};
|
|
1364
|
+
}, [elementRef, checkScrollable, checkScrollPosition, debouncedCheckScrollPosition]);
|
|
1365
|
+
return { isScrollable, isAtTop, isAtBottom, scrollPosition };
|
|
1366
|
+
};
|
|
1367
|
+
|
|
1313
1368
|
/**
|
|
1314
1369
|
* A useRef that updates its given value whenever it changes.
|
|
1315
1370
|
*
|
|
@@ -1881,331 +1936,6 @@ const CopyableText = ({ text, alternativeText, dataTestId, className }) => {
|
|
|
1881
1936
|
return (jsxRuntime.jsx("span", { className: cvaCopyableText({ animating, className }), "data-testid": dataTestId, onAnimationEnd: () => setAnimating(false), onClick: handleOnClick, title: value, children: text }));
|
|
1882
1937
|
};
|
|
1883
1938
|
|
|
1884
|
-
const cvaDialog = cssClassVarianceUtilities.cvaMerge([
|
|
1885
|
-
"z-toast",
|
|
1886
|
-
"pointer-events-auto",
|
|
1887
|
-
"absolute",
|
|
1888
|
-
"transform",
|
|
1889
|
-
"flex-col",
|
|
1890
|
-
"bg-neutral-50",
|
|
1891
|
-
"transition-transform",
|
|
1892
|
-
"duration-300",
|
|
1893
|
-
"ease-in-out",
|
|
1894
|
-
"shadow-lg",
|
|
1895
|
-
], {
|
|
1896
|
-
variants: {
|
|
1897
|
-
position: {
|
|
1898
|
-
left: "left-0 top-0 h-full w-fit rounded-r-lg",
|
|
1899
|
-
right: "right-0 top-0 h-full w-fit rounded-l-lg",
|
|
1900
|
-
top: "left-0 top-0 h-fit w-full rounded-b-lg",
|
|
1901
|
-
bottom: "bottom-0 left-0 right-0 h-fit w-full rounded-t-lg",
|
|
1902
|
-
},
|
|
1903
|
-
sidebarMode: {
|
|
1904
|
-
"semi-closed": "translate-y-[calc(100%-2.2rem)]",
|
|
1905
|
-
"1/3": "translate-y-2/3",
|
|
1906
|
-
"2/3": "translate-y-1/3",
|
|
1907
|
-
full: "translate-y-0",
|
|
1908
|
-
"semi-full": "translate-y-5",
|
|
1909
|
-
closed: "translate-y-full",
|
|
1910
|
-
},
|
|
1911
|
-
isLargeScreen: {
|
|
1912
|
-
true: "",
|
|
1913
|
-
false: "bottom-0 left-0 right-0 h-full w-full rounded-t-lg",
|
|
1914
|
-
},
|
|
1915
|
-
open: {
|
|
1916
|
-
true: "",
|
|
1917
|
-
false: "",
|
|
1918
|
-
},
|
|
1919
|
-
},
|
|
1920
|
-
compoundVariants: [
|
|
1921
|
-
{
|
|
1922
|
-
isLargeScreen: false,
|
|
1923
|
-
open: false,
|
|
1924
|
-
className: "translate-y-full",
|
|
1925
|
-
},
|
|
1926
|
-
{
|
|
1927
|
-
isLargeScreen: true,
|
|
1928
|
-
open: true,
|
|
1929
|
-
position: "left",
|
|
1930
|
-
className: "translate-x-0",
|
|
1931
|
-
},
|
|
1932
|
-
{
|
|
1933
|
-
isLargeScreen: true,
|
|
1934
|
-
open: false,
|
|
1935
|
-
position: "left",
|
|
1936
|
-
className: "-translate-x-full",
|
|
1937
|
-
},
|
|
1938
|
-
{
|
|
1939
|
-
isLargeScreen: true,
|
|
1940
|
-
open: true,
|
|
1941
|
-
position: "right",
|
|
1942
|
-
className: "translate-x-0",
|
|
1943
|
-
},
|
|
1944
|
-
{
|
|
1945
|
-
isLargeScreen: true,
|
|
1946
|
-
open: false,
|
|
1947
|
-
position: "right",
|
|
1948
|
-
className: "translate-x-full",
|
|
1949
|
-
},
|
|
1950
|
-
{
|
|
1951
|
-
isLargeScreen: true,
|
|
1952
|
-
open: true,
|
|
1953
|
-
position: "top",
|
|
1954
|
-
className: "translate-y-0",
|
|
1955
|
-
},
|
|
1956
|
-
{
|
|
1957
|
-
isLargeScreen: true,
|
|
1958
|
-
open: false,
|
|
1959
|
-
position: "top",
|
|
1960
|
-
className: "-translate-y-full",
|
|
1961
|
-
},
|
|
1962
|
-
{
|
|
1963
|
-
isLargeScreen: true,
|
|
1964
|
-
open: true,
|
|
1965
|
-
position: "bottom",
|
|
1966
|
-
className: "translate-y-0",
|
|
1967
|
-
},
|
|
1968
|
-
{
|
|
1969
|
-
isLargeScreen: true,
|
|
1970
|
-
open: false,
|
|
1971
|
-
position: "bottom",
|
|
1972
|
-
className: "translate-y-full",
|
|
1973
|
-
},
|
|
1974
|
-
],
|
|
1975
|
-
});
|
|
1976
|
-
const cvaDialogContainer = cssClassVarianceUtilities.cvaMerge(["flex", "flex-col", "overflow-hidden", "rounded-[inherit]"], {
|
|
1977
|
-
variants: {
|
|
1978
|
-
sidebarMode: {
|
|
1979
|
-
"semi-closed": "h-auto",
|
|
1980
|
-
"1/3": "h-[34%]",
|
|
1981
|
-
"2/3": "h-[67%]",
|
|
1982
|
-
"semi-full": "h-[calc(100%-1.25rem)]",
|
|
1983
|
-
full: "h-full",
|
|
1984
|
-
closed: "h-auto",
|
|
1985
|
-
},
|
|
1986
|
-
},
|
|
1987
|
-
});
|
|
1988
|
-
const cvaSwipeContainer = cssClassVarianceUtilities.cvaMerge(["my-4", "flex", "items-center", "justify-center", "lg:hidden"]);
|
|
1989
|
-
const cvaSwipeIcon = cssClassVarianceUtilities.cvaMerge(["block", "h-1", "w-10", "rounded-full", "bg-gray-400"]);
|
|
1990
|
-
const cvaToogleContainer = cssClassVarianceUtilities.cvaMerge(["z-8", "absolute"], {
|
|
1991
|
-
variants: {
|
|
1992
|
-
position: {
|
|
1993
|
-
left: "right-[-24px] top-[calc(50%-24px)]",
|
|
1994
|
-
right: "left-[-24px] top-[calc(50%-24px)]",
|
|
1995
|
-
top: "bottom-[-24px] left-[calc(50%-24px)]",
|
|
1996
|
-
bottom: "left-[calc(50%-24px)] top-[-24px]",
|
|
1997
|
-
},
|
|
1998
|
-
},
|
|
1999
|
-
defaultVariants: {
|
|
2000
|
-
position: "left",
|
|
2001
|
-
},
|
|
2002
|
-
});
|
|
2003
|
-
const cvaToogleButton = cssClassVarianceUtilities.cvaMerge([
|
|
2004
|
-
"flex",
|
|
2005
|
-
"cursor-pointer",
|
|
2006
|
-
"items-center",
|
|
2007
|
-
"justify-center",
|
|
2008
|
-
"border-gray-300",
|
|
2009
|
-
"bg-neutral-50",
|
|
2010
|
-
"bg-center",
|
|
2011
|
-
"bg-no-repeat",
|
|
2012
|
-
"shadow-md",
|
|
2013
|
-
], {
|
|
2014
|
-
variants: {
|
|
2015
|
-
position: {
|
|
2016
|
-
left: "h-12 w-6 rounded-r-lg",
|
|
2017
|
-
right: "h-12 w-6 rounded-l-lg",
|
|
2018
|
-
top: "h-6 w-12 rounded-b-lg",
|
|
2019
|
-
bottom: "h-6 w-12 rounded-t-lg",
|
|
2020
|
-
},
|
|
2021
|
-
},
|
|
2022
|
-
defaultVariants: {
|
|
2023
|
-
position: "left",
|
|
2024
|
-
},
|
|
2025
|
-
});
|
|
2026
|
-
const cvaOverlayContainer = cssClassVarianceUtilities.cvaMerge([
|
|
2027
|
-
"absolute",
|
|
2028
|
-
"flex",
|
|
2029
|
-
"items-center",
|
|
2030
|
-
"justify-center",
|
|
2031
|
-
"inset-0",
|
|
2032
|
-
"bg-black/30",
|
|
2033
|
-
"bg-opacity-50",
|
|
2034
|
-
"transition-opacity",
|
|
2035
|
-
"duration-200",
|
|
2036
|
-
"ease-in-out",
|
|
2037
|
-
"opacity-100",
|
|
2038
|
-
], {
|
|
2039
|
-
variants: {
|
|
2040
|
-
open: {
|
|
2041
|
-
true: "opacity-1 z-popover",
|
|
2042
|
-
false: "z-[-1] opacity-0",
|
|
2043
|
-
},
|
|
2044
|
-
},
|
|
2045
|
-
});
|
|
2046
|
-
|
|
2047
|
-
/**
|
|
2048
|
-
* Overlay Component
|
|
2049
|
-
*
|
|
2050
|
-
* @param {object} props - The Overlay component properties
|
|
2051
|
-
* @param {boolean} props.open - Open status of the Overlay
|
|
2052
|
-
* @param {Function} props.onClose - Callback function when Overlay is closed
|
|
2053
|
-
* @returns {JSX.Element|null} The Overlay component
|
|
2054
|
-
*/
|
|
2055
|
-
const Overlay = ({ open, onClose }) => {
|
|
2056
|
-
React.useEffect(() => {
|
|
2057
|
-
if (!onClose) {
|
|
2058
|
-
return;
|
|
2059
|
-
}
|
|
2060
|
-
const handleEscape = (event) => {
|
|
2061
|
-
if (event.key === "Escape") {
|
|
2062
|
-
onClose(event);
|
|
2063
|
-
}
|
|
2064
|
-
};
|
|
2065
|
-
if (open) {
|
|
2066
|
-
window.addEventListener("keyup", handleEscape);
|
|
2067
|
-
}
|
|
2068
|
-
return () => {
|
|
2069
|
-
window.removeEventListener("keyup", handleEscape);
|
|
2070
|
-
};
|
|
2071
|
-
}, [open, onClose]);
|
|
2072
|
-
const handleClick = (event) => {
|
|
2073
|
-
if (onClose) {
|
|
2074
|
-
onClose(event);
|
|
2075
|
-
}
|
|
2076
|
-
};
|
|
2077
|
-
return (jsxRuntime.jsx("div", { "aria-hidden": open, className: cvaOverlayContainer({ open }), "data-testid": "sidebar-overlay", onClick: handleClick }));
|
|
2078
|
-
};
|
|
2079
|
-
|
|
2080
|
-
const getIconName = (open, position) => {
|
|
2081
|
-
switch (position) {
|
|
2082
|
-
case "left":
|
|
2083
|
-
return open ? "ChevronLeft" : "ChevronRight";
|
|
2084
|
-
case "right":
|
|
2085
|
-
return open ? "ChevronRight" : "ChevronLeft";
|
|
2086
|
-
case "top":
|
|
2087
|
-
return open ? "ChevronUp" : "ChevronDown";
|
|
2088
|
-
case "bottom":
|
|
2089
|
-
return open ? "ChevronDown" : "ChevronUp";
|
|
2090
|
-
default:
|
|
2091
|
-
return open ? "ChevronLeft" : "ChevronRight";
|
|
2092
|
-
}
|
|
2093
|
-
};
|
|
2094
|
-
/**
|
|
2095
|
-
* ToggleButton is a React functional component that returns a button with a chevron icon.
|
|
2096
|
-
* The direction of the chevron changes depending on the state of the 'open' prop and
|
|
2097
|
-
* the side the button is positioned ('position' prop).
|
|
2098
|
-
* The button might be disabled based on the 'disableButton' prop.
|
|
2099
|
-
*
|
|
2100
|
-
* @param {object} props - The properties passed to the component
|
|
2101
|
-
* @param {boolean} props.open - Indicates if the button is in "open" state
|
|
2102
|
-
* @param {Function} [props.onToggle] - Optional callback function for when the button is clicked
|
|
2103
|
-
* @param {Position} props.position - The position of the button relative to its container
|
|
2104
|
-
*/
|
|
2105
|
-
const ToogleButton = ({ open, position, onToggle }) => {
|
|
2106
|
-
const name = getIconName(open, position);
|
|
2107
|
-
return (jsxRuntime.jsx("div", { className: cvaToogleContainer({ position }), children: jsxRuntime.jsx("button", { className: cvaToogleButton({ position }), "data-testid": "toggle-button", onClick: onToggle, children: jsxRuntime.jsx(Icon, { name: name }) }) }));
|
|
2108
|
-
};
|
|
2109
|
-
|
|
2110
|
-
/**
|
|
2111
|
-
* MapSidebar is a sidebar component used with Maps.
|
|
2112
|
-
* It provides a slide over sidebar drawer which can be used for displaying map related information or controls.
|
|
2113
|
-
*
|
|
2114
|
-
* @param {DrawerProps} props - The props for the MapSidebar component
|
|
2115
|
-
* @returns {JSX.Element | null} Drawer component
|
|
2116
|
-
*/
|
|
2117
|
-
const Drawer = ({ open = true, onToggle, onClose, disableOverlay, position = "left", children, dataTestId, className, dialogClassName, }) => {
|
|
2118
|
-
const { width } = useResize();
|
|
2119
|
-
const isLargeScreen = width >= 1024;
|
|
2120
|
-
const initialSidebarMode = () => {
|
|
2121
|
-
if (!open) {
|
|
2122
|
-
return "closed";
|
|
2123
|
-
}
|
|
2124
|
-
return isLargeScreen ? "full" : "2/3";
|
|
2125
|
-
};
|
|
2126
|
-
const [sidebarMode, setSidebarMode] = React.useState(initialSidebarMode);
|
|
2127
|
-
const [isVisible, setIsVisible] = React.useState(open);
|
|
2128
|
-
const [isAnimationStart, setStartAnimation] = React.useState(open);
|
|
2129
|
-
React.useEffect(() => {
|
|
2130
|
-
if (!isLargeScreen && open) {
|
|
2131
|
-
setSidebarMode("2/3");
|
|
2132
|
-
}
|
|
2133
|
-
if (onToggle) {
|
|
2134
|
-
setStartAnimation(open);
|
|
2135
|
-
return;
|
|
2136
|
-
}
|
|
2137
|
-
manageVisibilityAndAnimation(open);
|
|
2138
|
-
}, [onToggle, isLargeScreen, open]);
|
|
2139
|
-
const manageVisibilityAndAnimation = (isOpen) => {
|
|
2140
|
-
if (!isOpen) {
|
|
2141
|
-
setStartAnimation(false);
|
|
2142
|
-
return;
|
|
2143
|
-
}
|
|
2144
|
-
setIsVisible(true);
|
|
2145
|
-
setTimeout(() => {
|
|
2146
|
-
setStartAnimation(true);
|
|
2147
|
-
}, 150);
|
|
2148
|
-
};
|
|
2149
|
-
const handlers = reactSwipeable.useSwipeable({
|
|
2150
|
-
onSwipedUp: () => !isLargeScreen && handleSwipedUp(),
|
|
2151
|
-
onSwipedDown: () => !isLargeScreen && handleSwipedDown(),
|
|
2152
|
-
trackMouse: true,
|
|
2153
|
-
});
|
|
2154
|
-
const handleSwipedUp = () => {
|
|
2155
|
-
setSidebarMode(prev => {
|
|
2156
|
-
switch (prev) {
|
|
2157
|
-
case "semi-closed":
|
|
2158
|
-
return "1/3";
|
|
2159
|
-
case "1/3":
|
|
2160
|
-
return "2/3";
|
|
2161
|
-
case "2/3":
|
|
2162
|
-
return "semi-full";
|
|
2163
|
-
default:
|
|
2164
|
-
return prev;
|
|
2165
|
-
}
|
|
2166
|
-
});
|
|
2167
|
-
};
|
|
2168
|
-
const handleSwipedDown = () => {
|
|
2169
|
-
setSidebarMode(prev => {
|
|
2170
|
-
switch (prev) {
|
|
2171
|
-
case "semi-full":
|
|
2172
|
-
return "2/3";
|
|
2173
|
-
case "2/3":
|
|
2174
|
-
return "1/3";
|
|
2175
|
-
case "1/3":
|
|
2176
|
-
return onClose ? "closed" : "semi-closed";
|
|
2177
|
-
default:
|
|
2178
|
-
return prev;
|
|
2179
|
-
}
|
|
2180
|
-
});
|
|
2181
|
-
/*
|
|
2182
|
-
* Within a mobile device context, when swiping down,
|
|
2183
|
-
* if the Drawer is open a third and no onToggle function is provided,
|
|
2184
|
-
* the Drawer will automatically be closed using the onClose function.
|
|
2185
|
-
*/
|
|
2186
|
-
if (sidebarMode === "1/3" && !onToggle && onClose) {
|
|
2187
|
-
onClose();
|
|
2188
|
-
}
|
|
2189
|
-
};
|
|
2190
|
-
const handleAnimationEnd = () => {
|
|
2191
|
-
if (!open && !onToggle) {
|
|
2192
|
-
setIsVisible(false);
|
|
2193
|
-
}
|
|
2194
|
-
};
|
|
2195
|
-
if (!isVisible && !onToggle) {
|
|
2196
|
-
return null;
|
|
2197
|
-
}
|
|
2198
|
-
return (jsxRuntime.jsxs("div", { className: className, "data-testid": dataTestId, children: [!disableOverlay ? jsxRuntime.jsx(Overlay, { onClose: onClose, open: isAnimationStart }) : null, jsxRuntime.jsxs("div", { ...handlers, className: cvaDialog({
|
|
2199
|
-
sidebarMode: isLargeScreen ? null : sidebarMode,
|
|
2200
|
-
isLargeScreen,
|
|
2201
|
-
open: isAnimationStart,
|
|
2202
|
-
position: isLargeScreen ? position : undefined,
|
|
2203
|
-
className: dialogClassName,
|
|
2204
|
-
}), "data-testid": dataTestId ? `${dataTestId}-container` : undefined, onTransitionEnd: handleAnimationEnd, children: [isLargeScreen && onToggle ? jsxRuntime.jsx(ToogleButton, { onToggle: onToggle, open: open, position: position }) : null, jsxRuntime.jsxs("div", { className: cvaDialogContainer({
|
|
2205
|
-
sidebarMode: isLargeScreen ? "full" : sidebarMode,
|
|
2206
|
-
}), children: [jsxRuntime.jsx("div", { className: cvaSwipeContainer(), children: jsxRuntime.jsx("div", { className: cvaSwipeIcon() }) }), children] })] })] }));
|
|
2207
|
-
};
|
|
2208
|
-
|
|
2209
1939
|
const cvaSkeletonLine = cssClassVarianceUtilities.cvaMerge([
|
|
2210
1940
|
"rounded-md",
|
|
2211
1941
|
"h-3",
|
|
@@ -5164,7 +4894,6 @@ exports.CardHeader = CardHeader;
|
|
|
5164
4894
|
exports.Collapse = Collapse;
|
|
5165
4895
|
exports.CompletionStatusIndicator = CompletionStatusIndicator;
|
|
5166
4896
|
exports.CopyableText = CopyableText;
|
|
5167
|
-
exports.Drawer = Drawer;
|
|
5168
4897
|
exports.EmptyState = EmptyState;
|
|
5169
4898
|
exports.EmptyValue = EmptyValue;
|
|
5170
4899
|
exports.ExternalLink = ExternalLink;
|
|
@@ -5250,6 +4979,7 @@ exports.usePopoverContext = usePopoverContext;
|
|
|
5250
4979
|
exports.usePrevious = usePrevious;
|
|
5251
4980
|
exports.usePrompt = usePrompt;
|
|
5252
4981
|
exports.useResize = useResize;
|
|
4982
|
+
exports.useScrollDetection = useScrollDetection;
|
|
5253
4983
|
exports.useSelfUpdatingRef = useSelfUpdatingRef;
|
|
5254
4984
|
exports.useTimeout = useTimeout;
|
|
5255
4985
|
exports.useViewportSize = useViewportSize;
|
package/index.esm.js
CHANGED
|
@@ -12,9 +12,8 @@ import { snakeCase, titleCase } from 'string-ts';
|
|
|
12
12
|
import { cvaMerge } from '@trackunit/css-class-variance-utilities';
|
|
13
13
|
import { Slottable, Slot } from '@radix-ui/react-slot';
|
|
14
14
|
import isEqual from 'lodash/isEqual';
|
|
15
|
+
import { useDebounceCallback, useCopyToClipboard } from 'usehooks-ts';
|
|
15
16
|
import { Link, useBlocker } from '@tanstack/react-router';
|
|
16
|
-
import { useCopyToClipboard } from 'usehooks-ts';
|
|
17
|
-
import { useSwipeable } from 'react-swipeable';
|
|
18
17
|
import { useFloating, autoUpdate, offset, flip, shift, size, useClick, useDismiss, useHover as useHover$1, useRole, useInteractions, useMergeRefs, FloatingPortal, FloatingFocusManager, arrow, useTransitionStatus, FloatingArrow } from '@floating-ui/react';
|
|
19
18
|
import omit from 'lodash/omit';
|
|
20
19
|
import { twMerge } from 'tailwind-merge';
|
|
@@ -1290,6 +1289,62 @@ const getWindowSize = () => {
|
|
|
1290
1289
|
}
|
|
1291
1290
|
};
|
|
1292
1291
|
|
|
1292
|
+
const SCROLL_DEBOUNCE_TIME = 50;
|
|
1293
|
+
/**
|
|
1294
|
+
* Hook for getting detecting scroll values.
|
|
1295
|
+
*
|
|
1296
|
+
* @param {useRef} elementRef - Ref hook holding the element that needs to be observed during scrolling
|
|
1297
|
+
* @returns {object} An object containing if the element is scrollable, is at the top, is at the bottom, and its current scroll position.
|
|
1298
|
+
*/
|
|
1299
|
+
const useScrollDetection = (elementRef) => {
|
|
1300
|
+
const [isScrollable, setIsScrollable] = useState(false);
|
|
1301
|
+
const [isAtTop, setIsAtTop] = useState(true);
|
|
1302
|
+
const [isAtBottom, setIsAtBottom] = useState(false);
|
|
1303
|
+
const [scrollPosition, setScrollPosition] = useState({ top: 0, bottom: 0 });
|
|
1304
|
+
const observerRef = useRef();
|
|
1305
|
+
const checkScrollable = useCallback(() => {
|
|
1306
|
+
const element = elementRef.current;
|
|
1307
|
+
if (!element) {
|
|
1308
|
+
return;
|
|
1309
|
+
}
|
|
1310
|
+
const hasOverflow = element.scrollHeight > element.clientHeight;
|
|
1311
|
+
setIsScrollable(hasOverflow);
|
|
1312
|
+
}, [elementRef]);
|
|
1313
|
+
const checkScrollPosition = useCallback(() => {
|
|
1314
|
+
const element = elementRef.current;
|
|
1315
|
+
if (!element) {
|
|
1316
|
+
return;
|
|
1317
|
+
}
|
|
1318
|
+
const { scrollTop, scrollHeight, clientHeight } = element;
|
|
1319
|
+
setIsAtTop(scrollTop === 0);
|
|
1320
|
+
setIsAtBottom(Math.abs(scrollHeight - scrollTop - clientHeight) < 1);
|
|
1321
|
+
setScrollPosition(prev => ({ ...prev, top: scrollTop, bottom: clientHeight - scrollTop }));
|
|
1322
|
+
}, [elementRef]);
|
|
1323
|
+
const debouncedCheckScrollPosition = useDebounceCallback(checkScrollPosition, SCROLL_DEBOUNCE_TIME);
|
|
1324
|
+
useEffect(() => {
|
|
1325
|
+
const element = elementRef.current;
|
|
1326
|
+
if (!element) {
|
|
1327
|
+
return;
|
|
1328
|
+
}
|
|
1329
|
+
// Initial checks
|
|
1330
|
+
checkScrollable();
|
|
1331
|
+
checkScrollPosition();
|
|
1332
|
+
observerRef.current = new ResizeObserver(() => {
|
|
1333
|
+
checkScrollable();
|
|
1334
|
+
checkScrollPosition();
|
|
1335
|
+
});
|
|
1336
|
+
observerRef.current.observe(element);
|
|
1337
|
+
element.addEventListener("scroll", debouncedCheckScrollPosition);
|
|
1338
|
+
return () => {
|
|
1339
|
+
if (observerRef.current) {
|
|
1340
|
+
observerRef.current.disconnect();
|
|
1341
|
+
}
|
|
1342
|
+
element.removeEventListener("scroll", debouncedCheckScrollPosition);
|
|
1343
|
+
};
|
|
1344
|
+
}, [elementRef, checkScrollable, checkScrollPosition, debouncedCheckScrollPosition]);
|
|
1345
|
+
return { isScrollable, isAtTop, isAtBottom, scrollPosition };
|
|
1346
|
+
};
|
|
1347
|
+
|
|
1293
1348
|
/**
|
|
1294
1349
|
* A useRef that updates its given value whenever it changes.
|
|
1295
1350
|
*
|
|
@@ -1861,331 +1916,6 @@ const CopyableText = ({ text, alternativeText, dataTestId, className }) => {
|
|
|
1861
1916
|
return (jsx("span", { className: cvaCopyableText({ animating, className }), "data-testid": dataTestId, onAnimationEnd: () => setAnimating(false), onClick: handleOnClick, title: value, children: text }));
|
|
1862
1917
|
};
|
|
1863
1918
|
|
|
1864
|
-
const cvaDialog = cvaMerge([
|
|
1865
|
-
"z-toast",
|
|
1866
|
-
"pointer-events-auto",
|
|
1867
|
-
"absolute",
|
|
1868
|
-
"transform",
|
|
1869
|
-
"flex-col",
|
|
1870
|
-
"bg-neutral-50",
|
|
1871
|
-
"transition-transform",
|
|
1872
|
-
"duration-300",
|
|
1873
|
-
"ease-in-out",
|
|
1874
|
-
"shadow-lg",
|
|
1875
|
-
], {
|
|
1876
|
-
variants: {
|
|
1877
|
-
position: {
|
|
1878
|
-
left: "left-0 top-0 h-full w-fit rounded-r-lg",
|
|
1879
|
-
right: "right-0 top-0 h-full w-fit rounded-l-lg",
|
|
1880
|
-
top: "left-0 top-0 h-fit w-full rounded-b-lg",
|
|
1881
|
-
bottom: "bottom-0 left-0 right-0 h-fit w-full rounded-t-lg",
|
|
1882
|
-
},
|
|
1883
|
-
sidebarMode: {
|
|
1884
|
-
"semi-closed": "translate-y-[calc(100%-2.2rem)]",
|
|
1885
|
-
"1/3": "translate-y-2/3",
|
|
1886
|
-
"2/3": "translate-y-1/3",
|
|
1887
|
-
full: "translate-y-0",
|
|
1888
|
-
"semi-full": "translate-y-5",
|
|
1889
|
-
closed: "translate-y-full",
|
|
1890
|
-
},
|
|
1891
|
-
isLargeScreen: {
|
|
1892
|
-
true: "",
|
|
1893
|
-
false: "bottom-0 left-0 right-0 h-full w-full rounded-t-lg",
|
|
1894
|
-
},
|
|
1895
|
-
open: {
|
|
1896
|
-
true: "",
|
|
1897
|
-
false: "",
|
|
1898
|
-
},
|
|
1899
|
-
},
|
|
1900
|
-
compoundVariants: [
|
|
1901
|
-
{
|
|
1902
|
-
isLargeScreen: false,
|
|
1903
|
-
open: false,
|
|
1904
|
-
className: "translate-y-full",
|
|
1905
|
-
},
|
|
1906
|
-
{
|
|
1907
|
-
isLargeScreen: true,
|
|
1908
|
-
open: true,
|
|
1909
|
-
position: "left",
|
|
1910
|
-
className: "translate-x-0",
|
|
1911
|
-
},
|
|
1912
|
-
{
|
|
1913
|
-
isLargeScreen: true,
|
|
1914
|
-
open: false,
|
|
1915
|
-
position: "left",
|
|
1916
|
-
className: "-translate-x-full",
|
|
1917
|
-
},
|
|
1918
|
-
{
|
|
1919
|
-
isLargeScreen: true,
|
|
1920
|
-
open: true,
|
|
1921
|
-
position: "right",
|
|
1922
|
-
className: "translate-x-0",
|
|
1923
|
-
},
|
|
1924
|
-
{
|
|
1925
|
-
isLargeScreen: true,
|
|
1926
|
-
open: false,
|
|
1927
|
-
position: "right",
|
|
1928
|
-
className: "translate-x-full",
|
|
1929
|
-
},
|
|
1930
|
-
{
|
|
1931
|
-
isLargeScreen: true,
|
|
1932
|
-
open: true,
|
|
1933
|
-
position: "top",
|
|
1934
|
-
className: "translate-y-0",
|
|
1935
|
-
},
|
|
1936
|
-
{
|
|
1937
|
-
isLargeScreen: true,
|
|
1938
|
-
open: false,
|
|
1939
|
-
position: "top",
|
|
1940
|
-
className: "-translate-y-full",
|
|
1941
|
-
},
|
|
1942
|
-
{
|
|
1943
|
-
isLargeScreen: true,
|
|
1944
|
-
open: true,
|
|
1945
|
-
position: "bottom",
|
|
1946
|
-
className: "translate-y-0",
|
|
1947
|
-
},
|
|
1948
|
-
{
|
|
1949
|
-
isLargeScreen: true,
|
|
1950
|
-
open: false,
|
|
1951
|
-
position: "bottom",
|
|
1952
|
-
className: "translate-y-full",
|
|
1953
|
-
},
|
|
1954
|
-
],
|
|
1955
|
-
});
|
|
1956
|
-
const cvaDialogContainer = cvaMerge(["flex", "flex-col", "overflow-hidden", "rounded-[inherit]"], {
|
|
1957
|
-
variants: {
|
|
1958
|
-
sidebarMode: {
|
|
1959
|
-
"semi-closed": "h-auto",
|
|
1960
|
-
"1/3": "h-[34%]",
|
|
1961
|
-
"2/3": "h-[67%]",
|
|
1962
|
-
"semi-full": "h-[calc(100%-1.25rem)]",
|
|
1963
|
-
full: "h-full",
|
|
1964
|
-
closed: "h-auto",
|
|
1965
|
-
},
|
|
1966
|
-
},
|
|
1967
|
-
});
|
|
1968
|
-
const cvaSwipeContainer = cvaMerge(["my-4", "flex", "items-center", "justify-center", "lg:hidden"]);
|
|
1969
|
-
const cvaSwipeIcon = cvaMerge(["block", "h-1", "w-10", "rounded-full", "bg-gray-400"]);
|
|
1970
|
-
const cvaToogleContainer = cvaMerge(["z-8", "absolute"], {
|
|
1971
|
-
variants: {
|
|
1972
|
-
position: {
|
|
1973
|
-
left: "right-[-24px] top-[calc(50%-24px)]",
|
|
1974
|
-
right: "left-[-24px] top-[calc(50%-24px)]",
|
|
1975
|
-
top: "bottom-[-24px] left-[calc(50%-24px)]",
|
|
1976
|
-
bottom: "left-[calc(50%-24px)] top-[-24px]",
|
|
1977
|
-
},
|
|
1978
|
-
},
|
|
1979
|
-
defaultVariants: {
|
|
1980
|
-
position: "left",
|
|
1981
|
-
},
|
|
1982
|
-
});
|
|
1983
|
-
const cvaToogleButton = cvaMerge([
|
|
1984
|
-
"flex",
|
|
1985
|
-
"cursor-pointer",
|
|
1986
|
-
"items-center",
|
|
1987
|
-
"justify-center",
|
|
1988
|
-
"border-gray-300",
|
|
1989
|
-
"bg-neutral-50",
|
|
1990
|
-
"bg-center",
|
|
1991
|
-
"bg-no-repeat",
|
|
1992
|
-
"shadow-md",
|
|
1993
|
-
], {
|
|
1994
|
-
variants: {
|
|
1995
|
-
position: {
|
|
1996
|
-
left: "h-12 w-6 rounded-r-lg",
|
|
1997
|
-
right: "h-12 w-6 rounded-l-lg",
|
|
1998
|
-
top: "h-6 w-12 rounded-b-lg",
|
|
1999
|
-
bottom: "h-6 w-12 rounded-t-lg",
|
|
2000
|
-
},
|
|
2001
|
-
},
|
|
2002
|
-
defaultVariants: {
|
|
2003
|
-
position: "left",
|
|
2004
|
-
},
|
|
2005
|
-
});
|
|
2006
|
-
const cvaOverlayContainer = cvaMerge([
|
|
2007
|
-
"absolute",
|
|
2008
|
-
"flex",
|
|
2009
|
-
"items-center",
|
|
2010
|
-
"justify-center",
|
|
2011
|
-
"inset-0",
|
|
2012
|
-
"bg-black/30",
|
|
2013
|
-
"bg-opacity-50",
|
|
2014
|
-
"transition-opacity",
|
|
2015
|
-
"duration-200",
|
|
2016
|
-
"ease-in-out",
|
|
2017
|
-
"opacity-100",
|
|
2018
|
-
], {
|
|
2019
|
-
variants: {
|
|
2020
|
-
open: {
|
|
2021
|
-
true: "opacity-1 z-popover",
|
|
2022
|
-
false: "z-[-1] opacity-0",
|
|
2023
|
-
},
|
|
2024
|
-
},
|
|
2025
|
-
});
|
|
2026
|
-
|
|
2027
|
-
/**
|
|
2028
|
-
* Overlay Component
|
|
2029
|
-
*
|
|
2030
|
-
* @param {object} props - The Overlay component properties
|
|
2031
|
-
* @param {boolean} props.open - Open status of the Overlay
|
|
2032
|
-
* @param {Function} props.onClose - Callback function when Overlay is closed
|
|
2033
|
-
* @returns {JSX.Element|null} The Overlay component
|
|
2034
|
-
*/
|
|
2035
|
-
const Overlay = ({ open, onClose }) => {
|
|
2036
|
-
useEffect(() => {
|
|
2037
|
-
if (!onClose) {
|
|
2038
|
-
return;
|
|
2039
|
-
}
|
|
2040
|
-
const handleEscape = (event) => {
|
|
2041
|
-
if (event.key === "Escape") {
|
|
2042
|
-
onClose(event);
|
|
2043
|
-
}
|
|
2044
|
-
};
|
|
2045
|
-
if (open) {
|
|
2046
|
-
window.addEventListener("keyup", handleEscape);
|
|
2047
|
-
}
|
|
2048
|
-
return () => {
|
|
2049
|
-
window.removeEventListener("keyup", handleEscape);
|
|
2050
|
-
};
|
|
2051
|
-
}, [open, onClose]);
|
|
2052
|
-
const handleClick = (event) => {
|
|
2053
|
-
if (onClose) {
|
|
2054
|
-
onClose(event);
|
|
2055
|
-
}
|
|
2056
|
-
};
|
|
2057
|
-
return (jsx("div", { "aria-hidden": open, className: cvaOverlayContainer({ open }), "data-testid": "sidebar-overlay", onClick: handleClick }));
|
|
2058
|
-
};
|
|
2059
|
-
|
|
2060
|
-
const getIconName = (open, position) => {
|
|
2061
|
-
switch (position) {
|
|
2062
|
-
case "left":
|
|
2063
|
-
return open ? "ChevronLeft" : "ChevronRight";
|
|
2064
|
-
case "right":
|
|
2065
|
-
return open ? "ChevronRight" : "ChevronLeft";
|
|
2066
|
-
case "top":
|
|
2067
|
-
return open ? "ChevronUp" : "ChevronDown";
|
|
2068
|
-
case "bottom":
|
|
2069
|
-
return open ? "ChevronDown" : "ChevronUp";
|
|
2070
|
-
default:
|
|
2071
|
-
return open ? "ChevronLeft" : "ChevronRight";
|
|
2072
|
-
}
|
|
2073
|
-
};
|
|
2074
|
-
/**
|
|
2075
|
-
* ToggleButton is a React functional component that returns a button with a chevron icon.
|
|
2076
|
-
* The direction of the chevron changes depending on the state of the 'open' prop and
|
|
2077
|
-
* the side the button is positioned ('position' prop).
|
|
2078
|
-
* The button might be disabled based on the 'disableButton' prop.
|
|
2079
|
-
*
|
|
2080
|
-
* @param {object} props - The properties passed to the component
|
|
2081
|
-
* @param {boolean} props.open - Indicates if the button is in "open" state
|
|
2082
|
-
* @param {Function} [props.onToggle] - Optional callback function for when the button is clicked
|
|
2083
|
-
* @param {Position} props.position - The position of the button relative to its container
|
|
2084
|
-
*/
|
|
2085
|
-
const ToogleButton = ({ open, position, onToggle }) => {
|
|
2086
|
-
const name = getIconName(open, position);
|
|
2087
|
-
return (jsx("div", { className: cvaToogleContainer({ position }), children: jsx("button", { className: cvaToogleButton({ position }), "data-testid": "toggle-button", onClick: onToggle, children: jsx(Icon, { name: name }) }) }));
|
|
2088
|
-
};
|
|
2089
|
-
|
|
2090
|
-
/**
|
|
2091
|
-
* MapSidebar is a sidebar component used with Maps.
|
|
2092
|
-
* It provides a slide over sidebar drawer which can be used for displaying map related information or controls.
|
|
2093
|
-
*
|
|
2094
|
-
* @param {DrawerProps} props - The props for the MapSidebar component
|
|
2095
|
-
* @returns {JSX.Element | null} Drawer component
|
|
2096
|
-
*/
|
|
2097
|
-
const Drawer = ({ open = true, onToggle, onClose, disableOverlay, position = "left", children, dataTestId, className, dialogClassName, }) => {
|
|
2098
|
-
const { width } = useResize();
|
|
2099
|
-
const isLargeScreen = width >= 1024;
|
|
2100
|
-
const initialSidebarMode = () => {
|
|
2101
|
-
if (!open) {
|
|
2102
|
-
return "closed";
|
|
2103
|
-
}
|
|
2104
|
-
return isLargeScreen ? "full" : "2/3";
|
|
2105
|
-
};
|
|
2106
|
-
const [sidebarMode, setSidebarMode] = useState(initialSidebarMode);
|
|
2107
|
-
const [isVisible, setIsVisible] = useState(open);
|
|
2108
|
-
const [isAnimationStart, setStartAnimation] = useState(open);
|
|
2109
|
-
useEffect(() => {
|
|
2110
|
-
if (!isLargeScreen && open) {
|
|
2111
|
-
setSidebarMode("2/3");
|
|
2112
|
-
}
|
|
2113
|
-
if (onToggle) {
|
|
2114
|
-
setStartAnimation(open);
|
|
2115
|
-
return;
|
|
2116
|
-
}
|
|
2117
|
-
manageVisibilityAndAnimation(open);
|
|
2118
|
-
}, [onToggle, isLargeScreen, open]);
|
|
2119
|
-
const manageVisibilityAndAnimation = (isOpen) => {
|
|
2120
|
-
if (!isOpen) {
|
|
2121
|
-
setStartAnimation(false);
|
|
2122
|
-
return;
|
|
2123
|
-
}
|
|
2124
|
-
setIsVisible(true);
|
|
2125
|
-
setTimeout(() => {
|
|
2126
|
-
setStartAnimation(true);
|
|
2127
|
-
}, 150);
|
|
2128
|
-
};
|
|
2129
|
-
const handlers = useSwipeable({
|
|
2130
|
-
onSwipedUp: () => !isLargeScreen && handleSwipedUp(),
|
|
2131
|
-
onSwipedDown: () => !isLargeScreen && handleSwipedDown(),
|
|
2132
|
-
trackMouse: true,
|
|
2133
|
-
});
|
|
2134
|
-
const handleSwipedUp = () => {
|
|
2135
|
-
setSidebarMode(prev => {
|
|
2136
|
-
switch (prev) {
|
|
2137
|
-
case "semi-closed":
|
|
2138
|
-
return "1/3";
|
|
2139
|
-
case "1/3":
|
|
2140
|
-
return "2/3";
|
|
2141
|
-
case "2/3":
|
|
2142
|
-
return "semi-full";
|
|
2143
|
-
default:
|
|
2144
|
-
return prev;
|
|
2145
|
-
}
|
|
2146
|
-
});
|
|
2147
|
-
};
|
|
2148
|
-
const handleSwipedDown = () => {
|
|
2149
|
-
setSidebarMode(prev => {
|
|
2150
|
-
switch (prev) {
|
|
2151
|
-
case "semi-full":
|
|
2152
|
-
return "2/3";
|
|
2153
|
-
case "2/3":
|
|
2154
|
-
return "1/3";
|
|
2155
|
-
case "1/3":
|
|
2156
|
-
return onClose ? "closed" : "semi-closed";
|
|
2157
|
-
default:
|
|
2158
|
-
return prev;
|
|
2159
|
-
}
|
|
2160
|
-
});
|
|
2161
|
-
/*
|
|
2162
|
-
* Within a mobile device context, when swiping down,
|
|
2163
|
-
* if the Drawer is open a third and no onToggle function is provided,
|
|
2164
|
-
* the Drawer will automatically be closed using the onClose function.
|
|
2165
|
-
*/
|
|
2166
|
-
if (sidebarMode === "1/3" && !onToggle && onClose) {
|
|
2167
|
-
onClose();
|
|
2168
|
-
}
|
|
2169
|
-
};
|
|
2170
|
-
const handleAnimationEnd = () => {
|
|
2171
|
-
if (!open && !onToggle) {
|
|
2172
|
-
setIsVisible(false);
|
|
2173
|
-
}
|
|
2174
|
-
};
|
|
2175
|
-
if (!isVisible && !onToggle) {
|
|
2176
|
-
return null;
|
|
2177
|
-
}
|
|
2178
|
-
return (jsxs("div", { className: className, "data-testid": dataTestId, children: [!disableOverlay ? jsx(Overlay, { onClose: onClose, open: isAnimationStart }) : null, jsxs("div", { ...handlers, className: cvaDialog({
|
|
2179
|
-
sidebarMode: isLargeScreen ? null : sidebarMode,
|
|
2180
|
-
isLargeScreen,
|
|
2181
|
-
open: isAnimationStart,
|
|
2182
|
-
position: isLargeScreen ? position : undefined,
|
|
2183
|
-
className: dialogClassName,
|
|
2184
|
-
}), "data-testid": dataTestId ? `${dataTestId}-container` : undefined, onTransitionEnd: handleAnimationEnd, children: [isLargeScreen && onToggle ? jsx(ToogleButton, { onToggle: onToggle, open: open, position: position }) : null, jsxs("div", { className: cvaDialogContainer({
|
|
2185
|
-
sidebarMode: isLargeScreen ? "full" : sidebarMode,
|
|
2186
|
-
}), children: [jsx("div", { className: cvaSwipeContainer(), children: jsx("div", { className: cvaSwipeIcon() }) }), children] })] })] }));
|
|
2187
|
-
};
|
|
2188
|
-
|
|
2189
1919
|
const cvaSkeletonLine = cvaMerge([
|
|
2190
1920
|
"rounded-md",
|
|
2191
1921
|
"h-3",
|
|
@@ -5132,4 +4862,4 @@ const cvaClickable = cvaMerge([
|
|
|
5132
4862
|
},
|
|
5133
4863
|
});
|
|
5134
4864
|
|
|
5135
|
-
export { Alert, Badge, Breadcrumb, BreadcrumbContainer, Button, Card, CardBody, CardFooter, CardHeader, Collapse, CompletionStatusIndicator, CopyableText,
|
|
4865
|
+
export { Alert, Badge, Breadcrumb, BreadcrumbContainer, Button, Card, CardBody, CardFooter, CardHeader, Collapse, CompletionStatusIndicator, CopyableText, EmptyState, EmptyValue, ExternalLink, Heading, Icon, IconButton, Indicator, KPICard, MenuDivider, MenuItem, MenuList, MoreMenu, Notice, PackageNameStoryComponent, Page, PageContent, PageHeader, Pagination, Polygon, Popover, PopoverContent, PopoverTitle, PopoverTrigger, Prompt, ROLE_CARD, SectionHeader, Sidebar, SkeletonLines, Spacer, Spinner, StarButton, Tab, TabContent, TabList, Tabs, Tag, Text, Timeline, TimelineElement, ToggleGroup, ToggleItem, Tooltip, ValueBar, VirtualizedList, WidgetBody, cvaButton, cvaButtonPrefixSuffix, cvaButtonSpinner, cvaButtonSpinnerContainer, cvaClickable, cvaIconButton, cvaIndicator, cvaIndicatorIcon, cvaIndicatorIconBackground, cvaIndicatorLabel, cvaIndicatorPing, cvaInteractableItem, cvaMenuItem, cvaMenuItemLabel, cvaMenuItemPrefix, cvaMenuItemStyle, cvaMenuItemSuffix, docs, getDevicePixelRatio, getValueBarColorByValue, iconColorNames, iconPalette, setLocalStorage, useClickOutside, useContinuousTimeout, useDebounce, useDevicePixelRatio, useGeometry, useHover, useIsFirstRender, useIsFullscreen, useIsTextCutOff, useLocalStorage, useLocalStorageReducer, useOptionallyElevatedState, useOverflowItems, usePopoverContext, usePrevious, usePrompt, useResize, useScrollDetection, useSelfUpdatingRef, useTimeout, useViewportSize, useWindowActivity };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"engines": {
|
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
"@testing-library/react": "15.0.6",
|
|
24
24
|
"@floating-ui/react": "^0.26.25",
|
|
25
25
|
"@tanstack/react-router": "1.47.1",
|
|
26
|
-
"react-swipeable": "^7.0.1",
|
|
27
26
|
"string-ts": "^2.0.0",
|
|
28
27
|
"tailwind-merge": "^2.0.0",
|
|
29
28
|
"@trackunit/react-table-pagination": "*"
|
|
@@ -6,7 +6,6 @@ export * from "./Card";
|
|
|
6
6
|
export * from "./Collapse";
|
|
7
7
|
export * from "./CompletionStatusIndicator/CompletionStatusIndicator";
|
|
8
8
|
export * from "./CopyableText";
|
|
9
|
-
export * from "./Drawer";
|
|
10
9
|
export * from "./EmptyState/EmptyState";
|
|
11
10
|
export * from "./EmptyValue/EmptyValue";
|
|
12
11
|
export * from "./ExternalLink/ExternalLink";
|
|
@@ -41,4 +40,3 @@ export * from "./Tooltip";
|
|
|
41
40
|
export * from "./ValueBar";
|
|
42
41
|
export * from "./VirtualizedList/VirtualizedList";
|
|
43
42
|
export * from "./Widget";
|
|
44
|
-
export * from "./buttons";
|
package/src/hooks/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export * from "./useIsTextCutOff";
|
|
|
13
13
|
export * from "./useOptionallyElevatedState";
|
|
14
14
|
export * from "./usePrevious";
|
|
15
15
|
export * from "./useResize";
|
|
16
|
+
export * from "./useScrollDetection";
|
|
16
17
|
export * from "./useSelfUpdatingRef";
|
|
17
18
|
export * from "./useTimeout";
|
|
18
19
|
export * from "./useViewportSize";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type RefObject } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Hook for getting detecting scroll values.
|
|
4
|
+
*
|
|
5
|
+
* @param {useRef} elementRef - Ref hook holding the element that needs to be observed during scrolling
|
|
6
|
+
* @returns {object} An object containing if the element is scrollable, is at the top, is at the bottom, and its current scroll position.
|
|
7
|
+
*/
|
|
8
|
+
export declare const useScrollDetection: (elementRef: RefObject<HTMLElement>) => {
|
|
9
|
+
isScrollable: boolean;
|
|
10
|
+
isAtTop: boolean;
|
|
11
|
+
isAtBottom: boolean;
|
|
12
|
+
scrollPosition: {
|
|
13
|
+
top: number;
|
|
14
|
+
bottom: number;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { CommonProps } from "../../common";
|
|
2
|
-
export type Position = "left" | "right" | "top" | "bottom";
|
|
3
|
-
export interface DrawerProps extends CommonProps {
|
|
4
|
-
/**
|
|
5
|
-
* Specifies whether the sidebar drawer is open or not.
|
|
6
|
-
*/
|
|
7
|
-
open?: boolean;
|
|
8
|
-
/**
|
|
9
|
-
* The onClose handler for the drawer.
|
|
10
|
-
*/
|
|
11
|
-
onClose?: (event?: React.MouseEvent | KeyboardEvent) => void;
|
|
12
|
-
/**
|
|
13
|
-
* The handler for toggling the drawer state.
|
|
14
|
-
*/
|
|
15
|
-
onToggle?: (event: React.MouseEvent) => void;
|
|
16
|
-
/**
|
|
17
|
-
* Whether the drawer needs an overlay or not. Without the overlay, user will have to handle mechanism for closing the drawer.
|
|
18
|
-
*/
|
|
19
|
-
disableOverlay?: boolean;
|
|
20
|
-
/**
|
|
21
|
-
* The position of the drawer.
|
|
22
|
-
*/
|
|
23
|
-
position?: Position;
|
|
24
|
-
/**
|
|
25
|
-
* The child node that will be rendered inside the drawer.
|
|
26
|
-
*/
|
|
27
|
-
children?: React.ReactNode;
|
|
28
|
-
dialogClassName?: string;
|
|
29
|
-
}
|
|
30
|
-
/**
|
|
31
|
-
* MapSidebar is a sidebar component used with Maps.
|
|
32
|
-
* It provides a slide over sidebar drawer which can be used for displaying map related information or controls.
|
|
33
|
-
*
|
|
34
|
-
* @param {DrawerProps} props - The props for the MapSidebar component
|
|
35
|
-
* @returns {JSX.Element | null} Drawer component
|
|
36
|
-
*/
|
|
37
|
-
export declare const Drawer: ({ open, onToggle, onClose, disableOverlay, position, children, dataTestId, className, dialogClassName, }: DrawerProps) => JSX.Element | null;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
export declare const cvaDialog: (props?: ({
|
|
2
|
-
position?: "left" | "right" | "top" | "bottom" | null | undefined;
|
|
3
|
-
sidebarMode?: "semi-closed" | "1/3" | "2/3" | "full" | "semi-full" | "closed" | null | undefined;
|
|
4
|
-
isLargeScreen?: boolean | null | undefined;
|
|
5
|
-
open?: boolean | null | undefined;
|
|
6
|
-
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
7
|
-
export declare const cvaDialogContainer: (props?: ({
|
|
8
|
-
sidebarMode?: "semi-closed" | "1/3" | "2/3" | "full" | "semi-full" | "closed" | null | undefined;
|
|
9
|
-
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
10
|
-
export declare const cvaSwipeContainer: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
|
|
11
|
-
export declare const cvaSwipeIcon: (props?: import("class-variance-authority/dist/types").ClassProp | undefined) => string;
|
|
12
|
-
export declare const cvaToogleContainer: (props?: ({
|
|
13
|
-
position?: "left" | "right" | "top" | "bottom" | null | undefined;
|
|
14
|
-
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
15
|
-
export declare const cvaToogleButton: (props?: ({
|
|
16
|
-
position?: "left" | "right" | "top" | "bottom" | null | undefined;
|
|
17
|
-
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
18
|
-
export declare const cvaOverlayContainer: (props?: ({
|
|
19
|
-
open?: boolean | null | undefined;
|
|
20
|
-
} & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
interface OverlayProps {
|
|
2
|
-
open: boolean;
|
|
3
|
-
onClose?: (event: React.MouseEvent | KeyboardEvent) => void;
|
|
4
|
-
}
|
|
5
|
-
/**
|
|
6
|
-
* Overlay Component
|
|
7
|
-
*
|
|
8
|
-
* @param {object} props - The Overlay component properties
|
|
9
|
-
* @param {boolean} props.open - Open status of the Overlay
|
|
10
|
-
* @param {Function} props.onClose - Callback function when Overlay is closed
|
|
11
|
-
* @returns {JSX.Element|null} The Overlay component
|
|
12
|
-
*/
|
|
13
|
-
declare const Overlay: ({ open, onClose }: OverlayProps) => JSX.Element | null;
|
|
14
|
-
export default Overlay;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { Position } from "./Drawer";
|
|
2
|
-
interface ToogleButtonProps {
|
|
3
|
-
open: boolean;
|
|
4
|
-
onToggle?: (event: React.MouseEvent) => void;
|
|
5
|
-
position: Position;
|
|
6
|
-
}
|
|
7
|
-
/**
|
|
8
|
-
* ToggleButton is a React functional component that returns a button with a chevron icon.
|
|
9
|
-
* The direction of the chevron changes depending on the state of the 'open' prop and
|
|
10
|
-
* the side the button is positioned ('position' prop).
|
|
11
|
-
* The button might be disabled based on the 'disableButton' prop.
|
|
12
|
-
*
|
|
13
|
-
* @param {object} props - The properties passed to the component
|
|
14
|
-
* @param {boolean} props.open - Indicates if the button is in "open" state
|
|
15
|
-
* @param {Function} [props.onToggle] - Optional callback function for when the button is clicked
|
|
16
|
-
* @param {Position} props.position - The position of the button relative to its container
|
|
17
|
-
*/
|
|
18
|
-
declare const ToogleButton: ({ open, position, onToggle }: ToogleButtonProps) => import("react/jsx-runtime").JSX.Element;
|
|
19
|
-
export default ToogleButton;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./Drawer";
|