@redacto.io/consent-sdk-react 10.0.0-beta.9 → 10.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 (264) hide show
  1. package/NOTICE.md +17 -0
  2. package/README.md +141 -3
  3. package/dist/chunk-FEGTW73Q.mjs +182 -0
  4. package/dist/fonts.d.mts +35 -0
  5. package/dist/fonts.d.ts +35 -0
  6. package/dist/fonts.js +183 -0
  7. package/dist/fonts.mjs +10 -0
  8. package/dist/index.d.mts +12 -1
  9. package/dist/index.d.ts +12 -1
  10. package/dist/index.js +724 -365
  11. package/dist/index.mjs +346 -201
  12. package/dist/montserrat.generated-NBTECYRW.mjs +22 -0
  13. package/dist/privacy-center.d.mts +0 -1
  14. package/dist/privacy-center.d.ts +0 -1
  15. package/dist/privacy-center.js +2 -66
  16. package/dist/privacy-center.mjs +2 -66
  17. package/dist/types-6Aj7faxL.d.mts +57 -0
  18. package/dist/types-6Aj7faxL.d.ts +57 -0
  19. package/package.json +10 -1
  20. package/.turbo/turbo-build.log +0 -22
  21. package/.turbo/turbo-test.log +0 -203
  22. package/.turbo/turbo-verify-pack.log +0 -6
  23. package/CHANGELOG.md +0 -353
  24. package/src/RedactoNoticeAssisted/RedactoNoticeAssisted.test.tsx +0 -934
  25. package/src/RedactoNoticeAssisted/RedactoNoticeAssisted.tsx +0 -2160
  26. package/src/RedactoNoticeAssisted/api/index.ts +0 -275
  27. package/src/RedactoNoticeAssisted/api/types.ts +0 -182
  28. package/src/RedactoNoticeAssisted/assets/redacto-logo.png +0 -0
  29. package/src/RedactoNoticeAssisted/constants.ts +0 -51
  30. package/src/RedactoNoticeAssisted/i18n.ts +0 -1408
  31. package/src/RedactoNoticeAssisted/index.ts +0 -1
  32. package/src/RedactoNoticeAssisted/injectStyles.ts +0 -251
  33. package/src/RedactoNoticeAssisted/styles.ts +0 -730
  34. package/src/RedactoNoticeAssisted/types.ts +0 -26
  35. package/src/RedactoNoticeAssisted/useMediaQuery.ts +0 -36
  36. package/src/RedactoNoticeConsent/RedactoNoticeConsent.test.tsx +0 -1152
  37. package/src/RedactoNoticeConsent/RedactoNoticeConsent.tsx +0 -4308
  38. package/src/RedactoNoticeConsent/api/index.ts +0 -542
  39. package/src/RedactoNoticeConsent/api/sandbox.ts +0 -150
  40. package/src/RedactoNoticeConsent/api/types.ts +0 -515
  41. package/src/RedactoNoticeConsent/assets/redacto-logo.png +0 -0
  42. package/src/RedactoNoticeConsent/components/DigiLockerCallback.tsx +0 -602
  43. package/src/RedactoNoticeConsent/components/index.ts +0 -7
  44. package/src/RedactoNoticeConsent/constants.ts +0 -20
  45. package/src/RedactoNoticeConsent/index.ts +0 -1
  46. package/src/RedactoNoticeConsent/injectStyles.ts +0 -151
  47. package/src/RedactoNoticeConsent/language-codes.ts +0 -95
  48. package/src/RedactoNoticeConsent/services/storage.ts +0 -122
  49. package/src/RedactoNoticeConsent/styles.ts +0 -409
  50. package/src/RedactoNoticeConsent/types.ts +0 -80
  51. package/src/RedactoNoticeConsent/useMediaQuery.ts +0 -36
  52. package/src/RedactoNoticeConsentInline/RedactoNoticeConsentInline.test.tsx +0 -369
  53. package/src/RedactoNoticeConsentInline/RedactoNoticeConsentInline.tsx +0 -687
  54. package/src/RedactoNoticeConsentInline/api/index.ts +0 -106
  55. package/src/RedactoNoticeConsentInline/api/types.ts +0 -183
  56. package/src/RedactoNoticeConsentInline/assets/redacto-logo.png +0 -0
  57. package/src/RedactoNoticeConsentInline/index.ts +0 -1
  58. package/src/RedactoNoticeConsentInline/injectStyles.ts +0 -40
  59. package/src/RedactoNoticeConsentInline/styles.ts +0 -397
  60. package/src/RedactoNoticeConsentInline/types.ts +0 -51
  61. package/src/RedactoNoticeConsentInline/useMediaQuery.ts +0 -36
  62. package/src/RedactoPrivacyCenter/NotificationsPage.tsx +0 -182
  63. package/src/RedactoPrivacyCenter/PrivacyCenterActivityPage.tsx +0 -19
  64. package/src/RedactoPrivacyCenter/PrivacyCenterCaseDetailsPage.tsx +0 -156
  65. package/src/RedactoPrivacyCenter/PrivacyCenterConsentManagerPage.tsx +0 -17
  66. package/src/RedactoPrivacyCenter/PrivacyCenterFormPage.tsx +0 -79
  67. package/src/RedactoPrivacyCenter/PrivacyCenterHomePage.tsx +0 -36
  68. package/src/RedactoPrivacyCenter/PrivacyCenterLayout.tsx +0 -177
  69. package/src/RedactoPrivacyCenter/PrivacyCenterMyReceiptPage.tsx +0 -26
  70. package/src/RedactoPrivacyCenter/RedactoPrivacyCenter.tsx +0 -93
  71. package/src/RedactoPrivacyCenter/api/actions.ts +0 -695
  72. package/src/RedactoPrivacyCenter/api/client.ts +0 -1003
  73. package/src/RedactoPrivacyCenter/api/config.ts +0 -33
  74. package/src/RedactoPrivacyCenter/api/fetcher.ts +0 -275
  75. package/src/RedactoPrivacyCenter/api/orgBranding.ts +0 -16
  76. package/src/RedactoPrivacyCenter/api/upload.ts +0 -93
  77. package/src/RedactoPrivacyCenter/assets/character.svg +0 -31
  78. package/src/RedactoPrivacyCenter/assets/fileAttach.svg +0 -9
  79. package/src/RedactoPrivacyCenter/assets/greenTick.svg +0 -4
  80. package/src/RedactoPrivacyCenter/assets/mail.svg +0 -3
  81. package/src/RedactoPrivacyCenter/assets/poweredByRedacto.svg +0 -9
  82. package/src/RedactoPrivacyCenter/assets/sentImg.svg +0 -9
  83. package/src/RedactoPrivacyCenter/assets/uploadFileIcon.svg +0 -9
  84. package/src/RedactoPrivacyCenter/components/ActivitiesList.tsx +0 -252
  85. package/src/RedactoPrivacyCenter/components/ActivityTimeline.tsx +0 -239
  86. package/src/RedactoPrivacyCenter/components/AppShell/AppShell.tsx +0 -268
  87. package/src/RedactoPrivacyCenter/components/AppShell/MobileNavDrawer.tsx +0 -218
  88. package/src/RedactoPrivacyCenter/components/AppShell/NavItem.tsx +0 -205
  89. package/src/RedactoPrivacyCenter/components/AppShell/PageHeader.tsx +0 -107
  90. package/src/RedactoPrivacyCenter/components/AppShell/SidebarNav.tsx +0 -100
  91. package/src/RedactoPrivacyCenter/components/AppShell/TopAppBar.tsx +0 -339
  92. package/src/RedactoPrivacyCenter/components/AppShell/UserMenu.tsx +0 -245
  93. package/src/RedactoPrivacyCenter/components/AppShell/hooks/useIsTruncated.ts +0 -28
  94. package/src/RedactoPrivacyCenter/components/AppShell/hooks/useKeyboardShortcut.ts +0 -40
  95. package/src/RedactoPrivacyCenter/components/AppShell/hooks/useSidebarState.ts +0 -62
  96. package/src/RedactoPrivacyCenter/components/AppShell/usePrivacyCenterExitAction.ts +0 -36
  97. package/src/RedactoPrivacyCenter/components/CaseDetails/AttachmentCard.tsx +0 -38
  98. package/src/RedactoPrivacyCenter/components/CaseDetails/ChatBubble.tsx +0 -31
  99. package/src/RedactoPrivacyCenter/components/CaseDetails/DocumentRequestCard.tsx +0 -79
  100. package/src/RedactoPrivacyCenter/components/CaseDetails/FinalizedTooltipWrapper.tsx +0 -25
  101. package/src/RedactoPrivacyCenter/components/CaseDetails/MessageComposer.tsx +0 -96
  102. package/src/RedactoPrivacyCenter/components/CaseDetails/MessageItem.tsx +0 -97
  103. package/src/RedactoPrivacyCenter/components/CaseDetails/MessagesTab.tsx +0 -156
  104. package/src/RedactoPrivacyCenter/components/CaseDetails/RequestDetailsTab.tsx +0 -171
  105. package/src/RedactoPrivacyCenter/components/CaseDetails/StatusEvent.tsx +0 -23
  106. package/src/RedactoPrivacyCenter/components/CaseDetails/useFileUpload.ts +0 -116
  107. package/src/RedactoPrivacyCenter/components/CaseDetails/useMessagePolling.ts +0 -43
  108. package/src/RedactoPrivacyCenter/components/CaseDetails/utils.ts +0 -71
  109. package/src/RedactoPrivacyCenter/components/CaseDetailsModal.tsx +0 -469
  110. package/src/RedactoPrivacyCenter/components/CaseHistory.tsx +0 -426
  111. package/src/RedactoPrivacyCenter/components/ConsentManager.tsx +0 -1206
  112. package/src/RedactoPrivacyCenter/components/ConsentManagerCells.tsx +0 -218
  113. package/src/RedactoPrivacyCenter/components/ConsentManagerColumns.tsx +0 -138
  114. package/src/RedactoPrivacyCenter/components/ConsentManagerConstants.ts +0 -7
  115. package/src/RedactoPrivacyCenter/components/ConsentManagerExpandedRow.tsx +0 -179
  116. package/src/RedactoPrivacyCenter/components/ConsentManagerGroupedColumns.tsx +0 -318
  117. package/src/RedactoPrivacyCenter/components/ConsentManagerProductCards.tsx +0 -333
  118. package/src/RedactoPrivacyCenter/components/ConsentManagerPurposeCards.tsx +0 -102
  119. package/src/RedactoPrivacyCenter/components/ConsentManagerTableSkeleton.tsx +0 -159
  120. package/src/RedactoPrivacyCenter/components/DataRequest/CorrectionDataSection.tsx +0 -189
  121. package/src/RedactoPrivacyCenter/components/DataRequest/GrievanceDataSection.tsx +0 -118
  122. package/src/RedactoPrivacyCenter/components/DataRequest/NominationDataSection.tsx +0 -66
  123. package/src/RedactoPrivacyCenter/components/DataRequest/ProductSelectionSection.tsx +0 -222
  124. package/src/RedactoPrivacyCenter/components/DataRequest/PurposeSelectionSection.tsx +0 -331
  125. package/src/RedactoPrivacyCenter/components/Form.tsx +0 -1821
  126. package/src/RedactoPrivacyCenter/components/GrievanceTable.tsx +0 -174
  127. package/src/RedactoPrivacyCenter/components/GrievanceTablePagination.tsx +0 -337
  128. package/src/RedactoPrivacyCenter/components/ModifyConsentModal.tsx +0 -334
  129. package/src/RedactoPrivacyCenter/components/NotificationHub/NotificationBell.tsx +0 -173
  130. package/src/RedactoPrivacyCenter/components/NotificationHub/NotificationCTAButton.tsx +0 -18
  131. package/src/RedactoPrivacyCenter/components/NotificationHub/NotificationDropdown.tsx +0 -54
  132. package/src/RedactoPrivacyCenter/components/NotificationHub/NotificationDropdownItem.tsx +0 -57
  133. package/src/RedactoPrivacyCenter/components/NotificationHub/NotificationIcon.tsx +0 -19
  134. package/src/RedactoPrivacyCenter/components/NotificationHub/NotificationListPanel.tsx +0 -92
  135. package/src/RedactoPrivacyCenter/components/NotificationHub/NotificationRefreshButton.tsx +0 -20
  136. package/src/RedactoPrivacyCenter/components/NotificationHub/NotificationRow.tsx +0 -58
  137. package/src/RedactoPrivacyCenter/components/NotificationHub/StatCard.tsx +0 -10
  138. package/src/RedactoPrivacyCenter/components/NotificationHub/useNotificationActions.ts +0 -112
  139. package/src/RedactoPrivacyCenter/components/NotificationHub/utils.ts +0 -27
  140. package/src/RedactoPrivacyCenter/components/Pagination.tsx +0 -140
  141. package/src/RedactoPrivacyCenter/components/PrivacyCenterEmptyState.tsx +0 -76
  142. package/src/RedactoPrivacyCenter/components/PrivacyCenterSessionExpired.tsx +0 -97
  143. package/src/RedactoPrivacyCenter/components/ReceiptsList.tsx +0 -454
  144. package/src/RedactoPrivacyCenter/components/RequestSubmit.tsx +0 -270
  145. package/src/RedactoPrivacyCenter/components/SelectUser.tsx +0 -95
  146. package/src/RedactoPrivacyCenter/components/SelectUserGate.tsx +0 -195
  147. package/src/RedactoPrivacyCenter/components/SideMenuBarPC/constants.tsx +0 -25
  148. package/src/RedactoPrivacyCenter/components/SideMenuBarPC/types.ts +0 -21
  149. package/src/RedactoPrivacyCenter/components/caseHistoryColumns.tsx +0 -159
  150. package/src/RedactoPrivacyCenter/components/constant.ts +0 -52
  151. package/src/RedactoPrivacyCenter/components/groupHelpers.ts +0 -155
  152. package/src/RedactoPrivacyCenter/components/receiptColumns.tsx +0 -203
  153. package/src/RedactoPrivacyCenter/components/types.ts +0 -123
  154. package/src/RedactoPrivacyCenter/components/utils.tsx +0 -10
  155. package/src/RedactoPrivacyCenter/config/routes.ts +0 -9
  156. package/src/RedactoPrivacyCenter/config/table.ts +0 -25
  157. package/src/RedactoPrivacyCenter/context/AuthContext.tsx +0 -252
  158. package/src/RedactoPrivacyCenter/context/BaseUrlContext.tsx +0 -47
  159. package/src/RedactoPrivacyCenter/context/BrandingContext.tsx +0 -52
  160. package/src/RedactoPrivacyCenter/context/DataAvailabilityContext.session-expired.test.tsx +0 -92
  161. package/src/RedactoPrivacyCenter/context/DataAvailabilityContext.tsx +0 -181
  162. package/src/RedactoPrivacyCenter/context/LocaleContext.tsx +0 -11
  163. package/src/RedactoPrivacyCenter/context/NavigationContext.tsx +0 -96
  164. package/src/RedactoPrivacyCenter/context/OrganizationContext.tsx +0 -30
  165. package/src/RedactoPrivacyCenter/context/PageChromeContext.tsx +0 -80
  166. package/src/RedactoPrivacyCenter/context/ProfileSwitchContext.tsx +0 -15
  167. package/src/RedactoPrivacyCenter/context/types.ts +0 -57
  168. package/src/RedactoPrivacyCenter/lib/api.ts +0 -759
  169. package/src/RedactoPrivacyCenter/lib/consent-manager/utils.tsx +0 -67
  170. package/src/RedactoPrivacyCenter/lib/constants.ts +0 -283
  171. package/src/RedactoPrivacyCenter/lib/i18n.ts +0 -81
  172. package/src/RedactoPrivacyCenter/lib/locales.ts +0 -102
  173. package/src/RedactoPrivacyCenter/lib/queries.ts +0 -141
  174. package/src/RedactoPrivacyCenter/lib/sandbox.ts +0 -104
  175. package/src/RedactoPrivacyCenter/lib/types.ts +0 -896
  176. package/src/RedactoPrivacyCenter/lib/useCurrentLanguage.ts +0 -37
  177. package/src/RedactoPrivacyCenter/lib/utils.refresh-circuit.test.ts +0 -127
  178. package/src/RedactoPrivacyCenter/lib/utils.refresh-storage.test.ts +0 -85
  179. package/src/RedactoPrivacyCenter/lib/utils.session-expired.test.ts +0 -109
  180. package/src/RedactoPrivacyCenter/lib/utils.ts +0 -798
  181. package/src/RedactoPrivacyCenter/locales/as/translation.json +0 -342
  182. package/src/RedactoPrivacyCenter/locales/bn/translation.json +0 -342
  183. package/src/RedactoPrivacyCenter/locales/brx/translation.json +0 -342
  184. package/src/RedactoPrivacyCenter/locales/doi/translation.json +0 -342
  185. package/src/RedactoPrivacyCenter/locales/en/translation.json +0 -357
  186. package/src/RedactoPrivacyCenter/locales/gom/translation.json +0 -342
  187. package/src/RedactoPrivacyCenter/locales/gu/translation.json +0 -342
  188. package/src/RedactoPrivacyCenter/locales/hi/translation.json +0 -345
  189. package/src/RedactoPrivacyCenter/locales/kn/translation.json +0 -342
  190. package/src/RedactoPrivacyCenter/locales/ks/translation.json +0 -342
  191. package/src/RedactoPrivacyCenter/locales/mai/translation.json +0 -342
  192. package/src/RedactoPrivacyCenter/locales/ml/translation.json +0 -342
  193. package/src/RedactoPrivacyCenter/locales/mni-Mtei/translation.json +0 -342
  194. package/src/RedactoPrivacyCenter/locales/mr/translation.json +0 -342
  195. package/src/RedactoPrivacyCenter/locales/ne/translation.json +0 -342
  196. package/src/RedactoPrivacyCenter/locales/or/translation.json +0 -342
  197. package/src/RedactoPrivacyCenter/locales/pa/translation.json +0 -342
  198. package/src/RedactoPrivacyCenter/locales/sa/translation.json +0 -342
  199. package/src/RedactoPrivacyCenter/locales/sat/translation.json +0 -342
  200. package/src/RedactoPrivacyCenter/locales/sd/translation.json +0 -342
  201. package/src/RedactoPrivacyCenter/locales/ta/translation.json +0 -342
  202. package/src/RedactoPrivacyCenter/locales/te/translation.json +0 -342
  203. package/src/RedactoPrivacyCenter/locales/ur/translation.json +0 -342
  204. package/src/RedactoPrivacyCenter/styles/applyBrandingTheme.ts +0 -66
  205. package/src/RedactoPrivacyCenter/styles/base.css +0 -117
  206. package/src/RedactoPrivacyCenter/styles/injectStyles.ts +0 -3108
  207. package/src/RedactoPrivacyCenter/styles/pcStyles.ts +0 -831
  208. package/src/RedactoPrivacyCenter/styles/responsive.ts +0 -138
  209. package/src/RedactoPrivacyCenter/styles/variables.css +0 -96
  210. package/src/RedactoPrivacyCenter/table/AdvancedTable.tsx +0 -387
  211. package/src/RedactoPrivacyCenter/table/AdvancedTablePagination.tsx +0 -468
  212. package/src/RedactoPrivacyCenter/table/index.ts +0 -2
  213. package/src/RedactoPrivacyCenter/types/images.d.ts +0 -29
  214. package/src/RedactoPrivacyCenter/ui/Footer.tsx +0 -69
  215. package/src/RedactoPrivacyCenter/ui/FormBlockWrapper.tsx +0 -54
  216. package/src/RedactoPrivacyCenter/ui/PCAccordion.tsx +0 -93
  217. package/src/RedactoPrivacyCenter/ui/PCActionIcon.tsx +0 -47
  218. package/src/RedactoPrivacyCenter/ui/PCAvatar.test.tsx +0 -83
  219. package/src/RedactoPrivacyCenter/ui/PCAvatar.tsx +0 -93
  220. package/src/RedactoPrivacyCenter/ui/PCBadge.tsx +0 -48
  221. package/src/RedactoPrivacyCenter/ui/PCButton.tsx +0 -77
  222. package/src/RedactoPrivacyCenter/ui/PCCheckbox.tsx +0 -55
  223. package/src/RedactoPrivacyCenter/ui/PCCollapse.tsx +0 -107
  224. package/src/RedactoPrivacyCenter/ui/PCEmpty.tsx +0 -35
  225. package/src/RedactoPrivacyCenter/ui/PCInput.tsx +0 -132
  226. package/src/RedactoPrivacyCenter/ui/PCLoader.tsx +0 -31
  227. package/src/RedactoPrivacyCenter/ui/PCModal.tsx +0 -106
  228. package/src/RedactoPrivacyCenter/ui/PCPopover.tsx +0 -206
  229. package/src/RedactoPrivacyCenter/ui/PCSelect.tsx +0 -433
  230. package/src/RedactoPrivacyCenter/ui/PCTable.tsx +0 -149
  231. package/src/RedactoPrivacyCenter/ui/PCText.tsx +0 -41
  232. package/src/RedactoPrivacyCenter/ui/PCTextarea.tsx +0 -43
  233. package/src/RedactoPrivacyCenter/ui/PCTitle.tsx +0 -37
  234. package/src/RedactoPrivacyCenter/ui/PCTooltip.tsx +0 -121
  235. package/src/RedactoPrivacyCenter/ui/SimpleBar.tsx +0 -25
  236. package/src/RedactoPrivacyCenter/ui/StatusBadge.tsx +0 -53
  237. package/src/RedactoPrivacyCenter/ui/index.ts +0 -18
  238. package/src/RedactoPrivacyCenter/utils/cn.ts +0 -28
  239. package/src/RedactoPrivacyCenter/utils/date.ts +0 -48
  240. package/src/RedactoPrivacyCenter/utils/status.ts +0 -111
  241. package/src/RedactoPrivacyCenter/utils/toast.ts +0 -130
  242. package/src/index.ts +0 -19
  243. package/src/privacy-center.ts +0 -113
  244. package/src/shared/api-errors.ts +0 -180
  245. package/src/shared/notice-consent-status.ts +0 -190
  246. package/src/shared/sandbox.ts +0 -6
  247. package/src/types/css.d.ts +0 -4
  248. package/src/types/images.d.ts +0 -19
  249. package/src/types/react-jsx.d.ts +0 -26
  250. package/tests/DataAvailabilityContext.test.tsx +0 -123
  251. package/tests/Form.test.tsx +0 -1424
  252. package/tests/ManageConsentErrorMapping.test.tsx +0 -85
  253. package/tests/ProductSelectionSection.test.tsx +0 -328
  254. package/tests/RequestSubmit.test.tsx +0 -135
  255. package/tests/RevocablePurpose.test.tsx +0 -146
  256. package/tests/RevokeWarningMessage.test.tsx +0 -151
  257. package/tests/consentClient.test.ts +0 -217
  258. package/tests/manageConsentServer.test.ts +0 -38
  259. package/tests/mocks.ts +0 -257
  260. package/tests/resolveContactFromJwt.test.ts +0 -44
  261. package/tests/setup.ts +0 -16
  262. package/tsconfig.json +0 -16
  263. package/tsup.config.ts +0 -31
  264. package/vitest.config.ts +0 -16
