@tantainnovative/ndpr-toolkit 3.6.1 → 3.10.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +230 -0
- package/README.md +146 -1
- package/dist/chunk-2MIQXECH.mjs +3 -0
- package/dist/chunk-3GRGYT3P.js +1 -0
- package/dist/chunk-5IOC3VAW.js +1 -0
- package/dist/chunk-ATFUSHC2.mjs +2 -0
- package/dist/{chunk-SJRIOZ4K.mjs → chunk-EFIWANHF.mjs} +1 -1
- package/dist/chunk-GQYBS3A7.mjs +0 -0
- package/dist/chunk-HXWHL4BD.js +3 -0
- package/dist/chunk-OZCNFB5C.js +1 -0
- package/dist/chunk-R7545FP4.mjs +1 -0
- package/dist/chunk-UKLU6BQF.mjs +1 -0
- package/dist/{chunk-I2LMQWK3.js → chunk-W7OLQRJP.js} +2 -2
- package/dist/{chunk-RXZFYBUJ.js → chunk-XS3Z4UT7.js} +1 -1
- package/dist/core.d.mts +70 -0
- package/dist/core.d.ts +70 -0
- package/dist/core.js +1 -1
- package/dist/core.mjs +1 -1
- package/dist/cross-border-lite.d.mts +141 -0
- package/dist/cross-border-lite.d.ts +141 -0
- package/dist/cross-border-lite.js +2 -0
- package/dist/cross-border-lite.mjs +2 -0
- package/dist/dsr.js +1 -1
- package/dist/dsr.mjs +1 -1
- package/dist/headless.d.mts +2391 -0
- package/dist/headless.d.ts +2391 -0
- package/dist/headless.js +2 -0
- package/dist/headless.mjs +2 -0
- package/dist/hooks.d.mts +10 -0
- package/dist/hooks.d.ts +10 -0
- package/dist/hooks.js +1 -1
- package/dist/hooks.mjs +1 -1
- package/dist/index.d.mts +133 -0
- package/dist/index.d.ts +133 -0
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/lawful-basis-lite.d.mts +153 -0
- package/dist/lawful-basis-lite.d.ts +153 -0
- package/dist/lawful-basis-lite.js +2 -0
- package/dist/lawful-basis-lite.mjs +2 -0
- package/dist/policy.d.mts +86 -0
- package/dist/policy.d.ts +86 -0
- package/dist/policy.js +1 -1
- package/dist/policy.mjs +1 -1
- package/dist/presets-dsr.d.mts +25 -0
- package/dist/presets-dsr.d.ts +25 -0
- package/dist/presets-dsr.js +1 -1
- package/dist/presets-dsr.mjs +1 -1
- package/dist/presets-policy.d.mts +71 -0
- package/dist/presets-policy.d.ts +71 -0
- package/dist/presets-policy.js +1 -1
- package/dist/presets-policy.mjs +1 -1
- package/dist/presets.d.mts +96 -0
- package/dist/presets.d.ts +96 -0
- package/dist/presets.js +1 -1
- package/dist/presets.mjs +1 -1
- package/dist/ropa-lite.d.mts +218 -0
- package/dist/ropa-lite.d.ts +218 -0
- package/dist/ropa-lite.js +2 -0
- package/dist/ropa-lite.mjs +2 -0
- package/dist/server.d.mts +70 -0
- package/dist/server.d.ts +70 -0
- package/dist/server.js +1 -1
- package/dist/server.mjs +1 -1
- package/package.json +3 -2
- package/dist/chunk-BNHQFZHL.mjs +0 -2
- package/dist/chunk-O6CUBNXK.mjs +0 -3
- package/dist/chunk-RV2VMWZJ.mjs +0 -1
- package/dist/chunk-UI536RU2.js +0 -3
- package/dist/chunk-W7RBGZCC.js +0 -1
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import React__default from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Analyzes all processing activities and returns compliance gaps including
|
|
5
|
+
* missing DPO approval, overdue reviews, undocumented justifications,
|
|
6
|
+
* missing LIA for legitimate interests, and other documentation issues.
|
|
7
|
+
*
|
|
8
|
+
* @param activities Array of processing activities to analyze
|
|
9
|
+
* @returns Array of identified compliance gaps
|
|
10
|
+
*/
|
|
11
|
+
export declare function assessComplianceGaps(activities: ProcessingActivity[]): LawfulBasisComplianceGap[];
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Generates a summary of all lawful basis documentation across processing activities.
|
|
15
|
+
*
|
|
16
|
+
* @param activities Array of processing activities to summarize
|
|
17
|
+
* @returns LawfulBasisSummary with counts, breakdowns, and flagged activities
|
|
18
|
+
*/
|
|
19
|
+
export declare function generateLawfulBasisSummary(activities: ProcessingActivity[]): LawfulBasisSummary;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Compliance gap identified across processing activities
|
|
23
|
+
*/
|
|
24
|
+
export declare interface LawfulBasisComplianceGap {
|
|
25
|
+
activityId: string;
|
|
26
|
+
activityName: string;
|
|
27
|
+
type: 'missing_approval' | 'overdue_review' | 'missing_justification' | 'missing_lia' | 'missing_sensitive_condition' | 'missing_retention' | 'missing_data_categories' | 'missing_purposes';
|
|
28
|
+
severity: 'high' | 'medium' | 'low';
|
|
29
|
+
description: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Summary of all lawful basis documentation for compliance reporting
|
|
34
|
+
*/
|
|
35
|
+
export declare interface LawfulBasisSummary {
|
|
36
|
+
/** Total number of processing activities */
|
|
37
|
+
totalActivities: number;
|
|
38
|
+
/** Breakdown by lawful basis */
|
|
39
|
+
byBasis: Record<LawfulBasisType, number>;
|
|
40
|
+
/** Number of activities involving sensitive data */
|
|
41
|
+
sensitiveDataActivities: number;
|
|
42
|
+
/** Number of activities involving cross-border transfers */
|
|
43
|
+
crossBorderActivities: number;
|
|
44
|
+
/** Activities due for review */
|
|
45
|
+
activitiesDueForReview: ProcessingActivity[];
|
|
46
|
+
/** Activities without DPO approval */
|
|
47
|
+
activitiesWithoutApproval: ProcessingActivity[];
|
|
48
|
+
/** Last updated timestamp */
|
|
49
|
+
lastUpdated: number;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export declare const LawfulBasisTrackerLite: React__default.FC<LawfulBasisTrackerLiteProps>;
|
|
53
|
+
|
|
54
|
+
export declare interface LawfulBasisTrackerLiteClassNames {
|
|
55
|
+
root?: string;
|
|
56
|
+
header?: string;
|
|
57
|
+
title?: string;
|
|
58
|
+
summary?: string;
|
|
59
|
+
summaryCard?: string;
|
|
60
|
+
table?: string;
|
|
61
|
+
tableHeader?: string;
|
|
62
|
+
tableRow?: string;
|
|
63
|
+
statusBadge?: string;
|
|
64
|
+
complianceScore?: string;
|
|
65
|
+
gapAlert?: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export declare interface LawfulBasisTrackerLiteProps {
|
|
69
|
+
activities: ProcessingActivity[];
|
|
70
|
+
title?: string;
|
|
71
|
+
description?: string;
|
|
72
|
+
className?: string;
|
|
73
|
+
classNames?: LawfulBasisTrackerLiteClassNames;
|
|
74
|
+
unstyled?: boolean;
|
|
75
|
+
showSummary?: boolean;
|
|
76
|
+
showComplianceGaps?: boolean;
|
|
77
|
+
onActivityClick?: (activity: ProcessingActivity) => void;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Lawful Basis types aligned with NDPA 2023 Part III (Sections 24-28)
|
|
82
|
+
* Every processing activity must have a documented lawful basis
|
|
83
|
+
*/
|
|
84
|
+
/**
|
|
85
|
+
* The six lawful bases for processing personal data per NDPA Section 25(1)
|
|
86
|
+
*/
|
|
87
|
+
export declare type LawfulBasisType = 'consent' | 'contract' | 'legal_obligation' | 'vital_interests' | 'public_interest' | 'legitimate_interests';
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Validation result for a processing activity
|
|
91
|
+
*/
|
|
92
|
+
export declare interface LawfulBasisValidationResult {
|
|
93
|
+
isValid: boolean;
|
|
94
|
+
errors: string[];
|
|
95
|
+
warnings: string[];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Represents a processing activity and its lawful basis
|
|
100
|
+
*/
|
|
101
|
+
export declare interface ProcessingActivity {
|
|
102
|
+
/** Unique identifier */
|
|
103
|
+
id: string;
|
|
104
|
+
/** Name of the processing activity */
|
|
105
|
+
name: string;
|
|
106
|
+
/** Description of what processing is performed */
|
|
107
|
+
description: string;
|
|
108
|
+
/** The lawful basis for this processing activity */
|
|
109
|
+
lawfulBasis: LawfulBasisType;
|
|
110
|
+
/** Justification for why this lawful basis applies */
|
|
111
|
+
lawfulBasisJustification: string;
|
|
112
|
+
/** Categories of personal data being processed */
|
|
113
|
+
dataCategories: string[];
|
|
114
|
+
/** Whether sensitive personal data is involved */
|
|
115
|
+
involvesSensitiveData: boolean;
|
|
116
|
+
/** Condition for processing sensitive data (required if involvesSensitiveData is true) */
|
|
117
|
+
sensitiveDataCondition?: SensitiveDataCondition;
|
|
118
|
+
/** Categories of data subjects */
|
|
119
|
+
dataSubjectCategories: string[];
|
|
120
|
+
/** Purposes of the processing */
|
|
121
|
+
purposes: string[];
|
|
122
|
+
/** Data retention period */
|
|
123
|
+
retentionPeriod: string;
|
|
124
|
+
/** Justification for the retention period */
|
|
125
|
+
retentionJustification?: string;
|
|
126
|
+
/** Recipients or categories of recipients */
|
|
127
|
+
recipients?: string[];
|
|
128
|
+
/** Whether data is transferred outside Nigeria */
|
|
129
|
+
crossBorderTransfer: boolean;
|
|
130
|
+
/** Timestamp when the record was created */
|
|
131
|
+
createdAt: number;
|
|
132
|
+
/** Timestamp when the record was last updated */
|
|
133
|
+
updatedAt: number;
|
|
134
|
+
/** Next review date */
|
|
135
|
+
reviewDate?: number;
|
|
136
|
+
/** Status of the processing activity */
|
|
137
|
+
status: 'active' | 'inactive' | 'under_review' | 'archived';
|
|
138
|
+
/** DPO approval details */
|
|
139
|
+
dpoApproval?: {
|
|
140
|
+
approved: boolean;
|
|
141
|
+
approvedBy: string;
|
|
142
|
+
approvedAt: number;
|
|
143
|
+
notes?: string;
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Additional conditions required for processing sensitive personal data
|
|
149
|
+
* per NDPA Section 27
|
|
150
|
+
*/
|
|
151
|
+
declare type SensitiveDataCondition = 'explicit_consent' | 'employment_law' | 'vital_interests_incapable' | 'nonprofit_legitimate' | 'publicly_available' | 'legal_claims' | 'substantial_public_interest' | 'health_purposes' | 'public_health' | 'archiving_research';
|
|
152
|
+
|
|
153
|
+
export { }
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';var chunkWZYCBW2R_js=require('./chunk-WZYCBW2R.js'),chunkAME4HJR4_js=require('./chunk-AME4HJR4.js');require('./chunk-RFPLZDIO.js');var react=require('react'),jsxRuntime=require('react/jsx-runtime');var P={consent:"Consent",contract:"Contract",legal_obligation:"Legal Obligation",vital_interests:"Vital Interests",public_interest:"Public Interest",legitimate_interests:"Legitimate Interests"},T={consent:"ndpr-badge ndpr-badge--info",contract:"ndpr-badge ndpr-badge--info",legal_obligation:"ndpr-badge ndpr-badge--info",vital_interests:"ndpr-badge ndpr-badge--destructive",public_interest:"ndpr-badge ndpr-badge--warning",legitimate_interests:"bg-indigo-100 text-indigo-800 dark:bg-indigo-900 dark:text-indigo-200"},D={active:"Active",inactive:"Inactive",under_review:"Under Review",archived:"Archived"},R={active:"ndpr-badge ndpr-badge--success",inactive:"ndpr-badge ndpr-badge--neutral",under_review:"ndpr-badge ndpr-badge--warning",archived:"ndpr-badge ndpr-badge--destructive"},G=p=>new Date(p).toLocaleDateString(),E=({activities:p,title:x="Lawful Basis Tracker",description:w="Document and track the lawful basis for each processing activity as required by NDPA 2023 Section 25.",className:_="",classNames:e,unstyled:i,showSummary:h=true,showComplianceGaps:L=true,onActivityClick:g})=>{let f=react.useMemo(()=>[...p].sort((r,d)=>d.updatedAt-r.updatedAt),[p]),l=react.useMemo(()=>chunkWZYCBW2R_js.d(p),[p]),o=react.useMemo(()=>chunkWZYCBW2R_js.c(p),[p]),c=react.useMemo(()=>o.filter(r=>r.severity==="high"),[o]),u=react.useMemo(()=>o.filter(r=>r.severity==="medium"),[o]),y=r=>jsxRuntime.jsx("span",{className:chunkAME4HJR4_js.a(`px-2 py-1 rounded text-xs font-medium ${R[r]}`,e==null?void 0:e.statusBadge,i),children:D[r]}),A=r=>jsxRuntime.jsx("span",{className:`px-2 py-1 rounded text-xs font-medium ${T[r]}`,children:P[r]}),B=r=>r.dpoApproval?r.dpoApproval.approved?jsxRuntime.jsx("span",{className:"ndpr-badge ndpr-badge--success",children:"Approved"}):jsxRuntime.jsx("span",{className:"ndpr-badge ndpr-badge--warning",children:"Pending Approval"}):jsxRuntime.jsx("span",{className:"px-2 py-1 rounded text-xs font-medium bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400",children:"No DPO Review"}),S=()=>jsxRuntime.jsxs("div",{"data-ndpr-component":"lawful-basis-tracker-lite",className:chunkAME4HJR4_js.a("grid grid-cols-2 md:grid-cols-4 gap-4 mb-6",e==null?void 0:e.summary,i),role:"status","aria-label":"Compliance summary",children:[jsxRuntime.jsxs("div",{className:chunkAME4HJR4_js.a("ndpr-alert ndpr-alert--info",e==null?void 0:e.summaryCard,i),children:[jsxRuntime.jsx("p",{className:"ndpr-stat__value ndpr-text-info",children:l.totalActivities}),jsxRuntime.jsx("p",{className:"text-sm ndpr-text-info",children:"Total Activities"})]}),jsxRuntime.jsxs("div",{className:chunkAME4HJR4_js.a("bg-orange-50 dark:bg-orange-900/20 p-4 rounded-lg",e==null?void 0:e.summaryCard,i),children:[jsxRuntime.jsx("p",{className:"ndpr-stat__value ndpr-text-warning",children:l.sensitiveDataActivities}),jsxRuntime.jsx("p",{className:"text-sm ndpr-text-warning",children:"Sensitive Data"})]}),jsxRuntime.jsxs("div",{className:chunkAME4HJR4_js.a("ndpr-alert ndpr-alert--info",e==null?void 0:e.summaryCard,i),children:[jsxRuntime.jsx("p",{className:"ndpr-stat__value ndpr-text-info",children:l.crossBorderActivities}),jsxRuntime.jsx("p",{className:"text-sm ndpr-text-info",children:"Cross-Border Transfers"})]}),jsxRuntime.jsxs("div",{className:chunkAME4HJR4_js.a("ndpr-alert ndpr-alert--destructive",e==null?void 0:e.summaryCard,i),children:[jsxRuntime.jsx("p",{className:"ndpr-stat__value ndpr-text-destructive",children:l.activitiesWithoutApproval.length}),jsxRuntime.jsx("p",{className:"text-sm ndpr-text-destructive",children:"Pending Approval"})]})]}),k=()=>o.length===0?jsxRuntime.jsxs("div",{className:"bg-green-50 dark:bg-green-900/20 p-4 rounded-lg mb-6",role:"status","aria-label":"No compliance gaps",children:[jsxRuntime.jsx("p",{className:"text-sm ndpr-text-success font-medium",children:"No compliance gaps detected."}),jsxRuntime.jsx("p",{className:"text-xs ndpr-text-success mt-1",children:"All processing activities appear to be properly documented."})]}):jsxRuntime.jsxs("div",{className:"mb-6",role:"status","aria-label":`${o.length} compliance gaps detected`,children:[c.length>0&&jsxRuntime.jsxs("div",{className:chunkAME4HJR4_js.a("bg-red-50 dark:bg-red-900/20 p-4 rounded-lg mb-3",e==null?void 0:e.gapAlert,i),children:[jsxRuntime.jsxs("p",{className:"text-sm ndpr-text-destructive font-medium mb-2",children:["High Priority (",c.length,")"]}),jsxRuntime.jsx("ul",{className:"space-y-1",children:c.map((r,d)=>jsxRuntime.jsx("li",{className:"text-xs ndpr-text-destructive",children:r.description},d))})]}),u.length>0&&jsxRuntime.jsxs("div",{className:chunkAME4HJR4_js.a("ndpr-alert ndpr-alert--warning",e==null?void 0:e.gapAlert,i),children:[jsxRuntime.jsxs("p",{className:"text-sm ndpr-text-warning font-medium mb-2",children:["Medium Priority (",u.length,")"]}),jsxRuntime.jsx("ul",{className:"space-y-1",children:u.map((r,d)=>jsxRuntime.jsx("li",{className:"text-xs ndpr-text-warning",children:r.description},d))})]})]});return jsxRuntime.jsxs("div",{className:chunkAME4HJR4_js.a(`bg-white dark:bg-gray-800 p-6 rounded-lg shadow-md ${_}`,e==null?void 0:e.root,i),children:[jsxRuntime.jsxs("div",{className:chunkAME4HJR4_js.a("",e==null?void 0:e.header,i),children:[jsxRuntime.jsx("h2",{className:chunkAME4HJR4_js.a("ndpr-section-heading",e==null?void 0:e.title,i),children:x}),jsxRuntime.jsx("p",{className:"ndpr-card__subtitle",children:w})]}),h&&S(),L&&k(),f.length===0?jsxRuntime.jsx("div",{className:"flex items-center justify-center h-32 bg-gray-50 dark:bg-gray-700 rounded-md",children:jsxRuntime.jsx("p",{className:"ndpr-card__subtitle",children:"No processing activities found."})}):jsxRuntime.jsx("div",{className:"overflow-x-auto",children:jsxRuntime.jsxs("table",{className:chunkAME4HJR4_js.a("w-full text-sm text-left",e==null?void 0:e.table,i),children:[jsxRuntime.jsx("thead",{className:chunkAME4HJR4_js.a("ndpr-table__head",e==null?void 0:e.tableHeader,i),children:jsxRuntime.jsxs("tr",{children:[jsxRuntime.jsx("th",{className:"ndpr-table__cell",children:"Activity"}),jsxRuntime.jsx("th",{className:"ndpr-table__cell",children:"Lawful Basis"}),jsxRuntime.jsx("th",{className:"ndpr-table__cell",children:"Status"}),jsxRuntime.jsx("th",{className:"ndpr-table__cell",children:"DPO Approval"}),jsxRuntime.jsx("th",{className:"ndpr-table__cell",children:"Sensitive Data"}),jsxRuntime.jsx("th",{className:"ndpr-table__cell",children:"Last Updated"})]})}),jsxRuntime.jsx("tbody",{children:f.map(r=>{let d=typeof g=="function",C=d?m=>{(m.key==="Enter"||m.key===" ")&&(m.preventDefault(),g(r));}:void 0;return jsxRuntime.jsxs("tr",{className:chunkAME4HJR4_js.a(`border-b border-gray-200 dark:border-gray-600${d?" hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer":""}`,e==null?void 0:e.tableRow,i),onClick:d?()=>g(r):void 0,onKeyDown:C,role:d?"button":void 0,tabIndex:d?0:void 0,"aria-label":d?`View ${r.name}`:void 0,children:[jsxRuntime.jsxs("td",{className:"ndpr-table__cell",children:[jsxRuntime.jsx("span",{className:"font-medium ndpr-text-primary",children:r.name}),jsxRuntime.jsx("p",{className:"text-xs ndpr-text-muted mt-1 truncate max-w-xs",children:r.description})]}),jsxRuntime.jsx("td",{className:"ndpr-table__cell",children:A(r.lawfulBasis)}),jsxRuntime.jsx("td",{className:"ndpr-table__cell",children:y(r.status)}),jsxRuntime.jsx("td",{className:"ndpr-table__cell",children:B(r)}),jsxRuntime.jsx("td",{className:"ndpr-table__cell",children:jsxRuntime.jsx("span",{className:`text-xs ${r.involvesSensitiveData?"ndpr-text-warning font-medium":"ndpr-card__subtitle"}`,children:r.involvesSensitiveData?"Yes":"No"})}),jsxRuntime.jsx("td",{className:"ndpr-table__cell ndpr-table__cell--muted",children:G(r.updatedAt)})]},r.id)})})]})})]})};Object.defineProperty(exports,"assessComplianceGaps",{enumerable:true,get:function(){return chunkWZYCBW2R_js.c}});Object.defineProperty(exports,"generateLawfulBasisSummary",{enumerable:true,get:function(){return chunkWZYCBW2R_js.d}});exports.LawfulBasisTrackerLite=E;
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {d,c}from'./chunk-LWIKDDSU.mjs';export{c as assessComplianceGaps,d as generateLawfulBasisSummary}from'./chunk-LWIKDDSU.mjs';import {a}from'./chunk-SFGW37LE.mjs';import'./chunk-ZJYULEER.mjs';import {useMemo}from'react';import {jsxs,jsx}from'react/jsx-runtime';var P={consent:"Consent",contract:"Contract",legal_obligation:"Legal Obligation",vital_interests:"Vital Interests",public_interest:"Public Interest",legitimate_interests:"Legitimate Interests"},T={consent:"ndpr-badge ndpr-badge--info",contract:"ndpr-badge ndpr-badge--info",legal_obligation:"ndpr-badge ndpr-badge--info",vital_interests:"ndpr-badge ndpr-badge--destructive",public_interest:"ndpr-badge ndpr-badge--warning",legitimate_interests:"bg-indigo-100 text-indigo-800 dark:bg-indigo-900 dark:text-indigo-200"},D={active:"Active",inactive:"Inactive",under_review:"Under Review",archived:"Archived"},R={active:"ndpr-badge ndpr-badge--success",inactive:"ndpr-badge ndpr-badge--neutral",under_review:"ndpr-badge ndpr-badge--warning",archived:"ndpr-badge ndpr-badge--destructive"},G=p=>new Date(p).toLocaleDateString(),E=({activities:p,title:x="Lawful Basis Tracker",description:w="Document and track the lawful basis for each processing activity as required by NDPA 2023 Section 25.",className:_="",classNames:e,unstyled:i,showSummary:h=true,showComplianceGaps:L=true,onActivityClick:g})=>{let f=useMemo(()=>[...p].sort((r,d)=>d.updatedAt-r.updatedAt),[p]),l=useMemo(()=>d(p),[p]),o=useMemo(()=>c(p),[p]),c$1=useMemo(()=>o.filter(r=>r.severity==="high"),[o]),u=useMemo(()=>o.filter(r=>r.severity==="medium"),[o]),y=r=>jsx("span",{className:a(`px-2 py-1 rounded text-xs font-medium ${R[r]}`,e==null?void 0:e.statusBadge,i),children:D[r]}),A=r=>jsx("span",{className:`px-2 py-1 rounded text-xs font-medium ${T[r]}`,children:P[r]}),B=r=>r.dpoApproval?r.dpoApproval.approved?jsx("span",{className:"ndpr-badge ndpr-badge--success",children:"Approved"}):jsx("span",{className:"ndpr-badge ndpr-badge--warning",children:"Pending Approval"}):jsx("span",{className:"px-2 py-1 rounded text-xs font-medium bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400",children:"No DPO Review"}),S=()=>jsxs("div",{"data-ndpr-component":"lawful-basis-tracker-lite",className:a("grid grid-cols-2 md:grid-cols-4 gap-4 mb-6",e==null?void 0:e.summary,i),role:"status","aria-label":"Compliance summary",children:[jsxs("div",{className:a("ndpr-alert ndpr-alert--info",e==null?void 0:e.summaryCard,i),children:[jsx("p",{className:"ndpr-stat__value ndpr-text-info",children:l.totalActivities}),jsx("p",{className:"text-sm ndpr-text-info",children:"Total Activities"})]}),jsxs("div",{className:a("bg-orange-50 dark:bg-orange-900/20 p-4 rounded-lg",e==null?void 0:e.summaryCard,i),children:[jsx("p",{className:"ndpr-stat__value ndpr-text-warning",children:l.sensitiveDataActivities}),jsx("p",{className:"text-sm ndpr-text-warning",children:"Sensitive Data"})]}),jsxs("div",{className:a("ndpr-alert ndpr-alert--info",e==null?void 0:e.summaryCard,i),children:[jsx("p",{className:"ndpr-stat__value ndpr-text-info",children:l.crossBorderActivities}),jsx("p",{className:"text-sm ndpr-text-info",children:"Cross-Border Transfers"})]}),jsxs("div",{className:a("ndpr-alert ndpr-alert--destructive",e==null?void 0:e.summaryCard,i),children:[jsx("p",{className:"ndpr-stat__value ndpr-text-destructive",children:l.activitiesWithoutApproval.length}),jsx("p",{className:"text-sm ndpr-text-destructive",children:"Pending Approval"})]})]}),k=()=>o.length===0?jsxs("div",{className:"bg-green-50 dark:bg-green-900/20 p-4 rounded-lg mb-6",role:"status","aria-label":"No compliance gaps",children:[jsx("p",{className:"text-sm ndpr-text-success font-medium",children:"No compliance gaps detected."}),jsx("p",{className:"text-xs ndpr-text-success mt-1",children:"All processing activities appear to be properly documented."})]}):jsxs("div",{className:"mb-6",role:"status","aria-label":`${o.length} compliance gaps detected`,children:[c$1.length>0&&jsxs("div",{className:a("bg-red-50 dark:bg-red-900/20 p-4 rounded-lg mb-3",e==null?void 0:e.gapAlert,i),children:[jsxs("p",{className:"text-sm ndpr-text-destructive font-medium mb-2",children:["High Priority (",c$1.length,")"]}),jsx("ul",{className:"space-y-1",children:c$1.map((r,d)=>jsx("li",{className:"text-xs ndpr-text-destructive",children:r.description},d))})]}),u.length>0&&jsxs("div",{className:a("ndpr-alert ndpr-alert--warning",e==null?void 0:e.gapAlert,i),children:[jsxs("p",{className:"text-sm ndpr-text-warning font-medium mb-2",children:["Medium Priority (",u.length,")"]}),jsx("ul",{className:"space-y-1",children:u.map((r,d)=>jsx("li",{className:"text-xs ndpr-text-warning",children:r.description},d))})]})]});return jsxs("div",{className:a(`bg-white dark:bg-gray-800 p-6 rounded-lg shadow-md ${_}`,e==null?void 0:e.root,i),children:[jsxs("div",{className:a("",e==null?void 0:e.header,i),children:[jsx("h2",{className:a("ndpr-section-heading",e==null?void 0:e.title,i),children:x}),jsx("p",{className:"ndpr-card__subtitle",children:w})]}),h&&S(),L&&k(),f.length===0?jsx("div",{className:"flex items-center justify-center h-32 bg-gray-50 dark:bg-gray-700 rounded-md",children:jsx("p",{className:"ndpr-card__subtitle",children:"No processing activities found."})}):jsx("div",{className:"overflow-x-auto",children:jsxs("table",{className:a("w-full text-sm text-left",e==null?void 0:e.table,i),children:[jsx("thead",{className:a("ndpr-table__head",e==null?void 0:e.tableHeader,i),children:jsxs("tr",{children:[jsx("th",{className:"ndpr-table__cell",children:"Activity"}),jsx("th",{className:"ndpr-table__cell",children:"Lawful Basis"}),jsx("th",{className:"ndpr-table__cell",children:"Status"}),jsx("th",{className:"ndpr-table__cell",children:"DPO Approval"}),jsx("th",{className:"ndpr-table__cell",children:"Sensitive Data"}),jsx("th",{className:"ndpr-table__cell",children:"Last Updated"})]})}),jsx("tbody",{children:f.map(r=>{let d=typeof g=="function",C=d?m=>{(m.key==="Enter"||m.key===" ")&&(m.preventDefault(),g(r));}:void 0;return jsxs("tr",{className:a(`border-b border-gray-200 dark:border-gray-600${d?" hover:bg-gray-50 dark:hover:bg-gray-700 cursor-pointer":""}`,e==null?void 0:e.tableRow,i),onClick:d?()=>g(r):void 0,onKeyDown:C,role:d?"button":void 0,tabIndex:d?0:void 0,"aria-label":d?`View ${r.name}`:void 0,children:[jsxs("td",{className:"ndpr-table__cell",children:[jsx("span",{className:"font-medium ndpr-text-primary",children:r.name}),jsx("p",{className:"text-xs ndpr-text-muted mt-1 truncate max-w-xs",children:r.description})]}),jsx("td",{className:"ndpr-table__cell",children:A(r.lawfulBasis)}),jsx("td",{className:"ndpr-table__cell",children:y(r.status)}),jsx("td",{className:"ndpr-table__cell",children:B(r)}),jsx("td",{className:"ndpr-table__cell",children:jsx("span",{className:`text-xs ${r.involvesSensitiveData?"ndpr-text-warning font-medium":"ndpr-card__subtitle"}`,children:r.involvesSensitiveData?"Yes":"No"})}),jsx("td",{className:"ndpr-table__cell ndpr-table__cell--muted",children:G(r.updatedAt)})]},r.id)})})]})})]})};export{E as LawfulBasisTrackerLite};
|
package/dist/policy.d.mts
CHANGED
|
@@ -8,6 +8,12 @@ declare interface AdaptivePolicyWizardProps {
|
|
|
8
8
|
onComplete?: (policy: PrivacyPolicy) => void;
|
|
9
9
|
classNames?: Record<string, string>;
|
|
10
10
|
unstyled?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Initial template context — seeds the wizard with a sector-specific
|
|
13
|
+
* pre-fill. Use `templateContextFor('saas' | 'ecommerce' | …)` from
|
|
14
|
+
* `/server` (or `/core`) to construct it.
|
|
15
|
+
*/
|
|
16
|
+
initialContext?: TemplateContext;
|
|
11
17
|
}
|
|
12
18
|
|
|
13
19
|
/**
|
|
@@ -324,6 +330,18 @@ declare interface HTMLExportOptions {
|
|
|
324
330
|
/** Industry verticals with sector-specific compliance requirements. */
|
|
325
331
|
export declare type Industry = 'fintech' | 'healthcare' | 'ecommerce' | 'saas' | 'education' | 'government' | 'other';
|
|
326
332
|
|
|
333
|
+
/**
|
|
334
|
+
* Static metadata for every template — useful for picker UIs that need
|
|
335
|
+
* to list available templates with a one-line description.
|
|
336
|
+
*/
|
|
337
|
+
export declare const ORG_POLICY_TEMPLATE_REGISTRY: Record<OrgPolicyTemplateId, {
|
|
338
|
+
id: OrgPolicyTemplateId;
|
|
339
|
+
label: string;
|
|
340
|
+
description: string;
|
|
341
|
+
/** Best-fit org examples to show in the picker. */
|
|
342
|
+
examples: readonly string[];
|
|
343
|
+
}>;
|
|
344
|
+
|
|
327
345
|
/**
|
|
328
346
|
* Represents organization information for a privacy policy
|
|
329
347
|
*/
|
|
@@ -348,6 +366,48 @@ export declare interface OrganizationInfo {
|
|
|
348
366
|
ndpcRegistrationNumber?: string;
|
|
349
367
|
}
|
|
350
368
|
|
|
369
|
+
/**
|
|
370
|
+
* Org-specific privacy-policy templates — pre-filled `TemplateContext`
|
|
371
|
+
* factories for the most common Nigerian app shapes.
|
|
372
|
+
*
|
|
373
|
+
* Each template returns a fully-populated `TemplateContext` with:
|
|
374
|
+
* - industry set to the matching `Industry` value
|
|
375
|
+
* - the data categories the sector typically collects (selected: true)
|
|
376
|
+
* - the processing purposes that match the business model
|
|
377
|
+
* - sensitive-data / children / cross-border / automated-decisions flags
|
|
378
|
+
* set to the defaults that org type usually needs (a school will have
|
|
379
|
+
* children data, a hospital will have sensitive data, etc.)
|
|
380
|
+
*
|
|
381
|
+
* Templates are guidance starters. The wizard still walks the user through
|
|
382
|
+
* every step — they can flip any flag, add/remove categories, or rewrite
|
|
383
|
+
* any section before the policy is finalised. The legal-notice footer the
|
|
384
|
+
* toolkit ships everywhere applies to the generated output.
|
|
385
|
+
*
|
|
386
|
+
* @example
|
|
387
|
+
* import { templateContextFor } from '@tantainnovative/ndpr-toolkit/server';
|
|
388
|
+
* const ctx = templateContextFor('ecommerce', { orgName: 'Acme NG' });
|
|
389
|
+
* const draft = assemblePolicy(ctx);
|
|
390
|
+
*/
|
|
391
|
+
|
|
392
|
+
/** Identifiers for the bundled org templates. */
|
|
393
|
+
export declare type OrgPolicyTemplateId = 'saas' | 'ecommerce' | 'school' | 'healthcare' | 'procurement';
|
|
394
|
+
|
|
395
|
+
/** Optional overrides applied on top of a template's defaults. */
|
|
396
|
+
export declare interface OrgPolicyTemplateOverrides {
|
|
397
|
+
/** Organisation name (e.g. "Acme Nigeria Ltd"). Default: empty. */
|
|
398
|
+
orgName?: string;
|
|
399
|
+
/** Public website URL. */
|
|
400
|
+
website?: string;
|
|
401
|
+
/** Privacy contact email. */
|
|
402
|
+
privacyEmail?: string;
|
|
403
|
+
/** Postal address. */
|
|
404
|
+
address?: string;
|
|
405
|
+
/** DPO name. Required for DCPMI under NDPA Section 32. */
|
|
406
|
+
dpoName?: string;
|
|
407
|
+
/** DPO email. Required for the NDPC breach-notification contact. */
|
|
408
|
+
dpoEmail?: string;
|
|
409
|
+
}
|
|
410
|
+
|
|
351
411
|
/** Organisation size tiers — affects complexity of generated language. */
|
|
352
412
|
export declare type OrgSize = 'startup' | 'midsize' | 'enterprise';
|
|
353
413
|
|
|
@@ -936,6 +996,22 @@ export declare interface TemplateContext {
|
|
|
936
996
|
thirdPartyProcessors: ThirdPartyProcessor[];
|
|
937
997
|
}
|
|
938
998
|
|
|
999
|
+
/**
|
|
1000
|
+
* Returns a fresh `TemplateContext` pre-filled for the given org type.
|
|
1001
|
+
* Pass `overrides` to set organisation details (name, DPO, etc.) inline.
|
|
1002
|
+
*
|
|
1003
|
+
* Calling without arguments throws — pass a known template id.
|
|
1004
|
+
*
|
|
1005
|
+
* @example
|
|
1006
|
+
* const ctx = templateContextFor('healthcare', {
|
|
1007
|
+
* orgName: 'Lagos Heart Centre',
|
|
1008
|
+
* dpoEmail: 'dpo@lhc.ng',
|
|
1009
|
+
* });
|
|
1010
|
+
*/
|
|
1011
|
+
declare function templateContextFor(id: OrgPolicyTemplateId, overrides?: OrgPolicyTemplateOverrides): TemplateContext;
|
|
1012
|
+
export { templateContextFor as createOrgTemplate }
|
|
1013
|
+
export { templateContextFor }
|
|
1014
|
+
|
|
939
1015
|
/** A third-party entity that processes data on behalf of the organisation. */
|
|
940
1016
|
export declare interface ThirdPartyProcessor {
|
|
941
1017
|
/** Name of the third party. */
|
|
@@ -952,6 +1028,16 @@ export declare interface UseAdaptivePolicyWizardOptions {
|
|
|
952
1028
|
adapter?: StorageAdapter<PolicyDraft>;
|
|
953
1029
|
onComplete?: (policy: PrivacyPolicy) => void;
|
|
954
1030
|
onComplianceChange?: (score: number, gaps: ComplianceGap[]) => void;
|
|
1031
|
+
/**
|
|
1032
|
+
* Initial template context. Use an org-template factory like
|
|
1033
|
+
* `templateContextFor('healthcare')` to start the wizard with a sector-
|
|
1034
|
+
* specific pre-fill (lawful basis, data categories, sensitive-data flag,
|
|
1035
|
+
* cross-border default). Defaults to `createDefaultContext()` if omitted.
|
|
1036
|
+
*
|
|
1037
|
+
* If an adapter loads a saved draft, the draft's context wins — the
|
|
1038
|
+
* `initialContext` only seeds the very first session.
|
|
1039
|
+
*/
|
|
1040
|
+
initialContext?: TemplateContext;
|
|
955
1041
|
}
|
|
956
1042
|
|
|
957
1043
|
export declare interface UseAdaptivePolicyWizardReturn {
|
package/dist/policy.d.ts
CHANGED
|
@@ -8,6 +8,12 @@ declare interface AdaptivePolicyWizardProps {
|
|
|
8
8
|
onComplete?: (policy: PrivacyPolicy) => void;
|
|
9
9
|
classNames?: Record<string, string>;
|
|
10
10
|
unstyled?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Initial template context — seeds the wizard with a sector-specific
|
|
13
|
+
* pre-fill. Use `templateContextFor('saas' | 'ecommerce' | …)` from
|
|
14
|
+
* `/server` (or `/core`) to construct it.
|
|
15
|
+
*/
|
|
16
|
+
initialContext?: TemplateContext;
|
|
11
17
|
}
|
|
12
18
|
|
|
13
19
|
/**
|
|
@@ -324,6 +330,18 @@ declare interface HTMLExportOptions {
|
|
|
324
330
|
/** Industry verticals with sector-specific compliance requirements. */
|
|
325
331
|
export declare type Industry = 'fintech' | 'healthcare' | 'ecommerce' | 'saas' | 'education' | 'government' | 'other';
|
|
326
332
|
|
|
333
|
+
/**
|
|
334
|
+
* Static metadata for every template — useful for picker UIs that need
|
|
335
|
+
* to list available templates with a one-line description.
|
|
336
|
+
*/
|
|
337
|
+
export declare const ORG_POLICY_TEMPLATE_REGISTRY: Record<OrgPolicyTemplateId, {
|
|
338
|
+
id: OrgPolicyTemplateId;
|
|
339
|
+
label: string;
|
|
340
|
+
description: string;
|
|
341
|
+
/** Best-fit org examples to show in the picker. */
|
|
342
|
+
examples: readonly string[];
|
|
343
|
+
}>;
|
|
344
|
+
|
|
327
345
|
/**
|
|
328
346
|
* Represents organization information for a privacy policy
|
|
329
347
|
*/
|
|
@@ -348,6 +366,48 @@ export declare interface OrganizationInfo {
|
|
|
348
366
|
ndpcRegistrationNumber?: string;
|
|
349
367
|
}
|
|
350
368
|
|
|
369
|
+
/**
|
|
370
|
+
* Org-specific privacy-policy templates — pre-filled `TemplateContext`
|
|
371
|
+
* factories for the most common Nigerian app shapes.
|
|
372
|
+
*
|
|
373
|
+
* Each template returns a fully-populated `TemplateContext` with:
|
|
374
|
+
* - industry set to the matching `Industry` value
|
|
375
|
+
* - the data categories the sector typically collects (selected: true)
|
|
376
|
+
* - the processing purposes that match the business model
|
|
377
|
+
* - sensitive-data / children / cross-border / automated-decisions flags
|
|
378
|
+
* set to the defaults that org type usually needs (a school will have
|
|
379
|
+
* children data, a hospital will have sensitive data, etc.)
|
|
380
|
+
*
|
|
381
|
+
* Templates are guidance starters. The wizard still walks the user through
|
|
382
|
+
* every step — they can flip any flag, add/remove categories, or rewrite
|
|
383
|
+
* any section before the policy is finalised. The legal-notice footer the
|
|
384
|
+
* toolkit ships everywhere applies to the generated output.
|
|
385
|
+
*
|
|
386
|
+
* @example
|
|
387
|
+
* import { templateContextFor } from '@tantainnovative/ndpr-toolkit/server';
|
|
388
|
+
* const ctx = templateContextFor('ecommerce', { orgName: 'Acme NG' });
|
|
389
|
+
* const draft = assemblePolicy(ctx);
|
|
390
|
+
*/
|
|
391
|
+
|
|
392
|
+
/** Identifiers for the bundled org templates. */
|
|
393
|
+
export declare type OrgPolicyTemplateId = 'saas' | 'ecommerce' | 'school' | 'healthcare' | 'procurement';
|
|
394
|
+
|
|
395
|
+
/** Optional overrides applied on top of a template's defaults. */
|
|
396
|
+
export declare interface OrgPolicyTemplateOverrides {
|
|
397
|
+
/** Organisation name (e.g. "Acme Nigeria Ltd"). Default: empty. */
|
|
398
|
+
orgName?: string;
|
|
399
|
+
/** Public website URL. */
|
|
400
|
+
website?: string;
|
|
401
|
+
/** Privacy contact email. */
|
|
402
|
+
privacyEmail?: string;
|
|
403
|
+
/** Postal address. */
|
|
404
|
+
address?: string;
|
|
405
|
+
/** DPO name. Required for DCPMI under NDPA Section 32. */
|
|
406
|
+
dpoName?: string;
|
|
407
|
+
/** DPO email. Required for the NDPC breach-notification contact. */
|
|
408
|
+
dpoEmail?: string;
|
|
409
|
+
}
|
|
410
|
+
|
|
351
411
|
/** Organisation size tiers — affects complexity of generated language. */
|
|
352
412
|
export declare type OrgSize = 'startup' | 'midsize' | 'enterprise';
|
|
353
413
|
|
|
@@ -936,6 +996,22 @@ export declare interface TemplateContext {
|
|
|
936
996
|
thirdPartyProcessors: ThirdPartyProcessor[];
|
|
937
997
|
}
|
|
938
998
|
|
|
999
|
+
/**
|
|
1000
|
+
* Returns a fresh `TemplateContext` pre-filled for the given org type.
|
|
1001
|
+
* Pass `overrides` to set organisation details (name, DPO, etc.) inline.
|
|
1002
|
+
*
|
|
1003
|
+
* Calling without arguments throws — pass a known template id.
|
|
1004
|
+
*
|
|
1005
|
+
* @example
|
|
1006
|
+
* const ctx = templateContextFor('healthcare', {
|
|
1007
|
+
* orgName: 'Lagos Heart Centre',
|
|
1008
|
+
* dpoEmail: 'dpo@lhc.ng',
|
|
1009
|
+
* });
|
|
1010
|
+
*/
|
|
1011
|
+
declare function templateContextFor(id: OrgPolicyTemplateId, overrides?: OrgPolicyTemplateOverrides): TemplateContext;
|
|
1012
|
+
export { templateContextFor as createOrgTemplate }
|
|
1013
|
+
export { templateContextFor }
|
|
1014
|
+
|
|
939
1015
|
/** A third-party entity that processes data on behalf of the organisation. */
|
|
940
1016
|
export declare interface ThirdPartyProcessor {
|
|
941
1017
|
/** Name of the third party. */
|
|
@@ -952,6 +1028,16 @@ export declare interface UseAdaptivePolicyWizardOptions {
|
|
|
952
1028
|
adapter?: StorageAdapter<PolicyDraft>;
|
|
953
1029
|
onComplete?: (policy: PrivacyPolicy) => void;
|
|
954
1030
|
onComplianceChange?: (score: number, gaps: ComplianceGap[]) => void;
|
|
1031
|
+
/**
|
|
1032
|
+
* Initial template context. Use an org-template factory like
|
|
1033
|
+
* `templateContextFor('healthcare')` to start the wizard with a sector-
|
|
1034
|
+
* specific pre-fill (lawful basis, data categories, sensitive-data flag,
|
|
1035
|
+
* cross-border default). Defaults to `createDefaultContext()` if omitted.
|
|
1036
|
+
*
|
|
1037
|
+
* If an adapter loads a saved draft, the draft's context wins — the
|
|
1038
|
+
* `initialContext` only seeds the very first session.
|
|
1039
|
+
*/
|
|
1040
|
+
initialContext?: TemplateContext;
|
|
955
1041
|
}
|
|
956
1042
|
|
|
957
1043
|
export declare interface UseAdaptivePolicyWizardReturn {
|
package/dist/policy.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
'use strict';var
|
|
2
|
+
'use strict';var chunkW7OLQRJP_js=require('./chunk-W7OLQRJP.js'),chunkXO3VQYTL_js=require('./chunk-XO3VQYTL.js'),chunk3GRGYT3P_js=require('./chunk-3GRGYT3P.js'),chunkZ763UI5U_js=require('./chunk-Z763UI5U.js'),chunkHXWHL4BD_js=require('./chunk-HXWHL4BD.js'),chunkN3MQQUQP_js=require('./chunk-N3MQQUQP.js'),chunkLVGT3DLT_js=require('./chunk-LVGT3DLT.js'),chunkQ64735OC_js=require('./chunk-Q64735OC.js');require('./chunk-ZVOIR4QH.js'),require('./chunk-AME4HJR4.js'),require('./chunk-VWED6UTN.js');var chunkRFPLZDIO_js=require('./chunk-RFPLZDIO.js'),react=require('react'),jsxRuntime=require('react/jsx-runtime');var u=react.createContext(null);function X(){let e=react.useContext(u);if(!e)throw new Error("Policy compound components must be wrapped in <Policy.Provider>. Example: <Policy.Provider templates={...}><Policy.Generator /></Policy.Provider>");return e}var x=({templates:e,adapter:l,storageKey:t,useLocalStorage:i,initialPolicy:p,onGenerate:n,children:o})=>{let y=chunkZ763UI5U_js.a({templates:e,adapter:l,storageKey:t,useLocalStorage:i,initialPolicy:p,onGenerate:n}),r=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},y),{templates:e});return jsxRuntime.jsx(u.Provider,{value:r,children:o})};var J={Provider:x,Generator:chunkXO3VQYTL_js.a,Preview:chunkXO3VQYTL_js.b,Exporter:chunkXO3VQYTL_js.c};var $=({policy:e,className:l,mode:t="shadow",options:i})=>{let p=react.useRef(null);if(react.useEffect(()=>{var g;if(t!=="shadow")return;let o=p.current;if(!o)return;let y=chunkN3MQQUQP_js.a(e,chunkRFPLZDIO_js.a({includeStyles:true,includePrintCSS:true},i)),r=(g=o.shadowRoot)!=null?g:o.attachShadow({mode:"open"});r.innerHTML=y;let v=C=>{var R;let T=C.target;if(!T)return;let h=T.closest("a[href]");if(!h)return;let P=(R=h.getAttribute("href"))!=null?R:"";if(!P.startsWith("#")||P.length<2)return;let S=decodeURIComponent(P.slice(1)),E=r.getElementById(S);E&&(C.preventDefault(),E.scrollIntoView({behavior:"smooth",block:"start"}));};return r.addEventListener("click",v),()=>{r.removeEventListener("click",v),o.shadowRoot&&(o.shadowRoot.innerHTML="");}},[e,i,t]),t==="shadow")return jsxRuntime.jsx("div",{ref:p,"data-ndpr-component":"policy-page",className:l});let n=chunkN3MQQUQP_js.a(e,chunkRFPLZDIO_js.a({includeStyles:false},i));return jsxRuntime.jsx("div",{"data-ndpr-component":"policy-page",className:l,dangerouslySetInnerHTML:{__html:n}})};Object.defineProperty(exports,"AdaptivePolicyWizard",{enumerable:true,get:function(){return chunkW7OLQRJP_js.a}});Object.defineProperty(exports,"PolicyExporter",{enumerable:true,get:function(){return chunkXO3VQYTL_js.c}});Object.defineProperty(exports,"PolicyGenerator",{enumerable:true,get:function(){return chunkXO3VQYTL_js.a}});Object.defineProperty(exports,"PolicyPreview",{enumerable:true,get:function(){return chunkXO3VQYTL_js.b}});Object.defineProperty(exports,"ORG_POLICY_TEMPLATE_REGISTRY",{enumerable:true,get:function(){return chunk3GRGYT3P_js.a}});Object.defineProperty(exports,"createOrgTemplate",{enumerable:true,get:function(){return chunk3GRGYT3P_js.b}});Object.defineProperty(exports,"templateContextFor",{enumerable:true,get:function(){return chunk3GRGYT3P_js.b}});Object.defineProperty(exports,"useDefaultPrivacyPolicy",{enumerable:true,get:function(){return chunkZ763UI5U_js.b}});Object.defineProperty(exports,"usePrivacyPolicy",{enumerable:true,get:function(){return chunkZ763UI5U_js.a}});Object.defineProperty(exports,"useAdaptivePolicyWizard",{enumerable:true,get:function(){return chunkHXWHL4BD_js.a}});Object.defineProperty(exports,"exportDOCX",{enumerable:true,get:function(){return chunkN3MQQUQP_js.d}});Object.defineProperty(exports,"exportHTML",{enumerable:true,get:function(){return chunkN3MQQUQP_js.a}});Object.defineProperty(exports,"exportMarkdown",{enumerable:true,get:function(){return chunkN3MQQUQP_js.b}});Object.defineProperty(exports,"exportPDF",{enumerable:true,get:function(){return chunkN3MQQUQP_js.c}});Object.defineProperty(exports,"DEFAULT_POLICY_SECTIONS",{enumerable:true,get:function(){return chunkLVGT3DLT_js.c}});Object.defineProperty(exports,"DEFAULT_POLICY_VARIABLES",{enumerable:true,get:function(){return chunkLVGT3DLT_js.d}});Object.defineProperty(exports,"createBusinessPolicyTemplate",{enumerable:true,get:function(){return chunkLVGT3DLT_js.e}});Object.defineProperty(exports,"findUnfilledTokens",{enumerable:true,get:function(){return chunkLVGT3DLT_js.a}});Object.defineProperty(exports,"generatePolicyText",{enumerable:true,get:function(){return chunkLVGT3DLT_js.b}});Object.defineProperty(exports,"DEFAULT_DATA_CATEGORIES",{enumerable:true,get:function(){return chunkQ64735OC_js.d}});Object.defineProperty(exports,"assemblePolicy",{enumerable:true,get:function(){return chunkQ64735OC_js.c}});Object.defineProperty(exports,"createDefaultContext",{enumerable:true,get:function(){return chunkQ64735OC_js.e}});Object.defineProperty(exports,"evaluatePolicyCompliance",{enumerable:true,get:function(){return chunkQ64735OC_js.f}});exports.Policy=J;exports.PolicyPage=$;exports.PolicyProvider=x;exports.usePolicyCompound=X;
|
package/dist/policy.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
export{a as AdaptivePolicyWizard}from'./chunk-
|
|
2
|
+
export{a as AdaptivePolicyWizard}from'./chunk-ATFUSHC2.mjs';import {c,b,a}from'./chunk-TMXK4QKK.mjs';export{c as PolicyExporter,a as PolicyGenerator,b as PolicyPreview}from'./chunk-TMXK4QKK.mjs';export{a as ORG_POLICY_TEMPLATE_REGISTRY,b as createOrgTemplate,b as templateContextFor}from'./chunk-UKLU6BQF.mjs';import {a as a$1}from'./chunk-VYAL2TGT.mjs';export{b as useDefaultPrivacyPolicy,a as usePrivacyPolicy}from'./chunk-VYAL2TGT.mjs';export{a as useAdaptivePolicyWizard}from'./chunk-2MIQXECH.mjs';import {a as a$3}from'./chunk-AOHKVFAS.mjs';export{d as exportDOCX,a as exportHTML,b as exportMarkdown,c as exportPDF}from'./chunk-AOHKVFAS.mjs';export{c as DEFAULT_POLICY_SECTIONS,d as DEFAULT_POLICY_VARIABLES,e as createBusinessPolicyTemplate,a as findUnfilledTokens,b as generatePolicyText}from'./chunk-Y3MKMAFQ.mjs';export{d as DEFAULT_DATA_CATEGORIES,c as assemblePolicy,e as createDefaultContext,f as evaluatePolicyCompliance}from'./chunk-RMQ7OLNY.mjs';import'./chunk-ITCY2Z66.mjs';import'./chunk-SFGW37LE.mjs';import'./chunk-DBZSN4WP.mjs';import {b as b$1,a as a$2}from'./chunk-ZJYULEER.mjs';import {createContext,useContext,useRef,useEffect}from'react';import {jsx}from'react/jsx-runtime';var u=createContext(null);function X(){let e=useContext(u);if(!e)throw new Error("Policy compound components must be wrapped in <Policy.Provider>. Example: <Policy.Provider templates={...}><Policy.Generator /></Policy.Provider>");return e}var x=({templates:e,adapter:l,storageKey:t,useLocalStorage:i,initialPolicy:p,onGenerate:n,children:o})=>{let y=a$1({templates:e,adapter:l,storageKey:t,useLocalStorage:i,initialPolicy:p,onGenerate:n}),r=b$1(a$2({},y),{templates:e});return jsx(u.Provider,{value:r,children:o})};var J={Provider:x,Generator:a,Preview:b,Exporter:c};var $=({policy:e,className:l,mode:t="shadow",options:i})=>{let p=useRef(null);if(useEffect(()=>{var g;if(t!=="shadow")return;let o=p.current;if(!o)return;let y=a$3(e,a$2({includeStyles:true,includePrintCSS:true},i)),r=(g=o.shadowRoot)!=null?g:o.attachShadow({mode:"open"});r.innerHTML=y;let v=C=>{var R;let T=C.target;if(!T)return;let h=T.closest("a[href]");if(!h)return;let P=(R=h.getAttribute("href"))!=null?R:"";if(!P.startsWith("#")||P.length<2)return;let S=decodeURIComponent(P.slice(1)),E=r.getElementById(S);E&&(C.preventDefault(),E.scrollIntoView({behavior:"smooth",block:"start"}));};return r.addEventListener("click",v),()=>{r.removeEventListener("click",v),o.shadowRoot&&(o.shadowRoot.innerHTML="");}},[e,i,t]),t==="shadow")return jsx("div",{ref:p,"data-ndpr-component":"policy-page",className:l});let n=a$3(e,a$2({includeStyles:false},i));return jsx("div",{"data-ndpr-component":"policy-page",className:l,dangerouslySetInnerHTML:{__html:n}})};export{J as Policy,$ as PolicyPage,x as PolicyProvider,X as usePolicyCompound};
|
package/dist/presets-dsr.d.mts
CHANGED
|
@@ -85,6 +85,31 @@ export declare interface NDPRSubjectRightsProps {
|
|
|
85
85
|
error?: unknown;
|
|
86
86
|
response?: Response;
|
|
87
87
|
}) => void;
|
|
88
|
+
/**
|
|
89
|
+
* Called when a `submitTo` POST succeeds (2xx response). Receives the
|
|
90
|
+
* `Response` object, the submitted `DSRFormSubmission` payload, and the
|
|
91
|
+
* parsed JSON body if the server returned valid JSON. Use this to
|
|
92
|
+
* display a server-generated reference number, redirect the user, or
|
|
93
|
+
* trigger analytics.
|
|
94
|
+
*
|
|
95
|
+
* The `body` field is `undefined` if the response had no body or the
|
|
96
|
+
* body was not valid JSON. It is typed `unknown` to force consumers to
|
|
97
|
+
* narrow it themselves before reading fields.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* <NDPRSubjectRights
|
|
101
|
+
* submitTo="/api/dsr"
|
|
102
|
+
* onSubmitSuccess={({ response, data, body }) => {
|
|
103
|
+
* const ref = (body as { referenceId?: string })?.referenceId;
|
|
104
|
+
* if (ref) router.push(`/dsr-confirmation?ref=${ref}`);
|
|
105
|
+
* }}
|
|
106
|
+
* />
|
|
107
|
+
*/
|
|
108
|
+
onSubmitSuccess?: (ctx: {
|
|
109
|
+
response: Response;
|
|
110
|
+
data: DSRFormSubmission;
|
|
111
|
+
body?: unknown;
|
|
112
|
+
}) => void;
|
|
88
113
|
}
|
|
89
114
|
|
|
90
115
|
/**
|
package/dist/presets-dsr.d.ts
CHANGED
|
@@ -85,6 +85,31 @@ export declare interface NDPRSubjectRightsProps {
|
|
|
85
85
|
error?: unknown;
|
|
86
86
|
response?: Response;
|
|
87
87
|
}) => void;
|
|
88
|
+
/**
|
|
89
|
+
* Called when a `submitTo` POST succeeds (2xx response). Receives the
|
|
90
|
+
* `Response` object, the submitted `DSRFormSubmission` payload, and the
|
|
91
|
+
* parsed JSON body if the server returned valid JSON. Use this to
|
|
92
|
+
* display a server-generated reference number, redirect the user, or
|
|
93
|
+
* trigger analytics.
|
|
94
|
+
*
|
|
95
|
+
* The `body` field is `undefined` if the response had no body or the
|
|
96
|
+
* body was not valid JSON. It is typed `unknown` to force consumers to
|
|
97
|
+
* narrow it themselves before reading fields.
|
|
98
|
+
*
|
|
99
|
+
* @example
|
|
100
|
+
* <NDPRSubjectRights
|
|
101
|
+
* submitTo="/api/dsr"
|
|
102
|
+
* onSubmitSuccess={({ response, data, body }) => {
|
|
103
|
+
* const ref = (body as { referenceId?: string })?.referenceId;
|
|
104
|
+
* if (ref) router.push(`/dsr-confirmation?ref=${ref}`);
|
|
105
|
+
* }}
|
|
106
|
+
* />
|
|
107
|
+
*/
|
|
108
|
+
onSubmitSuccess?: (ctx: {
|
|
109
|
+
response: Response;
|
|
110
|
+
data: DSRFormSubmission;
|
|
111
|
+
body?: unknown;
|
|
112
|
+
}) => void;
|
|
88
113
|
}
|
|
89
114
|
|
|
90
115
|
/**
|
package/dist/presets-dsr.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
'use strict';var
|
|
2
|
+
'use strict';var chunkXS3Z4UT7_js=require('./chunk-XS3Z4UT7.js');require('./chunk-W47OSMT6.js'),require('./chunk-UXUMYP4L.js'),require('./chunk-AME4HJR4.js'),require('./chunk-RFPLZDIO.js');Object.defineProperty(exports,"NDPRSubjectRights",{enumerable:true,get:function(){return chunkXS3Z4UT7_js.a}});
|
package/dist/presets-dsr.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
export{a as NDPRSubjectRights}from'./chunk-
|
|
2
|
+
export{a as NDPRSubjectRights}from'./chunk-EFIWANHF.mjs';import'./chunk-XJO4DH3L.mjs';import'./chunk-EWVK45Z3.mjs';import'./chunk-SFGW37LE.mjs';import'./chunk-ZJYULEER.mjs';
|
|
@@ -39,6 +39,35 @@ export declare interface NDPRPrivacyPolicyProps {
|
|
|
39
39
|
onComplete?: (policy: PrivacyPolicy) => void;
|
|
40
40
|
classNames?: Record<string, string>;
|
|
41
41
|
unstyled?: boolean;
|
|
42
|
+
/**
|
|
43
|
+
* Pre-fill the policy wizard with a sector-specific starter template.
|
|
44
|
+
*
|
|
45
|
+
* Pass one of `'saas' | 'ecommerce' | 'school' | 'healthcare' |
|
|
46
|
+
* 'procurement'` and the wizard opens already populated with the data
|
|
47
|
+
* categories, lawful-basis defaults, sensitive-data / children /
|
|
48
|
+
* cross-border / automated-decisions flags that org type usually needs.
|
|
49
|
+
* The user can still flip every flag and rewrite every section.
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* <NDPRPrivacyPolicy
|
|
53
|
+
* template="healthcare"
|
|
54
|
+
* templateOverrides={{ orgName: 'Lagos Heart Centre' }}
|
|
55
|
+
* />
|
|
56
|
+
*
|
|
57
|
+
* @see templateContextFor in `/server` or `/core` for the underlying
|
|
58
|
+
* factory if you'd rather build the context yourself.
|
|
59
|
+
*/
|
|
60
|
+
template?: OrgPolicyTemplateId;
|
|
61
|
+
/**
|
|
62
|
+
* Organisation-level overrides applied on top of the chosen template.
|
|
63
|
+
* Ignored when `template` is unset.
|
|
64
|
+
*/
|
|
65
|
+
templateOverrides?: OrgPolicyTemplateOverrides;
|
|
66
|
+
/**
|
|
67
|
+
* Pass a fully-constructed `TemplateContext` to skip the template
|
|
68
|
+
* lookup entirely. Takes precedence over `template` if both are set.
|
|
69
|
+
*/
|
|
70
|
+
initialContext?: TemplateContext;
|
|
42
71
|
}
|
|
43
72
|
|
|
44
73
|
/**
|
|
@@ -65,6 +94,48 @@ declare interface OrganizationInfo {
|
|
|
65
94
|
ndpcRegistrationNumber?: string;
|
|
66
95
|
}
|
|
67
96
|
|
|
97
|
+
/**
|
|
98
|
+
* Org-specific privacy-policy templates — pre-filled `TemplateContext`
|
|
99
|
+
* factories for the most common Nigerian app shapes.
|
|
100
|
+
*
|
|
101
|
+
* Each template returns a fully-populated `TemplateContext` with:
|
|
102
|
+
* - industry set to the matching `Industry` value
|
|
103
|
+
* - the data categories the sector typically collects (selected: true)
|
|
104
|
+
* - the processing purposes that match the business model
|
|
105
|
+
* - sensitive-data / children / cross-border / automated-decisions flags
|
|
106
|
+
* set to the defaults that org type usually needs (a school will have
|
|
107
|
+
* children data, a hospital will have sensitive data, etc.)
|
|
108
|
+
*
|
|
109
|
+
* Templates are guidance starters. The wizard still walks the user through
|
|
110
|
+
* every step — they can flip any flag, add/remove categories, or rewrite
|
|
111
|
+
* any section before the policy is finalised. The legal-notice footer the
|
|
112
|
+
* toolkit ships everywhere applies to the generated output.
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* import { templateContextFor } from '@tantainnovative/ndpr-toolkit/server';
|
|
116
|
+
* const ctx = templateContextFor('ecommerce', { orgName: 'Acme NG' });
|
|
117
|
+
* const draft = assemblePolicy(ctx);
|
|
118
|
+
*/
|
|
119
|
+
|
|
120
|
+
/** Identifiers for the bundled org templates. */
|
|
121
|
+
declare type OrgPolicyTemplateId = 'saas' | 'ecommerce' | 'school' | 'healthcare' | 'procurement';
|
|
122
|
+
|
|
123
|
+
/** Optional overrides applied on top of a template's defaults. */
|
|
124
|
+
declare interface OrgPolicyTemplateOverrides {
|
|
125
|
+
/** Organisation name (e.g. "Acme Nigeria Ltd"). Default: empty. */
|
|
126
|
+
orgName?: string;
|
|
127
|
+
/** Public website URL. */
|
|
128
|
+
website?: string;
|
|
129
|
+
/** Privacy contact email. */
|
|
130
|
+
privacyEmail?: string;
|
|
131
|
+
/** Postal address. */
|
|
132
|
+
address?: string;
|
|
133
|
+
/** DPO name. Required for DCPMI under NDPA Section 32. */
|
|
134
|
+
dpoName?: string;
|
|
135
|
+
/** DPO email. Required for the NDPC breach-notification contact. */
|
|
136
|
+
dpoEmail?: string;
|
|
137
|
+
}
|
|
138
|
+
|
|
68
139
|
/** Organisation size tiers — affects complexity of generated language. */
|
|
69
140
|
declare type OrgSize = 'startup' | 'midsize' | 'enterprise';
|
|
70
141
|
|