@luscii-healthtech/web-ui 20.2.1 → 20.4.0

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.
@@ -5,6 +5,11 @@ export interface AccordionProps {
5
5
  items: AccordionItemProps[];
6
6
  className?: string;
7
7
  isCollapsedByDefault?: boolean;
8
+ /**
9
+ * A section at the bottom of the accordion that is
10
+ * always visible, even when the accordion is closed.
11
+ */
12
+ footer?: React.ReactNode;
8
13
  }
9
- declare const Accordion: React.VFC<AccordionProps>;
14
+ declare const Accordion: React.FC<AccordionProps>;
10
15
  export default Accordion;
@@ -1,9 +1,17 @@
1
1
  import React from "react";
2
2
  export interface AccordionItemProps {
3
3
  id: string | number;
4
- title: string;
4
+ title: React.ReactNode;
5
5
  content: React.ReactNode;
6
6
  className?: string;
7
7
  isCollapsedByDefault?: boolean;
8
+ /**
9
+ * Called when the accordion item opens.
10
+ */
11
+ onOpened?: () => void;
12
+ /**
13
+ * Called when the accordion item closes.
14
+ */
15
+ onClosed?: () => void;
8
16
  }
9
- export declare const AccordionItem: React.VFC<AccordionItemProps>;
17
+ export declare const AccordionItem: React.FC<AccordionItemProps>;
@@ -21,18 +21,21 @@ export interface AccordionListProps extends Omit<AccordionProps, "items"> {
21
21
  isLoading?: boolean;
22
22
  actions?: React.ReactNode;
23
23
  }
