@trackunit/react-components 0.1.66 → 0.1.67

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 CHANGED
@@ -9,7 +9,6 @@ var uiIcons = require('@trackunit/ui-icons');
9
9
  var reactUse = require('react-use');
10
10
  var dateFns = require('date-fns');
11
11
  var react = require('@floating-ui/react');
12
- var reactRouterDom = require('react-router-dom');
13
12
  var reactDayPicker = require('react-day-picker');
14
13
  var locale = require('date-fns/locale');
15
14
  var reactBrowserHooks = require('react-browser-hooks');
@@ -19,6 +18,7 @@ var ReactAsyncCreatableSelect = require('react-select/async-creatable');
19
18
  var ReactCreatableSelect = require('react-select/creatable');
20
19
  var ReactAsyncSelect = require('react-select/async');
21
20
  var libphonenumberJs = require('libphonenumber-js');
21
+ var reactRouterDom = require('react-router-dom');
22
22
  var reactHelmetAsync = require('react-helmet-async');
23
23
  var uiDesignTokens = require('@trackunit/ui-design-tokens');
24
24
 
@@ -392,7 +392,7 @@ const CustomIcon = tailwindStyledComponents.twx(Icon) `
392
392
  * @returns {JSX.Element} Text component
393
393
  */
394
394
  const Text$1 = ({ children, type = "p", size = "medium", align = "left", weight = "normal", underline = false, inverted = false, subtle = false, italicize = false, uppercase = false, className, dataTestId, }) => {
395
- return (jsxRuntime.jsx(StyledText$4, Object.assign({ "$as": type, className: className, "$align": align, "$inverted": inverted, "$subtle": subtle, "$italicize": italicize, "$uppercase": uppercase, "$size": size, "$weight": weight, "$underline": underline, "data-testid": dataTestId }, { children: children })));
395
+ return (jsxRuntime.jsx(StyledText$3, Object.assign({ "$as": type, className: className, "$align": align, "$inverted": inverted, "$subtle": subtle, "$italicize": italicize, "$uppercase": uppercase, "$size": size, "$weight": weight, "$underline": underline, "data-testid": dataTestId }, { children: children })));
396
396
  };
397
397
  const getTextSize = () => ({ $size }) => {
398
398
  const sizes = {
@@ -423,7 +423,7 @@ const getTextAlignment = () => ({ $align }) => {
423
423
  };
424
424
  return alignments[$align];
425
425
  };
426
- const StyledText$4 = tailwindStyledComponents.tw.text `
426
+ const StyledText$3 = tailwindStyledComponents.tw.text `
427
427
  tu-text
428
428
  ${getFontColor$1()}
429
429
  ${p => (p.$italicize ? tailwindStyledComponents.tws `tu-text--italic` : "")}
@@ -522,7 +522,7 @@ const Badge = (_a) => {
522
522
  return null;
523
523
  }
524
524
  const displayedCount = count && max ? (count > max ? `${max}+` : count) : count;
525
- return (jsxRuntime.jsx(StyledText$3, Object.assign({ className: className, "$color": color, "$subtle": subtle, "$count": count, "data-testid": dataTestId, "$as": "span" }, { children: displayedCount })));
525
+ return (jsxRuntime.jsx(StyledText$2, Object.assign({ className: className, "$color": color, "$subtle": subtle, "$count": count, "data-testid": dataTestId, "$as": "span" }, { children: displayedCount })));
526
526
  };
527
527
  const getBadgeModifierClass = () => ({ $color, $subtle }) => {
528
528
  const colorClasses = {
@@ -531,7 +531,7 @@ const getBadgeModifierClass = () => ({ $color, $subtle }) => {
531
531
  };
532
532
  return colorClasses[$color];
533
533
  };
534
- const StyledText$3 = tailwindStyledComponents.tw.text `
534
+ const StyledText$2 = tailwindStyledComponents.tw.text `
535
535
  tu-badge
536
536
  ${({ $count }) => ($count === null || $count === undefined) && tailwindStyledComponents.tws `tu-badge--square`}
537
537
  ${getBadgeModifierClass()}
@@ -907,17 +907,28 @@ const DateInput = React.forwardRef((_a, ref) => {
907
907
  });
908
908
 
909
909
  /**
910
- * @param {PopoverProps} props The children to render in the popover
911
- * @returns {ReactElement} Popover with specified content and placement
910
+ * The hook that powers the Popover component.
911
+ * It should not be used directly, but rather through the Popover component.
912
+ *
913
+ * @param {PopoverProps} options The options for the popover
914
+ * @returns {ReturnType<usePopover>} The data for the popover
912
915
  */
913
- const Popover = ({ children, render, placement, activation = { click: true, hover: false }, className, dataTestId, }) => {
914
- const [open, setOpen] = React.useState(false);
915
- const { x, y, reference, floating, strategy, context } = react.useFloating({
916
- open,
917
- onOpenChange: setOpen,
916
+ const usePopover = (_a) => {
917
+ var { initialOpen = false, placement = "bottom", isModal, isOpen: controlledIsOpen, activation = { click: true, hover: false }, onOpenStateChange: setControlledIsOpen } = _a, restOptions = __rest(_a, ["initialOpen", "placement", "isModal", "isOpen", "activation", "onOpenStateChange"]);
918
+ const [uncontrolledIsOpen, setUncontrolledIsOpen] = React.useState(initialOpen);
919
+ const [labelId, setLabelId] = React.useState();
920
+ const [descriptionId, setDescriptionId] = React.useState();
921
+ const isOpen = controlledIsOpen !== null && controlledIsOpen !== void 0 ? controlledIsOpen : uncontrolledIsOpen;
922
+ const setIsOpen = setControlledIsOpen !== null && setControlledIsOpen !== void 0 ? setControlledIsOpen : setUncontrolledIsOpen;
923
+ const popoverData = react.useFloating({
924
+ placement,
925
+ open: isOpen,
926
+ onOpenChange: setIsOpen,
927
+ whileElementsMounted: react.autoUpdate,
918
928
  middleware: [
919
929
  react.offset(8),
920
930
  react.flip({ fallbackPlacements: ["top", "bottom", "right", "left"] }),
931
+ react.shift(),
921
932
  react.size({
922
933
  apply({ availableWidth, availableHeight, elements }) {
923
934
  Object.assign(elements.floating.style, {
@@ -926,83 +937,68 @@ const Popover = ({ children, render, placement, activation = { click: true, hove
926
937
  });
927
938
  },
928
939
  }),
929
- react.shift(),
930
940
  ],
931
- placement,
932
- whileElementsMounted: react.autoUpdate,
933
941
  });
934
- const { getReferenceProps, getFloatingProps } = react.useInteractions([
935
- react.useClick(context, { enabled: activation.click, ignoreMouse: activation.hover }),
936
- react.useHover(context, { enabled: activation.hover }),
937
- react.useRole(context),
938
- react.useDismiss(context),
942
+ const popoverContext = popoverData.context;
943
+ const clickInteraction = react.useClick(popoverContext, { enabled: activation.click, ignoreMouse: activation.hover });
944
+ const dismissInteraction = react.useDismiss(popoverContext);
945
+ const hoverInteraction = react.useHover(popoverContext, { enabled: activation.hover });
946
+ const roleInteraction = react.useRole(popoverContext);
947
+ const combinedInteractions = react.useInteractions([
948
+ clickInteraction,
949
+ hoverInteraction,
950
+ dismissInteraction,
951
+ roleInteraction,
939
952
  ]);
940
- // Preserve the consumer's ref
941
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
942
- const ref = React.useMemo(() => mergeRefs([reference, children.ref]), [reference, children]);
943
- return (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [React.cloneElement(children, getReferenceProps(Object.assign({ ref }, children.props))), jsxRuntime.jsx(react.FloatingPortal, Object.assign({ id: "tu-floating-ui" }, { children: open && (jsxRuntime.jsx(react.FloatingFocusManager, Object.assign({ guards: false, context: context, modal: false, order: ["reference", "content"], returnFocus: false }, { children: jsxRuntime.jsx("div", Object.assign({ ref: floating, className: `tu-popover-container animate-fade-in-fast ${className !== null && className !== void 0 ? className : ""}`, "data-testid": dataTestId, style: {
944
- position: strategy,
945
- top: y !== null && y !== void 0 ? y : 0,
946
- left: x !== null && x !== void 0 ? x : 0,
947
- display: "flex",
948
- } }, getFloatingProps(), { children: render({
949
- close: () => {
950
- setOpen(false);
951
- },
952
- }) })) }))) }))] }));
953
- };
954
- // Utility to merge refs — Heavily inspired by https://github.com/gregberge/react-merge-refs
955
- function mergeRefs(refs) {
956
- return value => {
957
- refs.forEach(ref => {
958
- if (typeof ref === "function") {
959
- ref(value);
960
- }
961
- else if (ref !== null) {
962
- ref.current = value;
963
- }
964
- });
965
- };
966
- }
953
+ return React.useMemo(() => (Object.assign(Object.assign(Object.assign({ isOpen,
954
+ setIsOpen }, combinedInteractions), popoverData), { isModal,
955
+ labelId,
956
+ descriptionId,
957
+ setLabelId,
958
+ setDescriptionId, customProps: restOptions })), [isOpen, setIsOpen, combinedInteractions, popoverData, isModal, labelId, descriptionId, restOptions]);
959
+ };
967
960
 
961
+ const PopoverContext = React.createContext(null);
968
962
  /**
969
- * The PopoverList component.
963
+ * A hook to get the popover context.
964
+ * It should only be used by the Popover components.
970
965
  *
971
- * @param {PopoverListProps} props - The props for the PopoverList component
972
- * @returns {JSX.Element} PopoverList component
966
+ * @returns {ContextType} The popover context
973
967
  */
974
- const PopoverList = ({ className, children, dataTestId }) => {
975
- return (jsxRuntime.jsx(Card, Object.assign({ className: className, dataTestId: dataTestId }, { children: jsxRuntime.jsx(StyledCardBody, Object.assign({ density: "comfortable" }, { children: jsxRuntime.jsx(List, { children: children }) })) })));
968
+ const usePopoverContext = () => {
969
+ const context = React.useContext(PopoverContext);
970
+ if (context === null) {
971
+ throw new Error("Popover components must be wrapped in <Popover />");
972
+ }
973
+ return context;
976
974
  };
977
- const List = tailwindStyledComponents.tw.ul `
978
- tu-popover-list
979
- `;
980
- const StyledCardBody = tailwindStyledComponents.twx(CardBody) `
981
- tu-popover-list-body
982
- `;
983
-
984
975
  /**
985
- * The PopoverListItem component.
976
+ * The popover component.
977
+ * - This component should wrap all the popover components.
978
+ * - It returns a context that is used by the popover components.
979
+ * - The context is used to share the state of the popover, such as the open state and the reference element.
980
+ *
981
+ * To open the popover, use the `<PopoverTrigger />` component.
982
+ *
983
+ * To render the content of the popover, use the `<PopoverContent />` component.
986
984
  *
987
- * @param {PopoverListItemProps} props - The props for the PopoverListItem component
988
- * @returns {JSX.Element} PopoverListItem component
985
+ *
986
+ * @param {PopoverProps} props The props for the popover
987
+ * @returns {JSX.Element} A Popover Context Provider contining the children
989
988
  */
990
- const PopoverListItem = ({ selected, children, disabled, ariaLabel, url, onClick, prefix, suffix, dataTestId, className, }) => {
991
- const content = (jsxRuntime.jsxs("div", Object.assign({ className: "flex items-center gap-3" }, { children: [prefix && jsxRuntime.jsx("div", { children: prefix }), jsxRuntime.jsx(StyledText$2, Object.assign({ weight: selected ? "bold" : "normal", "$selected": selected }, { children: children })), suffix && jsxRuntime.jsx("div", { children: suffix })] })));
992
- return (jsxRuntime.jsx(ListItem, Object.assign({ "$selected": selected, disabled: disabled, onClick: onClick, "aria-label": ariaLabel, "data-testid": dataTestId, className: className }, { children: url ? jsxRuntime.jsx(PopoverLink, Object.assign({ to: url }, { children: content })) : content })));
993
- };
994
- const StyledText$2 = tailwindStyledComponents.twx(Text$1) `
995
- tu-popover-list-item__text
996
- ${p => p.$selected && tailwindStyledComponents.tws `tu-popover-list-item__text--selected`}
997
- `;
998
- const ListItem = tailwindStyledComponents.tw.li `
999
- group
1000
- tu-popover-list-item
1001
- ${p => p.disabled && tailwindStyledComponents.tws `tu-popover-list-item--disabled`}
1002
- `;
1003
- const PopoverLink = tailwindStyledComponents.twx(reactRouterDom.Link) `
1004
- tu-popover-list-item__anchor
1005
- `;
989
+ const Popover = (_a) => {
990
+ var { children, isModal = false } = _a, restOptions = __rest(_a, ["children", "isModal"]);
991
+ const popover = usePopover(Object.assign({ isModal }, restOptions));
992
+ return jsxRuntime.jsx(PopoverContext.Provider, Object.assign({ value: popover }, { children: children }));
993
+ };
994
+
995
+ const PopoverContent = React__default["default"].forwardRef(function PopoverContent(_a, propRef) {
996
+ var _b, _c, _d, _e;
997
+ var { className, dataTestId, children } = _a, props = __rest(_a, ["className", "dataTestId", "children"]);
998
+ const _f = usePopoverContext(), { context: floatingContext, customProps } = _f, context = __rest(_f, ["context", "customProps"]);
999
+ const ref = react.useMergeRefs([context.refs.setFloating, propRef]);
1000
+ return (jsxRuntime.jsx(react.FloatingPortal, Object.assign({ id: "tu-floating-ui" }, { children: context.isOpen && (jsxRuntime.jsx(react.FloatingFocusManager, Object.assign({ guards: false, context: floatingContext, modal: context.isModal, order: ["reference", "content"] }, { children: jsxRuntime.jsx("div", Object.assign({ ref: ref, className: `tu-popover-container animate-fade-in-fast ${(_b = className !== null && className !== void 0 ? className : customProps.className) !== null && _b !== void 0 ? _b : ""}`, "data-testid": (_c = dataTestId !== null && dataTestId !== void 0 ? dataTestId : customProps.dataTestId) !== null && _c !== void 0 ? _c : "popover-content", style: Object.assign({ position: context.strategy, top: (_d = context.y) !== null && _d !== void 0 ? _d : 0, left: (_e = context.x) !== null && _e !== void 0 ? _e : 0, width: "max-content" }, props.style), "aria-labelledby": context.labelId, "aria-describedby": context.descriptionId }, context.getFloatingProps(props), { children: typeof children === "function" ? children(() => context.setIsOpen(false)) : children })) }))) })));
1001
+ });
1006
1002
 
1007
1003
  /**
1008
1004
  * The PopoverTitle component.
@@ -1021,6 +1017,20 @@ const StyledText$1 = tailwindStyledComponents.twx(Text$1) `
1021
1017
  tu-popover-title-text
