@pallasoft/ps-core-components 2.33.0 → 2.34.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 (67) hide show
  1. package/dist/analytics/index.d.ts +12 -0
  2. package/dist/analytics/index.js +28 -0
  3. package/dist/analytics/report-client-error.d.ts +1 -0
  4. package/dist/analytics/report-client-error.js +6 -0
  5. package/dist/components/ps-analytics-provider.d.ts +14 -0
  6. package/dist/components/ps-analytics-provider.js +72 -0
  7. package/dist/components/ps-client-error-reporter.d.ts +5 -0
  8. package/dist/components/ps-client-error-reporter.js +22 -0
  9. package/dist/components/ps-consent-banner.d.ts +11 -0
  10. package/dist/components/ps-consent-banner.js +21 -0
  11. package/dist/constants/ps-analytics-config.d.ts +19 -0
  12. package/dist/constants/ps-analytics-config.js +22 -0
  13. package/dist/constants/ps-client-error-config.d.ts +23 -0
  14. package/dist/constants/ps-client-error-config.js +17 -0
  15. package/dist/esm/analytics/index.js +12 -0
  16. package/dist/esm/analytics/report-client-error.js +2 -0
  17. package/dist/esm/components/ps-analytics-provider.js +68 -0
  18. package/dist/esm/components/ps-client-error-reporter.js +18 -0
  19. package/dist/esm/components/ps-consent-banner.js +17 -0
  20. package/dist/esm/constants/ps-analytics-config.js +19 -0
  21. package/dist/esm/constants/ps-client-error-config.js +14 -0
  22. package/dist/esm/hooks/use-consent.js +17 -0
  23. package/dist/esm/models/analytics-csp-input.js +1 -0
  24. package/dist/esm/models/analytics-csp-origins.js +1 -0
  25. package/dist/esm/models/ps-client-error-payload.js +1 -0
  26. package/dist/esm/models/ps-client-error-settings.js +1 -0
  27. package/dist/esm/models/ps-consent-api.js +1 -0
  28. package/dist/esm/models/ps-consent-choice.js +1 -0
  29. package/dist/esm/models/ps-consent-state.js +1 -0
  30. package/dist/esm/models/ps-gtag-window.js +1 -0
  31. package/dist/esm/services/analytics-csp-service.js +27 -0
  32. package/dist/esm/services/ps-analytics-key-service.js +8 -0
  33. package/dist/esm/services/ps-client-error-service.js +72 -0
  34. package/dist/esm/services/ps-consent-service.js +57 -0
  35. package/dist/esm/services/ps-google-analytics-service.js +41 -0
  36. package/dist/esm/services/ps-post-hog-service.js +18 -0
  37. package/dist/hooks/use-consent.d.ts +2 -0
  38. package/dist/hooks/use-consent.js +21 -0
  39. package/dist/models/analytics-csp-input.d.ts +7 -0
  40. package/dist/models/analytics-csp-input.js +2 -0
  41. package/dist/models/analytics-csp-origins.d.ts +5 -0
  42. package/dist/models/analytics-csp-origins.js +2 -0
  43. package/dist/models/ps-client-error-payload.d.ts +9 -0
  44. package/dist/models/ps-client-error-payload.js +2 -0
  45. package/dist/models/ps-client-error-settings.d.ts +4 -0
  46. package/dist/models/ps-client-error-settings.js +2 -0
  47. package/dist/models/ps-consent-api.d.ts +9 -0
  48. package/dist/models/ps-consent-api.js +2 -0
  49. package/dist/models/ps-consent-choice.d.ts +1 -0
  50. package/dist/models/ps-consent-choice.js +2 -0
  51. package/dist/models/ps-consent-state.d.ts +5 -0
  52. package/dist/models/ps-consent-state.js +2 -0
  53. package/dist/models/ps-gtag-window.d.ts +4 -0
  54. package/dist/models/ps-gtag-window.js +2 -0
  55. package/dist/services/analytics-csp-service.d.ts +7 -0
  56. package/dist/services/analytics-csp-service.js +31 -0
  57. package/dist/services/ps-analytics-key-service.d.ts +3 -0
  58. package/dist/services/ps-analytics-key-service.js +12 -0
  59. package/dist/services/ps-client-error-service.d.ts +14 -0
  60. package/dist/services/ps-client-error-service.js +76 -0
  61. package/dist/services/ps-consent-service.d.ts +15 -0
  62. package/dist/services/ps-consent-service.js +61 -0
  63. package/dist/services/ps-google-analytics-service.d.ts +6 -0
  64. package/dist/services/ps-google-analytics-service.js +45 -0
  65. package/dist/services/ps-post-hog-service.d.ts +4 -0
  66. package/dist/services/ps-post-hog-service.js +55 -0
  67. package/package.json +15 -1
