UNPKG

@reactodia/workspace

Version:

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

242 lines (224 loc) 7.6 kB
import type { Size } from '../diagram/geometry'; import type { ElementTypeIri, LinkTypeIri, PropertyTypeIri } from './model'; /** * [JSON-LD](https://json-ld.org/) context IRI (`@context` value) for the * serialized diagram state. * * @category Constants */ export const DiagramContextV1 = 'https://ontodia.org/context/v1.json'; /** * Property type to mark placeholder (i.e. not loaded yet) entity data. * * @category Constants * @see {@link EntityElement.placeholderData} */ export const PlaceholderDataProperty: PropertyTypeIri = 'urn:reactodia:isPlaceholder'; /** * Type for a newly created temporary entity in graph authoring mode. * * @category Constants */ export const PlaceholderEntityType: ElementTypeIri = 'urn:reactodia:newElement'; /** * Type for an newly created temporary relation in graph authoring mode. * * @category Constants */ export const PlaceholderRelationType: LinkTypeIri = 'urn:reactodia:newLink'; /** * Typed {@link TemplateState template state} property (string literal). * * @see {@link templateProperty} */ export type TemplateProperty<K extends string = string, V = unknown> = K & { __value: V }; /** * Contains a state with typed values for any defined * {@link TemplateProperties template properties}. * * Each property value should be JSON-serializable to be able * to export and import it as part of the serialized diagram layout. */ export class TemplateState { static empty = new TemplateState(undefined); constructor( private readonly value: { [property: string]: unknown } | undefined ) {} /** * Utility function to define typed {@link TemplateProperty template property}. * * **Example**: * ```ts * const MyNumberProperty = TemplateState.property('urn:my:prop1').of<number>(); * ``` */ static property<K extends string>(key: K): { of<V>(): TemplateProperty<K, V> } { return { of: <V>() => key as TemplateProperty<K, V>, }; } /** * Gets typed {@link TemplateProperties template property} value from * a template state. */ get<V>(property: TemplateProperty<string, V>): V | undefined { return this.value?.[property] as V | undefined; } /** * Sets optional typed {@link TemplateProperties template property} value * on a template state. * * This function never mutates the original state and always return * either original state (if the property value is the same) or newly * created updated state. * * If the `value` is `undefined`, the property will be removed from the `state`, * otherwise the new value will be set. */ set<V>(property: TemplateProperty<string, V>, value: V): TemplateState { const state = this.value; if (value !== undefined) { if (state?.[property] !== value) { return new TemplateState({...state, [property]: value}); } } else if (state?.[property] !== undefined) { const {[property]: _, ...withoutProperty} = state; return new TemplateState(withoutProperty); } return this; } static fromJSON( value: { readonly [property: string]: unknown } | undefined ): TemplateState { return value === undefined ? TemplateState.empty : new TemplateState(value); } toJSON(): SerializedTemplateState | undefined { return this.value ? {...this.value} : undefined; } } /** * Serialized template state. * * @see {@link TemplateState} */ export type SerializedTemplateState = { readonly [property: string]: unknown }; /** * Well-known {@link TemplateProperty template properties} for * element state ({@link Element.elementState}) or link state ({@link Link.linkState}). * * @category Constants */ export namespace TemplateProperties { /** * Element state property to display the element as expanded * (if element template supports expanded state). * * @see {@link Element.isExpanded} */ export const Expanded = TemplateState.property('urn:reactodia:expanded').of<boolean>(); /** * Element state property for user-modifiable template size * (if element template supports changing its size). */ export const ElementSize = TemplateState.property('urn:reactodia:elementSize').of<Size>(); /** * Element state property to mark some element data properties as "pinned", * i.e. displayed even if element is collapsed. * * @see {@link PinnedProperties} */ export const PinnedProperties = TemplateState.property('urn:reactodia:pinnedProperties').of<PinnedProperties>(); /** * Link state property to change to name of a specific link only on the diagram * (instead of displaying link type label). */ export const CustomLabel = TemplateState.property('urn:reactodia:customLabel').of<string>(); /** * Link state property to mark link as present only on the diagram but * missing from the data returned by a data provider. */ export const LayoutOnly = TemplateState.property('urn:reactodia:layoutOnly').of<boolean>(); /** * Element state property for selected page index when element is a group * of multiple items displayed with pagination. */ export const GroupPageIndex = TemplateState.property('urn:reactodia:groupPageIndex').of<number>(); /** * Element state property for selected page size when element is a group * of multiple items displayed with pagination. */ export const GroupPageSize = TemplateState.property('urn:reactodia:groupPageSize').of<number>(); /** * Element state property for the annotation content. * * @see {@link AnnotationContent} */ export const AnnotationContent = TemplateState.property('urn:reactodia:annotationContent').of<AnnotationContent>(); /** * Element or link state property to select a color variant for its style * from a predefined list. * * @see {@link ColorVariant} */ export const ColorVariant = TemplateState.property('urn:reactodia:colorVariant').of<ColorVariant>(); } /** * Shape for a value of the template state property * {@link TemplateProperties.PinnedProperties}. * * @see {@link TemplateProperties.PinnedProperties} */ export interface PinnedProperties { readonly [propertyId: string]: boolean; } /** * Annotation content for the template state property * {@link TemplateProperties.AnnotationContent}. * * @see {@link TemplateProperties.AnnotationContent} */ export interface AnnotationContent { /** * Content type: plain text with specified styles. */ readonly type: 'plaintext'; /** * Plain text content without any formatting. */ readonly text: string; /** * Styles for the whole text content. */ readonly style?: AnnotationTextStyle; } /** * Subset of supported styles for the {@link AnnotationContent annotation text content}. */ export type AnnotationTextStyle = Pick< React.CSSProperties, 'fontStyle' | 'fontWeight' | 'textDecorationLine' | 'textAlign' >; /** * Color variant from a predefined list of theme colors. * * @see {@link TemplateProperties.ColorVariant} */ export type ColorVariant = 'default' | 'primary' | 'success' | 'info' | 'warning' | 'danger'; export const DefaultColorVariants: readonly ColorVariant[] = [ 'default', 'primary', 'success', 'info', 'warning', 'danger', ];