@tantainnovative/ndpr-toolkit 3.10.6 → 3.12.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.
Files changed (103) hide show
  1. package/CHANGELOG.md +111 -0
  2. package/README.md +38 -24
  3. package/dist/adapters.d.mts +90 -4
  4. package/dist/adapters.d.ts +90 -4
  5. package/dist/breach.d.mts +13 -1
  6. package/dist/breach.d.ts +13 -1
  7. package/dist/breach.js +1 -1
  8. package/dist/breach.mjs +1 -1
  9. package/dist/{chunk-EZCGTHQV.js → chunk-4GIMXUMI.js} +3 -3
  10. package/dist/{chunk-HBLGN4SD.js → chunk-5AECGMEB.js} +1 -1
  11. package/dist/chunk-67KA345Q.mjs +1 -0
  12. package/dist/chunk-6OWCUDTN.mjs +1 -0
  13. package/dist/{chunk-4G3SRVRI.mjs → chunk-B6BRD5SL.mjs} +1 -1
  14. package/dist/chunk-CAFCRCTZ.mjs +1 -0
  15. package/dist/{chunk-VJTQXVAF.js → chunk-EHQVTFYO.js} +1 -1
  16. package/dist/{chunk-CNM6G5IA.js → chunk-FC3PTJFL.js} +1 -1
  17. package/dist/{chunk-H3IULCE3.js → chunk-HOAC5VUF.js} +1 -1
  18. package/dist/{chunk-H3XJV2IR.mjs → chunk-I3V3ITN7.mjs} +1 -1
  19. package/dist/{chunk-MPBPAEZC.mjs → chunk-IB3KSUPZ.mjs} +1 -1
  20. package/dist/{chunk-TAHSSITO.mjs → chunk-IHNAFXDM.mjs} +1 -1
  21. package/dist/chunk-IQO3SIAG.mjs +1 -0
  22. package/dist/{chunk-UTFBKL73.js → chunk-IRRUYR6M.js} +1 -1
  23. package/dist/{chunk-C7IDR2IV.js → chunk-JLQT3W3E.js} +1 -1
  24. package/dist/chunk-JYZOKO2W.mjs +103 -0
  25. package/dist/chunk-NX5MOBRI.js +1 -0
  26. package/dist/chunk-O2WEABB3.js +1 -0
  27. package/dist/chunk-OZHUINWS.js +1 -0
  28. package/dist/{chunk-66NQ5CVY.mjs → chunk-Q4CSVWSS.mjs} +1 -1
  29. package/dist/{chunk-CR2QZTGW.js → chunk-QMAVEHOR.js} +1 -1
  30. package/dist/{chunk-3HOXQNCH.mjs → chunk-RFXGD5NE.mjs} +1 -1
  31. package/dist/chunk-ROC64RLP.js +1 -0
  32. package/dist/{chunk-O45PKBZA.mjs → chunk-RR3KXNET.mjs} +3 -3
  33. package/dist/{chunk-KY6WYHWB.mjs → chunk-TN4TH3CT.mjs} +1 -1
  34. package/dist/chunk-VPNK7OID.mjs +1 -0
  35. package/dist/{chunk-O2RDZGM2.js → chunk-VUFTRKKC.js} +1 -1
  36. package/dist/chunk-WKUC65HL.mjs +1 -0
  37. package/dist/chunk-WXUXCRAJ.js +1 -0
  38. package/dist/chunk-YK22SYCT.js +103 -0
  39. package/dist/chunk-YSD2DFBR.js +6 -0
  40. package/dist/chunk-ZHX62QAL.mjs +6 -0
  41. package/dist/consent.d.mts +23 -1
  42. package/dist/consent.d.ts +23 -1
  43. package/dist/consent.js +1 -1
  44. package/dist/consent.mjs +1 -1
  45. package/dist/core.js +1 -1
  46. package/dist/core.mjs +1 -1
  47. package/dist/cross-border.d.mts +12 -1
  48. package/dist/cross-border.d.ts +12 -1
  49. package/dist/cross-border.js +1 -1
  50. package/dist/cross-border.mjs +1 -1
  51. package/dist/dpia.d.mts +16 -1
  52. package/dist/dpia.d.ts +16 -1
  53. package/dist/dpia.js +1 -1
  54. package/dist/dpia.mjs +1 -1
  55. package/dist/dsr.d.mts +21 -1
  56. package/dist/dsr.d.ts +21 -1
  57. package/dist/dsr.js +1 -1
  58. package/dist/dsr.mjs +1 -1
  59. package/dist/headless.d.mts +217 -24
  60. package/dist/headless.d.ts +217 -24
  61. package/dist/headless.js +1 -1
  62. package/dist/headless.mjs +1 -1
  63. package/dist/hooks.d.mts +217 -24
  64. package/dist/hooks.d.ts +217 -24
  65. package/dist/hooks.js +1 -1
  66. package/dist/hooks.mjs +1 -1
  67. package/dist/index.d.mts +419 -29
  68. package/dist/index.d.ts +419 -29
  69. package/dist/index.js +1 -1
  70. package/dist/index.mjs +1 -1
  71. package/dist/lawful-basis.d.mts +10 -0
  72. package/dist/lawful-basis.d.ts +10 -0
  73. package/dist/lawful-basis.js +1 -1
  74. package/dist/lawful-basis.mjs +1 -1
  75. package/dist/policy.d.mts +39 -1
  76. package/dist/policy.d.ts +39 -1
  77. package/dist/presets.js +1 -1
  78. package/dist/presets.mjs +1 -1
  79. package/dist/ropa.d.mts +39 -3
  80. package/dist/ropa.d.ts +39 -3
  81. package/dist/ropa.js +1 -1
  82. package/dist/ropa.mjs +1 -1
  83. package/dist/server.d.mts +86 -0
  84. package/dist/server.d.ts +86 -0
  85. package/dist/server.js +1 -1
  86. package/dist/server.mjs +1 -1
  87. package/dist/styles.css +2 -0
  88. package/package.json +1 -1
  89. package/dist/chunk-3JPDTXGC.js +0 -1
  90. package/dist/chunk-43OQNS2J.mjs +0 -6
  91. package/dist/chunk-5GVMKUMP.js +0 -1
  92. package/dist/chunk-COD3RMTL.mjs +0 -1
  93. package/dist/chunk-EXEXUAF6.mjs +0 -1
  94. package/dist/chunk-L2BRFMVS.js +0 -1
  95. package/dist/chunk-MOHBL6LX.mjs +0 -1
  96. package/dist/chunk-PGI2LM6P.js +0 -103
  97. package/dist/chunk-PZRQWPWD.js +0 -1
  98. package/dist/chunk-RPXRPGHL.mjs +0 -1
  99. package/dist/chunk-RZ6GC6WN.mjs +0 -1
  100. package/dist/chunk-SSH4U4TJ.js +0 -6
  101. package/dist/chunk-WDDCKYWA.js +0 -1
  102. package/dist/chunk-X3GCGC3H.mjs +0 -103
  103. package/dist/chunk-ZQZJNKVB.mjs +0 -1
