@tantainnovative/ndpr-toolkit 3.6.1 → 3.7.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/dist/policy.js CHANGED
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- 'use strict';var chunkI2LMQWK3_js=require('./chunk-I2LMQWK3.js'),chunkXO3VQYTL_js=require('./chunk-XO3VQYTL.js'),chunkZ763UI5U_js=require('./chunk-Z763UI5U.js'),chunkUI536RU2_js=require('./chunk-UI536RU2.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 Y(){let o=react.useContext(u);if(!o)throw new Error("Policy compound components must be wrapped in <Policy.Provider>. Example: <Policy.Provider templates={...}><Policy.Generator /></Policy.Provider>");return o}var x=({templates:o,adapter:l,storageKey:t,useLocalStorage:i,initialPolicy:p,onGenerate:a,children:e})=>{let y=chunkZ763UI5U_js.a({templates:o,adapter:l,storageKey:t,useLocalStorage:i,initialPolicy:p,onGenerate:a}),r=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},y),{templates:o});return jsxRuntime.jsx(u.Provider,{value:r,children:e})};var X={Provider:x,Generator:chunkXO3VQYTL_js.a,Preview:chunkXO3VQYTL_js.b,Exporter:chunkXO3VQYTL_js.c};var Q=({policy:o,className:l,mode:t="shadow",options:i})=>{let p=react.useRef(null);if(react.useEffect(()=>{var g;if(t!=="shadow")return;let e=p.current;if(!e)return;let y=chunkN3MQQUQP_js.a(o,chunkRFPLZDIO_js.a({includeStyles:true,includePrintCSS:true},i)),r=(g=e.shadowRoot)!=null?g:e.attachShadow({mode:"open"});r.innerHTML=y;let v=h=>{var A;let C=h.target;if(!C)return;let T=C.closest("a[href]");if(!T)return;let P=(A=T.getAttribute("href"))!=null?A:"";if(!P.startsWith("#")||P.length<2)return;let R=decodeURIComponent(P.slice(1)),E=r.getElementById(R);E&&(h.preventDefault(),E.scrollIntoView({behavior:"smooth",block:"start"}));};return r.addEventListener("click",v),()=>{r.removeEventListener("click",v),e.shadowRoot&&(e.shadowRoot.innerHTML="");}},[o,i,t]),t==="shadow")return jsxRuntime.jsx("div",{ref:p,"data-ndpr-component":"policy-page",className:l});let a=chunkN3MQQUQP_js.a(o,chunkRFPLZDIO_js.a({includeStyles:false},i));return jsxRuntime.jsx("div",{"data-ndpr-component":"policy-page",className:l,dangerouslySetInnerHTML:{__html:a}})};Object.defineProperty(exports,"AdaptivePolicyWizard",{enumerable:true,get:function(){return chunkI2LMQWK3_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,"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 chunkUI536RU2_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=X;exports.PolicyPage=Q;exports.PolicyProvider=x;exports.usePolicyCompound=Y;
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-BNHQFZHL.mjs';import {c,b,a}from'./chunk-TMXK4QKK.mjs';export{c as PolicyExporter,a as PolicyGenerator,b as PolicyPreview}from'./chunk-TMXK4QKK.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-O6CUBNXK.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 Y(){let o=useContext(u);if(!o)throw new Error("Policy compound components must be wrapped in <Policy.Provider>. Example: <Policy.Provider templates={...}><Policy.Generator /></Policy.Provider>");return o}var x=({templates:o,adapter:l,storageKey:t,useLocalStorage:i,initialPolicy:p,onGenerate:a,children:e})=>{let y=a$1({templates:o,adapter:l,storageKey:t,useLocalStorage:i,initialPolicy:p,onGenerate:a}),r=b$1(a$2({},y),{templates:o});return jsx(u.Provider,{value:r,children:e})};var X={Provider:x,Generator:a,Preview:b,Exporter:c};var Q=({policy:o,className:l,mode:t="shadow",options:i})=>{let p=useRef(null);if(useEffect(()=>{var g;if(t!=="shadow")return;let e=p.current;if(!e)return;let y=a$3(o,a$2({includeStyles:true,includePrintCSS:true},i)),r=(g=e.shadowRoot)!=null?g:e.attachShadow({mode:"open"});r.innerHTML=y;let v=h=>{var A;let C=h.target;if(!C)return;let T=C.closest("a[href]");if(!T)return;let P=(A=T.getAttribute("href"))!=null?A:"";if(!P.startsWith("#")||P.length<2)return;let R=decodeURIComponent(P.slice(1)),E=r.getElementById(R);E&&(h.preventDefault(),E.scrollIntoView({behavior:"smooth",block:"start"}));};return r.addEventListener("click",v),()=>{r.removeEventListener("click",v),e.shadowRoot&&(e.shadowRoot.innerHTML="");}},[o,i,t]),t==="shadow")return jsx("div",{ref:p,"data-ndpr-component":"policy-page",className:l});let a=a$3(o,a$2({includeStyles:false},i));return jsx("div",{"data-ndpr-component":"policy-page",className:l,dangerouslySetInnerHTML:{__html:a}})};export{X as Policy,Q as PolicyPage,x as PolicyProvider,Y as usePolicyCompound};
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};
@@ -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
 
@@ -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
 
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- 'use strict';var chunkW7RBGZCC_js=require('./chunk-W7RBGZCC.js');require('./chunk-I2LMQWK3.js'),require('./chunk-UI536RU2.js'),require('./chunk-N3MQQUQP.js'),require('./chunk-Q64735OC.js'),require('./chunk-ZVOIR4QH.js'),require('./chunk-AME4HJR4.js'),require('./chunk-VWED6UTN.js'),require('./chunk-RFPLZDIO.js');Object.defineProperty(exports,"NDPRPrivacyPolicy",{enumerable:true,get:function(){return chunkW7RBGZCC_js.a}});
2
+ 'use strict';var chunk5IOC3VAW_js=require('./chunk-5IOC3VAW.js');require('./chunk-W7OLQRJP.js'),require('./chunk-3GRGYT3P.js'),require('./chunk-HXWHL4BD.js'),require('./chunk-N3MQQUQP.js'),require('./chunk-Q64735OC.js'),require('./chunk-ZVOIR4QH.js'),require('./chunk-AME4HJR4.js'),require('./chunk-VWED6UTN.js'),require('./chunk-RFPLZDIO.js');Object.defineProperty(exports,"NDPRPrivacyPolicy",{enumerable:true,get:function(){return chunk5IOC3VAW_js.a}});
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- export{a as NDPRPrivacyPolicy}from'./chunk-RV2VMWZJ.mjs';import'./chunk-BNHQFZHL.mjs';import'./chunk-O6CUBNXK.mjs';import'./chunk-AOHKVFAS.mjs';import'./chunk-RMQ7OLNY.mjs';import'./chunk-ITCY2Z66.mjs';import'./chunk-SFGW37LE.mjs';import'./chunk-DBZSN4WP.mjs';import'./chunk-ZJYULEER.mjs';
2
+ export{a as NDPRPrivacyPolicy}from'./chunk-R7545FP4.mjs';import'./chunk-ATFUSHC2.mjs';import'./chunk-UKLU6BQF.mjs';import'./chunk-2MIQXECH.mjs';import'./chunk-AOHKVFAS.mjs';import'./chunk-RMQ7OLNY.mjs';import'./chunk-ITCY2Z66.mjs';import'./chunk-SFGW37LE.mjs';import'./chunk-DBZSN4WP.mjs';import'./chunk-ZJYULEER.mjs';
@@ -674,6 +674,35 @@ export declare interface NDPRPrivacyPolicyProps {
674
674
  onComplete?: (policy: PrivacyPolicy) => void;
675
675
  classNames?: Record<string, string>;
676
676
  unstyled?: boolean;
677
+ /**
678
+ * Pre-fill the policy wizard with a sector-specific starter template.
679
+ *
680
+ * Pass one of `'saas' | 'ecommerce' | 'school' | 'healthcare' |
681
+ * 'procurement'` and the wizard opens already populated with the data
682
+ * categories, lawful-basis defaults, sensitive-data / children /
683
+ * cross-border / automated-decisions flags that org type usually needs.
684
+ * The user can still flip every flag and rewrite every section.
685
+ *
686
+ * @example
687
+ * <NDPRPrivacyPolicy
688
+ * template="healthcare"
689
+ * templateOverrides={{ orgName: 'Lagos Heart Centre' }}
690
+ * />
691
+ *
692
+ * @see templateContextFor in `/server` or `/core` for the underlying
693
+ * factory if you'd rather build the context yourself.
694
+ */
695
+ template?: OrgPolicyTemplateId;
696
+ /**
697
+ * Organisation-level overrides applied on top of the chosen template.
698
+ * Ignored when `template` is unset.
699
+ */
700
+ templateOverrides?: OrgPolicyTemplateOverrides;
701
+ /**
702
+ * Pass a fully-constructed `TemplateContext` to skip the template
703
+ * lookup entirely. Takes precedence over `template` if both are set.
704
+ */
705
+ initialContext?: TemplateContext;
677
706
  }
