@redacto.io/consent-sdk-react 0.0.2 → 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 (30) hide show
  1. package/.turbo/turbo-build.log +8 -8
  2. package/CHANGELOG.md +11 -0
  3. package/dist/index.d.mts +58 -4
  4. package/dist/index.d.ts +58 -4
  5. package/dist/index.js +3125 -1014
  6. package/dist/index.mjs +3131 -1014
  7. package/package.json +2 -3
  8. package/src/RedactoNoticeConsent/RedactoNoticeConsent.test.tsx +504 -17
  9. package/src/RedactoNoticeConsent/RedactoNoticeConsent.tsx +1286 -269
  10. package/src/RedactoNoticeConsent/api/index.ts +267 -46
  11. package/src/RedactoNoticeConsent/api/types.ts +76 -0
  12. package/src/RedactoNoticeConsent/injectStyles.ts +102 -0
  13. package/src/RedactoNoticeConsent/styles.ts +13 -1
  14. package/src/RedactoNoticeConsent/types.ts +2 -0
  15. package/src/RedactoNoticeConsentInline/RedactoNoticeConsentInline.test.tsx +369 -0
  16. package/src/RedactoNoticeConsentInline/RedactoNoticeConsentInline.tsx +597 -0
  17. package/src/RedactoNoticeConsentInline/api/index.ts +159 -0
  18. package/src/RedactoNoticeConsentInline/api/types.ts +190 -0
  19. package/src/RedactoNoticeConsentInline/assets/redacto-logo.png +0 -0
  20. package/src/RedactoNoticeConsentInline/index.ts +1 -0
  21. package/src/RedactoNoticeConsentInline/injectStyles.ts +40 -0
  22. package/src/RedactoNoticeConsentInline/styles.ts +397 -0
  23. package/src/RedactoNoticeConsentInline/types.ts +45 -0
  24. package/src/RedactoNoticeConsentInline/useMediaQuery.ts +36 -0
  25. package/src/index.ts +1 -0
  26. package/tests/mocks.ts +98 -2
  27. package/tests/setup.ts +15 -0
  28. package/.changeset/README.md +0 -8
  29. package/.changeset/config.json +0 -11
  30. package/.changeset/fifty-candies-drop.md +0 -5
