@pallasoft/ps-core-components 2.8.0 → 2.9.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 (53) hide show
  1. package/dist/components/ps-action-tile.js +2 -1
  2. package/dist/components/ps-audio-spectrum.d.ts +4 -2
  3. package/dist/components/ps-audio-spectrum.js +22 -6
  4. package/dist/components/ps-badge.js +2 -1
  5. package/dist/components/ps-card.js +2 -1
  6. package/dist/components/ps-pill.js +2 -1
  7. package/dist/components/ps-section-header.js +2 -1
  8. package/dist/components/ps-site-header.js +4 -1
  9. package/dist/components/ps-skeleton-group.d.ts +3 -1
  10. package/dist/components/ps-skeleton-group.js +2 -1
  11. package/dist/components/ps-skeleton-list.js +2 -1
  12. package/dist/components/ps-skeleton-media.d.ts +7 -0
  13. package/dist/components/ps-skeleton-media.js +10 -0
  14. package/dist/components/ps-skeleton-table.js +2 -1
  15. package/dist/components/ps-skeleton-text.d.ts +1 -1
  16. package/dist/components/ps-skeleton-text.js +2 -4
  17. package/dist/components/ps-skeleton.d.ts +7 -2
  18. package/dist/components/ps-skeleton.js +31 -4
  19. package/dist/constants/ps-audio-spectrum-config.d.ts +4 -0
  20. package/dist/constants/ps-audio-spectrum-config.js +7 -0
  21. package/dist/constants/ps-site-header-config.d.ts +3 -0
  22. package/dist/constants/ps-site-header-config.js +6 -0
  23. package/dist/constants/ps-skeleton-config.d.ts +2 -0
  24. package/dist/constants/ps-skeleton-config.js +2 -0
  25. package/dist/constants/ps-skeleton-shape.d.ts +6 -0
  26. package/dist/constants/ps-skeleton-shape.js +10 -0
  27. package/dist/esm/components/ps-action-tile.js +2 -1
  28. package/dist/esm/components/ps-audio-spectrum.js +22 -6
  29. package/dist/esm/components/ps-badge.js +2 -1
  30. package/dist/esm/components/ps-card.js +2 -1
  31. package/dist/esm/components/ps-pill.js +2 -1
  32. package/dist/esm/components/ps-section-header.js +2 -1
  33. package/dist/esm/components/ps-site-header.js +4 -1
  34. package/dist/esm/components/ps-skeleton-group.js +2 -1
  35. package/dist/esm/components/ps-skeleton-list.js +2 -1
  36. package/dist/esm/components/ps-skeleton-media.js +6 -0
  37. package/dist/esm/components/ps-skeleton-table.js +2 -1
  38. package/dist/esm/components/ps-skeleton-text.js +2 -4
  39. package/dist/esm/components/ps-skeleton.js +31 -4
  40. package/dist/esm/constants/ps-audio-spectrum-config.js +4 -0
  41. package/dist/esm/constants/ps-site-header-config.js +3 -0
  42. package/dist/esm/constants/ps-skeleton-config.js +2 -0
  43. package/dist/esm/constants/ps-skeleton-shape.js +7 -0
  44. package/dist/esm/hooks/use-ps-audio-spectrum.js +12 -4
  45. package/dist/esm/hooks/use-ps-published-height.js +15 -0
  46. package/dist/esm/index.js +5 -0
  47. package/dist/hooks/use-ps-audio-spectrum.d.ts +5 -1
  48. package/dist/hooks/use-ps-audio-spectrum.js +11 -3
  49. package/dist/hooks/use-ps-published-height.d.ts +1 -0
  50. package/dist/hooks/use-ps-published-height.js +19 -0
  51. package/dist/index.d.ts +5 -0
  52. package/dist/index.js +5 -0
  53. package/package.json +1 -1
@@ -3,10 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsActionTile = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const ps_design_system_1 = require("@pallasoft/ps-design-system");
6
+ const ps_skeleton_shape_1 = require("../constants/ps-skeleton-shape");
6
7
  const ps_skeleton_1 = require("./ps-skeleton");
7
8
  const variantClassNames = {
8
9
  default: 'ps-action-tile',
9
10
  primary: 'ps-action-tile ps-action-tile-primary',
10
11
  };
11
- const PsActionTile = ({ className, description, icon, isLoading = false, label, type = 'button', variant = 'default', ...props }) => isLoading ? ((0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: ps_design_system_1.PallasoftClassNameService.merge('h-16 w-full rounded-ps-card', className), shape: 'block' })) : ((0, jsx_runtime_1.jsxs)("button", { className: ps_design_system_1.PallasoftClassNameService.merge('ps-focus-ring w-full', variantClassNames[variant], className), type: type, ...props, children: [(0, jsx_runtime_1.jsxs)("span", { className: 'min-w-0', children: [(0, jsx_runtime_1.jsx)("span", { className: 'block break-words', children: label }), description ? ((0, jsx_runtime_1.jsx)("span", { className: ps_design_system_1.PallasoftClassNameService.merge('mt-0.5 block text-xs font-medium leading-5', variant === 'primary' ? 'text-white/75' : 'text-ink/50'), children: description })) : null] }), icon ? ((0, jsx_runtime_1.jsx)("span", { className: ps_design_system_1.PallasoftClassNameService.merge('flex h-9 w-9 shrink-0 items-center justify-center rounded-lg', variant === 'primary' ? 'bg-white/15 text-white' : 'ps-icon-surface'), children: icon })) : null] }));
12
+ const PsActionTile = ({ className, description, icon, isLoading = false, label, type = 'button', variant = 'default', ...props }) => isLoading ? ((0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: ps_design_system_1.PallasoftClassNameService.merge('h-16 w-full rounded-ps-card', className), shape: ps_skeleton_shape_1.PsSkeletonShape.Block })) : ((0, jsx_runtime_1.jsxs)("button", { className: ps_design_system_1.PallasoftClassNameService.merge('ps-focus-ring w-full', variantClassNames[variant], className), type: type, ...props, children: [(0, jsx_runtime_1.jsxs)("span", { className: 'min-w-0', children: [(0, jsx_runtime_1.jsx)("span", { className: 'block break-words', children: label }), description ? ((0, jsx_runtime_1.jsx)("span", { className: ps_design_system_1.PallasoftClassNameService.merge('mt-0.5 block text-xs font-medium leading-5', variant === 'primary' ? 'text-white/75' : 'text-ink/50'), children: description })) : null] }), icon ? ((0, jsx_runtime_1.jsx)("span", { className: ps_design_system_1.PallasoftClassNameService.merge('flex h-9 w-9 shrink-0 items-center justify-center rounded-lg', variant === 'primary' ? 'bg-white/15 text-white' : 'ps-icon-surface'), children: icon })) : null] }));
12
13
  exports.PsActionTile = PsActionTile;
@@ -1,5 +1,7 @@
1
+ import type { UsePsAudioSpectrum } from '../hooks/use-ps-audio-spectrum';
1
2
  export interface PsAudioSpectrumProps {
3
+ barCount?: number;
2
4
  className?: string;
3
- levels: number[];
5
+ spectrum: UsePsAudioSpectrum;
4
6
  }
5
- export declare const PsAudioSpectrum: (props: PsAudioSpectrumProps) => import("react").JSX.Element;
7
+ export declare const PsAudioSpectrum: ({ barCount, className, spectrum, }: PsAudioSpectrumProps) => import("react").JSX.Element;
@@ -2,12 +2,28 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsAudioSpectrum = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const react_1 = require("react");
5
6
  const ps_design_system_1 = require("@pallasoft/ps-design-system");
6
- const MinBarHeightPercent = 10;
7
- const PsAudioSpectrum = (props) => {
8
- return ((0, jsx_runtime_1.jsx)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('flex h-full w-full items-end gap-2', props.className), children: props.levels.map((level, index) => {
9
- const heightPercent = MinBarHeightPercent + Math.max(0, Math.min(1, level)) * (100 - MinBarHeightPercent);
10
- return ((0, jsx_runtime_1.jsx)("span", { className: 'min-w-0 flex-1 rounded-full bg-[linear-gradient(180deg,_rgb(var(--ps-color-primary-rgb)/0.25)_0%,_rgb(var(--ps-color-primary-rgb))_100%)] transition-[height] duration-100 ease-out', style: { height: `${heightPercent}%` } }, index));
11
- }) }));
7
+ const ps_audio_spectrum_config_1 = require("../constants/ps-audio-spectrum-config");
8
+ const scaleFor = (level) => {
9
+ const bounded = Math.max(0, Math.min(1, level));
10
+ return ps_audio_spectrum_config_1.PsAudioSpectrumConfig.minimumScale + bounded * (1 - ps_audio_spectrum_config_1.PsAudioSpectrumConfig.minimumScale);
11
+ };
12
+ const PsAudioSpectrum = ({ barCount = ps_audio_spectrum_config_1.PsAudioSpectrumConfig.defaultBarCount, className, spectrum, }) => {
13
+ const barsRef = (0, react_1.useRef)([]);
14
+ (0, react_1.useEffect)(() => {
15
+ const paint = (levels) => {
16
+ barsRef.current.forEach((bar, index) => {
17
+ if (bar === null)
18
+ return;
19
+ bar.style.transform = `scaleY(${scaleFor(levels[index] !== undefined ? levels[index] : 0)})`;
20
+ });
21
+ };
22
+ paint(spectrum.levelsRef.current);
23
+ return spectrum.subscribe(paint);
24
+ }, [spectrum]);
25
+ return ((0, jsx_runtime_1.jsx)("div", { "aria-hidden": 'true', className: ps_design_system_1.PallasoftClassNameService.merge('flex h-full w-full items-end gap-2', className), children: Array.from({ length: barCount }, (item, index) => ((0, jsx_runtime_1.jsx)("span", { className: 'h-full min-w-0 flex-1 origin-bottom rounded-full bg-[linear-gradient(180deg,_rgb(var(--ps-color-primary-rgb)/0.25)_0%,_rgb(var(--ps-color-primary-rgb))_100%)] will-change-transform', ref: (element) => {
26
+ barsRef.current[index] = element;
27
+ }, style: { transform: `scaleY(${ps_audio_spectrum_config_1.PsAudioSpectrumConfig.minimumScale})` } }, index))) }));
12
28
  };
13
29
  exports.PsAudioSpectrum = PsAudioSpectrum;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsBadge = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const ps_design_system_1 = require("@pallasoft/ps-design-system");
6
+ const ps_skeleton_shape_1 = require("../constants/ps-skeleton-shape");
6
7
  const ps_skeleton_1 = require("./ps-skeleton");