678
707
 
679
708
  export declare const NDPRROPA: React__default.FC<NDPRROPAProps>;
@@ -758,6 +787,48 @@ declare interface OrganizationInfo {
758
787
  ndpcRegistrationNumber?: string;
759
788
  }
760
789
 
790
+ /**
791
+ * Org-specific privacy-policy templates — pre-filled `TemplateContext`
792
+ * factories for the most common Nigerian app shapes.
793
+ *
794
+ * Each template returns a fully-populated `TemplateContext` with:
795
+ * - industry set to the matching `Industry` value
796
+ * - the data categories the sector typically collects (selected: true)
797
+ * - the processing purposes that match the business model
798
+ * - sensitive-data / children / cross-border / automated-decisions flags
799
+ * set to the defaults that org type usually needs (a school will have
800
+ * children data, a hospital will have sensitive data, etc.)
801
+ *
802
+ * Templates are guidance starters. The wizard still walks the user through
803
+ * every step — they can flip any flag, add/remove categories, or rewrite
804
+ * any section before the policy is finalised. The legal-notice footer the
805
+ * toolkit ships everywhere applies to the generated output.
806
+ *
807
+ * @example
808
+ * import { templateContextFor } from '@tantainnovative/ndpr-toolkit/server';
809
+ * const ctx = templateContextFor('ecommerce', { orgName: 'Acme NG' });
810
+ * const draft = assemblePolicy(ctx);
811
+ */
812
+
813
+ /** Identifiers for the bundled org templates. */
814
+ declare type OrgPolicyTemplateId = 'saas' | 'ecommerce' | 'school' | 'healthcare' | 'procurement';
815
+
816
+ /** Optional overrides applied on top of a template's defaults. */
817
+ declare interface OrgPolicyTemplateOverrides {
818
+ /** Organisation name (e.g. "Acme Nigeria Ltd"). Default: empty. */
819
+ orgName?: string;
820
+ /** Public website URL. */
821
+ website?: string;
822
+ /** Privacy contact email. */
823
+ privacyEmail?: string;
824
+ /** Postal address. */
825
+ address?: string;
826
+ /** DPO name. Required for DCPMI under NDPA Section 32. */
827
+ dpoName?: string;
828
+ /** DPO email. Required for the NDPC breach-notification contact. */
829
+ dpoEmail?: string;
830
+ }
831
+
761
832
  /** Organisation size tiers — affects complexity of generated language. */
762
833
  declare type OrgSize = 'startup' | 'midsize' | 'enterprise';
763
834
 
package/dist/presets.d.ts CHANGED
@@ -674,6 +674,35 @@ export declare interface NDPRPrivacyPolicyProps {
674
674
  onComplete?: (policy: PrivacyPolicy) => void;
675
675
  classNames?: Record<string, string>;
676
676
  unstyled?: boolean;
677
+ /**
678
+ * Pre-fill the policy wizard with a sector-specific starter template.
679
+ *
680
+ * Pass one of `'saas' | 'ecommerce' | 'school' | 'healthcare' |
681
+ * 'procurement'` and the wizard opens already populated with the data
682
+ * categories, lawful-basis defaults, sensitive-data / children /
683
+ * cross-border / automated-decisions flags that org type usually needs.
684
+ * The user can still flip every flag and rewrite every section.
685
+ *
686
+ * @example
687
+ * <NDPRPrivacyPolicy
688
+ * template="healthcare"
689
+ * templateOverrides={{ orgName: 'Lagos Heart Centre' }}
690
+ * />
691
+ *
692
+ * @see templateContextFor in `/server` or `/core` for the underlying
693
+ * factory if you'd rather build the context yourself.
694
+ */
695
+ template?: OrgPolicyTemplateId;
696
+ /**
697
+ * Organisation-level overrides applied on top of the chosen template.
698
+ * Ignored when `template` is unset.
699
+ */
700
+ templateOverrides?: OrgPolicyTemplateOverrides;
701
+ /**
702
+ * Pass a fully-constructed `TemplateContext` to skip the template
703
+ * lookup entirely. Takes precedence over `template` if both are set.
704
+ */
705
+ initialContext?: TemplateContext;
677
706
  }
678
707
 
679
708
  export declare const NDPRROPA: React__default.FC<NDPRROPAProps>;
@@ -758,6 +787,48 @@ declare interface OrganizationInfo {
758
787
  ndpcRegistrationNumber?: string;
759
788
  }
760
789
 
790
+ /**
791
+ * Org-specific privacy-policy templates — pre-filled `TemplateContext`
792
+ * factories for the most common Nigerian app shapes.
793
+ *
794
+ * Each template returns a fully-populated `TemplateContext` with:
795
+ * - industry set to the matching `Industry` value
796
+ * - the data categories the sector typically collects (selected: true)
797
+ * - the processing purposes that match the business model
798
+ * - sensitive-data / children / cross-border / automated-decisions flags
799
+ * set to the defaults that org type usually needs (a school will have
800
+ * children data, a hospital will have sensitive data, etc.)
801
+ *
802
+ * Templates are guidance starters. The wizard still walks the user through
803
+ * every step — they can flip any flag, add/remove categories, or rewrite
804
+ * any section before the policy is finalised. The legal-notice footer the
805
+ * toolkit ships everywhere applies to the generated output.
806
+ *
807
+ * @example
808
+ * import { templateContextFor } from '@tantainnovative/ndpr-toolkit/server';
809
+ * const ctx = templateContextFor('ecommerce', { orgName: 'Acme NG' });
810
+ * const draft = assemblePolicy(ctx);
811
+ */
812
+
813
+ /** Identifiers for the bundled org templates. */
814
+ declare type OrgPolicyTemplateId = 'saas' | 'ecommerce' | 'school' | 'healthcare' | 'procurement';
815
+
816
+ /** Optional overrides applied on top of a template's defaults. */
817
+ declare interface OrgPolicyTemplateOverrides {
818
+ /** Organisation name (e.g. "Acme Nigeria Ltd"). Default: empty. */
819
+ orgName?: string;
820
+ /** Public website URL. */
821
+ website?: string;
822
+ /** Privacy contact email. */
823
+ privacyEmail?: string;
824
+ /** Postal address. */
825
+ address?: string;
826
+ /** DPO name. Required for DCPMI under NDPA Section 32. */
827
+ dpoName?: string;
828
+ /** DPO email. Required for the NDPC breach-notification contact. */
829
+ dpoEmail?: string;
830
+ }
831
+
761
832
  /** Organisation size tiers — affects complexity of generated language. */
