@tantainnovative/ndpr-toolkit 4.1.0 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +67 -0
- package/dist/chunk-4FXRJH37.js +1 -0
- package/dist/{chunk-UJGNW6CH.js → chunk-ASEUTU45.js} +1 -1
- package/dist/chunk-BRJKIF7E.mjs +1 -0
- package/dist/chunk-CSE36REY.js +6 -0
- package/dist/chunk-DKLJ5DYN.js +1 -0
- package/dist/chunk-FRMVSG4N.mjs +1 -0
- package/dist/chunk-MAD7QYRK.js +1 -0
- package/dist/chunk-NBOJ2KGN.mjs +1 -0
- package/dist/chunk-PQ5IPUJN.mjs +1 -0
- package/dist/chunk-QKXGVT2Q.js +1 -0
- package/dist/chunk-R2ZZMATR.js +1 -0
- package/dist/chunk-R3ZKV2J7.mjs +1 -0
- package/dist/chunk-RRVML7CU.mjs +1 -0
- package/dist/{chunk-6H6IXTHA.mjs → chunk-SBSYHCPK.mjs} +1 -1
- package/dist/chunk-TLIHFGIJ.js +1 -0
- package/dist/{chunk-O4ATGGVK.js → chunk-TVA6D6S4.js} +1 -1
- package/dist/chunk-WPH6CJDL.mjs +6 -0
- package/dist/{chunk-6OPGI27L.mjs → chunk-ZSRO4L3C.mjs} +1 -1
- package/dist/consent.d.mts +59 -21
- package/dist/consent.d.ts +59 -21
- package/dist/consent.js +1 -1
- package/dist/consent.mjs +1 -1
- package/dist/core.d.mts +116 -74
- package/dist/core.d.ts +116 -74
- package/dist/core.js +1 -1
- package/dist/core.mjs +1 -1
- package/dist/cross-border.d.mts +4 -27
- package/dist/cross-border.d.ts +4 -27
- package/dist/cross-border.js +1 -1
- package/dist/cross-border.mjs +1 -1
- package/dist/dsr.d.mts +86 -57
- package/dist/dsr.d.ts +86 -57
- package/dist/dsr.js +1 -1
- package/dist/dsr.mjs +1 -1
- package/dist/headless.d.mts +20 -27
- package/dist/headless.d.ts +20 -27
- package/dist/headless.js +1 -1
- package/dist/headless.mjs +1 -1
- package/dist/hooks.d.mts +20 -27
- package/dist/hooks.d.ts +20 -27
- package/dist/hooks.js +1 -1
- package/dist/hooks.mjs +1 -1
- package/dist/index.d.mts +37 -202
- package/dist/index.d.ts +37 -202
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/lawful-basis.d.mts +3 -24
- package/dist/lawful-basis.d.ts +3 -24
- package/dist/lawful-basis.js +1 -1
- package/dist/lawful-basis.mjs +1 -1
- package/dist/presets.d.mts +1 -9
- package/dist/presets.d.ts +1 -9
- package/dist/presets.js +1 -1
- package/dist/presets.mjs +1 -1
- package/dist/ropa-lite.d.mts +2 -11
- package/dist/ropa-lite.d.ts +2 -11
- package/dist/ropa-lite.js +1 -1
- package/dist/ropa-lite.mjs +1 -1
- package/dist/ropa.d.mts +10 -52
- package/dist/ropa.d.ts +10 -52
- package/dist/ropa.js +1 -1
- package/dist/ropa.mjs +1 -1
- package/dist/server.d.mts +20 -100
- package/dist/server.d.ts +20 -100
- package/dist/server.js +1 -1
- package/dist/server.mjs +1 -1
- package/package.json +1 -1
- package/dist/chunk-3APT25XO.mjs +0 -1
- package/dist/chunk-45D7AMB3.js +0 -1
- package/dist/chunk-65J4P5ID.js +0 -1
- package/dist/chunk-7Z7NURIA.mjs +0 -1
- package/dist/chunk-D3HHDWBR.js +0 -1
- package/dist/chunk-DSIIEUAD.mjs +0 -1
- package/dist/chunk-H2FDWK4F.js +0 -6
- package/dist/chunk-HLFS3NXG.js +0 -1
- package/dist/chunk-JGY65SHX.mjs +0 -1
- package/dist/chunk-NI54X543.mjs +0 -1
- package/dist/chunk-P5MPUC5F.js +0 -1
- package/dist/chunk-ROOUYQD4.js +0 -1
- package/dist/chunk-UTXDZDYF.mjs +0 -6
- package/dist/chunk-W6VVLHRQ.mjs +0 -1
package/dist/consent.d.mts
CHANGED
|
@@ -213,7 +213,7 @@ declare interface ConsentContextValue {
|
|
|
213
213
|
rejectAll: () => void;
|
|
214
214
|
shouldShowBanner: boolean;
|
|
215
215
|
isValid: boolean;
|
|
216
|
-
validationErrors:
|
|
216
|
+
validationErrors: StructuredValidationError[];
|
|
217
217
|
resetConsent: () => void;
|
|
218
218
|
isLoading: boolean;
|
|
219
219
|
}
|
|
@@ -548,6 +548,30 @@ export declare interface StorageAdapter<T = unknown> {
|
|
|
548
548
|
remove(): void | Promise<void>;
|
|
549
549
|
}
|
|
550
550
|
|
|
551
|
+
/**
|
|
552
|
+
* Single structured validation error with a stable, locale-independent
|
|
553
|
+
* `code` consumers can switch on programmatically.
|
|
554
|
+
*/
|
|
555
|
+
export declare interface StructuredValidationError {
|
|
556
|
+
/** Dot-path of the offending field (e.g. `'timestamp'`, `'dataSubject.email'`, `'options[0].purpose'`). */
|
|
557
|
+
field: string;
|
|
558
|
+
/** Stable, snake_case error code — safe to switch on across locales. */
|
|
559
|
+
code: string;
|
|
560
|
+
/** Human-readable English message — informational only; do not regex-match. */
|
|
561
|
+
message: string;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Result of a structured validator. `errors` is an array (one entry per
|
|
566
|
+
* failed rule). `data` is the narrowed, typed payload, only populated on
|
|
567
|
+
* `valid: true`.
|
|
568
|
+
*/
|
|
569
|
+
export declare interface StructuredValidationResult<T> {
|
|
570
|
+
valid: boolean;
|
|
571
|
+
errors: StructuredValidationError[];
|
|
572
|
+
data?: T;
|
|
573
|
+
}
|
|
574
|
+
|
|
551
575
|
/**
|
|
552
576
|
* Hook for managing user consent in compliance with the NDPA.
|
|
553
577
|
*
|
|
@@ -632,9 +656,10 @@ declare interface UseConsentReturn {
|
|
|
632
656
|
*/
|
|
633
657
|
isValid: boolean;
|
|
634
658
|
/**
|
|
635
|
-
* Validation errors (if any)
|
|
659
|
+
* Validation errors (if any). Each entry is a structured `{ field, code,
|
|
660
|
+
* message }` so consumers can switch on `code` across locales.
|
|
636
661
|
*/
|
|
637
|
-
validationErrors:
|
|
662
|
+
validationErrors: StructuredValidationError[];
|
|
638
663
|
/**
|
|
639
664
|
* Reset consent settings (clear from storage)
|
|
640
665
|
*/
|
|
@@ -646,27 +671,40 @@ declare interface UseConsentReturn {
|
|
|
646
671
|
}
|
|
647
672
|
|
|
648
673
|
/**
|
|
649
|
-
* Validates consent
|
|
650
|
-
*
|
|
651
|
-
*
|
|
652
|
-
*
|
|
674
|
+
* Validates consent options against NDPA Section 26 requirements. Each option
|
|
675
|
+
* is checked for a non-empty `purpose`. Failing options are reported with
|
|
676
|
+
* `field: 'options[i].purpose'` so consumers can map errors back to the
|
|
677
|
+
* originating option index.
|
|
678
|
+
*
|
|
679
|
+
* Codes emitted:
|
|
680
|
+
* - `options_required` — empty / missing options array
|
|
681
|
+
* - `purpose_required` — single option missing a purpose
|
|
653
682
|
*/
|
|
654
|
-
export declare function
|
|
655
|
-
valid: boolean;
|
|
656
|
-
errors: string[];
|
|
657
|
-
};
|
|
683
|
+
export declare function validateConsentOptionsStructured(options: ConsentOption[]): StructuredValidationResult<ConsentOption[]>;
|
|
658
684
|
|
|
659
685
|
/**
|
|
660
|
-
* Validates
|
|
661
|
-
*
|
|
662
|
-
*
|
|
663
|
-
*
|
|
664
|
-
*
|
|
665
|
-
*
|
|
686
|
+
* Validates consent settings against NDPA requirements. Returns structured
|
|
687
|
+
* `{ field, code, message }[]` errors so consumers can switch on `code`
|
|
688
|
+
* across locales without regex-matching English strings.
|
|
689
|
+
*
|
|
690
|
+
* Codes emitted:
|
|
691
|
+
* - `consents_required`
|
|
692
|
+
* - `timestamp_required`
|
|
693
|
+
* - `timestamp_invalid`
|
|
694
|
+
* - `version_required`
|
|
695
|
+
* - `method_required`
|
|
696
|
+
* - `has_interacted_required`
|
|
697
|
+
* - `consent_stale`
|
|
698
|
+
*
|
|
699
|
+
* @example
|
|
700
|
+
* ```ts
|
|
701
|
+
* const { valid, errors, data } = validateConsentStructured(settings);
|
|
702
|
+
* if (!valid) {
|
|
703
|
+
* const stale = errors.find((e) => e.code === 'consent_stale');
|
|
704
|
+
* if (stale) showRefreshBanner();
|
|
705
|
+
* }
|
|
706
|
+
* ```
|
|
666
707
|
*/
|
|
667
|
-
export declare function
|
|
668
|
-
valid: boolean;
|
|
669
|
-
errors: string[];
|
|
670
|
-
};
|
|
708
|
+
export declare function validateConsentStructured(settings: ConsentSettings): StructuredValidationResult<ConsentSettings>;
|
|
671
709
|
|
|
672
710
|
export { }
|
package/dist/consent.d.ts
CHANGED
|
@@ -213,7 +213,7 @@ declare interface ConsentContextValue {
|
|
|
213
213
|
rejectAll: () => void;
|
|
214
214
|
shouldShowBanner: boolean;
|
|
215
215
|
isValid: boolean;
|
|
216
|
-
validationErrors:
|
|
216
|
+
validationErrors: StructuredValidationError[];
|
|
217
217
|
resetConsent: () => void;
|
|
218
218
|
isLoading: boolean;
|
|
219
219
|
}
|
|
@@ -548,6 +548,30 @@ export declare interface StorageAdapter<T = unknown> {
|
|
|
548
548
|
remove(): void | Promise<void>;
|
|
549
549
|
}
|
|
550
550
|
|
|
551
|
+
/**
|
|
552
|
+
* Single structured validation error with a stable, locale-independent
|
|
553
|
+
* `code` consumers can switch on programmatically.
|
|
554
|
+
*/
|
|
555
|
+
export declare interface StructuredValidationError {
|
|
556
|
+
/** Dot-path of the offending field (e.g. `'timestamp'`, `'dataSubject.email'`, `'options[0].purpose'`). */
|
|
557
|
+
field: string;
|
|
558
|
+
/** Stable, snake_case error code — safe to switch on across locales. */
|
|
559
|
+
code: string;
|
|
560
|
+
/** Human-readable English message — informational only; do not regex-match. */
|
|
561
|
+
message: string;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Result of a structured validator. `errors` is an array (one entry per
|
|
566
|
+
* failed rule). `data` is the narrowed, typed payload, only populated on
|
|
567
|
+
* `valid: true`.
|
|
568
|
+
*/
|
|
569
|
+
export declare interface StructuredValidationResult<T> {
|
|
570
|
+
valid: boolean;
|
|
571
|
+
errors: StructuredValidationError[];
|
|
572
|
+
data?: T;
|
|
573
|
+
}
|
|
574
|
+
|
|
551
575
|
/**
|
|
552
576
|
* Hook for managing user consent in compliance with the NDPA.
|
|
553
577
|
*
|
|
@@ -632,9 +656,10 @@ declare interface UseConsentReturn {
|
|
|
632
656
|
*/
|
|
633
657
|
isValid: boolean;
|
|
634
658
|
/**
|
|
635
|
-
* Validation errors (if any)
|
|
659
|
+
* Validation errors (if any). Each entry is a structured `{ field, code,
|
|
660
|
+
* message }` so consumers can switch on `code` across locales.
|
|
636
661
|
*/
|
|
637
|
-
validationErrors:
|
|
662
|
+
validationErrors: StructuredValidationError[];
|
|
638
663
|
/**
|
|
639
664
|
* Reset consent settings (clear from storage)
|
|
640
665
|
*/
|
|
@@ -646,27 +671,40 @@ declare interface UseConsentReturn {
|
|
|
646
671
|
}
|
|
647
672
|
|
|
648
673
|
/**
|
|
649
|
-
* Validates consent
|
|
650
|
-
*
|
|
651
|
-
*
|
|
652
|
-
*
|
|
674
|
+
* Validates consent options against NDPA Section 26 requirements. Each option
|
|
675
|
+
* is checked for a non-empty `purpose`. Failing options are reported with
|
|
676
|
+
* `field: 'options[i].purpose'` so consumers can map errors back to the
|
|
677
|
+
* originating option index.
|
|
678
|
+
*
|
|
679
|
+
* Codes emitted:
|
|
680
|
+
* - `options_required` — empty / missing options array
|
|
681
|
+
* - `purpose_required` — single option missing a purpose
|
|
653
682
|
*/
|
|
654
|
-
export declare function
|
|
655
|
-
valid: boolean;
|
|
656
|
-
errors: string[];
|
|
657
|
-
};
|
|
683
|
+
export declare function validateConsentOptionsStructured(options: ConsentOption[]): StructuredValidationResult<ConsentOption[]>;
|
|
658
684
|
|
|
659
685
|
/**
|
|
660
|
-
* Validates
|
|
661
|
-
*
|
|
662
|
-
*
|
|
663
|
-
*
|
|
664
|
-
*
|
|
665
|
-
*
|
|
686
|
+
* Validates consent settings against NDPA requirements. Returns structured
|
|
687
|
+
* `{ field, code, message }[]` errors so consumers can switch on `code`
|
|
688
|
+
* across locales without regex-matching English strings.
|
|
689
|
+
*
|
|
690
|
+
* Codes emitted:
|
|
691
|
+
* - `consents_required`
|
|
692
|
+
* - `timestamp_required`
|
|
693
|
+
* - `timestamp_invalid`
|
|
694
|
+
* - `version_required`
|
|
695
|
+
* - `method_required`
|
|
696
|
+
* - `has_interacted_required`
|
|
697
|
+
* - `consent_stale`
|
|
698
|
+
*
|
|
699
|
+
* @example
|
|
700
|
+
* ```ts
|
|
701
|
+
* const { valid, errors, data } = validateConsentStructured(settings);
|
|
702
|
+
* if (!valid) {
|
|
703
|
+
* const stale = errors.find((e) => e.code === 'consent_stale');
|
|
704
|
+
* if (stale) showRefreshBanner();
|
|
705
|
+
* }
|
|
706
|
+
* ```
|
|
666
707
|
*/
|
|
667
|
-
export declare function
|
|
668
|
-
valid: boolean;
|
|
669
|
-
errors: string[];
|
|
670
|
-
};
|
|
708
|
+
export declare function validateConsentStructured(settings: ConsentSettings): StructuredValidationResult<ConsentSettings>;
|
|
671
709
|
|
|
672
710
|
export { }
|
package/dist/consent.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
'use strict';var chunkSJDDNB6M_js=require('./chunk-SJDDNB6M.js'),chunk42UJFTII_js=require('./chunk-42UJFTII.js'),chunkZD2W3YU2_js=require('./chunk-ZD2W3YU2.js'),chunk3IA3KDII_js=require('./chunk-3IA3KDII.js'),
|
|
2
|
+
'use strict';var chunkSJDDNB6M_js=require('./chunk-SJDDNB6M.js'),chunk42UJFTII_js=require('./chunk-42UJFTII.js'),chunkZD2W3YU2_js=require('./chunk-ZD2W3YU2.js'),chunk3IA3KDII_js=require('./chunk-3IA3KDII.js'),chunkQKXGVT2Q_js=require('./chunk-QKXGVT2Q.js');require('./chunk-L2VO3MEJ.js'),require('./chunk-C2KEXHRX.js');var chunkDKLJ5DYN_js=require('./chunk-DKLJ5DYN.js'),chunkAME4HJR4_js=require('./chunk-AME4HJR4.js');require('./chunk-YDKWD6MQ.js'),require('./chunk-TTMGFC6C.js'),require('./chunk-VWED6UTN.js');var chunkRFPLZDIO_js=require('./chunk-RFPLZDIO.js'),react=require('react'),jsxRuntime=require('react/jsx-runtime');var v=react.createContext(null);function p(){let t=react.useContext(v);if(!t)throw new Error("Consent compound components must be wrapped in <Consent.Provider>. Example: <Consent.Provider options={...}><Consent.Banner /></Consent.Provider>");return t}var g=({options:t,adapter:n,version:s,onChange:r,children:c})=>{let d=chunkQKXGVT2Q_js.a({options:t,adapter:n,version:s,onChange:r}),o=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},d),{options:t});return jsxRuntime.jsx(v.Provider,{value:o,children:c})};var S=({classNames:t,unstyled:n})=>{let{options:s,settings:r}=p(),[c,d]=react.useState(()=>{let o={};return s.forEach(i=>{var a,_;o[i.id]=(_=(a=r==null?void 0:r.consents[i.id])!=null?a:i.defaultValue)!=null?_:false;}),o});return jsxRuntime.jsx("div",{className:chunkAME4HJR4_js.a("ndpr-consent-banner__options-list",t==null?void 0:t.root,n),"data-ndpr-component":"consent-option-list",children:s.map(o=>jsxRuntime.jsxs("div",{className:chunkAME4HJR4_js.a("ndpr-consent-banner__option",t==null?void 0:t.optionItem,n),children:[jsxRuntime.jsx("input",{id:`consent-${o.id}`,type:"checkbox",checked:c[o.id]||false,onChange:i=>d(a=>chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},a),{[o.id]:i.target.checked})),disabled:o.required,className:chunkAME4HJR4_js.a("ndpr-consent-banner__option-checkbox",t==null?void 0:t.optionCheckbox,n),"aria-label":o.label}),jsxRuntime.jsxs("div",{className:n?"":"ndpr-consent-banner__option-text",children:[jsxRuntime.jsxs("label",{htmlFor:`consent-${o.id}`,className:chunkAME4HJR4_js.a("ndpr-consent-banner__option-label",t==null?void 0:t.optionLabel,n),children:[o.label,o.required&&jsxRuntime.jsx("span",{className:n?"":"ndpr-consent-banner__required-marker",children:" *"})]}),jsxRuntime.jsx("p",{className:chunkAME4HJR4_js.a("ndpr-consent-banner__option-description",t==null?void 0:t.optionDescription,n),children:o.description})]})]},o.id))})};var P=({children:t,className:n,unstyled:s})=>{let{acceptAll:r}=p();return jsxRuntime.jsx("button",{onClick:r,className:chunkAME4HJR4_js.a("ndpr-consent-banner__button ndpr-consent-banner__button--primary",n,s),"data-ndpr-component":"consent-accept-button",children:t!=null?t:"Accept All"})};var R=({children:t,className:n,unstyled:s})=>{let{rejectAll:r}=p();return jsxRuntime.jsx("button",{onClick:r,className:chunkAME4HJR4_js.a("ndpr-consent-banner__button ndpr-consent-banner__button--secondary",n,s),"data-ndpr-component":"consent-reject-button",children:t!=null?t:"Reject All"})};var y=({children:t,className:n,unstyled:s,consents:r})=>{let{updateConsent:c,options:d}=p();return jsxRuntime.jsx("button",{onClick:()=>{if(r)c(r);else {let i={};d.forEach(a=>{i[a.id]=a.required||false;}),c(i);}},className:chunkAME4HJR4_js.a("ndpr-consent-banner__button ndpr-consent-banner__button--primary",n,s),"data-ndpr-component":"consent-save-button",children:t!=null?t:"Save Preferences"})};var I={Provider:g,OptionList:S,AcceptButton:P,RejectButton:R,SaveButton:y,Banner:chunkZD2W3YU2_js.a,Settings:chunk42UJFTII_js.a,Storage:chunkSJDDNB6M_js.a};Object.defineProperty(exports,"ConsentStorage",{enumerable:true,get:function(){return chunkSJDDNB6M_js.a}});Object.defineProperty(exports,"ConsentManager",{enumerable:true,get:function(){return chunk42UJFTII_js.a}});Object.defineProperty(exports,"ConsentBanner",{enumerable:true,get:function(){return chunkZD2W3YU2_js.a}});Object.defineProperty(exports,"appendAuditEntry",{enumerable:true,get:function(){return chunk3IA3KDII_js.c}});Object.defineProperty(exports,"createAuditEntry",{enumerable:true,get:function(){return chunk3IA3KDII_js.a}});Object.defineProperty(exports,"getAuditLog",{enumerable:true,get:function(){return chunk3IA3KDII_js.b}});Object.defineProperty(exports,"useConsent",{enumerable:true,get:function(){return chunkQKXGVT2Q_js.a}});Object.defineProperty(exports,"validateConsentOptionsStructured",{enumerable:true,get:function(){return chunkDKLJ5DYN_js.b}});Object.defineProperty(exports,"validateConsentStructured",{enumerable:true,get:function(){return chunkDKLJ5DYN_js.a}});Object.defineProperty(exports,"resolveClass",{enumerable:true,get:function(){return chunkAME4HJR4_js.a}});exports.Consent=I;exports.ConsentAcceptButton=P;exports.ConsentOptionList=S;exports.ConsentProvider=g;exports.ConsentRejectButton=R;exports.ConsentSaveButton=y;exports.useConsentCompound=p;
|
package/dist/consent.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {a}from'./chunk-XOH4WXOZ.mjs';export{a as ConsentStorage}from'./chunk-XOH4WXOZ.mjs';import {a as a$1}from'./chunk-BPMVJOHH.mjs';export{a as ConsentManager}from'./chunk-BPMVJOHH.mjs';import {a as a$2}from'./chunk-I2ZBMR7F.mjs';export{a as ConsentBanner}from'./chunk-I2ZBMR7F.mjs';export{c as appendAuditEntry,a as createAuditEntry,b as getAuditLog}from'./chunk-V7UFP6QU.mjs';import {a as a$3}from'./chunk-
|
|
2
|
+
import {a}from'./chunk-XOH4WXOZ.mjs';export{a as ConsentStorage}from'./chunk-XOH4WXOZ.mjs';import {a as a$1}from'./chunk-BPMVJOHH.mjs';export{a as ConsentManager}from'./chunk-BPMVJOHH.mjs';import {a as a$2}from'./chunk-I2ZBMR7F.mjs';export{a as ConsentBanner}from'./chunk-I2ZBMR7F.mjs';export{c as appendAuditEntry,a as createAuditEntry,b as getAuditLog}from'./chunk-V7UFP6QU.mjs';import {a as a$3}from'./chunk-PQ5IPUJN.mjs';export{a as useConsent}from'./chunk-PQ5IPUJN.mjs';import'./chunk-YTU4FNM2.mjs';import'./chunk-XC3DLYEG.mjs';export{b as validateConsentOptionsStructured,a as validateConsentStructured}from'./chunk-R3ZKV2J7.mjs';import {a as a$5}from'./chunk-SFGW37LE.mjs';export{a as resolveClass}from'./chunk-SFGW37LE.mjs';import'./chunk-FRQFU44F.mjs';import'./chunk-V5TZJJWU.mjs';import'./chunk-DBZSN4WP.mjs';import {b,a as a$4}from'./chunk-ZJYULEER.mjs';import {createContext,useContext,useState}from'react';import {jsx,jsxs}from'react/jsx-runtime';var v=createContext(null);function p(){let t=useContext(v);if(!t)throw new Error("Consent compound components must be wrapped in <Consent.Provider>. Example: <Consent.Provider options={...}><Consent.Banner /></Consent.Provider>");return t}var g=({options:t,adapter:n,version:s,onChange:r,children:c})=>{let d=a$3({options:t,adapter:n,version:s,onChange:r}),o=b(a$4({},d),{options:t});return jsx(v.Provider,{value:o,children:c})};var S=({classNames:t,unstyled:n})=>{let{options:s,settings:r}=p(),[c,d]=useState(()=>{let o={};return s.forEach(i=>{var a,_;o[i.id]=(_=(a=r==null?void 0:r.consents[i.id])!=null?a:i.defaultValue)!=null?_:false;}),o});return jsx("div",{className:a$5("ndpr-consent-banner__options-list",t==null?void 0:t.root,n),"data-ndpr-component":"consent-option-list",children:s.map(o=>jsxs("div",{className:a$5("ndpr-consent-banner__option",t==null?void 0:t.optionItem,n),children:[jsx("input",{id:`consent-${o.id}`,type:"checkbox",checked:c[o.id]||false,onChange:i=>d(a=>b(a$4({},a),{[o.id]:i.target.checked})),disabled:o.required,className:a$5("ndpr-consent-banner__option-checkbox",t==null?void 0:t.optionCheckbox,n),"aria-label":o.label}),jsxs("div",{className:n?"":"ndpr-consent-banner__option-text",children:[jsxs("label",{htmlFor:`consent-${o.id}`,className:a$5("ndpr-consent-banner__option-label",t==null?void 0:t.optionLabel,n),children:[o.label,o.required&&jsx("span",{className:n?"":"ndpr-consent-banner__required-marker",children:" *"})]}),jsx("p",{className:a$5("ndpr-consent-banner__option-description",t==null?void 0:t.optionDescription,n),children:o.description})]})]},o.id))})};var P=({children:t,className:n,unstyled:s})=>{let{acceptAll:r}=p();return jsx("button",{onClick:r,className:a$5("ndpr-consent-banner__button ndpr-consent-banner__button--primary",n,s),"data-ndpr-component":"consent-accept-button",children:t!=null?t:"Accept All"})};var R=({children:t,className:n,unstyled:s})=>{let{rejectAll:r}=p();return jsx("button",{onClick:r,className:a$5("ndpr-consent-banner__button ndpr-consent-banner__button--secondary",n,s),"data-ndpr-component":"consent-reject-button",children:t!=null?t:"Reject All"})};var y=({children:t,className:n,unstyled:s,consents:r})=>{let{updateConsent:c,options:d}=p();return jsx("button",{onClick:()=>{if(r)c(r);else {let i={};d.forEach(a=>{i[a.id]=a.required||false;}),c(i);}},className:a$5("ndpr-consent-banner__button ndpr-consent-banner__button--primary",n,s),"data-ndpr-component":"consent-save-button",children:t!=null?t:"Save Preferences"})};var I={Provider:g,OptionList:S,AcceptButton:P,RejectButton:R,SaveButton:y,Banner:a$2,Settings:a$1,Storage:a};export{I as Consent,P as ConsentAcceptButton,S as ConsentOptionList,g as ConsentProvider,R as ConsentRejectButton,y as ConsentSaveButton,p as useConsentCompound};
|
package/dist/core.d.mts
CHANGED
|
@@ -815,7 +815,7 @@ export declare type DSRStatus = 'pending' | 'awaitingVerification' | 'inProgress
|
|
|
815
815
|
/**
|
|
816
816
|
* Validated DSR submission shape — matches what `<DSRRequestForm onSubmit>`
|
|
817
817
|
* emits client-side. Use this as the typed parameter for your server-side
|
|
818
|
-
* handler after `
|
|
818
|
+
* handler after `validateDsrSubmissionStructured` returns `valid: true`.
|
|
819
819
|
*/
|
|
820
820
|
export declare interface DsrSubmissionPayload {
|
|
821
821
|
requestType: string;
|
|
@@ -830,16 +830,6 @@ export declare interface DsrSubmissionPayload {
|
|
|
830
830
|
submittedAt: number;
|
|
831
831
|
}
|
|
832
832
|
|
|
833
|
-
/** Result of validating a raw DSR submission payload. */
|
|
834
|
-
export declare interface DsrSubmissionValidationResult {
|
|
835
|
-
/** True when the payload conforms to the DSR submission contract. */
|
|
836
|
-
valid: boolean;
|
|
837
|
-
/** Field-keyed error messages. Empty when `valid` is true. */
|
|
838
|
-
errors: Record<string, string>;
|
|
839
|
-
/** The narrowed, typed payload — only populated when `valid` is true. */
|
|
840
|
-
data?: DsrSubmissionPayload;
|
|
841
|
-
}
|
|
842
|
-
|
|
843
833
|
/**
|
|
844
834
|
* Data Subject Rights types aligned with NDPA 2023 Part VI (Sections 34-38)
|
|
845
835
|
* and the related provisions in Part V (Section 27 — information to the data subject)
|
|
@@ -936,16 +926,29 @@ export declare function exportROPAToCSV(ropa: RecordOfProcessingActivities): str
|
|
|
936
926
|
export declare function findUnfilledTokens(rendered: string): string[];
|
|
937
927
|
|
|
938
928
|
/**
|
|
939
|
-
*
|
|
940
|
-
*
|
|
941
|
-
*
|
|
942
|
-
*
|
|
943
|
-
|
|
944
|
-
|
|
929
|
+
* Format a DSR request for display or submission. Returns the formatted
|
|
930
|
+
* payload plus a typed `errors` array of `{ field, code, message }` for any
|
|
931
|
+
* required fields missing from the source request.
|
|
932
|
+
*
|
|
933
|
+
* Codes emitted:
|
|
934
|
+
* - `request_id_required`
|
|
935
|
+
* - `request_type_required`
|
|
936
|
+
* - `request_status_required`
|
|
937
|
+
* - `created_at_required`
|
|
938
|
+
* - `subject_name_required`
|
|
939
|
+
* - `subject_email_required`
|
|
940
|
+
*/
|
|
941
|
+
export declare function formatDSRRequestStructured(request: DSRRequest): FormatDSRRequestStructuredResult;
|
|
942
|
+
|
|
943
|
+
/** Result of {@link formatDSRRequestStructured}. */
|
|
944
|
+
export declare interface FormatDSRRequestStructuredResult {
|
|
945
|
+
valid: boolean;
|
|
946
|
+
errors: StructuredValidationError[];
|
|
947
|
+
/** Formatted request payload — always populated regardless of `valid`. */
|
|
945
948
|
formattedRequest: Record<string, unknown>;
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
}
|
|
949
|
+
/** Narrowed input — populated only on `valid: true`. */
|
|
950
|
+
data?: DSRRequest;
|
|
951
|
+
}
|
|
949
952
|
|
|
950
953
|
export declare const frenchLocale: Required<{
|
|
951
954
|
[K in keyof NDPRLocale]: Required<NonNullable<NDPRLocale[K]>>;
|
|
@@ -2016,6 +2019,30 @@ export declare interface StorageAdapter<T = unknown> {
|
|
|
2016
2019
|
remove(): void | Promise<void>;
|
|
2017
2020
|
}
|
|
2018
2021
|
|
|
2022
|
+
/**
|
|
2023
|
+
* Single structured validation error with a stable, locale-independent
|
|
2024
|
+
* `code` consumers can switch on programmatically.
|
|
2025
|
+
*/
|
|
2026
|
+
export declare interface StructuredValidationError {
|
|
2027
|
+
/** Dot-path of the offending field (e.g. `'timestamp'`, `'dataSubject.email'`, `'options[0].purpose'`). */
|
|
2028
|
+
field: string;
|
|
2029
|
+
/** Stable, snake_case error code — safe to switch on across locales. */
|
|
2030
|
+
code: string;
|
|
2031
|
+
/** Human-readable English message — informational only; do not regex-match. */
|
|
2032
|
+
message: string;
|
|
2033
|
+
}
|
|
2034
|
+
|
|
2035
|
+
/**
|
|
2036
|
+
* Result of a structured validator. `errors` is an array (one entry per
|
|
2037
|
+
* failed rule). `data` is the narrowed, typed payload, only populated on
|
|
2038
|
+
* `valid: true`.
|
|
2039
|
+
*/
|
|
2040
|
+
export declare interface StructuredValidationResult<T> {
|
|
2041
|
+
valid: boolean;
|
|
2042
|
+
errors: StructuredValidationError[];
|
|
2043
|
+
data?: T;
|
|
2044
|
+
}
|
|
2045
|
+
|
|
2019
2046
|
/** Full context used to generate an adaptive privacy policy. */
|
|
2020
2047
|
export declare interface TemplateContext {
|
|
2021
2048
|
/** Organisation details, extended with industry and size. */
|
|
@@ -2155,70 +2182,43 @@ export declare function useNDPRConfig(): NDPRConfig;
|
|
|
2155
2182
|
export declare function useNDPRLocale(): typeof defaultLocale;
|
|
2156
2183
|
|
|
2157
2184
|
/**
|
|
2158
|
-
* Validates consent
|
|
2159
|
-
*
|
|
2160
|
-
*
|
|
2161
|
-
*
|
|
2185
|
+
* Validates consent options against NDPA Section 26 requirements. Each option
|
|
2186
|
+
* is checked for a non-empty `purpose`. Failing options are reported with
|
|
2187
|
+
* `field: 'options[i].purpose'` so consumers can map errors back to the
|
|
2188
|
+
* originating option index.
|
|
2189
|
+
*
|
|
2190
|
+
* Codes emitted:
|
|
2191
|
+
* - `options_required` — empty / missing options array
|
|
2192
|
+
* - `purpose_required` — single option missing a purpose
|
|
2162
2193
|
*/
|
|
2163
|
-
export declare function
|
|
2164
|
-
valid: boolean;
|
|
2165
|
-
errors: string[];
|
|
2166
|
-
};
|
|
2194
|
+
export declare function validateConsentOptionsStructured(options: ConsentOption[]): StructuredValidationResult<ConsentOption[]>;
|
|
2167
2195
|
|
|
2168
2196
|
/**
|
|
2169
|
-
* Validates
|
|
2170
|
-
*
|
|
2171
|
-
*
|
|
2172
|
-
* @param options The consent options to validate
|
|
2173
|
-
* @returns An object containing validation result and any error messages
|
|
2174
|
-
* @deprecated Use `validateConsentOptionsStructured()` for typed `{ field, code, message }[]` errors. The legacy string-returning shape will be removed in 5.0.
|
|
2175
|
-
*/
|
|
2176
|
-
export declare function validateConsentOptions(options: ConsentOption[]): {
|
|
2177
|
-
valid: boolean;
|
|
2178
|
-
errors: string[];
|
|
2179
|
-
};
|
|
2180
|
-
|
|
2181
|
-
/**
|
|
2182
|
-
* Validate a raw DSR submission payload against the same rules
|
|
2183
|
-
* `<DSRRequestForm />` enforces client-side. Designed to be called from a
|
|
2184
|
-
* server-side handler (Next.js Route Handler, NestJS controller, Express
|
|
2185
|
-
* middleware, Cloudflare Worker) so client and server stay in sync without
|
|
2186
|
-
* the consumer hand-rolling zod / class-validator schemas.
|
|
2197
|
+
* Validates consent settings against NDPA requirements. Returns structured
|
|
2198
|
+
* `{ field, code, message }[]` errors so consumers can switch on `code`
|
|
2199
|
+
* across locales without regex-matching English strings.
|
|
2187
2200
|
*
|
|
2188
|
-
*
|
|
2189
|
-
* `
|
|
2201
|
+
* Codes emitted:
|
|
2202
|
+
* - `consents_required`
|
|
2203
|
+
* - `timestamp_required`
|
|
2204
|
+
* - `timestamp_invalid`
|
|
2205
|
+
* - `version_required`
|
|
2206
|
+
* - `method_required`
|
|
2207
|
+
* - `has_interacted_required`
|
|
2208
|
+
* - `consent_stale`
|
|
2190
2209
|
*
|
|
2191
|
-
* @example
|
|
2210
|
+
* @example
|
|
2192
2211
|
* ```ts
|
|
2193
|
-
*
|
|
2194
|
-
*
|
|
2195
|
-
*
|
|
2196
|
-
*
|
|
2197
|
-
* const { valid, errors, data } = validateDsrSubmission(await req.json());
|
|
2198
|
-
* if (!valid) return Response.json({ errors }, { status: 422 });
|
|
2199
|
-
* // `data` is the typed DsrSubmissionPayload
|
|
2200
|
-
* await dsrStore.create(data);
|
|
2201
|
-
* return Response.json({ ok: true }, { status: 201 });
|
|
2212
|
+
* const { valid, errors, data } = validateConsentStructured(settings);
|
|
2213
|
+
* if (!valid) {
|
|
2214
|
+
* const stale = errors.find((e) => e.code === 'consent_stale');
|
|
2215
|
+
* if (stale) showRefreshBanner();
|
|
2202
2216
|
* }
|
|
2203
2217
|
* ```
|
|
2204
|
-
*
|
|
2205
|
-
* @example **Lock to specific request types**
|
|
2206
|
-
* ```ts
|
|
2207
|
-
* validateDsrSubmission(payload, {
|
|
2208
|
-
* allowedRequestTypes: ['access', 'erasure', 'rectification'],
|
|
2209
|
-
* });
|
|
2210
|
-
* ```
|
|
2211
|
-
*
|
|
2212
|
-
* @example **Skip identity verification (e.g. authenticated session)**
|
|
2213
|
-
* ```ts
|
|
2214
|
-
* validateDsrSubmission(payload, { requireIdentityVerification: false });
|
|
2215
|
-
* ```
|
|
2216
|
-
*
|
|
2217
|
-
* @deprecated Use `validateDsrSubmissionStructured()` for typed `{ field, code, message }[]` errors. The legacy string-returning shape will be removed in 5.0.
|
|
2218
2218
|
*/
|
|
2219
|
-
export declare function
|
|
2219
|
+
export declare function validateConsentStructured(settings: ConsentSettings): StructuredValidationResult<ConsentSettings>;
|
|
2220
2220
|
|
|
2221
|
-
/** Options for {@link
|
|
2221
|
+
/** Options for {@link validateDsrSubmissionStructured}. */
|
|
2222
2222
|
export declare interface ValidateDsrSubmissionOptions {
|
|
2223
2223
|
/**
|
|
2224
2224
|
* Whether the data subject is required to provide an identifier
|
|
@@ -2235,6 +2235,48 @@ export declare interface ValidateDsrSubmissionOptions {
|
|
|
2235
2235
|
allowedRequestTypes?: string[];
|
|
2236
2236
|
}
|
|
2237
2237
|
|
|
2238
|
+
/**
|
|
2239
|
+
* Validate a raw DSR submission payload against the same rules
|
|
2240
|
+
* `<DSRRequestForm />` enforces client-side. Designed to be called from a
|
|
2241
|
+
* server-side handler (Next.js Route Handler, NestJS controller, Express
|
|
2242
|
+
* middleware, Cloudflare Worker) so client and server stay in sync without
|
|
2243
|
+
* the consumer hand-rolling zod / class-validator schemas.
|
|
2244
|
+
*
|
|
2245
|
+
* Defensive — accepts `unknown` and narrows. Safe to call directly on
|
|
2246
|
+
* `await request.json()`. Returns `{ field, code, message }[]` errors so
|
|
2247
|
+
* callers can switch on `code` programmatically across locales.
|
|
2248
|
+
*
|
|
2249
|
+
* Codes emitted:
|
|
2250
|
+
* - `payload_not_object`
|
|
2251
|
+
* - `request_type_required`
|
|
2252
|
+
* - `request_type_not_allowed`
|
|
2253
|
+
* - `data_subject_required`
|
|
2254
|
+
* - `full_name_required`
|
|
2255
|
+
* - `email_required`
|
|
2256
|
+
* - `email_invalid_format`
|
|
2257
|
+
* - `phone_invalid_type`
|
|
2258
|
+
* - `identifier_type_required`
|
|
2259
|
+
* - `identifier_value_required`
|
|
2260
|
+
* - `submitted_at_invalid`
|
|
2261
|
+
* - `additional_info_invalid_type`
|
|
2262
|
+
* - `payload_final_narrowing_failed`
|
|
2263
|
+
*
|
|
2264
|
+
* @example **Next.js Route Handler**
|
|
2265
|
+
* ```ts
|
|
2266
|
+
* import { validateDsrSubmissionStructured } from '@tantainnovative/ndpr-toolkit/server';
|
|
2267
|
+
*
|
|
2268
|
+
* export async function POST(req: Request) {
|
|
2269
|
+
* const { valid, errors, data } = validateDsrSubmissionStructured(await req.json());
|
|
2270
|
+
* if (!valid) {
|
|
2271
|
+
* return Response.json({ errors }, { status: 422 });
|
|
2272
|
+
* }
|
|
2273
|
+
* await dsrStore.create(data);
|
|
2274
|
+
* return Response.json({ ok: true }, { status: 201 });
|
|
2275
|
+
* }
|
|
2276
|
+
* ```
|
|
2277
|
+
*/
|
|
2278
|
+
export declare function validateDsrSubmissionStructured(payload: unknown, options?: ValidateDsrSubmissionOptions): StructuredValidationResult<DsrSubmissionPayload>;
|
|
2279
|
+
|
|
2238
2280
|
/**
|
|
2239
2281
|
* Validates that all required fields are present on a processing activity
|
|
2240
2282
|
* and that the lawful basis is properly documented.
|