1022
1018
  `;
1023
1019
 
1020
+ const PopoverTrigger = React.forwardRef(function PopoverTrigger(_a, propRef) {
1021
+ var { children, renderButton } = _a, props = __rest(_a, ["children", "renderButton"]);
1022
+ const context = usePopoverContext();
1023
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1024
+ const childrenRef = children.ref;
1025
+ const ref = react.useMergeRefs([context.refs.setReference, propRef, childrenRef]);
1026
+ if (!renderButton && React.isValidElement(children)) {
1027
+ return React.cloneElement(children, context.getReferenceProps(Object.assign(Object.assign(Object.assign({ ref }, props), children.props), { "data-state": context.isOpen ? "open" : "closed" })));
1028
+ }
1029
+ else {
1030
+ return (jsxRuntime.jsx(Button, Object.assign({ ref: ref, type: "button", "data-state": context.isOpen ? "open" : "closed" }, context.getReferenceProps(props), { children: children })));
1031
+ }
1032
+ });
1033
+
1024
1034
  /**
1025
1035
  * The Tooltip component is used to show helpful tips or contextual information to the users.
1026
1036
  *
@@ -1035,7 +1045,7 @@ const Tooltip = (_a) => {
1035
1045
  }
1036
1046
  return (jsxRuntime.jsx(TooltipContainer, Object.assign({ dataTestId: dataTestId }, rest, { children: wrappedChildren })));
1037
1047
  };
1038
- const TooltipContainer = ({ label, placement = "bottom", mode = "dark", contentTextType = "p", children, dataTestId, }) => (jsxRuntime.jsx(StyledPopover, Object.assign({ className: "tu-tooltip__container", placement: placement, activation: { hover: true }, dataTestId: dataTestId !== null && dataTestId !== void 0 ? dataTestId : "", render: () => (jsxRuntime.jsx(Content, Object.assign({ "$mode": mode }, { children: jsxRuntime.jsx(Text$1, Object.assign({ inverted: mode === "dark", type: contentTextType }, { children: label })) }))) }, { children: children })));
1048
+ const TooltipContainer = ({ label, placement = "bottom", mode = "dark", contentTextType = "p", children, dataTestId, }) => (jsxRuntime.jsxs(StyledPopover, Object.assign({ className: "tu-tooltip__container", placement: placement, activation: { hover: true }, dataTestId: dataTestId !== null && dataTestId !== void 0 ? dataTestId : "" }, { children: [jsxRuntime.jsx(PopoverTrigger, { children: children }), jsxRuntime.jsx(PopoverContent, { children: jsxRuntime.jsx(Content, Object.assign({ "$mode": mode }, { children: jsxRuntime.jsx(Text$1, Object.assign({ inverted: mode === "dark", type: contentTextType }, { children: label })) })) })] })));
1039
1049
  const Flex$1 = tailwindStyledComponents.tw.div `
1040
1050
  inline-flex
1041
1051
  `;
@@ -1155,7 +1165,7 @@ const DayPicker = ({ onDaySelect, disabledDays, selectedDays, language, classNam
1155
1165
  * @returns {JSX.Element} DayPickerPopover component
1156
1166
  */
1157
1167
  const DayPickerPopover = ({ disabledDays, className, dataTestId, selectedDay, onDaySelect, color = "secondary", placement, size = "small", buttonContent, language, }) => {
1158
- return (jsxRuntime.jsx(Popover, Object.assign({ placement: placement, render: () => (jsxRuntime.jsx(PopoverList, { children: jsxRuntime.jsx(DayPicker, { disabledDays: disabledDays, onDaySelect: onDaySelect, selectedDays: selectedDay, language: language }) })) }, { children: jsxRuntime.jsx(Button, Object.assign({ color: color, size: size, className: className, prefix: jsxRuntime.jsx(Icon, { name: "CalendarIcon", size: "small" }), dataTestId: dataTestId !== null && dataTestId !== void 0 ? dataTestId : "show-day-picker" }, { children: buttonContent })) })));
1168
+ return (jsxRuntime.jsxs(Popover, Object.assign({ placement: placement }, { children: [jsxRuntime.jsx(PopoverTrigger, { children: jsxRuntime.jsx(Button, Object.assign({ color: color, size: size, className: className, prefix: jsxRuntime.jsx(Icon, { name: "CalendarIcon", size: "small" }), dataTestId: dataTestId !== null && dataTestId !== void 0 ? dataTestId : "show-day-picker" }, { children: buttonContent })) }), jsxRuntime.jsx(PopoverContent, { children: jsxRuntime.jsx(Card, { children: jsxRuntime.jsx(DayPicker, { disabledDays: disabledDays, onDaySelect: onDaySelect, selectedDays: selectedDay, language: language }) }) })] })));
1159
1169
  };
1160
1170
 
1161
1171
  /**
@@ -1439,7 +1449,7 @@ const MenuItem = ({ className, dataTestId, label, children, selected, focused, p
1439
1449
  return (jsxRuntime.jsxs(Container$4, Object.assign({}, containerProps, { onClick: e => {
1440
1450
  e.stopPropagation();
1441
1451
  onClick && onClick(e);
1442
- }, "$selected": selected, "$focused": focused, tabIndex: 0, "$disabled": disabled }, { children: [prefix && (jsxRuntime.jsx(Prefix, Object.assign({ "$selected": selected, "data-testid": dataTestId && `${dataTestId}-prefix` }, { children: prefix }))), children !== null && children !== void 0 ? children : jsxRuntime.jsx(Label, Object.assign({ "data-testid": dataTestId && `${dataTestId}-label` }, { children: label })), suffix && (jsxRuntime.jsx(Suffix, Object.assign({ "$selected": selected, "data-testid": dataTestId && `${dataTestId}-suffix` }, { children: suffix })))] })));
1452
+ }, "$selected": selected, "$focused": focused, tabIndex: 0, "$disabled": disabled }, { children: [prefix && (jsxRuntime.jsx(Prefix, Object.assign({ "$selected": selected, "data-testid": dataTestId && `${dataTestId}-prefix` }, { children: prefix }))), children && typeof children !== "string" ? (children) : (jsxRuntime.jsx(Label, Object.assign({ "data-testid": dataTestId && `${dataTestId}-label` }, { children: children !== null && children !== void 0 ? children : label }))), suffix && (jsxRuntime.jsx(Suffix, Object.assign({ "$selected": selected, "data-testid": dataTestId && `${dataTestId}-suffix` }, { children: suffix })))] })));
1443
1453
  };
1444
1454
  const Container$4 = tailwindStyledComponents.tw.div `