@@ -0,0 +1,397 @@
1
+ export const styles = {
2
+ overlay: {
3
+ position: "fixed",
4
+ top: 0,
5
+ left: 0,
6
+ width: "100%",
7
+ height: "100%",
8
+ backgroundColor: "rgba(0, 0, 0, 0.5)",
9
+ display: "flex",
10
+ alignItems: "center",
11
+ justifyContent: "center",
12
+ zIndex: 999,
13
+ animation: "overlayFadeIn 0.2s cubic-bezier(0.16, 1, 0.3, 1)",
14
+ pointerEvents: "all",
15
+ margin: 0,
16
+ padding: 0,
17
+ boxSizing: "border-box",
18
+ },
19
+
20
+ container: {
21
+ position: "relative",
22
+ width: "100%",
23
+ maxWidth: "700px",
24
+ borderRadius: "8px",
25
+ backgroundColor: "#ffffff",
26
+ boxShadow: "0px 1px 3px rgba(0, 0, 0, 0.1)",
27
+ border: "1px solid #e5e7eb",
28
+ display: "flex",
29
+ flexDirection: "column",
30
+ margin: 0,
31
+ padding: 0,
32
+ boxSizing: "border-box",
33
+ textAlign: "left",
34
+ fontFamily: "inherit",
35
+ },
36
+
37
+ content: {
38
+ margin: "22px",
39
+ display: "flex",
40
+ flexDirection: "column",
41
+ flexGrow: 1,
42
+ overflow: "hidden",
43
+ minHeight: 0,
44
+ boxSizing: "border-box",
45
+ textAlign: "left",
46
+ },
47
+
48
+ topSection: {
49
+ display: "flex",
50
+ justifyContent: "space-between",
51
+ alignItems: "center",
52
+ paddingBottom: "15px",
53
+ borderBottom: "1px solid #e5e7eb",
54
+ boxShadow: "0 1px 2px rgba(0, 0, 0, 0.03)",
55
+ backgroundColor: "#ffffff",
56
+ margin: 0,
57
+ boxSizing: "border-box",
58
+ textAlign: "left",
59
+ },
60
+
61
+ topLeft: {
62
+ display: "flex",
63
+ alignItems: "center",
64
+ gap: "10px",
65
+ margin: 0,
66
+ padding: 0,
67
+ boxSizing: "border-box",
68
+ },
69
+
70
+ logo: {
71
+ height: "32px",
72
+ width: "auto",
73
+ objectFit: "contain",
74
+ margin: 0,
75
+ padding: 0,
76
+ display: "block",
77
+ },
78
+
79
+ title: {
80
+ fontSize: "18px",
81
+ fontWeight: 700,
82
+ lineHeight: "150%",
83
+ letterSpacing: "0.2px",
84
+ verticalAlign: "middle",
85
+ color: "#101828",
86
+ margin: 0,
87
+ padding: 0,
88
+ textAlign: "left",
89
+ },
90
+
91
+ topRight: {
92
+ borderRadius: "8px",
93
+ padding: "3px 9px",
94
+ border: "1px solid #d0d5dd",
95
+ display: "flex",
96
+ alignItems: "center",
97
+ justifyContent: "center",
98
+ fontWeight: 400,
99
+ fontSize: "12px",
100
+ lineHeight: "150%",
101
+ letterSpacing: "0.2px",
102
+ verticalAlign: "middle",
103
+ color: "#344054",
104
+ gap: "5px",
105
+ margin: 0,
106
+ boxSizing: "border-box",
107
+ textAlign: "left",
108
+ cursor: "pointer",
109
+ backgroundColor: "#ffffff",
110
+ },
111
+
112
+ middleSection: {
113
+ margin: "20px 0px",
114
+ display: "flex",
115
+ flexDirection: "column",
116
+ gap: "12px",
117
+ flexGrow: 1,
118
+ overflowY: "auto",
119
+ minHeight: 0,
120
+ paddingRight: "15px",
121
+ boxSizing: "border-box",
122
+ textAlign: "left",
123
+ },
124
+
125
+ privacyText: {
126
+ fontSize: "16px",
127
+ fontWeight: 400,
128
+ lineHeight: "150%",
129
+ letterSpacing: "0.2px",
130
+ color: "#344054",
131
+ margin: 0,
132
+ padding: 0,
133
+ textAlign: "left",
134
+ },
135
+
136
+ link: {
137
+ color: "#4f87ff",
138
+ textDecoration: "none",
139
+ margin: 0,
140
+ padding: 0,
141
+ boxSizing: "border-box",
142
+ },
143
+
144
+ subTitle: {
145
+ fontWeight: 600,
146
+ fontSize: "16px",
147
+ lineHeight: "150%",
148
+ letterSpacing: "0.2px",
149
+ color: "#101828",
150
+ margin: 0,
151
+ padding: 0,
152
+ textAlign: "left",
153
+ },
154
+
155
+ optionsContainer: {
156
+ display: "flex",
157
+ flexDirection: "column",
158
+ gap: "14px",
159
+ margin: 0,
160
+ padding: 0,
161
+ boxSizing: "border-box",
162
+ },
163
+
164
+ optionItem: {
165
+ display: "flex",
166
+ justifyContent: "space-between",
167
+ alignItems: "center",
168
+ margin: 0,
169
+ padding: 0,
170
+ boxSizing: "border-box",
171
+ },
172
+
173
+ optionLeft: {
174
+ display: "flex",
175
+ gap: "12px",
176
+ alignItems: "center",
177
+ cursor: "pointer",
178
+ margin: 0,
179
+ padding: 0,
180
+ boxSizing: "border-box",
181
+ },
182
+
183
+ optionTextContainer: {
184
+ display: "flex",
185
+ flexDirection: "column",
186
+ margin: 0,
187
+ padding: 0,
188
+ boxSizing: "border-box",
189
+ },
190
+
191
+ optionTitle: {
192
+ fontWeight: 500,
193
+ fontSize: "16px",
194
+ lineHeight: "150%",
195
+ letterSpacing: "0.2px",
196
+ color: "#101828",
197
+ margin: 0,
198
+ padding: 0,
199
+ textAlign: "left",
200
+ },
201
+
202
+ optionDescription: {
203
+ fontWeight: 400,
204
+ fontSize: "12px",
205
+ lineHeight: "150%",
206
+ letterSpacing: "0.2px",
207
+ color: "#475467",
208
+ verticalAlign: "middle",
209
+ margin: 0,
210
+ padding: 0,
211
+ textAlign: "left",
212
+ },
213
+
214
+ checkboxLarge: {
215
+ height: "20px",
216
+ width: "20px",
217
+ padding: "4px",
218
+ borderRadius: "5px",
219
+ border: "2px solid #d0d5dd",
220
+ margin: 0,
221
+ boxSizing: "border-box",
222
+ appearance: "none",
223
+ WebkitAppearance: "none",
224
+ MozAppearance: "none",
225
+ cursor: "pointer",
226
+ position: "relative",
227
+ backgroundColor: "transparent",
228
+ },
229
+
230
+ dataElementsContainer: {
231
+ marginLeft: "27px",
232
+ display: "flex",
233
+ flexDirection: "column",
234
+ margin: 0,
235
+ padding: 0,
236
+ boxSizing: "border-box",
237
+ paddingLeft: "22px",
238
+ },
239
+
240
+ dataElementItem: {
241
+ display: "flex",
242
+ alignItems: "center",
243
+ gap: "10px",
244
+ justifyContent: "space-between",
245
+ margin: 0,
246
+ padding: 0,
247
+ boxSizing: "border-box",
248
+ minHeight: "24px",
249
+ },
250
+
251
+ dataElementText: {
252
+ fontWeight: 400,
253
+ fontSize: "14px",
254
+ lineHeight: "150%",
255
+ letterSpacing: "0.2px",
256
+ color: "#344054",
257
+ margin: 0,
258
+ padding: 0,
259
+ textAlign: "left",
260
+ },
261
+
262
+ checkboxSmall: {
263
+ height: "16px",
264
+ width: "16px",
265
+ padding: "4px",
266
+ borderRadius: "5px",
267
+ border: "2px solid #d0d5dd",
268
+ margin: 0,
269
+ boxSizing: "border-box",
270
+ appearance: "none",
271
+ WebkitAppearance: "none",
272
+ MozAppearance: "none",
273
+ cursor: "pointer",
274
+ position: "relative",
275
+ backgroundColor: "transparent",
276
+ },
277
+
278
+ bottomSection: {
279
+ display: "flex",
280
+ justifyContent: "space-between",
281
+ gap: "29px",
282
+ paddingTop: "15px",
283
+ borderTop: "1px solid #e5e7eb",
284
+ boxShadow: "0 -1px 2px rgba(0, 0, 0, 0.03)",
285
+ backgroundColor: "#ffffff",
286
+ margin: 0,
287
+ boxSizing: "border-box",
288
+ },
289
+
290
+ button: {
291
+ width: "100%",
292
+ borderRadius: "8px",
293
+ padding: "9px 45px",
294
+ fontWeight: 400,
295
+ fontSize: "16px",
296
+ lineHeight: "150%",
297
+ letterSpacing: "0.2px",
298
+ cursor: "pointer",
299
+ margin: 0,
300
+ boxSizing: "border-box",
301
+ textAlign: "center",
302
+ },
303
+
304
+ acceptButton: {
305
+ backgroundColor: "#4f87ff",
306
+ border: "none",
307
+ color: "#ffffff",
308
+ },
309
+
310
+ cancelButton: {
311
+ border: "1px solid #d0d5dd",
312
+ backgroundColor: "#ffffff",
313
+ color: "#000000",
314
+ },
315
+
316
+ languageSelectorContainer: {
317
+ position: "relative",
318
+ margin: 0,
319
+ padding: 0,
320
+ boxSizing: "border-box",
321
+ },
322
+
323
+ languageDropdown: {
324
+ position: "absolute",
325
+ top: "100%",
326
+ right: 0,
327
+ backgroundColor: "#ffffff",
328
+ border: "1px solid #d0d5dd",
329
+ borderRadius: "4px",
330
+ boxShadow: "0px 2px 4px rgba(0, 0, 0, 0.1)",
331
+ zIndex: 10,
332
+ width: "max-content",
333
+ marginTop: "4px",
334
+ padding: 0,
335
+ boxSizing: "border-box",
336
+ textAlign: "left",
337
+ },
338
+
339
+ languageItem: {
340
+ padding: "8px 12px",
341
+ cursor: "pointer",
342
+ fontSize: "12px",
343
+ color: "#344054",
344
+ backgroundColor: "#ffffff",
345
+ borderBottom: "1px solid #e5e7eb",
346
+ margin: 0,
347
+ boxSizing: "border-box",
348
+ textAlign: "left",
349
+ },
350
+
351
+ selectedLanguageItem: {
352
+ backgroundColor: "#f3f4f6",
353
+ fontWeight: 600,
354
+ },
355
+
356
+ loadingContainer: {
357
+ display: "flex",
358
+ flexDirection: "column",
359
+ alignItems: "center",
360
+ justifyContent: "center",
361
+ padding: "2rem",
362
+ minHeight: "200px",
363
+ margin: 0,
364
+ boxSizing: "border-box",
365
+ },
366
+
367
+ loadingSpinner: {
368
+ width: "40px",
369
+ height: "40px",
370
+ border: "4px solid #f3f3f3",
371
+ borderTop: "4px solid #3498db",
372
+ borderRadius: "50%",
373
+ animation: "spin 1s linear infinite",
374
+ marginBottom: "1rem",
375
+ boxSizing: "border-box",
376
+ },
377
+ } as const;
378
+
379
+ // Keyframes
380
+ export const keyframes = {
381
+ overlayFadeIn: {
382
+ from: {
383
+ opacity: 0,
384
+ },
385
+ to: {
386
+ opacity: 1,
387
+ },
388
+ },
389
+ spin: {
390
+ "0%": {
391
+ transform: "rotate(0deg)",
392
+ },
393
+ "100%": {
394
+ transform: "rotate(360deg)",
395
+ },
396
+ },
397
+ } as const;
@@ -0,0 +1,45 @@
1
+ import type { Settings } from "./api/types";
2
+
3
+ export type Props = Readonly<{
4
+ org_uuid: string;
5
+ workspace_uuid: string;
6
+ notice_uuid: string;
7
+ accessToken?: string;
8
+ refreshToken?: string;
9
+ baseUrl?: string;
10
+ settings?: Partial<Settings>;
11
+ language?: string;
12
+ onAccept?: () => void;
13
+ onDecline?: () => void;
14
+ onError?: (error: Error) => void;
15
+ onValidationChange?: (isValid: boolean) => void;
16
+ applicationId?: string;
17
+ }>;
18
+
19
+ export type PurposeTranslations = {
20
+ [purposeId: string]: string;
21
+ };
22
+
23
+ export type DataElementTranslations = {
24
+ [elementId: string]: string;
25
+ };
26
+
27
+ export type TranslationObject = {
28
+ notice_text?: string;
29
+ additional_text?: string;
30
+ confirm_button_text?: string;
31
+ decline_button_text?: string;
32
+ purposes?: PurposeTranslations;
33
+ data_elements?: DataElementTranslations;
34
+ purpose_section_heading?: string;
35
+ privacy_policy_prefix_text?: string;
36
+ vendor_list_prefix_text?: string;
37
+ privacy_policy_anchor_text?: string;
38
+ vendors_list_anchor_text?: string;
39
+ [key: string]:
40
+ | string
41
+ | PurposeTranslations
42
+ | DataElementTranslations
43
+ | Record<string, string>
44
+ | undefined;
45
+ };
@@ -0,0 +1,36 @@
1
+ import { useState, useEffect } from "react";
2
+
3
+ export const useMediaQuery = (query: string): boolean => {
4
+ const getMatches = () =>
5
+ typeof window !== "undefined" ? window.matchMedia(query).matches : false;
6
+ const [matches, setMatches] = useState<boolean>(getMatches);
7
+
8
+ useEffect(() => {
9
+ if (typeof window === "undefined") return;
10
+ const media = window.matchMedia(query);
11
+
12
+ // Create event listener
13
+ const listener = (e: MediaQueryListEvent) => {
14
+ setMatches(e.matches);
15
+ };
16
+
17
+ // Add listener (fallback for legacy browsers)
18
+ if (media.addEventListener) {
19
+ media.addEventListener("change", listener);
20
+ } else {
21
+ // @ts-ignore – deprecated fallback
22
+ media.addListener(listener);
23
+ }
24
+
25
+ // Clean up
26
+ return () => {
27
+ if (media.removeEventListener) {
28
+ media.removeEventListener("change", listener);
29
+ } else {
30
+ media.removeListener(listener);
31
+ }
32
+ };
33
+ }, [query]);
34
+
35
+ return matches;
36
+ };
package/src/index.ts CHANGED
@@ -1 +1,2 @@
1
1
  export { default as RedactoNoticeConsent } from "./RedactoNoticeConsent";
