Skip to content

About

Stickyflow.js is a framework-independent parser, renderer, and editing runtime for using SFL in browsers, Node, and your own applications.

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@*-  -                *                                       =                                            .         *@
@@*++-::-::-:::::---::.:.:::::::::::-:::::-::::-:---:-:.   .@@@@@@@.   ::::::---:-:::::::::---::::::--:--:-:::::---:: %@
@@ .::---::::::-::::::::::-:::::::::::::::-:::::::::.   -@@@@@: -@@@@@+   :::------:-::-::-:::.:::::::::::-::---::-:: #@
@@*-::::.:::-::::::::-----::::::::-::::::::-:-:::.   *@@@@@    -*+-+@@@@@*   .::::-::::--:::::-:::::-:-::::-:-::::::: %@
@@.----:--::::::::::::::::-:::::::::.::::--::.   .%@@@@%   .::.-%***+-+@@@@@%.   ::::----:::::::::::::-::::::::::::-: %@
@@ ------:-:::-::::::-::::-:-::::::-::-::..   +@@@@@@   .-:::::-%*%*%**:  %@@@@@+   :::-:---::-::::::::::.:::::::-::- *@
@@ .:-:-::-:-::::::-:::-:::::::::::::::    *@@@@@*@@@-.-:-::::.-%%*%**%-.:   +@@@@@*   .--::::::-::::::::::::::::::.: %@
@@.:.-:---:::::::-::-::::::::::::::.    @@@@@%+. +@@@-:-::-::.:+**%*%%**.-::. @@@@@@@@%   .::::-:::::::::::::::-::.:: %@
@@:-----::-::::::::-::.:::::::::.   -@@@@@*--    +@@@-.:::-:+*.+=%%**%%+::--: @@@@@@@@@@@@   .:.::::::.:--::-::-:---- %@
@@ .:::.-:::::::::::---::::::    -@@@@@.:-. .    +@@@-.---:. *-+*=*%%%%-.:-::.@@@@@@@@@%@@@@@    ::::::-:::::--:::::: %@
@@ ::::::::-::::::--:::::.    %@@@@@ :+-:  .-%%@ =@@@+.::..*%:-@*#*+%*%+.::::.@@@@@@*@@@@@#@@@@@.   .::-:-:-::::::::: %@
@@:::::::::::::::-::-:.   -@@@@@* -++   +@%@**%@ *@@@-.-:*%*+#%+*+*%%%%+.:-::.@@@@@@@@@@@@@@@@@@@@@+   .:--:::::::::: %@
@@ .::::::-::.::::..   *@@@@@*.---  .   -@@@*%*- *@@@-.:.. +*%**%#***##+.---:.@@@@@@@@+   -@@@@@@#@@@@%   .:::::::::: %@
@@ ::::-:::::::.    #@@@@#-   :-*@@ .+@%.@%:-.   *@@@.     .. -*+%##@#@=.-:-:.@@@@@@%  ::.***@@@@   %@@@@#.   .::--:: %@
@@ :::-:-:::.   .@@@@@@   ::: . #@@ %@@++   -@--:*@@@%@@@@ .:*=**-*%%#@+.:--..@@@@@@: ::..%%*@@@@ ...  :@@@@@-   .::: %@
@@ .:::-::   -@@@@@@@@@ ::--- . @@@-    -##-+@*- *@@@@@@@@:  - -  *%%%#+.--:::@@@@@@:.-:- %%*@@@@...-+- **+@@@@@+   . %@
@@ :::    +@@@@#@@@@@@@ -----..    %@@+ *@@+  %  *@@@  #=  @@%.-  *%*@@=.::::.@@@@@@: :-:.%%%@@@@ ..-=* #***+-@@@@@=  *@
@@ .   %@@@@%%@@@@@@@@@ -----.... .-@@**-   -@:  =@@@.   @@@@+ . -@@@::-=+-:..@@@@@@@ .:: %*%@@@@ :.+=+ #%*%*%+* #@@@@@@
@@ *@@@@@*   @@@@@@@@@@ ::--+ ...%@@:   *@%+ @+#@@@%@@@  @@@@@@@@@----+----%+:@@@@@@@@  . %%%@@@@...++*.%*%*%*%%-     *@
@@ -%@-  :--:@@@@@@@@@@ ----- . +   *@@.+@@@@@@@%*+  @@@@@@@@@@@@   -+*%*@@*@#%#@@@@@@@*  %*%@@@@ ..-**.%*%*%*%%+.:.- %@
@@ : ---+-+--@@@@@@@@@@ ---:-.. .@% %@#++:...+*+   #@@@@@@@@@@@@@  :. .@%-*%@@@%%%%#@@@@@ +**@@@@...=*% %%*%%%-+-:::: *@
@@ -.-*+-+-+:@@@@@@@@@@ ::-*-  . @**-+-++-     :@@@@@@@@@@@@@@@@@#+    %+ ..-+*@@##%%*@@@@@#+%@@@...=%*.%%%%+-=+--::- %@
@@ -.++---+::@@@%@@@@@@ ::.     .+-*-+   @@@@@@@@@@#@@@@*:*%#@@@@%%%%**++     .--*@@@#%%%*@@@@@@@...+*% %*%%:-::-::-- %@
@@ -.+-+--+-:#@@@@@@@@@ .  %@@@@*    %@@@@@@@@@@@@@@@@@@%   :-+*%%***+#@@@@@-   ..:--@@@##%%%@@@@...*%%.#*-*@%:+-:::- %@
@@ :.-+:-+---@@@@@@@@@@ :@@@@@@@@@@@@@@@@@@@@@@@@@@@@***% ....:%-  %@@@+   @@@@-.   .--+#@@%...-@:. +*% -::-+-.-+.::- %@
@@ ::+-+-----@@@@@@@@@@ .%==*@@@@@@@@@@@*@@@@@@@@***%%%%*:-.:.-    +@@@@#*@@@@@*%%*-    :--**+--=+*:*%%.%-:.---+-:::- %@
@@ :.*-+-+--:@@@@@@@@@@ .@@@@@%+#@@@@@@@@@@@@@@@@@%**%%%*.=:..+ :*-** -@@@@%. *%*%*%%*-. .   +*%-+. *%%.#+:+.:---:-:- %@
@@ ::+----+--@@@@@@@@@@ +  .%@@@@%*#@@@@@@@@@@@@@@@@@***#%=-  :  :+%%        -##@@%%%%%%%+. .  ...: *##::.*#* %%:::-- %@
@@ :.+++-----@@@@@@@@@.@@@@@   -@@@@*  #@@@@@@@@@@@%@@@@**%%#%*%%%%*=. ..    -=-- -%%%*%%%-    :::: *%#.-*%%%*@*:..-- %@
@@ :.+:-++--:@@@@@@@@@@   *@@@@%          *@@@@@@@@@@@@@@@@%+*%%%*%##%******%%%:. +#%%*%**%***:+-.:.*%%-*+. #@**@%--- %@
@@ ::=+------@@@@@@* %@@@@+   @@@*-....--:   -@@@@@@@@+  @@@@@%+*%*%%%##@##%%%% . :****%*%*+=-#*.::  *% :-#@%%*@%.:-- *@
@@ ::-+-+-+--@@@@@@@@+  -@@@@@+  :-....-----:.  .@%    .    @@@@@@***%%%%%%%*%*+-+*%*#**=*%@@@@% ::.*@%-+:-:-%+-:.::-.%@
@@ .:+-------@@@@  .@@@@@-  @%----+ ...---+----:.. .::.---::   #@@@@@%+**%*%*%*++-=**+%#@@@@@@@% :: *@@@@***-#-*%*-:- %@
@@ :.+--+-+-:@@%@@@@:  %@@@@- :--:-   .-+--+------::.::--=+---:   *@@@@@#+-+*%*%-+=@@@@@@@@@@@@+   .*@@@#: :+**-  -:- %@
@@ ..*-------@@:  *@@@@%  . -:-:..:-%%+**+--+-+-+-:::::--  -+--:::   -@@@@@@*--@@@@@@@@@@@% *##%*****%*#%:.. + .::-:- %@
@@ ::*+-+--. *@@@@%  -@@@#--:...#@%:   --+++--+--+.-:::-:.@-  :---:-:   :@@@@@@@@@@@@@%-  - :.-%%%%*%#@%%  . + .  %*- %@
@@ :-*+---+@@%  .@@@@@       @@*:.: ...+:-----.-+-::-::-:-@  %%. ---::::    @@@@@@@.-  -+-* --: ..%###%*%*+. - -%*-.: %@
@@ .:*--.  :@@@@@   @@- .*@@@@@ :-+ ...-+-.:%@%::+:::::::+%.@@@%+**--+----:.   *  .:*.-*+-*:%  .::..:*##%**%*@*:...:: %@
@@ .-*:-@@@@*  @@@@@+:#@@@@@@@@ ---....--:%@@@@@#-.:::.-.    -+ + --* .-------::..++% +*+-% @@@%:.:---:.*@%-. ..::::: %@
@@ .:***. -@@@@% .@@@@@@@@@@@@@ -:+ ...+-:%@@@@@@-:::..-: @*#- -+:*%@ ..   -+ ....+-%.-*+-* @@@@@@:-+----: ..:::::::: %@
@@ ..*@@@@@- :@@@@@@@@@@@*:@@@@ ---.. .---:%@@@*--..:..--.%#@@  %% -@.+: . *@@@-  ++% +**+* @@@@@@.--+-+---::::-:-::- %@
@@ :.@+  *@@@@@@@@@@@%=--=-@@@@ --+ ...-+--    :--.-++-::-.  +=-@@@@+ --.. *@@@@@%++% +*+-% @@@@@% *=+-+-+:::::-:::-- %@
@@...+%@@@@#@@@@@@*---==**+@@@@ ---....---------**%%+-@@-.:---  +%@*-..: . *@@@@@@*+% +**-* @@@@@# -::+=---::--:----- %@
@@ ::.  -@@@@@@@ :.:++****+@@@@ ---   .-::-++**%*-   :@@@@@:**=+-  -%.-- . *@@@@@@--%.-*+-* @@@@@#   : -**::--------- %@
@@ ::-: *@@@@@@@+@@@#+****+@@@@ :---+++-*+-%**       *@@@@: ..-****+. -: . %@@@@@@-*%.+=-**-@@@@@%*@@@@@ .--::-:-:--- *@
@@ ::-:.*@@@@@@@-@@@@#****-@@@@ *%%+=**##%.%*    .+#@%*=*@+   . .-*****+++:.*@@@@@-=*.:*+-*-%@@@@%@@%#@@@*.+--:---:-- %@
@@ .--:.*@@@@@@@-@@@@@***%-@@@@-=+-*@@@@@+ += +*@@@@##@#%%%##*-   ..-=**+--++:.-@@-=**:*%=**@#%@@%@@@@@@##- :+:::---- %@
@@ :--:.%@@@@@@@-@@@@@****-@@@@++++-+.   *@#@%%@@%*:   +%@######%-   ..:-%*******-*+**%****+*@@@@*.@@@@@@@@@  ---::-- #@
@@ ::-:.*@@@@@@@-@@@@@****+@@@@-**%.-. -=@@@@#+.    .*.   +%@@@#@#@%+      -*%-:  ***-*%**#+@%%@@% *@@@@#%@@@= -+-::- %@
@@ ::-:.%@@@@@@@-@@@@*****+@@@@:%%%*-     .:    .=*%%****.   -#@@@%%%@#%#@@+.   . ****-*%***@%--@%   #@@@@@@@@   -+.- %@
@@ .-+:.*@@@@@@@-@@@%+++-*@@   ---.*%**+: .  :%***+.  +*****.   .%@@#@%@@%--*-... **%+-#++%+@%@@@% :. +@#@@@@@@@-..=- *@
@@ :.--:*@@@@@@@-@@::+%@@@.-   -=++@#%%%%**#%***-:+@@#+--*%**%*.   :#@#%*-  .: .. *** -+-=+.@@@@@% -:: %@@@@@#@@*  :- %@
@@ ::--:%@@@@@@@::*@@@%..-.-*.-#* @@*-+%###**--+:@@@@@@%::.+***%**:   -%%...::   :%-*.:+--*--.*@@* .   .=##@@@@@@@  - %@
@@ .:+:.*@@@@@@@@@@*::--+-.*@@@@% @@%+++***++*+--      :*@*---=*%*%**-  .    -+**=***+.---*-+- .@* -#@@@%. @@@#@@@@@* %@
@@ ::--.*@@@@%%*::-+-+-:%@@@@@@@* @@%*%*#%*   -+*=+--@@@@%*#*+++++%*%*%++.-=++++=*%*%=*%=.+:   :@@@@@+ =*--@@@@@@@@*- %@
@@ .-+.:%@@#+  -***+-@@@@@@@@@@@* @::*%%*%*=-    .=**%@@@+*+*+:  :%*%%*%%***#%**+-+********:+@@@@+.  -+.-**@@#@.    . %@
@@ ::-:.**:+=. *#%%@@@@@@@@@@@@%  ---%%*%%%%%*+-    .-+-+*+      +%%**=++-*#**%=##++**#%%*@@@@@-   :+**:****+-+%+.::: *@
@@ ::---#+   *@*   @@@@@@@@@.   ::*%*#%%**%**%%%*=-    .     :+*@%=+*%**%*@%#@##**%###%*#*.  @@@@@=   +###%**%: ..:.: %@
@@ --+--#* ..  ... @@@@@@   .:-=+-*+-**%%%%%%*%%%%%**- .  -%%%%+-=*%%%*%*%**%**=-%%%%%%%%*--:   @@@@@*   -**+. .::::: %@
@@ ::::.**  .::...:@@*   --+***==+#*%++=+*%%*%*%*%%%%%%%%@%**==%%%%**%%%+--++-*+--:+%%%%%%.:---:   @@@@%+=@**%=-. ..- %@
@@.--*%@#*+:. ..--   .-*%@*****%**%*+***%*=*%%%%%*%*%%***-*%%%%*: +**-. :-++= ++++---:+*@%*+-::---.:@@@: .+-  .%#*+.- #@
@@  ..-*@#%**+-..:-*%#@@##%*%%**++*****%*%*%+*=*%%%%-***%%%**+  .---: *#*..-* ++++=*=++ +%++=**-...-@@@- .-.. .*##@%: %@
@@@#    .:%###%*%#%@@@##@#**++=****+**%**%%*****+++*%%%#* *#*=+++++-@@@@@@@-+ -++**+ *%*-@-+-+-***:-@@@*. .  -*@*:  . %@
@@@@@@@     -%@##%*##@@#@#*=*-++***#%***%**%%*%**%%%*:   :--+--+-++- *@@@* +***%   -#*@%-@+*++-*+=**@@@*%*###-.      .@@
@@@@@@@@@*     :##@%%%%#%%%++*=*%*****#%*#%***%%*%*%%-**=++-+++-++++-     -** .. :%%%-@*:@**%++++=%*%%#@#%. ...   +@@@@@
@@@@@@@@@@@@*     :#####%#*****=+******%%%#@%%*%*%==++++-+++++++++-+=**%*+ -**%*+#%**+#*+@*%****++%%@#+       :@@@@@@@@@
@@@@@@@@@@@@@@@%     =%@##%%%*+****%**%%%#####%%%+ ::+=+++++++++++=**+: :*%*-%@@:%+-+ #*-%*%*%*%*%*-      .*@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@*     +%#%*%%%****%%%*%###@%%%%*.@#  -***++-=+*+:-   +*%*: ..:--.:= ++=#%%##%*:..    -@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@*    .-@#%*##%****%*#@#%%*%%*.@%-@*: -***-:.-**+%%%%**-:-::-++*% %%*@@*+.      *@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@*     +#@#%%%%**####%%@%#* @#.*%#*++.+%#+%@@*+%*%-.*+--.:-+*%*@#*- .     @@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@:     +@##%#@@%%%%%%%#*.%*=#%*--- -**.: -*=-:++ =-+++.***#- ...   -@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@      *@@#@#@#%*%%%*+@%-***--+ -++:+-..++=+-.*-+=*%#-...    %@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@-     %@@@#@#%*%*+%+-**=--+ *%*----.+--++-%%**: ..   -@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+    .%@@#@##%:***+-****.+*****+.:-+=**+ :.   .*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@.    -%@@#%%%%++*****-***+-+=*%%+-::    +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@#     -%##%*%**+-=+-***%***+. .    %@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%     -#@%*%*%++*%%#*-:..    @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*     +##%*%%#*...    .@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@-    .%#-. .    *@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@-        -#@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