1445
1455
  group tu-menu-item
@@ -1470,7 +1480,7 @@ const MenuList = (_a) => {
1470
1480
  var { dataTestId, className, children, withStickyHeader = false, showDivider = false } = _a; __rest(_a, ["dataTestId", "className", "children", "withStickyHeader", "showDivider"]);
1471
1481
  const childrenArr = React.Children.toArray(children);
1472
1482
  const isLastItem = (index) => index === childrenArr.length - 1;
1473
- return (jsxRuntime.jsx(Container$3, Object.assign({ "$withStickyHeader": withStickyHeader, "data-testid": dataTestId, className: className, tabIndex: 0 }, { children: React.Children.map(childrenArr, (menuItem, index) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [menuItem, showDivider && !isLastItem(index) && jsxRuntime.jsx(Divider, {})] }))) })));
1483
+ return (jsxRuntime.jsx(Container$3, Object.assign({ "$withStickyHeader": withStickyHeader, "data-testid": dataTestId, className: className, tabIndex: 0, role: "list" }, { children: React.Children.map(childrenArr, (menuItem, index) => (jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [menuItem, showDivider && !isLastItem(index) && jsxRuntime.jsx(Divider, {})] }))) })));
1474
1484
  };
1475
1485
  const Container$3 = tailwindStyledComponents.tw.div `
1476
1486
  tu-menu-list
@@ -1501,9 +1511,9 @@ const MoreMenu = ({ className, dataTestId, dotsDirection = "horizontal", menuPla
1501
1511
  reactBrowserHooks.useClickOutside(actionMenuRef, () => {
1502
1512
  setActionMenuIsOpen(false);
1503
1513
  });
1504
- return (jsxRuntime.jsx(Root$4, Object.assign({ ref: actionMenuRef, className: className, "data-testid": dataTestId }, { children: jsxRuntime.jsx(Popover, Object.assign({ render: () => children, placement: menuPlacement }, { children: jsxRuntime.jsx(IconButton, Object.assign({}, iconButtonProps, { icon: jsxRuntime.jsx(Icon, Object.assign({ name: dotsName }, iconProps)), onClick: () => {
1505
- setActionMenuIsOpen(!actionMenuIsOpen);
1506
- } })) })) })));
1514
+ return (jsxRuntime.jsx(Root$4, Object.assign({ ref: actionMenuRef, className: className, "data-testid": dataTestId }, { children: jsxRuntime.jsxs(Popover, Object.assign({ placement: menuPlacement }, { children: [jsxRuntime.jsx(PopoverTrigger, { children: jsxRuntime.jsx(IconButton, Object.assign({}, iconButtonProps, { icon: jsxRuntime.jsx(Icon, Object.assign({ name: dotsName }, iconProps)), onClick: () => {
1515
+ setActionMenuIsOpen(!actionMenuIsOpen);
1516
+ } })) }), jsxRuntime.jsx(PopoverContent, { children: children })] })) })));
1507
1517
  };
1508
1518
  const Root$4 = tailwindStyledComponents.tw.div `
1509
1519
  tu-more-menu
@@ -2586,9 +2596,17 @@ const Sidebar = ({ childContainerClassName, children, breakpoint = "lg", classNa
2586
2596
  circular: false,
2587
2597
  variant: "transparent",
2588
2598
  color: "secondary",
2589
- }, menuPlacement: "bottom-end" }, moreMenuProps, { className: `${(moreMenuProps === null || moreMenuProps === void 0 ? void 0 : moreMenuProps.className) || ""} !p-0`, dataTestId: dataTestId && `${dataTestId}-more-menu` }, { children: jsxRuntime.jsx(MenuList, Object.assign({}, menuListProps, { dataTestId: dataTestId && `${dataTestId}-menu-list` }, { children: React__default["default"].Children.map(children, child => {
2590
- return itemOverflowMap[child.props.id] ? child : null;
2591
- }) })) }))) : null] })));
2599
+ }, menuPlacement: "bottom-end" }, moreMenuProps, { className: `${(moreMenuProps === null || moreMenuProps === void 0 ? void 0 : moreMenuProps.className) || ""} !p-0`, dataTestId: dataTestId && `${dataTestId}-more-menu` }, { children: close => (jsxRuntime.jsx(MenuList, Object.assign({}, menuListProps, { dataTestId: dataTestId && `${dataTestId}-menu-list` }, { children: React__default["default"].Children.map(children, child => {
2600
+ return itemOverflowMap[child.props.id]
2601
+ ? React__default["default"].cloneElement(child, {
2602
+ onClick: () => {
2603
+ var _a, _b;
2604
+ (_b = (_a = child === null || child === void 0 ? void 0 : child.props) === null || _a === void 0 ? void 0 : _a.onClick) === null || _b === void 0 ? void 0 : _b.call(_a);
2605
+ close();
2606
+ },
2607
+ })
2608
+ : null;
2609
+ }) }))) }))) : null] })));
2592
2610
  };
2593
2611
  const Root$2 = tailwindStyledComponents.tw.div `
2594
2612
  tu-sidebar
@@ -3266,9 +3284,9 @@ exports.Pagination = Pagination;
3266
3284
  exports.PhoneField = PhoneField;
3267
3285
  exports.PhoneInput = PhoneInput;
3268
3286
  exports.Popover = Popover;
3269
- exports.PopoverList = PopoverList;
3270
- exports.PopoverListItem = PopoverListItem;
3287
+ exports.PopoverContent = PopoverContent;
3271
3288
  exports.PopoverTitle = PopoverTitle;
3289
+ exports.PopoverTrigger = PopoverTrigger;
3272
3290
  exports.Prompt = Prompt;
3273
3291
  exports.ROLE_CARD = ROLE_CARD;
3274
3292
  exports.RadioGroup = RadioGroup;
@@ -3311,5 +3329,6 @@ exports.useDebounce = useDebounce;
3311
3329
  exports.useDevicePixelRatio = useDevicePixelRatio;
3312
3330
  exports.useLocalStorage = useLocalStorage;
3313
3331
  exports.useModal = useModal;
3332
+ exports.usePopoverContext = usePopoverContext;
3314
3333
  exports.usePrompt = usePrompt;
3315
3334
  exports.useTimeout = useTimeout;
package/index.js CHANGED
@@ -1,12 +1,11 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { tw, tws, twx } from '@trackunit/tailwind-styled-components';
3
3
  import * as React from 'react';
4
- import React__default, { useState, forwardRef, useMemo, cloneElement, useCallback, useEffect, Children, useRef, memo, useContext } from 'react';
4
+ import React__default, { useState, forwardRef, useMemo, createContext, useContext, isValidElement, cloneElement, useCallback, useEffect, Children, useRef, memo } from 'react';
5
5
  import { HeroIconsArray, heroIconLookup, TrackunitSolidIconsArray, TrackunitOutlineIconsArray, trackunitIconLookup } from '@trackunit/ui-icons';
6
6
  import { useMeasure, useCopyToClipboard } from 'react-use';
7
7
  import { format, formatDistance } from 'date-fns';
8
- import { useFloating, offset, flip, size, shift, autoUpdate, useInteractions, useClick, useHover, useRole, useDismiss, FloatingPortal, FloatingFocusManager } from '@floating-ui/react';
9
- import { Link, UNSAFE_NavigationContext } from 'react-router-dom';
8
+ import { useFloating, autoUpdate, offset, flip, shift, size, useClick, useDismiss, useHover, useRole, useInteractions, useMergeRefs, FloatingPortal, FloatingFocusManager } from '@floating-ui/react';
10
9
  import { DayPicker as DayPicker$1 } from 'react-day-picker';
11
10
  import { enGB, enUS, da, de, cs, nl, fr, fi, hu, it, nb, pl, pt, ru, ro, es, sv, ja, th } from 'date-fns/locale';
12
11
  import { useClickOutside } from 'react-browser-hooks';
@@ -17,6 +16,7 @@ import ReactAsyncCreatableSelect from 'react-select/async-creatable';
17
16
  import ReactCreatableSelect from 'react-select/creatable';
18
17
  import ReactAsyncSelect from 'react-select/async';
19
18
  import { getCountries, getCountryCallingCode } from 'libphonenumber-js';
19
+ import { UNSAFE_NavigationContext } from 'react-router-dom';
20
20
  import { HelmetProvider, Helmet } from 'react-helmet-async';
21
21
  import { color } from '@trackunit/ui-design-tokens';
22
22
 
@@ -362,7 +362,7 @@ const CustomIcon = twx(Icon) `
362
362
  * @returns {JSX.Element} Text component
363
363
  */