package/dist/hooks.d.mts CHANGED
@@ -1400,6 +1400,28 @@ declare interface TransferValidationResult {
1400
1400
  warnings: string[];
1401
1401
  }
1402
1402
 
1403
+ /**
1404
+ * Multi-step privacy-policy authoring hook that adapts the generated draft
1405
+ * to the supplied template context (industry, processing purposes, data
1406
+ * categories, processors). Auto-persists a draft via the supplied adapter
1407
+ * and surfaces a live compliance score against the configured rule set.
1408
+ *
1409
+ * @example
1410
+ * ```tsx
1411
+ * import { useAdaptivePolicyWizard } from '@tantainnovative/ndpr-toolkit/hooks';
1412
+ *
1413
+ * function PolicyWizard() {
1414
+ * const { currentStep, nextStep, policy, complianceScore } = useAdaptivePolicyWizard();
1415
+ * return (
1416
+ * <div>
1417
+ * <p>Step {currentStep} — compliance: {complianceScore}%</p>
1418
+ * <button onClick={nextStep}>Next</button>
1419
+ * {policy && <pre>{policy.title}</pre>}
1420
+ * </div>
1421
+ * );
1422
+ * }
1423
+ * ```
1424
+ */
1403
1425
  export declare function useAdaptivePolicyWizard(options?: UseAdaptivePolicyWizardOptions): UseAdaptivePolicyWizardReturn;
1404
1426
 
