@ankhzet/graph 0.1.0 → 0.3.0
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.
- package/CHANGELOG.md +20 -0
- package/dist/index.d.ts +676 -0
- package/dist/index.js +2283 -0
- package/dist/index.js.map +1 -0
- package/package.json +6 -6
- package/src/{CircuitGroups.tsx → GraphGroups.tsx} +5 -5
- package/src/LoadNodes.ts +5 -5
- package/src/{CircuitGraph.tsx → ManagedGraph.tsx} +22 -23
- package/src/{CircuitNode.ts → ManagedGraphNode.ts} +3 -3
- package/src/createGraphHandlers.ts +2 -2
- package/src/index.ts +3 -1
- package/src/useNodeSelection.ts +2 -2
- package/src/useNodes.tsx +4 -4
- package/src/utils.ts +3 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ankhzet/graph",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./src/index.ts",
|
|
6
6
|
"types": "./src/index.ts",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"package.json",
|
|
9
9
|
"src/**/*.ts",
|
|
10
10
|
"src/**/*.tsx",
|
|
11
|
-
"
|
|
11
|
+
"dist",
|
|
12
12
|
"*.md"
|
|
13
13
|
],
|
|
14
14
|
"exports": {
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
"@pixi/events": "^7.4.3",
|
|
31
31
|
"mobx": "^6.15.4",
|
|
32
32
|
"mobx-react-lite": "^4.1.1",
|
|
33
|
-
"@ankhzet/eventual": "1.
|
|
34
|
-
"@ankhzet/
|
|
35
|
-
"@ankhzet/utils": "1.
|
|
36
|
-
"@ankhzet/
|
|
33
|
+
"@ankhzet/eventual": "1.2.0",
|
|
34
|
+
"@ankhzet/ui": "0.2.0",
|
|
35
|
+
"@ankhzet/utils": "1.18.0",
|
|
36
|
+
"@ankhzet/gcl": "1.2.0"
|
|
37
37
|
},
|
|
38
38
|
"peerDependencies": {
|
|
39
39
|
"react": "^19.2.6"
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { useLastCallback } from '@ankhzet/ui';
|
|
2
2
|
import { type TypeId } from './types';
|
|
3
3
|
import { type ItemsGroup, NodeGroups } from './graph';
|
|
4
|
-
import {
|
|
4
|
+
import { ManagedGraphNode } from './ManagedGraphNode';
|
|
5
5
|
|
|
6
|
-
export interface
|
|
7
|
-
items:
|
|
6
|
+
export interface GraphGroupsProps {
|
|
7
|
+
items: ManagedGraphNode[];
|
|
8
8
|
onSelect: (ids: TypeId[]) => void;
|
|
9
9
|
}
|
|
10
10
|
|
|
11
|
-
export const
|
|
11
|
+
export const GraphGroups = ({ onSelect, ...props }: GraphGroupsProps) => {
|
|
12
12
|
const handleSelect = useLastCallback((group: ItemsGroup<TypeId>) => onSelect(group.ids));
|
|
13
13
|
|
|
14
14
|
return (
|
|
@@ -20,7 +20,7 @@ export const CircuitGroups = ({ onSelect, ...props }: CircuitGroupsProps) => {
|
|
|
20
20
|
);
|
|
21
21
|
};
|
|
22
22
|
|
|
23
|
-
const resolver = (node:
|
|
23
|
+
const resolver = (node: ManagedGraphNode) => {
|
|
24
24
|
if (!node.item.isolator) {
|
|
25
25
|
return;
|
|
26
26
|
}
|
package/src/LoadNodes.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { TypeId } from './types';
|
|
2
2
|
import type { NodeConnection, Position, StoreInterface } from './graph';
|
|
3
|
-
import {
|
|
3
|
+
import { ManagedGraphNode } from './ManagedGraphNode';
|
|
4
4
|
|
|
5
|
-
export type GraphListeners<N extends
|
|
5
|
+
export type GraphListeners<N extends ManagedGraphNode<any>> = {
|
|
6
6
|
onEdit: (node: N) => void;
|
|
7
7
|
onConnect: (connection: NodeConnection<TypeId>) => Promise<void>;
|
|
8
8
|
onMove: (node: N, pos: Position) => Promise<void>;
|
|
@@ -12,9 +12,9 @@ export type GraphListeners<N extends CircuitNode<any>> = {
|
|
|
12
12
|
onDelete: (node: N) => Promise<void>;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
type SyncConfig<N extends
|
|
15
|
+
type SyncConfig<N extends ManagedGraphNode<any>> = { added: N[]; removed: TypeId[] };
|
|
16
16
|
|
|
17
|
-
const connectHandlers = <N extends
|
|
17
|
+
const connectHandlers = <N extends ManagedGraphNode>(
|
|
18
18
|
node: N,
|
|
19
19
|
{ onEdit, onMove, onConnect, onDelete, onAddPort, onDisconnectPort, onDeletePort }: GraphListeners<N>,
|
|
20
20
|
) => {
|
|
@@ -27,7 +27,7 @@ const connectHandlers = <N extends CircuitNode>(
|
|
|
27
27
|
node.onDeletePortAction(({ port }) => onDeletePort(node, port));
|
|
28
28
|
};
|
|
29
29
|
|
|
30
|
-
export const syncNodes = <N extends
|
|
30
|
+
export const syncNodes = <N extends ManagedGraphNode<any>>(
|
|
31
31
|
nodes: StoreInterface<N>,
|
|
32
32
|
handlers: GraphListeners<N> | undefined,
|
|
33
33
|
{ added, removed }: SyncConfig<N>,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { useLastCallback, handleAsNoop, Styles } from '@ankhzet/ui';
|
|
2
2
|
import { RefObject, useRef, useMemo, useState, PropsWithChildren, useImperativeHandle } from 'react';
|
|
3
|
-
import {
|
|
4
|
-
import type {
|
|
3
|
+
import { GraphGroups } from './GraphGroups';
|
|
4
|
+
import type { ManagedGraphNode, IItem } from './ManagedGraphNode';
|
|
5
5
|
import { type GraphHandlers, createGraphHandlers } from './createGraphHandlers';
|
|
6
6
|
import type { GraphAdapter } from './graph';
|
|
7
7
|
import { Store, useStore } from './graph';
|
|
@@ -15,37 +15,36 @@ import { Coordinates, GRID_SIZE } from './utils';
|
|
|
15
15
|
|
|
16
16
|
export type { GraphHandlers };
|
|
17
17
|
|
|
18
|
-
export interface
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
export interface IGraph<Item extends IItem> extends Identifiable {
|
|
19
|
+
items: Item[];
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface ManagedGraphProps<Graph extends IGraph<Item>, Item extends IItem, DTO> {
|
|
23
|
+
innerRef?: RefObject<{ graph: GraphAdapter<ManagedGraphNode<Item>>; element?: HTMLDivElement }>;
|
|
24
|
+
graph: Graph;
|
|
21
25
|
selected?: Item[];
|
|
22
26
|
className?: string;
|
|
23
27
|
handlers?: Partial<GraphHandlers<DTO, Item>>;
|
|
24
|
-
|
|
28
|
+
onExport?: (graph: Graph) => string;
|
|
25
29
|
}
|
|
26
30
|
|
|
27
|
-
export const
|
|
31
|
+
export const ManagedGraph = <Graph extends IGraph<Item>, Item extends IItem, DTO extends GraphDTO>({
|
|
28
32
|
innerRef,
|
|
29
|
-
|
|
33
|
+
graph,
|
|
30
34
|
selected,
|
|
31
35
|
handlers,
|
|
32
36
|
children,
|
|
33
|
-
|
|
37
|
+
onExport,
|
|
34
38
|
...rest
|
|
35
|
-
}: PropsWithChildren<
|
|
36
|
-
const graphRef = useRef<{ graph: GraphAdapter<
|
|
39
|
+
}: PropsWithChildren<ManagedGraphProps<Graph, Item, DTO>>) => {
|
|
40
|
+
const graphRef = useRef<{ graph: GraphAdapter<ManagedGraphNode<Item>>; element?: HTMLDivElement }>(null);
|
|
37
41
|
const coordinator = useMemo(() => new Coordinates(GRID_SIZE), []);
|
|
38
|
-
const [nodes, all] = useStore(() => new Store<CircuitNode<Item>>());
|
|
39
|
-
const [group, setGroup] = useState<TypeId[] | undefined>();
|
|
40
|
-
|
|
41
42
|
const menu = useGraphMenu(coordinator, handlers?.onCreate);
|
|
43
|
+
const [nodes, all] = useStore(() => new Store<ManagedGraphNode<Item>>());
|
|
44
|
+
const [group, setGroup] = useState<TypeId[] | undefined>();
|
|
42
45
|
const { canvas, loader } = createGraphHandlers(coordinator, nodes, handlers);
|
|
43
46
|
|
|
44
|
-
const handleExport = useLastCallback(
|
|
45
|
-
exportToJson && await navigator.clipboard.writeText(
|
|
46
|
-
JSON.stringify(exportToJson(circuit), null, 3)
|
|
47
|
-
);
|
|
48
|
-
});
|
|
47
|
+
const handleExport = useLastCallback(() => onExport?.(graph));
|
|
49
48
|
|
|
50
49
|
useImperativeHandle(innerRef, () => ({
|
|
51
50
|
get graph() {
|
|
@@ -57,14 +56,14 @@ export const CircuitGraph = <Circuit extends Identifiable, Item extends IItem, D
|
|
|
57
56
|
}));
|
|
58
57
|
|
|
59
58
|
const store = useMemo(() => {
|
|
60
|
-
const items = new Store<Item>();
|
|
59
|
+
const items = new Store<Item>(graph.items);
|
|
61
60
|
|
|
62
61
|
return {
|
|
63
62
|
items,
|
|
64
63
|
get: () => items.all,
|
|
65
64
|
onChange: (cb: () => void) => items.onChange(cb),
|
|
66
65
|
};
|
|
67
|
-
}, []);
|
|
66
|
+
}, [graph.items]);
|
|
68
67
|
|
|
69
68
|
useNodes({
|
|
70
69
|
store,
|
|
@@ -81,11 +80,11 @@ export const CircuitGraph = <Circuit extends Identifiable, Item extends IItem, D
|
|
|
81
80
|
<div style={styles.selector}>
|
|
82
81
|
{children}
|
|
83
82
|
|
|
84
|
-
<
|
|
83
|
+
<GraphGroups items={all} onSelect={setGroup} />
|
|
85
84
|
|
|
86
85
|
<button onClick={() => setGroup(undefined)}>Update</button>
|
|
87
86
|
|
|
88
|
-
{
|
|
87
|
+
{onExport && (
|
|
89
88
|
<button onClick={handleExport}>Export</button>
|
|
90
89
|
)}
|
|
91
90
|
</div>
|
|
@@ -71,13 +71,13 @@ export enum NodeStatus {
|
|
|
71
71
|
Selected = 1 << 4,
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
type NodeData<Item> = {
|
|
74
|
+
export type NodeData<Item> = {
|
|
75
75
|
item: Item;
|
|
76
76
|
status: NodeStatus;
|
|
77
77
|
progress: number;
|
|
78
78
|
};
|
|
79
79
|
|
|
80
|
-
enum MenuActions {
|
|
80
|
+
export enum MenuActions {
|
|
81
81
|
EDIT_NODE = 1,
|
|
82
82
|
ADD_PORT = 2,
|
|
83
83
|
DISCONNECT_PORT = 3,
|
|
@@ -85,7 +85,7 @@ enum MenuActions {
|
|
|
85
85
|
DELETE_NODE = 5,
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
export class
|
|
88
|
+
export class ManagedGraphNode<Item extends IItem = IItem>
|
|
89
89
|
extends GraphNode<TypeId, NodeData<Item>, Container>
|
|
90
90
|
implements IMenuProvider<MenuAction>
|
|
91
91
|
{
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { TypeId } from './types';
|
|
2
2
|
import type { GraphListeners } from './LoadNodes';
|
|
3
|
-
import type {
|
|
3
|
+
import type { ManagedGraphNode, IItem } from './ManagedGraphNode';
|
|
4
4
|
import type { ConnectionPoint, Coordinator, NodeConnection, Position, StoreInterface } from './graph';
|
|
5
5
|
|
|
6
6
|
export interface GraphHandlers<DTO, Item> {
|
|
@@ -16,7 +16,7 @@ export interface GraphHandlers<DTO, Item> {
|
|
|
16
16
|
onContextMenu?: (item: Item | null, pos: Position) => void | false;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
export const createGraphHandlers = <DTO, Item extends IItem, Node extends
|
|
19
|
+
export const createGraphHandlers = <DTO, Item extends IItem, Node extends ManagedGraphNode<Item>>(
|
|
20
20
|
coordinator: Coordinator,
|
|
21
21
|
nodes: StoreInterface<Node>,
|
|
22
22
|
{
|
package/src/index.ts
CHANGED
package/src/useNodeSelection.ts
CHANGED
|
@@ -2,9 +2,9 @@ import { useRef } from 'react';
|
|
|
2
2
|
import { matchId } from '@ankhzet/utils';
|
|
3
3
|
import { useIsomorphicLayoutEffect } from '@ankhzet/ui';
|
|
4
4
|
|
|
5
|
-
import type {
|
|
5
|
+
import type { ManagedGraphNode, IItem } from './ManagedGraphNode';
|
|
6
6
|
|
|
7
|
-
export const useNodeSelection = <Item extends IItem>(nodes:
|
|
7
|
+
export const useNodeSelection = <Item extends IItem>(nodes: ManagedGraphNode<Item>[], selected?: Item[]) => {
|
|
8
8
|
const ref = useRef<Item[]>([]);
|
|
9
9
|
|
|
10
10
|
useIsomorphicLayoutEffect(() => {
|
package/src/useNodes.tsx
CHANGED
|
@@ -4,7 +4,7 @@ import { reaction } from 'mobx';
|
|
|
4
4
|
import { useLastCallback, useSyncStore } from '@ankhzet/ui';
|
|
5
5
|
import type { Coordinator} from './graph';
|
|
6
6
|
import { isEqualIdentifiables } from './graph';
|
|
7
|
-
import {
|
|
7
|
+
import { ManagedGraphNode, IItem } from './ManagedGraphNode';
|
|
8
8
|
import { TypeId } from './types';
|
|
9
9
|
|
|
10
10
|
export const useNodes = <Item extends IItem>({
|
|
@@ -16,7 +16,7 @@ export const useNodes = <Item extends IItem>({
|
|
|
16
16
|
}: {
|
|
17
17
|
store: { get: () => Item[]; onChange: (cb: () => void) => () => void };
|
|
18
18
|
coordinator: Coordinator;
|
|
19
|
-
sync: (config: { added:
|
|
19
|
+
sync: (config: { added: ManagedGraphNode<Item>[]; removed: TypeId[] }) => void;
|
|
20
20
|
toTitle: (item: Item) => string;
|
|
21
21
|
onUpdate: () => void;
|
|
22
22
|
}) => {
|
|
@@ -45,7 +45,7 @@ export const useNodes = <Item extends IItem>({
|
|
|
45
45
|
ref.current = sync;
|
|
46
46
|
|
|
47
47
|
useIsomorphicLayoutEffect(() => {
|
|
48
|
-
const factory = (item: Item):
|
|
48
|
+
const factory = (item: Item): ManagedGraphNode<Item> => new ManagedGraphNode<Item>({
|
|
49
49
|
finder,
|
|
50
50
|
item,
|
|
51
51
|
coordinator,
|
|
@@ -57,7 +57,7 @@ export const useNodes = <Item extends IItem>({
|
|
|
57
57
|
(acc: Record<TypeId, boolean>, { id }) => ((acc[id] = true), acc),
|
|
58
58
|
{}
|
|
59
59
|
);
|
|
60
|
-
const added = items.filter((
|
|
60
|
+
const added = items.filter((item) => !cache[item.id]).map(factory);
|
|
61
61
|
const removed = Object.keys(cache).filter((id) => !finder(id));
|
|
62
62
|
|
|
63
63
|
if (added.length || removed.length) {
|
package/src/utils.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import type { CircuitNode } from './CircuitNode';
|
|
1
|
+
import type { ManagedGraphNode } from './ManagedGraphNode';
|
|
3
2
|
import type { Coordinator, Position } from './graph';
|
|
4
3
|
|
|
5
4
|
export const GRID_SIZE = 16;
|
|
@@ -50,9 +49,8 @@ export class Coordinates implements Coordinator {
|
|
|
50
49
|
}
|
|
51
50
|
}
|
|
52
51
|
|
|
53
|
-
|
|
54
|
-
// processor.type === ProcessorType.Call || processor.isolator ? processor.title : null;
|
|
52
|
+
export const groupResolver = ({ description: { item } }: ManagedGraphNode) => item.isolator ? item.title : null;
|
|
55
53
|
|
|
56
54
|
const re = /^signal_?/;
|
|
57
55
|
|
|
58
|
-
export const isBarrier = ({ description }:
|
|
56
|
+
export const isBarrier = ({ description }: ManagedGraphNode<any>) => re.test(description.title);
|