7
8
  const toneClassNames = {
8
9
  danger: 'bg-danger-soft text-danger dark:bg-rose-500/18 dark:text-rose-100',
@@ -11,5 +12,5 @@ const toneClassNames = {
11
12
  success: 'bg-success-soft text-emerald-700 dark:bg-emerald-400/18 dark:text-emerald-50',
12
13
  warning: 'bg-warning-soft text-amber-800 dark:bg-amber-400/18 dark:text-amber-50',
13
14
  };
14
- const PsBadge = ({ children, className, isLoading = false, tone = 'neutral', }) => isLoading ? ((0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: ps_design_system_1.PallasoftClassNameService.merge('h-7 w-20', className), shape: 'block' })) : ((0, jsx_runtime_1.jsx)("span", { className: ps_design_system_1.PallasoftClassNameService.merge('inline-flex min-h-7 w-fit items-center justify-center whitespace-nowrap rounded-full px-3 py-0.5 text-center text-xs font-semibold capitalize', toneClassNames[tone], className), children: children }));
15
+ const PsBadge = ({ children, className, isLoading = false, tone = 'neutral', }) => isLoading ? ((0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: ps_design_system_1.PallasoftClassNameService.merge('h-7 w-20', className), shape: ps_skeleton_shape_1.PsSkeletonShape.Block })) : ((0, jsx_runtime_1.jsx)("span", { className: ps_design_system_1.PallasoftClassNameService.merge('inline-flex min-h-7 w-fit items-center justify-center whitespace-nowrap rounded-full px-3 py-0.5 text-center text-xs font-semibold capitalize', toneClassNames[tone], className), children: children }));
15
16
  exports.PsBadge = PsBadge;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsCard = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const ps_design_system_1 = require("@pallasoft/ps-design-system");
6
+ const ps_skeleton_shape_1 = require("../constants/ps-skeleton-shape");
6
7
  const ps_skeleton_1 = require("./ps-skeleton");
7
8
  const ps_skeleton_group_1 = require("./ps-skeleton-group");
8
9
  const densityClassNames = {
@@ -16,5 +17,5 @@ const variantClassNames = {
16
17
  glass: 'ps-glass',
17
18
  muted: 'ps-card-muted',
18
19
  };
19
- const PsCard = ({ children, className, density = 'normal', eyebrow, isLoading = false, title, trailing, variant = 'default', }) => isLoading ? ((0, jsx_runtime_1.jsxs)(ps_skeleton_group_1.PsSkeletonGroup, { className: ps_design_system_1.PallasoftClassNameService.merge('flex min-w-0 flex-col gap-3 rounded-ps-card', variantClassNames[variant], densityClassNames[density], className), label: title === undefined ? 'Loading' : title, children: [(0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'h-3 w-32' }), (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'h-20 w-full', shape: 'block' })] })) : ((0, jsx_runtime_1.jsxs)("section", { className: ps_design_system_1.PallasoftClassNameService.merge('min-w-0 overflow-hidden rounded-ps-card', variantClassNames[variant], densityClassNames[density], className), children: [title ? ((0, jsx_runtime_1.jsxs)("div", { className: 'mb-3 flex min-w-0 items-start justify-between gap-3', children: [(0, jsx_runtime_1.jsxs)("div", { className: 'min-w-0', children: [eyebrow ? (0, jsx_runtime_1.jsx)("p", { className: 'ps-eyebrow break-words', children: eyebrow }) : null, (0, jsx_runtime_1.jsx)("h2", { className: 'mt-1 break-words text-base font-bold text-ink', children: title })] }), trailing ? (0, jsx_runtime_1.jsx)("div", { className: 'shrink-0', children: trailing }) : null] })) : null, children] }));
20
+ const PsCard = ({ children, className, density = 'normal', eyebrow, isLoading = false, title, trailing, variant = 'default', }) => isLoading ? ((0, jsx_runtime_1.jsxs)(ps_skeleton_group_1.PsSkeletonGroup, { className: ps_design_system_1.PallasoftClassNameService.merge('flex min-w-0 flex-col gap-3 rounded-ps-card', variantClassNames[variant], densityClassNames[density], className), label: title === undefined ? 'Loading' : title, children: [(0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'h-3 w-32' }), (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'h-20 w-full', shape: ps_skeleton_shape_1.PsSkeletonShape.Block })] })) : ((0, jsx_runtime_1.jsxs)("section", { className: ps_design_system_1.PallasoftClassNameService.merge('min-w-0 overflow-hidden rounded-ps-card', variantClassNames[variant], densityClassNames[density], className), children: [title ? ((0, jsx_runtime_1.jsxs)("div", { className: 'mb-3 flex min-w-0 items-start justify-between gap-3', children: [(0, jsx_runtime_1.jsxs)("div", { className: 'min-w-0', children: [eyebrow ? (0, jsx_runtime_1.jsx)("p", { className: 'ps-eyebrow break-words', children: eyebrow }) : null, (0, jsx_runtime_1.jsx)("h2", { className: 'mt-1 break-words text-base font-bold text-ink', children: title })] }), trailing ? (0, jsx_runtime_1.jsx)("div", { className: 'shrink-0', children: trailing }) : null] })) : null, children] }));
20
21
  exports.PsCard = PsCard;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsPill = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const ps_design_system_1 = require("@pallasoft/ps-design-system");
6
+ const ps_skeleton_shape_1 = require("../constants/ps-skeleton-shape");
6
7
  const ps_skeleton_1 = require("./ps-skeleton");
7
8
  const toneClassNames = {
8
9
  danger: 'bg-rose-50 text-rose-700 ring-rose-100 dark:bg-rose-500/18 dark:text-rose-100 dark:ring-rose-300/22',
@@ -11,5 +12,5 @@ const toneClassNames = {
11
12
  success: 'bg-emerald-50 text-emerald-700 ring-emerald-100 dark:bg-emerald-400/18 dark:text-emerald-50 dark:ring-emerald-200/22',
12
13
  warning: 'bg-amber-50 text-amber-800 ring-amber-100 dark:bg-amber-400/18 dark:text-amber-50 dark:ring-amber-200/24',
13
14
  };
14
- const PsPill = ({ children, className, isLoading = false, tone = 'neutral', }) => isLoading ? ((0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: ps_design_system_1.PallasoftClassNameService.merge('h-8 w-24', className), shape: 'block' })) : ((0, jsx_runtime_1.jsx)("span", { className: ps_design_system_1.PallasoftClassNameService.merge('inline-flex min-h-8 min-w-[5.5rem] max-w-full items-center justify-center rounded-full px-5 py-1 text-center text-[0.72rem] font-black capitalize tracking-[0.01em] ring-1 ring-inset', toneClassNames[tone], className), children: (0, jsx_runtime_1.jsx)("span", { className: 'min-w-0 break-words', children: children }) }));
15
+ const PsPill = ({ children, className, isLoading = false, tone = 'neutral', }) => isLoading ? ((0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: ps_design_system_1.PallasoftClassNameService.merge('h-8 w-24', className), shape: ps_skeleton_shape_1.PsSkeletonShape.Block })) : ((0, jsx_runtime_1.jsx)("span", { className: ps_design_system_1.PallasoftClassNameService.merge('inline-flex min-h-8 min-w-[5.5rem] max-w-full items-center justify-center rounded-full px-5 py-1 text-center text-[0.72rem] font-black capitalize tracking-[0.01em] ring-1 ring-inset', toneClassNames[tone], className), children: (0, jsx_runtime_1.jsx)("span", { className: 'min-w-0 break-words', children: children }) }));
15
16
  exports.PsPill = PsPill;
@@ -2,7 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsSectionHeader = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const ps_skeleton_shape_1 = require("../constants/ps-skeleton-shape");
5
6
  const ps_skeleton_1 = require("./ps-skeleton");
6
7
  const ps_skeleton_group_1 = require("./ps-skeleton-group");
7
- const PsSectionHeader = ({ description, eyebrow, isLoading = false, leading, title, trailing, }) => isLoading ? ((0, jsx_runtime_1.jsxs)(ps_skeleton_group_1.PsSkeletonGroup, { className: 'flex flex-wrap items-end justify-between gap-x-4 gap-y-3', label: title, children: [(0, jsx_runtime_1.jsxs)("div", { className: 'flex min-w-0 flex-1 basis-auto flex-col gap-2', children: [eyebrow ? (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'h-2.5 w-24' }) : null, (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'h-6 w-52' }), description ? (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'h-3 w-72' }) : null] }), trailing ? (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'h-10 w-32', shape: 'block' }) : null] })) : ((0, jsx_runtime_1.jsxs)("div", { className: 'flex flex-wrap items-end justify-between gap-x-4 gap-y-3', children: [(0, jsx_runtime_1.jsxs)("div", { className: 'flex min-w-0 flex-1 basis-auto flex-col gap-2', children: [leading, eyebrow ? ((0, jsx_runtime_1.jsx)("p", { className: 'text-[0.68rem] font-semibold uppercase tracking-[0.22em] text-ink/50', children: eyebrow })) : null, (0, jsx_runtime_1.jsx)("h1", { className: 'break-words text-xl font-extrabold text-ink sm:text-2xl', children: title }), description ? ((0, jsx_runtime_1.jsx)("p", { className: 'max-w-3xl text-sm leading-6 text-ink/60', children: description })) : null] }), trailing ? ((0, jsx_runtime_1.jsx)("div", { className: 'flex w-full shrink-0 items-center justify-end sm:ml-auto sm:w-auto', children: trailing })) : null] }));
8
+ const PsSectionHeader = ({ description, eyebrow, isLoading = false, leading, title, trailing, }) => isLoading ? ((0, jsx_runtime_1.jsxs)(ps_skeleton_group_1.PsSkeletonGroup, { className: 'flex flex-wrap items-end justify-between gap-x-4 gap-y-3', label: title, children: [(0, jsx_runtime_1.jsxs)("div", { className: 'flex min-w-0 flex-1 basis-auto flex-col gap-2', children: [eyebrow ? (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'h-2.5 w-24' }) : null, (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'h-6 w-52' }), description ? (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'h-3 w-72' }) : null] }), trailing ? (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'h-10 w-32', shape: ps_skeleton_shape_1.PsSkeletonShape.Block }) : null] })) : ((0, jsx_runtime_1.jsxs)("div", { className: 'flex flex-wrap items-end justify-between gap-x-4 gap-y-3', children: [(0, jsx_runtime_1.jsxs)("div", { className: 'flex min-w-0 flex-1 basis-auto flex-col gap-2', children: [leading, eyebrow ? ((0, jsx_runtime_1.jsx)("p", { className: 'text-[0.68rem] font-semibold uppercase tracking-[0.22em] text-ink/50', children: eyebrow })) : null, (0, jsx_runtime_1.jsx)("h1", { className: 'break-words text-xl font-extrabold text-ink sm:text-2xl', children: title }), description ? ((0, jsx_runtime_1.jsx)("p", { className: 'max-w-3xl text-sm leading-6 text-ink/60', children: description })) : null] }), trailing ? ((0, jsx_runtime_1.jsx)("div", { className: 'flex w-full shrink-0 items-center justify-end sm:ml-auto sm:w-auto', children: trailing })) : null] }));
8
9
  exports.PsSectionHeader = PsSectionHeader;
