@dxos/app-graph 0.3.10-next.ef70620 → 0.3.11-main.bd26370

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.
@@ -54,7 +54,7 @@ var Graph = class {
54
54
  */
55
55
  traverse({ node = this._root, direction = "down", filter, visitor }, depth = 0) {
56
56
  if (!filter || filter(node)) {
57
- visitor?.(node);
57
+ visitor?.(node, this.getPath(node.id));
58
58
  }
59
59
  if (direction === "down") {
60
60
  Object.values(node.children).forEach((child) => this.traverse({
@@ -76,8 +76,8 @@ var Graph = class {
76
76
  // packages/sdk/app-graph/src/graph-builder.ts
77
77
  import { untracked } from "@preact/signals-react";
78
78
  import { deepSignal as deepSignal2 } from "deepsignal/react";
79
- import Mousetrap from "mousetrap";
80
79
  import { EventSubscriptions } from "@dxos/async";
80
+ import { Keyboard } from "@dxos/keyboard";
81
81
  var GraphBuilder = class {
82
82
  constructor() {
83
83
  this._nodeBuilders = /* @__PURE__ */ new Map();
@@ -139,6 +139,9 @@ var GraphBuilder = class {
139
139
  get actions() {
140
140
  return Object.values(node.actionsMap);
141
141
  },
142
+ //
143
+ // Properties
144
+ //
142
145
  addProperty: (key, value) => {
143
146
  untracked(() => {
144
147
  node.properties[key] = value;
@@ -149,6 +152,9 @@ var GraphBuilder = class {
149
152
  delete node.properties[key];
150
153
  });
151
154
  },
155
+ //
156
+ // Nodes
157
+ //
152
158
  addNode: (builder, ...partials) => {
153
159
  return untracked(() => {
154
160
  return partials.map((partial2) => {
@@ -178,13 +184,20 @@ var GraphBuilder = class {
178
184
  return child;
179
185
  });
180
186
  },
187
+ //
188
+ // Actions
189
+ //
181
190
  addAction: (...partials) => {
182
191
  return untracked(() => {
183
192
  return partials.map((partial2) => {
184
193
  const action = this._createAction(partial2);
185
194
  if (action.keyBinding) {
186
- Mousetrap.bind(action.keyBinding, () => {
187
- action.invoke();
195
+ Keyboard.singleton.getContext(path.join("/")).bind({
196
+ binding: action.keyBinding,
197
+ handler: () => {
198
+ action.invoke();
199
+ },
200
+ data: action.label
188
201
  });
189
202
  }
190
203
  node.actionsMap[action.id] = action;
@@ -196,7 +209,6 @@ var GraphBuilder = class {
196
209
  return untracked(() => {
197
210
  const action = node.actionsMap[id];
198
211
  if (action.keyBinding) {
199
- Mousetrap.unbind(action.keyBinding);
200
212
  }
201
213
  delete node.actionsMap[id];
202
214
  return action;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/graph.ts", "../../../src/graph-builder.ts", "../../../src/node.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { deepSignal } from 'deepsignal/react';\n// TODO(wittjosiah): Remove lodash dependency.\nimport get from 'lodash.get';\n\nimport { type Label } from './action';\nimport { type Node } from './node';\n\nexport type TraversalOptions = {\n /**\n * The node to start traversing from. Defaults to the root node.\n */\n node?: Node;\n\n /**\n * The direction to traverse the graph. Defaults to 'down'.\n */\n direction?: 'up' | 'down';\n\n /**\n * A predicate to filter nodes which are passed to the `visitor` callback.\n */\n filter?: (node: Node) => boolean;\n\n /**\n * A callback which is called for each node visited during traversal.\n */\n visitor?: (node: Node) => void;\n};\n\n/**\n * The Graph represents...\n */\nexport class Graph {\n // TODO(burdon): Document.\n // TODO(wittjosiah): Should this support multiple paths to the same node?\n private readonly _index = deepSignal<{ [key: string]: string[] }>({});\n\n constructor(private readonly _root: Node) {}\n\n toJSON() {\n const toLabel = (label: Label) => (Array.isArray(label) ? `${label[1].ns}[${label[0]}]` : label);\n const toJSON = (node: Node): any => {\n return {\n id: node.id.slice(0, 16),\n label: toLabel(node.label),\n children: node.children.length ? node.children.map((node) => toJSON(node)) : undefined,\n actions: node.actions.length\n ? node.actions.map(({ id, label }) => ({\n id,\n label: toLabel(label),\n }))\n : undefined,\n };\n };\n\n return toJSON(this._root);\n }\n\n /**\n * The root node of the graph which is the entry point for all knowledge.\n */\n get root(): Node {\n return this._root;\n }\n\n /**\n * Get the path through the graph from the root to the node with the given id.\n */\n getPath(id: string): string[] | undefined {\n return this._index[id];\n }\n\n /**\n * @internal\n */\n _setPath(id: string, path: string[]) {\n this._index[id] = path;\n }\n\n /**\n * Find the node with the given id in the graph.\n */\n findNode(id: string): Node | undefined {\n const path = this.getPath(id);\n if (!path) {\n return undefined;\n }\n\n return path.length > 0 ? get(this._root, path) : this._root;\n }\n\n /**\n * Recursive breadth-first traversal.\n */\n traverse({ node = this._root, direction = 'down', filter, visitor }: TraversalOptions, depth = 0): void {\n if (!filter || filter(node)) {\n visitor?.(node);\n }\n\n if (direction === 'down') {\n Object.values(node.children).forEach((child) => this.traverse({ node: child, filter, visitor }));\n } else if (direction === 'up' && node.parent) {\n this.traverse({ node: node.parent, direction, filter, visitor }, depth + 1);\n }\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { untracked } from '@preact/signals-react';\nimport { type RevertDeepSignal, deepSignal } from 'deepsignal/react';\nimport Mousetrap from 'mousetrap';\n\nimport { EventSubscriptions } from '@dxos/async';\n\nimport type { ActionArg, Action } from './action';\nimport { Graph } from './graph';\nimport type { NodeArg, Node, NodeBuilder } from './node';\n\n/**\n * The builder...\n */\nexport class GraphBuilder {\n private readonly _nodeBuilders = new Map<string, NodeBuilder>();\n private readonly _unsubscribe = new Map<string, EventSubscriptions>();\n\n /**\n * Register a node builder which will be called in order to construct the graph.\n */\n addNodeBuilder(id: string, builder: NodeBuilder): GraphBuilder {\n this._nodeBuilders.set(id, builder);\n return this;\n }\n\n /**\n * Remove a node builder from the graph builder.\n */\n removeNodeBuilder(id: string): GraphBuilder {\n this._nodeBuilders.delete(id);\n return this;\n }\n\n /**\n * Construct the graph, starting by calling all registered node builders on the root node.\n * Node builders will be filtered out as they are used such that they are only used once on any given path.\n * @param previousGraph If provided, the graph will be updated in place.\n * @param startingPath If provided, the graph will be updated starting at the given path.\n */\n build(previousGraph?: Graph, startingPath: string[] = []): Graph {\n const graph: Graph = previousGraph ?? new Graph(this._createNode(() => graph, { id: 'root', label: 'Root' }));\n return this._build(graph, graph.root, startingPath);\n }\n\n /**\n * Called recursively.\n */\n private _build(graph: Graph, node: Node, path: string[] = [], ignoreBuilders: string[] = []): Graph {\n // TODO(wittjosiah): Should this support multiple paths to the same node?\n graph._setPath(node.id, path);\n\n // TODO(burdon): Document.\n const subscriptions = this._unsubscribe.get(node.id) ?? new EventSubscriptions();\n subscriptions.clear();\n\n Array.from(this._nodeBuilders.entries())\n .filter(([id]) => ignoreBuilders.findIndex((ignore) => ignore === id) === -1)\n .forEach(([_, builder]) => {\n const unsubscribe = builder(node);\n unsubscribe && subscriptions.add(unsubscribe);\n });\n\n this._unsubscribe.set(node.id, subscriptions);\n\n return graph;\n }\n\n private _createNode<TData = null, TProperties extends Record<string, any> = Record<string, any>>(\n getGraph: () => Graph,\n partial: NodeArg<TData, TProperties>,\n path: string[] = [],\n ignoreBuilders: string[] = [],\n ): Node<TData, TProperties> {\n // TODO(burdon): Document implications and rationale of deepSignal.\n const node: Node<TData, TProperties> = deepSignal({\n parent: null,\n data: null as TData, // TODO(burdon): Allow null property?\n properties: {} as TProperties,\n childrenMap: {},\n actionsMap: {},\n // TODO(burdon): Document.\n ...partial,\n\n get children() {\n return Object.values(node.childrenMap);\n },\n get actions() {\n return Object.values(node.actionsMap);\n },\n\n addProperty: (key, value) => {\n untracked(() => {\n (node.properties as Record<string, any>)[key] = value;\n });\n },\n removeProperty: (key) => {\n untracked(() => {\n delete (node.properties as Record<string, any>)[key];\n });\n },\n\n addNode: (builder, ...partials) => {\n return untracked(() => {\n return partials.map((partial) => {\n const builders = [...ignoreBuilders, builder];\n const childPath = [...path, 'childrenMap', partial.id];\n const child = this._createNode(getGraph, { ...partial, parent: node }, childPath, builders);\n node.childrenMap[child.id] = child;\n // TODO(burdon): Defer triggering recursive updates until task has completed.\n this._build(getGraph(), child, childPath, builders);\n return child;\n });\n });\n },\n removeNode: (id) => {\n return untracked(() => {\n const child = node.childrenMap[id];\n delete node.childrenMap[id];\n return child;\n });\n },\n\n addAction: (...partials) => {\n return untracked(() => {\n return partials.map((partial) => {\n const action = this._createAction(partial);\n if (action.keyBinding) {\n // TODO(burdon): Last writer wins.\n Mousetrap.bind(action.keyBinding, () => {\n action.invoke();\n });\n }\n\n node.actionsMap[action.id] = action;\n return action;\n });\n });\n },\n removeAction: (id) => {\n return untracked(() => {\n const action = node.actionsMap[id];\n if (action.keyBinding) {\n Mousetrap.unbind(action.keyBinding);\n }\n\n delete node.actionsMap[id];\n return action;\n });\n },\n }) as RevertDeepSignal<Node<TData, TProperties>>;\n\n // Only actions added at this stage are available to subsequent builders.\n // `addNode` immediately passes the new node to other builders.\n // As such, actions added later with `addAction` are not available to those builders.\n // Having actions available to subsequent builders is useful for building groups.\n partial.actions && partial.actions.forEach((action) => node.addAction(action));\n\n return node;\n }\n\n private _createAction<TProperties extends Record<string, any> = Record<string, any>>(\n partial: ActionArg<TProperties>,\n ): Action<TProperties> {\n const action: Action<TProperties> = deepSignal({\n properties: {} as TProperties,\n ...partial,\n actionsMap: {},\n get actions() {\n return Object.values(action.actionsMap);\n },\n addAction: (...partials) => {\n return untracked(() => {\n return partials.map((partial) => {\n const subAction = this._createAction(partial);\n action.actionsMap[subAction.id] = subAction;\n return subAction;\n });\n });\n },\n removeAction: (id) => {\n return untracked(() => {\n const subAction = action.actionsMap[id];\n delete action.actionsMap[id];\n return subAction;\n });\n },\n addProperty: (key, value) => {\n return untracked(() => {\n (action.properties as Record<string, any>)[key] = value;\n });\n },\n removeProperty: (key) => {\n return untracked(() => {\n delete (action.properties as Record<string, any>)[key];\n });\n },\n }) as RevertDeepSignal<Action<TProperties>>;\n\n partial.actions && partial.actions.forEach((subAction) => action.addAction(subAction));\n\n return action;\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport type { IconProps } from '@phosphor-icons/react';\nimport { type FC } from 'react';\n\nimport type { UnsubscribeCallback } from '@dxos/async';\n\nimport { type ActionArg, type Action, type Label } from './action';\n\n/**\n * Called when a node is added to the graph, allowing other node builders to add children, actions or properties.\n */\nexport type NodeBuilder = (parent: Node) => UnsubscribeCallback | void;\n\n/**\n * Represents a node in the graph.\n */\nexport type Node<TData = any, TProperties extends Record<string, any> = Record<string, any>> = {\n /**\n * Globally unique ID.\n */\n id: string;\n\n /**\n * Parent node in the graph.\n */\n parent: Node | null;\n\n /**\n * Label to be used when displaying the node.\n * For default labels, use a translated string.\n *\n * @example 'My Node'\n * @example ['unknown node label, { ns: 'example-plugin' }]\n */\n label: Label;\n\n /**\n * Description to be used when displaying a detailed view of the node.\n * For default descriptions, use a translated string.\n */\n description?: Label;\n\n /**\n * Icon to be used when displaying the node.\n */\n icon?: FC<IconProps>;\n\n /**\n * Properties of the node relevant to displaying the node.\n */\n // TODO(burdon): Make this extensible and move label, description, and icon into here?\n properties: TProperties;\n\n /**\n * Data the node represents.\n */\n // TODO(burdon): Type system (e.g., minimally provide identifier string vs. TypedObject vs. Graph mixin type system)?\n // type field would prevent convoluted sniffing of object properties. And allow direct pass-through for ECHO TypedObjects.\n // TODO(burdon): In some places `null` is cast to TData so make optional?\n data: TData;\n\n /**\n * Children of the node stored by their id.\n */\n // TODO(burdon): Rename nodes/nodeMap?\n childrenMap: Record<string, Node>;\n\n /**\n * Actions of the node stored by their id.\n */\n actionsMap: Record<string, Action>;\n\n /**\n * Children of the node in default order.\n */\n get children(): Node[];\n\n /**\n * Actions of the node in default order.\n */\n get actions(): Action[];\n\n addProperty(key: string, value: any): void;\n removeProperty(key: string): void;\n\n addNode<TChildData = null, TChildProperties extends Record<string, any> = Record<string, any>>(\n id: string,\n ...node: NodeArg<TChildData, TChildProperties>[]\n ): Node<TChildData, TChildProperties>[];\n removeNode(id: string): Node;\n\n addAction<TActionProperties extends Record<string, any> = Record<string, any>>(\n ...action: ActionArg<TActionProperties>[]\n ): Action<TActionProperties>[];\n removeAction(id: string): Action;\n};\n\nexport type NodeArg<TData = null, TProperties extends Record<string, any> = Record<string, any>> = Pick<\n Node,\n 'id' | 'label'\n> &\n Partial<Omit<Node<TData, TProperties>, 'id' | 'label' | 'actions'>> & { actions?: ActionArg[] };\n\nexport const isGraphNode = (data: unknown): data is Node =>\n data && typeof data === 'object' ? 'id' in data && 'label' in data : false;\n"],
5
- "mappings": "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",
6
- "names": ["deepSignal", "get", "Graph", "constructor", "_root", "_index", "deepSignal", "toJSON", "toLabel", "label", "Array", "isArray", "ns", "node", "id", "slice", "children", "length", "map", "undefined", "actions", "root", "getPath", "_setPath", "path", "findNode", "get", "traverse", "direction", "filter", "visitor", "depth", "Object", "values", "forEach", "child", "parent", "untracked", "deepSignal", "Mousetrap", "EventSubscriptions", "GraphBuilder", "_nodeBuilders", "Map", "_unsubscribe", "addNodeBuilder", "id", "builder", "set", "removeNodeBuilder", "delete", "build", "previousGraph", "startingPath", "graph", "Graph", "_createNode", "label", "_build", "root", "node", "path", "ignoreBuilders", "_setPath", "subscriptions", "get", "EventSubscriptions", "clear", "Array", "from", "entries", "filter", "findIndex", "ignore", "forEach", "_", "unsubscribe", "add", "getGraph", "partial", "deepSignal", "parent", "data", "properties", "childrenMap", "actionsMap", "children", "Object", "values", "actions", "addProperty", "key", "value", "untracked", "removeProperty", "addNode", "partials", "map", "builders", "childPath", "child", "removeNode", "addAction", "action", "_createAction", "keyBinding", "Mousetrap", "bind", "invoke", "removeAction", "unbind", "subAction", "isGraphNode", "data"]
4
+ "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { deepSignal } from 'deepsignal/react';\n// TODO(wittjosiah): Remove lodash dependency.\nimport get from 'lodash.get';\n\nimport { type Label } from './action';\nimport { type Node } from './node';\n\nexport type TraversalOptions = {\n /**\n * The node to start traversing from. Defaults to the root node.\n */\n node?: Node;\n\n /**\n * The direction to traverse the graph. Defaults to 'down'.\n */\n direction?: 'up' | 'down';\n\n /**\n * A predicate to filter nodes which are passed to the `visitor` callback.\n */\n filter?: (node: Node) => boolean;\n\n /**\n * A callback which is called for each node visited during traversal.\n */\n visitor?: (node: Node, path: string[]) => void;\n};\n\n/**\n * The Graph represents the structure of the application constructed via plugins.\n */\nexport class Graph {\n // TODO(wittjosiah): Should this support multiple paths to the same node?\n private readonly _index = deepSignal<{ [key: string]: string[] }>({});\n\n constructor(private readonly _root: Node) {}\n\n toJSON() {\n const toLabel = (label: Label) => (Array.isArray(label) ? `${label[1].ns}[${label[0]}]` : label);\n const toJSON = (node: Node): any => {\n return {\n id: node.id.slice(0, 16),\n label: toLabel(node.label),\n children: node.children.length ? node.children.map((node) => toJSON(node)) : undefined,\n actions: node.actions.length\n ? node.actions.map(({ id, label }) => ({\n id,\n label: toLabel(label),\n }))\n : undefined,\n };\n };\n\n return toJSON(this._root);\n }\n\n /**\n * The root node of the graph which is the entry point for all knowledge.\n */\n get root(): Node {\n return this._root;\n }\n\n /**\n * Get the path through the graph from the root to the node with the given id.\n */\n getPath(id: string): string[] | undefined {\n return this._index[id];\n }\n\n /**\n * @internal\n */\n _setPath(id: string, path: string[]) {\n this._index[id] = path;\n }\n\n /**\n * Find the node with the given id in the graph.\n */\n findNode(id: string): Node | undefined {\n const path = this.getPath(id);\n if (!path) {\n return undefined;\n }\n\n return path.length > 0 ? get(this._root, path) : this._root;\n }\n\n /**\n * Recursive breadth-first traversal.\n */\n traverse({ node = this._root, direction = 'down', filter, visitor }: TraversalOptions, depth = 0): void {\n if (!filter || filter(node)) {\n visitor?.(node, this.getPath(node.id)!);\n }\n\n if (direction === 'down') {\n Object.values(node.children).forEach((child) => this.traverse({ node: child, filter, visitor }));\n } else if (direction === 'up' && node.parent) {\n this.traverse({ node: node.parent, direction, filter, visitor }, depth + 1);\n }\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { untracked } from '@preact/signals-react';\nimport { type RevertDeepSignal, deepSignal } from 'deepsignal/react';\n\nimport { EventSubscriptions } from '@dxos/async';\nimport { Keyboard } from '@dxos/keyboard';\n\nimport type { ActionArg, Action } from './action';\nimport { Graph } from './graph';\nimport type { NodeArg, Node, NodeBuilder } from './node';\n\n/**\n * The builder...\n */\nexport class GraphBuilder {\n private readonly _nodeBuilders = new Map<string, NodeBuilder>();\n private readonly _unsubscribe = new Map<string, EventSubscriptions>();\n\n /**\n * Register a node builder which will be called in order to construct the graph.\n */\n addNodeBuilder(id: string, builder: NodeBuilder): GraphBuilder {\n this._nodeBuilders.set(id, builder);\n return this;\n }\n\n /**\n * Remove a node builder from the graph builder.\n */\n removeNodeBuilder(id: string): GraphBuilder {\n this._nodeBuilders.delete(id);\n return this;\n }\n\n /**\n * Construct the graph, starting by calling all registered node builders on the root node.\n * Node builders will be filtered out as they are used such that they are only used once on any given path.\n * @param previousGraph If provided, the graph will be updated in place.\n * @param startingPath If provided, the graph will be updated starting at the given path.\n */\n build(previousGraph?: Graph, startingPath: string[] = []): Graph {\n const graph: Graph = previousGraph ?? new Graph(this._createNode(() => graph, { id: 'root', label: 'Root' }));\n return this._build(graph, graph.root, startingPath);\n }\n\n /**\n * Called recursively.\n */\n private _build(graph: Graph, node: Node, path: string[] = [], ignoreBuilders: string[] = []): Graph {\n // TODO(wittjosiah): Should this support multiple paths to the same node?\n graph._setPath(node.id, path);\n\n // TODO(burdon): Document.\n const subscriptions = this._unsubscribe.get(node.id) ?? new EventSubscriptions();\n subscriptions.clear();\n\n Array.from(this._nodeBuilders.entries())\n .filter(([id]) => ignoreBuilders.findIndex((ignore) => ignore === id) === -1)\n .forEach(([_, builder]) => {\n const unsubscribe = builder(node);\n unsubscribe && subscriptions.add(unsubscribe);\n });\n\n this._unsubscribe.set(node.id, subscriptions);\n\n return graph;\n }\n\n private _createNode<TData = null, TProperties extends Record<string, any> = Record<string, any>>(\n getGraph: () => Graph,\n partial: NodeArg<TData, TProperties>,\n path: string[] = [],\n ignoreBuilders: string[] = [],\n ): Node<TData, TProperties> {\n // TODO(burdon): Document implications and rationale of deepSignal.\n const node: Node<TData, TProperties> = deepSignal({\n parent: null,\n data: null as TData, // TODO(burdon): Allow null property?\n properties: {} as TProperties,\n childrenMap: {},\n actionsMap: {},\n // TODO(burdon): Document.\n ...partial,\n\n get children() {\n return Object.values(node.childrenMap);\n },\n get actions() {\n return Object.values(node.actionsMap);\n },\n\n //\n // Properties\n //\n\n addProperty: (key, value) => {\n untracked(() => {\n (node.properties as Record<string, any>)[key] = value;\n });\n },\n removeProperty: (key) => {\n untracked(() => {\n delete (node.properties as Record<string, any>)[key];\n });\n },\n\n //\n // Nodes\n //\n\n addNode: (builder, ...partials) => {\n return untracked(() => {\n return partials.map((partial) => {\n const builders = [...ignoreBuilders, builder];\n const childPath = [...path, 'childrenMap', partial.id];\n const child = this._createNode(getGraph, { ...partial, parent: node }, childPath, builders);\n node.childrenMap[child.id] = child;\n // TODO(burdon): Defer triggering recursive updates until task has completed.\n this._build(getGraph(), child, childPath, builders);\n return child;\n });\n });\n },\n removeNode: (id) => {\n return untracked(() => {\n const child = node.childrenMap[id];\n delete node.childrenMap[id];\n return child;\n });\n },\n\n //\n // Actions\n //\n\n addAction: (...partials) => {\n return untracked(() => {\n return partials.map((partial) => {\n const action = this._createAction(partial);\n if (action.keyBinding) {\n Keyboard.singleton.getContext(path.join('/')).bind({\n binding: action.keyBinding!,\n handler: () => {\n action.invoke();\n },\n data: action.label,\n });\n }\n\n node.actionsMap[action.id] = action;\n return action;\n });\n });\n },\n removeAction: (id) => {\n return untracked(() => {\n const action = node.actionsMap[id];\n if (action.keyBinding) {\n // keyboardjs.unbind(action.keyBinding);\n }\n\n delete node.actionsMap[id];\n return action;\n });\n },\n }) as RevertDeepSignal<Node<TData, TProperties>>;\n\n // Only actions added at this stage are available to subsequent builders.\n // `addNode` immediately passes the new node to other builders.\n // As such, actions added later with `addAction` are not available to those builders.\n // Having actions available to subsequent builders is useful for building groups.\n partial.actions && partial.actions.forEach((action) => node.addAction(action));\n\n return node;\n }\n\n private _createAction<TProperties extends Record<string, any> = Record<string, any>>(\n partial: ActionArg<TProperties>,\n ): Action<TProperties> {\n const action: Action<TProperties> = deepSignal({\n properties: {} as TProperties,\n ...partial,\n actionsMap: {},\n get actions() {\n return Object.values(action.actionsMap);\n },\n addAction: (...partials) => {\n return untracked(() => {\n return partials.map((partial) => {\n const subAction = this._createAction(partial);\n action.actionsMap[subAction.id] = subAction;\n return subAction;\n });\n });\n },\n removeAction: (id) => {\n return untracked(() => {\n const subAction = action.actionsMap[id];\n delete action.actionsMap[id];\n return subAction;\n });\n },\n addProperty: (key, value) => {\n return untracked(() => {\n (action.properties as Record<string, any>)[key] = value;\n });\n },\n removeProperty: (key) => {\n return untracked(() => {\n delete (action.properties as Record<string, any>)[key];\n });\n },\n }) as RevertDeepSignal<Action<TProperties>>;\n\n partial.actions && partial.actions.forEach((subAction) => action.addAction(subAction));\n\n return action;\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport type { IconProps } from '@phosphor-icons/react';\nimport { type FC } from 'react';\n\nimport type { UnsubscribeCallback } from '@dxos/async';\n\nimport { type ActionArg, type Action, type Label } from './action';\n\n/**\n * Called when a node is added to the graph, allowing other node builders to add children, actions or properties.\n */\nexport type NodeBuilder = (parent: Node) => UnsubscribeCallback | void;\n\n/**\n * Represents a node in the graph.\n */\nexport type Node<TData = any, TProperties extends Record<string, any> = Record<string, any>> = {\n /**\n * Globally unique ID.\n */\n id: string;\n\n /**\n * Parent node in the graph.\n */\n parent: Node | null;\n\n /**\n * Label to be used when displaying the node.\n * For default labels, use a translated string.\n *\n * @example 'My Node'\n * @example ['unknown node label, { ns: 'example-plugin' }]\n */\n label: Label;\n\n /**\n * Description to be used when displaying a detailed view of the node.\n * For default descriptions, use a translated string.\n */\n description?: Label;\n\n /**\n * Icon to be used when displaying the node.\n */\n icon?: FC<IconProps>;\n\n /**\n * Properties of the node relevant to displaying the node.\n */\n // TODO(burdon): Make this extensible and move label, description, and icon into here?\n properties: TProperties;\n\n /**\n * Data the node represents.\n */\n // TODO(burdon): Type system (e.g., minimally provide identifier string vs. TypedObject vs. Graph mixin type system)?\n // type field would prevent convoluted sniffing of object properties. And allow direct pass-through for ECHO TypedObjects.\n // TODO(burdon): In some places `null` is cast to TData so make optional?\n data: TData;\n\n /**\n * Children of the node stored by their id.\n */\n // TODO(burdon): Rename nodes/nodeMap?\n childrenMap: Record<string, Node>;\n\n /**\n * Actions of the node stored by their id.\n */\n actionsMap: Record<string, Action>;\n\n /**\n * Children of the node in default order.\n */\n get children(): Node[];\n\n /**\n * Actions of the node in default order.\n */\n get actions(): Action[];\n\n addProperty(key: string, value: any): void;\n removeProperty(key: string): void;\n\n addNode<TChildData = null, TChildProperties extends Record<string, any> = Record<string, any>>(\n id: string,\n ...node: NodeArg<TChildData, TChildProperties>[]\n ): Node<TChildData, TChildProperties>[];\n removeNode(id: string): Node;\n\n addAction<TActionProperties extends Record<string, any> = Record<string, any>>(\n ...action: ActionArg<TActionProperties>[]\n ): Action<TActionProperties>[];\n removeAction(id: string): Action;\n};\n\nexport type NodeArg<TData = null, TProperties extends Record<string, any> = Record<string, any>> = Pick<\n Node,\n 'id' | 'label'\n> &\n Partial<Omit<Node<TData, TProperties>, 'id' | 'label' | 'actions'>> & { actions?: ActionArg[] };\n\nexport const isGraphNode = (data: unknown): data is Node =>\n data && typeof data === 'object' ? 'id' in data && 'label' in data : false;\n"],
5
+ "mappings": "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",
6
+ "names": ["deepSignal", "get", "Graph", "constructor", "_root", "_index", "deepSignal", "toJSON", "toLabel", "label", "Array", "isArray", "ns", "node", "id", "slice", "children", "length", "map", "undefined", "actions", "root", "getPath", "_setPath", "path", "findNode", "get", "traverse", "direction", "filter", "visitor", "depth", "Object", "values", "forEach", "child", "parent", "untracked", "deepSignal", "EventSubscriptions", "Keyboard", "GraphBuilder", "_nodeBuilders", "Map", "_unsubscribe", "addNodeBuilder", "id", "builder", "set", "removeNodeBuilder", "delete", "build", "previousGraph", "startingPath", "graph", "Graph", "_createNode", "label", "_build", "root", "node", "path", "ignoreBuilders", "_setPath", "subscriptions", "get", "EventSubscriptions", "clear", "Array", "from", "entries", "filter", "findIndex", "ignore", "forEach", "_", "unsubscribe", "add", "getGraph", "partial", "deepSignal", "parent", "data", "properties", "childrenMap", "actionsMap", "children", "Object", "values", "actions", "addProperty", "key", "value", "untracked", "removeProperty", "addNode", "partials", "map", "builders", "childPath", "child", "removeNode", "addAction", "action", "_createAction", "keyBinding", "Keyboard", "singleton", "getContext", "join", "bind", "binding", "handler", "invoke", "removeAction", "subAction", "isGraphNode", "data"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"packages/sdk/app-graph/src/action.ts":{"bytes":3043,"imports":[],"format":"esm"},"packages/sdk/app-graph/src/graph.ts":{"bytes":9066,"imports":[{"path":"deepsignal/react","kind":"import-statement","external":true},{"path":"lodash.get","kind":"import-statement","external":true}],"format":"esm"},"packages/sdk/app-graph/src/graph-builder.ts":{"bytes":22793,"imports":[{"path":"@preact/signals-react","kind":"import-statement","external":true},{"path":"deepsignal/react","kind":"import-statement","external":true},{"path":"mousetrap","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"packages/sdk/app-graph/src/graph.ts","kind":"import-statement","original":"./graph"}],"format":"esm"},"packages/sdk/app-graph/src/node.ts":{"bytes":4772,"imports":[],"format":"esm"},"packages/sdk/app-graph/src/index.ts":{"bytes":722,"imports":[{"path":"packages/sdk/app-graph/src/action.ts","kind":"import-statement","original":"./action"},{"path":"packages/sdk/app-graph/src/graph.ts","kind":"import-statement","original":"./graph"},{"path":"packages/sdk/app-graph/src/graph-builder.ts","kind":"import-statement","original":"./graph-builder"},{"path":"packages/sdk/app-graph/src/node.ts","kind":"import-statement","original":"./node"}],"format":"esm"},"packages/sdk/app-graph/src/testing.ts":{"bytes":11884,"imports":[],"format":"esm"}},"outputs":{"packages/sdk/app-graph/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":19302},"packages/sdk/app-graph/dist/lib/browser/index.mjs":{"imports":[{"path":"deepsignal/react","kind":"import-statement","external":true},{"path":"lodash.get","kind":"import-statement","external":true},{"path":"@preact/signals-react","kind":"import-statement","external":true},{"path":"deepsignal/react","kind":"import-statement","external":true},{"path":"mousetrap","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true}],"exports":["Graph","GraphBuilder","isGraphNode"],"entryPoint":"packages/sdk/app-graph/src/index.ts","inputs":{"packages/sdk/app-graph/src/index.ts":{"bytesInOutput":0},"packages/sdk/app-graph/src/graph.ts":{"bytesInOutput":1818},"packages/sdk/app-graph/src/graph-builder.ts":{"bytesInOutput":5294},"packages/sdk/app-graph/src/node.ts":{"bytesInOutput":104}},"bytes":7428},"packages/sdk/app-graph/dist/lib/browser/testing.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":6167},"packages/sdk/app-graph/dist/lib/browser/testing.mjs":{"imports":[],"exports":["buildGraph","createTestNodeBuilder"],"entryPoint":"packages/sdk/app-graph/src/testing.ts","inputs":{"packages/sdk/app-graph/src/testing.ts":{"bytesInOutput":2180}},"bytes":2308}}}
1
+ {"inputs":{"packages/sdk/app-graph/src/action.ts":{"bytes":3043,"imports":[],"format":"esm"},"packages/sdk/app-graph/src/graph.ts":{"bytes":9237,"imports":[{"path":"deepsignal/react","kind":"import-statement","external":true},{"path":"lodash.get","kind":"import-statement","external":true}],"format":"esm"},"packages/sdk/app-graph/src/graph-builder.ts":{"bytes":23684,"imports":[{"path":"@preact/signals-react","kind":"import-statement","external":true},{"path":"deepsignal/react","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/keyboard","kind":"import-statement","external":true},{"path":"packages/sdk/app-graph/src/graph.ts","kind":"import-statement","original":"./graph"}],"format":"esm"},"packages/sdk/app-graph/src/node.ts":{"bytes":4772,"imports":[],"format":"esm"},"packages/sdk/app-graph/src/index.ts":{"bytes":722,"imports":[{"path":"packages/sdk/app-graph/src/action.ts","kind":"import-statement","original":"./action"},{"path":"packages/sdk/app-graph/src/graph.ts","kind":"import-statement","original":"./graph"},{"path":"packages/sdk/app-graph/src/graph-builder.ts","kind":"import-statement","original":"./graph-builder"},{"path":"packages/sdk/app-graph/src/node.ts","kind":"import-statement","original":"./node"}],"format":"esm"},"packages/sdk/app-graph/src/testing.ts":{"bytes":11884,"imports":[],"format":"esm"}},"outputs":{"packages/sdk/app-graph/dist/lib/browser/index.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":19741},"packages/sdk/app-graph/dist/lib/browser/index.mjs":{"imports":[{"path":"deepsignal/react","kind":"import-statement","external":true},{"path":"lodash.get","kind":"import-statement","external":true},{"path":"@preact/signals-react","kind":"import-statement","external":true},{"path":"deepsignal/react","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/keyboard","kind":"import-statement","external":true}],"exports":["Graph","GraphBuilder","isGraphNode"],"entryPoint":"packages/sdk/app-graph/src/index.ts","inputs":{"packages/sdk/app-graph/src/index.ts":{"bytesInOutput":0},"packages/sdk/app-graph/src/graph.ts":{"bytesInOutput":1841},"packages/sdk/app-graph/src/graph-builder.ts":{"bytesInOutput":5503},"packages/sdk/app-graph/src/node.ts":{"bytesInOutput":104}},"bytes":7660},"packages/sdk/app-graph/dist/lib/browser/testing.mjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":6167},"packages/sdk/app-graph/dist/lib/browser/testing.mjs":{"imports":[],"exports":["buildGraph","createTestNodeBuilder"],"entryPoint":"packages/sdk/app-graph/src/testing.ts","inputs":{"packages/sdk/app-graph/src/testing.ts":{"bytesInOutput":2180}},"bytes":2308}}}
@@ -37,8 +37,8 @@ var import_react = require("deepsignal/react");
37
37
  var import_lodash = __toESM(require("lodash.get"));
38
38
  var import_signals_react = require("@preact/signals-react");
39
39
  var import_react2 = require("deepsignal/react");
40
- var import_mousetrap = __toESM(require("mousetrap"));
41
40
  var import_async = require("@dxos/async");
41
+ var import_keyboard = require("@dxos/keyboard");
42
42
  var Graph = class {
43
43
  constructor(_root) {
44
44
  this._root = _root;
@@ -92,7 +92,7 @@ var Graph = class {
92
92
  */
93
93
  traverse({ node = this._root, direction = "down", filter, visitor }, depth = 0) {
94
94
  if (!filter || filter(node)) {
95
- visitor?.(node);
95
+ visitor?.(node, this.getPath(node.id));
96
96
  }
97
97
  if (direction === "down") {
98
98
  Object.values(node.children).forEach((child) => this.traverse({
@@ -171,6 +171,9 @@ var GraphBuilder = class {
171
171
  get actions() {
172
172
  return Object.values(node.actionsMap);
173
173
  },
174
+ //
175
+ // Properties
176
+ //
174
177
  addProperty: (key, value) => {
175
178
  (0, import_signals_react.untracked)(() => {
176
179
  node.properties[key] = value;
@@ -181,6 +184,9 @@ var GraphBuilder = class {
181
184
  delete node.properties[key];
182
185
  });
183
186
  },
187
+ //
188
+ // Nodes
189
+ //
184
190
  addNode: (builder, ...partials) => {
185
191
  return (0, import_signals_react.untracked)(() => {
186
192
  return partials.map((partial2) => {
@@ -210,13 +216,20 @@ var GraphBuilder = class {
210
216
  return child;
211
217
  });
212
218
  },
219
+ //
220
+ // Actions
221
+ //
213
222
  addAction: (...partials) => {
214
223
  return (0, import_signals_react.untracked)(() => {
215
224
  return partials.map((partial2) => {
216
225
  const action = this._createAction(partial2);
217
226
  if (action.keyBinding) {
218
- import_mousetrap.default.bind(action.keyBinding, () => {
219
- action.invoke();
227
+ import_keyboard.Keyboard.singleton.getContext(path.join("/")).bind({
228
+ binding: action.keyBinding,
229
+ handler: () => {
230
+ action.invoke();
231
+ },
232
+ data: action.label
220
233
  });
221
234
  }
222
235
  node.actionsMap[action.id] = action;
@@ -228,7 +241,6 @@ var GraphBuilder = class {
228
241
  return (0, import_signals_react.untracked)(() => {
229
242
  const action = node.actionsMap[id];
230
243
  if (action.keyBinding) {
231
- import_mousetrap.default.unbind(action.keyBinding);
232
244
  }
233
245
  delete node.actionsMap[id];
234
246
  return action;
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/graph.ts", "../../../src/graph-builder.ts", "../../../src/node.ts"],
4
- "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { deepSignal } from 'deepsignal/react';\n// TODO(wittjosiah): Remove lodash dependency.\nimport get from 'lodash.get';\n\nimport { type Label } from './action';\nimport { type Node } from './node';\n\nexport type TraversalOptions = {\n /**\n * The node to start traversing from. Defaults to the root node.\n */\n node?: Node;\n\n /**\n * The direction to traverse the graph. Defaults to 'down'.\n */\n direction?: 'up' | 'down';\n\n /**\n * A predicate to filter nodes which are passed to the `visitor` callback.\n */\n filter?: (node: Node) => boolean;\n\n /**\n * A callback which is called for each node visited during traversal.\n */\n visitor?: (node: Node) => void;\n};\n\n/**\n * The Graph represents...\n */\nexport class Graph {\n // TODO(burdon): Document.\n // TODO(wittjosiah): Should this support multiple paths to the same node?\n private readonly _index = deepSignal<{ [key: string]: string[] }>({});\n\n constructor(private readonly _root: Node) {}\n\n toJSON() {\n const toLabel = (label: Label) => (Array.isArray(label) ? `${label[1].ns}[${label[0]}]` : label);\n const toJSON = (node: Node): any => {\n return {\n id: node.id.slice(0, 16),\n label: toLabel(node.label),\n children: node.children.length ? node.children.map((node) => toJSON(node)) : undefined,\n actions: node.actions.length\n ? node.actions.map(({ id, label }) => ({\n id,\n label: toLabel(label),\n }))\n : undefined,\n };\n };\n\n return toJSON(this._root);\n }\n\n /**\n * The root node of the graph which is the entry point for all knowledge.\n */\n get root(): Node {\n return this._root;\n }\n\n /**\n * Get the path through the graph from the root to the node with the given id.\n */\n getPath(id: string): string[] | undefined {\n return this._index[id];\n }\n\n /**\n * @internal\n */\n _setPath(id: string, path: string[]) {\n this._index[id] = path;\n }\n\n /**\n * Find the node with the given id in the graph.\n */\n findNode(id: string): Node | undefined {\n const path = this.getPath(id);\n if (!path) {\n return undefined;\n }\n\n return path.length > 0 ? get(this._root, path) : this._root;\n }\n\n /**\n * Recursive breadth-first traversal.\n */\n traverse({ node = this._root, direction = 'down', filter, visitor }: TraversalOptions, depth = 0): void {\n if (!filter || filter(node)) {\n visitor?.(node);\n }\n\n if (direction === 'down') {\n Object.values(node.children).forEach((child) => this.traverse({ node: child, filter, visitor }));\n } else if (direction === 'up' && node.parent) {\n this.traverse({ node: node.parent, direction, filter, visitor }, depth + 1);\n }\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { untracked } from '@preact/signals-react';\nimport { type RevertDeepSignal, deepSignal } from 'deepsignal/react';\nimport Mousetrap from 'mousetrap';\n\nimport { EventSubscriptions } from '@dxos/async';\n\nimport type { ActionArg, Action } from './action';\nimport { Graph } from './graph';\nimport type { NodeArg, Node, NodeBuilder } from './node';\n\n/**\n * The builder...\n */\nexport class GraphBuilder {\n private readonly _nodeBuilders = new Map<string, NodeBuilder>();\n private readonly _unsubscribe = new Map<string, EventSubscriptions>();\n\n /**\n * Register a node builder which will be called in order to construct the graph.\n */\n addNodeBuilder(id: string, builder: NodeBuilder): GraphBuilder {\n this._nodeBuilders.set(id, builder);\n return this;\n }\n\n /**\n * Remove a node builder from the graph builder.\n */\n removeNodeBuilder(id: string): GraphBuilder {\n this._nodeBuilders.delete(id);\n return this;\n }\n\n /**\n * Construct the graph, starting by calling all registered node builders on the root node.\n * Node builders will be filtered out as they are used such that they are only used once on any given path.\n * @param previousGraph If provided, the graph will be updated in place.\n * @param startingPath If provided, the graph will be updated starting at the given path.\n */\n build(previousGraph?: Graph, startingPath: string[] = []): Graph {\n const graph: Graph = previousGraph ?? new Graph(this._createNode(() => graph, { id: 'root', label: 'Root' }));\n return this._build(graph, graph.root, startingPath);\n }\n\n /**\n * Called recursively.\n */\n private _build(graph: Graph, node: Node, path: string[] = [], ignoreBuilders: string[] = []): Graph {\n // TODO(wittjosiah): Should this support multiple paths to the same node?\n graph._setPath(node.id, path);\n\n // TODO(burdon): Document.\n const subscriptions = this._unsubscribe.get(node.id) ?? new EventSubscriptions();\n subscriptions.clear();\n\n Array.from(this._nodeBuilders.entries())\n .filter(([id]) => ignoreBuilders.findIndex((ignore) => ignore === id) === -1)\n .forEach(([_, builder]) => {\n const unsubscribe = builder(node);\n unsubscribe && subscriptions.add(unsubscribe);\n });\n\n this._unsubscribe.set(node.id, subscriptions);\n\n return graph;\n }\n\n private _createNode<TData = null, TProperties extends Record<string, any> = Record<string, any>>(\n getGraph: () => Graph,\n partial: NodeArg<TData, TProperties>,\n path: string[] = [],\n ignoreBuilders: string[] = [],\n ): Node<TData, TProperties> {\n // TODO(burdon): Document implications and rationale of deepSignal.\n const node: Node<TData, TProperties> = deepSignal({\n parent: null,\n data: null as TData, // TODO(burdon): Allow null property?\n properties: {} as TProperties,\n childrenMap: {},\n actionsMap: {},\n // TODO(burdon): Document.\n ...partial,\n\n get children() {\n return Object.values(node.childrenMap);\n },\n get actions() {\n return Object.values(node.actionsMap);\n },\n\n addProperty: (key, value) => {\n untracked(() => {\n (node.properties as Record<string, any>)[key] = value;\n });\n },\n removeProperty: (key) => {\n untracked(() => {\n delete (node.properties as Record<string, any>)[key];\n });\n },\n\n addNode: (builder, ...partials) => {\n return untracked(() => {\n return partials.map((partial) => {\n const builders = [...ignoreBuilders, builder];\n const childPath = [...path, 'childrenMap', partial.id];\n const child = this._createNode(getGraph, { ...partial, parent: node }, childPath, builders);\n node.childrenMap[child.id] = child;\n // TODO(burdon): Defer triggering recursive updates until task has completed.\n this._build(getGraph(), child, childPath, builders);\n return child;\n });\n });\n },\n removeNode: (id) => {\n return untracked(() => {\n const child = node.childrenMap[id];\n delete node.childrenMap[id];\n return child;\n });\n },\n\n addAction: (...partials) => {\n return untracked(() => {\n return partials.map((partial) => {\n const action = this._createAction(partial);\n if (action.keyBinding) {\n // TODO(burdon): Last writer wins.\n Mousetrap.bind(action.keyBinding, () => {\n action.invoke();\n });\n }\n\n node.actionsMap[action.id] = action;\n return action;\n });\n });\n },\n removeAction: (id) => {\n return untracked(() => {\n const action = node.actionsMap[id];\n if (action.keyBinding) {\n Mousetrap.unbind(action.keyBinding);\n }\n\n delete node.actionsMap[id];\n return action;\n });\n },\n }) as RevertDeepSignal<Node<TData, TProperties>>;\n\n // Only actions added at this stage are available to subsequent builders.\n // `addNode` immediately passes the new node to other builders.\n // As such, actions added later with `addAction` are not available to those builders.\n // Having actions available to subsequent builders is useful for building groups.\n partial.actions && partial.actions.forEach((action) => node.addAction(action));\n\n return node;\n }\n\n private _createAction<TProperties extends Record<string, any> = Record<string, any>>(\n partial: ActionArg<TProperties>,\n ): Action<TProperties> {\n const action: Action<TProperties> = deepSignal({\n properties: {} as TProperties,\n ...partial,\n actionsMap: {},\n get actions() {\n return Object.values(action.actionsMap);\n },\n addAction: (...partials) => {\n return untracked(() => {\n return partials.map((partial) => {\n const subAction = this._createAction(partial);\n action.actionsMap[subAction.id] = subAction;\n return subAction;\n });\n });\n },\n removeAction: (id) => {\n return untracked(() => {\n const subAction = action.actionsMap[id];\n delete action.actionsMap[id];\n return subAction;\n });\n },\n addProperty: (key, value) => {\n return untracked(() => {\n (action.properties as Record<string, any>)[key] = value;\n });\n },\n removeProperty: (key) => {\n return untracked(() => {\n delete (action.properties as Record<string, any>)[key];\n });\n },\n }) as RevertDeepSignal<Action<TProperties>>;\n\n partial.actions && partial.actions.forEach((subAction) => action.addAction(subAction));\n\n return action;\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport type { IconProps } from '@phosphor-icons/react';\nimport { type FC } from 'react';\n\nimport type { UnsubscribeCallback } from '@dxos/async';\n\nimport { type ActionArg, type Action, type Label } from './action';\n\n/**\n * Called when a node is added to the graph, allowing other node builders to add children, actions or properties.\n */\nexport type NodeBuilder = (parent: Node) => UnsubscribeCallback | void;\n\n/**\n * Represents a node in the graph.\n */\nexport type Node<TData = any, TProperties extends Record<string, any> = Record<string, any>> = {\n /**\n * Globally unique ID.\n */\n id: string;\n\n /**\n * Parent node in the graph.\n */\n parent: Node | null;\n\n /**\n * Label to be used when displaying the node.\n * For default labels, use a translated string.\n *\n * @example 'My Node'\n * @example ['unknown node label, { ns: 'example-plugin' }]\n */\n label: Label;\n\n /**\n * Description to be used when displaying a detailed view of the node.\n * For default descriptions, use a translated string.\n */\n description?: Label;\n\n /**\n * Icon to be used when displaying the node.\n */\n icon?: FC<IconProps>;\n\n /**\n * Properties of the node relevant to displaying the node.\n */\n // TODO(burdon): Make this extensible and move label, description, and icon into here?\n properties: TProperties;\n\n /**\n * Data the node represents.\n */\n // TODO(burdon): Type system (e.g., minimally provide identifier string vs. TypedObject vs. Graph mixin type system)?\n // type field would prevent convoluted sniffing of object properties. And allow direct pass-through for ECHO TypedObjects.\n // TODO(burdon): In some places `null` is cast to TData so make optional?\n data: TData;\n\n /**\n * Children of the node stored by their id.\n */\n // TODO(burdon): Rename nodes/nodeMap?\n childrenMap: Record<string, Node>;\n\n /**\n * Actions of the node stored by their id.\n */\n actionsMap: Record<string, Action>;\n\n /**\n * Children of the node in default order.\n */\n get children(): Node[];\n\n /**\n * Actions of the node in default order.\n */\n get actions(): Action[];\n\n addProperty(key: string, value: any): void;\n removeProperty(key: string): void;\n\n addNode<TChildData = null, TChildProperties extends Record<string, any> = Record<string, any>>(\n id: string,\n ...node: NodeArg<TChildData, TChildProperties>[]\n ): Node<TChildData, TChildProperties>[];\n removeNode(id: string): Node;\n\n addAction<TActionProperties extends Record<string, any> = Record<string, any>>(\n ...action: ActionArg<TActionProperties>[]\n ): Action<TActionProperties>[];\n removeAction(id: string): Action;\n};\n\nexport type NodeArg<TData = null, TProperties extends Record<string, any> = Record<string, any>> = Pick<\n Node,\n 'id' | 'label'\n> &\n Partial<Omit<Node<TData, TProperties>, 'id' | 'label' | 'actions'>> & { actions?: ActionArg[] };\n\nexport const isGraphNode = (data: unknown): data is Node =>\n data && typeof data === 'object' ? 'id' in data && 'label' in data : false;\n"],
5
- "mappings": "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",
6
- "names": ["import_react", "Graph", "constructor", "_root", "_index", "deepSignal", "toJSON", "toLabel", "label", "Array", "isArray", "ns", "node", "id", "slice", "children", "length", "map", "undefined", "actions", "root", "getPath", "_setPath", "path", "findNode", "get", "traverse", "direction", "filter", "visitor", "depth", "Object", "values", "forEach", "child", "parent", "GraphBuilder", "_nodeBuilders", "Map", "_unsubscribe", "addNodeBuilder", "builder", "set", "removeNodeBuilder", "delete", "build", "previousGraph", "startingPath", "graph", "_createNode", "_build", "ignoreBuilders", "subscriptions", "EventSubscriptions", "clear", "from", "entries", "findIndex", "ignore", "_", "unsubscribe", "add", "getGraph", "partial", "data", "properties", "childrenMap", "actionsMap", "addProperty", "key", "value", "untracked", "removeProperty", "addNode", "partials", "builders", "childPath", "removeNode", "addAction", "action", "_createAction", "keyBinding", "Mousetrap", "bind", "invoke", "removeAction", "unbind", "subAction", "isGraphNode"]
4
+ "sourcesContent": ["//\n// Copyright 2023 DXOS.org\n//\n\nimport { deepSignal } from 'deepsignal/react';\n// TODO(wittjosiah): Remove lodash dependency.\nimport get from 'lodash.get';\n\nimport { type Label } from './action';\nimport { type Node } from './node';\n\nexport type TraversalOptions = {\n /**\n * The node to start traversing from. Defaults to the root node.\n */\n node?: Node;\n\n /**\n * The direction to traverse the graph. Defaults to 'down'.\n */\n direction?: 'up' | 'down';\n\n /**\n * A predicate to filter nodes which are passed to the `visitor` callback.\n */\n filter?: (node: Node) => boolean;\n\n /**\n * A callback which is called for each node visited during traversal.\n */\n visitor?: (node: Node, path: string[]) => void;\n};\n\n/**\n * The Graph represents the structure of the application constructed via plugins.\n */\nexport class Graph {\n // TODO(wittjosiah): Should this support multiple paths to the same node?\n private readonly _index = deepSignal<{ [key: string]: string[] }>({});\n\n constructor(private readonly _root: Node) {}\n\n toJSON() {\n const toLabel = (label: Label) => (Array.isArray(label) ? `${label[1].ns}[${label[0]}]` : label);\n const toJSON = (node: Node): any => {\n return {\n id: node.id.slice(0, 16),\n label: toLabel(node.label),\n children: node.children.length ? node.children.map((node) => toJSON(node)) : undefined,\n actions: node.actions.length\n ? node.actions.map(({ id, label }) => ({\n id,\n label: toLabel(label),\n }))\n : undefined,\n };\n };\n\n return toJSON(this._root);\n }\n\n /**\n * The root node of the graph which is the entry point for all knowledge.\n */\n get root(): Node {\n return this._root;\n }\n\n /**\n * Get the path through the graph from the root to the node with the given id.\n */\n getPath(id: string): string[] | undefined {\n return this._index[id];\n }\n\n /**\n * @internal\n */\n _setPath(id: string, path: string[]) {\n this._index[id] = path;\n }\n\n /**\n * Find the node with the given id in the graph.\n */\n findNode(id: string): Node | undefined {\n const path = this.getPath(id);\n if (!path) {\n return undefined;\n }\n\n return path.length > 0 ? get(this._root, path) : this._root;\n }\n\n /**\n * Recursive breadth-first traversal.\n */\n traverse({ node = this._root, direction = 'down', filter, visitor }: TraversalOptions, depth = 0): void {\n if (!filter || filter(node)) {\n visitor?.(node, this.getPath(node.id)!);\n }\n\n if (direction === 'down') {\n Object.values(node.children).forEach((child) => this.traverse({ node: child, filter, visitor }));\n } else if (direction === 'up' && node.parent) {\n this.traverse({ node: node.parent, direction, filter, visitor }, depth + 1);\n }\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { untracked } from '@preact/signals-react';\nimport { type RevertDeepSignal, deepSignal } from 'deepsignal/react';\n\nimport { EventSubscriptions } from '@dxos/async';\nimport { Keyboard } from '@dxos/keyboard';\n\nimport type { ActionArg, Action } from './action';\nimport { Graph } from './graph';\nimport type { NodeArg, Node, NodeBuilder } from './node';\n\n/**\n * The builder...\n */\nexport class GraphBuilder {\n private readonly _nodeBuilders = new Map<string, NodeBuilder>();\n private readonly _unsubscribe = new Map<string, EventSubscriptions>();\n\n /**\n * Register a node builder which will be called in order to construct the graph.\n */\n addNodeBuilder(id: string, builder: NodeBuilder): GraphBuilder {\n this._nodeBuilders.set(id, builder);\n return this;\n }\n\n /**\n * Remove a node builder from the graph builder.\n */\n removeNodeBuilder(id: string): GraphBuilder {\n this._nodeBuilders.delete(id);\n return this;\n }\n\n /**\n * Construct the graph, starting by calling all registered node builders on the root node.\n * Node builders will be filtered out as they are used such that they are only used once on any given path.\n * @param previousGraph If provided, the graph will be updated in place.\n * @param startingPath If provided, the graph will be updated starting at the given path.\n */\n build(previousGraph?: Graph, startingPath: string[] = []): Graph {\n const graph: Graph = previousGraph ?? new Graph(this._createNode(() => graph, { id: 'root', label: 'Root' }));\n return this._build(graph, graph.root, startingPath);\n }\n\n /**\n * Called recursively.\n */\n private _build(graph: Graph, node: Node, path: string[] = [], ignoreBuilders: string[] = []): Graph {\n // TODO(wittjosiah): Should this support multiple paths to the same node?\n graph._setPath(node.id, path);\n\n // TODO(burdon): Document.\n const subscriptions = this._unsubscribe.get(node.id) ?? new EventSubscriptions();\n subscriptions.clear();\n\n Array.from(this._nodeBuilders.entries())\n .filter(([id]) => ignoreBuilders.findIndex((ignore) => ignore === id) === -1)\n .forEach(([_, builder]) => {\n const unsubscribe = builder(node);\n unsubscribe && subscriptions.add(unsubscribe);\n });\n\n this._unsubscribe.set(node.id, subscriptions);\n\n return graph;\n }\n\n private _createNode<TData = null, TProperties extends Record<string, any> = Record<string, any>>(\n getGraph: () => Graph,\n partial: NodeArg<TData, TProperties>,\n path: string[] = [],\n ignoreBuilders: string[] = [],\n ): Node<TData, TProperties> {\n // TODO(burdon): Document implications and rationale of deepSignal.\n const node: Node<TData, TProperties> = deepSignal({\n parent: null,\n data: null as TData, // TODO(burdon): Allow null property?\n properties: {} as TProperties,\n childrenMap: {},\n actionsMap: {},\n // TODO(burdon): Document.\n ...partial,\n\n get children() {\n return Object.values(node.childrenMap);\n },\n get actions() {\n return Object.values(node.actionsMap);\n },\n\n //\n // Properties\n //\n\n addProperty: (key, value) => {\n untracked(() => {\n (node.properties as Record<string, any>)[key] = value;\n });\n },\n removeProperty: (key) => {\n untracked(() => {\n delete (node.properties as Record<string, any>)[key];\n });\n },\n\n //\n // Nodes\n //\n\n addNode: (builder, ...partials) => {\n return untracked(() => {\n return partials.map((partial) => {\n const builders = [...ignoreBuilders, builder];\n const childPath = [...path, 'childrenMap', partial.id];\n const child = this._createNode(getGraph, { ...partial, parent: node }, childPath, builders);\n node.childrenMap[child.id] = child;\n // TODO(burdon): Defer triggering recursive updates until task has completed.\n this._build(getGraph(), child, childPath, builders);\n return child;\n });\n });\n },\n removeNode: (id) => {\n return untracked(() => {\n const child = node.childrenMap[id];\n delete node.childrenMap[id];\n return child;\n });\n },\n\n //\n // Actions\n //\n\n addAction: (...partials) => {\n return untracked(() => {\n return partials.map((partial) => {\n const action = this._createAction(partial);\n if (action.keyBinding) {\n Keyboard.singleton.getContext(path.join('/')).bind({\n binding: action.keyBinding!,\n handler: () => {\n action.invoke();\n },\n data: action.label,\n });\n }\n\n node.actionsMap[action.id] = action;\n return action;\n });\n });\n },\n removeAction: (id) => {\n return untracked(() => {\n const action = node.actionsMap[id];\n if (action.keyBinding) {\n // keyboardjs.unbind(action.keyBinding);\n }\n\n delete node.actionsMap[id];\n return action;\n });\n },\n }) as RevertDeepSignal<Node<TData, TProperties>>;\n\n // Only actions added at this stage are available to subsequent builders.\n // `addNode` immediately passes the new node to other builders.\n // As such, actions added later with `addAction` are not available to those builders.\n // Having actions available to subsequent builders is useful for building groups.\n partial.actions && partial.actions.forEach((action) => node.addAction(action));\n\n return node;\n }\n\n private _createAction<TProperties extends Record<string, any> = Record<string, any>>(\n partial: ActionArg<TProperties>,\n ): Action<TProperties> {\n const action: Action<TProperties> = deepSignal({\n properties: {} as TProperties,\n ...partial,\n actionsMap: {},\n get actions() {\n return Object.values(action.actionsMap);\n },\n addAction: (...partials) => {\n return untracked(() => {\n return partials.map((partial) => {\n const subAction = this._createAction(partial);\n action.actionsMap[subAction.id] = subAction;\n return subAction;\n });\n });\n },\n removeAction: (id) => {\n return untracked(() => {\n const subAction = action.actionsMap[id];\n delete action.actionsMap[id];\n return subAction;\n });\n },\n addProperty: (key, value) => {\n return untracked(() => {\n (action.properties as Record<string, any>)[key] = value;\n });\n },\n removeProperty: (key) => {\n return untracked(() => {\n delete (action.properties as Record<string, any>)[key];\n });\n },\n }) as RevertDeepSignal<Action<TProperties>>;\n\n partial.actions && partial.actions.forEach((subAction) => action.addAction(subAction));\n\n return action;\n }\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport type { IconProps } from '@phosphor-icons/react';\nimport { type FC } from 'react';\n\nimport type { UnsubscribeCallback } from '@dxos/async';\n\nimport { type ActionArg, type Action, type Label } from './action';\n\n/**\n * Called when a node is added to the graph, allowing other node builders to add children, actions or properties.\n */\nexport type NodeBuilder = (parent: Node) => UnsubscribeCallback | void;\n\n/**\n * Represents a node in the graph.\n */\nexport type Node<TData = any, TProperties extends Record<string, any> = Record<string, any>> = {\n /**\n * Globally unique ID.\n */\n id: string;\n\n /**\n * Parent node in the graph.\n */\n parent: Node | null;\n\n /**\n * Label to be used when displaying the node.\n * For default labels, use a translated string.\n *\n * @example 'My Node'\n * @example ['unknown node label, { ns: 'example-plugin' }]\n */\n label: Label;\n\n /**\n * Description to be used when displaying a detailed view of the node.\n * For default descriptions, use a translated string.\n */\n description?: Label;\n\n /**\n * Icon to be used when displaying the node.\n */\n icon?: FC<IconProps>;\n\n /**\n * Properties of the node relevant to displaying the node.\n */\n // TODO(burdon): Make this extensible and move label, description, and icon into here?\n properties: TProperties;\n\n /**\n * Data the node represents.\n */\n // TODO(burdon): Type system (e.g., minimally provide identifier string vs. TypedObject vs. Graph mixin type system)?\n // type field would prevent convoluted sniffing of object properties. And allow direct pass-through for ECHO TypedObjects.\n // TODO(burdon): In some places `null` is cast to TData so make optional?\n data: TData;\n\n /**\n * Children of the node stored by their id.\n */\n // TODO(burdon): Rename nodes/nodeMap?\n childrenMap: Record<string, Node>;\n\n /**\n * Actions of the node stored by their id.\n */\n actionsMap: Record<string, Action>;\n\n /**\n * Children of the node in default order.\n */\n get children(): Node[];\n\n /**\n * Actions of the node in default order.\n */\n get actions(): Action[];\n\n addProperty(key: string, value: any): void;\n removeProperty(key: string): void;\n\n addNode<TChildData = null, TChildProperties extends Record<string, any> = Record<string, any>>(\n id: string,\n ...node: NodeArg<TChildData, TChildProperties>[]\n ): Node<TChildData, TChildProperties>[];\n removeNode(id: string): Node;\n\n addAction<TActionProperties extends Record<string, any> = Record<string, any>>(\n ...action: ActionArg<TActionProperties>[]\n ): Action<TActionProperties>[];\n removeAction(id: string): Action;\n};\n\nexport type NodeArg<TData = null, TProperties extends Record<string, any> = Record<string, any>> = Pick<\n Node,\n 'id' | 'label'\n> &\n Partial<Omit<Node<TData, TProperties>, 'id' | 'label' | 'actions'>> & { actions?: ActionArg[] };\n\nexport const isGraphNode = (data: unknown): data is Node =>\n data && typeof data === 'object' ? 'id' in data && 'label' in data : false;\n"],
5
+ "mappings": "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",
6
+ "names": ["import_react", "Graph", "constructor", "_root", "_index", "deepSignal", "toJSON", "toLabel", "label", "Array", "isArray", "ns", "node", "id", "slice", "children", "length", "map", "undefined", "actions", "root", "getPath", "_setPath", "path", "findNode", "get", "traverse", "direction", "filter", "visitor", "depth", "Object", "values", "forEach", "child", "parent", "GraphBuilder", "_nodeBuilders", "Map", "_unsubscribe", "addNodeBuilder", "builder", "set", "removeNodeBuilder", "delete", "build", "previousGraph", "startingPath", "graph", "_createNode", "_build", "ignoreBuilders", "subscriptions", "EventSubscriptions", "clear", "from", "entries", "findIndex", "ignore", "_", "unsubscribe", "add", "getGraph", "partial", "data", "properties", "childrenMap", "actionsMap", "addProperty", "key", "value", "untracked", "removeProperty", "addNode", "partials", "builders", "childPath", "removeNode", "addAction", "action", "_createAction", "keyBinding", "Keyboard", "singleton", "getContext", "join", "bind", "binding", "handler", "invoke", "removeAction", "subAction", "isGraphNode"]
7
7
  }
@@ -1 +1 @@
1
- {"inputs":{"packages/sdk/app-graph/src/action.ts":{"bytes":3043,"imports":[],"format":"esm"},"packages/sdk/app-graph/src/graph.ts":{"bytes":9066,"imports":[{"path":"deepsignal/react","kind":"import-statement","external":true},{"path":"lodash.get","kind":"import-statement","external":true}],"format":"esm"},"packages/sdk/app-graph/src/graph-builder.ts":{"bytes":22793,"imports":[{"path":"@preact/signals-react","kind":"import-statement","external":true},{"path":"deepsignal/react","kind":"import-statement","external":true},{"path":"mousetrap","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"packages/sdk/app-graph/src/graph.ts","kind":"import-statement","original":"./graph"}],"format":"esm"},"packages/sdk/app-graph/src/node.ts":{"bytes":4772,"imports":[],"format":"esm"},"packages/sdk/app-graph/src/index.ts":{"bytes":722,"imports":[{"path":"packages/sdk/app-graph/src/action.ts","kind":"import-statement","original":"./action"},{"path":"packages/sdk/app-graph/src/graph.ts","kind":"import-statement","original":"./graph"},{"path":"packages/sdk/app-graph/src/graph-builder.ts","kind":"import-statement","original":"./graph-builder"},{"path":"packages/sdk/app-graph/src/node.ts","kind":"import-statement","original":"./node"}],"format":"esm"},"packages/sdk/app-graph/src/testing.ts":{"bytes":11884,"imports":[],"format":"esm"}},"outputs":{"packages/sdk/app-graph/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":19302},"packages/sdk/app-graph/dist/lib/node/index.cjs":{"imports":[{"path":"deepsignal/react","kind":"import-statement","external":true},{"path":"lodash.get","kind":"import-statement","external":true},{"path":"@preact/signals-react","kind":"import-statement","external":true},{"path":"deepsignal/react","kind":"import-statement","external":true},{"path":"mousetrap","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true}],"exports":["Graph","GraphBuilder","isGraphNode"],"entryPoint":"packages/sdk/app-graph/src/index.ts","inputs":{"packages/sdk/app-graph/src/index.ts":{"bytesInOutput":0},"packages/sdk/app-graph/src/graph.ts":{"bytesInOutput":1818},"packages/sdk/app-graph/src/graph-builder.ts":{"bytesInOutput":5294},"packages/sdk/app-graph/src/node.ts":{"bytesInOutput":104}},"bytes":7428},"packages/sdk/app-graph/dist/lib/node/testing.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":6167},"packages/sdk/app-graph/dist/lib/node/testing.cjs":{"imports":[],"exports":["buildGraph","createTestNodeBuilder"],"entryPoint":"packages/sdk/app-graph/src/testing.ts","inputs":{"packages/sdk/app-graph/src/testing.ts":{"bytesInOutput":2180}},"bytes":2308}}}
1
+ {"inputs":{"packages/sdk/app-graph/src/action.ts":{"bytes":3043,"imports":[],"format":"esm"},"packages/sdk/app-graph/src/graph.ts":{"bytes":9237,"imports":[{"path":"deepsignal/react","kind":"import-statement","external":true},{"path":"lodash.get","kind":"import-statement","external":true}],"format":"esm"},"packages/sdk/app-graph/src/graph-builder.ts":{"bytes":23684,"imports":[{"path":"@preact/signals-react","kind":"import-statement","external":true},{"path":"deepsignal/react","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/keyboard","kind":"import-statement","external":true},{"path":"packages/sdk/app-graph/src/graph.ts","kind":"import-statement","original":"./graph"}],"format":"esm"},"packages/sdk/app-graph/src/node.ts":{"bytes":4772,"imports":[],"format":"esm"},"packages/sdk/app-graph/src/index.ts":{"bytes":722,"imports":[{"path":"packages/sdk/app-graph/src/action.ts","kind":"import-statement","original":"./action"},{"path":"packages/sdk/app-graph/src/graph.ts","kind":"import-statement","original":"./graph"},{"path":"packages/sdk/app-graph/src/graph-builder.ts","kind":"import-statement","original":"./graph-builder"},{"path":"packages/sdk/app-graph/src/node.ts","kind":"import-statement","original":"./node"}],"format":"esm"},"packages/sdk/app-graph/src/testing.ts":{"bytes":11884,"imports":[],"format":"esm"}},"outputs":{"packages/sdk/app-graph/dist/lib/node/index.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":19741},"packages/sdk/app-graph/dist/lib/node/index.cjs":{"imports":[{"path":"deepsignal/react","kind":"import-statement","external":true},{"path":"lodash.get","kind":"import-statement","external":true},{"path":"@preact/signals-react","kind":"import-statement","external":true},{"path":"deepsignal/react","kind":"import-statement","external":true},{"path":"@dxos/async","kind":"import-statement","external":true},{"path":"@dxos/keyboard","kind":"import-statement","external":true}],"exports":["Graph","GraphBuilder","isGraphNode"],"entryPoint":"packages/sdk/app-graph/src/index.ts","inputs":{"packages/sdk/app-graph/src/index.ts":{"bytesInOutput":0},"packages/sdk/app-graph/src/graph.ts":{"bytesInOutput":1841},"packages/sdk/app-graph/src/graph-builder.ts":{"bytesInOutput":5503},"packages/sdk/app-graph/src/node.ts":{"bytesInOutput":104}},"bytes":7660},"packages/sdk/app-graph/dist/lib/node/testing.cjs.map":{"imports":[],"exports":[],"inputs":{},"bytes":6167},"packages/sdk/app-graph/dist/lib/node/testing.cjs":{"imports":[],"exports":["buildGraph","createTestNodeBuilder"],"entryPoint":"packages/sdk/app-graph/src/testing.ts","inputs":{"packages/sdk/app-graph/src/testing.ts":{"bytesInOutput":2180}},"bytes":2308}}}
@@ -1 +1 @@
1
- {"version":3,"file":"graph-builder.d.ts","sourceRoot":"","sources":["../../../src/graph-builder.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,KAAK,EAAiB,WAAW,EAAE,MAAM,QAAQ,CAAC;AAEzD;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAkC;IAChE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAyC;IAEtE;;OAEG;IACH,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,YAAY;IAK9D;;OAEG;IACH,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY;IAK3C;;;;;OAKG;IACH,KAAK,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,YAAY,GAAE,MAAM,EAAO,GAAG,KAAK;IAKhE;;OAEG;IACH,OAAO,CAAC,MAAM;IAoBd,OAAO,CAAC,WAAW;IA6FnB,OAAO,CAAC,aAAa;CA0CtB"}
1
+ {"version":3,"file":"graph-builder.d.ts","sourceRoot":"","sources":["../../../src/graph-builder.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,KAAK,EAAiB,WAAW,EAAE,MAAM,QAAQ,CAAC;AAEzD;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAkC;IAChE,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAyC;IAEtE;;OAEG;IACH,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,YAAY;IAK9D;;OAEG;IACH,iBAAiB,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY;IAK3C;;;;;OAKG;IACH,KAAK,CAAC,aAAa,CAAC,EAAE,KAAK,EAAE,YAAY,GAAE,MAAM,EAAO,GAAG,KAAK;IAKhE;;OAEG;IACH,OAAO,CAAC,MAAM;IAoBd,OAAO,CAAC,WAAW;IA4GnB,OAAO,CAAC,aAAa;CA0CtB"}
@@ -15,10 +15,10 @@ export type TraversalOptions = {
15
15
  /**
16
16
  * A callback which is called for each node visited during traversal.
17
17
  */
18
- visitor?: (node: Node) => void;
18
+ visitor?: (node: Node, path: string[]) => void;
19
19
  };
20
20
  /**
21
- * The Graph represents...
21
+ * The Graph represents the structure of the application constructed via plugins.
22
22
  */
23
23
  export declare class Graph {
24
24
  private readonly _root;
@@ -1 +1 @@
1
- {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../../src/graph.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEnC,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;OAEG;IACH,IAAI,CAAC,EAAE,IAAI,CAAC;IAEZ;;OAEG;IACH,SAAS,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IAE1B;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;IAEjC;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;CAChC,CAAC;AAEF;;GAEG;AACH,qBAAa,KAAK;IAKJ,OAAO,CAAC,QAAQ,CAAC,KAAK;IAFlC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+C;gBAEzC,KAAK,EAAE,IAAI;IAExC,MAAM;IAmBN;;OAEG;IACH,IAAI,IAAI,IAAI,IAAI,CAEf;IAED;;OAEG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IAWzC;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAStC;;OAEG;IACH,QAAQ,CAAC,EAAE,IAAiB,EAAE,SAAkB,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,gBAAgB,EAAE,KAAK,SAAI,GAAG,IAAI;CAWxG"}
1
+ {"version":3,"file":"graph.d.ts","sourceRoot":"","sources":["../../../src/graph.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,IAAI,EAAE,MAAM,QAAQ,CAAC;AAEnC,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;OAEG;IACH,IAAI,CAAC,EAAE,IAAI,CAAC;IAEZ;;OAEG;IACH,SAAS,CAAC,EAAE,IAAI,GAAG,MAAM,CAAC;IAE1B;;OAEG;IACH,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAC;IAEjC;;OAEG;IACH,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;CAChD,CAAC;AAEF;;GAEG;AACH,qBAAa,KAAK;IAIJ,OAAO,CAAC,QAAQ,CAAC,KAAK;IAFlC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+C;gBAEzC,KAAK,EAAE,IAAI;IAExC,MAAM;IAmBN;;OAEG;IACH,IAAI,IAAI,IAAI,IAAI,CAEf;IAED;;OAEG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IAWzC;;OAEG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS;IAStC;;OAEG;IACH,QAAQ,CAAC,EAAE,IAAiB,EAAE,SAAkB,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,gBAAgB,EAAE,KAAK,SAAI,GAAG,IAAI;CAWxG"}
@@ -4,7 +4,7 @@ declare const _default: {
4
4
  decorators: import("@storybook/react").Decorator[];
5
5
  };
6
6
  export default _default;
7
- export declare const EchoGraph: {
7
+ export declare const Default: {
8
8
  render: () => JSX.Element;
9
9
  };
10
10
  //# sourceMappingURL=EchoGraph.stories.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"EchoGraph.stories.d.ts","sourceRoot":"","sources":["../../../../src/stories/EchoGraph.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,YAAY,CAAC;;;;;AAmBpB,wBAGE;AA6MF,eAAO,MAAM,SAAS;;CAErB,CAAC"}
1
+ {"version":3,"file":"EchoGraph.stories.d.ts","sourceRoot":"","sources":["../../../../src/stories/EchoGraph.stories.tsx"],"names":[],"mappings":"AAIA,OAAO,YAAY,CAAC;;;;;AAoBpB,wBAGE;AA6MF,eAAO,MAAM,OAAO;;CAEnB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/app-graph",
3
- "version": "0.3.10-next.ef70620",
3
+ "version": "0.3.11-main.bd26370",
4
4
  "description": "Constructs knowledge graphs for the purpose of building applications on top of",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -37,27 +37,26 @@
37
37
  "deepsignal": "1.4.0-shallow.0",
38
38
  "lodash.get": "^4.4.2",
39
39
  "lodash.set": "^4.3.2",
40
- "mousetrap": "^1.6.5",
41
- "@dxos/async": "0.3.10-next.ef70620",
42
- "@dxos/debug": "0.3.10-next.ef70620",
43
- "@dxos/invariant": "0.3.10-next.ef70620",
44
- "@dxos/util": "0.3.10-next.ef70620"
40
+ "@dxos/async": "0.3.11-main.bd26370",
41
+ "@dxos/debug": "0.3.11-main.bd26370",
42
+ "@dxos/keyboard": "0.3.11-main.bd26370",
43
+ "@dxos/util": "0.3.11-main.bd26370",
44
+ "@dxos/invariant": "0.3.11-main.bd26370"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@faker-js/faker": "^8.0.2",
48
48
  "@phosphor-icons/react": "^2.0.5",
49
49
  "@types/lodash.get": "^4.4.7",
50
50
  "@types/lodash.set": "^4.3.7",
51
- "@types/mousetrap": "^1.6.11",
52
51
  "@types/react": "^18.0.21",
53
52
  "@types/react-dom": "^18.0.6",
54
53
  "react": "^18.2.0",
55
54
  "react-dom": "^18.2.0",
56
55
  "vite": "^4.3.9",
57
- "@dxos/react-client": "0.3.10-next.ef70620",
58
- "@dxos/react-ui-theme": "0.3.10-next.ef70620",
59
- "@dxos/react-ui": "0.3.10-next.ef70620",
60
- "@dxos/storybook-utils": "0.3.10-next.ef70620"
56
+ "@dxos/react-client": "0.3.11-main.bd26370",
57
+ "@dxos/react-ui": "0.3.11-main.bd26370",
58
+ "@dxos/react-ui-theme": "0.3.11-main.bd26370",
59
+ "@dxos/storybook-utils": "0.3.11-main.bd26370"
61
60
  },
62
61
  "peerDependencies": {
63
62
  "@phosphor-icons/react": "^2.0.5",
@@ -4,9 +4,9 @@
4
4
 
5
5
  import { untracked } from '@preact/signals-react';
6
6
  import { type RevertDeepSignal, deepSignal } from 'deepsignal/react';
7
- import Mousetrap from 'mousetrap';
8
7
 
9
8
  import { EventSubscriptions } from '@dxos/async';
9
+ import { Keyboard } from '@dxos/keyboard';
10
10
 
11
11
  import type { ActionArg, Action } from './action';
12
12
  import { Graph } from './graph';
@@ -92,6 +92,10 @@ export class GraphBuilder {
92
92
  return Object.values(node.actionsMap);
93
93
  },
94
94
 
95
+ //
96
+ // Properties
97
+ //
98
+
95
99
  addProperty: (key, value) => {
96
100
  untracked(() => {
97
101
  (node.properties as Record<string, any>)[key] = value;
@@ -103,6 +107,10 @@ export class GraphBuilder {
103
107
  });
104
108
  },
105
109
 
110
+ //
111
+ // Nodes
112
+ //
113
+
106
114
  addNode: (builder, ...partials) => {
107
115
  return untracked(() => {
108
116
  return partials.map((partial) => {
@@ -124,14 +132,21 @@ export class GraphBuilder {
124
132
  });
125
133
  },
126
134
 
135
+ //
136
+ // Actions
137
+ //
138
+
127
139
  addAction: (...partials) => {
128
140
  return untracked(() => {
129
141
  return partials.map((partial) => {
130
142
  const action = this._createAction(partial);
131
143
  if (action.keyBinding) {
132
- // TODO(burdon): Last writer wins.
133
- Mousetrap.bind(action.keyBinding, () => {
134
- action.invoke();
144
+ Keyboard.singleton.getContext(path.join('/')).bind({
145
+ binding: action.keyBinding!,
146
+ handler: () => {
147
+ action.invoke();
148
+ },
149
+ data: action.label,
135
150
  });
136
151
  }
137
152
 
@@ -144,7 +159,7 @@ export class GraphBuilder {
144
159
  return untracked(() => {
145
160
  const action = node.actionsMap[id];
146
161
  if (action.keyBinding) {
147
- Mousetrap.unbind(action.keyBinding);
162
+ // keyboardjs.unbind(action.keyBinding);
148
163
  }
149
164
 
150
165
  delete node.actionsMap[id];
package/src/graph.ts CHANGED
@@ -28,14 +28,13 @@ export type TraversalOptions = {
28
28
  /**
29
29
  * A callback which is called for each node visited during traversal.
30
30
  */
31
- visitor?: (node: Node) => void;
31
+ visitor?: (node: Node, path: string[]) => void;
32
32
  };
33
33
 
34
34
  /**
35
- * The Graph represents...
35
+ * The Graph represents the structure of the application constructed via plugins.
36
36
  */
37
37
  export class Graph {
38
- // TODO(burdon): Document.
39
38
  // TODO(wittjosiah): Should this support multiple paths to the same node?
40
39
  private readonly _index = deepSignal<{ [key: string]: string[] }>({});
41
40
 
@@ -98,7 +97,7 @@ export class Graph {
98
97
  */
99
98
  traverse({ node = this._root, direction = 'down', filter, visitor }: TraversalOptions, depth = 0): void {
100
99
  if (!filter || filter(node)) {
101
- visitor?.(node);
100
+ visitor?.(node, this.getPath(node.id)!);
102
101
  }
103
102
 
104
103
  if (direction === 'down') {
@@ -3,6 +3,7 @@
3
3
  //
4
4
 
5
5
  import '@dxosTheme';
6
+
6
7
  import { faker } from '@faker-js/faker';
7
8
  import { Pause, Play, Plus, Timer } from '@phosphor-icons/react';
8
9
  import { effect } from '@preact/signals-react';
@@ -22,7 +23,7 @@ import { GraphBuilder } from '../graph-builder';
22
23
  import { type Node } from '../node';
23
24
 
24
25
  export default {
25
- title: 'Echo Graph',
26
+ title: 'app-graph/EchoGraph',
26
27
  decorators: [withTheme],
27
28
  };
28
29
 
@@ -229,6 +230,6 @@ const EchoGraphStory = () => {
229
230
  );
230
231
  };
231
232
 
232
- export const EchoGraph = {
233
+ export const Default = {
233
234
  render: () => <ClientRepeater Component={EchoGraphStory} clients={[client]} className='flex flex-col' />,
234
235
  };