@redacto.io/consent-sdk-react 3.5.0 → 3.6.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 (152) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/LICENSE +176 -0
  3. package/dist/index.d.mts +51 -4
  4. package/dist/index.d.ts +51 -4
  5. package/dist/index.js +1891 -243
  6. package/dist/index.mjs +1890 -243
  7. package/dist/privacy-center.d.mts +566 -0
  8. package/dist/privacy-center.d.ts +566 -0
  9. package/dist/privacy-center.js +17174 -0
  10. package/dist/privacy-center.mjs +17136 -0
  11. package/package.json +47 -3
  12. package/src/RedactoNoticeConsent/RedactoNoticeConsent.test.tsx +201 -118
  13. package/src/RedactoNoticeConsent/RedactoNoticeConsent.tsx +1194 -93
  14. package/src/RedactoNoticeConsent/api/index.ts +335 -206
  15. package/src/RedactoNoticeConsent/api/types.ts +140 -16
  16. package/src/RedactoNoticeConsent/components/DigiLockerCallback.tsx +602 -0
  17. package/src/RedactoNoticeConsent/components/index.ts +7 -0
  18. package/src/RedactoNoticeConsent/injectStyles.ts +11 -0
  19. package/src/RedactoNoticeConsent/language-codes.ts +61 -0
  20. package/src/RedactoNoticeConsent/services/storage.ts +122 -0
  21. package/src/RedactoNoticeConsent/types.ts +2 -0
  22. package/src/RedactoPrivacyCenter/PrivacyCenterActivityPage.tsx +19 -0
  23. package/src/RedactoPrivacyCenter/PrivacyCenterConsentManagerPage.tsx +17 -0
  24. package/src/RedactoPrivacyCenter/PrivacyCenterFormPage.tsx +79 -0
  25. package/src/RedactoPrivacyCenter/PrivacyCenterHomePage.tsx +27 -0
  26. package/src/RedactoPrivacyCenter/PrivacyCenterLayout.tsx +142 -0
  27. package/src/RedactoPrivacyCenter/RedactoPrivacyCenter.tsx +51 -0
  28. package/src/RedactoPrivacyCenter/api/actions.ts +444 -0
  29. package/src/RedactoPrivacyCenter/api/client.ts +413 -0
  30. package/src/RedactoPrivacyCenter/api/config.ts +33 -0
  31. package/src/RedactoPrivacyCenter/api/fetcher.ts +181 -0
  32. package/src/RedactoPrivacyCenter/api/upload.ts +93 -0
  33. package/src/RedactoPrivacyCenter/assets/character.svg +31 -0
  34. package/src/RedactoPrivacyCenter/assets/fileAttach.svg +9 -0
  35. package/src/RedactoPrivacyCenter/assets/greenTick.svg +4 -0
  36. package/src/RedactoPrivacyCenter/assets/mail.svg +3 -0
  37. package/src/RedactoPrivacyCenter/assets/poweredByRedacto.svg +9 -0
  38. package/src/RedactoPrivacyCenter/assets/sentImg.svg +9 -0
  39. package/src/RedactoPrivacyCenter/assets/uploadFileIcon.svg +9 -0
  40. package/src/RedactoPrivacyCenter/components/ActivitiesList.tsx +272 -0
  41. package/src/RedactoPrivacyCenter/components/CaseDetailsModal.tsx +468 -0
  42. package/src/RedactoPrivacyCenter/components/CaseHistory.tsx +433 -0
  43. package/src/RedactoPrivacyCenter/components/ConsentManager.tsx +726 -0
  44. package/src/RedactoPrivacyCenter/components/ConsentManagerColumns.tsx +239 -0
  45. package/src/RedactoPrivacyCenter/components/ConsentManagerConstants.ts +7 -0
  46. package/src/RedactoPrivacyCenter/components/ConsentManagerTableSkeleton.tsx +155 -0
  47. package/src/RedactoPrivacyCenter/components/DataRequest/CorrectionDataSection.tsx +189 -0
  48. package/src/RedactoPrivacyCenter/components/DataRequest/GrievanceDataSection.tsx +118 -0
  49. package/src/RedactoPrivacyCenter/components/DataRequest/NominationDataSection.tsx +66 -0
  50. package/src/RedactoPrivacyCenter/components/DataRequest/PurposeSelectionSection.tsx +305 -0
  51. package/src/RedactoPrivacyCenter/components/Form.tsx +1455 -0
  52. package/src/RedactoPrivacyCenter/components/GrievanceTable.tsx +176 -0
  53. package/src/RedactoPrivacyCenter/components/GrievanceTablePagination.tsx +330 -0
  54. package/src/RedactoPrivacyCenter/components/ModifyConsentModal.tsx +329 -0
  55. package/src/RedactoPrivacyCenter/components/Pagination.tsx +140 -0
  56. package/src/RedactoPrivacyCenter/components/PrivacyCenterLayout.tsx +302 -0
  57. package/src/RedactoPrivacyCenter/components/RequestSubmit.tsx +218 -0
  58. package/src/RedactoPrivacyCenter/components/SideMenuBarPC/SideBarPC.tsx +475 -0
  59. package/src/RedactoPrivacyCenter/components/SideMenuBarPC/SideMenuPC.tsx +412 -0
  60. package/src/RedactoPrivacyCenter/components/SideMenuBarPC/constants.tsx +42 -0
  61. package/src/RedactoPrivacyCenter/components/SideMenuBarPC/menuItemsPC.tsx +1 -0
  62. package/src/RedactoPrivacyCenter/components/SideMenuBarPC/types.ts +40 -0
  63. package/src/RedactoPrivacyCenter/components/SideMenuBarPC/utils.ts +38 -0
  64. package/src/RedactoPrivacyCenter/components/ThemeTransitionOverlay.tsx +85 -0
  65. package/src/RedactoPrivacyCenter/components/activitiesColumns.tsx +141 -0
  66. package/src/RedactoPrivacyCenter/components/caseHistoryColumns.tsx +179 -0
  67. package/src/RedactoPrivacyCenter/components/constant.ts +20 -0
  68. package/src/RedactoPrivacyCenter/components/types.ts +68 -0
  69. package/src/RedactoPrivacyCenter/components/utils.tsx +10 -0
  70. package/src/RedactoPrivacyCenter/config/routes.ts +9 -0
  71. package/src/RedactoPrivacyCenter/config/table.ts +25 -0
  72. package/src/RedactoPrivacyCenter/context/AuthContext.tsx +123 -0
  73. package/src/RedactoPrivacyCenter/context/BaseUrlContext.tsx +44 -0
  74. package/src/RedactoPrivacyCenter/context/LocaleContext.tsx +11 -0
  75. package/src/RedactoPrivacyCenter/context/NavigationContext.tsx +64 -0
  76. package/src/RedactoPrivacyCenter/context/OrganizationContext.tsx +30 -0
  77. package/src/RedactoPrivacyCenter/context/PageChromeContext.tsx +60 -0
  78. package/src/RedactoPrivacyCenter/context/theme.tsx +127 -0
  79. package/src/RedactoPrivacyCenter/lib/api.ts +468 -0
  80. package/src/RedactoPrivacyCenter/lib/consent-manager/utils.tsx +63 -0
  81. package/src/RedactoPrivacyCenter/lib/constants.ts +116 -0
  82. package/src/RedactoPrivacyCenter/lib/i18n.ts +81 -0
  83. package/src/RedactoPrivacyCenter/lib/locales.ts +105 -0
  84. package/src/RedactoPrivacyCenter/lib/queries.ts +30 -0
  85. package/src/RedactoPrivacyCenter/lib/types.ts +346 -0
  86. package/src/RedactoPrivacyCenter/lib/useCurrentLanguage.ts +37 -0
  87. package/src/RedactoPrivacyCenter/lib/utils.ts +625 -0
  88. package/src/RedactoPrivacyCenter/locales/as/translation.json +188 -0
  89. package/src/RedactoPrivacyCenter/locales/bho/translation.json +188 -0
  90. package/src/RedactoPrivacyCenter/locales/bn/translation.json +188 -0
  91. package/src/RedactoPrivacyCenter/locales/brx/translation.json +188 -0
  92. package/src/RedactoPrivacyCenter/locales/doi/translation.json +188 -0
  93. package/src/RedactoPrivacyCenter/locales/en/translation.json +188 -0
  94. package/src/RedactoPrivacyCenter/locales/gom/translation.json +188 -0
  95. package/src/RedactoPrivacyCenter/locales/gu/translation.json +188 -0
  96. package/src/RedactoPrivacyCenter/locales/hi/translation.json +188 -0
  97. package/src/RedactoPrivacyCenter/locales/kn/translation.json +188 -0
  98. package/src/RedactoPrivacyCenter/locales/ks/translation.json +188 -0
  99. package/src/RedactoPrivacyCenter/locales/mai/translation.json +188 -0
  100. package/src/RedactoPrivacyCenter/locales/ml/translation.json +188 -0
  101. package/src/RedactoPrivacyCenter/locales/mni-Mtei/translation.json +188 -0
  102. package/src/RedactoPrivacyCenter/locales/mr/translation.json +188 -0
  103. package/src/RedactoPrivacyCenter/locales/ne/translation.json +188 -0
  104. package/src/RedactoPrivacyCenter/locales/or/translation.json +188 -0
  105. package/src/RedactoPrivacyCenter/locales/pa/translation.json +188 -0
  106. package/src/RedactoPrivacyCenter/locales/sa/translation.json +188 -0
  107. package/src/RedactoPrivacyCenter/locales/sat/translation.json +188 -0
  108. package/src/RedactoPrivacyCenter/locales/sd/translation.json +188 -0
  109. package/src/RedactoPrivacyCenter/locales/ta/translation.json +188 -0
  110. package/src/RedactoPrivacyCenter/locales/te/translation.json +188 -0
  111. package/src/RedactoPrivacyCenter/locales/ur/translation.json +188 -0
  112. package/src/RedactoPrivacyCenter/styles/base.css +117 -0
  113. package/src/RedactoPrivacyCenter/styles/injectStyles.ts +1000 -0
  114. package/src/RedactoPrivacyCenter/styles/pcStyles.ts +819 -0
  115. package/src/RedactoPrivacyCenter/styles/responsive.ts +138 -0
  116. package/src/RedactoPrivacyCenter/styles/variables.css +133 -0
  117. package/src/RedactoPrivacyCenter/table/AdvancedTable.tsx +365 -0
  118. package/src/RedactoPrivacyCenter/table/AdvancedTablePagination.tsx +479 -0
  119. package/src/RedactoPrivacyCenter/table/index.ts +2 -0
  120. package/src/RedactoPrivacyCenter/types/images.d.ts +29 -0
  121. package/src/RedactoPrivacyCenter/ui/Footer.tsx +73 -0
  122. package/src/RedactoPrivacyCenter/ui/FormBlockWrapper.tsx +54 -0
  123. package/src/RedactoPrivacyCenter/ui/PCAccordion.tsx +87 -0
  124. package/src/RedactoPrivacyCenter/ui/PCActionIcon.tsx +47 -0
  125. package/src/RedactoPrivacyCenter/ui/PCAvatar.tsx +69 -0
  126. package/src/RedactoPrivacyCenter/ui/PCBadge.tsx +48 -0
  127. package/src/RedactoPrivacyCenter/ui/PCButton.tsx +77 -0
  128. package/src/RedactoPrivacyCenter/ui/PCCheckbox.tsx +55 -0
  129. package/src/RedactoPrivacyCenter/ui/PCCollapse.tsx +97 -0
  130. package/src/RedactoPrivacyCenter/ui/PCEmpty.tsx +35 -0
  131. package/src/RedactoPrivacyCenter/ui/PCInput.tsx +128 -0
  132. package/src/RedactoPrivacyCenter/ui/PCLoader.tsx +30 -0
  133. package/src/RedactoPrivacyCenter/ui/PCModal.tsx +104 -0
  134. package/src/RedactoPrivacyCenter/ui/PCPopover.tsx +175 -0
  135. package/src/RedactoPrivacyCenter/ui/PCSelect.tsx +381 -0
  136. package/src/RedactoPrivacyCenter/ui/PCTable.tsx +137 -0
  137. package/src/RedactoPrivacyCenter/ui/PCText.tsx +39 -0
  138. package/src/RedactoPrivacyCenter/ui/PCTextarea.tsx +43 -0
  139. package/src/RedactoPrivacyCenter/ui/PCTitle.tsx +37 -0
  140. package/src/RedactoPrivacyCenter/ui/PCTooltip.tsx +119 -0
  141. package/src/RedactoPrivacyCenter/ui/SimpleBar.tsx +25 -0
  142. package/src/RedactoPrivacyCenter/ui/StatusBadge.tsx +55 -0
  143. package/src/RedactoPrivacyCenter/ui/ThemeToggle.tsx +70 -0
  144. package/src/RedactoPrivacyCenter/ui/index.ts +18 -0
  145. package/src/RedactoPrivacyCenter/utils/cn.ts +28 -0
  146. package/src/RedactoPrivacyCenter/utils/date.ts +48 -0
  147. package/src/RedactoPrivacyCenter/utils/status.ts +111 -0
  148. package/src/RedactoPrivacyCenter/utils/toast.ts +130 -0
  149. package/src/index.ts +10 -0
  150. package/src/privacy-center.ts +107 -0
  151. package/tsconfig.json +2 -0
  152. package/tsup.config.ts +16 -1