24
- export type AccordionListItemProps<T = ListItemProps> = Omit<AccordionItemProps, "content"> & {
24
+ export type AccordionListItemProps<T = ListItemProps> = Omit<AccordionItemProps, "title" | "content"> & {
25
25
  listItems: T[];
26
26
  draggableListType?: "default";
27
+ title: string;
27
28
  };
28
- export type DraggableAccordionListItemProps = Omit<AccordionItemProps, "content"> & {
29
+ export type DraggableAccordionListItemProps = Omit<AccordionItemProps, "title" | "content"> & {
29
30
  draggableListType: "draggable";
30
31
  listItems: DraggableListProps["items"];
32
+ title: string;
31
33
  };
32
- export type SortableAccordionListItemProps = Omit<AccordionItemProps, "content"> & {
34
+ export type SortableAccordionListItemProps = Omit<AccordionItemProps, "title" | "content"> & {
33
35
  draggableListType: "sortable";
34
36
  draggableIdentifier: string;
35
37
  listItems: SortableListProps["items"];
38
+ title: string;
36
39
  };
37
40
  export type AccordionItem = AccordionListItemProps | DraggableAccordionListItemProps | SortableAccordionListItemProps;
38
41
  interface StaticComponents {
@@ -0,0 +1,86 @@
1
+ import React from "react";
2
+ import { Text } from "../Text/Text";
3
+ import { Divider } from "../Divider/Divider";
4
+ type Props = React.ComponentPropsWithoutRef<"div"> & {
5
+ /**
6
+ * Renders above the menu items, but below the header.
7
+ */
8
+ title?: string | React.ReactNode;
9
+ /**
10
+ * Renders above everything else.
11
+ */
12
+ header?: React.ReactNode;
13
+ /**
14
+ * Renders below everything else.
15
+ */
16
+ footer?: React.ReactNode;
17
+ };
18
+ type StaticComponents = {
19
+ Divider: typeof MenuDivider;
20
+ Item: typeof MenuItem;
21
+ ItemLayout: typeof MenuItemLayout;
22
+ ItemText: typeof MenuItemText;
23
+ ItemPadding: typeof MenuItemPadding;
24
+ NotificationBubble: typeof MenuItemNotificationBubble;
25
+ };
26
+ export declare const VerticalMenu: React.FC<Props> & StaticComponents;
27
+ declare function MenuItemText(props: Readonly<React.ComponentPropsWithoutRef<typeof Text>>): React.JSX.Element;
28
+ type GetClassNameFunction = (args?: {
29
+ /**
30
+ * Whether the item should display as active.
31
+ */
32
+ isActive?: boolean;
33
+ /**
34
+ * Your own class name to add to the item.
35
+ */
36
+ classNameProp?: string;
37
+ }) => string;
38
+ type MenuItemProps = {
39
+ render: (props: {
40
+ /**
41
+ * Returns the "calculated" className for the item.
42
+ *
43
+ * The `VerticalMenu` component will decide which
44
+ * classes should be applied to a menu item to make
45
+ * it appear correctly in the menu. By placing the
46
+ * string of these classes on your own element/component,
47
+ * you allow the `VerticalMenu` component to style your
48
+ * element correctly.
49
+ */
50
+ getClassName: GetClassNameFunction;
51
+ }) => React.ReactNode;
52
+ children?: never;
53
+ paddingX?: never;
54
+ paddingY?: never;
55
+ } | {
56
+ render?: never;
57
+ children?: React.ReactNode;
58
+ paddingX?: boolean;
59
+ paddingY?: boolean;
60
+ };
61
+ declare function MenuItem(props: MenuItemProps): string | number | boolean | Iterable<React.ReactNode> | React.JSX.Element | null | undefined;
62
+ type MenuItemLayoutProps = {
63
+ icon?: React.ReactNode;
64
+ text?: React.ReactNode;
65
+ className?: string;
66
+ children?: React.ReactNode;
67
+ } & ({
68
+ aside?: React.ReactNode;
69
+ notificationBubbleText?: never;
70
+ } | {
71
+ aside?: never;
72
+ notificationBubbleText?: string;
73
+ });
74
+ declare function MenuItemLayout(props: MenuItemLayoutProps): React.JSX.Element;
75
+ declare function MenuItemPadding(props: Readonly<{
76
+ children?: React.ReactNode;
77
+ className?: string;
78
+ paddingX?: boolean;
79
+ paddingY?: boolean;
80
+ }>): React.JSX.Element;
81
+ declare function MenuItemNotificationBubble(props: Readonly<{
82
+ children?: React.ReactNode;
83
+ className?: string;
84
+ }>): React.JSX.Element;
85
+ declare function MenuDivider(props: React.ComponentPropsWithoutRef<typeof Divider>): React.JSX.Element;
86
+ export {};
package/dist/index.d.ts CHANGED
@@ -3,6 +3,13 @@ export { FlexRow } from "./components/Container/FlexRow";
3
3
  export type { FlexContainerProps } from "./components/Container/types/FlexContainerProps.type";
4
4
  export { default as Toaster, TOASTER_TYPE_OPTIONS, } from "./components/Toaster/Toaster";
5
5
  export { toast } from "./components/Toaster/toast";
6
+ /**
7
+ * We want a better version for the Accordion component, so we're
8
+ * only temporarily exporting the current version. The new version
9
+ * will be called `Accordion`, which will allow us to slowly migrate
10
+ * to the new version.
11
+ */
12
+ export { default as AccordionTemporary } from "./components/Accordion/Accordion";
6
13
  export { AccordionList, AccordionListItemProps, AccordionListProps, } from "./components/AccordionList/AccordionList";
7
14
  export { Modal, ModalProps } from "./components/Modal/Modal";
8
15
  export { ModalSize, ModalBaseProps } from "./components/Modal/ModalBase";
@@ -74,6 +81,7 @@ export type { IconProps, IconKey, } from "./components/Icons/types/IconProps.typ
74
81
  export * from "./components/Icons";
75
82
  export { Divider } from "./components/Divider/Divider";
76
83
  export { FullPageModal } from "./components/Modal/FullPageModal";
84
+ export { VerticalMenu } from "./components/VerticalMenu/VerticalMenu";
77
85
  export { Card, type Props as CardProps } from "./components/Card/Card";
78
86
  export { Dropzone, DropzoneProps } from "./components/Dropzone";
79
87
  export { FilterBar, FilterBarUtils } from "./components/FilterBar";
@@ -2,6 +2,7 @@
2
2
 
3
3
  var React = require('react');
4
4
  var classNames = require('classnames');
5
+ var isString = require('lodash/isString');
5
6
  var lodash = require('lodash');
6
7
  var core = require('@dnd-kit/core');
7
8
  var sortable = require('@dnd-kit/sortable');
@@ -49,6 +50,7 @@ function _interopNamespace(e) {
49
50
 
50
51
  var React__namespace = /*#__PURE__*/_interopNamespace(React);
51
52
  var classNames__default = /*#__PURE__*/_interopDefault(classNames);
53
+ var isString__default = /*#__PURE__*/_interopDefault(isString);
52
54
  var ReactTooltip__default = /*#__PURE__*/_interopDefault(ReactTooltip);
53
55
  var ReactModal__default = /*#__PURE__*/_interopDefault(ReactModal);
54
56
  var Glider__default = /*#__PURE__*/_interopDefault(Glider);
@@ -1073,8 +1075,16 @@ Title.defaultProps = {
1073
1075
  type: "base"
1074
1076
  };
1075
1077
 
1076
- const AccordionItem = ({ id, title, content, isCollapsedByDefault = false }) => {
1077
- const [isCollapsed, toggleIsCollapsed] = React.useReducer((state) => !state, isCollapsedByDefault);
1078
+ const AccordionItem = ({ id, title, content, isCollapsedByDefault = false, onClosed, onOpened }) => {
1079
+ const [isCollapsed, toggleIsCollapsed] = React.useReducer((isCol) => {
1080
+ const newStateIsCollapsed = !isCol;
1081
+ if (newStateIsCollapsed) {
1082
+ onClosed === null || onClosed === void 0 ? void 0 : onClosed();
1083
+ } else {
1084
+ onOpened === null || onOpened === void 0 ? void 0 : onOpened();
1085
+ }
1086
+ return newStateIsCollapsed;
1087
+ }, isCollapsedByDefault);
1078
1088
  const Chevron = isCollapsed ? RightArrowIcon : ChevronDownIcon;
1079
1089
  return React__namespace.default.createElement(
1080
1090
  "li",
@@ -1085,18 +1095,23 @@ const AccordionItem = ({ id, title, content, isCollapsedByDefault = false }) =>
1085
1095
  "ui-border-b ui-border-slate-200": !isCollapsed
1086
1096
  }) },
1087
1097
  React__namespace.default.createElement(Chevron, { className: "ui-text-slate-300" }),
1088
- React__namespace.default.createElement(Title, { text: title, type: "xs" })
1098
+ isString__default.default(title) ? React__namespace.default.createElement(Title, { type: "xs" }, title) : title
1089
1099
  ),
1090
1100
  React__namespace.default.createElement("div", { className: classNames__default.default({ "ui-hidden": isCollapsed }) }, content)
1091
1101
  );
1092
1102
  };
1093
1103
 
1094
- const Accordion = ({ dataTestId, isCollapsedByDefault = false, items, className }) => {
1104
+ const Accordion = ({ dataTestId, isCollapsedByDefault = false, items, className, footer }) => {
1095
1105
  var _a;
1096
- return React__namespace.default.createElement("ul", { "data-test-id": dataTestId, className }, (_a = items.map) === null || _a === void 0 ? void 0 : _a.call(items, (item) => {
1097
- var _a2;
1098
- return React__namespace.default.createElement(AccordionItem, Object.assign({}, item, { key: item.id, isCollapsedByDefault: (_a2 = item.isCollapsedByDefault) !== null && _a2 !== void 0 ? _a2 : isCollapsedByDefault }));
1099
- }));
1106
+ return React__namespace.default.createElement(
1107
+ "ul",
1108
+ { "data-test-id": dataTestId, className },
1109
+ (_a = items.map) === null || _a === void 0 ? void 0 : _a.call(items, (item) => {
1110
+ var _a2;
1111
+ return React__namespace.default.createElement(AccordionItem, Object.assign({}, item, { key: item.id, isCollapsedByDefault: (_a2 = item.isCollapsedByDefault) !== null && _a2 !== void 0 ? _a2 : isCollapsedByDefault }));
1112
+ }),
1113
+ footer && React__namespace.default.createElement("div", { className: "ui-p-4" }, footer)
1114
+ );
1100
1115
  };
1101
1116
 
1102
1117
  var css_248z$j = ".list-skeleton .skeleton-box {\n display: inline-block;\n height: 1em;\n position: relative;\n overflow: hidden;\n background-color: #cbd5e1;\n border-radius: 3px;\n}\n.list-skeleton .skeleton-box::after {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n transform: translateX(-100%);\n background-image: linear-gradient(90deg, rgba(255, 255, 255, 0) 0, rgba(255, 255, 255, 0.2) 20%, rgba(255, 255, 255, 0.5) 60%, rgba(255, 255, 255, 0));\n animation: shimmer 800ms infinite;\n content: \"\";\n}\n.list-skeleton .skeleton-box.is-circle {\n border-radius: 50%;\n}\n.list-skeleton .skeleton-box.is-button {\n background-color: #e2e8f0;\n border-radius: 9999px;\n}\n.list-skeleton .skeleton-box.is-button::after {\n position: absolute;\n top: 0;\n right: 0;\n bottom: 0;\n left: 0;\n transform: translateX(-100%);\n background-image: linear-gradient(90deg, rgba(221, 221, 221, 0) 0, rgba(221, 221, 221, 0.2) 20%, rgba(221, 221, 221, 0.5) 60%, rgba(221, 221, 221, 0));\n animation: shimmer 800ms infinite;\n content: \"\";\n}\n@keyframes shimmer {\n 100% {\n transform: translateX(100%);\n }\n}";
@@ -5394,6 +5409,95 @@ const FullPageModal = ({ children, dataTestId, isOpen = false, onCloseClick, pri
5394
5409
  FullPageModal.Actions = FullPageModalActions;
5395
5410
  FullPageModal.setAppElement = ReactModal__default.default.setAppElement;
5396
5411
 
5412
+ const VerticalMenu = (props) => {
5413
+ const { className, title, header, footer } = props, rest = __rest(props, ["className", "title", "header", "footer"]);
5414
+ return React__namespace.default.createElement(
5415
+ "div",
5416
+ Object.assign({ className: classNames__default.default("ui-flex ui-h-full ui-flex-col ui-px-xxs ui-py-m ui-text-slate-800", className) }, rest),
5417
+ React__namespace.default.createElement("div", null, header),
5418
+ React__namespace.default.createElement(Text, { className: "ui-px-m ui-pb-m ui-pt-xs", variant: "lg-strong" }, title),
5419
+ React__namespace.default.createElement("div", null, props.children),
5420
+ React__namespace.default.createElement("div", { className: "ui-mt-auto" }, footer)
5421
+ );
5422
+ };
5423
+ VerticalMenu.Divider = MenuDivider;
5424
+ VerticalMenu.Item = MenuItem;
5425
+ VerticalMenu.ItemLayout = MenuItemLayout;
5426
+ VerticalMenu.ItemText = MenuItemText;
5427
+ VerticalMenu.ItemPadding = MenuItemPadding;
5428
+ VerticalMenu.NotificationBubble = MenuItemNotificationBubble;
5429
+ function MenuItemText(props) {
5430
+ return React__namespace.default.createElement(Text, Object.assign({ color: "current", variant: "strong" }, props, { className: classNames__default.default("ui-leading-[24px]", props.className) }));
5431
+ }
5432
+ const getClassName = ({ isActive = false, classNameProp = "" } = {}) => classNames__default.default(
5433
+ // Base
5434
+ "ui-block ui-w-full ui-px-m ui-py-xs ui-radius-xxs",
5435
+ // Transitions
5436
+ "ui-transition-[color,background,transform]",
5437
+ // States
5438
+ "hover:ui-bg-primary-background hover:ui-text-primary focus:ui-text-primary active:ui-scale-[0.98]",
5439
+ {
5440
+ "ui-bg-transparent ui-text-on-surface": !isActive,
5441
+ "ui-bg-gradient-to-r ui-from-blue-800 ui-to-blue-700 ui-text-white hover:ui-text-white focus:ui-text-white": isActive
5442
+ },
5443
+ classNameProp
5444
+ );
5445
+ function MenuItem(props) {
5446
+ var _a;
5447
+ const { children, paddingX = true, paddingY = true } = props;
5448
+ if (children) {
5449
+ return React__namespace.default.createElement("div", { className: classNames__default.default({
5450
+ "ui-px-m": paddingX,
5451
+ "ui-py-xs": paddingY
5452
+ }) }, children);
5453
+ }
5454
+ return (_a = props.render) === null || _a === void 0 ? void 0 : _a.call(props, { getClassName });
5455
+ }
5456
+ function MenuItemLayout(props) {
5457
+ const { icon, text, aside, notificationBubbleText, className, children } = props;
5458
+ if (children) {
5459
+ return React__namespace.default.createElement("div", null, children);
5460
+ }
5461
+ return React__namespace.default.createElement(
5462
+ "div",
5463
+ { className: classNames__default.default("ui-flex ui-items-start ui-gap-xxs", className) },
5464
+ icon && React__namespace.default.createElement("span", null, icon),
5465
+ text && React__namespace.default.createElement(MenuItemText, null, text),
5466
+ aside && React__namespace.default.createElement("span", { className: "ui-ml-auto" }, aside),
5467
+ notificationBubbleText && React__namespace.default.createElement(
5468
+ "span",
5469
+ { className: "ui-ml-auto" },
5470
+ React__namespace.default.createElement(MenuItemNotificationBubble, null, notificationBubbleText)
5471
+ )
5472
+ );
5473
+ }
5474
+ function MenuItemPadding(props) {
5475
+ const { children, className, paddingX = true, paddingY = true } = props;
5476
+ return React__namespace.default.createElement("div", { className: classNames__default.default({
5477
+ "ui-px-m": paddingX,
5478
+ "ui-py-xs": paddingY
5479
+ }, className) }, children);
5480
+ }
5481
+ function MenuItemNotificationBubble(props) {
5482
+ return React__namespace.default.createElement(
5483
+ "div",
5484
+ { className: classNames__default.default(
5485
+ /**
5486
+ * Spacing `l` is 24px, which is the line height for the
5487
+ * text size here. This makes the bubble a perfect circle when
5488
+ * there is too little text.
5489
+ */
5490
+ "ui-min-w-l",
5491
+ "ui-rounded-full ui-bg-red-500 ui-px-xxs ui-text-center",
5492
+ props.className
5493
+ ) },
5494
+ React__namespace.default.createElement(Text, { color: "white", inline: true, className: "ui-align-text-bottom" }, props.children)
5495
+ );
5496
+ }
5497
+ function MenuDivider(props) {
5498
+ return React__namespace.default.createElement(Divider, Object.assign({ className: "ui-m-1 ui-my-xxs last:ui-border-b-1" }, props));
5499
+ }
5500
+
5397
5501
  const Actions = (props) => {
5398
5502
  const { children, className } = props, rest = __rest(props, ["children", "className"]);
5399
5503
  return React__namespace.default.createElement("div", Object.assign({}, rest, { className: classNames__default.default(
@@ -5807,6 +5911,7 @@ WeekdaysPicker.weekdayNameToIndex = weekdayNameToIndex;
5807
5911
  WeekdaysPicker.indexToWeekdayName = indexToWeekdayName;
5808
5912
 
5809
5913
  exports.AccordionList = AccordionList;
5914
+ exports.AccordionTemporary = Accordion;
5810
5915
  exports.AddIcon = AddIcon;
5811
5916
  exports.AlertsIcon = BellIcon;
5812
5917
  exports.Avatar = Avatar;
@@ -5969,6 +6074,7 @@ exports.Toaster = Toaster;
5969
6074
  exports.TrashBinIcon = DeleteIcon;
5970
6075
  exports.UList = UnorderedList;
5971
6076
  exports.UnorderedList = UnorderedList;
6077
+ exports.VerticalMenu = VerticalMenu;
5972
6078
  exports.ViewItem = ViewItem;
5973
6079
  exports.WarningIcon = ExclamationMarkIcon;
5974
6080
  exports.WeekdaysPicker = WeekdaysPicker;