@dloizides/legal-ui 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/LICENSE +21 -0
- package/README.md +43 -0
- package/dist/index.d.mts +124 -0
- package/dist/index.d.ts +124 -0
- package/dist/index.js +550 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +540 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +113 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 1.0.0
|
|
4
|
+
|
|
5
|
+
Initial release (Capability Wave C1, batch 4). Extracted the proven (erevna+katalogos identical) GDPR
|
|
6
|
+
legal UI: `CookieConsentBanner` + `useCookieConsent` + `ConsentButton`, `PrivacyPolicyModal`,
|
|
7
|
+
`TermsOfServiceModal`, `LegalSection`. Shares the `@dloizides/ui-feedback` context (`useUi`) and
|
|
8
|
+
`@dloizides/ui-icons`. `LegalPage` deferred (app-specific landing/SEO coupling).
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 dloizides
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# @dloizides/legal-ui
|
|
2
|
+
|
|
3
|
+
GDPR **cookie-consent banner** + **privacy/terms modals** (RN-web) for the dloizides.com portfolio.
|
|
4
|
+
Reads theme + translations from the shared `@dloizides/ui-feedback` context (`useUi`) and icons from
|
|
5
|
+
`@dloizides/ui-icons`.
|
|
6
|
+
|
|
7
|
+
## Components
|
|
8
|
+
|
|
9
|
+
| Export | Purpose |
|
|
10
|
+
|--------|---------|
|
|
11
|
+
| `CookieConsentBanner` | Bottom-of-screen GDPR banner: accept all / reject all / customise; persists in localStorage. |
|
|
12
|
+
| `useCookieConsent` | Hook: `{ consent, showBanner, acceptAll, rejectAll, savePreferences }`. |
|
|
13
|
+
| `PrivacyPolicyModal` / `TermsOfServiceModal` | Full-screen legal modals built from translated sections. |
|
|
14
|
+
| `LegalSection` | Title + body block used inside the modals. |
|
|
15
|
+
| `ConsentButton` | The banner's button primitive. |
|
|
16
|
+
| `LEGAL_TEST_IDS`, `COOKIE_CONSENT_STORAGE_KEY`, `CONSENT_VERSION`, `CookieConsent` | constants/types. |
|
|
17
|
+
|
|
18
|
+
`LegalPage` (the full standalone legal screen) is intentionally NOT here — it couples to app-specific
|
|
19
|
+
landing layout + SEO; extract when shared.
|
|
20
|
+
|
|
21
|
+
## Install
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install @dloizides/legal-ui @dloizides/ui-feedback @dloizides/ui-icons react-native-svg
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
Mount a `FeedbackUiProvider` / `UiProvider` (from `@dloizides/ui-feedback`) at the app root, then render
|
|
30
|
+
the banner once:
|
|
31
|
+
|
|
32
|
+
```tsx
|
|
33
|
+
import { CookieConsentBanner } from '@dloizides/legal-ui';
|
|
34
|
+
|
|
35
|
+
<CookieConsentBanner />
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The components call the injected `t(key)` with `cookieConsent.*`, `legal.privacyPolicy.*`,
|
|
39
|
+
`legal.termsOfService.*` and `common.close*` keys — provide them in your locale files.
|
|
40
|
+
|
|
41
|
+
## License
|
|
42
|
+
|
|
43
|
+
MIT
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* GDPR Cookie Consent Banner.
|
|
5
|
+
*
|
|
6
|
+
* Appears at the bottom of the screen on first visit. Allows the user to accept all,
|
|
7
|
+
* reject all, or customise analytics/marketing cookies. Consent is persisted in
|
|
8
|
+
* localStorage (via useCookieConsent) so the banner only shows once.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
declare const CookieConsentBanner: () => React.ReactElement | null;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Reusable button for the cookie consent banner.
|
|
15
|
+
* Supports primary (filled) and secondary (outlined) variants. Colours are passed in.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
interface ConsentButtonProps {
|
|
19
|
+
label: string;
|
|
20
|
+
testID: string;
|
|
21
|
+
textColor: string;
|
|
22
|
+
onPress: () => void;
|
|
23
|
+
a11yHint: string;
|
|
24
|
+
primary?: boolean;
|
|
25
|
+
primaryColor?: string;
|
|
26
|
+
borderColor?: string;
|
|
27
|
+
}
|
|
28
|
+
declare const ConsentButton: ({ label, testID, textColor, onPress, a11yHint, primary, primaryColor, borderColor, }: ConsentButtonProps) => React.ReactElement;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Types for the GDPR cookie consent system.
|
|
32
|
+
*/
|
|
33
|
+
/** Current version of the consent schema. Bump when consent categories change. */
|
|
34
|
+
declare const CONSENT_VERSION = "1.0";
|
|
35
|
+
/** Shape of the consent record persisted in localStorage. */
|
|
36
|
+
interface CookieConsent {
|
|
37
|
+
/** Always true — essential cookies cannot be disabled. */
|
|
38
|
+
necessary: true;
|
|
39
|
+
/** Whether the user opted in to analytics cookies. */
|
|
40
|
+
analytics: boolean;
|
|
41
|
+
/** Whether the user opted in to marketing cookies. */
|
|
42
|
+
marketing: boolean;
|
|
43
|
+
/** ISO-8601 timestamp of when consent was given. */
|
|
44
|
+
consentedAt: string;
|
|
45
|
+
/** Schema version that was active when consent was captured. */
|
|
46
|
+
version: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface UseCookieConsentReturn {
|
|
50
|
+
/** Current consent record, or null if user has not yet responded. */
|
|
51
|
+
consent: CookieConsent | null;
|
|
52
|
+
/** Whether the banner should be shown (no consent recorded yet). */
|
|
53
|
+
showBanner: boolean;
|
|
54
|
+
/** Accept all cookie categories. */
|
|
55
|
+
acceptAll: () => void;
|
|
56
|
+
/** Reject all optional cookie categories. */
|
|
57
|
+
rejectAll: () => void;
|
|
58
|
+
/** Save custom category preferences. */
|
|
59
|
+
savePreferences: (analytics: boolean, marketing: boolean) => void;
|
|
60
|
+
}
|
|
61
|
+
declare function useCookieConsent(): UseCookieConsentReturn;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Privacy Policy modal — full-screen scrollable legal text built from translated sections.
|
|
65
|
+
* Content keys live in the consuming app's locale files (legal.privacyPolicy.*).
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
interface PrivacyPolicyModalProps {
|
|
69
|
+
visible: boolean;
|
|
70
|
+
onClose: () => void;
|
|
71
|
+
/** ISO date shown in the "last updated" line. Defaults to the bundled placeholder. */
|
|
72
|
+
lastUpdated?: string;
|
|
73
|
+
}
|
|
74
|
+
declare const PrivacyPolicyModal: ({ visible, onClose, lastUpdated, }: PrivacyPolicyModalProps) => React.ReactElement;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Terms of Service modal — full-screen scrollable legal text built from translated sections.
|
|
78
|
+
* Content keys live in the consuming app's locale files (legal.termsOfService.*).
|
|
79
|
+
*/
|
|
80
|
+
|
|
81
|
+
interface TermsOfServiceModalProps {
|
|
82
|
+
visible: boolean;
|
|
83
|
+
onClose: () => void;
|
|
84
|
+
/** ISO date shown in the "last updated" line. Defaults to the bundled placeholder. */
|
|
85
|
+
lastUpdated?: string;
|
|
86
|
+
}
|
|
87
|
+
declare const TermsOfServiceModal: ({ visible, onClose, lastUpdated, }: TermsOfServiceModalProps) => React.ReactElement;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* A single section within a legal page (title + body text).
|
|
91
|
+
*/
|
|
92
|
+
|
|
93
|
+
interface LegalSectionProps {
|
|
94
|
+
title: string;
|
|
95
|
+
body: string;
|
|
96
|
+
}
|
|
97
|
+
declare const LegalSection: ({ title, body }: LegalSectionProps) => React.ReactElement;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* localStorage key for the persisted consent record. Kept as the exact string the
|
|
101
|
+
* apps already used so existing visitors' stored consent is preserved after migration.
|
|
102
|
+
*/
|
|
103
|
+
declare const COOKIE_CONSENT_STORAGE_KEY = "COOKIE_CONSENT";
|
|
104
|
+
/**
|
|
105
|
+
* Default testID strings — match the values the consuming apps already used so existing
|
|
106
|
+
* Playwright selectors keep working.
|
|
107
|
+
*/
|
|
108
|
+
declare const LEGAL_TEST_IDS: {
|
|
109
|
+
readonly cookieBanner: "cookie-consent-banner";
|
|
110
|
+
readonly cookieAcceptAll: "cookie-consent-accept-all";
|
|
111
|
+
readonly cookieRejectAll: "cookie-consent-reject-all";
|
|
112
|
+
readonly cookieCustomize: "cookie-consent-customize";
|
|
113
|
+
readonly cookieSavePreferences: "cookie-consent-save-preferences";
|
|
114
|
+
readonly cookieEssentialToggle: "cookie-consent-essential-toggle";
|
|
115
|
+
readonly cookieAnalyticsToggle: "cookie-consent-analytics-toggle";
|
|
116
|
+
readonly cookieMarketingToggle: "cookie-consent-marketing-toggle";
|
|
117
|
+
readonly cookiePrivacyLink: "cookie-consent-privacy-link";
|
|
118
|
+
readonly privacyPolicyScreen: "privacy-policy-screen";
|
|
119
|
+
readonly privacyPolicyClose: "privacy-policy-close";
|
|
120
|
+
readonly termsOfServiceScreen: "terms-of-service-screen";
|
|
121
|
+
readonly termsOfServiceClose: "terms-of-service-close";
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export { CONSENT_VERSION, COOKIE_CONSENT_STORAGE_KEY, ConsentButton, type ConsentButtonProps, type CookieConsent, CookieConsentBanner, LEGAL_TEST_IDS, LegalSection, type LegalSectionProps, PrivacyPolicyModal, type PrivacyPolicyModalProps, TermsOfServiceModal, type TermsOfServiceModalProps, type UseCookieConsentReturn, useCookieConsent };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* GDPR Cookie Consent Banner.
|
|
5
|
+
*
|
|
6
|
+
* Appears at the bottom of the screen on first visit. Allows the user to accept all,
|
|
7
|
+
* reject all, or customise analytics/marketing cookies. Consent is persisted in
|
|
8
|
+
* localStorage (via useCookieConsent) so the banner only shows once.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
declare const CookieConsentBanner: () => React.ReactElement | null;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Reusable button for the cookie consent banner.
|
|
15
|
+
* Supports primary (filled) and secondary (outlined) variants. Colours are passed in.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
interface ConsentButtonProps {
|
|
19
|
+
label: string;
|
|
20
|
+
testID: string;
|
|
21
|
+
textColor: string;
|
|
22
|
+
onPress: () => void;
|
|
23
|
+
a11yHint: string;
|
|
24
|
+
primary?: boolean;
|
|
25
|
+
primaryColor?: string;
|
|
26
|
+
borderColor?: string;
|
|
27
|
+
}
|
|
28
|
+
declare const ConsentButton: ({ label, testID, textColor, onPress, a11yHint, primary, primaryColor, borderColor, }: ConsentButtonProps) => React.ReactElement;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Types for the GDPR cookie consent system.
|
|
32
|
+
*/
|
|
33
|
+
/** Current version of the consent schema. Bump when consent categories change. */
|
|
34
|
+
declare const CONSENT_VERSION = "1.0";
|
|
35
|
+
/** Shape of the consent record persisted in localStorage. */
|
|
36
|
+
interface CookieConsent {
|
|
37
|
+
/** Always true — essential cookies cannot be disabled. */
|
|
38
|
+
necessary: true;
|
|
39
|
+
/** Whether the user opted in to analytics cookies. */
|
|
40
|
+
analytics: boolean;
|
|
41
|
+
/** Whether the user opted in to marketing cookies. */
|
|
42
|
+
marketing: boolean;
|
|
43
|
+
/** ISO-8601 timestamp of when consent was given. */
|
|
44
|
+
consentedAt: string;
|
|
45
|
+
/** Schema version that was active when consent was captured. */
|
|
46
|
+
version: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface UseCookieConsentReturn {
|
|
50
|
+
/** Current consent record, or null if user has not yet responded. */
|
|
51
|
+
consent: CookieConsent | null;
|
|
52
|
+
/** Whether the banner should be shown (no consent recorded yet). */
|
|
53
|
+
showBanner: boolean;
|
|
54
|
+
/** Accept all cookie categories. */
|
|
55
|
+
acceptAll: () => void;
|
|
56
|
+
/** Reject all optional cookie categories. */
|
|
57
|
+
rejectAll: () => void;
|
|
58
|
+
/** Save custom category preferences. */
|
|
59
|
+
savePreferences: (analytics: boolean, marketing: boolean) => void;
|
|
60
|
+
}
|
|
61
|
+
declare function useCookieConsent(): UseCookieConsentReturn;
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Privacy Policy modal — full-screen scrollable legal text built from translated sections.
|
|
65
|
+
* Content keys live in the consuming app's locale files (legal.privacyPolicy.*).
|
|
66
|
+
*/
|
|
67
|
+
|
|
68
|
+
interface PrivacyPolicyModalProps {
|
|
69
|
+
visible: boolean;
|
|
70
|
+
onClose: () => void;
|
|
71
|
+
/** ISO date shown in the "last updated" line. Defaults to the bundled placeholder. */
|
|
72
|
+
lastUpdated?: string;
|
|
73
|
+
}
|
|
74
|
+
declare const PrivacyPolicyModal: ({ visible, onClose, lastUpdated, }: PrivacyPolicyModalProps) => React.ReactElement;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Terms of Service modal — full-screen scrollable legal text built from translated sections.
|
|
78
|
+
* Content keys live in the consuming app's locale files (legal.termsOfService.*).
|
|
79
|
+
*/
|
|
80
|
+
|
|
81
|
+
interface TermsOfServiceModalProps {
|
|
82
|
+
visible: boolean;
|
|
83
|
+
onClose: () => void;
|
|
84
|
+
/** ISO date shown in the "last updated" line. Defaults to the bundled placeholder. */
|
|
85
|
+
lastUpdated?: string;
|
|
86
|
+
}
|
|
87
|
+
declare const TermsOfServiceModal: ({ visible, onClose, lastUpdated, }: TermsOfServiceModalProps) => React.ReactElement;
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* A single section within a legal page (title + body text).
|
|
91
|
+
*/
|
|
92
|
+
|
|
93
|
+
interface LegalSectionProps {
|
|
94
|
+
title: string;
|
|
95
|
+
body: string;
|
|
96
|
+
}
|
|
97
|
+
declare const LegalSection: ({ title, body }: LegalSectionProps) => React.ReactElement;
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* localStorage key for the persisted consent record. Kept as the exact string the
|
|
101
|
+
* apps already used so existing visitors' stored consent is preserved after migration.
|
|
102
|
+
*/
|
|
103
|
+
declare const COOKIE_CONSENT_STORAGE_KEY = "COOKIE_CONSENT";
|
|
104
|
+
/**
|
|
105
|
+
* Default testID strings — match the values the consuming apps already used so existing
|
|
106
|
+
* Playwright selectors keep working.
|
|
107
|
+
*/
|
|
108
|
+
declare const LEGAL_TEST_IDS: {
|
|
109
|
+
readonly cookieBanner: "cookie-consent-banner";
|
|
110
|
+
readonly cookieAcceptAll: "cookie-consent-accept-all";
|
|
111
|
+
readonly cookieRejectAll: "cookie-consent-reject-all";
|
|
112
|
+
readonly cookieCustomize: "cookie-consent-customize";
|
|
113
|
+
readonly cookieSavePreferences: "cookie-consent-save-preferences";
|
|
114
|
+
readonly cookieEssentialToggle: "cookie-consent-essential-toggle";
|
|
115
|
+
readonly cookieAnalyticsToggle: "cookie-consent-analytics-toggle";
|
|
116
|
+
readonly cookieMarketingToggle: "cookie-consent-marketing-toggle";
|
|
117
|
+
readonly cookiePrivacyLink: "cookie-consent-privacy-link";
|
|
118
|
+
readonly privacyPolicyScreen: "privacy-policy-screen";
|
|
119
|
+
readonly privacyPolicyClose: "privacy-policy-close";
|
|
120
|
+
readonly termsOfServiceScreen: "terms-of-service-screen";
|
|
121
|
+
readonly termsOfServiceClose: "terms-of-service-close";
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
export { CONSENT_VERSION, COOKIE_CONSENT_STORAGE_KEY, ConsentButton, type ConsentButtonProps, type CookieConsent, CookieConsentBanner, LEGAL_TEST_IDS, LegalSection, type LegalSectionProps, PrivacyPolicyModal, type PrivacyPolicyModalProps, TermsOfServiceModal, type TermsOfServiceModalProps, type UseCookieConsentReturn, useCookieConsent };
|