1 import { type ComponentType, type ElementType, type FC, type MouseEvent, type ReactNode, useCallback } from 'react';
3 import { c } from 'ttag';
5 import { Button } from '@proton/atoms';
6 import { Icon } from '@proton/components';
7 import { useSpotlight } from '@proton/pass/components/Spotlight/SpotlightProvider';
8 import { SpotlightMessage } from '@proton/pass/types';
9 import { pipe } from '@proton/pass/utils/fp/pipe';
10 import clsx from '@proton/utils/clsx';
12 import './SpotlightContent.scss';
14 export type BaseSpotlightMessage = {
18 type: SpotlightMessage;
23 export type DefaultSplotlightMessage = BaseSpotlightMessage & {
25 action?: { label: string; onClick: (e: MouseEvent<HTMLElement>) => void; type: 'link' | 'button' };
32 export type CustomSplotlightMessage = BaseSpotlightMessage & {
34 component: ComponentType<BaseSpotlightMessage>;
37 export type SpotlightMessageDefinition = DefaultSplotlightMessage | CustomSplotlightMessage;
39 export const SpotlightContent: FC<SpotlightMessageDefinition> = (props) => {
40 const { acknowledge } = useSpotlight();
42 const onClose = useCallback(() => {
43 if (props.type !== SpotlightMessage.NOOP) acknowledge(props.type);
51 props.mode === 'default' && props.weak && 'weak',
52 `pass-spotlight-content flex items-center gap-4 p-4 pr-6 rounded relative mt-2`
61 className="absolute top-0 right-0"
64 <Icon name="cross-circle-filled" color="var(--interaction-norm-contrast)" alt={c('Action').t`Close`} />
70 const { component, ...rest } = props;
71 const Component = component;
72 return <Component {...rest} onClose={onClose} />;
76 const { action, dense, icon: CustomIcon, message, title, weak } = props;
78 const actionNode = (() => {
79 switch (action?.type) {
83 onClick={pipe(action.onClick, onClose)}
84 className="unstyled text-sm color-invert px-3"
86 <span className="text-underline">{action.label}</span>
96 className="text-sm px-3"
97 onClick={pipe(action.onClick, onClose)}
98 style={{ backgroundColor: 'var(--interaction-norm-major-3)' }}
108 <div className="flex-1">
109 <strong className={clsx('block', !weak && 'color-invert')}>{title}</strong>
110 <span className={clsx('block text-sm', !weak && 'color-invert')}>{message}</span>
111 {!dense && <div className="mt-2">{actionNode}</div>}
115 <div {...(dense ? { style: { order: -1 } } : { className: 'mr-2' })}>
120 {dense && actionNode}