-
Notifications
You must be signed in to change notification settings - Fork 27
/
tabular-modal-page.tsx
145 lines (140 loc) · 4.85 KB
/
tabular-modal-page.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
import React from 'react';
import { MessageDescriptor } from 'react-intl';
import { css } from '@emotion/core';
import { customProperties } from '@commercetools-uikit/design-system';
import Spacings from '@commercetools-uikit/spacings';
import { sharedMessages } from '@commercetools-frontend/i18n';
import ModalPage from '../internals/modal-page';
import ModalPageHeaderTitle from '../internals/modal-page-header-title';
import ModalPageHeaderDefaultControls from '../internals/modal-page-header-default-controls';
import { ContentWrapper } from '../internals/modal-page.styles';
type Label = string | MessageDescriptor;
// [conditional A]
type WithCustomControls = {
customControls?: React.ReactNode;
};
// [conditional B]
type WithoutCustomControls = {
labelSecondaryButton?: Label;
labelPrimaryButton?: Label;
onSecondaryButtonClick?: (event: React.SyntheticEvent) => void;
onPrimaryButtonClick?: (event: React.SyntheticEvent) => void;
};
type CommonProps = {
level?: number;
title: string;
isOpen: boolean;
onClose?: (event: React.SyntheticEvent) => void;
children: React.ReactNode;
zIndex?: number;
baseZIndex?: number;
getParentSelector?: () => HTMLElement;
shouldDelayOnClose?: boolean;
// TopBar Props
topBarCurrentPathLabel?: string;
topBarPreviousPathLabel?: Label;
// Replaces the title/subtitle row with a custom one (for special use cases)
customTitleRow?: React.ReactNode;
// Pass tab components
tabControls: React.ReactNode;
// Header Props
subtitle?: string | React.ReactElement;
isPrimaryButtonDisabled?: boolean;
dataAttributesPrimaryButton?: { [key: string]: string };
dataAttributesSecondaryButton?: { [key: string]: string };
};
type Props = CommonProps & WithCustomControls & WithoutCustomControls;
type PropsWithCustomControls = CommonProps & Required<WithCustomControls>;
type PropsWithoutCustomControls = CommonProps & Required<WithoutCustomControls>;
const defaultProps: Pick<
Props,
'labelPrimaryButton' | 'labelSecondaryButton'
> = {
labelPrimaryButton: sharedMessages.confirm,
labelSecondaryButton: sharedMessages.cancel,
};
// Type-guard validation for the correct props, based on the existence `customControls`
const hasCustomControls = (
props: PropsWithCustomControls | PropsWithoutCustomControls
): props is PropsWithCustomControls =>
'customControls' in props && props.customControls !== undefined;
const getConditionalProps = (props: Props) => {
if ('customControls' in props && props.customControls !== undefined) {
return props as PropsWithCustomControls;
}
return props as PropsWithoutCustomControls;
};
const TabularModalPageHeaderControls = (
props: PropsWithCustomControls | PropsWithoutCustomControls
) => {
if (hasCustomControls(props)) {
return <>{props.customControls}</>;
}
return (
<ModalPageHeaderDefaultControls
labelSecondaryButton={props.labelSecondaryButton}
labelPrimaryButton={props.labelPrimaryButton}
isPrimaryButtonDisabled={props.isPrimaryButtonDisabled}
onSecondaryButtonClick={props.onSecondaryButtonClick}
onPrimaryButtonClick={props.onPrimaryButtonClick}
dataAttributesSecondaryButton={props.dataAttributesSecondaryButton}
dataAttributesPrimaryButton={props.dataAttributesPrimaryButton}
/>
);
};
const TabularModalPage = (props: Props) => (
<ModalPage
level={props.level}
title={props.title}
isOpen={props.isOpen}
zIndex={props.zIndex}
onClose={props.onClose}
baseZIndex={props.baseZIndex}
topBarColor="neutral"
currentPathLabel={props.topBarCurrentPathLabel || props.title}
previousPathLabel={props.topBarPreviousPathLabel}
getParentSelector={props.getParentSelector}
shouldDelayOnClose={props.shouldDelayOnClose}
>
<div
css={css`
background-color: ${customProperties.colorNeutral95};
padding: ${customProperties.spacingM} ${customProperties.spacingM} 0;
border-bottom: 1px ${customProperties.colorNeutral} solid;
`}
>
<Spacings.Stack>
{props.customTitleRow || (
<ModalPageHeaderTitle title={props.title} subtitle={props.subtitle} />
)}
<div
css={css`
display: flex;
align-items: flex-end;
justify-content: space-between;
`}
>
<div
css={css`
margin-top: 8px;
`}
>
{props.tabControls}
</div>
<div
css={css`
margin-bottom: 16px;
`}
>
<TabularModalPageHeaderControls {...getConditionalProps(props)} />
</div>
</div>
</Spacings.Stack>
</div>
<ContentWrapper>{props.children}</ContentWrapper>
</ModalPage>
);
TabularModalPage.displayName = 'TabularModalPage';
TabularModalPage.defaultProps = defaultProps;
TabularModalPage.Intl = sharedMessages;
export default TabularModalPage;