@@ -4,12 +4,15 @@ exports.PsSiteHeader = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const ps_design_system_1 = require("@pallasoft/ps-design-system");
6
6
  const ps_icons_1 = require("@pallasoft/ps-icons");
7
+ const ps_site_header_config_1 = require("../constants/ps-site-header-config");
8
+ const use_ps_published_height_1 = require("../hooks/use-ps-published-height");
7
9
  const logoLinkClassName = 'flex shrink-0 items-center gap-2.5';
8
10
  const PsSiteHeader = ({ centerContent, className, homeHref, label, LinkComponent, logoAlt, logoClassName, logoSrc, logoSrcDark, logoSrcMobile, logoSrcMobileDark, navClassName, onBack, showLabel = false, trailing, }) => {
11
+ const headerRef = (0, use_ps_published_height_1.usePsPublishedHeight)(ps_site_header_config_1.PsSiteHeaderConfig.heightVariable);
9
12
  const logoLabel = `${label} home`;
10
13
  const renderLogo = (src, darkSrc, baseClassName) => darkSrc ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("img", { alt: logoAlt !== null && logoAlt !== undefined ? logoAlt : label, className: ps_design_system_1.PallasoftClassNameService.merge(baseClassName, 'dark:hidden', logoClassName), src: src }), (0, jsx_runtime_1.jsx)("img", { alt: logoAlt !== null && logoAlt !== undefined ? logoAlt : label, className: ps_design_system_1.PallasoftClassNameService.merge(baseClassName, 'hidden dark:block', logoClassName), src: darkSrc })] })) : ((0, jsx_runtime_1.jsx)("img", { alt: logoAlt !== null && logoAlt !== undefined ? logoAlt : label, className: ps_design_system_1.PallasoftClassNameService.merge(baseClassName, logoClassName), src: src }));
11
14
  const logoContent = logoSrcMobile ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { className: 'hidden sm:contents', children: renderLogo(logoSrc, logoSrcDark, 'h-8 w-auto') }), (0, jsx_runtime_1.jsx)("span", { className: 'contents sm:hidden', children: renderLogo(logoSrcMobile, logoSrcMobileDark, 'h-8 w-auto') }), showLabel ? (0, jsx_runtime_1.jsx)("span", { className: 'text-base font-bold text-ink', children: label }) : null] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [renderLogo(logoSrc, logoSrcDark, 'h-8 w-auto'), showLabel ? (0, jsx_runtime_1.jsx)("span", { className: 'text-base font-bold text-ink', children: label }) : null] }));
12
15
  const logoLink = LinkComponent ? ((0, jsx_runtime_1.jsx)(LinkComponent, { "aria-label": logoLabel, className: logoLinkClassName, to: homeHref, children: logoContent })) : ((0, jsx_runtime_1.jsx)("a", { "aria-label": logoLabel, className: logoLinkClassName, href: homeHref, children: logoContent }));
13
- return ((0, jsx_runtime_1.jsx)("header", { className: ps_design_system_1.PallasoftClassNameService.merge('fixed inset-x-0 top-0 z-header px-6 pt-4', className), children: (0, jsx_runtime_1.jsxs)("nav", { className: ps_design_system_1.PallasoftClassNameService.merge('ps-glass mx-auto flex max-w-6xl items-center gap-3 rounded-ps-card px-5 py-3', navClassName), children: [onBack ? ((0, jsx_runtime_1.jsx)("button", { "aria-label": 'Back', className: 'ps-focus-ring flex h-9 w-9 shrink-0 items-center justify-center rounded-full text-ink md:hidden', onClick: onBack, type: 'button', children: (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { iconKey: ps_icons_1.PsIconKey.ChevronRight, width: 20, height: 20, className: 'rotate-180' }) })) : null, (0, jsx_runtime_1.jsx)("div", { className: onBack ? 'hidden md:flex' : 'contents', children: logoLink }), (0, jsx_runtime_1.jsx)("div", { className: 'flex min-w-0 flex-1 items-center justify-center gap-3', children: centerContent }), trailing ? (0, jsx_runtime_1.jsx)("div", { className: 'flex shrink-0 items-center gap-2.5', children: trailing }) : null] }) }));
16
+ return ((0, jsx_runtime_1.jsx)("header", { ref: headerRef, className: ps_design_system_1.PallasoftClassNameService.merge('fixed inset-x-0 top-0 z-header px-6 pt-4', className), children: (0, jsx_runtime_1.jsxs)("nav", { className: ps_design_system_1.PallasoftClassNameService.merge('ps-glass mx-auto flex max-w-6xl items-center gap-3 rounded-ps-card px-5 py-3', navClassName), children: [onBack ? ((0, jsx_runtime_1.jsx)("button", { "aria-label": 'Back', className: 'ps-focus-ring flex h-9 w-9 shrink-0 items-center justify-center rounded-full text-ink md:hidden', onClick: onBack, type: 'button', children: (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { iconKey: ps_icons_1.PsIconKey.ChevronRight, width: 20, height: 20, className: 'rotate-180' }) })) : null, (0, jsx_runtime_1.jsx)("div", { className: onBack ? 'hidden md:flex' : 'contents', children: logoLink }), (0, jsx_runtime_1.jsx)("div", { className: 'flex min-w-0 flex-1 items-center justify-center gap-3', children: centerContent }), trailing ? (0, jsx_runtime_1.jsx)("div", { className: 'flex shrink-0 items-center gap-2.5', children: trailing }) : null] }) }));
14
17
  };
15
18
  exports.PsSiteHeader = PsSiteHeader;
@@ -2,6 +2,8 @@ import type { ReactNode } from 'react';
2
2
  export interface PsSkeletonGroupProps {
3
3
  children: ReactNode;
4
4
  className?: string;
5
+ direction?: 'column' | 'row';
6
+ gap?: string;
5
7
  label?: string;
6
8
  }
7
- export declare const PsSkeletonGroup: ({ children, className, label, }: PsSkeletonGroupProps) => import("react").JSX.Element;
9
+ export declare const PsSkeletonGroup: ({ children, className, direction, gap, label, }: PsSkeletonGroupProps) => import("react").JSX.Element;
@@ -2,5 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsSkeletonGroup = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const PsSkeletonGroup = ({ children, className, label = 'Loading', }) => ((0, jsx_runtime_1.jsxs)("div", { "aria-busy": 'true', className: className, role: 'status', children: [(0, jsx_runtime_1.jsx)("span", { className: 'sr-only', children: label }), children] }));
5
+ const ps_design_system_1 = require("@pallasoft/ps-design-system");
6
+ const PsSkeletonGroup = ({ children, className, direction = 'column', gap, label = 'Loading', }) => ((0, jsx_runtime_1.jsxs)("div", { "aria-busy": 'true', className: ps_design_system_1.PallasoftClassNameService.merge('flex', direction === 'row' ? 'flex-row items-center' : 'flex-col', gap === undefined ? 'gap-3' : gap, className), role: 'status', children: [(0, jsx_runtime_1.jsx)("span", { className: 'sr-only', children: label }), children] }));
6
7
  exports.PsSkeletonGroup = PsSkeletonGroup;
@@ -4,7 +4,8 @@ exports.PsSkeletonList = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const ps_design_system_1 = require("@pallasoft/ps-design-system");
6
6
  const ps_skeleton_config_1 = require("../constants/ps-skeleton-config");
7
+ const ps_skeleton_shape_1 = require("../constants/ps-skeleton-shape");
7
8
  const ps_skeleton_1 = require("./ps-skeleton");
8
9
  const ps_skeleton_group_1 = require("./ps-skeleton-group");
9
- const PsSkeletonList = ({ className, hasLeading = false, hasTrailing = true, rows = 4, title = false, }) => ((0, jsx_runtime_1.jsxs)(ps_skeleton_group_1.PsSkeletonGroup, { className: ps_design_system_1.PallasoftClassNameService.merge('flex flex-col', className), children: [title ? (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'mx-3 mb-3 h-2.5 w-24' }) : null, Array.from({ length: rows }, (_, index) => ((0, jsx_runtime_1.jsxs)("div", { className: 'flex min-h-11 items-center gap-3 px-3 py-2.5', children: [hasLeading ? (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { shape: 'circle' }) : null, (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: ps_skeleton_config_1.PsSkeletonConfig.lineWidths[index % ps_skeleton_config_1.PsSkeletonConfig.lineWidths.length] }), hasTrailing ? (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'ml-auto h-2.5 w-20 shrink-0' }) : null] }, index)))] }));
10
+ const PsSkeletonList = ({ className, hasLeading = false, hasTrailing = true, rows = 4, title = false, }) => ((0, jsx_runtime_1.jsxs)(ps_skeleton_group_1.PsSkeletonGroup, { className: ps_design_system_1.PallasoftClassNameService.merge('flex flex-col', className), children: [title ? (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'mx-3 mb-3 h-2.5 w-24' }) : null, Array.from({ length: rows }, (_, index) => ((0, jsx_runtime_1.jsxs)("div", { className: 'flex min-h-11 items-center gap-3 px-3 py-2.5', children: [hasLeading ? (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { shape: ps_skeleton_shape_1.PsSkeletonShape.Circle }) : null, (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: ps_skeleton_config_1.PsSkeletonConfig.lineWidths[index % ps_skeleton_config_1.PsSkeletonConfig.lineWidths.length] }), hasTrailing ? (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'ml-auto h-2.5 w-20 shrink-0' }) : null] }, index)))] }));
10
11
  exports.PsSkeletonList = PsSkeletonList;
