UNPKG

@reactodia/workspace

Version:

Reactodia Workspace -- library for visual interaction with graphs in a form of a diagram.

241 lines (226 loc) 7.9 kB
import * as React from 'react'; import type { Events, EventTrigger } from '../coreUtils/events'; import type { Translation } from '../coreUtils/i18n'; import type { ElementIri, ElementTypeIri } from '../data/model'; import type { CanvasApi } from '../diagram/canvasApi'; import type { TypeStyle } from '../diagram/customization'; import type { Element } from '../diagram/elements'; import type { LayoutFunction } from '../diagram/layout'; import type { SharedCanvasState } from '../diagram/sharedCanvasState'; import type { DataDiagramModel } from '../editor/dataDiagramModel'; import type { EntityElement, EntityGroup } from '../editor/dataElements'; import type { EditorController } from '../editor/editorController'; import type { OverlayController } from '../editor/overlayController'; import type { CommandBusTopic } from './commandBusTopic'; /** * Represents a context for the whole workspace, its stores and services. * * This context is created once and exists for the full lifetime of the workspace. */ export interface WorkspaceContext { /** * Stores the diagram content and asynchronously fetches from a data provider. */ readonly model: DataDiagramModel; /** * Stores common state and settings for all canvases in the workspace. */ readonly view: SharedCanvasState; /** * Stores, modifies and validates changes from the visual graph authoring. */ readonly editor: EditorController; /** * Controls UI overlays for the canvases, including dialogs and tasks. */ readonly overlay: OverlayController; /** * Provides a translation for UI text strings. */ readonly translation: Translation; /** * Cancellation signal that becomes aborted when the workspace is disposed. */ readonly disposeSignal: AbortSignal; /** * Gets a common command event bus for the given topic definition which allows * interaction between related components. * * The returned event bus will share triggered events between all observers for * the same definition. */ readonly getCommandBus: <T>(definition: CommandBusTopic<T>) => Events<T> & EventTrigger<T>; /** * Computes a style to display target element in various parts of the UI. */ readonly getElementStyle: (element: Element) => ProcessedTypeStyle; /** * Computes a style to display an element with target set of types * in various parts of the UI. */ readonly getElementTypeStyle: (types: ReadonlyArray<ElementTypeIri>) => ProcessedTypeStyle; /** * Computes and applies **with animation** graph layout algorithm on the diagram content. * * A spinner overlay will be displayed if layout calculation will take too long (> 200ms). * * The operation puts a command to the {@link DiagramModel.history command history}. */ readonly performLayout: (params: WorkspacePerformLayoutParams) => Promise<void>; /** * Groups **with animation** multiple elements into an entity group. * * The operation puts a command to the {@link DiagramModel.history command history}. * * @see {@link DataDiagramModel.group} */ readonly group: (params: WorkspaceGroupParams) => Promise<EntityGroup>; /** * Ungroups **with animation** one or many entity groups into all contained elements. * * The operation puts a command to the {@link DiagramModel.history command history}. * * @see {@link DataDiagramModel.ungroupAll} */ readonly ungroupAll: (params: WorkspaceUngroupAllParams) => Promise<EntityElement[]>; /** * Ungroups **with animation** some entities from an entity group. * * The operation puts a command to the {@link DiagramModel.history command history}. * * @see {@link DataDiagramModel.ungroupSome} */ readonly ungroupSome: (params: WorkspaceUngroupSomeParams) => Promise<EntityElement[]>; /** * Triggers a well-known workspace event. */ readonly triggerWorkspaceEvent: (key: WorkspaceEventKey) => void; } /** * Options for {@link WorkspaceContext.performLayout} method. * * @see {@link WorkspaceContext.performLayout} */ export interface WorkspacePerformLayoutParams { /** * Target canvas to get element sizes from and perform layout algorithm on. * * If not specified, uses the result from {@link SharedCanvasState.findAnyCanvas}. * It is recommended to provide this value if possible for consistent * multi-canvas support. */ canvas?: CanvasApi; /** * Layout function to use when computing element positions. * * Default is defined by {@link WorkspaceProps.defaultLayout}. */ layoutFunction?: LayoutFunction; /** * Restrict the layout application to the subset of graph elements. */ selectedElements?: ReadonlySet<Element>; /** * Whether moving elements to final layout positions should be animated. * * @default false */ animate?: boolean; /** * Whether to fit elements into viewport after layout. * * @default true */ zoomToFit?: boolean; /** * Signal to cancel computing and applying the layout. */ signal?: AbortSignal; } /** * Options for {@link WorkspaceContext.group} method. * * @see {@link WorkspaceContext.group} */ export interface WorkspaceGroupParams { /** * Selected elements to group. */ elements: ReadonlyArray<EntityElement>; /** * Target canvas to get element sizes from for animation. */ canvas: CanvasApi; } /** * Options for {@link WorkspaceContext.ungroupAll} method. * * @see {@link WorkspaceContext.ungroupAll} */ export interface WorkspaceUngroupAllParams { /** * Selected groups to ungroup all entities from. */ groups: ReadonlyArray<EntityGroup>; /** * Target canvas to get element sizes from for animation. */ canvas: CanvasApi; } /** * Options for {@link WorkspaceContext.ungroupSome} method. * * @see {@link WorkspaceContext.ungroupSome} */ export interface WorkspaceUngroupSomeParams { /** * Selected group to ungroup some entities from. */ group: EntityGroup; /** * Subset of entities to ungroup from the target group. */ entities: ReadonlySet<ElementIri>; /** * Target canvas to get element sizes from for animation. */ canvas: CanvasApi; } /** * Well-known workspace events. */ export enum WorkspaceEventKey { searchUpdateCriteria = 'search:updateCriteria', searchQueryItem = 'search:queryItems', connectionsLoadLinks = 'connections:loadLinks', connectionsExpandLink = 'connections:expandLink', connectionsLoadElements = 'connections:loadElements', editorChangeSelection = 'editor:changeSelection', editorToggleDialog = 'editor:toggleDialog', editorAddElements = 'editor:addElements', } /** * Represents a computed style to display an element in various parts of the UI. */ export interface ProcessedTypeStyle extends Omit<TypeStyle, 'color'> { /** * CSS color string. */ readonly color: string; } /** @hidden */ export const WorkspaceContext = React.createContext<WorkspaceContext | null>(null); /** * React hook to get current workspace context. * * Throws an error if called from component which is outside the workspace. * * @category Hooks */ export function useWorkspace(): WorkspaceContext { const context = React.useContext(WorkspaceContext); if (!context) { throw new Error('Missing Reactodia workspace context'); } return context; }