@@ -0,0 +1,57 @@
1
+ import { PsAnalyticsConfig } from '../constants/ps-analytics-config';
2
+ export class PsConsentService {
3
+ static snapshot(cookieName) {
4
+ const existing = this.states.get(cookieName);
5
+ if (existing)
6
+ return existing;
7
+ const state = { choice: this.readCookie(cookieName), isReopened: false };
8
+ this.states.set(cookieName, state);
9
+ return state;
10
+ }
11
+ static subscribe(listener) {
12
+ this.listeners.add(listener);
13
+ return () => {
14
+ this.listeners.delete(listener);
15
+ };
16
+ }
17
+ static choose(cookieName, choice) {
18
+ this.writeCookie(cookieName, choice);
19
+ this.states.set(cookieName, { choice, isReopened: false });
20
+ this.notify();
21
+ }
22
+ static reopen(cookieName) {
23
+ this.states.set(cookieName, { ...this.snapshot(cookieName), isReopened: true });
24
+ this.notify();
25
+ }
26
+ static reset() {
27
+ this.states.clear();
28
+ this.notify();
29
+ }
30
+ static notify() {
31
+ this.listeners.forEach((listener) => listener());
32
+ }
33
+ static readCookie(cookieName) {
34
+ if (typeof document === 'undefined')
35
+ return null;
36
+ const prefix = `${cookieName}=`;
37
+ const entry = document.cookie
38
+ .split(';')
39
+ .map((part) => part.trim())
40
+ .find((part) => part.startsWith(prefix));
41
+ const value = entry ? entry.slice(prefix.length) : '';
42
+ if (value === PsAnalyticsConfig.consentGranted)
43
+ return PsAnalyticsConfig.consentGranted;
44
+ if (value === PsAnalyticsConfig.consentDenied)
45
+ return PsAnalyticsConfig.consentDenied;
46
+ return null;
47
+ }
48
+ static writeCookie(cookieName, choice) {
49
+ if (typeof document === 'undefined')
50
+ return;
51
+ const secure = window.location.protocol === 'https:' ? '; Secure' : '';
52
+ document.cookie = `${cookieName}=${choice}; Path=/; Max-Age=${PsAnalyticsConfig.consentMaxAgeSeconds}; SameSite=Lax${secure}`;
53
+ }
54
+ }
55
+ PsConsentService.serverState = { choice: null, isReopened: false };
56
+ PsConsentService.states = new Map();
57
+ PsConsentService.listeners = new Set();
@@ -0,0 +1,41 @@
1
+ import { PsAnalyticsConfig } from '../constants/ps-analytics-config';
2
+ export class PsGoogleAnalyticsService {
3
+ static load(id, tagManagerUrl, nonce) {
4
+ const target = window;
5
+ Reflect.set(window, `ga-disable-${id}`, false);
6
+ if (typeof target.gtag !== 'function') {
7
+ target.dataLayer = target.dataLayer ? target.dataLayer : [];
8
+ target.gtag = function gtag() {
9
+ target.dataLayer?.push(arguments);
10
+ };
11
+ target.gtag('js', new Date());
12
+ }
13
+ if (document.querySelector(`script[${PsAnalyticsConfig.scriptAttribute}="${id}"]`))
14
+ return;
15
+ const script = document.createElement('script');
16
+ script.async = true;
17
+ script.src = `${tagManagerUrl.replace(/\/+$/, '')}${PsAnalyticsConfig.tagManagerScriptPath}${encodeURIComponent(id)}`;
18
+ script.setAttribute(PsAnalyticsConfig.scriptAttribute, id);
19
+ if (nonce)
20
+ script.setAttribute('nonce', nonce);
21
+ document.head.appendChild(script);
22
+ }
23
+ static configure(id, pathname, userId) {
24
+ const target = window;
25
+ if (typeof target.gtag !== 'function')
26
+ return;
27
+ target.gtag('config', id, {
28
+ send_page_view: false,
29
+ page_path: pathname,
30
+ ...(userId ? { user_id: userId } : {}),
31
+ });
32
+ }
33
+ static clearUser() {
34
+ const target = window;
35
+ if (typeof target.gtag === 'function')
36
+ target.gtag('set', { user_id: undefined });
37
+ }
38
+ static disable(id) {
39
+ Reflect.set(window, `ga-disable-${id}`, true);
40
+ }
41
+ }
@@ -0,0 +1,18 @@
1
+ import { PsAnalyticsConfig } from '../constants/ps-analytics-config';
2
+ export class PsPostHogService {
3
+ static async load(key, apiHost) {
4
+ const module = await import('posthog-js');
5
+ const client = module.default;
6
+ client.init(key, {
7
+ ...(apiHost ? { api_host: apiHost } : {}),
8
+ defaults: PsAnalyticsConfig.postHog.defaults,
9
+ autocapture: PsAnalyticsConfig.postHog.autocapture,
10
+ capture_pageview: false,
11
+ capture_pageleave: PsAnalyticsConfig.postHog.capturePageleave,
12
+ capture_exceptions: PsAnalyticsConfig.postHog.captureExceptions,
13
+ person_profiles: PsAnalyticsConfig.postHog.personProfiles,
14
+ });
15
+ client.opt_in_capturing();
16
+ return client;
17
+ }
18
+ }
@@ -0,0 +1,2 @@
1
+ import type { PsConsentApi } from '../models/ps-consent-api';
2
+ export declare const useConsent: (consentCookieName?: string) => PsConsentApi;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useConsent = void 0;
4
+ const react_1 = require("react");
5
+ const ps_analytics_config_1 = require("../constants/ps-analytics-config");
6
+ const ps_consent_service_1 = require("../services/ps-consent-service");
7
+ const useConsent = (consentCookieName = ps_analytics_config_1.PsAnalyticsConfig.defaultConsentCookieName) => {
8
+ const state = (0, react_1.useSyncExternalStore)((listener) => ps_consent_service_1.PsConsentService.subscribe(listener), () => ps_consent_service_1.PsConsentService.snapshot(consentCookieName), () => ps_consent_service_1.PsConsentService.serverState);
9
+ const accept = (0, react_1.useCallback)(() => ps_consent_service_1.PsConsentService.choose(consentCookieName, ps_analytics_config_1.PsAnalyticsConfig.consentGranted), [consentCookieName]);
10
+ const reject = (0, react_1.useCallback)(() => ps_consent_service_1.PsConsentService.choose(consentCookieName, ps_analytics_config_1.PsAnalyticsConfig.consentDenied), [consentCookieName]);
11
+ const reopen = (0, react_1.useCallback)(() => ps_consent_service_1.PsConsentService.reopen(consentCookieName), [consentCookieName]);
12
+ return {
13
+ choice: state.choice,
14
+ isGranted: state.choice === ps_analytics_config_1.PsAnalyticsConfig.consentGranted,
15
+ isBannerOpen: state === ps_consent_service_1.PsConsentService.serverState ? false : state.choice === null || state.isReopened,
16
+ accept,
17
+ reject,
18
+ reopen,
19
+ };
20
+ };
21
+ exports.useConsent = useConsent;
@@ -0,0 +1,7 @@
1
+ export interface AnalyticsCspInput {
2
+ googleAnalyticsId?: string;
3
+ googleAnalyticsUrls?: string;
4
+ googleTagManagerUrls?: string;
5
+ postHogKey?: string;
6
+ postHogUrls?: string;
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,5 @@
1
+ export interface AnalyticsCspOrigins {
2
+ scriptSrc: string[];
3
+ connectSrc: string[];
4
+ imgSrc: string[];
5
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,9 @@
1
+ export interface PsClientErrorPayload {
2
+ message: string;
3
+ stack: string;
4
+ pathname: string;
5
+ appVersion: string;
6
+ userAgentClass: string;
7
+ source: string;
8
+ context: string;
9
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ export interface PsClientErrorSettings {
2
+ endpoint: string;
3
+ appVersion?: string;
4
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,9 @@
1
+ import type { PsConsentChoice } from './ps-consent-choice';
2
+ export interface PsConsentApi {
3
+ choice: PsConsentChoice | null;
4
+ isGranted: boolean;
5
+ isBannerOpen: boolean;
6
+ accept: () => void;
7
+ reject: () => void;
8
+ reopen: () => void;
9
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1 @@
1
+ export type PsConsentChoice = 'granted' | 'denied';
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,5 @@
1
+ import type { PsConsentChoice } from './ps-consent-choice';
2
+ export interface PsConsentState {
3
+ choice: PsConsentChoice | null;
4
+ isReopened: boolean;
5
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ export interface PsGtagWindow extends Window {
2
+ dataLayer?: unknown[];
3
+ gtag?: (...args: unknown[]) => void;
4
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ import type { AnalyticsCspInput } from '../models/analytics-csp-input';
2
+ import type { AnalyticsCspOrigins } from '../models/analytics-csp-origins';
3
+ export declare class AnalyticsCspService {
4
+ static origins(input: AnalyticsCspInput): AnalyticsCspOrigins;
5
+ private static parse;
6
+ private static unique;
7
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AnalyticsCspService = void 0;
4
+ const ps_analytics_config_1 = require("../constants/ps-analytics-config");
5
+ const ps_analytics_key_service_1 = require("./ps-analytics-key-service");
6
+ class AnalyticsCspService {
7
+ static origins(input) {
8
+ const isGoogleOn = ps_analytics_key_service_1.PsAnalyticsKeyService.isEnabled(input.googleAnalyticsId);
9
+ const isPostHogOn = ps_analytics_key_service_1.PsAnalyticsKeyService.isEnabled(input.postHogKey);
10
+ const googleUrls = isGoogleOn ? this.parse(input.googleAnalyticsUrls) : [];
11
+ const tagManagerUrls = isGoogleOn ? this.parse(input.googleTagManagerUrls) : [];
12
+ const postHogUrls = isPostHogOn ? this.parse(input.postHogUrls) : [];
13
+ return {
14
+ scriptSrc: this.unique([...tagManagerUrls, ...postHogUrls]),
15
+ connectSrc: this.unique([...googleUrls, ...tagManagerUrls, ...postHogUrls]),
16
+ imgSrc: this.unique([...googleUrls, ...tagManagerUrls]),
17
+ };
18
+ }
19
+ static parse(value) {
20
+ if (!value)
21
+ return [];
22
+ return value
23
+ .split(ps_analytics_config_1.PsAnalyticsConfig.listSeparator)
24
+ .map((item) => item.trim())
25
+ .filter((item) => ps_analytics_key_service_1.PsAnalyticsKeyService.isEnabled(item));
26
+ }
27
+ static unique(values) {
28
+ return Array.from(new Set(values));
29
+ }
30
+ }
31
+ exports.AnalyticsCspService = AnalyticsCspService;
@@ -0,0 +1,3 @@
1
+ export declare class PsAnalyticsKeyService {
2
+ static isEnabled(value: string | null | undefined): value is string;
3
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsAnalyticsKeyService = void 0;
4
+ const ps_analytics_config_1 = require("../constants/ps-analytics-config");
5
+ class PsAnalyticsKeyService {
6
+ static isEnabled(value) {
7
+ if (value === null || value === undefined)
8
+ return false;
9
+ return !ps_analytics_config_1.PsAnalyticsConfig.offValues.includes(value.trim());
10
+ }
11
+ }
12
+ exports.PsAnalyticsKeyService = PsAnalyticsKeyService;
@@ -0,0 +1,14 @@
1
+ import type { PsClientErrorSettings } from '../models/ps-client-error-settings';
2
+ export declare class PsClientErrorService {
3
+ private static settings;
4
+ private static sentKeys;
5
+ private static sentCount;
6
+ static configure(settings: PsClientErrorSettings): void;
7
+ static clear(): void;
8
+ static reset(): void;
9
+ static report(error: unknown, context?: string, source?: string): void;
10
+ private static payload;
11
+ private static clean;
12
+ private static userAgentClass;
13
+ private static send;
14
+ }
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsClientErrorService = void 0;
4
+ const ps_client_error_config_1 = require("../constants/ps-client-error-config");
5
+ class PsClientErrorService {
6
+ static configure(settings) {
7
+ this.settings = settings;
8
+ }
9
+ static clear() {
10
+ this.settings = null;
11
+ }
12
+ static reset() {
13
+ this.settings = null;
14
+ this.sentKeys.clear();
15
+ this.sentCount = 0;
16
+ }
17
+ static report(error, context = '', source = ps_client_error_config_1.PsClientErrorConfig.sources.boundary) {
18
+ if (!this.settings || typeof window === 'undefined')
19
+ return;
20
+ if (this.sentCount >= ps_client_error_config_1.PsClientErrorConfig.maxReportsPerPage)
21
+ return;
22
+ const payload = this.payload(error, context, source, this.settings);
23
+ const key = `${payload.message}|${payload.context}`;
24
+ if (this.sentKeys.has(key))
25
+ return;
26
+ this.sentKeys.add(key);
27
+ this.sentCount += 1;
28
+ this.send(this.settings.endpoint, JSON.stringify(payload));
29
+ }
30
+ static payload(error, context, source, settings) {
31
+ const isError = error instanceof Error;
32
+ const rawMessage = isError ? error.message : typeof error === 'string' ? error : '';
33
+ return {
34
+ message: this.clean(rawMessage ? rawMessage : ps_client_error_config_1.PsClientErrorConfig.unknownMessage).slice(0, ps_client_error_config_1.PsClientErrorConfig.maxMessageLength),
35
+ stack: isError && error.stack
36
+ ? this.clean(error.stack).slice(0, ps_client_error_config_1.PsClientErrorConfig.maxStackLength)
37
+ : '',
38
+ pathname: window.location.pathname,
39
+ appVersion: settings.appVersion ? settings.appVersion : '',
40
+ userAgentClass: this.userAgentClass(),
41
+ source,
42
+ context: this.clean(context).slice(0, ps_client_error_config_1.PsClientErrorConfig.maxContextLength),
43
+ };
44
+ }
45
+ static clean(value) {
46
+ return value.replace(ps_client_error_config_1.PsClientErrorConfig.emailPattern, ps_client_error_config_1.PsClientErrorConfig.redactedValue);
47
+ }
48
+ static userAgentClass() {
49
+ const agent = typeof navigator === 'undefined' ? '' : navigator.userAgent;
50
+ const classes = ps_client_error_config_1.PsClientErrorConfig.userAgentClasses;
51
+ if (!agent)
52
+ return classes.unknown;
53
+ if (ps_client_error_config_1.PsClientErrorConfig.botPattern.test(agent))
54
+ return classes.bot;
55
+ if (ps_client_error_config_1.PsClientErrorConfig.mobilePattern.test(agent))
56
+ return classes.mobile;
57
+ return classes.desktop;
58
+ }
59
+ static send(endpoint, body) {
60
+ if (typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function') {
61
+ const blob = new Blob([body], { type: ps_client_error_config_1.PsClientErrorConfig.jsonContentType });
62
+ if (navigator.sendBeacon(endpoint, blob))
63
+ return;
64
+ }
65
+ fetch(endpoint, {
66
+ method: 'POST',
67
+ headers: { 'Content-Type': ps_client_error_config_1.PsClientErrorConfig.jsonContentType },
68
+ body,
69
+ keepalive: true,
70
+ }).catch(() => undefined);
71
+ }
72
+ }
73
+ exports.PsClientErrorService = PsClientErrorService;
74
+ PsClientErrorService.settings = null;
75
+ PsClientErrorService.sentKeys = new Set();
76
+ PsClientErrorService.sentCount = 0;
@@ -0,0 +1,15 @@
1
+ import type { PsConsentChoice } from '../models/ps-consent-choice';
2
+ import type { PsConsentState } from '../models/ps-consent-state';
3
+ export declare class PsConsentService {
4
+ static readonly serverState: PsConsentState;
5
+ private static states;
6
+ private static listeners;
7
+ static snapshot(cookieName: string): PsConsentState;
8
+ static subscribe(listener: () => void): () => void;
9
+ static choose(cookieName: string, choice: PsConsentChoice): void;
10
+ static reopen(cookieName: string): void;
11
+ static reset(): void;
12
+ private static notify;
13
+ private static readCookie;
14
+ private static writeCookie;
15
+ }
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsConsentService = void 0;
4
+ const ps_analytics_config_1 = require("../constants/ps-analytics-config");
5
+ class PsConsentService {
6
+ static snapshot(cookieName) {
7
+ const existing = this.states.get(cookieName);
8
+ if (existing)
9
+ return existing;
10
+ const state = { choice: this.readCookie(cookieName), isReopened: false };
11
+ this.states.set(cookieName, state);
12
+ return state;
13
+ }
14
+ static subscribe(listener) {
15
+ this.listeners.add(listener);
16
+ return () => {
17
+ this.listeners.delete(listener);
18
+ };
19
+ }
20
+ static choose(cookieName, choice) {
21
+ this.writeCookie(cookieName, choice);
22
+ this.states.set(cookieName, { choice, isReopened: false });
23
+ this.notify();
24
+ }
25
+ static reopen(cookieName) {
26
+ this.states.set(cookieName, { ...this.snapshot(cookieName), isReopened: true });
27
+ this.notify();
28
+ }
29
+ static reset() {
30
+ this.states.clear();
31
+ this.notify();
32
+ }
33
+ static notify() {
34
+ this.listeners.forEach((listener) => listener());
35
+ }
36
+ static readCookie(cookieName) {
37
+ if (typeof document === 'undefined')
38
+ return null;
39
+ const prefix = `${cookieName}=`;
40
+ const entry = document.cookie
41
+ .split(';')
42
+ .map((part) => part.trim())
43
+ .find((part) => part.startsWith(prefix));
44
+ const value = entry ? entry.slice(prefix.length) : '';
45
+ if (value === ps_analytics_config_1.PsAnalyticsConfig.consentGranted)
46
+ return ps_analytics_config_1.PsAnalyticsConfig.consentGranted;
47
+ if (value === ps_analytics_config_1.PsAnalyticsConfig.consentDenied)
48
+ return ps_analytics_config_1.PsAnalyticsConfig.consentDenied;
49
+ return null;
50
+ }
51
+ static writeCookie(cookieName, choice) {
52
+ if (typeof document === 'undefined')
53
+ return;
54
+ const secure = window.location.protocol === 'https:' ? '; Secure' : '';
55
+ document.cookie = `${cookieName}=${choice}; Path=/; Max-Age=${ps_analytics_config_1.PsAnalyticsConfig.consentMaxAgeSeconds}; SameSite=Lax${secure}`;
56
+ }
57
+ }
58
+ exports.PsConsentService = PsConsentService;
59
+ PsConsentService.serverState = { choice: null, isReopened: false };
60
+ PsConsentService.states = new Map();
61
+ PsConsentService.listeners = new Set();
@@ -0,0 +1,6 @@
1
+ export declare class PsGoogleAnalyticsService {
2
+ static load(id: string, tagManagerUrl: string, nonce?: string): void;
3
+ static configure(id: string, pathname: string, userId: string | null | undefined): void;
4
+ static clearUser(): void;
5
+ static disable(id: string): void;
6
+ }
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsGoogleAnalyticsService = void 0;
4
+ const ps_analytics_config_1 = require("../constants/ps-analytics-config");
5
+ class PsGoogleAnalyticsService {
6
+ static load(id, tagManagerUrl, nonce) {
7
+ const target = window;
8
+ Reflect.set(window, `ga-disable-${id}`, false);
9
+ if (typeof target.gtag !== 'function') {
10
+ target.dataLayer = target.dataLayer ? target.dataLayer : [];
11
+ target.gtag = function gtag() {
12
+ target.dataLayer?.push(arguments);
13
+ };
14
+ target.gtag('js', new Date());
15
+ }
16
+ if (document.querySelector(`script[${ps_analytics_config_1.PsAnalyticsConfig.scriptAttribute}="${id}"]`))
17
+ return;
18
+ const script = document.createElement('script');
19
+ script.async = true;
20
+ script.src = `${tagManagerUrl.replace(/\/+$/, '')}${ps_analytics_config_1.PsAnalyticsConfig.tagManagerScriptPath}${encodeURIComponent(id)}`;
21
+ script.setAttribute(ps_analytics_config_1.PsAnalyticsConfig.scriptAttribute, id);
22
+ if (nonce)
23
+ script.setAttribute('nonce', nonce);
24
+ document.head.appendChild(script);
25
+ }
26
+ static configure(id, pathname, userId) {
27
+ const target = window;
28
+ if (typeof target.gtag !== 'function')
29
+ return;
30
+ target.gtag('config', id, {
31
+ send_page_view: false,
32
+ page_path: pathname,
33
+ ...(userId ? { user_id: userId } : {}),
34
+ });
35
+ }
36
+ static clearUser() {
37
+ const target = window;
38
+ if (typeof target.gtag === 'function')
39
+ target.gtag('set', { user_id: undefined });
40
+ }
41
+ static disable(id) {
42
+ Reflect.set(window, `ga-disable-${id}`, true);
43
+ }
44
+ }
45
+ exports.PsGoogleAnalyticsService = PsGoogleAnalyticsService;
@@ -0,0 +1,4 @@
1
+ import type { PostHog } from 'posthog-js';
2
+ export declare class PsPostHogService {
3
+ static load(key: string, apiHost: string | undefined): Promise<PostHog>;
4
+ }
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.PsPostHogService = void 0;
37
+ const ps_analytics_config_1 = require("../constants/ps-analytics-config");
38
+ class PsPostHogService {
39
+ static async load(key, apiHost) {
40
+ const module = await Promise.resolve().then(() => __importStar(require('posthog-js')));
41
+ const client = module.default;
42
+ client.init(key, {
43
+ ...(apiHost ? { api_host: apiHost } : {}),
44
+ defaults: ps_analytics_config_1.PsAnalyticsConfig.postHog.defaults,
45
+ autocapture: ps_analytics_config_1.PsAnalyticsConfig.postHog.autocapture,
46
+ capture_pageview: false,
47
+ capture_pageleave: ps_analytics_config_1.PsAnalyticsConfig.postHog.capturePageleave,
48
+ capture_exceptions: ps_analytics_config_1.PsAnalyticsConfig.postHog.captureExceptions,
49
+ person_profiles: ps_analytics_config_1.PsAnalyticsConfig.postHog.personProfiles,
50
+ });
51
+ client.opt_in_capturing();
52
+ return client;
53
+ }
54
+ }
55
+ exports.PsPostHogService = PsPostHogService;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pallasoft/ps-core-components",
3
- "version": "2.33.0",
3
+ "version": "2.34.0",
4
4
  "private": false,
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/esm/index.js",
@@ -12,6 +12,19 @@
12
12
  "module": "./dist/esm/index.js",
13
13
  "require": "./dist/index.js",
14
14
  "default": "./dist/index.js"
15
+ },
16
+ "./analytics": {
17
+ "types": "./dist/analytics/index.d.ts",
18
+ "module": "./dist/esm/analytics/index.js",
19
+ "require": "./dist/analytics/index.js",
20
+ "default": "./dist/analytics/index.js"
21
+ }
22
+ },
23
+ "typesVersions": {
24
+ "*": {
25
+ "analytics": [
26
+ "./dist/analytics/index.d.ts"
27
+ ]
15
28
  }
16
29
  },
17
30
  "files": [
@@ -41,6 +54,7 @@
41
54
  "@portabletext/react": "^3.2.4",
42
55
  "@portabletext/types": "^2.0.13",
43
56
  "@radix-ui/react-accordion": "^1.2.12",
57
+ "posthog-js": "^1.438.5",
44
58
  "react-infinite-scroll-component": "^6.1.1"
45
59
  },
46
60
  "peerDependencies": {