@pallasoft/ps-core-components 2.35.2 → 2.37.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/ps-action-tile-content.d.ts +8 -0
- package/dist/components/ps-action-tile-content.js +7 -0
- package/dist/components/ps-action-tile-link.d.ts +10 -0
- package/dist/components/ps-action-tile-link.js +16 -0
- package/dist/components/ps-action-tile.js +2 -1
- package/dist/components/ps-capped-list.js +1 -1
- package/dist/components/ps-detail-pane.d.ts +11 -0
- package/dist/components/ps-detail-pane.js +7 -0
- package/dist/components/ps-document-row.d.ts +2 -1
- package/dist/components/ps-document-row.js +11 -6
- package/dist/components/ps-form-footer.d.ts +5 -2
- package/dist/components/ps-form-footer.js +2 -1
- package/dist/components/ps-page-skeleton.d.ts +2 -1
- package/dist/components/ps-page-skeleton.js +1 -1
- package/dist/components/ps-split-view.d.ts +6 -0
- package/dist/components/ps-split-view.js +13 -0
- package/dist/constants/ps-button-classes.js +2 -2
- package/dist/constants/ps-split-view-config.d.ts +4 -0
- package/dist/constants/ps-split-view-config.js +7 -0
- package/dist/esm/components/ps-action-tile-content.js +3 -0
- package/dist/esm/components/ps-action-tile-link.js +12 -0
- package/dist/esm/components/ps-action-tile.js +3 -2
- package/dist/esm/components/ps-capped-list.js +1 -1
- package/dist/esm/components/ps-detail-pane.js +3 -0
- package/dist/esm/components/ps-document-row.js +11 -6
- package/dist/esm/components/ps-form-footer.js +2 -1
- package/dist/esm/components/ps-page-skeleton.js +1 -1
- package/dist/esm/components/ps-split-view.js +9 -0
- package/dist/esm/constants/ps-button-classes.js +2 -2
- package/dist/esm/constants/ps-split-view-config.js +4 -0
- package/dist/esm/hooks/use-ps-fill-height.js +20 -0
- package/dist/esm/hooks/use-ps-tab-channel.js +21 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/services/ps-fill-height-service.js +33 -0
- package/dist/hooks/use-ps-fill-height.d.ts +4 -0
- package/dist/hooks/use-ps-fill-height.js +24 -0
- package/dist/hooks/use-ps-tab-channel.d.ts +1 -0
- package/dist/hooks/use-ps-tab-channel.js +25 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/services/ps-fill-height-service.d.ts +5 -0
- package/dist/services/ps-fill-height-service.js +37 -0
- package/package.json +1 -1
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export interface PsActionTileContentProps {
|
|
3
|
+
description?: string;
|
|
4
|
+
icon?: ReactNode;
|
|
5
|
+
label: string;
|
|
6
|
+
variant: 'default' | 'primary';
|
|
7
|
+
}
|
|
8
|
+
export declare const PsActionTileContent: ({ description, icon, label, variant, }: PsActionTileContentProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsActionTileContent = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const ps_design_system_1 = require("@pallasoft/ps-design-system");
|
|
6
|
+
const PsActionTileContent = ({ description, icon, label, variant, }) => ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { 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] }));
|
|
7
|
+
exports.PsActionTileContent = PsActionTileContent;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { AnchorHTMLAttributes, ElementType, ReactNode } from 'react';
|
|
2
|
+
export interface PsActionTileLinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
3
|
+
description?: string;
|
|
4
|
+
href: string;
|
|
5
|
+
icon?: ReactNode;
|
|
6
|
+
label: string;
|
|
7
|
+
LinkComponent?: ElementType;
|
|
8
|
+
variant?: 'default' | 'primary';
|
|
9
|
+
}
|
|
10
|
+
export declare const PsActionTileLink: ({ className, description, href, icon, label, LinkComponent, variant, ...props }: PsActionTileLinkProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsActionTileLink = 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_action_tile_content_1 = require("./ps-action-tile-content");
|
|
7
|
+
const variantClassNames = {
|
|
8
|
+
default: 'ps-action-tile',
|
|
9
|
+
primary: 'ps-action-tile ps-action-tile-primary',
|
|
10
|
+
};
|
|
11
|
+
const PsActionTileLink = ({ className, description, href, icon, label, LinkComponent, variant = 'default', ...props }) => {
|
|
12
|
+
const linkClassName = ps_design_system_1.PallasoftClassNameService.merge('ps-focus-ring w-full', variantClassNames[variant], className);
|
|
13
|
+
const content = ((0, jsx_runtime_1.jsx)(ps_action_tile_content_1.PsActionTileContent, { description: description, icon: icon, label: label, variant: variant }));
|
|
14
|
+
return LinkComponent ? ((0, jsx_runtime_1.jsx)(LinkComponent, { className: linkClassName, prefetch: 'intent', to: href, ...props, children: content })) : ((0, jsx_runtime_1.jsx)("a", { className: linkClassName, href: href, ...props, children: content }));
|
|
15
|
+
};
|
|
16
|
+
exports.PsActionTileLink = PsActionTileLink;
|
|
@@ -4,10 +4,11 @@ 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
6
|
const ps_skeleton_shape_1 = require("../constants/ps-skeleton-shape");
|
|
7
|
+
const ps_action_tile_content_1 = require("./ps-action-tile-content");
|
|
7
8
|
const ps_skeleton_1 = require("./ps-skeleton");
|
|
8
9
|
const variantClassNames = {
|
|
9
10
|
default: 'ps-action-tile',
|
|
10
11
|
primary: 'ps-action-tile ps-action-tile-primary',
|
|
11
12
|
};
|
|
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', className), shape: ps_skeleton_shape_1.PsSkeletonShape.Card })) : ((0, jsx_runtime_1.
|
|
13
|
+
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', className), shape: ps_skeleton_shape_1.PsSkeletonShape.Card })) : ((0, jsx_runtime_1.jsx)("button", { className: ps_design_system_1.PallasoftClassNameService.merge('ps-focus-ring w-full', variantClassNames[variant], className), type: type, ...props, children: (0, jsx_runtime_1.jsx)(ps_action_tile_content_1.PsActionTileContent, { description: description, icon: icon, label: label, variant: variant }) }));
|
|
13
14
|
exports.PsActionTile = PsActionTile;
|
|
@@ -9,6 +9,6 @@ const PsCappedList = ({ getKey, items, renderItem, showAllLabel, visibleRows = p
|
|
|
9
9
|
const [isExpanded, setIsExpanded] = (0, react_1.useState)(false);
|
|
10
10
|
const isCapped = !isExpanded && items.length > visibleRows;
|
|
11
11
|
const shown = isCapped ? items.slice(0, visibleRows) : items;
|
|
12
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: 'flex flex-col gap-2', children: [(0, jsx_runtime_1.jsx)("ul", { className: '-my-2 flex flex-col divide-y divide-line', children: shown.map((item) => ((0, jsx_runtime_1.jsx)("li", { children: renderItem(item) }, getKey(item)))) }), isCapped ? ((0, jsx_runtime_1.jsx)(ps_button_1.PsButton, { className: 'self-start', onClick: () => setIsExpanded(true), size: 'compact', variant: '
|
|
12
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: 'flex flex-col gap-2', children: [(0, jsx_runtime_1.jsx)("ul", { className: '-my-2 flex flex-col divide-y divide-line', children: shown.map((item) => ((0, jsx_runtime_1.jsx)("li", { children: renderItem(item) }, getKey(item)))) }), isCapped ? ((0, jsx_runtime_1.jsx)(ps_button_1.PsButton, { className: 'self-start', onClick: () => setIsExpanded(true), size: 'compact', variant: 'surface', children: showAllLabel })) : null] }));
|
|
13
13
|
};
|
|
14
14
|
exports.PsCappedList = PsCappedList;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export interface PsDetailPaneProps {
|
|
3
|
+
children: ReactNode;
|
|
4
|
+
className?: string;
|
|
5
|
+
footer?: ReactNode;
|
|
6
|
+
footerStart?: ReactNode;
|
|
7
|
+
headerActions?: ReactNode;
|
|
8
|
+
subtitle?: ReactNode;
|
|
9
|
+
title: string;
|
|
10
|
+
}
|
|
11
|
+
export declare const PsDetailPane: ({ children, className, footer, footerStart, headerActions, subtitle, title, }: PsDetailPaneProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsDetailPane = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const ps_design_system_1 = require("@pallasoft/ps-design-system");
|
|
6
|
+
const PsDetailPane = ({ children, className, footer, footerStart, headerActions, subtitle, title, }) => ((0, jsx_runtime_1.jsxs)("section", { "aria-label": title, className: ps_design_system_1.PallasoftClassNameService.merge('ps-card flex h-full min-h-0 min-w-0 flex-col overflow-hidden rounded-ps-card', className), children: [(0, jsx_runtime_1.jsxs)("header", { className: 'flex shrink-0 items-start justify-between gap-3 border-b border-line/80 px-4 py-3.5 sm:px-5', children: [(0, jsx_runtime_1.jsxs)("div", { className: 'flex min-w-0 flex-col gap-0.5', children: [(0, jsx_runtime_1.jsx)("h2", { className: 'truncate text-lg font-semibold leading-tight text-ink', children: title }), subtitle ? (0, jsx_runtime_1.jsx)("p", { className: 'truncate text-xs text-ink/55', children: subtitle }) : null] }), headerActions ? ((0, jsx_runtime_1.jsx)("div", { className: 'flex shrink-0 items-center gap-2', children: headerActions })) : null] }), (0, jsx_runtime_1.jsx)("div", { className: 'ps-scrollbar-hidden min-h-0 flex-1 overflow-y-auto px-4 py-4 sm:px-5', children: children }), footer || footerStart ? ((0, jsx_runtime_1.jsxs)("footer", { className: 'flex shrink-0 flex-wrap items-center justify-between gap-2 border-t border-line/80 px-4 py-3 sm:px-5', children: [footerStart ? (0, jsx_runtime_1.jsx)("div", { className: 'flex min-w-0 items-center gap-2', children: footerStart }) : null, (0, jsx_runtime_1.jsx)("div", { className: 'ml-auto flex flex-wrap items-center justify-end gap-2', children: footer })] })) : null] }));
|
|
7
|
+
exports.PsDetailPane = PsDetailPane;
|
|
@@ -5,6 +5,7 @@ export interface PsDocumentRowProps {
|
|
|
5
5
|
badges?: ReactNode;
|
|
6
6
|
className?: string;
|
|
7
7
|
date?: string;
|
|
8
|
+
isActive?: boolean;
|
|
8
9
|
isSelected?: boolean;
|
|
9
10
|
note?: ReactNode;
|
|
10
11
|
onOpen?: () => void;
|
|
@@ -16,4 +17,4 @@ export interface PsDocumentRowProps {
|
|
|
16
17
|
thumbnailSrc?: string | null;
|
|
17
18
|
title: string;
|
|
18
19
|
}
|
|
19
|
-
export declare const PsDocumentRow: ({ actions, amount, badges, className, date, isSelected, note, onOpen, onPrefetch, select, subtitle, thumbnailAlt, thumbnailFallback, thumbnailSrc, title, }: PsDocumentRowProps) => import("react").JSX.Element;
|
|
20
|
+
export declare const PsDocumentRow: ({ actions, amount, badges, className, date, isActive, isSelected, note, onOpen, onPrefetch, select, subtitle, thumbnailAlt, thumbnailFallback, thumbnailSrc, title, }: PsDocumentRowProps) => import("react").JSX.Element;
|
|
@@ -3,14 +3,19 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.PsDocumentRow = 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 PsDocumentRow = ({ actions, amount, badges, className, date, isSelected = false, note, onOpen, onPrefetch, select, subtitle, thumbnailAlt = '', thumbnailFallback, thumbnailSrc, title, }) => {
|
|
6
|
+
const PsDocumentRow = ({ actions, amount, badges, className, date, isActive = false, isSelected = false, note, onOpen, onPrefetch, select, subtitle, thumbnailAlt = '', thumbnailFallback, thumbnailSrc, title, }) => {
|
|
7
7
|
const Main = onOpen ? 'button' : 'div';
|
|
8
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('flex min-w-0 flex-wrap items-center gap-x-3 gap-y-2 border-b border-line/70 px-3 py-3 transition-colors last:border-b-0 sm:flex-nowrap',
|
|
8
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: ps_design_system_1.PallasoftClassNameService.merge('flex min-w-0 flex-wrap items-center gap-x-3 gap-y-2 border-b border-line/70 px-3 py-3 transition-colors last:border-b-0 sm:flex-nowrap', isActive
|
|
9
|
+
? 'bg-primary/8 shadow-[inset_3px_0_0_rgb(var(--ps-color-primary-rgb))]'
|
|
10
|
+
: isSelected
|
|
11
|
+
? 'bg-primary/5'
|
|
12
|
+
: 'hover:bg-mist/40', className), children: [select ? (0, jsx_runtime_1.jsx)("span", { className: 'flex shrink-0 items-center', children: select }) : null, (0, jsx_runtime_1.jsxs)(Main, { className: 'ps-focus-ring grid min-w-0 flex-1 basis-0 grid-cols-[auto_minmax(0,1fr)] items-center gap-x-3 gap-y-1 rounded-ps-control text-left sm:grid-cols-[auto_minmax(0,1fr)_auto]', ...(onOpen
|
|
9
13
|
? {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
+
'aria-current': isActive ? 'true' : undefined,
|
|
15
|
+
'onClick': onOpen,
|
|
16
|
+
'onFocus': onPrefetch,
|
|
17
|
+
'onPointerEnter': onPrefetch,
|
|
18
|
+
'type': 'button',
|
|
14
19
|
}
|
|
15
20
|
: {}), children: [(0, jsx_runtime_1.jsx)("span", { className: 'row-span-2 flex h-14 w-11 shrink-0 items-center justify-center overflow-hidden rounded-ps-control border border-line/60 bg-mist/40 sm:row-span-1', children: thumbnailSrc ? ((0, jsx_runtime_1.jsx)("img", { alt: thumbnailAlt, className: 'h-full w-full object-cover object-top', decoding: 'async', loading: 'lazy', src: thumbnailSrc })) : (thumbnailFallback) }), (0, jsx_runtime_1.jsxs)("span", { className: 'flex min-w-0 flex-col gap-0.5', children: [(0, jsx_runtime_1.jsx)("span", { className: 'truncate text-sm font-semibold text-ink', children: title }), subtitle ? (0, jsx_runtime_1.jsx)("span", { className: 'truncate text-xs text-ink/55', children: subtitle }) : null, badges ? ((0, jsx_runtime_1.jsx)("span", { className: 'flex flex-wrap items-center gap-1.5 pt-1', children: badges })) : null, note ? ((0, jsx_runtime_1.jsx)("span", { className: 'line-clamp-2 break-words pt-0.5 text-xs text-ink/70', children: note })) : null] }), amount || date ? ((0, jsx_runtime_1.jsxs)("span", { className: 'col-start-2 flex items-baseline gap-2 sm:col-start-3 sm:flex-col sm:items-end sm:gap-0.5', children: [amount ? ((0, jsx_runtime_1.jsx)("span", { className: 'text-sm font-semibold tabular-nums text-ink', children: amount })) : null, date ? (0, jsx_runtime_1.jsx)("span", { className: 'text-xs tabular-nums text-ink/55', children: date }) : null] })) : null] }), actions ? ((0, jsx_runtime_1.jsx)("div", { className: 'flex w-full shrink-0 items-center justify-end gap-2 sm:w-auto', children: actions })) : null] }));
|
|
16
21
|
};
|
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
import type { ElementType } from 'react';
|
|
1
2
|
export interface PsFormFooterProps {
|
|
2
3
|
isSaving: boolean;
|
|
3
4
|
isSecondaryVisible?: boolean;
|
|
4
5
|
isSubmitDisabled: boolean;
|
|
5
|
-
|
|
6
|
+
LinkComponent?: ElementType;
|
|
7
|
+
onSecondary?: () => void;
|
|
6
8
|
savingLabel: string;
|
|
9
|
+
secondaryHref?: string;
|
|
7
10
|
secondaryLabel: string;
|
|
8
11
|
submitLabel: string;
|
|
9
12
|
}
|
|
10
|
-
export declare const PsFormFooter: ({ isSaving, isSecondaryVisible, isSubmitDisabled, onSecondary, savingLabel, secondaryLabel, submitLabel, }: PsFormFooterProps) => import("react").JSX.Element;
|
|
13
|
+
export declare const PsFormFooter: ({ isSaving, isSecondaryVisible, isSubmitDisabled, LinkComponent, onSecondary, savingLabel, secondaryHref, secondaryLabel, submitLabel, }: PsFormFooterProps) => import("react").JSX.Element;
|
|
@@ -3,5 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.PsFormFooter = void 0;
|
|
4
4
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
5
|
const ps_button_1 = require("./ps-button");
|
|
6
|
-
const
|
|
6
|
+
const ps_link_button_1 = require("./ps-link-button");
|
|
7
|
+
const PsFormFooter = ({ isSaving, isSecondaryVisible = true, isSubmitDisabled, LinkComponent, onSecondary, savingLabel, secondaryHref, secondaryLabel, submitLabel, }) => ((0, jsx_runtime_1.jsxs)("div", { className: 'sticky bottom-0 z-docked -mx-4 flex justify-end gap-2 border-t border-line bg-surface/90 px-4 py-3 backdrop-blur sm:bottom-4 sm:mx-0 sm:border-0 sm:bg-transparent sm:px-0 sm:py-0 sm:backdrop-blur-none', children: [!isSecondaryVisible ? null : secondaryHref === undefined ? ((0, jsx_runtime_1.jsx)(ps_button_1.PsButton, { disabled: isSaving, onClick: onSecondary, type: 'button', variant: 'surface', children: secondaryLabel })) : ((0, jsx_runtime_1.jsx)(ps_link_button_1.PsLinkButton, { href: secondaryHref, LinkComponent: LinkComponent, variant: 'surface', children: secondaryLabel })), (0, jsx_runtime_1.jsx)(ps_button_1.PsButton, { disabled: isSubmitDisabled || isSaving, isLoading: isSaving, loadingLabel: savingLabel, type: 'submit', variant: 'primary', children: submitLabel })] }));
|
|
7
8
|
exports.PsFormFooter = PsFormFooter;
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
export interface PsPageSkeletonProps {
|
|
3
|
+
actions?: ReactNode;
|
|
3
4
|
children: ReactNode;
|
|
4
5
|
hasActions?: boolean;
|
|
5
6
|
isNarrow?: boolean;
|
|
6
7
|
loadingLabel: string;
|
|
7
8
|
title?: string;
|
|
8
9
|
}
|
|
9
|
-
export declare const PsPageSkeleton: ({ children, hasActions, isNarrow, loadingLabel, title, }: PsPageSkeletonProps) => import("react").JSX.Element;
|
|
10
|
+
export declare const PsPageSkeleton: ({ actions, children, hasActions, isNarrow, loadingLabel, title, }: PsPageSkeletonProps) => import("react").JSX.Element;
|
|
@@ -8,5 +8,5 @@ const ps_page_layout_1 = require("./ps-page-layout");
|
|
|
8
8
|
const ps_page_stack_1 = require("./ps-page-stack");
|
|
9
9
|
const ps_section_header_1 = require("./ps-section-header");
|
|
10
10
|
const ps_skeleton_1 = require("./ps-skeleton");
|
|
11
|
-
const PsPageSkeleton = ({ children, hasActions = false, isNarrow = false, loadingLabel, title, }) => ((0, jsx_runtime_1.jsx)(ps_page_layout_1.PsPageLayout, { isNarrow: isNarrow, children: (0, jsx_runtime_1.jsxs)(ps_page_stack_1.PsPageStack, { children: [title === undefined ? ((0, jsx_runtime_1.jsx)(ps_section_header_1.PsSectionHeader, { isLoading: true, title: loadingLabel, trailing: hasActions })) : ((0, jsx_runtime_1.jsx)(ps_page_header_1.PsPageHeader, { actions: hasActions ? (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { shape: ps_skeleton_shape_1.PsSkeletonShape.Button }) : undefined, title: title })), children] }) }));
|
|
11
|
+
const PsPageSkeleton = ({ actions, children, hasActions = false, isNarrow = false, loadingLabel, title, }) => ((0, jsx_runtime_1.jsx)(ps_page_layout_1.PsPageLayout, { isNarrow: isNarrow, children: (0, jsx_runtime_1.jsxs)(ps_page_stack_1.PsPageStack, { children: [title === undefined ? ((0, jsx_runtime_1.jsx)(ps_section_header_1.PsSectionHeader, { isLoading: true, title: loadingLabel, trailing: hasActions })) : ((0, jsx_runtime_1.jsx)(ps_page_header_1.PsPageHeader, { actions: actions !== undefined ? (actions) : hasActions ? ((0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { shape: ps_skeleton_shape_1.PsSkeletonShape.Button })) : undefined, title: title })), children] }) }));
|
|
12
12
|
exports.PsPageSkeleton = PsPageSkeleton;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsSplitView = void 0;
|
|
4
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
5
|
+
const use_ps_fill_height_1 = require("../hooks/use-ps-fill-height");
|
|
6
|
+
const PsSplitView = ({ detail, list }) => {
|
|
7
|
+
const isSplit = detail !== null && detail !== undefined && detail !== false;
|
|
8
|
+
const { height, ref } = (0, use_ps_fill_height_1.usePsFillHeight)(isSplit);
|
|
9
|
+
if (!isSplit)
|
|
10
|
+
return (0, jsx_runtime_1.jsx)("div", { className: 'min-w-0', children: list });
|
|
11
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: 'min-w-0 xl:grid xl:h-[var(--ps-split-height,calc(100dvh-14rem))] xl:grid-cols-[minmax(0,1fr)_minmax(26rem,34rem)] xl:gap-4', ref: ref, style: height === null ? undefined : { '--ps-split-height': `${height}px` }, children: [(0, jsx_runtime_1.jsx)("div", { className: 'ps-scrollbar-hidden min-h-0 min-w-0 xl:overflow-y-auto', children: list }), (0, jsx_runtime_1.jsx)("div", { className: 'hidden min-h-0 min-w-0 xl:block', children: detail })] }));
|
|
12
|
+
};
|
|
13
|
+
exports.PsSplitView = PsSplitView;
|
|
@@ -9,14 +9,14 @@ exports.PsButtonSizeClassNames = {
|
|
|
9
9
|
};
|
|
10
10
|
exports.PsButtonVariantClassNames = {
|
|
11
11
|
danger: 'border-danger bg-danger text-white enabled:hover:opacity-90',
|
|
12
|
-
ghost: '
|
|
12
|
+
ghost: 'ps-liquid ps-liquid-control bg-white/72 text-ink enabled:hover:border-primary/30 dark:border-white/16 dark:bg-white/12',
|
|
13
13
|
primary: 'border-primary bg-primary text-[color:var(--ps-color-primary-contrast)] enabled:hover:border-primary-dark enabled:hover:bg-primary-dark',
|
|
14
14
|
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',
|
|
15
15
|
surface: 'ps-liquid ps-liquid-control bg-white/72 text-ink enabled:hover:border-primary/30 dark:border-white/16 dark:bg-white/12',
|
|
16
16
|
};
|
|
17
17
|
exports.PsLinkButtonVariantClassNames = {
|
|
18
18
|
danger: 'border-danger bg-danger text-white hover:opacity-90',
|
|
19
|
-
ghost: '
|
|
19
|
+
ghost: 'ps-liquid ps-liquid-control bg-white/72 text-ink hover:border-primary/30 dark:border-white/16 dark:bg-white/12',
|
|
20
20
|
primary: 'border-primary bg-primary text-[color:var(--ps-color-primary-contrast)] hover:border-primary-dark hover:bg-primary-dark',
|
|
21
21
|
secondary: 'ps-liquid ps-liquid-control bg-white/72 text-ink hover:border-primary/30 hover:text-primary dark:border-white/16 dark:bg-white/12 dark:hover:text-white',
|
|
22
22
|
surface: 'ps-liquid ps-liquid-control bg-white/72 text-ink hover:border-primary/30 dark:border-white/16 dark:bg-white/12',
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
3
|
+
export const PsActionTileContent = ({ description, icon, label, variant, }) => (_jsxs(_Fragment, { 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,12 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
3
|
+
import { PsActionTileContent } from './ps-action-tile-content.js';
|
|
4
|
+
const variantClassNames = {
|
|
5
|
+
default: 'ps-action-tile',
|
|
6
|
+
primary: 'ps-action-tile ps-action-tile-primary',
|
|
7
|
+
};
|
|
8
|
+
export const PsActionTileLink = ({ className, description, href, icon, label, LinkComponent, variant = 'default', ...props }) => {
|
|
9
|
+
const linkClassName = PallasoftClassNameService.merge('ps-focus-ring w-full', variantClassNames[variant], className);
|
|
10
|
+
const content = (_jsx(PsActionTileContent, { description: description, icon: icon, label: label, variant: variant }));
|
|
11
|
+
return LinkComponent ? (_jsx(LinkComponent, { className: linkClassName, prefetch: 'intent', to: href, ...props, children: content })) : (_jsx("a", { className: linkClassName, href: href, ...props, children: content }));
|
|
12
|
+
};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { jsx as _jsx
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
3
3
|
import { PsSkeletonShape } from '../constants/ps-skeleton-shape.js';
|
|
4
|
+
import { PsActionTileContent } from './ps-action-tile-content.js';
|
|
4
5
|
import { PsSkeleton } from './ps-skeleton.js';
|
|
5
6
|
const variantClassNames = {
|
|
6
7
|
default: 'ps-action-tile',
|
|
7
8
|
primary: 'ps-action-tile ps-action-tile-primary',
|
|
8
9
|
};
|
|
9
|
-
export const PsActionTile = ({ className, description, icon, isLoading = false, label, type = 'button', variant = 'default', ...props }) => isLoading ? (_jsx(PsSkeleton, { className: PallasoftClassNameService.merge('h-16', className), shape: PsSkeletonShape.Card })) : (
|
|
10
|
+
export const PsActionTile = ({ className, description, icon, isLoading = false, label, type = 'button', variant = 'default', ...props }) => isLoading ? (_jsx(PsSkeleton, { className: PallasoftClassNameService.merge('h-16', className), shape: PsSkeletonShape.Card })) : (_jsx("button", { className: PallasoftClassNameService.merge('ps-focus-ring w-full', variantClassNames[variant], className), type: type, ...props, children: _jsx(PsActionTileContent, { description: description, icon: icon, label: label, variant: variant }) }));
|
|
@@ -6,5 +6,5 @@ export const PsCappedList = ({ getKey, items, renderItem, showAllLabel, visibleR
|
|
|
6
6
|
const [isExpanded, setIsExpanded] = useState(false);
|
|
7
7
|
const isCapped = !isExpanded && items.length > visibleRows;
|
|
8
8
|
const shown = isCapped ? items.slice(0, visibleRows) : items;
|
|
9
|
-
return (_jsxs("div", { className: 'flex flex-col gap-2', children: [_jsx("ul", { className: '-my-2 flex flex-col divide-y divide-line', children: shown.map((item) => (_jsx("li", { children: renderItem(item) }, getKey(item)))) }), isCapped ? (_jsx(PsButton, { className: 'self-start', onClick: () => setIsExpanded(true), size: 'compact', variant: '
|
|
9
|
+
return (_jsxs("div", { className: 'flex flex-col gap-2', children: [_jsx("ul", { className: '-my-2 flex flex-col divide-y divide-line', children: shown.map((item) => (_jsx("li", { children: renderItem(item) }, getKey(item)))) }), isCapped ? (_jsx(PsButton, { className: 'self-start', onClick: () => setIsExpanded(true), size: 'compact', variant: 'surface', children: showAllLabel })) : null] }));
|
|
10
10
|
};
|
|
@@ -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 PsDetailPane = ({ children, className, footer, footerStart, headerActions, subtitle, title, }) => (_jsxs("section", { "aria-label": title, className: PallasoftClassNameService.merge('ps-card flex h-full min-h-0 min-w-0 flex-col overflow-hidden rounded-ps-card', className), children: [_jsxs("header", { className: 'flex shrink-0 items-start justify-between gap-3 border-b border-line/80 px-4 py-3.5 sm:px-5', children: [_jsxs("div", { className: 'flex min-w-0 flex-col gap-0.5', children: [_jsx("h2", { className: 'truncate text-lg font-semibold leading-tight text-ink', children: title }), subtitle ? _jsx("p", { className: 'truncate text-xs text-ink/55', children: subtitle }) : null] }), headerActions ? (_jsx("div", { className: 'flex shrink-0 items-center gap-2', children: headerActions })) : null] }), _jsx("div", { className: 'ps-scrollbar-hidden min-h-0 flex-1 overflow-y-auto px-4 py-4 sm:px-5', children: children }), footer || footerStart ? (_jsxs("footer", { className: 'flex shrink-0 flex-wrap items-center justify-between gap-2 border-t border-line/80 px-4 py-3 sm:px-5', children: [footerStart ? _jsx("div", { className: 'flex min-w-0 items-center gap-2', children: footerStart }) : null, _jsx("div", { className: 'ml-auto flex flex-wrap items-center justify-end gap-2', children: footer })] })) : null] }));
|
|
@@ -1,13 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
3
|
-
export const PsDocumentRow = ({ actions, amount, badges, className, date, isSelected = false, note, onOpen, onPrefetch, select, subtitle, thumbnailAlt = '', thumbnailFallback, thumbnailSrc, title, }) => {
|
|
3
|
+
export const PsDocumentRow = ({ actions, amount, badges, className, date, isActive = false, isSelected = false, note, onOpen, onPrefetch, select, subtitle, thumbnailAlt = '', thumbnailFallback, thumbnailSrc, title, }) => {
|
|
4
4
|
const Main = onOpen ? 'button' : 'div';
|
|
5
|
-
return (_jsxs("div", { className: PallasoftClassNameService.merge('flex min-w-0 flex-wrap items-center gap-x-3 gap-y-2 border-b border-line/70 px-3 py-3 transition-colors last:border-b-0 sm:flex-nowrap',
|
|
5
|
+
return (_jsxs("div", { className: PallasoftClassNameService.merge('flex min-w-0 flex-wrap items-center gap-x-3 gap-y-2 border-b border-line/70 px-3 py-3 transition-colors last:border-b-0 sm:flex-nowrap', isActive
|
|
6
|
+
? 'bg-primary/8 shadow-[inset_3px_0_0_rgb(var(--ps-color-primary-rgb))]'
|
|
7
|
+
: isSelected
|
|
8
|
+
? 'bg-primary/5'
|
|
9
|
+
: 'hover:bg-mist/40', className), children: [select ? _jsx("span", { className: 'flex shrink-0 items-center', children: select }) : null, _jsxs(Main, { className: 'ps-focus-ring grid min-w-0 flex-1 basis-0 grid-cols-[auto_minmax(0,1fr)] items-center gap-x-3 gap-y-1 rounded-ps-control text-left sm:grid-cols-[auto_minmax(0,1fr)_auto]', ...(onOpen
|
|
6
10
|
? {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
+
'aria-current': isActive ? 'true' : undefined,
|
|
12
|
+
'onClick': onOpen,
|
|
13
|
+
'onFocus': onPrefetch,
|
|
14
|
+
'onPointerEnter': onPrefetch,
|
|
15
|
+
'type': 'button',
|
|
11
16
|
}
|
|
12
17
|
: {}), children: [_jsx("span", { className: 'row-span-2 flex h-14 w-11 shrink-0 items-center justify-center overflow-hidden rounded-ps-control border border-line/60 bg-mist/40 sm:row-span-1', children: thumbnailSrc ? (_jsx("img", { alt: thumbnailAlt, className: 'h-full w-full object-cover object-top', decoding: 'async', loading: 'lazy', src: thumbnailSrc })) : (thumbnailFallback) }), _jsxs("span", { className: 'flex min-w-0 flex-col gap-0.5', children: [_jsx("span", { className: 'truncate text-sm font-semibold text-ink', children: title }), subtitle ? _jsx("span", { className: 'truncate text-xs text-ink/55', children: subtitle }) : null, badges ? (_jsx("span", { className: 'flex flex-wrap items-center gap-1.5 pt-1', children: badges })) : null, note ? (_jsx("span", { className: 'line-clamp-2 break-words pt-0.5 text-xs text-ink/70', children: note })) : null] }), amount || date ? (_jsxs("span", { className: 'col-start-2 flex items-baseline gap-2 sm:col-start-3 sm:flex-col sm:items-end sm:gap-0.5', children: [amount ? (_jsx("span", { className: 'text-sm font-semibold tabular-nums text-ink', children: amount })) : null, date ? _jsx("span", { className: 'text-xs tabular-nums text-ink/55', children: date }) : null] })) : null] }), actions ? (_jsx("div", { className: 'flex w-full shrink-0 items-center justify-end gap-2 sm:w-auto', children: actions })) : null] }));
|
|
13
18
|
};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { PsButton } from './ps-button.js';
|
|
3
|
-
|
|
3
|
+
import { PsLinkButton } from './ps-link-button.js';
|
|
4
|
+
export const PsFormFooter = ({ isSaving, isSecondaryVisible = true, isSubmitDisabled, LinkComponent, onSecondary, savingLabel, secondaryHref, secondaryLabel, submitLabel, }) => (_jsxs("div", { className: 'sticky bottom-0 z-docked -mx-4 flex justify-end gap-2 border-t border-line bg-surface/90 px-4 py-3 backdrop-blur sm:bottom-4 sm:mx-0 sm:border-0 sm:bg-transparent sm:px-0 sm:py-0 sm:backdrop-blur-none', children: [!isSecondaryVisible ? null : secondaryHref === undefined ? (_jsx(PsButton, { disabled: isSaving, onClick: onSecondary, type: 'button', variant: 'surface', children: secondaryLabel })) : (_jsx(PsLinkButton, { href: secondaryHref, LinkComponent: LinkComponent, variant: 'surface', children: secondaryLabel })), _jsx(PsButton, { disabled: isSubmitDisabled || isSaving, isLoading: isSaving, loadingLabel: savingLabel, type: 'submit', variant: 'primary', children: submitLabel })] }));
|
|
@@ -5,4 +5,4 @@ import { PsPageLayout } from './ps-page-layout.js';
|
|
|
5
5
|
import { PsPageStack } from './ps-page-stack.js';
|
|
6
6
|
import { PsSectionHeader } from './ps-section-header.js';
|
|
7
7
|
import { PsSkeleton } from './ps-skeleton.js';
|
|
8
|
-
export const PsPageSkeleton = ({ children, hasActions = false, isNarrow = false, loadingLabel, title, }) => (_jsx(PsPageLayout, { isNarrow: isNarrow, children: _jsxs(PsPageStack, { children: [title === undefined ? (_jsx(PsSectionHeader, { isLoading: true, title: loadingLabel, trailing: hasActions })) : (_jsx(PsPageHeader, { actions: hasActions ? _jsx(PsSkeleton, { shape: PsSkeletonShape.Button }) : undefined, title: title })), children] }) }));
|
|
8
|
+
export const PsPageSkeleton = ({ actions, children, hasActions = false, isNarrow = false, loadingLabel, title, }) => (_jsx(PsPageLayout, { isNarrow: isNarrow, children: _jsxs(PsPageStack, { children: [title === undefined ? (_jsx(PsSectionHeader, { isLoading: true, title: loadingLabel, trailing: hasActions })) : (_jsx(PsPageHeader, { actions: actions !== undefined ? (actions) : hasActions ? (_jsx(PsSkeleton, { shape: PsSkeletonShape.Button })) : undefined, title: title })), children] }) }));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { usePsFillHeight } from '../hooks/use-ps-fill-height.js';
|
|
3
|
+
export const PsSplitView = ({ detail, list }) => {
|
|
4
|
+
const isSplit = detail !== null && detail !== undefined && detail !== false;
|
|
5
|
+
const { height, ref } = usePsFillHeight(isSplit);
|
|
6
|
+
if (!isSplit)
|
|
7
|
+
return _jsx("div", { className: 'min-w-0', children: list });
|
|
8
|
+
return (_jsxs("div", { className: 'min-w-0 xl:grid xl:h-[var(--ps-split-height,calc(100dvh-14rem))] xl:grid-cols-[minmax(0,1fr)_minmax(26rem,34rem)] xl:gap-4', ref: ref, style: height === null ? undefined : { '--ps-split-height': `${height}px` }, children: [_jsx("div", { className: 'ps-scrollbar-hidden min-h-0 min-w-0 xl:overflow-y-auto', children: list }), _jsx("div", { className: 'hidden min-h-0 min-w-0 xl:block', children: detail })] }));
|
|
9
|
+
};
|
|
@@ -6,14 +6,14 @@ export const PsButtonSizeClassNames = {
|
|
|
6
6
|
};
|
|
7
7
|
export const PsButtonVariantClassNames = {
|
|
8
8
|
danger: 'border-danger bg-danger text-white enabled:hover:opacity-90',
|
|
9
|
-
ghost: '
|
|
9
|
+
ghost: 'ps-liquid ps-liquid-control bg-white/72 text-ink enabled:hover:border-primary/30 dark:border-white/16 dark:bg-white/12',
|
|
10
10
|
primary: 'border-primary bg-primary text-[color:var(--ps-color-primary-contrast)] enabled:hover:border-primary-dark enabled:hover:bg-primary-dark',
|
|
11
11
|
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',
|
|
12
12
|
surface: 'ps-liquid ps-liquid-control bg-white/72 text-ink enabled:hover:border-primary/30 dark:border-white/16 dark:bg-white/12',
|
|
13
13
|
};
|
|
14
14
|
export const PsLinkButtonVariantClassNames = {
|
|
15
15
|
danger: 'border-danger bg-danger text-white hover:opacity-90',
|
|
16
|
-
ghost: '
|
|
16
|
+
ghost: 'ps-liquid ps-liquid-control bg-white/72 text-ink hover:border-primary/30 dark:border-white/16 dark:bg-white/12',
|
|
17
17
|
primary: 'border-primary bg-primary text-[color:var(--ps-color-primary-contrast)] hover:border-primary-dark hover:bg-primary-dark',
|
|
18
18
|
secondary: 'ps-liquid ps-liquid-control bg-white/72 text-ink hover:border-primary/30 hover:text-primary dark:border-white/16 dark:bg-white/12 dark:hover:text-white',
|
|
19
19
|
surface: 'ps-liquid ps-liquid-control bg-white/72 text-ink hover:border-primary/30 dark:border-white/16 dark:bg-white/12',
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { useLayoutEffect, useRef, useState } from 'react';
|
|
2
|
+
import { PsFillHeightService } from '../services/ps-fill-height-service.js';
|
|
3
|
+
export const usePsFillHeight = (isActive) => {
|
|
4
|
+
const ref = useRef(null);
|
|
5
|
+
const [height, setHeight] = useState(null);
|
|
6
|
+
useLayoutEffect(() => {
|
|
7
|
+
const element = ref.current;
|
|
8
|
+
if (!isActive || element === null)
|
|
9
|
+
return;
|
|
10
|
+
const scroller = PsFillHeightService.scroller(element);
|
|
11
|
+
const measure = () => setHeight(PsFillHeightService.height(element, scroller));
|
|
12
|
+
const observer = new ResizeObserver(measure);
|
|
13
|
+
measure();
|
|
14
|
+
observer.observe(scroller);
|
|
15
|
+
if (element.parentElement !== null)
|
|
16
|
+
observer.observe(element.parentElement);
|
|
17
|
+
return () => observer.disconnect();
|
|
18
|
+
}, [isActive]);
|
|
19
|
+
return { height, ref };
|
|
20
|
+
};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef } from 'react';
|
|
2
|
+
export const usePsTabChannel = (name, onMessage) => {
|
|
3
|
+
const channel = useRef(null);
|
|
4
|
+
const latest = useRef(onMessage);
|
|
5
|
+
latest.current = onMessage;
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
if (typeof BroadcastChannel === 'undefined')
|
|
8
|
+
return;
|
|
9
|
+
const opened = new BroadcastChannel(name);
|
|
10
|
+
opened.onmessage = (event) => latest.current(event.data);
|
|
11
|
+
channel.current = opened;
|
|
12
|
+
return () => {
|
|
13
|
+
channel.current = null;
|
|
14
|
+
opened.close();
|
|
15
|
+
};
|
|
16
|
+
}, [name]);
|
|
17
|
+
return useCallback((message) => {
|
|
18
|
+
if (channel.current !== null)
|
|
19
|
+
channel.current.postMessage(message);
|
|
20
|
+
}, []);
|
|
21
|
+
};
|
package/dist/esm/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from './components/ps-layer.js';
|
|
2
2
|
export * from './components/ps-accordion.js';
|
|
3
3
|
export * from './components/ps-action-tile.js';
|
|
4
|
+
export * from './components/ps-action-tile-link.js';
|
|
4
5
|
export * from './components/ps-audio-spectrum.js';
|
|
5
6
|
export * from './constants/ps-audio-spectrum-config.js';
|
|
6
7
|
export * from './components/ps-badge.js';
|
|
@@ -58,6 +59,7 @@ export * from './hooks/use-ps-audio-spectrum.js';
|
|
|
58
59
|
export * from './hooks/use-ps-exit-snapshot.js';
|
|
59
60
|
export * from './hooks/use-ps-exit-transition.js';
|
|
60
61
|
export * from './hooks/use-ps-restore-focus.js';
|
|
62
|
+
export * from './hooks/use-ps-tab-channel.js';
|
|
61
63
|
export * from './hooks/use-ps-scroll-lock.js';
|
|
62
64
|
export * from './hooks/use-ps-hide-on-scroll.js';
|
|
63
65
|
export * from './hooks/use-ps-invisible-recaptcha.js';
|
|
@@ -68,6 +70,7 @@ export * from './hooks/use-ps-element-size.js';
|
|
|
68
70
|
export * from './hooks/use-ps-hydrated.js';
|
|
69
71
|
export * from './hooks/use-ps-viewport.js';
|
|
70
72
|
export * from './hooks/use-ps-media-query.js';
|
|
73
|
+
export * from './hooks/use-ps-fill-height.js';
|
|
71
74
|
export * from './interfaces/ps-component-props.js';
|
|
72
75
|
export * from './models/ps-element-size.js';
|
|
73
76
|
export * from './models/ps-voice-orb.js';
|
|
@@ -152,6 +155,8 @@ export * from './models/ps-theme-mode-state.js';
|
|
|
152
155
|
export * from './models/ps-tool-card-data.js';
|
|
153
156
|
export * from './components/ps-capped-list.js';
|
|
154
157
|
export * from './components/ps-detail-list.js';
|
|
158
|
+
export * from './components/ps-detail-pane.js';
|
|
159
|
+
export * from './components/ps-split-view.js';
|
|
155
160
|
export * from './components/ps-overview-card.js';
|
|
156
161
|
export * from './components/ps-form-footer.js';
|
|
157
162
|
export * from './components/ps-start-highlight.js';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { PsSplitViewConfig } from '../constants/ps-split-view-config.js';
|
|
2
|
+
export class PsFillHeightService {
|
|
3
|
+
static scroller(element) {
|
|
4
|
+
let parent = element.parentElement;
|
|
5
|
+
while (parent !== null) {
|
|
6
|
+
if (PsSplitViewConfig.scrollableOverflow.test(getComputedStyle(parent).overflowY))
|
|
7
|
+
return parent;
|
|
8
|
+
parent = parent.parentElement;
|
|
9
|
+
}
|
|
10
|
+
return document.documentElement;
|
|
11
|
+
}
|
|
12
|
+
static height(element, scroller) {
|
|
13
|
+
const isPage = scroller === document.documentElement;
|
|
14
|
+
const frameTop = isPage ? 0 : scroller.getBoundingClientRect().top;
|
|
15
|
+
const frameHeight = isPage ? window.innerHeight : scroller.clientHeight;
|
|
16
|
+
const scrolled = isPage ? window.scrollY : scroller.scrollTop;
|
|
17
|
+
const box = element.getBoundingClientRect();
|
|
18
|
+
const top = box.top - frameTop + scrolled;
|
|
19
|
+
const below = PsFillHeightService.below(element, scroller);
|
|
20
|
+
return Math.max(PsSplitViewConfig.minHeight, Math.floor(frameHeight - top - below));
|
|
21
|
+
}
|
|
22
|
+
static below(element, scroller) {
|
|
23
|
+
let node = element;
|
|
24
|
+
let parent = element.parentElement;
|
|
25
|
+
let total = parseFloat(getComputedStyle(scroller).paddingBottom);
|
|
26
|
+
while (parent !== null && parent !== scroller && parent !== document.body) {
|
|
27
|
+
total += Math.max(0, parent.getBoundingClientRect().bottom - node.getBoundingClientRect().bottom);
|
|
28
|
+
node = parent;
|
|
29
|
+
parent = parent.parentElement;
|
|
30
|
+
}
|
|
31
|
+
return total;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.usePsFillHeight = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const ps_fill_height_service_1 = require("../services/ps-fill-height-service");
|
|
6
|
+
const usePsFillHeight = (isActive) => {
|
|
7
|
+
const ref = (0, react_1.useRef)(null);
|
|
8
|
+
const [height, setHeight] = (0, react_1.useState)(null);
|
|
9
|
+
(0, react_1.useLayoutEffect)(() => {
|
|
10
|
+
const element = ref.current;
|
|
11
|
+
if (!isActive || element === null)
|
|
12
|
+
return;
|
|
13
|
+
const scroller = ps_fill_height_service_1.PsFillHeightService.scroller(element);
|
|
14
|
+
const measure = () => setHeight(ps_fill_height_service_1.PsFillHeightService.height(element, scroller));
|
|
15
|
+
const observer = new ResizeObserver(measure);
|
|
16
|
+
measure();
|
|
17
|
+
observer.observe(scroller);
|
|
18
|
+
if (element.parentElement !== null)
|
|
19
|
+
observer.observe(element.parentElement);
|
|
20
|
+
return () => observer.disconnect();
|
|
21
|
+
}, [isActive]);
|
|
22
|
+
return { height, ref };
|
|
23
|
+
};
|
|
24
|
+
exports.usePsFillHeight = usePsFillHeight;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const usePsTabChannel: <Message>(name: string, onMessage: (message: Message) => void) => ((message: Message) => void);
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.usePsTabChannel = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const usePsTabChannel = (name, onMessage) => {
|
|
6
|
+
const channel = (0, react_1.useRef)(null);
|
|
7
|
+
const latest = (0, react_1.useRef)(onMessage);
|
|
8
|
+
latest.current = onMessage;
|
|
9
|
+
(0, react_1.useEffect)(() => {
|
|
10
|
+
if (typeof BroadcastChannel === 'undefined')
|
|
11
|
+
return;
|
|
12
|
+
const opened = new BroadcastChannel(name);
|
|
13
|
+
opened.onmessage = (event) => latest.current(event.data);
|
|
14
|
+
channel.current = opened;
|
|
15
|
+
return () => {
|
|
16
|
+
channel.current = null;
|
|
17
|
+
opened.close();
|
|
18
|
+
};
|
|
19
|
+
}, [name]);
|
|
20
|
+
return (0, react_1.useCallback)((message) => {
|
|
21
|
+
if (channel.current !== null)
|
|
22
|
+
channel.current.postMessage(message);
|
|
23
|
+
}, []);
|
|
24
|
+
};
|
|
25
|
+
exports.usePsTabChannel = usePsTabChannel;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export * from './components/ps-layer';
|
|
2
2
|
export * from './components/ps-accordion';
|
|
3
3
|
export * from './components/ps-action-tile';
|
|
4
|
+
export * from './components/ps-action-tile-link';
|
|
4
5
|
export * from './components/ps-audio-spectrum';
|
|
5
6
|
export * from './constants/ps-audio-spectrum-config';
|
|
6
7
|
export * from './components/ps-badge';
|
|
@@ -58,6 +59,7 @@ export * from './hooks/use-ps-audio-spectrum';
|
|
|
58
59
|
export * from './hooks/use-ps-exit-snapshot';
|
|
59
60
|
export * from './hooks/use-ps-exit-transition';
|
|
60
61
|
export * from './hooks/use-ps-restore-focus';
|
|
62
|
+
export * from './hooks/use-ps-tab-channel';
|
|
61
63
|
export * from './hooks/use-ps-scroll-lock';
|
|
62
64
|
export * from './hooks/use-ps-hide-on-scroll';
|
|
63
65
|
export * from './hooks/use-ps-invisible-recaptcha';
|
|
@@ -68,6 +70,7 @@ export * from './hooks/use-ps-element-size';
|
|
|
68
70
|
export * from './hooks/use-ps-hydrated';
|
|
69
71
|
export * from './hooks/use-ps-viewport';
|
|
70
72
|
export * from './hooks/use-ps-media-query';
|
|
73
|
+
export * from './hooks/use-ps-fill-height';
|
|
71
74
|
export * from './interfaces/ps-component-props';
|
|
72
75
|
export * from './models/ps-element-size';
|
|
73
76
|
export * from './models/ps-voice-orb';
|
|
@@ -152,6 +155,8 @@ export * from './models/ps-theme-mode-state';
|
|
|
152
155
|
export * from './models/ps-tool-card-data';
|
|
153
156
|
export * from './components/ps-capped-list';
|
|
154
157
|
export * from './components/ps-detail-list';
|
|
158
|
+
export * from './components/ps-detail-pane';
|
|
159
|
+
export * from './components/ps-split-view';
|
|
155
160
|
export * from './components/ps-overview-card';
|
|
156
161
|
export * from './components/ps-form-footer';
|
|
157
162
|
export * from './components/ps-start-highlight';
|
package/dist/index.js
CHANGED
|
@@ -17,6 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
__exportStar(require("./components/ps-layer"), exports);
|
|
18
18
|
__exportStar(require("./components/ps-accordion"), exports);
|
|
19
19
|
__exportStar(require("./components/ps-action-tile"), exports);
|
|
20
|
+
__exportStar(require("./components/ps-action-tile-link"), exports);
|
|
20
21
|
__exportStar(require("./components/ps-audio-spectrum"), exports);
|
|
21
22
|
__exportStar(require("./constants/ps-audio-spectrum-config"), exports);
|
|
22
23
|
__exportStar(require("./components/ps-badge"), exports);
|
|
@@ -74,6 +75,7 @@ __exportStar(require("./hooks/use-ps-audio-spectrum"), exports);
|
|
|
74
75
|
__exportStar(require("./hooks/use-ps-exit-snapshot"), exports);
|
|
75
76
|
__exportStar(require("./hooks/use-ps-exit-transition"), exports);
|
|
76
77
|
__exportStar(require("./hooks/use-ps-restore-focus"), exports);
|
|
78
|
+
__exportStar(require("./hooks/use-ps-tab-channel"), exports);
|
|
77
79
|
__exportStar(require("./hooks/use-ps-scroll-lock"), exports);
|
|
78
80
|
__exportStar(require("./hooks/use-ps-hide-on-scroll"), exports);
|
|
79
81
|
__exportStar(require("./hooks/use-ps-invisible-recaptcha"), exports);
|
|
@@ -84,6 +86,7 @@ __exportStar(require("./hooks/use-ps-element-size"), exports);
|
|
|
84
86
|
__exportStar(require("./hooks/use-ps-hydrated"), exports);
|
|
85
87
|
__exportStar(require("./hooks/use-ps-viewport"), exports);
|
|
86
88
|
__exportStar(require("./hooks/use-ps-media-query"), exports);
|
|
89
|
+
__exportStar(require("./hooks/use-ps-fill-height"), exports);
|
|
87
90
|
__exportStar(require("./interfaces/ps-component-props"), exports);
|
|
88
91
|
__exportStar(require("./models/ps-element-size"), exports);
|
|
89
92
|
__exportStar(require("./models/ps-voice-orb"), exports);
|
|
@@ -168,6 +171,8 @@ __exportStar(require("./models/ps-theme-mode-state"), exports);
|
|
|
168
171
|
__exportStar(require("./models/ps-tool-card-data"), exports);
|
|
169
172
|
__exportStar(require("./components/ps-capped-list"), exports);
|
|
170
173
|
__exportStar(require("./components/ps-detail-list"), exports);
|
|
174
|
+
__exportStar(require("./components/ps-detail-pane"), exports);
|
|
175
|
+
__exportStar(require("./components/ps-split-view"), exports);
|
|
171
176
|
__exportStar(require("./components/ps-overview-card"), exports);
|
|
172
177
|
__exportStar(require("./components/ps-form-footer"), exports);
|
|
173
178
|
__exportStar(require("./components/ps-start-highlight"), exports);
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsFillHeightService = void 0;
|
|
4
|
+
const ps_split_view_config_1 = require("../constants/ps-split-view-config");
|
|
5
|
+
class PsFillHeightService {
|
|
6
|
+
static scroller(element) {
|
|
7
|
+
let parent = element.parentElement;
|
|
8
|
+
while (parent !== null) {
|
|
9
|
+
if (ps_split_view_config_1.PsSplitViewConfig.scrollableOverflow.test(getComputedStyle(parent).overflowY))
|
|
10
|
+
return parent;
|
|
11
|
+
parent = parent.parentElement;
|
|
12
|
+
}
|
|
13
|
+
return document.documentElement;
|
|
14
|
+
}
|
|
15
|
+
static height(element, scroller) {
|
|
16
|
+
const isPage = scroller === document.documentElement;
|
|
17
|
+
const frameTop = isPage ? 0 : scroller.getBoundingClientRect().top;
|
|
18
|
+
const frameHeight = isPage ? window.innerHeight : scroller.clientHeight;
|
|
19
|
+
const scrolled = isPage ? window.scrollY : scroller.scrollTop;
|
|
20
|
+
const box = element.getBoundingClientRect();
|
|
21
|
+
const top = box.top - frameTop + scrolled;
|
|
22
|
+
const below = PsFillHeightService.below(element, scroller);
|
|
23
|
+
return Math.max(ps_split_view_config_1.PsSplitViewConfig.minHeight, Math.floor(frameHeight - top - below));
|
|
24
|
+
}
|
|
25
|
+
static below(element, scroller) {
|
|
26
|
+
let node = element;
|
|
27
|
+
let parent = element.parentElement;
|
|
28
|
+
let total = parseFloat(getComputedStyle(scroller).paddingBottom);
|
|
29
|
+
while (parent !== null && parent !== scroller && parent !== document.body) {
|
|
30
|
+
total += Math.max(0, parent.getBoundingClientRect().bottom - node.getBoundingClientRect().bottom);
|
|
31
|
+
node = parent;
|
|
32
|
+
parent = parent.parentElement;
|
|
33
|
+
}
|
|
34
|
+
return total;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
exports.PsFillHeightService = PsFillHeightService;
|