@luscii-healthtech/web-ui 7.5.0 → 7.6.1
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/dist/components/FilterBar/ActiveFilters.d.ts +2 -2
- package/dist/components/FilterBar/FilterBar.d.ts +96 -0
- package/dist/components/FilterBar/FilterBar.utils.d.ts +4 -4
- package/dist/components/FilterBar/FilterBarProps.type.d.ts +9 -17
- package/dist/components/FilterBar/FiltersMenus.d.ts +2 -2
- package/dist/components/FilterBar/SortMenu.d.ts +5 -5
- package/dist/components/FilterBar/index.d.ts +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.development.js +235 -0
- package/dist/index.development.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/web-ui-tailwind.css +116 -25
- package/dist/web-ui.esm.js +1 -1
- package/dist/web-ui.esm.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { CategorizedFilters, FilterBarLocalization, OnFilterBarFilterChange } from "./FilterBarProps.type";
|
|
3
3
|
type ActiveFiltersProps = {
|
|
4
|
-
filters:
|
|
4
|
+
filters: CategorizedFilters;
|
|
5
5
|
onRemoveActiveFilter: OnFilterBarFilterChange;
|
|
6
6
|
localization: Pick<FilterBarLocalization, "filtersLabel">;
|
|
7
7
|
};
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { ReactElement } from "react";
|
|
2
|
+
import { CategorizedFilters, FilterBarLocalization, TransformedSortingOptions } from "./FilterBarProps.type";
|
|
3
|
+
type FilterBarProps<SortableEntity extends object> = {
|
|
4
|
+
/**
|
|
5
|
+
* A list of grouped filters to be displayed in the FilterBar.
|
|
6
|
+
*
|
|
7
|
+
* This is an array with items shaped as:
|
|
8
|
+
* ```ts
|
|
9
|
+
* type CategorizedFilter = {
|
|
10
|
+
* key: string;
|
|
11
|
+
* label: string;
|
|
12
|
+
* options: TransformedFilterOptions;
|
|
13
|
+
* }
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* You can choose to manually create this option or use the `getFilterGroups` helper function that will do the same
|
|
17
|
+
* for you based on your data.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
*
|
|
21
|
+
* If you decided to use the `getFilterGroups` function:
|
|
22
|
+
*
|
|
23
|
+
*
|
|
24
|
+
* ```ts
|
|
25
|
+
* const items = []; // any list of object you are working with
|
|
26
|
+
*
|
|
27
|
+
* // the list of filter generators, the `filterValuePredicate` will be the displayed
|
|
28
|
+
* // value in the filter dropdown, so you can map and transform it to any custom string if necessary, or use
|
|
29
|
+
* // the value from the object entry
|
|
30
|
+
*
|
|
31
|
+
* const filterGenerators: FilterGenerator<TShirtFromApi>[] = [
|
|
32
|
+
* {
|
|
33
|
+
* id: "brand",
|
|
34
|
+
* label: "Brand",
|
|
35
|
+
* filterValuePredicate: (tshirt) => tshirt.brand,
|
|
36
|
+
* },
|
|
37
|
+
* {
|
|
38
|
+
* id: "size",
|
|
39
|
+
* label: "Size",
|
|
40
|
+
* filterValuePredicate: (tshirt) => tshirt.size,
|
|
41
|
+
* },
|
|
42
|
+
* {
|
|
43
|
+
* id: "color",
|
|
44
|
+
* label: "Color",
|
|
45
|
+
* filterValuePredicate: (tshirt) => tshirt.color,
|
|
46
|
+
* },
|
|
47
|
+
* ];
|
|
48
|
+
*
|
|
49
|
+
* const categorizedFilters = getFilterGroups(items, filterGenerators);
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
*
|
|
53
|
+
* A compliant entry in the `categorizedFilters` has a shape like the object below:
|
|
54
|
+
*
|
|
55
|
+
*
|
|
56
|
+
* ```json
|
|
57
|
+
* {
|
|
58
|
+
* "key": "color",
|
|
59
|
+
* "label": "Color",
|
|
60
|
+
* "options": [
|
|
61
|
+
* {
|
|
62
|
+
* "isChecked": false,
|
|
63
|
+
* "id": "yellow",
|
|
64
|
+
* "label": "yellow",
|
|
65
|
+
* "value": "yellow"
|
|
66
|
+
* },
|
|
67
|
+
* {
|
|
68
|
+
* "isChecked": false,
|
|
69
|
+
* "id": "red",
|
|
70
|
+
* "label": "red",
|
|
71
|
+
* "value": "red"
|
|
72
|
+
* },
|
|
73
|
+
* {
|
|
74
|
+
* "isChecked": false,
|
|
75
|
+
* "id": "green",
|
|
76
|
+
* "label": "green",
|
|
77
|
+
* "value": "green"
|
|
78
|
+
* }
|
|
79
|
+
* ]
|
|
80
|
+
* }
|
|
81
|
+
*```
|
|
82
|
+
*/
|
|
83
|
+
categorizedFilters: CategorizedFilters;
|
|
84
|
+
/**
|
|
85
|
+
* For more details, see {@link TransformedSortingOptions}.
|
|
86
|
+
*/
|
|
87
|
+
sortingOptions: TransformedSortingOptions<SortableEntity>;
|
|
88
|
+
onFilterChange: (updatedFilters: CategorizedFilters) => void;
|
|
89
|
+
onSortingChange: (updatedSortingOptions: TransformedSortingOptions<SortableEntity>) => void;
|
|
90
|
+
/**
|
|
91
|
+
* See {@link FilterBarLocalization}.
|
|
92
|
+
*/
|
|
93
|
+
localization: FilterBarLocalization;
|
|
94
|
+
};
|
|
95
|
+
export declare const FilterBar: <SortableEntity extends object>({ localization, categorizedFilters, sortingOptions, ...props }: FilterBarProps<SortableEntity>) => ReactElement | null;
|
|
96
|
+
export {};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CategorizedFilters, FilterGenerator, TransformedSortingOptions } from "./FilterBarProps.type";
|
|
2
2
|
/**
|
|
3
3
|
* Generates the list of filters based on the data (see this as what you'd like to be filtered in your component).
|
|
4
4
|
*
|
|
@@ -6,7 +6,7 @@ import { CategorisedFilters, FilterGenerator, TransformedSortingOption } from ".
|
|
|
6
6
|
* @param groupers a list of functions used to create the filters dropdown
|
|
7
7
|
* @returns {CategorisedFilters} a list of filters properly grouped.
|
|
8
8
|
*/
|
|
9
|
-
export declare function getFilterGroups<T extends unknown[]>(dataToGenerateFiltersFrom: T, groupers: FilterGenerator<T[number]>[]):
|
|
9
|
+
export declare function getFilterGroups<T extends unknown[]>(dataToGenerateFiltersFrom: T, groupers: FilterGenerator<T[number]>[]): CategorizedFilters;
|
|
10
10
|
/**
|
|
11
11
|
*
|
|
12
12
|
* @param filterKey the key of the categorized filter (eg. color, size, brand) - which one of them are you gonna check.
|
|
@@ -20,7 +20,7 @@ export declare function getFilterGroups<T extends unknown[]>(dataToGenerateFilte
|
|
|
20
20
|
* const filteredBySize = items.filter(sizeFilterPredicate);
|
|
21
21
|
*
|
|
22
22
|
*/
|
|
23
|
-
export declare const createFilterPredicate: <T extends object>(filterKey:
|
|
23
|
+
export declare const createFilterPredicate: <T extends object>(filterKey: string, categorizedFilters: CategorizedFilters, attributeGetter: (item: T) => string) => (item: T) => boolean;
|
|
24
24
|
/**
|
|
25
25
|
* Creates a sorting function to be used on a specific object attribute.
|
|
26
26
|
*
|
|
@@ -29,4 +29,4 @@ export declare const createFilterPredicate: <T extends object>(filterKey: keyof
|
|
|
29
29
|
* @returns the sorting comparer function to be used in Array.sort
|
|
30
30
|
*/
|
|
31
31
|
export declare const createSortingComparer: <T extends object>(getter: (item: T) => string | number, order?: "asc" | "desc") => (itemA: T, itemB: T) => number;
|
|
32
|
-
export declare const applySorting: <T extends object[]>(sortable: T, sortingOptions:
|
|
32
|
+
export declare const applySorting: <T extends object[]>(sortable: T, sortingOptions: TransformedSortingOptions<T[number]>) => T;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* This is used based on the dataset passed to FilterBar, so we always calculate the filters
|
|
4
4
|
* looking at the data.
|
|
5
5
|
*/
|
|
6
|
-
export type FilterGenerator<
|
|
6
|
+
export type FilterGenerator<SortableEntity> = {
|
|
7
7
|
id: string;
|
|
8
8
|
label: string;
|
|
9
9
|
/**
|
|
@@ -13,7 +13,7 @@ export type FilterGenerator<T> = {
|
|
|
13
13
|
*
|
|
14
14
|
* @example
|
|
15
15
|
*
|
|
16
|
-
* ```
|
|
16
|
+
* ```ts
|
|
17
17
|
* {
|
|
18
18
|
id: "brand",
|
|
19
19
|
label: "Brand",
|
|
@@ -22,7 +22,7 @@ export type FilterGenerator<T> = {
|
|
|
22
22
|
* ```
|
|
23
23
|
* in the above, all unique values from `brand` will be used to populate the `Brand` filter.
|
|
24
24
|
*/
|
|
25
|
-
filterValuePredicate: (data:
|
|
25
|
+
filterValuePredicate: (data: SortableEntity) => string;
|
|
26
26
|
};
|
|
27
27
|
/**
|
|
28
28
|
* Allows customization of labels related to filter.
|
|
@@ -65,30 +65,22 @@ export type TransformedFilterOption = {
|
|
|
65
65
|
isChecked: boolean;
|
|
66
66
|
};
|
|
67
67
|
export type TransformedFilterOptions = TransformedFilterOption[];
|
|
68
|
-
type
|
|
68
|
+
type CategorizedFilter = {
|
|
69
69
|
key: string;
|
|
70
70
|
label: string;
|
|
71
71
|
options: TransformedFilterOptions;
|
|
72
72
|
};
|
|
73
|
-
export type
|
|
74
|
-
export type TransformedSortingOption = {
|
|
73
|
+
export type CategorizedFilters = CategorizedFilter[];
|
|
74
|
+
export type TransformedSortingOption<SortableEntity extends object> = {
|
|
75
75
|
id: string;
|
|
76
76
|
label: string;
|
|
77
77
|
value: string;
|
|
78
78
|
isChecked: boolean;
|
|
79
|
-
sortingCompare: (itemA:
|
|
79
|
+
sortingCompare: (itemA: SortableEntity, itemB: SortableEntity) => number;
|
|
80
80
|
};
|
|
81
|
-
export type TransformedSortingOptions = TransformedSortingOption[];
|
|
81
|
+
export type TransformedSortingOptions<SortableEntity extends object> = TransformedSortingOption<SortableEntity>[];
|
|
82
82
|
export type OnFilterBarFilterChange = (params: {
|
|
83
|
-
category: string;
|
|
84
83
|
changedFilterOption: TransformedFilterOption;
|
|
85
84
|
}) => void;
|
|
86
|
-
export type OnFilterBarSortingChange = (changedSortingOption: TransformedSortingOption) => void;
|
|
87
|
-
export type FilterBarProps = {
|
|
88
|
-
categorizedFilters: CategorisedFilters;
|
|
89
|
-
sortingOptions: TransformedSortingOptions;
|
|
90
|
-
onFilterChange: (updatedFilters: CategorisedFilters) => void;
|
|
91
|
-
onSortingChange: (updatedSortingOptions: TransformedSortingOptions) => void;
|
|
92
|
-
localization: FilterBarLocalization;
|
|
93
|
-
};
|
|
85
|
+
export type OnFilterBarSortingChange<SortableEntity extends object> = (changedSortingOption: TransformedSortingOption<SortableEntity>) => void;
|
|
94
86
|
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { CategorizedFilters, OnFilterBarFilterChange } from "./FilterBarProps.type";
|
|
3
3
|
type FiltersMenusProps = {
|
|
4
|
-
filters:
|
|
4
|
+
filters: CategorizedFilters;
|
|
5
5
|
onFilterOptionChange: OnFilterBarFilterChange;
|
|
6
6
|
};
|
|
7
7
|
export declare const FiltersMenus: React.FC<FiltersMenusProps>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { ReactElement } from "react";
|
|
2
2
|
import { FilterBarLocalization, OnFilterBarSortingChange, TransformedSortingOption } from "./FilterBarProps.type";
|
|
3
|
-
type SortMenuProps = {
|
|
3
|
+
type SortMenuProps<SortableEntity extends object> = {
|
|
4
4
|
localization: FilterBarLocalization;
|
|
5
|
-
sortingOptions: TransformedSortingOption[];
|
|
6
|
-
onSortOptionChange: OnFilterBarSortingChange
|
|
5
|
+
sortingOptions: TransformedSortingOption<SortableEntity>[];
|
|
6
|
+
onSortOptionChange: OnFilterBarSortingChange<SortableEntity>;
|
|
7
7
|
};
|
|
8
|
-
export declare const SortMenu:
|
|
8
|
+
export declare const SortMenu: <SortableEntity extends object>(props: SortMenuProps<SortableEntity>) => ReactElement | null;
|
|
9
9
|
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -78,4 +78,5 @@ export { Divider } from "./components/Divider/Divider";
|
|
|
78
78
|
export { FullPageModal } from "./components/Modal/FullPageModal";
|
|
79
79
|
export { Card, type CardProps } from "./components/Card/Card";
|
|
80
80
|
export { Dropzone, DropzoneProps } from "./components/Dropzone";
|
|
81
|
+
export { FilterBar, FilterBarUtils } from "./components/FilterBar";
|
|
81
82
|
export { default as DragHandle, DragHandleProps, } from "./components/DragHandle";
|
|
@@ -28,6 +28,8 @@ var htmlToDraft = require('html-to-draftjs');
|
|
|
28
28
|
require('react-draft-wysiwyg/dist/react-draft-wysiwyg.css');
|
|
29
29
|
var pick = require('lodash/pick');
|
|
30
30
|
var index_ie11 = require('react-hook-form/dist/index.ie11');
|
|
31
|
+
var react = require('@headlessui/react');
|
|
32
|
+
var solid = require('@heroicons/react/20/solid');
|
|
31
33
|
|
|
32
34
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
33
35
|
|
|
@@ -5254,6 +5256,237 @@ const Card = ({ title, children, dataTestId }) => {
|
|
|
5254
5256
|
);
|
|
5255
5257
|
};
|
|
5256
5258
|
|
|
5259
|
+
const CloseIcon = () => React__namespace.default.createElement(
|
|
5260
|
+
"svg",
|
|
5261
|
+
{ className: "ui-h-2 ui-w-2", stroke: "currentColor", fill: "none", viewBox: "0 0 8 8" },
|
|
5262
|
+
React__namespace.default.createElement("path", { strokeLinecap: "round", strokeWidth: "1.5", d: "M1 1l6 6m0-6L1 7" })
|
|
5263
|
+
);
|
|
5264
|
+
const ActiveFilters = (props) => {
|
|
5265
|
+
const { onRemoveActiveFilter, filters, localization } = props;
|
|
5266
|
+
const activeFilters = filters.flatMap((categorizedFilter) => {
|
|
5267
|
+
return categorizedFilter.options.map((categorizedFilterOption) => {
|
|
5268
|
+
return categorizedFilterOption;
|
|
5269
|
+
});
|
|
5270
|
+
}).filter((activeFilter) => activeFilter.isChecked);
|
|
5271
|
+
return React__namespace.default.createElement(
|
|
5272
|
+
"div",
|
|
5273
|
+
{ className: "ui-bg-gray-100" },
|
|
5274
|
+
React__namespace.default.createElement(
|
|
5275
|
+
"div",
|
|
5276
|
+
{ className: "ui-min-h-15 ui-max-w-7xl ui-px-4 ui-py-3 sm:ui-flex sm:ui-items-center sm:ui-px-6" },
|
|
5277
|
+
React__namespace.default.createElement("h3", { className: "ui-text-sm ui-font-medium ui-text-gray-500" }, localization.filtersLabel),
|
|
5278
|
+
React__namespace.default.createElement("div", { "aria-hidden": "true", className: "ui-hidden ui-h-5 ui-w-px ui-bg-gray-300 sm:ui-ml-4 sm:ui-block" }),
|
|
5279
|
+
React__namespace.default.createElement(
|
|
5280
|
+
"div",
|
|
5281
|
+
{ className: "ui-mt-2 sm:ui-ml-4 sm:ui-mt-0" },
|
|
5282
|
+
React__namespace.default.createElement("div", { className: "-ui-m-1 ui-flex ui-flex-wrap ui-items-center" }, activeFilters.map((activeFilter) => React__namespace.default.createElement(
|
|
5283
|
+
"span",
|
|
5284
|
+
{ key: activeFilter.value, className: "pr-2 ui-m-1 ui-inline-flex ui-items-center ui-rounded-full ui-border ui-border-gray-200 ui-bg-white ui-py-1.5 ui-pl-3 ui-text-sm ui-font-medium ui-text-gray-900" },
|
|
5285
|
+
React__namespace.default.createElement("span", null, activeFilter.label),
|
|
5286
|
+
React__namespace.default.createElement(
|
|
5287
|
+
"button",
|
|
5288
|
+
{ type: "button", className: "ui-mx-1 ui-inline-flex ui-h-4 ui-w-4 ui-flex-shrink-0 ui-rounded-full ui-p-1 ui-text-gray-400 hover:ui-bg-gray-200 hover:ui-text-gray-500", onClick: () => onRemoveActiveFilter({
|
|
5289
|
+
changedFilterOption: {
|
|
5290
|
+
isChecked: false,
|
|
5291
|
+
id: activeFilter.id,
|
|
5292
|
+
label: activeFilter.label,
|
|
5293
|
+
value: activeFilter.value
|
|
5294
|
+
}
|
|
5295
|
+
}) },
|
|
5296
|
+
React__namespace.default.createElement(CloseIcon, null)
|
|
5297
|
+
)
|
|
5298
|
+
)))
|
|
5299
|
+
)
|
|
5300
|
+
)
|
|
5301
|
+
);
|
|
5302
|
+
};
|
|
5303
|
+
|
|
5304
|
+
const SortMenu = (props) => {
|
|
5305
|
+
const { localization, sortingOptions, onSortOptionChange } = props;
|
|
5306
|
+
const selectedSorting = sortingOptions.find((sortingOption) => sortingOption.isChecked);
|
|
5307
|
+
const menuLabel = selectedSorting ? `${localization.sortedByLabel} ${selectedSorting.label}` : localization.sortLabel;
|
|
5308
|
+
return React__namespace.default.createElement(
|
|
5309
|
+
react.Menu,
|
|
5310
|
+
{ as: "div", className: "ui-relative ui-inline-block ui-text-left" },
|
|
5311
|
+
React__namespace.default.createElement(
|
|
5312
|
+
"div",
|
|
5313
|
+
null,
|
|
5314
|
+
React__namespace.default.createElement(
|
|
5315
|
+
react.Menu.Button,
|
|
5316
|
+
{ className: "ui-group ui-inline-flex ui-justify-center ui-text-sm ui-font-medium ui-text-slate-700 hover:ui-text-slate-900" },
|
|
5317
|
+
menuLabel,
|
|
5318
|
+
React__namespace.default.createElement(solid.ChevronDownIcon, { className: "ui-group-hover:ui-text-slate-500 -ui-mr-1 ui-ml-1 ui-h-5 ui-w-5 ui-flex-shrink-0 ui-text-slate-400", "aria-hidden": "true" })
|
|
5319
|
+
)
|
|
5320
|
+
),
|
|
5321
|
+
React__namespace.default.createElement(
|
|
5322
|
+
react.Transition,
|
|
5323
|
+
{ 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" },
|
|
5324
|
+
React__namespace.default.createElement(
|
|
5325
|
+
react.Menu.Items,
|
|
5326
|
+
{ 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" },
|
|
5327
|
+
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))))
|
|
5328
|
+
)
|
|
5329
|
+
)
|
|
5330
|
+
);
|
|
5331
|
+
};
|
|
5332
|
+
|
|
5333
|
+
const FiltersMenus = (props) => {
|
|
5334
|
+
const { filters } = props;
|
|
5335
|
+
return React__namespace.default.createElement(
|
|
5336
|
+
"div",
|
|
5337
|
+
{ className: "ui-hidden sm:ui-block" },
|
|
5338
|
+
React__namespace.default.createElement(
|
|
5339
|
+
"div",
|
|
5340
|
+
{ className: "ui-flow-root" },
|
|
5341
|
+
React__namespace.default.createElement(react.Popover.Group, { className: "-ui-mx-4 ui-flex ui-items-center ui-divide-x ui-divide-slate-200" }, filters.map((categorizedFilter) => {
|
|
5342
|
+
const amountOfCheckedItems = categorizedFilter.options.filter((option) => option.isChecked).length;
|
|
5343
|
+
return React__namespace.default.createElement(
|
|
5344
|
+
react.Popover,
|
|
5345
|
+
{ key: categorizedFilter.key, className: "ui-relative ui-inline-block ui-px-4 ui-text-left" },
|
|
5346
|
+
React__namespace.default.createElement(
|
|
5347
|
+
react.Popover.Button,
|
|
5348
|
+
{ className: "ui-group ui-inline-flex ui-justify-center ui-text-sm ui-font-medium ui-text-slate-700 hover:ui-text-slate-900" },
|
|
5349
|
+
React__namespace.default.createElement("span", null, categorizedFilter.label),
|
|
5350
|
+
amountOfCheckedItems > 0 ? React__namespace.default.createElement("span", { className: "ui-ml-1.5 ui-rounded ui-bg-slate-200 ui-px-1.5 ui-py-0.5 ui-text-xs ui-font-semibold ui-tabular-nums ui-text-slate-700" }, amountOfCheckedItems) : null,
|
|
5351
|
+
React__namespace.default.createElement(solid.ChevronDownIcon, { className: "ui-group-hover:ui-text-slate-500 -ui-mr-1 ui-ml-1 ui-h-5 ui-w-5 ui-flex-shrink-0 ui-text-slate-400", "aria-hidden": "true" })
|
|
5352
|
+
),
|
|
5353
|
+
React__namespace.default.createElement(
|
|
5354
|
+
react.Transition,
|
|
5355
|
+
{ 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" },
|
|
5356
|
+
React__namespace.default.createElement(
|
|
5357
|
+
react.Popover.Panel,
|
|
5358
|
+
{ 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" },
|
|
5359
|
+
React__namespace.default.createElement("form", { className: "ui-space-y-4" }, categorizedFilter.options.map((option) => React__namespace.default.createElement(
|
|
5360
|
+
"label",
|
|
5361
|
+
{ key: `${option.id}`, className: "ui-flex ui-items-center", htmlFor: `filter-${option.id}` },
|
|
5362
|
+
React__namespace.default.createElement("input", { id: `filter-${option.id}`, name: `${option.value}`, defaultValue: option.value, type: "checkbox", defaultChecked: option.isChecked, onChange: () => {
|
|
5363
|
+
props.onFilterOptionChange({
|
|
5364
|
+
changedFilterOption: Object.assign(Object.assign({}, option), { isChecked: !option.isChecked })
|
|
5365
|
+
});
|
|
5366
|
+
}, className: "ui-form-checkbox ui-h-4 ui-w-4 ui-rounded ui-border-slate-300 ui-text-blue-800 focus:ui-ring-blue-800" }),
|
|
5367
|
+
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)
|
|
5368
|
+
)))
|
|
5369
|
+
)
|
|
5370
|
+
)
|
|
5371
|
+
);
|
|
5372
|
+
}))
|
|
5373
|
+
)
|
|
5374
|
+
);
|
|
5375
|
+
};
|
|
5376
|
+
|
|
5377
|
+
const FilterBar = (_a) => {
|
|
5378
|
+
var { localization, categorizedFilters, sortingOptions } = _a, props = __rest(_a, ["localization", "categorizedFilters", "sortingOptions"]);
|
|
5379
|
+
const onSortOptionChange = (changedSortingOption) => {
|
|
5380
|
+
const updatedSortingOptions = sortingOptions.map((previousSortingOption) => {
|
|
5381
|
+
if (previousSortingOption.id === changedSortingOption.id) {
|
|
5382
|
+
return Object.assign({}, changedSortingOption);
|
|
5383
|
+
}
|
|
5384
|
+
return Object.assign(Object.assign({}, previousSortingOption), { isChecked: false });
|
|
5385
|
+
});
|
|
5386
|
+
props.onSortingChange(updatedSortingOptions);
|
|
5387
|
+
};
|
|
5388
|
+
const onFilterOptionChange = ({ changedFilterOption }) => {
|
|
5389
|
+
const updatedFilters = categorizedFilters.map((categorizedFilter) => {
|
|
5390
|
+
return Object.assign(Object.assign({}, categorizedFilter), { options: categorizedFilter.options.map((categorizedFilterOption) => {
|
|
5391
|
+
if (categorizedFilterOption.id === changedFilterOption.id) {
|
|
5392
|
+
return changedFilterOption;
|
|
5393
|
+
}
|
|
5394
|
+
return categorizedFilterOption;
|
|
5395
|
+
}) });
|
|
5396
|
+
});
|
|
5397
|
+
props.onFilterChange(updatedFilters);
|
|
5398
|
+
};
|
|
5399
|
+
return React__namespace.default.createElement(
|
|
5400
|
+
"div",
|
|
5401
|
+
null,
|
|
5402
|
+
React__namespace.default.createElement(
|
|
5403
|
+
"section",
|
|
5404
|
+
{ "aria-labelledby": "filter-heading" },
|
|
5405
|
+
React__namespace.default.createElement(
|
|
5406
|
+
"div",
|
|
5407
|
+
{ className: "ui-rounded-lg ui-bg-white ui-py-4" },
|
|
5408
|
+
React__namespace.default.createElement(
|
|
5409
|
+
"div",
|
|
5410
|
+
{ className: "ui-flex ui-items-center ui-justify-between ui-px-4 sm:ui-px-6" },
|
|
5411
|
+
React__namespace.default.createElement(SortMenu, { localization, sortingOptions, onSortOptionChange }),
|
|
5412
|
+
React__namespace.default.createElement(FiltersMenus, { filters: categorizedFilters, onFilterOptionChange })
|
|
5413
|
+
)
|
|
5414
|
+
),
|
|
5415
|
+
React__namespace.default.createElement(ActiveFilters, { localization, filters: categorizedFilters, onRemoveActiveFilter: onFilterOptionChange })
|
|
5416
|
+
)
|
|
5417
|
+
);
|
|
5418
|
+
};
|
|
5419
|
+
|
|
5420
|
+
function getFilterGroups(dataToGenerateFiltersFrom, groupers) {
|
|
5421
|
+
const res = [];
|
|
5422
|
+
for (const group of groupers) {
|
|
5423
|
+
const { id, label, filterValuePredicate } = group;
|
|
5424
|
+
const uniqueValues = Array.from(new Set(dataToGenerateFiltersFrom.map(filterValuePredicate)));
|
|
5425
|
+
const options = uniqueValues.map((uniqueValue) => ({
|
|
5426
|
+
isChecked: false,
|
|
5427
|
+
id: uniqueValue,
|
|
5428
|
+
label: uniqueValue,
|
|
5429
|
+
value: uniqueValue
|
|
5430
|
+
}));
|
|
5431
|
+
res.push({ key: id, label, options });
|
|
5432
|
+
}
|
|
5433
|
+
return res;
|
|
5434
|
+
}
|
|
5435
|
+
const createFilterGroupedValues = (filterKey, categorizedFilters) => {
|
|
5436
|
+
const filterForKey = categorizedFilters.find((option) => option.key === filterKey);
|
|
5437
|
+
if (!filterForKey) {
|
|
5438
|
+
throw new ReferenceError(`No filter has been found for key: [${String(filterKey)}]`, {
|
|
5439
|
+
cause: {
|
|
5440
|
+
message: "You have tried to retrieve a filter with a key that does not exist in the categorized filters.",
|
|
5441
|
+
existingKeys: categorizedFilters.map((categorizedFilter) => categorizedFilter.key).join(", ")
|
|
5442
|
+
}
|
|
5443
|
+
});
|
|
5444
|
+
}
|
|
5445
|
+
const selectedOptions = filterForKey.options.filter((option) => option.isChecked).map((option) => option.value);
|
|
5446
|
+
return selectedOptions;
|
|
5447
|
+
};
|
|
5448
|
+
const createFilterPredicate = (filterKey, categorizedFilters, attributeGetter) => {
|
|
5449
|
+
const selectedFilters = createFilterGroupedValues(filterKey, categorizedFilters);
|
|
5450
|
+
if (selectedFilters.length === 0) {
|
|
5451
|
+
return () => true;
|
|
5452
|
+
}
|
|
5453
|
+
return (item) => {
|
|
5454
|
+
const valueToBeCheckedInFilter = attributeGetter(item);
|
|
5455
|
+
return selectedFilters.includes(valueToBeCheckedInFilter);
|
|
5456
|
+
};
|
|
5457
|
+
};
|
|
5458
|
+
const createSortingComparer = (getter, order = "asc") => {
|
|
5459
|
+
return (a, b) => {
|
|
5460
|
+
const attributeToSortFromA = getter(a);
|
|
5461
|
+
const attributeToSortFromB = getter(b);
|
|
5462
|
+
const orderEnforcer = order === "asc" ? 1 : -1;
|
|
5463
|
+
if (attributeToSortFromA > attributeToSortFromB) {
|
|
5464
|
+
return 1 * orderEnforcer;
|
|
5465
|
+
}
|
|
5466
|
+
if (attributeToSortFromA < attributeToSortFromB) {
|
|
5467
|
+
return -1 * orderEnforcer;
|
|
5468
|
+
}
|
|
5469
|
+
return 0;
|
|
5470
|
+
};
|
|
5471
|
+
};
|
|
5472
|
+
const applySorting = (sortable, sortingOptions) => {
|
|
5473
|
+
const selectedSorting = sortingOptions.find((sortingOption) => sortingOption.isChecked);
|
|
5474
|
+
if (selectedSorting) {
|
|
5475
|
+
const arrayCopy = [...sortable];
|
|
5476
|
+
arrayCopy.sort(selectedSorting.sortingCompare);
|
|
5477
|
+
return arrayCopy;
|
|
5478
|
+
}
|
|
5479
|
+
return sortable;
|
|
5480
|
+
};
|
|
5481
|
+
|
|
5482
|
+
var FilterBar_utils = /*#__PURE__*/Object.freeze({
|
|
5483
|
+
__proto__: null,
|
|
5484
|
+
applySorting: applySorting,
|
|
5485
|
+
createFilterPredicate: createFilterPredicate,
|
|
5486
|
+
createSortingComparer: createSortingComparer,
|
|
5487
|
+
getFilterGroups: getFilterGroups
|
|
5488
|
+
});
|
|
5489
|
+
|
|
5257
5490
|
exports.AccordionList = AccordionList;
|
|
5258
5491
|
exports.AddIcon = AddIcon;
|
|
5259
5492
|
exports.AlertsIcon = AlertsIcon;
|
|
@@ -5293,6 +5526,8 @@ exports.EmptyStateDashboardIcon = EmptyStateDashboardIcon;
|
|
|
5293
5526
|
exports.ErrorBlock = ErrorBlock;
|
|
5294
5527
|
exports.ExclamationMarkIcon = ExclamationMarkIcon;
|
|
5295
5528
|
exports.EyeIcon = EyeIcon;
|
|
5529
|
+
exports.FilterBar = FilterBar;
|
|
5530
|
+
exports.FilterBarUtils = FilterBar_utils;
|
|
5296
5531
|
exports.FlexColumn = FlexColumn;
|
|
5297
5532
|
exports.FlexRow = FlexRow;
|
|
5298
5533
|
exports.Form = Form;
|