@olea-bps/views 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/Callmanager/index.js +148 -0
  2. package/Callmanager/styles.js +62 -0
  3. package/Canteens/index.js +383 -0
  4. package/Canteens/styles.js +89 -0
  5. package/Dashboard/index.js +176 -0
  6. package/Dashboard/styles.js +16 -0
  7. package/DashboardHtwk/index.js +197 -0
  8. package/DashboardHtwk/styles.js +24 -0
  9. package/Event/index.js +369 -0
  10. package/Event/styles.js +63 -0
  11. package/FeedList/index.js +165 -0
  12. package/FeedList/styles.js +15 -0
  13. package/FeedNews/index.js +243 -0
  14. package/FeedNews/styles.js +32 -0
  15. package/Flexmenu/index.js +185 -0
  16. package/Flexmenu/styles.js +62 -0
  17. package/FlexmenuWebview/index.js +167 -0
  18. package/FlexmenuWebview/styles.js +16 -0
  19. package/Howhy/index.js +151 -0
  20. package/Howhy/styles.js +11 -0
  21. package/Jobs/index.js +217 -0
  22. package/Jobs/styles.js +41 -0
  23. package/MainMenu/index.js +329 -0
  24. package/MainMenu/styles.js +36 -0
  25. package/NewsTabbar/index.js +164 -0
  26. package/NewsTabbar/styles.js +27 -0
  27. package/Opal/index.js +136 -0
  28. package/Opal/styles.js +11 -0
  29. package/PublicTransportTicket/index.js +173 -0
  30. package/PublicTransportTicket/styles.js +17 -0
  31. package/Search/index.js +186 -0
  32. package/Search/styles.js +67 -0
  33. package/SettingsAccessibility/index.js +148 -0
  34. package/SettingsAccessibility/styles.js +13 -0
  35. package/SettingsAppInfo/index.js +86 -0
  36. package/SettingsAppInfo/styles.js +18 -0
  37. package/SettingsCanteens/index.js +249 -0
  38. package/SettingsCanteens/styles.js +33 -0
  39. package/SettingsGeneral/index.js +173 -0
  40. package/SettingsGeneral/styles.js +28 -0
  41. package/SettingsNotifications/index.js +204 -0
  42. package/SettingsNotifications/styles.js +38 -0
  43. package/SettingsUser/index.js +170 -0
  44. package/SettingsUser/styles.js +17 -0
  45. package/TimetableCalendar/index.js +322 -0
  46. package/TimetableCalendar/styles.js +117 -0
  47. package/TimetableList/index.js +397 -0
  48. package/TimetableList/styles.js +55 -0
  49. package/Webviews/index.js +158 -0
  50. package/Webviews/styles.js +11 -0
  51. package/index.js +25 -0
  52. package/package.json +41 -0
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Licensed under the Apache License, Version 2.0 (the "License");
3
+ * you may not use this file except in compliance with the License.
4
+ * You may obtain a copy of the License at
5
+ *
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Unless required by applicable law or agreed to in writing, software
9
+ * distributed under the License is distributed on an "AS IS" BASIS,
10
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ * See the License for the specific language governing permissions and
12
+ * limitations under the License.
13
+ */
14
+
15
+ import React from 'react';
16
+ import {SafeAreaView, View, Image, TouchableOpacity, Linking} from 'react-native';
17
+
18
+ import {List, withTheme} from 'react-native-paper';
19
+ import {withTranslation} from "react-i18next";
20
+
21
+ import * as Application from 'expo-application';
22
+
23
+ import { AppBar as AppbarComponent } from '@olea-bps/components';
24
+ import componentStyles from "./styles";
25
+
26
+ /**
27
+ * Settings app info
28
+ *
29
+ * Parameters:
30
+ * - none
31
+ *
32
+ * Navigation-Parameters:
33
+ * - none
34
+ */
35
+ class AppInfoSettingsView extends React.Component {
36
+ // Styles of this component
37
+ styles;
38
+
39
+ constructor(props) {
40
+ super(props);
41
+
42
+ const {theme} = this.props;
43
+ this.styles = componentStyles(theme);
44
+ }
45
+
46
+ render() {
47
+ const { theme: { themeStyles, appSettings }, t } = this.props;
48
+
49
+ return (
50
+ <SafeAreaView style={[this.styles.container, themeStyles.appSafeAreaContainer]}>
51
+ <AppbarComponent
52
+ {...this.props}
53
+ title={t('settings:version.title')}
54
+ />
55
+ <View style={themeStyles.container}>
56
+ <List.Section>
57
+ <List.Item
58
+ key="version"
59
+ title={t('settings:version.version')}
60
+ description={Application.nativeApplicationVersion ?? t("settings:version.unknown")}
61
+ titleNumberOfLines={2}
62
+ titleStyle={this.styles.listItemTitle}
63
+ descriptionStyle={this.styles.listItemDescription}
64
+ >
65
+ </List.Item>
66
+ </List.Section>
67
+
68
+ {
69
+ appSettings.infoBanner &&
70
+ <TouchableOpacity
71
+ onPress={() => Linking.openURL(appSettings.infoBannerUrl)}
72
+ activeOpacity={0.7}
73
+ >
74
+ <Image
75
+ style={this.styles.infoBanner}
76
+ source={appSettings.infoBanner}
77
+ resizeMode="contain" />
78
+ </TouchableOpacity>
79
+ }
80
+ </View>
81
+ </SafeAreaView>
82
+ );
83
+ }
84
+ }
85
+
86
+ export default (withTranslation()(withTheme(AppInfoSettingsView)))
@@ -0,0 +1,18 @@
1
+ export default function(theme) {
2
+ return {
3
+ selectOption: {
4
+ display: 'flex',
5
+ flexDirection: 'row',
6
+ justifyContent: 'space-between'
7
+ },
8
+ listItemTitle: {
9
+ fontSize: theme.fontSizes.l
10
+ },
11
+ listItemDescription: {
12
+ fontSize: theme.fontSizes.m
13
+ },
14
+ infoBanner: {
15
+ width: '100%'
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,249 @@
1
+ /**
2
+ * Licensed under the Apache License, Version 2.0 (the "License");
3
+ * you may not use this file except in compliance with the License.
4
+ * You may obtain a copy of the License at
5
+ *
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Unless required by applicable law or agreed to in writing, software
9
+ * distributed under the License is distributed on an "AS IS" BASIS,
10
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ * See the License for the specific language governing permissions and
12
+ * limitations under the License.
13
+ */
14
+
15
+ import React, { useState, useMemo } from 'react';
16
+ import { SafeAreaView, View, StyleSheet } from 'react-native';
17
+
18
+ import { connect } from 'react-redux';
19
+ import { useTheme } from 'react-native-paper';
20
+ import { useTranslation } from 'react-i18next';
21
+
22
+ import { onSettingCanteenMerge, store } from '@olea-bps/core';
23
+ import { AppBar as AppbarComponent } from '@olea-bps/components';
24
+ import { SettingsDialogSelect } from '@olea-bps/components';
25
+ import { SettingsDialogRadio } from '@olea-bps/components';
26
+ import { useCanteens, useFavoriteCanteens, usePriceGroupCode } from '@olea-bps/context-canteen';
27
+ import { SettingSection } from '@olea-bps/components';
28
+
29
+ import componentStyles from './styles';
30
+
31
+ /**
32
+ * Renders the Canteens Settings view.
33
+ *
34
+ * @param {Object} props - The component props.
35
+ * @param {Object} props.settings - The settings object.
36
+ * @returns {React.JSX.Element} The rendered component.
37
+ */
38
+ function CanteensSettingsView(props) {
39
+ // Get theme from theme context
40
+ const theme = useTheme();
41
+ // Get translation function from translation hook
42
+ const { t } = useTranslation();
43
+ // Get canteens from canteen context
44
+ const [canteens] = useCanteens();
45
+
46
+ // Extract required datas using destructuring
47
+ const { settings } = props;
48
+ const { appSettings: { mealSelections, groupsOfPersons, mealTypes }, themeStyles } = theme;
49
+
50
+ // Get canteen settings from settings property or use default
51
+ const settingsCanteens = settings?.settingsCanteens;
52
+ const favoriteSelection = Array.isArray(settingsCanteens?.favoriteSelection)
53
+ ? settingsCanteens.favoriteSelection
54
+ : [];
55
+ const [favoriteCanteens, setFavoriteCanteens] = useFavoriteCanteens();
56
+
57
+ // Eingestellter Mensapreis aus dem Mensa-Kontext holen
58
+ const [favoritePrice, setFavoritePrice] = usePriceGroupCode();
59
+
60
+ const activeMealTypes = Array.isArray(settingsCanteens?.favoriteMealTypes) && settingsCanteens?.favoriteMealTypes?.length
61
+ ? settingsCanteens.favoriteMealTypes
62
+ // If no meal type is active, all meal types are active
63
+ // By getting the code auf all avaiables meal types
64
+ : mealTypes?.map?.(mealType => mealType.code) ?? [];
65
+
66
+ // State variables for showing/hiding dialogs
67
+ const [showPriceDialog, setShowPriceDialog] = useState(false);
68
+ const [showSelectionsDialog, setShowSelectionsDialog] = useState(false);
69
+ const [showCanteensDialog, setShowCanteensDialog] = useState(false);
70
+ const [showMealTypesDialog, setShowMealTypesDialog] = useState(false);
71
+
72
+ // Create styles object using useMemo to prevent unnecessary re-renders
73
+ const styles = useMemo(
74
+ () => StyleSheet.create(componentStyles(theme)),
75
+ [theme]
76
+ );
77
+
78
+ // JSX structure and Rendering for the component
79
+ return (
80
+ // SafeAreaView is used to render content within the safe area boundaries of a device.
81
+ <SafeAreaView style={[styles.container, themeStyles.appSafeAreaContainer]}>
82
+ {/* AppbarComponent is a custom component for the app's header bar. */}
83
+ <AppbarComponent {...props} t={t} title={t('settings:canteens.title')} />
84
+
85
+ {/* This View contains the main content of the screen. */}
86
+ <View accessible={false} style={themeStyles.container}>
87
+ {/* List.Section groups related content. */}
88
+ <SettingSection
89
+ title={t('settings:canteens.priceSelection')}
90
+ description={
91
+ favoritePrice
92
+ ? t(
93
+ groupsOfPersons
94
+ .find(personGroup => personGroup.code === favoritePrice)
95
+ .labelKey
96
+ )
97
+ : groupsOfPersons
98
+ .map(personGroup => personGroup.labelKey)
99
+ .map(t)
100
+ .join(', ')
101
+ }
102
+ onPress={() => setShowPriceDialog(true)}
103
+ />
104
+ <SettingsDialogRadio
105
+ title={t('settings:canteens.priceSelection')}
106
+ visible={showPriceDialog}
107
+ selectedOption={favoritePrice}
108
+ options={
109
+ groupsOfPersons
110
+ .map(
111
+ personGroup =>
112
+ ({
113
+ key: personGroup.code,
114
+ label: t(personGroup.labelKey),
115
+ })
116
+ )
117
+ }
118
+ onDismiss={() => setShowPriceDialog(false)}
119
+ onOk={() => setShowPriceDialog(false)}
120
+ onChange={setFavoritePrice}
121
+ />
122
+
123
+ {/* Conditional rendering based on whether mealSelections is an array. */}
124
+ {
125
+ Array.isArray(mealSelections)
126
+ ? <>
127
+ <SettingSection
128
+ title={t('settings:canteens.preferredSelections')}
129
+ description={
130
+ mealSelections
131
+ .filter(selection => favoriteSelection.includes(selection.code))
132
+ .map(selection => selection.labelKey)
133
+ .map(selectionLabelKey => t(selectionLabelKey))
134
+ .join(', ')
135
+ }
136
+ onPress={() => setShowSelectionsDialog(true)}
137
+ />
138
+ <SettingsDialogSelect
139
+ title={t('settings:canteens.preferredSelections')}
140
+ selectedOptions={favoriteSelection}
141
+ visible={showSelectionsDialog}
142
+ options={
143
+ mealSelections.map(
144
+ selection =>
145
+ ({
146
+ key: selection.code,
147
+ label: t(selection.labelKey),
148
+ })
149
+ )
150
+ }
151
+ onDismiss={() => { setShowSelectionsDialog(false) }}
152
+ onOk={() => { setShowSelectionsDialog(false) }}
153
+ onChange={
154
+ selectedOptions =>
155
+ store.dispatch(
156
+ onSettingCanteenMerge(
157
+ 'canteenSettings',
158
+ { favoriteSelection: selectedOptions }
159
+ )
160
+ )
161
+ }
162
+ />
163
+ </>
164
+ : null
165
+ }
166
+
167
+ <SettingSection
168
+ title={t('canteen:favoriteCanteen:title')}
169
+ description={
170
+ Object.entries(canteens)
171
+ .filter(([canteenId, canteenDatas]) => favoriteCanteens.includes(canteenId))
172
+ .map(([canteenId, canteenDatas]) => canteenDatas.title)
173
+ .join(', ')
174
+ }
175
+ onPress={() => setShowCanteensDialog(true)}
176
+ />
177
+ <SettingsDialogSelect
178
+ title={t('canteen:favoriteCanteen:select')}
179
+ selectedOptions={favoriteCanteens}
180
+ visible={showCanteensDialog}
181
+ options={
182
+ Object.entries(canteens).map(
183
+ ([canteenId, canteenDatas]) => ({
184
+ key: canteenId,
185
+ label: canteenDatas.title
186
+ })
187
+ )
188
+ }
189
+ onDismiss={() => setShowCanteensDialog(false)}
190
+ onOk={() => setShowCanteensDialog(false)}
191
+ onChange={setFavoriteCanteens}
192
+ />
193
+
194
+ {
195
+ Array.isArray(mealTypes)
196
+ ? <>
197
+ <SettingSection
198
+ title={t('settings:canteens:activeMealtypes:title')}
199
+ description={
200
+ mealTypes
201
+ .filter(mealType => activeMealTypes.includes(mealType.code))
202
+ .map(mealType => mealType.labelKey)
203
+ .map(mealTypeLabelKey => t(mealTypeLabelKey))
204
+ .join(', ')
205
+ }
206
+ onPress={() => setShowMealTypesDialog(true)}
207
+ />
208
+ <SettingsDialogSelect
209
+ title={t('settings:canteens:activeMealtypes:dialogTitle')}
210
+ selectedOptions={activeMealTypes}
211
+ visible={showMealTypesDialog}
212
+ options={
213
+ mealTypes.map(
214
+ mealType =>
215
+ ({
216
+ key: mealType.code,
217
+ label: t(mealType.labelKey),
218
+ })
219
+ )
220
+ }
221
+ onDismiss={() => setShowMealTypesDialog(false)}
222
+ onOk={() => setShowMealTypesDialog(false)}
223
+ onChange={
224
+ selectedOptions =>
225
+ store.dispatch(
226
+ onSettingCanteenMerge(
227
+ 'canteenSettings',
228
+ { favoriteMealTypes: selectedOptions }
229
+ )
230
+ )
231
+ }
232
+ />
233
+ </>
234
+ : null
235
+ }
236
+ </View>
237
+ </SafeAreaView>
238
+ );
239
+ }
240
+
241
+ // Map the Redux state to component props
242
+ const mapStateToProps = (state) => {
243
+ return {
244
+ settings: state.settingReducer,
245
+ };
246
+ };
247
+
248
+ // Connect the component to Redux store and apply translation and theme
249
+ export default connect(mapStateToProps)(CanteensSettingsView);
@@ -0,0 +1,33 @@
1
+ export default function(theme) {
2
+ return {
3
+ selectOption: {
4
+ display: 'flex',
5
+ flexDirection: 'row',
6
+ justifyContent: 'space-between'
7
+ },
8
+ listItemTitle: {
9
+ fontSize: theme.fontSizes.l
10
+ },
11
+ listItemDescription: {
12
+ fontSize: theme.fontSizes.m,
13
+ color: theme.colors.textLighter
14
+ },
15
+ buttonLabel: {
16
+ fontSize: theme.fontSizes.m,
17
+ color: theme.colors.text,
18
+ },
19
+ dialogTitle: {
20
+ fontSize: theme.fontSizes.l,
21
+ lineHeight: theme.lineHeights.xxl
22
+ },
23
+ dialogContent: {
24
+ fontSize: theme.fontSizes.m,
25
+ color: theme.colors.text,
26
+ },
27
+ listItems: {
28
+ flex: 1,
29
+
30
+ }
31
+
32
+ }
33
+ }
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Licensed under the Apache License, Version 2.0 (the "License");
3
+ * you may not use this file except in compliance with the License.
4
+ * You may obtain a copy of the License at
5
+ *
6
+ * http://www.apache.org/licenses/LICENSE-2.0
7
+ *
8
+ * Unless required by applicable law or agreed to in writing, software
9
+ * distributed under the License is distributed on an "AS IS" BASIS,
10
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
+ * See the License for the specific language governing permissions and
12
+ * limitations under the License.
13
+ */
14
+
15
+ import React from 'react';
16
+ import { SafeAreaView, View, Text } from 'react-native';
17
+
18
+ import { connect } from 'react-redux'
19
+ import { Button, List, Dialog, Portal, RadioButton, withTheme } from 'react-native-paper';
20
+ import { withTranslation } from 'react-i18next';
21
+
22
+ import merge from 'lodash/merge';
23
+
24
+ import { onSettingGeneralOverride, store } from '@olea-bps/core';
25
+ import { AppBar as AppbarComponent } from '@olea-bps/components';
26
+
27
+ import componentStyles from './styles';
28
+
29
+ /**
30
+ * Settings General
31
+ *
32
+ * Parameters:
33
+ * - none
34
+ *
35
+ * Navigation-Parameters:
36
+ * - none
37
+ */
38
+ class GeneralSettingsView extends React.Component {
39
+ // Styles of this component
40
+ styles;
41
+
42
+ constructor(props) {
43
+ super(props);
44
+
45
+ // ------------------------------------------------------------------------
46
+ // PLUGIN FUNCTIONALITY
47
+ // ------------------------------------------------------------------------
48
+
49
+ const { pluginStyles, theme } = this.props;
50
+ this.styles = componentStyles(theme);
51
+
52
+ if (pluginStyles) {
53
+ this.styles = merge(this.styles, pluginStyles);
54
+ }
55
+
56
+ this.state = {
57
+ language: this.props.settings.settingsGeneral.language,
58
+ };
59
+ }
60
+
61
+ /**
62
+ * update the general settings
63
+ *
64
+ * @private
65
+ */
66
+ _updateGeneralSettings = () => {
67
+ const generalSettings = {
68
+ language: this.state.language
69
+ };
70
+ this.setState({ isChangeMessageVisible: false });
71
+ store.dispatch(onSettingGeneralOverride('generalSettings', generalSettings));
72
+ };
73
+
74
+ getLanguageByKey = () => {
75
+ const { theme } = this.props;
76
+ const languageCode = this.state.language;
77
+ const languageObject = theme.appSettings.languages.find((language) => language.code === languageCode);
78
+ return languageObject ? languageObject : theme.appSettings.languages[0];
79
+ };
80
+
81
+ _renderLanguages = () => {
82
+ const { theme, t } = this.props;
83
+ const { colors } = theme;
84
+ const languages = theme.appSettings.languages.map(language =>
85
+ <View key={'lanuage-' + language.code} >
86
+ <RadioButton.Item
87
+ value={language.code}
88
+ color={colors.checkboxChecked}
89
+ label={t(language.labelKey)}
90
+ labelStyle={this.styles.dialogContent}
91
+ uncheckedColor={colors.checkboxUnchecked}
92
+ mode={'android'}
93
+ />
94
+ </View>
95
+ );
96
+
97
+ return (
98
+ <RadioButton.Group
99
+ onValueChange={value => this.setState({ language: value })}
100
+ value={this.state.language}>
101
+ {languages}
102
+ </RadioButton.Group>
103
+ );
104
+ };
105
+
106
+ _showDialog = () => this.setState({ visible: true });
107
+
108
+ _hideDialog = () => this.setState({ visible: false });
109
+
110
+ render() {
111
+ // ------------------------------------------------------------------------
112
+ // PLUGIN FUNCTIONALITY
113
+ // ------------------------------------------------------------------------
114
+ const PluginComponent = this.props.pluginComponent;
115
+ if (PluginComponent) {
116
+ return <PluginComponent />;
117
+ }
118
+ // ------------------------------------------------------------------------
119
+
120
+
121
+ const { theme: { themeStyles, colors }, t } = this.props;
122
+
123
+ return (
124
+ <SafeAreaView style={[this.styles.container, themeStyles.appSafeAreaContainer]}>
125
+ <AppbarComponent {...this.props} title={t('settings:common.title')} />
126
+ <View accessible={false} style={themeStyles.container}>
127
+ <List.Section>
128
+ <List.Item accessible={false} key='language' title={t('settings:common.language')} description={t(this.getLanguageByKey().labelKey)}
129
+ titleStyle={this.styles.listItemTitle} descriptionStyle={this.styles.listItemDescription}
130
+ right={() => <Button accessible={true} labelStyle={this.styles.buttonLabel} onPress={this._showDialog} color={colors.buttonText}>{t('common:changeLabel')}</Button>
131
+ }>
132
+ </List.Item>
133
+ </List.Section>
134
+ <Portal>
135
+ <Dialog visible={this.state.visible}
136
+ onDismiss={this._hideDialog}>
137
+ <Dialog.Title style={this.styles.dialogTitle}>{t('settings:common.language')}</Dialog.Title>
138
+ <Dialog.Content>
139
+ {this._renderLanguages()}
140
+ </Dialog.Content>
141
+ <Dialog.Actions>
142
+ <Button labelStyle={this.styles.dialogContent} onPress={() => { this.setState({ isChangeMessageVisible: true }); this._hideDialog(); }} color={colors.buttonText}>{t('common:okLabel')}</Button>
143
+ </Dialog.Actions>
144
+ </Dialog>
145
+ </Portal>
146
+ <Portal>
147
+ <Dialog visible={this.state.isChangeMessageVisible}
148
+ onDismiss={() => this.setState({ isChangeMessageVisible: false })}>
149
+ <Dialog.Title style={this.styles.dialogTitle}>{t('settings:common.languageChange')}</Dialog.Title>
150
+ <Dialog.Content>
151
+ <Text style={this.styles.dialogContent}>{t('settings:common.languageChangeText')}</Text>
152
+ </Dialog.Content>
153
+ <Dialog.Actions>
154
+ <Button labelStyle={this.styles.dialogContent} onPress={this._updateGeneralSettings} color={colors.buttonText}>{t('settings:common.languageChangeOk')}</Button>
155
+ <Button labelStyle={this.styles.dialogContent} onPress={() => this.setState({ isChangeMessageVisible: false })} color={colors.buttonText}>{t('common:cancelLabel')}</Button>
156
+ </Dialog.Actions>
157
+ </Dialog>
158
+ </Portal>
159
+ </View>
160
+ </SafeAreaView>
161
+ );
162
+ }
163
+ }
164
+
165
+ const mapStateToProps = state => {
166
+ return {
167
+ pluginComponent: state.pluginReducer.settingsGeneral.component,
168
+ pluginStyles: state.pluginReducer.settingsGeneral.styles,
169
+ settings: state.settingReducer
170
+ };
171
+ };
172
+
173
+ export default connect(mapStateToProps, null)(withTranslation()(withTheme(GeneralSettingsView)))
@@ -0,0 +1,28 @@
1
+ export default function(theme) {
2
+ return {
3
+ selectOption: {
4
+ display: 'flex',
5
+ flexDirection: 'row',
6
+ justifyContent: 'space-between'
7
+ },
8
+ listItemTitle: {
9
+ fontSize: theme.fontSizes.l
10
+ },
11
+ listItemDescription: {
12
+ fontSize: theme.fontSizes.m,
13
+ color: theme.colors.textLighter
14
+ },
15
+ buttonLabel: {
16
+ fontSize: theme.fontSizes.m,
17
+ color: theme.colors.text,
18
+ },
19
+ dialogTitle: {
20
+ fontSize: theme.fontSizes.l,
21
+ lineHeight: theme.lineHeights.xxl
22
+ },
23
+ dialogContent: {
24
+ fontSize: theme.fontSizes.m,
25
+ color: theme.colors.text,
26
+ }
27
+ }
28
+ }