graphwise-reactodia 0.0.1-TR19 → 0.0.1-TR20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/README.md +40 -0
  2. package/dist/cjs/graphwise-reactodia.cjs.entry.js +192 -43
  3. package/dist/cjs/index.cjs.js +16 -4
  4. package/dist/cjs/node-action-DkJ5ct17.js +96 -0
  5. package/dist/collection/components/graphwise-reactodia/graphwise-reactodia.css +6 -3
  6. package/dist/collection/components/graphwise-reactodia/graphwise-reactodia.js +2 -2
  7. package/dist/collection/components/graphwise-reactodia/menu/export-diagram-action.js +19 -0
  8. package/dist/collection/components/graphwise-reactodia/menu/graphwise-menu.js +19 -35
  9. package/dist/collection/components/graphwise-reactodia/menu/import-diagram-action.js +31 -0
  10. package/dist/collection/components/graphwise-reactodia/models/error/error-code.js +2 -0
  11. package/dist/collection/components/graphwise-reactodia/models/sparql/sparql-query-function.js +1 -0
  12. package/dist/collection/components/graphwise-reactodia/models/sparql/sparql-query-params.js +1 -0
  13. package/dist/collection/components/graphwise-reactodia/models/ui/menu-config.js +1 -0
  14. package/dist/collection/components/graphwise-reactodia/models/ui/menu-item.js +18 -0
  15. package/dist/collection/components/graphwise-reactodia/models/ui/node-action.js +22 -0
  16. package/dist/collection/components/graphwise-reactodia/models/ui/resolved-toolbar-position.js +1 -0
  17. package/dist/collection/components/graphwise-reactodia/models/ui/resolved-ui-config.js +1 -0
  18. package/dist/collection/components/graphwise-reactodia/models/ui/toolbar-dock.js +14 -0
  19. package/dist/collection/components/graphwise-reactodia/models/ui/toolbar-position.js +1 -0
  20. package/dist/collection/components/graphwise-reactodia/models/ui/ui-config.js +1 -0
  21. package/dist/collection/components/graphwise-reactodia/node-action/node-actions.js +22 -0
  22. package/dist/collection/components/graphwise-reactodia/reactodia-app.js +9 -7
  23. package/dist/collection/components/graphwise-reactodia/ui-config/default-ui-config.js +30 -0
  24. package/dist/collection/components/graphwise-reactodia/ui-config/ui-config-mapper.js +51 -0
  25. package/dist/collection/components/graphwise-reactodia/utils/object-util.js +30 -0
  26. package/dist/collection/index.js +3 -0
  27. package/dist/collection/pages/graphwise-reactodia/main.js +14 -0
  28. package/dist/esm/graphwise-reactodia.entry.js +181 -32
  29. package/dist/esm/index.js +1 -1
  30. package/dist/esm/node-action-fwJ3Zupw.js +94 -0
  31. package/dist/graphwise-reactodia/graphwise-reactodia.esm.js +1 -1
  32. package/dist/graphwise-reactodia/index.esm.js +1 -1
  33. package/dist/graphwise-reactodia/p-c3d8a69a.entry.js +1 -0
  34. package/dist/graphwise-reactodia/p-fwJ3Zupw.js +1 -0
  35. package/dist/types/components/graphwise-reactodia/graphwise-reactodia.d.ts +3 -3
  36. package/dist/types/components/graphwise-reactodia/menu/export-diagram-action.d.ts +4 -0
  37. package/dist/types/components/graphwise-reactodia/menu/graphwise-menu.d.ts +4 -7
  38. package/dist/types/components/graphwise-reactodia/menu/import-diagram-action.d.ts +4 -0
  39. package/dist/types/components/graphwise-reactodia/models/error/error-code.d.ts +3 -1
  40. package/dist/types/components/graphwise-reactodia/models/reactodia-config.d.ts +6 -1
  41. package/dist/types/components/graphwise-reactodia/models/sparql/sparql-query-function.d.ts +6 -0
  42. package/dist/types/components/graphwise-reactodia/models/sparql/sparql-query-params.d.ts +12 -0
  43. package/dist/types/components/graphwise-reactodia/models/ui/menu-config.d.ts +8 -0
  44. package/dist/types/components/graphwise-reactodia/models/ui/menu-item.d.ts +17 -0
  45. package/dist/types/components/graphwise-reactodia/models/ui/node-action.d.ts +21 -0
  46. package/dist/types/components/graphwise-reactodia/models/ui/resolved-toolbar-position.d.ts +8 -0
  47. package/dist/types/components/graphwise-reactodia/models/ui/resolved-ui-config.d.ts +12 -0
  48. package/dist/types/components/graphwise-reactodia/models/ui/toolbar-dock.d.ts +13 -0
  49. package/dist/types/components/graphwise-reactodia/models/ui/toolbar-position.d.ts +11 -0
  50. package/dist/types/components/graphwise-reactodia/models/ui/ui-config.d.ts +17 -0
  51. package/dist/types/components/graphwise-reactodia/node-action/node-actions.d.ts +6 -0
  52. package/dist/types/components/graphwise-reactodia/ui-config/default-ui-config.d.ts +5 -0
  53. package/dist/types/components/graphwise-reactodia/ui-config/ui-config-mapper.d.ts +14 -0
  54. package/dist/types/components/graphwise-reactodia/utils/object-util.d.ts +15 -0
  55. package/dist/types/components.d.ts +2 -2
  56. package/dist/types/index.d.ts +9 -0
  57. package/package.json +4 -1
  58. package/dist/cjs/error-code-BjU_V9e8.js +0 -37
  59. package/dist/esm/error-code-HfC639tc.js +0 -35
  60. package/dist/graphwise-reactodia/p-HfC639tc.js +0 -1
  61. package/dist/graphwise-reactodia/p-bf7f09d2.entry.js +0 -1