2
+ export { default as RedactoNoticeConsentInline } from "./RedactoNoticeConsentInline";
package/tests/mocks.ts CHANGED
@@ -33,6 +33,7 @@ export const mockConsentContent: ConsentContent = {
33
33
  privacy_policy_anchor_text: "Privacy Policy",
34
34
  vendors_list_anchor_text: "Vendors List",
35
35
  purpose_section_heading: "Manage Consent",
36
+ notice_banner_heading: "Privacy Notice",
36
37
  created_at: "2023-01-01T00:00:00Z",
37
38
  updated_at: "2023-01-01T00:00:00Z",
38
39
  deployed_at: "2023-01-01T00:00:00Z",
@@ -47,6 +48,7 @@ export const mockConsentContent: ConsentContent = {
47
48
  confirm_button_text: "Aceptar",
48
49
  decline_button_text: "Rechazar",
49
50
  purpose_section_heading: "Gestionar Consentimiento",
51
+ notice_banner_heading: "Aviso de Privacidad",
50
52
  purposes: {
51
53
  "purpose-1": "Marketing",
52
54
  "purpose-1-description": "Usamos datos para marketing.",
@@ -90,12 +92,106 @@ export const mockConsentContent: ConsentContent = {
90
92
  },
91
93
  } as const;
92
94
 
95
+ export const mockReconsentContent: ConsentContent = {
96
+ ...mockConsentContent,
97
+ detail: {
98
+ ...mockConsentContent.detail,
99
+ reconsent_required: true,
100
+ active_config: {
101
+ ...mockConsentContent.detail.active_config,
102
+ purposes: [
103
+ {
104
+ uuid: "purpose-1",
105
+ name: "Marketing",
106
+ description: "We use data for marketing purposes.",
107
+ industries: "Marketing",
108
+ data_elements: [
109
+ {
110
+ uuid: "element-1",
111
+ name: "Email",
112
+ required: false,
113
+ description: null,
114
+ industries: null,
115
+ enabled: true,
116
+ },
117
+ {
118
+ uuid: "element-2",
119
+ name: "Phone",
120
+ required: true,
121
+ description: null,
122
+ industries: null,
123
+ enabled: true,
124
+ },
125
+ ],
126
+ },
127
+ {
128
+ uuid: "purpose-2",
129
+ name: "Analytics",
130
+ description: "We use data for analytics purposes.",
131
+ industries: "Analytics",
132
+ data_elements: [
133
+ {
134
+ uuid: "element-3",
135
+ name: "Usage Data",
136
+ required: false,
137
+ description: null,
138
+ industries: null,
139
+ enabled: true,
140
+ },
141
+ ],
142
+ },
143
+ ],
144
+ },
145
+ purpose_selections: {
146
+ "purpose-1": {
147
+ selected: true,
148
+ status: "ACTIVE",
149
+ needs_reconsent: false,
150
+ data_elements: {
151
+ "element-1": {
152
+ selected: true,
153
+ enabled: true,
154
+ required: false,
155
+ },
156
+ "element-2": {
157
+ selected: true,
158
+ enabled: true,
159
+ required: true,
160
+ },
161
+ },
162
+ },
163
+ "purpose-2": {
164
+ selected: false,
165
+ status: "EXPIRED",
166
+ needs_reconsent: true,
167
+ data_elements: {
168
+ "element-3": {
169
+ selected: false,
170
+ enabled: true,
171
+ required: false,
172
+ },
173
+ },
174
+ },
175
+ },
176
+ },
177
+ } as const;
178
+
179
+ export const mockMinorConsentContent: ConsentContent = {
180
+ ...mockConsentContent,
181
+ detail: {
182
+ ...mockConsentContent.detail,
183
+ is_minor: true,
184
+ },
185
+ } as const;
186
+
93
187
  export const defaultProps = {
94
188
  noticeId: "notice-123",
189
+ org_uuid: "org-123",
190
+ workspace_uuid: "workspace-123",
191
+ notice_uuid: "notice-123",
95
192
  accessToken: "mock-token",
96
193
  refreshToken: "mock-refresh-token",
97
194
  language: "en",
98
- blockUI: true,
99
195
  onAccept: vi.fn(),
100
196
  onDecline: vi.fn(),
101
197
  onError: vi.fn(),
@@ -111,4 +207,4 @@ export const defaultProps = {
111
207
  },
112
208
  link: "#4f87ff",
113
209
  },
114
- } as const;
210
+ } as const;
package/tests/setup.ts CHANGED
@@ -1 +1,16 @@
1
1
  import "@testing-library/jest-dom";
