@innovaccer/design-system 2.5.0-2 → 2.5.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/.all-contributorsrc +170 -0
- package/.github/workflows/jira.yml +1 -2
- package/.github/workflows/main.yml +1 -6
- package/.github/workflows/test.yml +22 -0
- package/CHANGELOG.md +21 -54
- package/CONTRIBUTING.md +23 -0
- package/README.md +124 -75
- package/core/components/atoms/button/Button.tsx +56 -55
- package/core/components/atoms/button/__tests__/Button.test.tsx +3 -12
- package/core/components/atoms/checkbox/Checkbox.tsx +3 -6
- package/core/components/atoms/collapsible/__stories__/index.story.tsx +2 -2
- package/core/components/atoms/dropdown/DropdownList.tsx +1 -1
- package/core/components/atoms/dropdown/__stories__/Options.tsx +15 -0
- package/core/components/atoms/dropdown/__tests__/Dropdown.test.tsx +202 -1
- package/core/components/atoms/dropdown/__tests__/Option.test.tsx +3 -0
- package/core/components/atoms/message/__stories__/CustomDescription.tsx +25 -0
- package/core/components/atoms/metaList/Meta.tsx +3 -1
- package/core/components/atoms/metaList/__tests__/MetaList.test.tsx +30 -36
- package/core/components/atoms/metricInput/MetricInput.tsx +2 -2
- package/core/components/atoms/outsideClick/__stories__/index.story.tsx +1 -1
- package/core/components/atoms/radio/Radio.tsx +7 -10
- package/core/components/atoms/radio/__tests__/Radio.test.tsx +13 -7
- package/core/components/css-utilities/Align/Align.story.tsx +1 -1
- package/core/components/css-utilities/Background/Background.story.tsx +1 -1
- package/core/components/css-utilities/Border/Border.story.tsx +128 -0
- package/core/components/css-utilities/Display/Display.story.tsx +1 -1
- package/core/components/css-utilities/Flex/Flex.story.tsx +1 -1
- package/core/components/css-utilities/Miscellaneous/Miscellaneous.story.tsx +1 -1
- package/core/components/css-utilities/Overflow/Overflow.story.tsx +1 -1
- package/core/components/css-utilities/Position/Position.story.tsx +1 -1
- package/core/components/css-utilities/Sizing/Sizing.story.tsx +1 -1
- package/core/components/css-utilities/Spacing/Spacing.story.tsx +1 -1
- package/core/components/molecules/chatMessage/__tests__/ChatMessage.test.tsx +20 -46
- package/core/components/molecules/dropzone/__tests__/Dropzone.test.tsx +47 -111
- package/core/components/molecules/dropzone/__tests__/Utilities.test.tsx +13 -13
- package/core/components/molecules/editableChipInput/EditableChipInput.tsx +3 -1
- package/core/components/molecules/editableInput/EditableInput.tsx +5 -3
- package/core/components/molecules/editableInput/__stories__/variants/Uncontrolled.story.tsx +1 -1
- package/core/components/molecules/editableInput/__tests__/EditableInput.test.tsx +1 -3
- package/core/components/molecules/emptyState/_tests_/EmptyState.test.tsx +3 -7
- package/core/components/molecules/fileUploader/FileUploaderItem.tsx +13 -2
- package/core/components/molecules/fileUploader/__stories__/index.story.tsx +156 -21
- package/core/components/molecules/fileUploader/__tests__/FileUploader.test.tsx +21 -80
- package/core/components/molecules/fileUploader/__tests__/FileUploaderList.test.tsx +9 -40
- package/core/components/molecules/fullscreenModal/FullscreenModal.tsx +7 -13
- package/core/components/molecules/fullscreenModal/__stories__/Layering.story.tsx +2 -2
- package/core/components/molecules/modal/Modal.tsx +18 -17
- package/core/components/molecules/modal/ModalBody.tsx +1 -1
- package/core/components/molecules/modal/__stories__/Layering.story.tsx +1 -1
- package/core/components/molecules/modal/__stories__/NoFooter.story.tsx +0 -1
- package/core/components/molecules/modal/__stories__/Scrolling.story.tsx +20 -38
- package/core/components/molecules/modal/__tests__/Modal.test.tsx +1 -1
- package/core/components/molecules/sidesheet/Sidesheet.tsx +16 -17
- package/core/components/organisms/choiceList/ChoiceList.tsx +212 -0
- package/core/components/organisms/choiceList/__stories__/Alignment.story.tsx +32 -0
- package/core/components/organisms/choiceList/__stories__/AllowMultiple.story.tsx +23 -0
- package/core/components/organisms/choiceList/__stories__/Controlled.story.tsx +34 -0
- package/core/components/organisms/choiceList/__stories__/index.story.tsx +18 -0
- package/core/components/organisms/choiceList/__tests__/ChoiceList.test.tsx +155 -0
- package/core/components/organisms/choiceList/__tests__/__snapshots__/ChoiceList.test.tsx.snap +3393 -0
- package/core/components/organisms/choiceList/index.tsx +2 -0
- package/core/components/organisms/datePicker/__tests__/DatePicker.test.tsx +136 -46
- package/core/components/organisms/datePicker/__tests__/__snapshots__/DatePicker.test.tsx.snap +2594 -102
- package/core/components/organisms/dateRangePicker/DateRangePicker.tsx +5 -0
- package/core/components/organisms/dateRangePicker/__tests__/DateRangePicker.test.tsx +49 -410
- package/core/components/organisms/dateRangePicker/__tests__/Utilities.test.tsx +39 -0
- package/core/components/organisms/dateRangePicker/__tests__/__snapshots__/DateRangePicker.test.tsx.snap +45390 -2679
- package/core/components/organisms/dateRangePicker/utilities.tsx +2 -5
- package/core/components/organisms/grid/Cell.tsx +5 -4
- package/core/components/organisms/grid/Grid.tsx +1 -1
- package/core/components/organisms/grid/GridCell.tsx +18 -7
- package/core/components/organisms/grid/GridHead.tsx +1 -1
- package/core/components/organisms/grid/GridRow.tsx +5 -12
- package/core/components/organisms/grid/__tests__/Grid.test.tsx +179 -1
- package/core/components/organisms/grid/__tests__/GridCell.test.tsx +218 -0
- package/core/components/organisms/grid/__tests__/__snapshots__/Grid.test.tsx.snap +1024 -0
- package/core/components/organisms/grid/__tests__/rowUtility.test.tsx +62 -0
- package/core/components/organisms/inlineMessage/InlineMessage.tsx +10 -14
- package/core/components/organisms/inlineMessage/__stories__/InlineMessageWithinTable.story.tsx +9 -12
- package/core/components/organisms/inlineMessage/__stories__/variants/Default.story.tsx +2 -4
- package/core/components/organisms/inlineMessage/__stories__/variants/Error.story.tsx +2 -5
- package/core/components/organisms/inlineMessage/__stories__/variants/Info.story.tsx +2 -5
- package/core/components/organisms/inlineMessage/__stories__/variants/Success.story.tsx +2 -5
- package/core/components/organisms/inlineMessage/__stories__/variants/Warning.story.tsx +2 -5
- package/core/components/organisms/inlineMessage/__tests__/InlineMessage.test.tsx +4 -20
- package/core/components/organisms/navigation/VerticalNavigation.tsx +14 -3
- package/core/components/organisms/navigation/__tests__/Navigation.test.tsx +179 -0
- package/core/components/organisms/navigation/__tests__/__snapshots__/Navigation.test.tsx.snap +530 -0
- package/core/components/organisms/table/DraggableDropdown.tsx +1 -0
- package/core/components/organisms/table/Header.tsx +11 -2
- package/core/components/organisms/table/Table.tsx +2 -2
- package/core/components/organisms/table/__stories__/NestedTableWithNestedCard.story.tsx +4 -1
- package/core/components/organisms/table/__stories__/variants/nestedRows.story.tsx +5 -2
- package/core/components/organisms/table/__tests__/Table.test.tsx +292 -0
- package/core/components/organisms/table/__tests__/__snapshots__/Table.test.tsx.snap +349041 -0
- package/core/components/organisms/timePicker/__tests__/TimePicker.test.tsx +15 -66
- package/core/components/patterns/dateRangePicker/withCustomPopover.story.tsx +47 -36
- package/core/index.tsx +1 -1
- package/core/index.type.tsx +1 -0
- package/core/utils/OverlayManager.tsx +1 -3
- package/core/utils/__tests__/__snapshots__/TS.test.tsx.snap +4 -0
- package/core/utils/types.tsx +3 -4
- package/css/dist/index.css +78 -8
- package/css/dist/index.css.map +1 -1
- package/css/src/components/button.css +8 -4
- package/css/src/components/choiceList.css +25 -0
- package/css/src/components/modal.css +1 -2
- package/css/src/utils/border.css +39 -0
- package/dist/core/components/atoms/popperWrapper/PopperWrapper.d.ts +50 -49
- package/dist/core/components/css-utilities/Border/Border.story.d.ts +13 -0
- package/dist/core/components/organisms/choiceList/ChoiceList.d.ts +33 -0
- package/dist/core/components/organisms/choiceList/index.d.ts +2 -0
- package/dist/core/components/organisms/dateRangePicker/utilities.d.ts +2 -2
- package/dist/core/index.d.ts +1 -0
- package/dist/core/index.type.d.ts +1 -0
- package/dist/index.esm.js +207 -58
- package/dist/index.js +209 -57
- package/dist/index.js.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.br +0 -0
- package/dist/index.umd.js.gz +0 -0
- package/jest.config.js +2 -1
- package/package.json +6 -4
|
@@ -144,21 +144,21 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
144
144
|
|
|
145
145
|
onCloseHandler = (event: KeyboardEvent) => {
|
|
146
146
|
const isTopOverlay = OverlayManager.isTopOverlay(this.modalRef.current);
|
|
147
|
-
closeOnEscapeKeypress(event, isTopOverlay, this.onOutsideClickHandler)
|
|
148
|
-
}
|
|
147
|
+
closeOnEscapeKeypress(event, isTopOverlay, this.onOutsideClickHandler);
|
|
148
|
+
};
|
|
149
149
|
|
|
150
150
|
componentDidMount() {
|
|
151
151
|
if (this.props.closeOnEscape) {
|
|
152
152
|
if (this.state.open) {
|
|
153
153
|
OverlayManager.add(this.modalRef.current);
|
|
154
154
|
}
|
|
155
|
-
document.addEventListener('keydown', this.onCloseHandler)
|
|
155
|
+
document.addEventListener('keydown', this.onCloseHandler);
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
componentWillUnmount() {
|
|
160
160
|
if (this.props.closeOnEscape) {
|
|
161
|
-
document.removeEventListener('keydown', this.onCloseHandler)
|
|
161
|
+
document.removeEventListener('keydown', this.onCloseHandler);
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
164
|
|
|
@@ -178,20 +178,21 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
178
178
|
});
|
|
179
179
|
|
|
180
180
|
if (this.props.closeOnEscape) OverlayManager.add(this.modalRef.current);
|
|
181
|
-
|
|
182
181
|
} else {
|
|
183
|
-
this.setState(
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
182
|
+
this.setState(
|
|
183
|
+
{
|
|
184
|
+
animate: false,
|
|
185
|
+
},
|
|
186
|
+
() => {
|
|
187
|
+
window.setTimeout(() => {
|
|
188
|
+
this.setState({
|
|
189
|
+
open: false,
|
|
190
|
+
});
|
|
191
|
+
}, 120);
|
|
192
|
+
}
|
|
193
|
+
);
|
|
192
194
|
|
|
193
195
|
if (this.props.closeOnEscape) OverlayManager.remove(this.modalRef.current);
|
|
194
|
-
|
|
195
196
|
}
|
|
196
197
|
}
|
|
197
198
|
}
|
|
@@ -251,12 +252,12 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
251
252
|
['Overlay-container--open']: open,
|
|
252
253
|
});
|
|
253
254
|
|
|
254
|
-
const isAPINew =
|
|
255
|
+
const isAPINew = headerOptions || footerOptions || footer || header;
|
|
255
256
|
const bodyClass = classNames({
|
|
256
257
|
['Modal-body']: true,
|
|
257
258
|
['Modal-body--withMargin']: isAPINew ? !!footer : true,
|
|
258
259
|
['Modal-body--withPadding']: isAPINew ? !footer : true,
|
|
259
|
-
})
|
|
260
|
+
});
|
|
260
261
|
|
|
261
262
|
const baseProps = extractBaseProps(this.props);
|
|
262
263
|
const sizeMap: Record<ModalProps['dimension'], Partial<ColumnProps>> = {
|
|
@@ -31,50 +31,36 @@ export const scrolling = () => {
|
|
|
31
31
|
},
|
|
32
32
|
{
|
|
33
33
|
question:
|
|
34
|
-
|
|
34
|
+
'Moving or speaking so slowly that other people could have noticed? Or the opposite - being so fidgety or restless that you have been moving around a lot more than usual',
|
|
35
35
|
options: ['Not at all', 'Several Days', 'More than half the days', 'Nearly every day'],
|
|
36
36
|
},
|
|
37
37
|
{
|
|
38
|
-
question: 'Feeling tired or having little energy?',
|
|
38
|
+
question: 'Feeling tired or having little energy?',
|
|
39
|
+
options: ['Yes', 'No'],
|
|
39
40
|
},
|
|
40
41
|
{
|
|
41
|
-
question:
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
'ICT health',
|
|
45
|
-
'Health-tech',
|
|
46
|
-
'None of these',
|
|
47
|
-
],
|
|
42
|
+
question:
|
|
43
|
+
'Which of the following refers to a programme that aims to enable patients to make better use of information and communication technology for health and health care?',
|
|
44
|
+
options: ['Patient informatics', 'ICT health', 'Health-tech', 'None of these'],
|
|
48
45
|
},
|
|
49
46
|
{
|
|
50
|
-
question:
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
'Loss-framed messages',
|
|
54
|
-
'Neutrally-framed messages',
|
|
55
|
-
'None of these',
|
|
56
|
-
],
|
|
47
|
+
question:
|
|
48
|
+
'The way messages are framed influences people’s intentions and willingness to change their behaviour. Which of the following refers to the type of message framing that gives information about a health behaviour that emphasizes the costs of failing to take action?',
|
|
49
|
+
options: ['Gain-framed messages', 'Loss-framed messages', 'Neutrally-framed messages', 'None of these'],
|
|
57
50
|
},
|
|
58
51
|
{
|
|
59
|
-
question:
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
'health appraisal',
|
|
63
|
-
'health literacy',
|
|
64
|
-
'health promotion',
|
|
65
|
-
],
|
|
52
|
+
question:
|
|
53
|
+
'Which of the following refers to the capacity to access, understand, appraise and apply health information and services, and to make appropriate health decisions to promote and maintain health?',
|
|
54
|
+
options: ['health accessibility', 'health appraisal', 'health literacy', 'health promotion'],
|
|
66
55
|
},
|
|
67
56
|
{
|
|
68
|
-
question:
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
'Manchester',
|
|
72
|
-
'Liverpool',
|
|
73
|
-
'None of these',
|
|
74
|
-
],
|
|
57
|
+
question:
|
|
58
|
+
'Frederich Engels’ book entitled The Condition of the Working Class in England in 1844 provided a detailed description of the appalling living and working conditions and the limited health care of working-class residents in which of the following English cities?',
|
|
59
|
+
options: ['London', 'Manchester', 'Liverpool', 'None of these'],
|
|
75
60
|
},
|
|
76
61
|
{
|
|
77
|
-
question:
|
|
62
|
+
question:
|
|
63
|
+
'Which of the following explanations for health inequalities focus on the individual as the unit of analysis, emphasizing unthinking, reckless or irresponsible behaviour or incautious lifestyle as the moving determinant?',
|
|
78
64
|
options: [
|
|
79
65
|
'Individualist explanations',
|
|
80
66
|
'Natural and social selection',
|
|
@@ -83,13 +69,9 @@ export const scrolling = () => {
|
|
|
83
69
|
],
|
|
84
70
|
},
|
|
85
71
|
{
|
|
86
|
-
question:
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
'Community development approach',
|
|
90
|
-
'Biomedical approach',
|
|
91
|
-
'None of these',
|
|
92
|
-
],
|
|
72
|
+
question:
|
|
73
|
+
'This approach to health promotion is based on the assumption that humans are rational decision-makers, this approach relies heavily upon the provision of information about risks and benefits of certain behaviours.',
|
|
74
|
+
options: ['Behaviour change approach', 'Community development approach', 'Biomedical approach', 'None of these'],
|
|
93
75
|
},
|
|
94
76
|
];
|
|
95
77
|
|
|
@@ -169,7 +169,7 @@ describe('Modal component with props', () => {
|
|
|
169
169
|
});
|
|
170
170
|
|
|
171
171
|
it('renders children without footer props', () => {
|
|
172
|
-
const { getByTestId, queryByTestId } = render(<Modal backdropClose={FunctionValue} open={true} header={header}/>);
|
|
172
|
+
const { getByTestId, queryByTestId } = render(<Modal backdropClose={FunctionValue} open={true} header={header} />);
|
|
173
173
|
expect(getByTestId('DesignSystem-ModalContainer')).toBeInTheDocument();
|
|
174
174
|
expect(getByTestId('DesignSystem-Modal')).toBeInTheDocument();
|
|
175
175
|
expect(queryByTestId('Modal-body--withMargin')).not.toBeInTheDocument();
|
|
@@ -138,27 +138,26 @@ class Sidesheet extends React.Component<SidesheetProps, SidesheetState> {
|
|
|
138
138
|
|
|
139
139
|
onCloseHandler = (event: KeyboardEvent) => {
|
|
140
140
|
const isTopOverlay = OverlayManager.isTopOverlay(this.sidesheetRef.current);
|
|
141
|
-
closeOnEscapeKeypress(event, isTopOverlay, this.onOutsideClickHandler)
|
|
142
|
-
}
|
|
141
|
+
closeOnEscapeKeypress(event, isTopOverlay, this.onOutsideClickHandler);
|
|
142
|
+
};
|
|
143
143
|
|
|
144
144
|
componentDidMount() {
|
|
145
145
|
if (this.props.closeOnEscape) {
|
|
146
146
|
if (this.state.open) {
|
|
147
147
|
OverlayManager.add(this.sidesheetRef.current);
|
|
148
148
|
}
|
|
149
|
-
document.addEventListener('keydown', this.onCloseHandler)
|
|
149
|
+
document.addEventListener('keydown', this.onCloseHandler);
|
|
150
150
|
}
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
componentWillUnmount() {
|
|
154
154
|
if (this.props.closeOnEscape) {
|
|
155
|
-
document.removeEventListener('keydown', this.onCloseHandler)
|
|
155
|
+
document.removeEventListener('keydown', this.onCloseHandler);
|
|
156
156
|
}
|
|
157
157
|
}
|
|
158
158
|
|
|
159
159
|
componentDidUpdate(prevProps: SidesheetProps) {
|
|
160
160
|
if (prevProps.open !== this.props.open) {
|
|
161
|
-
|
|
162
161
|
if (this.props.open) {
|
|
163
162
|
const zIndex = getUpdatedZIndex({
|
|
164
163
|
element: this.element,
|
|
@@ -173,21 +172,21 @@ class Sidesheet extends React.Component<SidesheetProps, SidesheetState> {
|
|
|
173
172
|
});
|
|
174
173
|
|
|
175
174
|
if (this.props.closeOnEscape) OverlayManager.add(this.sidesheetRef.current);
|
|
176
|
-
|
|
177
175
|
} else {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
176
|
+
this.setState(
|
|
177
|
+
{
|
|
178
|
+
animate: false,
|
|
179
|
+
},
|
|
180
|
+
() => {
|
|
181
|
+
window.setTimeout(() => {
|
|
182
|
+
this.setState({
|
|
183
|
+
open: false,
|
|
184
|
+
});
|
|
185
|
+
}, 120);
|
|
186
|
+
}
|
|
187
|
+
);
|
|
188
188
|
|
|
189
189
|
if (this.props.closeOnEscape) OverlayManager.remove(this.sidesheetRef.current);
|
|
190
|
-
|
|
191
190
|
}
|
|
192
191
|
}
|
|
193
192
|
}
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import classNames from 'classnames';
|
|
3
|
+
import { Checkbox, Radio, Label } from '@/index';
|
|
4
|
+
import { BaseProps } from '@/utils/types';
|
|
5
|
+
|
|
6
|
+
export type Alignment = 'horizontal' | 'vertical';
|
|
7
|
+
export type Size = 'regular' | 'tiny';
|
|
8
|
+
type ChangeEvent = React.ChangeEvent<HTMLInputElement>;
|
|
9
|
+
type noop = (ev: ChangeEvent) => void;
|
|
10
|
+
|
|
11
|
+
export interface Choice {
|
|
12
|
+
/**
|
|
13
|
+
* Value of the choice
|
|
14
|
+
*/
|
|
15
|
+
value: string;
|
|
16
|
+
/**
|
|
17
|
+
* Label for the choice
|
|
18
|
+
*/
|
|
19
|
+
label?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Disable choice
|
|
22
|
+
*/
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Additional text
|
|
26
|
+
*/
|
|
27
|
+
helpText?: string;
|
|
28
|
+
/**
|
|
29
|
+
* Adds name to the choice
|
|
30
|
+
*/
|
|
31
|
+
name: string;
|
|
32
|
+
}
|
|
33
|
+
export interface ChoiceListProps extends BaseProps {
|
|
34
|
+
/**
|
|
35
|
+
* Describes title of the `ChoiceList`
|
|
36
|
+
*/
|
|
37
|
+
title?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Describes Collection of choices
|
|
40
|
+
*/
|
|
41
|
+
choices: Choice[];
|
|
42
|
+
/**
|
|
43
|
+
* Alignment in which the coices will be rendered
|
|
44
|
+
* @default "vertical"
|
|
45
|
+
*/
|
|
46
|
+
alignment?: Alignment;
|
|
47
|
+
/**
|
|
48
|
+
* Size of the `ChoiceList`
|
|
49
|
+
* @default "regular"
|
|
50
|
+
*/
|
|
51
|
+
size?: Size;
|
|
52
|
+
/**
|
|
53
|
+
* renders `checkbox` if `true` and renders `radio` if `false` of the `ChoiceList`
|
|
54
|
+
* @default false
|
|
55
|
+
*/
|
|
56
|
+
allowMultiple?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Disable the `ChoiceList`
|
|
59
|
+
* @default false
|
|
60
|
+
*/
|
|
61
|
+
disabled?: boolean;
|
|
62
|
+
/**
|
|
63
|
+
* Collection of selected choices
|
|
64
|
+
*/
|
|
65
|
+
selected?: string[];
|
|
66
|
+
/**
|
|
67
|
+
* Callback when the selected choices change
|
|
68
|
+
*/
|
|
69
|
+
onChange?(event: ChangeEvent, selected: string[]): void;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const renderCheckbox = (
|
|
73
|
+
list: Choice[],
|
|
74
|
+
handleOnChange: noop,
|
|
75
|
+
ChoiceListDisabled: boolean,
|
|
76
|
+
size: Size,
|
|
77
|
+
alignment: Alignment,
|
|
78
|
+
selected: string[]
|
|
79
|
+
) => {
|
|
80
|
+
return list.map((item: Choice, checkboxIndex: number) => {
|
|
81
|
+
const { name, value, helpText, disabled, label } = item;
|
|
82
|
+
return (
|
|
83
|
+
<Checkbox
|
|
84
|
+
key={checkboxIndex}
|
|
85
|
+
label={label}
|
|
86
|
+
onChange={handleOnChange}
|
|
87
|
+
disabled={disabled || ChoiceListDisabled}
|
|
88
|
+
helpText={helpText}
|
|
89
|
+
size={size}
|
|
90
|
+
name={name}
|
|
91
|
+
value={value}
|
|
92
|
+
defaultChecked={selected.length !== 0 && selected.includes(value)}
|
|
93
|
+
className={getCheckboxClassName(alignment, checkboxIndex)}
|
|
94
|
+
/>
|
|
95
|
+
);
|
|
96
|
+
});
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
const renderRadio = (
|
|
100
|
+
list: Choice[],
|
|
101
|
+
handleOnChange: noop,
|
|
102
|
+
ChoiceListDisabled: boolean,
|
|
103
|
+
size: Size,
|
|
104
|
+
alignment: Alignment,
|
|
105
|
+
selected: string[]
|
|
106
|
+
) => {
|
|
107
|
+
return list.map((item: Choice, radioIndex: number) => {
|
|
108
|
+
const { name, value, helpText, disabled, label } = item;
|
|
109
|
+
return (
|
|
110
|
+
<Radio
|
|
111
|
+
key={radioIndex}
|
|
112
|
+
label={label}
|
|
113
|
+
onChange={handleOnChange}
|
|
114
|
+
disabled={disabled || ChoiceListDisabled}
|
|
115
|
+
helpText={helpText}
|
|
116
|
+
size={size}
|
|
117
|
+
name={name}
|
|
118
|
+
value={value}
|
|
119
|
+
defaultChecked={selected.length !== 0 && selected.includes(value)}
|
|
120
|
+
className={getRadioClassName(alignment, radioIndex)}
|
|
121
|
+
/>
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
const getCheckboxClassName = (alignment: Alignment, index: number) => {
|
|
127
|
+
const ChoiceListCheckboxClass = classNames({
|
|
128
|
+
[`ChoiceList-checkbox--${alignment}`]: true,
|
|
129
|
+
['ml-0']: index === 0 && alignment === 'horizontal',
|
|
130
|
+
['mt-0']: index === 0 && alignment === 'vertical',
|
|
131
|
+
});
|
|
132
|
+
return ChoiceListCheckboxClass;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
const getRadioClassName = (alignment: Alignment, index: number) => {
|
|
136
|
+
const ChoiceListRadioClass = classNames({
|
|
137
|
+
[`ChoiceList-radio--${alignment}`]: true,
|
|
138
|
+
['ml-0']: index === 0 && alignment === 'horizontal',
|
|
139
|
+
['mt-0']: index === 0 && alignment === 'vertical',
|
|
140
|
+
});
|
|
141
|
+
return ChoiceListRadioClass;
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
export const ChoiceList = (props: ChoiceListProps) => {
|
|
145
|
+
const {
|
|
146
|
+
title,
|
|
147
|
+
choices,
|
|
148
|
+
alignment = 'vertical',
|
|
149
|
+
allowMultiple = false,
|
|
150
|
+
onChange,
|
|
151
|
+
disabled = false,
|
|
152
|
+
size = 'regular',
|
|
153
|
+
} = props;
|
|
154
|
+
|
|
155
|
+
const { selected = [] } = props;
|
|
156
|
+
let selectedChoiceValue = (selected && selected) || [];
|
|
157
|
+
const ChoiceListClass = classNames({
|
|
158
|
+
['ChoiceList']: true,
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
const ChoiceListVerticalClass = classNames({
|
|
162
|
+
['ChoiceList--alignVertical']: true,
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
const ChoiceHorizontalClass = classNames({
|
|
166
|
+
['ChoiceList--alignHorizontal']: true,
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
const handleOnChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
170
|
+
if (e.target.checked && allowMultiple) {
|
|
171
|
+
if (!selectedChoiceValue.includes(e.target.value)) {
|
|
172
|
+
selectedChoiceValue = [...selectedChoiceValue, e.target.value];
|
|
173
|
+
}
|
|
174
|
+
} else if (!e.target.checked && allowMultiple) {
|
|
175
|
+
selectedChoiceValue = selectedChoiceValue.filter((el) => el !== e.target.value);
|
|
176
|
+
}
|
|
177
|
+
if (!allowMultiple) {
|
|
178
|
+
if (!selectedChoiceValue.includes(e.target.value)) {
|
|
179
|
+
selectedChoiceValue = [];
|
|
180
|
+
selectedChoiceValue = [...selectedChoiceValue, e.target.value];
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
if (onChange) onChange(e, selectedChoiceValue);
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
return (
|
|
187
|
+
<>
|
|
188
|
+
<fieldset className={ChoiceListClass} data-test="DesignSystem-ChoiceList-Wrapper">
|
|
189
|
+
{title && title.trim() && <Label>{title.trim()}</Label>}
|
|
190
|
+
{!!allowMultiple ? (
|
|
191
|
+
<div className={`${alignment === 'horizontal' ? ChoiceHorizontalClass : ChoiceListVerticalClass}`}>
|
|
192
|
+
{renderCheckbox(choices, handleOnChange, disabled, size, alignment, selected)}
|
|
193
|
+
</div>
|
|
194
|
+
) : (
|
|
195
|
+
<div className={`${alignment === 'horizontal' ? ChoiceHorizontalClass : ChoiceListVerticalClass}`}>
|
|
196
|
+
{renderRadio(choices, handleOnChange, disabled, size, alignment, selected)}
|
|
197
|
+
</div>
|
|
198
|
+
)}
|
|
199
|
+
</fieldset>
|
|
200
|
+
</>
|
|
201
|
+
);
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
ChoiceList.displayName = 'ChoiceList';
|
|
205
|
+
ChoiceList.defaultProps = {
|
|
206
|
+
alignment: 'vertical',
|
|
207
|
+
size: 'regular',
|
|
208
|
+
allowMultiple: false,
|
|
209
|
+
disabled: false,
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
export default ChoiceList;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import ChoiceList from '../ChoiceList';
|
|
3
|
+
|
|
4
|
+
export const alignment = () => {
|
|
5
|
+
const label = 'Gender';
|
|
6
|
+
const alignmentHorizontal = 'horizontal';
|
|
7
|
+
const gender = [
|
|
8
|
+
{ label: 'Male', name: 'gender', value: 'Male' },
|
|
9
|
+
{ label: 'Female', name: 'gender', value: 'Female' },
|
|
10
|
+
{ label: 'Other', name: 'gender', value: 'Other' },
|
|
11
|
+
];
|
|
12
|
+
const alignmentVertical = 'vertical';
|
|
13
|
+
const allGender = [
|
|
14
|
+
{ label: 'Male', name: 'allGender', value: 'Male' },
|
|
15
|
+
{ label: 'Female', name: 'allGender', value: 'Female' },
|
|
16
|
+
{ label: 'Other', name: 'allGender', value: 'Other' },
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<>
|
|
21
|
+
<ChoiceList choices={gender} title={label} alignment={alignmentHorizontal} onChange={() => {}} />
|
|
22
|
+
<div className="mt-8">
|
|
23
|
+
<ChoiceList choices={allGender} title={label} alignment={alignmentVertical} onChange={() => {}} />
|
|
24
|
+
</div>
|
|
25
|
+
</>
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
export default {
|
|
30
|
+
title: 'Components/ChoiceList/Alignment',
|
|
31
|
+
component: ChoiceList,
|
|
32
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import ChoiceList from '../ChoiceList';
|
|
3
|
+
|
|
4
|
+
export const allowMultiple = () => {
|
|
5
|
+
const label = 'Days';
|
|
6
|
+
const alignment = 'horizontal';
|
|
7
|
+
const days = [
|
|
8
|
+
{ label: 'Mon', name: 'days', value: 'mon' },
|
|
9
|
+
{ label: 'Tue', name: 'days', value: 'tue' },
|
|
10
|
+
{ label: 'Wed', name: 'days', value: 'wed' },
|
|
11
|
+
{ label: 'Thu', name: 'days', value: 'thu' },
|
|
12
|
+
{ label: 'Fri', name: 'days', value: 'fri' },
|
|
13
|
+
{ label: 'Sat', name: 'days', value: 'sat' },
|
|
14
|
+
{ label: 'Sun', name: 'days', value: 'sun' },
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
return <ChoiceList choices={days} title={label} alignment={alignment} allowMultiple={true} onChange={() => {}} />;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
export default {
|
|
21
|
+
title: 'Components/ChoiceList/Allow Multiple',
|
|
22
|
+
component: ChoiceList,
|
|
23
|
+
};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import ChoiceList from '../ChoiceList';
|
|
3
|
+
|
|
4
|
+
export const Controlled = () => {
|
|
5
|
+
const label = 'Gender';
|
|
6
|
+
const alignmentHorizontal = 'horizontal';
|
|
7
|
+
const days = [
|
|
8
|
+
{ label: 'Mon', name: 'days', value: 'mon' },
|
|
9
|
+
{ label: 'Tue', name: 'days', value: 'tue' },
|
|
10
|
+
{ label: 'Wed', name: 'days', value: 'wed' },
|
|
11
|
+
{ label: 'Thu', name: 'days', value: 'thu' },
|
|
12
|
+
{ label: 'Fri', name: 'days', value: 'fri' },
|
|
13
|
+
{ label: 'Sat', name: 'days', value: 'sat' },
|
|
14
|
+
{ label: 'Sun', name: 'days', value: 'sun' },
|
|
15
|
+
];
|
|
16
|
+
|
|
17
|
+
return (
|
|
18
|
+
<>
|
|
19
|
+
<ChoiceList
|
|
20
|
+
selected={['mon', 'wed', 'sat']}
|
|
21
|
+
choices={days}
|
|
22
|
+
allowMultiple={true}
|
|
23
|
+
title={label}
|
|
24
|
+
alignment={alignmentHorizontal}
|
|
25
|
+
onChange={() => {}}
|
|
26
|
+
/>
|
|
27
|
+
</>
|
|
28
|
+
);
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export default {
|
|
32
|
+
title: 'Components/ChoiceList/Controlled',
|
|
33
|
+
component: ChoiceList,
|
|
34
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import ChoiceList from '../ChoiceList';
|
|
3
|
+
|
|
4
|
+
export const all = () => {
|
|
5
|
+
const label = 'Gender';
|
|
6
|
+
const gender = [
|
|
7
|
+
{ label: 'Male', name: 'gender', value: 'Male' },
|
|
8
|
+
{ label: 'Female', name: 'gender', value: 'Female' },
|
|
9
|
+
{ label: 'Other', name: 'gender', value: 'Other' },
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
return <ChoiceList choices={gender} title={label} onChange={() => {}} />;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default {
|
|
16
|
+
title: 'Components/ChoiceList/All',
|
|
17
|
+
component: ChoiceList,
|
|
18
|
+
};
|