@@ -0,0 +1,7 @@
1
+ export interface PsSkeletonMediaProps {
2
+ aspect?: string;
3
+ className?: string;
4
+ hasCaption?: boolean;
5
+ label?: string;
6
+ }
7
+ export declare const PsSkeletonMedia: ({ aspect, className, hasCaption, label, }: PsSkeletonMediaProps) => import("react").JSX.Element;
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsSkeletonMedia = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const ps_design_system_1 = require("@pallasoft/ps-design-system");
6
+ const ps_skeleton_shape_1 = require("../constants/ps-skeleton-shape");
7
+ const ps_skeleton_1 = require("./ps-skeleton");
8
+ const ps_skeleton_group_1 = require("./ps-skeleton-group");
9
+ const PsSkeletonMedia = ({ aspect = '16 / 9', className, hasCaption = true, label, }) => ((0, jsx_runtime_1.jsxs)(ps_skeleton_group_1.PsSkeletonGroup, { className: ps_design_system_1.PallasoftClassNameService.merge('w-full', className), label: label, children: [(0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { aspect: aspect, radius: 'var(--ps-radius-card, 1rem)', shape: ps_skeleton_shape_1.PsSkeletonShape.Block }), hasCaption ? (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { lines: 2, shape: ps_skeleton_shape_1.PsSkeletonShape.Text }) : null] }));
10
+ exports.PsSkeletonMedia = PsSkeletonMedia;
@@ -4,11 +4,12 @@ exports.PsSkeletonTable = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const ps_design_system_1 = require("@pallasoft/ps-design-system");
6
6
  const ps_skeleton_config_1 = require("../constants/ps-skeleton-config");
7
+ const ps_skeleton_shape_1 = require("../constants/ps-skeleton-shape");
7
8
  const ps_skeleton_1 = require("./ps-skeleton");
8
9
  const ps_skeleton_group_1 = require("./ps-skeleton-group");