2
+
3
+ // Mock window.matchMedia
4
+ Object.defineProperty(window, "matchMedia", {
5
+ writable: true,
6
+ value: (query: string) => ({
7
+ matches: false,
8
+ media: query,
9
+ onchange: null,
10
+ addListener: vi.fn(), // deprecated
11
+ removeListener: vi.fn(), // deprecated
12
+ addEventListener: vi.fn(),
13
+ removeEventListener: vi.fn(),
14
+ dispatchEvent: vi.fn(),
15
+ }),
16
+ });
@@ -1,8 +0,0 @@
1
- # Changesets
2
-
3
- Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4
- with multi-package repos, or single-package repos to help you version and publish your code. You can
5
- find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6
-
7
- We have a quick list of common questions to get you started engaging with this project in
8
- [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
@@ -1,11 +0,0 @@
1
- {
2
- "$schema": "https://unpkg.com/@changesets/config@3.1.1/schema.json",
3
- "changelog": "@changesets/cli/changelog",
4
- "commit": false,
5
- "fixed": [],
6
- "linked": [],
7
- "access": "public",
8
- "baseBranch": "main",
9
- "updateInternalDependencies": "patch",
10
- "ignore": []
11
- }
@@ -1,5 +0,0 @@
1
- ---
2
- "@redacto.io/consent-sdk-react": patch
3
- ---
4
-
5
- Added base url as prop