762
833
  declare type OrgSize = 'startup' | 'midsize' | 'enterprise';
763
834
 
package/dist/presets.js CHANGED
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- 'use strict';var chunkW7RBGZCC_js=require('./chunk-W7RBGZCC.js');require('./chunk-I2LMQWK3.js');var chunkV3RYHNHN_js=require('./chunk-V3RYHNHN.js'),chunkRXZFYBUJ_js=require('./chunk-RXZFYBUJ.js'),chunkNUWVPRNI_js=require('./chunk-NUWVPRNI.js'),chunkPZRQWPWD_js=require('./chunk-PZRQWPWD.js'),chunkI3Y4LOSL_js=require('./chunk-I3Y4LOSL.js'),chunk5GVMKUMP_js=require('./chunk-5GVMKUMP.js');require('./chunk-UI536RU2.js'),require('./chunk-N3MQQUQP.js');var chunkQPRYXVH2_js=require('./chunk-QPRYXVH2.js');require('./chunk-Q64735OC.js'),require('./chunk-WZYCBW2R.js'),require('./chunk-YFBDJ4FH.js'),require('./chunk-4CVBQC66.js'),require('./chunk-732C2EVN.js'),require('./chunk-L2VO3MEJ.js'),require('./chunk-W47OSMT6.js');var chunkWDDCKYWA_js=require('./chunk-WDDCKYWA.js'),chunkS6COXIZA_js=require('./chunk-S6COXIZA.js');require('./chunk-UXUMYP4L.js'),require('./chunk-ZVOIR4QH.js'),require('./chunk-AME4HJR4.js'),require('./chunk-VWED6UTN.js');var chunkRFPLZDIO_js=require('./chunk-RFPLZDIO.js'),jsxRuntime=require('react/jsx-runtime'),react=require('react');var L=[{id:"unauthorized_access",name:"Unauthorized Access",description:"Unauthorized access to personal data",defaultSeverity:"high"},{id:"data_loss",name:"Data Loss",description:"Loss of personal data",defaultSeverity:"high"},{id:"data_theft",name:"Data Theft",description:"Theft of personal data",defaultSeverity:"critical"},{id:"system_breach",name:"System Breach",description:"Breach of system containing personal data",defaultSeverity:"critical"},{id:"accidental_disclosure",name:"Accidental Disclosure",description:"Unintended disclosure of personal data",defaultSeverity:"medium"}],I=({categories:c=L,adapter:s,classNames:u,unstyled:p,onSubmit:o=()=>{}})=>jsxRuntime.jsx(chunkS6COXIZA_js.a,{categories:c,onSubmit:d=>{s&&s.save(d),o(d);},classNames:u,unstyled:p});var k=[{id:"project_overview",title:"Project Overview",description:"Provide basic details about the processing activity being assessed.",order:0,questions:[{id:"project_name",text:"What is the name of the project or processing activity?",type:"text",required:true},{id:"project_description",text:"Describe the nature and purpose of the processing.",guidance:"Include what personal data will be collected, why it is needed, and how it will be used.",type:"textarea",required:true},{id:"data_controller",text:"Who is the data controller responsible for this processing?",type:"text",required:true}]},{id:"necessity",title:"Necessity & Proportionality",description:"Assess whether the processing is necessary and proportionate to the purposes.",order:1,questions:[{id:"lawful_basis",text:"What is the lawful basis for processing under the NDPA 2023?",type:"select",required:true,options:[{value:"consent",label:"Consent (Section 25(1)(a))"},{value:"contract",label:"Contract (Section 25(1)(b))"},{value:"legal_obligation",label:"Legal Obligation (Section 25(1)(c))"},{value:"vital_interests",label:"Vital Interests (Section 25(1)(d))"},{value:"public_task",label:"Public Task (Section 25(1)(e))"},{value:"legitimate_interests",label:"Legitimate Interests (Section 25(1)(f))"}]},{id:"data_minimisation",text:"Is the processing limited to what is necessary for the specified purpose?",type:"radio",required:true,options:[{value:"yes",label:"Yes \u2014 only minimum data is collected",riskLevel:"low"},{value:"partial",label:"Partially \u2014 some additional data may be collected",riskLevel:"medium"},{value:"no",label:"No \u2014 more data is collected than strictly necessary",riskLevel:"high"}]}]},{id:"risk_identification",title:"Risk Identification",description:"Identify and assess risks to data subjects arising from the processing.",order:2,questions:[{id:"sensitive_data",text:"Does the processing involve sensitive personal data (e.g., health, biometric, financial, children's data)?",type:"radio",required:true,options:[{value:"no",label:"No sensitive data",riskLevel:"low"},{value:"yes_protected",label:"Yes, with appropriate safeguards",riskLevel:"medium"},{value:"yes_unprotected",label:"Yes, without adequate safeguards",riskLevel:"high"}]},{id:"scale",text:"What is the scale of processing?",type:"radio",required:true,options:[{value:"small",label:"Small scale (fewer than 1,000 individuals)",riskLevel:"low"},{value:"medium",label:"Medium scale (1,000 to 100,000 individuals)",riskLevel:"medium"},{value:"large",label:"Large scale (over 100,000 individuals)",riskLevel:"high"}]},{id:"cross_border",text:"Will data be transferred outside Nigeria?",type:"radio",required:true,options:[{value:"no",label:"No international transfers",riskLevel:"low"},{value:"adequate",label:"Yes, to countries with adequate protection",riskLevel:"medium"},{value:"inadequate",label:"Yes, to countries without adequate protection",riskLevel:"high"}]}]},{id:"mitigation",title:"Risk Mitigation & Measures",description:"Document the measures taken to address identified risks.",order:3,questions:[{id:"security_measures",text:"What technical and organisational security measures are in place?",guidance:"Include encryption, access controls, pseudonymisation, staff training, etc.",type:"textarea",required:true},{id:"retention_period",text:"What is the data retention period?",guidance:"Specify how long data will be kept and the criteria used to determine this.",type:"text",required:true},{id:"dpo_consulted",text:"Has the Data Protection Officer (DPO) been consulted on this assessment?",type:"radio",required:false,options:[{value:"yes",label:"Yes",riskLevel:"low"},{value:"no",label:"No",riskLevel:"medium"},{value:"na",label:"Not applicable \u2014 no DPO appointed",riskLevel:"medium"}]}]}],_=({sections:c=k,adapter:s,classNames:u,unstyled:p,onComplete:o=()=>{}})=>{let[n,d]=react.useState({}),[m,f]=react.useState(0),P=(a,C)=>{d(S=>chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},S),{[a]:C}));},e=()=>{m<c.length-1?f(a=>a+1):(s&&s.save(n),o(n));},t=()=>{m>0&&f(a=>a-1);},r=Math.round((m+1)/c.length*100);return jsxRuntime.jsx(chunkWDDCKYWA_js.a,{sections:c,answers:n,onAnswerChange:P,currentSectionIndex:m,onNextSection:e,onPrevSection:t,progress:r,classNames:u,unstyled:p})};var F=({initialActivities:c=[],adapter:s,classNames:u,unstyled:p})=>{let[o,n]=react.useState(()=>{if(s){let e=s.load();if(e&&!(e instanceof Promise))return e}return c}),d=e=>{s&&s.save(e);};return jsxRuntime.jsx(chunkPZRQWPWD_js.a,{activities:o,onAddActivity:e=>{let t=Date.now(),r=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},e),{id:`activity-${t}`,createdAt:t,updatedAt:t}),a=[...o,r];n(a),d(a);},onUpdateActivity:(e,t)=>{let r=o.map(a=>a.id===e?chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a(chunkRFPLZDIO_js.a({},a),t),{updatedAt:Date.now()}):a);n(r),d(r);},onArchiveActivity:e=>{let t=o.map(r=>r.id===e?chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},r),{status:"inactive",updatedAt:Date.now()}):r);n(t),d(t);},classNames:u,unstyled:p})};var W=({initialTransfers:c=[],adapter:s,classNames:u,unstyled:p})=>{let[o,n]=react.useState(()=>{if(s){let e=s.load();if(e&&!(e instanceof Promise))return e}return c}),d=e=>{s&&s.save(e);};return jsxRuntime.jsx(chunkI3Y4LOSL_js.a,{transfers:o,onAddTransfer:e=>{let t=Date.now(),r=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},e),{id:`transfer-${t}`,createdAt:t,updatedAt:t}),a=[...o,r];n(a),d(a);},onUpdateTransfer:(e,t)=>{let r=o.map(a=>a.id===e?chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a(chunkRFPLZDIO_js.a({},a),t),{updatedAt:Date.now()}):a);n(r),d(r);},onRemoveTransfer:e=>{let t=o.filter(r=>r.id!==e);n(t),d(t);},classNames:u,unstyled:p})};var j={id:"ndpr-ropa-default",organizationName:"Your Organisation",organizationContact:"",organizationAddress:"",records:[],lastUpdated:Date.now(),version:"1.0"},V=({initialData:c,adapter:s,classNames:u,unstyled:p})=>{let[o,n]=react.useState(c!=null?c:j);react.useEffect(()=>{if(!s)return;let e=false;return chunkRFPLZDIO_js.d(null,null,function*(){let r=yield s.load();!e&&r&&n(r);}),()=>{e=true;}},[s]);let d=e=>{s&&s.save(e);};return jsxRuntime.jsx(chunk5GVMKUMP_js.a,{ropa:o,onAddRecord:e=>{let t=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},o),{records:[...o.records,e],lastUpdated:Date.now()});n(t),d(t);},onUpdateRecord:(e,t)=>{let r=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},o),{records:o.records.map(a=>a.id===e?chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a(chunkRFPLZDIO_js.a({},a),t),{updatedAt:Date.now()}):a),lastUpdated:Date.now()});n(r),d(r);},onArchiveRecord:e=>{let t=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},o),{records:o.records.map(r=>r.id===e?chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},r),{status:"archived",updatedAt:Date.now()}):r),lastUpdated:Date.now()});n(t),d(t);},classNames:u,unstyled:p})};var G=u=>{var p=u,{input:c}=p,s=chunkRFPLZDIO_js.c(p,["input"]);let o=chunkQPRYXVH2_js.a(c);return jsxRuntime.jsx(chunkNUWVPRNI_js.a,chunkRFPLZDIO_js.a({report:o},s))};Object.defineProperty(exports,"NDPRPrivacyPolicy",{enumerable:true,get:function(){return chunkW7RBGZCC_js.a}});Object.defineProperty(exports,"NDPRConsent",{enumerable:true,get:function(){return chunkV3RYHNHN_js.a}});Object.defineProperty(exports,"NDPRSubjectRights",{enumerable:true,get:function(){return chunkRXZFYBUJ_js.a}});exports.NDPRBreachReport=I;exports.NDPRComplianceDashboard=G;exports.NDPRCrossBorder=W;exports.NDPRDPIA=_;exports.NDPRLawfulBasis=F;exports.NDPRROPA=V;
2
+ 'use strict';var chunk5IOC3VAW_js=require('./chunk-5IOC3VAW.js');require('./chunk-W7OLQRJP.js');var chunkV3RYHNHN_js=require('./chunk-V3RYHNHN.js'),chunkRXZFYBUJ_js=require('./chunk-RXZFYBUJ.js'),chunkNUWVPRNI_js=require('./chunk-NUWVPRNI.js'),chunkPZRQWPWD_js=require('./chunk-PZRQWPWD.js'),chunkI3Y4LOSL_js=require('./chunk-I3Y4LOSL.js'),chunk5GVMKUMP_js=require('./chunk-5GVMKUMP.js');require('./chunk-3GRGYT3P.js'),require('./chunk-HXWHL4BD.js'),require('./chunk-N3MQQUQP.js');var chunkQPRYXVH2_js=require('./chunk-QPRYXVH2.js');require('./chunk-Q64735OC.js'),require('./chunk-WZYCBW2R.js'),require('./chunk-YFBDJ4FH.js'),require('./chunk-4CVBQC66.js'),require('./chunk-732C2EVN.js'),require('./chunk-L2VO3MEJ.js'),require('./chunk-W47OSMT6.js');var chunkWDDCKYWA_js=require('./chunk-WDDCKYWA.js'),chunkS6COXIZA_js=require('./chunk-S6COXIZA.js');require('./chunk-UXUMYP4L.js'),require('./chunk-ZVOIR4QH.js'),require('./chunk-AME4HJR4.js'),require('./chunk-VWED6UTN.js');var chunkRFPLZDIO_js=require('./chunk-RFPLZDIO.js'),jsxRuntime=require('react/jsx-runtime'),react=require('react');var L=[{id:"unauthorized_access",name:"Unauthorized Access",description:"Unauthorized access to personal data",defaultSeverity:"high"},{id:"data_loss",name:"Data Loss",description:"Loss of personal data",defaultSeverity:"high"},{id:"data_theft",name:"Data Theft",description:"Theft of personal data",defaultSeverity:"critical"},{id:"system_breach",name:"System Breach",description:"Breach of system containing personal data",defaultSeverity:"critical"},{id:"accidental_disclosure",name:"Accidental Disclosure",description:"Unintended disclosure of personal data",defaultSeverity:"medium"}],I=({categories:c=L,adapter:s,classNames:u,unstyled:p,onSubmit:o=()=>{}})=>jsxRuntime.jsx(chunkS6COXIZA_js.a,{categories:c,onSubmit:d=>{s&&s.save(d),o(d);},classNames:u,unstyled:p});var k=[{id:"project_overview",title:"Project Overview",description:"Provide basic details about the processing activity being assessed.",order:0,questions:[{id:"project_name",text:"What is the name of the project or processing activity?",type:"text",required:true},{id:"project_description",text:"Describe the nature and purpose of the processing.",guidance:"Include what personal data will be collected, why it is needed, and how it will be used.",type:"textarea",required:true},{id:"data_controller",text:"Who is the data controller responsible for this processing?",type:"text",required:true}]},{id:"necessity",title:"Necessity & Proportionality",description:"Assess whether the processing is necessary and proportionate to the purposes.",order:1,questions:[{id:"lawful_basis",text:"What is the lawful basis for processing under the NDPA 2023?",type:"select",required:true,options:[{value:"consent",label:"Consent (Section 25(1)(a))"},{value:"contract",label:"Contract (Section 25(1)(b))"},{value:"legal_obligation",label:"Legal Obligation (Section 25(1)(c))"},{value:"vital_interests",label:"Vital Interests (Section 25(1)(d))"},{value:"public_task",label:"Public Task (Section 25(1)(e))"},{value:"legitimate_interests",label:"Legitimate Interests (Section 25(1)(f))"}]},{id:"data_minimisation",text:"Is the processing limited to what is necessary for the specified purpose?",type:"radio",required:true,options:[{value:"yes",label:"Yes \u2014 only minimum data is collected",riskLevel:"low"},{value:"partial",label:"Partially \u2014 some additional data may be collected",riskLevel:"medium"},{value:"no",label:"No \u2014 more data is collected than strictly necessary",riskLevel:"high"}]}]},{id:"risk_identification",title:"Risk Identification",description:"Identify and assess risks to data subjects arising from the processing.",order:2,questions:[{id:"sensitive_data",text:"Does the processing involve sensitive personal data (e.g., health, biometric, financial, children's data)?",type:"radio",required:true,options:[{value:"no",label:"No sensitive data",riskLevel:"low"},{value:"yes_protected",label:"Yes, with appropriate safeguards",riskLevel:"medium"},{value:"yes_unprotected",label:"Yes, without adequate safeguards",riskLevel:"high"}]},{id:"scale",text:"What is the scale of processing?",type:"radio",required:true,options:[{value:"small",label:"Small scale (fewer than 1,000 individuals)",riskLevel:"low"},{value:"medium",label:"Medium scale (1,000 to 100,000 individuals)",riskLevel:"medium"},{value:"large",label:"Large scale (over 100,000 individuals)",riskLevel:"high"}]},{id:"cross_border",text:"Will data be transferred outside Nigeria?",type:"radio",required:true,options:[{value:"no",label:"No international transfers",riskLevel:"low"},{value:"adequate",label:"Yes, to countries with adequate protection",riskLevel:"medium"},{value:"inadequate",label:"Yes, to countries without adequate protection",riskLevel:"high"}]}]},{id:"mitigation",title:"Risk Mitigation & Measures",description:"Document the measures taken to address identified risks.",order:3,questions:[{id:"security_measures",text:"What technical and organisational security measures are in place?",guidance:"Include encryption, access controls, pseudonymisation, staff training, etc.",type:"textarea",required:true},{id:"retention_period",text:"What is the data retention period?",guidance:"Specify how long data will be kept and the criteria used to determine this.",type:"text",required:true},{id:"dpo_consulted",text:"Has the Data Protection Officer (DPO) been consulted on this assessment?",type:"radio",required:false,options:[{value:"yes",label:"Yes",riskLevel:"low"},{value:"no",label:"No",riskLevel:"medium"},{value:"na",label:"Not applicable \u2014 no DPO appointed",riskLevel:"medium"}]}]}],_=({sections:c=k,adapter:s,classNames:u,unstyled:p,onComplete:o=()=>{}})=>{let[n,d]=react.useState({}),[m,f]=react.useState(0),P=(a,C)=>{d(S=>chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},S),{[a]:C}));},e=()=>{m<c.length-1?f(a=>a+1):(s&&s.save(n),o(n));},t=()=>{m>0&&f(a=>a-1);},r=Math.round((m+1)/c.length*100);return jsxRuntime.jsx(chunkWDDCKYWA_js.a,{sections:c,answers:n,onAnswerChange:P,currentSectionIndex:m,onNextSection:e,onPrevSection:t,progress:r,classNames:u,unstyled:p})};var F=({initialActivities:c=[],adapter:s,classNames:u,unstyled:p})=>{let[o,n]=react.useState(()=>{if(s){let e=s.load();if(e&&!(e instanceof Promise))return e}return c}),d=e=>{s&&s.save(e);};return jsxRuntime.jsx(chunkPZRQWPWD_js.a,{activities:o,onAddActivity:e=>{let t=Date.now(),r=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},e),{id:`activity-${t}`,createdAt:t,updatedAt:t}),a=[...o,r];n(a),d(a);},onUpdateActivity:(e,t)=>{let r=o.map(a=>a.id===e?chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a(chunkRFPLZDIO_js.a({},a),t),{updatedAt:Date.now()}):a);n(r),d(r);},onArchiveActivity:e=>{let t=o.map(r=>r.id===e?chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},r),{status:"inactive",updatedAt:Date.now()}):r);n(t),d(t);},classNames:u,unstyled:p})};var W=({initialTransfers:c=[],adapter:s,classNames:u,unstyled:p})=>{let[o,n]=react.useState(()=>{if(s){let e=s.load();if(e&&!(e instanceof Promise))return e}return c}),d=e=>{s&&s.save(e);};return jsxRuntime.jsx(chunkI3Y4LOSL_js.a,{transfers:o,onAddTransfer:e=>{let t=Date.now(),r=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},e),{id:`transfer-${t}`,createdAt:t,updatedAt:t}),a=[...o,r];n(a),d(a);},onUpdateTransfer:(e,t)=>{let r=o.map(a=>a.id===e?chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a(chunkRFPLZDIO_js.a({},a),t),{updatedAt:Date.now()}):a);n(r),d(r);},onRemoveTransfer:e=>{let t=o.filter(r=>r.id!==e);n(t),d(t);},classNames:u,unstyled:p})};var j={id:"ndpr-ropa-default",organizationName:"Your Organisation",organizationContact:"",organizationAddress:"",records:[],lastUpdated:Date.now(),version:"1.0"},V=({initialData:c,adapter:s,classNames:u,unstyled:p})=>{let[o,n]=react.useState(c!=null?c:j);react.useEffect(()=>{if(!s)return;let e=false;return chunkRFPLZDIO_js.d(null,null,function*(){let r=yield s.load();!e&&r&&n(r);}),()=>{e=true;}},[s]);let d=e=>{s&&s.save(e);};return jsxRuntime.jsx(chunk5GVMKUMP_js.a,{ropa:o,onAddRecord:e=>{let t=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},o),{records:[...o.records,e],lastUpdated:Date.now()});n(t),d(t);},onUpdateRecord:(e,t)=>{let r=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},o),{records:o.records.map(a=>a.id===e?chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a(chunkRFPLZDIO_js.a({},a),t),{updatedAt:Date.now()}):a),lastUpdated:Date.now()});n(r),d(r);},onArchiveRecord:e=>{let t=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},o),{records:o.records.map(r=>r.id===e?chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},r),{status:"archived",updatedAt:Date.now()}):r),lastUpdated:Date.now()});n(t),d(t);},classNames:u,unstyled:p})};var G=u=>{var p=u,{input:c}=p,s=chunkRFPLZDIO_js.c(p,["input"]);let o=chunkQPRYXVH2_js.a(c);return jsxRuntime.jsx(chunkNUWVPRNI_js.a,chunkRFPLZDIO_js.a({report:o},s))};Object.defineProperty(exports,"NDPRPrivacyPolicy",{enumerable:true,get:function(){return chunk5IOC3VAW_js.a}});Object.defineProperty(exports,"NDPRConsent",{enumerable:true,get:function(){return chunkV3RYHNHN_js.a}});Object.defineProperty(exports,"NDPRSubjectRights",{enumerable:true,get:function(){return chunkRXZFYBUJ_js.a}});exports.NDPRBreachReport=I;exports.NDPRComplianceDashboard=G;exports.NDPRCrossBorder=W;exports.NDPRDPIA=_;exports.NDPRLawfulBasis=F;exports.NDPRROPA=V;
package/dist/presets.mjs CHANGED
@@ -1,2 +1,2 @@
1
1
  "use client";
