nexus-shell 0.2.3 → 0.2.5
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/README.md +7 -1
- package/dist/components/graph/GraphCanvas.d.ts +95 -0
- package/dist/components/graph/GraphEdge.d.ts +71 -0
- package/dist/components/graph/GraphNode.d.ts +68 -0
- package/dist/components/graph/NodePalette.d.ts +76 -0
- package/dist/components/graph/index.d.ts +16 -0
- package/dist/components/graph/useGraphKeyboard.d.ts +115 -0
- package/dist/components/widgets/SettingsPanel.d.ts +6 -1
- package/dist/components/widgets/ThemeSwitcher.d.ts +7 -2
- package/dist/core/Boot.d.ts +1 -1
- package/dist/core/services/ThemeService.d.ts +10 -1
- package/dist/index.d.ts +3 -0
- package/dist/lib/graph.d.ts +144 -0
- package/dist/lib/themes.d.ts +57 -0
- package/dist/nexus-shell.es.js +1941 -1217
- package/dist/nexus-shell.umd.js +1 -1
- package/dist/style.css +1 -1
- package/package.json +3 -2
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The graph domain model and its geometry.
|
|
3
|
+
*
|
|
4
|
+
* Kept deliberately small and domain-neutral: the library knows about
|
|
5
|
+
* positioned nodes, edges between them, and a viewport. What a node *means* —
|
|
6
|
+
* an argument, a task, a service, a scene object — belongs to the application,
|
|
7
|
+
* exactly as with {@link ITreeNode}.
|
|
8
|
+
*
|
|
9
|
+
* This lives in `lib/` rather than `core/services/` so the presentational graph
|
|
10
|
+
* components can use it; they are barred from importing stores.
|
|
11
|
+
*/
|
|
12
|
+
/** A point in graph space. Graph space is unbounded in every direction. */
|
|
13
|
+
export interface IPoint {
|
|
14
|
+
x: number;
|
|
15
|
+
y: number;
|
|
16
|
+
}
|
|
17
|
+
/** A rectangle in graph space, anchored at its top-left corner. */
|
|
18
|
+
export interface IRect extends IPoint {
|
|
19
|
+
width: number;
|
|
20
|
+
height: number;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The four sides a node exposes for edge attachment.
|
|
24
|
+
*
|
|
25
|
+
* Ports are sides rather than discrete handles: an edge picks whichever side
|
|
26
|
+
* faces its counterpart, which keeps the model small and means a node needs no
|
|
27
|
+
* per-handle configuration to be connectable.
|
|
28
|
+
*/
|
|
29
|
+
export type GraphPort = 'top' | 'right' | 'bottom' | 'left';
|
|
30
|
+
/** A node in the graph. */
|
|
31
|
+
export interface IGraphNode {
|
|
32
|
+
/** Stable identifier, unique across the graph. */
|
|
33
|
+
id: string;
|
|
34
|
+
/** Top-left corner in graph space. */
|
|
35
|
+
position: IPoint;
|
|
36
|
+
/** Rendered size. Defaults to {@link DEFAULT_NODE_SIZE} when omitted. */
|
|
37
|
+
size?: {
|
|
38
|
+
width: number;
|
|
39
|
+
height: number;
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Your own classification, e.g. `"question"`, `"service"`, `"task"`. Never
|
|
43
|
+
* interpreted by the library — it exists so you can render and validate by
|
|
44
|
+
* type, and so palette entries and edge rules can target it.
|
|
45
|
+
*/
|
|
46
|
+
kind?: string;
|
|
47
|
+
/** Free-form payload. The library passes it through untouched. */
|
|
48
|
+
data?: unknown;
|
|
49
|
+
}
|
|
50
|
+
/** A directed edge between two nodes. */
|
|
51
|
+
export interface IGraphEdge {
|
|
52
|
+
/** Stable identifier, unique across the graph. */
|
|
53
|
+
id: string;
|
|
54
|
+
/** Id of the node the edge leaves. */
|
|
55
|
+
source: string;
|
|
56
|
+
/** Id of the node the edge enters. */
|
|
57
|
+
target: string;
|
|
58
|
+
/** Your own classification, e.g. `"supports"`, `"depends-on"`. */
|
|
59
|
+
kind?: string;
|
|
60
|
+
/** Text rendered at the edge's midpoint. */
|
|
61
|
+
label?: string;
|
|
62
|
+
/** Free-form payload. */
|
|
63
|
+
data?: unknown;
|
|
64
|
+
}
|
|
65
|
+
/** Pan and zoom. `scale` multiplies graph units to screen pixels. */
|
|
66
|
+
export interface IViewport {
|
|
67
|
+
x: number;
|
|
68
|
+
y: number;
|
|
69
|
+
scale: number;
|
|
70
|
+
}
|
|
71
|
+
export declare const DEFAULT_NODE_SIZE: {
|
|
72
|
+
readonly width: 180;
|
|
73
|
+
readonly height: 72;
|
|
74
|
+
};
|
|
75
|
+
export declare const IDENTITY_VIEWPORT: IViewport;
|
|
76
|
+
/** The rectangle a node occupies, filling in the default size. */
|
|
77
|
+
export declare const nodeRect: (node: IGraphNode) => IRect;
|
|
78
|
+
export declare const rectCenter: (rect: IRect) => IPoint;
|
|
79
|
+
/** Convert a screen-space point (relative to the canvas element) to graph space. */
|
|
80
|
+
export declare const toGraphSpace: (point: IPoint, viewport: IViewport) => IPoint;
|
|
81
|
+
/** Convert a graph-space point to screen space (relative to the canvas element). */
|
|
82
|
+
export declare const toScreenSpace: (point: IPoint, viewport: IViewport) => IPoint;
|
|
83
|
+
/**
|
|
84
|
+
* Zoom about a fixed screen point, so the graph position under the cursor stays
|
|
85
|
+
* under the cursor. Anything else feels wrong to use.
|
|
86
|
+
*/
|
|
87
|
+
export declare const zoomAt: (viewport: IViewport, screenPoint: IPoint, nextScale: number) => IViewport;
|
|
88
|
+
export declare const clampScale: (scale: number, min?: number, max?: number) => number;
|
|
89
|
+
/** The point on a rectangle's edge for a given side. */
|
|
90
|
+
export declare const portPoint: (rect: IRect, port: GraphPort) => IPoint;
|
|
91
|
+
/**
|
|
92
|
+
* Choose which sides an edge should leave and enter, based on which direction
|
|
93
|
+
* dominates. Picking automatically is what lets a node be connectable without
|
|
94
|
+
* declaring handles.
|
|
95
|
+
*/
|
|
96
|
+
export declare const resolvePorts: (from: IRect, to: IRect) => {
|
|
97
|
+
source: GraphPort;
|
|
98
|
+
target: GraphPort;
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* The bounding box of a set of nodes, or `null` when there are none.
|
|
102
|
+
* Used to fit the viewport to the graph.
|
|
103
|
+
*/
|
|
104
|
+
export declare const graphBounds: (nodes: IGraphNode[]) => IRect | null;
|
|
105
|
+
/** A viewport that fits `nodes` inside a element of the given size. */
|
|
106
|
+
export declare const fitViewport: (nodes: IGraphNode[], size: {
|
|
107
|
+
width: number;
|
|
108
|
+
height: number;
|
|
109
|
+
}, padding?: number) => IViewport;
|
|
110
|
+
export type Direction = 'up' | 'down' | 'left' | 'right';
|
|
111
|
+
/**
|
|
112
|
+
* The nearest node in a direction, for arrow-key traversal.
|
|
113
|
+
*
|
|
114
|
+
* Scores candidates by distance along the travel axis, penalised by how far
|
|
115
|
+
* they stray off it. Pure distance would jump to a node that is barely in the
|
|
116
|
+
* right direction but far to the side; requiring perfect alignment would make
|
|
117
|
+
* most of the graph unreachable. The 2× penalty on lateral offset is the
|
|
118
|
+
* compromise, and it matches what feels right when navigating a hand-arranged
|
|
119
|
+
* diagram.
|
|
120
|
+
*
|
|
121
|
+
* Returns `null` when nothing lies in that direction.
|
|
122
|
+
*/
|
|
123
|
+
export declare const findNeighbour: (nodes: IGraphNode[], fromId: string, direction: Direction) => IGraphNode | null;
|
|
124
|
+
/**
|
|
125
|
+
* A free position for a new node placed relative to an existing one, nudged
|
|
126
|
+
* along `direction` and then away from anything it would overlap.
|
|
127
|
+
*
|
|
128
|
+
* Used when creating a node from the keyboard, where there is no cursor to say
|
|
129
|
+
* where it should go.
|
|
130
|
+
*/
|
|
131
|
+
export declare const placeRelativeTo: (nodes: IGraphNode[], fromId: string, direction: Direction, gap?: number) => IPoint;
|
|
132
|
+
/** Edges touching a node, in either direction. */
|
|
133
|
+
export declare const edgesOf: (edges: IGraphEdge[], nodeId: string) => IGraphEdge[];
|
|
134
|
+
/** Whether an edge already joins two nodes, in either direction. */
|
|
135
|
+
export declare const isConnected: (edges: IGraphEdge[], a: string, b: string) => boolean;
|
|
136
|
+
/** Remove a node and every edge attached to it. */
|
|
137
|
+
export declare const removeNode: (nodes: IGraphNode[], edges: IGraphEdge[], nodeId: string) => {
|
|
138
|
+
nodes: IGraphNode[];
|
|
139
|
+
edges: IGraphEdge[];
|
|
140
|
+
};
|
|
141
|
+
/** Generate an id that is unique within a collection. */
|
|
142
|
+
export declare const nextId: (prefix: string, existing: {
|
|
143
|
+
id: string;
|
|
144
|
+
}[]) => string;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The themes bundled in the library's stylesheet.
|
|
3
|
+
*
|
|
4
|
+
* This is the single source of truth. `ThemeService` derives its union type and
|
|
5
|
+
* its class-swapping from it, `ThemeSwitcher` and `SettingsPanel` derive their
|
|
6
|
+
* default options, `initializeShell` derives its theme commands and View menu,
|
|
7
|
+
* and Storybook derives its toolbar. Adding a theme is a block in `index.css`
|
|
8
|
+
* plus one entry here.
|
|
9
|
+
*
|
|
10
|
+
* It lives in `lib/` rather than `core/services/` because the presentational
|
|
11
|
+
* components need it, and they are forbidden from importing stores.
|
|
12
|
+
*
|
|
13
|
+
* Themes are not a closed set — see {@link ThemeSwitcher}'s `options` prop and
|
|
14
|
+
* {@link SettingsPanel}'s `themes` prop for supplying your own.
|
|
15
|
+
*/
|
|
16
|
+
export interface IBundledTheme {
|
|
17
|
+
/** Matches the `.theme-<id>` class in the stylesheet. */
|
|
18
|
+
id: string;
|
|
19
|
+
/** Full name, for menus and the settings panel. */
|
|
20
|
+
label: string;
|
|
21
|
+
/** Abbreviated name, for the compact segmented switcher. */
|
|
22
|
+
shortLabel: string;
|
|
23
|
+
/** One line on what the theme is, used in documentation. */
|
|
24
|
+
description: string;
|
|
25
|
+
}
|
|
26
|
+
export declare const BUNDLED_THEMES: readonly [{
|
|
27
|
+
readonly id: "light";
|
|
28
|
+
readonly label: "Light";
|
|
29
|
+
readonly shortLabel: "Light";
|
|
30
|
+
readonly description: "Neutral light theme. The default.";
|
|
31
|
+
}, {
|
|
32
|
+
readonly id: "dark";
|
|
33
|
+
readonly label: "Dark";
|
|
34
|
+
readonly shortLabel: "Dark";
|
|
35
|
+
readonly description: "Low-glare dark theme on a soft grey base.";
|
|
36
|
+
}, {
|
|
37
|
+
readonly id: "gt";
|
|
38
|
+
readonly label: "Georgia Tech";
|
|
39
|
+
readonly shortLabel: "GT";
|
|
40
|
+
readonly description: "Buzz Gold (#EAAA00) on Tech Tower White.";
|
|
41
|
+
}, {
|
|
42
|
+
readonly id: "tamu";
|
|
43
|
+
readonly label: "Texas A&M";
|
|
44
|
+
readonly shortLabel: "TAMU";
|
|
45
|
+
readonly description: "Aggie Maroon (#500000) on white.";
|
|
46
|
+
}];
|
|
47
|
+
/** Ids of the themes that ship in the stylesheet. */
|
|
48
|
+
export type BundledThemeId = (typeof BUNDLED_THEMES)[number]['id'];
|
|
49
|
+
/** Every bundled theme's class name, e.g. `["theme-light", …]`. */
|
|
50
|
+
export declare const BUNDLED_THEME_CLASSES: string[];
|
|
51
|
+
/**
|
|
52
|
+
* The class name for a theme id.
|
|
53
|
+
*
|
|
54
|
+
* Accepts any string, not just a bundled id, so an app that defines its own
|
|
55
|
+
* `.theme-*` block can use it too.
|
|
56
|
+
*/
|
|
57
|
+
export declare const themeClass: (id: string) => string;
|