@tantainnovative/ndpr-toolkit 1.0.9 → 2.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/README.md +295 -124
- package/dist/breach-BpSBPrdk.d.mts +185 -0
- package/dist/breach-BpSBPrdk.d.ts +185 -0
- package/dist/breach-D5zJYNph.d.mts +17 -0
- package/dist/breach-D7NgrdMX.d.ts +17 -0
- package/dist/breach.d.mts +275 -0
- package/dist/breach.d.ts +275 -0
- package/dist/breach.js +2 -0
- package/dist/breach.js.map +1 -0
- package/dist/breach.mjs +2 -0
- package/dist/breach.mjs.map +1 -0
- package/dist/chunk-2SYNHRP6.mjs +2 -0
- package/dist/chunk-2SYNHRP6.mjs.map +1 -0
- package/dist/chunk-2XHD22J7.mjs +7 -0
- package/dist/chunk-2XHD22J7.mjs.map +1 -0
- package/dist/chunk-4A354HL3.js +2 -0
- package/dist/chunk-4A354HL3.js.map +1 -0
- package/dist/chunk-4DKT6IB6.js +94 -0
- package/dist/chunk-4DKT6IB6.js.map +1 -0
- package/dist/chunk-5ZBO2UPH.js +2 -0
- package/dist/chunk-5ZBO2UPH.js.map +1 -0
- package/dist/chunk-6JFTAYXV.mjs +2 -0
- package/dist/chunk-6JFTAYXV.mjs.map +1 -0
- package/dist/chunk-6JVYYLS7.js +2 -0
- package/dist/chunk-6JVYYLS7.js.map +1 -0
- package/dist/chunk-6SGG6WPA.mjs +2 -0
- package/dist/chunk-6SGG6WPA.mjs.map +1 -0
- package/dist/chunk-AQEGDEQM.js +7 -0
- package/dist/chunk-AQEGDEQM.js.map +1 -0
- package/dist/chunk-C2IJWCZQ.mjs +2 -0
- package/dist/chunk-C2IJWCZQ.mjs.map +1 -0
- package/dist/chunk-CMZTI7SG.js +2 -0
- package/dist/chunk-CMZTI7SG.js.map +1 -0
- package/dist/chunk-DB3JH4DS.mjs +2 -0
- package/dist/chunk-DB3JH4DS.mjs.map +1 -0
- package/dist/chunk-EWOZKYLY.mjs +2 -0
- package/dist/chunk-EWOZKYLY.mjs.map +1 -0
- package/dist/chunk-FFW7RUAG.mjs +94 -0
- package/dist/chunk-FFW7RUAG.mjs.map +1 -0
- package/dist/chunk-FK3CSFLJ.js +2 -0
- package/dist/chunk-FK3CSFLJ.js.map +1 -0
- package/dist/chunk-GIV2OHE6.mjs +2 -0
- package/dist/chunk-GIV2OHE6.mjs.map +1 -0
- package/dist/chunk-GMLNWS2N.mjs +2 -0
- package/dist/chunk-GMLNWS2N.mjs.map +1 -0
- package/dist/chunk-IQF726GS.js +2 -0
- package/dist/chunk-IQF726GS.js.map +1 -0
- package/dist/chunk-IWUUVRLJ.js +2 -0
- package/dist/chunk-IWUUVRLJ.js.map +1 -0
- package/dist/chunk-JUN6YPLL.mjs +72 -0
- package/dist/chunk-JUN6YPLL.mjs.map +1 -0
- package/dist/chunk-L3FKTBGV.js +72 -0
- package/dist/chunk-L3FKTBGV.js.map +1 -0
- package/dist/chunk-L52PDW6O.mjs +2 -0
- package/dist/chunk-L52PDW6O.mjs.map +1 -0
- package/dist/chunk-LI6WJ3LZ.js +2 -0
- package/dist/chunk-LI6WJ3LZ.js.map +1 -0
- package/dist/chunk-LXRXDTPI.js +2 -0
- package/dist/chunk-LXRXDTPI.js.map +1 -0
- package/dist/chunk-MQFZHA2D.js +2 -0
- package/dist/chunk-MQFZHA2D.js.map +1 -0
- package/dist/chunk-OITITR6K.mjs +2 -0
- package/dist/chunk-OITITR6K.mjs.map +1 -0
- package/dist/chunk-PDJGTQMY.mjs +2 -0
- package/dist/chunk-PDJGTQMY.mjs.map +1 -0
- package/dist/chunk-PGSA2O5P.mjs +2 -0
- package/dist/chunk-PGSA2O5P.mjs.map +1 -0
- package/dist/chunk-PM7CMTMB.js +4 -0
- package/dist/chunk-PM7CMTMB.js.map +1 -0
- package/dist/chunk-PYEX7DFR.mjs +4 -0
- package/dist/chunk-PYEX7DFR.mjs.map +1 -0
- package/dist/chunk-QKK5S54L.mjs +2 -0
- package/dist/chunk-QKK5S54L.mjs.map +1 -0
- package/dist/chunk-RB26MIRI.js +2 -0
- package/dist/chunk-RB26MIRI.js.map +1 -0
- package/dist/chunk-RGYK4VAY.mjs +2 -0
- package/dist/chunk-RGYK4VAY.mjs.map +1 -0
- package/dist/chunk-RHWW5FDP.js +16 -0
- package/dist/chunk-RHWW5FDP.js.map +1 -0
- package/dist/chunk-RYZEIDNR.js +2 -0
- package/dist/chunk-RYZEIDNR.js.map +1 -0
- package/dist/chunk-SLNMKGQ2.mjs +2 -0
- package/dist/chunk-SLNMKGQ2.mjs.map +1 -0
- package/dist/chunk-SSGJREE3.js +2 -0
- package/dist/chunk-SSGJREE3.js.map +1 -0
- package/dist/chunk-SWF3YVE5.js +4 -0
- package/dist/chunk-SWF3YVE5.js.map +1 -0
- package/dist/chunk-T44JQT2O.mjs +2 -0
- package/dist/chunk-T44JQT2O.mjs.map +1 -0
- package/dist/chunk-TDDAYVKK.js +2 -0
- package/dist/chunk-TDDAYVKK.js.map +1 -0
- package/dist/chunk-TXBZPCGF.mjs +2 -0
- package/dist/chunk-TXBZPCGF.mjs.map +1 -0
- package/dist/chunk-U2CGMEWB.js +2 -0
- package/dist/chunk-U2CGMEWB.js.map +1 -0
- package/dist/chunk-UUWVBENC.js +2 -0
- package/dist/chunk-UUWVBENC.js.map +1 -0
- package/dist/chunk-UYP64PV7.mjs +4 -0
- package/dist/chunk-UYP64PV7.mjs.map +1 -0
- package/dist/chunk-VMJBW3EF.mjs +2 -0
- package/dist/chunk-VMJBW3EF.mjs.map +1 -0
- package/dist/chunk-WW3X3ELF.js +2 -0
- package/dist/chunk-WW3X3ELF.js.map +1 -0
- package/dist/chunk-WWT2ZSNU.mjs +2 -0
- package/dist/chunk-WWT2ZSNU.mjs.map +1 -0
- package/dist/chunk-XMKA6GVK.mjs +16 -0
- package/dist/chunk-XMKA6GVK.mjs.map +1 -0
- package/dist/chunk-Y34DQYS7.js +2 -0
- package/dist/chunk-Y34DQYS7.js.map +1 -0
- package/dist/chunk-ZU73VG3X.js +2 -0
- package/dist/chunk-ZU73VG3X.js.map +1 -0
- package/dist/consent-CmVzqZUk.d.mts +99 -0
- package/dist/consent-CmVzqZUk.d.ts +99 -0
- package/dist/consent-DCc5zjXI.d.mts +24 -0
- package/dist/consent-DLWb5ota.d.ts +24 -0
- package/dist/consent.d.mts +197 -0
- package/dist/consent.d.ts +197 -0
- package/dist/consent.js +2 -0
- package/dist/consent.js.map +1 -0
- package/dist/consent.mjs +2 -0
- package/dist/consent.mjs.map +1 -0
- package/dist/core.d.mts +14 -0
- package/dist/core.d.ts +14 -0
- package/dist/core.js +2 -0
- package/dist/core.js.map +1 -0
- package/dist/core.mjs +2 -0
- package/dist/core.mjs.map +1 -0
- package/dist/cross-border-BrIy1ieh.d.mts +192 -0
- package/dist/cross-border-BrIy1ieh.d.ts +192 -0
- package/dist/cross-border.d.mts +58 -0
- package/dist/cross-border.d.ts +58 -0
- package/dist/cross-border.js +2 -0
- package/dist/cross-border.js.map +1 -0
- package/dist/cross-border.mjs +2 -0
- package/dist/cross-border.mjs.map +1 -0
- package/dist/dpia-B9ZZJG5a.d.mts +15 -0
- package/dist/dpia-fdtTd2DI.d.ts +15 -0
- package/dist/dpia-vWfE_9bO.d.mts +137 -0
- package/dist/dpia-vWfE_9bO.d.ts +137 -0
- package/dist/dpia.d.mts +179 -0
- package/dist/dpia.d.ts +179 -0
- package/dist/dpia.js +2 -0
- package/dist/dpia.js.map +1 -0
- package/dist/dpia.mjs +2 -0
- package/dist/dpia.mjs.map +1 -0
- package/dist/dsr-jq5NUEdz.d.ts +14 -0
- package/dist/dsr-pQzQ3H1O.d.mts +128 -0
- package/dist/dsr-pQzQ3H1O.d.ts +128 -0
- package/dist/dsr-whPkiI0_.d.mts +14 -0
- package/dist/dsr.d.mts +192 -0
- package/dist/dsr.d.ts +192 -0
- package/dist/dsr.js +2 -0
- package/dist/dsr.js.map +1 -0
- package/dist/dsr.mjs +2 -0
- package/dist/dsr.mjs.map +1 -0
- package/dist/hooks.d.mts +17 -0
- package/dist/hooks.d.ts +17 -0
- package/dist/hooks.js +2 -0
- package/dist/hooks.js.map +1 -0
- package/dist/hooks.mjs +2 -0
- package/dist/hooks.mjs.map +1 -0
- package/dist/index.d.mts +31 -448
- package/dist/index.d.ts +31 -448
- package/dist/index.js +1 -190
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -190
- package/dist/index.mjs.map +1 -1
- package/dist/lawful-basis-CWtvDG1x.d.mts +112 -0
- package/dist/lawful-basis-CWtvDG1x.d.ts +112 -0
- package/dist/lawful-basis-D-oXFizg.d.mts +57 -0
- package/dist/lawful-basis-v04AhbK2.d.ts +57 -0
- package/dist/lawful-basis.d.mts +55 -0
- package/dist/lawful-basis.d.ts +55 -0
- package/dist/lawful-basis.js +2 -0
- package/dist/lawful-basis.js.map +1 -0
- package/dist/lawful-basis.mjs +2 -0
- package/dist/lawful-basis.mjs.map +1 -0
- package/dist/policy.d.mts +195 -0
- package/dist/policy.d.ts +195 -0
- package/dist/policy.js +2 -0
- package/dist/policy.js.map +1 -0
- package/dist/policy.mjs +2 -0
- package/dist/policy.mjs.map +1 -0
- package/dist/privacy-9FcJceMr.d.mts +15 -0
- package/dist/privacy-BXz7O2ej.d.ts +15 -0
- package/dist/privacy-Ca6te9Ir.d.mts +138 -0
- package/dist/privacy-Ca6te9Ir.d.ts +138 -0
- package/dist/ropa-BebGfqKQ.d.ts +200 -0
- package/dist/ropa-Rb4dsFSz.d.mts +200 -0
- package/dist/ropa.d.mts +45 -0
- package/dist/ropa.d.ts +45 -0
- package/dist/ropa.js +2 -0
- package/dist/ropa.js.map +1 -0
- package/dist/ropa.mjs +2 -0
- package/dist/ropa.mjs.map +1 -0
- package/dist/unstyled.d.mts +4 -4
- package/dist/unstyled.d.ts +4 -4
- package/dist/unstyled.js +1 -1
- package/dist/unstyled.js.map +1 -1
- package/dist/unstyled.mjs +1 -1
- package/dist/unstyled.mjs.map +1 -1
- package/dist/useBreach-DRKnexsk.d.mts +99 -0
- package/dist/useBreach-DuT0N0K1.d.ts +99 -0
- package/dist/useConsent-D0pAfTlb.d.ts +65 -0
- package/dist/useConsent-DOt2Njst.d.mts +65 -0
- package/dist/useCrossBorderTransfer-D4FQYfFt.d.ts +66 -0
- package/dist/useCrossBorderTransfer-TVnY8_UX.d.mts +66 -0
- package/dist/useDPIA-DFDHBLSa.d.ts +94 -0
- package/dist/useDPIA-FqPofFaV.d.mts +94 -0
- package/dist/useDSR-DAqqOBXb.d.ts +74 -0
- package/dist/useDSR-OXM5Q9rf.d.mts +74 -0
- package/dist/useLawfulBasis-DNQ8YszQ.d.mts +68 -0
- package/dist/useLawfulBasis-RILM_xsx.d.ts +68 -0
- package/dist/usePrivacyPolicy-CfySfBLS.d.ts +89 -0
- package/dist/usePrivacyPolicy-Dit2sFuV.d.mts +89 -0
- package/dist/useROPA-Bcs6cRdi.d.ts +64 -0
- package/dist/useROPA-nmcSiUYv.d.mts +64 -0
- package/package.json +162 -35
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { L as LawfulBasis } from './lawful-basis-CWtvDG1x.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Record of Processing Activities (ROPA) types aligned with NDPA 2023
|
|
5
|
+
* Data controllers must maintain comprehensive records of all processing activities
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Represents a single processing record in the ROPA
|
|
10
|
+
*/
|
|
11
|
+
interface ProcessingRecord {
|
|
12
|
+
/** Unique identifier */
|
|
13
|
+
id: string;
|
|
14
|
+
/** Name of the processing activity */
|
|
15
|
+
name: string;
|
|
16
|
+
/** Detailed description of the processing */
|
|
17
|
+
description: string;
|
|
18
|
+
/** Data controller details */
|
|
19
|
+
controllerDetails: {
|
|
20
|
+
name: string;
|
|
21
|
+
contact: string;
|
|
22
|
+
address: string;
|
|
23
|
+
registrationNumber?: string;
|
|
24
|
+
dpoContact?: string;
|
|
25
|
+
};
|
|
26
|
+
/** Joint controller details (if applicable) */
|
|
27
|
+
jointControllerDetails?: {
|
|
28
|
+
name: string;
|
|
29
|
+
contact: string;
|
|
30
|
+
address: string;
|
|
31
|
+
responsibilities: string;
|
|
32
|
+
};
|
|
33
|
+
/** Data processor details (if processing is outsourced) */
|
|
34
|
+
processorDetails?: {
|
|
35
|
+
name: string;
|
|
36
|
+
contact: string;
|
|
37
|
+
address: string;
|
|
38
|
+
contractReference?: string;
|
|
39
|
+
};
|
|
40
|
+
/** Lawful basis for the processing */
|
|
41
|
+
lawfulBasis: LawfulBasis;
|
|
42
|
+
/** Justification for the chosen lawful basis */
|
|
43
|
+
lawfulBasisJustification: string;
|
|
44
|
+
/** Purposes of the processing */
|
|
45
|
+
purposes: string[];
|
|
46
|
+
/** Categories of personal data processed */
|
|
47
|
+
dataCategories: string[];
|
|
48
|
+
/** Categories of sensitive personal data (if any) */
|
|
49
|
+
sensitiveDataCategories?: string[];
|
|
50
|
+
/** Categories of data subjects */
|
|
51
|
+
dataSubjectCategories: string[];
|
|
52
|
+
/** Recipients or categories of recipients */
|
|
53
|
+
recipients: string[];
|
|
54
|
+
/** Cross-border transfer details */
|
|
55
|
+
crossBorderTransfers?: Array<{
|
|
56
|
+
destinationCountry: string;
|
|
57
|
+
countryCode?: string;
|
|
58
|
+
safeguards: string;
|
|
59
|
+
transferMechanism: string;
|
|
60
|
+
}>;
|
|
61
|
+
/** Data retention period */
|
|
62
|
+
retentionPeriod: string;
|
|
63
|
+
/** Justification for the retention period */
|
|
64
|
+
retentionJustification?: string;
|
|
65
|
+
/** Technical and organizational security measures */
|
|
66
|
+
securityMeasures: string[];
|
|
67
|
+
/** Data source (directly from data subject or from third party) */
|
|
68
|
+
dataSource: 'data_subject' | 'third_party' | 'public_source' | 'other';
|
|
69
|
+
/** Third-party source details (if dataSource is 'third_party') */
|
|
70
|
+
thirdPartySourceDetails?: string;
|
|
71
|
+
/** Whether a DPIA is required for this processing */
|
|
72
|
+
dpiaRequired: boolean;
|
|
73
|
+
/** Reference to the DPIA (if conducted) */
|
|
74
|
+
dpiaReference?: string;
|
|
75
|
+
/** Whether automated decision-making is involved */
|
|
76
|
+
automatedDecisionMaking: boolean;
|
|
77
|
+
/** Details of automated decision-making (if applicable) */
|
|
78
|
+
automatedDecisionMakingDetails?: string;
|
|
79
|
+
/** Status of the processing record */
|
|
80
|
+
status: 'active' | 'inactive' | 'archived';
|
|
81
|
+
/** Department or business unit responsible */
|
|
82
|
+
department?: string;
|
|
83
|
+
/** System or application used for processing */
|
|
84
|
+
systemsUsed?: string[];
|
|
85
|
+
/** Timestamp when the record was created */
|
|
86
|
+
createdAt: number;
|
|
87
|
+
/** Timestamp when the record was last updated */
|
|
88
|
+
updatedAt: number;
|
|
89
|
+
/** Timestamp when the record was last reviewed */
|
|
90
|
+
lastReviewedAt?: number;
|
|
91
|
+
/** Next review date */
|
|
92
|
+
nextReviewDate?: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Represents a complete Record of Processing Activities
|
|
96
|
+
*/
|
|
97
|
+
interface RecordOfProcessingActivities {
|
|
98
|
+
/** Unique identifier */
|
|
99
|
+
id: string;
|
|
100
|
+
/** Organization name */
|
|
101
|
+
organizationName: string;
|
|
102
|
+
/** Organization contact information */
|
|
103
|
+
organizationContact: string;
|
|
104
|
+
/** Organization address */
|
|
105
|
+
organizationAddress: string;
|
|
106
|
+
/** Data Protection Officer details */
|
|
107
|
+
dpoDetails?: {
|
|
108
|
+
name: string;
|
|
109
|
+
email: string;
|
|
110
|
+
phone?: string;
|
|
111
|
+
};
|
|
112
|
+
/** NDPC registration number */
|
|
113
|
+
ndpcRegistrationNumber?: string;
|
|
114
|
+
/** All processing records */
|
|
115
|
+
records: ProcessingRecord[];
|
|
116
|
+
/** Timestamp when the ROPA was last updated */
|
|
117
|
+
lastUpdated: number;
|
|
118
|
+
/** Version of the ROPA */
|
|
119
|
+
version: string;
|
|
120
|
+
/** Export format options */
|
|
121
|
+
exportFormats?: ('pdf' | 'csv' | 'json' | 'xlsx')[];
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Summary statistics for the ROPA
|
|
125
|
+
*/
|
|
126
|
+
interface ROPASummary {
|
|
127
|
+
/** Total number of processing records */
|
|
128
|
+
totalRecords: number;
|
|
129
|
+
/** Active processing records */
|
|
130
|
+
activeRecords: number;
|
|
131
|
+
/** Records by lawful basis */
|
|
132
|
+
byLawfulBasis: Record<LawfulBasis, number>;
|
|
133
|
+
/** Records involving sensitive data */
|
|
134
|
+
sensitiveDataRecords: number;
|
|
135
|
+
/** Records involving cross-border transfers */
|
|
136
|
+
crossBorderRecords: number;
|
|
137
|
+
/** Records requiring DPIA */
|
|
138
|
+
dpiaRequiredRecords: number;
|
|
139
|
+
/** Records involving automated decision-making */
|
|
140
|
+
automatedDecisionRecords: number;
|
|
141
|
+
/** Records due for review */
|
|
142
|
+
recordsDueForReview: ProcessingRecord[];
|
|
143
|
+
/** Departments with most processing activities */
|
|
144
|
+
topDepartments: Array<{
|
|
145
|
+
department: string;
|
|
146
|
+
count: number;
|
|
147
|
+
}>;
|
|
148
|
+
/** Last updated timestamp */
|
|
149
|
+
lastUpdated: number;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Compliance gap found in a processing record
|
|
154
|
+
*/
|
|
155
|
+
interface ROPAComplianceGap {
|
|
156
|
+
recordId: string;
|
|
157
|
+
recordName: string;
|
|
158
|
+
gaps: string[];
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Validation result for a processing record
|
|
162
|
+
*/
|
|
163
|
+
interface ROPAValidationResult {
|
|
164
|
+
valid: boolean;
|
|
165
|
+
errors: string[];
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Validates a processing record to ensure all required fields are present
|
|
169
|
+
* and properly filled per NDPA 2023 requirements.
|
|
170
|
+
*
|
|
171
|
+
* @param record - The processing record to validate
|
|
172
|
+
* @returns Validation result with any errors found
|
|
173
|
+
*/
|
|
174
|
+
declare function validateProcessingRecord(record: ProcessingRecord): ROPAValidationResult;
|
|
175
|
+
/**
|
|
176
|
+
* Generates a summary of the Record of Processing Activities.
|
|
177
|
+
* Provides statistics and identifies records that are due for review.
|
|
178
|
+
*
|
|
179
|
+
* @param ropa - The full Record of Processing Activities
|
|
180
|
+
* @returns Summary statistics for the ROPA
|
|
181
|
+
*/
|
|
182
|
+
declare function generateROPASummary(ropa: RecordOfProcessingActivities): ROPASummary;
|
|
183
|
+
/**
|
|
184
|
+
* Exports the Record of Processing Activities to a CSV string.
|
|
185
|
+
* The CSV includes all key fields from each processing record.
|
|
186
|
+
*
|
|
187
|
+
* @param ropa - The full Record of Processing Activities
|
|
188
|
+
* @returns CSV-formatted string
|
|
189
|
+
*/
|
|
190
|
+
declare function exportROPAToCSV(ropa: RecordOfProcessingActivities): string;
|
|
191
|
+
/**
|
|
192
|
+
* Identifies compliance gaps in the Record of Processing Activities.
|
|
193
|
+
* Finds records that are missing required information per NDPA 2023.
|
|
194
|
+
*
|
|
195
|
+
* @param ropa - The full Record of Processing Activities
|
|
196
|
+
* @returns Array of compliance gaps grouped by record
|
|
197
|
+
*/
|
|
198
|
+
declare function identifyComplianceGaps(ropa: RecordOfProcessingActivities): ROPAComplianceGap[];
|
|
199
|
+
|
|
200
|
+
export { type ProcessingRecord as P, type RecordOfProcessingActivities as R, type ROPASummary as a, type ROPAComplianceGap as b, type ROPAValidationResult as c, exportROPAToCSV as e, generateROPASummary as g, identifyComplianceGaps as i, validateProcessingRecord as v };
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { L as LawfulBasis } from './lawful-basis-CWtvDG1x.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Record of Processing Activities (ROPA) types aligned with NDPA 2023
|
|
5
|
+
* Data controllers must maintain comprehensive records of all processing activities
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Represents a single processing record in the ROPA
|
|
10
|
+
*/
|
|
11
|
+
interface ProcessingRecord {
|
|
12
|
+
/** Unique identifier */
|
|
13
|
+
id: string;
|
|
14
|
+
/** Name of the processing activity */
|
|
15
|
+
name: string;
|
|
16
|
+
/** Detailed description of the processing */
|
|
17
|
+
description: string;
|
|
18
|
+
/** Data controller details */
|
|
19
|
+
controllerDetails: {
|
|
20
|
+
name: string;
|
|
21
|
+
contact: string;
|
|
22
|
+
address: string;
|
|
23
|
+
registrationNumber?: string;
|
|
24
|
+
dpoContact?: string;
|
|
25
|
+
};
|
|
26
|
+
/** Joint controller details (if applicable) */
|
|
27
|
+
jointControllerDetails?: {
|
|
28
|
+
name: string;
|
|
29
|
+
contact: string;
|
|
30
|
+
address: string;
|
|
31
|
+
responsibilities: string;
|
|
32
|
+
};
|
|
33
|
+
/** Data processor details (if processing is outsourced) */
|
|
34
|
+
processorDetails?: {
|
|
35
|
+
name: string;
|
|
36
|
+
contact: string;
|
|
37
|
+
address: string;
|
|
38
|
+
contractReference?: string;
|
|
39
|
+
};
|
|
40
|
+
/** Lawful basis for the processing */
|
|
41
|
+
lawfulBasis: LawfulBasis;
|
|
42
|
+
/** Justification for the chosen lawful basis */
|
|
43
|
+
lawfulBasisJustification: string;
|
|
44
|
+
/** Purposes of the processing */
|
|
45
|
+
purposes: string[];
|
|
46
|
+
/** Categories of personal data processed */
|
|
47
|
+
dataCategories: string[];
|
|
48
|
+
/** Categories of sensitive personal data (if any) */
|
|
49
|
+
sensitiveDataCategories?: string[];
|
|
50
|
+
/** Categories of data subjects */
|
|
51
|
+
dataSubjectCategories: string[];
|
|
52
|
+
/** Recipients or categories of recipients */
|
|
53
|
+
recipients: string[];
|
|
54
|
+
/** Cross-border transfer details */
|
|
55
|
+
crossBorderTransfers?: Array<{
|
|
56
|
+
destinationCountry: string;
|
|
57
|
+
countryCode?: string;
|
|
58
|
+
safeguards: string;
|
|
59
|
+
transferMechanism: string;
|
|
60
|
+
}>;
|
|
61
|
+
/** Data retention period */
|
|
62
|
+
retentionPeriod: string;
|
|
63
|
+
/** Justification for the retention period */
|
|
64
|
+
retentionJustification?: string;
|
|
65
|
+
/** Technical and organizational security measures */
|
|
66
|
+
securityMeasures: string[];
|
|
67
|
+
/** Data source (directly from data subject or from third party) */
|
|
68
|
+
dataSource: 'data_subject' | 'third_party' | 'public_source' | 'other';
|
|
69
|
+
/** Third-party source details (if dataSource is 'third_party') */
|
|
70
|
+
thirdPartySourceDetails?: string;
|
|
71
|
+
/** Whether a DPIA is required for this processing */
|
|
72
|
+
dpiaRequired: boolean;
|
|
73
|
+
/** Reference to the DPIA (if conducted) */
|
|
74
|
+
dpiaReference?: string;
|
|
75
|
+
/** Whether automated decision-making is involved */
|
|
76
|
+
automatedDecisionMaking: boolean;
|
|
77
|
+
/** Details of automated decision-making (if applicable) */
|
|
78
|
+
automatedDecisionMakingDetails?: string;
|
|
79
|
+
/** Status of the processing record */
|
|
80
|
+
status: 'active' | 'inactive' | 'archived';
|
|
81
|
+
/** Department or business unit responsible */
|
|
82
|
+
department?: string;
|
|
83
|
+
/** System or application used for processing */
|
|
84
|
+
systemsUsed?: string[];
|
|
85
|
+
/** Timestamp when the record was created */
|
|
86
|
+
createdAt: number;
|
|
87
|
+
/** Timestamp when the record was last updated */
|
|
88
|
+
updatedAt: number;
|
|
89
|
+
/** Timestamp when the record was last reviewed */
|
|
90
|
+
lastReviewedAt?: number;
|
|
91
|
+
/** Next review date */
|
|
92
|
+
nextReviewDate?: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Represents a complete Record of Processing Activities
|
|
96
|
+
*/
|
|
97
|
+
interface RecordOfProcessingActivities {
|
|
98
|
+
/** Unique identifier */
|
|
99
|
+
id: string;
|
|
100
|
+
/** Organization name */
|
|
101
|
+
organizationName: string;
|
|
102
|
+
/** Organization contact information */
|
|
103
|
+
organizationContact: string;
|
|
104
|
+
/** Organization address */
|
|
105
|
+
organizationAddress: string;
|
|
106
|
+
/** Data Protection Officer details */
|
|
107
|
+
dpoDetails?: {
|
|
108
|
+
name: string;
|
|
109
|
+
email: string;
|
|
110
|
+
phone?: string;
|
|
111
|
+
};
|
|
112
|
+
/** NDPC registration number */
|
|
113
|
+
ndpcRegistrationNumber?: string;
|
|
114
|
+
/** All processing records */
|
|
115
|
+
records: ProcessingRecord[];
|
|
116
|
+
/** Timestamp when the ROPA was last updated */
|
|
117
|
+
lastUpdated: number;
|
|
118
|
+
/** Version of the ROPA */
|
|
119
|
+
version: string;
|
|
120
|
+
/** Export format options */
|
|
121
|
+
exportFormats?: ('pdf' | 'csv' | 'json' | 'xlsx')[];
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Summary statistics for the ROPA
|
|
125
|
+
*/
|
|
126
|
+
interface ROPASummary {
|
|
127
|
+
/** Total number of processing records */
|
|
128
|
+
totalRecords: number;
|
|
129
|
+
/** Active processing records */
|
|
130
|
+
activeRecords: number;
|
|
131
|
+
/** Records by lawful basis */
|
|
132
|
+
byLawfulBasis: Record<LawfulBasis, number>;
|
|
133
|
+
/** Records involving sensitive data */
|
|
134
|
+
sensitiveDataRecords: number;
|
|
135
|
+
/** Records involving cross-border transfers */
|
|
136
|
+
crossBorderRecords: number;
|
|
137
|
+
/** Records requiring DPIA */
|
|
138
|
+
dpiaRequiredRecords: number;
|
|
139
|
+
/** Records involving automated decision-making */
|
|
140
|
+
automatedDecisionRecords: number;
|
|
141
|
+
/** Records due for review */
|
|
142
|
+
recordsDueForReview: ProcessingRecord[];
|
|
143
|
+
/** Departments with most processing activities */
|
|
144
|
+
topDepartments: Array<{
|
|
145
|
+
department: string;
|
|
146
|
+
count: number;
|
|
147
|
+
}>;
|
|
148
|
+
/** Last updated timestamp */
|
|
149
|
+
lastUpdated: number;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Compliance gap found in a processing record
|
|
154
|
+
*/
|
|
155
|
+
interface ROPAComplianceGap {
|
|
156
|
+
recordId: string;
|
|
157
|
+
recordName: string;
|
|
158
|
+
gaps: string[];
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Validation result for a processing record
|
|
162
|
+
*/
|
|
163
|
+
interface ROPAValidationResult {
|
|
164
|
+
valid: boolean;
|
|
165
|
+
errors: string[];
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Validates a processing record to ensure all required fields are present
|
|
169
|
+
* and properly filled per NDPA 2023 requirements.
|
|
170
|
+
*
|
|
171
|
+
* @param record - The processing record to validate
|
|
172
|
+
* @returns Validation result with any errors found
|
|
173
|
+
*/
|
|
174
|
+
declare function validateProcessingRecord(record: ProcessingRecord): ROPAValidationResult;
|
|
175
|
+
/**
|
|
176
|
+
* Generates a summary of the Record of Processing Activities.
|
|
177
|
+
* Provides statistics and identifies records that are due for review.
|
|
178
|
+
*
|
|
179
|
+
* @param ropa - The full Record of Processing Activities
|
|
180
|
+
* @returns Summary statistics for the ROPA
|
|
181
|
+
*/
|
|
182
|
+
declare function generateROPASummary(ropa: RecordOfProcessingActivities): ROPASummary;
|
|
183
|
+
/**
|
|
184
|
+
* Exports the Record of Processing Activities to a CSV string.
|
|
185
|
+
* The CSV includes all key fields from each processing record.
|
|
186
|
+
*
|
|
187
|
+
* @param ropa - The full Record of Processing Activities
|
|
188
|
+
* @returns CSV-formatted string
|
|
189
|
+
*/
|
|
190
|
+
declare function exportROPAToCSV(ropa: RecordOfProcessingActivities): string;
|
|
191
|
+
/**
|
|
192
|
+
* Identifies compliance gaps in the Record of Processing Activities.
|
|
193
|
+
* Finds records that are missing required information per NDPA 2023.
|
|
194
|
+
*
|
|
195
|
+
* @param ropa - The full Record of Processing Activities
|
|
196
|
+
* @returns Array of compliance gaps grouped by record
|
|
197
|
+
*/
|
|
198
|
+
declare function identifyComplianceGaps(ropa: RecordOfProcessingActivities): ROPAComplianceGap[];
|
|
199
|
+
|
|
200
|
+
export { type ProcessingRecord as P, type RecordOfProcessingActivities as R, type ROPASummary as a, type ROPAComplianceGap as b, type ROPAValidationResult as c, exportROPAToCSV as e, generateROPASummary as g, identifyComplianceGaps as i, validateProcessingRecord as v };
|
package/dist/ropa.d.mts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { R as RecordOfProcessingActivities, P as ProcessingRecord } from './ropa-Rb4dsFSz.mjs';
|
|
3
|
+
export { b as ROPAComplianceGap, a as ROPASummary, c as ROPAValidationResult, e as exportROPAToCSV, g as generateROPASummary, i as identifyComplianceGaps, v as validateProcessingRecord } from './ropa-Rb4dsFSz.mjs';
|
|
4
|
+
export { U as UseROPAOptions, a as UseROPAReturn, u as useROPA } from './useROPA-nmcSiUYv.mjs';
|
|
5
|
+
import './lawful-basis-CWtvDG1x.mjs';
|
|
6
|
+
|
|
7
|
+
interface ROPAManagerProps {
|
|
8
|
+
/**
|
|
9
|
+
* The full Record of Processing Activities
|
|
10
|
+
*/
|
|
11
|
+
ropa: RecordOfProcessingActivities;
|
|
12
|
+
/**
|
|
13
|
+
* Callback when a new record is added
|
|
14
|
+
*/
|
|
15
|
+
onAddRecord?: (record: ProcessingRecord) => void;
|
|
16
|
+
/**
|
|
17
|
+
* Callback when a record is updated
|
|
18
|
+
*/
|
|
19
|
+
onUpdateRecord?: (id: string, updates: Partial<ProcessingRecord>) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Callback when a record is archived
|
|
22
|
+
*/
|
|
23
|
+
onArchiveRecord?: (id: string) => void;
|
|
24
|
+
/**
|
|
25
|
+
* Title displayed on the manager
|
|
26
|
+
* @default "Record of Processing Activities (ROPA)"
|
|
27
|
+
*/
|
|
28
|
+
title?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Description text
|
|
31
|
+
* @default "Maintain a comprehensive record of all data processing activities as required by the NDPA 2023."
|
|
32
|
+
*/
|
|
33
|
+
description?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Custom CSS class
|
|
36
|
+
*/
|
|
37
|
+
className?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Custom CSS class for buttons
|
|
40
|
+
*/
|
|
41
|
+
buttonClassName?: string;
|
|
42
|
+
}
|
|
43
|
+
declare const ROPAManager: React.FC<ROPAManagerProps>;
|
|
44
|
+
|
|
45
|
+
export { ProcessingRecord, ROPAManager, RecordOfProcessingActivities };
|
package/dist/ropa.d.ts
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { R as RecordOfProcessingActivities, P as ProcessingRecord } from './ropa-BebGfqKQ.js';
|
|
3
|
+
export { b as ROPAComplianceGap, a as ROPASummary, c as ROPAValidationResult, e as exportROPAToCSV, g as generateROPASummary, i as identifyComplianceGaps, v as validateProcessingRecord } from './ropa-BebGfqKQ.js';
|
|
4
|
+
export { U as UseROPAOptions, a as UseROPAReturn, u as useROPA } from './useROPA-Bcs6cRdi.js';
|
|
5
|
+
import './lawful-basis-CWtvDG1x.js';
|
|
6
|
+
|
|
7
|
+
interface ROPAManagerProps {
|
|
8
|
+
/**
|
|
9
|
+
* The full Record of Processing Activities
|
|
10
|
+
*/
|
|
11
|
+
ropa: RecordOfProcessingActivities;
|
|
12
|
+
/**
|
|
13
|
+
* Callback when a new record is added
|
|
14
|
+
*/
|
|
15
|
+
onAddRecord?: (record: ProcessingRecord) => void;
|
|
16
|
+
/**
|
|
17
|
+
* Callback when a record is updated
|
|
18
|
+
*/
|
|
19
|
+
onUpdateRecord?: (id: string, updates: Partial<ProcessingRecord>) => void;
|
|
20
|
+
/**
|
|
21
|
+
* Callback when a record is archived
|
|
22
|
+
*/
|
|
23
|
+
onArchiveRecord?: (id: string) => void;
|
|
24
|
+
/**
|
|
25
|
+
* Title displayed on the manager
|
|
26
|
+
* @default "Record of Processing Activities (ROPA)"
|
|
27
|
+
*/
|
|
28
|
+
title?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Description text
|
|
31
|
+
* @default "Maintain a comprehensive record of all data processing activities as required by the NDPA 2023."
|
|
32
|
+
*/
|
|
33
|
+
description?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Custom CSS class
|
|
36
|
+
*/
|
|
37
|
+
className?: string;
|
|
38
|
+
/**
|
|
39
|
+
* Custom CSS class for buttons
|
|
40
|
+
*/
|
|
41
|
+
buttonClassName?: string;
|
|
42
|
+
}
|
|
43
|
+
declare const ROPAManager: React.FC<ROPAManagerProps>;
|
|
44
|
+
|
|
45
|
+
export { ProcessingRecord, ROPAManager, RecordOfProcessingActivities };
|
package/dist/ropa.js
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';var chunkUUWVBENC_js=require('./chunk-UUWVBENC.js'),chunk4A354HL3_js=require('./chunk-4A354HL3.js'),chunkSWF3YVE5_js=require('./chunk-SWF3YVE5.js');require('./chunk-MQFZHA2D.js');Object.defineProperty(exports,"ROPAManager",{enumerable:true,get:function(){return chunkUUWVBENC_js.a}});Object.defineProperty(exports,"useROPA",{enumerable:true,get:function(){return chunk4A354HL3_js.a}});Object.defineProperty(exports,"exportROPAToCSV",{enumerable:true,get:function(){return chunkSWF3YVE5_js.c}});Object.defineProperty(exports,"generateROPASummary",{enumerable:true,get:function(){return chunkSWF3YVE5_js.b}});Object.defineProperty(exports,"identifyComplianceGaps",{enumerable:true,get:function(){return chunkSWF3YVE5_js.d}});Object.defineProperty(exports,"validateProcessingRecord",{enumerable:true,get:function(){return chunkSWF3YVE5_js.a}});//# sourceMappingURL=ropa.js.map
|
|
2
|
+
//# sourceMappingURL=ropa.js.map
|
package/dist/ropa.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"ropa.js"}
|
package/dist/ropa.mjs
ADDED
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export{a as ROPAManager}from'./chunk-6SGG6WPA.mjs';export{a as useROPA}from'./chunk-T44JQT2O.mjs';export{c as exportROPAToCSV,b as generateROPASummary,d as identifyComplianceGaps,a as validateProcessingRecord}from'./chunk-PYEX7DFR.mjs';import'./chunk-WWT2ZSNU.mjs';//# sourceMappingURL=ropa.mjs.map
|
|
2
|
+
//# sourceMappingURL=ropa.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"ropa.mjs"}
|
package/dist/unstyled.d.mts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
2
|
|
|
3
3
|
interface UnstyledConsentBannerProps {
|
|
4
4
|
className?: string;
|
|
5
5
|
children?: ReactNode;
|
|
6
6
|
}
|
|
7
|
-
declare const UnstyledConsentBanner:
|
|
7
|
+
declare const UnstyledConsentBanner: React.FC<UnstyledConsentBannerProps>;
|
|
8
8
|
|
|
9
9
|
interface UnstyledConsentSettingsProps {
|
|
10
10
|
className?: string;
|
|
11
11
|
children?: ReactNode;
|
|
12
12
|
}
|
|
13
|
-
declare const UnstyledConsentSettings:
|
|
13
|
+
declare const UnstyledConsentSettings: React.FC<UnstyledConsentSettingsProps>;
|
|
14
14
|
|
|
15
15
|
interface UnstyledConsentToggleProps {
|
|
16
16
|
category: 'analytics' | 'marketing' | 'functional';
|
|
17
17
|
className?: string;
|
|
18
18
|
label?: string;
|
|
19
19
|
}
|
|
20
|
-
declare const UnstyledConsentToggle:
|
|
20
|
+
declare const UnstyledConsentToggle: React.FC<UnstyledConsentToggleProps>;
|
|
21
21
|
|
|
22
22
|
export { UnstyledConsentBanner as ConsentBanner, UnstyledConsentSettings as ConsentSettings, UnstyledConsentToggle as ConsentToggle };
|
package/dist/unstyled.d.ts
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
2
|
|
|
3
3
|
interface UnstyledConsentBannerProps {
|
|
4
4
|
className?: string;
|
|
5
5
|
children?: ReactNode;
|
|
6
6
|
}
|
|
7
|
-
declare const UnstyledConsentBanner:
|
|
7
|
+
declare const UnstyledConsentBanner: React.FC<UnstyledConsentBannerProps>;
|
|
8
8
|
|
|
9
9
|
interface UnstyledConsentSettingsProps {
|
|
10
10
|
className?: string;
|
|
11
11
|
children?: ReactNode;
|
|
12
12
|
}
|
|
13
|
-
declare const UnstyledConsentSettings:
|
|
13
|
+
declare const UnstyledConsentSettings: React.FC<UnstyledConsentSettingsProps>;
|
|
14
14
|
|
|
15
15
|
interface UnstyledConsentToggleProps {
|
|
16
16
|
category: 'analytics' | 'marketing' | 'functional';
|
|
17
17
|
className?: string;
|
|
18
18
|
label?: string;
|
|
19
19
|
}
|
|
20
|
-
declare const UnstyledConsentToggle:
|
|
20
|
+
declare const UnstyledConsentToggle: React.FC<UnstyledConsentToggleProps>;
|
|
21
21
|
|
|
22
22
|
export { UnstyledConsentBanner as ConsentBanner, UnstyledConsentSettings as ConsentSettings, UnstyledConsentToggle as ConsentToggle };
|
package/dist/unstyled.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
'use strict';var e=require('react');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var e__default=/*#__PURE__*/_interopDefault(e);var v=e.createContext(void 0);function i(){let n=e.useContext(v);if(!n)throw new Error("useConsent must be used within a ConsentProvider");return n}var C=({className:n,children:a})=>{let{showBanner:o,acceptAll:r,rejectAll:l,openSettings:c}=i();return o?e__default.default.createElement("div",{className:n,role:"region","aria-label":"Cookie consent"},a||e__default.default.createElement(e__default.default.Fragment,null,e__default.default.createElement("div",null,e__default.default.createElement("h3",null,"Cookie Consent"),e__default.default.createElement("p",null,"We use cookies to enhance your experience. By continuing to visit this site you agree to our use of cookies.")),e__default.default.createElement("div",null,e__default.default.createElement("button",{onClick:r,"aria-label":"Accept all cookies"},"Accept All"),e__default.default.createElement("button",{onClick:l,"aria-label":"Reject non-essential cookies"},"Reject All"),e__default.default.createElement("button",{onClick:c,"aria-label":"Manage cookie preferences"},"Manage Preferences")))):null};var h=[{id:"necessary",name:"Necessary Cookies",description:"These cookies are essential for the website to function properly.",disabled:true},{id:"analytics",name:"Analytics Cookies",description:"These cookies help us understand how visitors interact with our website.",disabled:false},{id:"marketing",name:"Marketing Cookies",description:"These cookies are used to track visitors across websites for marketing purposes.",disabled:false},{id:"functional",name:"Functional Cookies",description:"These cookies enable personalized features and functionality.",disabled:false}],f=({className:n,children:a})=>{let{showSettings:o,consentState:r,updateConsent:l,savePreferences:c,closeSettings:p}=i();if(!o)return null;let g=()=>{c(r);};return e__default.default.createElement("div",{className:n,role:"dialog","aria-label":"Cookie preferences"},a||e__default.default.createElement(e__default.default.Fragment,null,e__default.default.createElement("div",null,e__default.default.createElement("h2",null,"Cookie Preferences"),e__default.default.createElement("p",null,"Manage your cookie preferences. You can enable or disable different categories of cookies below.")),e__default.default.createElement("div",null,h.map(s=>e__default.default.createElement("div",{key:s.id},e__default.default.createElement("div",null,e__default.default.createElement("h4",null,s.name),e__default.default.createElement("p",null,s.description)),e__default.default.createElement("input",{type:"checkbox",checked:r[s.id],onChange:k=>l(s.id,k.target.checked),disabled:s.disabled,"aria-label":`Toggle ${s.name}`})))),e__default.default.createElement("div",null,e__default.default.createElement("button",{onClick:p,"aria-label":"Cancel changes"},"Cancel"),e__default.default.createElement("button",{onClick:g,"aria-label":"Save cookie preferences"},"Save Preferences"))))};var u=({category:n,className:a,label:o})=>{let{consentState:r,updateConsent:l}=i();return e__default.default.createElement("label",{className:a},e__default.default.createElement("input",{type:"checkbox",checked:r[n],onChange:c=>l(n,c.target.checked),"aria-label":o||`Toggle ${n} cookies`}),o&&e__default.default.createElement("span",null,o))};exports.ConsentBanner=C;exports.ConsentSettings=f;exports.ConsentToggle=u;//# sourceMappingURL=unstyled.js.map
|
|
1
|
+
'use strict';require('./chunk-MQFZHA2D.js');var e=require('react');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var e__default=/*#__PURE__*/_interopDefault(e);var v=e.createContext(void 0);function i(){let n=e.useContext(v);if(!n)throw new Error("useConsent must be used within a ConsentProvider");return n}var C=({className:n,children:a})=>{let{showBanner:o,acceptAll:r,rejectAll:l,openSettings:c}=i();return o?e__default.default.createElement("div",{className:n,role:"region","aria-label":"Cookie consent"},a||e__default.default.createElement(e__default.default.Fragment,null,e__default.default.createElement("div",null,e__default.default.createElement("h3",null,"Cookie Consent"),e__default.default.createElement("p",null,"We use cookies to enhance your experience. By continuing to visit this site you agree to our use of cookies.")),e__default.default.createElement("div",null,e__default.default.createElement("button",{onClick:r,"aria-label":"Accept all cookies"},"Accept All"),e__default.default.createElement("button",{onClick:l,"aria-label":"Reject non-essential cookies"},"Reject All"),e__default.default.createElement("button",{onClick:c,"aria-label":"Manage cookie preferences"},"Manage Preferences")))):null};var h=[{id:"necessary",name:"Necessary Cookies",description:"These cookies are essential for the website to function properly.",disabled:true},{id:"analytics",name:"Analytics Cookies",description:"These cookies help us understand how visitors interact with our website.",disabled:false},{id:"marketing",name:"Marketing Cookies",description:"These cookies are used to track visitors across websites for marketing purposes.",disabled:false},{id:"functional",name:"Functional Cookies",description:"These cookies enable personalized features and functionality.",disabled:false}],f=({className:n,children:a})=>{let{showSettings:o,consentState:r,updateConsent:l,savePreferences:c,closeSettings:p}=i();if(!o)return null;let g=()=>{c(r);};return e__default.default.createElement("div",{className:n,role:"dialog","aria-label":"Cookie preferences"},a||e__default.default.createElement(e__default.default.Fragment,null,e__default.default.createElement("div",null,e__default.default.createElement("h2",null,"Cookie Preferences"),e__default.default.createElement("p",null,"Manage your cookie preferences. You can enable or disable different categories of cookies below.")),e__default.default.createElement("div",null,h.map(s=>e__default.default.createElement("div",{key:s.id},e__default.default.createElement("div",null,e__default.default.createElement("h4",null,s.name),e__default.default.createElement("p",null,s.description)),e__default.default.createElement("input",{type:"checkbox",checked:r[s.id],onChange:k=>l(s.id,k.target.checked),disabled:s.disabled,"aria-label":`Toggle ${s.name}`})))),e__default.default.createElement("div",null,e__default.default.createElement("button",{onClick:p,"aria-label":"Cancel changes"},"Cancel"),e__default.default.createElement("button",{onClick:g,"aria-label":"Save cookie preferences"},"Save Preferences"))))};var u=({category:n,className:a,label:o})=>{let{consentState:r,updateConsent:l}=i();return e__default.default.createElement("label",{className:a},e__default.default.createElement("input",{type:"checkbox",checked:r[n],onChange:c=>l(n,c.target.checked),"aria-label":o||`Toggle ${n} cookies`}),o&&e__default.default.createElement("span",null,o))};exports.ConsentBanner=C;exports.ConsentSettings=f;exports.ConsentToggle=u;//# sourceMappingURL=unstyled.js.map
|
|
2
2
|
//# sourceMappingURL=unstyled.js.map
|
package/dist/unstyled.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/contexts/ConsentContext.tsx","../src/components/consent/unstyled/UnstyledConsentBanner.tsx","../src/components/consent/unstyled/UnstyledConsentSettings.tsx","../src/components/consent/unstyled/UnstyledConsentToggle.tsx"],"names":["ConsentContext","createContext","useConsent","context","useContext","UnstyledConsentBanner","className","children","showBanner","acceptAll","rejectAll","openSettings","React","cookieCategories","UnstyledConsentSettings","showSettings","consentState","updateConsent","savePreferences","closeSettings","handleSave","category","e","UnstyledConsentToggle","label"],"mappings":"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","file":"unstyled.js","sourcesContent":["import React, { createContext, useContext, useState, useCallback, useEffect, ReactNode } from 'react';\n\nexport interface ConsentCategories {\n necessary: boolean;\n analytics: boolean;\n marketing: boolean;\n functional: boolean;\n [key: string]: boolean;\n}\n\nexport interface ConsentState {\n hasUserConsented: boolean;\n consentState: ConsentCategories;\n showBanner: boolean;\n showSettings: boolean;\n}\n\nexport interface ConsentActions {\n acceptAll: () => void;\n rejectAll: () => void;\n savePreferences: (preferences: Partial<ConsentCategories>) => void;\n openSettings: () => void;\n closeSettings: () => void;\n updateConsent: (category: keyof ConsentCategories, value: boolean) => void;\n}\n\nexport interface ConsentContextValue extends ConsentState, ConsentActions {}\n\nconst ConsentContext = createContext<ConsentContextValue | undefined>(undefined);\n\nexport interface ConsentProviderProps {\n children: ReactNode;\n initialConsent?: Partial<ConsentCategories>;\n onConsentChange?: (consent: ConsentCategories) => void;\n storageKey?: string;\n}\n\nconst defaultConsent: ConsentCategories = {\n necessary: true, // Always true\n analytics: false,\n marketing: false,\n functional: false,\n};\n\nexport function ConsentProvider({\n children,\n initialConsent = {},\n onConsentChange,\n storageKey = 'ndpr-consent',\n}: ConsentProviderProps) {\n const [consentState, setConsentState] = useState<ConsentCategories>(() => {\n // Try to load from localStorage\n if (typeof window !== 'undefined') {\n const stored = localStorage.getItem(storageKey);\n if (stored) {\n try {\n const parsed = JSON.parse(stored);\n return { ...defaultConsent, ...parsed };\n } catch (e) {\n console.error('Failed to parse consent from localStorage', e);\n }\n }\n }\n return { ...defaultConsent, ...initialConsent };\n });\n\n const [hasUserConsented, setHasUserConsented] = useState(() => {\n if (typeof window !== 'undefined') {\n return localStorage.getItem(`${storageKey}-set`) === 'true';\n }\n return false;\n });\n\n const [showBanner, setShowBanner] = useState(!hasUserConsented);\n const [showSettings, setShowSettings] = useState(false);\n\n // Persist consent to localStorage\n useEffect(() => {\n if (typeof window !== 'undefined' && hasUserConsented) {\n localStorage.setItem(storageKey, JSON.stringify(consentState));\n localStorage.setItem(`${storageKey}-set`, 'true');\n }\n }, [consentState, hasUserConsented, storageKey]);\n\n // Notify parent of consent changes\n useEffect(() => {\n if (hasUserConsented && onConsentChange) {\n onConsentChange(consentState);\n }\n }, [consentState, hasUserConsented, onConsentChange]);\n\n const acceptAll = useCallback(() => {\n const newConsent: ConsentCategories = {\n necessary: true,\n analytics: true,\n marketing: true,\n functional: true,\n };\n setConsentState(newConsent);\n setHasUserConsented(true);\n setShowBanner(false);\n setShowSettings(false);\n }, []);\n\n const rejectAll = useCallback(() => {\n const newConsent: ConsentCategories = {\n necessary: true,\n analytics: false,\n marketing: false,\n functional: false,\n };\n setConsentState(newConsent);\n setHasUserConsented(true);\n setShowBanner(false);\n setShowSettings(false);\n }, []);\n\n const savePreferences = useCallback((preferences: Partial<ConsentCategories>) => {\n setConsentState(prev => ({\n ...prev,\n ...preferences,\n necessary: true, // Always keep necessary as true\n }));\n setHasUserConsented(true);\n setShowBanner(false);\n setShowSettings(false);\n }, []);\n\n const updateConsent = useCallback((category: keyof ConsentCategories, value: boolean) => {\n if (category === 'necessary') return; // Can't change necessary cookies\n \n setConsentState(prev => ({\n ...prev,\n [category]: value,\n }));\n }, []);\n\n const openSettings = useCallback(() => {\n setShowSettings(true);\n setShowBanner(false);\n }, []);\n\n const closeSettings = useCallback(() => {\n setShowSettings(false);\n }, []);\n\n const value: ConsentContextValue = {\n hasUserConsented,\n consentState,\n showBanner,\n showSettings,\n acceptAll,\n rejectAll,\n savePreferences,\n openSettings,\n closeSettings,\n updateConsent,\n };\n\n return (\n <ConsentContext.Provider value={value}>\n {children}\n </ConsentContext.Provider>\n );\n}\n\nexport function useConsent() {\n const context = useContext(ConsentContext);\n if (!context) {\n throw new Error('useConsent must be used within a ConsentProvider');\n }\n return context;\n}\n\n// Export for external use\nexport { ConsentContext };","import React, { ReactNode } from 'react';\nimport { useConsent } from '@/contexts/ConsentContext';\n\nexport interface UnstyledConsentBannerProps {\n className?: string;\n children?: ReactNode;\n}\n\nexport const UnstyledConsentBanner: React.FC<UnstyledConsentBannerProps> = ({\n className,\n children,\n}) => {\n const { showBanner, acceptAll, rejectAll, openSettings } = useConsent();\n\n if (!showBanner) return null;\n\n return (\n <div className={className} role=\"region\" aria-label=\"Cookie consent\">\n {children || (\n <>\n <div>\n <h3>Cookie Consent</h3>\n <p>We use cookies to enhance your experience. By continuing to visit this site you agree to our use of cookies.</p>\n </div>\n <div>\n <button onClick={acceptAll} aria-label=\"Accept all cookies\">\n Accept All\n </button>\n <button onClick={rejectAll} aria-label=\"Reject non-essential cookies\">\n Reject All\n </button>\n <button onClick={openSettings} aria-label=\"Manage cookie preferences\">\n Manage Preferences\n </button>\n </div>\n </>\n )}\n </div>\n );\n};","import React, { ReactNode } from 'react';\nimport { useConsent } from '@/contexts/ConsentContext';\n\nexport interface UnstyledConsentSettingsProps {\n className?: string;\n children?: ReactNode;\n}\n\nconst cookieCategories = [\n {\n id: 'necessary',\n name: 'Necessary Cookies',\n description: 'These cookies are essential for the website to function properly.',\n disabled: true,\n },\n {\n id: 'analytics',\n name: 'Analytics Cookies',\n description: 'These cookies help us understand how visitors interact with our website.',\n disabled: false,\n },\n {\n id: 'marketing',\n name: 'Marketing Cookies',\n description: 'These cookies are used to track visitors across websites for marketing purposes.',\n disabled: false,\n },\n {\n id: 'functional',\n name: 'Functional Cookies',\n description: 'These cookies enable personalized features and functionality.',\n disabled: false,\n },\n];\n\nexport const UnstyledConsentSettings: React.FC<UnstyledConsentSettingsProps> = ({\n className,\n children,\n}) => {\n const { showSettings, consentState, updateConsent, savePreferences, closeSettings } = useConsent();\n\n if (!showSettings) return null;\n\n const handleSave = () => {\n savePreferences(consentState);\n };\n\n return (\n <div className={className} role=\"dialog\" aria-label=\"Cookie preferences\">\n {children || (\n <>\n <div>\n <h2>Cookie Preferences</h2>\n <p>Manage your cookie preferences. You can enable or disable different categories of cookies below.</p>\n </div>\n \n <div>\n {cookieCategories.map((category) => (\n <div key={category.id}>\n <div>\n <h4>{category.name}</h4>\n <p>{category.description}</p>\n </div>\n <input\n type=\"checkbox\"\n checked={consentState[category.id as keyof typeof consentState]}\n onChange={(e) => updateConsent(category.id as keyof typeof consentState, e.target.checked)}\n disabled={category.disabled}\n aria-label={`Toggle ${category.name}`}\n />\n </div>\n ))}\n </div>\n\n <div>\n <button onClick={closeSettings} aria-label=\"Cancel changes\">\n Cancel\n </button>\n <button onClick={handleSave} aria-label=\"Save cookie preferences\">\n Save Preferences\n </button>\n </div>\n </>\n )}\n </div>\n );\n};","import React from 'react';\nimport { useConsent } from '@/contexts/ConsentContext';\n\nexport interface UnstyledConsentToggleProps {\n category: 'analytics' | 'marketing' | 'functional';\n className?: string;\n label?: string;\n}\n\nexport const UnstyledConsentToggle: React.FC<UnstyledConsentToggleProps> = ({\n category,\n className,\n label,\n}) => {\n const { consentState, updateConsent } = useConsent();\n\n return (\n <label className={className}>\n <input\n type=\"checkbox\"\n checked={consentState[category]}\n onChange={(e) => updateConsent(category, e.target.checked)}\n aria-label={label || `Toggle ${category} cookies`}\n />\n {label && <span>{label}</span>}\n </label>\n );\n};"]}
|
|
1
|
+
{"version":3,"sources":["../src/contexts/ConsentContext.tsx","../src/components/consent/unstyled/UnstyledConsentBanner.tsx","../src/components/consent/unstyled/UnstyledConsentSettings.tsx","../src/components/consent/unstyled/UnstyledConsentToggle.tsx"],"names":["ConsentContext","createContext","useConsent","context","useContext","UnstyledConsentBanner","className","children","showBanner","acceptAll","rejectAll","openSettings","React","cookieCategories","UnstyledConsentSettings","showSettings","consentState","updateConsent","savePreferences","closeSettings","handleSave","category","e","UnstyledConsentToggle","label"],"mappings":"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","file":"unstyled.js","sourcesContent":["import React, { createContext, useContext, useState, useCallback, useEffect, ReactNode } from 'react';\n\nexport interface ConsentCategories {\n necessary: boolean;\n analytics: boolean;\n marketing: boolean;\n functional: boolean;\n [key: string]: boolean;\n}\n\nexport interface ConsentState {\n hasUserConsented: boolean;\n consentState: ConsentCategories;\n showBanner: boolean;\n showSettings: boolean;\n}\n\nexport interface ConsentActions {\n acceptAll: () => void;\n rejectAll: () => void;\n savePreferences: (preferences: Partial<ConsentCategories>) => void;\n openSettings: () => void;\n closeSettings: () => void;\n updateConsent: (category: keyof ConsentCategories, value: boolean) => void;\n}\n\nexport interface ConsentContextValue extends ConsentState, ConsentActions {}\n\nconst ConsentContext = createContext<ConsentContextValue | undefined>(undefined);\n\nexport interface ConsentProviderProps {\n children: ReactNode;\n initialConsent?: Partial<ConsentCategories>;\n onConsentChange?: (consent: ConsentCategories) => void;\n storageKey?: string;\n}\n\nconst defaultConsent: ConsentCategories = {\n necessary: true, // Always true\n analytics: false,\n marketing: false,\n functional: false,\n};\n\nexport function ConsentProvider({\n children,\n initialConsent = {},\n onConsentChange,\n storageKey = 'ndpr-consent',\n}: ConsentProviderProps) {\n const [consentState, setConsentState] = useState<ConsentCategories>(() => {\n // Try to load from localStorage\n if (typeof window !== 'undefined') {\n const stored = localStorage.getItem(storageKey);\n if (stored) {\n try {\n const parsed = JSON.parse(stored);\n return { ...defaultConsent, ...parsed };\n } catch (e) {\n console.error('Failed to parse consent from localStorage', e);\n }\n }\n }\n return { ...defaultConsent, ...initialConsent };\n });\n\n const [hasUserConsented, setHasUserConsented] = useState(() => {\n if (typeof window !== 'undefined') {\n return localStorage.getItem(`${storageKey}-set`) === 'true';\n }\n return false;\n });\n\n const [showBanner, setShowBanner] = useState(!hasUserConsented);\n const [showSettings, setShowSettings] = useState(false);\n\n // Persist consent to localStorage\n useEffect(() => {\n if (typeof window !== 'undefined' && hasUserConsented) {\n localStorage.setItem(storageKey, JSON.stringify(consentState));\n localStorage.setItem(`${storageKey}-set`, 'true');\n }\n }, [consentState, hasUserConsented, storageKey]);\n\n // Notify parent of consent changes\n useEffect(() => {\n if (hasUserConsented && onConsentChange) {\n onConsentChange(consentState);\n }\n }, [consentState, hasUserConsented, onConsentChange]);\n\n const acceptAll = useCallback(() => {\n const newConsent: ConsentCategories = {\n necessary: true,\n analytics: true,\n marketing: true,\n functional: true,\n };\n setConsentState(newConsent);\n setHasUserConsented(true);\n setShowBanner(false);\n setShowSettings(false);\n }, []);\n\n const rejectAll = useCallback(() => {\n const newConsent: ConsentCategories = {\n necessary: true,\n analytics: false,\n marketing: false,\n functional: false,\n };\n setConsentState(newConsent);\n setHasUserConsented(true);\n setShowBanner(false);\n setShowSettings(false);\n }, []);\n\n const savePreferences = useCallback((preferences: Partial<ConsentCategories>) => {\n setConsentState(prev => ({\n ...prev,\n ...preferences,\n necessary: true, // Always keep necessary as true\n }));\n setHasUserConsented(true);\n setShowBanner(false);\n setShowSettings(false);\n }, []);\n\n const updateConsent = useCallback((category: keyof ConsentCategories, value: boolean) => {\n if (category === 'necessary') return; // Can't change necessary cookies\n \n setConsentState(prev => ({\n ...prev,\n [category]: value,\n }));\n }, []);\n\n const openSettings = useCallback(() => {\n setShowSettings(true);\n setShowBanner(false);\n }, []);\n\n const closeSettings = useCallback(() => {\n setShowSettings(false);\n }, []);\n\n const value: ConsentContextValue = {\n hasUserConsented,\n consentState,\n showBanner,\n showSettings,\n acceptAll,\n rejectAll,\n savePreferences,\n openSettings,\n closeSettings,\n updateConsent,\n };\n\n return (\n <ConsentContext.Provider value={value}>\n {children}\n </ConsentContext.Provider>\n );\n}\n\nexport function useConsent() {\n const context = useContext(ConsentContext);\n if (!context) {\n throw new Error('useConsent must be used within a ConsentProvider');\n }\n return context;\n}\n\n// Export for external use\nexport { ConsentContext };","import React, { ReactNode } from 'react';\nimport { useConsent } from '@/contexts/ConsentContext';\n\nexport interface UnstyledConsentBannerProps {\n className?: string;\n children?: ReactNode;\n}\n\nexport const UnstyledConsentBanner: React.FC<UnstyledConsentBannerProps> = ({\n className,\n children,\n}) => {\n const { showBanner, acceptAll, rejectAll, openSettings } = useConsent();\n\n if (!showBanner) return null;\n\n return (\n <div className={className} role=\"region\" aria-label=\"Cookie consent\">\n {children || (\n <>\n <div>\n <h3>Cookie Consent</h3>\n <p>We use cookies to enhance your experience. By continuing to visit this site you agree to our use of cookies.</p>\n </div>\n <div>\n <button onClick={acceptAll} aria-label=\"Accept all cookies\">\n Accept All\n </button>\n <button onClick={rejectAll} aria-label=\"Reject non-essential cookies\">\n Reject All\n </button>\n <button onClick={openSettings} aria-label=\"Manage cookie preferences\">\n Manage Preferences\n </button>\n </div>\n </>\n )}\n </div>\n );\n};","import React, { ReactNode } from 'react';\nimport { useConsent } from '@/contexts/ConsentContext';\n\nexport interface UnstyledConsentSettingsProps {\n className?: string;\n children?: ReactNode;\n}\n\nconst cookieCategories = [\n {\n id: 'necessary',\n name: 'Necessary Cookies',\n description: 'These cookies are essential for the website to function properly.',\n disabled: true,\n },\n {\n id: 'analytics',\n name: 'Analytics Cookies',\n description: 'These cookies help us understand how visitors interact with our website.',\n disabled: false,\n },\n {\n id: 'marketing',\n name: 'Marketing Cookies',\n description: 'These cookies are used to track visitors across websites for marketing purposes.',\n disabled: false,\n },\n {\n id: 'functional',\n name: 'Functional Cookies',\n description: 'These cookies enable personalized features and functionality.',\n disabled: false,\n },\n];\n\nexport const UnstyledConsentSettings: React.FC<UnstyledConsentSettingsProps> = ({\n className,\n children,\n}) => {\n const { showSettings, consentState, updateConsent, savePreferences, closeSettings } = useConsent();\n\n if (!showSettings) return null;\n\n const handleSave = () => {\n savePreferences(consentState);\n };\n\n return (\n <div className={className} role=\"dialog\" aria-label=\"Cookie preferences\">\n {children || (\n <>\n <div>\n <h2>Cookie Preferences</h2>\n <p>Manage your cookie preferences. You can enable or disable different categories of cookies below.</p>\n </div>\n \n <div>\n {cookieCategories.map((category) => (\n <div key={category.id}>\n <div>\n <h4>{category.name}</h4>\n <p>{category.description}</p>\n </div>\n <input\n type=\"checkbox\"\n checked={consentState[category.id as keyof typeof consentState]}\n onChange={(e) => updateConsent(category.id as keyof typeof consentState, e.target.checked)}\n disabled={category.disabled}\n aria-label={`Toggle ${category.name}`}\n />\n </div>\n ))}\n </div>\n\n <div>\n <button onClick={closeSettings} aria-label=\"Cancel changes\">\n Cancel\n </button>\n <button onClick={handleSave} aria-label=\"Save cookie preferences\">\n Save Preferences\n </button>\n </div>\n </>\n )}\n </div>\n );\n};","import React from 'react';\nimport { useConsent } from '@/contexts/ConsentContext';\n\nexport interface UnstyledConsentToggleProps {\n category: 'analytics' | 'marketing' | 'functional';\n className?: string;\n label?: string;\n}\n\nexport const UnstyledConsentToggle: React.FC<UnstyledConsentToggleProps> = ({\n category,\n className,\n label,\n}) => {\n const { consentState, updateConsent } = useConsent();\n\n return (\n <label className={className}>\n <input\n type=\"checkbox\"\n checked={consentState[category]}\n onChange={(e) => updateConsent(category, e.target.checked)}\n aria-label={label || `Toggle ${category} cookies`}\n />\n {label && <span>{label}</span>}\n </label>\n );\n};"]}
|