@trackunit/react-components 1.8.22 → 1.8.24
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 +257 -205
- package/index.esm.js +256 -204
- package/package.json +7 -7
- package/src/common/PackageNameStoryComponent.d.ts +2 -1
- package/src/components/Alert/Alert.d.ts +2 -2
- package/src/components/Badge/Badge.d.ts +2 -1
- package/src/components/Breadcrumb/Breadcrumb.d.ts +3 -2
- package/src/components/Breadcrumb/BreadcrumbForLargeScreen.d.ts +2 -1
- package/src/components/Breadcrumb/BreadcrumbForMediumScreen.d.ts +2 -1
- package/src/components/Breadcrumb/BreadcrumbForSmallScreen.d.ts +2 -1
- package/src/components/Breadcrumb/BreadcrumbItem.d.ts +2 -1
- package/src/components/Card/Card.d.ts +2 -2
- package/src/components/Card/CardBody.d.ts +2 -2
- package/src/components/Card/CardFooter.d.ts +2 -2
- package/src/components/Card/CardHeader.d.ts +3 -3
- package/src/components/Collapse/Collapse.d.ts +2 -2
- package/src/components/CompletionStatusIndicator/CompletionStatusIndicator.d.ts +2 -1
- package/src/components/CopyableText/CopyableText.d.ts +2 -1
- package/src/components/EmptyState/EmptyState.d.ts +2 -1
- package/src/components/Highlight/Highlight.d.ts +2 -2
- package/src/components/Icon/Icon.d.ts +2 -2
- package/src/components/InteractableItem/InteractableItem.variants.d.ts +2 -2
- package/src/components/KPICard/KPICard.d.ts +1 -1
- package/src/components/{VirtualizedList/VirtualizedList.d.ts → List/List.d.ts} +4 -4
- package/src/components/{VirtualizedList/VirtualizedList.variants.d.ts → List/List.variants.d.ts} +3 -3
- package/src/components/Menu/MenuDivider/MenuDivider.d.ts +2 -1
- package/src/components/Menu/MenuItem/MenuItem.d.ts +2 -2
- package/src/components/Menu/MenuItem/MenuItem.variants.d.ts +3 -2
- package/src/components/Menu/MoreMenu/MoreMenu.d.ts +2 -2
- package/src/components/Page/Page.d.ts +2 -2
- package/src/components/Page/PageContent.d.ts +2 -2
- package/src/components/PageHeader/components/PageHeaderKpiMetrics.d.ts +9 -1
- package/src/components/PageHeader/components/PageHeaderSecondaryActions.d.ts +17 -2
- package/src/components/PageHeader/components/PageHeaderTitle.d.ts +10 -1
- package/src/components/Pagination/Pagination.d.ts +2 -1
- package/src/components/Polygon/Polygon.d.ts +2 -1
- package/src/components/Popover/PopoverContent.d.ts +2 -2
- package/src/components/Popover/PopoverTitle.d.ts +2 -2
- package/src/components/Popover/PopoverTrigger.d.ts +2 -2
- package/src/components/Portal/Portal.d.ts +2 -1
- package/src/components/Sidebar/Sidebar.d.ts +1 -1
- package/src/components/Sidebar/useOverflowItems.d.ts +1 -1
- package/src/components/SkeletonLines/SkeletonLines.d.ts +2 -1
- package/src/components/Spacer/Spacer.d.ts +2 -1
- package/src/components/Spinner/Spinner.d.ts +2 -1
- package/src/components/Tabs/Tab.d.ts +1 -1
- package/src/components/Tabs/TabContent.d.ts +2 -2
- package/src/components/Tabs/TabList.d.ts +1 -1
- package/src/components/Tabs/Tabs.d.ts +2 -2
- package/src/components/Tag/Tag.d.ts +2 -2
- package/src/components/ToggleGroup/ToggleGroup.d.ts +3 -3
- package/src/components/ValueBar/ValueBar.d.ts +2 -1
- package/src/components/ZStack/ZStack.d.ts +2 -2
- package/src/components/buttons/Button/Button.d.ts +2 -2
- package/src/components/buttons/IconButton/IconButton.d.ts +4 -3
- package/src/components/buttons/StarButton/StarButton.d.ts +2 -2
- package/src/components/index.d.ts +2 -2
- package/src/hooks/useContinuousTimeout.d.ts +1 -1
- package/src/hooks/useSelfUpdatingRef.d.ts +1 -1
package/index.esm.js
CHANGED
|
@@ -15,9 +15,9 @@ import { Link, useBlocker } from '@tanstack/react-router';
|
|
|
15
15
|
import { useFloating, autoUpdate, offset, flip, shift, size, useClick, useDismiss, useHover as useHover$1, useRole, useInteractions, FloatingPortal, useMergeRefs, FloatingFocusManager, arrow, useTransitionStatus, FloatingArrow } from '@floating-ui/react';
|
|
16
16
|
import omit from 'lodash/omit';
|
|
17
17
|
import { twMerge } from 'tailwind-merge';
|
|
18
|
-
import { HelmetProvider, Helmet } from 'react-helmet-async';
|
|
19
|
-
import { Trigger, Content, List, Root } from '@radix-ui/react-tabs';
|
|
20
18
|
import { noPagination, useInfiniteScroll } from '@trackunit/react-table-pagination';
|
|
19
|
+
import { HelmetProvider, Helmet } from 'react-helmet-async';
|
|
20
|
+
import { Trigger, Content, List as List$1, Root } from '@radix-ui/react-tabs';
|
|
21
21
|
|
|
22
22
|
const docs = {
|
|
23
23
|
source: {
|
|
@@ -133,33 +133,29 @@ const isSafari = () => {
|
|
|
133
133
|
* @param {IconProps} props - The props for the Icon component
|
|
134
134
|
* @returns {ReactElement} Icon component
|
|
135
135
|
*/
|
|
136
|
-
const Icon = ({ name, size = "medium", className, dataTestId, color, onClick, type, style, forwardedRef, ariaLabel, fontSize, ariaLabelledBy, ariaDescribedBy, ariaHidden, }) => {
|
|
136
|
+
const Icon = ({ name, size = "medium", className, dataTestId, color = undefined, onClick, type = size === "large" ? "outline" : "solid", style, forwardedRef, ariaLabel, fontSize = false, ariaLabelledBy, ariaDescribedBy, ariaHidden, }) => {
|
|
137
137
|
const useTagRef = useRef(null);
|
|
138
138
|
const ICON_CONTAINER_ID = uuidv4();
|
|
139
139
|
const correctIconType = useMemo(() => {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
return "solid";
|
|
140
|
+
switch (size) {
|
|
141
|
+
case "small":
|
|
142
|
+
return "micro";
|
|
143
|
+
case "medium":
|
|
144
|
+
return "mini";
|
|
145
|
+
default:
|
|
146
|
+
return type === "solid" ? "solid" : "outline";
|
|
148
147
|
}
|
|
149
|
-
return "outline";
|
|
150
148
|
}, [type, size]);
|
|
151
149
|
const correctViewBox = useMemo(() => {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
return "0 0 24 24";
|
|
150
|
+
switch (size) {
|
|
151
|
+
case "small":
|
|
152
|
+
return "0 0 16 16";
|
|
153
|
+
case "medium":
|
|
154
|
+
return "0 0 20 20";
|
|
155
|
+
default:
|
|
156
|
+
return "0 0 24 24";
|
|
160
157
|
}
|
|
161
|
-
|
|
162
|
-
}, [size, type]);
|
|
158
|
+
}, [size]);
|
|
163
159
|
const iconName = iconNames[name];
|
|
164
160
|
const href = useMemo(() => ({
|
|
165
161
|
solid: `${IconSpriteSolid}#${iconName}`,
|
|
@@ -258,15 +254,15 @@ const Tag = ({ className, dataTestId, children, size = "medium", onClose, color
|
|
|
258
254
|
return false;
|
|
259
255
|
}, [color]);
|
|
260
256
|
const layout = useMemo(() => {
|
|
261
|
-
if (onClose && isSupportedDismissColor) {
|
|
257
|
+
if (onClose !== undefined && isSupportedDismissColor) {
|
|
262
258
|
return "containsDismiss";
|
|
263
259
|
}
|
|
264
|
-
if (icon) {
|
|
260
|
+
if (icon !== null && icon !== undefined) {
|
|
265
261
|
return "containsIcon";
|
|
266
262
|
}
|
|
267
263
|
return "default";
|
|
268
264
|
}, [onClose, icon, isSupportedDismissColor]);
|
|
269
|
-
return (jsxs("div", { className: cvaTag({ className, size, color, layout, border: color === "white" ? "default" : "none" }), "data-testid": dataTestId, onMouseEnter: onMouseEnter, ref: ref, children: [icon && size === "medium" ? jsx("div", { className: cvaTagIconContainer(), children: icon }) : null, jsx("span", { className: cvaTagText(), children: children }), Boolean(onClose) && isSupportedDismissColor && size === "medium" && !disabled ? (
|
|
265
|
+
return (jsxs("div", { className: cvaTag({ className, size, color, layout, border: color === "white" ? "default" : "none" }), "data-testid": dataTestId, onMouseEnter: onMouseEnter, ref: ref, children: [icon !== null && icon !== undefined && size === "medium" ? (jsx("div", { className: cvaTagIconContainer(), children: icon })) : null, jsx("span", { className: cvaTagText(), children: children }), Boolean(onClose) && isSupportedDismissColor && size === "medium" && !disabled ? (
|
|
270
266
|
// a fix for multiselect deselecting tags working together with fade out animation
|
|
271
267
|
jsx("div", { className: cvaTagIconContainer(), onMouseDown: onClose, children: jsx(Icon, { className: cvaTagIcon(), dataTestId: dataTestId + "Icon", name: "XCircle", size: "small", style: { WebkitTransition: "-webkit-transform 0.150s" }, type: "solid" }) })) : null] }));
|
|
272
268
|
};
|
|
@@ -748,7 +744,7 @@ const cvaIconButton = cvaMerge([], {
|
|
|
748
744
|
* @param {ButtonProps} props - The props for the Button component
|
|
749
745
|
* @returns {ReactElement} Button component
|
|
750
746
|
*/
|
|
751
|
-
const Button = ({ onClick, children, loading, disabled, className, fullWidth = false, prefix, suffix, variant = "primary", type = "button", size = "medium", square = false, dataTestId, title, role, tabIndex, asChild = false, circular, ref, ...rest }) => {
|
|
747
|
+
const Button = ({ onClick, children, loading = false, disabled = false, className, fullWidth = false, prefix, suffix, variant = "primary", type = "button", size = "medium", square = false, dataTestId, title, role, tabIndex, asChild = false, circular = false, ref, ...rest }) => {
|
|
752
748
|
const Comp = asChild ? Slot : "button";
|
|
753
749
|
const sharedCompProps = {
|
|
754
750
|
ref,
|
|
@@ -766,7 +762,7 @@ const Button = ({ onClick, children, loading, disabled, className, fullWidth = f
|
|
|
766
762
|
disabled: disabled || loading,
|
|
767
763
|
type,
|
|
768
764
|
};
|
|
769
|
-
return (jsxs(Comp, { ...sharedCompProps, ...(asChild ? {} : buttonSpecificProps), children: [loading ? (jsx(Spinner, { centering: "vertically", className: cvaButtonSpinner({ variant }), containerClassName: cvaButtonSpinnerContainer(), size: "small" })) : null, prefix && !loading ? jsx("div", { className: cvaButtonPrefixSuffix({ size, variant }), children: prefix }) : null, jsx(Slottable, { children: children }), suffix && !loading ? jsx("div", { className: cvaButtonPrefixSuffix({ size, variant }), children: suffix }) : null] }));
|
|
765
|
+
return (jsxs(Comp, { ...sharedCompProps, ...(asChild ? {} : buttonSpecificProps), children: [loading ? (jsx(Spinner, { centering: "vertically", className: cvaButtonSpinner({ variant }), containerClassName: cvaButtonSpinnerContainer(), size: "small" })) : null, prefix !== null && prefix !== undefined && !loading ? (jsx("div", { className: cvaButtonPrefixSuffix({ size, variant }), children: prefix })) : null, jsx(Slottable, { children: children }), suffix !== null && suffix !== undefined && !loading ? (jsx("div", { className: cvaButtonPrefixSuffix({ size, variant }), children: suffix })) : null] }));
|
|
770
766
|
};
|
|
771
767
|
Button.displayName = "Button";
|
|
772
768
|
|
|
@@ -776,10 +772,8 @@ Button.displayName = "Button";
|
|
|
776
772
|
/**
|
|
777
773
|
*
|
|
778
774
|
*/
|
|
779
|
-
const IconButton = ({ icon, size = "medium", square = true, loading, disabled, className, ref, ...rest }) => {
|
|
780
|
-
return (jsx(Button, { className: cvaIconButton({ size: size, className }), disabled: disabled || loading, loading: loading,
|
|
781
|
-
// eslint-disable-next-line local-rules/design-guideline-button-icon-size-match
|
|
782
|
-
prefix: !loading ? icon : undefined, ref: ref, size: size, square: square, ...rest }));
|
|
775
|
+
const IconButton = ({ icon, size = "medium", square = true, loading = false, disabled = false, className, ref, ...rest }) => {
|
|
776
|
+
return (jsx(Button, { className: cvaIconButton({ size: size, className }), disabled: disabled || loading, loading: loading, prefix: !loading ? icon : undefined, ref: ref, size: size, square: square, ...rest }));
|
|
783
777
|
};
|
|
784
778
|
IconButton.displayName = "IconButton";
|
|
785
779
|
|
|
@@ -883,7 +877,7 @@ const cvaAlertIconContainer = cvaMerge(["shrink-0", "grid", "w-min", "flex"], {
|
|
|
883
877
|
* @param {AlertProps} props - The props for the Alert component
|
|
884
878
|
* @returns {ReactElement} Alert component
|
|
885
879
|
*/
|
|
886
|
-
const Alert = ({ color = "info", title, className, children, primaryAction, secondaryAction, onClose, dataTestId, autoScroll, actionsInline = false, }) => {
|
|
880
|
+
const Alert = ({ color = "info", title, className, children, primaryAction, secondaryAction, onClose, dataTestId, autoScroll = false, actionsInline = false, }) => {
|
|
887
881
|
const ref = useRef(null);
|
|
888
882
|
const { isTextWrapping, ref: titleRef } = useIsTextWrapping();
|
|
889
883
|
useEffect(() => {
|
|
@@ -892,7 +886,19 @@ const Alert = ({ color = "info", title, className, children, primaryAction, seco
|
|
|
892
886
|
ref.current?.scrollIntoView?.();
|
|
893
887
|
}
|
|
894
888
|
}, [ref, autoScroll]);
|
|
895
|
-
return (jsxs("div", { className: cvaAlert({ color, actionsInline, className }), "data-testid": dataTestId, ref: ref, role: "alert", children: [jsxs("div", { className: cvaAlertContentContainer({
|
|
889
|
+
return (jsxs("div", { className: cvaAlert({ color, actionsInline, className }), "data-testid": dataTestId, ref: ref, role: "alert", children: [jsxs("div", { className: cvaAlertContentContainer({
|
|
890
|
+
inline: !isTextWrapping && (children === null || children === undefined),
|
|
891
|
+
actionsInline,
|
|
892
|
+
}), children: [jsx("div", { className: cvaAlertIconContainer({
|
|
893
|
+
inline: !isTextWrapping && (children === null || children === undefined),
|
|
894
|
+
actionsInline,
|
|
895
|
+
}), children: jsx(Icon, { color: color, name: getIconName(color) }) }), jsxs("div", { className: cvaContent(), children: [title ? (jsx(Text, { dataTestId: `${dataTestId}-title`, ref: titleRef, weight: "bold", children: title })) : null, children !== null && children !== undefined ? (jsx(Text, { type: typeof children === "string" || typeof children === "number" ? "p" : "span", weight: "normal", children: children })) : null] }), onClose !== undefined && !actionsInline ? (jsx("div", { className: cvaAlertCloseButtonContainer({
|
|
896
|
+
inline: !isTextWrapping && (children === null || children === undefined),
|
|
897
|
+
actionsInline,
|
|
898
|
+
}), children: jsx(IconButton, { className: "!h-5 !min-h-0 !w-5 !p-0", icon: jsx(Icon, { name: "XMark", size: "small" }), onClick: onClose, size: "small", title: "Close Alert", variant: "ghost-neutral" }) })) : null] }), primaryAction !== undefined || secondaryAction !== undefined ? (jsxs("div", { className: cvaAlertActionsContainer({ actionsInline }), children: [secondaryAction !== undefined ? (jsx(Button, { loading: secondaryAction.loading, onClick: secondaryAction.onClick, size: "small", variant: "ghost-neutral", children: secondaryAction.label })) : null, primaryAction !== undefined ? (jsx(Button, { loading: primaryAction.loading, onClick: primaryAction.onClick, size: "small", variant: color === "danger" ? "primary-danger" : "primary", children: primaryAction.label })) : null] })) : null, onClose !== undefined && actionsInline ? (jsx("div", { className: cvaAlertCloseButtonContainer({
|
|
899
|
+
inline: !isTextWrapping && (children === null || children === undefined),
|
|
900
|
+
actionsInline,
|
|
901
|
+
}), children: jsx(IconButton, { className: "!h-5 !min-h-0 !w-5 !p-0", icon: jsx(Icon, { name: "XMark", size: "small" }), onClick: onClose, size: "small", title: "Close Alert", variant: "ghost-neutral" }) })) : null] }));
|
|
896
902
|
};
|
|
897
903
|
const getIconName = (color) => {
|
|
898
904
|
switch (color) {
|
|
@@ -966,7 +972,11 @@ const Badge = ({ color = "primary", compact = false, className, count, max, hide
|
|
|
966
972
|
if (hideZero && count === 0) {
|
|
967
973
|
return null;
|
|
968
974
|
}
|
|
969
|
-
const displayedCount = count &&
|
|
975
|
+
const displayedCount = count !== undefined && count !== 0 && !Number.isNaN(count) && max !== undefined && max !== 0 && !Number.isNaN(max)
|
|
976
|
+
? count > max
|
|
977
|
+
? `${max}+`
|
|
978
|
+
: count
|
|
979
|
+
: count;
|
|
970
980
|
const isSingleChar = displayedCount?.toString().length === 1;
|
|
971
981
|
return (jsx("span", { className: cvaBadge({ color, className, compact, isSingleChar }), "data-testid": dataTestId, children: compact ? null : displayedCount }));
|
|
972
982
|
};
|
|
@@ -1202,10 +1212,10 @@ const useDebounce = (value, delay = 500, direction, onBounce) => {
|
|
|
1202
1212
|
const [debouncedValue, setDebouncedValue] = useState(value);
|
|
1203
1213
|
useEffect(() => {
|
|
1204
1214
|
let handler;
|
|
1205
|
-
if ((direction === "in" && !debouncedValue && value) ||
|
|
1206
|
-
(direction === "out" && debouncedValue && !value) ||
|
|
1215
|
+
if ((direction === "in" && !Boolean(debouncedValue) && Boolean(value)) ||
|
|
1216
|
+
(direction === "out" && Boolean(debouncedValue) && !Boolean(value)) ||
|
|
1207
1217
|
direction === "both" ||
|
|
1208
|
-
|
|
1218
|
+
direction === undefined) {
|
|
1209
1219
|
handler = setTimeout(() => {
|
|
1210
1220
|
setDebouncedValue(value);
|
|
1211
1221
|
onBounce?.(value);
|
|
@@ -1426,7 +1436,7 @@ const useIsTextTruncated = (text) => {
|
|
|
1426
1436
|
}, [updateTextVisibility]);
|
|
1427
1437
|
// Re-check whenever text changes
|
|
1428
1438
|
useEffect(() => {
|
|
1429
|
-
if (
|
|
1439
|
+
if (text === undefined || text === "") {
|
|
1430
1440
|
return;
|
|
1431
1441
|
}
|
|
1432
1442
|
updateTextVisibility();
|
|
@@ -1632,7 +1642,11 @@ const useWatch = ({ value, onChange, immediate = false, isEqual }) => {
|
|
|
1632
1642
|
const prevValue = useRef(UNINITIALIZED);
|
|
1633
1643
|
useEffect(() => {
|
|
1634
1644
|
const prev = prevValue.current;
|
|
1635
|
-
const hasChanged = prev === UNINITIALIZED
|
|
1645
|
+
const hasChanged = prev === UNINITIALIZED
|
|
1646
|
+
? false
|
|
1647
|
+
: isEqual !== undefined
|
|
1648
|
+
? !isEqual(value, prev)
|
|
1649
|
+
: JSON.stringify(value) !== JSON.stringify(prev);
|
|
1636
1650
|
if (immediate && prev === UNINITIALIZED) {
|
|
1637
1651
|
onChange(value, null);
|
|
1638
1652
|
}
|
|
@@ -1892,7 +1906,7 @@ const Card = ({ children, onClick, fullHeight = false, onMouseEnter, onMouseLeav
|
|
|
1892
1906
|
* @param {CardBodyProps} props - The props for the CardBody component
|
|
1893
1907
|
* @returns {ReactElement} CardBody component
|
|
1894
1908
|
*/
|
|
1895
|
-
const CardBody = ({ density = "auto", children, dataTestId, className, direction, disableGap, id, }) => {
|
|
1909
|
+
const CardBody = ({ density = "auto", children, dataTestId, className, direction = "column", disableGap = false, id, }) => {
|
|
1896
1910
|
return (jsx("div", { className: cvaCardBodyDensityContainer$1({ density, disableGap, className, direction }), "data-testid": dataTestId, id: id, children: children }));
|
|
1897
1911
|
};
|
|
1898
1912
|
|
|
@@ -1904,7 +1918,7 @@ const CardBody = ({ density = "auto", children, dataTestId, className, direction
|
|
|
1904
1918
|
* @param {CardFooterProps} props - The props for the CardFooter component
|
|
1905
1919
|
* @returns {ReactElement} CardFooter component
|
|
1906
1920
|
*/
|
|
1907
|
-
const CardFooter = ({ dataTestId, className, children, density, hideSeparator = false }) => {
|
|
1921
|
+
const CardFooter = ({ dataTestId, className, children, density = "auto", hideSeparator = false, }) => {
|
|
1908
1922
|
return (jsx("div", { className: cvaCardFooterDensityContainer({
|
|
1909
1923
|
density,
|
|
1910
1924
|
border: hideSeparator ? "borderless" : "default",
|
|
@@ -1969,12 +1983,12 @@ const Heading = ({ variant = "primary", inverted = false, subtle = false, classN
|
|
|
1969
1983
|
* @param {CardHeaderProps} props - The props for the CardHeader component
|
|
1970
1984
|
* @returns {ReactElement} CardHeader component
|
|
1971
1985
|
*/
|
|
1972
|
-
const CardHeader = ({ heading, headingVariant = "secondary", subHeading, onClose, dataTestId, className, children, accessories, actions, density, hideSeparator = false, }) => {
|
|
1986
|
+
const CardHeader = ({ heading, headingVariant = "secondary", subHeading, onClose, dataTestId, className, children, accessories, actions, density = "auto", hideSeparator = false, }) => {
|
|
1973
1987
|
return (jsx("div", { className: cvaCardHeaderDensityContainer({
|
|
1974
1988
|
density,
|
|
1975
1989
|
border: hideSeparator ? "borderless" : "default",
|
|
1976
1990
|
className,
|
|
1977
|
-
}), "data-testid": dataTestId, children: jsxs("div", { className: cvaCardHeader(), children: [jsxs("div", { children: [jsxs("div", { className: cvaCardHeaderHeadingContainer(), children: [jsx(Heading, { className: "self-center", variant: headingVariant, children: heading }), accessories] }), subHeading ? (jsx(Heading, { subtle: true, variant: "subtitle", children: subHeading })) : null, children] }), jsxs("div", { className: "flex place-items-center gap-x-2 gap-y-1", children: [actions, onClose ? (jsx(IconButton, { className: "!h-min", dataTestId: "card-header-close-button", icon: jsx(Icon, { name: "XMark", size: "small" }), onClick: onClose, variant: "ghost-neutral" })) : null] })] }) }));
|
|
1991
|
+
}), "data-testid": dataTestId, children: jsxs("div", { className: cvaCardHeader(), children: [jsxs("div", { children: [jsxs("div", { className: cvaCardHeaderHeadingContainer(), children: [jsx(Heading, { className: "self-center", variant: headingVariant, children: heading }), accessories] }), subHeading !== null && subHeading !== undefined ? (jsx(Heading, { subtle: true, variant: "subtitle", children: subHeading })) : null, children] }), jsxs("div", { className: "flex place-items-center gap-x-2 gap-y-1", children: [actions, onClose ? (jsx(IconButton, { className: "!h-min", dataTestId: "card-header-close-button", icon: jsx(Icon, { name: "XMark", size: "small" }), onClick: onClose, variant: "ghost-neutral" })) : null] })] }) }));
|
|
1978
1992
|
};
|
|
1979
1993
|
|
|
1980
1994
|
const cvaCollapse = cvaMerge([
|
|
@@ -2060,9 +2074,9 @@ const Collapse = ({ id, initialExpanded = false, onToggle, label, children, clas
|
|
|
2060
2074
|
}
|
|
2061
2075
|
setExpanded(!expanded);
|
|
2062
2076
|
}, [expanded, onToggle]);
|
|
2063
|
-
return (jsxs("div", { className: cvaCollapse({ className }), "data-testid": dataTestId, children: [jsx("div", { "aria-controls": id, "aria-expanded": expanded, className: cvaCollapseHeader({ expanded, className: headerClassName }), onClick: handleClick, role: "button", children: jsxs("div", { className: cvaCollapseLabelContainer(), children: [jsx(Text, { id: LABEL_ID, type: "span", weight: "bold", children: label }), jsxs("div", { className: "flex items-center gap-2", children: [headerAddon ? headerAddon : null, jsx(Icon, { ariaLabelledBy: LABEL_ID, className: cvaChevronIcon({ expanded }), name: "ChevronUp", size: "medium" })] })] }) }), jsx(Collapsible, { expanded: expanded, extraPadding: extraPadding, id: id, children: expanded || animate ? children : null })] }));
|
|
2077
|
+
return (jsxs("div", { className: cvaCollapse({ className }), "data-testid": dataTestId, children: [jsx("div", { "aria-controls": id, "aria-expanded": expanded, className: cvaCollapseHeader({ expanded, className: headerClassName }), onClick: handleClick, role: "button", children: jsxs("div", { className: cvaCollapseLabelContainer(), children: [jsx(Text, { id: LABEL_ID, type: "span", weight: "bold", children: label }), jsxs("div", { className: "flex items-center gap-2", children: [headerAddon !== null && headerAddon !== undefined ? headerAddon : null, jsx(Icon, { ariaLabelledBy: LABEL_ID, className: cvaChevronIcon({ expanded }), name: "ChevronUp", size: "medium" })] })] }) }), jsx(Collapsible, { expanded: expanded, extraPadding: extraPadding, id: id, children: expanded || animate ? children : null })] }));
|
|
2064
2078
|
};
|
|
2065
|
-
const Collapsible = ({ children, expanded, id, extraPadding }) => {
|
|
2079
|
+
const Collapsible = ({ children, expanded, id, extraPadding = true }) => {
|
|
2066
2080
|
const ref = useRef(null);
|
|
2067
2081
|
const { height } = useGeometry(ref);
|
|
2068
2082
|
return (jsx("div", { className: cvaCollapseAnimated({ expanded }), id: id, style: { height: expanded ? height : "0" }, children: jsx("div", { ref: ref, children: jsx("div", { className: cvaCollapsible({ extraPadding }), children: children }) }) }));
|
|
@@ -2081,7 +2095,7 @@ const Collapsible = ({ children, expanded, id, extraPadding }) => {
|
|
|
2081
2095
|
* @param {boolean} props.warning - Indicates if the process has a warning.
|
|
2082
2096
|
* @param {boolean} props.success - Indicates if the process was successful.
|
|
2083
2097
|
*/
|
|
2084
|
-
const CompletionStatusIndicator = ({ loading, error, success, ...rest }) => {
|
|
2098
|
+
const CompletionStatusIndicator = ({ loading = false, error, success, ...rest }) => {
|
|
2085
2099
|
if (loading) {
|
|
2086
2100
|
return jsx(Spinner, { className: "h-[22px] w-[22px]", containerClassName: "w-min", ...rest });
|
|
2087
2101
|
}
|
|
@@ -2175,17 +2189,17 @@ const cvaSkeletonLine = cvaMerge([
|
|
|
2175
2189
|
/**
|
|
2176
2190
|
* Display placeholder lines before the data gets loaded to reduce load-time frustration.
|
|
2177
2191
|
*/
|
|
2178
|
-
const SkeletonLines = memo(({ margin = "10px 0", lines = 1, height, width = "100%", className, dataTestId }) => {
|
|
2192
|
+
const SkeletonLines = memo(({ margin = "10px 0", lines = 1, height, width = "100%", className, dataTestId, }) => {
|
|
2179
2193
|
const skeletonLines = [];
|
|
2180
2194
|
const getWidth = (index) => {
|
|
2181
|
-
if (width
|
|
2182
|
-
return width[index]
|
|
2195
|
+
if (Array.isArray(width)) {
|
|
2196
|
+
return width[index] ?? "100%";
|
|
2183
2197
|
}
|
|
2184
2198
|
return width;
|
|
2185
2199
|
};
|
|
2186
2200
|
const getHeight = (index) => {
|
|
2187
|
-
if (height
|
|
2188
|
-
return height[index]
|
|
2201
|
+
if (Array.isArray(height)) {
|
|
2202
|
+
return height[index] ?? "auto";
|
|
2189
2203
|
}
|
|
2190
2204
|
return height;
|
|
2191
2205
|
};
|
|
@@ -2269,7 +2283,7 @@ WorkerWithSignSVG.displayName = "WorkerWithSignSVG";
|
|
|
2269
2283
|
* - For guidance purposes (e.g., onboarding, adjusting filters, exploring alternative approaches).
|
|
2270
2284
|
* - In celebratory instances (e.g., no new notifications, services up to date).
|
|
2271
2285
|
*/
|
|
2272
|
-
const EmptyState = ({ description, altText, image = "SEARCH_DOCUMENT", customImageSrc, loading, dataTestId, className, primaryAction, secondaryAction, additionalHelpAction, }) => {
|
|
2286
|
+
const EmptyState = ({ description, altText, image = "SEARCH_DOCUMENT", customImageSrc, loading = false, dataTestId, className, primaryAction, secondaryAction, additionalHelpAction, }) => {
|
|
2273
2287
|
const ImageSource = useMemo(() => {
|
|
2274
2288
|
switch (image) {
|
|
2275
2289
|
case "WORKER_WITH_SIGN":
|
|
@@ -2287,7 +2301,7 @@ const EmptyState = ({ description, altText, image = "SEARCH_DOCUMENT", customIma
|
|
|
2287
2301
|
return SearchDocumentSVG;
|
|
2288
2302
|
}
|
|
2289
2303
|
}, [image]);
|
|
2290
|
-
return (jsx("div", { className: cvaContainerStyles({ className }), "data-testid": dataTestId ?? "empty-state", children: loading ? (jsxs(Fragment, { children: [jsx(Spinner, { centering: "centered", dataTestId: "spinner" }), jsx(SkeletonLines, { dataTestId: "skeleton-lines", width: 50 })] })) : (jsxs(Fragment, { children: [customImageSrc ? (typeof customImageSrc === "string" ? (jsx("img", { alt: altText, className: cvaImgStyles(), height: 200, src: customImageSrc, width: 200 })) : (customImageSrc)) : (typeof ImageSource !== "undefined" && (jsx(ImageSource, { "data-testid": "empty-state-image", height: 200, width: 200 }, image))), description ? (jsx(Text, { align: "center", size: "large", children: description })) : null, jsxs("div", { className: "mt-4 grid gap-3", children: [jsxs("div", { className: "flex gap-3", children: [secondaryAction ? (jsx(Button, { dataTestId: "empty-state-secondary-button", disabled: secondaryAction.disabled, onClick: secondaryAction.onClick, variant: "secondary", children: secondaryAction.to ? (jsx(Link, { params: secondaryAction.to.parameters, to: secondaryAction.to.pathname, children: secondaryAction.title })) : (secondaryAction.title) })) : null, primaryAction ? (jsx(Button, { dataTestId: "empty-state-primary-button", disabled: primaryAction.disabled, onClick: primaryAction.onClick, children: primaryAction.to ? (jsx(Link, { params: primaryAction.to.parameters, to: primaryAction.to.pathname, children: primaryAction.title })) : (primaryAction.title) })) : null] }), additionalHelpAction?.to ? (jsx(Button, { asChild: true, dataTestId: "empty-state-additional-button", disabled: additionalHelpAction.disabled, onClick: additionalHelpAction.onClick, suffix: jsx(Icon, { name: "ArrowTopRightOnSquare", size: "small" }), variant: "ghost", children: jsx(Link, { params: additionalHelpAction.to.parameters, target: additionalHelpAction.to.target, to: additionalHelpAction.to.pathname, children: additionalHelpAction.title }) })) : null] })] })) }));
|
|
2304
|
+
return (jsx("div", { className: cvaContainerStyles({ className }), "data-testid": dataTestId ?? "empty-state", children: loading ? (jsxs(Fragment, { children: [jsx(Spinner, { centering: "centered", dataTestId: "spinner" }), jsx(SkeletonLines, { dataTestId: "skeleton-lines", width: 50 })] })) : (jsxs(Fragment, { children: [customImageSrc !== null && customImageSrc !== undefined ? (typeof customImageSrc === "string" ? (jsx("img", { alt: altText, className: cvaImgStyles(), height: 200, src: customImageSrc, width: 200 })) : (customImageSrc)) : (typeof ImageSource !== "undefined" && (jsx(ImageSource, { "data-testid": "empty-state-image", height: 200, width: 200 }, image))), description !== undefined && description !== "" ? (jsx(Text, { align: "center", size: "large", children: description })) : null, jsxs("div", { className: "mt-4 grid gap-3", children: [jsxs("div", { className: "flex gap-3", children: [secondaryAction ? (jsx(Button, { dataTestId: "empty-state-secondary-button", disabled: secondaryAction.disabled, onClick: secondaryAction.onClick, variant: "secondary", children: secondaryAction.to ? (jsx(Link, { params: secondaryAction.to.parameters, to: secondaryAction.to.pathname, children: secondaryAction.title })) : (secondaryAction.title) })) : null, primaryAction ? (jsx(Button, { dataTestId: "empty-state-primary-button", disabled: primaryAction.disabled, onClick: primaryAction.onClick, children: primaryAction.to ? (jsx(Link, { params: primaryAction.to.parameters, to: primaryAction.to.pathname, children: primaryAction.title })) : (primaryAction.title) })) : null] }), additionalHelpAction?.to ? (jsx(Button, { asChild: true, dataTestId: "empty-state-additional-button", disabled: additionalHelpAction.disabled, onClick: additionalHelpAction.onClick, suffix: jsx(Icon, { name: "ArrowTopRightOnSquare", size: "small" }), variant: "ghost", children: jsx(Link, { params: additionalHelpAction.to.parameters, target: additionalHelpAction.to.target, to: additionalHelpAction.to.pathname, children: additionalHelpAction.title }) })) : null] })] })) }));
|
|
2291
2305
|
};
|
|
2292
2306
|
|
|
2293
2307
|
const cvaEmptyValue = cvaMerge(["text-neutral-400"]);
|
|
@@ -2638,7 +2652,7 @@ const cvaPopoverTitleText = cvaMerge(["flex-1", "text-neutral-500"]);
|
|
|
2638
2652
|
const PopoverContent = function PopoverContent({ className, dataTestId, children, portalId, ref: propRef, ...props }) {
|
|
2639
2653
|
const { context: floatingContext, customProps, ...context } = usePopoverContext();
|
|
2640
2654
|
const ref = useMergeRefs([context.refs.setFloating, propRef]);
|
|
2641
|
-
return (jsx(Portal, { id: portalId, children: context.isOpen ? (jsx(FloatingFocusManager, { closeOnFocusOut: false, context: floatingContext, guards: true, modal: context.isModal, order: ["reference", "content"], returnFocus: true, children: jsx("div", { "aria-describedby": context.descriptionId, "aria-labelledby": context.labelId, className: cvaPopoverContainer({ className: className ?? customProps.className }), "data-testid": dataTestId ?? customProps.dataTestId ?? "popover-content", ref: ref, style: {
|
|
2655
|
+
return (jsx(Portal, { id: portalId, children: context.isOpen === true ? (jsx(FloatingFocusManager, { closeOnFocusOut: false, context: floatingContext, guards: true, modal: context.isModal, order: ["reference", "content"], returnFocus: true, children: jsx("div", { "aria-describedby": context.descriptionId, "aria-labelledby": context.labelId, className: cvaPopoverContainer({ className: className ?? customProps.className }), "data-testid": dataTestId ?? customProps.dataTestId ?? "popover-content", ref: ref, style: {
|
|
2642
2656
|
position: context.strategy,
|
|
2643
2657
|
top: context.y,
|
|
2644
2658
|
left: context.x,
|
|
@@ -2653,7 +2667,7 @@ const PopoverContent = function PopoverContent({ className, dataTestId, children
|
|
|
2653
2667
|
* @param {PopoverTitleProps} props - The props for the PopoverTitle component
|
|
2654
2668
|
* @returns {ReactElement} PopoverTitle component
|
|
2655
2669
|
*/
|
|
2656
|
-
const PopoverTitle = ({ children, action, divider = false, className, dataTestId }) => {
|
|
2670
|
+
const PopoverTitle = ({ children, action, divider = false, className, dataTestId, }) => {
|
|
2657
2671
|
return (jsxs("div", { className: cvaPopoverTitleContainer({ divider, className }), "data-testid": dataTestId, children: [jsx(Text, { className: cvaPopoverTitleText(), size: "small", subtle: true, type: "div", uppercase: true, weight: "bold", children: children }), action] }));
|
|
2658
2672
|
};
|
|
2659
2673
|
|
|
@@ -2663,7 +2677,7 @@ const PopoverTitle = ({ children, action, divider = false, className, dataTestId
|
|
|
2663
2677
|
* @param {PopoverTriggerProps} props - The props for the PopoverTrigger component
|
|
2664
2678
|
* @returns {ReactElement} PopoverTrigger component
|
|
2665
2679
|
*/
|
|
2666
|
-
const PopoverTrigger = function PopoverTrigger({ children, renderButton, ref: propRef, ...props }) {
|
|
2680
|
+
const PopoverTrigger = function PopoverTrigger({ children, renderButton = false, ref: propRef, ...props }) {
|
|
2667
2681
|
const context = usePopoverContext();
|
|
2668
2682
|
const ref = useMergeRefs([context.refs.setReference, propRef]);
|
|
2669
2683
|
if (!renderButton && isValidElement(children)) {
|
|
@@ -2671,10 +2685,10 @@ const PopoverTrigger = function PopoverTrigger({ children, renderButton, ref: pr
|
|
|
2671
2685
|
ref,
|
|
2672
2686
|
...props,
|
|
2673
2687
|
...children.props,
|
|
2674
|
-
"data-state": context.isOpen ? "open" : "closed",
|
|
2688
|
+
"data-state": context.isOpen === true ? "open" : "closed",
|
|
2675
2689
|
}));
|
|
2676
2690
|
}
|
|
2677
|
-
return (jsx(Button, { "data-state": context.isOpen ? "open" : "closed", ref: ref, type: "button", ...context.getReferenceProps(props), children: children }));
|
|
2691
|
+
return (jsx(Button, { "data-state": context.isOpen === true ? "open" : "closed", ref: ref, type: "button", ...context.getReferenceProps(props), children: children }));
|
|
2678
2692
|
};
|
|
2679
2693
|
|
|
2680
2694
|
const cvaTooltipContainer = cvaMerge(["flex", "leading-5"]);
|
|
@@ -2750,7 +2764,7 @@ const FloatingArrowContainer = ({ arrowRef, mode = "dark", }) => {
|
|
|
2750
2764
|
* @param {TooltipProps} props - The props for the Tooltip component
|
|
2751
2765
|
* @returns {ReactElement} Tooltip component
|
|
2752
2766
|
*/
|
|
2753
|
-
const Tooltip = ({ children, dataTestId, disabled, className, label, placement = "auto", mode = "dark", iconProps, id, }) => {
|
|
2767
|
+
const Tooltip = ({ children, dataTestId, disabled = false, className, label, placement = "auto", mode = "dark", iconProps, id, }) => {
|
|
2754
2768
|
const [isOpen, setIsOpen] = useState(false);
|
|
2755
2769
|
const arrowRef = useRef(null);
|
|
2756
2770
|
const { refs, floatingStyles, context } = useFloating({
|
|
@@ -2916,8 +2930,8 @@ const cvaIndicatorIconBackground = cvaMerge(["rounded-full", "items-center", "ju
|
|
|
2916
2930
|
* @param {IndicatorProps} props - The props for the Indicator component
|
|
2917
2931
|
* @returns {ReactElement} Indicator component
|
|
2918
2932
|
*/
|
|
2919
|
-
const Indicator = ({ dataTestId, icon, label, color = "unknown", withBackground = true, withLabel = true, ping = false, size, weight, className, ...rest }) => {
|
|
2920
|
-
return (jsx(Tooltip, { className: className, disabled: withLabel, label: label, placement: "bottom", children: jsxs("div", { "aria-label": label, className: cvaIndicator(), "data-testid": dataTestId, ...rest, children: [jsxs("div", { className: cvaIndicatorIconBackground({ color, background: withBackground ? "visible" : "hidden" }), "data-testid": dataTestId ? `${dataTestId}-background` : "indicator-background", children: [ping ? (jsx("div", { className: cvaIndicatorPing({ color }), "data-testid": dataTestId ? `${dataTestId}-ping` : "indicator-ping" })) : null, icon] }), label
|
|
2933
|
+
const Indicator = ({ dataTestId, icon, label, color = "unknown", withBackground = true, withLabel = true, ping = false, size = "medium", weight = "normal", className, ...rest }) => {
|
|
2934
|
+
return (jsx(Tooltip, { className: className, disabled: withLabel, label: label, placement: "bottom", children: jsxs("div", { "aria-label": label, className: cvaIndicator(), "data-testid": dataTestId, ...rest, children: [jsxs("div", { className: cvaIndicatorIconBackground({ color, background: withBackground ? "visible" : "hidden" }), "data-testid": dataTestId ? `${dataTestId}-background` : "indicator-background", children: [ping ? (jsx("div", { className: cvaIndicatorPing({ color }), "data-testid": dataTestId ? `${dataTestId}-ping` : "indicator-ping" })) : null, icon] }), label && withLabel ? (jsx("div", { className: cvaIndicatorLabel({ size, weight, background: withBackground ? "visible" : "hidden" }), "data-testid": dataTestId ? `${dataTestId}-label` : undefined, children: label })) : null] }) }));
|
|
2921
2935
|
};
|
|
2922
2936
|
|
|
2923
2937
|
const cvaKPI = cvaMerge(["w-full", "px-4", "py-2", "flex", "flex-col"], {
|
|
@@ -2977,10 +2991,10 @@ const LoadingContent$1 = () => (jsx("div", { className: "flex h-11 flex-row item
|
|
|
2977
2991
|
* @param {KPIProps} props - The props for the KPI component
|
|
2978
2992
|
* @returns {ReactElement} KPI component
|
|
2979
2993
|
*/
|
|
2980
|
-
const KPI = ({ title, value, loading, unit, className, dataTestId, tooltipLabel, variant = "default", trend, ...rest }) => {
|
|
2994
|
+
const KPI = ({ title, value, loading = false, unit, className, dataTestId, tooltipLabel, variant = "default", trend, ...rest }) => {
|
|
2981
2995
|
const isSmallVariant = variant === "small";
|
|
2982
|
-
return (jsx(Tooltip, { dataTestId: dataTestId ? `${dataTestId}-tooltip` : undefined, disabled:
|
|
2983
|
-
isDefaultAndHasTrendValue: Boolean(trend
|
|
2996
|
+
return (jsx(Tooltip, { dataTestId: dataTestId ? `${dataTestId}-tooltip` : undefined, disabled: tooltipLabel === undefined || tooltipLabel === "", label: tooltipLabel, placement: "bottom", children: jsx("div", { className: cvaKPI({ variant, className }), "data-testid": dataTestId ? `${dataTestId}` : undefined, ...rest, children: loading ? (jsx(LoadingContent$1, {})) : (jsxs(Fragment, { children: [jsx("div", { className: cvaKPIHeader(), children: jsx(Text, { className: cvaKPITitleText(), dataTestId: dataTestId ? `${dataTestId}-title` : undefined, size: isSmallVariant ? "small" : "medium", subtle: true, weight: isSmallVariant ? "normal" : "bold", children: title }) }), jsx(Text, { className: cvaKPIvalueText({ variant }), dataTestId: dataTestId ? `${dataTestId}-value` : undefined, size: isSmallVariant ? "small" : "large", type: "div", weight: isSmallVariant ? "bold" : "thick", children: jsxs("div", { className: cvaKPIValueContainer({
|
|
2997
|
+
isDefaultAndHasTrendValue: Boolean(trend !== undefined && trend.value !== undefined && !isSmallVariant),
|
|
2984
2998
|
className,
|
|
2985
2999
|
}), children: [jsxs("span", { className: cvaKPIvalueText({ variant }), children: [value, " ", unit] }), jsx(TrendIndicator, { isSmallVariant: isSmallVariant, trend: trend, unit: unit })] }) })] })) }) }));
|
|
2986
3000
|
};
|
|
@@ -2988,7 +3002,7 @@ const TrendIndicator = ({ trend, unit, isSmallVariant }) => {
|
|
|
2988
3002
|
if (!trend) {
|
|
2989
3003
|
return null;
|
|
2990
3004
|
}
|
|
2991
|
-
return (jsxs("div", { className: "flex flex-row items-center gap-1", "data-testid": "trend-indicator", children: [!isSmallVariant && trend.value ? (jsxs(Text, { dataTestId: "trend-value", size: "small", weight: "normal", children: [trend.value, " ", unit] })) : null, trend.variant
|
|
3005
|
+
return (jsxs("div", { className: "flex flex-row items-center gap-1", "data-testid": "trend-indicator", children: [!isSmallVariant && trend.value !== undefined ? (jsxs(Text, { dataTestId: "trend-value", size: "small", weight: "normal", children: [trend.value, " ", unit] })) : null, trend.variant !== undefined && trend.variant.icon !== undefined ? (jsx(Icon, { color: trend.variant.color, name: trend.variant.icon, size: "small" })) : null, trend.percentage !== undefined ? (jsxs(Text, { className: cvaKPITrendPercentage({ color: trend.variant?.color }), size: "small", weight: "bold", children: [trend.percentage, "%"] })) : null] }));
|
|
2992
3006
|
};
|
|
2993
3007
|
|
|
2994
3008
|
const cvaKPICard = cvaMerge([
|
|
@@ -3033,14 +3047,14 @@ const cvaKPIIconContainer = cvaMerge(["flex", "items-center", "justify-center",
|
|
|
3033
3047
|
* @param {KPICardProps} props - The props for the KPICard component
|
|
3034
3048
|
* @returns {ReactElement} KPICard component
|
|
3035
3049
|
*/
|
|
3036
|
-
const KPICard = ({ isActive, onClick, className, dataTestId, children, iconName, iconColor, ...rest }) => {
|
|
3037
|
-
const isClickable = Boolean(onClick &&
|
|
3050
|
+
const KPICard = ({ isActive = false, onClick, className, dataTestId, children, iconName = undefined, iconColor = "info", loading = false, ...rest }) => {
|
|
3051
|
+
const isClickable = Boolean(onClick !== undefined && loading !== true);
|
|
3038
3052
|
return (jsx(Card, { className: cvaKPICard({
|
|
3039
3053
|
isClickable,
|
|
3040
3054
|
isActive,
|
|
3041
3055
|
minHeight: rest.trend ? "withTrends" : "default",
|
|
3042
3056
|
className,
|
|
3043
|
-
}), "data-testid": dataTestId ? dataTestId : undefined, onClick: onClick, children: jsxs(CardBody, { className: cvaCardBodyDensityContainer({ iconName: Boolean(iconName) }), density: "none", children: [jsx(KPI, { ...rest, className: twMerge(iconName ? "gap-2" : "", "p-0"), dataTestId: dataTestId ? `${dataTestId}-kpi` : undefined }), iconName ? (jsx("div", { className: cvaKPIIconContainer({ iconColor
|
|
3057
|
+
}), "data-testid": dataTestId ? dataTestId : undefined, onClick: onClick, children: jsxs(CardBody, { className: cvaCardBodyDensityContainer({ iconName: Boolean(iconName) }), density: "none", children: [jsx(KPI, { ...rest, className: twMerge(iconName ? "gap-2" : "", "p-0"), dataTestId: dataTestId ? `${dataTestId}-kpi` : undefined, loading: loading }), iconName ? (jsx("div", { className: cvaKPIIconContainer({ iconColor }), children: jsx(Icon, { name: iconName, size: "small", type: "solid" }) })) : null, children] }) }));
|
|
3044
3058
|
};
|
|
3045
3059
|
const cvaCardBodyDensityContainer = cvaMerge(["grid", "grid-cols-[1fr_auto]"], {
|
|
3046
3060
|
variants: {
|
|
@@ -3051,6 +3065,92 @@ const cvaCardBodyDensityContainer = cvaMerge(["grid", "grid-cols-[1fr_auto]"], {
|
|
|
3051
3065
|
},
|
|
3052
3066
|
});
|
|
3053
3067
|
|
|
3068
|
+
const cvaListContainer = cvaMerge(["h-full"], {
|
|
3069
|
+
variants: {
|
|
3070
|
+
parentControlledScrollable: {
|
|
3071
|
+
true: [""],
|
|
3072
|
+
false: ["overflow-auto"],
|
|
3073
|
+
},
|
|
3074
|
+
},
|
|
3075
|
+
defaultVariants: {
|
|
3076
|
+
parentControlledScrollable: false,
|
|
3077
|
+
},
|
|
3078
|
+
});
|
|
3079
|
+
const cvaList = cvaMerge(["relative"]);
|
|
3080
|
+
const cvaListItem$1 = cvaMerge(["absolute", "top-0", "left-0", "w-full"], {
|
|
3081
|
+
variants: {
|
|
3082
|
+
separator: {
|
|
3083
|
+
alternating: ["even:bg-slate-100"],
|
|
3084
|
+
line: ["[&:not(:last-child)]:border-b", "border-gray-200"],
|
|
3085
|
+
none: "",
|
|
3086
|
+
space: "[&:not(:last-child)]:pb-0.5",
|
|
3087
|
+
},
|
|
3088
|
+
},
|
|
3089
|
+
defaultVariants: {
|
|
3090
|
+
separator: "none",
|
|
3091
|
+
},
|
|
3092
|
+
});
|
|
3093
|
+
|
|
3094
|
+
/**
|
|
3095
|
+
* Render a performant virtualized list of items. Optionally with infinite scrolling.
|
|
3096
|
+
*
|
|
3097
|
+
* @property {number} count - The total number of items in the list.
|
|
3098
|
+
* @property {number} [rowHeight="40"] - The estimated height of each row in the list.
|
|
3099
|
+
* @property {RelayPagination | undefined} pagination - Pagination configuration for the list.
|
|
3100
|
+
* @property {separator} [separator="line"] - The separator style between items in the list.
|
|
3101
|
+
* @property {(index: number) =>ReactElement} children - A function that takes an index and returns the JSX element to be rendered at said index.
|
|
3102
|
+
* @property {loadingIndicator} [loadingIndicator="spinner"] - The type of loading indicator in the list.
|
|
3103
|
+
* @property {skeletonLinesHeight} [skeletonLinesHeight="2rem"] - The height of the skeleton lines.
|
|
3104
|
+
*/
|
|
3105
|
+
const List = ({ count, rowHeight = 40, pagination, children, className, dataTestId, separator = "none", loadingIndicator = "spinner", skeletonLinesHeight = rowHeight + "px", onRowClick, scrollRef, }) => {
|
|
3106
|
+
const containerRef = useRef(null);
|
|
3107
|
+
const listRef = useRef(null);
|
|
3108
|
+
const [scrollParent, setScrollParent] = useState(null);
|
|
3109
|
+
const [parentControlledScrollable, setParentControlledScrollable] = useState(false);
|
|
3110
|
+
useEffect(() => {
|
|
3111
|
+
if (scrollRef?.current) {
|
|
3112
|
+
setParentControlledScrollable(true);
|
|
3113
|
+
setScrollParent(scrollRef.current);
|
|
3114
|
+
}
|
|
3115
|
+
else {
|
|
3116
|
+
setParentControlledScrollable(false);
|
|
3117
|
+
setScrollParent(containerRef.current);
|
|
3118
|
+
}
|
|
3119
|
+
}, [scrollRef]);
|
|
3120
|
+
const infiniteScrollProps = useMemo(() => {
|
|
3121
|
+
return {
|
|
3122
|
+
pagination: pagination || noPagination,
|
|
3123
|
+
containerRef: { current: scrollParent },
|
|
3124
|
+
rowSize: pagination !== undefined &&
|
|
3125
|
+
pagination.pageInfo !== undefined &&
|
|
3126
|
+
pagination.pageInfo.hasNextPage === true &&
|
|
3127
|
+
pagination.isLoading === true
|
|
3128
|
+
? count + 1
|
|
3129
|
+
: count,
|
|
3130
|
+
rowHeight,
|
|
3131
|
+
};
|
|
3132
|
+
}, [pagination, scrollParent, count, rowHeight]);
|
|
3133
|
+
const { fetchMoreOnBottomReached, getVirtualItems, getTotalSize, measureElement } = useInfiniteScroll(infiniteScrollProps);
|
|
3134
|
+
useEffect(() => {
|
|
3135
|
+
if (scrollParent) {
|
|
3136
|
+
const handleScroll = () => {
|
|
3137
|
+
fetchMoreOnBottomReached(scrollParent);
|
|
3138
|
+
};
|
|
3139
|
+
scrollParent.addEventListener("scroll", handleScroll);
|
|
3140
|
+
return () => {
|
|
3141
|
+
scrollParent.removeEventListener("scroll", handleScroll);
|
|
3142
|
+
};
|
|
3143
|
+
}
|
|
3144
|
+
return undefined;
|
|
3145
|
+
}, [scrollParent, fetchMoreOnBottomReached]);
|
|
3146
|
+
return (jsx("div", { className: cvaListContainer({ parentControlledScrollable, className }), "data-testid": dataTestId, ref: containerRef, children: jsx("ul", { className: cvaList(), ref: listRef, style: { height: `${getTotalSize()}px`, outline: "none" }, children: getVirtualItems().map(virtualRow => {
|
|
3147
|
+
const isLoaderRow = virtualRow.index > count - 1;
|
|
3148
|
+
return (jsx("li", { className: cvaListItem$1({ separator }), "data-index": virtualRow.index, onClick: onRowClick !== undefined ? () => onRowClick(virtualRow.index) : undefined, ref: measureElement, style: {
|
|
3149
|
+
transform: `translateY(${virtualRow.start}px)`,
|
|
3150
|
+
}, tabIndex: -1, children: isLoaderRow ? (pagination?.isLoading === true ? (jsxs(Fragment, { children: [loadingIndicator === "spinner" && jsx(Spinner, { centering: "horizontally", containerClassName: "p-4" }), loadingIndicator === "skeletonLines" && (jsx(SkeletonLines, { height: skeletonLinesHeight, lines: 3, width: "full" }))] })) : null) : (children(virtualRow.index)) }, virtualRow.key));
|
|
3151
|
+
}) }) }));
|
|
3152
|
+
};
|
|
3153
|
+
|
|
3054
3154
|
/**
|
|
3055
3155
|
* Applies standardized interaction-related styles to an element.
|
|
3056
3156
|
*
|
|
@@ -3076,9 +3176,9 @@ const cvaInteractableItem = cvaMerge("", {
|
|
|
3076
3176
|
default: "cursor-default",
|
|
3077
3177
|
"not-allowed": "cursor-not-allowed",
|
|
3078
3178
|
},
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
|
|
3179
|
+
selection: {
|
|
3180
|
+
selected: ["bg-primary-50", "hover:bg-primary-50", "focus-within:bg-primary-50"],
|
|
3181
|
+
unselected: "",
|
|
3082
3182
|
auto: [
|
|
3083
3183
|
"hover:bg-neutral-100",
|
|
3084
3184
|
"has-[:checked]:bg-primary-50",
|
|
@@ -3091,24 +3191,24 @@ const cvaInteractableItem = cvaMerge("", {
|
|
|
3091
3191
|
true: ["pointer-events-none", "!bg-neutral-100", "!cursor-not-allowed"],
|
|
3092
3192
|
false: "", // use compoundVariants instead
|
|
3093
3193
|
},
|
|
3094
|
-
|
|
3095
|
-
|
|
3096
|
-
|
|
3194
|
+
focus: {
|
|
3195
|
+
focused: ["bg-neutral-600/5"],
|
|
3196
|
+
unfocused: "",
|
|
3097
3197
|
auto: "[&:has(:focus-visible)]:outline-native",
|
|
3098
3198
|
},
|
|
3099
3199
|
},
|
|
3100
3200
|
compoundVariants: [
|
|
3101
3201
|
{
|
|
3102
3202
|
disabled: false,
|
|
3103
|
-
|
|
3203
|
+
selection: "unselected",
|
|
3104
3204
|
className: ["hover:bg-neutral-600/5", "focus-within:bg-neutral-600/5"],
|
|
3105
3205
|
},
|
|
3106
3206
|
],
|
|
3107
3207
|
defaultVariants: {
|
|
3108
3208
|
cursor: "auto",
|
|
3109
|
-
|
|
3209
|
+
selection: "auto",
|
|
3110
3210
|
disabled: false,
|
|
3111
|
-
|
|
3211
|
+
focus: "auto",
|
|
3112
3212
|
},
|
|
3113
3213
|
});
|
|
3114
3214
|
|
|
@@ -3145,7 +3245,7 @@ const ListItem = ({ className, dataTestId, onClick, details, title, description,
|
|
|
3145
3245
|
}), children: thumbnail })) : null, jsxs("div", { className: "grid-rows-min-fr grid items-center text-sm", children: [jsx("div", { className: "gap-responsive-space-sm flex w-full min-w-0 items-center text-sm", children: typeof title === "string" ? (jsx(Text, { className: "truncate", dataTestId: dataTestId ? `${dataTestId}-title` : undefined, weight: "bold", children: title })) : (cloneElement(title, {
|
|
3146
3246
|
className: twMerge(title.props.className, "neutral-900 text-sm font-medium truncate"),
|
|
3147
3247
|
dataTestId: !title.props.dataTestId && dataTestId ? `${dataTestId}-title` : undefined,
|
|
3148
|
-
})) }), description ? (jsx("div", { className: "gap-responsive-space-sm flex w-full min-w-0 items-center", children: typeof description === "string" ? (jsx(Text, { className: "truncate text-xs text-neutral-500", dataTestId: dataTestId ? `${dataTestId}-description` : undefined, weight: "bold", children: description })) : (cloneElement(description, {
|
|
3248
|
+
})) }), description !== undefined && description !== "" ? (jsx("div", { className: "gap-responsive-space-sm flex w-full min-w-0 items-center", children: typeof description === "string" ? (jsx(Text, { className: "truncate text-xs text-neutral-500", dataTestId: dataTestId ? `${dataTestId}-description` : undefined, weight: "bold", children: description })) : (cloneElement(description, {
|
|
3149
3249
|
className: twMerge(description.props.className, "text-neutral-500 text-xs font-medium truncate"),
|
|
3150
3250
|
dataTestId: !description.props.dataTestId && dataTestId ? `${dataTestId}-description` : undefined,
|
|
3151
3251
|
})) })) : null, meta ? (jsx("div", { className: "gap-responsive-space-sm flex w-full min-w-0 items-center pt-0.5", children: jsx(Text, { className: "truncate text-xs text-neutral-400", dataTestId: dataTestId ? `${dataTestId}-meta` : undefined, weight: "bold", children: meta }) })) : null] })] }), jsxs("div", { className: "flex items-center gap-0.5 pl-2", children: [details, onClick ? jsx(Icon, { color: "neutral", name: "ChevronRight", size: "medium" }) : null] })] }));
|
|
@@ -3187,7 +3287,12 @@ const MenuDivider = () => {
|
|
|
3187
3287
|
*/
|
|
3188
3288
|
const cvaMenuItem = (props) => {
|
|
3189
3289
|
const { selected, disabled, focused, className, variant, fieldSize } = props ?? {};
|
|
3190
|
-
return twMerge(cvaMenuItemStyle({ variant, selected, disabled, fieldSize }), cvaInteractableItem({
|
|
3290
|
+
return twMerge(cvaMenuItemStyle({ variant, selected, disabled, fieldSize }), cvaInteractableItem({
|
|
3291
|
+
selection: selected === true ? "selected" : "unselected",
|
|
3292
|
+
disabled,
|
|
3293
|
+
cursor: "pointer",
|
|
3294
|
+
focus: focused === true ? "focused" : "unfocused",
|
|
3295
|
+
}), className);
|
|
3191
3296
|
};
|
|
3192
3297
|
const cvaMenuItemStyle = cvaMerge(["py-2", "px-2", "h-auto", "flex", "flex-row", "items-center", "gap-x-2", "select-none", "rounded", "text-sm"], {
|
|
3193
3298
|
variants: {
|
|
@@ -3300,10 +3405,10 @@ const cvaMenuItemSuffix = cvaMerge(["text-secondary-400", "text-sm", "flex", "it
|
|
|
3300
3405
|
* @param {MenuItemProps} props - The props for the MenuItem component
|
|
3301
3406
|
* @returns {ReactElement} MenuItem component
|
|
3302
3407
|
*/
|
|
3303
|
-
const MenuItem = ({ className, dataTestId, label, children, selected, focused, prefix, suffix, disabled, onClick, stopPropagation = true, id, tabIndex, optionLabelDescription, optionPrefix, fieldSize = "medium", variant = "primary", }) => {
|
|
3408
|
+
const MenuItem = ({ className, dataTestId, label, children, selected = false, focused = false, prefix, suffix, disabled = false, onClick, stopPropagation = true, id, tabIndex, optionLabelDescription, optionPrefix, fieldSize = "medium", variant = "primary", }) => {
|
|
3304
3409
|
/* Handle tab navigation */
|
|
3305
3410
|
const handleKeyDown = (e) => {
|
|
3306
|
-
if (e.key === "Enter" && onClick &&
|
|
3411
|
+
if (e.key === "Enter" && onClick !== undefined && disabled !== true) {
|
|
3307
3412
|
if (stopPropagation) {
|
|
3308
3413
|
e.stopPropagation();
|
|
3309
3414
|
}
|
|
@@ -3323,7 +3428,7 @@ const MenuItem = ({ className, dataTestId, label, children, selected, focused, p
|
|
|
3323
3428
|
e.stopPropagation();
|
|
3324
3429
|
}
|
|
3325
3430
|
onClick?.(e);
|
|
3326
|
-
}, onKeyDown: handleKeyDown, role: "menuitem", tabIndex: disabled ? -1 : (tabIndex ?? 0), children: [prefix ? (jsx("div", { className: cvaMenuItemPrefix({ selected, variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-prefix` : "menu-item-prefix", children: prefix })) : null, children && typeof children !== "string" ? (children) : (jsxs("div", { className: cvaMenuItemLabel({ variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-label` : "menu-item-label", children: [optionPrefix ? optionPrefix : null, children ?? label, optionLabelDescription ? jsxs("span", { className: "text-secondary-400 ml-1", children: ["(", optionLabelDescription, ")"] }) : null] })), suffix ? (jsx("div", { className: cvaMenuItemSuffix({ selected, variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-suffix` : "menu-item-suffix", children: suffix })) : null] }));
|
|
3431
|
+
}, onKeyDown: handleKeyDown, role: "menuitem", tabIndex: disabled ? -1 : (tabIndex ?? 0), children: [prefix !== null && prefix !== undefined ? (jsx("div", { className: cvaMenuItemPrefix({ selected, variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-prefix` : "menu-item-prefix", children: prefix })) : null, children !== null && children !== undefined && typeof children !== "string" ? (children) : (jsxs("div", { className: cvaMenuItemLabel({ variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-label` : "menu-item-label", children: [optionPrefix !== null && optionPrefix !== undefined ? optionPrefix : null, children ?? label, optionLabelDescription !== undefined && optionLabelDescription !== "" ? (jsxs("span", { className: "text-secondary-400 ml-1", children: ["(", optionLabelDescription, ")"] })) : null] })), suffix !== null && suffix !== undefined ? (jsx("div", { className: cvaMenuItemSuffix({ selected, variant, disabled }), "data-testid": dataTestId ? `${dataTestId}-suffix` : "menu-item-suffix", children: suffix })) : null] }));
|
|
3327
3432
|
};
|
|
3328
3433
|
|
|
3329
3434
|
/**
|
|
@@ -3341,16 +3446,13 @@ const MenuList = ({ dataTestId, className, children, withStickyHeader = false, i
|
|
|
3341
3446
|
const childrenArr = Children.toArray(children);
|
|
3342
3447
|
const [internalSelectedItems, setInternalSelectedItems] = useState(controlledSelectedItems ?? []);
|
|
3343
3448
|
const selectedItems = controlledSelectedItems ?? internalSelectedItems;
|
|
3344
|
-
const handleItemClick = useCallback((id
|
|
3345
|
-
if (disabled) {
|
|
3346
|
-
return;
|
|
3347
|
-
}
|
|
3449
|
+
const handleItemClick = useCallback((id) => {
|
|
3348
3450
|
const newSelectedItems = isMulti
|
|
3349
3451
|
? selectedItems.includes(id)
|
|
3350
3452
|
? selectedItems.filter(item => item !== id)
|
|
3351
3453
|
: [...selectedItems, id]
|
|
3352
3454
|
: [id];
|
|
3353
|
-
if (onSelectionChange) {
|
|
3455
|
+
if (onSelectionChange !== undefined) {
|
|
3354
3456
|
onSelectionChange(newSelectedItems);
|
|
3355
3457
|
}
|
|
3356
3458
|
else {
|
|
@@ -3359,13 +3461,15 @@ const MenuList = ({ dataTestId, className, children, withStickyHeader = false, i
|
|
|
3359
3461
|
}, [isMulti, selectedItems, onSelectionChange]);
|
|
3360
3462
|
return (jsx("div", { className: cvaMenuList({ stickyHeader: withStickyHeader, className }), "data-testid": dataTestId ? `${dataTestId}-menu-list` : "menu-list", onClick: args.onClick, role: "list", tabIndex: 0, children: childrenArr.map((menuItem, index) => {
|
|
3361
3463
|
if (isValidElement(menuItem)) {
|
|
3362
|
-
const isSelected = selectedItems.includes(menuItem.props.id ?? `${index}`) || menuItem.props.selected;
|
|
3464
|
+
const isSelected = (selectedItems.includes(menuItem.props.id ?? `${index}`) || menuItem.props.selected) ?? false;
|
|
3363
3465
|
return cloneElement(menuItem, {
|
|
3364
3466
|
...menuItem.props,
|
|
3365
3467
|
key: index,
|
|
3366
3468
|
onClick: (event) => {
|
|
3367
3469
|
menuItem.props.onClick?.(event);
|
|
3368
|
-
|
|
3470
|
+
if (menuItem.props.disabled !== true) {
|
|
3471
|
+
handleItemClick(menuItem.props.id ?? `${index}`);
|
|
3472
|
+
}
|
|
3369
3473
|
},
|
|
3370
3474
|
className: isMulti && isSelected
|
|
3371
3475
|
? cvaMenuListMultiSelect({ className: menuItem.props.className })
|
|
@@ -3447,7 +3551,7 @@ const cvaNoticeIcon = cvaMerge(["rounded-full", "items-center", "justify-center"
|
|
|
3447
3551
|
* @returns {ReactElement} Notice component
|
|
3448
3552
|
*/
|
|
3449
3553
|
const Notice = ({ dataTestId, icon, label, color = "neutral", withLabel = true, className, tooltipLabel = label, withTooltip = false, size = "medium", ...rest }) => {
|
|
3450
|
-
return (jsx(Tooltip, { className: className, disabled:
|
|
3554
|
+
return (jsx(Tooltip, { className: className, disabled: withTooltip === false, label: tooltipLabel, placement: "bottom", children: jsxs("div", { "aria-label": label, className: cvaNotice(), "data-testid": dataTestId, ...rest, children: [jsx("div", { className: cvaNoticeIcon({ color }), "data-testid": dataTestId ? `${dataTestId}-icon` : "notice-icon", children: icon }), label && withLabel ? (jsx("div", { className: cvaNoticeLabel({ color, size }), "data-testid": dataTestId ? `${dataTestId}-label` : "notice-label", children: label })) : null] }) }));
|
|
3451
3555
|
};
|
|
3452
3556
|
|
|
3453
3557
|
const cvaPage = cvaMerge(["grid", "h-full"], {
|
|
@@ -3480,7 +3584,7 @@ const cvaPageContent = cvaMerge(["overflow-auto", "page-content", "grid", "gap-r
|
|
|
3480
3584
|
* Renders the page component. Adds padding and layout to the page.
|
|
3481
3585
|
*/
|
|
3482
3586
|
const Page = ({ layout, className, children, dataTestId }) => {
|
|
3483
|
-
return (jsx("div", { className: cvaPage({ className, layout }), "data-testid": dataTestId
|
|
3587
|
+
return (jsx("div", { className: cvaPage({ className, layout }), "data-testid": dataTestId ? dataTestId : "page", children: children }));
|
|
3484
3588
|
};
|
|
3485
3589
|
|
|
3486
3590
|
/**
|
|
@@ -3495,17 +3599,30 @@ const PageContent = ({ className, children, dataTestId, layout }) => {
|
|
|
3495
3599
|
};
|
|
3496
3600
|
|
|
3497
3601
|
const LoadingContent = () => (jsx("div", { className: "flex flex-row items-center gap-3", "data-testid": "kpi-card-loading-content", children: jsx("div", { className: "w-full", children: jsx(SkeletonLines, { height: [16, 25], lines: 2, margin: "3px 0 0 0", width: [75, 50] }) }) }));
|
|
3602
|
+
/**
|
|
3603
|
+
* The PageHeaderKpiMetrics component is used to render the KPI metrics in the PageHeader component.
|
|
3604
|
+
*
|
|
3605
|
+
* @param {object} props - The props for the PageHeaderKpiMetrics component
|
|
3606
|
+
* @param {Array<PageHeaderKpiMetricsType>} props.kpiMetrics - The KPI metrics to render
|
|
3607
|
+
* @returns {ReactElement} PageHeaderKpiMetrics component
|
|
3608
|
+
*/
|
|
3498
3609
|
const PageHeaderKpiMetrics = ({ kpiMetrics }) => {
|
|
3499
3610
|
return (jsx("div", { className: "hidden items-center gap-4 md:flex", children: kpiMetrics
|
|
3500
|
-
.filter(kpi =>
|
|
3611
|
+
.filter(kpi => kpi.hidden === false || kpi.hidden === undefined)
|
|
3501
3612
|
.map((kpi, index) => {
|
|
3502
|
-
if (kpi.loading) {
|
|
3613
|
+
if (kpi.loading === true) {
|
|
3503
3614
|
return jsx(LoadingContent, {}, `${kpi}-${index}`);
|
|
3504
3615
|
}
|
|
3505
3616
|
return (jsxs("div", { className: "flex flex-col text-nowrap text-left", children: [jsx("span", { className: "text-xs text-slate-500", children: kpi.header }), jsxs("div", { className: "flex flex-row items-center gap-1", children: [jsx("span", { className: "text-lg font-medium text-slate-900", children: kpi.value }), kpi.unit ? jsx("span", { className: "text-xs text-slate-900", children: kpi.unit }) : null] })] }, `${kpi}-${index}`));
|
|
3506
3617
|
}) }));
|
|
3507
3618
|
};
|
|
3508
3619
|
|
|
3620
|
+
/**
|
|
3621
|
+
* The ActionRenderer component is used to render the action in the PageHeaderSecondaryActions component.
|
|
3622
|
+
*
|
|
3623
|
+
* @param {ActionRendererProps} props - The props for the ActionRenderer component
|
|
3624
|
+
* @returns {ReactElement} ActionRenderer component
|
|
3625
|
+
*/
|
|
3509
3626
|
function ActionRenderer({ action, isMenuItem = false, externalOnClick }) {
|
|
3510
3627
|
const { to, tooltipLabel, prefixIconName, disabled, actionText, actionCallback, dataTestId, target, variant } = action;
|
|
3511
3628
|
// This component handles all the "wrapping" logic for Link/Tooltip
|
|
@@ -3520,10 +3637,18 @@ function ActionRenderer({ action, isMenuItem = false, externalOnClick }) {
|
|
|
3520
3637
|
// Wrap `content` with Tooltip
|
|
3521
3638
|
const wrappedWithTooltip = tooltipLabel ? (jsx(Tooltip, { className: "block", label: tooltipLabel, children: content })) : (content);
|
|
3522
3639
|
// Finally, wrap with Link if `to` is provided
|
|
3523
|
-
return to ? (jsx(Link, { target: target, to: to, children: wrappedWithTooltip })) : (wrappedWithTooltip);
|
|
3640
|
+
return to !== undefined && to !== "" ? (jsx(Link, { target: target, to: to, children: wrappedWithTooltip })) : (wrappedWithTooltip);
|
|
3524
3641
|
}
|
|
3525
|
-
|
|
3526
|
-
|
|
3642
|
+
/**
|
|
3643
|
+
* The PageHeaderSecondaryActions component is used to render the secondary actions in the PageHeader component.
|
|
3644
|
+
*
|
|
3645
|
+
* @param {object} props - The props for the PageHeaderSecondaryActions component
|
|
3646
|
+
* @param {Array<PageHeaderSecondaryActionType>} props.actions - The secondary actions to render
|
|
3647
|
+
* @param {boolean} [props.hasPrimaryAction] - Whether there is a primary action present
|
|
3648
|
+
* @returns {ReactElement} PageHeaderSecondaryActions component
|
|
3649
|
+
*/
|
|
3650
|
+
const PageHeaderSecondaryActions = ({ actions, hasPrimaryAction = false, }) => {
|
|
3651
|
+
const enabledActions = useMemo(() => actions.filter(action => action.hidden === false || action.hidden === undefined), [actions]);
|
|
3527
3652
|
// If we need to render a "More Menu" because we have too many actions:
|
|
3528
3653
|
if (enabledActions.length > 2 || (hasPrimaryAction && enabledActions.length > 1)) {
|
|
3529
3654
|
// Separate them into danger vs. other
|
|
@@ -3535,7 +3660,7 @@ const PageHeaderSecondaryActions = ({ actions, hasPrimaryAction, }) => {
|
|
|
3535
3660
|
return [danger, [...others, action]];
|
|
3536
3661
|
}
|
|
3537
3662
|
}, [[], []]);
|
|
3538
|
-
return (jsx(MoreMenu, { dataTestId: "secondary-actions-more-menu", iconButtonProps: { size: "small", variant: "secondary" }, children: close => (jsxs(MenuList, { className: "min-w-[160px]", children: [otherActions.map((action, index) => (jsx(ActionRenderer, { action: action, externalOnClick: close, isMenuItem: true }, `${action.actionText}-${index}`))), dangerActions.length ? jsx(MenuDivider, {}) : null, dangerActions.map((action, index) => (jsx(ActionRenderer, { action: action, externalOnClick: close, isMenuItem: true }, `${action.actionText}-${index}`)))] })) }));
|
|
3663
|
+
return (jsx(MoreMenu, { dataTestId: "secondary-actions-more-menu", iconButtonProps: { size: "small", variant: "secondary" }, children: close => (jsxs(MenuList, { className: "min-w-[160px]", children: [otherActions.map((action, index) => (jsx(ActionRenderer, { action: action, externalOnClick: close, isMenuItem: true }, `${action.actionText}-${index}`))), dangerActions.length > 0 ? jsx(MenuDivider, {}) : null, dangerActions.map((action, index) => (jsx(ActionRenderer, { action: action, externalOnClick: close, isMenuItem: true }, `${action.actionText}-${index}`)))] })) }));
|
|
3539
3664
|
}
|
|
3540
3665
|
// Otherwise, render them inline as buttons
|
|
3541
3666
|
return (jsx("div", { className: "flex flex-row items-center gap-2", children: enabledActions
|
|
@@ -3562,6 +3687,14 @@ const cvaPageHeaderContainer = cvaMerge(["bg-white", "tu-page-header"], {
|
|
|
3562
3687
|
const cvaPageHeader = cvaMerge(["box-border", "py-4", "px-6", "flex", "items-center", "gap-y-1"]);
|
|
3563
3688
|
const cvaPageHeaderHeading = cvaMerge(["text-slate-900", "text-xl", "font-semibold", "truncate"]);
|
|
3564
3689
|
|
|
3690
|
+
/**
|
|
3691
|
+
* The PageHeaderTitle component is used to display the title of the page header.
|
|
3692
|
+
*
|
|
3693
|
+
* @param {object} props - The props for the PageHeaderTitle component
|
|
3694
|
+
* @param {string} props.title - The title of the page header
|
|
3695
|
+
* @param {string} [props.dataTestId] - The data test id of the page header title
|
|
3696
|
+
* @returns {ReactElement} PageHeaderTitle component
|
|
3697
|
+
*/
|
|
3565
3698
|
const PageHeaderTitle = ({ title, dataTestId }) => {
|
|
3566
3699
|
const { ref, isTextTruncated } = useIsTextTruncated();
|
|
3567
3700
|
return (jsx("div", { className: "flex flex-row items-center", children: jsx(Tooltip, { className: "grid min-w-16", disabled: !isTextTruncated, label: title, placement: "top", children: jsx("h1", { className: cvaPageHeaderHeading(), "data-testid": dataTestId ? `${dataTestId}-heading` : undefined, ref: ref, children: title }) }) }));
|
|
@@ -3577,21 +3710,21 @@ const PageHeaderTitle = ({ title, dataTestId }) => {
|
|
|
3577
3710
|
* @param {PageHeaderProps} props - The props for the PageHeader component
|
|
3578
3711
|
* @returns {ReactElement} PageHeader component
|
|
3579
3712
|
*/
|
|
3580
|
-
const PageHeader = ({ className, dataTestId, secondaryActions, showLoading, description, title, tagLabel, backTo, tagColor, tabsList, descriptionIcon, kpiMetrics, tagTooltipLabel, primaryAction, }) => {
|
|
3713
|
+
const PageHeader = ({ className, dataTestId, secondaryActions, showLoading = false, description, title, tagLabel, backTo, tagColor, tabsList, descriptionIcon = "QuestionMarkCircle", kpiMetrics, tagTooltipLabel, primaryAction, }) => {
|
|
3581
3714
|
const tagRenderer = useMemo(() => {
|
|
3582
|
-
if (
|
|
3715
|
+
if (tagLabel === undefined || tagLabel === "" || showLoading) {
|
|
3583
3716
|
return null;
|
|
3584
3717
|
}
|
|
3585
3718
|
// If the user passes a string, we render the string as a tag with props provided.
|
|
3586
|
-
return (jsx("div", { className: "ml-auto flex flex-row gap-2", children: jsx(Tooltip, { dataTestId: "page-header-tag-tooltip", disabled:
|
|
3719
|
+
return (jsx("div", { className: "ml-auto flex flex-row gap-2", children: jsx(Tooltip, { dataTestId: "page-header-tag-tooltip", disabled: tagTooltipLabel === undefined || tagTooltipLabel === "", label: tagTooltipLabel, placement: "top", children: jsx(Tag, { color: tagColor, dataTestId: "page-header-tag", children: tagLabel }) }) }));
|
|
3587
3720
|
}, [showLoading, tagColor, tagLabel, tagTooltipLabel]);
|
|
3588
3721
|
return (jsxs("div", { className: cvaPageHeaderContainer({
|
|
3589
3722
|
className,
|
|
3590
|
-
withBorder:
|
|
3591
|
-
}), "data-testid": dataTestId, children: [jsxs("div", { className: cvaPageHeader(), children: [backTo ? (jsx(Link, { to: backTo, children: jsx(Button, { className: "mr-4 bg-black/5 hover:bg-black/10", prefix: jsx(Icon, { name: "ArrowLeft", size: "small" }), size: "medium", square: true, variant: "ghost-neutral" }) })) : undefined, typeof title === "string" ? jsx(PageHeaderTitle, { dataTestId: dataTestId, title: title }) : title, tagRenderer || description ? (jsxs("div", { className: "mx-2 flex items-center gap-2", children: [description && !showLoading ? (jsx(Tooltip, { dataTestId: dataTestId ? `${dataTestId}-description-tooltip` : undefined, iconProps: {
|
|
3592
|
-
name: descriptionIcon
|
|
3723
|
+
withBorder: tabsList === undefined,
|
|
3724
|
+
}), "data-testid": dataTestId, children: [jsxs("div", { className: cvaPageHeader(), children: [backTo ? (jsx(Link, { to: backTo, children: jsx(Button, { className: "mr-4 bg-black/5 hover:bg-black/10", prefix: jsx(Icon, { name: "ArrowLeft", size: "small" }), size: "medium", square: true, variant: "ghost-neutral" }) })) : undefined, typeof title === "string" ? jsx(PageHeaderTitle, { dataTestId: dataTestId, title: title }) : title, tagRenderer || (description !== null && description !== undefined) ? (jsxs("div", { className: "mx-2 flex items-center gap-2", children: [description !== null && description !== undefined && !showLoading ? (jsx(Tooltip, { dataTestId: dataTestId ? `${dataTestId}-description-tooltip` : undefined, iconProps: {
|
|
3725
|
+
name: descriptionIcon,
|
|
3593
3726
|
dataTestId: "page-header-description-icon",
|
|
3594
|
-
}, label: description, placement: "bottom" })) : undefined, tagRenderer] })) : null, jsxs("div", { className: "ml-auto flex gap-2", children: [kpiMetrics ? jsx(PageHeaderKpiMetrics, { kpiMetrics: kpiMetrics }) : null, Array.isArray(secondaryActions) ? (jsx(PageHeaderSecondaryActions, { actions: secondaryActions, hasPrimaryAction: !!primaryAction })) : secondaryActions ? (secondaryActions) : null, primaryAction &&
|
|
3727
|
+
}, label: description, placement: "bottom" })) : undefined, tagRenderer] })) : null, jsxs("div", { className: "ml-auto flex gap-2", children: [kpiMetrics ? jsx(PageHeaderKpiMetrics, { kpiMetrics: kpiMetrics }) : null, Array.isArray(secondaryActions) ? (jsx(PageHeaderSecondaryActions, { actions: secondaryActions, hasPrimaryAction: !!primaryAction })) : secondaryActions !== null && secondaryActions !== undefined ? (secondaryActions) : null, primaryAction !== undefined && (primaryAction.hidden === false || primaryAction.hidden === undefined) ? (jsx(Tooltip, { disabled: primaryAction.tooltipLabel === undefined || primaryAction.tooltipLabel === "", label: primaryAction.tooltipLabel, children: jsx(Button, { dataTestId: primaryAction.dataTestId, disabled: primaryAction.disabled, loading: primaryAction.loading, onClick: () => primaryAction.actionCallback?.(), prefix: primaryAction.prefixIconName !== undefined ? (jsx(Icon, { name: primaryAction.prefixIconName, size: "small" })) : undefined, size: "medium", variant: primaryAction.variant, children: primaryAction.actionText }) })) : null] })] }), tabsList] }));
|
|
3595
3728
|
};
|
|
3596
3729
|
|
|
3597
3730
|
const cvaPagination = cvaMerge(["flex", "items-center", "gap-1"]);
|
|
@@ -3603,7 +3736,7 @@ const cvaPaginationText = cvaMerge("whitespace-nowrap");
|
|
|
3603
3736
|
* @param {PaginationProps} props - The props for the Pagination component
|
|
3604
3737
|
* @returns {ReactElement} Pagination component
|
|
3605
3738
|
*/
|
|
3606
|
-
const Pagination = ({ previousPage, nextPage, canPreviousPage, canNextPage, pageCount, pageIndex, loading, className, dataTestId, getTranslatedCount, onPageChange, cursorBase, }) => {
|
|
3739
|
+
const Pagination = ({ previousPage, nextPage, canPreviousPage = false, canNextPage = false, pageCount, pageIndex, loading = false, className, dataTestId, getTranslatedCount, onPageChange, cursorBase = false, }) => {
|
|
3607
3740
|
const [page, setPage] = useState(pageIndex);
|
|
3608
3741
|
const [currentPage, setCurrentPage] = useState(String(pageIndex !== undefined ? pageIndex + 1 : 1));
|
|
3609
3742
|
if (!loading && pageCount === undefined) {
|
|
@@ -3652,7 +3785,7 @@ const STROKE_WIDTH_THRESHOLD = 32;
|
|
|
3652
3785
|
* @param { PolygonProps} props - The props for the Polygon component
|
|
3653
3786
|
* @returns {ReactElement} Polygon component
|
|
3654
3787
|
*/
|
|
3655
|
-
const Polygon = ({ points, size, color = "black", opaque = true, className, dataTestId }) => {
|
|
3788
|
+
const Polygon = ({ points, size, color = "black", opaque = true, className, dataTestId, }) => {
|
|
3656
3789
|
// Calculate the bounds of the points
|
|
3657
3790
|
const minX = Math.min(...points.map(coord => coord[0]));
|
|
3658
3791
|
const maxX = Math.max(...points.map(coord => coord[0]));
|
|
@@ -3755,7 +3888,7 @@ const Spacer = ({ size = "medium", border = false, dataTestId, className }) => {
|
|
|
3755
3888
|
* @returns {ReactElement} SectionHeader component
|
|
3756
3889
|
*/
|
|
3757
3890
|
const SectionHeader = ({ title, subtitle, dataTestId, addons }) => {
|
|
3758
|
-
return (jsxs("div", { className: "flex flex-col", children: [jsx(HelmetProvider, { children: jsx(Helmet, { title: title }) }), jsxs("div", { className: "mb-2 flex flex-row gap-2", children: [jsxs("div", { className: "flex grow flex-col gap-2", children: [jsx(Heading, { dataTestId: dataTestId, variant: "secondary", children: title }), subtitle ? (jsx(Heading, { subtle: true, variant: "subtitle", children: subtitle })) : null] }), addons ? jsx("div", { className: "flex gap-2", children: addons }) : null] }), jsx(Spacer, { size: "small" })] }));
|
|
3891
|
+
return (jsxs("div", { className: "flex flex-col", children: [jsx(HelmetProvider, { children: jsx(Helmet, { title: title }) }), jsxs("div", { className: "mb-2 flex flex-row gap-2", children: [jsxs("div", { className: "flex grow flex-col gap-2", children: [jsx(Heading, { dataTestId: dataTestId, variant: "secondary", children: title }), subtitle ? (jsx(Heading, { subtle: true, variant: "subtitle", children: subtitle })) : null] }), addons !== null && addons !== undefined ? jsx("div", { className: "flex gap-2", children: addons }) : null] }), jsx(Spacer, { size: "small" })] }));
|
|
3759
3892
|
};
|
|
3760
3893
|
|
|
3761
3894
|
const cvaSidebar = cvaMerge(["apply", "grid", "grid-cols-fr-min", "items-center"]);
|
|
@@ -3789,7 +3922,7 @@ const useOverflowItems = ({ threshold = 1, childUniqueIdentifierAttribute = "id"
|
|
|
3789
3922
|
entries.forEach(entry => {
|
|
3790
3923
|
// @ts-expect-error - suppressImplicitAnyIndexErrors
|
|
3791
3924
|
const targetElementId = entry.target[childUniqueIdentifierAttribute];
|
|
3792
|
-
if (targetElementId) {
|
|
3925
|
+
if (targetElementId !== null && targetElementId !== undefined) {
|
|
3793
3926
|
updatedEntries[targetElementId] = entry.isIntersecting ? false : true;
|
|
3794
3927
|
}
|
|
3795
3928
|
});
|
|
@@ -3845,19 +3978,19 @@ const Sidebar = ({ childContainerClassName, children, breakpoint = "lg", classNa
|
|
|
3845
3978
|
});
|
|
3846
3979
|
const overflowItemCount = objectValues(itemOverflowMap).filter(isOverflowing => isOverflowing).length;
|
|
3847
3980
|
const itemVisibilityClassName = (id) => {
|
|
3848
|
-
if (itemOverflowMap[id]) {
|
|
3981
|
+
if (itemOverflowMap[id] === true) {
|
|
3849
3982
|
return "invisible";
|
|
3850
3983
|
}
|
|
3851
3984
|
return "visible";
|
|
3852
3985
|
};
|
|
3853
|
-
return (jsxs("div", { className: cvaSidebar({ className }), "data-testid": dataTestId, children: [jsx("div", { className: cvaSidebarChildContainer({ breakpoint, className: childContainerClassName }), "data-testid":
|
|
3986
|
+
return (jsxs("div", { className: cvaSidebar({ className }), "data-testid": dataTestId, children: [jsx("div", { className: cvaSidebarChildContainer({ breakpoint, className: childContainerClassName }), "data-testid": `${dataTestId}-child-container`, ref: overflowContainerRef, children: Children.map(children, child => {
|
|
3854
3987
|
return cloneElement(child, {
|
|
3855
3988
|
className: twMerge(child.props.className, itemVisibilityClassName(child.props.id)),
|
|
3856
3989
|
});
|
|
3857
3990
|
}) }), overflowItemCount > 0 ? (jsx(MoreMenu, { iconButtonProps: {
|
|
3858
3991
|
variant: "ghost-neutral",
|
|
3859
|
-
}, ...moreMenuProps, className: moreMenuProps?.className, dataTestId:
|
|
3860
|
-
return itemOverflowMap[child.props.id]
|
|
3992
|
+
}, ...moreMenuProps, className: moreMenuProps?.className, dataTestId: `${dataTestId}-more-menu`, children: close => (jsx(MenuList, { ...menuListProps, dataTestId: dataTestId, children: Children.map(children, child => {
|
|
3993
|
+
return itemOverflowMap[child.props.id] === true
|
|
3861
3994
|
? cloneElement(child, {
|
|
3862
3995
|
onClick: () => {
|
|
3863
3996
|
child.props.onClick?.();
|
|
@@ -3920,8 +4053,8 @@ const cvaTab = cvaMerge([
|
|
|
3920
4053
|
* Wrapper for radix tab component.
|
|
3921
4054
|
* We add a custom implementation of the asChild prop to make it easy to make the child element look like other tabs.
|
|
3922
4055
|
*/
|
|
3923
|
-
const Tab = ({ value, isFullWidth = false, iconName, dataTestId, className, children, suffix, asChild, appendTabStylesToChildIfAsChild = true, ...rest }) => {
|
|
3924
|
-
const renderContent = () => (jsxs(Fragment, { children: [iconName ? jsx(Icon, { name: iconName, size: "small" }) : null, isValidElement(children) ? children.props.children : children, suffix] }));
|
|
4056
|
+
const Tab = ({ value, isFullWidth = false, iconName = undefined, dataTestId, className, children, suffix, asChild = false, appendTabStylesToChildIfAsChild = true, ...rest }) => {
|
|
4057
|
+
const renderContent = () => (jsxs(Fragment, { children: [iconName !== undefined ? jsx(Icon, { name: iconName, size: "small" }) : null, isValidElement(children) ? children.props.children : children, suffix] }));
|
|
3925
4058
|
const commonProps = {
|
|
3926
4059
|
className: appendTabStylesToChildIfAsChild ? cvaTab({ className, isFullWidth }) : className,
|
|
3927
4060
|
...rest,
|
|
@@ -3943,7 +4076,7 @@ const TabContent = ({ className, dataTestId, children, ...rest }) => {
|
|
|
3943
4076
|
* Wrapper for radix tab list component.
|
|
3944
4077
|
*/
|
|
3945
4078
|
const TabList = ({ className, dataTestId, children, ...rest }) => {
|
|
3946
|
-
return (jsx(List, { className: cvaTabList({ className }), "data-testid": dataTestId, ...rest, children: children }));
|
|
4079
|
+
return (jsx(List$1, { className: cvaTabList({ className }), "data-testid": dataTestId, ...rest, children: children }));
|
|
3947
4080
|
};
|
|
3948
4081
|
|
|
3949
4082
|
/**
|
|
@@ -4081,8 +4214,8 @@ const ToggleGroup = ({ list, selected, setSelected, onChange, disabled = false,
|
|
|
4081
4214
|
const containerPadding = 2; // p-0.5 = 2px
|
|
4082
4215
|
const gap = 4;
|
|
4083
4216
|
const slidingLeft = containerPadding +
|
|
4084
|
-
buttonRefs.current.slice(0, validIndex).reduce((sum, ref) => sum + (ref?.offsetWidth
|
|
4085
|
-
const slidingWidth = buttonRefs.current[validIndex]?.offsetWidth
|
|
4217
|
+
buttonRefs.current.slice(0, validIndex).reduce((sum, ref) => sum + (ref?.offsetWidth ?? 0) + gap, 0);
|
|
4218
|
+
const slidingWidth = buttonRefs.current[validIndex]?.offsetWidth ?? 0;
|
|
4086
4219
|
useEffect(() => {
|
|
4087
4220
|
setIsMounted(true);
|
|
4088
4221
|
}, []);
|
|
@@ -4102,7 +4235,7 @@ const ToggleItem = ({ title, onClick, disabled, isIconOnly, iconName, size, clas
|
|
|
4102
4235
|
className,
|
|
4103
4236
|
selected,
|
|
4104
4237
|
disabled,
|
|
4105
|
-
}), dataTestId: dataTestId, disabled: disabled, icon: iconName ? (jsx(Icon, { className: cvaToggleItemContent({ selected, disabled }), name: iconName, size: size === "large" ? "medium" : "small" })) : null, isIconOnly: isIconOnly, onClick: onClick, ref: ref, size: size, title: title }) })) : (jsx(Tooltip, { disabled: !tooltip?.content &&
|
|
4238
|
+
}), dataTestId: dataTestId, disabled: disabled, icon: iconName ? (jsx(Icon, { className: cvaToggleItemContent({ selected, disabled }), name: iconName, size: size === "large" ? "medium" : "small" })) : null, isIconOnly: isIconOnly, onClick: onClick, ref: ref, size: size, title: title }) })) : (jsx(Tooltip, { disabled: !tooltip?.content && text?.truncate === false, label: tooltip?.content || title, placement: tooltip?.placement || "top", children: jsx(ToggleButton, { className: cvaToggleItem({
|
|
4106
4239
|
className,
|
|
4107
4240
|
selected,
|
|
4108
4241
|
disabled,
|
|
@@ -4168,7 +4301,7 @@ const cvaValueBarText = cvaMerge(["whitespace-nowrap"], {
|
|
|
4168
4301
|
*/
|
|
4169
4302
|
const getScore = (value, min, max, zeroScoreAllowed) => {
|
|
4170
4303
|
if (value <= min) {
|
|
4171
|
-
if (zeroScoreAllowed) {
|
|
4304
|
+
if (zeroScoreAllowed === true) {
|
|
4172
4305
|
return 0;
|
|
4173
4306
|
}
|
|
4174
4307
|
return 0.01; // always render at least some small fragment
|
|
@@ -4201,10 +4334,10 @@ const getDefaultFillColor = (score) => {
|
|
|
4201
4334
|
* @returns {string} color value
|
|
4202
4335
|
*/
|
|
4203
4336
|
const getFillColor = (score, levelColors) => {
|
|
4204
|
-
if (levelColors.low && score < (levelColors.low.level
|
|
4337
|
+
if (levelColors.low !== undefined && score < (levelColors.low.level !== undefined ? levelColors.low.level : 0)) {
|
|
4205
4338
|
return levelColors.low.color;
|
|
4206
4339
|
}
|
|
4207
|
-
if (levelColors.high && score >= (levelColors.high.level
|
|
4340
|
+
if (levelColors.high !== undefined && score >= (levelColors.high.level !== undefined ? levelColors.high.level : 0)) {
|
|
4208
4341
|
return levelColors.high.color;
|
|
4209
4342
|
}
|
|
4210
4343
|
return levelColors.medium?.color ?? color("WARNING", 300);
|
|
@@ -4229,94 +4362,13 @@ const getValueBarColorByValue = (value, min, max, levelColors) => {
|
|
|
4229
4362
|
* @param {ValueBarProps} props - The props for the ValueBar component
|
|
4230
4363
|
* @returns {ReactElement} ValueBar component
|
|
4231
4364
|
*/
|
|
4232
|
-
const ValueBar = ({ value, min = 0, max = 100, unit, size = "small", levelColors, valueColor, showValue, className, dataTestId, zeroScoreAllowed, }) => {
|
|
4365
|
+
const ValueBar = ({ value, min = 0, max = 100, unit, size = "small", levelColors, valueColor, showValue = false, className, dataTestId, zeroScoreAllowed = false, }) => {
|
|
4233
4366
|
const score = getScore(value, min, max, zeroScoreAllowed);
|
|
4234
4367
|
const barFillColor = levelColors ? getFillColor(score, levelColors) : getDefaultFillColor(score);
|
|
4235
4368
|
const valueText = `${Number(value.toFixed(1))}${nonNullable(unit) ? unit : ""}`;
|
|
4236
4369
|
return (jsxs("span", { className: "relative flex items-center gap-2", "data-testid": dataTestId, children: [jsx("progress", { "aria-label": valueText, className: cvaValueBar({ className, size }), max: 100, style: { color: barFillColor }, value: score * 100 }), showValue && (size === "small" || size === "large") ? (jsx(Text, { className: cvaValueBarText({ size }), dataTestId: dataTestId ? `${dataTestId}-value` : undefined, children: jsx("span", { style: valueColor ? { color: valueColor } : undefined, children: valueText }) })) : null] }));
|
|
4237
4370
|
};
|
|
4238
4371
|
|
|
4239
|
-
const cvaVirtualizedListContainer = cvaMerge(["h-full"], {
|
|
4240
|
-
variants: {
|
|
4241
|
-
parentControlledScrollable: {
|
|
4242
|
-
true: [""],
|
|
4243
|
-
false: ["overflow-auto"],
|
|
4244
|
-
},
|
|
4245
|
-
},
|
|
4246
|
-
defaultVariants: {
|
|
4247
|
-
parentControlledScrollable: false,
|
|
4248
|
-
},
|
|
4249
|
-
});
|
|
4250
|
-
const cvaVirtualizedList = cvaMerge(["relative"]);
|
|
4251
|
-
const cvaVirtualizedListItem = cvaMerge(["absolute", "top-0", "left-0", "w-full"], {
|
|
4252
|
-
variants: {
|
|
4253
|
-
separator: {
|
|
4254
|
-
alternating: ["even:bg-slate-100"],
|
|
4255
|
-
line: ["[&:not(:last-child)]:border-b", "border-gray-200"],
|
|
4256
|
-
none: "",
|
|
4257
|
-
space: "[&:not(:last-child)]:pb-0.5",
|
|
4258
|
-
},
|
|
4259
|
-
},
|
|
4260
|
-
defaultVariants: {
|
|
4261
|
-
separator: "none",
|
|
4262
|
-
},
|
|
4263
|
-
});
|
|
4264
|
-
|
|
4265
|
-
/**
|
|
4266
|
-
* Render a performant virtualized list of items. Optionally with infinite scrolling.
|
|
4267
|
-
*
|
|
4268
|
-
* @property {number} count - The total number of items in the list.
|
|
4269
|
-
* @property {number} [rowHeight="40"] - The estimated height of each row in the list.
|
|
4270
|
-
* @property {RelayPagination | undefined} pagination - Pagination configuration for the list.
|
|
4271
|
-
* @property {separator} [separator="line"] - The separator style between items in the list.
|
|
4272
|
-
* @property {(index: number) =>ReactElement} children - A function that takes an index and returns the JSX element to be rendered at said index.
|
|
4273
|
-
* @property {loadingIndicator} [loadingIndicator="spinner"] - The type of loading indicator in the list.
|
|
4274
|
-
* @property {skeletonLinesHeight} [skeletonLinesHeight="2rem"] - The height of the skeleton lines.
|
|
4275
|
-
*/
|
|
4276
|
-
const VirtualizedList = ({ count, rowHeight = 40, pagination, children, className, dataTestId, separator = "none", loadingIndicator = "spinner", skeletonLinesHeight = rowHeight + "px", onRowClick, scrollRef, }) => {
|
|
4277
|
-
const containerRef = useRef(null);
|
|
4278
|
-
const listRef = useRef(null);
|
|
4279
|
-
const [scrollParent, setScrollParent] = useState(null);
|
|
4280
|
-
const [parentControlledScrollable, setParentControlledScrollable] = useState(false);
|
|
4281
|
-
useEffect(() => {
|
|
4282
|
-
if (scrollRef?.current) {
|
|
4283
|
-
setParentControlledScrollable(true);
|
|
4284
|
-
setScrollParent(scrollRef.current);
|
|
4285
|
-
}
|
|
4286
|
-
else {
|
|
4287
|
-
setParentControlledScrollable(false);
|
|
4288
|
-
setScrollParent(containerRef.current);
|
|
4289
|
-
}
|
|
4290
|
-
}, [scrollRef]);
|
|
4291
|
-
const infiniteScrollProps = useMemo(() => {
|
|
4292
|
-
return {
|
|
4293
|
-
pagination: pagination || noPagination,
|
|
4294
|
-
containerRef: { current: scrollParent },
|
|
4295
|
-
rowSize: pagination?.pageInfo?.hasNextPage && pagination.isLoading ? count + 1 : count,
|
|
4296
|
-
rowHeight,
|
|
4297
|
-
};
|
|
4298
|
-
}, [pagination, scrollParent, count, rowHeight]);
|
|
4299
|
-
const { fetchMoreOnBottomReached, getVirtualItems, getTotalSize, measureElement } = useInfiniteScroll(infiniteScrollProps);
|
|
4300
|
-
useEffect(() => {
|
|
4301
|
-
if (scrollParent) {
|
|
4302
|
-
const handleScroll = () => {
|
|
4303
|
-
fetchMoreOnBottomReached(scrollParent);
|
|
4304
|
-
};
|
|
4305
|
-
scrollParent.addEventListener("scroll", handleScroll);
|
|
4306
|
-
return () => {
|
|
4307
|
-
scrollParent.removeEventListener("scroll", handleScroll);
|
|
4308
|
-
};
|
|
4309
|
-
}
|
|
4310
|
-
return undefined;
|
|
4311
|
-
}, [scrollParent, fetchMoreOnBottomReached]);
|
|
4312
|
-
return (jsx("div", { className: cvaVirtualizedListContainer({ parentControlledScrollable, className }), "data-testid": dataTestId, ref: containerRef, children: jsx("ul", { className: cvaVirtualizedList(), ref: listRef, style: { height: `${getTotalSize()}px`, outline: "none" }, children: getVirtualItems().map(virtualRow => {
|
|
4313
|
-
const isLoaderRow = virtualRow.index > count - 1;
|
|
4314
|
-
return (jsx("li", { className: cvaVirtualizedListItem({ separator }), "data-index": virtualRow.index, onClick: onRowClick ? () => onRowClick(virtualRow.index) : undefined, ref: measureElement, style: {
|
|
4315
|
-
transform: `translateY(${virtualRow.start}px)`,
|
|
4316
|
-
}, tabIndex: -1, children: isLoaderRow ? (pagination?.isLoading ? (jsxs(Fragment, { children: [loadingIndicator === "spinner" && jsx(Spinner, { centering: "horizontally", containerClassName: "p-4" }), loadingIndicator === "skeletonLines" && (jsx(SkeletonLines, { height: skeletonLinesHeight, lines: 3, width: "full" }))] })) : null) : (children(virtualRow.index)) }, virtualRow.key));
|
|
4317
|
-
}) }) }));
|
|
4318
|
-
};
|
|
4319
|
-
|
|
4320
4372
|
const cvaZStackContainer = cvaMerge(["grid", "grid-cols-1", "grid-rows-1"]);
|
|
4321
4373
|
const cvaZStackItem = cvaMerge(["col-start-1", "col-end-1", "row-start-1", "row-end-2"]);
|
|
4322
4374
|
|
|
@@ -4363,4 +4415,4 @@ const cvaClickable = cvaMerge([
|
|
|
4363
4415
|
},
|
|
4364
4416
|
});
|
|
4365
4417
|
|
|
4366
|
-
export { ActionRenderer, Alert, Badge, Breadcrumb, BreadcrumbContainer, Button, Card, CardBody, CardFooter, CardHeader, Collapse, CompletionStatusIndicator, CopyableText, DetailsList, EmptyState, EmptyValue, ExternalLink, Heading, Highlight, Icon, IconButton, Indicator, KPI, KPICard, ListItem, MenuDivider, MenuItem, MenuList, MoreMenu, Notice, PackageNameStoryComponent, Page, PageContent, PageHeader, PageHeaderKpiMetrics, PageHeaderSecondaryActions, PageHeaderTitle, Pagination, Polygon, Popover, PopoverContent, PopoverTitle, PopoverTrigger, Portal, Prompt, ROLE_CARD, SectionHeader, Sidebar, SkeletonLines, Spacer, Spinner, StarButton, Tab, TabContent, TabList, Tabs, Tag, Text, ToggleGroup, Tooltip, ValueBar,
|
|
4418
|
+
export { ActionRenderer, Alert, Badge, Breadcrumb, BreadcrumbContainer, Button, Card, CardBody, CardFooter, CardHeader, Collapse, CompletionStatusIndicator, CopyableText, DetailsList, EmptyState, EmptyValue, ExternalLink, Heading, Highlight, Icon, IconButton, Indicator, KPI, KPICard, List, ListItem, MenuDivider, MenuItem, MenuList, MoreMenu, Notice, PackageNameStoryComponent, Page, PageContent, PageHeader, PageHeaderKpiMetrics, PageHeaderSecondaryActions, PageHeaderTitle, Pagination, Polygon, Popover, PopoverContent, PopoverTitle, PopoverTrigger, Portal, Prompt, ROLE_CARD, SectionHeader, Sidebar, SkeletonLines, Spacer, Spinner, StarButton, Tab, TabContent, TabList, Tabs, Tag, Text, ToggleGroup, Tooltip, ValueBar, ZStack, cvaButton, cvaButtonPrefixSuffix, cvaButtonSpinner, cvaButtonSpinnerContainer, cvaClickable, cvaContainerStyles, cvaIconButton, cvaImgStyles, cvaIndicator, cvaIndicatorIcon, cvaIndicatorIconBackground, cvaIndicatorLabel, cvaIndicatorPing, cvaInteractableItem, cvaList, cvaListContainer, cvaListItem$1 as cvaListItem, cvaMenuItem, cvaMenuItemLabel, cvaMenuItemPrefix, cvaMenuItemStyle, cvaMenuItemSuffix, cvaPageHeader, cvaPageHeaderContainer, cvaPageHeaderHeading, cvaToggleGroup, cvaToggleGroupWithSlidingBackground, cvaToggleItem, cvaToggleItemContent, cvaToggleItemText, cvaZStackContainer, cvaZStackItem, docs, getDevicePixelRatio, getValueBarColorByValue, iconColorNames, iconPalette, useClickOutside, useContainerBreakpoints, useContinuousTimeout, useDebounce, useDevicePixelRatio, useElevatedReducer, useElevatedState, useGeometry, useHover, useIsFirstRender, useIsFullscreen, useIsTextTruncated, useModifierKey, useOverflowItems, usePopoverContext, usePrompt, useResize, useScrollDetection, useSelfUpdatingRef, useTimeout, useViewportBreakpoints, useWatch, useWindowActivity };
|