@pallasoft/ps-core-components 2.3.1 → 2.4.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 (65) hide show
  1. package/dist/components/ps-draggable-grid.d.ts +9 -12
  2. package/dist/components/ps-draggable-grid.js +72 -45
  3. package/dist/components/ps-navigation-progress.d.ts +3 -2
  4. package/dist/components/ps-navigation-progress.js +13 -22
  5. package/dist/components/ps-section-header.js +1 -1
  6. package/dist/constants/ps-draggable-grid.d.ts +17 -0
  7. package/dist/constants/ps-draggable-grid.js +26 -0
  8. package/dist/constants/ps-navigation-progress-config.d.ts +5 -0
  9. package/dist/constants/ps-navigation-progress-config.js +5 -0
  10. package/dist/esm/components/ps-accordion.js +5 -0
  11. package/dist/esm/components/ps-action-tile.js +7 -0
  12. package/dist/esm/components/ps-audio-spectrum.js +9 -0
  13. package/dist/esm/components/ps-badge.js +10 -0
  14. package/dist/esm/components/ps-button.js +16 -0
  15. package/dist/esm/components/ps-card.js +14 -0
  16. package/dist/esm/components/ps-draggable-grid.js +80 -0
  17. package/dist/esm/components/ps-empty-state.js +28 -0
  18. package/dist/esm/components/ps-fab.js +9 -0
  19. package/dist/esm/components/ps-infinite-scroll.js +5 -0
  20. package/dist/esm/components/ps-layer.js +3 -0
  21. package/dist/esm/components/ps-list-tile.js +11 -0
  22. package/dist/esm/components/ps-metric-card.js +3 -0
  23. package/dist/esm/components/ps-navigation-progress.js +21 -0
  24. package/dist/esm/components/ps-pill.js +10 -0
  25. package/dist/esm/components/ps-portable-text.js +34 -0
  26. package/dist/esm/components/ps-reflective-app-shell.js +13 -0
  27. package/dist/esm/components/ps-section-header.js +2 -0
  28. package/dist/esm/components/ps-site-header.js +11 -0
  29. package/dist/esm/components/ps-skeleton.js +3 -0
  30. package/dist/esm/components/ps-spinner.js +12 -0
  31. package/dist/esm/components/ps-theme-toggle.js +7 -0
  32. package/dist/esm/components/ps-voice-orb.js +100 -0
  33. package/dist/esm/constants/ps-draggable-grid.js +23 -0
  34. package/dist/esm/constants/ps-navigation-progress-config.js +12 -0
  35. package/dist/esm/constants/ps-voice-orb.js +85 -0
  36. package/dist/esm/contexts/ps-layer-context.js +2 -0
  37. package/dist/esm/hooks/use-ps-audio-spectrum.js +65 -0
  38. package/dist/esm/hooks/use-ps-exit-transition.js +29 -0
  39. package/dist/esm/hooks/use-ps-hide-on-scroll.js +25 -0
  40. package/dist/esm/hooks/use-ps-invisible-recaptcha.js +90 -0
  41. package/dist/esm/hooks/use-ps-layer-z-index.js +4 -0
  42. package/dist/esm/hooks/use-ps-navigation-progress.js +41 -0
  43. package/dist/esm/hooks/use-ps-route-loader-data.js +12 -0
  44. package/dist/esm/hooks/use-ps-viewport.js +18 -0
  45. package/dist/esm/index.js +38 -0
  46. package/dist/esm/interfaces/ps-component-props.js +1 -0
  47. package/dist/esm/models/ps-draggable-grid.js +1 -0
  48. package/dist/esm/models/ps-navigation-progress.js +1 -0
  49. package/dist/esm/models/ps-recaptcha-pending-request.js +1 -0
  50. package/dist/esm/models/ps-remix-react-module.js +1 -0
  51. package/dist/esm/models/ps-voice-orb.js +1 -0
  52. package/dist/hooks/use-ps-exit-transition.js +0 -1
  53. package/dist/hooks/use-ps-navigation-progress.d.ts +2 -0
  54. package/dist/hooks/use-ps-navigation-progress.js +45 -0
  55. package/dist/index.d.ts +4 -0
  56. package/dist/index.js +4 -0
  57. package/dist/models/ps-draggable-grid.d.ts +19 -0
  58. package/dist/models/ps-draggable-grid.js +2 -0
  59. package/dist/models/ps-navigation-progress.d.ts +5 -0
  60. package/dist/models/ps-navigation-progress.js +2 -0
  61. package/dist/models/ps-recaptcha-pending-request.d.ts +4 -0
  62. package/dist/models/ps-recaptcha-pending-request.js +2 -0
  63. package/dist/models/ps-remix-react-module.d.ts +3 -0
  64. package/dist/models/ps-remix-react-module.js +2 -0
  65. package/package.json +11 -3
