@osano/osano-cmp-react-native 0.13.0 → 0.15.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 (145) hide show
  1. package/README.dev.md +237 -12
  2. package/android/build.gradle +1 -1
  3. package/android/src/main/java/com/OsanoCMPSDK/OsanoCMPSDKModule.kt +147 -64
  4. package/android/src/main/java/com/OsanoCMPSDK/OsanoCMPSDKPackage.kt +0 -1
  5. package/ios/OsanoCmpSDK.mm +33 -3
  6. package/ios/OsanoCmpSdk.h +0 -7
  7. package/lib/commonjs/ConsentManager.js +32 -4
  8. package/lib/commonjs/ConsentManager.js.map +1 -1
  9. package/lib/commonjs/components/Button.js +105 -95
  10. package/lib/commonjs/components/Button.js.map +1 -1
  11. package/lib/commonjs/components/Locale.js +5 -3
  12. package/lib/commonjs/components/Locale.js.map +1 -1
  13. package/lib/commonjs/index.js +1 -1
  14. package/lib/commonjs/index.js.map +1 -1
  15. package/lib/commonjs/native/OsanoCmp.js +35 -8
  16. package/lib/commonjs/native/OsanoCmp.js.map +1 -1
  17. package/lib/commonjs/native/OsanoCmpSdkSpec.js +9 -0
  18. package/lib/commonjs/native/OsanoCmpSdkSpec.js.map +1 -0
  19. package/lib/commonjs/services/consent.js +6 -2
  20. package/lib/commonjs/services/consent.js.map +1 -1
  21. package/lib/commonjs/utils/ExpoDetector.js +105 -0
  22. package/lib/commonjs/utils/ExpoDetector.js.map +1 -0
  23. package/lib/commonjs/utils/ExpoGoMemoryStorage.js +61 -0
  24. package/lib/commonjs/utils/ExpoGoMemoryStorage.js.map +1 -0
  25. package/lib/commonjs/views/Dialog/Buttons.js +26 -16
  26. package/lib/commonjs/views/Dialog/Buttons.js.map +1 -1
  27. package/lib/commonjs/views/Dialog/index.js +58 -95
  28. package/lib/commonjs/views/Dialog/index.js.map +1 -1
  29. package/lib/commonjs/views/Drawer/Drawer.ConsentCategories.js +12 -13
  30. package/lib/commonjs/views/Drawer/Drawer.ConsentCategories.js.map +1 -1
  31. package/lib/commonjs/views/Drawer/Drawer.Header.js +2 -2
  32. package/lib/commonjs/views/Drawer/Drawer.Header.js.map +1 -1
  33. package/lib/commonjs/views/Drawer/Drawer.Iab.Disclosures.js +10 -1
  34. package/lib/commonjs/views/Drawer/Drawer.Iab.Disclosures.js.map +1 -1
  35. package/lib/commonjs/views/Drawer/index.js +5 -4
  36. package/lib/commonjs/views/Drawer/index.js.map +1 -1
  37. package/lib/module/ConsentManager.js +32 -4
  38. package/lib/module/ConsentManager.js.map +1 -1
  39. package/lib/module/components/Button.js +99 -88
  40. package/lib/module/components/Button.js.map +1 -1
  41. package/lib/module/components/Locale.js +4 -3
  42. package/lib/module/components/Locale.js.map +1 -1
  43. package/lib/module/index.js +1 -1
  44. package/lib/module/index.js.map +1 -1
  45. package/lib/module/native/OsanoCmp.js +34 -8
  46. package/lib/module/native/OsanoCmp.js.map +1 -1
  47. package/lib/module/native/OsanoCmpSdkSpec.js +3 -0
  48. package/lib/module/native/OsanoCmpSdkSpec.js.map +1 -0
  49. package/lib/module/services/consent.js +7 -3
  50. package/lib/module/services/consent.js.map +1 -1
  51. package/lib/module/utils/ExpoDetector.js +98 -0
  52. package/lib/module/utils/ExpoDetector.js.map +1 -0
  53. package/lib/module/utils/ExpoGoMemoryStorage.js +54 -0
  54. package/lib/module/utils/ExpoGoMemoryStorage.js.map +1 -0
  55. package/lib/module/views/Dialog/Buttons.js +27 -17
  56. package/lib/module/views/Dialog/Buttons.js.map +1 -1
  57. package/lib/module/views/Dialog/index.js +59 -96
  58. package/lib/module/views/Dialog/index.js.map +1 -1
  59. package/lib/module/views/Drawer/Drawer.ConsentCategories.js +10 -12
  60. package/lib/module/views/Drawer/Drawer.ConsentCategories.js.map +1 -1
  61. package/lib/module/views/Drawer/Drawer.Header.js +2 -2
  62. package/lib/module/views/Drawer/Drawer.Header.js.map +1 -1
  63. package/lib/module/views/Drawer/Drawer.Iab.Disclosures.js +10 -1
  64. package/lib/module/views/Drawer/Drawer.Iab.Disclosures.js.map +1 -1
  65. package/lib/module/views/Drawer/index.js +6 -6
  66. package/lib/module/views/Drawer/index.js.map +1 -1
  67. package/lib/typescript/lib/commonjs/ConsentManager.d.ts.map +1 -1
  68. package/lib/typescript/lib/commonjs/components/Button.d.ts +4 -4
  69. package/lib/typescript/lib/commonjs/components/Button.d.ts.map +1 -1
  70. package/lib/typescript/lib/commonjs/components/Locale.d.ts.map +1 -1
  71. package/lib/typescript/lib/commonjs/hooks/useDeviceOrientation.d.ts +1 -1
  72. package/lib/typescript/lib/commonjs/native/OsanoCmp.d.ts.map +1 -1
  73. package/lib/typescript/lib/commonjs/native/OsanoCmpSdkSpec.d.ts +5 -0
  74. package/lib/typescript/lib/commonjs/native/OsanoCmpSdkSpec.d.ts.map +1 -0
  75. package/lib/typescript/lib/commonjs/services/consent.d.ts.map +1 -1
  76. package/lib/typescript/lib/commonjs/utils/ExpoDetector.d.ts +28 -0
  77. package/lib/typescript/lib/commonjs/utils/ExpoDetector.d.ts.map +1 -0
  78. package/lib/typescript/lib/commonjs/utils/ExpoGoMemoryStorage.d.ts +22 -0
  79. package/lib/typescript/lib/commonjs/utils/ExpoGoMemoryStorage.d.ts.map +1 -0
  80. package/lib/typescript/lib/commonjs/views/Dialog/Buttons.d.ts.map +1 -1
  81. package/lib/typescript/lib/commonjs/views/Dialog/index.d.ts.map +1 -1
  82. package/lib/typescript/lib/commonjs/views/Drawer/Drawer.ConsentCategories.d.ts.map +1 -1
  83. package/lib/typescript/lib/commonjs/views/Drawer/Drawer.Iab.Disclosures.d.ts.map +1 -1
  84. package/lib/typescript/lib/commonjs/views/Drawer/index.d.ts.map +1 -1
  85. package/lib/typescript/lib/module/ConsentManager.d.ts.map +1 -1
  86. package/lib/typescript/lib/module/components/Button.d.ts +7 -7
  87. package/lib/typescript/lib/module/components/Button.d.ts.map +1 -1
  88. package/lib/typescript/lib/module/components/Locale.d.ts +4 -1
  89. package/lib/typescript/lib/module/components/Locale.d.ts.map +1 -1
  90. package/lib/typescript/lib/module/hooks/useDeviceOrientation.d.ts +1 -1
  91. package/lib/typescript/lib/module/native/OsanoCmp.d.ts.map +1 -1
  92. package/lib/typescript/lib/module/native/OsanoCmpSdkSpec.d.ts +3 -0
  93. package/lib/typescript/lib/module/native/OsanoCmpSdkSpec.d.ts.map +1 -0
  94. package/lib/typescript/lib/module/services/consent.d.ts.map +1 -1
  95. package/lib/typescript/lib/module/utils/ExpoDetector.d.ts +27 -0
  96. package/lib/typescript/lib/module/utils/ExpoDetector.d.ts.map +1 -0
  97. package/lib/typescript/lib/module/utils/ExpoGoMemoryStorage.d.ts +21 -0
  98. package/lib/typescript/lib/module/utils/ExpoGoMemoryStorage.d.ts.map +1 -0
  99. package/lib/typescript/lib/module/views/Dialog/Buttons.d.ts.map +1 -1
  100. package/lib/typescript/lib/module/views/Dialog/index.d.ts.map +1 -1
  101. package/lib/typescript/lib/module/views/Drawer/Drawer.ConsentCategories.d.ts.map +1 -1
  102. package/lib/typescript/lib/module/views/Drawer/Drawer.Header.d.ts.map +1 -1
  103. package/lib/typescript/lib/module/views/Drawer/Drawer.Iab.Disclosures.d.ts.map +1 -1
  104. package/lib/typescript/lib/module/views/Drawer/index.d.ts.map +1 -1
  105. package/lib/typescript/src/ConsentManager.d.ts.map +1 -1
  106. package/lib/typescript/src/components/Button.d.ts +7 -7
  107. package/lib/typescript/src/components/Button.d.ts.map +1 -1
  108. package/lib/typescript/src/components/Locale.d.ts +2 -1
  109. package/lib/typescript/src/components/Locale.d.ts.map +1 -1
  110. package/lib/typescript/src/native/OsanoCmp.d.ts.map +1 -1
  111. package/lib/typescript/src/native/OsanoCmpSdkSpec.d.ts +17 -0
  112. package/lib/typescript/src/native/OsanoCmpSdkSpec.d.ts.map +1 -0
  113. package/lib/typescript/src/services/consent.d.ts.map +1 -1
  114. package/lib/typescript/src/utils/ExpoDetector.d.ts +29 -0
  115. package/lib/typescript/src/utils/ExpoDetector.d.ts.map +1 -0
  116. package/lib/typescript/src/utils/ExpoGoMemoryStorage.d.ts +21 -0
  117. package/lib/typescript/src/utils/ExpoGoMemoryStorage.d.ts.map +1 -0
  118. package/lib/typescript/src/views/Dialog/Buttons.d.ts +4 -2
  119. package/lib/typescript/src/views/Dialog/Buttons.d.ts.map +1 -1
  120. package/lib/typescript/src/views/Dialog/index.d.ts +1 -1
  121. package/lib/typescript/src/views/Dialog/index.d.ts.map +1 -1
  122. package/lib/typescript/src/views/Drawer/Drawer.ConsentCategories.d.ts.map +1 -1
  123. package/lib/typescript/src/views/Drawer/Drawer.Header.d.ts +1 -1
  124. package/lib/typescript/src/views/Drawer/Drawer.Header.d.ts.map +1 -1
  125. package/lib/typescript/src/views/Drawer/Drawer.Iab.Disclosures.d.ts.map +1 -1
  126. package/lib/typescript/src/views/Drawer/index.d.ts.map +1 -1
  127. package/osano-cmp-sdk.podspec +15 -15
  128. package/package.json +28 -3
  129. package/src/ConsentManager.ts +37 -4
  130. package/src/components/Button.tsx +122 -88
  131. package/src/components/Locale.tsx +28 -28
  132. package/src/constants.ts +2 -2
  133. package/src/index.tsx +1 -1
  134. package/src/native/OsanoCmp.ts +39 -23
  135. package/src/native/OsanoCmpSdkSpec.ts +25 -0
  136. package/src/services/consent.ts +9 -3
  137. package/src/utils/ExpoDetector.ts +114 -0
  138. package/src/utils/ExpoGoMemoryStorage.ts +61 -0
  139. package/src/views/Dialog/Buttons.tsx +33 -23
  140. package/src/views/Dialog/index.tsx +164 -208
  141. package/src/views/Drawer/Drawer.ConsentCategories.tsx +25 -25
  142. package/src/views/Drawer/Drawer.Header.tsx +7 -7
  143. package/src/views/Drawer/Drawer.Iab.Disclosures.tsx +6 -3
  144. package/src/views/Drawer/index.tsx +20 -19
  145. package/android/src/main/AndroidManifestNew.xml +0 -2
