@privacykit/web 0.1.0 → 0.1.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@privacykit/web",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Developer-friendly GDPR consent management with real enforcement.",
5
5
  "main": "index.js",
6
6
  "keywords": [
@@ -14,5 +14,17 @@
14
14
  "license": "MIT",
15
15
  "devDependencies": {
16
16
  "typescript": "^6.0.3"
17
+ },
18
+ "files": [
19
+ "dist",
20
+ "privacykit.d.ts",
21
+ "styles.css",
22
+ "readme.md"
23
+ ],
24
+ "scripts": {
25
+ "sync-types": "cp ../privacykit-sdk/public/privacykit.d.ts ./privacykit.d.ts",
26
+ "update:patch": "npm run sync-types && npm version patch",
27
+ "update:minor": "npm run sync-types && npm version minor",
28
+ "publish": "npm publish"
17
29
  }
18
30
  }
@@ -0,0 +1,373 @@
1
+ export {};
2
+
3
+ declare global {
4
+ /**
5
+ * PrivacyKit web component type declarations.
6
+ *
7
+ * Drop this file into any TypeScript project and add it to the
8
+ * "include" array in tsconfig.json, or place it in a `types/` folder
9
+ * that TypeScript already scans.
10
+ *
11
+ * Supported components:
12
+ * <consent-dialog> — cookie consent banner / modal
13
+ * <consent-guard> — conditionally renders content based on consent
14
+ * <consent-missing> — fallback shown when consent is absent
15
+ *
16
+ * CDN usage:
17
+ * PrivacyKit web components are distributed as static assets through a CDN.
18
+ * Add this to your <head> (module builds):
19
+ * <script type="module" src="https://cdn.privacykit.eu/v1/privacykit.esm.js"></script>
20
+ *
21
+ * Framework notes:
22
+ * - React: JSX typings are included below (React 18 global + scoped JSX).
23
+ * - Vue 3: no extra typings required; configure `compilerOptions.isCustomElement`
24
+ * for `consent-dialog`, `consent-guard`, and `consent-missing`.
25
+ * - Angular: no extra typings required; add `CUSTOM_ELEMENTS_SCHEMA` where
26
+ * these elements are used.
27
+ * - Svelte: no extra typings required for runtime usage.
28
+ */
29
+
30
+ // ── Shared types ──────────────────────────────────────────────────────────────
31
+
32
+ /** Visual variant of the consent dialog. */
33
+ type ConsentDialogVariant = 'standard' | 'modern' | 'modest' | 'panel';
34
+
35
+ /** Token preset theme of the consent dialog. */
36
+ type ConsentDialogTheme = 'standard' | 'dark' | 'teal' | 'slate' | 'light' | 'vibrant' | 'high-contrast';
37
+
38
+ /** Locale supported by PrivacyKit. Falls back to 'en'. */
39
+ type ConsentDialogLocale = 'da' | 'de' | 'en' | 'es' | 'fi' | 'fr' | 'it' | 'nl' | 'no' | 'pl' | 'sv';
40
+
41
+ /**
42
+ * Payload dispatched on `window` as the `privacykit:consent-changed` event.
43
+ *
44
+ * @example
45
+ * window.addEventListener('privacykit:consent-changed', (e) => {
46
+ * const { consent, mode } = (e as CustomEvent<PrivacyKitConsentChangedDetail>).detail;
47
+ * });
48
+ */
49
+ interface PrivacyKitConsentChangedDetail {
50
+ consent: {
51
+ analytics: boolean;
52
+ marketing: boolean;
53
+ preferences: boolean;
54
+ };
55
+ mode: 'accept-all' | 'accept-selected' | 'reject-all';
56
+ timestamp: string;
57
+ }
58
+
59
+ interface PrivacyKitConsentState {
60
+ analytics: boolean;
61
+ marketing: boolean;
62
+ preferences: boolean;
63
+ }
64
+
65
+ interface PrivacyKitSubscriptionStatus {
66
+ status: string | null;
67
+ billingInterval: string | null;
68
+ subscriptionEnd: string | null;
69
+ trailingEnd: string | null;
70
+ }
71
+
72
+ interface PrivacyKitGlobalApi {
73
+ readConsent(): PrivacyKitConsentState | null;
74
+ hasConsent(expression?: string): boolean;
75
+ onConsentChanged(callback: (consent: PrivacyKitConsentState | null) => void): () => void;
76
+ openConsentDialog(): void;
77
+ openPrivacyPolicyDialog(): void;
78
+ onConsentDialogClosed(callback: () => void): () => void;
79
+ getSubscriptionStatus(): PrivacyKitSubscriptionStatus | null;
80
+ /**
81
+ * Toggle the compliance monitor UI by flipping the `debug` prop on the <compliance-monitor> element.
82
+ * No parameters; flips the current debug state.
83
+ */
84
+ toggleComplianceMonitor(): void;
85
+ /**
86
+ * Subscribes to the privacykit:ready event. Callback is called when PrivacyKit is ready.
87
+ * Replay-safe: if PrivacyKit is already ready when you subscribe, the callback still runs once.
88
+ * Returns an unsubscribe function.
89
+ */
90
+ onReady(callback: () => void): () => void;
91
+ subscriptionStatus?: PrivacyKitSubscriptionStatus | null;
92
+ }
93
+
94
+ // ── DOM element interfaces ────────────────────────────────────────────────────
95
+
96
+ /**
97
+ * `<consent-dialog>` — the public entry component.
98
+ *
99
+ * Manages open/close state, locale resolution, and variant routing.
100
+ * All visual rendering is delegated to the active design variant.
101
+ *
102
+ * Named slots for content overrides:
103
+ * - `dialog-logo` Optional logo content shown next to the title
104
+ * - `dialog-logo-alt` Alternative location for your brand logo
105
+ * - `dialog-title` Override the dialog heading
106
+ * - `dialog-summary-part-1` Override the first summary paragraph
107
+ * - `dialog-summary-part-2` Override the second summary paragraph
108
+ * - `necessary-content` Override "Functional cookies" body text
109
+ * - `preferences-content` Override "Preferences" body text
110
+ * - `analytics-content` Override "Analytics" body text
111
+ * - `marketing-content` Override "Marketing" body text
112
+ * - `read-more-title` Override the "Read more" label
113
+ * - `read-more-content` Override the read-more body text
114
+ * - `privacy-policy-content` Override the privacy policy content
115
+ *
116
+ * CSS custom properties:
117
+ * --pk-bg-color Dialog background color
118
+ * --pk-text-color Dialog text color
119
+ * --pk-primary-color Accent / primary color
120
+ * --pk-border-width Border width
121
+ * --pk-radius Border radius
122
+ * --pk-dialog-max-height Dialog max height
123
+ * --pk-font-family Font family
124
+ * --pk-spacing-unit Base spacing unit (rem)
125
+ */
126
+ interface HTMLConsentDialogElement extends HTMLElement {
127
+ /** Visual variant for consent UI. @default 'standard' */
128
+ variant: ConsentDialogVariant;
129
+ /** Token preset theme for dialog design tokens. @default 'standard' */
130
+ theme: ConsentDialogTheme;
131
+ /** Cookie TTL in days. @default 180 */
132
+ expiresDays: number;
133
+ /** Schema version string; triggers re-consent when changed. @default 0 */
134
+ version: number;
135
+ /** Explicit locale override. Auto-detected from browser when omitted. */
136
+ locale: string | undefined;
137
+ /** Hide the "Strictly necessary" section from the dialog. */
138
+ hideNecessary: boolean | undefined;
139
+ /** Hide the "Preferences" section from the dialog. */
140
+ hidePreferences: boolean | undefined;
141
+ /** Hide the "Analytics" section from the dialog. */
142
+ hideAnalytics: boolean | undefined;
143
+ /** Hide the "Marketing" section from the dialog. */
144
+ hideMarketing: boolean | undefined;
145
+ /** Hide the expandable "Read more" section from the dialog. */
146
+ hideReadmore: boolean | undefined;
147
+ /** Hide the default Privacy Policy link in the footer. */
148
+ hidePrivacyPolicyLink: boolean | undefined;
149
+ /** Override the privacy policy link to redirect to an external URL instead of opening the internal privacy policy dialog. */
150
+ privacyPolicyUrl: string | undefined;
151
+ /** Hide the second summary paragraph from the dialog. */
152
+ hideSummaryPart2: boolean | undefined;
153
+ /** Demo mode: disables auto-open and mocks subscription status. */
154
+ demo: boolean | undefined;
155
+ /** Show a floating action button to re-open the dialog. Only visible once a consent cookie exists. @default false */
156
+ showFab: boolean;
157
+ /** Position of the FAB in the viewport. @default 'left' */
158
+ fabPosition: 'left' | 'right';
159
+ /** Whether the dialog is currently open. @default false */
160
+ open: boolean;
161
+
162
+ /** Programmatically open the dialog. */
163
+ openDialog(): Promise<void>;
164
+ /** Programmatically close the dialog. */
165
+ closeDialog(): Promise<void>;
166
+ /** Re-fetch the subscription status from the API. */
167
+ checkSubscriptionStatus(): Promise<void>;
168
+ }
169
+
170
+ /**
171
+ * `<consent-guard>` — renders slot content only when the required consent is granted.
172
+ *
173
+ * Activates `<script type="text/plain">` children by cloning them as live scripts.
174
+ * Listens to the `privacykit:consent-changed` window event for reactive updates.
175
+ *
176
+ * @example Single category
177
+ * <consent-guard consent="analytics">...</consent-guard>
178
+ *
179
+ * @example AND — require all listed (space-separated with `+`)
180
+ * <consent-guard consent="analytics+marketing">...</consent-guard>
181
+ *
182
+ * @example OR — require any one (pipe-separated)
183
+ * <consent-guard consent="analytics|marketing">...</consent-guard>
184
+ *
185
+ * @example Default — omit `consent` to require ALL categories
186
+ * <consent-guard>...</consent-guard>
187
+ */
188
+ interface HTMLConsentGuardElement extends HTMLElement {
189
+ /**
190
+ * Consent expression to evaluate. Omit to require ALL categories.
191
+ *
192
+ * Single: `"analytics"` | `"marketing"` | `"preferences"`
193
+ * AND (all): `"analytics+marketing"` | `"analytics+marketing+preferences"`
194
+ * OR (any): `"analytics|marketing"` | `"analytics|preferences"`
195
+ */
196
+ consent: string | undefined;
197
+ }
198
+
199
+ /**
200
+ * `<consent-missing>` — shows fallback content when a paired `<consent-guard>` is blocked.
201
+ *
202
+ * Observes attribute changes on the target guard element and displays its
203
+ * slot content whenever `data-pk-blocked` is present on the guard.
204
+ *
205
+ * @example
206
+ * <consent-guard consent="analytics" id="analytics-guard">...</consent-guard>
207
+ * <consent-missing for="analytics-guard">Please accept analytics to continue.</consent-missing>
208
+ */
209
+ interface HTMLConsentMissingElement extends HTMLElement {
210
+ /** The `id` of the paired `<consent-guard>` element. */
211
+ for: string;
212
+ }
213
+
214
+ /**
215
+ * `<compliance-monitor>` — developer compliance monitor for outgoing requests.
216
+ *
217
+ * Shows a floating action button (FAB) and dialog UI for monitoring outgoing
218
+ * network requests and their consent/guard status. Intended for developer/debug use.
219
+ *
220
+ * Props:
221
+ * - `debug` (boolean): Show FAB and enable monitor UI (default: false)
222
+ * - `delay` (number): Observation window in ms (default: 5000)
223
+ * - `compliance-state` (string): Current compliance state (readonly, for status)
224
+ *
225
+ * Usage:
226
+ * <compliance-monitor debug delay="5000"></compliance-monitor>
227
+ */
228
+ interface HTMLComplianceMonitorElement extends HTMLElement {
229
+ /** Show FAB and enable monitor UI. */
230
+ debug: boolean;
231
+ /** Observation window in ms. */
232
+ delay: number;
233
+ /** Exclude requests to first-party subdomains from compliance checks. @default true */
234
+ ignoreFirstPartySubdomains: boolean;
235
+ /** Position of the FAB in the viewport (vertically centered). @default 'right' */
236
+ fabPosition: 'left' | 'right';
237
+ /** Current compliance state (readonly). */
238
+ complianceState: 'observing' | 'observation_complete_success' | 'observation_complete_warning';
239
+ }
240
+
241
+ interface Window {
242
+ PrivacyKit?: PrivacyKitGlobalApi;
243
+ }
244
+
245
+ interface HTMLElementTagNameMap {
246
+ 'consent-dialog': HTMLConsentDialogElement;
247
+ 'consent-guard': HTMLConsentGuardElement;
248
+ 'consent-missing': HTMLConsentMissingElement;
249
+ 'compliance-monitor': HTMLComplianceMonitorElement;
250
+ }
251
+
252
+ interface WindowEventMap {
253
+ 'privacykit:consent-changed': CustomEvent<PrivacyKitConsentChangedDetail>;
254
+ }
255
+ }
256
+
257
+ // ── React JSX augmentation ────────────────────────────────────────────────────
258
+ //
259
+ // React passes custom element props as DOM attributes. Boolean Stencil props
260
+ // (e.g. `noNecessary`) map to their kebab-case HTML attribute names (e.g.
261
+ // `no-necessary`). Presence without a value or `={true}` both set the attribute.
262
+ //
263
+ // Ref: React 19 (used by Next.js 15+) has full custom-element support — props
264
+ // that are not event handlers are passed as attributes automatically.
265
+
266
+ type CKRef<T> = { current: T | null } | ((instance: T | null) => void) | null;
267
+
268
+ interface ConsentDialogJSXProps {
269
+ /** Visual variant. @default 'standard' */
270
+ 'variant'?: ConsentDialogVariant;
271
+ /** Token preset theme. @default 'standard' */
272
+ 'theme'?: ConsentDialogTheme;
273
+ /** Cookie TTL in days. @default 180 */
274
+ 'expires-days'?: number;
275
+ /** Policy version; bump to force re-consent. @default 0 */
276
+ 'version'?: number;
277
+ /** Locale override. Defaults to browser locale. */
278
+ 'locale'?: string;
279
+ /** Hide the "Strictly necessary" section. */
280
+ 'hide-necessary'?: boolean | '';
281
+ /** Hide the "Preferences" section. */
282
+ 'hide-preferences'?: boolean | '';
283
+ /** Hide the "Analytics" section. */
284
+ 'hide-analytics'?: boolean | '';
285
+ /** Hide the "Marketing" section. */
286
+ 'hide-marketing'?: boolean | '';
287
+ /** Hide the second summary paragraph. */
288
+ 'hide-summary-part-2'?: boolean | '';
289
+ /** Enable demo mode. */
290
+ 'demo'?: boolean | '';
291
+ /** Show a floating action button to re-open the dialog once consent has been given. @default false */
292
+ 'show-fab'?: boolean | '';
293
+ /** Position of the FAB: bottom-left or bottom-right. @default 'left' */
294
+ 'fab-position'?: 'left' | 'right';
295
+ /** Open/close state. */
296
+ 'open'?: boolean | '';
297
+ 'ref'?: CKRef<HTMLConsentDialogElement>;
298
+ 'children'?: unknown;
299
+ /** Inline styles — pass CSS custom properties like `--pk-primary-color` here. */
300
+ 'style'?: Record<string, string | number>;
301
+ 'class'?: string;
302
+ 'className'?: string;
303
+ 'id'?: string;
304
+ }
305
+
306
+ interface ConsentGuardJSXProps {
307
+ /**
308
+ * Consent expression. Omit to require ALL categories.
309
+ *
310
+ * Single: `"analytics"` | `"marketing"` | `"preferences"`
311
+ * AND (all): `"analytics+marketing"` | `"analytics+marketing+preferences"`
312
+ * OR (any): `"analytics|marketing"` | `"analytics|preferences"`
313
+ */
314
+ consent?: string;
315
+ ref?: CKRef<HTMLConsentGuardElement>;
316
+ children?: unknown;
317
+ style?: Record<string, string | number>;
318
+ class?: string;
319
+ className?: string;
320
+ id?: string;
321
+ }
322
+
323
+ interface ConsentMissingJSXProps {
324
+ /** ID of the paired `<consent-guard>` element. */
325
+ for: string;
326
+ ref?: CKRef<HTMLConsentMissingElement>;
327
+ children?: unknown;
328
+ style?: Record<string, string | number>;
329
+ class?: string;
330
+ className?: string;
331
+ id?: string;
332
+ }
333
+
334
+ interface ComplianceMonitorJSXProps {
335
+ /** Show FAB and enable monitor UI. */
336
+ 'debug'?: boolean | '';
337
+ /** Observation window in ms. */
338
+ 'delay'?: number;
339
+ /** Exclude requests to first-party subdomains from compliance checks. @default true */
340
+ 'ignore-first-party-subdomains'?: boolean | '';
341
+ /** Position of the FAB in the viewport (vertically centered). @default 'right' */
342
+ 'fab-position'?: 'left' | 'right';
343
+ /** Current compliance state (readonly). */
344
+ 'compliance-state'?: 'observing' | 'observation_complete_success' | 'observation_complete_warning';
345
+ 'ref'?: CKRef<HTMLComplianceMonitorElement>;
346
+ 'style'?: Record<string, string | number>;
347
+ 'class'?: string;
348
+ 'className'?: string;
349
+ 'id'?: string;
350
+ }
351
+
352
+ // React 18 global JSX namespace (also consumed by older Next.js setups)
353
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
354
+ declare namespace JSX {
355
+ interface IntrinsicElements {
356
+ 'consent-dialog': ConsentDialogJSXProps;
357
+ 'consent-guard': ConsentGuardJSXProps;
358
+ 'consent-missing': ConsentMissingJSXProps;
359
+ 'compliance-monitor': ComplianceMonitorJSXProps;
360
+ }
361
+ }
362
+
363
+ // React 18+ scoped JSX namespace (preferred in modern Next.js / React setups)
364
+ declare module 'react' {
365
+ namespace JSX {
366
+ interface IntrinsicElements {
367
+ 'consent-dialog': ConsentDialogJSXProps;
368
+ 'consent-guard': ConsentGuardJSXProps;
369
+ 'consent-missing': ConsentMissingJSXProps;
370
+ 'compliance-monitor': ComplianceMonitorJSXProps;
371
+ }
372
+ }
373
+ }
package/styles.css ADDED
@@ -0,0 +1,11 @@
1
+ consent-dialog:not(:defined) [slot] {
2
+ display: none;
3
+ }
4
+
5
+ consent-guard:not([active]) {
6
+ display: none;
7
+ }
8
+
9
+ consent-missing:not([active]) {
10
+ display: none;
11
+ }
package/src/index.ts DELETED
@@ -1 +0,0 @@
1
- export const PRIVACYKIT_PACKAGE_VERSION = "0.1.0";