@@ -1,40 +1,24 @@
1
- import { createElement, Fragment } from "react";
2
- import { ToolbarAction, ToolbarActionClearAll, ToolbarActionExport, ToolbarActionOpen, useTranslation, useWorkspace } from "@reactodia/workspace";
3
- import { service } from "../providers/service/service-inject";
4
- import { DiagramService } from "../services/diagram/diagram.service";
5
- import { DiagramFileService } from "../services/diagram-file/diagram-file.service";
6
- import { ErrorService } from "../services/error/error.service";
7
- import { ErrorCode } from "../models/error/error-code";
1
+ import { createElement } from "react";
2
+ import { ToolbarActionClearAll, ToolbarActionExport } from "@reactodia/workspace";
3
+ import { MenuItem } from "../models/ui/menu-item";
4
+ import { ExportDiagramAction } from "./export-diagram-action";
5
+ import { ImportDiagramAction } from "./import-diagram-action";
8
6
  /**
9
- * The workspace main menu: Reactodia's default actions, followed by the diagram download and upload.
7
+ * Each menu entry.
10
8
  *
11
9
  * Passing a `menu` to the `DefaultWorkspace` replaces its default actions, so they are listed here again.
12
- * Rendered inside the workspace, so the actions can use the workspace hooks.
13
10
  */
