/* eslint-disable react/prop-types */ import React, { useCallback, useMemo } from 'react'; import { Card, css, Icon, spacing, Subtitle, useHoverState, Badge, Tooltip, cx, useFocusState, FocusState, palette, mergeProps, useDefaultAction, ItemActionControls, useDarkMode, } from '@mongodb-js/compass-components'; import type { BadgeVariant, IconGlyph, ItemAction, SignalPopover, } from '@mongodb-js/compass-components'; import { NamespaceParam } from './namespace-param'; import type { ItemType } from './use-create'; import type { ViewType } from './use-view-type'; import { usePreference } from 'compass-preferences-model'; const cardTitleGroup = css({ display: 'flex', alignItems: 'center', gap: spacing[3], marginBottom: spacing[2], }); const CardTitleGroup: React.FunctionComponent = ({ children }) => { return
{children}
; }; const cardNameWrapper = css({ // Workaround for uncollapsible text in flex children minWidth: 0, }); const cardNameDark = css({ color: palette.green.light2, }); const cardNameLight = css({ color: palette.green.dark2, }); const cardName = css({ overflow: 'hidden', whiteSpace: 'nowrap', textOverflow: 'ellipsis', // To make container 28px to match leafygreen buttons paddingTop: 2, paddingBottom: 2, // TS is very confused if fontWeight is not a number even though it's a valid // CSS value fontWeight: '600 !important' as unknown as number, }); const CardName: React.FunctionComponent<{ children: string }> = ({ children, }) => { const darkMode = useDarkMode(); return (
{children}
); }; const cardActionContainer = css({ marginLeft: 'auto', flex: 'none', }); const cardBadges = css({ display: 'flex', gap: spacing[2], // Preserving space for when cards with and without badges are mixed in a // single row minHeight: 20, }); const CardBadges: React.FunctionComponent = ({ children }) => { return
{children}
; }; const cardBadge = css({ gap: spacing[1], }); const cardBadgeLabel = css({}); export type BadgeProp = { id: string; name: string; variant?: BadgeVariant; icon?: IconGlyph; hint?: React.ReactNode; }; const CardBadge: React.FunctionComponent = ({ id, name, icon, variant, hint, }) => { const badge = useCallback( ({ className, children, ...props } = {}) => { return ( {icon && } {name} {/* Tooltip will be rendered here */} {children} ); }, [id, icon, name, variant] ); if (hint) { return ( {hint} ); } return badge(); }; const card = css({ padding: spacing[3], }); export type DataProp = { label: React.ReactNode; value: React.ReactNode; hint?: React.ReactNode; insights?: React.ComponentProps['signals']; }; export type NamespaceItemCardProps = { id: string; type: ItemType; viewType: ViewType; name: string; status: 'initial' | 'fetching' | 'refreshing' | 'ready' | 'error'; data: DataProp[]; badges?: BadgeProp[] | null; onItemClick(id: string): void; onItemDeleteClick?: (id: string) => void; }; const namespaceDataGroup = css({ display: 'flex', gap: spacing[2], marginTop: spacing[3], }); const column = css({ flexDirection: 'column', }); type NamespaceAction = 'delete'; export const NamespaceItemCard: React.FunctionComponent< NamespaceItemCardProps & Omit< React.HTMLProps, Extract > > = ({ id, type, name, status, data, onItemClick, onItemDeleteClick, badges = null, viewType, ...props }) => { const readOnly = usePreference('readOnly', React); const [hoverProps, isHovered] = useHoverState(); const [focusProps, focusState] = useFocusState(); const onDefaultAction = useCallback(() => { onItemClick(id); }, [onItemClick, id]); const hasDeleteHandler = !!onItemDeleteClick; const cardActions: ItemAction[] = useMemo(() => { return readOnly || !hasDeleteHandler ? [] : [ { action: 'delete', label: `Delete ${type}`, icon: 'Trash', }, ]; }, [type, readOnly, hasDeleteHandler]); const defaultActionProps = useDefaultAction(onDefaultAction); const onAction = useCallback( (action: NamespaceAction) => { if (action === 'delete') { onItemDeleteClick?.(id); } }, [onItemDeleteClick, id] ); const badgesGroup = badges && ( {badges.map((badge) => { return ; })} ); const cardProps = mergeProps( { className: card }, defaultActionProps, hoverProps, focusProps, props ); const isButtonVisible = [FocusState.FocusVisible, FocusState.FocusWithinVisible].includes( focusState ) || isHovered; return ( // @ts-expect-error the error here is caused by passing children to Card // component, even though it's allowed on the implementation level the types // are super confused and don't allow that {name} {viewType === 'list' && badgesGroup} 0} actions={cardActions} onAction={onAction} className={cardActionContainer} > {viewType === 'grid' && badgesGroup}
{data.map(({ label, value, hint, insights }, idx) => { return ( ); })}
); };