2
- export{a as NDPRPrivacyPolicy}from'./chunk-RV2VMWZJ.mjs';import'./chunk-BNHQFZHL.mjs';export{a as NDPRConsent}from'./chunk-LTPSN2SU.mjs';export{a as NDPRSubjectRights}from'./chunk-SJRIOZ4K.mjs';import {a as a$7}from'./chunk-ZIZL37BG.mjs';import {a as a$2}from'./chunk-COD3RMTL.mjs';import {a as a$4}from'./chunk-GTYXVAJX.mjs';import {a as a$5}from'./chunk-EXEXUAF6.mjs';import'./chunk-O6CUBNXK.mjs';import'./chunk-AOHKVFAS.mjs';import {a as a$6}from'./chunk-EFIBHKQE.mjs';import'./chunk-RMQ7OLNY.mjs';import'./chunk-LWIKDDSU.mjs';import'./chunk-7BJXI2HI.mjs';import'./chunk-XP5PL6K7.mjs';import'./chunk-BFAX7JQA.mjs';import'./chunk-YTU4FNM2.mjs';import'./chunk-XJO4DH3L.mjs';import {a as a$1}from'./chunk-ZQZJNKVB.mjs';import {a}from'./chunk-ZHFLBL63.mjs';import'./chunk-EWVK45Z3.mjs';import'./chunk-ITCY2Z66.mjs';import'./chunk-SFGW37LE.mjs';import'./chunk-DBZSN4WP.mjs';import {b,a as a$3,d,c}from'./chunk-ZJYULEER.mjs';import {jsx}from'react/jsx-runtime';import {useState,useEffect}from'react';var L=[{id:"unauthorized_access",name:"Unauthorized Access",description:"Unauthorized access to personal data",defaultSeverity:"high"},{id:"data_loss",name:"Data Loss",description:"Loss of personal data",defaultSeverity:"high"},{id:"data_theft",name:"Data Theft",description:"Theft of personal data",defaultSeverity:"critical"},{id:"system_breach",name:"System Breach",description:"Breach of system containing personal data",defaultSeverity:"critical"},{id:"accidental_disclosure",name:"Accidental Disclosure",description:"Unintended disclosure of personal data",defaultSeverity:"medium"}],I=({categories:c=L,adapter:s,classNames:u,unstyled:p,onSubmit:o=()=>{}})=>jsx(a,{categories:c,onSubmit:d=>{s&&s.save(d),o(d);},classNames:u,unstyled:p});var k=[{id:"project_overview",title:"Project Overview",description:"Provide basic details about the processing activity being assessed.",order:0,questions:[{id:"project_name",text:"What is the name of the project or processing activity?",type:"text",required:true},{id:"project_description",text:"Describe the nature and purpose of the processing.",guidance:"Include what personal data will be collected, why it is needed, and how it will be used.",type:"textarea",required:true},{id:"data_controller",text:"Who is the data controller responsible for this processing?",type:"text",required:true}]},{id:"necessity",title:"Necessity & Proportionality",description:"Assess whether the processing is necessary and proportionate to the purposes.",order:1,questions:[{id:"lawful_basis",text:"What is the lawful basis for processing under the NDPA 2023?",type:"select",required:true,options:[{value:"consent",label:"Consent (Section 25(1)(a))"},{value:"contract",label:"Contract (Section 25(1)(b))"},{value:"legal_obligation",label:"Legal Obligation (Section 25(1)(c))"},{value:"vital_interests",label:"Vital Interests (Section 25(1)(d))"},{value:"public_task",label:"Public Task (Section 25(1)(e))"},{value:"legitimate_interests",label:"Legitimate Interests (Section 25(1)(f))"}]},{id:"data_minimisation",text:"Is the processing limited to what is necessary for the specified purpose?",type:"radio",required:true,options:[{value:"yes",label:"Yes \u2014 only minimum data is collected",riskLevel:"low"},{value:"partial",label:"Partially \u2014 some additional data may be collected",riskLevel:"medium"},{value:"no",label:"No \u2014 more data is collected than strictly necessary",riskLevel:"high"}]}]},{id:"risk_identification",title:"Risk Identification",description:"Identify and assess risks to data subjects arising from the processing.",order:2,questions:[{id:"sensitive_data",text:"Does the processing involve sensitive personal data (e.g., health, biometric, financial, children's data)?",type:"radio",required:true,options:[{value:"no",label:"No sensitive data",riskLevel:"low"},{value:"yes_protected",label:"Yes, with appropriate safeguards",riskLevel:"medium"},{value:"yes_unprotected",label:"Yes, without adequate safeguards",riskLevel:"high"}]},{id:"scale",text:"What is the scale of processing?",type:"radio",required:true,options:[{value:"small",label:"Small scale (fewer than 1,000 individuals)",riskLevel:"low"},{value:"medium",label:"Medium scale (1,000 to 100,000 individuals)",riskLevel:"medium"},{value:"large",label:"Large scale (over 100,000 individuals)",riskLevel:"high"}]},{id:"cross_border",text:"Will data be transferred outside Nigeria?",type:"radio",required:true,options:[{value:"no",label:"No international transfers",riskLevel:"low"},{value:"adequate",label:"Yes, to countries with adequate protection",riskLevel:"medium"},{value:"inadequate",label:"Yes, to countries without adequate protection",riskLevel:"high"}]}]},{id:"mitigation",title:"Risk Mitigation & Measures",description:"Document the measures taken to address identified risks.",order:3,questions:[{id:"security_measures",text:"What technical and organisational security measures are in place?",guidance:"Include encryption, access controls, pseudonymisation, staff training, etc.",type:"textarea",required:true},{id:"retention_period",text:"What is the data retention period?",guidance:"Specify how long data will be kept and the criteria used to determine this.",type:"text",required:true},{id:"dpo_consulted",text:"Has the Data Protection Officer (DPO) been consulted on this assessment?",type:"radio",required:false,options:[{value:"yes",label:"Yes",riskLevel:"low"},{value:"no",label:"No",riskLevel:"medium"},{value:"na",label:"Not applicable \u2014 no DPO appointed",riskLevel:"medium"}]}]}],_=({sections:c=k,adapter:s,classNames:u,unstyled:p,onComplete:o=()=>{}})=>{let[n,d]=useState({}),[m,f]=useState(0),P=(a,C)=>{d(S=>b(a$3({},S),{[a]:C}));},e=()=>{m<c.length-1?f(a=>a+1):(s&&s.save(n),o(n));},t=()=>{m>0&&f(a=>a-1);},r=Math.round((m+1)/c.length*100);return jsx(a$1,{sections:c,answers:n,onAnswerChange:P,currentSectionIndex:m,onNextSection:e,onPrevSection:t,progress:r,classNames:u,unstyled:p})};var F=({initialActivities:c=[],adapter:s,classNames:u,unstyled:p})=>{let[o,n]=useState(()=>{if(s){let e=s.load();if(e&&!(e instanceof Promise))return e}return c}),d=e=>{s&&s.save(e);};return jsx(a$2,{activities:o,onAddActivity:e=>{let t=Date.now(),r=b(a$3({},e),{id:`activity-${t}`,createdAt:t,updatedAt:t}),a=[...o,r];n(a),d(a);},onUpdateActivity:(e,t)=>{let r=o.map(a=>a.id===e?b(a$3(a$3({},a),t),{updatedAt:Date.now()}):a);n(r),d(r);},onArchiveActivity:e=>{let t=o.map(r=>r.id===e?b(a$3({},r),{status:"inactive",updatedAt:Date.now()}):r);n(t),d(t);},classNames:u,unstyled:p})};var W=({initialTransfers:c=[],adapter:s,classNames:u,unstyled:p})=>{let[o,n]=useState(()=>{if(s){let e=s.load();if(e&&!(e instanceof Promise))return e}return c}),d=e=>{s&&s.save(e);};return jsx(a$4,{transfers:o,onAddTransfer:e=>{let t=Date.now(),r=b(a$3({},e),{id:`transfer-${t}`,createdAt:t,updatedAt:t}),a=[...o,r];n(a),d(a);},onUpdateTransfer:(e,t)=>{let r=o.map(a=>a.id===e?b(a$3(a$3({},a),t),{updatedAt:Date.now()}):a);n(r),d(r);},onRemoveTransfer:e=>{let t=o.filter(r=>r.id!==e);n(t),d(t);},classNames:u,unstyled:p})};var j={id:"ndpr-ropa-default",organizationName:"Your Organisation",organizationContact:"",organizationAddress:"",records:[],lastUpdated:Date.now(),version:"1.0"},V=({initialData:c,adapter:s,classNames:u,unstyled:p})=>{let[o,n]=useState(c!=null?c:j);useEffect(()=>{if(!s)return;let e=false;return d(null,null,function*(){let r=yield s.load();!e&&r&&n(r);}),()=>{e=true;}},[s]);let d$1=e=>{s&&s.save(e);};return jsx(a$5,{ropa:o,onAddRecord:e=>{let t=b(a$3({},o),{records:[...o.records,e],lastUpdated:Date.now()});n(t),d$1(t);},onUpdateRecord:(e,t)=>{let r=b(a$3({},o),{records:o.records.map(a=>a.id===e?b(a$3(a$3({},a),t),{updatedAt:Date.now()}):a),lastUpdated:Date.now()});n(r),d$1(r);},onArchiveRecord:e=>{let t=b(a$3({},o),{records:o.records.map(r=>r.id===e?b(a$3({},r),{status:"archived",updatedAt:Date.now()}):r),lastUpdated:Date.now()});n(t),d$1(t);},classNames:u,unstyled:p})};var G=u=>{var p=u,{input:c$1}=p,s=c(p,["input"]);let o=a$6(c$1);return jsx(a$7,a$3({report:o},s))};export{I as NDPRBreachReport,G as NDPRComplianceDashboard,W as NDPRCrossBorder,_ as NDPRDPIA,F as NDPRLawfulBasis,V as NDPRROPA};
2
+ export{a as NDPRPrivacyPolicy}from'./chunk-R7545FP4.mjs';import'./chunk-ATFUSHC2.mjs';export{a as NDPRConsent}from'./chunk-LTPSN2SU.mjs';export{a as NDPRSubjectRights}from'./chunk-SJRIOZ4K.mjs';import {a as a$7}from'./chunk-ZIZL37BG.mjs';import {a as a$2}from'./chunk-COD3RMTL.mjs';import {a as a$4}from'./chunk-GTYXVAJX.mjs';import {a as a$5}from'./chunk-EXEXUAF6.mjs';import'./chunk-UKLU6BQF.mjs';import'./chunk-2MIQXECH.mjs';import'./chunk-AOHKVFAS.mjs';import {a as a$6}from'./chunk-EFIBHKQE.mjs';import'./chunk-RMQ7OLNY.mjs';import'./chunk-LWIKDDSU.mjs';import'./chunk-7BJXI2HI.mjs';import'./chunk-XP5PL6K7.mjs';import'./chunk-BFAX7JQA.mjs';import'./chunk-YTU4FNM2.mjs';import'./chunk-XJO4DH3L.mjs';import {a as a$1}from'./chunk-ZQZJNKVB.mjs';import {a}from'./chunk-ZHFLBL63.mjs';import'./chunk-EWVK45Z3.mjs';import'./chunk-ITCY2Z66.mjs';import'./chunk-SFGW37LE.mjs';import'./chunk-DBZSN4WP.mjs';import {b,a as a$3,d,c}from'./chunk-ZJYULEER.mjs';import {jsx}from'react/jsx-runtime';import {useState,useEffect}from'react';var L=[{id:"unauthorized_access",name:"Unauthorized Access",description:"Unauthorized access to personal data",defaultSeverity:"high"},{id:"data_loss",name:"Data Loss",description:"Loss of personal data",defaultSeverity:"high"},{id:"data_theft",name:"Data Theft",description:"Theft of personal data",defaultSeverity:"critical"},{id:"system_breach",name:"System Breach",description:"Breach of system containing personal data",defaultSeverity:"critical"},{id:"accidental_disclosure",name:"Accidental Disclosure",description:"Unintended disclosure of personal data",defaultSeverity:"medium"}],I=({categories:c=L,adapter:s,classNames:u,unstyled:p,onSubmit:o=()=>{}})=>jsx(a,{categories:c,onSubmit:d=>{s&&s.save(d),o(d);},classNames:u,unstyled:p});var k=[{id:"project_overview",title:"Project Overview",description:"Provide basic details about the processing activity being assessed.",order:0,questions:[{id:"project_name",text:"What is the name of the project or processing activity?",type:"text",required:true},{id:"project_description",text:"Describe the nature and purpose of the processing.",guidance:"Include what personal data will be collected, why it is needed, and how it will be used.",type:"textarea",required:true},{id:"data_controller",text:"Who is the data controller responsible for this processing?",type:"text",required:true}]},{id:"necessity",title:"Necessity & Proportionality",description:"Assess whether the processing is necessary and proportionate to the purposes.",order:1,questions:[{id:"lawful_basis",text:"What is the lawful basis for processing under the NDPA 2023?",type:"select",required:true,options:[{value:"consent",label:"Consent (Section 25(1)(a))"},{value:"contract",label:"Contract (Section 25(1)(b))"},{value:"legal_obligation",label:"Legal Obligation (Section 25(1)(c))"},{value:"vital_interests",label:"Vital Interests (Section 25(1)(d))"},{value:"public_task",label:"Public Task (Section 25(1)(e))"},{value:"legitimate_interests",label:"Legitimate Interests (Section 25(1)(f))"}]},{id:"data_minimisation",text:"Is the processing limited to what is necessary for the specified purpose?",type:"radio",required:true,options:[{value:"yes",label:"Yes \u2014 only minimum data is collected",riskLevel:"low"},{value:"partial",label:"Partially \u2014 some additional data may be collected",riskLevel:"medium"},{value:"no",label:"No \u2014 more data is collected than strictly necessary",riskLevel:"high"}]}]},{id:"risk_identification",title:"Risk Identification",description:"Identify and assess risks to data subjects arising from the processing.",order:2,questions:[{id:"sensitive_data",text:"Does the processing involve sensitive personal data (e.g., health, biometric, financial, children's data)?",type:"radio",required:true,options:[{value:"no",label:"No sensitive data",riskLevel:"low"},{value:"yes_protected",label:"Yes, with appropriate safeguards",riskLevel:"medium"},{value:"yes_unprotected",label:"Yes, without adequate safeguards",riskLevel:"high"}]},{id:"scale",text:"What is the scale of processing?",type:"radio",required:true,options:[{value:"small",label:"Small scale (fewer than 1,000 individuals)",riskLevel:"low"},{value:"medium",label:"Medium scale (1,000 to 100,000 individuals)",riskLevel:"medium"},{value:"large",label:"Large scale (over 100,000 individuals)",riskLevel:"high"}]},{id:"cross_border",text:"Will data be transferred outside Nigeria?",type:"radio",required:true,options:[{value:"no",label:"No international transfers",riskLevel:"low"},{value:"adequate",label:"Yes, to countries with adequate protection",riskLevel:"medium"},{value:"inadequate",label:"Yes, to countries without adequate protection",riskLevel:"high"}]}]},{id:"mitigation",title:"Risk Mitigation & Measures",description:"Document the measures taken to address identified risks.",order:3,questions:[{id:"security_measures",text:"What technical and organisational security measures are in place?",guidance:"Include encryption, access controls, pseudonymisation, staff training, etc.",type:"textarea",required:true},{id:"retention_period",text:"What is the data retention period?",guidance:"Specify how long data will be kept and the criteria used to determine this.",type:"text",required:true},{id:"dpo_consulted",text:"Has the Data Protection Officer (DPO) been consulted on this assessment?",type:"radio",required:false,options:[{value:"yes",label:"Yes",riskLevel:"low"},{value:"no",label:"No",riskLevel:"medium"},{value:"na",label:"Not applicable \u2014 no DPO appointed",riskLevel:"medium"}]}]}],_=({sections:c=k,adapter:s,classNames:u,unstyled:p,onComplete:o=()=>{}})=>{let[n,d]=useState({}),[m,f]=useState(0),P=(a,C)=>{d(S=>b(a$3({},S),{[a]:C}));},e=()=>{m<c.length-1?f(a=>a+1):(s&&s.save(n),o(n));},t=()=>{m>0&&f(a=>a-1);},r=Math.round((m+1)/c.length*100);return jsx(a$1,{sections:c,answers:n,onAnswerChange:P,currentSectionIndex:m,onNextSection:e,onPrevSection:t,progress:r,classNames:u,unstyled:p})};var F=({initialActivities:c=[],adapter:s,classNames:u,unstyled:p})=>{let[o,n]=useState(()=>{if(s){let e=s.load();if(e&&!(e instanceof Promise))return e}return c}),d=e=>{s&&s.save(e);};return jsx(a$2,{activities:o,onAddActivity:e=>{let t=Date.now(),r=b(a$3({},e),{id:`activity-${t}`,createdAt:t,updatedAt:t}),a=[...o,r];n(a),d(a);},onUpdateActivity:(e,t)=>{let r=o.map(a=>a.id===e?b(a$3(a$3({},a),t),{updatedAt:Date.now()}):a);n(r),d(r);},onArchiveActivity:e=>{let t=o.map(r=>r.id===e?b(a$3({},r),{status:"inactive",updatedAt:Date.now()}):r);n(t),d(t);},classNames:u,unstyled:p})};var W=({initialTransfers:c=[],adapter:s,classNames:u,unstyled:p})=>{let[o,n]=useState(()=>{if(s){let e=s.load();if(e&&!(e instanceof Promise))return e}return c}),d=e=>{s&&s.save(e);};return jsx(a$4,{transfers:o,onAddTransfer:e=>{let t=Date.now(),r=b(a$3({},e),{id:`transfer-${t}`,createdAt:t,updatedAt:t}),a=[...o,r];n(a),d(a);},onUpdateTransfer:(e,t)=>{let r=o.map(a=>a.id===e?b(a$3(a$3({},a),t),{updatedAt:Date.now()}):a);n(r),d(r);},onRemoveTransfer:e=>{let t=o.filter(r=>r.id!==e);n(t),d(t);},classNames:u,unstyled:p})};var j={id:"ndpr-ropa-default",organizationName:"Your Organisation",organizationContact:"",organizationAddress:"",records:[],lastUpdated:Date.now(),version:"1.0"},V=({initialData:c,adapter:s,classNames:u,unstyled:p})=>{let[o,n]=useState(c!=null?c:j);useEffect(()=>{if(!s)return;let e=false;return d(null,null,function*(){let r=yield s.load();!e&&r&&n(r);}),()=>{e=true;}},[s]);let d$1=e=>{s&&s.save(e);};return jsx(a$5,{ropa:o,onAddRecord:e=>{let t=b(a$3({},o),{records:[...o.records,e],lastUpdated:Date.now()});n(t),d$1(t);},onUpdateRecord:(e,t)=>{let r=b(a$3({},o),{records:o.records.map(a=>a.id===e?b(a$3(a$3({},a),t),{updatedAt:Date.now()}):a),lastUpdated:Date.now()});n(r),d$1(r);},onArchiveRecord:e=>{let t=b(a$3({},o),{records:o.records.map(r=>r.id===e?b(a$3({},r),{status:"archived",updatedAt:Date.now()}):r),lastUpdated:Date.now()});n(t),d$1(t);},classNames:u,unstyled:p})};var G=u=>{var p=u,{input:c$1}=p,s=c(p,["input"]);let o=a$6(c$1);return jsx(a$7,a$3({report:o},s))};export{I as NDPRBreachReport,G as NDPRComplianceDashboard,W as NDPRCrossBorder,_ as NDPRDPIA,F as NDPRLawfulBasis,V as NDPRROPA};
package/dist/server.d.mts CHANGED
@@ -1532,6 +1532,18 @@ export declare interface NotificationRequirement {
1532
1532
  nitdaNotificationDeadline?: number;
1533
1533
  }