-------------------------------------------------- StickyFlow.js----------------------------------------------------------

SFL parser, scene builder, SVG renderer, interactive viewer and editing runtime in one package. No runtime dependencies, no React, no Konva. The static tier is DOM-free and runs in Node.

Install

npm install stickyflow

Node 18 or newer. The package ships ESM, CJS and TypeScript types.

Quick start

import { render } from 'stickyflow'

const { svg, width, height, diagnostics } = render(sfl)
// A complete, deterministic SVG string. render() never touches the DOM.

Five entry points

Import What it is
stickyflow Static tier. SFL text in, SVG string out. Node, SSR, CLI.
stickyflow/viewer Viewer in the DOM: select, hover, pan, zoom, typed events, and live input for components such as a switch or a button.
stickyflow/interaction Editing gestures on a viewer. Reports what changed; the host applies the patch to the SFL text.
stickyflow/binding Data sources, bindings and handlers. createDataSource, createBindingRuntime, renderBound. No DOM.
stickyflow/web-component <stickyflow-diagram> custom element in Shadow DOM, no build step.

Each entry only depends on the ones below it; test/architecture enforces that.

import { createViewer } from 'stickyflow/viewer'
import { bindEditing, applyMoveChange } from 'stickyflow/interaction'

const viewer = createViewer({ container, source: sfl, interactive: true })
const editing = bindEditing(viewer)