14
- export function GraphwiseMenu() {
15
- const { model } = useWorkspace();
16
- const t = useTranslation();
17
- const diagramFileService = service(DiagramFileService);
18
- const diagramService = service(DiagramService);
19
- const errorService = service(ErrorService);
20
- const downloadDiagram = () => {
21
- const timestamp = new Date().toISOString().replace(/[-:]|\.\d+Z$/g, '');
22
- diagramFileService.download(model.exportLayout(), `diagram-${timestamp}${DiagramFileService.FILE_EXTENSION}`);
23
- };
24
- const uploadDiagram = async (file) => {
25
- try {
26
- const diagram = await diagramFileService.read(file);
27
- await diagramService.importDiagram(model, model.dataProvider, diagram);
28
- }
29
- catch (error) {
30
- errorService.report(ErrorCode.DIAGRAM_IMPORT, error);
31
- }
32
- };
33
- return createElement(Fragment, null, createElement(ToolbarActionClearAll, {}), createElement(ToolbarActionExport, { kind: 'exportRaster' }), createElement(ToolbarActionExport, { kind: 'exportSvg' }), createElement(ToolbarActionExport, { kind: 'print' }), createElement(ToolbarAction,
34
- // The same icon as ToolbarActionSave. We dont use that action, since it disables saving on refresh
35
- { className: 'reactodia-toolbar-action__save', title: t.text('graphwise_toolbar_action.download_diagram.title'), onSelect: downloadDiagram }, t.text('graphwise_toolbar_action.download_diagram.label')), createElement(ToolbarActionOpen, {
36
- title: t.text('graphwise_toolbar_action.upload_diagram.title'),
37
- fileAccept: DiagramFileService.FILE_EXTENSION,
38
- onSelect: (file) => void uploadDiagram(file)
39
- }, t.text('graphwise_toolbar_action.upload_diagram.label')));
11
+ const MENU_ITEMS = {
12
+ [MenuItem.CLEAR_ALL]: (key) => createElement(ToolbarActionClearAll, { key }),
13
+ [MenuItem.EXPORT_PNG]: (key) => createElement(ToolbarActionExport, { key, kind: 'exportRaster' }),
14
+ [MenuItem.EXPORT_SVG]: (key) => createElement(ToolbarActionExport, { key, kind: 'exportSvg' }),
15
+ [MenuItem.PRINT]: (key) => createElement(ToolbarActionExport, { key, kind: 'print' }),
16
+ [MenuItem.EXPORT_JSON]: (key) => createElement(ExportDiagramAction, { key }),
17
+ [MenuItem.IMPORT_JSON]: (key) => createElement(ImportDiagramAction, { key })
18
+ };
19
+ /**
20
+ * The menu entries for the given menu items.
21
+ */
22
+ export function createMenuItems(items) {
23
+ return items.map((item) => MENU_ITEMS[item](item));
40
24
  }
@@ -0,0 +1,31 @@
1
+ import { createElement } from "react";
2
+ import { ToolbarActionOpen, useTranslation, useWorkspace } from "@reactodia/workspace";
3
+ import { service } from "../providers/service/service-inject";
4
+ import { DiagramService } from "../services/diagram/diagram.service";
5
+ import { DiagramFileService } from "../services/diagram-file/diagram-file.service";
6
+ import { ErrorService } from "../services/error/error.service";
7
+ import { ErrorCode } from "../models/error/error-code";
8
+ /**
9
+ * Imports a diagram from a JSON file into the workspace.
10
+ */
11
+ export function ImportDiagramAction() {
12
+ const { model } = useWorkspace();
13
+ const t = useTranslation();
14
+ const diagramFileService = service(DiagramFileService);
15
+ const diagramService = service(DiagramService);
16
+ const errorService = service(ErrorService);
17
+ const importDiagram = async (file) => {
18
+ try {
19
+ const diagram = await diagramFileService.read(file);
20
+ await diagramService.importDiagram(model, model.dataProvider, diagram);
21
+ }
22
+ catch (error) {
23
+ errorService.report(ErrorCode.DIAGRAM_IMPORT, error);
24
+ }
25
+ };
26
+ return createElement(ToolbarActionOpen, {
27
+ title: t.text('graphwise_toolbar_action.import_json.title'),
28
+ fileAccept: DiagramFileService.FILE_EXTENSION,
29
+ onSelect: (file) => void importDiagram(file)
30
+ }, t.text('graphwise_toolbar_action.import_json.label'));
31
+ }
@@ -15,4 +15,6 @@ export var ErrorCode;
15
15
  ErrorCode["LOCAL_DIAGRAM_READ"] = "local-diagram-read";
16
16
  /** Saving the diagram in local storage failed. */
17
17
  ErrorCode["LOCAL_DIAGRAM_SAVE"] = "local-diagram-save";
18
+ /** The host's UI configuration has an unknown value, which is skipped. */
19
+ ErrorCode["UNKNOWN_UI_CONFIG"] = "unknown-ui-config";
18
20
  })(ErrorCode || (ErrorCode = {}));
