import React, { useEffect, useRef, useState } from 'react'; import { Link } from '@teambit/base-react.navigation.link'; import { PreviewPlaceholder } from '@teambit/preview.ui.preview-placeholder'; import { Tooltip } from '@teambit/design.ui.tooltip'; import { LoadPreview } from '@teambit/workspace.ui.load-preview'; import { ComponentID } from '@teambit/component-id'; import type { ComponentModel } from '@teambit/component'; import type { ComponentDescriptor } from '@teambit/component-descriptor'; import type { ScopeID } from '@teambit/scopes.scope-id'; import { getComponentStatus } from './filter-utils'; import { ChangedPill, BuildSpinner, BuildingPreview } from './card-overlays'; import styles from './hope-component-card.module.scss'; export type HopeComponentCardProps = { component: ComponentModel; componentDescriptor: ComponentDescriptor; scope?: { id: ScopeID; icon?: string; backgroundIconColor?: string }; showPreview?: boolean; }; export function HopeComponentCard({ component, componentDescriptor, scope, showPreview: showPreviewProp, }: HopeComponentCardProps) { const [shouldShowPreview, setShouldShowPreview] = useState(Boolean(showPreviewProp)); const prevServerUrlRef = useRef(component.server?.url); useEffect(() => { if (prevServerUrlRef.current !== component.server?.url && shouldShowPreview) { setShouldShowPreview(false); setTimeout(() => setShouldShowPreview(true), 50); } prevServerUrlRef.current = component.server?.url; }, [component.server?.url]); useEffect(() => { setShouldShowPreview(Boolean(showPreviewProp)); }, [showPreviewProp]); const item = { component } as any; const status = getComponentStatus(item); const accent = 'var(--bit-accent-color, #6c5ce7)'; const isBuilding = status === 'building'; const isQueued = status === 'queued'; const isChanged = status === 'changed'; const href = `${component.id.fullName}?scope=${component.id.scope}`; const loadPreviewVisible = component.compositions.length > 0 && !isBuilding && !shouldShowPreview; const showPreviewClick = (e: React.MouseEvent) => { e.stopPropagation(); e.preventDefault(); setShouldShowPreview(true); }; const envAspect = componentDescriptor.get('teambit.envs/envs'); const env = envAspect?.data || envAspect; const envComponentId = env?.id ? ComponentID.fromString(env.id) : undefined; const cardClass = isBuilding ? styles.cardBuilding : styles.card; const buildingBorderStyle = isBuilding ? { borderColor: accent, boxShadow: `0 0 0 3px color-mix(in srgb, var(--bit-accent-color, #6c5ce7) 10%, transparent)`, } : undefined; const nameLabel = component.id.namespace ? `${component.id.namespace}/${component.id.name}` : component.id.name; const shortHash = component.id.version?.slice(0, 7); const scopeInitial = component.id.scope?.split('.').pop()?.charAt(0).toUpperCase(); return (
{loadPreviewVisible && }
{!isQueued && env?.icon && (
)} {(isChanged || isBuilding) && (
{isChanged && } {isBuilding && }
)}
{scope?.icon ? ( ) : ( {scopeInitial} )}
{nameLabel} {!isBuilding && !isQueued && shortHash && {shortHash}} {isBuilding && ( BUILDING )}
); } function CardPreview({ component, componentDescriptor, status, shouldShowPreview, }: { component: ComponentModel; componentDescriptor: ComponentDescriptor; status: string; shouldShowPreview: boolean; }) { if (status === 'building') return ; return ( ); }