1534
1534
 
1535
+ /**
1536
+ * Static metadata for every template — useful for picker UIs that need
1537
+ * to list available templates with a one-line description.
1538
+ */
1539
+ export declare const ORG_POLICY_TEMPLATE_REGISTRY: Record<OrgPolicyTemplateId, {
1540
+ id: OrgPolicyTemplateId;
1541
+ label: string;
1542
+ description: string;
1543
+ /** Best-fit org examples to show in the picker. */
1544
+ examples: readonly string[];
1545
+ }>;
1546
+
1535
1547
  /**
1536
1548
  * Represents organization information for a privacy policy
1537
1549
  */
@@ -1556,6 +1568,48 @@ export declare interface OrganizationInfo {
1556
1568
  ndpcRegistrationNumber?: string;
1557
1569
  }
1558
1570
 
1571
+ /**
1572
+ * Org-specific privacy-policy templates — pre-filled `TemplateContext`
1573
+ * factories for the most common Nigerian app shapes.
1574
+ *
1575
+ * Each template returns a fully-populated `TemplateContext` with:
1576
+ * - industry set to the matching `Industry` value
1577
+ * - the data categories the sector typically collects (selected: true)
1578
+ * - the processing purposes that match the business model
1579
+ * - sensitive-data / children / cross-border / automated-decisions flags
1580
+ * set to the defaults that org type usually needs (a school will have
1581
+ * children data, a hospital will have sensitive data, etc.)
1582
+ *
1583
+ * Templates are guidance starters. The wizard still walks the user through
1584
+ * every step — they can flip any flag, add/remove categories, or rewrite
1585
+ * any section before the policy is finalised. The legal-notice footer the
1586
+ * toolkit ships everywhere applies to the generated output.
1587
+ *
1588
+ * @example
1589
+ * import { templateContextFor } from '@tantainnovative/ndpr-toolkit/server';
1590
+ * const ctx = templateContextFor('ecommerce', { orgName: 'Acme NG' });
1591
+ * const draft = assemblePolicy(ctx);
1592
+ */
1593
+
1594
+ /** Identifiers for the bundled org templates. */
1595
+ export declare type OrgPolicyTemplateId = 'saas' | 'ecommerce' | 'school' | 'healthcare' | 'procurement';
1596
+
1597
+ /** Optional overrides applied on top of a template's defaults. */
1598
+ export declare interface OrgPolicyTemplateOverrides {
1599
+ /** Organisation name (e.g. "Acme Nigeria Ltd"). Default: empty. */
1600
+ orgName?: string;
1601
+ /** Public website URL. */
1602
+ website?: string;
1603
+ /** Privacy contact email. */
1604
+ privacyEmail?: string;
1605
+ /** Postal address. */
1606
+ address?: string;
1607
+ /** DPO name. Required for DCPMI under NDPA Section 32. */
1608
+ dpoName?: string;
1609
+ /** DPO email. Required for the NDPC breach-notification contact. */
1610
+ dpoEmail?: string;
1611
+ }
1612
+
1559
1613
  /** Organisation size tiers — affects complexity of generated language. */