@@ -0,0 +1,18 @@
1
+ /**
2
+ * An entry of the workspace main menu.
3
+ */
4
+ export var MenuItem;
5
+ (function (MenuItem) {
6
+ /** Removes all nodes from the diagram. */
7
+ MenuItem["CLEAR_ALL"] = "clear-all";
8
+ /** Exports the diagram as a PNG image. */
9
+ MenuItem["EXPORT_PNG"] = "export-png";
10
+ /** Exports the diagram as an SVG image. */
11
+ MenuItem["EXPORT_SVG"] = "export-svg";
12
+ /** Prints the diagram. */
13
+ MenuItem["PRINT"] = "print";
14
+ /** Exports the diagram as a JSON file. */
15
+ MenuItem["EXPORT_JSON"] = "export-json";
16
+ /** Imports a diagram from a JSON file. */
17
+ MenuItem["IMPORT_JSON"] = "import-json";
18
+ })(MenuItem || (MenuItem = {}));
@@ -0,0 +1,22 @@
1
+ /**
2
+ * A button shown around a selected node that acts on it.
3
+ */
4
+ export var NodeAction;
5
+ (function (NodeAction) {
6
+ /** Groups or ungroups the selected nodes. */
7
+ NodeAction["GROUP"] = "group";
8
+ /** Removes the node from the diagram. */
9
+ NodeAction["REMOVE"] = "remove";
10
+ /** Expands or collapses the node to show its properties. */
11
+ NodeAction["EXPAND"] = "expand";
12
+ /** Opens the node IRI. */
13
+ NodeAction["OPEN_LINK"] = "open-link";
14
+ /** Opens the menu to navigate to connected nodes. */
15
+ NodeAction["CONNECTIONS"] = "connections";
16
+ /** Searches for nodes connected to this one. */
17
+ NodeAction["ADD_TO_FILTER"] = "add-to-filter";
18
+ /** Adds an annotation to the node. */
19
+ NodeAction["ANNOTATE"] = "annotate";
20
+ /** Draws a new link from the node; for an entity, only in authoring mode. */
21
+ NodeAction["ESTABLISH_LINK"] = "establish-link";
22
+ })(NodeAction || (NodeAction = {}));
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The side or corner of the canvas a toolbar is docked to.
3
+ */
4
+ export var ToolbarDock;
5
+ (function (ToolbarDock) {
6
+ ToolbarDock["NW"] = "nw";
7
+ ToolbarDock["N"] = "n";
8
+ ToolbarDock["NE"] = "ne";
9
+ ToolbarDock["E"] = "e";
10
+ ToolbarDock["SE"] = "se";
11
+ ToolbarDock["S"] = "s";
12
+ ToolbarDock["SW"] = "sw";
13
+ ToolbarDock["W"] = "w";
14
+ })(ToolbarDock || (ToolbarDock = {}));
@@ -0,0 +1,22 @@
1
+ import { createElement } from "react";
2
+ import { SelectionActionAddToFilter, SelectionActionAnchor, SelectionActionAnnotate, SelectionActionConnections, SelectionActionEstablishLink, SelectionActionExpand, SelectionActionGroup, SelectionActionRemove } from "@reactodia/workspace";
3
+ import { NodeAction } from "../models/ui/node-action";
4
+ /**
5
+ * Each node action at its position in the fork's default `Halo`.
6
+ */
7
+ const NODE_ACTIONS = {
8
+ [NodeAction.GROUP]: (key) => createElement(SelectionActionGroup, { key, dock: 'nw', dockColumn: 1 }),
9
+ [NodeAction.REMOVE]: (key) => createElement(SelectionActionRemove, { key, dock: 'ne' }),
10
+ [NodeAction.EXPAND]: (key) => createElement(SelectionActionExpand, { key, dock: 's' }),
11
+ [NodeAction.OPEN_LINK]: (key) => createElement(SelectionActionAnchor, { key, dock: 'w' }),
12
+ [NodeAction.CONNECTIONS]: (key) => createElement(SelectionActionConnections, { key, dock: 'e' }),
13
+ [NodeAction.ADD_TO_FILTER]: (key) => createElement(SelectionActionAddToFilter, { key, dock: 'se' }),
14
+ [NodeAction.ANNOTATE]: (key) => createElement(SelectionActionAnnotate, { key, dock: 'se', dockColumn: 1 }),
15
+ [NodeAction.ESTABLISH_LINK]: (key) => createElement(SelectionActionEstablishLink, { key, dock: 'sw' })
16
+ };
17
+ /**
18
+ * The `Halo` children for the given node actions.
19
+ */
20
+ export function createNodeActions(actions) {
21
+ return actions.map((action) => NODE_ACTIONS[action](action));
22
+ }
@@ -12,7 +12,7 @@ import { ErrorCode } from "./models/error/error-code";
12
12
  import { EventType } from "./models/event/event-type";
