@luscii-healthtech/web-ui 35.13.1 → 35.14.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.
@@ -1,5 +1,5 @@
1
1
  import { ReactElement } from "react";
2
- import { CategorizedFilters, FilterBarLocalization, TransformedPresetFilterOptions, TransformedSortingOptions } from "./FilterBarProps.type";
2
+ import { CategorizedFilters, FilterBarLocalization, HasSingleSelection, TransformedPresetFilterOptions, TransformedSortingOptions } from "./FilterBarProps.type";
3
3
  type FilterBarProps<SortableEntity extends object> = {
4
4
  /**
5
5
  * A list of grouped filters to be displayed in the FilterBar.
@@ -93,6 +93,6 @@ type FilterBarProps<SortableEntity extends object> = {
93
93
  * See {@link FilterBarLocalization}.
94
94
  */
95
95
  localization: FilterBarLocalization;
96
- };
96
+ } & HasSingleSelection;
97
97
  export declare const FilterBar: <SortableEntity extends object>({ localization, categorizedFilters, sortingOptions, presetFilterOptions, ...props }: FilterBarProps<SortableEntity>) => ReactElement | null;
98
98
  export {};
@@ -1,3 +1,15 @@
1
+ export type HasSingleSelection = {
2
+ /**
3
+ * When `true`, will still allow multiple filters to be added
4
+ * but each filter can only have a single value selected.
5
+ *
6
+ * The checkboxes in the filter list are hidden and you only see a checkmark ✓ on the selected item.
7
+ *
8
+ * `[⚠️ WARNING]` - this doesn't work with the `presetFilterOptions` prop, so do not combine them.
9
+ *
10
+ */
11
+ singleSelection?: boolean;
12
+ };
1
13
  /**
2
14
  * The object used to create a filter dropdown in the component.
3
15
  * This is used based on the dataset passed to FilterBar, so we always calculate the filters
@@ -1,8 +1,11 @@
1
1
  import React from "react";
2
- import { CategorizedFilters, OnFilterBarFilterChange } from "./FilterBarProps.type";
2
+ import { CategorizedFilters, HasSingleSelection, OnFilterBarFilterChange } from "./FilterBarProps.type";
3
3
  type FiltersMenusProps = {
4
4
  filters: CategorizedFilters;
5
5
  onFilterOptionChange: OnFilterBarFilterChange;
6
- };
6
+ } & HasSingleSelection;
7
+ /**
8
+ * Each of the menu lists on the right side of the the `FilterBar` component.
9
+ */
7
10
  export declare const FiltersMenus: React.FC<FiltersMenusProps>;
8
11
  export {};
@@ -29,6 +29,12 @@ export interface SelectProps<Option extends OptionMinimal = OptionMinimal, IsMul
29
29
  * This change is protected by policy: https://app.glassfrog.com/organizations/13950/orgnav/policies/12870328
30
30
  */
31
31
  value?: any;
32
+ /**
33
+ * The internal processing in this component is causing issues, but we cannot
34
+ * just remove it. This prop allows us to use the component in a fully controlled
35
+ * way, without any processing of the value.
36
+ */
37
+ skipValueProcessing?: boolean;
32
38
  }