9
10
  const PsSkeletonTable = ({ className, columns = 4, hasToolbar = false, rows = 6, }) => {
10
11
  const gridTemplateColumns = `minmax(0, 2fr) repeat(${Math.max(columns - 1, 0)}, minmax(0, 1fr))`;
11
- return ((0, jsx_runtime_1.jsxs)(ps_skeleton_group_1.PsSkeletonGroup, { className: ps_design_system_1.PallasoftClassNameService.merge('flex flex-col gap-3', className), children: [hasToolbar ? ((0, jsx_runtime_1.jsxs)("div", { className: 'flex items-center gap-3', children: [(0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'max-w-sm', shape: 'block' }), (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'ml-auto w-24', shape: 'block' })] })) : null, (0, jsx_runtime_1.jsxs)("div", { className: 'overflow-hidden rounded-[1.25rem] border border-line bg-surface', children: [(0, jsx_runtime_1.jsx)("div", { className: 'grid gap-4 bg-mist/70 px-5 py-4', style: { gridTemplateColumns }, children: Array.from({ length: columns }, (_, index) => ((0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'h-2.5 w-16' }, index))) }), Array.from({ length: rows }, (_, rowIndex) => ((0, jsx_runtime_1.jsx)("div", { className: 'grid items-center gap-4 border-t border-line px-5 py-4', style: { gridTemplateColumns }, children: Array.from({ length: columns }, (__, columnIndex) => ((0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: columnIndex === columns - 1 && columns > 1
12
+ return ((0, jsx_runtime_1.jsxs)(ps_skeleton_group_1.PsSkeletonGroup, { className: ps_design_system_1.PallasoftClassNameService.merge('flex flex-col gap-3', className), children: [hasToolbar ? ((0, jsx_runtime_1.jsxs)("div", { className: 'flex items-center gap-3', children: [(0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'max-w-sm', shape: ps_skeleton_shape_1.PsSkeletonShape.Block }), (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'ml-auto w-24', shape: ps_skeleton_shape_1.PsSkeletonShape.Block })] })) : null, (0, jsx_runtime_1.jsxs)("div", { className: 'overflow-hidden rounded-[1.25rem] border border-line bg-surface', children: [(0, jsx_runtime_1.jsx)("div", { className: 'grid gap-4 bg-mist/70 px-5 py-4', style: { gridTemplateColumns }, children: Array.from({ length: columns }, (_, index) => ((0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'h-2.5 w-16' }, index))) }), Array.from({ length: rows }, (_, rowIndex) => ((0, jsx_runtime_1.jsx)("div", { className: 'grid items-center gap-4 border-t border-line px-5 py-4', style: { gridTemplateColumns }, children: Array.from({ length: columns }, (__, columnIndex) => ((0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: columnIndex === columns - 1 && columns > 1
12
13
  ? 'ml-auto w-16'
13
14
  : ps_skeleton_config_1.PsSkeletonConfig.lineWidths[(rowIndex + columnIndex) % ps_skeleton_config_1.PsSkeletonConfig.lineWidths.length] }, columnIndex))) }, rowIndex)))] })] }));
14
15
  };
@@ -2,4 +2,4 @@ export interface PsSkeletonTextProps {
2
2
  className?: string;
3
3
  lines?: number;
4
4
  }
5
- export declare const PsSkeletonText: ({ className, lines }: PsSkeletonTextProps) => import("react").JSX.Element;
5
+ export declare const PsSkeletonText: ({ className, lines, }: PsSkeletonTextProps) => import("react").JSX.Element;
@@ -4,9 +4,7 @@ exports.PsSkeletonText = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const ps_design_system_1 = require("@pallasoft/ps-design-system");
6
6
  const ps_skeleton_config_1 = require("../constants/ps-skeleton-config");
7
+ const ps_skeleton_shape_1 = require("../constants/ps-skeleton-shape");
7
8
  const ps_skeleton_1 = require("./ps-skeleton");
8
- const ps_skeleton_group_1 = require("./ps-skeleton-group");
9
- const PsSkeletonText = ({ className, lines = 3 }) => ((0, jsx_runtime_1.jsx)(ps_skeleton_group_1.PsSkeletonGroup, { className: ps_design_system_1.PallasoftClassNameService.merge('flex flex-col gap-2.5', className), children: Array.from({ length: lines }, (_, index) => ((0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: index === lines - 1 && lines > 1
10
- ? 'w-2/3'
11
- : ps_skeleton_config_1.PsSkeletonConfig.lineWidths[index % ps_skeleton_config_1.PsSkeletonConfig.lineWidths.length] }, index))) }));
9
+ const PsSkeletonText = ({ className, lines = ps_skeleton_config_1.PsSkeletonConfig.defaultTextLines, }) => ((0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: ps_design_system_1.PallasoftClassNameService.merge('w-full', className), lines: lines, shape: ps_skeleton_shape_1.PsSkeletonShape.Text }));
12
10
  exports.PsSkeletonText = PsSkeletonText;
@@ -1,6 +1,11 @@
1
- export type PsSkeletonShape = 'block' | 'circle' | 'line';
1
+ import { PsSkeletonShape } from '../constants/ps-skeleton-shape';
2
2
  export interface PsSkeletonProps {
3
+ aspect?: string;
3
4
  className?: string;
5
+ height?: string;
6
+ lines?: number;
7
+ radius?: string;
4
8
  shape?: PsSkeletonShape;
9
+ width?: string;
5
10
  }
6
- export declare const PsSkeleton: ({ className, shape }: PsSkeletonProps) => import("react").JSX.Element;
11
+ export declare const PsSkeleton: ({ shape, ...props }: PsSkeletonProps) => import("react").JSX.Element;
@@ -3,10 +3,37 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsSkeleton = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
5
  const ps_design_system_1 = require("@pallasoft/ps-design-system");
6
+ const ps_skeleton_config_1 = require("../constants/ps-skeleton-config");
7
+ const ps_skeleton_shape_1 = require("../constants/ps-skeleton-shape");
6
8
  const shapeClassNames = {
7
- block: 'h-11 w-full rounded-ps-control',
8
- circle: 'h-9 w-9 shrink-0 rounded-full',
9
- line: 'h-3 w-full rounded-full',
9
+ [ps_skeleton_shape_1.PsSkeletonShape.Block]: 'h-11 w-full rounded-ps-control',
10
+ [ps_skeleton_shape_1.PsSkeletonShape.Circle]: 'h-9 w-9 shrink-0 rounded-full',
11
+ [ps_skeleton_shape_1.PsSkeletonShape.Line]: 'h-3 w-full rounded-full',
12
+ [ps_skeleton_shape_1.PsSkeletonShape.Text]: 'h-3 w-full rounded-full',
13
+ };
14
+ const sizeStyle = (props) => {
15
+ const style = {};
16
+ if (props.width !== undefined)
17
+ style.width = props.width;
18
+ if (props.height !== undefined)
19
+ style.height = props.height;
20
+ if (props.radius !== undefined)
21
+ style.borderRadius = props.radius;
22
+ if (props.aspect !== undefined) {
23
+ style.aspectRatio = props.aspect;
24
+ if (props.height === undefined)
25
+ style.height = 'auto';
26
+ }
27
+ return Object.keys(style).length > 0 ? style : undefined;
28
+ };
29
+ const PsSkeleton = ({ shape = ps_skeleton_shape_1.PsSkeletonShape.Line, ...props }) => {
30
+ const style = sizeStyle(props);
31
+ if (shape === ps_skeleton_shape_1.PsSkeletonShape.Text) {
32
+ const lines = props.lines !== undefined ? props.lines : ps_skeleton_config_1.PsSkeletonConfig.defaultTextLines;
33
+ return ((0, jsx_runtime_1.jsx)("span", { className: ps_design_system_1.PallasoftClassNameService.merge('flex flex-col gap-2.5', props.className), children: Array.from({ length: lines }, (item, index) => ((0, jsx_runtime_1.jsx)("span", { "aria-hidden": 'true', className: ps_design_system_1.PallasoftClassNameService.merge('ps-skeleton', shapeClassNames[ps_skeleton_shape_1.PsSkeletonShape.Line], index === lines - 1 && lines > 1
34
+ ? ps_skeleton_config_1.PsSkeletonConfig.lastLineWidth
35
+ : ps_skeleton_config_1.PsSkeletonConfig.lineWidths[index % ps_skeleton_config_1.PsSkeletonConfig.lineWidths.length]), style: style }, index))) }));
36
+ }
37
+ return ((0, jsx_runtime_1.jsx)("span", { "aria-hidden": 'true', className: ps_design_system_1.PallasoftClassNameService.merge('ps-skeleton', shapeClassNames[shape], props.className), style: style }));
10
38
  };
11
- const PsSkeleton = ({ className, shape = 'line' }) => ((0, jsx_runtime_1.jsx)("span", { "aria-hidden": 'true', className: ps_design_system_1.PallasoftClassNameService.merge('ps-skeleton', shapeClassNames[shape], className) }));
12
39
  exports.PsSkeleton = PsSkeleton;
@@ -0,0 +1,4 @@
1
+ export declare const PsAudioSpectrumConfig: {
2
+ readonly defaultBarCount: 12;
3
+ readonly minimumScale: 0.1;
4
+ };
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsAudioSpectrumConfig = void 0;
4
+ exports.PsAudioSpectrumConfig = {
5
+ defaultBarCount: 12,
6
+ minimumScale: 0.1,
7
+ };
@@ -0,0 +1,3 @@
1
+ export declare const PsSiteHeaderConfig: {
2
+ readonly heightVariable: "--ps-site-header-height";
3
+ };
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsSiteHeaderConfig = void 0;
4
+ exports.PsSiteHeaderConfig = {
5
+ heightVariable: '--ps-site-header-height',
6
+ };
@@ -1,3 +1,5 @@
1
1
  export declare const PsSkeletonConfig: {
2
+ readonly defaultTextLines: 3;
3
+ readonly lastLineWidth: "w-2/3";
2
4
  readonly lineWidths: readonly ["w-3/4", "w-1/2", "w-5/6", "w-2/3"];
3
5
  };
@@ -2,5 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsSkeletonConfig = void 0;
4
4
  exports.PsSkeletonConfig = {
5
+ defaultTextLines: 3,
6
+ lastLineWidth: 'w-2/3',
5
7
  lineWidths: ['w-3/4', 'w-1/2', 'w-5/6', 'w-2/3'],
6
8
  };
@@ -0,0 +1,6 @@
1
+ export declare enum PsSkeletonShape {
2
+ Block = "block",
3
+ Circle = "circle",
4
+ Line = "line",
5
+ Text = "text"
6
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsSkeletonShape = void 0;
4
+ var PsSkeletonShape;
5
+ (function (PsSkeletonShape) {
6
+ PsSkeletonShape["Block"] = "block";
7
+ PsSkeletonShape["Circle"] = "circle";
8
+ PsSkeletonShape["Line"] = "line";
9
+ PsSkeletonShape["Text"] = "text";
10
+ })(PsSkeletonShape || (exports.PsSkeletonShape = PsSkeletonShape = {}));
@@ -1,8 +1,9 @@
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';
3
4
  import { PsSkeleton } from './ps-skeleton';
4
5
  const variantClassNames = {
5
6
  default: 'ps-action-tile',
6
7
  primary: 'ps-action-tile ps-action-tile-primary',
7
8
  };
8
- export const PsActionTile = ({ className, description, icon, isLoading = false, label, type = 'button', variant = 'default', ...props }) => isLoading ? (_jsx(PsSkeleton, { className: PallasoftClassNameService.merge('h-16 w-full rounded-ps-card', className), shape: 'block' })) : (_jsxs("button", { className: PallasoftClassNameService.merge('ps-focus-ring w-full', variantClassNames[variant], className), type: type, ...props, children: [_jsxs("span", { className: 'min-w-0', children: [_jsx("span", { className: 'block break-words', children: label }), description ? (_jsx("span", { className: PallasoftClassNameService.merge('mt-0.5 block text-xs font-medium leading-5', variant === 'primary' ? 'text-white/75' : 'text-ink/50'), children: description })) : null] }), icon ? (_jsx("span", { className: PallasoftClassNameService.merge('flex h-9 w-9 shrink-0 items-center justify-center rounded-lg', variant === 'primary' ? 'bg-white/15 text-white' : 'ps-icon-surface'), children: icon })) : null] }));
9
+ export const PsActionTile = ({ className, description, icon, isLoading = false, label, type = 'button', variant = 'default', ...props }) => isLoading ? (_jsx(PsSkeleton, { className: PallasoftClassNameService.merge('h-16 w-full rounded-ps-card', className), shape: PsSkeletonShape.Block })) : (_jsxs("button", { className: PallasoftClassNameService.merge('ps-focus-ring w-full', variantClassNames[variant], className), type: type, ...props, children: [_jsxs("span", { className: 'min-w-0', children: [_jsx("span", { className: 'block break-words', children: label }), description ? (_jsx("span", { className: PallasoftClassNameService.merge('mt-0.5 block text-xs font-medium leading-5', variant === 'primary' ? 'text-white/75' : 'text-ink/50'), children: description })) : null] }), icon ? (_jsx("span", { className: PallasoftClassNameService.merge('flex h-9 w-9 shrink-0 items-center justify-center rounded-lg', variant === 'primary' ? 'bg-white/15 text-white' : 'ps-icon-surface'), children: icon })) : null] }));
@@ -1,9 +1,25 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useEffect, useRef } from 'react';
2
3
  import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
- const MinBarHeightPercent = 10;
4
- export const PsAudioSpectrum = (props) => {
5
- return (_jsx("div", { className: PallasoftClassNameService.merge('flex h-full w-full items-end gap-2', props.className), children: props.levels.map((level, index) => {
6
- const heightPercent = MinBarHeightPercent + Math.max(0, Math.min(1, level)) * (100 - MinBarHeightPercent);
7
- return (_jsx("span", { className: 'min-w-0 flex-1 rounded-full bg-[linear-gradient(180deg,_rgb(var(--ps-color-primary-rgb)/0.25)_0%,_rgb(var(--ps-color-primary-rgb))_100%)] transition-[height] duration-100 ease-out', style: { height: `${heightPercent}%` } }, index));
8
- }) }));
4
+ import { PsAudioSpectrumConfig } from '../constants/ps-audio-spectrum-config';
5
+ const scaleFor = (level) => {
6
+ const bounded = Math.max(0, Math.min(1, level));
7
+ return PsAudioSpectrumConfig.minimumScale + bounded * (1 - PsAudioSpectrumConfig.minimumScale);
8
+ };
9
+ export const PsAudioSpectrum = ({ barCount = PsAudioSpectrumConfig.defaultBarCount, className, spectrum, }) => {
10
+ const barsRef = useRef([]);
11
+ useEffect(() => {
12
+ const paint = (levels) => {
13
+ barsRef.current.forEach((bar, index) => {
14
+ if (bar === null)
15
+ return;
16
+ bar.style.transform = `scaleY(${scaleFor(levels[index] !== undefined ? levels[index] : 0)})`;
17
+ });
18
+ };
19
+ paint(spectrum.levelsRef.current);
20
+ return spectrum.subscribe(paint);
21
+ }, [spectrum]);
22
+ return (_jsx("div", { "aria-hidden": 'true', className: PallasoftClassNameService.merge('flex h-full w-full items-end gap-2', className), children: Array.from({ length: barCount }, (item, index) => (_jsx("span", { className: 'h-full min-w-0 flex-1 origin-bottom rounded-full bg-[linear-gradient(180deg,_rgb(var(--ps-color-primary-rgb)/0.25)_0%,_rgb(var(--ps-color-primary-rgb))_100%)] will-change-transform', ref: (element) => {
23
+ barsRef.current[index] = element;
24
+ }, style: { transform: `scaleY(${PsAudioSpectrumConfig.minimumScale})` } }, index))) }));
9
25
  };
@@ -1,5 +1,6 @@
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';
3
4
  import { PsSkeleton } from './ps-skeleton';
4
5
  const toneClassNames = {
5
6
  danger: 'bg-danger-soft text-danger dark:bg-rose-500/18 dark:text-rose-100',
@@ -8,4 +9,4 @@ const toneClassNames = {
8
9
  success: 'bg-success-soft text-emerald-700 dark:bg-emerald-400/18 dark:text-emerald-50',
9
10
  warning: 'bg-warning-soft text-amber-800 dark:bg-amber-400/18 dark:text-amber-50',
10
11
  };
11
- export const PsBadge = ({ children, className, isLoading = false, tone = 'neutral', }) => isLoading ? (_jsx(PsSkeleton, { className: PallasoftClassNameService.merge('h-7 w-20', className), shape: 'block' })) : (_jsx("span", { className: PallasoftClassNameService.merge('inline-flex min-h-7 w-fit items-center justify-center whitespace-nowrap rounded-full px-3 py-0.5 text-center text-xs font-semibold capitalize', toneClassNames[tone], className), children: children }));
12
+ export const PsBadge = ({ children, className, isLoading = false, tone = 'neutral', }) => isLoading ? (_jsx(PsSkeleton, { className: PallasoftClassNameService.merge('h-7 w-20', className), shape: PsSkeletonShape.Block })) : (_jsx("span", { className: PallasoftClassNameService.merge('inline-flex min-h-7 w-fit items-center justify-center whitespace-nowrap rounded-full px-3 py-0.5 text-center text-xs font-semibold capitalize', toneClassNames[tone], className), children: children }));
@@ -1,5 +1,6 @@
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';
3
4
  import { PsSkeleton } from './ps-skeleton';
4
5
  import { PsSkeletonGroup } from './ps-skeleton-group';
5
6
  const densityClassNames = {
@@ -13,4 +14,4 @@ const variantClassNames = {
13
14
  glass: 'ps-glass',
14
15
  muted: 'ps-card-muted',
15
16
  };
16
- export const PsCard = ({ children, className, density = 'normal', eyebrow, isLoading = false, title, trailing, variant = 'default', }) => isLoading ? (_jsxs(PsSkeletonGroup, { className: PallasoftClassNameService.merge('flex min-w-0 flex-col gap-3 rounded-ps-card', variantClassNames[variant], densityClassNames[density], className), label: title === undefined ? 'Loading' : title, children: [_jsx(PsSkeleton, { className: 'h-3 w-32' }), _jsx(PsSkeleton, { className: 'h-20 w-full', shape: 'block' })] })) : (_jsxs("section", { className: PallasoftClassNameService.merge('min-w-0 overflow-hidden rounded-ps-card', variantClassNames[variant], densityClassNames[density], className), children: [title ? (_jsxs("div", { className: 'mb-3 flex min-w-0 items-start justify-between gap-3', children: [_jsxs("div", { className: 'min-w-0', children: [eyebrow ? _jsx("p", { className: 'ps-eyebrow break-words', children: eyebrow }) : null, _jsx("h2", { className: 'mt-1 break-words text-base font-bold text-ink', children: title })] }), trailing ? _jsx("div", { className: 'shrink-0', children: trailing }) : null] })) : null, children] }));
17
+ export const PsCard = ({ children, className, density = 'normal', eyebrow, isLoading = false, title, trailing, variant = 'default', }) => isLoading ? (_jsxs(PsSkeletonGroup, { className: PallasoftClassNameService.merge('flex min-w-0 flex-col gap-3 rounded-ps-card', variantClassNames[variant], densityClassNames[density], className), label: title === undefined ? 'Loading' : title, children: [_jsx(PsSkeleton, { className: 'h-3 w-32' }), _jsx(PsSkeleton, { className: 'h-20 w-full', shape: PsSkeletonShape.Block })] })) : (_jsxs("section", { className: PallasoftClassNameService.merge('min-w-0 overflow-hidden rounded-ps-card', variantClassNames[variant], densityClassNames[density], className), children: [title ? (_jsxs("div", { className: 'mb-3 flex min-w-0 items-start justify-between gap-3', children: [_jsxs("div", { className: 'min-w-0', children: [eyebrow ? _jsx("p", { className: 'ps-eyebrow break-words', children: eyebrow }) : null, _jsx("h2", { className: 'mt-1 break-words text-base font-bold text-ink', children: title })] }), trailing ? _jsx("div", { className: 'shrink-0', children: trailing }) : null] })) : null, children] }));
@@ -1,5 +1,6 @@
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';
3
4
  import { PsSkeleton } from './ps-skeleton';
4
5
  const toneClassNames = {
5
6
  danger: 'bg-rose-50 text-rose-700 ring-rose-100 dark:bg-rose-500/18 dark:text-rose-100 dark:ring-rose-300/22',
@@ -8,4 +9,4 @@ const toneClassNames = {
8
9
  success: 'bg-emerald-50 text-emerald-700 ring-emerald-100 dark:bg-emerald-400/18 dark:text-emerald-50 dark:ring-emerald-200/22',
9
10
  warning: 'bg-amber-50 text-amber-800 ring-amber-100 dark:bg-amber-400/18 dark:text-amber-50 dark:ring-amber-200/24',
10
11
  };
11
- export const PsPill = ({ children, className, isLoading = false, tone = 'neutral', }) => isLoading ? (_jsx(PsSkeleton, { className: PallasoftClassNameService.merge('h-8 w-24', className), shape: 'block' })) : (_jsx("span", { className: PallasoftClassNameService.merge('inline-flex min-h-8 min-w-[5.5rem] max-w-full items-center justify-center rounded-full px-5 py-1 text-center text-[0.72rem] font-black capitalize tracking-[0.01em] ring-1 ring-inset', toneClassNames[tone], className), children: _jsx("span", { className: 'min-w-0 break-words', children: children }) }));
12
+ export const PsPill = ({ children, className, isLoading = false, tone = 'neutral', }) => isLoading ? (_jsx(PsSkeleton, { className: PallasoftClassNameService.merge('h-8 w-24', className), shape: PsSkeletonShape.Block })) : (_jsx("span", { className: PallasoftClassNameService.merge('inline-flex min-h-8 min-w-[5.5rem] max-w-full items-center justify-center rounded-full px-5 py-1 text-center text-[0.72rem] font-black capitalize tracking-[0.01em] ring-1 ring-inset', toneClassNames[tone], className), children: _jsx("span", { className: 'min-w-0 break-words', children: children }) }));
@@ -1,4 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { PsSkeletonShape } from '../constants/ps-skeleton-shape';
2
3
  import { PsSkeleton } from './ps-skeleton';
3
4
  import { PsSkeletonGroup } from './ps-skeleton-group';
4
- export const PsSectionHeader = ({ description, eyebrow, isLoading = false, leading, title, trailing, }) => isLoading ? (_jsxs(PsSkeletonGroup, { className: 'flex flex-wrap items-end justify-between gap-x-4 gap-y-3', label: title, children: [_jsxs("div", { className: 'flex min-w-0 flex-1 basis-auto flex-col gap-2', children: [eyebrow ? _jsx(PsSkeleton, { className: 'h-2.5 w-24' }) : null, _jsx(PsSkeleton, { className: 'h-6 w-52' }), description ? _jsx(PsSkeleton, { className: 'h-3 w-72' }) : null] }), trailing ? _jsx(PsSkeleton, { className: 'h-10 w-32', shape: 'block' }) : null] })) : (_jsxs("div", { className: 'flex flex-wrap items-end justify-between gap-x-4 gap-y-3', children: [_jsxs("div", { className: 'flex min-w-0 flex-1 basis-auto flex-col gap-2', children: [leading, eyebrow ? (_jsx("p", { className: 'text-[0.68rem] font-semibold uppercase tracking-[0.22em] text-ink/50', children: eyebrow })) : null, _jsx("h1", { className: 'break-words text-xl font-extrabold text-ink sm:text-2xl', children: title }), description ? (_jsx("p", { className: 'max-w-3xl text-sm leading-6 text-ink/60', children: description })) : null] }), trailing ? (_jsx("div", { className: 'flex w-full shrink-0 items-center justify-end sm:ml-auto sm:w-auto', children: trailing })) : null] }));
5
+ export const PsSectionHeader = ({ description, eyebrow, isLoading = false, leading, title, trailing, }) => isLoading ? (_jsxs(PsSkeletonGroup, { className: 'flex flex-wrap items-end justify-between gap-x-4 gap-y-3', label: title, children: [_jsxs("div", { className: 'flex min-w-0 flex-1 basis-auto flex-col gap-2', children: [eyebrow ? _jsx(PsSkeleton, { className: 'h-2.5 w-24' }) : null, _jsx(PsSkeleton, { className: 'h-6 w-52' }), description ? _jsx(PsSkeleton, { className: 'h-3 w-72' }) : null] }), trailing ? _jsx(PsSkeleton, { className: 'h-10 w-32', shape: PsSkeletonShape.Block }) : null] })) : (_jsxs("div", { className: 'flex flex-wrap items-end justify-between gap-x-4 gap-y-3', children: [_jsxs("div", { className: 'flex min-w-0 flex-1 basis-auto flex-col gap-2', children: [leading, eyebrow ? (_jsx("p", { className: 'text-[0.68rem] font-semibold uppercase tracking-[0.22em] text-ink/50', children: eyebrow })) : null, _jsx("h1", { className: 'break-words text-xl font-extrabold text-ink sm:text-2xl', children: title }), description ? (_jsx("p", { className: 'max-w-3xl text-sm leading-6 text-ink/60', children: description })) : null] }), trailing ? (_jsx("div", { className: 'flex w-full shrink-0 items-center justify-end sm:ml-auto sm:w-auto', children: trailing })) : null] }));
@@ -1,11 +1,14 @@
1
1
  import { jsx as _jsx, Fragment as _Fragment, 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
+ import { PsSiteHeaderConfig } from '../constants/ps-site-header-config';
5
+ import { usePsPublishedHeight } from '../hooks/use-ps-published-height';
4
6
  const logoLinkClassName = 'flex shrink-0 items-center gap-2.5';
5
7
  export const PsSiteHeader = ({ centerContent, className, homeHref, label, LinkComponent, logoAlt, logoClassName, logoSrc, logoSrcDark, logoSrcMobile, logoSrcMobileDark, navClassName, onBack, showLabel = false, trailing, }) => {
8
+ const headerRef = usePsPublishedHeight(PsSiteHeaderConfig.heightVariable);
6
9
  const logoLabel = `${label} home`;
7
10
  const renderLogo = (src, darkSrc, baseClassName) => darkSrc ? (_jsxs(_Fragment, { children: [_jsx("img", { alt: logoAlt !== null && logoAlt !== undefined ? logoAlt : label, className: PallasoftClassNameService.merge(baseClassName, 'dark:hidden', logoClassName), src: src }), _jsx("img", { alt: logoAlt !== null && logoAlt !== undefined ? logoAlt : label, className: PallasoftClassNameService.merge(baseClassName, 'hidden dark:block', logoClassName), src: darkSrc })] })) : (_jsx("img", { alt: logoAlt !== null && logoAlt !== undefined ? logoAlt : label, className: PallasoftClassNameService.merge(baseClassName, logoClassName), src: src }));
8
11
  const logoContent = logoSrcMobile ? (_jsxs(_Fragment, { children: [_jsx("span", { className: 'hidden sm:contents', children: renderLogo(logoSrc, logoSrcDark, 'h-8 w-auto') }), _jsx("span", { className: 'contents sm:hidden', children: renderLogo(logoSrcMobile, logoSrcMobileDark, 'h-8 w-auto') }), showLabel ? _jsx("span", { className: 'text-base font-bold text-ink', children: label }) : null] })) : (_jsxs(_Fragment, { children: [renderLogo(logoSrc, logoSrcDark, 'h-8 w-auto'), showLabel ? _jsx("span", { className: 'text-base font-bold text-ink', children: label }) : null] }));
9
12
  const logoLink = LinkComponent ? (_jsx(LinkComponent, { "aria-label": logoLabel, className: logoLinkClassName, to: homeHref, children: logoContent })) : (_jsx("a", { "aria-label": logoLabel, className: logoLinkClassName, href: homeHref, children: logoContent }));
10
- return (_jsx("header", { className: PallasoftClassNameService.merge('fixed inset-x-0 top-0 z-header px-6 pt-4', className), children: _jsxs("nav", { className: PallasoftClassNameService.merge('ps-glass mx-auto flex max-w-6xl items-center gap-3 rounded-ps-card px-5 py-3', navClassName), children: [onBack ? (_jsx("button", { "aria-label": 'Back', className: 'ps-focus-ring flex h-9 w-9 shrink-0 items-center justify-center rounded-full text-ink md:hidden', onClick: onBack, type: 'button', children: _jsx(PsIcon, { iconKey: PsIconKey.ChevronRight, width: 20, height: 20, className: 'rotate-180' }) })) : null, _jsx("div", { className: onBack ? 'hidden md:flex' : 'contents', children: logoLink }), _jsx("div", { className: 'flex min-w-0 flex-1 items-center justify-center gap-3', children: centerContent }), trailing ? _jsx("div", { className: 'flex shrink-0 items-center gap-2.5', children: trailing }) : null] }) }));
13
+ return (_jsx("header", { ref: headerRef, className: PallasoftClassNameService.merge('fixed inset-x-0 top-0 z-header px-6 pt-4', className), children: _jsxs("nav", { className: PallasoftClassNameService.merge('ps-glass mx-auto flex max-w-6xl items-center gap-3 rounded-ps-card px-5 py-3', navClassName), children: [onBack ? (_jsx("button", { "aria-label": 'Back', className: 'ps-focus-ring flex h-9 w-9 shrink-0 items-center justify-center rounded-full text-ink md:hidden', onClick: onBack, type: 'button', children: _jsx(PsIcon, { iconKey: PsIconKey.ChevronRight, width: 20, height: 20, className: 'rotate-180' }) })) : null, _jsx("div", { className: onBack ? 'hidden md:flex' : 'contents', children: logoLink }), _jsx("div", { className: 'flex min-w-0 flex-1 items-center justify-center gap-3', children: centerContent }), trailing ? _jsx("div", { className: 'flex shrink-0 items-center gap-2.5', children: trailing }) : null] }) }));
11
14
  };
@@ -1,2 +1,3 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- export const PsSkeletonGroup = ({ children, className, label = 'Loading', }) => (_jsxs("div", { "aria-busy": 'true', className: className, role: 'status', children: [_jsx("span", { className: 'sr-only', children: label }), children] }));
2
+ import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
+ export const PsSkeletonGroup = ({ children, className, direction = 'column', gap, label = 'Loading', }) => (_jsxs("div", { "aria-busy": 'true', className: PallasoftClassNameService.merge('flex', direction === 'row' ? 'flex-row items-center' : 'flex-col', gap === undefined ? 'gap-3' : gap, className), role: 'status', children: [_jsx("span", { className: 'sr-only', children: label }), children] }));
@@ -1,6 +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
3
  import { PsSkeletonConfig } from '../constants/ps-skeleton-config';
4
+ import { PsSkeletonShape } from '../constants/ps-skeleton-shape';
4
5
  import { PsSkeleton } from './ps-skeleton';
5
6
  import { PsSkeletonGroup } from './ps-skeleton-group';
6
- export const PsSkeletonList = ({ className, hasLeading = false, hasTrailing = true, rows = 4, title = false, }) => (_jsxs(PsSkeletonGroup, { className: PallasoftClassNameService.merge('flex flex-col', className), children: [title ? _jsx(PsSkeleton, { className: 'mx-3 mb-3 h-2.5 w-24' }) : null, Array.from({ length: rows }, (_, index) => (_jsxs("div", { className: 'flex min-h-11 items-center gap-3 px-3 py-2.5', children: [hasLeading ? _jsx(PsSkeleton, { shape: 'circle' }) : null, _jsx(PsSkeleton, { className: PsSkeletonConfig.lineWidths[index % PsSkeletonConfig.lineWidths.length] }), hasTrailing ? _jsx(PsSkeleton, { className: 'ml-auto h-2.5 w-20 shrink-0' }) : null] }, index)))] }));
7
+ export const PsSkeletonList = ({ className, hasLeading = false, hasTrailing = true, rows = 4, title = false, }) => (_jsxs(PsSkeletonGroup, { className: PallasoftClassNameService.merge('flex flex-col', className), children: [title ? _jsx(PsSkeleton, { className: 'mx-3 mb-3 h-2.5 w-24' }) : null, Array.from({ length: rows }, (_, index) => (_jsxs("div", { className: 'flex min-h-11 items-center gap-3 px-3 py-2.5', children: [hasLeading ? _jsx(PsSkeleton, { shape: PsSkeletonShape.Circle }) : null, _jsx(PsSkeleton, { className: PsSkeletonConfig.lineWidths[index % PsSkeletonConfig.lineWidths.length] }), hasTrailing ? _jsx(PsSkeleton, { className: 'ml-auto h-2.5 w-20 shrink-0' }) : null] }, index)))] }));
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
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';
6
+ export const PsSkeletonMedia = ({ aspect = '16 / 9', className, hasCaption = true, label, }) => (_jsxs(PsSkeletonGroup, { className: PallasoftClassNameService.merge('w-full', className), label: label, children: [_jsx(PsSkeleton, { aspect: aspect, radius: 'var(--ps-radius-card, 1rem)', shape: PsSkeletonShape.Block }), hasCaption ? _jsx(PsSkeleton, { lines: 2, shape: PsSkeletonShape.Text }) : null] }));
@@ -1,11 +1,12 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
3
  import { PsSkeletonConfig } from '../constants/ps-skeleton-config';
4
+ import { PsSkeletonShape } from '../constants/ps-skeleton-shape';
4
5
  import { PsSkeleton } from './ps-skeleton';
5
6
  import { PsSkeletonGroup } from './ps-skeleton-group';
6
7
  export const PsSkeletonTable = ({ className, columns = 4, hasToolbar = false, rows = 6, }) => {
7
8
  const gridTemplateColumns = `minmax(0, 2fr) repeat(${Math.max(columns - 1, 0)}, minmax(0, 1fr))`;
8
- return (_jsxs(PsSkeletonGroup, { className: PallasoftClassNameService.merge('flex flex-col gap-3', className), children: [hasToolbar ? (_jsxs("div", { className: 'flex items-center gap-3', children: [_jsx(PsSkeleton, { className: 'max-w-sm', shape: 'block' }), _jsx(PsSkeleton, { className: 'ml-auto w-24', shape: 'block' })] })) : null, _jsxs("div", { className: 'overflow-hidden rounded-[1.25rem] border border-line bg-surface', children: [_jsx("div", { className: 'grid gap-4 bg-mist/70 px-5 py-4', style: { gridTemplateColumns }, children: Array.from({ length: columns }, (_, index) => (_jsx(PsSkeleton, { className: 'h-2.5 w-16' }, index))) }), Array.from({ length: rows }, (_, rowIndex) => (_jsx("div", { className: 'grid items-center gap-4 border-t border-line px-5 py-4', style: { gridTemplateColumns }, children: Array.from({ length: columns }, (__, columnIndex) => (_jsx(PsSkeleton, { className: columnIndex === columns - 1 && columns > 1
9
+ return (_jsxs(PsSkeletonGroup, { className: PallasoftClassNameService.merge('flex flex-col gap-3', className), children: [hasToolbar ? (_jsxs("div", { className: 'flex items-center gap-3', children: [_jsx(PsSkeleton, { className: 'max-w-sm', shape: PsSkeletonShape.Block }), _jsx(PsSkeleton, { className: 'ml-auto w-24', shape: PsSkeletonShape.Block })] })) : null, _jsxs("div", { className: 'overflow-hidden rounded-[1.25rem] border border-line bg-surface', children: [_jsx("div", { className: 'grid gap-4 bg-mist/70 px-5 py-4', style: { gridTemplateColumns }, children: Array.from({ length: columns }, (_, index) => (_jsx(PsSkeleton, { className: 'h-2.5 w-16' }, index))) }), Array.from({ length: rows }, (_, rowIndex) => (_jsx("div", { className: 'grid items-center gap-4 border-t border-line px-5 py-4', style: { gridTemplateColumns }, children: Array.from({ length: columns }, (__, columnIndex) => (_jsx(PsSkeleton, { className: columnIndex === columns - 1 && columns > 1
9
10
  ? 'ml-auto w-16'
10
11
  : PsSkeletonConfig.lineWidths[(rowIndex + columnIndex) % PsSkeletonConfig.lineWidths.length] }, columnIndex))) }, rowIndex)))] })] }));
11
12
  };
@@ -1,8 +1,6 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
3
  import { PsSkeletonConfig } from '../constants/ps-skeleton-config';
4
+ import { PsSkeletonShape } from '../constants/ps-skeleton-shape';
4
5
  import { PsSkeleton } from './ps-skeleton';
5
- import { PsSkeletonGroup } from './ps-skeleton-group';
6
- export const PsSkeletonText = ({ className, lines = 3 }) => (_jsx(PsSkeletonGroup, { className: PallasoftClassNameService.merge('flex flex-col gap-2.5', className), children: Array.from({ length: lines }, (_, index) => (_jsx(PsSkeleton, { className: index === lines - 1 && lines > 1
7
- ? 'w-2/3'
8
- : PsSkeletonConfig.lineWidths[index % PsSkeletonConfig.lineWidths.length] }, index))) }));
6
+ export const PsSkeletonText = ({ className, lines = PsSkeletonConfig.defaultTextLines, }) => (_jsx(PsSkeleton, { className: PallasoftClassNameService.merge('w-full', className), lines: lines, shape: PsSkeletonShape.Text }));
@@ -1,8 +1,35 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
+ import { PsSkeletonConfig } from '../constants/ps-skeleton-config';
4
+ import { PsSkeletonShape } from '../constants/ps-skeleton-shape';
3
5
  const shapeClassNames = {
4
- block: 'h-11 w-full rounded-ps-control',
5
- circle: 'h-9 w-9 shrink-0 rounded-full',
6
- line: 'h-3 w-full rounded-full',
6
+ [PsSkeletonShape.Block]: 'h-11 w-full rounded-ps-control',
7
+ [PsSkeletonShape.Circle]: 'h-9 w-9 shrink-0 rounded-full',
8
+ [PsSkeletonShape.Line]: 'h-3 w-full rounded-full',
9
+ [PsSkeletonShape.Text]: 'h-3 w-full rounded-full',
10
+ };
11
+ const sizeStyle = (props) => {
12
+ const style = {};
13
+ if (props.width !== undefined)
14
+ style.width = props.width;
15
+ if (props.height !== undefined)
16
+ style.height = props.height;
17
+ if (props.radius !== undefined)
18
+ style.borderRadius = props.radius;
19
+ if (props.aspect !== undefined) {
20
+ style.aspectRatio = props.aspect;
21
+ if (props.height === undefined)
22
+ style.height = 'auto';
23
+ }
24
+ return Object.keys(style).length > 0 ? style : undefined;
25
+ };
26
+ export const PsSkeleton = ({ shape = PsSkeletonShape.Line, ...props }) => {
27
+ const style = sizeStyle(props);
28
+ if (shape === PsSkeletonShape.Text) {
29
+ const lines = props.lines !== undefined ? props.lines : PsSkeletonConfig.defaultTextLines;
30
+ return (_jsx("span", { className: PallasoftClassNameService.merge('flex flex-col gap-2.5', props.className), children: Array.from({ length: lines }, (item, index) => (_jsx("span", { "aria-hidden": 'true', className: PallasoftClassNameService.merge('ps-skeleton', shapeClassNames[PsSkeletonShape.Line], index === lines - 1 && lines > 1
31
+ ? PsSkeletonConfig.lastLineWidth
32
+ : PsSkeletonConfig.lineWidths[index % PsSkeletonConfig.lineWidths.length]), style: style }, index))) }));
33
+ }
34
+ return (_jsx("span", { "aria-hidden": 'true', className: PallasoftClassNameService.merge('ps-skeleton', shapeClassNames[shape], props.className), style: style }));
7
35
  };
8
- export const PsSkeleton = ({ className, shape = 'line' }) => (_jsx("span", { "aria-hidden": 'true', className: PallasoftClassNameService.merge('ps-skeleton', shapeClassNames[shape], className) }));
@@ -0,0 +1,4 @@
1
+ export const PsAudioSpectrumConfig = {
2
+ defaultBarCount: 12,
3
+ minimumScale: 0.1,
4
+ };
@@ -0,0 +1,3 @@
1
+ export const PsSiteHeaderConfig = {
2
+ heightVariable: '--ps-site-header-height',
3
+ };
@@ -1,3 +1,5 @@
1
1
  export const PsSkeletonConfig = {
2
+ defaultTextLines: 3,
3
+ lastLineWidth: 'w-2/3',
2
4
  lineWidths: ['w-3/4', 'w-1/2', 'w-5/6', 'w-2/3'],
3
5
  };
@@ -0,0 +1,7 @@
1
+ export var PsSkeletonShape;
2
+ (function (PsSkeletonShape) {
3
+ PsSkeletonShape["Block"] = "block";
4
+ PsSkeletonShape["Circle"] = "circle";
5
+ PsSkeletonShape["Line"] = "line";
6
+ PsSkeletonShape["Text"] = "text";
7
+ })(PsSkeletonShape || (PsSkeletonShape = {}));
@@ -1,4 +1,4 @@
1
- import { useEffect, useRef, useState } from 'react';
1
+ import { useCallback, useEffect, useRef } from 'react';
2
2
  export const usePsAudioSpectrum = (audioElement, options = {}) => {
3
3
  const DefaultBarCount = 12;
4
4
  const DefaultFftSize = 128;
@@ -6,9 +6,16 @@ export const usePsAudioSpectrum = (audioElement, options = {}) => {
6
6
  const barCount = typeof options.barCount === 'number' ? options.barCount : DefaultBarCount;
7
7
  const fftSize = typeof options.fftSize === 'number' ? options.fftSize : DefaultFftSize;
8
8
  const smoothing = typeof options.smoothing === 'number' ? options.smoothing : DefaultSmoothing;
9
- const [levels, setLevels] = useState(() => Array(barCount).fill(0));
9
+ const levelsRef = useRef(Array(barCount).fill(0));
10
+ const listenersRef = useRef(new Set());
10
11
  const configRef = useRef({ barCount, fftSize, smoothing });
11
12
  configRef.current = { barCount, fftSize, smoothing };
13
+ const subscribe = useCallback((listener) => {
14
+ listenersRef.current.add(listener);
15
+ return () => {
16
+ listenersRef.current.delete(listener);
17
+ };
18
+ }, []);
12
19
  useEffect(() => {
13
20
  if (!audioElement)
14
21
  return;
@@ -40,7 +47,8 @@ export const usePsAudioSpectrum = (audioElement, options = {}) => {
40
47
  }
41
48
  nextLevels.push(Math.min(1, sum / binsPerBar / 255));
42
49
  }
43
- setLevels(nextLevels);
50
+ levelsRef.current = nextLevels;
51
+ listenersRef.current.forEach((listener) => listener(nextLevels));
44
52
  animationFrame = requestAnimationFrame(tick);
45
53
  };
46
54
  const resumeAudioContext = () => {
@@ -61,5 +69,5 @@ export const usePsAudioSpectrum = (audioElement, options = {}) => {
61
69
  audioContext.close().catch(() => undefined);
62
70
  };
63
71
  }, [audioElement]);
64
- return { levels };
72
+ return { levelsRef, subscribe };
65
73
  };
@@ -0,0 +1,15 @@
1
+ import { useEffect, useRef } from 'react';
2
+ export const usePsPublishedHeight = (variableName) => {
3
+ const elementRef = useRef(null);
4
+ useEffect(() => {
5
+ const element = elementRef.current;
6
+ if (element === null || typeof ResizeObserver === 'undefined')
7
+ return;
8
+ const publish = () => document.documentElement.style.setProperty(variableName, `${element.offsetHeight}px`);
9
+ publish();
10
+ const observer = new ResizeObserver(publish);
11
+ observer.observe(element);
12
+ return () => observer.disconnect();
13
+ }, [variableName]);
14
+ return elementRef;
15
+ };
package/dist/esm/index.js CHANGED
@@ -2,6 +2,7 @@ export * from './components/ps-layer';
2
2
  export * from './components/ps-accordion';
3
3
  export * from './components/ps-action-tile';
4
4
  export * from './components/ps-audio-spectrum';
5
+ export * from './constants/ps-audio-spectrum-config';
5
6
  export * from './components/ps-badge';
6
7
  export * from './components/ps-button';
7
8
  export * from './components/ps-card';
@@ -18,10 +19,14 @@ export * from './components/ps-navigation-progress';
18
19
  export * from './components/ps-step-progress';
19
20
  export * from './components/ps-section-header';
20
21
  export * from './components/ps-site-header';
22
+ export * from './hooks/use-ps-published-height';
23
+ export * from './constants/ps-site-header-config';
21
24
  export * from './components/ps-skeleton';
25
+ export * from './constants/ps-skeleton-shape';
22
26
  export * from './components/ps-skeleton-card';
23
27
  export * from './components/ps-skeleton-group';
24
28
  export * from './components/ps-skeleton-list';
29
+ export * from './components/ps-skeleton-media';
25
30
  export * from './components/ps-skeleton-table';
26
31
  export * from './components/ps-skeleton-text';
27
32
  export * from './components/ps-spinner';
@@ -4,6 +4,10 @@ export interface UsePsAudioSpectrumOptions {
4
4
  smoothing?: number;
5
5
  }
6
6
  export interface UsePsAudioSpectrum {
7
- levels: number[];
7
+ levelsRef: {
8
+ current: number[];
9
+ };
10
+ subscribe: (listener: PsAudioSpectrumListener) => () => void;
8
11
  }
12
+ export type PsAudioSpectrumListener = (levels: number[]) => void;
9
13
  export declare const usePsAudioSpectrum: (audioElement: HTMLAudioElement | null, options?: UsePsAudioSpectrumOptions) => UsePsAudioSpectrum;
@@ -9,9 +9,16 @@ const usePsAudioSpectrum = (audioElement, options = {}) => {
9
9
  const barCount = typeof options.barCount === 'number' ? options.barCount : DefaultBarCount;
10
10
  const fftSize = typeof options.fftSize === 'number' ? options.fftSize : DefaultFftSize;
11
11
  const smoothing = typeof options.smoothing === 'number' ? options.smoothing : DefaultSmoothing;
12
- const [levels, setLevels] = (0, react_1.useState)(() => Array(barCount).fill(0));
12
+ const levelsRef = (0, react_1.useRef)(Array(barCount).fill(0));
13
+ const listenersRef = (0, react_1.useRef)(new Set());
13
14
  const configRef = (0, react_1.useRef)({ barCount, fftSize, smoothing });
14
15
  configRef.current = { barCount, fftSize, smoothing };
16
+ const subscribe = (0, react_1.useCallback)((listener) => {
17
+ listenersRef.current.add(listener);
18
+ return () => {
19
+ listenersRef.current.delete(listener);
20
+ };
21
+ }, []);
15
22
  (0, react_1.useEffect)(() => {
16
23
  if (!audioElement)
17
24
  return;
@@ -43,7 +50,8 @@ const usePsAudioSpectrum = (audioElement, options = {}) => {
43
50
  }
44
51
  nextLevels.push(Math.min(1, sum / binsPerBar / 255));
45
52
  }
46
- setLevels(nextLevels);
53
+ levelsRef.current = nextLevels;
54
+ listenersRef.current.forEach((listener) => listener(nextLevels));
47
55
  animationFrame = requestAnimationFrame(tick);
48
56
  };
49
57
  const resumeAudioContext = () => {
@@ -64,6 +72,6 @@ const usePsAudioSpectrum = (audioElement, options = {}) => {
64
72
  audioContext.close().catch(() => undefined);
65
73
  };
66
74
  }, [audioElement]);
67
- return { levels };
75
+ return { levelsRef, subscribe };
68
76
  };
69
77
  exports.usePsAudioSpectrum = usePsAudioSpectrum;
@@ -0,0 +1 @@
1
+ export declare const usePsPublishedHeight: <T extends HTMLElement>(variableName: string) => import("react").MutableRefObject<T | null>;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.usePsPublishedHeight = void 0;
4
+ const react_1 = require("react");
5
+ const usePsPublishedHeight = (variableName) => {
6
+ const elementRef = (0, react_1.useRef)(null);
7
+ (0, react_1.useEffect)(() => {
8
+ const element = elementRef.current;
9
+ if (element === null || typeof ResizeObserver === 'undefined')
10
+ return;
11
+ const publish = () => document.documentElement.style.setProperty(variableName, `${element.offsetHeight}px`);
12
+ publish();
13
+ const observer = new ResizeObserver(publish);
14
+ observer.observe(element);
15
+ return () => observer.disconnect();
16
+ }, [variableName]);
17
+ return elementRef;
18
+ };
19
+ exports.usePsPublishedHeight = usePsPublishedHeight;
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ export * from './components/ps-layer';
2
2
  export * from './components/ps-accordion';
3
3
  export * from './components/ps-action-tile';
4
4
  export * from './components/ps-audio-spectrum';
5
+ export * from './constants/ps-audio-spectrum-config';
5
6
  export * from './components/ps-badge';
6
7
  export * from './components/ps-button';
7
8
  export * from './components/ps-card';
@@ -18,10 +19,14 @@ export * from './components/ps-navigation-progress';
18
19
  export * from './components/ps-step-progress';
19
20
  export * from './components/ps-section-header';
20
21
  export * from './components/ps-site-header';
22
+ export * from './hooks/use-ps-published-height';
23
+ export * from './constants/ps-site-header-config';
21
24
  export * from './components/ps-skeleton';
25
+ export * from './constants/ps-skeleton-shape';
22
26
  export * from './components/ps-skeleton-card';
23
27
  export * from './components/ps-skeleton-group';
24
28
  export * from './components/ps-skeleton-list';
29
+ export * from './components/ps-skeleton-media';
25
30
  export * from './components/ps-skeleton-table';
26
31
  export * from './components/ps-skeleton-text';
27
32
  export * from './components/ps-spinner';
package/dist/index.js CHANGED
@@ -18,6 +18,7 @@ __exportStar(require("./components/ps-layer"), exports);
18
18
  __exportStar(require("./components/ps-accordion"), exports);
19
19
  __exportStar(require("./components/ps-action-tile"), exports);
20
20
  __exportStar(require("./components/ps-audio-spectrum"), exports);
21
+ __exportStar(require("./constants/ps-audio-spectrum-config"), exports);
21
22
  __exportStar(require("./components/ps-badge"), exports);
22
23
  __exportStar(require("./components/ps-button"), exports);
23
24
  __exportStar(require("./components/ps-card"), exports);
@@ -34,10 +35,14 @@ __exportStar(require("./components/ps-navigation-progress"), exports);
34
35
  __exportStar(require("./components/ps-step-progress"), exports);
35
36
  __exportStar(require("./components/ps-section-header"), exports);
36
37
  __exportStar(require("./components/ps-site-header"), exports);
38
+ __exportStar(require("./hooks/use-ps-published-height"), exports);
39
+ __exportStar(require("./constants/ps-site-header-config"), exports);
37
40
  __exportStar(require("./components/ps-skeleton"), exports);
41
+ __exportStar(require("./constants/ps-skeleton-shape"), exports);
38
42
  __exportStar(require("./components/ps-skeleton-card"), exports);
39
43
  __exportStar(require("./components/ps-skeleton-group"), exports);
40
44
  __exportStar(require("./components/ps-skeleton-list"), exports);
45
+ __exportStar(require("./components/ps-skeleton-media"), exports);
41
46
  __exportStar(require("./components/ps-skeleton-table"), exports);
42
47
  __exportStar(require("./components/ps-skeleton-text"), exports);
43
48
  __exportStar(require("./components/ps-spinner"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pallasoft/ps-core-components",
3
- "version": "2.8.0",
3
+ "version": "2.9.0",
4
4
  "private": false,
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/esm/index.js",