13
13
  import { SubscriptionList } from "./models/subscription-list";
14
14
  import { resolveTypeStyle } from "./styles/type-style.resolver";
15
- import { GraphwiseMenu } from "./menu/graphwise-menu";
15
+ import { toWorkspaceProps } from "./ui-config/ui-config-mapper";
16
16
  /**
17
17
  * Reactodia ships English as its built-in default bundle, so the English bundle only adds our own keys.
18
18
  * Other languages are layered on top as partial bundles; unknown codes fall back to English.
@@ -37,6 +37,11 @@ let workspaceContext = null;
37
37
  */
38
38
  const subscriptions = new SubscriptionList();
39
39
  let diagramStorageSubscription;
40
+ /**
41
+ * The `DefaultWorkspace` props from the host's UI configuration. Kept across reloads, so unknown values are reported
42
+ * once, and cleared in {@link unmountReactodia}.
43
+ */
44
+ let uiConfigProps;
40
45
  const diagramService = service(DiagramService);
41
46
  const diagramStorageService = service(DiagramStorageService);
42
47
  const eventService = service(EventService);
@@ -220,17 +225,13 @@ function ReactodiaApp(props) {
220
225
  defaultLanguage: language,
221
226
  translations: translationsForLanguage(language),
222
227
  typeStyleResolver: resolveTypeStyle
223
- }, createElement(DefaultWorkspace, {
224
- colorScheme: props.theme,
225
- menu: createElement(GraphwiseMenu),
226
- // place Undo/redo/layout actions in top right corner.
227
- actionsToolbar: { dock: 'ne' }
228
- }));
228
+ }, createElement(DefaultWorkspace, Object.assign({ colorScheme: props.theme }, uiConfigProps)));
229
229
  }
230
230
  /**
231
231
  * Mounts the Reactodia application into the given container and returns the React root.
232
232
  */