1560
1614
  export declare type OrgSize = 'startup' | 'midsize' | 'enterprise';
1561
1615
 
@@ -2126,6 +2180,22 @@ export declare interface TemplateContext {
2126
2180
  thirdPartyProcessors: ThirdPartyProcessor[];
2127
2181
  }
2128
2182
 
2183
+ /**
2184
+ * Returns a fresh `TemplateContext` pre-filled for the given org type.
2185
+ * Pass `overrides` to set organisation details (name, DPO, etc.) inline.
2186
+ *
2187
+ * Calling without arguments throws — pass a known template id.
2188
+ *
2189
+ * @example
2190
+ * const ctx = templateContextFor('healthcare', {
2191
+ * orgName: 'Lagos Heart Centre',
2192
+ * dpoEmail: 'dpo@lhc.ng',
2193
+ * });
2194
+ */
2195
+ declare function templateContextFor(id: OrgPolicyTemplateId, overrides?: OrgPolicyTemplateOverrides): TemplateContext;
2196
+ export { templateContextFor as createOrgTemplate }
2197
+ export { templateContextFor }
2198
+
2129
2199
  /** A third-party entity that processes data on behalf of the organisation. */
2130
2200
  export declare interface ThirdPartyProcessor {
2131
2201
  /** Name of the third party. */