@pallasoft/ps-mobile-components 1.14.0 → 1.15.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/index.d.ts +2 -0
- package/dist/components/ps-link-preview-card/index.js +2 -0
- package/dist/components/ps-link-preview-card/ps-link-preview-card-props.d.ts +21 -0
- package/dist/components/ps-link-preview-card/ps-link-preview-card-props.js +1 -0
- package/dist/components/ps-link-preview-card/ps-link-preview-card-skeleton.d.ts +2 -0
- package/dist/components/ps-link-preview-card/ps-link-preview-card-skeleton.js +28 -0
- package/dist/components/ps-link-preview-card/ps-link-preview-card.d.ts +2 -0
- package/dist/components/ps-link-preview-card/ps-link-preview-card.js +66 -0
- package/dist/components/ps-list/ps-list-person-row.js +1 -3
- package/dist/components/ps-list/ps-list-row-body.js +1 -3
- package/dist/components/ps-list/ps-list-row-skeleton.js +1 -3
- package/dist/components/ps-native-menu/ps-native-menu-row.js +1 -1
- package/dist/constants/ps-chart-config.d.ts +1 -0
- package/dist/constants/ps-chart-config.js +1 -0
- package/dist/constants/ps-layout-config.d.ts +2 -2
- package/dist/constants/ps-layout-config.js +2 -2
- package/dist/constants/ps-link-preview-config.d.ts +19 -0
- package/dist/constants/ps-link-preview-config.js +19 -0
- package/dist/constants/ps-link-preview-size.d.ts +5 -0
- package/dist/constants/ps-link-preview-size.js +4 -0
- package/dist/hooks/use-ps-chart-reveal.js +6 -2
- package/dist/index.d.ts +3 -0
- package/dist/index.js +3 -0
- package/dist/interfaces/ps-link-preview-meta.d.ts +5 -0
- package/dist/interfaces/ps-link-preview-meta.js +1 -0
- package/dist/services/ps-chart-reveal-service.d.ts +4 -0
- package/dist/services/ps-chart-reveal-service.js +9 -0
- package/dist/services/ps-link-preview-service.d.ts +12 -0
- package/dist/services/ps-link-preview-service.js +38 -0
- package/package.json +1 -1
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PsLinkPreviewSize } from '../../constants/ps-link-preview-size';
|
|
2
|
+
import type { PsDocumentSource } from '../../interfaces/ps-document-source';
|
|
3
|
+
export interface PsLinkPreviewCardProps {
|
|
4
|
+
description?: string | null;
|
|
5
|
+
faviconSource?: PsDocumentSource | null;
|
|
6
|
+
href: string;
|
|
7
|
+
imageSource?: PsDocumentSource | null;
|
|
8
|
+
isFramed?: boolean;
|
|
9
|
+
isLoading?: boolean;
|
|
10
|
+
loadingLabel?: string;
|
|
11
|
+
onPress: () => void;
|
|
12
|
+
opensInBrowserLabel?: string;
|
|
13
|
+
siteName?: string | null;
|
|
14
|
+
size?: PsLinkPreviewSize;
|
|
15
|
+
title?: string | null;
|
|
16
|
+
}
|
|
17
|
+
export interface PsLinkPreviewCardSkeletonProps {
|
|
18
|
+
isCompact: boolean;
|
|
19
|
+
isFramed: boolean;
|
|
20
|
+
label?: string;
|
|
21
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { View } from 'react-native';
|
|
4
|
+
import { PsLinkPreviewConfig } from '../../constants/ps-link-preview-config';
|
|
5
|
+
import { PsMobileControlConfig } from '../../constants/ps-mobile-control-config';
|
|
6
|
+
import { PsSkeletonShape } from '../../constants/ps-skeleton-shape';
|
|
7
|
+
import { usePsMobileTheme } from '../../hooks/use-ps-mobile-theme';
|
|
8
|
+
import { PsLinkPreviewService } from '../../services/ps-link-preview-service';
|
|
9
|
+
import { PsSkeleton } from '../ps-skeleton/ps-skeleton';
|
|
10
|
+
export const PsLinkPreviewCardSkeleton = ({ isCompact, isFramed, label, }) => {
|
|
11
|
+
const theme = usePsMobileTheme();
|
|
12
|
+
const [width, setWidth] = useState(0);
|
|
13
|
+
const bodyPadding = isCompact
|
|
14
|
+
? PsLinkPreviewConfig.compactBodyPadding
|
|
15
|
+
: PsLinkPreviewConfig.fullBodyPadding;
|
|
16
|
+
return (_jsxs(View, { accessibilityLabel: label, accessible: label !== undefined, onLayout: (event) => setWidth(event.nativeEvent.layout.width), style: {
|
|
17
|
+
backgroundColor: theme.surface,
|
|
18
|
+
borderColor: theme.line,
|
|
19
|
+
borderRadius: PsMobileControlConfig.cardRadius,
|
|
20
|
+
borderWidth: isFramed ? 1 : 0,
|
|
21
|
+
flexDirection: isCompact ? 'row' : 'column',
|
|
22
|
+
overflow: 'hidden',
|
|
23
|
+
}, testID: 'ps-link-preview-card-skeleton', children: [isCompact ? (_jsx(PsSkeleton, { height: PsLinkPreviewConfig.compactImageMinHeight, radius: 0, shape: PsSkeletonShape.Block, width: PsLinkPreviewConfig.compactImageWidth })) : (_jsx(PsSkeleton, { height: PsLinkPreviewService.imageHeight(width), radius: 0, shape: PsSkeletonShape.Block })), _jsxs(View, { style: {
|
|
24
|
+
flex: isCompact ? 1 : undefined,
|
|
25
|
+
gap: PsLinkPreviewConfig.skeletonLineGap,
|
|
26
|
+
padding: bodyPadding,
|
|
27
|
+
}, children: [_jsx(PsSkeleton, { shape: PsSkeletonShape.Line, width: PsLinkPreviewConfig.skeletonMetaWidth }), _jsx(PsSkeleton, { shape: PsSkeletonShape.Line, width: PsLinkPreviewConfig.skeletonTitleWidth }), isCompact ? null : _jsx(PsSkeleton, { shape: PsSkeletonShape.Line })] })] }));
|
|
28
|
+
};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import type { PsLinkPreviewCardProps } from './ps-link-preview-card-props';
|
|
2
|
+
export declare const PsLinkPreviewCard: ({ description, faviconSource, href, imageSource, isFramed, isLoading, loadingLabel, onPress, opensInBrowserLabel, siteName, size, title, }: PsLinkPreviewCardProps) => import("react").JSX.Element | null;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { PsIconKey } from '@pallasoft/ps-icons';
|
|
4
|
+
import { Image, Pressable, View } from 'react-native';
|
|
5
|
+
import { PsLinkPreviewConfig } from '../../constants/ps-link-preview-config';
|
|
6
|
+
import { PsLinkPreviewSize } from '../../constants/ps-link-preview-size';
|
|
7
|
+
import { PsMobileControlConfig } from '../../constants/ps-mobile-control-config';
|
|
8
|
+
import { PsRippleKind } from '../../constants/ps-ripple-kind';
|
|
9
|
+
import { usePsHaptics } from '../../hooks/use-ps-haptics';
|
|
10
|
+
import { usePsMobileTheme } from '../../hooks/use-ps-mobile-theme';
|
|
11
|
+
import { PsLinkPreviewService } from '../../services/ps-link-preview-service';
|
|
12
|
+
import { PsRippleService } from '../../services/ps-ripple-service';
|
|
13
|
+
import { PsStateService } from '../../services/ps-state-service';
|
|
14
|
+
import { PsIcon } from '../ps-icon/ps-icon';
|
|
15
|
+
import { PsText } from '../ps-text/ps-text';
|
|
16
|
+
import { PsLinkPreviewCardSkeleton } from './ps-link-preview-card-skeleton';
|
|
17
|
+
export const PsLinkPreviewCard = ({ description, faviconSource, href, imageSource, isFramed = true, isLoading = false, loadingLabel, onPress, opensInBrowserLabel, siteName, size = PsLinkPreviewSize.Full, title, }) => {
|
|
18
|
+
const theme = usePsMobileTheme();
|
|
19
|
+
const haptic = usePsHaptics();
|
|
20
|
+
const [failedImageUri, setFailedImageUri] = useState(null);
|
|
21
|
+
const [failedFaviconUri, setFailedFaviconUri] = useState(null);
|
|
22
|
+
if (!PsLinkPreviewService.isWebAddress(href))
|
|
23
|
+
return null;
|
|
24
|
+
const isCompact = PsLinkPreviewService.isCompact(size);
|
|
25
|
+
if (isLoading)
|
|
26
|
+
return (_jsx(PsLinkPreviewCardSkeleton, { isCompact: isCompact, isFramed: isFramed, label: loadingLabel }));
|
|
27
|
+
const meta = PsLinkPreviewService.meta(href, title, siteName, description, size);
|
|
28
|
+
const hasImage = PsLinkPreviewService.hasSource(imageSource, failedImageUri);
|
|
29
|
+
const hasFavicon = PsLinkPreviewService.hasSource(faviconSource, failedFaviconUri);
|
|
30
|
+
return (_jsxs(Pressable, { accessibilityHint: opensInBrowserLabel, accessibilityRole: 'link', android_ripple: PsRippleService.resolve(theme, PsRippleKind.Surface), onPress: () => {
|
|
31
|
+
haptic('light');
|
|
32
|
+
onPress();
|
|
33
|
+
}, style: ({ pressed }) => ({
|
|
34
|
+
backgroundColor: pressed ? PsStateService.pressedFill(theme, theme.surface) : theme.surface,
|
|
35
|
+
borderColor: theme.line,
|
|
36
|
+
borderRadius: PsMobileControlConfig.cardRadius,
|
|
37
|
+
borderWidth: isFramed ? 1 : 0,
|
|
38
|
+
flexDirection: isCompact ? 'row' : 'column',
|
|
39
|
+
overflow: 'hidden',
|
|
40
|
+
}), testID: 'ps-link-preview-card', children: [hasImage && imageSource !== null && imageSource !== undefined ? (_jsx(Image, { onError: () => setFailedImageUri(imageSource.uri), resizeMode: 'cover', source: { headers: imageSource.headers, uri: imageSource.uri }, style: isCompact
|
|
41
|
+
? {
|
|
42
|
+
alignSelf: 'stretch',
|
|
43
|
+
backgroundColor: theme.skeletonBase,
|
|
44
|
+
minHeight: PsLinkPreviewConfig.compactImageMinHeight,
|
|
45
|
+
width: PsLinkPreviewConfig.compactImageWidth,
|
|
46
|
+
}
|
|
47
|
+
: {
|
|
48
|
+
aspectRatio: PsLinkPreviewConfig.imageAspectRatio,
|
|
49
|
+
backgroundColor: theme.skeletonBase,
|
|
50
|
+
width: '100%',
|
|
51
|
+
}, testID: 'ps-link-preview-card-image' })) : null, _jsxs(View, { style: {
|
|
52
|
+
flex: isCompact ? 1 : undefined,
|
|
53
|
+
gap: PsLinkPreviewConfig.textGap,
|
|
54
|
+
padding: isCompact
|
|
55
|
+
? PsLinkPreviewConfig.compactBodyPadding
|
|
56
|
+
: PsLinkPreviewConfig.fullBodyPadding,
|
|
57
|
+
}, children: [_jsxs(View, { style: {
|
|
58
|
+
alignItems: 'center',
|
|
59
|
+
flexDirection: 'row',
|
|
60
|
+
gap: PsLinkPreviewConfig.metaGap,
|
|
61
|
+
}, children: [hasFavicon && faviconSource !== null && faviconSource !== undefined ? (_jsx(Image, { onError: () => setFailedFaviconUri(faviconSource.uri), resizeMode: 'contain', source: { headers: faviconSource.headers, uri: faviconSource.uri }, style: {
|
|
62
|
+
borderRadius: PsLinkPreviewConfig.faviconRadius,
|
|
63
|
+
height: PsLinkPreviewConfig.faviconSize,
|
|
64
|
+
width: PsLinkPreviewConfig.faviconSize,
|
|
65
|
+
}, testID: 'ps-link-preview-card-favicon' })) : (_jsx(PsIcon, { color: theme.muted, iconKey: PsIconKey.Globe, size: PsLinkPreviewConfig.faviconSize })), _jsx(View, { style: { flex: 1 }, children: _jsx(PsText, { numberOfLines: 1, tone: 'muted', variant: 'caption', weight: 'medium', children: meta.siteLabel }) }), _jsx(PsIcon, { color: theme.muted, iconKey: PsIconKey.ExternalLink, size: PsLinkPreviewConfig.faviconSize })] }), meta.hasTitle ? (_jsx(PsText, { numberOfLines: PsLinkPreviewConfig.titleLines, weight: 'bold', children: title })) : (_jsx(PsText, { numberOfLines: 1, tone: 'muted', variant: 'caption', children: href })), meta.hasDescription ? (_jsx(PsText, { numberOfLines: PsLinkPreviewConfig.descriptionLines, tone: 'muted', variant: 'small', children: description })) : null] })] }));
|
|
66
|
+
};
|
|
@@ -12,9 +12,7 @@ export const PsListPersonRow = ({ badge, initials, subtitle, title }) => {
|
|
|
12
12
|
backgroundColor: theme.surface,
|
|
13
13
|
flexDirection: 'row',
|
|
14
14
|
gap: PsLayoutConfig.headerSlotGap,
|
|
15
|
-
minHeight:
|
|
16
|
-
? PsLayoutConfig.rowMinHeight
|
|
17
|
-
: PsLayoutConfig.rowMinHeightWithSubtitle,
|
|
15
|
+
minHeight: PsLayoutConfig.rowMinHeight,
|
|
18
16
|
paddingHorizontal: PsLayoutConfig.gutter,
|
|
19
17
|
paddingVertical: PsLayoutConfig.rowPaddingVertical,
|
|
20
18
|
}, testID: 'ps-list-person-row', children: [_jsx(PsAvatar, { initials: initials, size: 'small' }), _jsxs(View, { style: { flex: 1, gap: PsLayoutConfig.rowLineGap }, children: [_jsx(PsText, { numberOfLines: 1, weight: 'semibold', children: title }), subtitle === undefined ? null : (_jsx(PsText, { numberOfLines: 1, tone: 'muted', variant: 'small', children: subtitle }))] }), badge === undefined ? null : (_jsx(PsBadge, { size: 'small', tone: badge.tone, children: badge.label }))] }));
|
|
@@ -21,9 +21,7 @@ export const PsListRowBody = ({ badge, hasChevron = false, hasMenu, isSelectable
|
|
|
21
21
|
backgroundColor: PsListRowStyleService.background(isSelectable && isSelected, pressed, theme),
|
|
22
22
|
flexDirection: 'row',
|
|
23
23
|
gap: PsLayoutConfig.headerSlotGap,
|
|
24
|
-
minHeight:
|
|
25
|
-
? PsLayoutConfig.rowMinHeightWithSubtitle
|
|
26
|
-
: PsLayoutConfig.rowMinHeight,
|
|
24
|
+
minHeight: PsLayoutConfig.rowMinHeight,
|
|
27
25
|
paddingHorizontal: PsLayoutConfig.gutter,
|
|
28
26
|
paddingVertical: PsLayoutConfig.rowPaddingVertical,
|
|
29
27
|
}), testID: 'ps-list-row', children: [isSelectable ? _jsx(PsListRowSelectMark, { isSelected: isSelected }) : null, leadingIcon === undefined ? null : (_jsx(View, { style: {
|
|
@@ -16,9 +16,7 @@ export const PsListRowSkeleton = ({ badge, isSection = false, leadingIcon, skele
|
|
|
16
16
|
alignItems: 'center',
|
|
17
17
|
flexDirection: 'row',
|
|
18
18
|
gap: PsLayoutConfig.headerSlotGap,
|
|
19
|
-
minHeight:
|
|
20
|
-
? PsLayoutConfig.rowMinHeightWithSubtitle
|
|
21
|
-
: PsLayoutConfig.rowMinHeight,
|
|
19
|
+
minHeight: PsLayoutConfig.rowMinHeight,
|
|
22
20
|
paddingHorizontal: PsLayoutConfig.gutter,
|
|
23
21
|
paddingVertical: PsLayoutConfig.rowPaddingVertical,
|
|
24
22
|
}, testID: 'ps-skeleton-row', children: [hasIcon ? (_jsx(PsSkeleton, { height: PsLayoutConfig.rowIconBox, radius: PsLayoutConfig.rowIconBoxRadius, width: PsLayoutConfig.rowIconBox })) : null, _jsxs(View, { style: { flex: 1, gap: PsLayoutConfig.rowLineGap * 3 }, children: [_jsxs(View, { style: {
|
|
@@ -16,7 +16,7 @@ export const PsNativeMenuRow = ({ item, onSelect }) => {
|
|
|
16
16
|
backgroundColor: pressed ? PsStateService.pressedFill(theme, theme.surface) : theme.surface,
|
|
17
17
|
flexDirection: 'row',
|
|
18
18
|
gap: PsMobileControlConfig.rowSpacing,
|
|
19
|
-
minHeight: PsLayoutConfig.
|
|
19
|
+
minHeight: PsLayoutConfig.menuRowMinHeight,
|
|
20
20
|
paddingHorizontal: PsLayoutConfig.gutter,
|
|
21
21
|
}), children: [_jsx(PsText, { style: { flex: 1 }, weight: item.isSelected ? 'semibold' : 'regular', children: item.label }), item.isSelected ? _jsx(PsIcon, { color: theme.primary, iconKey: PsIconKey.Check }) : null] }));
|
|
22
22
|
};
|
|
@@ -18,8 +18,8 @@ export declare const PsLayoutConfig: {
|
|
|
18
18
|
readonly rowIconSize: 16;
|
|
19
19
|
readonly scrollEventThrottle: 16;
|
|
20
20
|
readonly selectMarkSize: 22;
|
|
21
|
-
readonly
|
|
22
|
-
readonly
|
|
21
|
+
readonly menuRowMinHeight: 48;
|
|
22
|
+
readonly rowMinHeight: 62;
|
|
23
23
|
readonly rowLineGap: 2;
|
|
24
24
|
readonly rowPaddingVertical: 12;
|
|
25
25
|
readonly sheetFooterGap: 8;
|
|
@@ -18,8 +18,8 @@ export const PsLayoutConfig = {
|
|
|
18
18
|
rowIconSize: 16,
|
|
19
19
|
scrollEventThrottle: 16,
|
|
20
20
|
selectMarkSize: 22,
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
menuRowMinHeight: 48,
|
|
22
|
+
rowMinHeight: 62,
|
|
23
23
|
rowLineGap: 2,
|
|
24
24
|
rowPaddingVertical: 12,
|
|
25
25
|
sheetFooterGap: 8,
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare const PsLinkPreviewConfig: {
|
|
2
|
+
readonly compactBodyPadding: 12;
|
|
3
|
+
readonly compactImageMinHeight: 80;
|
|
4
|
+
readonly compactImageWidth: 96;
|
|
5
|
+
readonly descriptionLines: 2;
|
|
6
|
+
readonly domainPrefixPattern: RegExp;
|
|
7
|
+
readonly faviconRadius: 2;
|
|
8
|
+
readonly faviconSize: 16;
|
|
9
|
+
readonly fullBodyPadding: 16;
|
|
10
|
+
readonly imageAspectRatio: 1.91;
|
|
11
|
+
readonly metaGap: 8;
|
|
12
|
+
readonly portSuffixPattern: RegExp;
|
|
13
|
+
readonly skeletonLineGap: 8;
|
|
14
|
+
readonly skeletonMetaWidth: 96;
|
|
15
|
+
readonly skeletonTitleWidth: 192;
|
|
16
|
+
readonly textGap: 4;
|
|
17
|
+
readonly titleLines: 2;
|
|
18
|
+
readonly webAddressPattern: RegExp;
|
|
19
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export const PsLinkPreviewConfig = {
|
|
2
|
+
compactBodyPadding: 12,
|
|
3
|
+
compactImageMinHeight: 80,
|
|
4
|
+
compactImageWidth: 96,
|
|
5
|
+
descriptionLines: 2,
|
|
6
|
+
domainPrefixPattern: /^www\./i,
|
|
7
|
+
faviconRadius: 2,
|
|
8
|
+
faviconSize: 16,
|
|
9
|
+
fullBodyPadding: 16,
|
|
10
|
+
imageAspectRatio: 1.91,
|
|
11
|
+
metaGap: 8,
|
|
12
|
+
portSuffixPattern: /:\d*$/,
|
|
13
|
+
skeletonLineGap: 8,
|
|
14
|
+
skeletonMetaWidth: 96,
|
|
15
|
+
skeletonTitleWidth: 192,
|
|
16
|
+
textGap: 4,
|
|
17
|
+
titleLines: 2,
|
|
18
|
+
webAddressPattern: /^https?:\/\/([^/?#\s]+)/i,
|
|
19
|
+
};
|
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
import { useEffect } from 'react';
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
|
2
2
|
import { useSharedValue, withTiming } from 'react-native-reanimated';
|
|
3
3
|
import { PsChartConfig } from '../constants/ps-chart-config';
|
|
4
|
+
import { PsChartRevealService } from '../services/ps-chart-reveal-service';
|
|
4
5
|
import { usePsMobileTheme } from './use-ps-mobile-theme';
|
|
5
6
|
export const usePsChartReveal = (isReady, revealKey) => {
|
|
6
7
|
const { isReduceMotion: isReduced } = usePsMobileTheme();
|
|
7
8
|
const progress = useSharedValue(isReduced ? 1 : 0);
|
|
9
|
+
const played = useRef(null);
|
|
8
10
|
useEffect(() => {
|
|
9
11
|
if (isReduced) {
|
|
10
12
|
progress.set(1);
|
|
11
13
|
return;
|
|
12
14
|
}
|
|
13
|
-
|
|
15
|
+
const token = PsChartRevealService.token(revealKey);
|
|
16
|
+
if (!PsChartRevealService.shouldPlay(isReady, played.current, token))
|
|
14
17
|
return;
|
|
18
|
+
played.current = token;
|
|
15
19
|
progress.set(0);
|
|
16
20
|
progress.set(withTiming(1, { duration: PsChartConfig.drawMs }));
|
|
17
21
|
}, [isReady, isReduced, progress, revealKey]);
|
package/dist/index.d.ts
CHANGED
|
@@ -133,6 +133,9 @@ export * from './components/ps-date-range-field';
|
|
|
133
133
|
export * from './components/ps-statement-table';
|
|
134
134
|
export * from './components/ps-action-sheet';
|
|
135
135
|
export * from './components/ps-card';
|
|
136
|
+
export * from './components/ps-link-preview-card';
|
|
137
|
+
export * from './constants/ps-link-preview-size';
|
|
138
|
+
export { PsLinkPreviewService } from './services/ps-link-preview-service';
|
|
136
139
|
export * from './components/ps-checkbox';
|
|
137
140
|
export * from './components/ps-chip';
|
|
138
141
|
export * from './components/ps-icon-button';
|
package/dist/index.js
CHANGED
|
@@ -128,6 +128,9 @@ export * from './components/ps-date-range-field';
|
|
|
128
128
|
export * from './components/ps-statement-table';
|
|
129
129
|
export * from './components/ps-action-sheet';
|
|
130
130
|
export * from './components/ps-card';
|
|
131
|
+
export * from './components/ps-link-preview-card';
|
|
132
|
+
export * from './constants/ps-link-preview-size';
|
|
133
|
+
export { PsLinkPreviewService } from './services/ps-link-preview-service';
|
|
131
134
|
export * from './components/ps-checkbox';
|
|
132
135
|
export * from './components/ps-chip';
|
|
133
136
|
export * from './components/ps-icon-button';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { PsChartConfig } from '../constants/ps-chart-config';
|
|
2
|
+
export class PsChartRevealService {
|
|
3
|
+
static token(revealKey) {
|
|
4
|
+
return revealKey === undefined ? PsChartConfig.revealDefaultToken : `key:${revealKey}`;
|
|
5
|
+
}
|
|
6
|
+
static shouldPlay(isReady, played, token) {
|
|
7
|
+
return isReady && played !== token;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { PsLinkPreviewSize } from '../constants/ps-link-preview-size';
|
|
2
|
+
import type { PsDocumentSource } from '../interfaces/ps-document-source';
|
|
3
|
+
import type { PsLinkPreviewMeta } from '../interfaces/ps-link-preview-meta';
|
|
4
|
+
export declare class PsLinkPreviewService {
|
|
5
|
+
static isWebAddress(href: string): boolean;
|
|
6
|
+
static domain(href: string): string;
|
|
7
|
+
static hasText(value: string | null | undefined): boolean;
|
|
8
|
+
static hasSource(source: PsDocumentSource | null | undefined, failedUri: string | null): boolean;
|
|
9
|
+
static isCompact(size: PsLinkPreviewSize): boolean;
|
|
10
|
+
static meta(href: string, title: string | null | undefined, siteName: string | null | undefined, description: string | null | undefined, size: PsLinkPreviewSize): PsLinkPreviewMeta;
|
|
11
|
+
static imageHeight(width: number): number;
|
|
12
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { PsLinkPreviewConfig } from '../constants/ps-link-preview-config';
|
|
2
|
+
import { PsLinkPreviewSize } from '../constants/ps-link-preview-size';
|
|
3
|
+
export class PsLinkPreviewService {
|
|
4
|
+
static isWebAddress(href) {
|
|
5
|
+
return PsLinkPreviewConfig.webAddressPattern.test(href);
|
|
6
|
+
}
|
|
7
|
+
static domain(href) {
|
|
8
|
+
const match = PsLinkPreviewConfig.webAddressPattern.exec(href);
|
|
9
|
+
if (match === null)
|
|
10
|
+
return href;
|
|
11
|
+
const authority = match[1];
|
|
12
|
+
const host = authority
|
|
13
|
+
.slice(authority.lastIndexOf('@') + 1)
|
|
14
|
+
.replace(PsLinkPreviewConfig.portSuffixPattern, '');
|
|
15
|
+
return host.replace(PsLinkPreviewConfig.domainPrefixPattern, '');
|
|
16
|
+
}
|
|
17
|
+
static hasText(value) {
|
|
18
|
+
return value !== null && value !== undefined && value.trim() !== '';
|
|
19
|
+
}
|
|
20
|
+
static hasSource(source, failedUri) {
|
|
21
|
+
return source !== null && source !== undefined && source.uri !== '' && source.uri !== failedUri;
|
|
22
|
+
}
|
|
23
|
+
static isCompact(size) {
|
|
24
|
+
return size === PsLinkPreviewSize.Compact;
|
|
25
|
+
}
|
|
26
|
+
static meta(href, title, siteName, description, size) {
|
|
27
|
+
return {
|
|
28
|
+
hasDescription: PsLinkPreviewService.hasText(description) && !PsLinkPreviewService.isCompact(size),
|
|
29
|
+
hasTitle: PsLinkPreviewService.hasText(title),
|
|
30
|
+
siteLabel: siteName !== null && siteName !== undefined && PsLinkPreviewService.hasText(siteName)
|
|
31
|
+
? siteName
|
|
32
|
+
: PsLinkPreviewService.domain(href),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
static imageHeight(width) {
|
|
36
|
+
return Math.round(width / PsLinkPreviewConfig.imageAspectRatio);
|
|
37
|
+
}
|
|
38
|
+
}
|
package/package.json
CHANGED