@tantainnovative/ndpr-toolkit 2.4.0 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +226 -246
- package/dist/BreachReportForm-DpRrBoxU.d.ts +158 -0
- package/dist/BreachReportForm-yJ2Zl6gz.d.mts +158 -0
- package/dist/ConsentBanner-CDRT0o2k.d.mts +146 -0
- package/dist/ConsentBanner-Vxyt8SCX.d.ts +146 -0
- package/dist/{cross-border-entry-BrWVPly6.d.ts → CrossBorderTransferManager-D5Lc0e46.d.ts} +4 -5
- package/dist/{cross-border-entry-cCTvpwnT.d.mts → CrossBorderTransferManager-DkZhv9vD.d.mts} +4 -5
- package/dist/DPIAQuestionnaire-BkejviPj.d.mts +123 -0
- package/dist/DPIAQuestionnaire-DdSqXG3x.d.ts +123 -0
- package/dist/DSRRequestForm-BY8PogCU.d.mts +146 -0
- package/dist/DSRRequestForm-CHUg9cZh.d.ts +146 -0
- package/dist/DSRTracker-C6u_jAaK.d.mts +163 -0
- package/dist/DSRTracker-Dr_aT0pg.d.ts +163 -0
- package/dist/{lawful-basis-entry-CxZrofwG.d.mts → LawfulBasisTracker-CBqOxX1D.d.mts} +3 -5
- package/dist/{lawful-basis-entry-15qjKcNO.d.ts → LawfulBasisTracker-Cg30NbDA.d.ts} +3 -5
- package/dist/NDPRDashboard-CLJpEg0X.d.mts +44 -0
- package/dist/NDPRDashboard-DDWNd2Ah.d.ts +44 -0
- package/dist/{policy-E0fXZkda.d.mts → PolicyExporter-BIqSVjfC.d.mts} +4 -98
- package/dist/{policy-D2_jh5-T.d.ts → PolicyExporter-BNWaPBGU.d.ts} +4 -98
- package/dist/PolicyGenerator-BvcWPbxp.d.mts +96 -0
- package/dist/PolicyGenerator-BzRwtlgn.d.ts +96 -0
- package/dist/{ropa-entry-B0D7X1GV.d.ts → ROPAManager-BS4eB8Hw.d.mts} +4 -5
- package/dist/{ropa-entry-DiOThOc2.d.mts → ROPAManager-qxTrXLkD.d.ts} +4 -5
- package/dist/{breach-ouXoVTWs.d.ts → RegulatoryReportGenerator-BUYgzTTT.d.ts} +6 -162
- package/dist/{breach-yRiyyc4n.d.mts → RegulatoryReportGenerator-DwcHcEFp.d.mts} +6 -162
- package/dist/StepIndicator-D-nwRTyo.d.mts +171 -0
- package/dist/StepIndicator-D9ZATz_O.d.ts +171 -0
- package/dist/adapters.d.mts +25 -0
- package/dist/adapters.d.ts +25 -0
- package/dist/adapters.js +2 -0
- package/dist/adapters.mjs +2 -0
- package/dist/breach.d.mts +43 -4
- package/dist/breach.d.ts +43 -4
- package/dist/breach.js +1 -1
- package/dist/breach.mjs +1 -1
- package/dist/chunk-27NYSWUG.mjs +2 -0
- package/dist/chunk-2ORDHJRD.js +2 -0
- package/dist/chunk-2W7ARAW2.js +2 -0
- package/dist/chunk-3F34NACG.js +2 -0
- package/dist/chunk-3RGJV3VF.js +7 -0
- package/dist/chunk-3UWT64FI.mjs +2 -0
- package/dist/chunk-3V23O4ZJ.js +2 -0
- package/dist/chunk-3XAUN5IM.mjs +3 -0
- package/dist/chunk-5VMHKNJY.js +2 -0
- package/dist/chunk-6D3ZUGBB.mjs +2 -0
- package/dist/chunk-6E54NSAO.mjs +2 -0
- package/dist/chunk-7F5F5YWI.mjs +2 -0
- package/dist/chunk-7FIUX3ZM.js +89 -0
- package/dist/chunk-FR7ZYZXB.js +2 -0
- package/dist/chunk-FY5G6DGZ.js +7 -0
- package/dist/chunk-G26I6MP5.mjs +2 -0
- package/dist/chunk-GPJVTGHR.mjs +2 -0
- package/dist/chunk-GVANK6PL.js +3 -0
- package/dist/chunk-HNZK7LY3.mjs +2 -0
- package/dist/chunk-IKEPXHCZ.js +2 -0
- package/dist/chunk-IQQW52EF.js +2 -0
- package/dist/chunk-ISSGO2YT.mjs +72 -0
- package/dist/chunk-J6IKAGUP.mjs +89 -0
- package/dist/chunk-KHRBU5K7.js +2 -0
- package/dist/chunk-KNE4NXCY.mjs +7 -0
- package/dist/chunk-LFNA6WYQ.mjs +2 -0
- package/dist/chunk-NPI5T6NH.mjs +7 -0
- package/dist/chunk-NPLXE43Q.mjs +2 -0
- package/dist/chunk-P7BSBCB3.js +2 -0
- package/dist/chunk-PEH5GIMN.js +2 -0
- package/dist/chunk-RSUDIFZV.mjs +2 -0
- package/dist/chunk-SBNAMPAP.mjs +2 -0
- package/dist/chunk-SVCRYM4I.mjs +2 -0
- package/dist/chunk-U6VWHC46.js +72 -0
- package/dist/chunk-UK656RCG.js +2 -0
- package/dist/chunk-UNKXYVXY.js +2 -0
- package/dist/chunk-UOSEH6DC.js +2 -0
- package/dist/chunk-V37BM2LF.js +2 -0
- package/dist/chunk-V3MXWGXU.mjs +2 -0
- package/dist/chunk-VDZKGCAF.js +2 -0
- package/dist/chunk-WLSW4Z4W.mjs +2 -0
- package/dist/chunk-XSK4BSZJ.mjs +2 -0
- package/dist/chunk-YJCGEOLO.mjs +2 -0
- package/dist/chunk-ZCZ5RRZO.js +2 -0
- package/dist/compliance-score-racQe_E_.d.mts +115 -0
- package/dist/compliance-score-racQe_E_.d.ts +115 -0
- package/dist/consent.d.mts +67 -295
- package/dist/consent.d.ts +67 -295
- package/dist/consent.js +1 -1
- package/dist/consent.mjs +1 -1
- package/dist/core.d.mts +8 -5
- package/dist/core.d.ts +8 -5
- package/dist/core.js +1 -1
- package/dist/core.mjs +1 -1
- package/dist/cross-border-BBi9rZyO.d.mts +54 -0
- package/dist/cross-border-Dy-U9Hu6.d.ts +54 -0
- package/dist/{cross-border-BMcqLvjC.d.mts → cross-border-UyT00llA.d.mts} +1 -52
- package/dist/{cross-border-BMcqLvjC.d.ts → cross-border-UyT00llA.d.ts} +1 -52
- package/dist/cross-border.d.mts +32 -4
- package/dist/cross-border.d.ts +32 -4
- package/dist/cross-border.js +1 -1
- package/dist/cross-border.mjs +1 -1
- package/dist/dpia.d.mts +28 -284
- package/dist/dpia.d.ts +28 -284
- package/dist/dpia.js +1 -1
- package/dist/dpia.mjs +1 -1
- package/dist/dsr.d.mts +36 -4
- package/dist/dsr.d.ts +36 -4
- package/dist/dsr.js +1 -1
- package/dist/dsr.mjs +1 -1
- package/dist/hooks.d.mts +21 -10
- package/dist/hooks.d.ts +21 -10
- package/dist/hooks.js +1 -1
- package/dist/hooks.mjs +1 -1
- package/dist/index.d.mts +28 -18
- package/dist/index.d.ts +28 -18
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/lawful-basis.d.mts +31 -4
- package/dist/lawful-basis.d.ts +31 -4
- package/dist/lawful-basis.js +1 -1
- package/dist/lawful-basis.mjs +1 -1
- package/dist/policy.d.mts +36 -4
- package/dist/policy.d.ts +36 -4
- package/dist/policy.js +1 -1
- package/dist/policy.mjs +1 -1
- package/dist/presets.d.mts +124 -0
- package/dist/presets.d.ts +124 -0
- package/dist/presets.js +2 -0
- package/dist/presets.mjs +2 -0
- package/dist/{ropa-Li6UlL5H.d.ts → ropa-BDTM06tr.d.ts} +1 -49
- package/dist/{ropa-DP7pPPql.d.mts → ropa-CFHuT7jE.d.mts} +1 -49
- package/dist/ropa-CyynscU6.d.ts +51 -0
- package/dist/ropa-NIgxd8uP.d.mts +51 -0
- package/dist/ropa.d.mts +30 -4
- package/dist/ropa.d.ts +30 -4
- package/dist/ropa.js +1 -1
- package/dist/ropa.mjs +1 -1
- package/dist/styling-B7CBzYG7.d.ts +165 -0
- package/dist/styling-uJLsBbER.d.mts +165 -0
- package/dist/types-DK2CoKOC.d.mts +10 -0
- package/dist/types-DK2CoKOC.d.ts +10 -0
- package/dist/unstyled.d.mts +4 -4
- package/dist/unstyled.d.ts +4 -4
- package/dist/{useBreach-BBSoIcZO.d.mts → useBreach-CPr86Yan.d.mts} +18 -2
- package/dist/{useBreach-lFLbSyAN.d.ts → useBreach-DkVXvtJK.d.ts} +18 -2
- package/dist/{useConsent-D0pAfTlb.d.ts → useConsent-DCNkIJHR.d.mts} +12 -2
- package/dist/{useConsent-DOt2Njst.d.mts → useConsent-dOcELSfX.d.ts} +12 -2
- package/dist/{useCrossBorderTransfer-DmtACeqW.d.ts → useCrossBorderTransfer-BGNZt2lk.d.mts} +15 -3
- package/dist/{useCrossBorderTransfer-BZVFCXfr.d.mts → useCrossBorderTransfer-COqjgjsu.d.ts} +15 -3
- package/dist/{useDPIA-DBsg2yZx.d.ts → useDPIA-Dl16Te3r.d.ts} +13 -2
- package/dist/{useDPIA-Da7-Q_yW.d.mts → useDPIA-DzWye8JB.d.mts} +13 -2
- package/dist/{useDSR-YYZ6FYFs.d.mts → useDSR-C1LksCfP.d.mts} +13 -2
- package/dist/{useDSR-CYI7WCXr.d.ts → useDSR-DZel52O1.d.ts} +13 -2
- package/dist/{useDefaultPrivacyPolicy-CUluF_ic.d.mts → useDefaultPrivacyPolicy-BsYttRey.d.mts} +13 -2
- package/dist/{useDefaultPrivacyPolicy-B7kTHbZh.d.ts → useDefaultPrivacyPolicy-C-mG-A5S.d.ts} +13 -2
- package/dist/{useLawfulBasis-CpWuHtyh.d.mts → useLawfulBasis-CKJ-kw84.d.mts} +13 -2
- package/dist/{useLawfulBasis-CCWF9waR.d.ts → useLawfulBasis-DFTmu1ca.d.ts} +13 -2
- package/dist/{useROPA-BhJ3kvHp.d.ts → useROPA-BSSU1rfx.d.ts} +14 -2
- package/dist/{useROPA-DLFdjkxP.d.mts → useROPA-C2hjaBTz.d.mts} +14 -2
- package/package.json +18 -2
- package/dist/chunk-2XFAV267.mjs +0 -2
- package/dist/chunk-32UIWTGD.js +0 -72
- package/dist/chunk-3YCV2BA6.js +0 -2
- package/dist/chunk-4A354HL3.js +0 -2
- package/dist/chunk-5ZBO2UPH.js +0 -2
- package/dist/chunk-6GGGTRDZ.mjs +0 -2
- package/dist/chunk-BGHQTZAC.js +0 -94
- package/dist/chunk-BZTTQS4A.mjs +0 -7
- package/dist/chunk-EKVTLHBQ.js +0 -2
- package/dist/chunk-GMLNWS2N.mjs +0 -2
- package/dist/chunk-IBEKLDBY.mjs +0 -2
- package/dist/chunk-K3GMTMQ6.js +0 -2
- package/dist/chunk-L52PDW6O.mjs +0 -2
- package/dist/chunk-LI6WJ3LZ.js +0 -2
- package/dist/chunk-LXRXDTPI.js +0 -2
- package/dist/chunk-NW4A3JW6.mjs +0 -2
- package/dist/chunk-OITITR6K.mjs +0 -2
- package/dist/chunk-PDJGTQMY.mjs +0 -2
- package/dist/chunk-SKJCQKFL.mjs +0 -94
- package/dist/chunk-T44JQT2O.mjs +0 -2
- package/dist/chunk-TCJCE6WN.js +0 -2
- package/dist/chunk-VMJBW3EF.mjs +0 -2
- package/dist/chunk-WW3X3ELF.js +0 -2
- package/dist/chunk-XMYUYQH7.mjs +0 -72
- package/dist/chunk-ZNTMZ6NM.js +0 -7
- package/dist/chunk-ZU73VG3X.js +0 -2
- package/dist/dsr-190YpijW.d.ts +0 -307
- package/dist/dsr-BTT-Xd7H.d.mts +0 -307
package/README.md
CHANGED
|
@@ -7,336 +7,311 @@
|
|
|
7
7
|
[](https://www.typescriptlang.org/)
|
|
8
8
|
[](https://bundlephobia.com/package/@tantainnovative/ndpr-toolkit)
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
v3 ships **zero-config presets**, **pluggable storage adapters**, **compound components**, and a **compliance score engine** — eight production-ready modules covering consent, data subject rights, DPIA, breach notification, privacy policies, lawful basis, cross-border transfers, and ROPA.
|
|
11
11
|
|
|
12
12
|
**[Documentation](https://ndprtoolkit.com.ng)** | **[Live Demos](https://ndprtoolkit.com.ng/ndpr-demos)** | **[npm](https://www.npmjs.com/package/@tantainnovative/ndpr-toolkit)**
|
|
13
13
|
|
|
14
14
|
---
|
|
15
15
|
|
|
16
|
-
##
|
|
16
|
+
## The 3-File Quickstart
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
pnpm add @tantainnovative/ndpr-toolkit
|
|
20
|
-
```
|
|
18
|
+
Three files. Full NDPA consent compliance.
|
|
21
19
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
**`app/layout.tsx`**
|
|
21
|
+
```tsx
|
|
22
|
+
import { NDPRConsent } from '@tantainnovative/ndpr-toolkit/presets';
|
|
23
|
+
|
|
24
|
+
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
25
|
+
return (
|
|
26
|
+
<html>
|
|
27
|
+
<body>
|
|
28
|
+
{children}
|
|
29
|
+
<NDPRConsent />
|
|
30
|
+
</body>
|
|
31
|
+
</html>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
```
|
|
27
35
|
|
|
28
|
-
|
|
36
|
+
**`app/api/consent/route.ts`**
|
|
37
|
+
```ts
|
|
38
|
+
import { NextRequest, NextResponse } from 'next/server';
|
|
29
39
|
|
|
30
|
-
|
|
40
|
+
let store: unknown = null;
|
|
31
41
|
|
|
32
|
-
|
|
33
|
-
|
|
42
|
+
export async function GET() { return NextResponse.json(store ?? {}); }
|
|
43
|
+
export async function POST(req: NextRequest) {
|
|
44
|
+
store = await req.json();
|
|
45
|
+
return NextResponse.json({ ok: true });
|
|
46
|
+
}
|
|
34
47
|
```
|
|
35
48
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
49
|
+
**Persist to your API instead of localStorage:**
|
|
50
|
+
```tsx
|
|
51
|
+
import { NDPRConsent } from '@tantainnovative/ndpr-toolkit/presets';
|
|
52
|
+
import { apiAdapter } from '@tantainnovative/ndpr-toolkit/adapters';
|
|
39
53
|
|
|
40
|
-
|
|
41
|
-
import { useConsent, useLawfulBasis } from '@tantainnovative/ndpr-toolkit/hooks';
|
|
54
|
+
<NDPRConsent adapter={apiAdapter('/api/consent')} />
|
|
42
55
|
```
|
|
43
56
|
|
|
44
|
-
|
|
57
|
+
That's it. NDPA-compliant consent with server-side persistence in under 20 lines.
|
|
45
58
|
|
|
46
|
-
|
|
59
|
+
---
|
|
47
60
|
|
|
48
|
-
|
|
49
|
-
|
|
61
|
+
## Install
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
pnpm add @tantainnovative/ndpr-toolkit
|
|
50
65
|
```
|
|
51
66
|
|
|
52
|
-
Install
|
|
67
|
+
Install UI peer dependencies (only needed for styled components):
|
|
53
68
|
|
|
54
69
|
```bash
|
|
55
70
|
pnpm add @radix-ui/react-switch @radix-ui/react-tabs @radix-ui/react-label @radix-ui/react-slot lucide-react tailwind-merge clsx class-variance-authority
|
|
56
71
|
```
|
|
57
72
|
|
|
58
|
-
|
|
73
|
+
Or scaffold instantly with the CLI:
|
|
59
74
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
```typescript
|
|
63
|
-
import { ConsentBanner, useConsent } from '@tantainnovative/ndpr-toolkit/consent';
|
|
64
|
-
import { BreachReportForm, useBreach } from '@tantainnovative/ndpr-toolkit/breach';
|
|
75
|
+
```bash
|
|
76
|
+
npx @tantainnovative/create-ndpr
|
|
65
77
|
```
|
|
66
78
|
|
|
67
79
|
---
|
|
68
80
|
|
|
69
|
-
##
|
|
70
|
-
|
|
71
|
-
A consent banner in under 10 lines:
|
|
81
|
+
## Choose Your Layer
|
|
72
82
|
|
|
73
|
-
|
|
74
|
-
import { useConsent } from '@tantainnovative/ndpr-toolkit/hooks';
|
|
75
|
-
|
|
76
|
-
function App() {
|
|
77
|
-
const { hasConsent, acceptAll, rejectAll, shouldShowBanner } = useConsent({
|
|
78
|
-
options: [
|
|
79
|
-
{ id: 'essential', label: 'Essential', description: 'Required for the site to function', required: true, purpose: 'Site operation' },
|
|
80
|
-
{ id: 'analytics', label: 'Analytics', description: 'Help us improve', required: false, purpose: 'Usage analytics' },
|
|
81
|
-
],
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
if (shouldShowBanner) {
|
|
85
|
-
return (
|
|
86
|
-
<div>
|
|
87
|
-
<p>We use cookies to improve your experience.</p>
|
|
88
|
-
<button onClick={acceptAll}>Accept All</button>
|
|
89
|
-
<button onClick={rejectAll}>Reject Optional</button>
|
|
90
|
-
</div>
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return <main>{hasConsent('analytics') && <AnalyticsScript />}</main>;
|
|
95
|
-
}
|
|
96
|
-
```
|
|
97
|
-
|
|
98
|
-
---
|
|
83
|
+
Pick exactly what your project needs.
|
|
99
84
|
|
|
100
|
-
|
|
85
|
+
### Presets — zero-config
|
|
101
86
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
**Default (Tailwind CSS built-in):**
|
|
87
|
+
Drop-in components with sensible defaults. No configuration required.
|
|
105
88
|
|
|
106
89
|
```tsx
|
|
107
|
-
|
|
90
|
+
import {
|
|
91
|
+
NDPRConsent, // Consent banner — works with zero props
|
|
92
|
+
NDPRSubjectRights, // DSR request form
|
|
93
|
+
NDPRBreachReport, // Breach report form
|
|
94
|
+
NDPRPrivacyPolicy, // Policy generator wizard
|
|
95
|
+
NDPRDPIA, // DPIA questionnaire
|
|
96
|
+
NDPRComplianceDashboard, // Visual compliance dashboard
|
|
97
|
+
} from '@tantainnovative/ndpr-toolkit/presets';
|
|
108
98
|
```
|
|
109
99
|
|
|
110
|
-
|
|
100
|
+
### Components — compound pattern
|
|
111
101
|
|
|
112
|
-
|
|
113
|
-
import { ConsentBanner } from '@tantainnovative/ndpr-toolkit/consent';
|
|
102
|
+
Full control over layout without rebuilding logic.
|
|
114
103
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
104
|
+
```tsx
|
|
105
|
+
import { Consent } from '@tantainnovative/ndpr-toolkit/consent';
|
|
106
|
+
|
|
107
|
+
<Consent.Provider options={options} onSave={handleSave}>
|
|
108
|
+
<div className="my-layout">
|
|
109
|
+
<Consent.OptionList />
|
|
110
|
+
<div className="flex gap-2">
|
|
111
|
+
<Consent.AcceptButton />
|
|
112
|
+
<Consent.RejectButton />
|
|
113
|
+
</div>
|
|
114
|
+
</div>
|
|
115
|
+
</Consent.Provider>
|
|
125
116
|
```
|
|
126
117
|
|
|
127
|
-
|
|
118
|
+
### Hooks — headless
|
|
119
|
+
|
|
120
|
+
Stateful hooks for every module. Bring your own UI entirely.
|
|
128
121
|
|
|
129
122
|
```tsx
|
|
130
|
-
|
|
131
|
-
options={options}
|
|
132
|
-
onSave={handleSave}
|
|
133
|
-
unstyled
|
|
134
|
-
classNames={{
|
|
135
|
-
root: "my-consent-banner",
|
|
136
|
-
acceptButton: "btn btn-primary",
|
|
137
|
-
rejectButton: "btn btn-outline-secondary",
|
|
138
|
-
}}
|
|
139
|
-
/>
|
|
140
|
-
```
|
|
123
|
+
import { useConsent } from '@tantainnovative/ndpr-toolkit/hooks';
|
|
141
124
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
| Component | Keys | All classNames |
|
|
145
|
-
|-----------|------|----------------|
|
|
146
|
-
| ConsentBanner | 14 | root, container, title, description, optionsList, optionItem, optionCheckbox, optionLabel, optionDescription, buttonGroup, acceptButton, rejectButton, customizeButton, saveButton |
|
|
147
|
-
| ConsentManager | 9 | root, header, title, description, optionsList, optionItem, toggle, saveButton, resetButton |
|
|
148
|
-
| ConsentStorage | 1 | root |
|
|
149
|
-
| DSRRequestForm | 11 | root, title, description, form, fieldGroup, label, input, select, textarea, submitButton, successMessage |
|
|
150
|
-
| DSRDashboard | 8 | root, header, title, filters, requestList, requestItem, statusBadge, detailPanel |
|
|
151
|
-
| DSRTracker | 9 | root, header, title, stats, statCard, table, tableHeader, tableRow, statusBadge |
|
|
152
|
-
| DPIAQuestionnaire | 15 | root, header, title, section, sectionTitle, question, questionText, guidance, input, radioGroup, radioOption, navigation, nextButton, prevButton, progressBar |
|
|
153
|
-
| DPIAReport | 10 | root, header, title, summary, riskBadge, riskTable, riskRow, recommendation, conclusion, printButton |
|
|
154
|
-
| StepIndicator | 7 | root, step, stepActive, stepCompleted, stepPending, connector, label |
|
|
155
|
-
| BreachReportForm | 10 | root, title, form, fieldGroup, label, input, select, textarea, submitButton, notice |
|
|
156
|
-
| BreachRiskAssessment | 8 | root, header, title, slider, riskBadge, riskScore, notificationStatus, submitButton |
|
|
157
|
-
| BreachNotificationManager | 9 | root, header, title, breachList, breachItem, statusBadge, timeline, timelineStep, detailPanel |
|
|
158
|
-
| RegulatoryReportGenerator | 9 | root, header, title, reportPreview, field, fieldLabel, fieldValue, generateButton, downloadButton |
|
|
159
|
-
| PolicyGenerator | 10 | root, header, title, description, sectionList, sectionItem, form, input, generateButton, complianceNotice |
|
|
160
|
-
| PolicyPreview | 9 | root, header, title, description, content, section, sectionTitle, sectionContent, complianceNotice |
|
|
161
|
-
| PolicyExporter | 9 | root, header, title, description, formatSelector, formatOption, exportButton, complianceNotice, preview |
|
|
162
|
-
| LawfulBasisTracker | 15 | root, header, title, summary, summaryCard, table, tableHeader, tableRow, form, input, select, submitButton, statusBadge, complianceScore, gapAlert |
|
|
163
|
-
| CrossBorderTransferManager | 15 | root, header, title, summary, summaryCard, transferList, transferItem, form, input, select, submitButton, riskBadge, statusBadge, detailPanel, approvalStatus |
|
|
164
|
-
| ROPAManager | 16 | root, header, title, orgInfo, summary, summaryCard, table, tableHeader, tableRow, form, input, select, submitButton, statusBadge, exportButton, complianceGap |
|
|
165
|
-
| **All 19 components** | **169** | |
|
|
166
|
-
|
|
167
|
-
Every component follows the same pattern. Pass `classNames` to override specific sections, or set `unstyled` to strip all default styles. Each component exports its ClassNames TypeScript interface for autocomplete support.
|
|
125
|
+
const { hasConsent, acceptAll, rejectAll, shouldShowBanner } = useConsent({ options });
|
|
126
|
+
```
|
|
168
127
|
|
|
169
|
-
|
|
128
|
+
### Core — no React
|
|
170
129
|
|
|
171
|
-
|
|
130
|
+
Pure TypeScript utilities and validators. Works anywhere — Node, edge functions, Deno.
|
|
172
131
|
|
|
173
|
-
|
|
132
|
+
```ts
|
|
133
|
+
import { validateConsent, getComplianceScore } from '@tantainnovative/ndpr-toolkit/core';
|
|
134
|
+
```
|
|
174
135
|
|
|
175
|
-
|
|
136
|
+
### Adapters — pluggable storage
|
|
176
137
|
|
|
177
|
-
|
|
178
|
-
import { ConsentBanner, ConsentManager, useConsent, validateConsent } from '@tantainnovative/ndpr-toolkit/consent';
|
|
179
|
-
```
|
|
138
|
+
Swap where consent (and other state) is stored without changing any component code.
|
|
180
139
|
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
options={[
|
|
184
|
-
{ id: 'essential', label: 'Essential', description: 'Required for the site to function', required: true, purpose: 'Site operation' },
|
|
185
|
-
{ id: 'analytics', label: 'Analytics', description: 'Help us improve', required: false, purpose: 'Usage analytics' },
|
|
186
|
-
]}
|
|
187
|
-
onSave={(settings) => {
|
|
188
|
-
if (settings.consents.analytics) loadAnalytics();
|
|
189
|
-
}}
|
|
190
|
-
/>
|
|
140
|
+
```ts
|
|
141
|
+
import { apiAdapter, localStorageAdapter, cookieAdapter } from '@tantainnovative/ndpr-toolkit/adapters';
|
|
191
142
|
```
|
|
192
143
|
|
|
193
|
-
**Key exports:** `ConsentBanner`, `ConsentManager`, `ConsentStorage`, `useConsent`, `validateConsent`, `validateConsentOptions`
|
|
194
|
-
|
|
195
144
|
---
|
|
196
145
|
|
|
197
|
-
|
|
146
|
+
## Pluggable Storage
|
|
198
147
|
|
|
199
|
-
|
|
148
|
+
Every stateful component accepts an `adapter` prop. Built-in adapters ship out of the box.
|
|
200
149
|
|
|
201
|
-
```
|
|
202
|
-
import {
|
|
150
|
+
```ts
|
|
151
|
+
import {
|
|
152
|
+
localStorageAdapter, // default for browsers
|
|
153
|
+
sessionStorageAdapter, // cleared on tab close
|
|
154
|
+
cookieAdapter, // server-readable cookies
|
|
155
|
+
apiAdapter, // HTTP endpoint (any backend)
|
|
156
|
+
memoryAdapter, // in-process, good for SSR / tests
|
|
157
|
+
composeAdapters, // fan-out writes to multiple stores
|
|
158
|
+
} from '@tantainnovative/ndpr-toolkit/adapters';
|
|
203
159
|
```
|
|
204
160
|
|
|
161
|
+
**localStorage (default browser behaviour):**
|
|
205
162
|
```tsx
|
|
206
|
-
|
|
207
|
-
requestTypes: [
|
|
208
|
-
{ id: 'access', name: 'Access Request', description: 'Right of access (Section 30)', estimatedCompletionTime: 30, requiresAdditionalInfo: false },
|
|
209
|
-
],
|
|
210
|
-
});
|
|
163
|
+
<NDPRConsent adapter={localStorageAdapter('ndpr_consent')} />
|
|
211
164
|
```
|
|
212
165
|
|
|
213
|
-
**
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
166
|
+
**API endpoint:**
|
|
167
|
+
```tsx
|
|
168
|
+
<NDPRConsent adapter={apiAdapter('/api/consent', {
|
|
169
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
170
|
+
})} />
|
|
171
|
+
```
|
|
218
172
|
|
|
219
|
-
**
|
|
173
|
+
**Write to API + keep a local cache:**
|
|
174
|
+
```tsx
|
|
175
|
+
import { composeAdapters, apiAdapter, localStorageAdapter } from '@tantainnovative/ndpr-toolkit/adapters';
|
|
220
176
|
|
|
221
|
-
|
|
222
|
-
|
|
177
|
+
<NDPRConsent adapter={composeAdapters(
|
|
178
|
+
apiAdapter('/api/consent'),
|
|
179
|
+
localStorageAdapter('ndpr_consent'),
|
|
180
|
+
)} />
|
|
223
181
|
```
|
|
224
182
|
|
|
183
|
+
**Cookie (server-readable, for SSR consent gating):**
|
|
225
184
|
```tsx
|
|
226
|
-
|
|
227
|
-
sections: dpiaSections,
|
|
228
|
-
onComplete: (result) => saveAssessment(result),
|
|
229
|
-
});
|
|
185
|
+
<NDPRConsent adapter={cookieAdapter({ name: 'ndpr_consent', maxAge: 365 * 24 * 60 * 60 })} />
|
|
230
186
|
```
|
|
231
187
|
|
|
232
|
-
**Key exports:** `DPIAQuestionnaire`, `DPIAReport`, `StepIndicator`, `useDPIA`, `assessDPIARisk`
|
|
233
|
-
|
|
234
188
|
---
|
|
235
189
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
190
|
+
## Compliance Score
|
|
191
|
+
|
|
192
|
+
`getComplianceScore()` evaluates your posture across all 8 NDPA modules and returns a 0–100 score with rated gaps and prioritised recommendations.
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
import { getComplianceScore } from '@tantainnovative/ndpr-toolkit/core';
|
|
196
|
+
|
|
197
|
+
const report = getComplianceScore({
|
|
198
|
+
consent: {
|
|
199
|
+
hasConsentMechanism: true,
|
|
200
|
+
hasPurposeSpecification: true,
|
|
201
|
+
hasWithdrawalMechanism: true,
|
|
202
|
+
hasMinorProtection: false,
|
|
203
|
+
consentRecordsRetained: true,
|
|
204
|
+
},
|
|
205
|
+
dsr: {
|
|
206
|
+
hasRequestMechanism: true,
|
|
207
|
+
supportsAccess: true,
|
|
208
|
+
supportsRectification: false,
|
|
209
|
+
supportsErasure: false,
|
|
210
|
+
supportsPortability: false,
|
|
211
|
+
supportsObjection: false,
|
|
212
|
+
maxResponseDays: 30,
|
|
213
|
+
},
|
|
214
|
+
// ... other modules
|
|
215
|
+
});
|
|
239
216
|
|
|
240
|
-
|
|
241
|
-
|
|
217
|
+
console.log(report.score); // e.g. 74
|
|
218
|
+
console.log(report.rating); // "good" | "excellent" | "needs-work" | "critical"
|
|
219
|
+
console.log(report.recommendations[0].priority); // "critical"
|
|
242
220
|
```
|
|
243
221
|
|
|
222
|
+
Render a live dashboard:
|
|
223
|
+
|
|
244
224
|
```tsx
|
|
245
|
-
|
|
246
|
-
categories: breachCategories,
|
|
247
|
-
onReport: (report) => notifyNDPC(report),
|
|
248
|
-
});
|
|
249
|
-
```
|
|
225
|
+
import { NDPRComplianceDashboard } from '@tantainnovative/ndpr-toolkit/presets';
|
|
250
226
|
|
|
251
|
-
|
|
227
|
+
<NDPRComplianceDashboard
|
|
228
|
+
input={complianceInput}
|
|
229
|
+
showRecommendations
|
|
230
|
+
maxRecommendations={5}
|
|
231
|
+
/>
|
|
232
|
+
```
|
|
252
233
|
|
|
253
234
|
---
|
|
254
235
|
|
|
255
|
-
|
|
236
|
+
## Backend Integration
|
|
256
237
|
|
|
257
|
-
|
|
238
|
+
### CLI scaffolder
|
|
258
239
|
|
|
259
|
-
|
|
260
|
-
import { PolicyGenerator, PolicyPreview, usePrivacyPolicy, generatePolicyText } from '@tantainnovative/ndpr-toolkit/policy';
|
|
261
|
-
```
|
|
240
|
+
Scaffold a complete wiring for your stack in seconds:
|
|
262
241
|
|
|
263
|
-
```
|
|
264
|
-
|
|
265
|
-
sections={policySections}
|
|
266
|
-
variables={policyVariables}
|
|
267
|
-
onGenerate={({ content }) => console.log(content)}
|
|
268
|
-
/>
|
|
242
|
+
```bash
|
|
243
|
+
npx @tantainnovative/create-ndpr
|
|
269
244
|
```
|
|
270
245
|
|
|
271
|
-
|
|
246
|
+
Detects Next.js (App Router or Pages Router) or Express, prompts for your ORM (Prisma / Drizzle / none), and generates API routes, schema, and layout files — no manual copy-pasting.
|
|
272
247
|
|
|
273
|
-
|
|
248
|
+
### Backend recipes
|
|
274
249
|
|
|
275
|
-
|
|
250
|
+
`@tantainnovative/ndpr-recipes` is a reference implementation with production-ready patterns:
|
|
276
251
|
|
|
277
|
-
|
|
252
|
+
| Recipe | What you get |
|
|
253
|
+
|--------|-------------|
|
|
254
|
+
| `prisma/schema.prisma` | All 5 NDPA compliance tables |
|
|
255
|
+
| `src/adapters/prisma-consent.ts` | Prisma `StorageAdapter<ConsentSettings>` |
|
|
256
|
+
| `src/adapters/drizzle-consent.ts` | Drizzle `StorageAdapter<ConsentSettings>` |
|
|
257
|
+
| `src/nextjs/app-router/` | Consent, DSR, Breach, ROPA, compliance route handlers |
|
|
258
|
+
| `src/express/` | Full NDPR router with consent, DSR, breach, ROPA routes |
|
|
259
|
+
| `src/nextjs/app-router/middleware.ts` | Next.js consent gate middleware |
|
|
278
260
|
|
|
279
|
-
|
|
261
|
+
Copy the files you need into your project. [Browse the recipes →](https://github.com/tantainnovative/ndpr-toolkit/tree/main/packages/ndpr-recipes)
|
|
280
262
|
|
|
281
|
-
|
|
282
|
-
import { LawfulBasisTracker, useLawfulBasis, validateProcessingActivity, getLawfulBasisDescription } from '@tantainnovative/ndpr-toolkit/lawful-basis';
|
|
283
|
-
```
|
|
263
|
+
---
|
|
284
264
|
|
|
285
|
-
|
|
286
|
-
const { activities, addActivity, getSummary } = useLawfulBasis();
|
|
287
|
-
|
|
288
|
-
addActivity({
|
|
289
|
-
name: 'Email marketing',
|
|
290
|
-
description: 'Send promotional emails',
|
|
291
|
-
lawfulBasis: 'consent',
|
|
292
|
-
lawfulBasisJustification: 'Explicit opt-in at signup',
|
|
293
|
-
dataCategories: ['email', 'name'],
|
|
294
|
-
involvesSensitiveData: false,
|
|
295
|
-
dataSubjectCategories: ['customers'],
|
|
296
|
-
purposes: ['marketing'],
|
|
297
|
-
retentionPeriod: '2 years',
|
|
298
|
-
crossBorderTransfer: false,
|
|
299
|
-
status: 'active',
|
|
300
|
-
});
|
|
301
|
-
```
|
|
265
|
+
## All 8 Modules
|
|
302
266
|
|
|
303
|
-
|
|
267
|
+
| Module | Import path | NDPA reference | Key exports |
|
|
268
|
+
|--------|-------------|----------------|-------------|
|
|
269
|
+
| Consent Management | `/consent` | Sections 25–26 | `ConsentBanner`, `ConsentManager`, `Consent.*`, `useConsent` |
|
|
270
|
+
| Data Subject Rights | `/dsr` | Part IV §29–36 | `DSRRequestForm`, `DSRDashboard`, `useDSR` |
|
|
271
|
+
| DPIA | `/dpia` | Sections 38–39 | `DPIAQuestionnaire`, `DPIAReport`, `useDPIA` |
|
|
272
|
+
| Breach Notification | `/breach` | Section 40 | `BreachReportForm`, `BreachRiskAssessment`, `useBreach` |
|
|
273
|
+
| Privacy Policy | `/policy` | Sections 27–28 | `PolicyGenerator`, `PolicyPreview`, `PolicyExporter` |
|
|
274
|
+
| Lawful Basis | `/lawful-basis` | Section 25 | `LawfulBasisTracker`, `useLawfulBasis` |
|
|
275
|
+
| Cross-Border Transfers | `/cross-border` | Part VI §41–45 | `CrossBorderTransferManager`, `useCrossBorderTransfer` |
|
|
276
|
+
| ROPA | `/ropa` | Section 28(2) | `ROPAManager`, `useROPA`, `exportROPAToCSV` |
|
|
304
277
|
|
|
305
278
|
---
|
|
306
279
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
**NDPA Part VI, Sections 41-45** -- Evaluate adequacy decisions, standard contractual clauses, binding corporate rules, and derogations for international data transfers.
|
|
280
|
+
## Styling & Customization
|
|
310
281
|
|
|
311
|
-
|
|
312
|
-
import { CrossBorderTransferManager, useCrossBorderTransfer, validateTransfer, assessTransferRisk } from '@tantainnovative/ndpr-toolkit/cross-border';
|
|
313
|
-
```
|
|
282
|
+
Every component supports three modes:
|
|
314
283
|
|
|
284
|
+
**Default (Tailwind CSS):**
|
|
315
285
|
```tsx
|
|
316
|
-
|
|
317
|
-
onAdd: (transfer) => logTransfer(transfer),
|
|
318
|
-
});
|
|
286
|
+
<ConsentBanner options={options} onSave={handleSave} />
|
|
319
287
|
```
|
|
320
288
|
|
|
321
|
-
**
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
289
|
+
**Override specific sections:**
|
|
290
|
+
```tsx
|
|
291
|
+
<ConsentBanner
|
|
292
|
+
options={options}
|
|
293
|
+
onSave={handleSave}
|
|
294
|
+
classNames={{
|
|
295
|
+
root: "fixed bottom-0 inset-x-0 bg-white shadow-xl p-6",
|
|
296
|
+
acceptButton: "bg-green-600 text-white px-6 py-2 rounded-full",
|
|
297
|
+
}}
|
|
298
|
+
/>
|
|
331
299
|
```
|
|
332
300
|
|
|
301
|
+
**Fully unstyled (BYO CSS — Bootstrap, CSS Modules, vanilla):**
|
|
333
302
|
```tsx
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
}
|
|
303
|
+
<ConsentBanner
|
|
304
|
+
options={options}
|
|
305
|
+
onSave={handleSave}
|
|
306
|
+
unstyled
|
|
307
|
+
classNames={{
|
|
308
|
+
root: "my-consent-banner",
|
|
309
|
+
acceptButton: "btn btn-primary",
|
|
310
|
+
}}
|
|
311
|
+
/>
|
|
337
312
|
```
|
|
338
313
|
|
|
339
|
-
|
|
314
|
+
Each component exports its `ClassNames` TypeScript interface for autocomplete. Full reference in the [docs](https://ndprtoolkit.com.ng/docs/styling).
|
|
340
315
|
|
|
341
316
|
---
|
|
342
317
|
|
|
@@ -344,18 +319,20 @@ const { ropa, addRecord, getSummary } = useROPA({
|
|
|
344
319
|
|
|
345
320
|
| Path | What you get | Dependencies |
|
|
346
321
|
|------|-------------|--------------|
|
|
322
|
+
| `.` (default) | Everything | All peer deps |
|
|
347
323
|
| `/core` | Types + utility functions | `tslib` |
|
|
348
324
|
| `/hooks` | React hooks for all 8 modules | `react` |
|
|
349
|
-
| `/
|
|
350
|
-
| `/
|
|
351
|
-
| `/
|
|
352
|
-
| `/
|
|
353
|
-
| `/
|
|
354
|
-
| `/
|
|
355
|
-
| `/
|
|
356
|
-
| `/
|
|
325
|
+
| `/presets` | Zero-config preset components | `react`, Radix, Tailwind |
|
|
326
|
+
| `/adapters` | Storage adapters | none |
|
|
327
|
+
| `/consent` | Consent components + `Consent.*` compound API | `react`, Radix, Tailwind |
|
|
328
|
+
| `/dsr` | DSR components + hook | `react`, Radix, Tailwind |
|
|
329
|
+
| `/dpia` | DPIA components + hook | `react`, Radix, Tailwind |
|
|
330
|
+
| `/breach` | Breach components + hook | `react`, Radix, Tailwind |
|
|
331
|
+
| `/policy` | Policy components + hook | `react`, Radix, Tailwind, `jspdf` |
|
|
332
|
+
| `/lawful-basis` | Lawful basis component + hook | `react`, Radix, Tailwind |
|
|
333
|
+
| `/cross-border` | Cross-border component + hook | `react`, Radix, Tailwind |
|
|
334
|
+
| `/ropa` | ROPA component + hook | `react`, Radix, Tailwind |
|
|
357
335
|
| `/unstyled` | Unstyled consent primitives | `react` |
|
|
358
|
-
| `.` (default) | Everything | All peer deps |
|
|
359
336
|
|
|
360
337
|
---
|
|
361
338
|
|
|
@@ -367,7 +344,6 @@ The **Nigeria Data Protection Act (NDPA) 2023** replaced the NDPR 2019 and estab
|
|
|
367
344
|
|--------|-------------|-------------|
|
|
368
345
|
| Legal status | NITDA regulation | Act of the National Assembly |
|
|
369
346
|
| Regulator | NITDA | NDPC (independent commission) |
|
|
370
|
-
| Scope | Organizations processing data in Nigeria | Broader territorial + extraterritorial application |
|
|
371
347
|
| Enforcement | Limited | Independent investigation and penalty powers |
|
|
372
348
|
| Data subject rights | 6 rights | 8 rights (added information + automated decision-making) |
|
|
373
349
|
| Cross-border transfers | Basic provisions | Comprehensive framework with adequacy decisions |
|
|
@@ -378,26 +354,30 @@ The **Nigeria Data Protection Act (NDPA) 2023** replaced the NDPR 2019 and estab
|
|
|
378
354
|
|
|
379
355
|
## TypeScript
|
|
380
356
|
|
|
381
|
-
|
|
357
|
+
Written in TypeScript. All types are exported:
|
|
382
358
|
|
|
383
359
|
```typescript
|
|
384
360
|
import type {
|
|
385
361
|
// Consent
|
|
386
|
-
ConsentOption, ConsentSettings,
|
|
362
|
+
ConsentOption, ConsentSettings,
|
|
387
363
|
// DSR
|
|
388
|
-
DSRRequest, DSRType, DSRStatus,
|
|
364
|
+
DSRRequest, DSRType, DSRStatus,
|
|
389
365
|
// DPIA
|
|
390
|
-
DPIAQuestion, DPIASection, DPIAResult,
|
|
366
|
+
DPIAQuestion, DPIASection, DPIAResult,
|
|
391
367
|
// Breach
|
|
392
368
|
BreachReport, BreachCategory, RiskAssessment,
|
|
393
369
|
// Policy
|
|
394
|
-
PolicySection, PolicyTemplate,
|
|
370
|
+
PolicySection, PolicyTemplate, PrivacyPolicy,
|
|
395
371
|
// Lawful Basis
|
|
396
|
-
LawfulBasis, ProcessingActivity,
|
|
372
|
+
LawfulBasis, ProcessingActivity,
|
|
397
373
|
// Cross-Border
|
|
398
|
-
CrossBorderTransfer, TransferMechanism,
|
|
374
|
+
CrossBorderTransfer, TransferMechanism,
|
|
399
375
|
// ROPA
|
|
400
|
-
ProcessingRecord, RecordOfProcessingActivities,
|
|
376
|
+
ProcessingRecord, RecordOfProcessingActivities,
|
|
377
|
+
// Compliance score
|
|
378
|
+
ComplianceInput, ComplianceReport, ComplianceRating,
|
|
379
|
+
// Storage
|
|
380
|
+
StorageAdapter,
|
|
401
381
|
} from '@tantainnovative/ndpr-toolkit/core';
|
|
402
382
|
```
|
|
403
383
|
|