@@ -1,19 +1,16 @@
1
- import type { JSX } from 'react';
2
- export interface PsDraggableGridItem {
3
- id: string;
1
+ import { type JSX } from 'react';
2
+ import { useSortable } from '@dnd-kit/sortable';
3
+ import { PsDraggableGridItem, PsDraggableGridProps, PsDraggableGridRenderOptions } from '../models/ps-draggable-grid';
4
+ export interface PsDraggableGridHandleProps {
4
5
  label: string;
6
+ listeners?: ReturnType<typeof useSortable>['listeners'];
7
+ attributes?: ReturnType<typeof useSortable>['attributes'];
8
+ setActivatorNodeRef?: (element: HTMLElement | null) => void;
5
9
  }
6
- export interface PsDraggableGridRenderOptions<TItem extends PsDraggableGridItem> {
7
- handle: JSX.Element;
10
+ export interface PsSortableGridItemProps<TItem extends PsDraggableGridItem> {
11
+ className: string;
8
12
  index: number;
9
- isDragging: boolean;
10
13
  item: TItem;
11
- }
12
- export interface PsDraggableGridProps<TItem extends PsDraggableGridItem> {
13
- getItemClassName?: (item: TItem) => string;
14
- items: TItem[];
15
- onReorder: (items: TItem[]) => void;
16
- onReorderEnd?: (items: TItem[]) => void;
17
14
  renderItem: (options: PsDraggableGridRenderOptions<TItem>) => JSX.Element | null;
18
15
  }
19
16
  export declare const PsDraggableGrid: <TItem extends PsDraggableGridItem>({ getItemClassName, items, onReorder, onReorderEnd, renderItem, }: PsDraggableGridProps<TItem>) => JSX.Element;
@@ -2,56 +2,83 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsDraggableGrid = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const moveItem = (items, fromIndex, toIndex) => {
6
- const nextItems = [...items];
7
- const [movingItem] = nextItems.splice(fromIndex, 1);
8
- nextItems.splice(toIndex, 0, movingItem);
9
- return nextItems;
5
+ const react_1 = require("react");
6
+ const core_1 = require("@dnd-kit/core");
7
+ const sortable_1 = require("@dnd-kit/sortable");
8
+ const utilities_1 = require("@dnd-kit/utilities");
9
+ const react_dom_1 = require("react-dom");
10
+ const ps_draggable_grid_1 = require("../constants/ps-draggable-grid");
11
+ const liftCard = (element) => {
12
+ if (element === null)
13
+ return;
14
+ element.animate(ps_draggable_grid_1.PsDraggableGridLiftFrames, {
15
+ duration: ps_draggable_grid_1.PsDraggableGridConfig.liftDuration,
16
+ easing: ps_draggable_grid_1.PsDraggableGridConfig.liftEasing,
17
+ fill: 'forwards',
18
+ });
19
+ };
20
+ const dropAnimation = {
21
+ duration: ps_draggable_grid_1.PsDraggableGridConfig.dropDuration,
22
+ easing: ps_draggable_grid_1.PsDraggableGridConfig.dropEasing,
23
+ sideEffects: (0, core_1.defaultDropAnimationSideEffects)({
24
+ styles: { active: { opacity: ps_draggable_grid_1.PsDraggableGridConfig.placeholderOpacity } },
25
+ }),
26
+ };
27
+ const DragHandleIcon = () => ((0, jsx_runtime_1.jsx)("span", { "aria-hidden": 'true', className: 'grid grid-cols-2 gap-[0.1875rem]', children: Array.from({ length: 6 }).map((_, index) => ((0, jsx_runtime_1.jsx)("span", { className: 'h-[3px] w-[3px] rounded-full bg-current' }, index))) }));
28
+ const PsDraggableGridHandle = ({ attributes, label, listeners, setActivatorNodeRef, }) => ((0, jsx_runtime_1.jsx)("button", { ...attributes, ...listeners, "aria-label": `Move ${label}`, className: ps_draggable_grid_1.PsDraggableGridClasses.handle, ref: setActivatorNodeRef, title: `Move ${label}`, type: 'button', children: (0, jsx_runtime_1.jsx)(DragHandleIcon, {}) }));
29
+ const PsSortableGridItem = ({ className, index, item, renderItem, }) => {
30
+ const { attributes, isDragging, listeners, setActivatorNodeRef, setNodeRef, transform, transition, } = (0, sortable_1.useSortable)({ id: item.id });
31
+ const rendered = renderItem({
32
+ handle: ((0, jsx_runtime_1.jsx)(PsDraggableGridHandle, { attributes: attributes, label: item.label, listeners: listeners, setActivatorNodeRef: setActivatorNodeRef })),
33
+ index,
34
+ isDragging,
35
+ isOverlay: false,
36
+ item,
37
+ });
38
+ if (!rendered)
39
+ return null;
40
+ return ((0, jsx_runtime_1.jsx)("div", { className: `${ps_draggable_grid_1.PsDraggableGridClasses.item} ${className} ${isDragging ? ps_draggable_grid_1.PsDraggableGridClasses.placeholder : ''}`, ref: setNodeRef, style: {
41
+ opacity: isDragging ? ps_draggable_grid_1.PsDraggableGridConfig.placeholderOpacity : undefined,
42
+ transform: utilities_1.CSS.Translate.toString(transform),
43
+ transition,
44
+ }, children: rendered }));
10
45
  };
11
- let draggedItemId;
12
- let latestItems = [];
13
- const DragHandleIcon = () => ((0, jsx_runtime_1.jsx)("span", { "aria-hidden": 'true', className: 'grid grid-cols-2 gap-[0.1875rem]', children: Array.from({ length: 6 }).map((_, index) => ((0, jsx_runtime_1.jsx)("span", { className: 'h-0.5 w-0.5 rounded-full bg-current' }, index))) }));
14
46
  const PsDraggableGrid = ({ getItemClassName, items, onReorder, onReorderEnd, renderItem, }) => {
15
- latestItems = items;
16
- const finishDrag = () => {
17
- if (!draggedItemId)
18
- return;
19
- draggedItemId = undefined;
20
- onReorderEnd?.(latestItems);
21
- };
22
- const moveDraggedItemTo = (targetItemId) => {
23
- if (!draggedItemId || draggedItemId === targetItemId)
47
+ const [activeId, setActiveId] = (0, react_1.useState)(null);
48
+ const [isMounted, setIsMounted] = (0, react_1.useState)(false);
49
+ (0, react_1.useEffect)(() => setIsMounted(true), []);
50
+ const sensors = (0, core_1.useSensors)((0, core_1.useSensor)(core_1.MouseSensor, {
51
+ activationConstraint: { distance: ps_draggable_grid_1.PsDraggableGridConfig.activationDistance },
52
+ }), (0, core_1.useSensor)(core_1.TouchSensor, {
53
+ activationConstraint: {
54
+ delay: ps_draggable_grid_1.PsDraggableGridConfig.touchDelay,
55
+ tolerance: ps_draggable_grid_1.PsDraggableGridConfig.touchTolerance,
56
+ },
57
+ }), (0, core_1.useSensor)(core_1.KeyboardSensor, { coordinateGetter: sortable_1.sortableKeyboardCoordinates }));
58
+ const className = (item) => getItemClassName !== undefined ? getItemClassName(item) : '';
59
+ const activeIndex = items.findIndex((item) => item.id === activeId);
60
+ const activeItem = activeIndex >= 0 ? items[activeIndex] : null;
61
+ const handleDragEnd = (event) => {
62
+ setActiveId(null);
63
+ if (event.over === null || event.active.id === event.over.id)
24
64
  return;
25
- const currentItems = latestItems;
26
- const fromIndex = currentItems.findIndex((item) => item.id === draggedItemId);
27
- const toIndex = currentItems.findIndex((item) => item.id === targetItemId);
28
- if (fromIndex < 0 || toIndex < 0 || fromIndex === toIndex)
65
+ const fromIndex = items.findIndex((item) => item.id === event.active.id);
66
+ const toIndex = items.findIndex((item) => item.id === event.over?.id);
67
+ if (fromIndex < 0 || toIndex < 0)
29
68
  return;
30
- const nextItems = moveItem(currentItems, fromIndex, toIndex);
31
- latestItems = nextItems;
69
+ const nextItems = (0, sortable_1.arrayMove)(items, fromIndex, toIndex);
32
70
  onReorder(nextItems);
71
+ if (onReorderEnd !== undefined)
72
+ onReorderEnd(nextItems);
33
73
  };
34
- return ((0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: items.map((item, index) => {
35
- const isDragging = false;
36
- const handle = ((0, jsx_runtime_1.jsx)("button", { "aria-label": `Move ${item.label}`, className: 'ps-focus-ring inline-flex h-6 w-6 shrink-0 cursor-grab items-center justify-center rounded-full text-slate-400/55 opacity-45 transition hover:bg-white/36 hover:text-slate-600 hover:opacity-90 active:cursor-grabbing dark:text-slate-300/45 dark:hover:bg-white/8 dark:hover:text-slate-100', draggable: true, onDragEnd: finishDrag, onDragStart: (event) => {
37
- event.dataTransfer.effectAllowed = 'move';
38
- event.dataTransfer.setData('text/plain', item.id);
39
- draggedItemId = item.id;
40
- }, title: `Move ${item.label}`, type: 'button', children: (0, jsx_runtime_1.jsx)(DragHandleIcon, {}) }));
41
- const renderedItem = renderItem({ handle, index, isDragging, item });
42
- const itemClassName = getItemClassName?.(item);
43
- if (!renderedItem)
44
- return null;
45
- return ((0, jsx_runtime_1.jsx)("div", { className: `ps-page-enter min-w-0 rounded-[1.7rem] transition ${itemClassName !== null && itemClassName !== undefined ? itemClassName : ''} ${isDragging ? 'scale-[0.985] opacity-70' : ''}`, onDragOver: (event) => {
46
- if (!draggedItemId)
47
- return;
48
- event.preventDefault();
49
- event.dataTransfer.dropEffect = 'move';
50
- moveDraggedItemTo(item.id);
51
- }, onDrop: (event) => {
52
- event.preventDefault();
53
- finishDrag();
54
- }, children: renderedItem }, item.id));
55
- }) }));
74
+ return ((0, jsx_runtime_1.jsxs)(core_1.DndContext, { collisionDetection: core_1.closestCenter, onDragCancel: () => setActiveId(null), onDragEnd: handleDragEnd, onDragStart: (event) => setActiveId(String(event.active.id)), sensors: sensors, children: [(0, jsx_runtime_1.jsx)(sortable_1.SortableContext, { items: items.map((item) => item.id), strategy: sortable_1.rectSortingStrategy, children: items.map((item, index) => ((0, jsx_runtime_1.jsx)(PsSortableGridItem, { className: className(item), index: index, item: item, renderItem: renderItem }, item.id))) }), isMounted
75
+ ? (0, react_dom_1.createPortal)((0, jsx_runtime_1.jsx)(core_1.DragOverlay, { dropAnimation: dropAnimation, children: activeItem !== null ? ((0, jsx_runtime_1.jsx)("div", { className: ps_draggable_grid_1.PsDraggableGridClasses.lifted, ref: liftCard, children: renderItem({
76
+ handle: (0, jsx_runtime_1.jsx)(PsDraggableGridHandle, { label: activeItem.label }),
77
+ index: activeIndex,
78
+ isDragging: true,
79
+ isOverlay: true,
80
+ item: activeItem,
81
+ }) })) : null }), document.body)
82
+ : null] }));
56
83
  };
57
84
  exports.PsDraggableGrid = PsDraggableGrid;
@@ -2,8 +2,9 @@ export interface PsNavigationProgressProps {
2
2
  className?: string;
3
3
  color?: string;
4
4
  height?: number;
5
+ isLoading?: boolean;
5
6
  label?: string;
6
- progress: number;
7
+ progress?: number;
7
8
  shadow?: boolean;
8
9
  }
9
- export declare const PsNavigationProgress: ({ className, color, height, label, progress, shadow, }: PsNavigationProgressProps) => import("react").JSX.Element;
10
+ export declare const PsNavigationProgress: ({ className, color, height, isLoading, label, progress, shadow, }: PsNavigationProgressProps) => import("react").JSX.Element;
@@ -2,33 +2,24 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsNavigationProgress = void 0;
4
4
  const jsx_runtime_1 = require("react/jsx-runtime");
5
- const react_1 = require("react");
6
5
  const ps_design_system_1 = require("@pallasoft/ps-design-system");
7
6
  const ps_navigation_progress_config_1 = require("../constants/ps-navigation-progress-config");
8
- const PsNavigationProgress = ({ className, color = ps_navigation_progress_config_1.PsNavigationProgressConfig.defaultColor, height = ps_navigation_progress_config_1.PsNavigationProgressConfig.defaultHeight, label = ps_navigation_progress_config_1.PsNavigationProgressConfig.defaultLabel, progress, shadow = true, }) => {
9
- const [isVisible, setIsVisible] = (0, react_1.useState)(false);
10
- const hideTimer = (0, react_1.useRef)(null);
11
- (0, react_1.useEffect)(() => {
12
- if (typeof window === 'undefined')
13
- return;
14
- if (hideTimer.current !== null)
15
- window.clearTimeout(hideTimer.current);
16
- if (progress > 0 && progress < 100) {
17
- setIsVisible(true);
18
- return;
19
- }
20
- hideTimer.current = window.setTimeout(() => setIsVisible(false), ps_navigation_progress_config_1.PsNavigationProgressConfig.fadeMs);
21
- return () => {
22
- if (hideTimer.current !== null)
23
- window.clearTimeout(hideTimer.current);
24
- };
25
- }, [progress]);
26
- return ((0, jsx_runtime_1.jsx)("div", { "aria-hidden": isVisible ? undefined : 'true', "aria-label": label, "aria-valuemax": 100, "aria-valuemin": 0, "aria-valuenow": Math.round(progress), className: ps_design_system_1.PallasoftClassNameService.merge('pointer-events-none fixed inset-x-0 top-0', className), role: 'progressbar', style: { height, zIndex: ps_design_system_1.PallasoftZIndex.Toast }, children: (0, jsx_runtime_1.jsx)("div", { className: 'h-full origin-left transition-[width,opacity] ease-out', style: {
7
+ const use_ps_navigation_progress_1 = require("../hooks/use-ps-navigation-progress");
8
+ const PsNavigationProgress = ({ className, color = ps_navigation_progress_config_1.PsNavigationProgressConfig.defaultColor, height = ps_navigation_progress_config_1.PsNavigationProgressConfig.defaultHeight, isLoading, label = ps_navigation_progress_config_1.PsNavigationProgressConfig.defaultLabel, progress, shadow = true, }) => {
9
+ const { isAnimated, isVisible, width } = (0, use_ps_navigation_progress_1.usePsNavigationProgress)(isLoading !== undefined
10
+ ? isLoading
11
+ : progress !== undefined &&
12
+ progress > 0 &&
13
+ progress < ps_navigation_progress_config_1.PsNavigationProgressConfig.completeWidth);
14
+ return ((0, jsx_runtime_1.jsx)("div", { "aria-hidden": isVisible ? undefined : 'true', "aria-label": label, "aria-valuemax": 100, "aria-valuemin": 0, "aria-valuenow": Math.round(width), className: ps_design_system_1.PallasoftClassNameService.merge('pointer-events-none fixed inset-x-0 top-0', className), role: 'progressbar', style: { height, zIndex: ps_design_system_1.PallasoftZIndex.Toast }, children: (0, jsx_runtime_1.jsx)("div", { className: 'h-full origin-left ease-out', style: {
27
15
  backgroundColor: color,
28
16
  boxShadow: shadow ? `0 0 10px ${color}, 0 0 5px ${color}` : undefined,
29
17
  opacity: isVisible ? 1 : 0,
30
- transitionDuration: `${ps_navigation_progress_config_1.PsNavigationProgressConfig.transitionMs}ms`,
31
- width: `${Math.min(Math.max(progress, 0), 100)}%`,
18
+ transitionDuration: isAnimated
19
+ ? `${ps_navigation_progress_config_1.PsNavigationProgressConfig.transitionMs}ms, ${ps_navigation_progress_config_1.PsNavigationProgressConfig.fadeMs}ms`
20
+ : '0ms',
21
+ transitionProperty: 'width, opacity',
22
+ width: `${Math.min(Math.max(width, 0), 100)}%`,
32
23
  } }) }));
33
24
  };
34
25
  exports.PsNavigationProgress = PsNavigationProgress;
@@ -2,5 +2,5 @@
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 PsSectionHeader = ({ description, eyebrow, leading, title, trailing, }) => ((0, jsx_runtime_1.jsxs)("div", { className: 'flex flex-col justify-between gap-3 lg:flex-row lg:items-end', children: [(0, jsx_runtime_1.jsxs)("div", { className: 'flex min-w-0 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: 'text-2xl font-extrabold text-ink', children: title }), description ? ((0, jsx_runtime_1.jsx)("p", { className: 'max-w-3xl text-sm leading-6 text-ink/60', children: description })) : null] }), trailing] }));
5
+ const PsSectionHeader = ({ description, eyebrow, leading, title, trailing, }) => ((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: 'ml-auto flex shrink-0 items-center', children: trailing }) : null] }));
6
6
  exports.PsSectionHeader = PsSectionHeader;
@@ -0,0 +1,17 @@
1
+ export declare const PsDraggableGridConfig: {
2
+ readonly activationDistance: 6;
3
+ readonly dropDuration: 220;
4
+ readonly dropEasing: "cubic-bezier(0.2, 0.8, 0.2, 1)";
5
+ readonly liftDuration: 200;
6
+ readonly liftEasing: "cubic-bezier(0.2, 0.9, 0.3, 1.2)";
7
+ readonly placeholderOpacity: "0.4";
8
+ readonly touchDelay: 180;
9
+ readonly touchTolerance: 6;
10
+ };
11
+ export declare const PsDraggableGridClasses: {
12
+ readonly handle: "ps-focus-ring inline-flex h-7 w-7 shrink-0 cursor-grab touch-none items-center justify-center rounded-full text-slate-400/70 transition hover:bg-white/36 hover:text-slate-600 active:cursor-grabbing dark:text-slate-300/55 dark:hover:bg-white/8 dark:hover:text-slate-100";
13
+ readonly item: "min-w-0 rounded-[1.7rem]";
14
+ readonly lifted: "cursor-grabbing rounded-[1.7rem] ring-1 ring-primary/30";
15
+ readonly placeholder: "rounded-[1.7rem] outline-dashed outline-2 outline-offset-[-2px] outline-primary/35";
16
+ };
17
+ export declare const PsDraggableGridLiftFrames: Keyframe[];
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PsDraggableGridLiftFrames = exports.PsDraggableGridClasses = exports.PsDraggableGridConfig = void 0;
4
+ exports.PsDraggableGridConfig = {
5
+ activationDistance: 6,
6
+ dropDuration: 220,
7
+ dropEasing: 'cubic-bezier(0.2, 0.8, 0.2, 1)',
8
+ liftDuration: 200,
9
+ liftEasing: 'cubic-bezier(0.2, 0.9, 0.3, 1.2)',
10
+ placeholderOpacity: '0.4',
11
+ touchDelay: 180,
12
+ touchTolerance: 6,
13
+ };
14
+ exports.PsDraggableGridClasses = {
15
+ handle: 'ps-focus-ring inline-flex h-7 w-7 shrink-0 cursor-grab touch-none items-center justify-center rounded-full text-slate-400/70 transition hover:bg-white/36 hover:text-slate-600 active:cursor-grabbing dark:text-slate-300/55 dark:hover:bg-white/8 dark:hover:text-slate-100',
16
+ item: 'min-w-0 rounded-[1.7rem]',
17
+ lifted: 'cursor-grabbing rounded-[1.7rem] ring-1 ring-primary/30',
18
+ placeholder: 'rounded-[1.7rem] outline-dashed outline-2 outline-offset-[-2px] outline-primary/35',
19
+ };
20
+ exports.PsDraggableGridLiftFrames = [
21
+ { boxShadow: '0 0 0 0 rgb(15 23 42 / 0)', transform: 'scale(1) rotate(0deg)' },
22
+ {
23
+ boxShadow: '0 28px 64px -18px rgb(15 23 42 / 0.5)',
24
+ transform: 'scale(1.035) rotate(-1.2deg)',
25
+ },
26
+ ];
@@ -1,7 +1,12 @@
1
1
  export declare const PsNavigationProgressConfig: {
2
+ readonly completeWidth: 100;
2
3
  readonly defaultColor: "rgb(var(--ps-color-primary-rgb))";
3
4
  readonly defaultHeight: 3;
4
5
  readonly defaultLabel: "Page loading";
5
6
  readonly fadeMs: 320;
7
+ readonly startWidth: 12;
6
8
  readonly transitionMs: 240;
9
+ readonly trickleFactor: 0.14;
10
+ readonly trickleMax: 90;
11
+ readonly trickleMs: 260;
7
12
  };
@@ -2,9 +2,14 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.PsNavigationProgressConfig = void 0;
4
4
  exports.PsNavigationProgressConfig = {
5
+ completeWidth: 100,
5
6
  defaultColor: 'rgb(var(--ps-color-primary-rgb))',
6
7
  defaultHeight: 3,
7
8
  defaultLabel: 'Page loading',
8
9
  fadeMs: 320,
10
+ startWidth: 12,
9
11
  transitionMs: 240,
12
+ trickleFactor: 0.14,
13
+ trickleMax: 90,
14
+ trickleMs: 260,
10
15
  };
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
+ import { PsIcon, PsIconKey } from '@pallasoft/ps-icons';
4
+ import * as AccordionPrimitive from '@radix-ui/react-accordion';
5
+ export const PsAccordion = ({ children, className, isOpen, label, onToggle, trailing, }) => (_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 }) })] }) }));
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
+ const variantClassNames = {
4
+ default: 'ps-action-tile',
5
+ primary: 'ps-action-tile ps-action-tile-primary',
6
+ };
7
+ export const PsActionTile = ({ className, description, icon, label, type = 'button', variant = 'default', ...props }) => (_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] }));
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ 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
+ }) }));
9
+ };
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
+ const toneClassNames = {
4
+ danger: 'bg-danger-soft text-danger dark:bg-rose-500/18 dark:text-rose-100',
5
+ neutral: 'bg-slate-100 text-slate-700 dark:bg-white/10 dark:text-slate-100',
6
+ primary: 'bg-primary-soft text-ink dark:bg-primary/22 dark:text-white',
7
+ success: 'bg-success-soft text-emerald-700 dark:bg-emerald-400/18 dark:text-emerald-50',
8
+ warning: 'bg-warning-soft text-amber-800 dark:bg-amber-400/18 dark:text-amber-50',
9
+ };
10
+ export const PsBadge = ({ children, className, tone = 'neutral' }) => (_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 }));
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
+ import { PsSpinner } from './ps-spinner';
4
+ const sizeClassNames = {
5
+ compact: 'min-h-9 px-3 py-2 text-sm',
6
+ default: 'min-h-10 px-4 py-2.5 text-sm',
7
+ large: 'min-h-11 px-5 py-3 text-sm',
8
+ };
9
+ const variantClassNames = {
10
+ danger: 'border-danger bg-danger text-white enabled:hover:opacity-90',
11
+ ghost: 'border-transparent bg-transparent text-ink/60 enabled:hover:text-ink',
12
+ primary: 'border-primary bg-primary text-[color:var(--ps-color-primary-contrast)] enabled:hover:border-primary-dark enabled:hover:bg-primary-dark',
13
+ secondary: 'ps-liquid ps-liquid-control bg-white/72 text-ink enabled:hover:border-primary/30 enabled:hover:text-primary dark:border-white/16 dark:bg-white/12 dark:enabled:hover:text-white',
14
+ surface: 'ps-liquid ps-liquid-control bg-white/72 text-ink enabled:hover:border-primary/30 dark:border-white/16 dark:bg-white/12',
15
+ };
16
+ export const PsButton = ({ children, className, disabled, isLoading = false, leadingIcon, loadingLabel, size = 'default', trailingIcon, type = 'button', variant = 'secondary', ...props }) => (_jsxs("button", { className: PallasoftClassNameService.merge('ps-focus-ring relative inline-flex max-w-full items-center justify-center gap-2 rounded-full border text-center font-semibold disabled:cursor-not-allowed disabled:opacity-50', sizeClassNames[size], variantClassNames[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: 'truncate', children: children }), trailingIcon ? _jsx("span", { className: 'shrink-0', children: trailingIcon }) : null] })] }));
@@ -0,0 +1,14 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
+ const densityClassNames = {
4
+ compact: 'p-3',
5
+ normal: 'p-4',
6
+ spacious: 'p-5',
7
+ };
8
+ const variantClassNames = {
9
+ default: 'ps-card',
10
+ elevated: 'ps-card',
11
+ glass: 'ps-glass',
12
+ muted: 'ps-card-muted',
13
+ };
14
+ export const PsCard = ({ children, className, density = 'normal', eyebrow, title, trailing, variant = 'default', }) => (_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] }));
@@ -0,0 +1,80 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useState } from 'react';
3
+ import { DndContext, DragOverlay, KeyboardSensor, MouseSensor, TouchSensor, closestCenter, defaultDropAnimationSideEffects, useSensor, useSensors, } from '@dnd-kit/core';
4
+ import { SortableContext, arrayMove, rectSortingStrategy, sortableKeyboardCoordinates, useSortable, } from '@dnd-kit/sortable';
5
+ import { CSS } from '@dnd-kit/utilities';
6
+ import { createPortal } from 'react-dom';
7
+ import { PsDraggableGridClasses, PsDraggableGridConfig, PsDraggableGridLiftFrames, } from '../constants/ps-draggable-grid';
8
+ const liftCard = (element) => {
9
+ if (element === null)
10
+ return;
11
+ element.animate(PsDraggableGridLiftFrames, {
12
+ duration: PsDraggableGridConfig.liftDuration,
13
+ easing: PsDraggableGridConfig.liftEasing,
14
+ fill: 'forwards',
15
+ });
16
+ };
17
+ const dropAnimation = {
18
+ duration: PsDraggableGridConfig.dropDuration,
19
+ easing: PsDraggableGridConfig.dropEasing,
20
+ sideEffects: defaultDropAnimationSideEffects({
21
+ styles: { active: { opacity: PsDraggableGridConfig.placeholderOpacity } },
22
+ }),
23
+ };
24
+ const DragHandleIcon = () => (_jsx("span", { "aria-hidden": 'true', className: 'grid grid-cols-2 gap-[0.1875rem]', children: Array.from({ length: 6 }).map((_, index) => (_jsx("span", { className: 'h-[3px] w-[3px] rounded-full bg-current' }, index))) }));
25
+ 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(DragHandleIcon, {}) }));
26
+ const PsSortableGridItem = ({ className, index, item, renderItem, }) => {
27
+ const { attributes, isDragging, listeners, setActivatorNodeRef, setNodeRef, transform, transition, } = useSortable({ id: item.id });
28
+ const rendered = renderItem({
29
+ handle: (_jsx(PsDraggableGridHandle, { attributes: attributes, label: item.label, listeners: listeners, setActivatorNodeRef: setActivatorNodeRef })),
30
+ index,
31
+ isDragging,
32
+ isOverlay: false,
33
+ item,
34
+ });
35
+ if (!rendered)
36
+ return null;
37
+ return (_jsx("div", { className: `${PsDraggableGridClasses.item} ${className} ${isDragging ? PsDraggableGridClasses.placeholder : ''}`, ref: setNodeRef, style: {
38
+ opacity: isDragging ? PsDraggableGridConfig.placeholderOpacity : undefined,
39
+ transform: CSS.Translate.toString(transform),
40
+ transition,
41
+ }, children: rendered }));
42
+ };
43
+ export const PsDraggableGrid = ({ getItemClassName, items, onReorder, onReorderEnd, renderItem, }) => {
44
+ const [activeId, setActiveId] = useState(null);
45
+ const [isMounted, setIsMounted] = useState(false);
46
+ useEffect(() => setIsMounted(true), []);
47
+ const sensors = useSensors(useSensor(MouseSensor, {
48
+ activationConstraint: { distance: PsDraggableGridConfig.activationDistance },
49
+ }), useSensor(TouchSensor, {
50
+ activationConstraint: {
51
+ delay: PsDraggableGridConfig.touchDelay,
52
+ tolerance: PsDraggableGridConfig.touchTolerance,
53
+ },
54
+ }), useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates }));
55
+ const className = (item) => getItemClassName !== undefined ? getItemClassName(item) : '';
56
+ const activeIndex = items.findIndex((item) => item.id === activeId);
57
+ const activeItem = activeIndex >= 0 ? items[activeIndex] : null;
58
+ const handleDragEnd = (event) => {
59
+ setActiveId(null);
60
+ if (event.over === null || event.active.id === event.over.id)
61
+ return;
62
+ const fromIndex = items.findIndex((item) => item.id === event.active.id);
63
+ const toIndex = items.findIndex((item) => item.id === event.over?.id);
64
+ if (fromIndex < 0 || toIndex < 0)
65
+ return;
66
+ const nextItems = arrayMove(items, fromIndex, toIndex);
67
+ onReorder(nextItems);
68
+ if (onReorderEnd !== undefined)
69
+ onReorderEnd(nextItems);
70
+ };
71
+ return (_jsxs(DndContext, { collisionDetection: closestCenter, onDragCancel: () => setActiveId(null), onDragEnd: handleDragEnd, onDragStart: (event) => setActiveId(String(event.active.id)), sensors: sensors, children: [_jsx(SortableContext, { items: items.map((item) => item.id), strategy: rectSortingStrategy, children: items.map((item, index) => (_jsx(PsSortableGridItem, { className: className(item), index: index, item: item, renderItem: renderItem }, item.id))) }), isMounted
72
+ ? createPortal(_jsx(DragOverlay, { dropAnimation: dropAnimation, children: activeItem !== null ? (_jsx("div", { className: PsDraggableGridClasses.lifted, ref: liftCard, children: renderItem({
73
+ handle: _jsx(PsDraggableGridHandle, { label: activeItem.label }),
74
+ index: activeIndex,
75
+ isDragging: true,
76
+ isOverlay: true,
77
+ item: activeItem,
78
+ }) })) : null }), document.body)
79
+ : null] }));
80
+ };
@@ -0,0 +1,28 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
+ const getActionClassName = (variant = 'secondary') => {
4
+ if (variant === 'primary') {
5
+ return 'border-primary bg-primary text-white hover:bg-primary-dark';
6
+ }
7
+ return 'border-line bg-surface text-ink hover:border-primary/40 hover:text-primary';
8
+ };
9
+ export const PsEmptyState = ({ actions = [], badge, children, className, detail, description, eyebrow, icon, title, variant = 'page', }) => {
10
+ const isInline = variant === 'inline';
11
+ const Wrapper = isInline ? 'div' : 'main';
12
+ const Heading = isInline ? 'h3' : 'h1';
13
+ return (_jsx(Wrapper, { className: PallasoftClassNameService.merge(isInline
14
+ ? 'flex items-center justify-center rounded-ps-panel border border-dashed border-line bg-mist/40 px-6 py-10 text-ink'
15
+ : 'relative flex min-h-screen items-center justify-center bg-mist px-4 py-10 text-ink', className), children: _jsx("section", { className: isInline
16
+ ? 'relative w-full max-w-2xl text-center'
17
+ : 'ps-card relative w-full max-w-2xl p-6 sm:p-8', children: _jsxs("div", { className: isInline
18
+ ? 'flex flex-col items-center gap-3'
19
+ : 'flex flex-col gap-5 sm:flex-row sm:items-start', children: [icon ? _jsx("div", { className: 'ps-icon-surface h-14 w-14', children: icon }) : null, _jsxs("div", { className: isInline ? 'min-w-0' : 'min-w-0 flex-1', children: [_jsxs("div", { className: isInline
20
+ ? 'flex flex-wrap items-center justify-center gap-2'
21
+ : 'flex flex-wrap items-center gap-2', children: [eyebrow ? (_jsx("p", { className: 'text-xs font-semibold uppercase tracking-[0.22em] text-primary', children: eyebrow })) : null, eyebrow && badge ? _jsx("span", { className: 'h-1 w-1 rounded-full bg-line' }) : null, badge ? (_jsx("p", { className: 'text-xs font-semibold uppercase tracking-[0.22em] text-ink/40', children: badge })) : null] }), _jsx(Heading, { className: isInline
22
+ ? 'text-base font-semibold text-ink'
23
+ : 'mt-3 text-3xl font-semibold tracking-tight sm:text-4xl', children: title }), description ? (_jsx("p", { className: isInline
24
+ ? 'mt-1.5 text-sm leading-6 text-ink/60'
25
+ : 'mt-3 text-sm leading-6 text-ink/60', children: description })) : null, detail ? (_jsx("p", { className: 'mt-4 rounded-2xl border border-line bg-mist px-4 py-3 text-left text-xs leading-5 text-ink/60', children: detail })) : null, children ? _jsx("div", { className: 'mt-5 flex justify-center', children: children }) : null, actions.length > 0 ? (_jsx("div", { className: isInline
26
+ ? 'mt-5 flex flex-col justify-center gap-2 sm:flex-row'
27
+ : 'mt-6 flex flex-col gap-2 sm:flex-row', children: actions.map((action) => (_jsx("a", { className: PallasoftClassNameService.merge('ps-focus-ring ps-pressable inline-flex items-center justify-center rounded-ps-control border px-4 py-3 text-sm font-semibold', getActionClassName(action.variant)), href: action.href, rel: action.rel, target: action.target, children: action.label }, `${action.href}-${action.label}`))) })) : null] })] }) }) }));
28
+ };
@@ -0,0 +1,9 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
+ import { PsButton } from './ps-button';
4
+ const positionClassNames = {
5
+ 'bottom-right': 'bottom-6 right-6',
6
+ 'bottom-left': 'bottom-6 left-6',
7
+ 'bottom-center': 'bottom-6 left-1/2 -translate-x-1/2',
8
+ };
9
+ export const PsFab = ({ className, position = 'bottom-right', ...props }) => (_jsx(PsButton, { size: 'large', variant: 'primary', className: PallasoftClassNameService.merge('fixed z-docked h-14 w-14 shrink-0 !px-0 shadow-lg', positionClassNames[position], className), ...props }));
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import InfiniteScroll from 'react-infinite-scroll-component';
3
+ import { PsSpinner } from './ps-spinner';
4
+ const defaultLoader = (_jsx("div", { className: 'flex w-full justify-center py-8', children: _jsx(PsSpinner, {}) }));
5
+ export const PsInfiniteScroll = ({ children, className, dataLength, hasMore, loader, next, }) => (_jsx(InfiniteScroll, { className: className, dataLength: dataLength, hasMore: hasMore, loader: loader !== null && loader !== undefined ? loader : defaultLoader, next: next, children: children }));
@@ -0,0 +1,3 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { PsLayerContext } from '../contexts/ps-layer-context';
3
+ export const PsLayer = ({ children, zIndex }) => (_jsx(PsLayerContext.Provider, { value: zIndex, children: children }));
@@ -0,0 +1,11 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
+ const densityClassNames = {
4
+ compact: 'py-2',
5
+ normal: 'py-2.5',
6
+ };
7
+ const variantClassNames = {
8
+ card: 'ps-surface px-3',
9
+ row: 'border-b border-line/70 px-0 last:border-b-0',
10
+ };
11
+ export const PsListTile = ({ children, className, density = 'normal', eyebrow, isPrivateTitle = false, subtitle, title, variant = 'row', }) => (_jsxs("div", { className: PallasoftClassNameService.merge('min-w-0 overflow-hidden', variantClassNames[variant], densityClassNames[density], className), children: [eyebrow ? _jsx("p", { className: 'ps-eyebrow break-words', children: eyebrow }) : null, _jsx("p", { className: PallasoftClassNameService.merge('break-words text-sm font-semibold text-ink', eyebrow && 'mt-1', isPrivateTitle && 'private-number'), children: title }), subtitle ? (_jsx("p", { className: 'mt-1 break-words text-sm leading-5 text-slate-500', children: subtitle })) : null, children] }));
@@ -0,0 +1,3 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
+ export const PsMetricCard = ({ changeLabel, className, icon, label, value }) => (_jsx("section", { className: PallasoftClassNameService.merge('ps-metric-card min-w-0 p-3.5 sm:p-4', className), children: _jsxs("div", { className: 'flex items-start justify-between gap-3', children: [_jsxs("div", { className: 'min-w-0', children: [_jsx("p", { className: 'ps-eyebrow truncate', children: label }), _jsx("p", { className: 'mt-2 truncate text-2xl font-semibold text-ink', children: value }), changeLabel ? _jsx("p", { className: 'mt-1 text-sm text-slate-500', children: changeLabel }) : null] }), icon ? (_jsx("div", { className: 'flex h-9 w-9 shrink-0 items-center justify-center rounded-lg bg-primary-soft text-primary', children: icon })) : null] }) }));
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { PallasoftClassNameService, PallasoftZIndex } from '@pallasoft/ps-design-system';
3
+ import { PsNavigationProgressConfig } from '../constants/ps-navigation-progress-config';
4
+ import { usePsNavigationProgress } from '../hooks/use-ps-navigation-progress';
5
+ export const PsNavigationProgress = ({ className, color = PsNavigationProgressConfig.defaultColor, height = PsNavigationProgressConfig.defaultHeight, isLoading, label = PsNavigationProgressConfig.defaultLabel, progress, shadow = true, }) => {
6
+ const { isAnimated, isVisible, width } = usePsNavigationProgress(isLoading !== undefined
7
+ ? isLoading
8
+ : progress !== undefined &&
9
+ progress > 0 &&
10
+ progress < PsNavigationProgressConfig.completeWidth);
11
+ return (_jsx("div", { "aria-hidden": isVisible ? undefined : 'true', "aria-label": label, "aria-valuemax": 100, "aria-valuemin": 0, "aria-valuenow": Math.round(width), className: PallasoftClassNameService.merge('pointer-events-none fixed inset-x-0 top-0', className), role: 'progressbar', style: { height, zIndex: PallasoftZIndex.Toast }, children: _jsx("div", { className: 'h-full origin-left ease-out', style: {
12
+ backgroundColor: color,
13
+ boxShadow: shadow ? `0 0 10px ${color}, 0 0 5px ${color}` : undefined,
14
+ opacity: isVisible ? 1 : 0,
15
+ transitionDuration: isAnimated
16
+ ? `${PsNavigationProgressConfig.transitionMs}ms, ${PsNavigationProgressConfig.fadeMs}ms`
17
+ : '0ms',
18
+ transitionProperty: 'width, opacity',
19
+ width: `${Math.min(Math.max(width, 0), 100)}%`,
20
+ } }) }));
21
+ };
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
3
+ const toneClassNames = {
4
+ danger: 'bg-rose-50 text-rose-700 ring-rose-100 dark:bg-rose-500/18 dark:text-rose-100 dark:ring-rose-300/22',
5
+ neutral: 'bg-slate-100 text-slate-700 ring-slate-200 dark:bg-white/10 dark:text-slate-100 dark:ring-white/12',
6
+ primary: 'bg-primary-soft text-ink ring-primary/12 dark:bg-primary/22 dark:text-white dark:ring-primary/32',
7
+ success: 'bg-emerald-50 text-emerald-700 ring-emerald-100 dark:bg-emerald-400/18 dark:text-emerald-50 dark:ring-emerald-200/22',
8
+ warning: 'bg-amber-50 text-amber-800 ring-amber-100 dark:bg-amber-400/18 dark:text-amber-50 dark:ring-amber-200/24',
9
+ };
10
+ export const PsPill = ({ children, className, tone = 'neutral' }) => (_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 }) }));