@databiosphere/findable-ui 32.1.1 → 34.0.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.
Files changed (185) hide show
  1. package/.release-please-manifest.json +1 -1
  2. package/CHANGELOG.md +27 -0
  3. package/jest.config.js +4 -0
  4. package/lib/common/categories/config/utils.d.ts +1 -1
  5. package/lib/common/categories/config/utils.js +5 -1
  6. package/lib/common/entities.d.ts +4 -4
  7. package/lib/components/DataDictionary/components/Entities/entities.d.ts +1 -1
  8. package/lib/components/DataDictionary/components/Entities/entities.js +3 -2
  9. package/lib/components/DataDictionary/components/Entities/types.d.ts +3 -4
  10. package/lib/components/DataDictionary/components/Entity/entity.d.ts +1 -1
  11. package/lib/components/DataDictionary/components/Entity/entity.js +12 -6
  12. package/lib/components/DataDictionary/components/Entity/entity.styles.js +7 -1
  13. package/lib/components/DataDictionary/components/Entity/types.d.ts +4 -4
  14. package/lib/components/DataDictionary/components/Entity/utils.d.ts +9 -0
  15. package/lib/components/DataDictionary/components/Entity/utils.js +18 -0
  16. package/lib/components/DataDictionary/components/Filters/components/ColumnFilters/columnFilters.d.ts +4 -0
  17. package/lib/components/DataDictionary/components/Filters/components/ColumnFilters/columnFilters.js +9 -0
  18. package/lib/components/DataDictionary/components/Filters/components/ColumnFilters/types.d.ts +5 -0
  19. package/lib/components/DataDictionary/components/Filters/components/ColumnFilters/types.js +1 -0
  20. package/lib/components/DataDictionary/components/Filters/filters.d.ts +4 -0
  21. package/lib/components/DataDictionary/components/Filters/filters.js +7 -0
  22. package/lib/components/DataDictionary/components/Filters/filters.styles.d.ts +7 -0
  23. package/lib/components/DataDictionary/components/Filters/filters.styles.js +13 -0
  24. package/lib/components/DataDictionary/components/Filters/stories/constants.d.ts +4 -0
  25. package/lib/components/DataDictionary/components/Filters/stories/constants.js +25 -0
  26. package/lib/components/DataDictionary/components/Filters/stories/filters.stories.d.ts +6 -0
  27. package/lib/components/DataDictionary/components/Filters/stories/filters.stories.js +31 -0
  28. package/lib/components/DataDictionary/components/Filters/stories/hook.d.ts +5 -0
  29. package/lib/components/DataDictionary/components/Filters/stories/hook.js +5 -0
  30. package/lib/components/DataDictionary/components/Filters/stories/types.d.ts +4 -0
  31. package/lib/components/DataDictionary/components/Filters/stories/types.js +1 -0
  32. package/lib/components/DataDictionary/components/Filters/types.d.ts +5 -0
  33. package/lib/components/DataDictionary/components/Filters/types.js +1 -0
  34. package/lib/components/DataDictionary/components/Layout/components/EntitiesLayout/entitiesLayout.styles.js +3 -1
  35. package/lib/components/DataDictionary/components/Layout/components/FiltersLayout/filtersLayout.d.ts +2 -0
  36. package/lib/components/DataDictionary/components/Layout/components/FiltersLayout/filtersLayout.js +5 -0
  37. package/lib/components/DataDictionary/components/Layout/components/FiltersLayout/filtersLayout.styles.d.ts +5 -0
  38. package/lib/components/DataDictionary/components/Layout/components/FiltersLayout/filtersLayout.styles.js +24 -0
  39. package/lib/components/DataDictionary/components/Layout/components/FiltersLayout/types.d.ts +5 -0
  40. package/lib/components/DataDictionary/components/Layout/components/FiltersLayout/types.js +1 -0
  41. package/lib/components/DataDictionary/components/Layout/components/OutlineLayout/outlineLayout.styles.js +1 -1
  42. package/lib/components/DataDictionary/components/Layout/components/TitleLayout/titleLayout.styles.js +1 -0
  43. package/lib/components/DataDictionary/components/Layout/constants.d.ts +4 -0
  44. package/lib/components/DataDictionary/components/Layout/constants.js +4 -0
  45. package/lib/components/DataDictionary/components/Outline/utils.d.ts +5 -5
  46. package/lib/components/DataDictionary/components/Outline/utils.js +23 -6
  47. package/lib/components/DataDictionary/components/Table/hook.d.ts +3 -3
  48. package/lib/components/DataDictionary/components/Table/hook.js +11 -3
  49. package/lib/components/DataDictionary/components/Table/options/columnFilters/constants.d.ts +2 -0
  50. package/lib/components/DataDictionary/components/Table/options/columnFilters/constants.js +8 -0
  51. package/lib/components/DataDictionary/components/Table/options/columnFilters/hook.d.ts +6 -0
  52. package/lib/components/DataDictionary/components/Table/options/columnFilters/hook.js +14 -0
  53. package/lib/components/DataDictionary/components/Table/options/expanded/constants.d.ts +2 -0
  54. package/lib/components/DataDictionary/components/Table/options/expanded/constants.js +5 -0
  55. package/lib/components/DataDictionary/components/Table/options/faceted/constants.d.ts +2 -0
  56. package/lib/components/DataDictionary/components/Table/options/faceted/constants.js +6 -0
  57. package/lib/components/DataDictionary/components/Table/options/grouping/constants.d.ts +2 -0
  58. package/lib/components/DataDictionary/components/Table/options/grouping/constants.js +5 -0
  59. package/lib/components/DataDictionary/components/Table/options/hook.d.ts +1 -1
  60. package/lib/components/DataDictionary/components/Table/options/hook.js +17 -0
  61. package/lib/components/DataDictionary/components/Table/options/visibility/constants.d.ts +2 -0
  62. package/lib/components/DataDictionary/components/Table/options/visibility/constants.js +3 -0
  63. package/lib/components/DataDictionary/components/Table/table.d.ts +1 -1
  64. package/lib/components/DataDictionary/components/Table/table.js +2 -2
  65. package/lib/components/DataDictionary/components/Table/types.d.ts +4 -1
  66. package/lib/components/DataDictionary/components/Table/utils.d.ts +18 -0
  67. package/lib/components/DataDictionary/components/Table/utils.js +27 -0
  68. package/lib/components/DataDictionary/dataDictionary.d.ts +1 -1
  69. package/lib/components/DataDictionary/dataDictionary.js +9 -7
  70. package/lib/components/DataDictionary/hooks/UseDataDictionary/hook.js +16 -4
  71. package/lib/components/DataDictionary/hooks/UseDataDictionary/types.d.ts +6 -4
  72. package/lib/components/DataDictionary/types.d.ts +1 -0
  73. package/lib/components/Detail/components/Table/components/TableBody/tableBody.d.ts +8 -2
  74. package/lib/components/Detail/components/Table/components/TableBody/tableBody.js +2 -2
  75. package/lib/components/Detail/components/Table/components/TableRows/components/CollapsableRows/collapsableRows.d.ts +8 -2
  76. package/lib/components/Detail/components/Table/components/TableRows/components/CollapsableRows/collapsableRows.js +2 -2
  77. package/lib/components/Detail/components/Table/components/TableRows/tableRows.d.ts +8 -2
  78. package/lib/components/Detail/components/Table/components/TableRows/tableRows.js +2 -2
  79. package/lib/components/Filter/components/FilterLabel/filterLabel.styles.d.ts +1 -1
  80. package/lib/components/Filter/components/FilterList/filterList.styles.d.ts +2 -0
  81. package/lib/components/Filter/components/FilterList/filterList.styles.js +28 -15
  82. package/lib/components/Filter/components/SearchAllFiltersSearch/searchAllFiltersSearch.styles.d.ts +1 -1
  83. package/lib/components/Layout/components/Header/components/Content/components/Actions/components/Authentication/components/Button/button.styles.d.ts +1 -1
  84. package/lib/components/Layout/components/Header/components/Content/components/Actions/components/Search/components/Button/button.styles.d.ts +1 -1
  85. package/lib/components/Layout/components/Header/header.styles.js +4 -1
  86. package/lib/components/Layout/components/Outline/components/ContentsTab/contentsTab.styles.d.ts +1 -1
  87. package/lib/components/Layout/components/Outline/outline.styles.d.ts +1 -1
  88. package/lib/components/Login/components/Button/button.styles.d.ts +1 -1
  89. package/lib/components/Table/common/utils.d.ts +6 -0
  90. package/lib/components/Table/common/utils.js +14 -0
  91. package/lib/components/Table/components/TableFeatures/ColumnFilter/columnFilter.d.ts +7 -0
  92. package/lib/components/Table/components/TableFeatures/ColumnFilter/columnFilter.js +33 -0
  93. package/lib/components/Table/components/TableFeatures/ColumnFilter/columnFilter.styles.d.ts +3 -0
  94. package/lib/components/Table/components/TableFeatures/ColumnFilter/columnFilter.styles.js +19 -0
  95. package/lib/components/Table/components/TableFeatures/ColumnFilter/constants.d.ts +2 -0
  96. package/lib/components/Table/components/TableFeatures/ColumnFilter/constants.js +14 -0
  97. package/lib/components/Table/components/TableFeatures/ColumnFilter/types.d.ts +7 -0
  98. package/lib/components/Table/components/TableFeatures/ColumnFilter/types.js +1 -0
  99. package/lib/components/Table/components/TableFeatures/ColumnFilter/utils.d.ts +6 -0
  100. package/lib/components/Table/components/TableFeatures/ColumnFilter/utils.js +23 -0
  101. package/lib/components/Table/featureOptions/facetedColumn/utils.d.ts +6 -0
  102. package/lib/components/Table/featureOptions/facetedColumn/utils.js +9 -0
  103. package/lib/components/common/ButtonGroup/constants.d.ts +2 -0
  104. package/lib/components/common/ButtonGroup/constants.js +11 -0
  105. package/lib/components/common/Tabs/tabs.styles.d.ts +1 -1
  106. package/lib/mocks/@storybook/addon-actions.d.ts +9 -0
  107. package/lib/mocks/@storybook/addon-actions.js +9 -0
  108. package/lib/styles/common/mui/buttonGroup.d.ts +13 -0
  109. package/lib/styles/common/mui/buttonGroup.js +34 -0
  110. package/lib/styles/common/mui/typography.js +2 -0
  111. package/lib/tests/mui/constants.d.ts +1 -0
  112. package/lib/tests/mui/constants.js +1 -0
  113. package/lib/tests/utils.d.ts +6 -0
  114. package/lib/tests/utils.js +8 -0
  115. package/lib/theme/common/components.d.ts +0 -6
  116. package/lib/theme/common/components.js +17 -31
  117. package/lib/theme/components/index.d.ts +1 -0
  118. package/lib/theme/components/index.js +1 -0
  119. package/lib/theme/components/muiButtonGroup.d.ts +2 -0
  120. package/lib/theme/components/muiButtonGroup.js +76 -0
  121. package/lib/theme/theme.js +1 -1
  122. package/package.json +1 -1
  123. package/src/common/categories/config/utils.ts +6 -3
  124. package/src/common/entities.ts +5 -4
  125. package/src/components/DataDictionary/components/Entities/entities.tsx +5 -9
  126. package/src/components/DataDictionary/components/Entities/types.ts +3 -4
  127. package/src/components/DataDictionary/components/Entity/entity.styles.ts +9 -1
  128. package/src/components/DataDictionary/components/Entity/entity.tsx +18 -8
  129. package/src/components/DataDictionary/components/Entity/types.ts +4 -4
  130. package/src/components/DataDictionary/components/Entity/utils.ts +25 -0
  131. package/src/components/DataDictionary/components/Filters/components/ColumnFilters/columnFilters.tsx +21 -0
  132. package/src/components/DataDictionary/components/Filters/components/ColumnFilters/types.ts +6 -0
  133. package/src/components/DataDictionary/components/Filters/filters.styles.ts +14 -0
  134. package/src/components/DataDictionary/components/Filters/filters.tsx +16 -0
  135. package/src/components/DataDictionary/components/Filters/stories/constants.ts +31 -0
  136. package/src/components/DataDictionary/components/Filters/stories/filters.stories.tsx +42 -0
  137. package/src/components/DataDictionary/components/Filters/stories/hook.ts +9 -0
  138. package/src/components/DataDictionary/components/Filters/stories/types.ts +3 -0
  139. package/src/components/DataDictionary/components/Filters/types.ts +6 -0
  140. package/src/components/DataDictionary/components/Layout/components/EntitiesLayout/entitiesLayout.styles.ts +4 -1
  141. package/src/components/DataDictionary/components/Layout/components/FiltersLayout/filtersLayout.styles.ts +27 -0
  142. package/src/components/DataDictionary/components/Layout/components/FiltersLayout/filtersLayout.tsx +10 -0
  143. package/src/components/DataDictionary/components/Layout/components/FiltersLayout/types.ts +6 -0
  144. package/src/components/DataDictionary/components/Layout/components/OutlineLayout/outlineLayout.styles.ts +1 -1
  145. package/src/components/DataDictionary/components/Layout/components/TitleLayout/titleLayout.styles.ts +1 -0
  146. package/src/components/DataDictionary/components/Layout/constants.ts +4 -0
  147. package/src/components/DataDictionary/components/Outline/utils.ts +35 -13
  148. package/src/components/DataDictionary/components/Table/hook.ts +17 -5
  149. package/src/components/DataDictionary/components/Table/options/columnFilters/constants.ts +16 -0
  150. package/src/components/DataDictionary/components/Table/options/columnFilters/hook.ts +32 -0
  151. package/src/components/DataDictionary/components/Table/options/expanded/constants.ts +13 -0
  152. package/src/components/DataDictionary/components/Table/options/faceted/constants.ts +14 -0
  153. package/src/components/DataDictionary/components/Table/options/grouping/constants.ts +9 -0
  154. package/src/components/DataDictionary/components/Table/options/hook.ts +26 -3
  155. package/src/components/DataDictionary/components/Table/options/visibility/constants.ts +5 -0
  156. package/src/components/DataDictionary/components/Table/table.tsx +2 -0
  157. package/src/components/DataDictionary/components/Table/types.ts +8 -1
  158. package/src/components/DataDictionary/components/Table/utils.ts +40 -0
  159. package/src/components/DataDictionary/dataDictionary.tsx +10 -6
  160. package/src/components/DataDictionary/hooks/UseDataDictionary/hook.ts +19 -4
  161. package/src/components/DataDictionary/hooks/UseDataDictionary/types.ts +6 -4
  162. package/src/components/DataDictionary/types.ts +1 -0
  163. package/src/components/Detail/components/Table/components/TableBody/tableBody.tsx +14 -3
  164. package/src/components/Detail/components/Table/components/TableRows/components/CollapsableRows/collapsableRows.tsx +9 -2
  165. package/src/components/Detail/components/Table/components/TableRows/tableRows.tsx +9 -2
  166. package/src/components/Filter/components/FilterList/filterList.styles.ts +34 -15
  167. package/src/components/Layout/components/Header/header.styles.ts +6 -1
  168. package/src/components/Table/common/utils.ts +16 -0
  169. package/src/components/Table/components/TableFeatures/ColumnFilter/columnFilter.styles.ts +23 -0
  170. package/src/components/Table/components/TableFeatures/ColumnFilter/columnFilter.tsx +98 -0
  171. package/src/components/Table/components/TableFeatures/ColumnFilter/constants.ts +16 -0
  172. package/src/components/Table/components/TableFeatures/ColumnFilter/types.ts +10 -0
  173. package/src/components/Table/components/TableFeatures/ColumnFilter/utils.ts +27 -0
  174. package/src/components/Table/featureOptions/facetedColumn/utils.ts +14 -0
  175. package/src/components/common/ButtonGroup/constants.ts +13 -0
  176. package/src/mocks/@storybook/addon-actions.ts +10 -0
  177. package/src/styles/common/mui/buttonGroup.ts +46 -0
  178. package/src/styles/common/mui/typography.ts +2 -0
  179. package/src/tests/mui/constants.ts +1 -0
  180. package/src/tests/utils.ts +9 -0
  181. package/src/theme/common/components.ts +17 -32
  182. package/src/theme/components/index.ts +1 -0
  183. package/src/theme/components/muiButtonGroup.ts +79 -0
  184. package/src/theme/theme.ts +1 -1
  185. package/tests/dataDictionaryColumnFilters.test.tsx +101 -0