364
364
  const Text$1 = ({ children, type = "p", size = "medium", align = "left", weight = "normal", underline = false, inverted = false, subtle = false, italicize = false, uppercase = false, className, dataTestId, }) => {
365
- return (jsx(StyledText$4, Object.assign({ "$as": type, className: className, "$align": align, "$inverted": inverted, "$subtle": subtle, "$italicize": italicize, "$uppercase": uppercase, "$size": size, "$weight": weight, "$underline": underline, "data-testid": dataTestId }, { children: children })));
365
+ return (jsx(StyledText$3, Object.assign({ "$as": type, className: className, "$align": align, "$inverted": inverted, "$subtle": subtle, "$italicize": italicize, "$uppercase": uppercase, "$size": size, "$weight": weight, "$underline": underline, "data-testid": dataTestId }, { children: children })));
366
366
  };
367
367
  const getTextSize = () => ({ $size }) => {
368
368
  const sizes = {
@@ -393,7 +393,7 @@ const getTextAlignment = () => ({ $align }) => {
393
393
  };
394
394
  return alignments[$align];
395
395
  };
396
- const StyledText$4 = tw.text `
396
+ const StyledText$3 = tw.text `
397
397
  tu-text
398
398
  ${getFontColor$1()}
399
399
  ${p => (p.$italicize ? tws `tu-text--italic` : "")}
@@ -492,7 +492,7 @@ const Badge = (_a) => {
492
492
  return null;
493
493
  }
494
494
  const displayedCount = count && max ? (count > max ? `${max}+` : count) : count;
495
- return (jsx(StyledText$3, Object.assign({ className: className, "$color": color, "$subtle": subtle, "$count": count, "data-testid": dataTestId, "$as": "span" }, { children: displayedCount })));
495
+ return (jsx(StyledText$2, Object.assign({ className: className, "$color": color, "$subtle": subtle, "$count": count, "data-testid": dataTestId, "$as": "span" }, { children: displayedCount })));
496
496
  };
