@luscii-healthtech/web-ui 0.0.0-alpha.ab3fdb2 → 0.0.0-dynamic
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/README.md +116 -46
- package/dist/components/AccordionList/AccordionList.d.ts +11 -1
- package/dist/components/AccordionList/subcomponents/AccordionListActions.d.ts +18 -0
- package/dist/components/Card/Card.d.ts +1 -1
- package/dist/components/Checkbox/Checkbox.d.ts +46 -1
- package/dist/components/CheckboxList/CheckboxGroup.d.ts +1 -1
- package/dist/components/CheckboxList/CheckboxList.d.ts +1 -2
- package/dist/components/CheckboxList/CheckboxList.types.d.ts +35 -13
- package/dist/components/Container/types/FlexContainerProps.type.d.ts +2 -2
- package/dist/components/FilterBar/ActiveFilters.d.ts +9 -0
- package/dist/components/FilterBar/FilterBar.d.ts +96 -0
- package/dist/components/FilterBar/FilterBar.utils.d.ts +32 -0
- package/dist/components/FilterBar/FilterBarProps.type.d.ts +86 -0
- package/dist/components/FilterBar/FiltersMenus.d.ts +8 -0
- package/dist/components/FilterBar/SortMenu.d.ts +9 -0
- package/dist/components/FilterBar/index.d.ts +2 -0
- package/dist/components/Form/form.types.d.ts +4 -3
- package/dist/components/Icon/Icon.d.ts +1 -1
- package/dist/components/Icons/EyeIconSlashed.d.ts +4 -0
- package/dist/components/Icons/PageViewIcon.d.ts +4 -0
- package/dist/components/Icons/index.d.ts +2 -0
- package/dist/components/InfoField/InfoField.d.ts +19 -9
- package/dist/components/Input/Input.d.ts +1 -1
- package/dist/components/Input/SearchInput.d.ts +23 -3
- package/dist/components/Link/Link.d.ts +19 -0
- package/dist/components/{ImagePicker → MediaPicker}/ImageCategory.d.ts +2 -2
- package/dist/components/MediaPicker/MediaPicker.d.ts +95 -0
- package/dist/components/Modal/FullPageModal.d.ts +29 -1
- package/dist/components/Modal/FullPageModalHeader.d.ts +6 -0
- package/dist/components/Modal/subcomponents/FullPageModalActions.d.ts +18 -0
- package/dist/components/PreviewPhone/PreviewPhone.d.ts +1 -1
- package/dist/components/Section/Section.d.ts +1 -1
- package/dist/components/Select/Select.d.ts +9 -3
- package/dist/components/Spinner/Spinner.d.ts +2 -2
- package/dist/components/Text/Text.d.ts +78 -29
- package/dist/components/TextEditor/TextEditor.d.ts +17 -0
- package/dist/components/TextLink/TextLink.d.ts +3 -0
- package/dist/components/Timeline/TimelineHeader.d.ts +1 -1
- package/dist/components/Toaster/toast-progress-animator.d.ts +1 -1
- package/dist/index.d.ts +6 -4
- package/dist/index.development.js +5678 -0
- package/dist/index.development.js.map +1 -0
- package/dist/index.js +1 -1356
- package/dist/index.js.map +1 -1
- package/dist/web-ui-tailwind.css +907 -474
- package/dist/web-ui.esm.js +1 -1356
- package/dist/web-ui.esm.js.map +1 -1
- package/package.json +44 -49
- package/dist/components/CheckboxList/CheckboxListItem.d.ts +0 -3
- package/dist/components/ImagePicker/ImagePicker.d.ts +0 -29
package/README.md
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
#
|
|
1
|
+
# WebUI
|
|
2
2
|
|
|
3
|
-
The web-ui repository contains the
|
|
3
|
+
The `web-ui` repository contains the UI components for Luscii's frontend projects. It is published to NPM for usage into our projects. It uses Storybook and is published to Chromatic for easy review and tracking of visual changes.
|
|
4
4
|
|
|
5
5
|
## Running locally
|
|
6
6
|
|
|
7
|
-
If you want to run
|
|
7
|
+
If you want to run Storybook locally you can use:
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
yarn install
|
|
11
|
-
yarn
|
|
11
|
+
yarn dev # runs a Tailwind watcher and Storybook
|
|
12
12
|
```
|
|
13
13
|
|
|
14
14
|
## Testing your production build
|
|
15
15
|
|
|
16
16
|
Assuming the following setup:
|
|
17
17
|
|
|
18
|
-
- The `web-ui` and `cVitals-Web` repositories are siblings
|
|
19
|
-
- You
|
|
20
|
-
- You
|
|
18
|
+
- The `web-ui` and `cVitals-Web` repositories are siblings in the same folder.
|
|
19
|
+
- You ran `yarn install` in `cVitals-Web`.
|
|
20
|
+
- You ran `yarn build` in `web-ui`.
|
|
21
21
|
|
|
22
22
|
Run the script below in your terminal, _in the parent folder of the repositories_.
|
|
23
23
|
|
|
@@ -31,79 +31,149 @@ Or use the shortcut:
|
|
|
31
31
|
yarn test-copy-build
|
|
32
32
|
```
|
|
33
33
|
|
|
34
|
-
When you run cVitals again, it should contain your latest updates in the component library. Use this to make sure your changes are solid before
|
|
34
|
+
When you run `cVitals-Web` again, it should contain your latest updates in the component library. Use this to make sure your changes are solid before opening a pull request.
|
|
35
35
|
|
|
36
36
|
## Contributing
|
|
37
37
|
|
|
38
|
-
|
|
38
|
+
Thank you for your help in keeping our component library organized and easy to use!
|
|
39
39
|
|
|
40
|
-
If you want to add components, do so in
|
|
40
|
+
When adding components, please make sure to implement them consistently in our projects and that it is clear where and when they should be used. We want to avoid having many similar components. If you want to add components, do so in the `/src/components` directory. When you create new components, add them to Storybook as well. Stories go in the `/stories` directory.
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
/src/components
|
|
44
|
-
```
|
|
42
|
+
If you add new components, please make sure they fit in with our existing ones and that it's clear where and when they should be used. We want to avoid having too many similar components.
|
|
45
43
|
|
|
46
|
-
|
|
44
|
+
### Documentation
|
|
47
45
|
|
|
48
|
-
|
|
46
|
+
Every component should have proper documentation that explains when, where and how to use it. This sounds like a lot of work, but it doesn't have to be. And it's important, also for you, to quickly see how to best use a component.
|
|
49
47
|
|
|
48
|
+
Component documentation should include the following parts:
|
|
49
|
+
|
|
50
|
+
- A short explanation of each prop in a JSDoc comment style.
|
|
51
|
+
- A stories file (`<ComponentName>.stories.tsx`).
|
|
52
|
+
- A docs file (`<ComponentName>.docs.mdx`).
|
|
53
|
+
|
|
54
|
+
Below is an explanation of each.
|
|
55
|
+
|
|
56
|
+
#### Props documented via JSDoc comments
|
|
57
|
+
|
|
58
|
+
A short explanation of each prop in a JSDoc comment style. These will show up in your IDE for on the fly documentation when you need it. It will also show up in Storybook, so this is a double-whammy and provides documentation exactly where you need it.
|
|
59
|
+
|
|
60
|
+
```ts
|
|
61
|
+
type Props = {
|
|
62
|
+
/**
|
|
63
|
+
* Optional description that will be shown close to the label, used to provide more
|
|
64
|
+
* detail about the field next to the concise text of the label.
|
|
65
|
+
*/
|
|
66
|
+
helperText?: string;
|
|
67
|
+
};
|
|
50
68
|
```
|
|
51
|
-
|
|
52
|
-
|
|
69
|
+
|
|
70
|
+
#### Stories file
|
|
71
|
+
|
|
72
|
+
Stories files (`*stories.tsx`) will show up in Storybook as separate entries/pages for each component. Each component can have multiple stories defined for it, showing different use cases, variants and states of that component.
|
|
73
|
+
It is important to include stories for a lot of these different variants and states, because visual snapshots will be created of these stories by a tool called Chromatic. This allows us to visually track changes to the component over time, and ensure that it looks and behaves correctly across different use cases. By writing stories that showcase all the different ways your component can be used, you can catch issues early and ensure that your component is robust and reliable.
|
|
74
|
+
|
|
75
|
+
You can find the Chromatic project for WebUI [here](https://www.chromatic.com/library?appId=62b0c4d5afd432f7ee70a740).
|
|
76
|
+
|
|
77
|
+
#### Docs file
|
|
78
|
+
|
|
79
|
+
The component docs file brings everything together and should be considered the source of truth about the component. What should be documented:
|
|
80
|
+
|
|
81
|
+
- Why we have the component and where it should be used.
|
|
82
|
+
- An overview of the different variants and states.
|
|
83
|
+
- Usage guidelines of when and where to use the component.
|
|
84
|
+
- Best practices to show what to do and what not do when working with the component.
|
|
85
|
+
|
|
86
|
+
> 🔎 If you need to e.g. create a story to show how NOT to use a component, you might not want
|
|
87
|
+
> to create a snapshot for that component or show it in the sidebar of Storybook. To omit a story
|
|
88
|
+
> from snapshots, add the following to its parameters:
|
|
89
|
+
>
|
|
90
|
+
> ```ts
|
|
91
|
+
> chromatic: { disableSnapshot: true },
|
|
92
|
+
> ```
|
|
93
|
+
>
|
|
94
|
+
> To hide a story from the sidebar, prefix the story (variable) name
|
|
95
|
+
> with `HIDE_`.
|
|
96
|
+
|
|
97
|
+
Please see examples of other components' docs files for inspiration and try to stay consistent with how they are documented.
|
|
98
|
+
|
|
99
|
+
### Accessibility
|
|
100
|
+
|
|
101
|
+
WebUI is not currently designed to support screen reader usage. This is because our application is designed specifically for healthcare providers and is not publicly accessible. Our primary users are caregivers who work in healthcare and do not rely on screen readers to be able to use our application.
|
|
102
|
+
However, it is important for developers to write accessible frontend code. Even if our current application is not designed to support screen reader usage. This means following best practices for web accessibility, such as using semantic HTML, providing alternative text for images, and ensuring keyboard navigation is possible. While our primary users may not rely on screen readers, it is important to make our application as inclusive as possible to all users.
|
|
103
|
+
|
|
104
|
+
### Testing
|
|
105
|
+
|
|
106
|
+
WebUI relies on two types of testing: Visual snapshot testing via Chromatic and interaction testing via Storybook.
|
|
107
|
+
|
|
108
|
+
Visual snapshot testing is handled for you. Any story you write will be picked up by Chromatic and it will create a snapshot for it.
|
|
109
|
+
|
|
110
|
+
Interaction testing via Storybook allows to programmatically interact with the component. This is very helpful in testing any logic that the component may use internally and any states of the component that might be hard/impossible to trigger from the outside.
|
|
111
|
+
More information on how to approach writing interaction tests can be found in [this page of the Storybook documentation](https://storybook.js.org/docs/react/writing-tests/interaction-testing#write-an-interaction-test).
|
|
53
112
|
|
|
54
113
|
### Adding icons
|
|
55
114
|
|
|
56
|
-
Add new icons by:
|
|
115
|
+
Add new icons by following these steps:
|
|
57
116
|
|
|
58
|
-
- Add the svg file(s) in `src/components/Icons/icons
|
|
59
|
-
- Run `yarn icons
|
|
117
|
+
- Add the svg file(s) in `src/components/Icons/icons`.
|
|
118
|
+
- Run `yarn icons`.
|
|
60
119
|
|
|
61
120
|
The icons are optimized by SVGO and transformed into React components by [SVGR](https://react-svgr.com) which are placed in `src/components/Icons`.
|
|
62
121
|
|
|
63
122
|
## CI setup
|
|
64
123
|
|
|
65
|
-
|
|
124
|
+
### Branching
|
|
66
125
|
|
|
67
|
-
The `main` branch is our default branch. When you contribute, branch from there and
|
|
126
|
+
The `main` branch is our default branch. When you contribute, branch from there and use the following branch naming convention:
|
|
68
127
|
|
|
69
128
|
```
|
|
70
|
-
//Branch
|
|
129
|
+
// Branch naming convention (enforced)
|
|
71
130
|
|
|
72
|
-
major/* //
|
|
73
|
-
minor/* //
|
|
74
|
-
patch/* //
|
|
75
|
-
bug/* //
|
|
131
|
+
major/* // For a new design system or changes that effect our foundations (e.g. typography, color).
|
|
132
|
+
minor/* // For new components and stories.
|
|
133
|
+
patch/* // For small improvements to existing components or stories.
|
|
134
|
+
bug/* // For bugs or fixes.
|
|
135
|
+
chore/* // For things related to development that don't impact the output for consumers and/or users.
|
|
76
136
|
```
|
|
77
137
|
|
|
78
138
|
We have configured at lot of magic for your convenience.
|
|
79
139
|
|
|
80
|
-
|
|
140
|
+
### On every PR
|
|
81
141
|
|
|
82
|
-
1.
|
|
83
|
-
2. The
|
|
142
|
+
1. The module build, lint and tests are checked.
|
|
143
|
+
2. The Storybook build is published to Chromatic.
|
|
84
144
|
3. Labels are added based on the branch name and PR size.
|
|
85
|
-
4. Branch names must follow the convention and are checked
|
|
86
|
-
|
|
87
|
-
#### On merge to main
|
|
145
|
+
4. Branch names must follow the convention and are checked.
|
|
88
146
|
|
|
89
|
-
|
|
90
|
-
2. Version bump of the package
|
|
91
|
-
3. Publish new package to NPM
|
|
147
|
+
### On merge to main
|
|
92
148
|
|
|
93
|
-
|
|
149
|
+
1. Drafts a GitHub release.
|
|
150
|
+
2. Bumps the version of the package.
|
|
151
|
+
3. Publishes the new package version to NPM.
|
|
94
152
|
|
|
95
|
-
##
|
|
153
|
+
## Stories
|
|
96
154
|
|
|
97
|
-
|
|
155
|
+
### Stories using deprecated props
|
|
98
156
|
|
|
99
|
-
|
|
157
|
+
When creating new stories for components with deprecated functionality please prefix the story name with `Deprecated`. In addition, also mark it with a "DEPRECATED" badge via the story's parameters.
|
|
100
158
|
|
|
101
|
-
|
|
102
|
-
- [regenerator-runtime](https://www.npmjs.com/package/regenerator-runtime)
|
|
103
|
-
- [smoothscroll-polyfill](https://www.npmjs.com/package/smoothscroll-polyfill)
|
|
159
|
+
For example a story of a `FullPageModal` component using the deprecated `primaryButtonProps` prop would look like this:
|
|
104
160
|
|
|
105
|
-
|
|
161
|
+
```tsx
|
|
162
|
+
import { BADGES } from "../.storybook/constants";
|
|
106
163
|
|
|
107
|
-
|
|
164
|
+
export const DeprecatedWithPrimaryButtonProps = {
|
|
165
|
+
render: OneColumTemplate,
|
|
166
|
+
args: {
|
|
167
|
+
isOpen: true,
|
|
168
|
+
primaryButtonProps: {
|
|
169
|
+
onClick: action("onClick Primary Button"),
|
|
170
|
+
text: "Primary",
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
parameters: {
|
|
174
|
+
badges: [BADGES.DEPRECATED],
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
```
|
|
108
178
|
|
|
109
|
-
This
|
|
179
|
+
This groups deprecated stories together and will make it easier to remove them later on.
|
|
@@ -3,6 +3,7 @@ import { AccordionProps } from "../Accordion/Accordion";
|
|
|
3
3
|
import { DraggableListProps, ListItemProps, SortableListProps } from "../List/List.types";
|
|
4
4
|
import { AccordionItemProps } from "../Accordion/AccordionItem";
|
|
5
5
|
import { BaseButtonProps } from "../ButtonV2/ButtonProps.type";
|
|
6
|
+
import { AccordionListActions } from "./subcomponents/AccordionListActions";
|
|
6
7
|
export interface AccordionListProps extends Omit<AccordionProps, "items"> {
|
|
7
8
|
localisations: {
|
|
8
9
|
title: string;
|
|
@@ -10,9 +11,15 @@ export interface AccordionListProps extends Omit<AccordionProps, "items"> {
|
|
|
10
11
|
emptyListText?: string;
|
|
11
12
|
};
|
|
12
13
|
accordionItems: AccordionItem[];
|
|
14
|
+
/**
|
|
15
|
+
* @deprecated
|
|
16
|
+
* Use the `actions` prop to render any button(s)
|
|
17
|
+
* or other component(s) automatically in the correct area.
|
|
18
|
+
*/
|
|
13
19
|
buttonProps?: BaseButtonProps;
|
|
14
20
|
isSearchEnabled?: boolean;
|
|
15
21
|
isLoading?: boolean;
|
|
22
|
+
actions?: React.ReactNode;
|
|
16
23
|
}
|
|
17
24
|
export type AccordionListItemProps<T = ListItemProps> = Omit<AccordionItemProps, "content"> & {
|
|
18
25
|
listItems: T[];
|
|
@@ -28,5 +35,8 @@ export type SortableAccordionListItemProps = Omit<AccordionItemProps, "content">
|
|
|
28
35
|
listItems: SortableListProps["items"];
|
|
29
36
|
};
|
|
30
37
|
export type AccordionItem = AccordionListItemProps | DraggableAccordionListItemProps | SortableAccordionListItemProps;
|
|
31
|
-
|
|
38
|
+
interface StaticComponents {
|
|
39
|
+
Actions: typeof AccordionListActions;
|
|
40
|
+
}
|
|
41
|
+
export declare const AccordionList: React.FC<AccordionListProps> & StaticComponents;
|
|
32
42
|
export default AccordionList;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Use in the actions of an AccordionList. Spaces out the action
|
|
4
|
+
* components correctly in relation to the styling of the AccordionList component.
|
|
5
|
+
*
|
|
6
|
+
* @usage
|
|
7
|
+
* ```tsx
|
|
8
|
+
* <AccordionList
|
|
9
|
+
* actions={
|
|
10
|
+
* <AccordionList.Actions>
|
|
11
|
+
* <PrimaryButton />
|
|
12
|
+
* <SecondaryButton />
|
|
13
|
+
* </AccordionList.Actions>
|
|
14
|
+
* }
|
|
15
|
+
* />
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export declare const AccordionListActions: React.FC<React.PropsWithChildren>;
|
|
@@ -6,7 +6,7 @@ export type CardProps = {
|
|
|
6
6
|
};
|
|
7
7
|
/**
|
|
8
8
|
* Card component that centralizes itself inside a container.
|
|
9
|
-
* Specific variant made with w-135 to suffice the use case needed,
|
|
9
|
+
* Specific variant made with ui-w-135 to suffice the use case needed,
|
|
10
10
|
* more variants can be added.
|
|
11
11
|
*/
|
|
12
12
|
export declare const Card: React.FC<CardProps>;
|
|
@@ -1,19 +1,64 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import "./Checkbox.scss";
|
|
3
3
|
export interface CheckboxProps {
|
|
4
|
+
/**
|
|
5
|
+
* ID used for semantic targeting, as can be used in attributes like `<label htmlFor="some-id">`.
|
|
6
|
+
*/
|
|
4
7
|
id?: string;
|
|
8
|
+
/**
|
|
9
|
+
* The visible text labeling the checkbox element.
|
|
10
|
+
*/
|
|
5
11
|
text?: string;
|
|
12
|
+
/**
|
|
13
|
+
* Helper text that adds some more information on what the option means, or inform
|
|
14
|
+
* the user about the consequences of the checkbox.
|
|
15
|
+
*
|
|
16
|
+
* Only works if the `renderLabel` prop isn't set.
|
|
17
|
+
*/
|
|
6
18
|
explanation?: string;
|
|
19
|
+
/**
|
|
20
|
+
* Shows a different checkbox variant. `type="switch"` shows a switch-like component
|
|
21
|
+
* without a visual label.
|
|
22
|
+
*/
|
|
7
23
|
type?: "regular" | "switch";
|
|
24
|
+
/**
|
|
25
|
+
* Set the value.
|
|
26
|
+
* Same as `checked` on `<input type="checkbox" />`.
|
|
27
|
+
*/
|
|
8
28
|
isChecked?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Value for when it is not clear if the state of this checkbox
|
|
31
|
+
* is "checked" or not (for hierarchical checkboxes).
|
|
32
|
+
*/
|
|
9
33
|
isIndeterminate?: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Disallow the user to change the checkbox value.
|
|
36
|
+
* Same as `disabled` on `<input type="checkbox" />`.
|
|
37
|
+
*/
|
|
10
38
|
isDisabled?: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* The name that the value of the checkbox will be associated with.
|
|
41
|
+
* Same as `name` on `<input type="checkbox" />`.
|
|
42
|
+
*/
|
|
11
43
|
name?: string;
|
|
44
|
+
/**
|
|
45
|
+
* This can be used to retrieve the value it is referring to through onChange.
|
|
46
|
+
*/
|
|
12
47
|
value?: string;
|
|
13
48
|
onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
|
|
14
49
|
className?: string;
|
|
50
|
+
classNameCheckboxLabel?: string;
|
|
51
|
+
/**
|
|
52
|
+
* Visually show that the currently selected value has an issue the user needs to attend to.
|
|
53
|
+
*/
|
|
15
54
|
error?: boolean;
|
|
16
55
|
innerRef?: React.Ref<HTMLInputElement>;
|
|
56
|
+
/**
|
|
57
|
+
* Renders a completely custom label. Can change its contents or
|
|
58
|
+
* appearance based on the props of the checkbox item.
|
|
59
|
+
*
|
|
60
|
+
* Overrides the `text` prop.
|
|
61
|
+
*/
|
|
62
|
+
renderLabel?: (props: CheckboxProps) => JSX.Element | null;
|
|
17
63
|
}
|
|
18
64
|
export declare const Checkbox: React.ForwardRefExoticComponent<CheckboxProps & React.RefAttributes<HTMLInputElement>>;
|
|
19
|
-
export default Checkbox;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { CheckboxGroupProps } from "./CheckboxList.types";
|
|
3
|
-
export declare const CheckboxGroup: ({ title, items, onChange, className,
|
|
3
|
+
export declare const CheckboxGroup: ({ title, items, onChange, className, isCollapsed, collapsible, }: CheckboxGroupProps) => JSX.Element;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { CheckboxListProps } from "./CheckboxList.types";
|
|
3
3
|
export { CheckboxListProps };
|
|
4
|
-
export declare const CheckboxList: ({ groups, onChange, className,
|
|
5
|
-
export default CheckboxList;
|
|
4
|
+
export declare const CheckboxList: ({ groups, onChange, className, }: CheckboxListProps) => JSX.Element;
|
|
@@ -4,34 +4,47 @@ export declare enum CheckboxState {
|
|
|
4
4
|
UNCHECKED = "unchecked"
|
|
5
5
|
}
|
|
6
6
|
export interface CheckboxListProps {
|
|
7
|
+
/**
|
|
8
|
+
* An array of items to render as checkboxes. Each item can be a single item or a group. When the
|
|
9
|
+
* title isn't specified, the group will render as a non-collapsible list. This is the way to
|
|
10
|
+
* render a regular list of checkboxes.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* Single list of checkboxes without visual grouping.
|
|
14
|
+
*
|
|
15
|
+
* ```tsx
|
|
16
|
+
* const groups = [{
|
|
17
|
+
* items: [
|
|
18
|
+
* {
|
|
19
|
+
* id: "1",
|
|
20
|
+
* label: "Item 1",
|
|
21
|
+
* },
|
|
22
|
+
* {
|
|
23
|
+
* id: "2",
|
|
24
|
+
* label: "Item 2",
|
|
25
|
+
* },
|
|
26
|
+
* ],
|
|
27
|
+
* }]
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
7
30
|
groups: CheckboxGroup[];
|
|
8
31
|
onChange: (event: CheckboxChangeEvent) => void;
|
|
9
|
-
hasDividers?: boolean;
|
|
10
32
|
className?: string;
|
|
11
33
|
}
|
|
12
34
|
type WithCollapsible = {
|
|
13
35
|
/**
|
|
14
|
-
* When `false
|
|
36
|
+
* When `false` will prevent the checkbox list from being collapsed (also disabling clicking to expand/collapse)
|
|
15
37
|
* in the component and it will be displayed expanded by default.
|
|
16
38
|
* @default true
|
|
17
39
|
*/
|
|
18
40
|
collapsible?: boolean;
|
|
19
41
|
};
|
|
20
|
-
export type CheckboxGroupProps = {
|
|
21
|
-
title?: string;
|
|
22
|
-
items: CheckboxListItem[];
|
|
42
|
+
export type CheckboxGroupProps = CheckboxGroup & {
|
|
23
43
|
onChange: (event: CheckboxChangeEvent) => void;
|
|
24
|
-
hasDividers?: boolean;
|
|
25
44
|
className?: string;
|
|
26
|
-
isCollapsed?: boolean;
|
|
27
45
|
} & WithCollapsible;
|
|
28
|
-
export interface CheckboxGroupItemProps {
|
|
29
|
-
id: string;
|
|
30
|
-
label: string;
|
|
31
|
-
isChecked?: boolean;
|
|
32
|
-
isDisabled?: boolean;
|
|
46
|
+
export interface CheckboxGroupItemProps extends CheckboxListItem {
|
|
33
47
|
onChange: (event: CheckboxChangeEvent) => void;
|
|
34
|
-
className?: string;
|
|
35
48
|
}
|
|
36
49
|
export interface CheckboxListItem {
|
|
37
50
|
id: string;
|
|
@@ -41,8 +54,17 @@ export interface CheckboxListItem {
|
|
|
41
54
|
className?: string;
|
|
42
55
|
}
|
|
43
56
|
export type CheckboxGroup = {
|
|
57
|
+
/**
|
|
58
|
+
* When the title isn't specified, the group will render as a non-collapsible list.
|
|
59
|
+
*/
|
|
44
60
|
title?: string;
|
|
61
|
+
/**
|
|
62
|
+
* The checkbox items to be shown inside of this group.
|
|
63
|
+
*/
|
|
45
64
|
items: CheckboxListItem[];
|
|
65
|
+
/**
|
|
66
|
+
* Whether the group is initially collapsed or not.
|
|
67
|
+
*/
|
|
46
68
|
isCollapsed?: boolean;
|
|
47
69
|
} & WithCollapsible;
|
|
48
70
|
export interface CheckboxChangeEvent {
|
|
@@ -7,12 +7,12 @@ type FlexContainerBase = {
|
|
|
7
7
|
verticalSpacing?: Spacing;
|
|
8
8
|
horizontalSpacing?: Spacing;
|
|
9
9
|
/**
|
|
10
|
-
* Applies the default padding (`"p-4"`) inside the container.
|
|
10
|
+
* Applies the default padding (`"ui-p-4"`) inside the container.
|
|
11
11
|
*/
|
|
12
12
|
hasPadding?: boolean;
|
|
13
13
|
backgroundColor?: string;
|
|
14
14
|
/**
|
|
15
|
-
* If `true`, will make the flexbox full width and not size
|
|
15
|
+
* If `true`, will make the flexbox full width and not size itui-relative to its content.
|
|
16
16
|
* @default true
|
|
17
17
|
*/
|
|
18
18
|
stretch?: boolean;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { CategorizedFilters, FilterBarLocalization, OnFilterBarFilterChange } from "./FilterBarProps.type";
|
|
3
|
+
type ActiveFiltersProps = {
|
|
4
|
+
filters: CategorizedFilters;
|
|
5
|
+
onRemoveActiveFilter: OnFilterBarFilterChange;
|
|
6
|
+
localization: Pick<FilterBarLocalization, "filtersLabel">;
|
|
7
|
+
};
|
|
8
|
+
export declare const ActiveFilters: React.FC<ActiveFiltersProps>;
|
|
9
|
+
export {};
|
|
@@ -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 {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { CategorizedFilters, FilterGenerator, TransformedSortingOptions } from "./FilterBarProps.type";
|
|
2
|
+
/**
|
|
3
|
+
* Generates the list of filters based on the data (see this as what you'd like to be filtered in your component).
|
|
4
|
+
*
|
|
5
|
+
* @param dataToGenerateFiltersFrom - The data (list of entities) that will be used to create the filters.
|
|
6
|
+
* @param groupers a list of functions used to create the filters dropdown
|
|
7
|
+
* @returns {CategorisedFilters} a list of filters properly grouped.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getFilterGroups<T extends unknown[]>(dataToGenerateFiltersFrom: T, groupers: FilterGenerator<T[number]>[]): CategorizedFilters;
|
|
10
|
+
/**
|
|
11
|
+
*
|
|
12
|
+
* @param filterKey the key of the categorized filter (eg. color, size, brand) - which one of them are you gonna check.
|
|
13
|
+
* @param categorizedFilters the array of categorized filters the FilterBar component needs
|
|
14
|
+
* @param attributeGetter the getter to retrieve the attribute to be filtered on, this allow maximum flexibility on how to process
|
|
15
|
+
* filters on any level of nesting if necessary.
|
|
16
|
+
* @returns a predicate to be used in the filter function
|
|
17
|
+
* @example
|
|
18
|
+
*
|
|
19
|
+
* const sizeFilterPredicate = createFilterPredicate<TShirtFromApi>("size", filtersOptions, (item) => item.meta.size);
|
|
20
|
+
* const filteredBySize = items.filter(sizeFilterPredicate);
|
|
21
|
+
*
|
|
22
|
+
*/
|
|
23
|
+
export declare const createFilterPredicate: <T extends object>(filterKey: string, categorizedFilters: CategorizedFilters, attributeGetter: (item: T) => string) => (item: T) => boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Creates a sorting function to be used on a specific object attribute.
|
|
26
|
+
*
|
|
27
|
+
* @param getter the getter function to retrieve the attribute used in the sorting
|
|
28
|
+
* @param order if ascending or descending
|
|
29
|
+
* @returns the sorting comparer function to be used in Array.sort
|
|
30
|
+
*/
|
|
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: TransformedSortingOptions<T[number]>) => T;
|