233
233
  export function mountReactodia(container, props) {
234
+ uiConfigProps !== null && uiConfigProps !== void 0 ? uiConfigProps : (uiConfigProps = toWorkspaceProps(props.config.ui));
234
235
  const root = createRoot(container);
235
236
  root.render(createElement(ReactodiaApp, props));
236
237
  return root;
@@ -265,5 +266,6 @@ export function exportReactodiaLayout() {
265
266
  */
266
267
  export function unmountReactodia(root) {
267
268
  subscriptions.unsubscribeAll();
269
+ uiConfigProps = undefined;
268
270
  root.unmount();
269
271
  }
@@ -0,0 +1,30 @@
1
+ import { MenuItem } from "../models/ui/menu-item";
2
+ import { NodeAction } from "../models/ui/node-action";
3
+ import { ToolbarDock } from "../models/ui/toolbar-dock";
4
+ /**
5
+ * The default UI configuration: Reactodia's behaviour, plus the diagram download and upload in the menu.
6
+ */
7
+ export const DEFAULT_UI_CONFIG = {
8
+ mainToolbar: { dock: ToolbarDock.NW },
9
+ actionsToolbar: { dock: ToolbarDock.SW },
10
+ menu: {
11
+ items: [
12
+ MenuItem.CLEAR_ALL,
13
+ MenuItem.EXPORT_PNG,
14
+ MenuItem.EXPORT_SVG,
15
+ MenuItem.PRINT,
16
+ MenuItem.EXPORT_JSON,
17
+ MenuItem.IMPORT_JSON
18
+ ]
19
+ },
20
+ nodeActions: [
21
+ NodeAction.GROUP,
22
+ NodeAction.REMOVE,
23
+ NodeAction.EXPAND,
24
+ NodeAction.OPEN_LINK,
25
+ NodeAction.CONNECTIONS,
26
+ NodeAction.ADD_TO_FILTER,
27
+ NodeAction.ANNOTATE,
28
+ NodeAction.ESTABLISH_LINK
29
+ ]
30
+ };
@@ -0,0 +1,51 @@
1
+ import { createElement, Fragment } from "react";
2
+ import { ToolbarDock } from "../models/ui/toolbar-dock";
3
+ import { MenuItem } from "../models/ui/menu-item";
4
+ import { NodeAction } from "../models/ui/node-action";
5
+ import { ErrorCode } from "../models/error/error-code";
6
+ import { service } from "../providers/service/service-inject";
7
+ import { ErrorService } from "../services/error/error.service";
8
+ import { mergeWithDefaults } from "../utils/object-util";
9
+ import { DEFAULT_UI_CONFIG } from "./default-ui-config";
10
+ import { createMenuItems } from "../menu/graphwise-menu";
11
+ import { createNodeActions } from "../node-action/node-actions";
12
+ const errorService = service(ErrorService);
13
+ /**
14
+ * Merges the host's UI configuration over the default and maps the result to `DefaultWorkspace` props. A `null` or
15
+ * missing field keeps the default; objects merge key by key and lists replace the default whole. Unknown values are
16
+ * reported and left out; a repeated list entry is kept once.
17
+ *
18
+ * @param ui The host's UI configuration.
19
+ */
20
+ export function toWorkspaceProps(ui) {
21
+ const resolved = mergeWithDefaults(ui !== null && ui !== void 0 ? ui : {}, DEFAULT_UI_CONFIG);
22
+ const menuItems = [...new Set(resolved.menu.items)].filter((item) => isValid(item, MenuItem));
23
+ const nodeActions = [...new Set(resolved.nodeActions)].filter((action) => isValid(action, NodeAction));
24
+ return {
25
+ menu: menuItems.length ? createElement(Fragment, null, createMenuItems(menuItems)) : null,
26
+ mainToolbar: toToolbarProps(resolved.mainToolbar, DEFAULT_UI_CONFIG.mainToolbar),
27
+ actionsToolbar: toToolbarProps(resolved.actionsToolbar, DEFAULT_UI_CONFIG.actionsToolbar),
28
+ halo: { children: createNodeActions(nodeActions) }
29
+ };
30
+ }
31
+ /**
32
+ * Maps a toolbar position to the `DefaultWorkspace` toolbar props. With an unknown dock, `defaultPosition` is used
33
+ * whole, since the offsets are relative to the dock.
34
+ */
35
+ function toToolbarProps(position, defaultPosition) {
36
+ const { dock, offsetX, offsetY } = isValid(position.dock, ToolbarDock) ? position : defaultPosition;
37
+ return { dock, dockOffsetX: offsetX, dockOffsetY: offsetY };
38
+ }
39
+ /**
40
+ * Whether `value` is one of the `known` values. Reports it as unknown UI configuration when it is not.
41
+ *
42
+ * @param value The value from the UI configuration.
43
+ * @param known The known values, e.g. an enum.
44
+ */
45
+ function isValid(value, known) {
46
+ const isValid = Object.values(known).includes(value);
47
+ if (!isValid) {
48
+ errorService.report(ErrorCode.UNKNOWN_UI_CONFIG, new Error(`Unknown UI configuration value: "${value}"`));
49
+ }
50
+ return isValid;
51
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Merges an object with default values. Ported from the GraphDB Workbench `ObjectUtil.mergeWithDefaults`.
3
+ *
4
+ * For each property in `defaults`, if the value in `object` is `null` or `undefined`, the default value is used instead.
5
+ * Nested objects are merged recursively. Arrays and other non-plain values are treated as single values and are not
6
+ * merged.
7
+ *
8
+ * The returned object is a new object and does not share references with the inputs. The inputs must be
9
+ * structured-cloneable.
10
+ *
11
+ * @param object Source object whose values take precedence over defaults.
12
+ * @param defaults Default values applied when properties are missing or null.
13
+ * @returns A new object containing the merged result.
14
+ */
15
+ export function mergeWithDefaults(object, defaults) {
16
+ const result = structuredClone(object);
17
+ Object.entries(defaults).forEach(([key, defaultValue]) => {
18
+ const value = result[key];
19
+ if (value === null || value === undefined) {
20
+ result[key] = structuredClone(defaultValue);
21
+ }
22
+ else if (isPlainObject(value) && isPlainObject(defaultValue)) {
23
+ result[key] = mergeWithDefaults(value, defaultValue);
24
+ }
25
+ });
26
+ return result;
27
+ }
28
+ function isPlainObject(value) {
29
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
30
+ }
@@ -2,3 +2,6 @@ export { CLEAR_DIAGRAM_STORAGE_EVENT } from './components/graphwise-reactodia/mo
2
2
  export { GRAPHWISE_REACTODIA_EVENT } from './components/graphwise-reactodia/models/event/event-detail';
3
3
  export { EventType } from './components/graphwise-reactodia/models/event/event-type';
4
4
  export { ErrorCode } from './components/graphwise-reactodia/models/error/error-code';
5
+ export { ToolbarDock } from './components/graphwise-reactodia/models/ui/toolbar-dock';
6
+ export { MenuItem } from './components/graphwise-reactodia/models/ui/menu-item';
7
+ export { NodeAction } from './components/graphwise-reactodia/models/ui/node-action';
@@ -124,6 +124,20 @@ function setSeedGraph() {
124
124
  reactodia.config = {...reactodia.config, seedGraph: SEED_GRAPH};
125
125
  }
126
126
 
127
+ // A partial host UI configuration, merged over the default.
128
+ const HOST_UI = {
129
+ actionsToolbar: {dock: 'ne'},
130
+ nodeActions: ['group', 'remove', 'expand', 'connections', 'add-to-filter', 'annotate', 'establish-link'],
131
+ };
132
+
133
+ function setHostUi() {
134
+ reactodia.config = {...reactodia.config, ui: HOST_UI};
135
+ }
136
+
137
+ function setEmptyMenuUi() {
138
+ reactodia.config = {...reactodia.config, ui: {menu: {items: []}}};
139
+ }
140
+
127
141
  function setRepository(repository) {
128
142
  reactodia.currentRepository = repository;
129
143
  }