import { DiagramEdge, DiagramNode, DynamicViewDisplayVariant, LayoutedView, LayoutType, WhereOperator } from '@likec4/core/types'; import { ReactFlowProps } from '@xyflow/react'; import { MouseEvent as ReactMouseEvent, ReactNode } from 'react'; import { CamelCasedProperties, SetRequired } from 'type-fest'; import { DiagramApi } from './hooks/useDiagram'; import { XYFlowInstance } from './hooks/useXYFlow'; import { Types } from './likec4diagram/types'; import type * as t from '@likec4/core/types'; type Any = t.aux.Any; type Unknown = t.aux.UnknownLayouted; type ViewId = t.aux.ViewId; type Fqn = t.aux.Fqn; type RelationId = t.aux.RelationId; type DeploymentFqn = t.aux.DeploymentFqn; type StrictViewId = t.aux.StrictViewId; export type NodeRenderers = Partial>; export type { WhereOperator }; export type DiagramNodeWithNavigate = SetRequired, 'navigateTo'>; export type ElementIconRendererProps = { node: { id: string; title: string; icon?: string | null | undefined; }; className?: string; }; export type ElementIconRenderer = (props: ElementIconRendererProps) => ReactNode; export type LikeC4ColorScheme = 'light' | 'dark'; export type OverrideReactFlowProps = Pick, 'paneClickDistance' | 'nodeClickDistance' | 'selectionKeyCode' | 'panActivationKeyCode' | 'multiSelectionKeyCode' | 'zoomActivationKeyCode' | 'snapToGrid' | 'snapGrid' | 'onlyRenderVisibleElements' | 'nodesDraggable' | 'nodesFocusable' | 'elementsSelectable' | 'selectNodesOnDrag' | 'panOnDrag' | 'preventScrolling' | 'zoomOnScroll' | 'zoomOnPinch' | 'panOnScroll' | 'panOnScrollSpeed' | 'panOnScrollMode' | 'zoomOnDoubleClick' | 'nodeDragThreshold'>; export type PaddingUnit = 'px' | '%'; export type PaddingWithUnit = `${number}${PaddingUnit}` | number; export type ViewPaddings = { top?: PaddingWithUnit; right?: PaddingWithUnit; bottom?: PaddingWithUnit; left?: PaddingWithUnit; x?: PaddingWithUnit; y?: PaddingWithUnit; }; /** * Padding around the diagram * * @example * { * top: '8px', * right: '8px', * bottom: '8px', * left: '8px', * } * * { * x: '16px', * y: '16px', * } */ export type ViewPadding = PaddingWithUnit | ViewPaddings; export interface LikeC4DiagramProperties { view: LayoutedView; className?: string | undefined; /** * Enable/disable panning * @default true */ pannable?: boolean | undefined; /** * Enable/disable zooming * @default true */ zoomable?: boolean | undefined; /** * Show/hide panel with top left controls * * @default true */ controls?: boolean | undefined; /** * If set, initial viewport will show all nodes & edges * @default true */ fitView?: boolean | undefined; /** * Padding around the diagram (number - pixels) * @default 16 - 16px * * @see {@link ViewPadding} * * @example * ```tsx * * * * ``` */ fitViewPadding?: ViewPadding | undefined; /** * If not readonly, or `enableFocusMode`, `onNavigateTo` or `onNodeClick` are set - nodes will be selectable * * @default false */ nodesSelectable?: boolean | undefined; /** * Initial width of the diagram * (supposed to be used during SSR) */ initialWidth?: number | undefined; /** * Initial height of the diagram * (supposed to be used during SSR) */ initialHeight?: number | undefined; /** * Background pattern * @default 'dots' */ background?: 'transparent' | 'solid' | 'dots' | 'lines' | 'cross' | undefined; /** * Show back/forward history navigation buttons * @default true if `onNavigateTo` is set */ showNavigationButtons?: undefined | boolean; /** * Display notations in the bottom right corner * (Active if only notations are present) * * @default false */ enableNotations?: boolean | undefined; /** * Display dropdown with details on relationship's label click * @default false */ enableRelationshipDetails?: boolean | undefined; /** * If double click on a node should enable focus mode, i.e. highlight incoming/outgoing edges * @default false */ enableFocusMode?: boolean | undefined; /** * Enable search popup for elements and views * @default true */ enableSearch?: boolean | undefined; /** * Enable modal with element details * @default false */ enableElementDetails?: boolean | undefined; /** * Experimental feature to browse relationships * * @default false */ enableRelationshipBrowser?: boolean | undefined; /** * If Walkthrough for dynamic views should be enabled * @default false */ enableDynamicViewWalkthrough?: boolean | undefined; /** * Enable "Compare with auto layout" action when view was manually modified and out of sync with latest model * @default true if `onLayoutTypeChange` is set, false otherwise */ enableCompareWithLatest?: boolean | undefined; /** * Default dynamic view display variant * @default 'diagram' */ dynamicViewVariant?: DynamicViewDisplayVariant | undefined; /** * Display element tags in the bottom left corner * @default false */ enableElementTags?: boolean | undefined; /** * Display element notes, if they are present in the view * * @default true */ enableNotes?: boolean | undefined; /** * Improve performance by hiding certain elements and reducing visual effects (disable mix-blend, shadows, animations) * Enable it if you have a large or static view * - `auto` - will be `true` if view has more then 3000 * 2000 pixels * * @default 'auto' */ reduceGraphics?: 'auto' | boolean | undefined; /** * Render icon for an element, bundled or remote * By default, if icon is http:// or https://, it will be rendered as an image * * Consider using `IconRendererProvider` */ renderIcon?: ElementIconRenderer | undefined; /** * Override node renderers */ renderNodes?: NodeRenderers | undefined; /** * Dynamic filter, applies both to nodes and edges */ where?: WhereOperator | undefined; /** * Override ReactFlow props */ reactFlowProps?: OverrideReactFlowProps | undefined; } export type OpenSourceParams = { element: Fqn; property?: string; } | { relation: RelationId; } | { deployment: DeploymentFqn; property?: string; } | { view: StrictViewId; } | { view: StrictViewId; astPath: string; }; /** * "Go to source" action */ export type OnOpenSource = (params: OpenSourceParams) => void; export type OnNavigateTo = (to: ViewId, event?: ReactMouseEvent, element?: DiagramNodeWithNavigate) => void; export type OnNodeClick = (node: DiagramNode, event: ReactMouseEvent) => void; export type OnEdgeClick = (edge: DiagramEdge, event: ReactMouseEvent) => void; /** * On pane/canvas click (not on any node or edge) */ export type OnCanvasClick = (event: ReactMouseEvent) => void; export type OnCanvasContextMenu = (event: ReactMouseEvent) => void; export type OnInitialized = (params: { diagram: DiagramApi; xyflow: XYFlowInstance; }) => void; export type OnLayoutTypeChange = (layoutType: LayoutType) => void; export interface LikeC4DiagramEventHandlers { onNavigateTo?: OnNavigateTo | null | undefined; onNodeClick?: OnNodeClick | null | undefined; onNodeContextMenu?: OnNodeClick | null | undefined; onCanvasContextMenu?: OnCanvasContextMenu | null | undefined; onEdgeClick?: OnEdgeClick | null | undefined; onEdgeContextMenu?: OnEdgeClick | null | undefined; onCanvasClick?: OnCanvasClick | null | undefined; onCanvasDblClick?: OnCanvasClick | null | undefined; onLogoClick?: null | undefined | (() => void); onOpenSource?: OnOpenSource | null | undefined; onInitialized?: OnInitialized | null | undefined; /** * Triggered when user changes layout type (e.g. from 'manual' to 'auto') * Expected another `view` to be passed to the diagram * * @param layoutType new layout type */ onLayoutTypeChange?: OnLayoutTypeChange | null | undefined; }