@redacto.io/consent-sdk-react 4.0.0 → 5.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/CHANGELOG.md +19 -1
- package/LICENSE +176 -0
- package/README.md +98 -1
- package/dist/index.js +231 -96
- package/dist/index.mjs +231 -96
- package/dist/privacy-center.d.mts +649 -0
- package/dist/privacy-center.d.ts +649 -0
- package/dist/privacy-center.js +20824 -0
- package/dist/privacy-center.mjs +20789 -0
- package/package.json +47 -3
- package/src/RedactoNoticeConsent/RedactoNoticeConsent.tsx +6 -4
- package/src/RedactoNoticeConsent/api/index.ts +2 -0
- package/src/RedactoNoticeConsent/api/types.ts +2 -0
- package/src/RedactoNoticeConsent/components/DigiLockerCallback.tsx +128 -62
- package/src/RedactoNoticeConsent/language-codes.ts +97 -0
- package/src/RedactoNoticeConsentInline/RedactoNoticeConsentInline.tsx +0 -3
- package/src/RedactoNoticeConsentInline/api/index.ts +0 -1
- package/src/RedactoPrivacyCenter/PrivacyCenterActivityPage.tsx +19 -0
- package/src/RedactoPrivacyCenter/PrivacyCenterCaseDetailsPage.tsx +154 -0
- package/src/RedactoPrivacyCenter/PrivacyCenterConsentManagerPage.tsx +17 -0
- package/src/RedactoPrivacyCenter/PrivacyCenterFormPage.tsx +79 -0
- package/src/RedactoPrivacyCenter/PrivacyCenterHomePage.tsx +30 -0
- package/src/RedactoPrivacyCenter/PrivacyCenterLayout.tsx +173 -0
- package/src/RedactoPrivacyCenter/RedactoPrivacyCenter.tsx +55 -0
- package/src/RedactoPrivacyCenter/api/actions.ts +476 -0
- package/src/RedactoPrivacyCenter/api/client.ts +524 -0
- package/src/RedactoPrivacyCenter/api/config.ts +33 -0
- package/src/RedactoPrivacyCenter/api/fetcher.ts +181 -0
- package/src/RedactoPrivacyCenter/api/upload.ts +93 -0
- package/src/RedactoPrivacyCenter/assets/character.svg +31 -0
- package/src/RedactoPrivacyCenter/assets/fileAttach.svg +9 -0
- package/src/RedactoPrivacyCenter/assets/greenTick.svg +4 -0
- package/src/RedactoPrivacyCenter/assets/mail.svg +3 -0
- package/src/RedactoPrivacyCenter/assets/poweredByRedacto.svg +9 -0
- package/src/RedactoPrivacyCenter/assets/sentImg.svg +9 -0
- package/src/RedactoPrivacyCenter/assets/uploadFileIcon.svg +9 -0
- package/src/RedactoPrivacyCenter/components/ActivitiesList.tsx +272 -0
- package/src/RedactoPrivacyCenter/components/CaseDetails/AttachmentCard.tsx +38 -0
- package/src/RedactoPrivacyCenter/components/CaseDetails/ChatBubble.tsx +31 -0
- package/src/RedactoPrivacyCenter/components/CaseDetails/DocumentRequestCard.tsx +73 -0
- package/src/RedactoPrivacyCenter/components/CaseDetails/MessageComposer.tsx +87 -0
- package/src/RedactoPrivacyCenter/components/CaseDetails/MessageItem.tsx +95 -0
- package/src/RedactoPrivacyCenter/components/CaseDetails/MessagesTab.tsx +147 -0
- package/src/RedactoPrivacyCenter/components/CaseDetails/RequestDetailsTab.tsx +171 -0
- package/src/RedactoPrivacyCenter/components/CaseDetails/StatusEvent.tsx +23 -0
- package/src/RedactoPrivacyCenter/components/CaseDetails/useFileUpload.ts +116 -0
- package/src/RedactoPrivacyCenter/components/CaseDetails/useMessagePolling.ts +36 -0
- package/src/RedactoPrivacyCenter/components/CaseDetails/utils.ts +56 -0
- package/src/RedactoPrivacyCenter/components/CaseDetailsModal.tsx +469 -0
- package/src/RedactoPrivacyCenter/components/CaseHistory.tsx +426 -0
- package/src/RedactoPrivacyCenter/components/ConsentManager.tsx +732 -0
- package/src/RedactoPrivacyCenter/components/ConsentManagerColumns.tsx +238 -0
- package/src/RedactoPrivacyCenter/components/ConsentManagerConstants.ts +7 -0
- package/src/RedactoPrivacyCenter/components/ConsentManagerTableSkeleton.tsx +155 -0
- package/src/RedactoPrivacyCenter/components/DataRequest/CorrectionDataSection.tsx +189 -0
- package/src/RedactoPrivacyCenter/components/DataRequest/GrievanceDataSection.tsx +118 -0
- package/src/RedactoPrivacyCenter/components/DataRequest/NominationDataSection.tsx +66 -0
- package/src/RedactoPrivacyCenter/components/DataRequest/PurposeSelectionSection.tsx +304 -0
- package/src/RedactoPrivacyCenter/components/Form.tsx +1596 -0
- package/src/RedactoPrivacyCenter/components/GrievanceTable.tsx +174 -0
- package/src/RedactoPrivacyCenter/components/GrievanceTablePagination.tsx +337 -0
- package/src/RedactoPrivacyCenter/components/ModifyConsentModal.tsx +330 -0
- package/src/RedactoPrivacyCenter/components/Pagination.tsx +140 -0
- package/src/RedactoPrivacyCenter/components/PrivacyCenterLayout.tsx +304 -0
- package/src/RedactoPrivacyCenter/components/RequestSubmit.tsx +232 -0
- package/src/RedactoPrivacyCenter/components/SideMenuBarPC/SideBarPC.tsx +475 -0
- package/src/RedactoPrivacyCenter/components/SideMenuBarPC/SideMenuPC.tsx +408 -0
- package/src/RedactoPrivacyCenter/components/SideMenuBarPC/constants.tsx +42 -0
- package/src/RedactoPrivacyCenter/components/SideMenuBarPC/menuItemsPC.tsx +1 -0
- package/src/RedactoPrivacyCenter/components/SideMenuBarPC/types.ts +40 -0
- package/src/RedactoPrivacyCenter/components/SideMenuBarPC/utils.ts +38 -0
- package/src/RedactoPrivacyCenter/components/ThemeTransitionOverlay.tsx +85 -0
- package/src/RedactoPrivacyCenter/components/activitiesColumns.tsx +141 -0
- package/src/RedactoPrivacyCenter/components/caseHistoryColumns.tsx +159 -0
- package/src/RedactoPrivacyCenter/components/constant.ts +16 -0
- package/src/RedactoPrivacyCenter/components/types.ts +76 -0
- package/src/RedactoPrivacyCenter/components/utils.tsx +10 -0
- package/src/RedactoPrivacyCenter/config/routes.ts +9 -0
- package/src/RedactoPrivacyCenter/config/table.ts +25 -0
- package/src/RedactoPrivacyCenter/context/AuthContext.tsx +137 -0
- package/src/RedactoPrivacyCenter/context/BaseUrlContext.tsx +41 -0
- package/src/RedactoPrivacyCenter/context/LocaleContext.tsx +11 -0
- package/src/RedactoPrivacyCenter/context/NavigationContext.tsx +96 -0
- package/src/RedactoPrivacyCenter/context/OrganizationContext.tsx +30 -0
- package/src/RedactoPrivacyCenter/context/PageChromeContext.tsx +60 -0
- package/src/RedactoPrivacyCenter/context/theme.tsx +127 -0
- package/src/RedactoPrivacyCenter/context/types.ts +14 -0
- package/src/RedactoPrivacyCenter/lib/api.ts +566 -0
- package/src/RedactoPrivacyCenter/lib/consent-manager/utils.tsx +63 -0
- package/src/RedactoPrivacyCenter/lib/constants.ts +161 -0
- package/src/RedactoPrivacyCenter/lib/i18n.ts +81 -0
- package/src/RedactoPrivacyCenter/lib/locales.ts +105 -0
- package/src/RedactoPrivacyCenter/lib/queries.ts +134 -0
- package/src/RedactoPrivacyCenter/lib/types.ts +531 -0
- package/src/RedactoPrivacyCenter/lib/useCurrentLanguage.ts +37 -0
- package/src/RedactoPrivacyCenter/lib/utils.ts +626 -0
- package/src/RedactoPrivacyCenter/locales/as/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/bho/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/bn/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/brx/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/doi/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/en/translation.json +255 -0
- package/src/RedactoPrivacyCenter/locales/gom/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/gu/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/hi/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/kn/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/ks/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/mai/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/ml/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/mni-Mtei/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/mr/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/ne/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/or/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/pa/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/sa/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/sat/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/sd/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/ta/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/te/translation.json +280 -0
- package/src/RedactoPrivacyCenter/locales/ur/translation.json +280 -0
- package/src/RedactoPrivacyCenter/styles/base.css +117 -0
- package/src/RedactoPrivacyCenter/styles/injectStyles.ts +1725 -0
- package/src/RedactoPrivacyCenter/styles/pcStyles.ts +813 -0
- package/src/RedactoPrivacyCenter/styles/responsive.ts +138 -0
- package/src/RedactoPrivacyCenter/styles/variables.css +133 -0
- package/src/RedactoPrivacyCenter/table/AdvancedTable.tsx +367 -0
- package/src/RedactoPrivacyCenter/table/AdvancedTablePagination.tsx +476 -0
- package/src/RedactoPrivacyCenter/table/index.ts +2 -0
- package/src/RedactoPrivacyCenter/types/images.d.ts +29 -0
- package/src/RedactoPrivacyCenter/ui/Footer.tsx +75 -0
- package/src/RedactoPrivacyCenter/ui/FormBlockWrapper.tsx +54 -0
- package/src/RedactoPrivacyCenter/ui/PCAccordion.tsx +93 -0
- package/src/RedactoPrivacyCenter/ui/PCActionIcon.tsx +47 -0
- package/src/RedactoPrivacyCenter/ui/PCAvatar.tsx +69 -0
- package/src/RedactoPrivacyCenter/ui/PCBadge.tsx +48 -0
- package/src/RedactoPrivacyCenter/ui/PCButton.tsx +77 -0
- package/src/RedactoPrivacyCenter/ui/PCCheckbox.tsx +55 -0
- package/src/RedactoPrivacyCenter/ui/PCCollapse.tsx +107 -0
- package/src/RedactoPrivacyCenter/ui/PCEmpty.tsx +35 -0
- package/src/RedactoPrivacyCenter/ui/PCInput.tsx +132 -0
- package/src/RedactoPrivacyCenter/ui/PCLoader.tsx +31 -0
- package/src/RedactoPrivacyCenter/ui/PCModal.tsx +106 -0
- package/src/RedactoPrivacyCenter/ui/PCPopover.tsx +173 -0
- package/src/RedactoPrivacyCenter/ui/PCSelect.tsx +387 -0
- package/src/RedactoPrivacyCenter/ui/PCTable.tsx +149 -0
- package/src/RedactoPrivacyCenter/ui/PCText.tsx +41 -0
- package/src/RedactoPrivacyCenter/ui/PCTextarea.tsx +43 -0
- package/src/RedactoPrivacyCenter/ui/PCTitle.tsx +37 -0
- package/src/RedactoPrivacyCenter/ui/PCTooltip.tsx +119 -0
- package/src/RedactoPrivacyCenter/ui/SimpleBar.tsx +25 -0
- package/src/RedactoPrivacyCenter/ui/StatusBadge.tsx +53 -0
- package/src/RedactoPrivacyCenter/ui/ThemeToggle.tsx +72 -0
- package/src/RedactoPrivacyCenter/ui/index.ts +18 -0
- package/src/RedactoPrivacyCenter/utils/cn.ts +28 -0
- package/src/RedactoPrivacyCenter/utils/date.ts +48 -0
- package/src/RedactoPrivacyCenter/utils/status.ts +111 -0
- package/src/RedactoPrivacyCenter/utils/toast.ts +130 -0
- package/src/privacy-center.ts +108 -0
- package/tsconfig.json +2 -0
- package/tsup.config.ts +16 -1
- package/.turbo/turbo-build.log +0 -21
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { type ReactNode, type CSSProperties, type HTMLAttributes, type TdHTMLAttributes, type ThHTMLAttributes, createContext } from 'react';
|
|
2
|
+
import { pcStyles } from '../styles/pcStyles';
|
|
3
|
+
|
|
4
|
+
interface TableContextValue {
|
|
5
|
+
variant?: 'modern' | 'minimal';
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const TableContext = createContext<TableContextValue>({});
|
|
9
|
+
|
|
10
|
+
// Main Table component
|
|
11
|
+
export type PCTableProps = Readonly<
|
|
12
|
+
HTMLAttributes<HTMLTableElement> & {
|
|
13
|
+
children: ReactNode;
|
|
14
|
+
variant?: 'modern' | 'minimal';
|
|
15
|
+
className?: string;
|
|
16
|
+
style?: CSSProperties;
|
|
17
|
+
}
|
|
18
|
+
>;
|
|
19
|
+
|
|
20
|
+
export function PCTable({ children, variant = 'modern', className = '', style = {}, ...props }: PCTableProps) {
|
|
21
|
+
const tableStyle: CSSProperties = {
|
|
22
|
+
...pcStyles.table,
|
|
23
|
+
...style,
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<TableContext.Provider value={{ variant }}>
|
|
28
|
+
<table className={className} style={tableStyle} {...props}>
|
|
29
|
+
{children}
|
|
30
|
+
</table>
|
|
31
|
+
</TableContext.Provider>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Header component
|
|
36
|
+
export type PCTableHeaderProps = Readonly<
|
|
37
|
+
HTMLAttributes<HTMLTableSectionElement> & {
|
|
38
|
+
children: ReactNode;
|
|
39
|
+
className?: string;
|
|
40
|
+
style?: CSSProperties;
|
|
41
|
+
}
|
|
42
|
+
>;
|
|
43
|
+
|
|
44
|
+
export function PCTableHeader({ children, className = '', style = {}, ...props }: PCTableHeaderProps) {
|
|
45
|
+
const headerStyle: CSSProperties = {
|
|
46
|
+
...pcStyles.tableHeader,
|
|
47
|
+
...style,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<thead className={className} style={headerStyle} {...props}>
|
|
52
|
+
{children}
|
|
53
|
+
</thead>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// Body component
|
|
58
|
+
export type PCTableBodyProps = Readonly<
|
|
59
|
+
HTMLAttributes<HTMLTableSectionElement> & {
|
|
60
|
+
children: ReactNode;
|
|
61
|
+
className?: string;
|
|
62
|
+
style?: CSSProperties;
|
|
63
|
+
}
|
|
64
|
+
>;
|
|
65
|
+
|
|
66
|
+
export function PCTableBody({ children, className = '', style = {}, ...props }: PCTableBodyProps) {
|
|
67
|
+
const bodyStyle: CSSProperties = {
|
|
68
|
+
...style,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
return (
|
|
72
|
+
<tbody className={className} style={bodyStyle} {...props}>
|
|
73
|
+
{children}
|
|
74
|
+
</tbody>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Row component
|
|
79
|
+
export type PCTableRowProps = Readonly<
|
|
80
|
+
HTMLAttributes<HTMLTableRowElement> & {
|
|
81
|
+
children: ReactNode;
|
|
82
|
+
className?: string;
|
|
83
|
+
style?: CSSProperties;
|
|
84
|
+
}
|
|
85
|
+
>;
|
|
86
|
+
|
|
87
|
+
export function PCTableRow({ children, className = '', style = {}, ...props }: PCTableRowProps) {
|
|
88
|
+
const rowStyle: CSSProperties = {
|
|
89
|
+
...pcStyles.tableRow,
|
|
90
|
+
...style,
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<tr className={`pc-table-row ${className}`} style={rowStyle} {...props}>
|
|
95
|
+
{children}
|
|
96
|
+
</tr>
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Header Cell component
|
|
101
|
+
export type PCTableHeadProps = Readonly<
|
|
102
|
+
ThHTMLAttributes<HTMLTableCellElement> & {
|
|
103
|
+
children: ReactNode;
|
|
104
|
+
className?: string;
|
|
105
|
+
style?: CSSProperties;
|
|
106
|
+
}
|
|
107
|
+
>;
|
|
108
|
+
|
|
109
|
+
export function PCTableHead({ children, className = '', style = {}, ...props }: PCTableHeadProps) {
|
|
110
|
+
const headStyle: CSSProperties = {
|
|
111
|
+
...pcStyles.tableHeaderCell,
|
|
112
|
+
...style,
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
return (
|
|
116
|
+
<th className={className} style={headStyle} {...props}>
|
|
117
|
+
{children}
|
|
118
|
+
</th>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Cell component
|
|
123
|
+
export type PCTableCellProps = Readonly<
|
|
124
|
+
TdHTMLAttributes<HTMLTableCellElement> & {
|
|
125
|
+
children: ReactNode;
|
|
126
|
+
className?: string;
|
|
127
|
+
style?: CSSProperties;
|
|
128
|
+
}
|
|
129
|
+
>;
|
|
130
|
+
|
|
131
|
+
export function PCTableCell({ children, className = '', style = {}, ...props }: PCTableCellProps) {
|
|
132
|
+
const cellStyle: CSSProperties = {
|
|
133
|
+
...pcStyles.tableCell,
|
|
134
|
+
...style,
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
return (
|
|
138
|
+
<td className={className} style={cellStyle} {...props}>
|
|
139
|
+
{children}
|
|
140
|
+
</td>
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Compound component pattern
|
|
145
|
+
PCTable.Header = PCTableHeader;
|
|
146
|
+
PCTable.Body = PCTableBody;
|
|
147
|
+
PCTable.Row = PCTableRow;
|
|
148
|
+
PCTable.Head = PCTableHead;
|
|
149
|
+
PCTable.Cell = PCTableCell;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type ReactNode, type CSSProperties } from 'react';
|
|
2
|
+
import { pcStyles } from '../styles/pcStyles';
|
|
3
|
+
|
|
4
|
+
export type PCTextProps = Readonly<{
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
className?: string;
|
|
7
|
+
style?: CSSProperties;
|
|
8
|
+
as?: 'p' | 'span' | 'div' | 'label';
|
|
9
|
+
size?: 'xs' | 'sm' | 'base' | 'lg' | 'xl' | '2xl' | '3xl';
|
|
10
|
+
weight?: 'normal' | 'medium' | 'semibold' | 'bold';
|
|
11
|
+
color?: 'primary' | 'secondary' | 'tertiary' | 'inverse' | 'disabled';
|
|
12
|
+
align?: 'left' | 'center' | 'right';
|
|
13
|
+
title?: string;
|
|
14
|
+
}>;
|
|
15
|
+
|
|
16
|
+
export function PCText({
|
|
17
|
+
children,
|
|
18
|
+
className = '',
|
|
19
|
+
style = {},
|
|
20
|
+
as: Component = 'p',
|
|
21
|
+
size = 'base',
|
|
22
|
+
weight = 'normal',
|
|
23
|
+
color = 'primary',
|
|
24
|
+
align,
|
|
25
|
+
title,
|
|
26
|
+
}: PCTextProps) {
|
|
27
|
+
const baseStyle: CSSProperties = {
|
|
28
|
+
...pcStyles.text,
|
|
29
|
+
...pcStyles[`text${size.charAt(0).toUpperCase() + size.slice(1)}` as keyof typeof pcStyles] as CSSProperties,
|
|
30
|
+
...pcStyles[`fontWeight${weight.charAt(0).toUpperCase() + weight.slice(1)}` as keyof typeof pcStyles] as CSSProperties,
|
|
31
|
+
...pcStyles[`text${color.charAt(0).toUpperCase() + color.slice(1)}` as keyof typeof pcStyles] as CSSProperties,
|
|
32
|
+
...(align && pcStyles[`text${align.charAt(0).toUpperCase() + align.slice(1)}` as keyof typeof pcStyles] as CSSProperties),
|
|
33
|
+
...style,
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<Component className={className} style={baseStyle} title={title}>
|
|
38
|
+
{children}
|
|
39
|
+
</Component>
|
|
40
|
+
);
|
|
41
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { type ReactNode, type CSSProperties, type TextareaHTMLAttributes } from 'react';
|
|
2
|
+
import { pcStyles } from '../styles/pcStyles';
|
|
3
|
+
|
|
4
|
+
export interface PCTextareaProps extends Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'style' | 'size'> {
|
|
5
|
+
className?: string;
|
|
6
|
+
style?: CSSProperties;
|
|
7
|
+
label?: ReactNode;
|
|
8
|
+
error?: boolean;
|
|
9
|
+
size?: 'sm' | 'md' | 'lg';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export function PCTextarea({
|
|
13
|
+
className = '',
|
|
14
|
+
style = {},
|
|
15
|
+
label,
|
|
16
|
+
error = false,
|
|
17
|
+
size = 'md',
|
|
18
|
+
...props
|
|
19
|
+
}: PCTextareaProps) {
|
|
20
|
+
const textareaStyle: CSSProperties = {
|
|
21
|
+
...pcStyles.textarea,
|
|
22
|
+
...(size === 'sm' && pcStyles.inputSm),
|
|
23
|
+
...(size === 'lg' && pcStyles.inputLg),
|
|
24
|
+
...(error && pcStyles.inputError),
|
|
25
|
+
...(props.disabled && pcStyles.inputDisabled),
|
|
26
|
+
...style,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const wrapperStyle: CSSProperties = {
|
|
30
|
+
...pcStyles.inputWrapper,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<div className={className} style={wrapperStyle}>
|
|
35
|
+
{label && <label style={pcStyles.inputLabel}>{label}</label>}
|
|
36
|
+
<textarea
|
|
37
|
+
className="pc-textarea"
|
|
38
|
+
style={textareaStyle}
|
|
39
|
+
{...props}
|
|
40
|
+
/>
|
|
41
|
+
</div>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type ReactNode, type CSSProperties } from 'react';
|
|
2
|
+
import { pcStyles } from '../styles/pcStyles';
|
|
3
|
+
|
|
4
|
+
export interface PCTitleProps {
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
className?: string;
|
|
7
|
+
style?: CSSProperties;
|
|
8
|
+
as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function PCTitle({
|
|
12
|
+
children,
|
|
13
|
+
className = '',
|
|
14
|
+
style = {},
|
|
15
|
+
as: Component = 'h3',
|
|
16
|
+
}: PCTitleProps) {
|
|
17
|
+
const sizeMap: Record<string, keyof typeof pcStyles> = {
|
|
18
|
+
h1: 'titleH1',
|
|
19
|
+
h2: 'titleH2',
|
|
20
|
+
h3: 'titleH3',
|
|
21
|
+
h4: 'titleH4',
|
|
22
|
+
h5: 'titleH5',
|
|
23
|
+
h6: 'titleH6',
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const baseStyle: CSSProperties = {
|
|
27
|
+
...pcStyles.title,
|
|
28
|
+
...(pcStyles[sizeMap[Component] as keyof typeof pcStyles] as CSSProperties),
|
|
29
|
+
...style,
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<Component className={className} style={baseStyle}>
|
|
34
|
+
{children}
|
|
35
|
+
</Component>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { type ReactNode, type CSSProperties, useState, useRef, useEffect } from 'react';
|
|
2
|
+
import { createPortal } from 'react-dom';
|
|
3
|
+
import { pcStyles } from '../styles/pcStyles';
|
|
4
|
+
|
|
5
|
+
export interface PCTooltipProps {
|
|
6
|
+
content: ReactNode;
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
placement?: 'top' | 'bottom' | 'left' | 'right';
|
|
9
|
+
className?: string;
|
|
10
|
+
style?: CSSProperties;
|
|
11
|
+
color?: 'default' | 'invert';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function PCTooltip({
|
|
15
|
+
content,
|
|
16
|
+
children,
|
|
17
|
+
placement = 'top',
|
|
18
|
+
className = '',
|
|
19
|
+
style = {},
|
|
20
|
+
color = 'default',
|
|
21
|
+
}: PCTooltipProps) {
|
|
22
|
+
const [isVisible, setIsVisible] = useState(false);
|
|
23
|
+
const [position, setPosition] = useState({ top: 0, left: 0 });
|
|
24
|
+
const triggerRef = useRef<HTMLDivElement>(null);
|
|
25
|
+
const tooltipRef = useRef<HTMLDivElement>(null);
|
|
26
|
+
|
|
27
|
+
const updatePosition = () => {
|
|
28
|
+
if (!triggerRef.current || !tooltipRef.current) return;
|
|
29
|
+
|
|
30
|
+
const triggerRect = triggerRef.current.getBoundingClientRect();
|
|
31
|
+
const tooltipRect = tooltipRef.current.getBoundingClientRect();
|
|
32
|
+
const gap = 2;
|
|
33
|
+
const viewportGutter = 12;
|
|
34
|
+
|
|
35
|
+
let top = 0;
|
|
36
|
+
let left = 0;
|
|
37
|
+
|
|
38
|
+
switch (placement) {
|
|
39
|
+
case 'top':
|
|
40
|
+
top = triggerRect.top - tooltipRect.height - gap;
|
|
41
|
+
left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;
|
|
42
|
+
break;
|
|
43
|
+
case 'bottom':
|
|
44
|
+
top = triggerRect.bottom + gap;
|
|
45
|
+
left = triggerRect.left + (triggerRect.width - tooltipRect.width) / 2;
|
|
46
|
+
break;
|
|
47
|
+
case 'left':
|
|
48
|
+
top = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2;
|
|
49
|
+
left = triggerRect.left - tooltipRect.width - gap;
|
|
50
|
+
break;
|
|
51
|
+
case 'right':
|
|
52
|
+
top = triggerRect.top + (triggerRect.height - tooltipRect.height) / 2;
|
|
53
|
+
left = triggerRect.right + gap;
|
|
54
|
+
break;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const maxLeft = window.innerWidth - tooltipRect.width - viewportGutter;
|
|
58
|
+
const maxTop = window.innerHeight - tooltipRect.height - viewportGutter;
|
|
59
|
+
|
|
60
|
+
left = Math.min(Math.max(left, viewportGutter), Math.max(viewportGutter, maxLeft));
|
|
61
|
+
top = Math.min(Math.max(top, viewportGutter), Math.max(viewportGutter, maxTop));
|
|
62
|
+
|
|
63
|
+
setPosition({ top, left });
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (isVisible) {
|
|
68
|
+
updatePosition();
|
|
69
|
+
window.addEventListener('scroll', updatePosition, true);
|
|
70
|
+
window.addEventListener('resize', updatePosition);
|
|
71
|
+
return () => {
|
|
72
|
+
window.removeEventListener('scroll', updatePosition, true);
|
|
73
|
+
window.removeEventListener('resize', updatePosition);
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}, [isVisible, placement]);
|
|
77
|
+
|
|
78
|
+
const tooltipStyle: CSSProperties = {
|
|
79
|
+
...pcStyles.tooltip,
|
|
80
|
+
...(color === 'invert' && {
|
|
81
|
+
backgroundColor: '#ffffff',
|
|
82
|
+
color: '#1f2937',
|
|
83
|
+
border: '1px solid #e5e7eb',
|
|
84
|
+
boxShadow: '0 8px 18px rgba(15, 23, 42, 0.10)',
|
|
85
|
+
}),
|
|
86
|
+
position: 'fixed',
|
|
87
|
+
top: `${position.top}px`,
|
|
88
|
+
left: `${position.left}px`,
|
|
89
|
+
display: isVisible ? 'block' : 'none',
|
|
90
|
+
padding: '0.375rem 0.625rem',
|
|
91
|
+
fontSize: '0.8125rem',
|
|
92
|
+
lineHeight: 1.2,
|
|
93
|
+
borderRadius: '0.75rem',
|
|
94
|
+
...style,
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
return (
|
|
98
|
+
<>
|
|
99
|
+
<div
|
|
100
|
+
ref={triggerRef}
|
|
101
|
+
onMouseEnter={() => setIsVisible(true)}
|
|
102
|
+
onMouseLeave={() => setIsVisible(false)}
|
|
103
|
+
style={{ display: 'inline-block', width: '100%' }}
|
|
104
|
+
>
|
|
105
|
+
{children}
|
|
106
|
+
</div>
|
|
107
|
+
{isVisible && typeof document !== 'undefined' && createPortal(
|
|
108
|
+
<div
|
|
109
|
+
ref={tooltipRef}
|
|
110
|
+
className={`pc-tooltip ${className}`}
|
|
111
|
+
style={tooltipStyle}
|
|
112
|
+
>
|
|
113
|
+
{content}
|
|
114
|
+
</div>,
|
|
115
|
+
document.body
|
|
116
|
+
)}
|
|
117
|
+
</>
|
|
118
|
+
);
|
|
119
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { pcStyles } from '../styles/pcStyles';
|
|
2
|
+
|
|
3
|
+
type SimpleBarProps = {
|
|
4
|
+
children: React.ReactNode;
|
|
5
|
+
className?: string;
|
|
6
|
+
style?: React.CSSProperties;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export default function SimpleBar({
|
|
10
|
+
children,
|
|
11
|
+
className,
|
|
12
|
+
style,
|
|
13
|
+
}: SimpleBarProps) {
|
|
14
|
+
return (
|
|
15
|
+
<div
|
|
16
|
+
className={`pc-scrollbar ${className || ''}`}
|
|
17
|
+
style={{
|
|
18
|
+
...pcStyles.overflowYAuto,
|
|
19
|
+
...style,
|
|
20
|
+
}}
|
|
21
|
+
>
|
|
22
|
+
{children}
|
|
23
|
+
</div>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { PCBadge } from './index';
|
|
2
|
+
|
|
3
|
+
type StatusBadgeProps = {
|
|
4
|
+
status?: 'success' | 'warning' | 'error' | 'info' | 'pending' | string;
|
|
5
|
+
children?: React.ReactNode;
|
|
6
|
+
className?: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const predefinedStatusMap: Record<string, 'success' | 'warning' | 'error' | 'info' | 'pending'> = {
|
|
10
|
+
success: 'success',
|
|
11
|
+
warning: 'warning',
|
|
12
|
+
error: 'error',
|
|
13
|
+
info: 'info',
|
|
14
|
+
pending: 'pending',
|
|
15
|
+
active: 'success',
|
|
16
|
+
completed: 'success',
|
|
17
|
+
processing: 'warning',
|
|
18
|
+
in_progress: 'warning',
|
|
19
|
+
rejected: 'error',
|
|
20
|
+
declined: 'error',
|
|
21
|
+
expired: 'warning',
|
|
22
|
+
suspended: 'error',
|
|
23
|
+
revoked: 'error',
|
|
24
|
+
withdrawn: 'error',
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export default function StatusBadge({
|
|
28
|
+
status = 'info',
|
|
29
|
+
children,
|
|
30
|
+
className,
|
|
31
|
+
}: StatusBadgeProps) {
|
|
32
|
+
// Check if it's a predefined status
|
|
33
|
+
const normalizedStatus = status.toLowerCase();
|
|
34
|
+
const mappedStatus = predefinedStatusMap[normalizedStatus] || status;
|
|
35
|
+
|
|
36
|
+
let badgeVariant: 'success' | 'error' | 'warning' | 'info' | 'secondary' = 'secondary';
|
|
37
|
+
|
|
38
|
+
if (mappedStatus === 'success') {
|
|
39
|
+
badgeVariant = 'success';
|
|
40
|
+
} else if (mappedStatus === 'error') {
|
|
41
|
+
badgeVariant = 'error';
|
|
42
|
+
} else if (mappedStatus === 'warning') {
|
|
43
|
+
badgeVariant = 'warning';
|
|
44
|
+
} else if (mappedStatus === 'info') {
|
|
45
|
+
badgeVariant = 'info';
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<PCBadge variant={badgeVariant} className={className}>
|
|
50
|
+
{children || status}
|
|
51
|
+
</PCBadge>
|
|
52
|
+
);
|
|
53
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { useRef } from 'react';
|
|
2
|
+
import { useTranslation } from 'react-i18next';
|
|
3
|
+
import { PCActionIcon } from './index';
|
|
4
|
+
import { IoSunnyOutline, IoMoonOutline } from 'react-icons/io5';
|
|
5
|
+
import { useTheme } from '../context/theme';
|
|
6
|
+
import { PCTooltip } from './PCTooltip';
|
|
7
|
+
|
|
8
|
+
const getVar = (varName: string): string => `var(${varName})`;
|
|
9
|
+
|
|
10
|
+
type ThemeToggleProps = {
|
|
11
|
+
className?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default function ThemeToggle({ className }: ThemeToggleProps) {
|
|
15
|
+
const { t } = useTranslation();
|
|
16
|
+
const { theme, toggleTheme } = useTheme();
|
|
17
|
+
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
18
|
+
const tooltipLabel =
|
|
19
|
+
theme === 'light' ? t('switchToDarkMode') : t('switchToLightMode');
|
|
20
|
+
|
|
21
|
+
const handleClick = () => {
|
|
22
|
+
// Capture click position for animation
|
|
23
|
+
let position: { x: number; y: number };
|
|
24
|
+
|
|
25
|
+
if (buttonRef.current) {
|
|
26
|
+
const rect = buttonRef.current.getBoundingClientRect();
|
|
27
|
+
position = {
|
|
28
|
+
x: rect.left + rect.width / 2,
|
|
29
|
+
y: rect.top + rect.height / 2
|
|
30
|
+
};
|
|
31
|
+
} else {
|
|
32
|
+
// Fallback to center
|
|
33
|
+
position = {
|
|
34
|
+
x: window.innerWidth / 2,
|
|
35
|
+
y: window.innerHeight / 2
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Store position globally for ThemeTransitionOverlay to access
|
|
40
|
+
if (typeof window !== 'undefined') {
|
|
41
|
+
(window as any).__pcThemeTransitionPosition = position;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
toggleTheme();
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<PCTooltip content={tooltipLabel} placement="bottom" color="invert">
|
|
49
|
+
<div style={{ display: 'inline-flex' }}>
|
|
50
|
+
<PCActionIcon
|
|
51
|
+
ref={buttonRef}
|
|
52
|
+
variant="default"
|
|
53
|
+
className={className}
|
|
54
|
+
onClick={handleClick}
|
|
55
|
+
aria-label={tooltipLabel}
|
|
56
|
+
style={{
|
|
57
|
+
width: '32px',
|
|
58
|
+
height: '32px',
|
|
59
|
+
color: getVar('--pc-text-primary'),
|
|
60
|
+
transition: 'color 0.3s ease, transform 0.2s ease',
|
|
61
|
+
}}
|
|
62
|
+
>
|
|
63
|
+
{theme === 'light' ? (
|
|
64
|
+
<IoMoonOutline size={18} />
|
|
65
|
+
) : (
|
|
66
|
+
<IoSunnyOutline size={18} />
|
|
67
|
+
)}
|
|
68
|
+
</PCActionIcon>
|
|
69
|
+
</div>
|
|
70
|
+
</PCTooltip>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { PCText, type PCTextProps } from './PCText';
|
|
2
|
+
export { PCTitle, type PCTitleProps } from './PCTitle';
|
|
3
|
+
export { PCButton, type PCButtonProps } from './PCButton';
|
|
4
|
+
export { PCActionIcon, type PCActionIconProps } from './PCActionIcon';
|
|
5
|
+
export { PCInput, type PCInputProps } from './PCInput';
|
|
6
|
+
export { PCTextarea, type PCTextareaProps } from './PCTextarea';
|
|
7
|
+
export { PCCheckbox, type PCCheckboxProps } from './PCCheckbox';
|
|
8
|
+
export { PCSelect, type PCSelectProps, type SelectOption } from './PCSelect';
|
|
9
|
+
export { PCModal, type PCModalProps } from './PCModal';
|
|
10
|
+
export { PCTable, PCTableHeader, PCTableBody, PCTableRow, PCTableHead, PCTableCell, type PCTableProps, type PCTableHeaderProps, type PCTableBodyProps, type PCTableRowProps, type PCTableHeadProps, type PCTableCellProps } from './PCTable';
|
|
11
|
+
export { PCLoader, type PCLoaderProps } from './PCLoader';
|
|
12
|
+
export { PCBadge, type PCBadgeProps } from './PCBadge';
|
|
13
|
+
export { PCTooltip, type PCTooltipProps } from './PCTooltip';
|
|
14
|
+
export { PCPopover, type PCPopoverProps } from './PCPopover';
|
|
15
|
+
export { PCAccordion, PCAccordionHeader, PCAccordionBody, type PCAccordionProps, type PCAccordionHeaderProps, type PCAccordionBodyProps } from './PCAccordion';
|
|
16
|
+
export { PCCollapse, PCCollapseHeader, PCCollapseBody, type PCCollapseProps, type PCCollapseHeaderProps, type PCCollapseBodyProps } from './PCCollapse';
|
|
17
|
+
export { PCAvatar, type PCAvatarProps } from './PCAvatar';
|
|
18
|
+
export { PCEmpty, type PCEmptyProps } from './PCEmpty';
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
// Simple className utility - replaces clsx and tailwind-merge
|
|
2
|
+
// Accepts strings, objects, arrays, and undefined/null values
|
|
3
|
+
type ClassValue = string | number | boolean | undefined | null | Record<string, boolean> | ClassValue[];
|
|
4
|
+
|
|
5
|
+
export function cn(...inputs: ClassValue[]): string {
|
|
6
|
+
const classes: string[] = [];
|
|
7
|
+
|
|
8
|
+
for (const input of inputs) {
|
|
9
|
+
if (!input) continue;
|
|
10
|
+
|
|
11
|
+
if (typeof input === 'string') {
|
|
12
|
+
classes.push(input);
|
|
13
|
+
} else if (typeof input === 'number') {
|
|
14
|
+
classes.push(String(input));
|
|
15
|
+
} else if (Array.isArray(input)) {
|
|
16
|
+
const inner = cn(...input);
|
|
17
|
+
if (inner) classes.push(inner);
|
|
18
|
+
} else if (typeof input === 'object') {
|
|
19
|
+
for (const key in input) {
|
|
20
|
+
if (input[key]) {
|
|
21
|
+
classes.push(key);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return classes.filter(Boolean).join(' ');
|
|
28
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unified date formatting utilities for privacy center app
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type FormatDateParams = {
|
|
6
|
+
date: string | Date;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Format date for display in consent records (with time)
|
|
11
|
+
* Format: "January 15, 2025 at 2:30 PM"
|
|
12
|
+
*/
|
|
13
|
+
export const formatDate = ({ date }: FormatDateParams): string => {
|
|
14
|
+
return new Date(date).toLocaleDateString('en-US', {
|
|
15
|
+
year: 'numeric',
|
|
16
|
+
month: 'long',
|
|
17
|
+
day: 'numeric',
|
|
18
|
+
hour: '2-digit',
|
|
19
|
+
minute: '2-digit',
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Format date for display in case history (short format)
|
|
25
|
+
* Format: "15 Jan 2025"
|
|
26
|
+
*/
|
|
27
|
+
export const formatDateShort = (dateString: string): string => {
|
|
28
|
+
if (!dateString) return '-';
|
|
29
|
+
return new Date(dateString).toLocaleDateString('en-GB', {
|
|
30
|
+
day: 'numeric',
|
|
31
|
+
month: 'short',
|
|
32
|
+
year: 'numeric'
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Format date time for consent manager (with day/month/year)
|
|
38
|
+
* Format: "15 Jan 2025"
|
|
39
|
+
*/
|
|
40
|
+
export const formatDateTime = (timestamp: string): string => {
|
|
41
|
+
const date = new Date(timestamp);
|
|
42
|
+
const options: Intl.DateTimeFormatOptions = {
|
|
43
|
+
day: '2-digit',
|
|
44
|
+
month: 'short',
|
|
45
|
+
year: 'numeric',
|
|
46
|
+
};
|
|
47
|
+
return date.toLocaleString('en-US', options);
|
|
48
|
+
};
|