@@ -0,0 +1,33 @@
1
+ import { Checkbox, ListItemButton, ListItemText, Button as MButton, Typography, } from "@mui/material";
2
+ import React, { Fragment } from "react";
3
+ import { SVG_ICON_PROPS } from "../../../../../styles/common/mui/svgIcon";
4
+ import { TYPOGRAPHY_PROPS } from "../../../../../styles/common/mui/typography";
5
+ import { CheckedIcon } from "../../../../common/CustomIcon/components/CheckedIcon/checkedIcon";
6
+ import { UncheckedIcon } from "../../../../common/CustomIcon/components/UncheckedIcon/uncheckedIcon";
7
+ import { DropDownIcon } from "../../../../common/Form/components/Select/components/DropDownIcon/dropDownIcon";
8
+ import { useMenu } from "../../../../common/Menu/hooks/useMenu";
9
+ import { getColumnHeader } from "../../../common/utils";
10
+ import { getSortedFacetedValues } from "../../../featureOptions/facetedColumn/utils";
11
+ import { StyledMenu } from "./columnFilter.styles";
12
+ import { MENU_PROPS } from "./constants";
13
+ import { updater } from "./utils";
14
+ /**
15
+ * Column filter component with supported filter functions:
16
+ * - `arrIncludesSome`
17
+ */
18
+ export const ColumnFilter = ({ Button = MButton, className, column, ...props /* MuiMenuProps */ }) => {
19
+ const { anchorEl, onClose, onOpen, open } = useMenu();
20
+ const facetedUniqueValues = column.getFacetedUniqueValues();
21
+ const sortedValues = getSortedFacetedValues(facetedUniqueValues);
22
+ const filterValue = (column.getFilterValue() || []);
23
+ return (React.createElement(Fragment, null,
24
+ React.createElement(Button, { key: column.id, endIcon: React.createElement(DropDownIcon, { color: SVG_ICON_PROPS.COLOR.INK_LIGHT }), onClick: onOpen }, getColumnHeader(column)),
25
+ React.createElement(StyledMenu, { ...MENU_PROPS, ...props, className: className, anchorEl: anchorEl, onClose: onClose, open: open },
26
+ sortedValues.map(([value, occurrence]) => (React.createElement(ListItemButton, { key: String(value), selected: filterValue.includes(value), onClick: () => column.setFilterValue(updater(value)) },
27
+ React.createElement(Checkbox, { checked: filterValue.includes(value), checkedIcon: React.createElement(CheckedIcon, null), icon: React.createElement(UncheckedIcon, null) }),
28
+ React.createElement(ListItemText, { disableTypography: true, primary: React.createElement("span", null, String(value)), secondary: React.createElement(Typography, { color: TYPOGRAPHY_PROPS.COLOR.INK_LIGHT, variant: TYPOGRAPHY_PROPS.VARIANT.TEXT_BODY_SMALL_400 }, occurrence) })))),
29
+ React.createElement(ListItemButton, { disabled: !column.getIsFiltered(), onClick: () => column.setFilterValue(undefined) },
30
+ React.createElement(Typography, { color: column.getIsFiltered()
31
+ ? TYPOGRAPHY_PROPS.COLOR.PRIMARY
32
+ : TYPOGRAPHY_PROPS.COLOR.INHERIT, variant: TYPOGRAPHY_PROPS.VARIANT.TEXT_BODY_500 }, "Clear All")))));
33
+ };
@@ -0,0 +1,3 @@
1
+ export declare const StyledMenu: import("@emotion/styled").StyledComponent<import("@mui/material").MenuProps & {
2
+ theme?: import("@emotion/react").Theme;
3
+ }, {}, {}>;
@@ -0,0 +1,19 @@
1
+ import styled from "@emotion/styled";
2
+ import { Menu, menuClasses, paperClasses } from "@mui/material";
3
+ import { MAX_LIST_HEIGHT_PX } from "../../../../Filter/common/constants";
4
+ import { MuiListItemButtonRoot, MuiListItemTextRoot, } from "../../../../Filter/components/FilterList/filterList.styles";
5
+ export const StyledMenu = styled(Menu) `
6
+ .${paperClasses.root} {
7
+ margin: 4px 0;
8
+ width: 288px;
9
+
10
+ .${menuClasses.list} {
11
+ max-height: ${MAX_LIST_HEIGHT_PX}px;
12
+ overflow-wrap: break-word;
13
+
14
+ ${MuiListItemButtonRoot}
15
+
16
+ ${MuiListItemTextRoot}
17
+ }
18
+ }
19
+ `;
@@ -0,0 +1,2 @@
1
+ import { MenuProps } from "@mui/material";
2
+ export declare const MENU_PROPS: Omit<MenuProps, "anchorEl" | "onClose" | "open">;
@@ -0,0 +1,14 @@
1
+ export const MENU_PROPS = {
2
+ anchorOrigin: {
3
+ horizontal: "right",
4
+ vertical: "bottom",
5
+ },
6
+ marginThreshold: 8,
7
+ slotProps: {
8
+ paper: { variant: "menu" },
9
+ },
10
+ transformOrigin: {
11
+ horizontal: "right",
12
+ vertical: "top",
13
+ },
14
+ };
@@ -0,0 +1,7 @@
1
+ import { Button, MenuProps } from "@mui/material";
2
+ import { Column, RowData } from "@tanstack/react-table";
3
+ import { BaseComponentProps } from "../../../../types";
4
+ export interface ColumnFilterProps<T extends RowData> extends BaseComponentProps, Omit<MenuProps, "anchorEl" | "onClose" | "open"> {
5
+ Button?: typeof Button;
6
+ column: Column<T>;
7
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Returns an updater function for column filter.
3
+ * @param value - Value.
4
+ * @returns An updater function that returns the new filter value.
5
+ */
6
+ export declare function updater(value: unknown): (old: unknown[] | undefined) => unknown[] | undefined;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Returns an updater function for column filter.
3
+ * @param value - Value.
4
+ * @returns An updater function that returns the new filter value.
5
+ */
6
+ export function updater(value) {
7
+ return (old) => {
8
+ // If no old value, return new value.
9
+ if (!old)
10
+ return [value];
11
+ // If value already exists, remove it.
12
+ if (old.includes(value)) {
13
+ // Filter out the value.
14
+ const next = old.filter((v) => v !== value);
15
+ // If no values remain, return undefined.
16
+ if (next.length === 0)
17
+ return undefined;
18
+ return next;
19
+ }
20
+ // Otherwise, add the value.
21
+ return [...old, value];
22
+ };
23
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Sorts Map entries by key.
3
+ * @param facetedValues - Map of faceted values.
4
+ * @returns Sorted array of [key, value] entries.
5
+ */
6
+ export declare function getSortedFacetedValues(facetedValues: Map<unknown, number>): [unknown, number][];
@@ -0,0 +1,9 @@
1
+ import { COLLATOR_CASE_INSENSITIVE } from "../../../../common/constants";
2
+ /**
3
+ * Sorts Map entries by key.
4
+ * @param facetedValues - Map of faceted values.
5
+ * @returns Sorted array of [key, value] entries.
6
+ */
7
+ export function getSortedFacetedValues(facetedValues) {
8
+ return [...facetedValues].sort((a, b) => COLLATOR_CASE_INSENSITIVE.compare(String(a), String(b)));
9
+ }
@@ -0,0 +1,2 @@
1
+ import { ButtonGroupProps } from "@mui/material";
2
+ export declare const BUTTON_GROUP_PROPS: Record<string, Partial<ButtonGroupProps>>;
@@ -0,0 +1,11 @@
1
+ import { BUTTON_GROUP_PROPS as MUI_BUTTON_GROUP_PROPS } from "../../../styles/common/mui/buttonGroup";
2
+ export const BUTTON_GROUP_PROPS = {
3
+ PRIMARY_CONTAINED: {
4
+ color: MUI_BUTTON_GROUP_PROPS.COLOR.PRIMARY,
5
+ variant: MUI_BUTTON_GROUP_PROPS.VARIANT.CONTAINED,
6
+ },
7
+ SECONDARY_OUTLINED: {
8
+ color: MUI_BUTTON_GROUP_PROPS.COLOR.SECONDARY,
9
+ variant: MUI_BUTTON_GROUP_PROPS.VARIANT.OUTLINED,
10
+ },
11
+ };
@@ -9,7 +9,7 @@ export declare const TabScrollFuzz: import("@emotion/styled").StyledComponent<{
9
9
  } & Props, import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, {}>;
10
10
  export declare const Tab: import("@emotion/styled").StyledComponent<import("@mui/material").TabOwnProps & Omit<import("@mui/material").ButtonBaseOwnProps, "classes"> & import("@mui/material/OverridableComponent").CommonProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "ref"> & {
11
11
  ref?: ((instance: HTMLDivElement | null) => void | import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES[keyof import("react").DO_NOT_USE_OR_YOU_WILL_BE_FIRED_CALLBACK_REF_RETURN_VALUES]) | import("react").RefObject<HTMLDivElement> | null | undefined;
12
- }, "label" | "style" | "className" | "classes" | "tabIndex" | "children" | "sx" | "disabled" | "value" | "action" | "icon" | "centerRipple" | "disableRipple" | "disableTouchRipple" | "focusRipple" | "focusVisibleClassName" | "LinkComponent" | "onFocusVisible" | "TouchRippleProps" | "touchRippleRef" | "disableFocusRipple" | "wrapped" | "iconPosition"> & {
12
+ }, "label" | "style" | "className" | "classes" | "tabIndex" | "children" | "sx" | "disabled" | "value" | "action" | "centerRipple" | "disableRipple" | "disableTouchRipple" | "focusRipple" | "focusVisibleClassName" | "LinkComponent" | "onFocusVisible" | "TouchRippleProps" | "touchRippleRef" | "disableFocusRipple" | "icon" | "wrapped" | "iconPosition"> & {
13
13
  theme?: import("@emotion/react").Theme;
14
14
  }, {}, {}>;
15
15
  export {};
@@ -0,0 +1,9 @@
1
+ import { jest } from "@jest/globals";
2
+ /**
3
+ * Mock for Storybook's @storybook/addon-actions function.
4
+ * The mock keeps the same function signature as the real Storybook action,
5
+ * does not trigger any Storybook logic, and simply returns a Jest mock function
6
+ * for use in tests.
7
+ * @returns A Jest mock function.
8
+ */
9
+ export declare const action: () => jest.Mock;
@@ -0,0 +1,9 @@
1
+ import { jest } from "@jest/globals";
2
+ /**
3
+ * Mock for Storybook's @storybook/addon-actions function.
4
+ * The mock keeps the same function signature as the real Storybook action,
5
+ * does not trigger any Storybook logic, and simply returns a Jest mock function
6
+ * for use in tests.
7
+ * @returns A Jest mock function.
8
+ */
9
+ export const action = () => jest.fn();
@@ -0,0 +1,13 @@
1
+ import { ButtonGroupProps } from "@mui/material";
2
+ type ButtonGroupPropsOptions = {
3
+ CLASSES: typeof CLASSES;
4
+ COLOR: typeof COLOR;
5
+ SIZE: typeof SIZE;
6
+ VARIANT: typeof VARIANT;
7
+ };
8
+ declare const CLASSES: Record<string, ButtonGroupProps["classes"]>;
9
+ declare const COLOR: Record<string, ButtonGroupProps["color"]>;
10
+ declare const SIZE: Record<string, ButtonGroupProps["size"]>;
11
+ declare const VARIANT: Record<string, ButtonGroupProps["variant"]>;
12
+ export declare const BUTTON_GROUP_PROPS: ButtonGroupPropsOptions;
13
+ export {};
@@ -0,0 +1,34 @@
1
+ import { buttonGroupClasses } from "@mui/material";
2
+ const CLASSES = {
3
+ COLOR_PRIMARY: buttonGroupClasses.colorPrimary,
4
+ COLOR_SECONDARY: buttonGroupClasses.colorSecondary,
5
+ CONTAINED: buttonGroupClasses.contained,
6
+ GROUPED: buttonGroupClasses.grouped,
7
+ OUTLINED: buttonGroupClasses.outlined,
8
+ ROOT: buttonGroupClasses.root,
9
+ };
10
+ const COLOR = {
11
+ ERROR: "error",
12
+ INFO: "info",
13
+ INHERIT: "inherit",
14
+ PRIMARY: "primary",
15
+ SECONDARY: "secondary",
16
+ SUCCESS: "success",
17
+ WARNING: "warning",
18
+ };
19
+ const SIZE = {
20
+ LARGE: "large",
21
+ MEDIUM: "medium",
22
+ SMALL: "small",
23
+ };
24
+ const VARIANT = {
25
+ CONTAINED: "contained",
26
+ OUTLINED: "outlined",
27
+ TEXT: "text",
28
+ };
29
+ export const BUTTON_GROUP_PROPS = {
30
+ CLASSES,
31
+ COLOR,
32
+ SIZE,
33
+ VARIANT,
34
+ };
@@ -3,11 +3,13 @@ const COLOR = {
3
3
  INHERIT: "inherit",
4
4
  INK_LIGHT: "ink.light",
5
5
  INK_MAIN: "ink.main",
6
+ PRIMARY: "primary",
6
7
  };
7
8
  const VARIANT = {
8
9
  INHERIT: "inherit",
9
10
  TEXT_BODY_400: "text-body-400",
10
11
  TEXT_BODY_400_2_LINES: "text-body-400-2lines",
12
+ TEXT_BODY_500: "text-body-500",
11
13
  TEXT_BODY_SMALL_400: "text-body-small-400",
12
14
  TEXT_HEADING_LARGE: "text-heading-large",
13
15
  TEXT_HEADING_SMALL: "text-heading-small",
@@ -1,5 +1,6 @@
1
1
  export declare const MUI_CLASSES: {
2
2
  ACTIVE: string;
3
3
  COMPLETED: string;
4
+ DISABLED: string;
4
5
  SELECTED: string;
5
6
  };
@@ -1,5 +1,6 @@
1
1
  export const MUI_CLASSES = {
2
2
  ACTIVE: "Mui-active",
3
3
  COMPLETED: "Mui-completed",
4
+ DISABLED: "Mui-disabled",
4
5
  SELECTED: "Mui-selected",
5
6
  };
@@ -16,6 +16,12 @@ export declare function getLabelText<T extends HTMLElement = HTMLElement>(text:
16
16
  * @returns RegExp.
17
17
  */
18
18
  export declare function getStartsWithRegex(text: string): RegExp;
19
+ /**
20
+ * Retrieves an element by its role.
21
+ * @param role - The role of the element.
22
+ * @returns The element.
23
+ */
24
+ export declare function getRole<T extends HTMLElement = HTMLElement>(role: string): T;
19
25
  /**
20
26
  * Retrieves an element by its text content.
21
27
  * @param text - The text content of the element.
@@ -24,6 +24,14 @@ export function getLabelText(text) {
24
24
  export function getStartsWithRegex(text) {
25
25
  return new RegExp(`^${escapeRegExp(text)}`);
26
26
  }
27
+ /**
28
+ * Retrieves an element by its role.
29
+ * @param role - The role of the element.
30
+ * @returns The element.
31
+ */
32
+ export function getRole(role) {
33
+ return screen.getByRole(role);
34
+ }
27
35
  /**
28
36
  * Retrieves an element by its text content.
29
37
  * @param text - The text content of the element.
@@ -40,12 +40,6 @@ export declare const MuiButton: (theme: Theme) => Components["MuiButton"];
40
40
  * @returns MuiButtonBase component theme styles.
41
41
  */
42
42
  export declare const MuiButtonBase: (theme: Theme) => Components["MuiButtonBase"];
43
- /**
44
- * MuiButtonGroup Component
45
- * @param theme - Theme.
46
- * @returns MuiButtonGroup component theme styles.
47
- */
48
- export declare const MuiButtonGroup: (theme: Theme) => Components["MuiButtonGroup"];
49
43
  /**
50
44
  * MuiCard Component
51
45
  */
@@ -2,6 +2,7 @@ import { DropDownIcon } from "../../components/common/Form/components/Select/com
2
2
  import { COLOR_MIXES } from "../../styles/common/constants/colorMixes";
3
3
  import { PALETTE } from "../../styles/common/constants/palette";
4
4
  import { SHADOWS } from "../../styles/common/constants/shadows";
5
+ import { BUTTON_PROPS } from "../../styles/common/mui/button";
5
6
  import { CHIP_PROPS } from "../../styles/common/mui/chip";
6
7
  import { desktopUp, mobileUp, tabletUp } from "./breakpoints";
7
8
  import { TEXT_BODY_400, TEXT_BODY_400_2_LINES, TEXT_BODY_500, TEXT_BODY_SMALL_400, TEXT_BODY_SMALL_500, TEXT_HEADING, TEXT_HEADING_SMALL, } from "./typography";
@@ -183,6 +184,22 @@ export const MuiButton = (theme) => {
183
184
  },
184
185
  endIcon: {
185
186
  margin: 0,
187
+ variants: [
188
+ {
189
+ props: { size: BUTTON_PROPS.SIZE.MEDIUM },
190
+ style: {
191
+ marginLeft: -6,
192
+ marginRight: -6,
193
+ },
194
+ },
195
+ {
196
+ props: { size: BUTTON_PROPS.SIZE.SMALL },
197
+ style: {
198
+ marginLeft: -6,
199
+ marginRight: -6,
200
+ },
201
+ },
202
+ ],
186
203
  },
187
204
  outlinedSecondary: {
188
205
  backgroundColor: "transparent",
@@ -298,37 +315,6 @@ export const MuiButtonBase = (theme) => {
298
315
  },
299
316
  };
300
317
  };
301
- /**
302
- * MuiButtonGroup Component
303
- * @param theme - Theme.
304
- * @returns MuiButtonGroup component theme styles.
305
- */
306
- export const MuiButtonGroup = (theme) => {
307
- return {
308
- defaultProps: {
309
- disableElevation: true,
310
- disableRipple: true,
311
- },
312
- styleOverrides: {
313
- grouped: {
314
- minWidth: 0,
315
- padding: "6px 8px",
316
- },
317
- groupedContainedPrimary: {
318
- borderColor: theme.palette.primary.dark,
319
- boxShadow: `0 1px 0 0 ${theme.palette.primary.dark}`,
320
- // eslint-disable-next-line sort-keys -- disabling key order for readability
321
- "&:hover": {
322
- boxShadow: `0 1px 0 0 ${theme.palette.primary.dark}`,
323
- },
324
- // eslint-disable-next-line sort-keys -- disabling key order for readability
325
- "&:active": {
326
- boxShadow: "none",
327
- },
328
- },
329
- },
330
- };
331
- };
332
318
  /**
333
319
  * MuiCard Component
334
320
  */
@@ -1,3 +1,4 @@
1
1
  export { MuiAlert } from "./muiAlert";
2
2
  export { MuiAlertTitle } from "./muiAlertTitle";
3
+ export { MuiButtonGroup } from "./muiButtonGroup";
3
4
  export { MuiTableCell } from "./muiTableCell";
@@ -1,3 +1,4 @@
1
1
  export { MuiAlert } from "./muiAlert";
2
2
  export { MuiAlertTitle } from "./muiAlertTitle";
3
+ export { MuiButtonGroup } from "./muiButtonGroup";
3
4
  export { MuiTableCell } from "./muiTableCell";
@@ -0,0 +1,2 @@
1
+ import { Components } from "@mui/material";
2
+ export declare const MuiButtonGroup: Components["MuiButtonGroup"];
@@ -0,0 +1,76 @@
1
+ import { COLOR_MIXES } from "../../styles/common/constants/colorMixes";
2
+ import { PALETTE } from "../../styles/common/constants/palette";
3
+ import { BUTTON_GROUP_PROPS } from "../../styles/common/mui/buttonGroup";
4
+ const SELECTORS = {
5
+ GROUPED: `.${BUTTON_GROUP_PROPS.CLASSES.GROUPED}`,
6
+ };
7
+ export const MuiButtonGroup = {
8
+ defaultProps: {
9
+ disableElevation: true,
10
+ disableRipple: true,
11
+ },
12
+ styleOverrides: {
13
+ root: {
14
+ variants: [
15
+ /* PRIMARY CONTAINED */
16
+ {
17
+ props: {
18
+ color: BUTTON_GROUP_PROPS.COLOR.PRIMARY,
19
+ variant: BUTTON_GROUP_PROPS.VARIANT.CONTAINED,
20
+ },
21
+ style: {
22
+ [SELECTORS.GROUPED]: {
23
+ borderColor: PALETTE.PRIMARY_DARK,
24
+ boxShadow: `0 1px 0 0 ${PALETTE.PRIMARY_DARK}`,
25
+ minWidth: 0,
26
+ // eslint-disable-next-line sort-keys -- disabling key order for readability
27
+ "&:hover": {
28
+ boxShadow: `0 1px 0 0 ${PALETTE.PRIMARY_DARK}`,
29
+ },
30
+ // eslint-disable-next-line sort-keys -- disabling key order for readability
31
+ "&:active": {
32
+ boxShadow: "none",
33
+ },
34
+ },
35
+ },
36
+ },
37
+ /* SECONDARY OUTLINED */
38
+ {
39
+ props: {
40
+ color: BUTTON_GROUP_PROPS.COLOR.SECONDARY,
41
+ variant: BUTTON_GROUP_PROPS.VARIANT.OUTLINED,
42
+ },
43
+ style: {
44
+ [SELECTORS.GROUPED]: {
45
+ backgroundColor: PALETTE.COMMON_WHITE,
46
+ boxShadow: `inset 0 0 0 1px ${PALETTE.SMOKE_DARK}, 0 1px 0 0 ${COLOR_MIXES.COMMON_BLACK_08}`,
47
+ color: PALETTE.INK_MAIN,
48
+ minWidth: 0,
49
+ // eslint-disable-next-line sort-keys -- disabling key order for readability
50
+ "&:hover": {
51
+ backgroundColor: PALETTE.SMOKE_LIGHTEST,
52
+ boxShadow: `inset 0 0 0 1px ${PALETTE.SMOKE_DARK}, 0 1px 0 0 ${COLOR_MIXES.COMMON_BLACK_08}`,
53
+ },
54
+ // eslint-disable-next-line sort-keys -- disabling key order for readability
55
+ "&:active": {
56
+ backgroundColor: PALETTE.SMOKE_LIGHTEST,
57
+ boxShadow: `inset 0 0 0 1px ${PALETTE.SMOKE_DARK}`,
58
+ },
59
+ },
60
+ },
61
+ },
62
+ /* SMALL */
63
+ {
64
+ props: {
65
+ size: BUTTON_GROUP_PROPS.SIZE.SMALL,
66
+ },
67
+ style: {
68
+ [SELECTORS.GROUPED]: {
69
+ padding: "6px 8px",
70
+ },
71
+ },
72
+ },
73
+ ],
74
+ },
75
+ },
76
+ };
@@ -69,7 +69,7 @@ export function createAppTheme(customOptions = {}) {
69
69
  MuiBreadcrumbs: C.MuiBreadcrumbs(theme),
70
70
  MuiButton: C.MuiButton(theme),
71
71
  MuiButtonBase: C.MuiButtonBase(theme),
72
- MuiButtonGroup: C.MuiButtonGroup(theme),
72
+ MuiButtonGroup: M.MuiButtonGroup,
73
73
  MuiCard: C.MuiCard,
74
74
  MuiCheckbox: C.MuiCheckbox(theme),
75
75
  MuiChip: C.MuiChip(theme),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@databiosphere/findable-ui",
3
- "version": "32.1.1",
3
+ "version": "34.0.0",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
@@ -13,10 +13,13 @@ export function findCategoryConfig<V extends VIEW_KIND>(
13
13
  viewKind: V,
14
14
  key: Category["key"],
15
15
  configs: CategoryConfig[]
16
- ): Extract<CategoryConfig, { viewKind: V }> | undefined {
16
+ ): Extract<CategoryConfig, { viewKind?: V }> | undefined {
17
17
  return configs.find(
18
- (c): c is Extract<CategoryConfig, { viewKind: V }> =>
19
- c.viewKind === viewKind && c.key === key
18
+ (c): c is Extract<CategoryConfig, { viewKind?: V }> =>
19
+ // When `viewKind` is undefined, it corresponds to a `SelectCategoryConfig`.
20
+ // This predicate ensures that `viewKind` is either explicitly matched or treated as undefined
21
+ // for compatibility with `SelectCategoryConfig` and other explicitly defined view kinds.
22
+ (c.viewKind === undefined || c.viewKind === viewKind) && c.key === key
20
23
  );
21
24
  }
22
25
 
@@ -1,12 +1,12 @@
1
- import { ColumnDef, RowData } from "@tanstack/react-table";
1
+ import { ColumnDef, RowData, TableOptions } from "@tanstack/react-table";
2
2
 
3
3
  /**
4
4
  * Model of a value of a metadata class.
5
5
  */
6
6
  export interface Attribute {
7
- annotations?: {
8
- [key in keyof DataDictionaryPrefix]: string; // Prefix to fragment mapping, e.g. cxg: "batch_condition".
9
- };
7
+ // Prefix to fragment mapping, e.g. cxg: "batch_condition", or, general tags e.g. tier: "Tier 1" and bionetwork: ["gut"]
8
+ annotations?: Record<string, string | string[] | undefined>; // 'undefined' allows for mix of keys across attributes e.g. tier, or tier and cxg, or cxg
9
+ classKey?: string; // Programmatic class name or key (e.g. cell, sample) the attribute belongs to.
10
10
  description: string;
11
11
  example?: string; // Free text example of attribute
12
12
  multivalued: boolean; // True if attribute can have multiple values
@@ -74,6 +74,7 @@ export interface DataDictionary<T extends RowData = Attribute> {
74
74
  export interface DataDictionaryConfig<T extends RowData = Attribute> {
75
75
  columnDefs: ColumnDef<T, T[keyof T]>[];
76
76
  dataDictionary: DataDictionary<T>;
77
+ tableOptions?: Omit<TableOptions<T>, "columns" | "data" | "getCoreRowModel">;
77
78
  }
78
79
 
79
80
  /**
@@ -7,19 +7,15 @@ import { GRID_PROPS } from "./constants";
7
7
  import { ClassesProps } from "./types";
8
8
 
9
9
  export const Entities = <T extends RowData = Attribute>({
10
- classes,
11
- columnDefs,
12
10
  spacing,
11
+ table,
13
12
  }: ClassesProps<T>): JSX.Element => {
13
+ const { getGroupedRowModel } = table;
14
14
  return (
15
15
  <Grid {...GRID_PROPS}>
16
- {classes.map((cls) => (
17
- <Entity
18
- key={cls.name}
19
- class={cls}
20
- columnDefs={columnDefs}
21
- spacing={spacing}
22
- />
16
+ {/* Render grouped rows where each "group" is a class e.g. "donor" */}
17
+ {getGroupedRowModel().rows.map((row) => (
18
+ <Entity key={row.id} row={row} spacing={spacing} table={table} />
23
19
  ))}
24
20
  </Grid>
25
21
  );
@@ -1,9 +1,8 @@
1
- import { ColumnDef, RowData } from "@tanstack/react-table";
2
- import { Attribute, Class } from "../../../../common/entities";
1
+ import { RowData, Table } from "@tanstack/react-table";
2
+ import { Attribute } from "../../../../common/entities";
3
3
  import { LayoutSpacing } from "../../hooks/UseLayoutSpacing/types";
4
4
 
5
5
  export interface ClassesProps<T extends RowData = Attribute> {
6
- classes: Class<T>[];
7
- columnDefs: ColumnDef<T, T[keyof T]>[];
8
6
  spacing?: LayoutSpacing;
7
+ table: Table<T>;
9
8
  }
@@ -2,9 +2,17 @@ import styled from "@emotion/styled";
2
2
  import { Typography } from "@mui/material";
3
3
  import { LayoutSpacing } from "../../hooks/UseLayoutSpacing/types";
4
4
  import { ENTITIES_ROW_GAP } from "../Entities/constants";
5
+ import { LAYOUT_SPACING } from "../Layout/constants";
6
+
7
+ const TOP =
8
+ ENTITIES_ROW_GAP +
9
+ LAYOUT_SPACING.TITLE_HEIGHT +
10
+ LAYOUT_SPACING.FILTERS_HEIGHT +
11
+ LAYOUT_SPACING.FILTERS_PADDING_TOP +
12
+ LAYOUT_SPACING.CONTENT_PADDING_TOP;
5
13
 
6
14
  export const StyledTypography = styled(Typography)<Partial<LayoutSpacing>>`
7
- scroll-margin-top: ${({ top = 0 }) => top + ENTITIES_ROW_GAP}px;
15
+ scroll-margin-top: ${({ top = 0 }) => top + TOP}px;
8
16
 
9
17
  &:hover a {
10
18
  opacity: 1;