editing.on('moveChange', (event) => {
  sfl = applyMoveChange(sfl, event)   // the text changes, nothing else does
  viewer.update({ source: sfl })
})

Components and data binding

A component is an interface element with a value, a look and a behavior. Seven are built in. RollingNumber, TickScale and Ruler show a value. Switch, Checkbox, ToggleButton and Button are operated by the user. An application adds its own type with defineComponent().

A document declares a data source and binds to it. <- makes a property follow the data. <-> also writes the data when the user changes a component value, and onChange runs for each change by the user.

DataSource lamp {
  mode: record
  fields {
    on: boolean
  }
}

Model demo {
  Component power {
    type: switch
    value: <-> lamp.on
    layout {
      position: 0, 0
      size: 104, 60
    }
  }
}
import { createBindingRuntime, createDataSource } from 'stickyflow/binding'
import { connectInteraction, createViewer } from 'stickyflow/viewer'

const viewer = createViewer({ container, source: sfl, interactive: true })
const runtime = createBindingRuntime(sfl)
const lamp = createDataSource({ on: false })

runtime.registerSource('lamp', lamp)
runtime.attach(viewer)
connectInteraction(viewer, runtime)

lamp.set({ on: true })   // the switch follows

Binding and live input need only stickyflow/binding and stickyflow/viewer. Editing with stickyflow/interaction is separate.