@@ -1,318 +0,0 @@
1
- import { useMemo } from 'react';
2
- import { useTranslation } from 'react-i18next';
3
- import { ChevronDown } from 'lucide-react';
4
- import { createColumnHelper } from '@tanstack/react-table';
5
- import dayjs from 'dayjs';
6
- import relativeTime from 'dayjs/plugin/relativeTime';
7
- import { PCBadge, PCText } from '../ui';
8
- import { pcStyles } from '../styles/pcStyles';
9
- import type { DisplayProductGroup } from '../lib/types';
10
-
11
- dayjs.extend(relativeTime);
12
-
13
- const getVar = (varName: string): string => `var(${varName})`;
14
-
15
- type DotChipVariant = 'success' | 'error' | 'warning';
16
-
17
- const dotChipColors: Record<DotChipVariant, { bg: string; text: string }> = {
18
- success: { bg: 'rgba(16, 185, 129, 0.12)', text: getVar('--pc-success') },
19
- error: { bg: 'rgba(239, 68, 68, 0.12)', text: getVar('--pc-error') },
20
- warning: { bg: 'rgba(245, 158, 11, 0.12)', text: getVar('--pc-warning') },
21
- };
22
-
23
- const ConsentCountChip = ({ count, label }: { count: number; label: string }) => (
24
- <PCBadge
25
- className="pc-status-badge"
26
- size="sm"
27
- variant="secondary"
28
- style={{
29
- display: 'inline-flex',
30
- alignItems: 'center',
31
- gap: '0.3125rem',
32
- padding: '0.1875rem 0.5rem',
33
- borderRadius: '9999px',
34
- border: `1px solid ${getVar('--pc-border-color')}`,
35
- backgroundColor: getVar('--pc-bg-primary'),
36
- color: getVar('--pc-text-primary'),
37
- fontSize: '0.6875rem',
38
- fontWeight: 600,
39
- lineHeight: 1.2,
40
- }}
41
- >
42
- <span
43
- aria-hidden="true"
44
- style={{
45
- display: 'inline-flex',
46
- alignItems: 'center',
47
- justifyContent: 'center',
48
- minWidth: '1rem',
49
- color: getVar('--pc-primary'),
50
- fontSize: '0.6875rem',
51
- fontWeight: 700,
52
- lineHeight: 1,
53
- }}
54
- >
55
- {count}
56
- </span>
57
- <span>{label}</span>
58
- </PCBadge>
59
- );
60
-
61
- const DotChip = ({ variant, label }: { variant: DotChipVariant; label: string }) => {
62
- const colors = dotChipColors[variant];
63
- return (
64
- <span
65
- className="pc-status-badge"
66
- style={{
67
- display: 'inline-flex',
68
- alignItems: 'center',
69
- gap: '0.3125rem',
70
- padding: '0.125rem 0.5rem',
71
- borderRadius: '9999px',
72
- fontSize: '0.6875rem',
73
- fontWeight: 600,
74
- lineHeight: 1.2,
75
- backgroundColor: colors.bg,
76
- color: colors.text,
77
- }}
78
- >
79
- <span
80
- aria-hidden="true"
81
- style={{
82
- width: '0.375rem',
83
- height: '0.375rem',
84
- borderRadius: '9999px',
85
- backgroundColor: colors.text,
86
- flexShrink: 0,
87
- }}
88
- />
89
- {label}
90
- </span>
91
- );
92
- };
93
-
94
- const avatarColors: Array<'primary' | 'secondary' | 'success' | 'error' | 'warning' | 'info'> = [
95
- 'primary',
96
- 'info',
97
- 'success',
98
- 'warning',
99
- 'error',
100
- 'secondary',
101
- ];
102
-
103
- const pickAvatarColor = (seed: string) => {
104
- let hash = 0;
105
- for (let i = 0; i < seed.length; i += 1) {
106
- hash = (hash << 5) - hash + seed.charCodeAt(i);
107
- hash |= 0;
108
- }
109
- return avatarColors[Math.abs(hash) % avatarColors.length];
110
- };
111
-
112
- const avatarColorMap: Record<ReturnType<typeof pickAvatarColor>, { bg: string; color: string }> = {
113
- primary: { bg: '#4f46e5', color: '#ffffff' },
114
- secondary: { bg: '#6b7280', color: '#ffffff' },
115
- success: { bg: '#10b981', color: '#ffffff' },
116
- error: { bg: '#ec4899', color: '#ffffff' },
117
- warning: { bg: '#f59e0b', color: '#ffffff' },
118
- info: { bg: '#0ea5e9', color: '#ffffff' },
119
- };
120
-
121
- const getProductInitials = (name: string) => {
122
- const words = name.trim().split(/\s+/).filter(Boolean);
123
- if (words.length >= 2) {
124
- return `${words[0][0]}${words[1][0]}`.toUpperCase();
125
- }
126
- return name.slice(0, 2).toUpperCase();
127
- };
128
-
129
- const ProductAvatar = ({ name, seed }: { name: string; seed: string }) => {
130
- const colors = avatarColorMap[pickAvatarColor(seed)];
131
- return (
132
- <span
133
- style={{
134
- display: 'inline-flex',
135
- alignItems: 'center',
136
- justifyContent: 'center',
137
- width: '24px',
138
- height: '24px',
139
- flexShrink: 0,
140
- borderRadius: '0.4375rem',
141
- backgroundColor: colors.bg,
142
- color: colors.color,
143
- fontSize: '0.6875rem',
144
- fontWeight: 700,
145
- lineHeight: 1,
146
- }}
147
- >
148
- {getProductInitials(name)}
149
- </span>
150
- );
151
- };
152
-
153
- const columnHelper = createColumnHelper<DisplayProductGroup>();
154
-
155
- export const useConsentManagerGroupedColumns = () => {
156
- const { t } = useTranslation();
157
-
158
- return useMemo(
159
- () => [
160
- columnHelper.display({
161
- id: 'expander',
162
- size: 36,
163
- minSize: 36,
164
- header: '',
165
- cell: ({ row }) => (
166
- <button
167
- type="button"
168
- aria-label={row.getIsExpanded() ? t('collapseSidebar') : t('expandSidebar')}
169
- onClick={(e) => {
170
- e.stopPropagation();
171
- row.toggleExpanded();
172
- }}
173
- style={{
174
- display: 'flex',
175
- alignItems: 'center',
176
- justifyContent: 'center',
177
- width: '14px',
178
- height: '14px',
179
- margin: '0 auto',
180
- padding: 0,
181
- border: 'none',
182
- background: 'transparent',
183
- cursor: 'pointer',
184
- color: getVar('--pc-text-secondary'),
185
- borderRadius: 0,
186
- transition: 'color 0.15s ease',
187
- }}
188
- onMouseEnter={(e) => {
189
- e.currentTarget.style.color = getVar('--pc-text-primary');
190
- }}
191
- onMouseLeave={(e) => {
192
- e.currentTarget.style.color = getVar('--pc-text-secondary');
193
- }}
194
- >
195
- <ChevronDown
196
- size={12}
197
- style={{
198
- transform: row.getIsExpanded() ? 'rotate(0deg)' : 'rotate(-90deg)',
199
- transition: 'transform 0.2s ease',
200
- }}
201
- />
202
- </button>
203
- ),
204
- }),
205
-
206
- columnHelper.accessor('product_name', {
207
- id: 'product',
208
- size: 280,
209
- minSize: 200,
210
- header: t('product'),
211
- cell: ({ row }) => {
212
- const group = row.original;
213
- const name = group.product_name || '-';
214
- return (
215
- <div style={{
216
- ...pcStyles.flex,
217
- ...pcStyles.itemsCenter,
218
- gap: getVar('--pc-spacing-sm'),
219
- minWidth: 0,
220
- }}>
221
- <ProductAvatar name={name} seed={group.product_uuid || name} />
222
- <div style={{ minWidth: 0, ...pcStyles.flex, ...pcStyles.flexCol, gap: '0.125rem' }}>
223
- <PCText size="sm" weight="semibold">{name}</PCText>
224
- {group.product_description && (
225
- <PCText
226
- size="sm"
227
- color="secondary"
228
- style={{
229
- display: '-webkit-box',
230
- WebkitLineClamp: 1,
231
- WebkitBoxOrient: 'vertical',
232
- overflow: 'hidden',
233
- wordBreak: 'break-word',
234
- fontSize: '0.6875rem',
235
- }}
236
- title={group.product_description}
237
- >
238
- {group.product_description}
239
- </PCText>
240
- )}
241
- </div>
242
- </div>
243
- );
244
- },
245
- enableSorting: false,
246
- }),
247
-
248
- columnHelper.display({
249
- id: 'consents',
250
- size: 120,
251
- minSize: 90,
252
- header: t('consent'),
253
- cell: ({ row }) => {
254
- if (row.getIsExpanded()) return null;
255
- const count = row.original.total_purposes;
256
- const consentLabel = t('consent', { count });
257
- return (
258
- <div style={{ display: 'inline-flex', alignItems: 'center', minHeight: '1.5rem' }}>
259
- <ConsentCountChip count={count} label={consentLabel} />
260
- </div>
261
- );
262
- },
263
- }),
264
-
265
- columnHelper.display({
266
- id: 'statusSummary',
267
- size: 160,
268
- minSize: 130,
269
- header: t('status'),
270
- cell: ({ row }) => {
271
- if (row.getIsExpanded()) return null;
272
- const g = row.original;
273
- const items: Array<{ count: number; label: string; variant: 'success' | 'error' | 'warning' }> = [];
274
- if (g.active_purposes > 0) {
275
- items.push({ count: g.active_purposes, label: `${g.active_purposes} ${t('statusActive')}`, variant: 'success' });
276
- }
277
- if (g.withdrawn_purposes > 0) {
278
- items.push({ count: g.withdrawn_purposes, label: `${g.withdrawn_purposes} ${t('statusWithdrawn')}`, variant: 'error' });
279
- }
280
- if (g.expired_purposes > 0) {
281
- items.push({ count: g.expired_purposes, label: `${g.expired_purposes} ${t('statusExpired')}`, variant: 'warning' });
282
- }
283
- if (g.declined_purposes > 0) {
284
- items.push({ count: g.declined_purposes, label: `${g.declined_purposes} ${t('statusDeclined')}`, variant: 'warning' });
285
- }
286
- if (items.length === 0) return <PCText size="sm" color="secondary">-</PCText>;
287
- return (
288
- <div style={{ ...pcStyles.flex, ...pcStyles.flexCol, gap: '0.25rem', alignItems: 'flex-start' }}>
289
- {items.map((item) => (
290
- <DotChip key={item.label} variant={item.variant} label={item.label} />
291
- ))}
292
- </div>
293
- );
294
- },
295
- }),
296
-
297
- columnHelper.display({
298
- id: 'latestActivity',
299
- size: 208,
300
- minSize: 170,
301
- header: t('activity'),
302
- cell: ({ row }) => {
303
- if (row.getIsExpanded()) return null;
304
- const ts = row.original.latest_given_date;
305
- if (!ts) return <PCText size="sm" color="secondary">-</PCText>;
306
- const date = dayjs(ts);
307
- return (
308
- <div style={{ ...pcStyles.flex, ...pcStyles.flexCol, gap: '0.0625rem' }}>
309
- <PCText size="sm" weight="medium">{date.format('MMM D, YYYY • h:mm A')}</PCText>
310
- <PCText size="sm" color="secondary" style={{ fontSize: '0.6875rem' }}>{date.fromNow()}</PCText>
311
- </div>
312
- );
313
- },
314
- }),
315
- ],
316
- [t]
317
- );
318
- };
@@ -1,333 +0,0 @@
1
- import { type CSSProperties, useMemo, useState } from 'react';
2
- import { useTranslation } from 'react-i18next';
3
- import dayjs from 'dayjs';
4
- import relativeTime from 'dayjs/plugin/relativeTime';
5
- import { ChevronDown } from 'lucide-react';
6
- import { PCBadge, PCButton, PCEmpty, PCText } from '../ui';
7
- import type {
8
- ConsentModalRecord,
9
- DisplayProductGroup,
10
- PurposeItem,
11
- } from '../lib/types';
12
- import { pcStyles } from '../styles/pcStyles';
13
- import {
14
- renderGivenDate,
15
- renderMethod,
16
- renderModifyButton,
17
- renderStatusBadge,
18
- renderValidTill,
19
- } from './ConsentManagerCells';
20
-
21
- dayjs.extend(relativeTime);
22
-
23
- const getVar = (varName: string): string => `var(${varName})`;
24
-
25
- const avatarColors: Array<'primary' | 'secondary' | 'success' | 'error' | 'warning' | 'info'> = [
26
- 'primary',
27
- 'info',
28
- 'success',
29
- 'warning',
30
- 'error',
31
- 'secondary',
32
- ];
33
-
34
- const pickAvatarColor = (seed: string) => {
35
- let hash = 0;
36
- for (let i = 0; i < seed.length; i += 1) {
37
- hash = (hash << 5) - hash + seed.charCodeAt(i);
38
- hash |= 0;
39
- }
40
- return avatarColors[Math.abs(hash) % avatarColors.length];
41
- };
42
-
43
- const avatarColorMap: Record<ReturnType<typeof pickAvatarColor>, { bg: string; color: string }> = {
44
- primary: { bg: '#4f46e5', color: '#ffffff' },
45
- secondary: { bg: '#6b7280', color: '#ffffff' },
46
- success: { bg: '#10b981', color: '#ffffff' },
47
- error: { bg: '#ec4899', color: '#ffffff' },
48
- warning: { bg: '#f59e0b', color: '#ffffff' },
49
- info: { bg: '#0ea5e9', color: '#ffffff' },
50
- };
51
-
52
- const getProductInitials = (name: string) => {
53
- const words = name.trim().split(/\s+/).filter(Boolean);
54
- if (words.length >= 2) {
55
- return `${words[0][0]}${words[1][0]}`.toUpperCase();
56
- }
57
- return name.slice(0, 2).toUpperCase();
58
- };
59
-
60
- const ProductAvatar = ({ name, seed }: { name: string; seed: string }) => {
61
- const colors = avatarColorMap[pickAvatarColor(seed)];
62
- return (
63
- <span
64
- className="pc-consent-mobile-avatar"
65
- style={{
66
- backgroundColor: colors.bg,
67
- color: colors.color,
68
- }}
69
- >
70
- {getProductInitials(name)}
71
- </span>
72
- );
73
- };
74
-
75
- type ProductStatusItem = {
76
- label: string;
77
- variant: 'success' | 'error' | 'warning';
78
- };
79
-
80
- const statusChipStyles: Record<ProductStatusItem['variant'], CSSProperties> = {
81
- success: { backgroundColor: 'rgba(16, 185, 129, 0.12)', color: getVar('--pc-success') },
82
- error: { backgroundColor: 'rgba(239, 68, 68, 0.12)', color: getVar('--pc-error') },
83
- warning: { backgroundColor: 'rgba(245, 158, 11, 0.12)', color: getVar('--pc-warning') },
84
- };
85
-
86
- type ConsentManagerProductCardsProps = {
87
- groups: DisplayProductGroup[];
88
- onModify: (record: ConsentModalRecord) => void;
89
- extraPurposesByKey?: Record<string, PurposeItem[]>;
90
- hasMoreByKey?: Record<string, boolean>;
91
- loadingMoreByKey?: Record<string, boolean>;
92
- onLoadMore?: (group: DisplayProductGroup) => void;
93
- cardKeyFor?: (group: DisplayProductGroup) => string;
94
- };
95
-
96
- const buildModalRecord = (
97
- purpose: PurposeItem,
98
- group: DisplayProductGroup
99
- ): ConsentModalRecord => ({
100
- ...purpose,
101
- product_uuid: group.product_uuid,
102
- product_name: group.product_name,
103
- product_description: group.product_description,
104
- nominator: group.nominator,
105
- });
106
-
107
- export function ConsentManagerProductCards({
108
- groups,
109
- onModify,
110
- extraPurposesByKey,
111
- hasMoreByKey,
112
- loadingMoreByKey,
113
- onLoadMore,
114
- cardKeyFor,
115
- }: ConsentManagerProductCardsProps) {
116
- const { t } = useTranslation();
117
- const [expandedCards, setExpandedCards] = useState<Record<string, boolean>>({});
118
-
119
- const handleToggle = (key: string) => {
120
- setExpandedCards((prev) => ({ ...prev, [key]: !prev[key] }));
121
- };
122
-
123
- const getStatusItems = useMemo(
124
- () =>
125
- (group: DisplayProductGroup): ProductStatusItem[] => {
126
- const items: ProductStatusItem[] = [];
127
- if (group.active_purposes > 0) {
128
- items.push({
129
- label: `${group.active_purposes} ${t('statusActive')}`,
130
- variant: 'success',
131
- });
132
- }
133
- if (group.withdrawn_purposes > 0) {
134
- items.push({
135
- label: `${group.withdrawn_purposes} ${t('statusWithdrawn')}`,
136
- variant: 'error',
137
- });
138
- }
139
- if (group.expired_purposes > 0) {
140
- items.push({
141
- label: `${group.expired_purposes} ${t('statusExpired')}`,
142
- variant: 'warning',
143
- });
144
- }
145
- if (group.declined_purposes > 0) {
146
- items.push({
147
- label: `${group.declined_purposes} ${t('statusDeclined')}`,
148
- variant: 'warning',
149
- });
150
- }
151
- return items;
152
- },
153
- [t]
154
- );
155
-
156
- if (groups.length === 0) {
157
- return (
158
- <div className="pc-consent-mobile-empty">
159
- <PCEmpty title={t('noData')} />
160
- </div>
161
- );
162
- }
163
-
164
- return (
165
- <div className="pc-consent-mobile-list">
166
- {groups.map((group) => {
167
- const cardKey = cardKeyFor ? cardKeyFor(group) : (group.product_uuid || group.product_name);
168
- const productName = group.product_name || '-';
169
- const statusItems = getStatusItems(group);
170
- const latestDate = group.latest_given_date ? dayjs(group.latest_given_date) : null;
171
- const isExpanded = Boolean(expandedCards[cardKey]);
172
- const extraPurposes = extraPurposesByKey?.[cardKey] ?? [];
173
- const purposes: PurposeItem[] = [...group.purposes, ...extraPurposes];
174
- const hasMore = hasMoreByKey?.[cardKey] ?? group.has_more_purposes;
175
- const isLoadingMore = Boolean(loadingMoreByKey?.[cardKey]);
176
- const consentLabel = t('consent', { count: group.total_purposes });
177
-
178
- return (
179
- <article key={cardKey} className="pc-consent-mobile-card">
180
- <div className="pc-consent-mobile-card-header">
181
- <div className="pc-consent-mobile-product-head">
182
- <ProductAvatar name={productName} seed={group.product_uuid || productName} />
183
- <div style={{ minWidth: 0 }}>
184
- <PCText size="sm" weight="semibold">{productName}</PCText>
185
- {group.product_description && (
186
- <PCText size="sm" color="secondary" className="pc-consent-mobile-subtle-text">
187
- {group.product_description}
188
- </PCText>
189
- )}
190
- {group.nominator && (
191
- <PCText size="sm" color="secondary" className="pc-consent-mobile-subtle-text">
192
- {t('nominatedBy')}{' '}
193
- <span style={{ fontWeight: 600 }}>
194
- {group.nominator.name || group.nominator.email || group.nominator.org_user_id}
195
- </span>
196
- </PCText>
197
- )}
198
- </div>
199
- </div>
200
- <PCBadge
201
- className="pc-status-badge"
202
- size="sm"
203
- variant="secondary"
204
- style={{
205
- border: `1px solid ${getVar('--pc-border-color')}`,
206
- backgroundColor: getVar('--pc-bg-primary'),
207
- }}
208
- >
209
- <span style={{ color: getVar('--pc-primary'), fontWeight: 700 }}>
210
- {group.total_purposes}
211
- </span>{' '}
212
- {consentLabel}
213
- </PCBadge>
214
- </div>
215
-
216
- {statusItems.length > 0 && (
217
- <div className="pc-consent-mobile-chip-row">
218
- {statusItems.map((item) => (
219
- <span
220
- key={item.label}
221
- className="pc-status-badge pc-consent-mobile-status-chip"
222
- style={statusChipStyles[item.variant]}
223
- >
224
- {item.label}
225
- </span>
226
- ))}
227
- </div>
228
- )}
229
-
230
- <div className="pc-consent-mobile-activity-row">
231
- <PCText size="sm" color="secondary" className="pc-consent-mobile-meta-label">
232
- {t('activity')}
233
- </PCText>
234
- {latestDate ? (
235
- <div style={{ ...pcStyles.flex, ...pcStyles.flexCol, gap: '0.0625rem', minWidth: 0 }}>
236
- <PCText size="sm" weight="medium">{latestDate.format('MMM D, YYYY • h:mm A')}</PCText>
237
- <PCText size="sm" color="secondary" className="pc-consent-mobile-subtle-text">
238
- {latestDate.fromNow()}
239
- </PCText>
240
- </div>
241
- ) : (
242
- <PCText size="sm" color="secondary">-</PCText>
243
- )}
244
- </div>
245
-
246
- <button
247
- type="button"
248
- className="pc-consent-mobile-expand-btn"
249
- onClick={() => handleToggle(cardKey)}
250
- aria-expanded={isExpanded}
251
- >
252
- <span>
253
- {purposes.length} {t('purpose')}
254
- </span>
255
- <ChevronDown
256
- size={14}
257
- style={{
258
- transform: isExpanded ? 'rotate(180deg)' : 'rotate(0deg)',
259
- transition: 'transform 0.2s ease',
260
- }}
261
- />
262
- </button>
263
-
264
- {isExpanded && (
265
- <div className="pc-consent-mobile-purpose-list">
266
- {purposes.map((purpose) => {
267
- const modalRecord = buildModalRecord(purpose, group);
268
- return (
269
- <div
270
- key={purpose.purpose_uuid}
271
- className="pc-consent-mobile-purpose-item"
272
- >
273
- <div className="pc-consent-mobile-purpose-head">
274
- <div style={{ minWidth: 0 }}>
275
- <PCText size="sm" weight="semibold">{purpose.name}</PCText>
276
- {purpose.description && (
277
- <PCText size="sm" color="secondary" className="pc-consent-mobile-subtle-text">
278
- {purpose.description}
279
- </PCText>
280
- )}
281
- </div>
282
- {renderStatusBadge(purpose.status, t)}
283
- </div>
284
-
285
- <div className="pc-consent-mobile-meta-grid">
286
- <div>
287
- <PCText size="sm" color="secondary" className="pc-consent-mobile-meta-label">
288
- {t('givenDate')}
289
- </PCText>
290
- {renderGivenDate(purpose.given_date, { showTooltip: false })}
291
- </div>
292
- <div>
293
- <PCText size="sm" color="secondary" className="pc-consent-mobile-meta-label">
294
- {t('validTill')}
295
- </PCText>
296
- {renderValidTill(purpose, t)}
297
- </div>
298
- <div>
299
- <PCText size="sm" color="secondary" className="pc-consent-mobile-meta-label">
300
- {t('method')}
301
- </PCText>
302
- {renderMethod(purpose.method)}
303
- </div>
304
- <div className="pc-consent-mobile-action-cell">
305
- <PCText size="sm" color="secondary" className="pc-consent-mobile-meta-label">
306
- {t('action')}
307
- </PCText>
308
- {renderModifyButton(modalRecord, onModify, t)}
309
- </div>
310
- </div>
311
- </div>
312
- );
313
- })}
314
- {hasMore && onLoadMore && (
315
- <div style={{ display: 'flex', justifyContent: 'center', padding: '0.5rem' }}>
316
- <PCButton
317
- size="sm"
318
- variant="outline"
319
- onClick={() => onLoadMore(group)}
320
- disabled={isLoadingMore}
321
- >
322
- {isLoadingMore ? t('loading') : t('loadMorePurposes')}
323
- </PCButton>
324
- </div>
325
- )}
326
- </div>
327
- )}
328
- </article>
329
- );
330
- })}
331
- </div>
332
- );
333
- }