1 import { type FC, useMemo } from 'react';
2 import { useSelector } from 'react-redux';
4 import { c } from 'ttag';
6 import { Icon, Option } from '@proton/components';
7 import type { VaultIconName } from '@proton/pass/components/Vault/VaultIcon';
8 import { VaultIcon } from '@proton/pass/components/Vault/VaultIcon';
9 import type { ShareItem } from '@proton/pass/store/reducers';
10 import { selectWritableVaults } from '@proton/pass/store/selectors';
11 import type { Maybe, ShareType } from '@proton/pass/types';
12 import { VaultColor } from '@proton/pass/types/protobuf/vault-v1';
13 import clsx from '@proton/utils/clsx';
15 import { VAULT_COLOR_MAP } from '../../Vault/constants';
16 import { SelectField, type SelectFieldProps } from './SelectField';
18 import './VaultPickerField.scss';
20 type VaultPickerSelection = { title: string; icon?: VaultIconName; color?: VaultColor };
21 type VaultPickerFieldProps = Omit<SelectFieldProps, 'children'> & { legacy?: boolean };
22 type VaultPickerProps = VaultPickerFieldProps & { vaults: ShareItem<ShareType.Vault>[] };
24 export const VaultPicker: FC<VaultPickerProps> = ({ legacy, vaults, ...props }) => {
25 const selectedId = props.field.value;
27 const selectedVault = useMemo<Maybe<VaultPickerSelection>>(() => {
28 const vaultMatch = vaults.find(({ shareId }) => shareId === selectedId);
32 title: vaultMatch?.content.name,
33 icon: vaultMatch?.content.display.icon,
34 color: vaultMatch?.content.display.color,
37 }, [selectedId, vaults]);
40 <div style={{ '--vault-item-color': VAULT_COLOR_MAP[selectedVault?.color ?? VaultColor.COLOR1] }}>
44 className={clsx('pass-vault-picker', legacy && 'pass-vault-picker--legacy', props.className)}
45 selectClassName={clsx(!legacy && 'button button-pill button-medium button-solid-norm')}
46 renderSelected={() => (
47 <div className="flex flex-nowrap gap-2 justify-items-center items-center">
49 icon={selectedVault?.icon}
50 color={selectedVault?.color ?? VaultColor.COLOR1}
54 <span className="text-sm text-ellipsis">
55 {selectedVault?.title ?? c('Placeholder').t`Pick a vault`}
60 {vaults.map(({ content, shared, shareId }: ShareItem<ShareType.Vault>) => {
61 const selected = selectedId === shareId;
64 <Option key={shareId} value={shareId} title={content.name}>
65 <div className="flex gap-x-3 items-center">
67 icon={content.display.icon}
68 color={content.display.color}
70 highlighted={selected}
72 <span className="flex-1 text-ellipsis">{content.name}</span>
76 color={`var(${selected ? '--interaction-norm-contrast' : '--text-weak'})`}
89 export const VaultPickerField: FC<VaultPickerFieldProps> = (props) => {
90 const vaults = useSelector(selectWritableVaults);
91 return <VaultPicker vaults={vaults} {...props} />;