33
39
  /**
34
40
  * A wrapper around react-select to style it according to our design specification.
@@ -4289,12 +4289,25 @@ const SelectLoadingIndicator = (props) => React__namespace.default.createElement
4289
4289
  function generateCustomStyles(hasError) {
4290
4290
  return {
4291
4291
  option: (baseStyles, state) => {
4292
- return Object.assign(Object.assign({}, baseStyles), { fontWeight: state.isSelected ? "bold" : "normal", fontSize: "14px", backgroundColor: "none", color: "inherit", position: "relative", padding: "0.75rem", opacity: state.isDisabled ? "0.5" : 1, "&:after": {
4293
- visibility: state.isSelected ? "visible" : "hidden"
4294
- }, transition: "background-color 0.3s ease-in-out", "&:hover": {
4292
+ return Object.assign(Object.assign({}, baseStyles), {
4293
+ fontWeight: state.isSelected ? "bold" : "normal",
4294
+ fontSize: "14px",
4295
4295
  // tailwind blue-50
4296
- backgroundColor: state.isSelected ? "transparent" : "#F2FAFD"
4297
- }, pointerEvents: state.isDisabled ? "none" : "auto" });
4296
+ backgroundColor: state.isFocused ? "#F2FAFD" : "none",
4297
+ color: "inherit",
4298
+ position: "relative",
4299
+ padding: "0.75rem",
4300
+ opacity: state.isDisabled ? "0.5" : 1,
4301
+ "&:after": {
4302
+ visibility: state.isSelected ? "visible" : "hidden"
4303
+ },
4304
+ transition: "background-color 0.3s ease-in-out",
4305
+ "&:hover": {
4306
+ // tailwind blue-50
4307
+ backgroundColor: state.isSelected ? "transparent" : "#F2FAFD"
4308
+ },
4309
+ pointerEvents: state.isDisabled ? "none" : "auto"
4310
+ });
4298
4311
  },
4299
4312
  container: (baseStyles) => {
4300
4313
  return Object.assign(Object.assign({}, baseStyles), { flexGrow: "initial" });
@@ -4355,7 +4368,7 @@ function generateCustomStyles(hasError) {
4355
4368
  };
4356
4369
  }
4357
4370
  const Select = React__namespace.default.forwardRef((_a, innerRef) => {
4358
- var { isError = false, styles, options, onChange, value, width = "full", isMulti, className } = _a, otherProps = __rest(_a, ["isError", "styles", "options", "onChange", "value", "width", "isMulti", "className"]);
4371
+ var { isError = false, styles, options, onChange, value, width = "full", isMulti, className, skipValueProcessing } = _a, otherProps = __rest(_a, ["isError", "styles", "options", "onChange", "value", "width", "isMulti", "className", "skipValueProcessing"]);
4359
4372
  const customStyles = generateCustomStyles(isError);
4360
4373
  const mergedStyles = ReactSelect.mergeStyles(customStyles, styles);
4361
4374
  const isOptionsGrouped = !options ? false : options.reduce((acc, o) => acc || "options" in o && !("values" in o), false);
@@ -4375,7 +4388,7 @@ const Select = React__namespace.default.forwardRef((_a, innerRef) => {
4375
4388
  var { children } = _a2, commonProps = __rest(_a2, ["children"]);
4376
4389
  return React__namespace.default.createElement(ReactSelect.components.SelectContainer, Object.assign({}, commonProps, { innerProps: Object.assign({}, commonProps.innerProps, Object.assign({}, getDataAttributes())) }), children);
4377
4390
  };
4378
- return React__namespace.default.createElement(ReactSelect__default.default, Object.assign({}, otherProps, { ref: innerRef, styles: mergedStyles, options, onChange: onChangeWrapped, value: valueWrapped, isMulti, className: classNames__default.default("customized-select", className, {
4391
+ return React__namespace.default.createElement(ReactSelect__default.default, Object.assign({}, otherProps, { ref: innerRef, styles: mergedStyles, options, onChange: skipValueProcessing ? onChange : onChangeWrapped, value: skipValueProcessing ? value : valueWrapped, isMulti, className: classNames__default.default("customized-select", className, {
4379
4392
  "ui-w-16": width === "sm",
4380
4393
  "ui-w-32": width === "md",
4381
4394
  "ui-w-56": width === "lg",
@@ -6421,7 +6434,7 @@ const ActiveFilters = (props) => {
6421
6434
  null,
6422
6435
  React__namespace.default.createElement(
6423
6436
  "span",
6424
- { key: activeFilter.id, className: "ui-mx-1 ui-inline-flex ui-items-center ui-rounded-full ui-border ui-border-neutral-interactive ui-bg-white ui-py-xxxxs ui-pl-m ui-pr-xxs hover:ui-border-neutral-interactive--hover hover:ui-bg-primary-background" },
6437
+ { key: `${activeFilter.id}-${activeFilter.label}`, className: "ui-mx-1 ui-inline-flex ui-items-center ui-rounded-full ui-border ui-border-neutral-interactive ui-bg-white ui-py-xxxxs ui-pl-m ui-pr-xxs hover:ui-border-neutral-interactive--hover hover:ui-bg-primary-background" },
6425
6438
  React__namespace.default.createElement(Text, { variant: "base" }, activeFilter.label),
6426
6439
  React__namespace.default.createElement(
6427
6440
  "button",
@@ -6463,17 +6476,42 @@ const SortMenu = (props) => {
6463
6476
  React__namespace.default.createElement(
6464
6477
  react.Transition,
6465
6478
  { as: React.Fragment, enter: "ui-transition ui-ease-out ui-duration-100", enterFrom: "ui-transform ui-opacity-0 ui-scale-95", enterTo: "ui-transform ui-opacity-100 ui-scale-100", leave: "ui-transition ui-ease-in ui-duration-75", leaveFrom: "ui-transform ui-opacity-100 ui-scale-100", leaveTo: "ui-transform ui-opacity-0 ui-scale-95" },
6466
- React__namespace.default.createElement(
6467
- react.Menu.Items,
6468
- { className: "ui-absolute ui-left-0 ui-z-10 ui-mt-2 ui-w-40 ui-origin-top-left ui-rounded-md ui-bg-white ui-shadow-2xl ui-ring-1 ui-ring-black ui-ring-opacity-5 focus:ui-outline-none" },
6469
- React__namespace.default.createElement("div", { className: "ui-py-1" }, sortingOptions.map((option) => React__namespace.default.createElement(react.Menu.Item, { key: option.id }, ({ active }) => React__namespace.default.createElement("span", { onClick: () => onSortOptionChange(Object.assign(Object.assign({}, option), { isChecked: !option.isChecked })), role: "button", className: classNames__default.default(option.isChecked ? "ui-font-medium ui-text-slate-900" : "ui-text-slate-500", "ui-block ui-px-4 ui-py-2 ui-text-sm", "ui-cursor-pointer", { "ui-bg-slate-100": active }) }, option.label))))
6470
- )
6479
+ React__namespace.default.createElement(react.Menu.Items, { className: classNames__default.default("ui-z-10", "ui-absolute ui-left-0 ui-origin-top-left", "ui-min-w-58 ui-rounded-2xl ui-bg-white ui-shadow-2xl", "ui-border ui-border-neutral-border-high-contrast", "ui-ring-1 ui-ring-black ui-ring-opacity-5 focus:ui-outline-none") }, sortingOptions.map((option) => React__namespace.default.createElement(react.Menu.Item, { key: option.id }, () => {
6480
+ return React__namespace.default.createElement(
6481
+ "div",
6482
+ { className: classNames__default.default(
6483
+ // Making sure the hover color doesn't bleed
6484
+ // out of the menu cointainer
6485
+ "first-of-type:ui-rounded-t-2xl",
6486
+ "last-of-type:ui-rounded-b-2xl",
6487
+ "ui-flex ui-items-center ui-p-s",
6488
+ "ui-cursor-pointer",
6489
+ "ui-transition-colors ui-duration-300 ui-ease-in-out hover:ui-bg-blue-50"
6490
+ ), onClick: () => {
6491
+ onSortOptionChange(Object.assign(Object.assign({}, option), { isChecked: !option.isChecked }));
6492
+ }, role: "button" },
6493
+ React__namespace.default.createElement(
6494
+ "span",
6495
+ { className: classNames__default.default("ui-block ui-text-nowrap ui-text-sm") },
6496
+ React__namespace.default.createElement(Text, { variant: option.isChecked ? "strong" : "base" }, option.label)
6497
+ ),
6498
+ React__namespace.default.createElement(
6499
+ "span",
6500
+ { className: classNames__default.default("ui-ml-auto", {
6501
+ "ui-text-primary": option.isChecked,
6502
+ "ui-text-transparent": !option.isChecked
6503
+ }) },
6504
+ React__namespace.default.createElement(solid.CheckIcon, { className: "ui-ml-s ui-h-5 ui-w-5 ui-flex-shrink-0" })
6505
+ )
6506
+ );
6507
+ })))
6471
6508
  )
6472
6509
  );
6473
6510
  };
6474
6511
 
6475
6512
  const FiltersMenus = (props) => {
6476
- const { filters } = props;
6513
+ const { filters, singleSelection } = props;
6514
+ const multiSelection = !singleSelection;
6477
6515
  return React__namespace.default.createElement(
6478
6516
  "div",
6479
6517
  { className: "ui-hidden sm:ui-block" },
@@ -6497,16 +6535,34 @@ const FiltersMenus = (props) => {
6497
6535
  { as: React.Fragment, enter: "ui-transition ui-ease-out ui-duration-100", enterFrom: "ui-transform ui-opacity-0 ui-scale-95", enterTo: "ui-transform ui-opacity-100 ui-scale-100", leave: "ui-transition ui-ease-in ui-duration-75", leaveFrom: "ui-transform ui-opacity-100 ui-scale-100", leaveTo: "ui-transform ui-opacity-0 ui-scale-95" },
6498
6536
  React__namespace.default.createElement(
6499
6537
  react.Popover.Panel,
6500
- { className: "ui-absolute ui-right-0 ui-z-10 ui-mt-2 ui-origin-top-right ui-rounded-md ui-bg-white ui-p-4 ui-shadow-2xl ui-ring-1 ui-ring-black ui-ring-opacity-5 focus:ui-outline-none" },
6501
- React__namespace.default.createElement("form", { className: "ui-max-h-120 ui-space-y-4 ui-overflow-y-auto ui-p-1" }, categorizedFilter.options.map((option) => React__namespace.default.createElement(
6538
+ { className: classNames__default.default("ui-min-w-58", "ui-absolute ui-right-0 ui-z-10 ui-mt-2 ui-origin-top-right", "ui-rounded-2xl ui-bg-white ui-shadow-2xl ui-ring-1 ui-ring-black ui-ring-opacity-5", "focus:ui-outline-none", "ui-border ui-border-neutral-border-high-contrast") },
6539
+ React__namespace.default.createElement("form", { className: "ui-max-h-120 ui-overflow-y-auto" }, categorizedFilter.options.map((option) => React__namespace.default.createElement(
6502
6540
  "label",
6503
- { key: `${option.id}`, className: "ui-flex ui-items-center", htmlFor: `filter-${option.id}` },
6504
- React__namespace.default.createElement("input", { id: `filter-${option.id}`, name: `${option.value}`, defaultValue: option.value, type: "checkbox", defaultChecked: option.isChecked, onChange: () => {
6541
+ { key: `${option.id}`, className: classNames__default.default("first-of-type:ui-rounded-t-2xl", "last-of-type:ui-rounded-b-2xl", "ui-flex ui-items-center ui-p-3", "ui-transition-colors ui-duration-300 ui-ease-in-out hover:ui-bg-blue-50"), htmlFor: `filter-${option.id}` },
6542
+ React__namespace.default.createElement("input", { id: `filter-${option.id}`, name: `${option.value}`, defaultValue: option.value, type: "checkbox", checked: option.isChecked, onChange: () => {
6505
6543
  props.onFilterOptionChange({
6506
6544
  changedFilterOption: Object.assign(Object.assign({}, option), { isChecked: !option.isChecked })
6507
6545
  });
6508
- }, className: "ui-form-checkbox ui-h-4 ui-w-4 ui-rounded ui-border-slate-300 ui-text-primary focus:ui-ring-primary" }),
6509
- React__namespace.default.createElement("span", { className: "ui-ml-3 ui-whitespace-nowrap ui-pr-6 ui-text-sm ui-font-medium ui-capitalize ui-text-slate-900" }, option.label)
6546
+ }, className: classNames__default.default("ui-form-checkbox ui-h-4 ui-w-4 ui-rounded ui-border-slate-300 ui-text-primary focus:ui-ring-primary", {
6547
+ "ui-hidden": singleSelection
6548
+ }) }),
6549
+ React__namespace.default.createElement(
6550
+ "span",
6551
+ { className: classNames__default.default({
6552
+ "ui-pr-l": multiSelection,
6553
+ "ui-ml-s": multiSelection
6554
+ }) },
6555
+ React__namespace.default.createElement(Text, { className: "ui-whitespace-nowrap ui-capitalize", variant: option.isChecked ? "strong" : "base" }, option.label)
6556
+ ),
6557
+ React__namespace.default.createElement(
6558
+ "span",
6559
+ { className: classNames__default.default("ui-ml-auto ui-pr-s", {
6560
+ "ui-hidden": multiSelection,
6561
+ "ui-text-primary": option.isChecked,
6562
+ "ui-text-transparent": !option.isChecked
6563
+ }) },
6564
+ React__namespace.default.createElement(solid.CheckIcon, { className: "ui-ml-s ui-h-5 ui-w-5 ui-flex-shrink-0" })
6565
+ )
6510
6566
  )))
6511
6567
  )
6512
6568
  )
@@ -6575,7 +6631,7 @@ const FilterBar = (_a) => {
6575
6631
  if (categorizedFilterOption.id === changedFilterOption.id) {
6576
6632
  return changedFilterOption;
6577
6633
  }
6578
- return categorizedFilterOption;
6634
+ return Object.assign(Object.assign({}, categorizedFilterOption), { isChecked: props.singleSelection ? false : categorizedFilterOption.isChecked });
6579
6635
  }) });
6580
6636
  });
6581
6637
  props.onFilterChange(updatedFilters);
@@ -6603,7 +6659,7 @@ const FilterBar = (_a) => {
6603
6659
  ),
6604
6660
  React__namespace.default.createElement(SortMenu, { localization, sortingOptions, onSortOptionChange })
6605
6661
  ),
6606
- React__namespace.default.createElement(FiltersMenus, { filters: categorizedFilters, onFilterOptionChange })
6662
+ React__namespace.default.createElement(FiltersMenus, { singleSelection: props.singleSelection, filters: categorizedFilters, onFilterOptionChange })
6607
6663
  )
6608
6664
  ),
6609
6665
  React__namespace.default.createElement(Divider, { version: "v2", color: "border" }),