1405
1427
  export declare interface UseAdaptivePolicyWizardOptions {
@@ -1460,11 +1482,23 @@ export declare interface UseAdaptivePolicyWizardReturn {
1460
1482
  }
1461
1483
 
1462
1484
  /**
1463
- * Hook for managing data breach notifications in compliance with the NDPA (Section 40)
1485
+ * Hook for managing data breach notifications in compliance with the NDPA (Section 40).
1486
+ *
1487
+ * @example
1488
+ * ```tsx
1489
+ * import { useBreach } from '@tantainnovative/ndpr-toolkit/hooks';
1490
+ *
1491
+ * function BreachConsole() {
1492
+ * const { reports, reportBreach } = useBreach({
1493
+ * categories: [{ id: 'unauthorized-access', name: 'Unauthorised access', description: '' }],
1494
+ * });
1495
+ * return <p>{reports.length} breach report(s) on record.</p>;
1496
+ * }
1497
+ * ```
1464
1498
  */
1465
1499
  export declare function useBreach({ categories, initialReports, adapter, storageKey, useLocalStorage, onReport, onAssessment, onNotification, }: UseBreachOptions): UseBreachReturn;
1466
1500
 
1467
- declare interface UseBreachOptions {
1501
+ export declare interface UseBreachOptions {
1468
1502
  /**
1469
1503
  * Available breach categories
1470
1504
  */
@@ -1503,7 +1537,7 @@ declare interface UseBreachOptions {
1503
1537
  onNotification?: (notification: RegulatoryNotification) => void;
1504
1538
  }
1505
1539
 
1506
- declare interface UseBreachReturn {
1540
+ export declare interface UseBreachReturn {
1507
1541
  /**
1508
1542
  * All breach reports
1509
1543
  */
@@ -1567,18 +1601,69 @@ declare interface UseBreachReturn {
1567
1601
  isLoading: boolean;
1568
1602
  }
1569
1603
 
1604
+ /**
1605
+ * Computes an NDPA compliance score and returns a structured report
1606
+ * (score, rating, per-module breakdown, recommendations).
1607
+ *
1608
+ * The computation is memoised by the structural identity of `input` — passing
1609
+ * a fresh-but-equal object on every render is safe and does not force a recompute.
1610
+ *
1611
+ * @param options - The compliance score options.
1612
+ * @param options.input - A {@link ComplianceInput} snapshot summarising the
1613
+ * organisation's current compliance posture.
1614
+ * @returns A memoised {@link ComplianceReport} with overall score, rating,
1615
+ * module-level breakdowns, and prioritised recommendations.
1616
+ *
1617
+ * @example
1618
+ * ```tsx
1619
+ * import { useComplianceScore } from '@tantainnovative/ndpr-toolkit/hooks';
1620
+ *
1621
+ * function ComplianceBadge({ input }) {
1622
+ * const report = useComplianceScore({ input });
1623
+ * return <span>{report.overallScore}/100 — {report.rating}</span>;
1624
+ * }
1625
+ * ```
1626
+ */
1570
1627
  export declare function useComplianceScore({ input }: UseComplianceScoreOptions): ComplianceReport;
1571
1628
 
1572
- declare interface UseComplianceScoreOptions {
1629
+ export declare interface UseComplianceScoreOptions {
1630
+ /**
1631
+ * Snapshot of the organisation's compliance signals — consent settings,
1632
+ * DSR queue, breach log, lawful-basis register, transfers, ROPA, etc.
1633
+ * The hook recomputes the report whenever this input changes by value
1634
+ * (compared via a stable JSON key under the hood).
1635
+ */
1573
1636
  input: ComplianceInput;
1574
1637
  }
1575
1638
 
1576
1639
  /**
1577
- * Hook for managing user consent in compliance with NDPA
1640
+ * Hook for managing user consent in compliance with the NDPA.
1641
+ *
1642
+ * @example
1643
+ * ```tsx
1644
+ * import { useConsent } from '@tantainnovative/ndpr-toolkit/hooks';
1645
+ *
1646
+ * function App() {
1647
+ * const { hasConsent, acceptAll, rejectAll, shouldShowBanner } = useConsent({
1648
+ * options: [
1649
+ * { id: 'necessary', label: 'Necessary', required: true },
1650
+ * { id: 'analytics', label: 'Analytics' },
1651
+ * ],
1652
+ * });
1653
+ * if (!shouldShowBanner) return null;
1654
+ * return (
1655
+ * <div role="dialog">
1656
+ * <button onClick={acceptAll}>Accept all</button>
1657
+ * <button onClick={rejectAll}>Reject non-essential</button>
1658
+ * {hasConsent('analytics') && <AnalyticsScripts />}
1659
+ * </div>
1660
+ * );
1661
+ * }
1662
+ * ```
1578
1663
  */
1579
1664
  export declare function useConsent({ options, adapter, storageOptions, version, onChange, }: UseConsentOptions): UseConsentReturn;
1580
1665
 
1581
- declare interface UseConsentOptions {
1666
+ export declare interface UseConsentOptions {
1582
1667
  /**
1583
1668
  * Consent options to present to the user
1584
1669
  */
@@ -1603,7 +1688,7 @@ declare interface UseConsentOptions {
1603
1688
  onChange?: (settings: ConsentSettings) => void;
1604
1689
  }
1605
1690
 
1606
- declare interface UseConsentReturn {
1691
+ export declare interface UseConsentReturn {
1607
1692
  /**
1608
1693
  * Current consent settings
1609
1694
  */
@@ -1647,11 +1732,22 @@ declare interface UseConsentReturn {
1647
1732
  }
1648
1733
 
1649
1734
  /**
1650
- * Hook for managing cross-border data transfers in compliance with NDPA Part VIII (Sections 41-43)
1735
+ * Hook for managing cross-border data transfers in compliance with NDPA Part VIII (Sections 41-43).
1736
+ *
1737
+ * @example
1738
+ * ```tsx
1739
+ * import { useCrossBorderTransfer } from '@tantainnovative/ndpr-toolkit/hooks';
1740
+ *
1741
+ * function TransferRegister() {
1742
+ * const { transfers, getSummary } = useCrossBorderTransfer();
1743
+ * const summary = getSummary();
1744
+ * return <p>{summary.totalActiveTransfers} active cross-border transfers.</p>;
1745
+ * }
1746
+ * ```
1651
1747
  */
1652
1748
  export declare function useCrossBorderTransfer({ initialTransfers, adapter, storageKey, useLocalStorage, onAdd, onUpdate, onRemove, }?: UseCrossBorderTransferOptions): UseCrossBorderTransferReturn;
1653
1749
 
1654
- declare interface UseCrossBorderTransferOptions {
1750
+ export declare interface UseCrossBorderTransferOptions {
1655
1751
  /**
1656
1752
  * Initial transfers to load
1657
1753
  */
@@ -1686,7 +1782,7 @@ declare interface UseCrossBorderTransferOptions {
1686
1782
  onRemove?: (id: string) => void;
1687
1783
  }
1688
1784
 
1689
- declare interface UseCrossBorderTransferReturn {
1785
+ export declare interface UseCrossBorderTransferReturn {
1690
1786
  /**
1691
1787
  * All cross-border transfers
1692
1788
  */
@@ -1793,11 +1889,26 @@ declare interface UseDefaultPrivacyPolicyOptions {
1793
1889
  }
1794
1890
 
1795
1891
  /**
1796
- * Hook for conducting Data Protection Impact Assessments in compliance with the NDPA 2023
1892
+ * Hook for conducting Data Protection Impact Assessments in compliance with the NDPA 2023.
1893
+ *
1894
+ * @example
1895
+ * ```tsx
1896
+ * import { useDPIA } from '@tantainnovative/ndpr-toolkit/hooks';
1897
+ *
1898
+ * function DPIAWizard({ sections }) {
1899
+ * const { currentSection, progress, updateAnswer, nextSection } = useDPIA({ sections });
1900
+ * return (
1901
+ * <div>
1902
+ * <h2>{currentSection?.title} ({progress}%)</h2>
1903
+ * <button onClick={nextSection}>Next</button>
1904
+ * </div>
1905
+ * );
1906
+ * }
1907
+ * ```
1797
1908
  */
1798
1909
  export declare function useDPIA({ sections, initialAnswers, adapter, storageKey, useLocalStorage, onComplete, }: UseDPIAOptions): UseDPIAReturn;
1799
1910
 
1800
- declare interface UseDPIAOptions {
1911
+ export declare interface UseDPIAOptions {
1801
1912
  /**
1802
1913
  * Sections of the DPIA questionnaire
1803
1914
  */
@@ -1828,7 +1939,7 @@ declare interface UseDPIAOptions {
1828
1939
  onComplete?: (result: DPIAResult) => void;
1829
1940
  }
1830
1941
 
1831
- declare interface UseDPIAReturn {
1942
+ export declare interface UseDPIAReturn {
1832
1943
  /**
1833
1944
  * Current section index
1834
1945
  */
@@ -1896,11 +2007,31 @@ declare interface UseDPIAReturn {
1896
2007
  }
1897
2008
 
1898
2009
  /**
1899
- * Hook for managing Data Subject Requests in compliance with the NDPA
2010
+ * Hook for managing Data Subject Requests in compliance with the NDPA.
2011
+ *
2012
+ * @example
2013
+ * ```tsx
2014
+ * import { useDSR } from '@tantainnovative/ndpr-toolkit/hooks';
2015
+ *
2016
+ * function DSRPanel() {
2017
+ * const { requests, submitRequest } = useDSR({
2018
+ * requestTypes: [
2019
+ * { id: 'access', name: 'Access', description: 'Request access', estimatedCompletionTime: 30 },
2020
+ * ],
2021
+ * });
2022
+ * return (
2023
+ * <ul>
2024
+ * {requests.map((r) => (
2025
+ * <li key={r.id}>{r.type} — {r.status}</li>
2026
+ * ))}
2027
+ * </ul>
2028
+ * );
2029
+ * }
2030
+ * ```
1900
2031
  */
1901
2032
  export declare function useDSR({ initialRequests, requestTypes, adapter, storageKey, useLocalStorage, onSubmit, onUpdate, }: UseDSROptions): UseDSRReturn;
1902
2033
 
1903
- declare interface UseDSROptions {
2034
+ export declare interface UseDSROptions {
1904
2035
  /**
1905
2036
  * Initial requests to load
1906
2037
  */
@@ -1935,7 +2066,7 @@ declare interface UseDSROptions {
1935
2066
  onUpdate?: (request: DSRRequest) => void;
1936
2067
  }
1937
2068
 
1938
- declare interface UseDSRReturn {
2069
+ export declare interface UseDSRReturn {
1939
2070
  /**
1940
2071
  * All requests
1941
2072
  */
@@ -2021,10 +2152,20 @@ export declare interface UseFocusTrapOptions {
2021
2152
  /**
2022
2153
  * Hook for managing lawful basis documentation for processing activities
2023
2154
  * in compliance with NDPA 2023 Section 25.
2155
+ *
2156
+ * @example
2157
+ * ```tsx
2158
+ * import { useLawfulBasis } from '@tantainnovative/ndpr-toolkit/hooks';
2159
+ *
2160
+ * function LawfulBasisRegistry() {
2161
+ * const { activities, addActivity } = useLawfulBasis();
2162
+ * return <p>{activities.length} processing activities documented.</p>;
2163
+ * }
2164
+ * ```
2024
2165
  */
2025
2166
  export declare function useLawfulBasis({ initialActivities, adapter, storageKey, useLocalStorage, onAdd, onUpdate, onRemove, }?: UseLawfulBasisOptions): UseLawfulBasisReturn;
2026
2167
 
2027
- declare interface UseLawfulBasisOptions {
2168
+ export declare interface UseLawfulBasisOptions {
2028
2169
  /**
2029
2170
  * Initial processing activities to load
2030
2171
  */
@@ -2059,7 +2200,7 @@ declare interface UseLawfulBasisOptions {
2059
2200
  onRemove?: (id: string) => void;
2060
2201
  }
2061
2202
 
2062
- declare interface UseLawfulBasisReturn {
2203
+ export declare interface UseLawfulBasisReturn {
2063
2204
  /**
2064
2205
  * All processing activities
2065
2206
  */
@@ -2095,11 +2236,27 @@ declare interface UseLawfulBasisReturn {
2095
2236
  }
2096
2237
 
2097
2238
  /**
2098
- * Hook for generating NDPA-compliant privacy policies
2239
+ * Hook for generating NDPA-compliant privacy policies.
2240
+ *
2241
+ * @example
2242
+ * ```tsx
2243
+ * import { usePrivacyPolicy } from '@tantainnovative/ndpr-toolkit/hooks';
2244
+ *
2245
+ * function PolicyBuilder({ templates }) {
2246
+ * const { policy, selectTemplate, generatePolicy } = usePrivacyPolicy({ templates });
2247
+ * return (
2248
+ * <div>
2249
+ * <button onClick={() => selectTemplate(templates[0].id)}>Select default</button>
2250
+ * <button onClick={generatePolicy}>Generate</button>
2251
+ * {policy && <pre>{policy.title}</pre>}
2252
+ * </div>
2253
+ * );
2254
+ * }
2255
+ * ```
2099
2256
  */
2100
2257
  export declare function usePrivacyPolicy({ templates, initialPolicy, adapter, storageKey, persist, useLocalStorage, onGenerate, }: UsePrivacyPolicyOptions): UsePrivacyPolicyReturn;
2101
2258
 
2102
- declare interface UsePrivacyPolicyOptions {
2259
+ export declare interface UsePrivacyPolicyOptions {
2103
2260
  /**
2104
2261
  * Available policy templates
2105
2262
  */
@@ -2139,7 +2296,7 @@ declare interface UsePrivacyPolicyOptions {
2139
2296
  onGenerate?: (policy: PrivacyPolicy) => void;
2140
2297
  }
2141
2298
 
2142
- declare interface UsePrivacyPolicyReturn {
2299
+ export declare interface UsePrivacyPolicyReturn {
2143
2300
  /**
2144
2301
  * Current policy data
2145
2302
  */
@@ -2207,6 +2364,21 @@ declare interface UsePrivacyPolicyReturn {
2207
2364
  *
2208
2365
  * Provides state management and utility functions for maintaining
2209
2366
  * a comprehensive register of all data processing activities.
2367
+ *
2368
+ * @example
2369
+ * ```tsx
2370
+ * import { useROPA } from '@tantainnovative/ndpr-toolkit/hooks';
2371
+ *
2372
+ * function ROPARegister({ initialData }) {
2373
+ * const { ropa, addRecord, exportCSV } = useROPA({ initialData });
2374
+ * return (
2375
+ * <div>
2376
+ * <p>{ropa.records.length} processing records</p>
2377
+ * <button onClick={() => download(exportCSV())}>Export CSV</button>
2378
+ * </div>
2379
+ * );
2380
+ * }
2381
+ * ```
2210
2382
  */
2211
2383
  export declare function useROPA({ initialData, adapter, onRecordAdd, onRecordUpdate, onRecordArchive, }: UseROPAOptions): UseROPAReturn;
2212
2384
 
@@ -2257,17 +2429,38 @@ export declare interface UseROPAReturn {
2257
2429
  */
2258
2430
  getRecord: (id: string) => ProcessingRecord | undefined;
2259
2431
  /**
2260
- * Get a summary of the ROPA including statistics
2432
+ * Get a summary of the ROPA including statistics.
2433
+ * @deprecated Use the cached `summary` field instead — it is memoised on
2434
+ * `ropa` so consumers don't pay the recompute cost on every call.
2261
2435
  */
2262
2436
  getSummary: () => ROPASummary;
2263
2437
  /**
2264
- * Export the ROPA as a CSV string
2438
+ * Export the ROPA as a CSV string.
2439
+ * @deprecated Use the cached `csv` field instead — it is memoised on
2440
+ * `ropa` so consumers don't pay the recompute cost on every call.
2265
2441
  */
2266
2442
  exportCSV: () => string;
2267
2443
  /**
2268
- * Identify compliance gaps across all records
2444
+ * Identify compliance gaps across all records.
2445
+ * @deprecated Use the cached `complianceGaps` field instead — it is
2446
+ * memoised on `ropa` so consumers don't pay the recompute cost on every call.
2269
2447
  */
2270
2448
  getComplianceGaps: () => ROPAComplianceGap[];
2449
+ /**
2450
+ * Memoised ROPA summary. Recomputed only when `ropa` changes.
2451
+ * Prefer this over `getSummary()` to avoid redundant recomputation.
2452
+ */
2453
+ summary: ROPASummary;
2454
+ /**
2455
+ * Memoised CSV export string. Recomputed only when `ropa` changes.
2456
+ * Prefer this over `exportCSV()` to avoid redundant recomputation.
2457
+ */
2458
+ csv: string;
2459
+ /**
2460
+ * Memoised compliance gap list. Recomputed only when `ropa` changes.
2461
+ * Prefer this over `getComplianceGaps()` to avoid redundant recomputation.
2462
+ */
2463
+ complianceGaps: ROPAComplianceGap[];
2271
2464
  /**
2272
2465
  * Whether the adapter is still loading data (relevant for async adapters)
2273
2466
  */