@@ -1,45 +1,46 @@
1
- import {
2
- Modal,
3
- StyleSheet,
4
- View,
5
- type StyleProp,
6
- type ViewStyle,
7
- Text,
8
- SafeAreaView,
9
- Dimensions,
10
- type LayoutChangeEvent,
11
- Platform,
12
- type TextStyle,
13
- } from 'react-native';
1
+ import type { ReactElement } from 'react';
14
2
  import React, {
15
3
  useCallback,
16
4
  useContext,
17
5
  useEffect,
18
6
  useMemo,
19
7
  useRef,
20
- useState,
21
8
  } from 'react';
22
- import type { ReactElement } from 'react';
9
+ import {
10
+ Modal,
11
+ Platform,
12
+ SafeAreaView,
13
+ StyleSheet,
14
+ Text,
15
+ useWindowDimensions,
16
+ View,
17
+ type DimensionValue,
18
+ type StyleProp,
19
+ type TextStyle,
20
+ type ViewStyle,
21
+ } from 'react-native';
23
22
  import { acceptAll, close, toggleCategory } from '../../actions';
24
23
  import { saveConsent } from '../../commands';
25
24
  import { getConsent, isDialogOpen } from '../../selectors';
26
25
 
26
+ import { CloseButton } from '../../components/Button';
27
+ import Locale from '../../components/Locale';
28
+ import StoragePolicyLink from '../../components/StoragePolicyLink';
29
+ import Toggle from '../../components/Toggle';
30
+ import { type ConsentCategory } from '../../constants';
27
31
  import { OsanoPrivateContext } from '../../context';
