@pallasoft/ps-core-components 2.33.0 → 2.35.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/dist/analytics/index.d.ts +12 -0
- package/dist/analytics/index.js +28 -0
- package/dist/analytics/report-client-error.d.ts +1 -0
- package/dist/analytics/report-client-error.js +6 -0
- package/dist/components/ps-analytics-provider.d.ts +15 -0
- package/dist/components/ps-analytics-provider.js +73 -0
- package/dist/components/ps-client-error-reporter.d.ts +5 -0
- package/dist/components/ps-client-error-reporter.js +22 -0
- package/dist/components/ps-consent-banner.d.ts +11 -0
- package/dist/components/ps-consent-banner.js +21 -0
- package/dist/constants/ps-analytics-config.d.ts +20 -0
- package/dist/constants/ps-analytics-config.js +23 -0
- package/dist/constants/ps-client-error-config.d.ts +23 -0
- package/dist/constants/ps-client-error-config.js +17 -0
- package/dist/esm/analytics/index.js +12 -0
- package/dist/esm/analytics/report-client-error.js +2 -0
- package/dist/esm/components/ps-accordion.js +2 -2
- package/dist/esm/components/ps-action-tile.js +2 -2
- package/dist/esm/components/ps-active-filter-chip.js +1 -1
- package/dist/esm/components/ps-analytics-provider.js +69 -0
- package/dist/esm/components/ps-app-store-buttons.js +3 -3
- package/dist/esm/components/ps-audio-spectrum.js +1 -1
- package/dist/esm/components/ps-badge.js +2 -2
- package/dist/esm/components/ps-button.js +2 -2
- package/dist/esm/components/ps-capped-list.js +2 -2
- package/dist/esm/components/ps-card-block-skeleton.js +2 -2
- package/dist/esm/components/ps-card.js +3 -3
- package/dist/esm/components/ps-client-error-reporter.js +18 -0
- package/dist/esm/components/ps-client-only.js +1 -1
- package/dist/esm/components/ps-consent-banner.js +17 -0
- package/dist/esm/components/ps-drag-overlay.js +2 -2
- package/dist/esm/components/ps-draggable-grid.js +5 -5
- package/dist/esm/components/ps-fab.js +1 -1
- package/dist/esm/components/ps-faq-answer.js +1 -1
- package/dist/esm/components/ps-feature-card.js +1 -1
- package/dist/esm/components/ps-feature-grid.js +3 -3
- package/dist/esm/components/ps-form-fields-skeleton.js +3 -3
- package/dist/esm/components/ps-form-footer.js +1 -1
- package/dist/esm/components/ps-form-page-skeleton.js +4 -4
- package/dist/esm/components/ps-icon-button.js +1 -1
- package/dist/esm/components/ps-icon-link.js +1 -1
- package/dist/esm/components/ps-infinite-scroll.js +1 -1
- package/dist/esm/components/ps-intro-skeleton.js +1 -1
- package/dist/esm/components/ps-layer.js +1 -1
- package/dist/esm/components/ps-link-button.js +1 -1
- package/dist/esm/components/ps-link-tile-grid.js +1 -1
- package/dist/esm/components/ps-list-tile.js +2 -2
- package/dist/esm/components/ps-metric-card.js +2 -2
- package/dist/esm/components/ps-metric-grid-skeleton.js +1 -1
- package/dist/esm/components/ps-metric-grid.js +2 -2
- package/dist/esm/components/ps-metric-row.js +2 -2
- package/dist/esm/components/ps-navigation-progress.js +2 -2
- package/dist/esm/components/ps-page-header.js +2 -2
- package/dist/esm/components/ps-page-skeleton.js +6 -6
- package/dist/esm/components/ps-pallasoft-mark.js +1 -1
- package/dist/esm/components/ps-pallasoft-sign-in-button.js +2 -2
- package/dist/esm/components/ps-pill.js +2 -2
- package/dist/esm/components/ps-rating-display.js +2 -2
- package/dist/esm/components/ps-scaled-preview.js +2 -2
- package/dist/esm/components/ps-section-header.js +3 -3
- package/dist/esm/components/ps-section-panel-skeleton.js +1 -1
- package/dist/esm/components/ps-signed-amount.js +1 -1
- package/dist/esm/components/ps-site-header.js +2 -2
- package/dist/esm/components/ps-skeleton-card.js +2 -2
- package/dist/esm/components/ps-skeleton-list.js +4 -4
- package/dist/esm/components/ps-skeleton-media.js +3 -3
- package/dist/esm/components/ps-skeleton-table.js +4 -4
- package/dist/esm/components/ps-skeleton-text.js +3 -3
- package/dist/esm/components/ps-skeleton.js +3 -3
- package/dist/esm/components/ps-sortable-list.js +5 -5
- package/dist/esm/components/ps-start-panel.js +1 -1
- package/dist/esm/components/ps-step-list.js +2 -2
- package/dist/esm/components/ps-step-progress.js +1 -1
- package/dist/esm/components/ps-store-badge.js +1 -1
- package/dist/esm/components/ps-tab-row-skeleton.js +2 -2
- package/dist/esm/components/ps-table-list-skeleton.js +2 -2
- package/dist/esm/components/ps-table-page-skeleton.js +2 -2
- package/dist/esm/components/ps-theme-controller.js +2 -2
- package/dist/esm/components/ps-tool-card-grid.js +2 -2
- package/dist/esm/components/ps-voice-orb.js +1 -1
- package/dist/esm/constants/ps-analytics-config.js +20 -0
- package/dist/esm/constants/ps-client-error-config.js +14 -0
- package/dist/esm/constants/ps-draggable-grid.js +1 -1
- package/dist/esm/constants/ps-rating-display-config.js +1 -1
- package/dist/esm/constants/ps-skeleton-config.js +1 -1
- package/dist/esm/constants/ps-step-marker-class-names.js +1 -1
- package/dist/esm/constants/ps-store-badge-config.js +1 -1
- package/dist/esm/hooks/use-consent.js +17 -0
- package/dist/esm/hooks/use-ps-drag-sensors.js +1 -1
- package/dist/esm/hooks/use-ps-exit-transition.js +1 -1
- package/dist/esm/hooks/use-ps-hydrated.js +1 -1
- package/dist/esm/hooks/use-ps-layer-z-index.js +1 -1
- package/dist/esm/hooks/use-ps-navigation-progress.js +1 -1
- package/dist/esm/hooks/use-ps-optimistic-fetcher.js +2 -2
- package/dist/esm/hooks/use-ps-optimistic-save.js +2 -2
- package/dist/esm/hooks/use-ps-scroll-lock.js +1 -1
- package/dist/esm/index.js +173 -173
- package/dist/esm/models/analytics-csp-input.js +1 -0
- package/dist/esm/models/analytics-csp-origins.js +1 -0
- package/dist/esm/models/ps-client-error-payload.js +1 -0
- package/dist/esm/models/ps-client-error-settings.js +1 -0
- package/dist/esm/models/ps-consent-api.js +1 -0
- package/dist/esm/models/ps-consent-choice.js +1 -0
- package/dist/esm/models/ps-consent-state.js +1 -0
- package/dist/esm/models/ps-gtag-window.js +1 -0
- package/dist/esm/services/analytics-csp-service.js +27 -0
- package/dist/esm/services/ps-analytics-key-service.js +8 -0
- package/dist/esm/services/ps-client-error-service.js +72 -0
- package/dist/esm/services/ps-consent-service.js +57 -0
- package/dist/esm/services/ps-google-analytics-service.js +41 -0
- package/dist/esm/services/ps-optimistic-save-service.js +1 -1
- package/dist/esm/services/ps-post-hog-service.js +18 -0
- package/dist/esm/services/ps-skeleton-class-service.js +1 -1
- package/dist/hooks/use-consent.d.ts +2 -0
- package/dist/hooks/use-consent.js +21 -0
- package/dist/models/analytics-csp-input.d.ts +7 -0
- package/dist/models/analytics-csp-input.js +2 -0
- package/dist/models/analytics-csp-origins.d.ts +5 -0
- package/dist/models/analytics-csp-origins.js +2 -0
- package/dist/models/ps-client-error-payload.d.ts +9 -0
- package/dist/models/ps-client-error-payload.js +2 -0
- package/dist/models/ps-client-error-settings.d.ts +4 -0
- package/dist/models/ps-client-error-settings.js +2 -0
- package/dist/models/ps-consent-api.d.ts +9 -0
- package/dist/models/ps-consent-api.js +2 -0
- package/dist/models/ps-consent-choice.d.ts +1 -0
- package/dist/models/ps-consent-choice.js +2 -0
- package/dist/models/ps-consent-state.d.ts +5 -0
- package/dist/models/ps-consent-state.js +2 -0
- package/dist/models/ps-gtag-window.d.ts +4 -0
- package/dist/models/ps-gtag-window.js +2 -0
- package/dist/services/analytics-csp-service.d.ts +7 -0
- package/dist/services/analytics-csp-service.js +31 -0
- package/dist/services/ps-analytics-key-service.d.ts +3 -0
- package/dist/services/ps-analytics-key-service.js +12 -0
- package/dist/services/ps-client-error-service.d.ts +14 -0
- package/dist/services/ps-client-error-service.js +76 -0
- package/dist/services/ps-consent-service.d.ts +15 -0
- package/dist/services/ps-consent-service.js +61 -0
- package/dist/services/ps-google-analytics-service.d.ts +6 -0
- package/dist/services/ps-google-analytics-service.js +45 -0
- package/dist/services/ps-post-hog-service.d.ts +4 -0
- package/dist/services/ps-post-hog-service.js +55 -0
- package/package.json +17 -2
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from '../components/ps-analytics-provider';
|
|
2
|
+
export * from '../components/ps-client-error-reporter';
|
|
3
|
+
export * from '../components/ps-consent-banner';
|
|
4
|
+
export * from '../constants/ps-analytics-config';
|
|
5
|
+
export * from '../constants/ps-client-error-config';
|
|
6
|
+
export * from '../hooks/use-consent';
|
|
7
|
+
export * from '../models/analytics-csp-input';
|
|
8
|
+
export * from '../models/analytics-csp-origins';
|
|
9
|
+
export * from '../models/ps-consent-api';
|
|
10
|
+
export * from '../models/ps-consent-choice';
|
|
11
|
+
export * from '../services/analytics-csp-service';
|
|
12
|
+
export * from './report-client-error';
|
|
@@ -0,0 +1,28 @@
|
|
|
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("../components/ps-analytics-provider"), exports);
|
|
18
|
+
__exportStar(require("../components/ps-client-error-reporter"), exports);
|
|
19
|
+
__exportStar(require("../components/ps-consent-banner"), exports);
|
|
20
|
+
__exportStar(require("../constants/ps-analytics-config"), exports);
|
|
21
|
+
__exportStar(require("../constants/ps-client-error-config"), exports);
|
|
22
|
+
__exportStar(require("../hooks/use-consent"), exports);
|
|
23
|
+
__exportStar(require("../models/analytics-csp-input"), exports);
|
|
24
|
+
__exportStar(require("../models/analytics-csp-origins"), exports);
|
|
25
|
+
__exportStar(require("../models/ps-consent-api"), exports);
|
|
26
|
+
__exportStar(require("../models/ps-consent-choice"), exports);
|
|
27
|
+
__exportStar(require("../services/analytics-csp-service"), exports);
|
|
28
|
+
__exportStar(require("./report-client-error"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const reportClientError: (error: unknown, context?: string) => void;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.reportClientError = void 0;
|
|
4
|
+
const ps_client_error_service_1 = require("../services/ps-client-error-service");
|
|
5
|
+
const reportClientError = (error, context) => ps_client_error_service_1.PsClientErrorService.report(error, context);
|
|
6
|
+
exports.reportClientError = reportClientError;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ReactNode } from 'react';
|
|
2
|
+
export interface PsAnalyticsProviderProps {
|
|
3
|
+
children?: ReactNode;
|
|
4
|
+
googleAnalyticsId?: string;
|
|
5
|
+
googleTagManagerUrl?: string;
|
|
6
|
+
postHogKey?: string;
|
|
7
|
+
postHogApiHost?: string;
|
|
8
|
+
userId?: string | null;
|
|
9
|
+
appVersion?: string;
|
|
10
|
+
nonce?: string;
|
|
11
|
+
consentCookieName?: string;
|
|
12
|
+
requireConsent?: boolean;
|
|
13
|
+
pathname?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare const PsAnalyticsProvider: ({ children, googleAnalyticsId, googleTagManagerUrl, postHogKey, postHogApiHost, userId, appVersion, nonce, consentCookieName, requireConsent, pathname, }: PsAnalyticsProviderProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsAnalyticsProvider = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const ps_analytics_config_1 = require("../constants/ps-analytics-config");
|
|
7
|
+
const use_consent_1 = require("../hooks/use-consent");
|
|
8
|
+
const ps_analytics_key_service_1 = require("../services/ps-analytics-key-service");
|
|
9
|
+
const ps_google_analytics_service_1 = require("../services/ps-google-analytics-service");
|
|
10
|
+
const ps_post_hog_service_1 = require("../services/ps-post-hog-service");
|
|
11
|
+
const PsAnalyticsProvider = ({ children, googleAnalyticsId, googleTagManagerUrl = ps_analytics_config_1.PsAnalyticsConfig.defaultTagManagerUrl, postHogKey, postHogApiHost, userId, appVersion, nonce, consentCookieName = ps_analytics_config_1.PsAnalyticsConfig.defaultConsentCookieName, requireConsent = ps_analytics_config_1.PsAnalyticsConfig.defaultRequireConsent, pathname, }) => {
|
|
12
|
+
const consent = (0, use_consent_1.useConsent)(consentCookieName);
|
|
13
|
+
const isGranted = requireConsent ? consent.isGranted : true;
|
|
14
|
+
const [postHog, setPostHog] = (0, react_1.useState)(null);
|
|
15
|
+
const identifiedRef = (0, react_1.useRef)(null);
|
|
16
|
+
const isGoogleOn = ps_analytics_key_service_1.PsAnalyticsKeyService.isEnabled(googleAnalyticsId);
|
|
17
|
+
const isPostHogOn = ps_analytics_key_service_1.PsAnalyticsKeyService.isEnabled(postHogKey);
|
|
18
|
+
const currentPath = pathname !== undefined ? pathname : '';
|
|
19
|
+
const normalizedUserId = userId ? userId : null;
|
|
20
|
+
(0, react_1.useEffect)(() => {
|
|
21
|
+
if (!isGoogleOn)
|
|
22
|
+
return;
|
|
23
|
+
if (!isGranted) {
|
|
24
|
+
ps_google_analytics_service_1.PsGoogleAnalyticsService.disable(googleAnalyticsId);
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
ps_google_analytics_service_1.PsGoogleAnalyticsService.load(googleAnalyticsId, googleTagManagerUrl, nonce);
|
|
28
|
+
}, [isGoogleOn, isGranted, googleAnalyticsId, googleTagManagerUrl, nonce]);
|
|
29
|
+
(0, react_1.useEffect)(() => {
|
|
30
|
+
if (!isGoogleOn || !isGranted)
|
|
31
|
+
return;
|
|
32
|
+
ps_google_analytics_service_1.PsGoogleAnalyticsService.configure(googleAnalyticsId, currentPath, normalizedUserId);
|
|
33
|
+
}, [isGoogleOn, isGranted, googleAnalyticsId, currentPath, normalizedUserId]);
|
|
34
|
+
(0, react_1.useEffect)(() => {
|
|
35
|
+
if (!isPostHogOn)
|
|
36
|
+
return;
|
|
37
|
+
if (!isGranted) {
|
|
38
|
+
if (postHog)
|
|
39
|
+
postHog.opt_out_capturing();
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
let isCancelled = false;
|
|
43
|
+
ps_post_hog_service_1.PsPostHogService.load(postHogKey, postHogApiHost).then((client) => {
|
|
44
|
+
if (!isCancelled)
|
|
45
|
+
setPostHog(client);
|
|
46
|
+
});
|
|
47
|
+
return () => {
|
|
48
|
+
isCancelled = true;
|
|
49
|
+
};
|
|
50
|
+
}, [isPostHogOn, isGranted, postHogKey, postHogApiHost]);
|
|
51
|
+
(0, react_1.useEffect)(() => {
|
|
52
|
+
if (!postHog || !isGranted)
|
|
53
|
+
return;
|
|
54
|
+
if (normalizedUserId) {
|
|
55
|
+
postHog.identify(normalizedUserId, appVersion ? { app_version: appVersion } : undefined);
|
|
56
|
+
identifiedRef.current = normalizedUserId;
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (identifiedRef.current) {
|
|
60
|
+
postHog.reset();
|
|
61
|
+
identifiedRef.current = null;
|
|
62
|
+
}
|
|
63
|
+
}, [postHog, isGranted, normalizedUserId, appVersion]);
|
|
64
|
+
(0, react_1.useEffect)(() => {
|
|
65
|
+
if (!postHog || !isGranted)
|
|
66
|
+
return;
|
|
67
|
+
postHog.capture(ps_analytics_config_1.PsAnalyticsConfig.postHog.pageviewEvent, {
|
|
68
|
+
$pathname: currentPath,
|
|
69
|
+
});
|
|
70
|
+
}, [postHog, isGranted, currentPath]);
|
|
71
|
+
return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: children });
|
|
72
|
+
};
|
|
73
|
+
exports.PsAnalyticsProvider = PsAnalyticsProvider;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsClientErrorReporter = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const ps_client_error_config_1 = require("../constants/ps-client-error-config");
|
|
6
|
+
const ps_client_error_service_1 = require("../services/ps-client-error-service");
|
|
7
|
+
const PsClientErrorReporter = ({ endpoint, appVersion }) => {
|
|
8
|
+
(0, react_1.useEffect)(() => {
|
|
9
|
+
ps_client_error_service_1.PsClientErrorService.configure({ endpoint, appVersion });
|
|
10
|
+
const onError = (event) => ps_client_error_service_1.PsClientErrorService.report(event.error ? event.error : event.message, '', ps_client_error_config_1.PsClientErrorConfig.sources.error);
|
|
11
|
+
const onRejection = (event) => ps_client_error_service_1.PsClientErrorService.report(event.reason, '', ps_client_error_config_1.PsClientErrorConfig.sources.rejection);
|
|
12
|
+
window.addEventListener('error', onError);
|
|
13
|
+
window.addEventListener('unhandledrejection', onRejection);
|
|
14
|
+
return () => {
|
|
15
|
+
window.removeEventListener('error', onError);
|
|
16
|
+
window.removeEventListener('unhandledrejection', onRejection);
|
|
17
|
+
ps_client_error_service_1.PsClientErrorService.clear();
|
|
18
|
+
};
|
|
19
|
+
}, [endpoint, appVersion]);
|
|
20
|
+
return null;
|
|
21
|
+
};
|
|
22
|
+
exports.PsClientErrorReporter = PsClientErrorReporter;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface PsConsentBannerProps {
|
|
2
|
+
title: string;
|
|
3
|
+
message: string;
|
|
4
|
+
acceptLabel: string;
|
|
5
|
+
rejectLabel: string;
|
|
6
|
+
privacyPolicyHref: string;
|
|
7
|
+
privacyPolicyLabel: string;
|
|
8
|
+
consentCookieName?: string;
|
|
9
|
+
className?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare const PsConsentBanner: ({ title, message, acceptLabel, rejectLabel, privacyPolicyHref, privacyPolicyLabel, consentCookieName, className, }: PsConsentBannerProps) => import("react").JSX.Element | null;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsConsentBanner = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const ps_design_system_1 = require("@pallasoft/ps-design-system");
|
|
7
|
+
const ps_analytics_config_1 = require("../constants/ps-analytics-config");
|
|
8
|
+
const use_consent_1 = require("../hooks/use-consent");
|
|
9
|
+
const ps_button_1 = require("./ps-button");
|
|
10
|
+
const PsConsentBanner = ({ title, message, acceptLabel, rejectLabel, privacyPolicyHref, privacyPolicyLabel, consentCookieName = ps_analytics_config_1.PsAnalyticsConfig.defaultConsentCookieName, className, }) => {
|
|
11
|
+
const { isBannerOpen, accept, reject } = (0, use_consent_1.useConsent)(consentCookieName);
|
|
12
|
+
const ref = (0, react_1.useRef)(null);
|
|
13
|
+
(0, react_1.useEffect)(() => {
|
|
14
|
+
if (isBannerOpen)
|
|
15
|
+
ref.current?.focus();
|
|
16
|
+
}, [isBannerOpen]);
|
|
17
|
+
if (!isBannerOpen)
|
|
18
|
+
return null;
|
|
19
|
+
return ((0, jsx_runtime_1.jsxs)("div", { ref: ref, role: 'dialog', "aria-label": title, "aria-live": 'polite', tabIndex: -1, className: `ps-card fixed inset-x-3 bottom-3 flex flex-col gap-3 p-4 shadow-lg outline-none sm:left-auto sm:right-4 sm:max-w-md ${className ? className : ''}`, style: { zIndex: ps_design_system_1.PallasoftZIndex.Toast }, children: [(0, jsx_runtime_1.jsxs)("p", { className: 'text-sm', children: [message, ' ', (0, jsx_runtime_1.jsx)("a", { className: 'underline', href: privacyPolicyHref, children: privacyPolicyLabel })] }), (0, jsx_runtime_1.jsxs)("div", { className: 'flex gap-2', children: [(0, jsx_runtime_1.jsx)(ps_button_1.PsButton, { className: 'flex-1', size: 'compact', variant: 'secondary', onClick: reject, children: rejectLabel }), (0, jsx_runtime_1.jsx)(ps_button_1.PsButton, { className: 'flex-1', size: 'compact', variant: 'secondary', onClick: accept, children: acceptLabel })] })] }));
|
|
20
|
+
};
|
|
21
|
+
exports.PsConsentBanner = PsConsentBanner;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const PsAnalyticsConfig: {
|
|
2
|
+
readonly offValues: readonly ["", "_"];
|
|
3
|
+
readonly defaultConsentCookieName: "ps_consent";
|
|
4
|
+
readonly defaultRequireConsent: true;
|
|
5
|
+
readonly consentGranted: "granted";
|
|
6
|
+
readonly consentDenied: "denied";
|
|
7
|
+
readonly consentMaxAgeSeconds: 31536000;
|
|
8
|
+
readonly defaultTagManagerUrl: "https://www.googletagmanager.com";
|
|
9
|
+
readonly tagManagerScriptPath: "/gtag/js?id=";
|
|
10
|
+
readonly scriptAttribute: "data-ps-analytics";
|
|
11
|
+
readonly postHog: {
|
|
12
|
+
readonly defaults: "2026-05-30";
|
|
13
|
+
readonly personProfiles: "identified_only";
|
|
14
|
+
readonly autocapture: true;
|
|
15
|
+
readonly capturePageleave: true;
|
|
16
|
+
readonly captureExceptions: true;
|
|
17
|
+
readonly pageviewEvent: "$pageview";
|
|
18
|
+
};
|
|
19
|
+
readonly listSeparator: ",";
|
|
20
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsAnalyticsConfig = void 0;
|
|
4
|
+
exports.PsAnalyticsConfig = {
|
|
5
|
+
offValues: ['', '_'],
|
|
6
|
+
defaultConsentCookieName: 'ps_consent',
|
|
7
|
+
defaultRequireConsent: true,
|
|
8
|
+
consentGranted: 'granted',
|
|
9
|
+
consentDenied: 'denied',
|
|
10
|
+
consentMaxAgeSeconds: 31536000,
|
|
11
|
+
defaultTagManagerUrl: 'https://www.googletagmanager.com',
|
|
12
|
+
tagManagerScriptPath: '/gtag/js?id=',
|
|
13
|
+
scriptAttribute: 'data-ps-analytics',
|
|
14
|
+
postHog: {
|
|
15
|
+
defaults: '2026-05-30',
|
|
16
|
+
personProfiles: 'identified_only',
|
|
17
|
+
autocapture: true,
|
|
18
|
+
capturePageleave: true,
|
|
19
|
+
captureExceptions: true,
|
|
20
|
+
pageviewEvent: '$pageview',
|
|
21
|
+
},
|
|
22
|
+
listSeparator: ',',
|
|
23
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export declare const PsClientErrorConfig: {
|
|
2
|
+
readonly maxReportsPerPage: 10;
|
|
3
|
+
readonly maxStackLength: 2048;
|
|
4
|
+
readonly maxMessageLength: 500;
|
|
5
|
+
readonly maxContextLength: 200;
|
|
6
|
+
readonly jsonContentType: "application/json";
|
|
7
|
+
readonly emailPattern: RegExp;
|
|
8
|
+
readonly redactedValue: "[redacted]";
|
|
9
|
+
readonly unknownMessage: "Unknown error";
|
|
10
|
+
readonly botPattern: RegExp;
|
|
11
|
+
readonly mobilePattern: RegExp;
|
|
12
|
+
readonly userAgentClasses: {
|
|
13
|
+
readonly bot: "bot";
|
|
14
|
+
readonly mobile: "mobile";
|
|
15
|
+
readonly desktop: "desktop";
|
|
16
|
+
readonly unknown: "unknown";
|
|
17
|
+
};
|
|
18
|
+
readonly sources: {
|
|
19
|
+
readonly error: "error";
|
|
20
|
+
readonly rejection: "unhandledrejection";
|
|
21
|
+
readonly boundary: "boundary";
|
|
22
|
+
};
|
|
23
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsClientErrorConfig = void 0;
|
|
4
|
+
exports.PsClientErrorConfig = {
|
|
5
|
+
maxReportsPerPage: 10,
|
|
6
|
+
maxStackLength: 2048,
|
|
7
|
+
maxMessageLength: 500,
|
|
8
|
+
maxContextLength: 200,
|
|
9
|
+
jsonContentType: 'application/json',
|
|
10
|
+
emailPattern: /[^\s@"'()<>]+@[^\s@"'()<>]+\.[^\s@"'()<>]+/g,
|
|
11
|
+
redactedValue: '[redacted]',
|
|
12
|
+
unknownMessage: 'Unknown error',
|
|
13
|
+
botPattern: /bot|crawl|spider|slurp|headless/i,
|
|
14
|
+
mobilePattern: /mobi|android|iphone|ipad/i,
|
|
15
|
+
userAgentClasses: { bot: 'bot', mobile: 'mobile', desktop: 'desktop', unknown: 'unknown' },
|
|
16
|
+
sources: { error: 'error', rejection: 'unhandledrejection', boundary: 'boundary' },
|
|
17
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export * from '../components/ps-analytics-provider.js';
|
|
2
|
+
export * from '../components/ps-client-error-reporter.js';
|
|
3
|
+
export * from '../components/ps-consent-banner.js';
|
|
4
|
+
export * from '../constants/ps-analytics-config.js';
|
|
5
|
+
export * from '../constants/ps-client-error-config.js';
|
|
6
|
+
export * from '../hooks/use-consent.js';
|
|
7
|
+
export * from '../models/analytics-csp-input.js';
|
|
8
|
+
export * from '../models/analytics-csp-origins.js';
|
|
9
|
+
export * from '../models/ps-consent-api.js';
|
|
10
|
+
export * from '../models/ps-consent-choice.js';
|
|
11
|
+
export * from '../services/analytics-csp-service.js';
|
|
12
|
+
export * from './report-client-error.js';
|
|
@@ -2,6 +2,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
3
3
|
import { PsIcon, PsIconKey } from '@pallasoft/ps-icons';
|
|
4
4
|
import * as AccordionPrimitive from '@radix-ui/react-accordion';
|
|
5
|
-
import { PsSkeleton } from './ps-skeleton';
|
|
6
|
-
import { PsSkeletonGroup } from './ps-skeleton-group';
|
|
5
|
+
import { PsSkeleton } from './ps-skeleton.js';
|
|
6
|
+
import { PsSkeletonGroup } from './ps-skeleton-group.js';
|
|
7
7
|
export const PsAccordion = ({ children, className, isLoading = false, isOpen, label, onToggle, trailing, }) => isLoading ? (_jsx(PsSkeletonGroup, { className: PallasoftClassNameService.merge('rounded-ps-card border border-line/70 bg-surface/60 px-4 py-3.5', className), label: 'Loading', children: _jsx(PsSkeleton, { className: 'h-4 w-40' }) })) : (_jsx(AccordionPrimitive.Root, { type: 'single', collapsible: true, value: isOpen ? 'open' : '', onValueChange: onToggle, className: PallasoftClassNameService.merge('overflow-hidden rounded-ps-card border border-line/70 bg-surface/60 transition-colors duration-200', isOpen ? 'border-primary/25 bg-surface' : 'hover:border-line hover:bg-surface/90', className), children: _jsxs(AccordionPrimitive.Item, { value: 'open', children: [_jsx(AccordionPrimitive.Header, { children: _jsxs(AccordionPrimitive.Trigger, { className: 'ps-focus-ring flex w-full items-center justify-between gap-3 px-4 py-3.5 text-left', children: [_jsx("span", { className: 'text-body-2 font-semibold text-ink', children: label }), _jsxs("span", { className: 'flex shrink-0 items-center gap-2', children: [trailing, _jsx(PsIcon, { iconKey: PsIconKey.ChevronRight, className: PallasoftClassNameService.merge('h-4 w-4 text-ink/40 transition-transform duration-200', isOpen ? 'rotate-90 text-primary' : '') })] })] }) }), _jsx(AccordionPrimitive.Content, { className: 'ps-accordion-content', children: _jsx("div", { className: 'border-t border-line/70 p-4', children: children }) })] }) }));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
3
|
-
import { PsSkeletonShape } from '../constants/ps-skeleton-shape';
|
|
4
|
-
import { PsSkeleton } from './ps-skeleton';
|
|
3
|
+
import { PsSkeletonShape } from '../constants/ps-skeleton-shape.js';
|
|
4
|
+
import { PsSkeleton } from './ps-skeleton.js';
|
|
5
5
|
const variantClassNames = {
|
|
6
6
|
default: 'ps-action-tile',
|
|
7
7
|
primary: 'ps-action-tile ps-action-tile-primary',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { PsIcon, PsIconKey } from '@pallasoft/ps-icons';
|
|
3
|
-
import { PsPill } from './ps-pill';
|
|
3
|
+
import { PsPill } from './ps-pill.js';
|
|
4
4
|
export const PsActiveFilterChip = ({ id, label, onRemove, removeLabel, }) => (_jsx("button", { "aria-label": removeLabel, className: 'ps-focus-ring shrink-0 rounded-ps-control', id: id, onClick: onRemove, type: 'button', children: _jsx(PsPill, { className: 'pr-2', tone: 'primary', children: _jsxs("span", { className: 'flex items-center gap-1.5', children: [label, _jsx(PsIcon, { className: 'h-3 w-3', iconKey: PsIconKey.Close })] }) }) }));
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { PsAnalyticsConfig } from '../constants/ps-analytics-config.js';
|
|
4
|
+
import { useConsent } from '../hooks/use-consent.js';
|
|
5
|
+
import { PsAnalyticsKeyService } from '../services/ps-analytics-key-service.js';
|
|
6
|
+
import { PsGoogleAnalyticsService } from '../services/ps-google-analytics-service.js';
|
|
7
|
+
import { PsPostHogService } from '../services/ps-post-hog-service.js';
|
|
8
|
+
export const PsAnalyticsProvider = ({ children, googleAnalyticsId, googleTagManagerUrl = PsAnalyticsConfig.defaultTagManagerUrl, postHogKey, postHogApiHost, userId, appVersion, nonce, consentCookieName = PsAnalyticsConfig.defaultConsentCookieName, requireConsent = PsAnalyticsConfig.defaultRequireConsent, pathname, }) => {
|
|
9
|
+
const consent = useConsent(consentCookieName);
|
|
10
|
+
const isGranted = requireConsent ? consent.isGranted : true;
|
|
11
|
+
const [postHog, setPostHog] = useState(null);
|
|
12
|
+
const identifiedRef = useRef(null);
|
|
13
|
+
const isGoogleOn = PsAnalyticsKeyService.isEnabled(googleAnalyticsId);
|
|
14
|
+
const isPostHogOn = PsAnalyticsKeyService.isEnabled(postHogKey);
|
|
15
|
+
const currentPath = pathname !== undefined ? pathname : '';
|
|
16
|
+
const normalizedUserId = userId ? userId : null;
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
if (!isGoogleOn)
|
|
19
|
+
return;
|
|
20
|
+
if (!isGranted) {
|
|
21
|
+
PsGoogleAnalyticsService.disable(googleAnalyticsId);
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
PsGoogleAnalyticsService.load(googleAnalyticsId, googleTagManagerUrl, nonce);
|
|
25
|
+
}, [isGoogleOn, isGranted, googleAnalyticsId, googleTagManagerUrl, nonce]);
|
|
26
|
+
useEffect(() => {
|
|
27
|
+
if (!isGoogleOn || !isGranted)
|
|
28
|
+
return;
|
|
29
|
+
PsGoogleAnalyticsService.configure(googleAnalyticsId, currentPath, normalizedUserId);
|
|
30
|
+
}, [isGoogleOn, isGranted, googleAnalyticsId, currentPath, normalizedUserId]);
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (!isPostHogOn)
|
|
33
|
+
return;
|
|
34
|
+
if (!isGranted) {
|
|
35
|
+
if (postHog)
|
|
36
|
+
postHog.opt_out_capturing();
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
let isCancelled = false;
|
|
40
|
+
PsPostHogService.load(postHogKey, postHogApiHost).then((client) => {
|
|
41
|
+
if (!isCancelled)
|
|
42
|
+
setPostHog(client);
|
|
43
|
+
});
|
|
44
|
+
return () => {
|
|
45
|
+
isCancelled = true;
|
|
46
|
+
};
|
|
47
|
+
}, [isPostHogOn, isGranted, postHogKey, postHogApiHost]);
|
|
48
|
+
useEffect(() => {
|
|
49
|
+
if (!postHog || !isGranted)
|
|
50
|
+
return;
|
|
51
|
+
if (normalizedUserId) {
|
|
52
|
+
postHog.identify(normalizedUserId, appVersion ? { app_version: appVersion } : undefined);
|
|
53
|
+
identifiedRef.current = normalizedUserId;
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
if (identifiedRef.current) {
|
|
57
|
+
postHog.reset();
|
|
58
|
+
identifiedRef.current = null;
|
|
59
|
+
}
|
|
60
|
+
}, [postHog, isGranted, normalizedUserId, appVersion]);
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
if (!postHog || !isGranted)
|
|
63
|
+
return;
|
|
64
|
+
postHog.capture(PsAnalyticsConfig.postHog.pageviewEvent, {
|
|
65
|
+
$pathname: currentPath,
|
|
66
|
+
});
|
|
67
|
+
}, [postHog, isGranted, currentPath]);
|
|
68
|
+
return _jsx(_Fragment, { children: children });
|
|
69
|
+
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
3
|
-
import { PsStoreBadgeClasses } from '../constants/ps-store-badge-config';
|
|
4
|
-
import { PsStorePlatform } from '../constants/ps-store-platform';
|
|
5
|
-
import { PsStoreBadge } from './ps-store-badge';
|
|
3
|
+
import { PsStoreBadgeClasses } from '../constants/ps-store-badge-config.js';
|
|
4
|
+
import { PsStorePlatform } from '../constants/ps-store-platform.js';
|
|
5
|
+
import { PsStoreBadge } from './ps-store-badge.js';
|
|
6
6
|
const isLinked = (url) => url !== undefined && url.trim() !== '';
|
|
7
7
|
export const PsAppStoreButtons = ({ appStoreLabels, appStoreUrl, className, playStoreLabels, playStoreUrl, size = 'default', }) => {
|
|
8
8
|
const appStoreHref = isLinked(appStoreUrl) ? appStoreUrl : undefined;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useEffect, useRef } from 'react';
|
|
3
3
|
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
4
|
-
import { PsAudioSpectrumConfig } from '../constants/ps-audio-spectrum-config';
|
|
4
|
+
import { PsAudioSpectrumConfig } from '../constants/ps-audio-spectrum-config.js';
|
|
5
5
|
const scaleFor = (level) => {
|
|
6
6
|
const bounded = Math.max(0, Math.min(1, level));
|
|
7
7
|
return PsAudioSpectrumConfig.minimumScale + bounded * (1 - PsAudioSpectrumConfig.minimumScale);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
3
|
-
import { PsSkeletonShape } from '../constants/ps-skeleton-shape';
|
|
4
|
-
import { PsSkeleton } from './ps-skeleton';
|
|
3
|
+
import { PsSkeletonShape } from '../constants/ps-skeleton-shape.js';
|
|
4
|
+
import { PsSkeleton } from './ps-skeleton.js';
|
|
5
5
|
const toneClassNames = {
|
|
6
6
|
danger: 'bg-danger-soft text-danger dark:bg-rose-500/18 dark:text-rose-100',
|
|
7
7
|
neutral: 'bg-slate-100 text-slate-700 dark:bg-white/10 dark:text-slate-100',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
3
|
-
import { PsButtonBaseClassName, PsButtonSizeClassNames, PsButtonVariantClassNames, } from '../constants/ps-button-classes';
|
|
4
|
-
import { PsSpinner } from './ps-spinner';
|
|
3
|
+
import { PsButtonBaseClassName, PsButtonSizeClassNames, PsButtonVariantClassNames, } from '../constants/ps-button-classes.js';
|
|
4
|
+
import { PsSpinner } from './ps-spinner.js';
|
|
5
5
|
export const PsButton = ({ children, className, disabled, isLabelHiddenOnMobile = false, isLoading = false, leadingIcon, loadingLabel, size = 'default', trailingIcon, type = 'button', variant = 'secondary', ...props }) => (_jsxs("button", { className: PallasoftClassNameService.merge(PsButtonBaseClassName, 'disabled:cursor-not-allowed disabled:opacity-50', PsButtonSizeClassNames[size], isLabelHiddenOnMobile && leadingIcon ? 'min-w-11 max-sm:px-0' : '', PsButtonVariantClassNames[variant], className), "aria-busy": isLoading || undefined, disabled: disabled || isLoading, type: type, ...props, children: [isLoading ? (_jsx(PsSpinner, { className: 'absolute inset-0 m-auto', color: 'current', label: loadingLabel !== null && loadingLabel !== undefined ? loadingLabel : 'Loading', size: 'small' })) : null, _jsxs("span", { "aria-hidden": isLoading || undefined, className: PallasoftClassNameService.merge('inline-flex min-w-0 items-center gap-2', isLoading ? 'invisible' : ''), children: [leadingIcon ? _jsx("span", { className: 'shrink-0', children: leadingIcon }) : null, _jsx("span", { className: isLabelHiddenOnMobile && leadingIcon ? 'sr-only sm:not-sr-only sm:truncate' : 'truncate', children: children }), trailingIcon ? _jsx("span", { className: 'shrink-0', children: trailingIcon }) : null] })] }));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useState } from 'react';
|
|
3
|
-
import { PsCappedListConfig } from '../constants/ps-capped-list-config';
|
|
4
|
-
import { PsButton } from './ps-button';
|
|
3
|
+
import { PsCappedListConfig } from '../constants/ps-capped-list-config.js';
|
|
4
|
+
import { PsButton } from './ps-button.js';
|
|
5
5
|
export const PsCappedList = ({ getKey, items, renderItem, showAllLabel, visibleRows = PsCappedListConfig.defaultVisibleRows, }) => {
|
|
6
6
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
7
7
|
const isCapped = !isExpanded && items.length > visibleRows;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { PsSkeletonShape } from '../constants/ps-skeleton-shape';
|
|
3
|
-
import { PsSkeleton } from './ps-skeleton';
|
|
2
|
+
import { PsSkeletonShape } from '../constants/ps-skeleton-shape.js';
|
|
3
|
+
import { PsSkeleton } from './ps-skeleton.js';
|
|
4
4
|
export const PsCardBlockSkeleton = ({ height }) => (_jsx(PsSkeleton, { height: height, radius: '1.25rem', shape: PsSkeletonShape.Block, width: '100%' }));
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
3
|
-
import { PsSkeletonShape } from '../constants/ps-skeleton-shape';
|
|
4
|
-
import { PsSkeleton } from './ps-skeleton';
|
|
5
|
-
import { PsSkeletonGroup } from './ps-skeleton-group';
|
|
3
|
+
import { PsSkeletonShape } from '../constants/ps-skeleton-shape.js';
|
|
4
|
+
import { PsSkeleton } from './ps-skeleton.js';
|
|
5
|
+
import { PsSkeletonGroup } from './ps-skeleton-group.js';
|
|
6
6
|
const densityClassNames = {
|
|
7
7
|
compact: 'p-3',
|
|
8
8
|
normal: 'p-4',
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useEffect } from 'react';
|
|
2
|
+
import { PsClientErrorConfig } from '../constants/ps-client-error-config.js';
|
|
3
|
+
import { PsClientErrorService } from '../services/ps-client-error-service.js';
|
|
4
|
+
export const PsClientErrorReporter = ({ endpoint, appVersion }) => {
|
|
5
|
+
useEffect(() => {
|
|
6
|
+
PsClientErrorService.configure({ endpoint, appVersion });
|
|
7
|
+
const onError = (event) => PsClientErrorService.report(event.error ? event.error : event.message, '', PsClientErrorConfig.sources.error);
|
|
8
|
+
const onRejection = (event) => PsClientErrorService.report(event.reason, '', PsClientErrorConfig.sources.rejection);
|
|
9
|
+
window.addEventListener('error', onError);
|
|
10
|
+
window.addEventListener('unhandledrejection', onRejection);
|
|
11
|
+
return () => {
|
|
12
|
+
window.removeEventListener('error', onError);
|
|
13
|
+
window.removeEventListener('unhandledrejection', onRejection);
|
|
14
|
+
PsClientErrorService.clear();
|
|
15
|
+
};
|
|
16
|
+
}, [endpoint, appVersion]);
|
|
17
|
+
return null;
|
|
18
|
+
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { usePsHydrated } from '../hooks/use-ps-hydrated';
|
|
2
|
+
import { usePsHydrated } from '../hooks/use-ps-hydrated.js';
|
|
3
3
|
export const PsClientOnly = ({ children, fallback = null }) => usePsHydrated() ? _jsx(_Fragment, { children: children() }) : _jsx(_Fragment, { children: fallback });
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef } from 'react';
|
|
3
|
+
import { PallasoftZIndex } from '@pallasoft/ps-design-system';
|
|
4
|
+
import { PsAnalyticsConfig } from '../constants/ps-analytics-config.js';
|
|
5
|
+
import { useConsent } from '../hooks/use-consent.js';
|
|
6
|
+
import { PsButton } from './ps-button.js';
|
|
7
|
+
export const PsConsentBanner = ({ title, message, acceptLabel, rejectLabel, privacyPolicyHref, privacyPolicyLabel, consentCookieName = PsAnalyticsConfig.defaultConsentCookieName, className, }) => {
|
|
8
|
+
const { isBannerOpen, accept, reject } = useConsent(consentCookieName);
|
|
9
|
+
const ref = useRef(null);
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
if (isBannerOpen)
|
|
12
|
+
ref.current?.focus();
|
|
13
|
+
}, [isBannerOpen]);
|
|
14
|
+
if (!isBannerOpen)
|
|
15
|
+
return null;
|
|
16
|
+
return (_jsxs("div", { ref: ref, role: 'dialog', "aria-label": title, "aria-live": 'polite', tabIndex: -1, className: `ps-card fixed inset-x-3 bottom-3 flex flex-col gap-3 p-4 shadow-lg outline-none sm:left-auto sm:right-4 sm:max-w-md ${className ? className : ''}`, style: { zIndex: PallasoftZIndex.Toast }, children: [_jsxs("p", { className: 'text-sm', children: [message, ' ', _jsx("a", { className: 'underline', href: privacyPolicyHref, children: privacyPolicyLabel })] }), _jsxs("div", { className: 'flex gap-2', children: [_jsx(PsButton, { className: 'flex-1', size: 'compact', variant: 'secondary', onClick: reject, children: rejectLabel }), _jsx(PsButton, { className: 'flex-1', size: 'compact', variant: 'secondary', onClick: accept, children: acceptLabel })] })] }));
|
|
17
|
+
};
|
|
@@ -2,8 +2,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { useEffect, useState } from 'react';
|
|
3
3
|
import { DragOverlay, defaultDropAnimationSideEffects } from '@dnd-kit/core';
|
|
4
4
|
import { createPortal } from 'react-dom';
|
|
5
|
-
import { PsDragConfig } from '../constants/ps-drag-config';
|
|
6
|
-
import { usePsReducedMotion } from '../hooks/use-ps-reduced-motion';
|
|
5
|
+
import { PsDragConfig } from '../constants/ps-drag-config.js';
|
|
6
|
+
import { usePsReducedMotion } from '../hooks/use-ps-reduced-motion.js';
|
|
7
7
|
const dropAnimation = {
|
|
8
8
|
duration: PsDragConfig.dropDuration,
|
|
9
9
|
easing: PsDragConfig.dropEasing,
|
|
@@ -3,11 +3,11 @@ import { useState } from 'react';
|
|
|
3
3
|
import { DndContext, closestCenter } from '@dnd-kit/core';
|
|
4
4
|
import { SortableContext, arrayMove, rectSortingStrategy, useSortable } from '@dnd-kit/sortable';
|
|
5
5
|
import { CSS } from '@dnd-kit/utilities';
|
|
6
|
-
import { PsDragConfig } from '../constants/ps-drag-config';
|
|
7
|
-
import { PsDraggableGridClasses, PsDraggableGridLiftFrames } from '../constants/ps-draggable-grid';
|
|
8
|
-
import { usePsDragSensors } from '../hooks/use-ps-drag-sensors';
|
|
9
|
-
import { PsDragGrip } from './ps-drag-grip';
|
|
10
|
-
import { PsDragOverlay } from './ps-drag-overlay';
|
|
6
|
+
import { PsDragConfig } from '../constants/ps-drag-config.js';
|
|
7
|
+
import { PsDraggableGridClasses, PsDraggableGridLiftFrames } from '../constants/ps-draggable-grid.js';
|
|
8
|
+
import { usePsDragSensors } from '../hooks/use-ps-drag-sensors.js';
|
|
9
|
+
import { PsDragGrip } from './ps-drag-grip.js';
|
|
10
|
+
import { PsDragOverlay } from './ps-drag-overlay.js';
|
|
11
11
|
const PsDraggableGridHandle = ({ attributes, label, listeners, setActivatorNodeRef, }) => (_jsx("button", { ...attributes, ...listeners, "aria-label": `Move ${label}`, className: PsDraggableGridClasses.handle, ref: setActivatorNodeRef, title: `Move ${label}`, type: 'button', children: _jsx(PsDragGrip, {}) }));
|
|
12
12
|
const PsSortableGridItem = ({ className, index, item, renderItem, }) => {
|
|
13
13
|
const { attributes, isDragging, listeners, setActivatorNodeRef, setNodeRef, transform, transition, } = useSortable({ id: item.id });
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
3
|
-
import { PsButton } from './ps-button';
|
|
3
|
+
import { PsButton } from './ps-button.js';
|
|
4
4
|
const positionClassNames = {
|
|
5
5
|
'bottom-right': 'bottom-6 right-6',
|
|
6
6
|
'bottom-left': 'bottom-6 left-6',
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { PsFaqBlockKind } from '../constants/ps-faq-block-kind';
|
|
2
|
+
import { PsFaqBlockKind } from '../constants/ps-faq-block-kind.js';
|
|
3
3
|
export const PsFaqAnswer = ({ blocks }) => (_jsx("div", { className: 'flex flex-col gap-3', children: blocks.map((block, index) => block.kind === PsFaqBlockKind.List ? (_jsx("ul", { className: 'list-disc pl-5', children: block.items.map((item) => (_jsx("li", { children: item }, item))) }, index)) : (_jsx("div", { className: 'flex flex-col gap-3', children: block.items.map((item) => (_jsx("p", { children: item }, item))) }, index))) }));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { PsIcon } from '@pallasoft/ps-icons';
|
|
3
|
-
import { PsCard } from './ps-card';
|
|
3
|
+
import { PsCard } from './ps-card.js';
|
|
4
4
|
export const PsFeatureCard = ({ description, iconKey, title }) => (_jsxs(PsCard, { className: 'h-full text-center', density: 'spacious', children: [_jsx("span", { className: 'ps-icon-surface mx-auto h-12 w-12', children: _jsx(PsIcon, { className: 'h-6 w-6', iconKey: iconKey }) }), _jsx("h3", { className: 'text-header-4 mb-2 mt-4 text-ink', children: title }), _jsx("p", { className: 'text-body-2 text-ink/60', children: description })] }));
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { PsStaggerContainer, PsStaggerItem } from '@pallasoft/ps-motion-components';
|
|
3
|
-
import { PsWebsiteSectionConfig } from '../constants/ps-website-section-config';
|
|
4
|
-
import { PsFeatureCard } from './ps-feature-card';
|
|
5
|
-
import { PsSectionIntro } from './ps-section-intro';
|
|
3
|
+
import { PsWebsiteSectionConfig } from '../constants/ps-website-section-config.js';
|
|
4
|
+
import { PsFeatureCard } from './ps-feature-card.js';
|
|
5
|
+
import { PsSectionIntro } from './ps-section-intro.js';
|
|
6
6
|
export const PsFeatureGrid = ({ description, eyebrow, features, title }) => (_jsxs("div", { className: 'flex w-full flex-col items-center gap-8', children: [_jsx(PsSectionIntro, { description: description, eyebrow: eyebrow, title: title }), _jsx(PsStaggerContainer, { className: 'grid w-full grid-cols-1 gap-5 md:grid-cols-3', staggerDelay: PsWebsiteSectionConfig.staggerDelay, children: features.map((feature) => (_jsx(PsStaggerItem, { children: _jsx(PsFeatureCard, { description: feature.description, iconKey: feature.iconKey, title: feature.title }) }, feature.title))) })] }));
|