@tantainnovative/ndpr-toolkit 3.10.6 → 3.11.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 +65 -0
- package/README.md +38 -24
- package/dist/adapters.d.mts +90 -4
- package/dist/adapters.d.ts +90 -4
- package/dist/breach.d.mts +13 -1
- package/dist/breach.d.ts +13 -1
- package/dist/breach.js +1 -1
- package/dist/breach.mjs +1 -1
- package/dist/{chunk-HBLGN4SD.js → chunk-5AECGMEB.js} +1 -1
- package/dist/{chunk-4G3SRVRI.mjs → chunk-B6BRD5SL.mjs} +1 -1
- package/dist/{chunk-VJTQXVAF.js → chunk-EHQVTFYO.js} +1 -1
- package/dist/{chunk-CNM6G5IA.js → chunk-FC3PTJFL.js} +1 -1
- package/dist/{chunk-H3IULCE3.js → chunk-HOAC5VUF.js} +1 -1
- package/dist/{chunk-H3XJV2IR.mjs → chunk-I3V3ITN7.mjs} +1 -1
- package/dist/{chunk-MPBPAEZC.mjs → chunk-IB3KSUPZ.mjs} +1 -1
- package/dist/{chunk-TAHSSITO.mjs → chunk-IHNAFXDM.mjs} +1 -1
- package/dist/chunk-IQO3SIAG.mjs +1 -0
- package/dist/{chunk-UTFBKL73.js → chunk-IRRUYR6M.js} +1 -1
- package/dist/{chunk-C7IDR2IV.js → chunk-JLQT3W3E.js} +1 -1
- package/dist/chunk-OZHUINWS.js +1 -0
- package/dist/{chunk-66NQ5CVY.mjs → chunk-Q4CSVWSS.mjs} +1 -1
- package/dist/{chunk-CR2QZTGW.js → chunk-QMAVEHOR.js} +1 -1
- package/dist/{chunk-3HOXQNCH.mjs → chunk-RFXGD5NE.mjs} +1 -1
- package/dist/chunk-VPNK7OID.mjs +1 -0
- package/dist/consent.d.mts +23 -1
- package/dist/consent.d.ts +23 -1
- package/dist/consent.js +1 -1
- package/dist/consent.mjs +1 -1
- package/dist/core.js +1 -1
- package/dist/core.mjs +1 -1
- package/dist/cross-border.d.mts +12 -1
- package/dist/cross-border.d.ts +12 -1
- package/dist/dpia.d.mts +16 -1
- package/dist/dpia.d.ts +16 -1
- package/dist/dpia.js +1 -1
- package/dist/dpia.mjs +1 -1
- package/dist/dsr.d.mts +21 -1
- package/dist/dsr.d.ts +21 -1
- package/dist/dsr.js +1 -1
- package/dist/dsr.mjs +1 -1
- package/dist/headless.d.mts +193 -21
- package/dist/headless.d.ts +193 -21
- package/dist/headless.js +1 -1
- package/dist/headless.mjs +1 -1
- package/dist/hooks.d.mts +193 -21
- package/dist/hooks.d.ts +193 -21
- package/dist/hooks.js +1 -1
- package/dist/hooks.mjs +1 -1
- package/dist/index.d.mts +395 -26
- package/dist/index.d.ts +395 -26
- package/dist/index.js +1 -1
- package/dist/index.mjs +1 -1
- package/dist/lawful-basis.d.mts +10 -0
- package/dist/lawful-basis.d.ts +10 -0
- package/dist/lawful-basis.js +1 -1
- package/dist/lawful-basis.mjs +1 -1
- package/dist/policy.d.mts +39 -1
- package/dist/policy.d.ts +39 -1
- package/dist/ropa.d.mts +15 -0
- package/dist/ropa.d.ts +15 -0
- package/dist/server.d.mts +86 -0
- package/dist/server.d.ts +86 -0
- package/dist/server.js +1 -1
- package/dist/server.mjs +1 -1
- package/package.json +1 -1
- package/dist/chunk-L2BRFMVS.js +0 -1
- package/dist/chunk-MOHBL6LX.mjs +0 -1
- package/dist/chunk-RZ6GC6WN.mjs +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,71 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [commit-and-tag-version](https://github.com/absolute-version/commit-and-tag-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
+
## [3.11.0](https://github.com/mr-tanta/ndpr-toolkit/compare/v3.10.6...v3.11.0) (2026-05-27)
|
|
6
|
+
|
|
7
|
+
Release 3 of 6 on the post-audit roadmap. Strictly additive — every change here adds to the public surface or fixes a docs lie. Existing consumers keep working without changes.
|
|
8
|
+
|
|
9
|
+
### Type-export baseline — `*Props` interfaces, adapter ecosystem types, hook return types now reachable
|
|
10
|
+
|
|
11
|
+
Every component's `Props` interface is now re-exported from `src/index.ts` (the default entry):
|
|
12
|
+
|
|
13
|
+
`ConsentBannerProps`, `ConsentManagerProps`, `ConsentStorageProps`, `DSRRequestFormProps`, `DSRDashboardProps`, `DSRTrackerProps`, `DPIAQuestionnaireProps`, `DPIAReportProps`, `StepIndicatorProps`, `BreachReportFormProps`, `BreachRiskAssessmentProps`, `BreachNotificationManagerProps`, `RegulatoryReportGeneratorProps`, `PolicyGeneratorProps`, `PolicyPreviewProps`, `PolicyExporterProps`, `LawfulBasisTrackerProps`, `CrossBorderTransferManagerProps`, `ROPAManagerProps`.
|
|
14
|
+
|
|
15
|
+
Consumers can now type-safely wrap the toolkit's components — e.g.
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import type { ConsentBannerProps, NDPRThemeProvider } from '@tantainnovative/ndpr-toolkit';
|
|
19
|
+
|
|
20
|
+
function MyConsentBanner(props: ConsentBannerProps & { brand?: string }) { … }
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
Adapter ecosystem types reachable too:
|
|
24
|
+
- `ApiAdapterErrorContext<T>`, `ApiAdapterSuccessContext<T>`, `ApiAdapterRetryConfig`, `ApiAdapterMethod` from `/adapters` and root
|
|
25
|
+
- `CookieAdapterOptions`, `StorageAdapter<T>` from `/adapters` and root
|
|
26
|
+
|
|
27
|
+
DSR validator types reachable:
|
|
28
|
+
- `DsrSubmissionPayload`, `DsrSubmissionValidationResult`, `ValidateDsrSubmissionOptions` from `/server` (canonical) and root
|
|
29
|
+
|
|
30
|
+
Hook option/return interfaces promoted to `export interface` and re-exported through `hooks-entry.ts` (auto-flows to `/headless`):
|
|
31
|
+
- `UseConsentOptions`/`Return`, `UseDSROptions`, `UseBreachOptions`, `UseDPIAOptions`, `UseLawfulBasisOptions`, `UseCrossBorderTransferOptions`, `UseComplianceScoreOptions`, `UsePrivacyPolicyOptions`.
|
|
32
|
+
|
|
33
|
+
### JSDoc `@example` blocks on every public hook + adapter
|
|
34
|
+
|
|
35
|
+
Added `@example` blocks to all 10 public hooks (`useConsent`, `useDSR`, `useBreach`, `useDPIA`, `useLawfulBasis`, `useCrossBorderTransfer`, `usePrivacyPolicy`, `useROPA`, `useAdaptivePolicyWizard`, `useComplianceScore`) and 5 adapters (`cookieAdapter`, `localStorageAdapter`, `sessionStorageAdapter`, `memoryAdapter`, `composeAdapters`). `useComplianceScore` previously had zero JSDoc; full block added (description + `@param` + `@returns` + `@example`).
|
|
36
|
+
|
|
37
|
+
### Internal: `validateDsrSubmission` type-guard refactor
|
|
38
|
+
|
|
39
|
+
Replaced the `as string` cast chain in `utils/dsr.ts` with a `isDsrPayloadRaw(payload): payload is DsrPayloadRaw` type guard. External signature unchanged. Safer narrowing; no consumer-visible difference.
|
|
40
|
+
|
|
41
|
+
### Docs
|
|
42
|
+
|
|
43
|
+
**9 new component pages** under `src/app/docs/components/`, all wired into the sidebar nav:
|
|
44
|
+
|
|
45
|
+
- `ndpr-theme-provider`, `ndpr-provider`, `ndpr-dashboard`, `adaptive-policy-wizard`, `policy-page`, `legal-notice` (previously had no dedicated pages)
|
|
46
|
+
- `lawful-basis-tracker-lite`, `cross-border-transfer-manager-lite`, `ropa-manager-lite` (Lite variants previously only mentioned inline)
|
|
47
|
+
|
|
48
|
+
**Fixed broken docs** that taught fictitious symbol names:
|
|
49
|
+
- 5 `useDSR()` calls without the required `requestTypes` arg, in `components/data-subject-rights/page.tsx`, `components/hooks/page.tsx`, and `guides/data-subject-requests/page.tsx`. All now show `useDSR({ requestTypes })` with the correct API.
|
|
50
|
+
- `getRequestById` → `getRequest`, `filterRequestsByStatus` → `getRequestsByStatus`, `filterRequestsByType` → `getRequestsByType` (the docs were inventing names that don't exist). `deleteRequest` removed — no such function ships.
|
|
51
|
+
- `onSubmit` prop on the DSR component page now typed `DSRFormSubmission`, not the fictitious `DSRFormData`.
|
|
52
|
+
|
|
53
|
+
### README compact pass
|
|
54
|
+
|
|
55
|
+
- Bumped version refs `v3.10.3` → `v3.11.0` (6 occurrences: header release link + 5 screenshot URL tags).
|
|
56
|
+
- Replaced the 3-File Quickstart's throwaway `let store: unknown = null` API route with a clean 2-file quickstart that uses `localStorageAdapter` by default and shows `cookieAdapter` / `apiAdapter` / `composeAdapters` as opt-ins. The throwaway demo always looked unprofessional next to claims of production-readiness.
|
|
57
|
+
- New **"When NOT to use this toolkit"** section between Adapters and Pluggable Storage. Honest framing: non-React stacks, banner-only use cases, GDPR-primary regimes, enterprise CMP shoppers should pick something else. Builds trust with the people who are the right fit.
|
|
58
|
+
- "What's new" notice rewritten for 3.11.0 (less narrative, more skimmable).
|
|
59
|
+
|
|
60
|
+
### CONTRIBUTING.md rewritten
|
|
61
|
+
|
|
62
|
+
The previous file was generic boilerplate. The new one covers the practical things contributors actually need: pnpm 10 / Node ≥20 setup, repo layout (with a callout that the root `package.json` is the publish surface, not the inner one), how to run a single test, the `verify:tarball` gate, the release flow, branch conventions, patch/minor/major decision table, i18n contribution guide.
|
|
63
|
+
|
|
64
|
+
### Verification
|
|
65
|
+
|
|
66
|
+
- Jest: **1212 / 1212 passing** (no behaviour changes)
|
|
67
|
+
- `tsc --noEmit -p tsconfig.json` — clean
|
|
68
|
+
- `pnpm verify:tarball --skip-ts` — clean across all 22 subpaths
|
|
69
|
+
|
|
5
70
|
## [3.10.6](https://github.com/mr-tanta/ndpr-toolkit/compare/v3.10.5...v3.10.6) (2026-05-27)
|
|
6
71
|
|
|
7
72
|
Release 2 of 6 on the post-audit roadmap. CI / repo plumbing only — zero `dist/` changes, zero behaviour changes for consumers.
|
package/README.md
CHANGED
|
@@ -11,28 +11,29 @@
|
|
|
11
11
|
|
|
12
12
|
v3 ships **zero-config presets**, **pluggable storage adapters**, **compound components**, and a **compliance score engine** — eight production-ready modules covering consent, data subject rights, DPIA, breach notification, privacy policies, lawful basis, cross-border transfers, and ROPA.
|
|
13
13
|
|
|
14
|
-
**[Documentation](https://ndprtoolkit.com.ng)** | **[Live Demos](https://ndprtoolkit.com.ng/ndpr-demos)** | **[npm](https://www.npmjs.com/package/@tantainnovative/ndpr-toolkit)** | **[Blog](https://ndprtoolkit.com.ng/blog)** | **[v3.
|
|
14
|
+
**[Documentation](https://ndprtoolkit.com.ng)** | **[Live Demos](https://ndprtoolkit.com.ng/ndpr-demos)** | **[npm](https://www.npmjs.com/package/@tantainnovative/ndpr-toolkit)** | **[Blog](https://ndprtoolkit.com.ng/blog)** | **[v3.11.0 Release](https://github.com/mr-tanta/ndpr-toolkit/releases/tag/v3.11.0)**
|
|
15
15
|
|
|
16
16
|
[](https://stackblitz.com/github/mr-tanta/ndpr-toolkit/tree/main/examples/nextjs-app)
|
|
17
17
|
[](https://codesandbox.io/p/github/mr-tanta/ndpr-toolkit/main/examples/nextjs-app)
|
|
18
18
|
|
|
19
|
-
> **What's new in 3.
|
|
19
|
+
> **What's new in 3.11.0:** Every component's `Props` interface is now re-exported from the root (consumers can finally wrap toolkit components without copying types). Adapter ecosystem types (`ApiAdapterErrorContext`, `StorageAdapter<T>`, …) and DSR validator types reachable from `/server` + root. 9 new component docs pages cover `NDPRThemeProvider`, `NDPRProvider`, `NDPRDashboard`, `AdaptivePolicyWizard`, `PolicyPage`, the 3 Lite manager variants, and `LegalNotice`.
|
|
20
20
|
>
|
|
21
|
-
> **Upgrading from 3.7.x
|
|
21
|
+
> **3.10.x highlights:** Typed theming via `<NDPRThemeProvider>`, a `/headless` subpath alias of `/hooks`, the production-grade DSR backend reference at `examples/dsr-backend-prod/`, plus the `verify:tarball` CI gate that catches broken exports at PR time. Upgrading from 3.7.x? See the [3.7 → 3.10 upgrade guide](https://ndprtoolkit.com.ng/docs/guides/upgrading-3-7-to-3-10). Full history in the [CHANGELOG](https://github.com/mr-tanta/ndpr-toolkit/blob/main/CHANGELOG.md).
|
|
22
22
|
|
|
23
23
|
<p align="center">
|
|
24
|
-
<img src="https://raw.githubusercontent.com/mr-tanta/ndpr-toolkit/v3.
|
|
24
|
+
<img src="https://raw.githubusercontent.com/mr-tanta/ndpr-toolkit/v3.11.0/public/screenshots/hero.png" alt="NDPA Toolkit — NDPA Compliance Made Beautiful" width="800" />
|
|
25
25
|
</p>
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
29
|
-
##
|
|
29
|
+
## Quickstart
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
Two files. Full NDPA-compliant consent with no backend.
|
|
32
32
|
|
|
33
33
|
**`app/layout.tsx`**
|
|
34
34
|
```tsx
|
|
35
35
|
import { NDPRConsent } from '@tantainnovative/ndpr-toolkit/presets';
|
|
36
|
+
import '@tantainnovative/ndpr-toolkit/styles';
|
|
36
37
|
|
|
37
38
|
export default function RootLayout({ children }: { children: React.ReactNode }) {
|
|
38
39
|
return (
|
|
@@ -46,31 +47,31 @@ export default function RootLayout({ children }: { children: React.ReactNode })
|
|
|
46
47
|
}
|
|
47
48
|
```
|
|
48
49
|
|
|
49
|
-
|
|
50
|
-
```ts
|
|
51
|
-
import { NextRequest, NextResponse } from 'next/server';
|
|
52
|
-
|
|
53
|
-
let store: unknown = null;
|
|
50
|
+
That's it — `NDPRConsent` defaults to `localStorageAdapter`, so consent persists across page loads with zero backend code.
|
|
54
51
|
|
|
55
|
-
|
|
56
|
-
export async function POST(req: NextRequest) {
|
|
57
|
-
store = await req.json();
|
|
58
|
-
return NextResponse.json({ ok: true });
|
|
59
|
-
}
|
|
60
|
-
```
|
|
52
|
+
**Want server-side persistence?** Pass any `StorageAdapter`:
|
|
61
53
|
|
|
62
|
-
**Persist to your API instead of localStorage:**
|
|
63
54
|
```tsx
|
|
64
55
|
import { NDPRConsent } from '@tantainnovative/ndpr-toolkit/presets';
|
|
65
|
-
import { apiAdapter } from '@tantainnovative/ndpr-toolkit/adapters';
|
|
56
|
+
import { cookieAdapter, apiAdapter, composeAdapters, localStorageAdapter } from '@tantainnovative/ndpr-toolkit/adapters';
|
|
66
57
|
|
|
58
|
+
// Server-readable cookie (best for SSR consent gating)
|
|
59
|
+
<NDPRConsent adapter={cookieAdapter('ndpr_consent', { expires: 180 })} />
|
|
60
|
+
|
|
61
|
+
// Or POST to your own backend
|
|
67
62
|
<NDPRConsent adapter={apiAdapter('/api/consent')} />
|
|
63
|
+
|
|
64
|
+
// Or both — fan-out writes
|
|
65
|
+
<NDPRConsent adapter={composeAdapters(
|
|
66
|
+
apiAdapter('/api/consent'),
|
|
67
|
+
localStorageAdapter('ndpr_consent'),
|
|
68
|
+
)} />
|
|
68
69
|
```
|
|
69
70
|
|
|
70
|
-
|
|
71
|
+
The full SSR pattern (cookie read server-side → banner hydrates already-resolved, no flash) is in the [Server-Side Storage guide](https://ndprtoolkit.com.ng/docs/guides/server-side-storage).
|
|
71
72
|
|
|
72
73
|
<p align="center">
|
|
73
|
-
<img src="https://raw.githubusercontent.com/mr-tanta/ndpr-toolkit/v3.
|
|
74
|
+
<img src="https://raw.githubusercontent.com/mr-tanta/ndpr-toolkit/v3.11.0/public/screenshots/consent-demo.png" alt="Consent Management Demo — interactive consent banner with state inspector" width="800" />
|
|
74
75
|
<br />
|
|
75
76
|
<em>Interactive consent demo with configurable position, theme, storage, and real-time state inspector</em>
|
|
76
77
|
</p>
|
|
@@ -304,6 +305,19 @@ import { apiAdapter, localStorageAdapter, cookieAdapter } from '@tantainnovative
|
|
|
304
305
|
|
|
305
306
|
---
|
|
306
307
|
|
|
308
|
+
## When NOT to use this toolkit
|
|
309
|
+
|
|
310
|
+
The toolkit is React-first, NDPA-specific, and built for product engineers shipping a compliant app — not a generic cookie-banner library. Pick something else if:
|
|
311
|
+
|
|
312
|
+
- **You're not on React.** No Vue / Svelte / Angular bindings exist. The `/server` entry exposes framework-agnostic validators and the compliance-score engine — usable from any Node runtime — but the UI components are React-only.
|
|
313
|
+
- **You only need a cookie banner**, with no DSR portal, breach reporting, DPIA, ROPA, or compliance scoring. A purpose-built consent library (Iubenda, OneTrust, Cookiebot, Osano) is a better fit and will integrate with your CMP / TCF setup. The toolkit can do the banner alone, but you'd be paying for surface you don't use.
|
|
314
|
+
- **Your compliance regime is GDPR / CCPA-primary** and you don't operate under the Nigeria Data Protection Act 2023. The validators, statutory deadlines, and section citations are NDPA-specific. (NDPA + GDPR overlap a lot in practice; the toolkit doesn't pretend to be a GDPR product.)
|
|
315
|
+
- **You need an enterprise consent-management platform** with audit trails, marketing-team UIs, regional CMP exports, and a vendor SLA. That's a different product category.
|
|
316
|
+
|
|
317
|
+
The toolkit is what we wished existed when building Nigerian SaaS apps in 2025 and need NDPA components that don't fight the rest of the stack. If that's your shape, read on.
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
307
321
|
## Pluggable Storage
|
|
308
322
|
|
|
309
323
|
Every stateful component accepts an `adapter` prop. Built-in adapters ship out of the box.
|
|
@@ -434,13 +448,13 @@ Every module has an interactive demo. No signup, no setup — try them instantly
|
|
|
434
448
|
|
|
435
449
|
<p align="center">
|
|
436
450
|
<a href="https://ndprtoolkit.com.ng/ndpr-demos">
|
|
437
|
-
<img src="https://raw.githubusercontent.com/mr-tanta/ndpr-toolkit/v3.
|
|
451
|
+
<img src="https://raw.githubusercontent.com/mr-tanta/ndpr-toolkit/v3.11.0/public/screenshots/demos-overview.png" alt="8 interactive live demos — zero setup required" width="800" />
|
|
438
452
|
</a>
|
|
439
453
|
</p>
|
|
440
454
|
|
|
441
455
|
<p align="center">
|
|
442
|
-
<img src="https://raw.githubusercontent.com/mr-tanta/ndpr-toolkit/v3.
|
|
443
|
-
<img src="https://raw.githubusercontent.com/mr-tanta/ndpr-toolkit/v3.
|
|
456
|
+
<img src="https://raw.githubusercontent.com/mr-tanta/ndpr-toolkit/v3.11.0/public/screenshots/dsr-demo.png" alt="Data Subject Rights — 8 rights with request tracking" width="400" />
|
|
457
|
+
<img src="https://raw.githubusercontent.com/mr-tanta/ndpr-toolkit/v3.11.0/public/screenshots/breach-demo.png" alt="Breach Notification — 72-hour countdown with step-by-step workflow" width="400" />
|
|
444
458
|
</p>
|
|
445
459
|
|
|
446
460
|
<p align="center">
|
package/dist/adapters.d.mts
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
*/
|
|
33
33
|
export declare function apiAdapter<T = unknown>(endpoint: string, options?: ApiAdapterOptions<T>): StorageAdapter<T>;
|
|
34
34
|
|
|
35
|
-
declare interface ApiAdapterErrorContext<T = unknown> {
|
|
35
|
+
export declare interface ApiAdapterErrorContext<T = unknown> {
|
|
36
36
|
/** Which adapter operation triggered this — `load`, `save`, or `remove`. */
|
|
37
37
|
method: ApiAdapterMethod;
|
|
38
38
|
/** The endpoint URL that failed. */
|
|
@@ -49,7 +49,7 @@ declare interface ApiAdapterErrorContext<T = unknown> {
|
|
|
49
49
|
attempt: number;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
declare type ApiAdapterMethod = 'load' | 'save' | 'remove';
|
|
52
|
+
export declare type ApiAdapterMethod = 'load' | 'save' | 'remove';
|
|
53
53
|
|
|
54
54
|
export declare interface ApiAdapterOptions<T = unknown> {
|
|
55
55
|
/**
|
|
@@ -106,7 +106,7 @@ export declare interface ApiAdapterOptions<T = unknown> {
|
|
|
106
106
|
fetchInit?: Omit<RequestInit, 'method' | 'headers' | 'body' | 'credentials'>;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
declare interface ApiAdapterRetryConfig {
|
|
109
|
+
export declare interface ApiAdapterRetryConfig {
|
|
110
110
|
/**
|
|
111
111
|
* Number of additional attempts after the initial request. Defaults to 0
|
|
112
112
|
* (no retries). e.g. `attempts: 2` means up to 3 total requests.
|
|
@@ -125,7 +125,7 @@ declare interface ApiAdapterRetryConfig {
|
|
|
125
125
|
shouldRetry?: (ctx: ApiAdapterErrorContext<unknown>) => boolean;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
declare interface ApiAdapterSuccessContext<T = unknown> {
|
|
128
|
+
export declare interface ApiAdapterSuccessContext<T = unknown> {
|
|
129
129
|
/** Which adapter operation succeeded — `load`, `save`, or `remove`. */
|
|
130
130
|
method: ApiAdapterMethod;
|
|
131
131
|
/** The endpoint URL. */
|
|
@@ -138,8 +138,51 @@ declare interface ApiAdapterSuccessContext<T = unknown> {
|
|
|
138
138
|
payload?: T;
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Compose a primary adapter with one or more secondary adapters. Reads
|
|
143
|
+
* always go to the primary; writes (`save` / `remove`) fan out to the
|
|
144
|
+
* primary first, then each secondary. Secondary failures are logged but
|
|
145
|
+
* never propagated.
|
|
146
|
+
*
|
|
147
|
+
* Useful for shadowing localStorage to an API endpoint, mirroring consent
|
|
148
|
+
* to a cookie for SSR, or building offline-first sync.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```ts
|
|
152
|
+
* import {
|
|
153
|
+
* composeAdapters,
|
|
154
|
+
* localStorageAdapter,
|
|
155
|
+
* apiAdapter,
|
|
156
|
+
* } from '@tantainnovative/ndpr-toolkit/adapters';
|
|
157
|
+
* import { useConsent } from '@tantainnovative/ndpr-toolkit/hooks';
|
|
158
|
+
*
|
|
159
|
+
* const adapter = composeAdapters(
|
|
160
|
+
* localStorageAdapter('ndpr_consent'),
|
|
161
|
+
* apiAdapter('/api/consent'),
|
|
162
|
+
* );
|
|
163
|
+
* useConsent({ options, adapter });
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
141
166
|
export declare function composeAdapters<T = unknown>(primary: StorageAdapter<T>, ...secondaries: StorageAdapter<T>[]): StorageAdapter<T>;
|
|
142
167
|
|
|
168
|
+
/**
|
|
169
|
+
* Storage adapter backed by a browser cookie. Useful for consent state that
|
|
170
|
+
* needs to be shared with server-side rendering, or for cross-subdomain
|
|
171
|
+
* persistence via the `domain` option.
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```ts
|
|
175
|
+
* import { cookieAdapter } from '@tantainnovative/ndpr-toolkit/adapters';
|
|
176
|
+
* import { useConsent } from '@tantainnovative/ndpr-toolkit/hooks';
|
|
177
|
+
*
|
|
178
|
+
* const adapter = cookieAdapter('ndpr_consent', {
|
|
179
|
+
* domain: '.example.com',
|
|
180
|
+
* sameSite: 'Lax',
|
|
181
|
+
* expires: 180,
|
|
182
|
+
* });
|
|
183
|
+
* useConsent({ options, adapter });
|
|
184
|
+
* ```
|
|
185
|
+
*/
|
|
143
186
|
export declare function cookieAdapter<T = unknown>(key: string, options?: CookieAdapterOptions): StorageAdapter<T>;
|
|
144
187
|
|
|
145
188
|
export declare interface CookieAdapterOptions {
|
|
@@ -150,10 +193,53 @@ export declare interface CookieAdapterOptions {
|
|
|
150
193
|
sameSite?: 'Strict' | 'Lax' | 'None';
|
|
151
194
|
}
|
|
152
195
|
|
|
196
|
+
/**
|
|
197
|
+
* Storage adapter backed by `window.localStorage`. The default adapter used
|
|
198
|
+
* by every hook in the toolkit when no `adapter` prop is supplied.
|
|
199
|
+
*
|
|
200
|
+
* Safe to import server-side — every method short-circuits when
|
|
201
|
+
* `window` is undefined, so calling `load()` on the server returns `null`.
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* ```ts
|
|
205
|
+
* import { localStorageAdapter } from '@tantainnovative/ndpr-toolkit/adapters';
|
|
206
|
+
* import { useConsent } from '@tantainnovative/ndpr-toolkit/hooks';
|
|
207
|
+
*
|
|
208
|
+
* const adapter = localStorageAdapter('ndpr_consent');
|
|
209
|
+
* useConsent({ options, adapter });
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
153
212
|
export declare function localStorageAdapter<T = unknown>(key: string): StorageAdapter<T>;
|
|
154
213
|
|
|
214
|
+
/**
|
|
215
|
+
* Storage adapter backed by an in-memory value. Useful in tests, Storybook,
|
|
216
|
+
* SSR previews, or anywhere persistence across reloads is undesirable.
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```ts
|
|
220
|
+
* import { memoryAdapter } from '@tantainnovative/ndpr-toolkit/adapters';
|
|
221
|
+
* import { useConsent } from '@tantainnovative/ndpr-toolkit/hooks';
|
|
222
|
+
*
|
|
223
|
+
* const adapter = memoryAdapter({ consents: {}, version: '1.0' });
|
|
224
|
+
* useConsent({ options, adapter });
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
155
227
|
export declare function memoryAdapter<T = unknown>(initialData?: T): StorageAdapter<T>;
|
|
156
228
|
|
|
229
|
+
/**
|
|
230
|
+
* Storage adapter backed by `window.sessionStorage`. Data is scoped to the
|
|
231
|
+
* current tab and discarded when the tab closes — useful for consent
|
|
232
|
+
* choices that should not survive a fresh session.
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```ts
|
|
236
|
+
* import { sessionStorageAdapter } from '@tantainnovative/ndpr-toolkit/adapters';
|
|
237
|
+
* import { useConsent } from '@tantainnovative/ndpr-toolkit/hooks';
|
|
238
|
+
*
|
|
239
|
+
* const adapter = sessionStorageAdapter('ndpr_consent');
|
|
240
|
+
* useConsent({ options, adapter });
|
|
241
|
+
* ```
|
|
242
|
+
*/
|
|
157
243
|
export declare function sessionStorageAdapter<T = unknown>(key: string): StorageAdapter<T>;
|
|
158
244
|
|
|
159
245
|
export declare interface StorageAdapter<T = unknown> {
|
package/dist/adapters.d.ts
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
*/
|
|
33
33
|
export declare function apiAdapter<T = unknown>(endpoint: string, options?: ApiAdapterOptions<T>): StorageAdapter<T>;
|
|
34
34
|
|
|
35
|
-
declare interface ApiAdapterErrorContext<T = unknown> {
|
|
35
|
+
export declare interface ApiAdapterErrorContext<T = unknown> {
|
|
36
36
|
/** Which adapter operation triggered this — `load`, `save`, or `remove`. */
|
|
37
37
|
method: ApiAdapterMethod;
|
|
38
38
|
/** The endpoint URL that failed. */
|
|
@@ -49,7 +49,7 @@ declare interface ApiAdapterErrorContext<T = unknown> {
|
|
|
49
49
|
attempt: number;
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
-
declare type ApiAdapterMethod = 'load' | 'save' | 'remove';
|
|
52
|
+
export declare type ApiAdapterMethod = 'load' | 'save' | 'remove';
|
|
53
53
|
|
|
54
54
|
export declare interface ApiAdapterOptions<T = unknown> {
|
|
55
55
|
/**
|
|
@@ -106,7 +106,7 @@ export declare interface ApiAdapterOptions<T = unknown> {
|
|
|
106
106
|
fetchInit?: Omit<RequestInit, 'method' | 'headers' | 'body' | 'credentials'>;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
-
declare interface ApiAdapterRetryConfig {
|
|
109
|
+
export declare interface ApiAdapterRetryConfig {
|
|
110
110
|
/**
|
|
111
111
|
* Number of additional attempts after the initial request. Defaults to 0
|
|
112
112
|
* (no retries). e.g. `attempts: 2` means up to 3 total requests.
|
|
@@ -125,7 +125,7 @@ declare interface ApiAdapterRetryConfig {
|
|
|
125
125
|
shouldRetry?: (ctx: ApiAdapterErrorContext<unknown>) => boolean;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
declare interface ApiAdapterSuccessContext<T = unknown> {
|
|
128
|
+
export declare interface ApiAdapterSuccessContext<T = unknown> {
|
|
129
129
|
/** Which adapter operation succeeded — `load`, `save`, or `remove`. */
|
|
130
130
|
method: ApiAdapterMethod;
|
|
131
131
|
/** The endpoint URL. */
|
|
@@ -138,8 +138,51 @@ declare interface ApiAdapterSuccessContext<T = unknown> {
|
|
|
138
138
|
payload?: T;
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
+
/**
|
|
142
|
+
* Compose a primary adapter with one or more secondary adapters. Reads
|
|
143
|
+
* always go to the primary; writes (`save` / `remove`) fan out to the
|
|
144
|
+
* primary first, then each secondary. Secondary failures are logged but
|
|
145
|
+
* never propagated.
|
|
146
|
+
*
|
|
147
|
+
* Useful for shadowing localStorage to an API endpoint, mirroring consent
|
|
148
|
+
* to a cookie for SSR, or building offline-first sync.
|
|
149
|
+
*
|
|
150
|
+
* @example
|
|
151
|
+
* ```ts
|
|
152
|
+
* import {
|
|
153
|
+
* composeAdapters,
|
|
154
|
+
* localStorageAdapter,
|
|
155
|
+
* apiAdapter,
|
|
156
|
+
* } from '@tantainnovative/ndpr-toolkit/adapters';
|
|
157
|
+
* import { useConsent } from '@tantainnovative/ndpr-toolkit/hooks';
|
|
158
|
+
*
|
|
159
|
+
* const adapter = composeAdapters(
|
|
160
|
+
* localStorageAdapter('ndpr_consent'),
|
|
161
|
+
* apiAdapter('/api/consent'),
|
|
162
|
+
* );
|
|
163
|
+
* useConsent({ options, adapter });
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
141
166
|
export declare function composeAdapters<T = unknown>(primary: StorageAdapter<T>, ...secondaries: StorageAdapter<T>[]): StorageAdapter<T>;
|
|
142
167
|
|
|
168
|
+
/**
|
|
169
|
+
* Storage adapter backed by a browser cookie. Useful for consent state that
|
|
170
|
+
* needs to be shared with server-side rendering, or for cross-subdomain
|
|
171
|
+
* persistence via the `domain` option.
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```ts
|
|
175
|
+
* import { cookieAdapter } from '@tantainnovative/ndpr-toolkit/adapters';
|
|
176
|
+
* import { useConsent } from '@tantainnovative/ndpr-toolkit/hooks';
|
|
177
|
+
*
|
|
178
|
+
* const adapter = cookieAdapter('ndpr_consent', {
|
|
179
|
+
* domain: '.example.com',
|
|
180
|
+
* sameSite: 'Lax',
|
|
181
|
+
* expires: 180,
|
|
182
|
+
* });
|
|
183
|
+
* useConsent({ options, adapter });
|
|
184
|
+
* ```
|
|
185
|
+
*/
|
|
143
186
|
export declare function cookieAdapter<T = unknown>(key: string, options?: CookieAdapterOptions): StorageAdapter<T>;
|
|
144
187
|
|
|
145
188
|
export declare interface CookieAdapterOptions {
|
|
@@ -150,10 +193,53 @@ export declare interface CookieAdapterOptions {
|
|
|
150
193
|
sameSite?: 'Strict' | 'Lax' | 'None';
|
|
151
194
|
}
|
|
152
195
|
|
|
196
|
+
/**
|
|
197
|
+
* Storage adapter backed by `window.localStorage`. The default adapter used
|
|
198
|
+
* by every hook in the toolkit when no `adapter` prop is supplied.
|
|
199
|
+
*
|
|
200
|
+
* Safe to import server-side — every method short-circuits when
|
|
201
|
+
* `window` is undefined, so calling `load()` on the server returns `null`.
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* ```ts
|
|
205
|
+
* import { localStorageAdapter } from '@tantainnovative/ndpr-toolkit/adapters';
|
|
206
|
+
* import { useConsent } from '@tantainnovative/ndpr-toolkit/hooks';
|
|
207
|
+
*
|
|
208
|
+
* const adapter = localStorageAdapter('ndpr_consent');
|
|
209
|
+
* useConsent({ options, adapter });
|
|
210
|
+
* ```
|
|
211
|
+
*/
|
|
153
212
|
export declare function localStorageAdapter<T = unknown>(key: string): StorageAdapter<T>;
|
|
154
213
|
|
|
214
|
+
/**
|
|
215
|
+
* Storage adapter backed by an in-memory value. Useful in tests, Storybook,
|
|
216
|
+
* SSR previews, or anywhere persistence across reloads is undesirable.
|
|
217
|
+
*
|
|
218
|
+
* @example
|
|
219
|
+
* ```ts
|
|
220
|
+
* import { memoryAdapter } from '@tantainnovative/ndpr-toolkit/adapters';
|
|
221
|
+
* import { useConsent } from '@tantainnovative/ndpr-toolkit/hooks';
|
|
222
|
+
*
|
|
223
|
+
* const adapter = memoryAdapter({ consents: {}, version: '1.0' });
|
|
224
|
+
* useConsent({ options, adapter });
|
|
225
|
+
* ```
|
|
226
|
+
*/
|
|
155
227
|
export declare function memoryAdapter<T = unknown>(initialData?: T): StorageAdapter<T>;
|
|
156
228
|
|
|
229
|
+
/**
|
|
230
|
+
* Storage adapter backed by `window.sessionStorage`. Data is scoped to the
|
|
231
|
+
* current tab and discarded when the tab closes — useful for consent
|
|
232
|
+
* choices that should not survive a fresh session.
|
|
233
|
+
*
|
|
234
|
+
* @example
|
|
235
|
+
* ```ts
|
|
236
|
+
* import { sessionStorageAdapter } from '@tantainnovative/ndpr-toolkit/adapters';
|
|
237
|
+
* import { useConsent } from '@tantainnovative/ndpr-toolkit/hooks';
|
|
238
|
+
*
|
|
239
|
+
* const adapter = sessionStorageAdapter('ndpr_consent');
|
|
240
|
+
* useConsent({ options, adapter });
|
|
241
|
+
* ```
|
|
242
|
+
*/
|
|
157
243
|
export declare function sessionStorageAdapter<T = unknown>(key: string): StorageAdapter<T>;
|
|
158
244
|
|
|
159
245
|
export declare interface StorageAdapter<T = unknown> {
|
package/dist/breach.d.mts
CHANGED
|
@@ -770,7 +770,19 @@ export declare interface StorageAdapter<T = unknown> {
|
|
|
770
770
|
}
|
|
771
771
|
|
|
772
772
|
/**
|
|
773
|
-
* Hook for managing data breach notifications in compliance with the NDPA (Section 40)
|
|
773
|
+
* Hook for managing data breach notifications in compliance with the NDPA (Section 40).
|
|
774
|
+
*
|
|
775
|
+
* @example
|
|
776
|
+
* ```tsx
|
|
777
|
+
* import { useBreach } from '@tantainnovative/ndpr-toolkit/hooks';
|
|
778
|
+
*
|
|
779
|
+
* function BreachConsole() {
|
|
780
|
+
* const { reports, reportBreach } = useBreach({
|
|
781
|
+
* categories: [{ id: 'unauthorized-access', name: 'Unauthorised access', description: '' }],
|
|
782
|
+
* });
|
|
783
|
+
* return <p>{reports.length} breach report(s) on record.</p>;
|
|
784
|
+
* }
|
|
785
|
+
* ```
|
|
774
786
|
*/
|
|
775
787
|
export declare function useBreach({ categories, initialReports, adapter, storageKey, useLocalStorage, onReport, onAssessment, onNotification, }: UseBreachOptions): UseBreachReturn;
|
|
776
788
|
|
package/dist/breach.d.ts
CHANGED
|
@@ -770,7 +770,19 @@ export declare interface StorageAdapter<T = unknown> {
|
|
|
770
770
|
}
|
|
771
771
|
|
|
772
772
|
/**
|
|
773
|
-
* Hook for managing data breach notifications in compliance with the NDPA (Section 40)
|
|
773
|
+
* Hook for managing data breach notifications in compliance with the NDPA (Section 40).
|
|
774
|
+
*
|
|
775
|
+
* @example
|
|
776
|
+
* ```tsx
|
|
777
|
+
* import { useBreach } from '@tantainnovative/ndpr-toolkit/hooks';
|
|
778
|
+
*
|
|
779
|
+
* function BreachConsole() {
|
|
780
|
+
* const { reports, reportBreach } = useBreach({
|
|
781
|
+
* categories: [{ id: 'unauthorized-access', name: 'Unauthorised access', description: '' }],
|
|
782
|
+
* });
|
|
783
|
+
* return <p>{reports.length} breach report(s) on record.</p>;
|
|
784
|
+
* }
|
|
785
|
+
* ```
|
|
774
786
|
*/
|
|
775
787
|
export declare function useBreach({ categories, initialReports, adapter, storageKey, useLocalStorage, onReport, onAssessment, onNotification, }: UseBreachOptions): UseBreachReturn;
|
|
776
788
|
|
package/dist/breach.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
'use strict';var chunkPGI2LM6P_js=require('./chunk-PGI2LM6P.js'),chunkO2RDZGM2_js=require('./chunk-O2RDZGM2.js'),
|
|
2
|
+
'use strict';var chunkPGI2LM6P_js=require('./chunk-PGI2LM6P.js'),chunkO2RDZGM2_js=require('./chunk-O2RDZGM2.js'),chunkEHQVTFYO_js=require('./chunk-EHQVTFYO.js'),chunk3YTAOT5O_js=require('./chunk-3YTAOT5O.js');require('./chunk-UXUMYP4L.js'),require('./chunk-NDKDKDDX.js'),require('./chunk-WKTKTLMF.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 c=react.createContext(null);function P(){let e=react.useContext(c);if(!e)throw new Error("Breach compound components must be wrapped in <Breach.Provider>. Example: <Breach.Provider categories={...}><Breach.ReportForm /></Breach.Provider>");return e}var p=({categories:e,adapter:m,storageKey:h,useLocalStorage:B,initialReports:f,onReport:R,onAssessment:x,onNotification:u,children:d})=>{let y=chunkEHQVTFYO_js.a({categories:e,adapter:m,storageKey:h,useLocalStorage:B,initialReports:f,onReport:R,onAssessment:x,onNotification:u}),l=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},y),{categories:e});return jsxRuntime.jsx(c.Provider,{value:l,children:d})};var A={Provider:p,ReportForm:chunkO2RDZGM2_js.a,RiskAssessment:chunkPGI2LM6P_js.a,NotificationManager:chunkPGI2LM6P_js.b,ReportGenerator:chunkPGI2LM6P_js.c};Object.defineProperty(exports,"BreachNotificationManager",{enumerable:true,get:function(){return chunkPGI2LM6P_js.b}});Object.defineProperty(exports,"BreachRiskAssessment",{enumerable:true,get:function(){return chunkPGI2LM6P_js.a}});Object.defineProperty(exports,"RegulatoryReportGenerator",{enumerable:true,get:function(){return chunkPGI2LM6P_js.c}});Object.defineProperty(exports,"BreachReportForm",{enumerable:true,get:function(){return chunkO2RDZGM2_js.a}});Object.defineProperty(exports,"useBreach",{enumerable:true,get:function(){return chunkEHQVTFYO_js.a}});Object.defineProperty(exports,"calculateBreachSeverity",{enumerable:true,get:function(){return chunk3YTAOT5O_js.a}});exports.Breach=A;exports.BreachProvider=p;exports.useBreachCompound=P;
|
package/dist/breach.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {c as c$1,b,a}from'./chunk-X3GCGC3H.mjs';export{b as BreachNotificationManager,a as BreachRiskAssessment,c as RegulatoryReportGenerator}from'./chunk-X3GCGC3H.mjs';import {a as a$1}from'./chunk-KY6WYHWB.mjs';export{a as BreachReportForm}from'./chunk-KY6WYHWB.mjs';import {a as a$2}from'./chunk-
|
|
2
|
+
import {c as c$1,b,a}from'./chunk-X3GCGC3H.mjs';export{b as BreachNotificationManager,a as BreachRiskAssessment,c as RegulatoryReportGenerator}from'./chunk-X3GCGC3H.mjs';import {a as a$1}from'./chunk-KY6WYHWB.mjs';export{a as BreachReportForm}from'./chunk-KY6WYHWB.mjs';import {a as a$2}from'./chunk-RFXGD5NE.mjs';export{a as useBreach}from'./chunk-RFXGD5NE.mjs';export{a as calculateBreachSeverity}from'./chunk-WTGKZX7J.mjs';import'./chunk-EWVK45Z3.mjs';import'./chunk-25TNTLHJ.mjs';import'./chunk-RBMLGRDN.mjs';import'./chunk-ITCY2Z66.mjs';import'./chunk-SFGW37LE.mjs';import'./chunk-DBZSN4WP.mjs';import {b as b$1,a as a$3}from'./chunk-ZJYULEER.mjs';import {createContext,useContext}from'react';import {jsx}from'react/jsx-runtime';var c=createContext(null);function P(){let e=useContext(c);if(!e)throw new Error("Breach compound components must be wrapped in <Breach.Provider>. Example: <Breach.Provider categories={...}><Breach.ReportForm /></Breach.Provider>");return e}var p=({categories:e,adapter:m,storageKey:h,useLocalStorage:B,initialReports:f,onReport:R,onAssessment:x,onNotification:u,children:d})=>{let y=a$2({categories:e,adapter:m,storageKey:h,useLocalStorage:B,initialReports:f,onReport:R,onAssessment:x,onNotification:u}),l=b$1(a$3({},y),{categories:e});return jsx(c.Provider,{value:l,children:d})};var A={Provider:p,ReportForm:a$1,RiskAssessment:a,NotificationManager:b,ReportGenerator:c$1};export{A as Breach,p as BreachProvider,P as useBreachCompound};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var
|
|
1
|
+
'use strict';var chunkOZHUINWS_js=require('./chunk-OZHUINWS.js'),chunkVWED6UTN_js=require('./chunk-VWED6UTN.js'),chunkRFPLZDIO_js=require('./chunk-RFPLZDIO.js'),react=require('react');function K(f,R){return R?chunkVWED6UTN_js.a(f):{load:()=>null,save:()=>{},remove:()=>{}}}function G({initialRequests:f=[],requestTypes:R,adapter:p,storageKey:T="ndpr_dsr_requests",useLocalStorage:h=true,onSubmit:g,onUpdate:m}){let y=p!=null?p:K(T,h),a=react.useRef(y);a.current=y;let[n,i]=react.useState(f),[k,l]=react.useState(true);react.useEffect(()=>{let e=false;try{let t=a.current.load();t instanceof Promise?t.then(s=>{e||(s&&i(s),l(!1));},()=>{e||l(!1);}):(t&&i(t),l(!1));}catch(t){e||l(false);}return ()=>{e=true;}},[]);let c=react.useCallback(e=>{Promise.resolve(a.current.save(e)).catch(t=>{console.warn("[ndpr-toolkit] Failed to save DSR requests:",t);});},[]),x=()=>"dsr_"+Date.now()+"_"+Math.random().toString(36).substr(2,9),P=react.useCallback(e=>{let t=R.find(o=>o.id===e.type),s=(t==null?void 0:t.estimatedCompletionTime)||30,r=Date.now(),d=r+s*24*60*60*1e3,q=chunkRFPLZDIO_js.a({id:x(),status:"pending",createdAt:r,updatedAt:r,dueDate:d},e);return i(o=>{let S=[...o,q];return c(S),S}),g&&g(q),q},[R,c,g]),B=react.useCallback((e,t)=>{let s=null;return i(r=>{let d=r.findIndex(S=>S.id===e);if(d===-1)return r;let q=r[d];s=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a(chunkRFPLZDIO_js.a({},q),t),{updatedAt:Date.now()});let o=[...r];return o[d]=s,c(o),o}),s&&m&&m(s),s},[c,m]),C=react.useCallback(e=>n.find(t=>t.id===e)||null,[n]),I=react.useCallback(e=>n.filter(t=>t.status===e),[n]),L=react.useCallback(e=>n.filter(t=>t.type===e),[n]),O=react.useCallback(e=>R.find(t=>t.id===e),[R]),_=react.useCallback(e=>{let{formattedRequest:t}=chunkOZHUINWS_js.b(e);return t},[]),U=react.useCallback(()=>{i([]),Promise.resolve(a.current.remove()).catch(e=>{console.warn("[ndpr-toolkit] Failed to remove DSR requests:",e);});},[a]);return {requests:n,submitRequest:P,updateRequest:B,getRequest:C,getRequestsByStatus:I,getRequestsByType:L,getRequestType:O,formatRequest:_,clearRequests:U,isLoading:k}}exports.a=G;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import {d,a as a$1}from'./chunk-LWIKDDSU.mjs';import {a as a$2}from'./chunk-DBZSN4WP.mjs';import {b,a}from'./chunk-ZJYULEER.mjs';import {useRef,useState,useEffect,useCallback}from'react';function F(v,c){return c?a$2(v):{load:()=>null,save:()=>{},remove:()=>{}}}function z({initialActivities:v=[],adapter:c,storageKey:b$1="ndpr_lawful_basis_activities",useLocalStorage:
|
|
1
|
+
import {d,a as a$1}from'./chunk-LWIKDDSU.mjs';import {a as a$2}from'./chunk-DBZSN4WP.mjs';import {b,a}from'./chunk-ZJYULEER.mjs';import {useRef,useState,useEffect,useCallback}from'react';function F(v,c){return c?a$2(v):{load:()=>null,save:()=>{},remove:()=>{}}}function z({initialActivities:v=[],adapter:c,storageKey:b$1="ndpr_lawful_basis_activities",useLocalStorage:x=true,onAdd:g,onUpdate:A,onRemove:y}={}){let p=c!=null?c:F(b$1,x),f=useRef(p);f.current=p;let[o,u]=useState(v),[R,l]=useState(true);useEffect(()=>{let t=false;try{let i=f.current.load();i instanceof Promise?i.then(e=>{t||(e&&u(e),l(!1));},()=>{t||l(!1);}):(i&&u(i),l(!1));}catch(i){t||l(false);}return ()=>{t=true;}},[]);let a$2=useCallback(t=>{Promise.resolve(f.current.save(t)).catch(i=>{console.warn("[ndpr-toolkit] Failed to save lawful basis activities:",i);});},[]),_=()=>"lb_"+Date.now()+"_"+Math.random().toString(36).substring(2,11),h=useCallback(t=>{let i=Date.now(),e=b(a({},t),{id:_(),createdAt:i,updatedAt:i});return u(s=>{let r=[...s,e];return a$2(r),r}),g&&g(e),e},[g,a$2]),O=useCallback((t,i)=>{let e=null;return u(s=>{let r=s.findIndex(k=>k.id===t);if(r===-1)return s;e=b(a(a({},s[r]),i),{id:s[r].id,updatedAt:Date.now()});let P=[...s];return P[r]=e,a$2(P),P}),e&&A&&A(e),e},[A,a$2]),D=useCallback(t=>{u(i=>{let e=i.filter(s=>s.id!==t);return a$2(e),e}),y&&y(t);},[y,a$2]),I=useCallback(t=>o.find(i=>i.id===t)||null,[o]),U=useCallback(()=>d(o),[o]),V=useCallback(t=>a$1(t),[]);return {activities:o,addActivity:h,updateActivity:O,removeActivity:D,getActivity:I,getSummary:U,validateActivity:V,isLoading:R}}export{z as a};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var chunk3YTAOT5O_js=require('./chunk-3YTAOT5O.js'),chunkVWED6UTN_js=require('./chunk-VWED6UTN.js'),chunkRFPLZDIO_js=require('./chunk-RFPLZDIO.js'),react=require('react');function G(c,d){switch(d.type){case "LOAD":return d.payload;case "ADD_REPORT":return chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},c),{reports:[...c.reports,d.payload]});case "UPDATE_REPORT":{let f=[...c.reports];return f[d.payload.index]=d.payload.report,chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},c),{reports:f})}case "SET_ASSESSMENT":{let{existing:f,id:S,assessment:g}=d.payload,A=f?c.assessments.map(R=>R.id===S?g:R):[...c.assessments,g];return chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},c),{assessments:A})}case "SET_NOTIFICATION":{let{existing:f,id:S,notification:g}=d.payload,A=f?c.notifications.map(R=>R.id===S?g:R):[...c.notifications,g];return chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},c),{notifications:A})}case "CLEAR":return {reports:[],assessments:[],notifications:[]}}}function J(c,d){return d?chunkVWED6UTN_js.a(c):{load:()=>null,save:()=>{},remove:()=>{}}}function X({categories:c,initialReports:d=[],adapter:f,storageKey:S="ndpr_breach_data",useLocalStorage:g=true,onReport:A,onAssessment:R,onNotification:I}){let k=f!=null?f:J(S,g),E=react.useRef(k);E.current=k;let[b,y]=react.useReducer(G,{reports:d,assessments:[],notifications:[]}),[
|
|
1
|
+
'use strict';var chunk3YTAOT5O_js=require('./chunk-3YTAOT5O.js'),chunkVWED6UTN_js=require('./chunk-VWED6UTN.js'),chunkRFPLZDIO_js=require('./chunk-RFPLZDIO.js'),react=require('react');function G(c,d){switch(d.type){case "LOAD":return d.payload;case "ADD_REPORT":return chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},c),{reports:[...c.reports,d.payload]});case "UPDATE_REPORT":{let f=[...c.reports];return f[d.payload.index]=d.payload.report,chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},c),{reports:f})}case "SET_ASSESSMENT":{let{existing:f,id:S,assessment:g}=d.payload,A=f?c.assessments.map(R=>R.id===S?g:R):[...c.assessments,g];return chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},c),{assessments:A})}case "SET_NOTIFICATION":{let{existing:f,id:S,notification:g}=d.payload,A=f?c.notifications.map(R=>R.id===S?g:R):[...c.notifications,g];return chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},c),{notifications:A})}case "CLEAR":return {reports:[],assessments:[],notifications:[]}}}function J(c,d){return d?chunkVWED6UTN_js.a(c):{load:()=>null,save:()=>{},remove:()=>{}}}function X({categories:c,initialReports:d=[],adapter:f,storageKey:S="ndpr_breach_data",useLocalStorage:g=true,onReport:A,onAssessment:R,onNotification:I}){let k=f!=null?f:J(S,g),E=react.useRef(k);E.current=k;let[b,y]=react.useReducer(G,{reports:d,assessments:[],notifications:[]}),[C,T]=react.useState(true),l=react.useRef(b);l.current=b;let h=react.useCallback(t=>{Promise.resolve(E.current.save(t)).catch(s=>{console.warn("[ndpr-toolkit] Failed to save breach data:",s);});},[]);react.useEffect(()=>{let t=false;try{let s=E.current.load(),i=e=>{var r,n,a;e&&y({type:"LOAD",payload:{reports:(r=e.reports)!=null?r:[],assessments:(n=e.assessments)!=null?n:[],notifications:(a=e.notifications)!=null?a:[]}}),T(!1);};s instanceof Promise?s.then(e=>{t||i(e);},()=>{t||T(!1);}):i(s);}catch(s){t||T(false);}return ()=>{t=true;}},[]);let B=react.useCallback(t=>`${t}_${Date.now()}_${Math.random().toString(36).substr(2,9)}`,[]),_=react.useCallback(t=>{let s=chunkRFPLZDIO_js.a({id:B("breach"),reportedAt:Date.now()},t);y({type:"ADD_REPORT",payload:s});let i=l.current,e=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},i),{reports:[...i.reports,s]});return h(e),A&&A(s),s},[B,A,h]),P=react.useCallback((t,s)=>{let i=l.current,e=i.reports.findIndex(a=>a.id===t);if(e===-1)return null;let r=chunkRFPLZDIO_js.a(chunkRFPLZDIO_js.a({},i.reports[e]),s);y({type:"UPDATE_REPORT",payload:{index:e,report:r}});let n=[...i.reports];return n[e]=r,h(chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},i),{reports:n})),r},[h]),w=react.useCallback(t=>l.current.reports.find(s=>s.id===t)||null,[]),L=react.useCallback((t,s)=>{let i=l.current,e=i.assessments.find(u=>u.breachId===t),r,n;e?(r=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a(chunkRFPLZDIO_js.a({},e),s),{assessedAt:Date.now()}),n=true):(r=chunkRFPLZDIO_js.a({id:B("assessment"),breachId:t,assessedAt:Date.now()},s),n=false),y({type:"SET_ASSESSMENT",payload:{existing:n,id:e==null?void 0:e.id,assessment:r}});let a=n?i.assessments.map(u=>u.id===e.id?r:u):[...i.assessments,r];return h(chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},i),{assessments:a})),R&&R(r),r},[B,R,h]),U=react.useCallback(t=>l.current.assessments.find(s=>s.breachId===t)||null,[]),D=react.useCallback(t=>{let s=l.current.reports.find(N=>N.id===t)||null,i=l.current.assessments.find(N=>N.breachId===t)||null;if(!s)return null;let{severityLevel:e,notificationRequired:r,timeframeHours:n,justification:a}=chunk3YTAOT5O_js.a(s,i||void 0),u=s.discoveredAt+n*60*60*1e3;return {ndpcNotificationRequired:r,ndpcNotificationDeadline:u,dataSubjectNotificationRequired:e==="high"||e==="critical",justification:a}},[]),F=react.useCallback((t,s)=>{let i=l.current,e=i.notifications.find(u=>u.breachId===t),r,n;e?(r=chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a(chunkRFPLZDIO_js.a({},e),s),{sentAt:Date.now()}),n=true):(r=chunkRFPLZDIO_js.a({id:B("notification"),breachId:t,sentAt:Date.now()},s),n=false),y({type:"SET_NOTIFICATION",payload:{existing:n,id:e==null?void 0:e.id,notification:r}});let a=n?i.notifications.map(u=>u.id===e.id?r:u):[...i.notifications,r];return h(chunkRFPLZDIO_js.b(chunkRFPLZDIO_js.a({},i),{notifications:a})),I&&I(r),r},[B,I,h]),M=react.useCallback(t=>l.current.notifications.find(s=>s.breachId===t)||null,[]),$=react.useCallback((t=24)=>{let s=Date.now(),i=l.current,e=[];return i.reports.forEach(r=>{if(i.notifications.some(O=>O.breachId===r.id))return;let n=i.assessments.find(O=>O.breachId===r.id)||null;if(!n)return;let a=D(r.id);if(!a||!a.ndpcNotificationRequired)return;let N=(a.ndpcNotificationDeadline-s)/(3600*1e3);N<=t&&e.push({report:r,assessment:n,requirements:a,hoursRemaining:N});}),e.sort((r,n)=>r.hoursRemaining-n.hoursRemaining)},[D]),j=react.useCallback(()=>{y({type:"CLEAR"}),Promise.resolve(E.current.remove()).catch(t=>{console.warn("[ndpr-toolkit] Failed to remove breach data:",t);});},[]);return {reports:b.reports,assessments:b.assessments,notifications:b.notifications,reportBreach:_,updateReport:P,getReport:w,assessRisk:L,getAssessment:U,calculateNotificationRequirements:D,sendNotification:F,getNotification:M,getBreachesRequiringNotification:$,clearBreachData:j,isLoading:C}}exports.a=X;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var chunkRDALAH3Y_js=require('./chunk-RDALAH3Y.js'),react=require('react');function
|
|
1
|
+
'use strict';var chunkRDALAH3Y_js=require('./chunk-RDALAH3Y.js'),react=require('react');function r({input:e}){let p=JSON.stringify(e);return react.useMemo(()=>chunkRDALAH3Y_js.a(e),[p])}exports.a=r;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
'use strict';var chunkC2KEXHRX_js=require('./chunk-C2KEXHRX.js'),chunkB46SJB5V_js=require('./chunk-B46SJB5V.js'),chunkVWED6UTN_js=require('./chunk-VWED6UTN.js'),react=require('react');function F(n){if(!n)return chunkVWED6UTN_js.a("ndpr_consent");let{storageKey:o="ndpr_consent",storageType:i="localStorage"}=n;return i==="sessionStorage"?chunkC2KEXHRX_js.a(o):i==="cookie"?chunkC2KEXHRX_js.b(o,n.cookieOptions):chunkVWED6UTN_js.a(o)}function k(n,o,i,r,a,g,l){if(n){i(n);let{valid:s,errors:c}=chunkB46SJB5V_js.a(n);r(s),a(c),g(!(s&&n.version===o));}else g(true);l(false);}function z({options:n,adapter:o,storageOptions:i,version:r="1.0",onChange:a}){let g=o!=null?o:F(i),l=react.useRef(g);l.current=g;let[s,c]=react.useState(null),[y,d]=react.useState(false),[E,C]=react.useState(false),[w,S]=react.useState([]),[
|
|
1
|
+
'use strict';var chunkC2KEXHRX_js=require('./chunk-C2KEXHRX.js'),chunkB46SJB5V_js=require('./chunk-B46SJB5V.js'),chunkVWED6UTN_js=require('./chunk-VWED6UTN.js'),react=require('react');function F(n){if(!n)return chunkVWED6UTN_js.a("ndpr_consent");let{storageKey:o="ndpr_consent",storageType:i="localStorage"}=n;return i==="sessionStorage"?chunkC2KEXHRX_js.a(o):i==="cookie"?chunkC2KEXHRX_js.b(o,n.cookieOptions):chunkVWED6UTN_js.a(o)}function k(n,o,i,r,a,g,l){if(n){i(n);let{valid:s,errors:c}=chunkB46SJB5V_js.a(n);r(s),a(c),g(!(s&&n.version===o));}else g(true);l(false);}function z({options:n,adapter:o,storageOptions:i,version:r="1.0",onChange:a}){let g=o!=null?o:F(i),l=react.useRef(g);l.current=g;let[s,c]=react.useState(null),[y,d]=react.useState(false),[E,C]=react.useState(false),[w,S]=react.useState([]),[x,v]=react.useState(true);react.useEffect(()=>{let e=false;try{let t=l.current.load();t instanceof Promise?t.then(m=>{e||k(m,r,c,C,S,d,v);},()=>{e||(d(!0),v(!1));}):k(t,r,c,C,S,d,v);}catch(t){e||(d(true),v(false));}return ()=>{e=true;}},[r]);let h=react.useCallback(e=>{let{valid:t,errors:m}=chunkB46SJB5V_js.a(e);C(t),S(m),a==null||a(e),Promise.resolve(l.current.save(e)).catch(j=>{console.warn("[ndpr-toolkit] Failed to save consent:",j);});},[a]),p=react.useCallback(e=>{let t={consents:e,timestamp:Date.now(),version:r,method:"explicit",hasInteracted:true};c(t),h(t),d(false);},[r,h]),I=react.useCallback(()=>{let e={};n.forEach(t=>{e[t.id]=true;}),p(e);},[n,p]),L=react.useCallback(()=>{let e={};n.forEach(t=>{e[t.id]=t.required||false;}),p(e);},[n,p]),U=react.useCallback(e=>!!(s!=null&&s.consents[e]),[s]),V=react.useCallback(()=>{c(null),d(true),C(false),S([]),Promise.resolve(l.current.remove()).catch(e=>{console.warn("[ndpr-toolkit] Failed to remove consent:",e);});},[]);return {settings:s,hasConsent:U,updateConsent:p,acceptAll:I,rejectAll:L,shouldShowBanner:y,isValid:E,validationErrors:w,resetConsent:V,isLoading:x}}exports.a=z;
|