32
+ import Translator from '../../utils/Translator';
28
33
  import Buttons from './Buttons';
29
- import Message from './Message';
30
- import StoragePolicyLink from '../../components/StoragePolicyLink';
31
34
  import FirstLayerUsage from './FirstLayerUsage';
35
+ import Message from './Message';
32
36
  import PreferenceManagementDeepLinks from './PreferenceManagementDeepLinks';
33
- import Toggle from '../../components/Toggle';
34
- import { CloseButton } from '../../components/Button';
35
- import Translator from '../../utils/Translator';
36
- import Locale from '../../components/Locale';
37
- import { type ConsentCategory } from '../../constants';
38
37
 
39
38
  export const Dialog = (): ReactElement<Modal> => {
40
39
  const { cmp, config, dispatch, getState, locale } =
41
40
  useContext(OsanoPrivateContext);
42
- const impliedConsentTimeout = useRef<NodeJS.Timeout | null>(null);
41
+ const impliedConsentTimeout = useRef<ReturnType<typeof setTimeout> | null>(
42
+ null,
43
+ );
43
44
  const state = getState();
44
45
  const { palette } = config || {};
45
46
  const {
@@ -58,13 +59,7 @@ export const Dialog = (): ReactElement<Modal> => {
58
59
  const categories = useTcf
59
60
  ? config.iabCategories
60
61
  : config?.nonEssentialCategories || [];
61
- const [windowWidth, setWindowWidth] = useState(
62
- Dimensions.get('window').width,
63
- );
64
- const handleLayoutChange = useCallback((e: LayoutChangeEvent) => {
65
- const width = e.nativeEvent.layout.width;
66
- setWindowWidth(width);
67
- }, []);
62
+ const { width: windowWidth } = useWindowDimensions();
68
63
 
69
64
  const clearImpliedConsentTimeout = useCallback(() => {
70
65
  if (!impliedConsentTimeout.current) return;
@@ -91,6 +86,7 @@ export const Dialog = (): ReactElement<Modal> => {
91
86
  const dialogOverlay = useMemo(() => {
92
87
  return {
93
88
  backgroundColor: infoDialogOverlayColor,
89
+ width: '100%' as DimensionValue,
94
90
  };
95
91
  }, [infoDialogOverlayColor]);
96
92
  const dialogForeground = useMemo(() => {
@@ -105,10 +101,18 @@ export const Dialog = (): ReactElement<Modal> => {
105
101
  const [hDialogLeft = [], hDialogRight = []]: StyleProp<ViewStyle>[][] =
106
102
  useMemo(
107
103
  () => [
108
- [styles.col, { width: dialogType === 'box' ? 32 : 0 }],
109
- [styles.col, { width: dialogType === 'box' ? 32 : 0 }],
104
+ [
105
+ styles.col,
106
+ { width: dialogType === 'box' ? 32 : 0 },
107
+ displayPosition.indexOf('right') >= 0 ? styles.grow : undefined,
108
+ ],
109
+ [
110
+ styles.col,
111
+ { width: dialogType === 'box' ? 32 : 0 },
112
+ displayPosition.indexOf('left') >= 0 ? styles.grow : undefined,
113
+ ],
110
114
  ],
111
- [dialogType],
115
+ [displayPosition, dialogType],
112
116
  );
113
117
  const [vDialogTop = [], vDialogBottom = []]: StyleProp<ViewStyle>[][] =
114
118
  useMemo(
@@ -118,66 +122,28 @@ export const Dialog = (): ReactElement<Modal> => {
118
122
  {
119
123
  minHeight: dialogType === 'box' ? 32 : 0,
120
124
  },
121
- ],
125
+ displayPosition.indexOf('bottom') >= 0 ? styles.grow : undefined,
126
+ ].filter(Boolean),
122
127
  [
123
128
  styles.row,
124
129
  {
125
130
  minHeight: dialogType === 'box' ? 32 : 0,
126
131
  },
132
+ displayPosition.indexOf('top') >= 0 ? styles.grow : undefined,
127
133
  ],
128
134
  ],
129
- [dialogType],
135
+ [displayPosition, dialogType],
130
136
  );
131
137
  const dialogStyles: StyleProp<ViewStyle>[] = [
132
138
  {
133
- alignItems: 'center',
134
139
  backgroundColor: dialogBackgroundColor,
135
- justifyContent: 'center',
136
- flex: 1,
137
- // flexGrow: 1,
138
- // flexShrink: 1,
140
+ maxWidth: 1024,
141
+ width: '100%',
142
+ borderRadius: dialogType === 'box' ? 8 : 0,
143
+ padding: 28,
139
144
  },
140
145
  ];
141
146
 
142
- dialogStyles.push(
143
- Platform.OS === 'web' && dialogType === 'box'
144
- ? styles.dialogBox
145
- : styles.dialogBar,
146
- );
147
- dialogStyles.push(
148
- windowWidth >= 768 ? (isRTL ? styles.rowReverse : styles.row) : styles.col,
149
- );
150
-
151
- switch (displayPosition) {
152
- case 'bottom':
153
- case 'bottom-left':
154
- case 'bottom-right':
155
- vDialogTop.push(styles.grow);
156
- break;
157
- case 'center':
158
- break;
159
- case 'top':
160
- case 'top-left':
161
- case 'top-right':
162
- vDialogBottom.push(styles.grow);
163
- break;
164
- }
165
-
166
- switch (displayPosition) {
167
- case 'top-left':
168
- case 'bottom-left':
169
- hDialogRight.push(styles.grow);
170
- break;
171
- case 'top':
172
- case 'center':
173
- case 'bottom':
174
- break;
175
- case 'top-right':
176
- case 'bottom-right':
177
- hDialogLeft.push(styles.grow);
178
- break;
179
- }
180
-
181
147
  useEffect(() => {
182
148
  if (!open) {
183
149
  return;
@@ -211,123 +177,98 @@ export const Dialog = (): ReactElement<Modal> => {
211
177
  transparent={true}
212
178
  visible={open}
213
179
  onRequestClose={handleClose}
214
- onLayout={handleLayoutChange}
180
+ presentationStyle="overFullScreen"
181
+ supportedOrientations={['portrait', 'landscape']}
215
182
  >
216
- <SafeAreaView style={[styles.container, dialogOverlay]}>
217
- <View
218
- style={vDialogTop}
219
- onPointerUp={handleClose}
220
- onTouchEnd={handleClose}
221
- onResponderRelease={handleClose}
222
- />
223
- <View style={[styles.row, styles.fullWidth, styles.fitContent]}>
224
- <View
225
- style={hDialogLeft}
226
- onPointerUp={handleClose}
227
- onTouchEnd={handleClose}
228
- onResponderRelease={handleClose}
229
- />
230
- <View style={dialogStyles}>
231
- <View style={styles.dialogContent}>
232
- <View style={[styles.row, styles.fitContent]}>
233
- <Text style={dialogForeground} testID="dialog-message">
234
- <Message />
235
- <Text> </Text>
236
- <StoragePolicyLink
237
- testID="dialog-policy-link-1"
238
- policyLinkText={config?.policyLinkText}
239
- href={config?.storagePolicyHref}
240
- />
241
- {config?.additionalLinks &&
242
- config?.additionalLinks?.length >= 1 ? (
243
- <Text> | </Text>
244
- ) : null}
245
- <StoragePolicyLink
246
- testID="dialog-policy-link-2"
247
- policyLinkText={config?.additionalLinks?.at(0)?.at(0)}
248
- href={config?.additionalLinks?.at(0)?.at(1)}
249
- />
250
- </Text>
251
- </View>
252
- {isFirstLayerUsageRequired ? (
253
- <View
254
- testID="first-layer-usage"
255
- style={[
256
- styles.row,
257
- styles.categories,
258
- isRTL ? styles.hRight : styles.hLeft,
259
- ]}
260
- >
261
- <FirstLayerUsage />
262
- </View>
263
- ) : null}
264
- {useTcf || config?.showManagePreferencesLinkInDialog ? (
265
- <View
266
- testID="preference-management-deep-links"
267
- style={[
268
- styles.row,
269
- styles.categories,
270
- isRTL ? styles.hRight : styles.hLeft,
271
- ]}
272
- >
273
- <PreferenceManagementDeepLinks />
274
- </View>
275
- ) : null}
276
- {(useTcf && !config?.showManagePreferencesButtonInDialog) ||
277
- config?.showFirstLayerCategories ? (
278
- <View
279
- testID="show-first-layer-categories"
280
- style={[
281
- styles.col,
282
- styles.categories,
283
- isRTL ? styles.hRight : styles.hLeft,
284
- ]}
285
- >
286
- {categories.map((category) => (
287
- <Toggle
288
- align="left"
289
- key={category}
290
- onValueChange={handleToggleCategory(category)}
291
- value={getConsent(state, category)}
292
- >
293
- <Text style={dialogForeground}>
294
- <Locale path={`categories.${category}.label`} />
295
- </Text>
296
- </Toggle>
297
- ))}
298
- </View>
299
- ) : null}
183
+ <View style={[styles.modalContainer, dialogOverlay]}>
184
+ <View style={dialogStyles}>
185
+ <View style={styles.dialogContent}>
186
+ <View style={[styles.row, styles.fitContent]}>
187
+ <Text style={dialogForeground} testID="dialog-message">
188
+ <Message />
189
+ <Text> </Text>
190
+ <StoragePolicyLink
191
+ testID="dialog-policy-link-1"
192
+ policyLinkText={config?.policyLinkText}
193
+ href={config?.storagePolicyHref}
194
+ />
195
+ {config?.additionalLinks &&
196
+ config?.additionalLinks?.length >= 1 ? (
197
+ <Text> | </Text>
198
+ ) : null}
199
+ <StoragePolicyLink
200
+ testID="dialog-policy-link-2"
201
+ policyLinkText={config?.additionalLinks?.at(0)?.at(0)}
202
+ href={config?.additionalLinks?.at(0)?.at(1)}
203
+ />
204
+ </Text>
300
205
  </View>
301
- <Buttons
302
- style={[
303
- styles.buttons,
304
- windowWidth >= 768 ? styles.dialogCol : styles.dialogRow,
305
- ]}
306
- />
307
- <CloseButton
308
- testID="close-dialog"
309
- onPress={handleClose}
310
- style={[
311
- styles.close,
312
- isRTL ? styles.closeLeft : styles.closeRight,
313
- ]}
314
- color={dialogForegroundColor}
315
- />
206
+ {isFirstLayerUsageRequired ? (
207
+ <View
208
+ testID="first-layer-usage"
209
+ style={[
210
+ styles.row,
211
+ styles.categories,
212
+ isRTL ? styles.hRight : styles.hLeft,
213
+ ]}
214
+ >
215
+ <FirstLayerUsage />
216
+ </View>
217
+ ) : null}
218
+ {useTcf || config?.showManagePreferencesLinkInDialog ? (
219
+ <View
220
+ testID="preference-management-deep-links"
221
+ style={[
222
+ styles.row,
223
+ styles.categories,
224
+ isRTL ? styles.hRight : styles.hLeft,
225
+ ]}
226
+ >
227
+ <PreferenceManagementDeepLinks />
228
+ </View>
229
+ ) : null}
230
+ {(useTcf && !config?.showManagePreferencesButtonInDialog) ||
231
+ config?.showFirstLayerCategories ? (
232
+ <View
233
+ testID="show-first-layer-categories"
234
+ style={[
235
+ styles.col,
236
+ styles.categories,
237
+ isRTL ? styles.hRight : styles.hLeft,
238
+ ]}
239
+ >
240
+ {categories.map((category) => (
241
+ <Toggle
242
+ align="left"
243
+ key={category}
244
+ onValueChange={handleToggleCategory(category)}
245
+ value={getConsent(state, category)}
246
+ >
247
+ <Text style={dialogForeground}>
248
+ <Locale path={`categories.${category}.label`} />
249
+ </Text>
250
+ </Toggle>
251
+ ))}
252
+ </View>
253
+ ) : null}
316
254
  </View>
317
- <View
318
- style={hDialogRight}
319
- onPointerUp={handleClose}
320
- onTouchEnd={handleClose}
321
- onResponderRelease={handleClose}
255
+ <Buttons
256
+ style={windowWidth >= 768 ? styles.dialogRow : styles.dialogCol}
257
+ buttonStyle={
258
+ windowWidth >= 768 ? styles.buttonRow : styles.buttonCol
259
+ }
260
+ />
261
+ <CloseButton
262
+ testID="close-dialog"
263
+ onPress={handleClose}
264
+ style={[
265
+ styles.close,
266
+ isRTL ? styles.closeLeft : styles.closeRight,
267
+ ]}
268
+ color={dialogForegroundColor}
322
269
  />
323
270
  </View>
324
- <View
325
- style={vDialogBottom}
326
- onPointerUp={handleClose}
327
- onTouchEnd={handleClose}
328
- onResponderRelease={handleClose}
329
- />
330
- </SafeAreaView>
271
+ </View>
331
272
  </Modal>
332
273
  );
333
274
  };
@@ -335,6 +276,14 @@ export const Dialog = (): ReactElement<Modal> => {
335
276
  const styles = StyleSheet.create({
336
277
  container: {
337
278
  flex: 1,
279
+ justifyContent: 'center',
280
+ alignItems: 'center',
281
+ },
282
+ modalContainer: {
283
+ flex: 1,
284
+ justifyContent: 'center',
285
+ alignItems: 'center',
286
+ padding: 20,
338
287
  },
339
288
  close: {
340
289
  margin: 4,
@@ -352,15 +301,20 @@ const styles = StyleSheet.create({
352
301
  justifyContent: 'center',
353
302
  width: '100%',
354
303
  },
355
- dialogContent: {
356
- // flexShrink: 1,
304
+ dialogWrapper: {
305
+ flex: 1,
306
+ alignItems: 'center',
357
307
  justifyContent: 'center',
358
- maxWidth: 1024,
359
308
  },
360
- buttons: {
361
- alignItems: 'stretch',
362
- gap: 8,
363
- justifyContent: 'center',
309
+ dialogContent: {
310
+ marginBottom: 16,
311
+ },
312
+ buttonCol: {
313
+ maxWidth: Number.MAX_SAFE_INTEGER,
314
+ },
315
+ buttonRow: {
316
+ flexGrow: 0,
317
+ width: '100%',
364
318
  },
365
319
  categories: {
366
320
  alignItems: 'flex-start',
@@ -383,26 +337,28 @@ const styles = StyleSheet.create({
383
337
  display: 'flex',
384
338
  gap: 16,
385
339
  flex: 1,
386
- paddingHorizontal: 40,
387
- paddingVertical: 16,
340
+ padding: 28,
388
341
  },
389
342
  dialogBox: {
390
343
  display: 'flex',
391
344
  gap: 16,
392
- flex: 1,
393
345
  alignItems: 'center',
394
346
  justifyContent: 'center',
395
- margin: 'auto',
396
- maxWidth: 320,
347
+ maxWidth: 1024,
348
+ padding: 28,
349
+ borderRadius: 8,
397
350
  },
398
351
  dialogRow: {
399
- flexDirection: 'row',
400
- flexWrap: 'wrap',
401
- width: '100%',
352
+ display: 'flex',
353
+ flexDirection: 'column',
402
354
  },
403
355
  dialogCol: {
356
+ display: 'flex',
404
357
  flexDirection: 'column',
405
- flexWrap: 'wrap',
358
+ alignItems: 'stretch',
359
+ flexWrap: 'nowrap',
360
+ width: '100%',
361
+ paddingVertical: 16,
406
362
  },
407
363
  grow: {
408
364
  flex: 1,
@@ -435,4 +391,4 @@ const styles = StyleSheet.create({
435
391
  },
436
392
  });
437
393
 
438
- export default Dialog;
394
+ export default Dialog;
@@ -1,3 +1,10 @@
1
+ import React, {
2
+ useCallback,
3
+ useContext,
4
+ useEffect,
5
+ useMemo,
6
+ useRef,
7
+ } from 'react';
1
8
  import {
2
9
  ActivityIndicator,
3
10
  FlatList,
@@ -11,51 +18,44 @@ import {
11
18
  View,
12
19
  type ViewStyle,
13
20
  } from 'react-native';
14
- import React, {
15
- useCallback,
16
- useContext,
17
- useEffect,
18
- useMemo,
19
- useRef,
20
- } from 'react';
21
21
  import Translator, { type LocalizedStrings } from '../../utils/Translator';
22
22
 
23
+ import {
24
+ close,
25
+ SHOW_DRAWER,
26
+ showIabDisclosures,
27
+ showIabVendors,
28
+ toggleCategory,
29
+ } from '../../actions';
30
+ import { saveConsent, toggleDisclosure } from '../../commands';
23
31
  import {
24
32
  AcceptAllButton,
25
- Button,
26
33
  RejectAllButton,
34
+ SaveButton,
27
35
  } from '../../components/Button';
28
- import type { Disclosure } from '../../types/store';
29
36
  import { Divider } from '../../components/Divider';
30
- import DrawerHeader from './Drawer.Header';
31
37
  import { ExpansionPanel } from '../../components/ExpansionPanel';
32
38
  import { Link } from '../../components/Link';
33
39
  import Locale from '../../components/Locale';
34
- import { OsanoPrivateContext } from '../../context';
35
40
  import StoragePolicyLink from '../../components/StoragePolicyLink';
36
41
  import Toggle from '../../components/Toggle';
37
- import { purposeMap } from '../../iab/tcf/constants';
38
- import useBoundCallback from '../../hooks/useBoundCallback';
39
- import { usePrevious } from '../../hooks/usePrevious';
40
42
  import {
41
- type ConsentCategory as ConsentCategoryType,
42
43
  ConsentCategory,
44
+ type ConsentCategory as ConsentCategoryType,
43
45
  } from '../../constants';
46
+ import { OsanoPrivateContext } from '../../context';
47
+ import useBoundCallback from '../../hooks/useBoundCallback';
48
+ import { usePrevious } from '../../hooks/usePrevious';
49
+ import { setSpecialFeatureConsent } from '../../iab/tcf/actions';
50
+ import { purposeMap } from '../../iab/tcf/constants';
44
51
  import {
45
52
  getCategoryDisclosures,
46
53
  getStack,
47
54
  isCategoryAccepted,
48
55
  isCategoryDisabled,
49
56
  } from '../../selectors';
50
- import { saveConsent, toggleDisclosure } from '../../commands';
51
- import {
52
- close,
53
- showIabDisclosures,
54
- showIabVendors,
55
- toggleCategory,
56
- } from '../../actions';
57
- import { SHOW_DRAWER } from '../../actions';
58
- import { setSpecialFeatureConsent } from '../../iab/tcf/actions';
57
+ import type { Disclosure } from '../../types/store';
58
+ import DrawerHeader from './Drawer.Header';
59
59
 
60
60
  type ConsentCategoryItem = {
61
61
  type: 'info' | 'category' | 'specialFeature';
@@ -517,7 +517,7 @@ const CategoryListFooter: React.FC = () => {
517
517
 
518
518
  return (
519
519
  <View style={[styles.listItem, styles.listFooter]}>
520
- <Button title="buttons.save" onPress={handleSave} />
520
+ <SaveButton onPress={handleSave} />
521
521
  <View style={styles.poweredBy}>
522
522
  <Link href="https://www.osano.com/?utm_campaign=cmp&utm_source=cmp-dialog&utm_medium=drawer">
523
523
  <Locale path="messaging.poweredBy" />
@@ -1,14 +1,14 @@
1
- import { Defs, LinearGradient, Rect, Stop, Svg } from 'react-native-svg';
1
+ import React, { useCallback, useContext, useMemo } from 'react';
2
2
  import {
3
- type LayoutChangeEvent,
4
3
  Platform,
5
- type StyleProp,
6
4
  StyleSheet,
7
5
  Text,
8
- type TextStyle,
9
6
  View,
7
+ type LayoutChangeEvent,
8
+ type StyleProp,
9
+ type TextStyle,
10
10
  } from 'react-native';
11
- import React, { useCallback, useContext, useMemo } from 'react';
11
+ import { Defs, LinearGradient, Rect, Stop, Svg } from 'react-native-svg';
12
12
 
13
13
  import { BackButton } from '../../components/Button';
14
14
  import Locale from '../../components/Locale';
@@ -52,7 +52,7 @@ export const DrawerHeader: React.FC<DrawerHeaderType> = (props) => {
52
52
  setHeaderHeight(height);
53
53
  onHeaderLayoutChange && onHeaderLayoutChange(e);
54
54
  },
55
- [onHeaderLayoutChange]
55
+ [onHeaderLayoutChange],
56
56
  );
57
57
 
58
58
  return (
@@ -136,4 +136,4 @@ const styles = StyleSheet.create({
136
136
  writingDirection: 'rtl',
137
137
  flexDirection: 'row-reverse',
138
138
  },
139
- });
139
+ });
@@ -164,7 +164,7 @@ const IabDisclosureListHeader: React.FC<{ style: StyleProp<ViewStyle> }> = ({
164
164
  const ListItemRenderer = ({
165
165
  item,
166
166
  }: ListRenderItemInfo<
167
- (IabDisclosureType & { id: number; type: string }) | number
167
+ (IabDisclosureType & { id: number; type: string; key: string }) | number
168
168
  >) => {
169
169
  if (typeof item === 'number') {
170
170
  return (
@@ -174,7 +174,9 @@ const ListItemRenderer = ({
174
174
  );
175
175
  }
176
176
 
177
- return <IabDisclosureItem {...item} />;
177
+ // Extract key from item and pass other props
178
+ const { key, ...itemProps } = item;
179
+ return <IabDisclosureItem key={key} {...itemProps} />;
178
180
  };
179
181
 
180
182
  const termAssign = (
@@ -196,6 +198,7 @@ export const IabDisclosuresDrawer: React.FC = () => {
196
198
  | (IabDisclosureType & {
197
199
  id: number;
198
200
  type: string;
201
+ key: string;
199
202
  })
200
203
  >
201
204
  > | null = useRef(null);
@@ -321,7 +324,7 @@ export const IabDisclosuresDrawer: React.FC = () => {
321
324
  ]);
322
325
 
323
326
  const disclosures: (
324
- | (IabDisclosureType & { id: number; type: string })
327
+ | (IabDisclosureType & { id: number; type: string; key: string })
325
328
  | number
326
329
  )[] = useMemo(() => {
327
330
  return [