diff --git a/.github/workflows/ci-checks.yml b/.github/workflows/ci-checks.yml new file mode 100644 index 00000000..71e38fdc --- /dev/null +++ b/.github/workflows/ci-checks.yml @@ -0,0 +1,40 @@ +# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs + +name: Node.js CI + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +jobs: + build: + runs-on: ubuntu-latest + + strategy: + matrix: + node-version: [22.x] + # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + + steps: + - uses: actions/checkout@v4 + - name: Checkout @reactodia/workspace + uses: actions/checkout@v4 + with: + repository: reactodia/reactodia-workspace + path: ./reactodia-workspace + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + - name: Install dependencies + run: npm ci + - name: Install dependencies for library + run: cd ./reactodia-workspace && npm ci + - name: Typecheck + run: npm run typecheck + - name: Build + run: npm run build diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml new file mode 100644 index 00000000..1e529e35 --- /dev/null +++ b/.github/workflows/deploy-pages.yml @@ -0,0 +1,47 @@ +# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node +# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-nodejs + +name: Deploy to GitHub pages + +on: + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 22.x + cache: 'npm' + - run: npm ci + - run: npm run typecheck + - run: npm run build + - name: Archive build artifacts + uses: actions/upload-pages-artifact@v3 + with: + path: build + + deploy: + # Add a dependency to the build job + needs: build + + # Grant GITHUB_TOKEN the permissions required to make a Pages deployment + permissions: + pages: write # to deploy to Pages + id-token: write # to verify the deployment originates from an appropriate source + + # Deploy to the github-pages environment + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + + # Specify runner + deployment step + runs-on: ubuntu-latest + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 # or specific "vX.X.X" version tag for this action diff --git a/docs/components/annotation-support.md b/docs/components/annotation-support.md new file mode 100644 index 00000000..9f57a5f4 --- /dev/null +++ b/docs/components/annotation-support.md @@ -0,0 +1,79 @@ +--- +title: +--- + +# Annotation Support + +[``](/docs/api/workspace/functions/AnnotationSupport.md) component is a [canvas widget](/docs/components/canvas.md#widgets) to provide UI for the [annotation](/docs/concepts/graph-model.md#annotations) elements and links. + +:::important +`` widget must be provided to the canvas to in order to enable annotation UI features such as creating a new annotation with [``](/docs/components/selection.md#selecting-elements), linking annotation to an element with [``](/docs/components/selection.md#selecting-elements) or [``](/docs/components/selection.md#selecting-links). +::: + +The component observes [`AnnotationTopic`](/docs/api/workspace/variables/AnnotationTopic.md) [command bus topic](/docs/concepts/event-system.md#command-bus). + +### Example: annotation elements and links + +```tsx live noInline +function Example() { + const {defaultLayout} = Reactodia.useWorker(Layouts); + + const {onMount} = Reactodia.useLoadedWorkspace(async ({context, signal}) => { + const {model, view, performLayout} = context; + const entity = model.createElement('http://example.com/entity1'); + const annotation1 = new Reactodia.AnnotationElement({ + elementState: Reactodia.TemplateState.empty + .set(Reactodia.TemplateProperties.AnnotationContent, { + type: 'plaintext', + text: 'Double-click to edit\nnote about "entity1"', + }), + }); + const annotation2 = new Reactodia.AnnotationElement({ + elementState: Reactodia.TemplateState.empty + .set(Reactodia.TemplateProperties.AnnotationContent, { + type: 'plaintext', + text: 'Note about entity AND annotation', + }) + .set(Reactodia.TemplateProperties.ColorVariant, 'primary'), + }); + model.addElement(annotation1); + model.addElement(annotation2); + model.addLink(new Reactodia.AnnotationLink({ + sourceId: annotation1.id, + targetId: entity.id, + })); + model.addLink(new Reactodia.AnnotationLink({ + sourceId: annotation2.id, + targetId: entity.id, + })); + model.addLink(new Reactodia.AnnotationLink({ + sourceId: annotation2.id, + targetId: annotation1.id, + linkState: Reactodia.TemplateState.empty + .set( + Reactodia.TemplateProperties.CustomLabel, + 'note about another note' + ), + })); + await performLayout({signal}); + }, []); + + return ( +
+ + + + + + + + + + +
+ ); +} + +render(); +``` diff --git a/docs/components/canvas.md b/docs/components/canvas.md index ce1c07c4..b4cb3ea0 100644 --- a/docs/components/canvas.md +++ b/docs/components/canvas.md @@ -23,7 +23,9 @@ The library provides the following built-in templates: | [`StandardTemplate`](/docs/api/workspace/variables/StandardTemplate.md) | element | Default (fallback) template for an element; supports single entity elements and [entity groups](/docs/concepts/graph-model.md#data-graph).
Uses [`StandardEntity`](/docs/api/workspace/functions/StandardEntity.md) and [`StandardEntityGroup`](/docs/api/workspace/functions/StandardEntityGroup.md) components to render elements. | | [`ClassicTemplate`](/docs/api/workspace/variables/ClassicTemplate.md) | element | Element template component with classic "look and feel" which was used for elements before v0.8; does not support entity groups.
Uses [`ClassicEntity`](/docs/api/workspace/functions/ClassicEntity.md) component to render elements. | | [`RoundTemplate`](/docs/api/workspace/variables/RoundTemplate.md) | element | Basic element template with an round (elliptical) shape; does not support entity groups.
Uses [`RoundEntity`](/docs/api/workspace/functions/RoundEntity.md) component to render elements. | -| [`DefaultLinkTemplate`](/docs/api/workspace/variables/DefaultLinkTemplate.md) | link | Default (fallback) template for a link; supports single relation links and [relation groups](/docs/concepts/graph-model.md#data-graph).
Uses [`DefaultLink`](/docs/api/workspace/functions/DefaultLink.md) component to render links which uses [`LinkPath`](/docs/api/workspace/functions/LinkPath.md), [`LinkLabel`](/docs/api/workspace/functions/LinkLabel.md) and [`LinkVertices`](/docs/api/workspace/functions/LinkVertices.md) components inside to display the link connection itself, the labels and vertices (to change link geometry). | +| [`StandardLinkTemplate`](/docs/api/workspace/variables/StandardLinkTemplate.md) | link | Default (fallback) template for a link; supports single relation links and [relation groups](/docs/concepts/graph-model.md#data-graph).
Uses [`StandardRelation`](/docs/api/workspace/functions/StandardRelation.md) component to render links which uses [`LinkPath`](/docs/api/workspace/functions/LinkPath.md), [`LinkLabel`](/docs/api/workspace/functions/LinkLabel.md) and [`LinkVertices`](/docs/api/workspace/functions/LinkVertices.md) components inside to display the link connection itself, the labels and vertices (to change link geometry). | +| [`NoteTemplate`](/docs/api/workspace/variables/NoteTemplate.md) | element | Default template for [annotation elements](/docs/concepts/graph-model.md#annotations).
Uses [`NoteAnnotation`](/docs/api/workspace/functions/NoteAnnotation.md) component to render a user-resizable note with editable text content and style. | +| [`NoteLinkTemplate`](/docs/api/workspace/variables/NoteLinkTemplate.md) | link | Default template for [annotation links](/docs/concepts/graph-model.md#annotations).
Uses [`NoteLink`](/docs/api/workspace/functions/NoteLink.md) component to render a [basic link](/docs/api/workspace/functions/BasicLink.md) with an optional label if the link was [renamed](/docs/api/workspace/interfaces/RenameLinkProvider.md). | Additionally, it is possible to override how the link are routed (how default path geometry is computed) on the canvas by providing `linkRouter` ([`LinkRouter`](/docs/api/workspace/interfaces/LinkRouter.md)) prop to the ``. By default, the [`DefaultLinkRouter`](/docs/api/workspace/classes/DefaultLinkRouter.md) is used which moves apart multiple links between same elements and displays self-links (where target is equal to source) as loops. @@ -81,25 +83,63 @@ function NonWidgetComponent { } ``` -## Canvas widgets +## Widgets -Canvas widget is an instance of any React component type which is marked by [defineCanvasWidget()](/docs/api/workspace/functions/defineCanvasWidget) function with metadata such as its attachment layer i.e. where the component should be displayed in relation to other canvas content. +Canvas widget is any React component placed as a child to [``](/docs/api/workspace/functions/Canvas). There are multiple canvas layers to place widgets on, from top one to the bottom: -| Layer name | [Coordinate type](/docs/concepts/canvas-coordinates.md) | Description | -|----------------|-------------------|-------------| -| `viewport` | client (viewport) | Topmost layer, does not scale or scroll with the diagram. | -| `overElements` | paper | Displayed over both elements and links, scales and scrolls with the diagram. | -| `overLinks` | paper | Displayed under elements but over links, scales and scrolls with the diagram. | +| Layer name | [Coordinate type](/docs/concepts/canvas-coordinates.md) | Is scaled | Is scrolled | Description | +|--------------------|-------------------|---|---|-------------| +| `viewport` | client (viewport) | ❌ | ❌ | Top layer, placed over all diagram content and other layers. | +| `overElements` | scrollable pane | ❌ | ✔ | Placed over both elements and links. | +| `overLinks` | scrollable pane | ❌ | ✔ | Placed under elements but over links (including its geometry and labels). | +| `overLinkGeometry` | scrollable pane | ❌ | ✔ | Placed under link labels but over link geometry (paths). | +| `underlay` | scrollable pane | ❌ | ✔ | Bottom layer, placed under all diagram content and other layers. | -### Example: custom viewport widget +By default, every child component (widget) is placed at `viewport` layer over canvas viewport. However, [``](/docs/api/workspace/functions/CanvasPlaceAt.md) can be used to display its children at a different layer: + +```tsx +function MyWidget() { + return ( + <> +
+ {/* This will be displayer over viewport */} +
+ + {/* ... render additonal link decorations ... */} + + + {/* ... render additional background content */} + + + ); +} + +... +return ( + + + + + + + +); +``` + +:::warning +`` cannot be nested into itself, otherwise an error will be thrown. +::: + +### Example: simple viewport widget ```tsx live noInline -function CustomSelectAllWidget() { +function SelectAllButton() { const {model} = Reactodia.useWorkspace(); return ( - +