diff --git a/packages/react/src/additional-components/Controls/ControlButton.tsx b/packages/react/src/additional-components/Controls/ControlButton.tsx index 744f46d4..12c58663 100644 --- a/packages/react/src/additional-components/Controls/ControlButton.tsx +++ b/packages/react/src/additional-components/Controls/ControlButton.tsx @@ -2,6 +2,29 @@ import cc from 'classcat'; import type { ControlButtonProps } from './types'; +/** + * You can add buttons to the control panel by using the `` component + *and pass it as a child to the [``](/api-reference/components/controls) component. + * + * @public + * @example + *```jsx + *import { MagicWand } from '@radix-ui/react-icons' + *import { ReactFlow, Controls, ControlButton } from '@xyflow/react' + * + *export default function Flow() { + * return ( + * + * + * alert('Something magical just happened. ✨')}> + * + * + * + * + * ) + *} + *``` + */ export function ControlButton({ children, className, ...rest }: ControlButtonProps) { return ( diff --git a/packages/react/src/additional-components/Controls/Controls.tsx b/packages/react/src/additional-components/Controls/Controls.tsx index e08c9ca2..1b0beae3 100644 --- a/packages/react/src/additional-components/Controls/Controls.tsx +++ b/packages/react/src/additional-components/Controls/Controls.tsx @@ -125,4 +125,26 @@ function ControlsComponent({ ControlsComponent.displayName = 'Controls'; +/** + * The `` component renders a small panel that contains convenient + *buttons to zoom in, zoom out, fit the view, and lock the viewport. + * + * @public + * @example + *```tsx + *import { ReactFlow, Controls } from '@xyflow/react' + * + *export default function Flow() { + * return ( + * + * + * + * ) + *} + *``` + * + * @remarks To extend or customise the controls, you can use the [``](/api-reference/components/control-button) + *component + * + */ export const Controls = memo(ControlsComponent); diff --git a/packages/react/src/additional-components/MiniMap/MiniMap.tsx b/packages/react/src/additional-components/MiniMap/MiniMap.tsx index 2f749395..c5e8d719 100644 --- a/packages/react/src/additional-components/MiniMap/MiniMap.tsx +++ b/packages/react/src/additional-components/MiniMap/MiniMap.tsx @@ -178,4 +178,24 @@ function MiniMapComponent({ MiniMapComponent.displayName = 'MiniMap'; +/** + * The `` component can be used to render an overview of your flow. It + *renders each node as an SVG element and visualizes where the current viewport is + *in relation to the rest of the flow. + * + * @public + * @example + * + * ```jsx + *import { ReactFlow, MiniMap } from '@xyflow/react'; + * + *export default function Flow() { + * return ( + * + * + * + * ); + *} + *``` + */ export const MiniMap = memo(MiniMapComponent) as typeof MiniMapComponent; diff --git a/packages/react/src/additional-components/NodeResizer/NodeResizeControl.tsx b/packages/react/src/additional-components/NodeResizer/NodeResizeControl.tsx index aeb9d77f..8a2faea7 100644 --- a/packages/react/src/additional-components/NodeResizer/NodeResizeControl.tsx +++ b/packages/react/src/additional-components/NodeResizer/NodeResizeControl.tsx @@ -203,4 +203,9 @@ export function ResizeControlLine(props: ResizeControlLineProps) { return ; } +/** + * To create your own resizing UI, you can use the `NodeResizeControl` component where you can pass children (such as icons). + * @public + * + */ export const NodeResizeControl = memo(ResizeControl); diff --git a/packages/react/src/additional-components/NodeResizer/NodeResizer.tsx b/packages/react/src/additional-components/NodeResizer/NodeResizer.tsx index 6f481865..f3e6cf8a 100644 --- a/packages/react/src/additional-components/NodeResizer/NodeResizer.tsx +++ b/packages/react/src/additional-components/NodeResizer/NodeResizer.tsx @@ -3,6 +3,30 @@ import { ResizeControlVariant, XY_RESIZER_HANDLE_POSITIONS, XY_RESIZER_LINE_POSI import { NodeResizeControl } from './NodeResizeControl'; import type { NodeResizerProps } from './types'; +/** + * The `` component can be used to add a resize functionality to your + *nodes. It renders draggable controls around the node to resize in all directions. + * @public + * + * @example + *```jsx + *import { memo } from 'react'; + *import { Handle, Position, NodeResizer } from '@xyflow/react'; + * + *function ResizableNode({ data }) { + * return ( + * <> + * + * + * {data.label} + * + * > + * ); + *}; + * + *export default memo(ResizableNode); + *``` + */ export function NodeResizer({ nodeId, isVisible = true, diff --git a/packages/react/src/additional-components/NodeToolbar/NodeToolbar.tsx b/packages/react/src/additional-components/NodeToolbar/NodeToolbar.tsx index b4431157..4e486425 100644 --- a/packages/react/src/additional-components/NodeToolbar/NodeToolbar.tsx +++ b/packages/react/src/additional-components/NodeToolbar/NodeToolbar.tsx @@ -38,6 +38,42 @@ const storeSelector = (state: ReactFlowState) => ({ selectedNodesCount: state.nodes.filter((node) => node.selected).length, }); +/** + * This component can render a toolbar or tooltip to one side of a custom node. This + *toolbar doesn't scale with the viewport so that the content is always visible. + * + * @public + * @example + * ```jsx + *import { memo } from 'react'; + *import { Handle, Position, NodeToolbar } from '@xyflow/react'; + * + *function CustomNode({ data }) { + * return ( + * <> + * + * delete + * copy + * expand + * + * + * + * {data.label} + * + * + * + * + * > + * ); + *}; + * + *export default memo(CustomNode); + *``` + * @remarks By default, the toolbar is only visible when a node is selected. If multiple + *nodes are selected it will not be visible to prevent overlapping toolbars or + *clutter. You can override this behavior by setting the `isVisible` prop to + *`true`. + */ export function NodeToolbar({ nodeId, children, diff --git a/packages/react/src/components/EdgeLabelRenderer/index.tsx b/packages/react/src/components/EdgeLabelRenderer/index.tsx index c66b70ae..b3aa1a91 100644 --- a/packages/react/src/components/EdgeLabelRenderer/index.tsx +++ b/packages/react/src/components/EdgeLabelRenderer/index.tsx @@ -6,6 +6,47 @@ import type { ReactFlowState } from '../../types'; const selector = (s: ReactFlowState) => s.domNode?.querySelector('.react-flow__edgelabel-renderer'); +/** + * Edges are SVG-based. If you want to render more complex labels you can use the + *`` component to access a div based renderer. This component + *is a portal that renders the label in a `` that is positioned on top of + *the edges. You can see an example usage of the component in the [edge label renderer](/examples/edges/edge-label-renderer) + *example. + * @public + * + * @example + *```jsx + *import React from 'react'; + *import { getBezierPath, EdgeLabelRenderer, BaseEdge } from '@xyflow/react'; + * + *export function CustomEdge({ id, data, ...props }) { + * const [edgePath, labelX, labelY] = getBezierPath(props); + * + * return ( + * <> + * + * + * + * {data.label} + * + * + * > + * ); + *}; + *``` + * + *@remarks The `` has no pointer events by default. If you want to + *add mouse interactions you need to set the style `pointerEvents: all` and add + *the `nopan` class on the label or the element you want to interact with. + */ export function EdgeLabelRenderer({ children }: { children: ReactNode }) { const edgeLabelRenderer = useStore(selector); diff --git a/packages/react/src/components/Edges/BaseEdge.tsx b/packages/react/src/components/Edges/BaseEdge.tsx index 3d951796..e19412f2 100644 --- a/packages/react/src/components/Edges/BaseEdge.tsx +++ b/packages/react/src/components/Edges/BaseEdge.tsx @@ -4,6 +4,33 @@ import cc from 'classcat'; import { EdgeText } from './EdgeText'; import type { BaseEdgeProps } from '../../types'; +/** + * The `` component gets used internally for all the edges. It can be + *used inside a custom edge and handles the invisible helper edge and the edge label + *for you. + * + * @public + * @example + * ```jsx + *import { BaseEdge } from '@xyflow/react'; + * + *export function CustomEdge({ sourceX, sourceY, targetX, targetY, ...props }) { + * const [edgePath] = getStraightPath({ + * sourceX, + * sourceY, + * targetX, + * targetY, + * }); + * + * return ; + *} + *``` + * + * @remarks If you want to use an edge marker with the [``](/api-reference/components/base-edge) component, + *you can pass the `markerStart` or `markerEnd` props passed to your custom edge + *through to the [``](/api-reference/components/base-edge) component. You can see all the props + *passed to a custom edge by looking at the [`EdgeProps`](/api-reference/types/edge-props) type. + */ export function BaseEdge({ path, labelX, diff --git a/packages/react/src/components/Edges/EdgeText.tsx b/packages/react/src/components/Edges/EdgeText.tsx index 2e3ad041..e2d162b0 100644 --- a/packages/react/src/components/Edges/EdgeText.tsx +++ b/packages/react/src/components/Edges/EdgeText.tsx @@ -73,4 +73,30 @@ function EdgeTextComponent({ EdgeTextComponent.displayName = 'EdgeText'; +/** + * You can use the `` component as a helper component to display text + *within your custom edges. + * + *@public + * + *@example + *```jsx + *import { EdgeText } from '@xyflow/react'; + * + *export function CustomEdgeLabel({ label }) { + * return ( + * + * ); + *} + *``` + */ export const EdgeText = memo(EdgeTextComponent); diff --git a/packages/react/src/components/Handle/index.tsx b/packages/react/src/components/Handle/index.tsx index 70e52dbe..07d18378 100644 --- a/packages/react/src/components/Handle/index.tsx +++ b/packages/react/src/components/Handle/index.tsx @@ -250,6 +250,28 @@ function HandleComponent( } /** - * The Handle component is a UI element that is used to connect nodes. + * The `` component is used in your [custom nodes](/learn/customization/custom-nodes) + *to define connection points. + * + *@public + * + *@example + * + *```jsx + *import { Handle, Position } from '@xyflow/react'; + * + *export function CustomNode({ data }) { + * return ( + * <> + * + * {data.label} + * + * + * + * + * > + * ); + *}; + *``` */ export const Handle = memo(fixedForwardRef(HandleComponent)); diff --git a/packages/react/src/components/Panel/index.tsx b/packages/react/src/components/Panel/index.tsx index 63695928..1859b034 100644 --- a/packages/react/src/components/Panel/index.tsx +++ b/packages/react/src/components/Panel/index.tsx @@ -5,10 +5,34 @@ import type { PanelPosition } from '@xyflow/system'; import { useStore } from '../../hooks/useStore'; import type { ReactFlowState } from '../../types'; +/** + * The `` component helps you position content above the viewport. It is + *used internally by the [``](/api-reference/components/minimap) and [``](/api-reference/components/controls) + *components. + * + * @public + * + * @example + * ```jsx + *import { ReactFlow, Background, Panel } from '@xyflow/react'; + * + *export default function Flow() { + * return ( + * + * top-left + * top-center + * top-right + * bottom-left + * bottom-center + * bottom-right + * + * ); + *} + *``` + */ export type PanelProps = HTMLAttributes & { /** - * Set position of the panel - * @example 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right' + * The position of the panel */ position?: PanelPosition; children: ReactNode; @@ -34,4 +58,4 @@ export const Panel = forwardRef( } ); -Panel.displayName = 'Panel' +Panel.displayName = 'Panel'; diff --git a/packages/react/src/components/ViewportPortal/index.tsx b/packages/react/src/components/ViewportPortal/index.tsx index c1b9b406..ea306935 100644 --- a/packages/react/src/components/ViewportPortal/index.tsx +++ b/packages/react/src/components/ViewportPortal/index.tsx @@ -6,6 +6,30 @@ import type { ReactFlowState } from '../../types'; const selector = (s: ReactFlowState) => s.domNode?.querySelector('.react-flow__viewport-portal'); +/** + * The `` component can be used to add components to the same viewport of the flow where nodes and edges are rendered. + *This is useful when you want to render your own components that are adhere to the same coordinate system as the nodes & edges and are also + *affected by zooming and panning + * @public + * @example + * + * ```jsx + *import React from 'react'; + *import { ViewportPortal } from '@xyflow/react'; + * + *export default function () { + * return ( + * + * + * This div is positioned at [100, 100] on the flow. + * + * + * ); + *} + *``` + */ export function ViewportPortal({ children }: { children: ReactNode }) { const viewPortalDiv = useStore(selector);