What it draws

Shapes, links, frames, swimlanes, paths and text. Fifteen chart types. Isometric objects. Shader surfaces and components. Data sources with bindings, and events with handlers, so a document can react to data and input.

Principles

  • Deterministic. The same SFL gives the same SVG, byte for byte.
  • Text stays the source. Edits patch the SFL text; comments and order survive.
  • Layered. Language, semantic, render input, scene, SVG, runtime, each with one job and one direction.
src/
  model/         types and registries for shapes, charts, components
  sflLanguage/   AST, lexer, parser, canonical emitter
  sflSemantic/   SFL AST to canvas state
  renderInput/   renderer contract and style decoding
  renderScene/   deterministic scene construction
  svg/           SVG serialization and the DOM contract
  binding/       data sources, bindings and handlers
  runtime/       viewer, interaction, web component

Develop

npm run ci      # lint, typecheck, tests, build, smoke
npm run build   # tsup

How the package and its neighbours fit together: docs/ARCHITECTURE.md. Adding a new placeable object: docs/ADDING_CANVAS_OBJECT.md. Adding a component: docs/ADDING_COMPONENT.md. Changes: CHANGELOG.md.

More

License

Apache-2.0

About

Stickyflow.js is a framework-independent parser, renderer, and editing runtime for using SFL in browsers, Node, and your own applications.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages