@redacto.io/consent-sdk-react 6.0.0 → 7.1.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.
- package/.turbo/turbo-build.log +25 -24
- package/CHANGELOG.md +23 -0
- package/dist/index.js +228 -166
- package/dist/index.mjs +228 -166
- package/dist/privacy-center.d.mts +2 -4
- package/dist/privacy-center.d.ts +2 -4
- package/dist/privacy-center.js +1876 -2079
- package/dist/privacy-center.mjs +1470 -1679
- package/package.json +1 -1
- package/src/RedactoNoticeConsent/RedactoNoticeConsent.tsx +209 -155
- package/src/RedactoNoticeConsent/styles.ts +10 -1
- package/src/RedactoPrivacyCenter/PrivacyCenterLayout.tsx +6 -10
- package/src/RedactoPrivacyCenter/RedactoPrivacyCenter.tsx +18 -17
- package/src/RedactoPrivacyCenter/api/orgBranding.ts +9 -0
- package/src/RedactoPrivacyCenter/components/ConsentManager.tsx +16 -14
- package/src/RedactoPrivacyCenter/components/Form.tsx +3 -3
- package/src/RedactoPrivacyCenter/components/ModifyConsentModal.tsx +1 -1
- package/src/RedactoPrivacyCenter/components/PrivacyCenterLayout.tsx +0 -4
- package/src/RedactoPrivacyCenter/components/SideMenuBarPC/SideBarPC.tsx +16 -2
- package/src/RedactoPrivacyCenter/context/BrandingContext.tsx +44 -0
- package/src/RedactoPrivacyCenter/lib/types.ts +22 -0
- package/src/RedactoPrivacyCenter/styles/applyBrandingTheme.ts +66 -0
- package/src/RedactoPrivacyCenter/styles/injectStyles.ts +3 -111
- package/src/RedactoPrivacyCenter/styles/pcStyles.ts +3 -2
- package/src/RedactoPrivacyCenter/styles/variables.css +1 -43
- package/src/RedactoPrivacyCenter/ui/Footer.tsx +4 -10
- package/src/RedactoPrivacyCenter/components/ThemeTransitionOverlay.tsx +0 -85
- package/src/RedactoPrivacyCenter/context/theme.tsx +0 -127
- package/src/RedactoPrivacyCenter/ui/ThemeToggle.tsx +0 -70
package/package.json
CHANGED
|
@@ -1511,6 +1511,15 @@ export const RedactoNoticeConsent = ({
|
|
|
1511
1511
|
height: isMobile ? "auto" : undefined,
|
|
1512
1512
|
width: isMobile ? "auto" : undefined,
|
|
1513
1513
|
},
|
|
1514
|
+
topSection: {
|
|
1515
|
+
flexDirection: isMobile ? ("column" as const) : ("row" as const),
|
|
1516
|
+
alignItems: isMobile ? ("stretch" as const) : ("flex-start" as const),
|
|
1517
|
+
gap: isMobile ? "12px" : "10px",
|
|
1518
|
+
},
|
|
1519
|
+
logo: {
|
|
1520
|
+
maxWidth: isMobile ? "96px" : "140px",
|
|
1521
|
+
maxHeight: isMobile ? "28px" : "32px",
|
|
1522
|
+
},
|
|
1514
1523
|
languageItem: {
|
|
1515
1524
|
fontSize: isMobile ? "11px" : "12px",
|
|
1516
1525
|
padding: isMobile ? "6px 10px" : "8px 12px",
|
|
@@ -3663,176 +3672,221 @@ export const RedactoNoticeConsent = ({
|
|
|
3663
3672
|
</button>
|
|
3664
3673
|
</div>
|
|
3665
3674
|
)}
|
|
3666
|
-
<div
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
3670
|
-
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
|
|
3679
|
-
|
|
3680
|
-
|
|
3681
|
-
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3675
|
+
<div
|
|
3676
|
+
style={{
|
|
3677
|
+
...styles.topSection,
|
|
3678
|
+
...responsiveStyles.topSection,
|
|
3679
|
+
...sectionStyle,
|
|
3680
|
+
}}
|
|
3681
|
+
>
|
|
3682
|
+
{(() => {
|
|
3683
|
+
const logoNode = (
|
|
3684
|
+
<img
|
|
3685
|
+
style={{ ...styles.logo, ...responsiveStyles.logo }}
|
|
3686
|
+
src={content?.logo_url || logo}
|
|
3687
|
+
alt="Redacto Logo"
|
|
3688
|
+
/>
|
|
3689
|
+
);
|
|
3690
|
+
const titleNode = (
|
|
3691
|
+
<h2
|
|
3692
|
+
key={`privacy-notice-title-${selectedLanguage}`}
|
|
3693
|
+
id="privacy-notice-title"
|
|
3694
|
+
style={{
|
|
3695
|
+
...styles.title,
|
|
3696
|
+
...responsiveStyles.title,
|
|
3697
|
+
...componentHeadingStyle,
|
|
3698
|
+
}}
|
|
3699
|
+
>
|
|
3700
|
+
{getTranslatedText(
|
|
3701
|
+
"notice_banner_heading",
|
|
3702
|
+
content?.notice_banner_heading || "Privacy Notice"
|
|
3703
|
+
)}
|
|
3704
|
+
</h2>
|
|
3705
|
+
);
|
|
3706
|
+
const controlsBlock = (
|
|
3707
|
+
<div style={styles.languageSelectorContainer}>
|
|
3708
|
+
<div
|
|
3700
3709
|
style={{
|
|
3701
|
-
...styles.topRight,
|
|
3702
|
-
...responsiveStyles.topRight,
|
|
3703
|
-
...languageSelectorStyle,
|
|
3704
|
-
padding: "3px 9px",
|
|
3705
3710
|
display: "flex",
|
|
3706
3711
|
alignItems: "center",
|
|
3707
|
-
|
|
3712
|
+
gap: "8px",
|
|
3708
3713
|
}}
|
|
3709
|
-
aria-label={
|
|
3710
|
-
isPlaying && !isPaused
|
|
3711
|
-
? "Pause audio playback"
|
|
3712
|
-
: isPaused
|
|
3713
|
-
? "Resume audio playback"
|
|
3714
|
-
: "Start audio playback"
|
|
3715
|
-
}
|
|
3716
|
-
title={
|
|
3717
|
-
isPlaying && !isPaused
|
|
3718
|
-
? "Pause Talkback"
|
|
3719
|
-
: isPaused
|
|
3720
|
-
? "Resume Talkback"
|
|
3721
|
-
: "Start Talkback"
|
|
3722
|
-
}
|
|
3723
3714
|
>
|
|
3724
|
-
{
|
|
3725
|
-
|
|
3726
|
-
<
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
"
|
|
3715
|
+
{/* Speaker icon button - only visible when TTS is available */}
|
|
3716
|
+
{isTTSAvailable && (
|
|
3717
|
+
<button
|
|
3718
|
+
onClick={toggleAudio}
|
|
3719
|
+
style={{
|
|
3720
|
+
...styles.topRight,
|
|
3721
|
+
...responsiveStyles.topRight,
|
|
3722
|
+
...languageSelectorStyle,
|
|
3723
|
+
padding: "3px 9px",
|
|
3724
|
+
display: "flex",
|
|
3725
|
+
alignItems: "center",
|
|
3726
|
+
justifyContent: "center",
|
|
3727
|
+
}}
|
|
3728
|
+
aria-label={
|
|
3729
|
+
isPlaying && !isPaused
|
|
3730
|
+
? "Pause audio playback"
|
|
3731
|
+
: isPaused
|
|
3732
|
+
? "Resume audio playback"
|
|
3733
|
+
: "Start audio playback"
|
|
3735
3734
|
}
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
<rect x="14" y="4" width="4" height="16" />
|
|
3743
|
-
</svg>
|
|
3744
|
-
) : (
|
|
3745
|
-
// Play/Sound icon
|
|
3746
|
-
<svg
|
|
3747
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
3748
|
-
width="16"
|
|
3749
|
-
height="16"
|
|
3750
|
-
viewBox="0 0 24 24"
|
|
3751
|
-
fill="none"
|
|
3752
|
-
stroke={
|
|
3753
|
-
settings?.button?.language?.textColor ||
|
|
3754
|
-
"currentColor"
|
|
3735
|
+
title={
|
|
3736
|
+
isPlaying && !isPaused
|
|
3737
|
+
? "Pause Talkback"
|
|
3738
|
+
: isPaused
|
|
3739
|
+
? "Resume Talkback"
|
|
3740
|
+
: "Start Talkback"
|
|
3755
3741
|
}
|
|
3756
|
-
strokeWidth="2"
|
|
3757
|
-
strokeLinecap="round"
|
|
3758
|
-
strokeLinejoin="round"
|
|
3759
|
-
aria-hidden="true"
|
|
3760
3742
|
>
|
|
3761
|
-
|
|
3762
|
-
|
|
3763
|
-
|
|
3743
|
+
{isPlaying && !isPaused ? (
|
|
3744
|
+
// Pause icon
|
|
3745
|
+
<svg
|
|
3746
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
3747
|
+
width="16"
|
|
3748
|
+
height="16"
|
|
3749
|
+
viewBox="0 0 24 24"
|
|
3750
|
+
fill="none"
|
|
3751
|
+
stroke={
|
|
3752
|
+
settings?.button?.language?.textColor ||
|
|
3753
|
+
"currentColor"
|
|
3754
|
+
}
|
|
3755
|
+
strokeWidth="2"
|
|
3756
|
+
strokeLinecap="round"
|
|
3757
|
+
strokeLinejoin="round"
|
|
3758
|
+
aria-hidden="true"
|
|
3759
|
+
>
|
|
3760
|
+
<rect x="6" y="4" width="4" height="16" />
|
|
3761
|
+
<rect x="14" y="4" width="4" height="16" />
|
|
3762
|
+
</svg>
|
|
3763
|
+
) : (
|
|
3764
|
+
// Play/Sound icon
|
|
3765
|
+
<svg
|
|
3766
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
3767
|
+
width="16"
|
|
3768
|
+
height="16"
|
|
3769
|
+
viewBox="0 0 24 24"
|
|
3770
|
+
fill="none"
|
|
3771
|
+
stroke={
|
|
3772
|
+
settings?.button?.language?.textColor ||
|
|
3773
|
+
"currentColor"
|
|
3774
|
+
}
|
|
3775
|
+
strokeWidth="2"
|
|
3776
|
+
strokeLinecap="round"
|
|
3777
|
+
strokeLinejoin="round"
|
|
3778
|
+
aria-hidden="true"
|
|
3779
|
+
>
|
|
3780
|
+
<polygon points="11 5 6 9 2 9 2 15 6 15 11 19 11 5" />
|
|
3781
|
+
<path d="M19.07 4.93a10 10 0 0 1 0 14.14M15.54 8.46a5 5 0 0 1 0 7.07" />
|
|
3782
|
+
</svg>
|
|
3783
|
+
)}
|
|
3784
|
+
</button>
|
|
3764
3785
|
)}
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
|
|
3769
|
-
|
|
3786
|
+
<div>
|
|
3787
|
+
<button
|
|
3788
|
+
ref={firstFocusableRef}
|
|
3789
|
+
style={{
|
|
3790
|
+
...styles.topRight,
|
|
3791
|
+
...responsiveStyles.topRight,
|
|
3792
|
+
...languageSelectorStyle,
|
|
3793
|
+
}}
|
|
3794
|
+
onClick={toggleLanguageDropdown}
|
|
3795
|
+
aria-expanded={isLanguageDropdownOpen}
|
|
3796
|
+
aria-haspopup="listbox"
|
|
3797
|
+
aria-controls="language-listbox"
|
|
3798
|
+
aria-label={`Select language. Current language: ${toNativeLabel(selectedLanguage)}`}
|
|
3799
|
+
>
|
|
3800
|
+
{toNativeLabel(selectedLanguage)}
|
|
3801
|
+
<svg
|
|
3802
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
3803
|
+
width="16"
|
|
3804
|
+
height="16"
|
|
3805
|
+
viewBox="0 0 16 16"
|
|
3806
|
+
fill="none"
|
|
3807
|
+
stroke={
|
|
3808
|
+
settings?.button?.language?.textColor ||
|
|
3809
|
+
"currentColor"
|
|
3810
|
+
}
|
|
3811
|
+
strokeWidth="2"
|
|
3812
|
+
strokeLinecap="round"
|
|
3813
|
+
strokeLinejoin="round"
|
|
3814
|
+
style={{ flexShrink: 0, marginLeft: "4px" }}
|
|
3815
|
+
aria-hidden="true"
|
|
3816
|
+
>
|
|
3817
|
+
<path d="M4 6l4 4 4-4" />
|
|
3818
|
+
</svg>
|
|
3819
|
+
</button>
|
|
3820
|
+
</div>
|
|
3821
|
+
</div>
|
|
3822
|
+
{isLanguageDropdownOpen && (
|
|
3823
|
+
<ul
|
|
3824
|
+
id="language-listbox"
|
|
3825
|
+
style={{
|
|
3826
|
+
...styles.languageDropdown,
|
|
3827
|
+
...languageSelectorStyle,
|
|
3828
|
+
}}
|
|
3829
|
+
role="listbox"
|
|
3830
|
+
aria-label="Select language"
|
|
3831
|
+
>
|
|
3832
|
+
{availableLanguages.map((lang: string) => (
|
|
3833
|
+
<li
|
|
3834
|
+
key={lang}
|
|
3835
|
+
style={{
|
|
3836
|
+
...styles.languageItem,
|
|
3837
|
+
...responsiveStyles.languageItem,
|
|
3838
|
+
...(selectedLanguage === lang
|
|
3839
|
+
? selectedLanguageItemStyle
|
|
3840
|
+
: languageSelectorStyle),
|
|
3841
|
+
listStyle: "none",
|
|
3842
|
+
}}
|
|
3843
|
+
onClick={() => handleLanguageSelect(lang)}
|
|
3844
|
+
role="option"
|
|
3845
|
+
aria-selected={selectedLanguage === lang}
|
|
3846
|
+
tabIndex={0}
|
|
3847
|
+
aria-label={`Select ${toNativeLabel(lang)} language`}
|
|
3848
|
+
>
|
|
3849
|
+
{toNativeLabel(lang)}
|
|
3850
|
+
</li>
|
|
3851
|
+
))}
|
|
3852
|
+
</ul>
|
|
3853
|
+
)}
|
|
3854
|
+
</div>
|
|
3855
|
+
);
|
|
3856
|
+
return isMobile ? (
|
|
3857
|
+
<>
|
|
3858
|
+
<div
|
|
3770
3859
|
style={{
|
|
3771
|
-
|
|
3772
|
-
|
|
3773
|
-
|
|
3860
|
+
display: "flex",
|
|
3861
|
+
alignItems: "center",
|
|
3862
|
+
gap: "10px",
|
|
3863
|
+
width: "100%",
|
|
3774
3864
|
}}
|
|
3775
|
-
onClick={toggleLanguageDropdown}
|
|
3776
|
-
aria-expanded={isLanguageDropdownOpen}
|
|
3777
|
-
aria-haspopup="listbox"
|
|
3778
|
-
aria-controls="language-listbox"
|
|
3779
|
-
aria-label={`Select language. Current language: ${toNativeLabel(selectedLanguage)}`}
|
|
3780
3865
|
>
|
|
3781
|
-
{
|
|
3782
|
-
<
|
|
3783
|
-
xmlns="http://www.w3.org/2000/svg"
|
|
3784
|
-
width="16"
|
|
3785
|
-
height="16"
|
|
3786
|
-
viewBox="0 0 16 16"
|
|
3787
|
-
fill="none"
|
|
3788
|
-
stroke={
|
|
3789
|
-
settings?.button?.language?.textColor ||
|
|
3790
|
-
"currentColor"
|
|
3791
|
-
}
|
|
3792
|
-
strokeWidth="2"
|
|
3793
|
-
strokeLinecap="round"
|
|
3794
|
-
strokeLinejoin="round"
|
|
3795
|
-
style={{ flexShrink: 0, marginLeft: "4px" }}
|
|
3796
|
-
aria-hidden="true"
|
|
3797
|
-
>
|
|
3798
|
-
<path d="M4 6l4 4 4-4" />
|
|
3799
|
-
</svg>
|
|
3800
|
-
</button>
|
|
3801
|
-
</div>
|
|
3802
|
-
</div>
|
|
3803
|
-
{isLanguageDropdownOpen && (
|
|
3804
|
-
<ul
|
|
3805
|
-
id="language-listbox"
|
|
3806
|
-
style={{
|
|
3807
|
-
...styles.languageDropdown,
|
|
3808
|
-
...languageSelectorStyle,
|
|
3809
|
-
}}
|
|
3810
|
-
role="listbox"
|
|
3811
|
-
aria-label="Select language"
|
|
3812
|
-
>
|
|
3813
|
-
{availableLanguages.map((lang: string) => (
|
|
3814
|
-
<li
|
|
3815
|
-
key={lang}
|
|
3866
|
+
{logoNode}
|
|
3867
|
+
<div
|
|
3816
3868
|
style={{
|
|
3817
|
-
|
|
3818
|
-
|
|
3819
|
-
|
|
3820
|
-
|
|
3821
|
-
: languageSelectorStyle),
|
|
3822
|
-
listStyle: "none",
|
|
3869
|
+
marginLeft: "auto",
|
|
3870
|
+
display: "flex",
|
|
3871
|
+
alignItems: "center",
|
|
3872
|
+
flexShrink: 0,
|
|
3823
3873
|
}}
|
|
3824
|
-
onClick={() => handleLanguageSelect(lang)}
|
|
3825
|
-
role="option"
|
|
3826
|
-
aria-selected={selectedLanguage === lang}
|
|
3827
|
-
tabIndex={0}
|
|
3828
|
-
aria-label={`Select ${toNativeLabel(lang)} language`}
|
|
3829
3874
|
>
|
|
3830
|
-
{
|
|
3831
|
-
</
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3875
|
+
{controlsBlock}
|
|
3876
|
+
</div>
|
|
3877
|
+
</div>
|
|
3878
|
+
{titleNode}
|
|
3879
|
+
</>
|
|
3880
|
+
) : (
|
|
3881
|
+
<>
|
|
3882
|
+
<div style={styles.topLeft}>
|
|
3883
|
+
{logoNode}
|
|
3884
|
+
{titleNode}
|
|
3885
|
+
</div>
|
|
3886
|
+
{controlsBlock}
|
|
3887
|
+
</>
|
|
3888
|
+
);
|
|
3889
|
+
})()}
|
|
3836
3890
|
</div>
|
|
3837
3891
|
<div
|
|
3838
3892
|
id="privacy-notice-description"
|
|
@@ -52,7 +52,8 @@ export const styles = {
|
|
|
52
52
|
topSection: {
|
|
53
53
|
display: "flex",
|
|
54
54
|
justifyContent: "space-between",
|
|
55
|
-
alignItems: "
|
|
55
|
+
alignItems: "flex-start",
|
|
56
|
+
gap: "10px",
|
|
56
57
|
paddingBottom: "15px",
|
|
57
58
|
borderBottom: "none",
|
|
58
59
|
backgroundColor: "#ffffff",
|
|
@@ -65,6 +66,8 @@ export const styles = {
|
|
|
65
66
|
display: "flex",
|
|
66
67
|
alignItems: "center",
|
|
67
68
|
gap: "10px",
|
|
69
|
+
flex: "1 1 0",
|
|
70
|
+
minWidth: 0,
|
|
68
71
|
margin: 0,
|
|
69
72
|
padding: 0,
|
|
70
73
|
boxSizing: "border-box",
|
|
@@ -73,7 +76,9 @@ export const styles = {
|
|
|
73
76
|
logo: {
|
|
74
77
|
height: "32px",
|
|
75
78
|
width: "auto",
|
|
79
|
+
maxWidth: "140px",
|
|
76
80
|
objectFit: "contain",
|
|
81
|
+
flexShrink: 0,
|
|
77
82
|
margin: 0,
|
|
78
83
|
padding: 0,
|
|
79
84
|
display: "block",
|
|
@@ -86,6 +91,10 @@ export const styles = {
|
|
|
86
91
|
letterSpacing: "0.2px",
|
|
87
92
|
verticalAlign: "middle",
|
|
88
93
|
color: "#101828",
|
|
94
|
+
flex: "1 1 auto",
|
|
95
|
+
minWidth: 0,
|
|
96
|
+
wordBreak: "normal",
|
|
97
|
+
overflowWrap: "anywhere",
|
|
89
98
|
margin: 0,
|
|
90
99
|
padding: 0,
|
|
91
100
|
textAlign: "left",
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { useEffect, useState, useRef, type ReactNode } from 'react';
|
|
2
2
|
import { OrganizationProvider } from './context/OrganizationContext';
|
|
3
|
-
import { ThemeProvider } from './context/theme';
|
|
4
3
|
import type { OrganizationDetail } from './lib/types';
|
|
5
4
|
import {
|
|
6
5
|
checkAndRefreshAuth,
|
|
@@ -14,12 +13,11 @@ import PrivacyCenterLayoutComponent from './components/PrivacyCenterLayout';
|
|
|
14
13
|
|
|
15
14
|
interface PrivacyCenterLayoutProps {
|
|
16
15
|
children: ReactNode;
|
|
17
|
-
defaultTheme?: 'light' | 'dark';
|
|
18
16
|
slug: string;
|
|
19
17
|
onBack?: 'back' | 'signout';
|
|
20
18
|
}
|
|
21
19
|
|
|
22
|
-
export function PrivacyCenterLayout({ children,
|
|
20
|
+
export function PrivacyCenterLayout({ children, slug, onBack }: PrivacyCenterLayoutProps) {
|
|
23
21
|
const { consentClient } = useBaseUrl();
|
|
24
22
|
// Read accessToken from AuthContext so this effect re-runs after AuthProvider
|
|
25
23
|
// syncs JWT data to sessionStorage (fixes race condition where child effects
|
|
@@ -162,12 +160,10 @@ export function PrivacyCenterLayout({ children, defaultTheme, slug, onBack }: Pr
|
|
|
162
160
|
}
|
|
163
161
|
|
|
164
162
|
return (
|
|
165
|
-
<
|
|
166
|
-
<
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
</OrganizationProvider>
|
|
171
|
-
</ThemeProvider>
|
|
163
|
+
<OrganizationProvider organization={organization}>
|
|
164
|
+
<PrivacyCenterLayoutComponent onBack={onBack}>
|
|
165
|
+
{children}
|
|
166
|
+
</PrivacyCenterLayoutComponent>
|
|
167
|
+
</OrganizationProvider>
|
|
172
168
|
);
|
|
173
169
|
}
|
|
@@ -7,6 +7,7 @@ import { AuthProvider } from './context/AuthContext';
|
|
|
7
7
|
import { NavigationProvider } from './context/NavigationContext';
|
|
8
8
|
import type { InternalPage } from './context/NavigationContext';
|
|
9
9
|
import { PageChromeProvider } from './context/PageChromeContext';
|
|
10
|
+
import { BrandingProvider } from './context/BrandingContext';
|
|
10
11
|
import { injectPCStyles } from './styles/injectStyles';
|
|
11
12
|
|
|
12
13
|
// Inject Privacy Center CSS styles on module load
|
|
@@ -15,7 +16,6 @@ injectPCStyles();
|
|
|
15
16
|
interface RedactoPrivacyCenterProps {
|
|
16
17
|
baseUrl: string; // Consent server base URL
|
|
17
18
|
slug: string;
|
|
18
|
-
theme?: 'light' | 'dark';
|
|
19
19
|
accessToken: string;
|
|
20
20
|
refreshToken: string;
|
|
21
21
|
onError: (error: Error) => boolean;
|
|
@@ -26,7 +26,6 @@ interface RedactoPrivacyCenterProps {
|
|
|
26
26
|
export function RedactoPrivacyCenter({
|
|
27
27
|
baseUrl,
|
|
28
28
|
slug,
|
|
29
|
-
theme = 'light',
|
|
30
29
|
accessToken,
|
|
31
30
|
refreshToken,
|
|
32
31
|
onError,
|
|
@@ -35,21 +34,23 @@ export function RedactoPrivacyCenter({
|
|
|
35
34
|
}: RedactoPrivacyCenterProps) {
|
|
36
35
|
return (
|
|
37
36
|
<I18nextProvider i18n={i18n}>
|
|
38
|
-
<
|
|
39
|
-
<
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
<
|
|
46
|
-
<
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
37
|
+
<BrandingProvider slug={slug}>
|
|
38
|
+
<BaseUrlProvider baseUrl={baseUrl}>
|
|
39
|
+
<AuthProvider
|
|
40
|
+
accessToken={accessToken}
|
|
41
|
+
refreshToken={refreshToken}
|
|
42
|
+
onError={onError}
|
|
43
|
+
>
|
|
44
|
+
<NavigationProvider initialPage={initialPage}>
|
|
45
|
+
<PageChromeProvider>
|
|
46
|
+
<PrivacyCenterLayout slug={slug} onBack={onBack}>
|
|
47
|
+
<PrivacyCenterHomePage />
|
|
48
|
+
</PrivacyCenterLayout>
|
|
49
|
+
</PageChromeProvider>
|
|
50
|
+
</NavigationProvider>
|
|
51
|
+
</AuthProvider>
|
|
52
|
+
</BaseUrlProvider>
|
|
53
|
+
</BrandingProvider>
|
|
53
54
|
</I18nextProvider>
|
|
54
55
|
);
|
|
55
56
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { apiFetch } from './fetcher';
|
|
2
|
+
import type { OrgBrandingDetail } from '../lib/types';
|
|
3
|
+
|
|
4
|
+
const USER_SERVER_BASE_URL = 'https://api.redacto.tech/user/api/0';
|
|
5
|
+
|
|
6
|
+
export async function fetchOrgBranding(slug: string): Promise<OrgBrandingDetail> {
|
|
7
|
+
const url = `${USER_SERVER_BASE_URL}/public/org-branding/by-slug/${encodeURIComponent(slug)}`;
|
|
8
|
+
return apiFetch<OrgBrandingDetail>(url, { method: 'GET' });
|
|
9
|
+
}
|
|
@@ -447,12 +447,17 @@ export default function ConsentManager({ variant }: ConsentManagerProps) {
|
|
|
447
447
|
);
|
|
448
448
|
setConsentRows(filteredRows);
|
|
449
449
|
|
|
450
|
-
//
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
450
|
+
// Only refresh the product filter options from an unfiltered fetch.
|
|
451
|
+
// When a product filter is active the API returns rows for that one
|
|
452
|
+
// product, so re-deriving options here would shrink the dropdown to
|
|
453
|
+
// just the selected product (forcing the user to refresh to recover).
|
|
454
|
+
if (!productFilter) {
|
|
455
|
+
const combinedGroups = [
|
|
456
|
+
...(response.direct || []),
|
|
457
|
+
...(response.nominated || []),
|
|
458
|
+
];
|
|
459
|
+
setProductOptions(buildProductOptionsFromGroups(combinedGroups));
|
|
460
|
+
}
|
|
456
461
|
} catch (error) {
|
|
457
462
|
console.error(error);
|
|
458
463
|
setConsentDetail(null);
|
|
@@ -1122,14 +1127,11 @@ export default function ConsentManager({ variant }: ConsentManagerProps) {
|
|
|
1122
1127
|
</>
|
|
1123
1128
|
)}
|
|
1124
1129
|
|
|
1125
|
-
{
|
|
1126
|
-
|
|
1127
|
-
{viewMode === 'product' ? (
|
|
1130
|
+
{viewMode === 'product' && (
|
|
1131
|
+
<div className="pc-consent-pagination-wrap">
|
|
1128
1132
|
<AdvancedTablePagination table={productTable} />
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
)}
|
|
1132
|
-
</div>
|
|
1133
|
+
</div>
|
|
1134
|
+
)}
|
|
1133
1135
|
</div>
|
|
1134
1136
|
|
|
1135
1137
|
<PCModal
|
|
@@ -1153,7 +1155,7 @@ export default function ConsentManager({ variant }: ConsentManagerProps) {
|
|
|
1153
1155
|
}
|
|
1154
1156
|
footer={
|
|
1155
1157
|
<div className="pc-modal-footer-actions">
|
|
1156
|
-
<PCButton variant="
|
|
1158
|
+
<PCButton variant="secondary" onClick={() => setExportModal(false)}>
|
|
1157
1159
|
{t('cancel')}
|
|
1158
1160
|
</PCButton>
|
|
1159
1161
|
<PCButton variant="primary" onClick={handleExport}>
|
|
@@ -1483,11 +1483,11 @@ export default function Form({
|
|
|
1483
1483
|
className="pc-flex-responsive pc-spacing-responsive"
|
|
1484
1484
|
>
|
|
1485
1485
|
{isPopup ? (
|
|
1486
|
-
<PCButton variant="
|
|
1486
|
+
<PCButton variant="secondary" onClick={onClose} style={{ flexShrink: 0 }}>
|
|
1487
1487
|
{t('cancel') ?? 'Cancel'}
|
|
1488
1488
|
</PCButton>
|
|
1489
1489
|
) : (
|
|
1490
|
-
<PCButton variant="
|
|
1490
|
+
<PCButton variant="secondary" style={{ flexShrink: 0 }}>
|
|
1491
1491
|
{t('saveDraft')}
|
|
1492
1492
|
</PCButton>
|
|
1493
1493
|
)}
|
|
@@ -1523,7 +1523,7 @@ export default function Form({
|
|
|
1523
1523
|
footer={
|
|
1524
1524
|
<div className="pc-erasure-modal-footer">
|
|
1525
1525
|
<PCButton
|
|
1526
|
-
variant="
|
|
1526
|
+
variant="secondary"
|
|
1527
1527
|
onClick={() => handleErasureModalChoice(false)}
|
|
1528
1528
|
disabled={isLoading}
|
|
1529
1529
|
>
|