@pallasoft/ps-core-components 2.48.0 → 2.50.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-link-preview-card.d.ts +15 -0
- package/dist/components/ps-link-preview-card.js +34 -0
- package/dist/constants/ps-link-preview-config.d.ts +20 -0
- package/dist/constants/ps-link-preview-config.js +23 -0
- package/dist/constants/ps-link-preview-size.d.ts +4 -0
- package/dist/constants/ps-link-preview-size.js +8 -0
- package/dist/esm/components/ps-link-preview-card.js +30 -0
- package/dist/esm/constants/ps-link-preview-config.js +20 -0
- package/dist/esm/constants/ps-link-preview-size.js +5 -0
- package/dist/esm/hooks/use-ps-optimistic-fetcher.js +3 -2
- package/dist/esm/index.js +4 -0
- package/dist/esm/services/ps-link-preview-service.js +19 -0
- package/dist/hooks/use-ps-optimistic-fetcher.js +3 -2
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/interfaces/ps-optimistic-fetcher-result.d.ts +1 -0
- package/dist/services/ps-link-preview-service.d.ts +4 -0
- package/dist/services/ps-link-preview-service.js +23 -0
- package/package.json +2 -2
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PsLinkPreviewSize } from '../constants/ps-link-preview-size';
|
|
2
|
+
export interface PsLinkPreviewCardProps {
|
|
3
|
+
className?: string;
|
|
4
|
+
description?: string | null;
|
|
5
|
+
faviconSrc?: string | null;
|
|
6
|
+
href: string;
|
|
7
|
+
imageSrc?: string | null;
|
|
8
|
+
isLoading?: boolean;
|
|
9
|
+
loadingLabel?: string;
|
|
10
|
+
opensInNewTabLabel?: string;
|
|
11
|
+
siteName?: string | null;
|
|
12
|
+
size?: PsLinkPreviewSize | 'compact' | 'full';
|
|
13
|
+
title?: string | null;
|
|
14
|
+
}
|
|
15
|
+
export declare const PsLinkPreviewCard: ({ className, description, faviconSrc, href, imageSrc, isLoading, loadingLabel, opensInNewTabLabel, siteName, size, title, }: PsLinkPreviewCardProps) => import("react").JSX.Element | null;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsLinkPreviewCard = 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_icons_1 = require("@pallasoft/ps-icons");
|
|
7
|
+
const ps_link_preview_config_1 = require("../constants/ps-link-preview-config");
|
|
8
|
+
const ps_link_preview_size_1 = require("../constants/ps-link-preview-size");
|
|
9
|
+
const ps_skeleton_shape_1 = require("../constants/ps-skeleton-shape");
|
|
10
|
+
const ps_link_preview_service_1 = require("../services/ps-link-preview-service");
|
|
11
|
+
const ps_image_1 = require("./ps-image");
|
|
12
|
+
const ps_skeleton_1 = require("./ps-skeleton");
|
|
13
|
+
const ps_skeleton_group_1 = require("./ps-skeleton-group");
|
|
14
|
+
const PsLinkPreviewCard = ({ className, description, faviconSrc, href, imageSrc, isLoading = false, loadingLabel, opensInNewTabLabel, siteName, size = ps_link_preview_size_1.PsLinkPreviewSize.Full, title, }) => {
|
|
15
|
+
const isCompact = size === ps_link_preview_size_1.PsLinkPreviewSize.Compact;
|
|
16
|
+
const domain = ps_link_preview_service_1.PsLinkPreviewService.domain(href);
|
|
17
|
+
const hasTitle = title !== null && title !== undefined && title.trim() !== '';
|
|
18
|
+
const hasSite = siteName !== null && siteName !== undefined && siteName.trim() !== '';
|
|
19
|
+
const hasDescription = description !== null && description !== undefined && description.trim() !== '';
|
|
20
|
+
const hasImage = imageSrc !== null && imageSrc !== undefined && imageSrc !== '';
|
|
21
|
+
const hasFavicon = faviconSrc !== null && faviconSrc !== undefined && faviconSrc !== '';
|
|
22
|
+
if (!ps_link_preview_service_1.PsLinkPreviewService.isWebAddress(href))
|
|
23
|
+
return null;
|
|
24
|
+
if (isLoading)
|
|
25
|
+
return ((0, jsx_runtime_1.jsxs)(ps_skeleton_group_1.PsSkeletonGroup, { className: ps_design_system_1.PallasoftClassNameService.merge('ps-card min-w-0 overflow-hidden rounded-ps-card', className), direction: isCompact ? 'row' : 'column', gap: 'gap-0', label: loadingLabel, children: [isCompact ? ((0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'h-20 w-24 shrink-0', shape: ps_skeleton_shape_1.PsSkeletonShape.Block, radius: '0' })) : ((0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { aspect: '1.91 / 1', className: 'w-full', shape: ps_skeleton_shape_1.PsSkeletonShape.Block, radius: '0' })), (0, jsx_runtime_1.jsxs)("span", { className: isCompact ? 'flex flex-1 flex-col gap-2 p-3' : 'flex flex-col gap-2 p-4', children: [(0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'h-3 w-24' }), (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'h-4 w-3/4' }), isCompact ? null : (0, jsx_runtime_1.jsx)(ps_skeleton_1.PsSkeleton, { className: 'h-3 w-full' })] })] }));
|
|
26
|
+
const favicon = hasFavicon ? ((0, jsx_runtime_1.jsx)(ps_image_1.PsImage, { alt: '', className: ps_link_preview_config_1.PsLinkPreviewConfig.faviconClassName, errorFallback: (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { className: ps_link_preview_config_1.PsLinkPreviewConfig.globeIconClassName, iconKey: ps_icons_1.PsIconKey.Globe }), height: 16, loading: 'lazy', src: faviconSrc, width: 16 })) : ((0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { className: ps_link_preview_config_1.PsLinkPreviewConfig.globeIconClassName, iconKey: ps_icons_1.PsIconKey.Globe }));
|
|
27
|
+
const meta = ((0, jsx_runtime_1.jsxs)("span", { className: ps_link_preview_config_1.PsLinkPreviewConfig.metaRowClassName, children: [favicon, (0, jsx_runtime_1.jsx)("span", { className: ps_link_preview_config_1.PsLinkPreviewConfig.siteClassName, children: hasSite ? siteName : domain }), (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { className: ps_link_preview_config_1.PsLinkPreviewConfig.externalIconClassName, iconKey: ps_icons_1.PsIconKey.ExternalLink })] }));
|
|
28
|
+
const text = ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [meta, hasTitle ? ((0, jsx_runtime_1.jsx)("span", { className: ps_link_preview_config_1.PsLinkPreviewConfig.titleClassName, children: title })) : ((0, jsx_runtime_1.jsx)("span", { className: ps_link_preview_config_1.PsLinkPreviewConfig.urlClassName, children: href })), hasDescription && !isCompact ? ((0, jsx_runtime_1.jsx)("span", { className: ps_link_preview_config_1.PsLinkPreviewConfig.descriptionClassName, children: description })) : null, opensInNewTabLabel === undefined ? null : ((0, jsx_runtime_1.jsx)("span", { className: 'sr-only', children: opensInNewTabLabel }))] }));
|
|
29
|
+
const media = hasImage ? ((0, jsx_runtime_1.jsx)(ps_image_1.PsImage, { alt: '', className: isCompact
|
|
30
|
+
? ps_link_preview_config_1.PsLinkPreviewConfig.compactImageClassName
|
|
31
|
+
: ps_link_preview_config_1.PsLinkPreviewConfig.fullImageClassName, errorFallback: null, loading: 'lazy', src: imageSrc })) : null;
|
|
32
|
+
return ((0, jsx_runtime_1.jsx)("a", { className: ps_design_system_1.PallasoftClassNameService.merge(ps_link_preview_config_1.PsLinkPreviewConfig.anchorClassName, className), href: href, rel: ps_link_preview_config_1.PsLinkPreviewConfig.rel, target: ps_link_preview_config_1.PsLinkPreviewConfig.target, children: isCompact ? ((0, jsx_runtime_1.jsxs)("span", { className: ps_link_preview_config_1.PsLinkPreviewConfig.compactRowClassName, children: [media === null ? null : ((0, jsx_runtime_1.jsx)("span", { className: ps_link_preview_config_1.PsLinkPreviewConfig.compactMediaClassName, children: media })), (0, jsx_runtime_1.jsx)("span", { className: ps_link_preview_config_1.PsLinkPreviewConfig.compactBodyClassName, children: text })] })) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [media === null ? null : ((0, jsx_runtime_1.jsx)("span", { className: ps_link_preview_config_1.PsLinkPreviewConfig.fullMediaClassName, children: media })), (0, jsx_runtime_1.jsx)("span", { className: ps_link_preview_config_1.PsLinkPreviewConfig.fullBodyClassName, children: text })] })) }));
|
|
33
|
+
};
|
|
34
|
+
exports.PsLinkPreviewCard = PsLinkPreviewCard;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export declare const PsLinkPreviewConfig: {
|
|
2
|
+
readonly anchorClassName: "ps-card ps-focus-ring group block min-w-0 overflow-hidden rounded-ps-card text-left no-underline transition hover:border-primary/60";
|
|
3
|
+
readonly compactBodyClassName: "flex min-w-0 flex-1 flex-col gap-0.5 p-3";
|
|
4
|
+
readonly compactImageClassName: "h-full w-full object-cover";
|
|
5
|
+
readonly compactMediaClassName: "relative block w-20 shrink-0 self-stretch overflow-hidden bg-ink/5 empty:hidden sm:w-24 [&>span]:block [&>span]:h-full [&>span]:w-full";
|
|
6
|
+
readonly compactRowClassName: "flex min-w-0 items-stretch";
|
|
7
|
+
readonly descriptionClassName: "line-clamp-2 break-words text-sm text-ink/70";
|
|
8
|
+
readonly externalIconClassName: "h-4 w-4 shrink-0 text-ink/50 transition group-hover:text-primary";
|
|
9
|
+
readonly faviconClassName: "h-4 w-4 shrink-0 rounded-sm object-contain";
|
|
10
|
+
readonly fullBodyClassName: "flex min-w-0 flex-col gap-1 p-4";
|
|
11
|
+
readonly fullImageClassName: "h-full w-full object-cover";
|
|
12
|
+
readonly fullMediaClassName: "relative block aspect-[1.91/1] w-full overflow-hidden bg-ink/5 empty:hidden [&>span]:block [&>span]:h-full [&>span]:w-full";
|
|
13
|
+
readonly globeIconClassName: "h-4 w-4 shrink-0 text-ink/50";
|
|
14
|
+
readonly metaRowClassName: "flex min-w-0 items-center gap-2 text-xs font-medium text-ink/60";
|
|
15
|
+
readonly rel: "noopener noreferrer";
|
|
16
|
+
readonly siteClassName: "min-w-0 flex-1 truncate";
|
|
17
|
+
readonly target: "_blank";
|
|
18
|
+
readonly titleClassName: "line-clamp-2 break-words text-sm font-bold text-ink transition group-hover:text-primary";
|
|
19
|
+
readonly urlClassName: "truncate text-xs text-ink/60";
|
|
20
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsLinkPreviewConfig = void 0;
|
|
4
|
+
exports.PsLinkPreviewConfig = {
|
|
5
|
+
anchorClassName: 'ps-card ps-focus-ring group block min-w-0 overflow-hidden rounded-ps-card text-left no-underline transition hover:border-primary/60',
|
|
6
|
+
compactBodyClassName: 'flex min-w-0 flex-1 flex-col gap-0.5 p-3',
|
|
7
|
+
compactImageClassName: 'h-full w-full object-cover',
|
|
8
|
+
compactMediaClassName: 'relative block w-20 shrink-0 self-stretch overflow-hidden bg-ink/5 empty:hidden sm:w-24 [&>span]:block [&>span]:h-full [&>span]:w-full',
|
|
9
|
+
compactRowClassName: 'flex min-w-0 items-stretch',
|
|
10
|
+
descriptionClassName: 'line-clamp-2 break-words text-sm text-ink/70',
|
|
11
|
+
externalIconClassName: 'h-4 w-4 shrink-0 text-ink/50 transition group-hover:text-primary',
|
|
12
|
+
faviconClassName: 'h-4 w-4 shrink-0 rounded-sm object-contain',
|
|
13
|
+
fullBodyClassName: 'flex min-w-0 flex-col gap-1 p-4',
|
|
14
|
+
fullImageClassName: 'h-full w-full object-cover',
|
|
15
|
+
fullMediaClassName: 'relative block aspect-[1.91/1] w-full overflow-hidden bg-ink/5 empty:hidden [&>span]:block [&>span]:h-full [&>span]:w-full',
|
|
16
|
+
globeIconClassName: 'h-4 w-4 shrink-0 text-ink/50',
|
|
17
|
+
metaRowClassName: 'flex min-w-0 items-center gap-2 text-xs font-medium text-ink/60',
|
|
18
|
+
rel: 'noopener noreferrer',
|
|
19
|
+
siteClassName: 'min-w-0 flex-1 truncate',
|
|
20
|
+
target: '_blank',
|
|
21
|
+
titleClassName: 'line-clamp-2 break-words text-sm font-bold text-ink transition group-hover:text-primary',
|
|
22
|
+
urlClassName: 'truncate text-xs text-ink/60',
|
|
23
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsLinkPreviewSize = void 0;
|
|
4
|
+
var PsLinkPreviewSize;
|
|
5
|
+
(function (PsLinkPreviewSize) {
|
|
6
|
+
PsLinkPreviewSize["Compact"] = "compact";
|
|
7
|
+
PsLinkPreviewSize["Full"] = "full";
|
|
8
|
+
})(PsLinkPreviewSize || (exports.PsLinkPreviewSize = PsLinkPreviewSize = {}));
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
3
|
+
import { PsIcon, PsIconKey } from '@pallasoft/ps-icons';
|
|
4
|
+
import { PsLinkPreviewConfig } from '../constants/ps-link-preview-config.js';
|
|
5
|
+
import { PsLinkPreviewSize } from '../constants/ps-link-preview-size.js';
|
|
6
|
+
import { PsSkeletonShape } from '../constants/ps-skeleton-shape.js';
|
|
7
|
+
import { PsLinkPreviewService } from '../services/ps-link-preview-service.js';
|
|
8
|
+
import { PsImage } from './ps-image.js';
|
|
9
|
+
import { PsSkeleton } from './ps-skeleton.js';
|
|
10
|
+
import { PsSkeletonGroup } from './ps-skeleton-group.js';
|
|
11
|
+
export const PsLinkPreviewCard = ({ className, description, faviconSrc, href, imageSrc, isLoading = false, loadingLabel, opensInNewTabLabel, siteName, size = PsLinkPreviewSize.Full, title, }) => {
|
|
12
|
+
const isCompact = size === PsLinkPreviewSize.Compact;
|
|
13
|
+
const domain = PsLinkPreviewService.domain(href);
|
|
14
|
+
const hasTitle = title !== null && title !== undefined && title.trim() !== '';
|
|
15
|
+
const hasSite = siteName !== null && siteName !== undefined && siteName.trim() !== '';
|
|
16
|
+
const hasDescription = description !== null && description !== undefined && description.trim() !== '';
|
|
17
|
+
const hasImage = imageSrc !== null && imageSrc !== undefined && imageSrc !== '';
|
|
18
|
+
const hasFavicon = faviconSrc !== null && faviconSrc !== undefined && faviconSrc !== '';
|
|
19
|
+
if (!PsLinkPreviewService.isWebAddress(href))
|
|
20
|
+
return null;
|
|
21
|
+
if (isLoading)
|
|
22
|
+
return (_jsxs(PsSkeletonGroup, { className: PallasoftClassNameService.merge('ps-card min-w-0 overflow-hidden rounded-ps-card', className), direction: isCompact ? 'row' : 'column', gap: 'gap-0', label: loadingLabel, children: [isCompact ? (_jsx(PsSkeleton, { className: 'h-20 w-24 shrink-0', shape: PsSkeletonShape.Block, radius: '0' })) : (_jsx(PsSkeleton, { aspect: '1.91 / 1', className: 'w-full', shape: PsSkeletonShape.Block, radius: '0' })), _jsxs("span", { className: isCompact ? 'flex flex-1 flex-col gap-2 p-3' : 'flex flex-col gap-2 p-4', children: [_jsx(PsSkeleton, { className: 'h-3 w-24' }), _jsx(PsSkeleton, { className: 'h-4 w-3/4' }), isCompact ? null : _jsx(PsSkeleton, { className: 'h-3 w-full' })] })] }));
|
|
23
|
+
const favicon = hasFavicon ? (_jsx(PsImage, { alt: '', className: PsLinkPreviewConfig.faviconClassName, errorFallback: _jsx(PsIcon, { className: PsLinkPreviewConfig.globeIconClassName, iconKey: PsIconKey.Globe }), height: 16, loading: 'lazy', src: faviconSrc, width: 16 })) : (_jsx(PsIcon, { className: PsLinkPreviewConfig.globeIconClassName, iconKey: PsIconKey.Globe }));
|
|
24
|
+
const meta = (_jsxs("span", { className: PsLinkPreviewConfig.metaRowClassName, children: [favicon, _jsx("span", { className: PsLinkPreviewConfig.siteClassName, children: hasSite ? siteName : domain }), _jsx(PsIcon, { className: PsLinkPreviewConfig.externalIconClassName, iconKey: PsIconKey.ExternalLink })] }));
|
|
25
|
+
const text = (_jsxs(_Fragment, { children: [meta, hasTitle ? (_jsx("span", { className: PsLinkPreviewConfig.titleClassName, children: title })) : (_jsx("span", { className: PsLinkPreviewConfig.urlClassName, children: href })), hasDescription && !isCompact ? (_jsx("span", { className: PsLinkPreviewConfig.descriptionClassName, children: description })) : null, opensInNewTabLabel === undefined ? null : (_jsx("span", { className: 'sr-only', children: opensInNewTabLabel }))] }));
|
|
26
|
+
const media = hasImage ? (_jsx(PsImage, { alt: '', className: isCompact
|
|
27
|
+
? PsLinkPreviewConfig.compactImageClassName
|
|
28
|
+
: PsLinkPreviewConfig.fullImageClassName, errorFallback: null, loading: 'lazy', src: imageSrc })) : null;
|
|
29
|
+
return (_jsx("a", { className: PallasoftClassNameService.merge(PsLinkPreviewConfig.anchorClassName, className), href: href, rel: PsLinkPreviewConfig.rel, target: PsLinkPreviewConfig.target, children: isCompact ? (_jsxs("span", { className: PsLinkPreviewConfig.compactRowClassName, children: [media === null ? null : (_jsx("span", { className: PsLinkPreviewConfig.compactMediaClassName, children: media })), _jsx("span", { className: PsLinkPreviewConfig.compactBodyClassName, children: text })] })) : (_jsxs(_Fragment, { children: [media === null ? null : (_jsx("span", { className: PsLinkPreviewConfig.fullMediaClassName, children: media })), _jsx("span", { className: PsLinkPreviewConfig.fullBodyClassName, children: text })] })) }));
|
|
30
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const PsLinkPreviewConfig = {
|
|
2
|
+
anchorClassName: 'ps-card ps-focus-ring group block min-w-0 overflow-hidden rounded-ps-card text-left no-underline transition hover:border-primary/60',
|
|
3
|
+
compactBodyClassName: 'flex min-w-0 flex-1 flex-col gap-0.5 p-3',
|
|
4
|
+
compactImageClassName: 'h-full w-full object-cover',
|
|
5
|
+
compactMediaClassName: 'relative block w-20 shrink-0 self-stretch overflow-hidden bg-ink/5 empty:hidden sm:w-24 [&>span]:block [&>span]:h-full [&>span]:w-full',
|
|
6
|
+
compactRowClassName: 'flex min-w-0 items-stretch',
|
|
7
|
+
descriptionClassName: 'line-clamp-2 break-words text-sm text-ink/70',
|
|
8
|
+
externalIconClassName: 'h-4 w-4 shrink-0 text-ink/50 transition group-hover:text-primary',
|
|
9
|
+
faviconClassName: 'h-4 w-4 shrink-0 rounded-sm object-contain',
|
|
10
|
+
fullBodyClassName: 'flex min-w-0 flex-col gap-1 p-4',
|
|
11
|
+
fullImageClassName: 'h-full w-full object-cover',
|
|
12
|
+
fullMediaClassName: 'relative block aspect-[1.91/1] w-full overflow-hidden bg-ink/5 empty:hidden [&>span]:block [&>span]:h-full [&>span]:w-full',
|
|
13
|
+
globeIconClassName: 'h-4 w-4 shrink-0 text-ink/50',
|
|
14
|
+
metaRowClassName: 'flex min-w-0 items-center gap-2 text-xs font-medium text-ink/60',
|
|
15
|
+
rel: 'noopener noreferrer',
|
|
16
|
+
siteClassName: 'min-w-0 flex-1 truncate',
|
|
17
|
+
target: '_blank',
|
|
18
|
+
titleClassName: 'line-clamp-2 break-words text-sm font-bold text-ink transition group-hover:text-primary',
|
|
19
|
+
urlClassName: 'truncate text-xs text-ink/60',
|
|
20
|
+
};
|
|
@@ -9,10 +9,11 @@ export const usePsOptimisticFetcher = ({ apply, fetcher, isHolding = false, isSu
|
|
|
9
9
|
const dataBefore = useRef(fetcher.data);
|
|
10
10
|
const dataSeen = useRef(fetcher.data);
|
|
11
11
|
const failure = useRef(null);
|
|
12
|
+
const isSaving = isUnsettled || fetcher.state !== 'idle';
|
|
12
13
|
const { forgetLast, remember, rows: shown, } = usePsOptimisticRows({
|
|
13
14
|
apply,
|
|
14
15
|
isHolding,
|
|
15
|
-
isSaving:
|
|
16
|
+
isSaving: isSaving || revalidator.state !== 'idle',
|
|
16
17
|
rows,
|
|
17
18
|
});
|
|
18
19
|
useEffect(() => {
|
|
@@ -100,5 +101,5 @@ export const usePsOptimisticFetcher = ({ apply, fetcher, isHolding = false, isSu
|
|
|
100
101
|
remember(values);
|
|
101
102
|
queue.enqueue(values);
|
|
102
103
|
}, [queue, remember]);
|
|
103
|
-
return { rows: shown, submit };
|
|
104
|
+
return { isSaving, rows: shown, submit };
|
|
104
105
|
};
|
package/dist/esm/index.js
CHANGED
|
@@ -248,3 +248,7 @@ export * from './services/ps-image-service.js';
|
|
|
248
248
|
export * from './components/ps-image.js';
|
|
249
249
|
export { PsDeepEqualService, PsOptimisticConfig, PsOptimisticSaveService, } from '@pallasoft/ps-utilities';
|
|
250
250
|
export { usePsChangeQueue, usePsDebouncedValue, usePsOptimisticRows, } from '@pallasoft/ps-utilities/react';
|
|
251
|
+
export * from './constants/ps-link-preview-size.js';
|
|
252
|
+
export * from './constants/ps-link-preview-config.js';
|
|
253
|
+
export * from './services/ps-link-preview-service.js';
|
|
254
|
+
export * from './components/ps-link-preview-card.js';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export class PsLinkPreviewService {
|
|
2
|
+
static isWebAddress(href) {
|
|
3
|
+
try {
|
|
4
|
+
const { protocol } = new URL(href);
|
|
5
|
+
return protocol === 'http:' || protocol === 'https:';
|
|
6
|
+
}
|
|
7
|
+
catch {
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
static domain(href) {
|
|
12
|
+
try {
|
|
13
|
+
return new URL(href).hostname.replace(/^www\./i, '');
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return href;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -12,10 +12,11 @@ const usePsOptimisticFetcher = ({ apply, fetcher, isHolding = false, isSuccess,
|
|
|
12
12
|
const dataBefore = (0, react_1.useRef)(fetcher.data);
|
|
13
13
|
const dataSeen = (0, react_1.useRef)(fetcher.data);
|
|
14
14
|
const failure = (0, react_1.useRef)(null);
|
|
15
|
+
const isSaving = isUnsettled || fetcher.state !== 'idle';
|
|
15
16
|
const { forgetLast, remember, rows: shown, } = (0, react_2.usePsOptimisticRows)({
|
|
16
17
|
apply,
|
|
17
18
|
isHolding,
|
|
18
|
-
isSaving:
|
|
19
|
+
isSaving: isSaving || revalidator.state !== 'idle',
|
|
19
20
|
rows,
|
|
20
21
|
});
|
|
21
22
|
(0, react_1.useEffect)(() => {
|
|
@@ -103,6 +104,6 @@ const usePsOptimisticFetcher = ({ apply, fetcher, isHolding = false, isSuccess,
|
|
|
103
104
|
remember(values);
|
|
104
105
|
queue.enqueue(values);
|
|
105
106
|
}, [queue, remember]);
|
|
106
|
-
return { rows: shown, submit };
|
|
107
|
+
return { isSaving, rows: shown, submit };
|
|
107
108
|
};
|
|
108
109
|
exports.usePsOptimisticFetcher = usePsOptimisticFetcher;
|
package/dist/index.d.ts
CHANGED
|
@@ -248,3 +248,7 @@ export * from './services/ps-image-service';
|
|
|
248
248
|
export * from './components/ps-image';
|
|
249
249
|
export { PsDeepEqualService, PsOptimisticConfig, PsOptimisticSaveService, type PsOptimisticFailureReason, type PsOptimisticSaveSpec, } from '@pallasoft/ps-utilities';
|
|
250
250
|
export { usePsChangeQueue, usePsDebouncedValue, usePsOptimisticRows, type PsChangeQueueInput, type PsChangeQueueResult, type PsOptimisticRowsInput, type PsOptimisticRowsResult, } from '@pallasoft/ps-utilities/react';
|
|
251
|
+
export * from './constants/ps-link-preview-size';
|
|
252
|
+
export * from './constants/ps-link-preview-config';
|
|
253
|
+
export * from './services/ps-link-preview-service';
|
|
254
|
+
export * from './components/ps-link-preview-card';
|
package/dist/index.js
CHANGED
|
@@ -271,3 +271,7 @@ var react_1 = require("@pallasoft/ps-utilities/react");
|
|
|
271
271
|
Object.defineProperty(exports, "usePsChangeQueue", { enumerable: true, get: function () { return react_1.usePsChangeQueue; } });
|
|
272
272
|
Object.defineProperty(exports, "usePsDebouncedValue", { enumerable: true, get: function () { return react_1.usePsDebouncedValue; } });
|
|
273
273
|
Object.defineProperty(exports, "usePsOptimisticRows", { enumerable: true, get: function () { return react_1.usePsOptimisticRows; } });
|
|
274
|
+
__exportStar(require("./constants/ps-link-preview-size"), exports);
|
|
275
|
+
__exportStar(require("./constants/ps-link-preview-config"), exports);
|
|
276
|
+
__exportStar(require("./services/ps-link-preview-service"), exports);
|
|
277
|
+
__exportStar(require("./components/ps-link-preview-card"), exports);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PsLinkPreviewService = void 0;
|
|
4
|
+
class PsLinkPreviewService {
|
|
5
|
+
static isWebAddress(href) {
|
|
6
|
+
try {
|
|
7
|
+
const { protocol } = new URL(href);
|
|
8
|
+
return protocol === 'http:' || protocol === 'https:';
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return false;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
static domain(href) {
|
|
15
|
+
try {
|
|
16
|
+
return new URL(href).hostname.replace(/^www\./i, '');
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return href;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
exports.PsLinkPreviewService = PsLinkPreviewService;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pallasoft/ps-core-components",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.50.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"@dnd-kit/core": "^6.3.1",
|
|
47
47
|
"@dnd-kit/sortable": "^10.0.0",
|
|
48
48
|
"@dnd-kit/utilities": "^3.2.2",
|
|
49
|
-
"@pallasoft/ps-icons": "^1.
|
|
49
|
+
"@pallasoft/ps-icons": "^1.12.0",
|
|
50
50
|
"@pallasoft/ps-motion-components": "^1.2.2",
|
|
51
51
|
"@pallasoft/ps-utilities": "^2.29.0",
|
|
52
52
|
"@portabletext/react": "^3.2.4",
|