497
497
  const getBadgeModifierClass = () => ({ $color, $subtle }) => {
498
498
  const colorClasses = {
@@ -501,7 +501,7 @@ const getBadgeModifierClass = () => ({ $color, $subtle }) => {
501
501
  };
502
502
  return colorClasses[$color];
503
503
  };
504
- const StyledText$3 = tw.text `
504
+ const StyledText$2 = tw.text `
505
505
  tu-badge
506
506
  ${({ $count }) => ($count === null || $count === undefined) && tws `tu-badge--square`}
507
507
  ${getBadgeModifierClass()}
@@ -877,17 +877,28 @@ const DateInput = forwardRef((_a, ref) => {
877
877
  });
878
878
 
879
879
  /**
880
- * @param {PopoverProps} props The children to render in the popover
881
- * @returns {ReactElement} Popover with specified content and placement
880
+ * The hook that powers the Popover component.
881
+ * It should not be used directly, but rather through the Popover component.
882
+ *
883
+ * @param {PopoverProps} options The options for the popover
884
+ * @returns {ReturnType<usePopover>} The data for the popover
882
885
  */
883
- const Popover = ({ children, render, placement, activation = { click: true, hover: false }, className, dataTestId, }) => {
884
- const [open, setOpen] = useState(false);
885
- const { x, y, reference, floating, strategy, context } = useFloating({
886
- open,
887
- onOpenChange: setOpen,
886
+ const usePopover = (_a) => {
887
+ var { initialOpen = false, placement = "bottom", isModal, isOpen: controlledIsOpen, activation = { click: true, hover: false }, onOpenStateChange: setControlledIsOpen } = _a, restOptions = __rest(_a, ["initialOpen", "placement", "isModal", "isOpen", "activation", "onOpenStateChange"]);
888
+ const [uncontrolledIsOpen, setUncontrolledIsOpen] = useState(initialOpen);
889
+ const [labelId, setLabelId] = useState();
890
+ const [descriptionId, setDescriptionId] = useState();
891
+ const isOpen = controlledIsOpen !== null && controlledIsOpen !== void 0 ? controlledIsOpen : uncontrolledIsOpen;
892
+ const setIsOpen = setControlledIsOpen !== null && setControlledIsOpen !== void 0 ? setControlledIsOpen : setUncontrolledIsOpen;
893
+ const popoverData = useFloating({
894
+ placement,
895
+ open: isOpen,
896
+ onOpenChange: setIsOpen,
897
+ whileElementsMounted: autoUpdate,
888
898
  middleware: [
889
899
  offset(8),
890
900
  flip({ fallbackPlacements: ["top", "bottom", "right", "left"] }),
901
+ shift(),
891
902
  size({
892
903
  apply({ availableWidth, availableHeight, elements }) {
893
904
  Object.assign(elements.floating.style, {
@@ -896,83 +907,68 @@ const Popover = ({ children, render, placement, activation = { click: true, hove
896
907
  });
897
908
  },
898
909
  }),
899
- shift(),
900
910
  ],
901
- placement,
902
- whileElementsMounted: autoUpdate,
903
911
  });
904
- const { getReferenceProps, getFloatingProps } = useInteractions([
905
- useClick(context, { enabled: activation.click, ignoreMouse: activation.hover }),
906
- useHover(context, { enabled: activation.hover }),
907
- useRole(context),
908
- useDismiss(context),
912
+ const popoverContext = popoverData.context;
913
+ const clickInteraction = useClick(popoverContext, { enabled: activation.click, ignoreMouse: activation.hover });
914
+ const dismissInteraction = useDismiss(popoverContext);
915
+ const hoverInteraction = useHover(popoverContext, { enabled: activation.hover });
916
+ const roleInteraction = useRole(popoverContext);
917
+ const combinedInteractions = useInteractions([
918
+ clickInteraction,
919
+ hoverInteraction,
920
+ dismissInteraction,
921
+ roleInteraction,
909
922
  ]);
910
- // Preserve the consumer's ref
911
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
912
- const ref = useMemo(() => mergeRefs([reference, children.ref]), [reference, children]);
913
- return (jsxs(Fragment, { children: [cloneElement(children, getReferenceProps(Object.assign({ ref }, children.props))), jsx(FloatingPortal, Object.assign({ id: "tu-floating-ui" }, { children: open && (jsx(FloatingFocusManager, Object.assign({ guards: false, context: context, modal: false, order: ["reference", "content"], returnFocus: false }, { children: jsx("div", Object.assign({ ref: floating, className: `tu-popover-container animate-fade-in-fast ${className !== null && className !== void 0 ? className : ""}`, "data-testid": dataTestId, style: {
914
- position: strategy,
915
- top: y !== null && y !== void 0 ? y : 0,
916
- left: x !== null && x !== void 0 ? x : 0,
917
- display: "flex",
918
- } }, getFloatingProps(), { children: render({
919
- close: () => {
920
- setOpen(false);
921
- },
922
- }) })) }))) }))] }));
923
- };
924
- // Utility to merge refs — Heavily inspired by https://github.com/gregberge/react-merge-refs
925
- function mergeRefs(refs) {
926
- return value => {
927
- refs.forEach(ref => {
928
- if (typeof ref === "function") {
929
- ref(value);
930
- }
931
- else if (ref !== null) {
932
- ref.current = value;
933
- }
934
- });
935
- };
936
- }
923
+ return useMemo(() => (Object.assign(Object.assign(Object.assign({ isOpen,
924
+ setIsOpen }, combinedInteractions), popoverData), { isModal,
925
+ labelId,
926
+ descriptionId,
927
+ setLabelId,
928
+ setDescriptionId, customProps: restOptions })), [isOpen, setIsOpen, combinedInteractions, popoverData, isModal, labelId, descriptionId, restOptions]);
929
+ };
937
930
 
931
+ const PopoverContext = createContext(null);
938
932
  /**
939
- * The PopoverList component.
933
+ * A hook to get the popover context.
934
+ * It should only be used by the Popover components.
940
935
  *
941
- * @param {PopoverListProps} props - The props for the PopoverList component
942
- * @returns {JSX.Element} PopoverList component
936
+ * @returns {ContextType} The popover context
943
937
  */
944
- const PopoverList = ({ className, children, dataTestId }) => {
945
- return (jsx(Card, Object.assign({ className: className, dataTestId: dataTestId }, { children: jsx(StyledCardBody, Object.assign({ density: "comfortable" }, { children: jsx(List, { children: children }) })) })));
938
+ const usePopoverContext = () => {
939
+ const context = useContext(PopoverContext);
940
+ if (context === null) {
941
+ throw new Error("Popover components must be wrapped in <Popover />");
942
+ }
943
+ return context;
946
944
  };
947
- const List = tw.ul `
948
- tu-popover-list
949
- `;
950
- const StyledCardBody = twx(CardBody) `
951
- tu-popover-list-body
952
- `;
953
-
954
945
  /**
955
- * The PopoverListItem component.
946
+ * The popover component.
947
+ * - This component should wrap all the popover components.
948
+ * - It returns a context that is used by the popover components.
949
+ * - The context is used to share the state of the popover, such as the open state and the reference element.
950
+ *
951
+ * To open the popover, use the `<PopoverTrigger />` component.
952
+ *
953
+ * To render the content of the popover, use the `<PopoverContent />` component.
954
+ *
956
955
  *
957
- * @param {PopoverListItemProps} props - The props for the PopoverListItem component
958
- * @returns {JSX.Element} PopoverListItem component
956
+ * @param {PopoverProps} props The props for the popover
957
+ * @returns {JSX.Element} A Popover Context Provider contining the children
959
958
  */
960
- const PopoverListItem = ({ selected, children, disabled, ariaLabel, url, onClick, prefix, suffix, dataTestId, className, }) => {
961
- const content = (jsxs("div", Object.assign({ className: "flex items-center gap-3" }, { children: [prefix && jsx("div", { children: prefix }), jsx(StyledText$2, Object.assign({ weight: selected ? "bold" : "normal", "$selected": selected }, { children: children })), suffix && jsx("div", { children: suffix })] })));
962
- return (jsx(ListItem, Object.assign({ "$selected": selected, disabled: disabled, onClick: onClick, "aria-label": ariaLabel, "data-testid": dataTestId, className: className }, { children: url ? jsx(PopoverLink, Object.assign({ to: url }, { children: content })) : content })));
963
- };
964
- const StyledText$2 = twx(Text$1) `
965
- tu-popover-list-item__text
966
- ${p => p.$selected && tws `tu-popover-list-item__text--selected`}
967
- `;
968
- const ListItem = tw.li `
969
- group
970
- tu-popover-list-item
971
- ${p => p.disabled && tws `tu-popover-list-item--disabled`}
972
- `;
973
- const PopoverLink = twx(Link) `
974
- tu-popover-list-item__anchor
975
- `;
959
+ const Popover = (_a) => {
960
+ var { children, isModal = false } = _a, restOptions = __rest(_a, ["children", "isModal"]);
961
+ const popover = usePopover(Object.assign({ isModal }, restOptions));
962
+ return jsx(PopoverContext.Provider, Object.assign({ value: popover }, { children: children }));
963
+ };
964
+
965
+ const PopoverContent = React__default.forwardRef(function PopoverContent(_a, propRef) {
966
+ var _b, _c, _d, _e;
967
+ var { className, dataTestId, children } = _a, props = __rest(_a, ["className", "dataTestId", "children"]);
968
+ const _f = usePopoverContext(), { context: floatingContext, customProps } = _f, context = __rest(_f, ["context", "customProps"]);
969
+ const ref = useMergeRefs([context.refs.setFloating, propRef]);
970
+ return (jsx(FloatingPortal, Object.assign({ id: "tu-floating-ui" }, { children: context.isOpen && (jsx(FloatingFocusManager, Object.assign({ guards: false, context: floatingContext, modal: context.isModal, order: ["reference", "content"] }, { children: jsx("div", Object.assign({ ref: ref, className: `tu-popover-container animate-fade-in-fast ${(_b = className !== null && className !== void 0 ? className : customProps.className) !== null && _b !== void 0 ? _b : ""}`, "data-testid": (_c = dataTestId !== null && dataTestId !== void 0 ? dataTestId : customProps.dataTestId) !== null && _c !== void 0 ? _c : "popover-content", style: Object.assign({ position: context.strategy, top: (_d = context.y) !== null && _d !== void 0 ? _d : 0, left: (_e = context.x) !== null && _e !== void 0 ? _e : 0, width: "max-content" }, props.style), "aria-labelledby": context.labelId, "aria-describedby": context.descriptionId }, context.getFloatingProps(props), { children: typeof children === "function" ? children(() => context.setIsOpen(false)) : children })) }))) })));
971
+ });
976
972
 
977
973
  /**
978
974
  * The PopoverTitle component.
@@ -991,6 +987,20 @@ const StyledText$1 = twx(Text$1) `
991
987
  tu-popover-title-text
992
988
  `;
993
989
 
990
+ const PopoverTrigger = forwardRef(function PopoverTrigger(_a, propRef) {
991
+ var { children, renderButton } = _a, props = __rest(_a, ["children", "renderButton"]);
992
+ const context = usePopoverContext();
993
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
994
+ const childrenRef = children.ref;
995
+ const ref = useMergeRefs([context.refs.setReference, propRef, childrenRef]);
996
+ if (!renderButton && isValidElement(children)) {
997
+ return cloneElement(children, context.getReferenceProps(Object.assign(Object.assign(Object.assign({ ref }, props), children.props), { "data-state": context.isOpen ? "open" : "closed" })));
998
+ }
999
+ else {
1000
+ return (jsx(Button, Object.assign({ ref: ref, type: "button", "data-state": context.isOpen ? "open" : "closed" }, context.getReferenceProps(props), { children: children })));
1001
+ }
1002
+ });
1003
+
994
1004
  /**
995
1005
  * The Tooltip component is used to show helpful tips or contextual information to the users.
996
1006
  *
@@ -1005,7 +1015,7 @@ const Tooltip = (_a) => {
1005
1015
  }
1006
1016
  return (jsx(TooltipContainer, Object.assign({ dataTestId: dataTestId }, rest, { children: wrappedChildren })));
1007
1017
  };
1008
- const TooltipContainer = ({ label, placement = "bottom", mode = "dark", contentTextType = "p", children, dataTestId, }) => (jsx(StyledPopover, Object.assign({ className: "tu-tooltip__container", placement: placement, activation: { hover: true }, dataTestId: dataTestId !== null && dataTestId !== void 0 ? dataTestId : "", render: () => (jsx(Content, Object.assign({ "$mode": mode }, { children: jsx(Text$1, Object.assign({ inverted: mode === "dark", type: contentTextType }, { children: label })) }))) }, { children: children })));
1018
+ const TooltipContainer = ({ label, placement = "bottom", mode = "dark", contentTextType = "p", children, dataTestId, }) => (jsxs(StyledPopover, Object.assign({ className: "tu-tooltip__container", placement: placement, activation: { hover: true }, dataTestId: dataTestId !== null && dataTestId !== void 0 ? dataTestId : "" }, { children: [jsx(PopoverTrigger, { children: children }), jsx(PopoverContent, { children: jsx(Content, Object.assign({ "$mode": mode }, { children: jsx(Text$1, Object.assign({ inverted: mode === "dark", type: contentTextType }, { children: label })) })) })] })));
1009
1019
  const Flex$1 = tw.div `
1010
1020
  inline-flex
1011
1021
  `;
@@ -1125,7 +1135,7 @@ const DayPicker = ({ onDaySelect, disabledDays, selectedDays, language, classNam
1125
1135
  * @returns {JSX.Element} DayPickerPopover component
1126
1136
  */
1127
1137
  const DayPickerPopover = ({ disabledDays, className, dataTestId, selectedDay, onDaySelect, color = "secondary", placement, size = "small", buttonContent, language, }) => {
1128
- return (jsx(Popover, Object.assign({ placement: placement, render: () => (jsx(PopoverList, { children: jsx(DayPicker, { disabledDays: disabledDays, onDaySelect: onDaySelect, selectedDays: selectedDay, language: language }) })) }, { children: jsx(Button, Object.assign({ color: color, size: size, className: className, prefix: jsx(Icon, { name: "CalendarIcon", size: "small" }), dataTestId: dataTestId !== null && dataTestId !== void 0 ? dataTestId : "show-day-picker" }, { children: buttonContent })) })));
1138
+ return (jsxs(Popover, Object.assign({ placement: placement }, { children: [jsx(PopoverTrigger, { children: jsx(Button, Object.assign({ color: color, size: size, className: className, prefix: jsx(Icon, { name: "CalendarIcon", size: "small" }), dataTestId: dataTestId !== null && dataTestId !== void 0 ? dataTestId : "show-day-picker" }, { children: buttonContent })) }), jsx(PopoverContent, { children: jsx(Card, { children: jsx(DayPicker, { disabledDays: disabledDays, onDaySelect: onDaySelect, selectedDays: selectedDay, language: language }) }) })] })));
1129
1139
  };
1130
1140
 
1131
1141
  /**
@@ -1409,7 +1419,7 @@ const MenuItem = ({ className, dataTestId, label, children, selected, focused, p
1409
1419
  return (jsxs(Container$4, Object.assign({}, containerProps, { onClick: e => {
1410
1420
  e.stopPropagation();
1411
1421
  onClick && onClick(e);
1412
- }, "$selected": selected, "$focused": focused, tabIndex: 0, "$disabled": disabled }, { children: [prefix && (jsx(Prefix, Object.assign({ "$selected": selected, "data-testid": dataTestId && `${dataTestId}-prefix` }, { children: prefix }))), children !== null && children !== void 0 ? children : jsx(Label, Object.assign({ "data-testid": dataTestId && `${dataTestId}-label` }, { children: label })), suffix && (jsx(Suffix, Object.assign({ "$selected": selected, "data-testid": dataTestId && `${dataTestId}-suffix` }, { children: suffix })))] })));
1422
+ }, "$selected": selected, "$focused": focused, tabIndex: 0, "$disabled": disabled }, { children: [prefix && (jsx(Prefix, Object.assign({ "$selected": selected, "data-testid": dataTestId && `${dataTestId}-prefix` }, { children: prefix }))), children && typeof children !== "string" ? (children) : (jsx(Label, Object.assign({ "data-testid": dataTestId && `${dataTestId}-label` }, { children: children !== null && children !== void 0 ? children : label }))), suffix && (jsx(Suffix, Object.assign({ "$selected": selected, "data-testid": dataTestId && `${dataTestId}-suffix` }, { children: suffix })))] })));
1413
1423
  };
1414
1424
  const Container$4 = tw.div `
1415
1425
  group tu-menu-item
@@ -1440,7 +1450,7 @@ const MenuList = (_a) => {
1440
1450
  var { dataTestId, className, children, withStickyHeader = false, showDivider = false } = _a; __rest(_a, ["dataTestId", "className", "children", "withStickyHeader", "showDivider"]);
1441
1451
  const childrenArr = Children.toArray(children);
1442
1452
  const isLastItem = (index) => index === childrenArr.length - 1;
1443
- return (jsx(Container$3, Object.assign({ "$withStickyHeader": withStickyHeader, "data-testid": dataTestId, className: className, tabIndex: 0 }, { children: Children.map(childrenArr, (menuItem, index) => (jsxs(Fragment, { children: [menuItem, showDivider && !isLastItem(index) && jsx(Divider, {})] }))) })));
1453
+ return (jsx(Container$3, Object.assign({ "$withStickyHeader": withStickyHeader, "data-testid": dataTestId, className: className, tabIndex: 0, role: "list" }, { children: Children.map(childrenArr, (menuItem, index) => (jsxs(Fragment, { children: [menuItem, showDivider && !isLastItem(index) && jsx(Divider, {})] }))) })));
1444
1454
  };
1445
1455
  const Container$3 = tw.div `
1446
1456
  tu-menu-list
@@ -1471,9 +1481,9 @@ const MoreMenu = ({ className, dataTestId, dotsDirection = "horizontal", menuPla
1471
1481
  useClickOutside(actionMenuRef, () => {
1472
1482
  setActionMenuIsOpen(false);
1473
1483
  });
1474
- return (jsx(Root$4, Object.assign({ ref: actionMenuRef, className: className, "data-testid": dataTestId }, { children: jsx(Popover, Object.assign({ render: () => children, placement: menuPlacement }, { children: jsx(IconButton, Object.assign({}, iconButtonProps, { icon: jsx(Icon, Object.assign({ name: dotsName }, iconProps)), onClick: () => {
1475
- setActionMenuIsOpen(!actionMenuIsOpen);
1476
- } })) })) })));
1484
+ return (jsx(Root$4, Object.assign({ ref: actionMenuRef, className: className, "data-testid": dataTestId }, { children: jsxs(Popover, Object.assign({ placement: menuPlacement }, { children: [jsx(PopoverTrigger, { children: jsx(IconButton, Object.assign({}, iconButtonProps, { icon: jsx(Icon, Object.assign({ name: dotsName }, iconProps)), onClick: () => {
1485
+ setActionMenuIsOpen(!actionMenuIsOpen);
1486
+ } })) }), jsx(PopoverContent, { children: children })] })) })));
1477
1487
  };
1478
1488
  const Root$4 = tw.div `
1479
1489
  tu-more-menu
@@ -2556,9 +2566,17 @@ const Sidebar = ({ childContainerClassName, children, breakpoint = "lg", classNa
2556
2566
  circular: false,
2557
2567
  variant: "transparent",
2558
2568
  color: "secondary",
2559
- }, menuPlacement: "bottom-end" }, moreMenuProps, { className: `${(moreMenuProps === null || moreMenuProps === void 0 ? void 0 : moreMenuProps.className) || ""} !p-0`, dataTestId: dataTestId && `${dataTestId}-more-menu` }, { children: jsx(MenuList, Object.assign({}, menuListProps, { dataTestId: dataTestId && `${dataTestId}-menu-list` }, { children: React__default.Children.map(children, child => {
2560
- return itemOverflowMap[child.props.id] ? child : null;
2561
- }) })) }))) : null] })));
2569
+ }, menuPlacement: "bottom-end" }, moreMenuProps, { className: `${(moreMenuProps === null || moreMenuProps === void 0 ? void 0 : moreMenuProps.className) || ""} !p-0`, dataTestId: dataTestId && `${dataTestId}-more-menu` }, { children: close => (jsx(MenuList, Object.assign({}, menuListProps, { dataTestId: dataTestId && `${dataTestId}-menu-list` }, { children: React__default.Children.map(children, child => {
2570
+ return itemOverflowMap[child.props.id]
2571
+ ? React__default.cloneElement(child, {
2572
+ onClick: () => {
2573
+ var _a, _b;
2574
+ (_b = (_a = child === null || child === void 0 ? void 0 : child.props) === null || _a === void 0 ? void 0 : _a.onClick) === null || _b === void 0 ? void 0 : _b.call(_a);
2575
+ close();
2576
+ },
2577
+ })
2578
+ : null;
2579
+ }) }))) }))) : null] })));
2562
2580
  };
2563
2581
  const Root$2 = tw.div `
2564
2582
  tu-sidebar
@@ -3182,4 +3200,4 @@ const Layout = tw.div `
3182
3200
  tu-layout-TwoColumnLayout
3183
3201
  `;
3184
3202
 
3185
- export { ActionButton, Alert, Badge, BaseInput, Button, Card, CardBody, CardFooter, CardHeader, Checkbox, Collapse, ContentGridArea, CopyableText, CreatableSelect, DateField, DateInput, DayPicker, DayPickerPopover, DayRangePicker, DensityContainer, Drawer, DropZone, EmailField, EmailInput, ExternalLink, FilterListMapLayout, FormGroup, FullWidthRepeatingLayout, GridArea, Heading$1 as Heading, Icon, IconButton, Indicator, IntrinsicallyResponsiveGrid, Label$2 as Label, MenuItem, MenuList, MinTopFullContentLayout, Modal, ModalBackdrop, MoreMenu, MultiSelectMenuItem, NavGridArea, NumberField, NumberInput, PageHeader, Pagination, PhoneField, PhoneInput, Popover, PopoverList, PopoverListItem, PopoverTitle, Prompt, ROLE_CARD, RadioGroup, RadioItem, Search, SectionHeader, Select, SelectPrefix, Sidebar, SingleSelectMenuItem, SkeletonLines, Spacer, Spinner, StarButton, Tag, Text$1 as Text, TextArea, TextAreaField, TextField, TextInput, Timeline, TimelineElement, Tip, TitleGridArea, TitleNavContentLayout, Toggle, Tooltip, TwoColumnLayout, UploadField, UploadInput, ValueBar, docs, getDevicePixelRatio, getOrderedOptions, getValueBarColorByValue, isMultiValue, useContainerProps, useCustomComponents, useDebounce, useDevicePixelRatio, useLocalStorage, useModal, usePrompt, useTimeout };
3203
+ export { ActionButton, Alert, Badge, BaseInput, Button, Card, CardBody, CardFooter, CardHeader, Checkbox, Collapse, ContentGridArea, CopyableText, CreatableSelect, DateField, DateInput, DayPicker, DayPickerPopover, DayRangePicker, DensityContainer, Drawer, DropZone, EmailField, EmailInput, ExternalLink, FilterListMapLayout, FormGroup, FullWidthRepeatingLayout, GridArea, Heading$1 as Heading, Icon, IconButton, Indicator, IntrinsicallyResponsiveGrid, Label$2 as Label, MenuItem, MenuList, MinTopFullContentLayout, Modal, ModalBackdrop, MoreMenu, MultiSelectMenuItem, NavGridArea, NumberField, NumberInput, PageHeader, Pagination, PhoneField, PhoneInput, Popover, PopoverContent, PopoverTitle, PopoverTrigger, Prompt, ROLE_CARD, RadioGroup, RadioItem, Search, SectionHeader, Select, SelectPrefix, Sidebar, SingleSelectMenuItem, SkeletonLines, Spacer, Spinner, StarButton, Tag, Text$1 as Text, TextArea, TextAreaField, TextField, TextInput, Timeline, TimelineElement, Tip, TitleGridArea, TitleNavContentLayout, Toggle, Tooltip, TwoColumnLayout, UploadField, UploadInput, ValueBar, docs, getDevicePixelRatio, getOrderedOptions, getValueBarColorByValue, isMultiValue, useContainerProps, useCustomComponents, useDebounce, useDevicePixelRatio, useLocalStorage, useModal, usePopoverContext, usePrompt, useTimeout };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-components",
3
- "version": "0.1.66",
3
+ "version": "0.1.67",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "dependencies": {
@@ -11,7 +11,7 @@
11
11
  "react-use": "17.4.0",
12
12
  "date-fns": "2.29.3",
13
13
  "react-day-picker": "8.3.7",
14
- "@floating-ui/react": "0.15.1",
14
+ "@floating-ui/react": "0.22.2",
15
15
  "@trackunit/ui-icons": "0.0.61",
16
16
  "react-browser-hooks": "2.2.4",
17
17
  "react-useportal": "1.0.17",
@@ -9,7 +9,7 @@ export interface MenuItemProps extends CommonProps {
9
9
  * The children element is a custom element that can be used to override the label.
10
10
  * If you use this prop, the label prop will be ignored.
11
11
  */
12
- children?: JSX.Element;
12
+ children?: React.ReactNode;
13
13
  /**
14
14
  * Additional tailwind classes to be applied to the component.
15
15
  */
@@ -2,13 +2,13 @@
2
2
  import { CommonProps } from "../../../common/CommonProps";
3
3
  import { IconButtonProps } from "../../buttons";
4
4
  import { IconProps } from "../../Icon/Icon";
5
- import { PopoverPlacement } from "../../Popover";
5
+ import { PopoverContentChildren, PopoverPlacement } from "../../Popover";
6
6
  export type DotsDirection = "horizontal" | "vertical";
7
7
  export type MenuPlacement = "above" | "below";
8
8
  type FilteredIconProps = Omit<IconProps, "name">;
9
9
  type FilteredIconButtonProps = Omit<IconButtonProps, "icon" | "onClick">;
10
10
  export interface MoreMenuProps extends CommonProps {
11
- children: JSX.Element;
11
+ children: PopoverContentChildren;
12
12
  dotsDirection?: DotsDirection;
13
13
  menuPlacement?: PopoverPlacement;
14
14
  iconProps?: FilteredIconProps;
@@ -1,37 +1,72 @@
1
- import { Placement } from "@floating-ui/react";
2
- import { ReactElement } from "react";
3
- import { CommonProps } from "../../common";
4
- type Render = (data: {
5
- close: () => void;
6
- }) => ReactElement;
7
- export type PopoverPlacement = Placement;
8
- export type PopoverActivation = {
9
- click?: boolean;
10
- hover?: boolean;
1
+ /// <reference types="react" />
2
+ import { PopoverProps } from "./PopoverTypes";
3
+ /**
4
+ * A hook to get the popover context.
5
+ * It should only be used by the Popover components.
6
+ *
7
+ * @returns {ContextType} The popover context
8
+ */
9
+ export declare const usePopoverContext: () => {
10
+ isModal: boolean | undefined;
11
+ labelId: string | undefined;
12
+ descriptionId: string | undefined;
13
+ setLabelId: import("react").Dispatch<import("react").SetStateAction<string | undefined>>;
14
+ setDescriptionId: import("react").Dispatch<import("react").SetStateAction<string | undefined>>;
15
+ customProps: {
16
+ className?: string | undefined;
17
+ dataTestId?: string | undefined;
18
+ };
19
+ placement: import("@floating-ui/react-dom").Placement;
20
+ strategy: import("@floating-ui/react-dom").Strategy;
21
+ middlewareData: import("@floating-ui/react-dom").MiddlewareData;
22
+ x: number | null;
23
+ y: number | null;
24
+ update: () => void;
25
+ reference: (node: import("@floating-ui/react").ReferenceType | null) => void;
26
+ floating: (node: HTMLElement | null) => void;
27
+ positionReference: (node: import("@floating-ui/react").ReferenceType | null) => void;
28
+ context: {
29
+ placement: import("@floating-ui/react-dom").Placement;
30
+ strategy: import("@floating-ui/react-dom").Strategy;
31
+ x: number | null;
32
+ y: number | null;
33
+ middlewareData: import("@floating-ui/react-dom").MiddlewareData;
34
+ update: () => void;
35
+ reference: (node: import("@floating-ui/react").ReferenceType | null) => void;
36
+ floating: (node: HTMLElement | null) => void;
37
+ isPositioned: boolean;
38
+ open: boolean;
39
+ onOpenChange: (open: boolean) => void;
40
+ events: import("@floating-ui/react").FloatingEvents;
41
+ dataRef: import("react").MutableRefObject<import("@floating-ui/react").ContextData>;
42
+ nodeId: string | undefined;
43
+ floatingId: string;
44
+ refs: import("@floating-ui/react").ExtendedRefs<import("@floating-ui/react").ReferenceType>;
45
+ elements: import("@floating-ui/react").ExtendedElements<import("@floating-ui/react").ReferenceType>;
46
+ };
47
+ refs: import("@floating-ui/react").ExtendedRefs<import("@floating-ui/react").ReferenceType>;
48
+ elements: import("@floating-ui/react").ExtendedElements<import("@floating-ui/react").ReferenceType>;
49
+ isPositioned: boolean;
50
+ getReferenceProps: (userProps?: import("react").HTMLProps<Element> | undefined) => Record<string, unknown>;
51
+ getFloatingProps: (userProps?: import("react").HTMLProps<HTMLElement> | undefined) => Record<string, unknown>;
52
+ getItemProps: (userProps?: import("react").HTMLProps<HTMLElement> | undefined) => Record<string, unknown>;
53
+ isOpen: boolean;
54
+ setIsOpen: (open: boolean) => void;
11
55
  };
12
- export interface PopoverProps extends CommonProps {
13
- /**
14
- * What to render indide the popover with callback to close the popover
15
- */
16
- render: Render;
17
- /**
18
- * Where to preferentially render the popover relative to the invoking element.
19
- * Will not be respected in case of insufficient space.
20
- */
21
- placement?: PopoverPlacement;
22
- /**
23
- * Action(s) that activates the tooltip
24
- */
25
- activation?: PopoverActivation;
26
- /**
27
- * The element, usually a button, that activates the popover.
28
- * Event handling is automatic and tied to this element. No manual Event handling is necessary.
29
- */
30
- children: ReactElement;
31
- }
32
56
  /**
33
- * @param {PopoverProps} props The children to render in the popover
34
- * @returns {ReactElement} Popover with specified content and placement
57
+ * The popover component.
58
+ * - This component should wrap all the popover components.
59
+ * - It returns a context that is used by the popover components.
60
+ * - The context is used to share the state of the popover, such as the open state and the reference element.
61
+ *
62
+ * To open the popover, use the `<PopoverTrigger />` component.
63
+ *
64
+ * To render the content of the popover, use the `<PopoverContent />` component.
65
+ *
66
+ *
67
+ * @param {PopoverProps} props The props for the popover
68
+ * @returns {JSX.Element} A Popover Context Provider contining the children
35
69
  */
36
- export declare const Popover: ({ children, render, placement, activation, className, dataTestId, }: PopoverProps) => JSX.Element;
37
- export {};
70
+ export declare const Popover: ({ children, isModal, ...restOptions }: {
71
+ children: React.ReactNode;
72
+ } & PopoverProps) => JSX.Element;
@@ -0,0 +1,7 @@
1
+ import React from "react";
2
+ import { CommonProps } from "../../common";
3
+ export type PopoverContentChildren = ((close: () => void) => React.ReactNode) | React.ReactNode;
4
+ export interface PopoverContentProps extends Omit<React.HTMLProps<HTMLDivElement>, "children">, CommonProps {
5
+ children: PopoverContentChildren;
6
+ }
7
+ export declare const PopoverContent: React.ForwardRefExoticComponent<Pick<PopoverContentProps, "children" | "accept" | "acceptCharset" | "action" | "allowFullScreen" | "allowTransparency" | "alt" | "as" | "async" | "autoComplete" | "autoFocus" | "autoPlay" | "capture" | "cellPadding" | "cellSpacing" | "charSet" | "challenge" | "checked" | "cite" | "classID" | "cols" | "colSpan" | "content" | "controls" | "coords" | "crossOrigin" | "data" | "dateTime" | "default" | "defer" | "disabled" | "download" | "encType" | "form" | "formAction" | "formEncType" | "formMethod" | "formNoValidate" | "formTarget" | "frameBorder" | "headers" | "height" | "high" | "href" | "hrefLang" | "htmlFor" | "httpEquiv" | "integrity" | "keyParams" | "keyType" | "kind" | "label" | "list" | "loop" | "low" | "manifest" | "marginHeight" | "marginWidth" | "max" | "maxLength" | "media" | "mediaGroup" | "method" | "min" | "minLength" | "multiple" | "muted" | "name" | "noValidate" | "open" | "optimum" | "pattern" | "placeholder" | "playsInline" | "poster" | "preload" | "readOnly" | "rel" | "required" | "reversed" | "rows" | "rowSpan" | "sandbox" | "scope" | "scoped" | "scrolling" | "seamless" | "selected" | "shape" | "size" | "sizes" | "span" | "src" | "srcDoc" | "srcLang" | "srcSet" | "start" | "step" | "summary" | "target" | "type" | "useMap" | "value" | "width" | "wmode" | "wrap" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "className" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "id" | "lang" | "nonce" | "slot" | "spellCheck" | "style" | "tabIndex" | "title" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onResize" | "onResizeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "key" | "dataTestId"> & React.RefAttributes<HTMLDivElement>>;
@@ -0,0 +1,12 @@
1
+ /// <reference types="react" />
2
+ interface PopoverTriggerProps {
3
+ /** Any elements that when clicked should open the popover */
4
+ children: React.ReactNode;
5
+ /**
6
+ * When enabled the trigger will be rendered as a button
7
+ * note that not all elements are valid children of a button
8
+ */
9
+ renderButton?: boolean;
10
+ }
11
+ export declare const PopoverTrigger: import("react").ForwardRefExoticComponent<Pick<import("react").HTMLProps<HTMLElement> & PopoverTriggerProps, "children" | "renderButton" | "accept" | "acceptCharset" | "action" | "allowFullScreen" | "allowTransparency" | "alt" | "as" | "async" | "autoComplete" | "autoFocus" | "autoPlay" | "capture" | "cellPadding" | "cellSpacing" | "charSet" | "challenge" | "checked" | "cite" | "classID" | "cols" | "colSpan" | "content" | "controls" | "coords" | "crossOrigin" | "data" | "dateTime" | "default" | "defer" | "disabled" | "download" | "encType" | "form" | "formAction" | "formEncType" | "formMethod" | "formNoValidate" | "formTarget" | "frameBorder" | "headers" | "height" | "high" | "href" | "hrefLang" | "htmlFor" | "httpEquiv" | "integrity" | "keyParams" | "keyType" | "kind" | "label" | "list" | "loop" | "low" | "manifest" | "marginHeight" | "marginWidth" | "max" | "maxLength" | "media" | "mediaGroup" | "method" | "min" | "minLength" | "multiple" | "muted" | "name" | "noValidate" | "open" | "optimum" | "pattern" | "placeholder" | "playsInline" | "poster" | "preload" | "readOnly" | "rel" | "required" | "reversed" | "rows" | "rowSpan" | "sandbox" | "scope" | "scoped" | "scrolling" | "seamless" | "selected" | "shape" | "size" | "sizes" | "span" | "src" | "srcDoc" | "srcLang" | "srcSet" | "start" | "step" | "summary" | "target" | "type" | "useMap" | "value" | "width" | "wmode" | "wrap" | "defaultChecked" | "defaultValue" | "suppressContentEditableWarning" | "suppressHydrationWarning" | "accessKey" | "className" | "contentEditable" | "contextMenu" | "dir" | "draggable" | "hidden" | "id" | "lang" | "nonce" | "slot" | "spellCheck" | "style" | "tabIndex" | "title" | "translate" | "radioGroup" | "role" | "about" | "datatype" | "inlist" | "prefix" | "property" | "resource" | "typeof" | "vocab" | "autoCapitalize" | "autoCorrect" | "autoSave" | "color" | "itemProp" | "itemScope" | "itemType" | "itemID" | "itemRef" | "results" | "security" | "unselectable" | "inputMode" | "is" | "aria-activedescendant" | "aria-atomic" | "aria-autocomplete" | "aria-busy" | "aria-checked" | "aria-colcount" | "aria-colindex" | "aria-colspan" | "aria-controls" | "aria-current" | "aria-describedby" | "aria-details" | "aria-disabled" | "aria-dropeffect" | "aria-errormessage" | "aria-expanded" | "aria-flowto" | "aria-grabbed" | "aria-haspopup" | "aria-hidden" | "aria-invalid" | "aria-keyshortcuts" | "aria-label" | "aria-labelledby" | "aria-level" | "aria-live" | "aria-modal" | "aria-multiline" | "aria-multiselectable" | "aria-orientation" | "aria-owns" | "aria-placeholder" | "aria-posinset" | "aria-pressed" | "aria-readonly" | "aria-relevant" | "aria-required" | "aria-roledescription" | "aria-rowcount" | "aria-rowindex" | "aria-rowspan" | "aria-selected" | "aria-setsize" | "aria-sort" | "aria-valuemax" | "aria-valuemin" | "aria-valuenow" | "aria-valuetext" | "dangerouslySetInnerHTML" | "onCopy" | "onCopyCapture" | "onCut" | "onCutCapture" | "onPaste" | "onPasteCapture" | "onCompositionEnd" | "onCompositionEndCapture" | "onCompositionStart" | "onCompositionStartCapture" | "onCompositionUpdate" | "onCompositionUpdateCapture" | "onFocus" | "onFocusCapture" | "onBlur" | "onBlurCapture" | "onChange" | "onChangeCapture" | "onBeforeInput" | "onBeforeInputCapture" | "onInput" | "onInputCapture" | "onReset" | "onResetCapture" | "onSubmit" | "onSubmitCapture" | "onInvalid" | "onInvalidCapture" | "onLoad" | "onLoadCapture" | "onError" | "onErrorCapture" | "onKeyDown" | "onKeyDownCapture" | "onKeyPress" | "onKeyPressCapture" | "onKeyUp" | "onKeyUpCapture" | "onAbort" | "onAbortCapture" | "onCanPlay" | "onCanPlayCapture" | "onCanPlayThrough" | "onCanPlayThroughCapture" | "onDurationChange" | "onDurationChangeCapture" | "onEmptied" | "onEmptiedCapture" | "onEncrypted" | "onEncryptedCapture" | "onEnded" | "onEndedCapture" | "onLoadedData" | "onLoadedDataCapture" | "onLoadedMetadata" | "onLoadedMetadataCapture" | "onLoadStart" | "onLoadStartCapture" | "onPause" | "onPauseCapture" | "onPlay" | "onPlayCapture" | "onPlaying" | "onPlayingCapture" | "onProgress" | "onProgressCapture" | "onRateChange" | "onRateChangeCapture" | "onResize" | "onResizeCapture" | "onSeeked" | "onSeekedCapture" | "onSeeking" | "onSeekingCapture" | "onStalled" | "onStalledCapture" | "onSuspend" | "onSuspendCapture" | "onTimeUpdate" | "onTimeUpdateCapture" | "onVolumeChange" | "onVolumeChangeCapture" | "onWaiting" | "onWaitingCapture" | "onAuxClick" | "onAuxClickCapture" | "onClick" | "onClickCapture" | "onContextMenu" | "onContextMenuCapture" | "onDoubleClick" | "onDoubleClickCapture" | "onDrag" | "onDragCapture" | "onDragEnd" | "onDragEndCapture" | "onDragEnter" | "onDragEnterCapture" | "onDragExit" | "onDragExitCapture" | "onDragLeave" | "onDragLeaveCapture" | "onDragOver" | "onDragOverCapture" | "onDragStart" | "onDragStartCapture" | "onDrop" | "onDropCapture" | "onMouseDown" | "onMouseDownCapture" | "onMouseEnter" | "onMouseLeave" | "onMouseMove" | "onMouseMoveCapture" | "onMouseOut" | "onMouseOutCapture" | "onMouseOver" | "onMouseOverCapture" | "onMouseUp" | "onMouseUpCapture" | "onSelect" | "onSelectCapture" | "onTouchCancel" | "onTouchCancelCapture" | "onTouchEnd" | "onTouchEndCapture" | "onTouchMove" | "onTouchMoveCapture" | "onTouchStart" | "onTouchStartCapture" | "onPointerDown" | "onPointerDownCapture" | "onPointerMove" | "onPointerMoveCapture" | "onPointerUp" | "onPointerUpCapture" | "onPointerCancel" | "onPointerCancelCapture" | "onPointerEnter" | "onPointerEnterCapture" | "onPointerLeave" | "onPointerLeaveCapture" | "onPointerOver" | "onPointerOverCapture" | "onPointerOut" | "onPointerOutCapture" | "onGotPointerCapture" | "onGotPointerCaptureCapture" | "onLostPointerCapture" | "onLostPointerCaptureCapture" | "onScroll" | "onScrollCapture" | "onWheel" | "onWheelCapture" | "onAnimationStart" | "onAnimationStartCapture" | "onAnimationEnd" | "onAnimationEndCapture" | "onAnimationIteration" | "onAnimationIterationCapture" | "onTransitionEnd" | "onTransitionEndCapture" | "key"> & import("react").RefAttributes<HTMLElement>>;
12
+ export {};
@@ -0,0 +1,33 @@
1
+ import { Placement } from "@floating-ui/react";
2
+ import { CommonProps } from "../../common";
3
+ export type PopoverActivation = {
4
+ click?: boolean;
5
+ hover?: boolean;
6
+ };
7
+ export type PopoverPlacement = Placement;
8
+ export interface PopoverProps extends CommonProps {
9
+ /**
10
+ * Whether the popover should be open on initial render
11
+ */
12
+ initialOpen?: boolean;
13
+ /**
14
+ * Where to preferentially render the popover relative to the invoking element.
15
+ */
16
+ placement?: PopoverPlacement;
17
+ /**
18
+ * Determines if focus is “modal”, meaning focus is fully trapped inside the floating element and outside content cannot be accessed. This includes screen reader virtual cursors.
19
+ */
20
+ isModal?: boolean;
21
+ /**
22
+ * Whether the popover IS CURRENTLY open
23
+ */
24
+ isOpen?: boolean;
25
+ /**
26
+ * Action(s) that activates the popover
27
+ */
28
+ activation?: PopoverActivation;
29
+ /**
30
+ * Callback to be called when the popover open state changes
31
+ */
32
+ onOpenStateChange?: (open: boolean) => void;
33
+ }
@@ -1,4 +1,5 @@
1
1
  export * from "./Popover";
2
- export * from "./PopoverList";
3
- export * from "./PopoverListItem";
2
+ export * from "./PopoverContent";
4
3
  export * from "./PopoverTitle";
4
+ export * from "./PopoverTrigger";
5
+ export * from "./PopoverTypes";
@@ -0,0 +1,56 @@
1
+ /// <reference types="react" />
2
+ import { PopoverProps } from "./PopoverTypes";
3
+ /**
4
+ * The hook that powers the Popover component.
5
+ * It should not be used directly, but rather through the Popover component.
6
+ *
7
+ * @param {PopoverProps} options The options for the popover
8
+ * @returns {ReturnType<usePopover>} The data for the popover
9
+ */
10
+ export declare const usePopover: ({ initialOpen, placement, isModal, isOpen: controlledIsOpen, activation, onOpenStateChange: setControlledIsOpen, ...restOptions }: PopoverProps) => {
11
+ isModal: boolean | undefined;
12
+ labelId: string | undefined;
13
+ descriptionId: string | undefined;
14
+ setLabelId: import("react").Dispatch<import("react").SetStateAction<string | undefined>>;
15
+ setDescriptionId: import("react").Dispatch<import("react").SetStateAction<string | undefined>>;
16
+ customProps: {
17
+ className?: string | undefined;
18
+ dataTestId?: string | undefined;
19
+ };
20
+ placement: import("@floating-ui/react").Placement;
21
+ strategy: import("@floating-ui/react").Strategy;
22
+ middlewareData: import("@floating-ui/react").MiddlewareData;
23
+ x: number | null;
24
+ y: number | null;
25
+ update: () => void;
26
+ reference: (node: import("@floating-ui/react").ReferenceType | null) => void;
27
+ floating: (node: HTMLElement | null) => void;
28
+ positionReference: (node: import("@floating-ui/react").ReferenceType | null) => void;
29
+ context: {
30
+ placement: import("@floating-ui/react").Placement;
31
+ strategy: import("@floating-ui/react").Strategy;
32
+ x: number | null;
33
+ y: number | null;
34
+ middlewareData: import("@floating-ui/react").MiddlewareData;
35
+ update: () => void;
36
+ reference: (node: import("@floating-ui/react").ReferenceType | null) => void;
37
+ floating: (node: HTMLElement | null) => void;
38
+ isPositioned: boolean;
39
+ open: boolean;
40
+ onOpenChange: (open: boolean) => void;
41
+ events: import("@floating-ui/react").FloatingEvents;
42
+ dataRef: import("react").MutableRefObject<import("@floating-ui/react").ContextData>;
43
+ nodeId: string | undefined;
44
+ floatingId: string;
45
+ refs: import("@floating-ui/react").ExtendedRefs<import("@floating-ui/react").ReferenceType>;
46
+ elements: import("@floating-ui/react").ExtendedElements<import("@floating-ui/react").ReferenceType>;
47
+ };
48
+ refs: import("@floating-ui/react").ExtendedRefs<import("@floating-ui/react").ReferenceType>;
49
+ elements: import("@floating-ui/react").ExtendedElements<import("@floating-ui/react").ReferenceType>;
50
+ isPositioned: boolean;
51
+ getReferenceProps: (userProps?: import("react").HTMLProps<Element> | undefined) => Record<string, unknown>;
52
+ getFloatingProps: (userProps?: import("react").HTMLProps<HTMLElement> | undefined) => Record<string, unknown>;
53
+ getItemProps: (userProps?: import("react").HTMLProps<HTMLElement> | undefined) => Record<string, unknown>;
54
+ isOpen: boolean;
55
+ setIsOpen: (open: boolean) => void;
56
+ };
@@ -7,6 +7,8 @@ export interface SidebarItemProps extends CommonProps {
7
7
  * This is needed as it is used for the intersection observer to determine which items are visible and which are not.
8
8
  */
9
9
  id: string;
10
+ /** Optional onClick */
11
+ onClick?: () => void;
10
12
  }
11
13
  export type Breakpoints = "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "3xl";
12
14
  export interface SidebarProps extends CommonProps {
@@ -1,12 +0,0 @@
1
- import * as React from "react";
2
- import { CommonProps } from "../../common/CommonProps";
3
- export interface PopoverListProps extends CommonProps {
4
- children: React.ReactNode;
5
- }
6
- /**
7
- * The PopoverList component.
8
- *
9
- * @param {PopoverListProps} props - The props for the PopoverList component
10
- * @returns {JSX.Element} PopoverList component
11
- */
12
- export declare const PopoverList: ({ className, children, dataTestId }: PopoverListProps) => JSX.Element;
@@ -1,30 +0,0 @@
1
- import * as React from "react";
2
- import { CommonProps } from "../../common/CommonProps";
3
- export interface PopoverListItemProps extends CommonProps {
4
- selected?: boolean;
5
- disabled?: boolean;
6
- ariaLabel?: string;
7
- /** Optional event handler for logging etc. Important: Please use the Url prop for navigation. */
8
- onClick?: (event: React.MouseEvent<HTMLLIElement, MouseEvent>) => void;
9
- /** Navigation Url for this item */
10
- url?: string;
11
- /**
12
- * The prefix to be displayed for the list item.
13
- */
14
- prefix?: React.ReactNode;
15
- /**
16
- * The suffix to be displayed for the list item.
17
- */
18
- suffix?: React.ReactNode;
19
- /**
20
- * The child nodes.
21
- */
22
- children: React.ReactNode;
23
- }
24
- /**
25
- * The PopoverListItem component.
26
- *
27
- * @param {PopoverListItemProps} props - The props for the PopoverListItem component
28
- * @returns {JSX.Element} PopoverListItem component
29
- */
30
- export declare const PopoverListItem: ({ selected, children, disabled, ariaLabel, url, onClick, prefix, suffix, dataTestId, className, }: PopoverListItemProps) => JSX.Element;