@pallasoft/ps-mobile-components 1.2.0 → 1.3.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-menu/ps-action-menu-avatar-entry.d.ts +5 -0
- package/dist/components/ps-action-menu/ps-action-menu-avatar-entry.js +16 -0
- package/dist/components/ps-action-menu/ps-action-menu-entries.js +4 -2
- package/dist/components/ps-action-menu/ps-action-menu-labelled.d.ts +2 -1
- package/dist/components/ps-action-menu/ps-action-menu-labelled.js +2 -2
- package/dist/components/ps-action-menu/ps-action-menu.android.js +1 -1
- package/dist/components/ps-action-menu/ps-action-menu.ios.js +10 -1
- package/dist/components/ps-action-menu/ps-menu-tile-canvas.d.ts +6 -0
- package/dist/components/ps-action-menu/ps-menu-tile-canvas.js +5 -0
- package/dist/components/ps-action-menu/ps-menu-tile-drawing.d.ts +6 -0
- package/dist/components/ps-action-menu/ps-menu-tile-drawing.js +34 -0
- package/dist/components/ps-app-lock-screen/index.d.ts +2 -0
- package/dist/components/ps-app-lock-screen/index.js +2 -0
- package/dist/components/ps-app-lock-screen/ps-app-lock-screen-props.d.ts +9 -0
- package/dist/components/ps-app-lock-screen/ps-app-lock-screen-props.js +1 -0
- package/dist/components/ps-app-lock-screen/ps-app-lock-screen.d.ts +2 -0
- package/dist/components/ps-app-lock-screen/ps-app-lock-screen.js +19 -0
- package/dist/components/ps-chip/ps-chip.js +1 -1
- package/dist/components/ps-form-sheet/ps-form-sheet-props.d.ts +2 -0
- package/dist/components/ps-form-sheet/ps-form-sheet.d.ts +1 -1
- package/dist/components/ps-form-sheet/ps-form-sheet.js +17 -7
- package/dist/components/ps-list/ps-list-context-menu.js +1 -1
- package/dist/components/ps-list/ps-list-link-menu-entry.d.ts +5 -0
- package/dist/components/ps-list/ps-list-link-menu-entry.js +11 -0
- package/dist/components/ps-list/ps-list-link-menu.d.ts +10 -0
- package/dist/components/ps-list/ps-list-link-menu.js +16 -0
- package/dist/components/ps-list/ps-list-link-row.js +1 -1
- package/dist/components/ps-list/ps-list-props.d.ts +3 -1
- package/dist/components/ps-list/ps-list-row-body.js +2 -4
- package/dist/components/ps-list/ps-list-row.d.ts +1 -1
- package/dist/components/ps-list/ps-list-row.js +3 -2
- package/dist/components/ps-mobile-theme-provider/ps-mobile-theme-provider-props.d.ts +4 -2
- package/dist/components/ps-mobile-theme-provider/ps-mobile-theme-provider.d.ts +1 -1
- package/dist/components/ps-mobile-theme-provider/ps-mobile-theme-provider.js +20 -10
- package/dist/components/ps-native-menu/ps-native-menu.android.js +1 -1
- package/dist/components/ps-option-picker/index.d.ts +2 -0
- package/dist/components/ps-option-picker/index.js +2 -0
- package/dist/components/ps-option-picker/ps-option-picker-props.d.ts +16 -0
- package/dist/components/ps-option-picker/ps-option-picker-props.js +1 -0
- package/dist/components/ps-option-picker/ps-option-picker.d.ts +2 -0
- package/dist/components/ps-option-picker/ps-option-picker.js +33 -0
- package/dist/components/ps-privacy-cover/index.d.ts +2 -0
- package/dist/components/ps-privacy-cover/index.js +2 -0
- package/dist/components/ps-privacy-cover/ps-privacy-cover-props.d.ts +4 -0
- package/dist/components/ps-privacy-cover/ps-privacy-cover-props.js +1 -0
- package/dist/components/ps-privacy-cover/ps-privacy-cover.d.ts +2 -0
- package/dist/components/ps-privacy-cover/ps-privacy-cover.js +17 -0
- package/dist/components/ps-search-select-field/index.d.ts +2 -0
- package/dist/components/ps-search-select-field/index.js +2 -0
- package/dist/components/ps-search-select-field/ps-search-select-field-props.d.ts +10 -0
- package/dist/components/ps-search-select-field/ps-search-select-field-props.js +1 -0
- package/dist/components/ps-search-select-field/ps-search-select-field.d.ts +2 -0
- package/dist/components/ps-search-select-field/ps-search-select-field.js +15 -0
- package/dist/components/ps-selection-mode/index.d.ts +2 -0
- package/dist/components/ps-selection-mode/index.js +2 -0
- package/dist/components/ps-selection-mode/ps-selection-mode-props.d.ts +13 -0
- package/dist/components/ps-selection-mode/ps-selection-mode-props.js +1 -0
- package/dist/components/ps-selection-mode/ps-selection-mode.d.ts +2 -0
- package/dist/components/ps-selection-mode/ps-selection-mode.js +28 -0
- package/dist/components/ps-sheet/ps-sheet-props.d.ts +4 -1
- package/dist/components/ps-sheet/ps-sheet.d.ts +1 -1
- package/dist/components/ps-sheet/ps-sheet.js +4 -5
- package/dist/components/ps-sheet-header/ps-sheet-header-props.d.ts +2 -0
- package/dist/components/ps-sheet-header/ps-sheet-header.d.ts +1 -1
- package/dist/components/ps-sheet-header/ps-sheet-header.js +2 -2
- package/dist/components/ps-sheet-page/ps-sheet-page-view.d.ts +8 -0
- package/dist/components/ps-sheet-page/ps-sheet-page-view.js +11 -0
- package/dist/components/ps-sheet-presenter/ps-sheet-presenter.ios.js +9 -2
- package/dist/components/ps-tab-bar-provider/index.d.ts +2 -0
- package/dist/components/ps-tab-bar-provider/index.js +2 -0
- package/dist/components/ps-tab-bar-provider/ps-tab-bar-provider-props.d.ts +4 -0
- package/dist/components/ps-tab-bar-provider/ps-tab-bar-provider-props.js +1 -0
- package/dist/components/ps-tab-bar-provider/ps-tab-bar-provider.d.ts +2 -0
- package/dist/components/ps-tab-bar-provider/ps-tab-bar-provider.js +8 -0
- package/dist/components/ps-tabs/ps-tabs.js +1 -1
- package/dist/components/ps-text-link/ps-text-link.js +1 -1
- package/dist/constants/ps-app-lock-config.d.ts +13 -0
- package/dist/constants/ps-app-lock-config.js +13 -0
- package/dist/constants/ps-app-lock-native-codes.d.ts +10 -0
- package/dist/constants/ps-app-lock-native-codes.js +10 -0
- package/dist/constants/ps-biometry-kind.d.ts +7 -0
- package/dist/constants/ps-biometry-kind.js +6 -0
- package/dist/constants/ps-list-config.d.ts +2 -0
- package/dist/constants/ps-list-config.js +2 -0
- package/dist/constants/ps-menu-tile-config.d.ts +9 -0
- package/dist/constants/ps-menu-tile-config.js +9 -0
- package/dist/constants/ps-mobile-control-config.d.ts +0 -12
- package/dist/constants/ps-mobile-control-config.js +0 -6
- package/dist/constants/ps-option-picker-config.d.ts +6 -0
- package/dist/constants/ps-option-picker-config.js +6 -0
- package/dist/constants/ps-sf-symbol-config.d.ts +92 -0
- package/dist/constants/ps-sf-symbol-config.js +92 -0
- package/dist/constants/ps-sheet-page-config.d.ts +4 -0
- package/dist/constants/ps-sheet-page-config.js +4 -0
- package/dist/contexts/ps-tab-bar-context.d.ts +2 -0
- package/dist/contexts/ps-tab-bar-context.js +5 -0
- package/dist/hooks/use-ps-app-lock.d.ts +3 -0
- package/dist/hooks/use-ps-app-lock.js +72 -0
- package/dist/hooks/use-ps-menu-tiles.d.ts +4 -0
- package/dist/hooks/use-ps-menu-tiles.js +8 -0
- package/dist/hooks/use-ps-tab-bar.d.ts +2 -0
- package/dist/hooks/use-ps-tab-bar.js +3 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.js +18 -0
- package/dist/interfaces/ps-action-menu-header.d.ts +1 -0
- package/dist/interfaces/ps-app-lock-native.d.ts +13 -0
- package/dist/interfaces/ps-app-lock-native.js +1 -0
- package/dist/interfaces/ps-app-lock-prompt.d.ts +4 -0
- package/dist/interfaces/ps-app-lock-prompt.js +1 -0
- package/dist/interfaces/ps-menu-item.d.ts +2 -0
- package/dist/interfaces/ps-menu-tile-request.d.ts +7 -0
- package/dist/interfaces/ps-menu-tile-request.js +1 -0
- package/dist/interfaces/ps-menu-tile-shape.d.ts +1 -0
- package/dist/interfaces/ps-menu-tile-shape.js +1 -0
- package/dist/interfaces/ps-mobile-brand-colors.d.ts +5 -0
- package/dist/interfaces/ps-mobile-brand-colors.js +1 -0
- package/dist/interfaces/ps-mobile-brand-input.d.ts +7 -0
- package/dist/interfaces/ps-mobile-brand-input.js +1 -0
- package/dist/interfaces/ps-mobile-theme-input.d.ts +1 -1
- package/dist/interfaces/ps-mobile-theme.d.ts +32 -0
- package/dist/interfaces/ps-sheet-leading-kind.d.ts +1 -0
- package/dist/interfaces/ps-sheet-leading-kind.js +1 -0
- package/dist/interfaces/ps-sheet-page.d.ts +8 -0
- package/dist/interfaces/ps-sheet-page.js +1 -0
- package/dist/interfaces/ps-tab-bar-context-data.d.ts +4 -0
- package/dist/interfaces/ps-tab-bar-context-data.js +1 -0
- package/dist/interfaces/use-ps-app-lock-options.d.ts +6 -0
- package/dist/interfaces/use-ps-app-lock-options.js +1 -0
- package/dist/interfaces/use-ps-app-lock-result.d.ts +7 -0
- package/dist/interfaces/use-ps-app-lock-result.js +1 -0
- package/dist/services/ps-action-menu-service.d.ts +4 -0
- package/dist/services/ps-action-menu-service.js +25 -2
- package/dist/services/ps-app-lock-grace-service.d.ts +6 -0
- package/dist/services/ps-app-lock-grace-service.js +17 -0
- package/dist/services/ps-app-lock-service.d.ts +10 -0
- package/dist/services/ps-app-lock-service.js +84 -0
- package/dist/services/ps-badge-tone-service.js +3 -3
- package/dist/services/ps-button-style-service.js +2 -2
- package/dist/services/ps-context-menu-service.d.ts +1 -0
- package/dist/services/ps-context-menu-service.js +13 -0
- package/dist/services/ps-list-row-style-service.d.ts +4 -0
- package/dist/services/ps-list-row-style-service.js +11 -0
- package/dist/services/ps-menu-tile-service.d.ts +16 -0
- package/dist/services/ps-menu-tile-service.js +70 -0
- package/dist/services/ps-menu-tile-style-service.d.ts +4 -0
- package/dist/services/ps-menu-tile-style-service.js +5 -0
- package/dist/services/ps-mobile-brand-service.d.ts +5 -0
- package/dist/services/ps-mobile-brand-service.js +24 -0
- package/dist/services/ps-mobile-theme-service.d.ts +0 -2
- package/dist/services/ps-mobile-theme-service.js +64 -94
- package/dist/services/ps-option-picker-service.d.ts +8 -0
- package/dist/services/ps-option-picker-service.js +10 -0
- package/dist/services/ps-selection-service.d.ts +5 -0
- package/dist/services/ps-selection-service.js +13 -0
- package/dist/services/ps-sheet-service.d.ts +5 -0
- package/dist/services/ps-sheet-service.js +11 -0
- package/dist/services/ps-text-service.js +4 -4
- package/jest-setup.js +71 -0
- package/package.json +14 -2
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Button, Image, Label, Toggle } from '@expo/ui/swift-ui';
|
|
3
|
+
import { disabled } from '@expo/ui/swift-ui/modifiers';
|
|
4
|
+
import { usePsHaptics } from '../../hooks/use-ps-haptics';
|
|
5
|
+
import { PsActionMenuService } from '../../services/ps-action-menu-service';
|
|
6
|
+
export const PsActionMenuAvatarEntry = ({ item }) => {
|
|
7
|
+
const haptic = usePsHaptics();
|
|
8
|
+
const choose = () => {
|
|
9
|
+
haptic('selection');
|
|
10
|
+
item.onSelect();
|
|
11
|
+
};
|
|
12
|
+
const label = (_jsx(Label, { icon: item.imageUri === undefined ? undefined : _jsx(Image, { uiImage: item.imageUri }), systemImage: PsActionMenuService.symbol(item), title: item.label }));
|
|
13
|
+
if (item.isChecked)
|
|
14
|
+
return (_jsx(Toggle, { isOn: true, modifiers: [disabled(item.isDisabled === true)], onIsOnChange: choose, children: label }));
|
|
15
|
+
return (_jsx(Button, { modifiers: [disabled(item.isDisabled === true)], onPress: choose, children: label }));
|
|
16
|
+
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Button, Menu, Section } from '@expo/ui/swift-ui';
|
|
3
3
|
import { disabled, tint } from '@expo/ui/swift-ui/modifiers';
|
|
4
|
-
import { PsSfSymbolConfig } from '../../constants/ps-sf-symbol-config';
|
|
5
4
|
import { usePsHaptics } from '../../hooks/use-ps-haptics';
|
|
6
5
|
import { usePsMobileTheme } from '../../hooks/use-ps-mobile-theme';
|
|
7
6
|
import { PsActionMenuService } from '../../services/ps-action-menu-service';
|
|
7
|
+
import { PsActionMenuAvatarEntry } from './ps-action-menu-avatar-entry';
|
|
8
8
|
import { PsActionMenuLabelled } from './ps-action-menu-labelled';
|
|
9
9
|
export const PsActionMenuEntry = ({ item }) => {
|
|
10
10
|
const haptic = usePsHaptics();
|
|
@@ -12,6 +12,8 @@ export const PsActionMenuEntry = ({ item }) => {
|
|
|
12
12
|
const symbol = PsActionMenuService.symbol(item);
|
|
13
13
|
if (item.children !== undefined && item.children.length > 0)
|
|
14
14
|
return (_jsx(Menu, { label: item.label, systemImage: symbol, children: item.children.map((child) => (_jsx(PsActionMenuEntry, { item: child }, child.id))) }));
|
|
15
|
+
if (PsActionMenuService.hasAvatar(item))
|
|
16
|
+
return _jsx(PsActionMenuAvatarEntry, { item: item });
|
|
15
17
|
if (item.subtitle !== undefined)
|
|
16
18
|
return (_jsx(Button, { modifiers: [
|
|
17
19
|
disabled(item.isDisabled === true),
|
|
@@ -28,4 +30,4 @@ export const PsActionMenuEntry = ({ item }) => {
|
|
|
28
30
|
item.onSelect();
|
|
29
31
|
}, role: item.isDanger ? 'destructive' : undefined, systemImage: symbol }));
|
|
30
32
|
};
|
|
31
|
-
export const PsActionMenuEntries = ({ header, sections }) => (_jsxs(_Fragment, { children: [header === undefined ? null : (_jsx(Section, { children: _jsx(Button, { modifiers: [disabled(header.onSelect === undefined)], onPress: header.onSelect, children: _jsx(PsActionMenuLabelled, { subtitle: header.subtitle === undefined ? '' : header.subtitle, symbol:
|
|
33
|
+
export const PsActionMenuEntries = ({ header, sections }) => (_jsxs(_Fragment, { children: [header === undefined ? null : (_jsx(Section, { children: _jsx(Button, { modifiers: [disabled(header.onSelect === undefined)], onPress: header.onSelect, children: _jsx(PsActionMenuLabelled, { imageUri: header.imageUri, subtitle: header.subtitle === undefined ? '' : header.subtitle, symbol: PsActionMenuService.headerSymbol(header), title: header.title }) }) })), sections.map((section) => (_jsx(Section, { title: section.title, children: section.items.map((item) => (_jsx(PsActionMenuEntry, { item: item }, item.id))) }, section.id)))] }));
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { SFSymbol } from 'sf-symbols-typescript';
|
|
2
2
|
export interface PsActionMenuLabelledProps {
|
|
3
|
+
imageUri?: string;
|
|
3
4
|
subtitle: string;
|
|
4
5
|
symbol: SFSymbol | undefined;
|
|
5
6
|
title: string;
|
|
6
7
|
}
|
|
7
|
-
export declare const PsActionMenuLabelled: ({ subtitle, symbol, title }: PsActionMenuLabelledProps) => import("react").JSX.Element;
|
|
8
|
+
export declare const PsActionMenuLabelled: ({ imageUri, subtitle, symbol, title, }: PsActionMenuLabelledProps) => import("react").JSX.Element;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { Label, Text, VStack } from '@expo/ui/swift-ui';
|
|
3
|
-
export const PsActionMenuLabelled = ({ subtitle, symbol, title }) => (_jsx(Label, { systemImage: symbol, children: _jsxs(VStack, { alignment: 'leading', children: [_jsx(Text, { children: title }), _jsx(Text, { children: subtitle })] }) }));
|
|
2
|
+
import { Image, Label, Text, VStack } from '@expo/ui/swift-ui';
|
|
3
|
+
export const PsActionMenuLabelled = ({ imageUri, subtitle, symbol, title, }) => (_jsx(Label, { icon: imageUri === undefined ? undefined : _jsx(Image, { uiImage: imageUri }), systemImage: symbol, children: _jsxs(VStack, { alignment: 'leading', children: [_jsx(Text, { children: title }), _jsx(Text, { children: subtitle })] }) }));
|
|
@@ -18,7 +18,7 @@ export const PsActionMenu = ({ children, header, isDisabled = false, items, labe
|
|
|
18
18
|
textColor: item.isDanger
|
|
19
19
|
? theme.danger
|
|
20
20
|
: item.isChecked
|
|
21
|
-
? theme.
|
|
21
|
+
? theme.primaryText
|
|
22
22
|
: theme.ink,
|
|
23
23
|
}, enabled: item.isDisabled !== true, onClick: () => {
|
|
24
24
|
setIsOpen(false);
|
|
@@ -1,6 +1,15 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { View } from 'react-native';
|
|
3
|
+
import { usePsMenuTiles } from '../../hooks/use-ps-menu-tiles';
|
|
3
4
|
import { PsActionMenuService } from '../../services/ps-action-menu-service';
|
|
5
|
+
import { PsMenuTileService } from '../../services/ps-menu-tile-service';
|
|
4
6
|
import { PsNativeMenuOverlay } from '../ps-native-menu-overlay/ps-native-menu-overlay';
|
|
5
7
|
import { PsActionMenuEntries } from './ps-action-menu-entries';
|
|
6
|
-
|
|
8
|
+
import { PsMenuTileCanvas } from './ps-menu-tile-canvas';
|
|
9
|
+
export const PsActionMenu = ({ children, header, isDisabled = false, items, label, sections, }) => {
|
|
10
|
+
const { onTile, tiles } = usePsMenuTiles();
|
|
11
|
+
const all = PsActionMenuService.sections(items, sections);
|
|
12
|
+
return (_jsxs(View, { children: [_jsx(PsMenuTileCanvas, { onTile: onTile, requests: PsMenuTileService.requests(header, all) }), typeof children === 'function'
|
|
13
|
+
? children({ isOpen: false, open: () => undefined })
|
|
14
|
+
: children, _jsx(PsNativeMenuOverlay, { isDisabled: isDisabled, label: label, children: _jsx(PsActionMenuEntries, { header: PsMenuTileService.header(header, tiles), sections: PsMenuTileService.sections(all, tiles) }) })] }));
|
|
15
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { PsMenuTileRequest } from '../../interfaces/ps-menu-tile-request';
|
|
2
|
+
export interface PsMenuTileCanvasProps {
|
|
3
|
+
onTile: (key: string, uri: string) => void;
|
|
4
|
+
requests: PsMenuTileRequest[];
|
|
5
|
+
}
|
|
6
|
+
export declare const PsMenuTileCanvas: ({ onTile, requests }: PsMenuTileCanvasProps) => import("react").JSX.Element | null;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import { PsMenuTileStyleService } from '../../services/ps-menu-tile-style-service';
|
|
4
|
+
import { PsMenuTileDrawing } from './ps-menu-tile-drawing';
|
|
5
|
+
export const PsMenuTileCanvas = ({ onTile, requests }) => requests.length === 0 ? null : (_jsx(View, { accessibilityElementsHidden: true, importantForAccessibility: 'no-hide-descendants', pointerEvents: 'none', style: PsMenuTileStyleService.canvas(), children: requests.map((request) => (_jsx(PsMenuTileDrawing, { onTile: onTile, request: request }, request.key))) }));
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { PsMenuTileRequest } from '../../interfaces/ps-menu-tile-request';
|
|
2
|
+
export interface PsMenuTileDrawingProps {
|
|
3
|
+
onTile: (key: string, uri: string) => void;
|
|
4
|
+
request: PsMenuTileRequest;
|
|
5
|
+
}
|
|
6
|
+
export declare const PsMenuTileDrawing: ({ onTile, request }: PsMenuTileDrawingProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useId, useRef, useState } from 'react';
|
|
3
|
+
import Svg, { ClipPath, Defs, G, Rect, Image as SvgImage, Text as SvgText } from 'react-native-svg';
|
|
4
|
+
import { PsMenuTileConfig } from '../../constants/ps-menu-tile-config';
|
|
5
|
+
import { usePsMobileTheme } from '../../hooks/use-ps-mobile-theme';
|
|
6
|
+
export const PsMenuTileDrawing = ({ onTile, request }) => {
|
|
7
|
+
const theme = usePsMobileTheme();
|
|
8
|
+
const ref = useRef(null);
|
|
9
|
+
const clipId = `tile${useId().replace(/[^a-zA-Z0-9]/g, '')}`;
|
|
10
|
+
const size = PsMenuTileConfig.size;
|
|
11
|
+
const isCircle = request.shape === 'circle';
|
|
12
|
+
const inset = isCircle ? 0 : PsMenuTileConfig.logoPadding;
|
|
13
|
+
const fontSize = request.text.length > 1 ? PsMenuTileConfig.initialsFontSize : PsMenuTileConfig.fontSize;
|
|
14
|
+
const isMounted = useRef(true);
|
|
15
|
+
const [isLaidOut, setIsLaidOut] = useState(false);
|
|
16
|
+
const [isImageLoaded, setIsImageLoaded] = useState(false);
|
|
17
|
+
const isReady = isLaidOut && (request.imageUri === undefined || isImageLoaded);
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
isMounted.current = true;
|
|
20
|
+
return () => {
|
|
21
|
+
isMounted.current = false;
|
|
22
|
+
};
|
|
23
|
+
}, []);
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
const svg = ref.current;
|
|
26
|
+
if (!isReady || svg === null)
|
|
27
|
+
return;
|
|
28
|
+
svg.toDataURL((base64) => {
|
|
29
|
+
if (isMounted.current)
|
|
30
|
+
onTile(request.key, `${PsMenuTileConfig.dataUriPrefix}${base64}`);
|
|
31
|
+
});
|
|
32
|
+
}, [isReady, onTile, request.key, theme.primary, theme.primaryContrast]);
|
|
33
|
+
return (_jsxs(Svg, { height: size, onLayout: () => setIsLaidOut(true), ref: ref, width: size, children: [_jsx(Defs, { children: _jsx(ClipPath, { id: clipId, children: _jsx(Rect, { height: size, rx: isCircle ? size / 2 : PsMenuTileConfig.roundedRadius, width: size }) }) }), _jsxs(G, { clipPath: `url(#${clipId})`, children: [_jsx(Rect, { fill: request.imageUri === undefined ? theme.primary : theme.white, height: size, width: size }), request.imageUri === undefined ? (_jsx(SvgText, { fill: theme.primaryContrast, fontFamily: theme.fonts.semibold, fontSize: fontSize, textAnchor: 'middle', x: size / 2, y: size / 2 + fontSize * PsMenuTileConfig.textBaseline, children: request.text })) : (_jsx(SvgImage, { height: size - inset * 2, href: { uri: request.imageUri }, onLoad: () => setIsImageLoaded(true), preserveAspectRatio: isCircle ? 'xMidYMid slice' : 'xMidYMid meet', width: size - inset * 2, x: inset, y: inset }))] })] }));
|
|
34
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { View } from 'react-native';
|
|
3
|
+
import { SafeAreaView } from 'react-native-safe-area-context';
|
|
4
|
+
import { PsAppLockConfig } from '../../constants/ps-app-lock-config';
|
|
5
|
+
import { PsButton } from '../ps-button/ps-button';
|
|
6
|
+
import { PsPrivacyCover } from '../ps-privacy-cover/ps-privacy-cover';
|
|
7
|
+
import { PsTextLink } from '../ps-text-link/ps-text-link';
|
|
8
|
+
export const PsAppLockScreen = ({ children, isUnlocking = false, onSignOut, onUnlock, signOutLabel, unlockLabel, }) => (_jsx(PsPrivacyCover, { children: _jsx(SafeAreaView, { style: {
|
|
9
|
+
alignItems: 'center',
|
|
10
|
+
flex: 1,
|
|
11
|
+
justifyContent: 'center',
|
|
12
|
+
paddingHorizontal: PsAppLockConfig.layout.horizontalPadding,
|
|
13
|
+
width: '100%',
|
|
14
|
+
}, children: _jsxs(View, { style: {
|
|
15
|
+
alignItems: 'center',
|
|
16
|
+
gap: PsAppLockConfig.layout.gap,
|
|
17
|
+
maxWidth: PsAppLockConfig.layout.maxWidth,
|
|
18
|
+
width: '100%',
|
|
19
|
+
}, children: [children, _jsx(PsButton, { isFullWidth: true, isLoading: isUnlocking, onPress: onUnlock, size: 'large', children: unlockLabel }), _jsx(PsTextLink, { onPress: onSignOut, tone: 'muted', children: signOutLabel })] }) }) }));
|
|
@@ -23,5 +23,5 @@ export const PsChip = ({ children, isSelected = false, onPress, trailingIcon })
|
|
|
23
23
|
gap: PsMobileControlConfig.buttonIconSpacing / 2,
|
|
24
24
|
height: PsMobileControlConfig.controlHeights.compact,
|
|
25
25
|
paddingHorizontal: PsMobileControlConfig.controlPaddingX.compact,
|
|
26
|
-
}, children: [_jsx(PsText, { numberOfLines: 1, variant: 'label', weight: 'semibold', children: children }), trailingIcon === undefined ? null : (_jsx(PsIcon, { color: theme.muted, iconKey: trailingIcon, size: PsMobileControlConfig.iconSizeInline }))] }));
|
|
26
|
+
}, children: [_jsx(PsText, { numberOfLines: 1, tone: isSelected ? 'primary' : 'ink', variant: 'label', weight: 'semibold', children: children }), trailingIcon === undefined ? null : (_jsx(PsIcon, { color: theme.muted, iconKey: trailingIcon, size: PsMobileControlConfig.iconSizeInline }))] }));
|
|
27
27
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
+
import type { PsSheetPage } from '../../interfaces/ps-sheet-page';
|
|
2
3
|
export interface PsFormSheetProps {
|
|
3
4
|
cancelLabel: string;
|
|
4
5
|
closeLabel?: string;
|
|
@@ -12,6 +13,7 @@ export interface PsFormSheetProps {
|
|
|
12
13
|
isSubmitDisabled?: boolean;
|
|
13
14
|
onClose: () => void;
|
|
14
15
|
onSubmit: () => void;
|
|
16
|
+
page?: PsSheetPage | null;
|
|
15
17
|
submitLabel: string;
|
|
16
18
|
submitVariant?: 'danger' | 'primary';
|
|
17
19
|
title: string;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { PsFormSheetProps } from './ps-form-sheet-props';
|
|
2
|
-
export declare const PsFormSheet: ({ cancelLabel, children, eyebrow, footerStart, isLoading, isOpen, isSubmitting, loadingFields, isSubmitDisabled, onClose, onSubmit, submitLabel, submitVariant, title, }: PsFormSheetProps) => import("react").JSX.Element;
|
|
2
|
+
export declare const PsFormSheet: ({ cancelLabel, children, eyebrow, footerStart, isLoading, isOpen, isSubmitting, loadingFields, isSubmitDisabled, onClose, onSubmit, page, submitLabel, submitVariant, title, }: PsFormSheetProps) => import("react").JSX.Element;
|
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useRef } from 'react';
|
|
2
3
|
import { PsFormSheetConfig } from '../../constants/ps-form-sheet-config';
|
|
4
|
+
import { PsSheetPageConfig } from '../../constants/ps-sheet-page-config';
|
|
3
5
|
import { PsFieldSkeleton } from '../ps-field-skeleton/ps-field-skeleton';
|
|
6
|
+
import { PsSheetPageView } from '../ps-sheet-page/ps-sheet-page-view';
|
|
4
7
|
import { PsSheet } from '../ps-sheet/ps-sheet';
|
|
5
|
-
export const PsFormSheet = ({ cancelLabel, children, eyebrow, footerStart, isLoading = false, isOpen, isSubmitting = false, loadingFields = PsFormSheetConfig.loadingFields, isSubmitDisabled = false, onClose, onSubmit, submitLabel, submitVariant = 'primary', title, }) =>
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
export const PsFormSheet = ({ cancelLabel, children, eyebrow, footerStart, isLoading = false, isOpen, isSubmitting = false, loadingFields = PsFormSheetConfig.loadingFields, isSubmitDisabled = false, onClose, onSubmit, page = null, submitLabel, submitVariant = 'primary', title, }) => {
|
|
9
|
+
const lastPageId = useRef(null);
|
|
10
|
+
const isReturning = page === null && lastPageId.current !== null;
|
|
11
|
+
useEffect(() => {
|
|
12
|
+
lastPageId.current = page === null ? null : page.id;
|
|
13
|
+
}, [page]);
|
|
14
|
+
return page === null ? (_jsx(PsSheet, { eyebrow: eyebrow, footer: footerStart, isDismissBlocked: isSubmitting, isOpen: isOpen, leadingLabel: cancelLabel, onClose: onClose, title: title, trailingAction: {
|
|
15
|
+
isDisabled: isSubmitDisabled || isLoading,
|
|
16
|
+
isSubmitting,
|
|
17
|
+
label: submitLabel,
|
|
18
|
+
onPress: onSubmit,
|
|
19
|
+
tone: submitVariant,
|
|
20
|
+
}, children: _jsx(PsSheetPageView, { isAnimated: isReturning, isPage: false, pageId: PsSheetPageConfig.formId, children: isLoading ? _jsx(PsFieldSkeleton, { count: loadingFields }) : children }) })) : (_jsx(PsSheet, { isOpen: isOpen, leadingKind: 'back', leadingLabel: page.backLabel, onClose: onClose, onLeadingPress: page.onBack, title: page.title, trailingAction: null, children: _jsx(PsSheetPageView, { isAnimated: true, isPage: true, pageId: page.id, children: page.children }) }));
|
|
21
|
+
};
|
|
@@ -9,6 +9,6 @@ export const PsListContextMenu = ({ children, items, title }) => {
|
|
|
9
9
|
const haptic = usePsHaptics();
|
|
10
10
|
return (_jsx(MenuView, { actions: PsContextMenuService.actions(items, theme, Platform.OS === 'ios'), onOpenMenu: () => haptic('medium'), onPressAction: ({ nativeEvent }) => {
|
|
11
11
|
haptic('selection');
|
|
12
|
-
|
|
12
|
+
PsContextMenuService.find(items, nativeEvent.event)?.onSelect();
|
|
13
13
|
}, shouldOpenOnLongPress: true, testID: 'ps-list-context-menu', themeVariant: theme.isDark ? 'dark' : 'light', title: title, children: children }));
|
|
14
14
|
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { Link } from 'expo-router';
|
|
3
|
+
import { PsActionMenuService } from '../../services/ps-action-menu-service';
|
|
4
|
+
export class PsListLinkMenuEntry {
|
|
5
|
+
static render(item, onSelect) {
|
|
6
|
+
const icon = PsActionMenuService.symbol(item);
|
|
7
|
+
if (item.children !== undefined && item.children.length > 0)
|
|
8
|
+
return (_jsx(Link.Menu, { icon: icon, title: item.label, children: item.children.map((child) => PsListLinkMenuEntry.render(child, onSelect)) }, item.id));
|
|
9
|
+
return (_jsx(Link.MenuAction, { destructive: item.isDanger === true, disabled: item.isDisabled === true, icon: icon, onPress: () => onSelect(item), title: item.label }, item.id));
|
|
10
|
+
}
|
|
11
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ReactElement, ReactNode } from 'react';
|
|
2
|
+
import type { PsMenuItem } from '../../interfaces/ps-menu-item';
|
|
3
|
+
export interface PsListLinkMenuProps {
|
|
4
|
+
children: ReactElement;
|
|
5
|
+
href: string;
|
|
6
|
+
items: PsMenuItem[];
|
|
7
|
+
preview?: ReactNode;
|
|
8
|
+
title: string;
|
|
9
|
+
}
|
|
10
|
+
export declare const PsListLinkMenu: ({ children, href, items, preview, title }: PsListLinkMenuProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Link } from 'expo-router';
|
|
3
|
+
import { PsListConfig } from '../../constants/ps-list-config';
|
|
4
|
+
import { usePsHaptics } from '../../hooks/use-ps-haptics';
|
|
5
|
+
import { PsActionMenuService } from '../../services/ps-action-menu-service';
|
|
6
|
+
import { PsListLinkMenuEntry } from './ps-list-link-menu-entry';
|
|
7
|
+
export const PsListLinkMenu = ({ children, href, items, preview, title }) => {
|
|
8
|
+
const haptic = usePsHaptics();
|
|
9
|
+
const sections = PsActionMenuService.consistent([{ id: 'items', items }]);
|
|
10
|
+
const entries = sections.length === 0 ? [] : sections[0].items;
|
|
11
|
+
const choose = (item) => {
|
|
12
|
+
haptic('selection');
|
|
13
|
+
item.onSelect();
|
|
14
|
+
};
|
|
15
|
+
return (_jsxs(Link, { asChild: true, href: href, children: [_jsx(Link.Trigger, { children: children }), preview === undefined ? (_jsx(Link.Preview, {})) : (_jsx(Link.Preview, { style: { height: PsListConfig.previewHeight, width: PsListConfig.previewWidth }, children: preview })), entries.length === 0 ? null : (_jsx(Link.Menu, { title: title, children: entries.map((item) => PsListLinkMenuEntry.render(item, choose)) }))] }));
|
|
16
|
+
};
|
|
@@ -36,5 +36,5 @@ export const PsListLinkRow = ({ count, countLabel, iconKey, isAlert = false, isL
|
|
|
36
36
|
height: PsLayoutConfig.linkRowIconBox,
|
|
37
37
|
justifyContent: 'center',
|
|
38
38
|
width: PsLayoutConfig.linkRowIconBox,
|
|
39
|
-
}, children: _jsx(PsIcon, { color: theme.
|
|
39
|
+
}, children: _jsx(PsIcon, { color: theme.primaryText, iconKey: iconKey, size: PsLayoutConfig.linkRowIconSize }) }), _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 }))] }), hasCount ? _jsx(PsCountBadge, { count: count, isAlert: isAlert, label: countLabel }) : null, _jsx(PsIcon, { color: theme.muted, iconKey: PsIconKey.ChevronRight, size: PsMobileControlConfig.iconSizeInline })] }));
|
|
40
40
|
};
|
|
@@ -46,6 +46,7 @@ export interface PsListRowProps {
|
|
|
46
46
|
actions?: PsMenuItem[];
|
|
47
47
|
badge?: PsListRowBadge;
|
|
48
48
|
hasChevron?: boolean;
|
|
49
|
+
href?: string;
|
|
49
50
|
isLoading?: boolean;
|
|
50
51
|
isSection?: boolean;
|
|
51
52
|
isSelectable?: boolean;
|
|
@@ -53,6 +54,7 @@ export interface PsListRowProps {
|
|
|
53
54
|
leadingSwipe?: PsMenuItem;
|
|
54
55
|
leadingIcon?: PsIconKey;
|
|
55
56
|
onPress?: () => void;
|
|
57
|
+
preview?: ReactNode;
|
|
56
58
|
skeleton?: PsListSkeletonLayout;
|
|
57
59
|
subtitle?: string;
|
|
58
60
|
trailingSwipe?: PsMenuItem;
|
|
@@ -63,7 +65,7 @@ export interface PsListActionRowProps {
|
|
|
63
65
|
children: string;
|
|
64
66
|
iconKey?: PsIconKey;
|
|
65
67
|
isDisabled?: boolean;
|
|
66
|
-
onPress
|
|
68
|
+
onPress?: () => void;
|
|
67
69
|
tone?: 'primary' | 'destructive';
|
|
68
70
|
}
|
|
69
71
|
export interface PsListContentProps {
|
|
@@ -4,7 +4,7 @@ import { Pressable, View } from 'react-native';
|
|
|
4
4
|
import { PsLayoutConfig } from '../../constants/ps-layout-config';
|
|
5
5
|
import { PsMobileControlConfig } from '../../constants/ps-mobile-control-config';
|
|
6
6
|
import { usePsMobileTheme } from '../../hooks/use-ps-mobile-theme';
|
|
7
|
-
import {
|
|
7
|
+
import { PsListRowStyleService } from '../../services/ps-list-row-style-service';
|
|
8
8
|
import { PsBadge } from '../ps-badge/ps-badge';
|
|
9
9
|
import { PsIcon } from '../ps-icon/ps-icon';
|
|
10
10
|
import { PsText } from '../ps-text/ps-text';
|
|
@@ -15,9 +15,7 @@ export const PsListRowBody = ({ badge, hasChevron = false, hasMenu, isSelectable
|
|
|
15
15
|
const hasSecondLine = subtitle !== undefined || badge !== undefined;
|
|
16
16
|
return (_jsxs(Pressable, { accessibilityRole: onPress === undefined ? undefined : 'button', accessibilityState: isSelectable ? { selected: isSelected } : undefined, delayLongPress: PsLayoutConfig.longPressDelayMs, disabled: !isInteractive, onLongPress: hasMenu ? onLongPress : undefined, onPress: onPress, style: ({ pressed }) => ({
|
|
17
17
|
alignItems: 'center',
|
|
18
|
-
backgroundColor: pressed
|
|
19
|
-
? PsMobileColorService.withAlpha(theme.ink, PsMobileControlConfig.pressedAlpha)
|
|
20
|
-
: theme.surface,
|
|
18
|
+
backgroundColor: PsListRowStyleService.background(isSelectable && isSelected, pressed, theme),
|
|
21
19
|
flexDirection: 'row',
|
|
22
20
|
gap: PsLayoutConfig.headerSlotGap,
|
|
23
21
|
minHeight: hasSecondLine
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { PsListRowProps } from './ps-list-props';
|
|
2
|
-
export declare const PsListRow: ({ actions, badge, hasChevron, isLoading, isSection, isSelectable, isSelected, leadingIcon, leadingSwipe, onPress, skeleton, subtitle, trailingSwipe, title, value, }: PsListRowProps) => import("react").JSX.Element;
|
|
2
|
+
export declare const PsListRow: ({ actions, badge, hasChevron, href, isLoading, isSection, isSelectable, isSelected, leadingIcon, leadingSwipe, onPress, preview, skeleton, subtitle, trailingSwipe, title, value, }: PsListRowProps) => import("react").JSX.Element;
|
|
@@ -2,14 +2,15 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import { View } from 'react-native';
|
|
3
3
|
import { PsListService } from '../../services/ps-list-service';
|
|
4
4
|
import { PsListContextMenu } from './ps-list-context-menu';
|
|
5
|
+
import { PsListLinkMenu } from './ps-list-link-menu';
|
|
5
6
|
import { PsListRowBody } from './ps-list-row-body';
|
|
6
7
|
import { PsListRowSkeleton } from './ps-list-row-skeleton';
|
|
7
8
|
import { PsListSwipeRow } from './ps-list-swipe-row';
|
|
8
|
-
export const PsListRow = ({ actions, badge, hasChevron, isLoading = false, isSection, isSelectable, isSelected, leadingIcon, leadingSwipe, onPress, skeleton, subtitle, trailingSwipe, title, value, }) => {
|
|
9
|
+
export const PsListRow = ({ actions, badge, hasChevron, href, isLoading = false, isSection, isSelectable, isSelected, leadingIcon, leadingSwipe, onPress, preview, skeleton, subtitle, trailingSwipe, title, value, }) => {
|
|
9
10
|
const menuItems = PsListService.menuItems(actions, PsListService.swipes(leadingSwipe, trailingSwipe));
|
|
10
11
|
if (isLoading)
|
|
11
12
|
return (_jsx(PsListRowSkeleton, { badge: badge, isSection: isSection, leadingIcon: leadingIcon, skeleton: skeleton, subtitle: subtitle, value: value }));
|
|
12
13
|
const row = (_jsx(PsListRowBody, { badge: badge, hasChevron: hasChevron, hasMenu: false, isSelectable: isSelectable, isSelected: isSelected, leadingIcon: leadingIcon, onLongPress: () => undefined, onPress: onPress, subtitle: subtitle, title: title, value: value }));
|
|
13
|
-
const body = menuItems.length === 0 ? (row) : (_jsx(PsListContextMenu, { items: menuItems, title: title, children: row }));
|
|
14
|
+
const body = href !== undefined ? (_jsx(PsListLinkMenu, { href: href, items: menuItems, preview: preview, title: title, children: row })) : menuItems.length === 0 ? (row) : (_jsx(PsListContextMenu, { items: menuItems, title: title, children: row }));
|
|
14
15
|
return (_jsx(View, { accessibilityActions: menuItems.map((item) => ({ label: item.label, name: item.id })), onAccessibilityAction: (event) => menuItems.find((item) => item.id === event.nativeEvent.actionName)?.onSelect(), children: leadingSwipe === undefined && trailingSwipe === undefined ? (body) : (_jsx(PsListSwipeRow, { leading: leadingSwipe, trailing: trailingSwipe, children: body })) }));
|
|
15
16
|
};
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
+
import type { PallasoftProductBrand } from '@pallasoft/ps-design-system';
|
|
2
3
|
import type { PsChartPaletteColors } from '../../interfaces/ps-chart-palette-colors';
|
|
3
4
|
import type { PsColorSchemeChoice } from '../../interfaces/ps-color-scheme-choice';
|
|
4
5
|
export interface PsMobileThemeProviderProps {
|
|
@@ -7,7 +8,8 @@ export interface PsMobileThemeProviderProps {
|
|
|
7
8
|
colorScheme?: PsColorSchemeChoice;
|
|
8
9
|
hasHaptics?: boolean;
|
|
9
10
|
isReduceMotion?: boolean;
|
|
10
|
-
primaryColor
|
|
11
|
-
primaryContrastColor
|
|
11
|
+
primaryColor?: string;
|
|
12
|
+
primaryContrastColor?: string;
|
|
13
|
+
product?: PallasoftProductBrand;
|
|
12
14
|
secondaryColor?: string;
|
|
13
15
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { PsMobileThemeProviderProps } from './ps-mobile-theme-provider-props';
|
|
2
|
-
export declare const PsMobileThemeProvider: ({ chartPalette, children, colorScheme, hasHaptics, isReduceMotion, primaryColor, primaryContrastColor, secondaryColor, }: PsMobileThemeProviderProps) => import("react").JSX.Element;
|
|
2
|
+
export declare const PsMobileThemeProvider: ({ chartPalette, children, colorScheme, hasHaptics, isReduceMotion, primaryColor, primaryContrastColor, product, secondaryColor, }: PsMobileThemeProviderProps) => import("react").JSX.Element;
|
|
@@ -3,29 +3,39 @@ import { useMemo } from 'react';
|
|
|
3
3
|
import { useColorScheme } from 'react-native';
|
|
4
4
|
import { useReducedMotion } from 'react-native-reanimated';
|
|
5
5
|
import { PsMobileThemeContext } from '../../contexts/ps-mobile-theme-context';
|
|
6
|
+
import { PsMobileBrandService } from '../../services/ps-mobile-brand-service';
|
|
6
7
|
import { PsMobileThemeService } from '../../services/ps-mobile-theme-service';
|
|
7
|
-
export const PsMobileThemeProvider = ({ chartPalette, children, colorScheme, hasHaptics, isReduceMotion, primaryColor, primaryContrastColor, secondaryColor, }) => {
|
|
8
|
+
export const PsMobileThemeProvider = ({ chartPalette, children, colorScheme, hasHaptics, isReduceMotion, primaryColor, primaryContrastColor, product, secondaryColor, }) => {
|
|
8
9
|
const scheme = useColorScheme();
|
|
9
10
|
const isSystemReduced = useReducedMotion();
|
|
10
11
|
const isDark = colorScheme === undefined || colorScheme === 'system'
|
|
11
12
|
? scheme === 'dark'
|
|
12
13
|
: colorScheme === 'dark';
|
|
13
14
|
const isReduced = isSystemReduced || isReduceMotion === true;
|
|
14
|
-
const theme = useMemo(() =>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
const theme = useMemo(() => {
|
|
16
|
+
const brand = PsMobileBrandService.resolve({
|
|
17
|
+
primaryColor,
|
|
18
|
+
primaryContrastColor,
|
|
19
|
+
product,
|
|
20
|
+
secondaryColor,
|
|
21
|
+
});
|
|
22
|
+
return PsMobileThemeService.create({
|
|
23
|
+
chart: chartPalette === undefined ? undefined : isDark ? chartPalette.dark : chartPalette.light,
|
|
24
|
+
hasHaptics,
|
|
25
|
+
isDark,
|
|
26
|
+
isReduceMotion: isReduced,
|
|
27
|
+
primary: brand.primary,
|
|
28
|
+
primaryContrast: brand.primaryContrast,
|
|
29
|
+
secondary: brand.secondary,
|
|
30
|
+
});
|
|
31
|
+
}, [
|
|
23
32
|
chartPalette,
|
|
24
33
|
hasHaptics,
|
|
25
34
|
isDark,
|
|
26
35
|
isReduced,
|
|
27
36
|
primaryColor,
|
|
28
37
|
primaryContrastColor,
|
|
38
|
+
product,
|
|
29
39
|
secondaryColor,
|
|
30
40
|
]);
|
|
31
41
|
return _jsx(PsMobileThemeContext.Provider, { value: theme, children: children });
|
|
@@ -11,7 +11,7 @@ export const PsNativeMenu = ({ children, isDisabled = false, isFullWidth = false
|
|
|
11
11
|
const theme = usePsMobileTheme();
|
|
12
12
|
const [isOpen, setIsOpen] = useState(false);
|
|
13
13
|
const matchContents = isFullWidth ? { vertical: true } : true;
|
|
14
|
-
return (_jsx(PsHostScope, { matchContents: matchContents, children: _jsxs(DropdownMenu, { color: theme.surface, expanded: isOpen, modifiers: isFullWidth ? [fillMaxWidth()] : [], onDismissRequest: () => setIsOpen(false), children: [_jsx(DropdownMenu.Items, { children: items.map((item) => (_jsx(DropdownMenuItem, { elementColors: { textColor: item.isSelected ? theme.
|
|
14
|
+
return (_jsx(PsHostScope, { matchContents: matchContents, children: _jsxs(DropdownMenu, { color: theme.surface, expanded: isOpen, modifiers: isFullWidth ? [fillMaxWidth()] : [], onDismissRequest: () => setIsOpen(false), children: [_jsx(DropdownMenu.Items, { children: items.map((item) => (_jsx(DropdownMenuItem, { elementColors: { textColor: item.isSelected ? theme.primaryText : theme.ink }, onClick: () => {
|
|
15
15
|
setIsOpen(false);
|
|
16
16
|
haptic('selection');
|
|
17
17
|
onSelect(item.value);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface PsOptionPickerOption {
|
|
2
|
+
label: string;
|
|
3
|
+
subtitle?: string;
|
|
4
|
+
value: string;
|
|
5
|
+
}
|
|
6
|
+
export interface PsOptionPickerProps {
|
|
7
|
+
emptyLabel: string;
|
|
8
|
+
limit?: number;
|
|
9
|
+
moreLabel: string;
|
|
10
|
+
onSearchChange?: (search: string) => void;
|
|
11
|
+
onSelect: (value: string) => void;
|
|
12
|
+
options: PsOptionPickerOption[];
|
|
13
|
+
searchClearLabel: string;
|
|
14
|
+
searchPlaceholder: string;
|
|
15
|
+
selectedValue: string;
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import type { PsOptionPickerProps } from './ps-option-picker-props';
|
|
2
|
+
export declare const PsOptionPicker: ({ emptyLabel, limit, moreLabel, onSearchChange, onSelect, options, searchClearLabel, searchPlaceholder, selectedValue, }: PsOptionPickerProps) => import("react").JSX.Element;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, useState } from 'react';
|
|
3
|
+
import { PsIconKey } from '@pallasoft/ps-icons';
|
|
4
|
+
import { Pressable, View } from 'react-native';
|
|
5
|
+
import { PsOptionPickerConfig } from '../../constants/ps-option-picker-config';
|
|
6
|
+
import { usePsHaptics } from '../../hooks/use-ps-haptics';
|
|
7
|
+
import { usePsMobileTheme } from '../../hooks/use-ps-mobile-theme';
|
|
8
|
+
import { PsOptionPickerService } from '../../services/ps-option-picker-service';
|
|
9
|
+
import { PsCard } from '../ps-card/ps-card';
|
|
10
|
+
import { PsIcon } from '../ps-icon/ps-icon';
|
|
11
|
+
import { PsSearchField } from '../ps-search-field/ps-search-field';
|
|
12
|
+
import { PsText } from '../ps-text/ps-text';
|
|
13
|
+
export const PsOptionPicker = ({ emptyLabel, limit = PsOptionPickerConfig.defaultLimit, moreLabel, onSearchChange, onSelect, options, searchClearLabel, searchPlaceholder, selectedValue, }) => {
|
|
14
|
+
const theme = usePsMobileTheme();
|
|
15
|
+
const haptic = usePsHaptics();
|
|
16
|
+
const [search, setSearch] = useState('');
|
|
17
|
+
const result = useMemo(() => PsOptionPickerService.visible(options, onSearchChange === undefined ? search : '', limit), [limit, onSearchChange, options, search]);
|
|
18
|
+
return (_jsxs(View, { style: { gap: PsOptionPickerConfig.gap }, children: [_jsx(PsSearchField, { clearLabel: searchClearLabel, onChange: (next) => {
|
|
19
|
+
setSearch(next);
|
|
20
|
+
if (onSearchChange !== undefined)
|
|
21
|
+
onSearchChange(next);
|
|
22
|
+
}, placeholder: searchPlaceholder, value: search }), result.options.length === 0 ? (_jsx(PsText, { tone: 'muted', children: emptyLabel })) : (_jsx(PsCard, { padding: 'none', children: result.options.map((option, index) => (_jsxs(Pressable, { accessibilityRole: 'button', accessibilityState: { selected: option.value === selectedValue }, onPress: () => {
|
|
23
|
+
haptic('selection');
|
|
24
|
+
onSelect(option.value);
|
|
25
|
+
}, style: {
|
|
26
|
+
alignItems: 'center',
|
|
27
|
+
borderTopColor: theme.line,
|
|
28
|
+
borderTopWidth: index === 0 ? 0 : 1,
|
|
29
|
+
flexDirection: 'row',
|
|
30
|
+
gap: PsOptionPickerConfig.gap,
|
|
31
|
+
padding: PsOptionPickerConfig.rowPadding,
|
|
32
|
+
}, children: [_jsxs(View, { style: { flex: 1, gap: PsOptionPickerConfig.rowGap }, children: [_jsx(PsText, { numberOfLines: 1, weight: 'semibold', children: option.label }), option.subtitle === undefined ? null : (_jsx(PsText, { numberOfLines: 1, tone: 'muted', variant: 'caption', children: option.subtitle }))] }), option.value === selectedValue ? (_jsx(PsIcon, { color: theme.primary, iconKey: PsIconKey.Check })) : null] }, option.value))) })), result.hasMore ? (_jsx(PsText, { tone: 'muted', variant: 'caption', children: moreLabel })) : null] }));
|
|
33
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { PallasoftZIndex } from '@pallasoft/ps-design-system';
|
|
3
|
+
import { StyleSheet, View } from 'react-native';
|
|
4
|
+
import { usePsMobileTheme } from '../../hooks/use-ps-mobile-theme';
|
|
5
|
+
import { PsPageBackdrop } from '../ps-page-backdrop/ps-page-backdrop';
|
|
6
|
+
export const PsPrivacyCover = ({ children }) => {
|
|
7
|
+
const theme = usePsMobileTheme();
|
|
8
|
+
return (_jsxs(View, { accessibilityViewIsModal: true, style: [
|
|
9
|
+
StyleSheet.absoluteFill,
|
|
10
|
+
{
|
|
11
|
+
alignItems: 'center',
|
|
12
|
+
backgroundColor: theme.background,
|
|
13
|
+
justifyContent: 'center',
|
|
14
|
+
zIndex: PallasoftZIndex.TopLayer,
|
|
15
|
+
},
|
|
16
|
+
], testID: 'ps-privacy-cover', children: [_jsx(PsPageBackdrop, {}), children] }));
|
|
17
|
+
};
|