@@ -0,0 +1,475 @@
1
+ import { cn } from '../../utils/cn';
2
+ import SimpleBar from '../../ui/SimpleBar';
3
+ import { PCText, PCAvatar, PCButton, PCActionIcon } from '../../ui';
4
+ import { PCTooltip } from '../../ui/PCTooltip';
5
+ import { pcStyles } from '../../styles/pcStyles';
6
+ import { useState, useEffect, useCallback, useMemo } from 'react';
7
+ import { useTranslation } from 'react-i18next';
8
+ import {
9
+ IoArrowBackOutline,
10
+ IoChevronBackOutline,
11
+ IoChevronForwardOutline,
12
+ IoCloseOutline,
13
+ IoLogOutOutline,
14
+ IoMenuOutline,
15
+ } from 'react-icons/io5';
16
+
17
+ const getVar = (varName: string): string => `var(${varName})`;
18
+ import { SideMenuPC } from './SideMenuPC';
19
+ import { useMenuItemsPC } from '../../lib/constants';
20
+ import { useOrganization } from '../../context/OrganizationContext';
21
+ import type { SideBarPCProps } from './types';
22
+ import { signOutPrivacyCenter } from '../../lib/utils';
23
+
24
+ export default function SideBarPC({
25
+ className,
26
+ isCompact = false,
27
+ onBack,
28
+ }: SideBarPCProps) {
29
+ const { t } = useTranslation();
30
+ const menuItems = useMenuItemsPC();
31
+ const [isCollapsed, setIsCollapsed] = useState(true); // Always start collapsed
32
+ const [isMobileOpen, setIsMobileOpen] = useState(false);
33
+ const [isDesktopHovered, setIsDesktopHovered] = useState(false);
34
+ const [email, setEmail] = useState<string>('');
35
+ // const [isSigningOut, setIsSigningOut] = useState(false);
36
+ const { organization } = useOrganization();
37
+
38
+ useEffect(() => {
39
+ setEmail(sessionStorage.getItem('email') || '');
40
+ }, []);
41
+
42
+ // const handleSignOut = useCallback(async () => {
43
+ // setIsSigningOut(true);
44
+ // signOutPrivacyCenter();
45
+ // // Sign out handled - parent component should handle navigation/error
46
+ // setIsSigningOut(false);
47
+ // }, []);
48
+
49
+ const handleDesktopToggle = useCallback(() => {
50
+ if (!isCompact && !isMobileOpen) {
51
+ setIsCollapsed((prev) => !prev);
52
+ }
53
+ }, [isCompact, isMobileOpen]);
54
+
55
+ const handleMobileToggle = useCallback(() => {
56
+ setIsMobileOpen((prev) => !prev);
57
+ }, []);
58
+
59
+ const handleMobileClose = useCallback(() => {
60
+ setIsMobileOpen(false);
61
+ }, []);
62
+
63
+ const handleMenuItemSelect = useCallback(() => {
64
+ if (isMobileOpen) {
65
+ setIsMobileOpen(false);
66
+ return;
67
+ }
68
+
69
+ if (!isCompact) {
70
+ setIsCollapsed(true);
71
+ }
72
+ }, [isCompact, isMobileOpen]);
73
+
74
+ const handleDesktopMouseEnter = useCallback(() => {
75
+ if (!isMobileOpen) {
76
+ setIsDesktopHovered(true);
77
+ }
78
+ }, [isMobileOpen]);
79
+
80
+ const handleDesktopMouseLeave = useCallback(() => {
81
+ setIsDesktopHovered(false);
82
+ }, []);
83
+
84
+ // Close mobile menu when clicking outside
85
+ useEffect(() => {
86
+ const handleClickOutside = (event: MouseEvent) => {
87
+ const target = event.target as HTMLElement;
88
+ if (
89
+ isMobileOpen &&
90
+ !target.closest('aside') &&
91
+ !target.closest('[data-mobile-menu-button]')
92
+ ) {
93
+ setIsMobileOpen(false);
94
+ }
95
+ };
96
+
97
+ if (isMobileOpen) {
98
+ document.addEventListener('mousedown', handleClickOutside);
99
+ // Prevent body scroll when mobile menu is open
100
+ document.body.style.overflow = 'hidden';
101
+ } else {
102
+ document.body.style.overflow = '';
103
+ }
104
+
105
+ return () => {
106
+ document.removeEventListener('mousedown', handleClickOutside);
107
+ document.body.style.overflow = '';
108
+ };
109
+ }, [isMobileOpen]);
110
+
111
+ const organizationName = organization?.name || '';
112
+
113
+ const sidebarClassName = useMemo(
114
+ () =>
115
+ cn(
116
+ className,
117
+ isCollapsed && 'pc-sidebar-collapsed'
118
+ ),
119
+ [isCollapsed, className]
120
+ );
121
+
122
+ const sidebarStyle = useMemo(
123
+ () => ({
124
+ position: 'fixed' as const,
125
+ top: 0,
126
+ bottom: 0,
127
+ left: 0,
128
+ zIndex: 1100,
129
+ backgroundColor: getVar('--pc-bg-shell'),
130
+ boxShadow: getVar('--pc-sidebar-shadow'),
131
+ transition: 'width 0.3s cubic-bezier(0.4, 0, 0.2, 1), transform 0.3s cubic-bezier(0.4, 0, 0.2, 1), background-color 0.3s ease, border-color 0.3s ease',
132
+ display: 'flex',
133
+ flexDirection: 'column',
134
+ overflowY: 'hidden' as const,
135
+ overflowX: 'visible' as const,
136
+ boxSizing: 'border-box',
137
+ height: '100vh',
138
+ willChange: 'width',
139
+ // Width will be controlled by CSS classes, but set default inline for non-desktop
140
+ width: isMobileOpen
141
+ ? getVar('--pc-sidebar-mobile-width')
142
+ : isCollapsed
143
+ ? getVar('--pc-sidebar-collapsed-width')
144
+ : getVar('--pc-sidebar-expanded-width'),
145
+ }),
146
+ [isCollapsed, isMobileOpen]
147
+ );
148
+
149
+ const headerTextStyle = useMemo(
150
+ () => ({
151
+ overflow: 'hidden',
152
+ transition: 'opacity 0.3s ease, width 0.3s ease, max-width 0.3s ease, margin-left 0.3s ease',
153
+ flex: 1,
154
+ minWidth: 0,
155
+ willChange: 'opacity, width, max-width, margin-left',
156
+ ...(isMobileOpen || !isCollapsed ? {
157
+ opacity: 1,
158
+ maxWidth: '100%',
159
+ width: 'auto',
160
+ marginLeft: '0.75rem',
161
+ } : {
162
+ width: 0,
163
+ opacity: 0,
164
+ maxWidth: 0,
165
+ marginLeft: 0,
166
+ }),
167
+ }),
168
+ [isCollapsed, isMobileOpen]
169
+ );
170
+
171
+ const emailContainerStyle = useMemo(
172
+ () => ({
173
+ overflow: 'hidden',
174
+ transition: 'all 0.3s',
175
+ ...(isMobileOpen || !isCollapsed ? {
176
+ height: email ? 'auto' : 0,
177
+ opacity: email ? 1 : 0,
178
+ marginBottom: email ? '0.5rem' : 0,
179
+ } : {
180
+ height: 0,
181
+ opacity: 0,
182
+ marginBottom: 0,
183
+ }),
184
+ }),
185
+ [isCollapsed, isMobileOpen, email]
186
+ );
187
+
188
+ const buttonStyle = useMemo(
189
+ () => ({
190
+ height: 'auto',
191
+ minHeight: '2.25rem',
192
+ width: '100%',
193
+ justifyContent: (isMobileOpen || !isCollapsed) ? 'flex-start' : 'center',
194
+ padding: 0,
195
+ fontWeight: pcStyles.fontWeightMedium.fontWeight,
196
+ color: getVar('--pc-text-primary'),
197
+ outline: 'none',
198
+ transition: 'all 0.3s',
199
+ alignItems: 'center',
200
+ display: 'flex',
201
+ }),
202
+ [isCollapsed, isMobileOpen]
203
+ );
204
+
205
+ const handleBack = useCallback(() => {
206
+ if (onBack === 'back') {
207
+ window.history.back();
208
+ } else if (onBack === 'signout') {
209
+ signOutPrivacyCenter();
210
+ // Redirect to previous page after clearing cookies and sessionStorage
211
+ window.history.back();
212
+ }
213
+ }, [onBack]);
214
+
215
+ const footerActionLabel = onBack === 'back' ? t('back') : t('signOut');
216
+ const footerActionIconSize = !isMobileOpen && isCollapsed ? 19 : 18;
217
+ const footerActionIcon =
218
+ onBack === 'back' ? (
219
+ <IoArrowBackOutline size={footerActionIconSize} style={{ flexShrink: 0 }} />
220
+ ) : (
221
+ <IoLogOutOutline size={footerActionIconSize} style={{ flexShrink: 0 }} />
222
+ );
223
+
224
+ return (
225
+ <>
226
+ {!isCompact && !isMobileOpen && (
227
+ <PCActionIcon
228
+ variant="outline"
229
+ aria-label={isCollapsed ? 'Expand sidebar' : 'Collapse sidebar'}
230
+ className="pc-sidebar-toggle-desktop pc-hidden-xs pc-hidden-sm pc-flex-md"
231
+ data-collapsed={isCollapsed ? 'true' : 'false'}
232
+ data-visible={(!isCollapsed || isDesktopHovered) ? 'true' : 'false'}
233
+ style={{
234
+ position: 'fixed',
235
+ top: '28px',
236
+ zIndex: 2000,
237
+ width: '28px',
238
+ height: '28px',
239
+ borderRadius: '9999px',
240
+ borderColor: getVar('--pc-border-color'),
241
+ backgroundColor: getVar('--pc-bg-primary'),
242
+ color: getVar('--pc-text-secondary'),
243
+ boxShadow: '0 10px 24px rgba(15, 23, 42, 0.14)',
244
+ }}
245
+ onMouseEnter={handleDesktopMouseEnter}
246
+ onMouseLeave={handleDesktopMouseLeave}
247
+ onClick={handleDesktopToggle}
248
+ >
249
+ {isCollapsed ? (
250
+ <IoChevronForwardOutline size={14} />
251
+ ) : (
252
+ <IoChevronBackOutline size={14} />
253
+ )}
254
+ </PCActionIcon>
255
+ )}
256
+
257
+ {/* Mobile Menu Button - visible only on mobile when sidebar is closed */}
258
+ {!isMobileOpen && (
259
+ <PCActionIcon
260
+ data-mobile-menu-button
261
+ aria-label="Open Sidebar Menu"
262
+ variant="default"
263
+ style={{
264
+ position: 'fixed',
265
+ left: '0.75rem',
266
+ top: '0.75rem',
267
+ zIndex: 992,
268
+ height: '2.25rem',
269
+ width: '2.25rem',
270
+ padding: 0,
271
+ color: getVar('--pc-text-primary'),
272
+ }}
273
+ className="pc-hidden-md"
274
+ onClick={handleMobileToggle}
275
+ >
276
+ <IoMenuOutline size={20} />
277
+ </PCActionIcon>
278
+ )}
279
+
280
+ {/* Mobile Overlay */}
281
+ <div
282
+ className="pc-hidden-md pc-mobile-overlay"
283
+ data-open={isMobileOpen}
284
+ style={{
285
+ position: 'fixed',
286
+ inset: 0,
287
+ zIndex: 990,
288
+ backgroundColor: getVar('--pc-bg-overlay'),
289
+ }}
290
+ onClick={handleMobileClose}
291
+ aria-hidden={!isMobileOpen}
292
+ />
293
+
294
+ {/* Sidebar */}
295
+ <aside
296
+ style={sidebarStyle}
297
+ className={cn(sidebarClassName, 'pc-sidebar')}
298
+ data-mobile-open={isMobileOpen}
299
+ onMouseEnter={handleDesktopMouseEnter}
300
+ onMouseLeave={handleDesktopMouseLeave}
301
+ >
302
+ {/* Sidebar Header */}
303
+ <div style={{
304
+ flexShrink: 0,
305
+ ...pcStyles.flex,
306
+ minHeight: '56px',
307
+ height: '56px',
308
+ ...pcStyles.itemsCenter,
309
+ ...(isMobileOpen || !isCollapsed ? { ...pcStyles.justifyBetween } : { ...pcStyles.justifyCenter }),
310
+ backgroundColor: getVar('--pc-bg-shell'),
311
+ paddingLeft: isMobileOpen || !isCollapsed ? '1rem' : '0.5rem',
312
+ paddingRight: isMobileOpen || !isCollapsed ? '1rem' : '0.5rem',
313
+ transition: 'padding-left 0.3s ease, padding-right 0.3s ease, justify-content 0.3s ease',
314
+ willChange: 'padding-left, padding-right',
315
+ }}>
316
+ <div style={{
317
+ ...pcStyles.flex,
318
+ ...pcStyles.itemsCenter,
319
+ ...(isMobileOpen || !isCollapsed ? { flex: 1, minWidth: 0 } : { justifyContent: 'center', width: '100%' }),
320
+ transition: 'flex 0.3s ease, min-width 0.3s ease, justify-content 0.3s ease, width 0.3s ease',
321
+ willChange: 'flex, min-width, justify-content, width',
322
+ }}>
323
+ <div style={{
324
+ flexShrink: 0,
325
+ transition: 'transform 0.3s ease',
326
+ willChange: 'transform',
327
+ }}>
328
+ <PCAvatar name={organizationName} color="info" size="md" />
329
+ </div>
330
+ <div style={headerTextStyle}>
331
+ <PCText style={{
332
+ whiteSpace: 'nowrap',
333
+ fontSize: pcStyles.textBase.fontSize,
334
+ fontWeight: pcStyles.fontWeightSemibold.fontWeight,
335
+ letterSpacing: '-0.025em',
336
+ color: getVar('--pc-text-primary'),
337
+ transition: 'opacity 0.3s ease, transform 0.3s ease',
338
+ willChange: 'opacity, transform',
339
+ }}>
340
+ {organizationName}
341
+ </PCText>
342
+ </div>
343
+ </div>
344
+ <div style={{
345
+ ...pcStyles.flex,
346
+ ...pcStyles.itemsCenter,
347
+ flexShrink: 0,
348
+ opacity: (isMobileOpen || !isCollapsed) ? 1 : 0,
349
+ width: (isMobileOpen || !isCollapsed) ? 'auto' : 0,
350
+ overflow: 'hidden',
351
+ transition: 'opacity 0.3s ease, width 0.3s ease',
352
+ willChange: 'opacity, width',
353
+ pointerEvents: (isMobileOpen || !isCollapsed) ? 'auto' : 'none',
354
+ }}>
355
+ <PCActionIcon
356
+ variant="default"
357
+ style={{ color: getVar('--pc-text-primary') }}
358
+ className="pc-hidden-md"
359
+ onClick={handleMobileClose}
360
+ aria-label="Close Sidebar Menu"
361
+ >
362
+ <IoCloseOutline size={20} />
363
+ </PCActionIcon>
364
+ </div>
365
+ </div>
366
+
367
+ <div style={{
368
+ flex: 1,
369
+ minHeight: 0,
370
+ display: 'flex',
371
+ flexDirection: 'column',
372
+ overflow: 'hidden',
373
+ position: 'relative',
374
+ }}>
375
+ <SimpleBar style={{
376
+ flex: 1,
377
+ minHeight: 0,
378
+ height: '100%',
379
+ overflowY: 'auto',
380
+ overflowX: 'hidden',
381
+ }}>
382
+ <SideMenuPC
383
+ menuItems={menuItems}
384
+ isCollapsed={isMobileOpen ? false : isCollapsed}
385
+ onItemSelect={handleMenuItemSelect}
386
+ />
387
+ </SimpleBar>
388
+ </div>
389
+
390
+ <div style={{
391
+ flexShrink: 0,
392
+ backgroundColor: getVar('--pc-bg-shell'),
393
+ paddingTop: '0.75rem',
394
+ paddingBottom: '0.75rem',
395
+ paddingLeft: isMobileOpen || !isCollapsed ? '1rem' : '0.5rem',
396
+ paddingRight: isMobileOpen || !isCollapsed ? '1rem' : '0.5rem',
397
+ minHeight: 'fit-content',
398
+ transition: 'padding-left 0.3s ease, padding-right 0.3s ease',
399
+ willChange: 'padding-left, padding-right',
400
+ }}>
401
+ <div style={emailContainerStyle}>
402
+ <PCText size="sm" color="secondary" style={{
403
+ maxWidth: '100%',
404
+ overflow: 'hidden',
405
+ textOverflow: 'ellipsis',
406
+ whiteSpace: 'nowrap',
407
+ fontSize: pcStyles.textXs.fontSize,
408
+ color: getVar('--pc-text-secondary'),
409
+ lineHeight: 1.5,
410
+ }}>
411
+ {email}
412
+ </PCText>
413
+ </div>
414
+ {onBack && (
415
+ !isMobileOpen && isCollapsed ? (
416
+ <div style={{ display: 'flex', justifyContent: 'center' }}>
417
+ <PCTooltip content={footerActionLabel} placement="right" color="invert">
418
+ <div style={{ width: 'fit-content', margin: '0 auto' }}>
419
+ <PCButton
420
+ variant="text"
421
+ onClick={handleBack}
422
+ aria-label={footerActionLabel}
423
+ style={{
424
+ ...buttonStyle,
425
+ width: '2.25rem',
426
+ height: '2.25rem',
427
+ minHeight: '2.25rem',
428
+ padding: 0,
429
+ marginTop: email ? '0.5rem' : 0,
430
+ justifyContent: 'center',
431
+ alignItems: 'center',
432
+ fontSize: pcStyles.textSm.fontSize,
433
+ }}
434
+ >
435
+ {footerActionIcon}
436
+ </PCButton>
437
+ </div>
438
+ </PCTooltip>
439
+ </div>
440
+ ) : (
441
+ <PCButton
442
+ variant="text"
443
+ onClick={handleBack}
444
+ aria-label={footerActionLabel}
445
+ style={{
446
+ ...buttonStyle,
447
+ width: '100%',
448
+ padding: '0.4375rem 0',
449
+ marginTop: email && (isMobileOpen || !isCollapsed) ? '0.5rem' : 0,
450
+ justifyContent: (isMobileOpen || !isCollapsed) ? 'flex-start' : 'center',
451
+ fontSize: pcStyles.textSm.fontSize,
452
+ minHeight: 'auto',
453
+ }}
454
+ >
455
+ <span
456
+ style={{
457
+ marginRight: (isMobileOpen || !isCollapsed) ? '0.625rem' : 0,
458
+ display: 'inline-flex',
459
+ alignItems: 'center',
460
+ justifyContent: 'center',
461
+ }}
462
+ >
463
+ {footerActionIcon}
464
+ </span>
465
+ {(isMobileOpen || !isCollapsed) && (
466
+ <span style={{ whiteSpace: 'nowrap', lineHeight: 1.5 }}>{footerActionLabel}</span>
467
+ )}
468
+ </PCButton>
469
+ )
470
+ )}
471
+ </div>
472
+ </aside>
473
+ </>
474
+ );
475
+ }