@onerjs/shared-ui-components 8.44.7 → 8.44.9
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/components/bars/CommandButton.module.scss +2 -0
- package/historyStack.js +3 -0
- package/historyStack.js.map +1 -1
- package/nodeGraphSystem/common.module.scss +3 -0
- package/nodeGraphSystem/graphCanvas.d.ts +37 -0
- package/nodeGraphSystem/graphCanvas.js +139 -6
- package/nodeGraphSystem/graphCanvas.js.map +1 -1
- package/nodeGraphSystem/graphMinimap.d.ts +79 -0
- package/nodeGraphSystem/graphMinimap.js +319 -0
- package/nodeGraphSystem/graphMinimap.js.map +1 -0
- package/nodeGraphSystem/graphMinimap.module.scss +30 -0
- package/nodeGraphSystem/graphNode.d.ts +16 -0
- package/nodeGraphSystem/graphNode.js +76 -1
- package/nodeGraphSystem/graphNode.js.map +1 -1
- package/nodeGraphSystem/graphNode.module.scss +61 -0
- package/nodeGraphSystem/graphSearch.d.ts +54 -0
- package/nodeGraphSystem/graphSearch.js +181 -0
- package/nodeGraphSystem/graphSearch.js.map +1 -0
- package/nodeGraphSystem/graphSearch.module.scss +86 -0
- package/nodeGraphSystem/graphStickyNote.d.ts +94 -0
- package/nodeGraphSystem/graphStickyNote.js +310 -0
- package/nodeGraphSystem/graphStickyNote.js.map +1 -0
- package/nodeGraphSystem/graphStickyNote.module.scss +87 -0
- package/nodeGraphSystem/interfaces/nodeData.d.ts +2 -0
- package/nodeGraphSystem/interfaces/nodeData.js.map +1 -1
- package/nodeGraphSystem/interfaces/nodeLocationInfo.d.ts +10 -0
- package/nodeGraphSystem/interfaces/nodeLocationInfo.js.map +1 -1
- package/nodeGraphSystem/interfaces/portData.d.ts +2 -1
- package/nodeGraphSystem/interfaces/portData.js +1 -0
- package/nodeGraphSystem/interfaces/portData.js.map +1 -1
- package/nodeGraphSystem/interfaces/selectionChangedOptions.d.ts +2 -1
- package/nodeGraphSystem/interfaces/selectionChangedOptions.js.map +1 -1
- package/nodeGraphSystem/nodeLink.d.ts +12 -0
- package/nodeGraphSystem/nodeLink.js +77 -0
- package/nodeGraphSystem/nodeLink.js.map +1 -1
- package/nodeGraphSystem/nodePort.js +26 -1
- package/nodeGraphSystem/nodePort.js.map +1 -1
- package/nodeGraphSystem/nodePort.module.scss +37 -0
- package/nodeGraphSystem/stateManager.d.ts +6 -0
- package/nodeGraphSystem/stateManager.js +6 -0
- package/nodeGraphSystem/stateManager.js.map +1 -1
- package/package.json +1 -1
- package/split/splitContainer.js +2 -1
- package/split/splitContainer.js.map +1 -1
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import * as styles from "./graphSearch.module.scss";
|
|
4
|
+
/**
|
|
5
|
+
* An overlay search bar for finding nodes and frames in the graph by name or type.
|
|
6
|
+
* Triggered via an observable; press Escape or the close button to dismiss.
|
|
7
|
+
*/
|
|
8
|
+
export class GraphSearchComponent extends React.Component {
|
|
9
|
+
/** @internal */
|
|
10
|
+
constructor(props) {
|
|
11
|
+
super(props);
|
|
12
|
+
this._inputRef = React.createRef();
|
|
13
|
+
this._escHandler = null;
|
|
14
|
+
this._onKeyDown = (evt) => {
|
|
15
|
+
if (evt.key === "Enter") {
|
|
16
|
+
evt.preventDefault();
|
|
17
|
+
if (evt.shiftKey) {
|
|
18
|
+
this._goPrev();
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
this._goNext();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
else if (evt.key === "ArrowDown") {
|
|
25
|
+
evt.preventDefault();
|
|
26
|
+
this._goNext();
|
|
27
|
+
}
|
|
28
|
+
else if (evt.key === "ArrowUp") {
|
|
29
|
+
evt.preventDefault();
|
|
30
|
+
this._goPrev();
|
|
31
|
+
}
|
|
32
|
+
// Stop propagation so the canvas doesn't handle it
|
|
33
|
+
evt.stopPropagation();
|
|
34
|
+
};
|
|
35
|
+
this.state = { visible: false, query: "", currentIndex: 0, results: [] };
|
|
36
|
+
}
|
|
37
|
+
/** Show the search bar and focus the input. */
|
|
38
|
+
show() {
|
|
39
|
+
if (this._escHandler) {
|
|
40
|
+
this.props.canvas.stateManager.hostDocument.removeEventListener("keydown", this._escHandler);
|
|
41
|
+
this._escHandler = null;
|
|
42
|
+
}
|
|
43
|
+
this.setState({ visible: true, query: "", currentIndex: 0, results: [] }, () => {
|
|
44
|
+
this._inputRef.current?.focus();
|
|
45
|
+
});
|
|
46
|
+
this._escHandler = (evt) => {
|
|
47
|
+
if (evt.key === "Escape") {
|
|
48
|
+
this.hide();
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
this.props.canvas.stateManager.hostDocument.addEventListener("keydown", this._escHandler);
|
|
52
|
+
}
|
|
53
|
+
/** Hide the search bar and clear highlights. */
|
|
54
|
+
hide() {
|
|
55
|
+
this._clearHighlights(this.state.results);
|
|
56
|
+
this.setState({ visible: false, query: "", currentIndex: 0, results: [] });
|
|
57
|
+
if (this._escHandler) {
|
|
58
|
+
this.props.canvas.stateManager.hostDocument.removeEventListener("keydown", this._escHandler);
|
|
59
|
+
this._escHandler = null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
_search(query) {
|
|
63
|
+
if (!query.trim()) {
|
|
64
|
+
this._clearHighlights(this.state.results);
|
|
65
|
+
this.setState({ query, results: [], currentIndex: 0 });
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const lowerQuery = query.toLowerCase();
|
|
69
|
+
const results = [];
|
|
70
|
+
for (const node of this.props.canvas.nodes) {
|
|
71
|
+
const name = node.name || "";
|
|
72
|
+
const className = node.content.getClassName ? node.content.getClassName() : "";
|
|
73
|
+
if (name.toLowerCase().includes(lowerQuery) || className.toLowerCase().includes(lowerQuery)) {
|
|
74
|
+
results.push({ node, label: name || className });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
for (const frame of this.props.canvas.frames) {
|
|
78
|
+
if (frame.name.toLowerCase().includes(lowerQuery)) {
|
|
79
|
+
results.push({ frame, label: frame.name });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
// Clear old highlights, apply new
|
|
83
|
+
this._clearHighlights(this.state.results);
|
|
84
|
+
this._applyHighlights(results);
|
|
85
|
+
const newIndex = results.length > 0 ? 0 : 0;
|
|
86
|
+
this.setState({ query, results, currentIndex: newIndex }, () => {
|
|
87
|
+
if (results.length > 0) {
|
|
88
|
+
this._navigateTo(0);
|
|
89
|
+
}
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
_applyHighlights(results) {
|
|
93
|
+
for (const r of results) {
|
|
94
|
+
if (r.node) {
|
|
95
|
+
r.node.rootElement.classList.add(styles["search-match"]);
|
|
96
|
+
}
|
|
97
|
+
else if (r.frame) {
|
|
98
|
+
r.frame.element.classList.add(styles["search-match"]);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
_clearHighlights(results) {
|
|
103
|
+
for (const r of results) {
|
|
104
|
+
if (r.node) {
|
|
105
|
+
r.node.rootElement.classList.remove(styles["search-match"]);
|
|
106
|
+
r.node.rootElement.classList.remove(styles["search-current"]);
|
|
107
|
+
}
|
|
108
|
+
else if (r.frame) {
|
|
109
|
+
r.frame.element.classList.remove(styles["search-match"]);
|
|
110
|
+
r.frame.element.classList.remove(styles["search-current"]);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
_navigateTo(index) {
|
|
115
|
+
const { results } = this.state;
|
|
116
|
+
if (results.length === 0) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
// Remove current highlight from previous
|
|
120
|
+
const prev = results[this.state.currentIndex];
|
|
121
|
+
if (prev) {
|
|
122
|
+
if (prev.node) {
|
|
123
|
+
prev.node.rootElement.classList.remove(styles["search-current"]);
|
|
124
|
+
}
|
|
125
|
+
else if (prev.frame) {
|
|
126
|
+
prev.frame.element.classList.remove(styles["search-current"]);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const result = results[index];
|
|
130
|
+
if (result.node) {
|
|
131
|
+
result.node.rootElement.classList.add(styles["search-current"]);
|
|
132
|
+
this.props.canvas.zoomToNode(result.node);
|
|
133
|
+
this.props.canvas.stateManager.onSelectionChangedObservable.notifyObservers({ selection: result.node });
|
|
134
|
+
}
|
|
135
|
+
else if (result.frame) {
|
|
136
|
+
result.frame.element.classList.add(styles["search-current"]);
|
|
137
|
+
// Center on frame
|
|
138
|
+
const canvas = this.props.canvas;
|
|
139
|
+
const hostWidth = canvas._rootContainer?.clientWidth || 800;
|
|
140
|
+
const hostHeight = canvas._rootContainer?.clientHeight || 600;
|
|
141
|
+
canvas.x = -result.frame.x + hostWidth / (2 * canvas.zoom) - (result.frame.width || 200) / 2;
|
|
142
|
+
canvas.y = -result.frame.y + hostHeight / (2 * canvas.zoom) - 20;
|
|
143
|
+
this.props.canvas.stateManager.onSelectionChangedObservable.notifyObservers({ selection: result.frame });
|
|
144
|
+
}
|
|
145
|
+
this.setState({ currentIndex: index });
|
|
146
|
+
}
|
|
147
|
+
_goNext() {
|
|
148
|
+
const { results, currentIndex } = this.state;
|
|
149
|
+
if (results.length === 0) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const next = (currentIndex + 1) % results.length;
|
|
153
|
+
this._navigateTo(next);
|
|
154
|
+
}
|
|
155
|
+
_goPrev() {
|
|
156
|
+
const { results, currentIndex } = this.state;
|
|
157
|
+
if (results.length === 0) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
const prev = (currentIndex - 1 + results.length) % results.length;
|
|
161
|
+
this._navigateTo(prev);
|
|
162
|
+
}
|
|
163
|
+
/** @internal */
|
|
164
|
+
componentWillUnmount() {
|
|
165
|
+
this._clearHighlights(this.state.results);
|
|
166
|
+
if (this._escHandler) {
|
|
167
|
+
this.props.canvas.stateManager.hostDocument.removeEventListener("keydown", this._escHandler);
|
|
168
|
+
this._escHandler = null;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/** @internal */
|
|
172
|
+
render() {
|
|
173
|
+
if (!this.state.visible) {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
const { results, currentIndex, query } = this.state;
|
|
177
|
+
const hasResults = results.length > 0;
|
|
178
|
+
return (_jsxs("div", { className: styles["search-overlay"], children: [_jsx("input", { ref: this._inputRef, className: styles["search-input"], type: "text", placeholder: "Find in graph...", value: query, onChange: (e) => this._search(e.target.value), onKeyDown: this._onKeyDown, autoFocus: true }), _jsx("span", { className: styles["result-count"], children: query ? (hasResults ? `${currentIndex + 1} of ${results.length}` : "No results") : "" }), _jsx("button", { className: styles["nav-btn"], disabled: !hasResults, onClick: () => this._goPrev(), title: "Previous match (Shift+Enter)", children: "\u25B2" }), _jsx("button", { className: styles["nav-btn"], disabled: !hasResults, onClick: () => this._goNext(), title: "Next match (Enter)", children: "\u25BC" }), _jsx("button", { className: styles["close-btn"], onClick: () => this.hide(), title: "Close (Escape)", children: "\u2715" })] }));
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=graphSearch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"graphSearch.js","sourceRoot":"","sources":["../../../../dev/sharedUiComponents/src/nodeGraphSystem/graphSearch.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from \"react\";\nimport * as styles from \"./graphSearch.module.scss\";\nimport type { GraphCanvasComponent } from \"./graphCanvas\";\nimport type { GraphNode } from \"./graphNode\";\nimport type { GraphFrame } from \"./graphFrame\";\n\n/** A search result pointing to either a node or a frame. */\ninterface ISearchResult {\n node?: GraphNode;\n frame?: GraphFrame;\n label: string;\n}\n\n/**\n * Props for the GraphSearchComponent.\n */\nexport interface IGraphSearchComponentProps {\n /** The graph canvas to search within */\n canvas: GraphCanvasComponent;\n}\n\n/** Internal state for GraphSearchComponent. */\ninterface IGraphSearchState {\n /** Whether the search overlay is visible */\n visible: boolean;\n /** The current search query */\n query: string;\n /** Index of the currently focused result */\n currentIndex: number;\n /** Matching search results */\n results: ISearchResult[];\n}\n\n/**\n * An overlay search bar for finding nodes and frames in the graph by name or type.\n * Triggered via an observable; press Escape or the close button to dismiss.\n */\nexport class GraphSearchComponent extends React.Component<IGraphSearchComponentProps, IGraphSearchState> {\n private _inputRef = React.createRef<HTMLInputElement>();\n private _escHandler: ((evt: KeyboardEvent) => void) | null = null;\n\n /** @internal */\n constructor(props: IGraphSearchComponentProps) {\n super(props);\n this.state = { visible: false, query: \"\", currentIndex: 0, results: [] };\n }\n\n /** Show the search bar and focus the input. */\n show() {\n if (this._escHandler) {\n this.props.canvas.stateManager.hostDocument.removeEventListener(\"keydown\", this._escHandler);\n this._escHandler = null;\n }\n this.setState({ visible: true, query: \"\", currentIndex: 0, results: [] }, () => {\n this._inputRef.current?.focus();\n });\n this._escHandler = (evt: KeyboardEvent) => {\n if (evt.key === \"Escape\") {\n this.hide();\n }\n };\n this.props.canvas.stateManager.hostDocument.addEventListener(\"keydown\", this._escHandler);\n }\n\n /** Hide the search bar and clear highlights. */\n hide() {\n this._clearHighlights(this.state.results);\n this.setState({ visible: false, query: \"\", currentIndex: 0, results: [] });\n if (this._escHandler) {\n this.props.canvas.stateManager.hostDocument.removeEventListener(\"keydown\", this._escHandler);\n this._escHandler = null;\n }\n }\n\n private _search(query: string) {\n if (!query.trim()) {\n this._clearHighlights(this.state.results);\n this.setState({ query, results: [], currentIndex: 0 });\n return;\n }\n\n const lowerQuery = query.toLowerCase();\n const results: ISearchResult[] = [];\n\n for (const node of this.props.canvas.nodes) {\n const name = node.name || \"\";\n const className = node.content.getClassName ? node.content.getClassName() : \"\";\n if (name.toLowerCase().includes(lowerQuery) || className.toLowerCase().includes(lowerQuery)) {\n results.push({ node, label: name || className });\n }\n }\n\n for (const frame of this.props.canvas.frames) {\n if (frame.name.toLowerCase().includes(lowerQuery)) {\n results.push({ frame, label: frame.name });\n }\n }\n\n // Clear old highlights, apply new\n this._clearHighlights(this.state.results);\n this._applyHighlights(results);\n\n const newIndex = results.length > 0 ? 0 : 0;\n this.setState({ query, results, currentIndex: newIndex }, () => {\n if (results.length > 0) {\n this._navigateTo(0);\n }\n });\n }\n\n private _applyHighlights(results: ISearchResult[]) {\n for (const r of results) {\n if (r.node) {\n r.node.rootElement.classList.add(styles[\"search-match\"]);\n } else if (r.frame) {\n r.frame.element.classList.add(styles[\"search-match\"]);\n }\n }\n }\n\n private _clearHighlights(results: ISearchResult[]) {\n for (const r of results) {\n if (r.node) {\n r.node.rootElement.classList.remove(styles[\"search-match\"]);\n r.node.rootElement.classList.remove(styles[\"search-current\"]);\n } else if (r.frame) {\n r.frame.element.classList.remove(styles[\"search-match\"]);\n r.frame.element.classList.remove(styles[\"search-current\"]);\n }\n }\n }\n\n private _navigateTo(index: number) {\n const { results } = this.state;\n if (results.length === 0) {\n return;\n }\n\n // Remove current highlight from previous\n const prev = results[this.state.currentIndex];\n if (prev) {\n if (prev.node) {\n prev.node.rootElement.classList.remove(styles[\"search-current\"]);\n } else if (prev.frame) {\n prev.frame.element.classList.remove(styles[\"search-current\"]);\n }\n }\n\n const result = results[index];\n if (result.node) {\n result.node.rootElement.classList.add(styles[\"search-current\"]);\n this.props.canvas.zoomToNode(result.node);\n this.props.canvas.stateManager.onSelectionChangedObservable.notifyObservers({ selection: result.node });\n } else if (result.frame) {\n result.frame.element.classList.add(styles[\"search-current\"]);\n // Center on frame\n const canvas = this.props.canvas;\n const hostWidth = (canvas as any)._rootContainer?.clientWidth || 800;\n const hostHeight = (canvas as any)._rootContainer?.clientHeight || 600;\n canvas.x = -result.frame.x + hostWidth / (2 * canvas.zoom) - (result.frame.width || 200) / 2;\n canvas.y = -result.frame.y + hostHeight / (2 * canvas.zoom) - 20;\n this.props.canvas.stateManager.onSelectionChangedObservable.notifyObservers({ selection: result.frame });\n }\n\n this.setState({ currentIndex: index });\n }\n\n private _goNext() {\n const { results, currentIndex } = this.state;\n if (results.length === 0) {\n return;\n }\n const next = (currentIndex + 1) % results.length;\n this._navigateTo(next);\n }\n\n private _goPrev() {\n const { results, currentIndex } = this.state;\n if (results.length === 0) {\n return;\n }\n const prev = (currentIndex - 1 + results.length) % results.length;\n this._navigateTo(prev);\n }\n\n private _onKeyDown = (evt: React.KeyboardEvent) => {\n if (evt.key === \"Enter\") {\n evt.preventDefault();\n if (evt.shiftKey) {\n this._goPrev();\n } else {\n this._goNext();\n }\n } else if (evt.key === \"ArrowDown\") {\n evt.preventDefault();\n this._goNext();\n } else if (evt.key === \"ArrowUp\") {\n evt.preventDefault();\n this._goPrev();\n }\n // Stop propagation so the canvas doesn't handle it\n evt.stopPropagation();\n };\n\n /** @internal */\n override componentWillUnmount() {\n this._clearHighlights(this.state.results);\n if (this._escHandler) {\n this.props.canvas.stateManager.hostDocument.removeEventListener(\"keydown\", this._escHandler);\n this._escHandler = null;\n }\n }\n\n /** @internal */\n override render() {\n if (!this.state.visible) {\n return null;\n }\n\n const { results, currentIndex, query } = this.state;\n const hasResults = results.length > 0;\n\n return (\n <div className={styles[\"search-overlay\"]}>\n <input\n ref={this._inputRef}\n className={styles[\"search-input\"]}\n type=\"text\"\n placeholder=\"Find in graph...\"\n value={query}\n onChange={(e) => this._search(e.target.value)}\n onKeyDown={this._onKeyDown}\n autoFocus\n />\n <span className={styles[\"result-count\"]}>{query ? (hasResults ? `${currentIndex + 1} of ${results.length}` : \"No results\") : \"\"}</span>\n <button className={styles[\"nav-btn\"]} disabled={!hasResults} onClick={() => this._goPrev()} title=\"Previous match (Shift+Enter)\">\n ▲\n </button>\n <button className={styles[\"nav-btn\"]} disabled={!hasResults} onClick={() => this._goNext()} title=\"Next match (Enter)\">\n ▼\n </button>\n <button className={styles[\"close-btn\"]} onClick={() => this.hide()} title=\"Close (Escape)\">\n ✕\n </button>\n </div>\n );\n }\n}\n"]}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
.search-overlay {
|
|
2
|
+
position: absolute;
|
|
3
|
+
top: 12px;
|
|
4
|
+
right: 12px;
|
|
5
|
+
z-index: 100;
|
|
6
|
+
display: flex;
|
|
7
|
+
align-items: center;
|
|
8
|
+
gap: 4px;
|
|
9
|
+
background: #2b2b2b;
|
|
10
|
+
border: 1px solid #555;
|
|
11
|
+
border-radius: 6px;
|
|
12
|
+
padding: 4px 8px;
|
|
13
|
+
box-shadow: 0 2px 12px rgba(0, 0, 0, 0.5);
|
|
14
|
+
font-family: "acumin-pro-condensed", sans-serif;
|
|
15
|
+
font-size: 13px;
|
|
16
|
+
color: #ccc;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.search-input {
|
|
20
|
+
background: #1e1e1e;
|
|
21
|
+
border: 1px solid #444;
|
|
22
|
+
border-radius: 4px;
|
|
23
|
+
color: #eee;
|
|
24
|
+
font-size: 13px;
|
|
25
|
+
padding: 4px 8px;
|
|
26
|
+
width: 200px;
|
|
27
|
+
outline: none;
|
|
28
|
+
|
|
29
|
+
&:focus {
|
|
30
|
+
border-color: #5da0e0;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&::placeholder {
|
|
34
|
+
color: #777;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
.result-count {
|
|
39
|
+
color: #999;
|
|
40
|
+
font-size: 12px;
|
|
41
|
+
min-width: 56px;
|
|
42
|
+
text-align: center;
|
|
43
|
+
white-space: nowrap;
|
|
44
|
+
user-select: none;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.nav-btn {
|
|
48
|
+
background: transparent;
|
|
49
|
+
border: 1px solid #555;
|
|
50
|
+
border-radius: 3px;
|
|
51
|
+
color: #ccc;
|
|
52
|
+
cursor: pointer;
|
|
53
|
+
font-size: 13px;
|
|
54
|
+
width: 24px;
|
|
55
|
+
height: 24px;
|
|
56
|
+
display: flex;
|
|
57
|
+
align-items: center;
|
|
58
|
+
justify-content: center;
|
|
59
|
+
padding: 0;
|
|
60
|
+
|
|
61
|
+
&:hover {
|
|
62
|
+
background: #3a3a3a;
|
|
63
|
+
color: #fff;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
&:disabled {
|
|
67
|
+
opacity: 0.3;
|
|
68
|
+
cursor: default;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.close-btn {
|
|
73
|
+
composes: nav-btn;
|
|
74
|
+
margin-left: 2px;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.search-match {
|
|
78
|
+
outline: 2px solid rgba(255, 200, 50, 0.8) !important;
|
|
79
|
+
outline-offset: 2px;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
.search-current {
|
|
83
|
+
outline: 2px solid #5da0e0 !important;
|
|
84
|
+
outline-offset: 2px;
|
|
85
|
+
box-shadow: 0 0 12px rgba(93, 160, 224, 0.5);
|
|
86
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import type { GraphCanvasComponent } from "./graphCanvas.js";
|
|
2
|
+
import type { IStickyNoteData } from "./interfaces/nodeLocationInfo.js";
|
|
3
|
+
/**
|
|
4
|
+
* A free-floating sticky note annotation on the graph canvas.
|
|
5
|
+
*
|
|
6
|
+
* Sticky notes are lightweight, text-only overlays that live in the frame container.
|
|
7
|
+
* They support dragging, resizing, and inline editing of both title and body text.
|
|
8
|
+
* Unlike frames, they do not group or contain nodes.
|
|
9
|
+
*/
|
|
10
|
+
export declare class GraphStickyNote {
|
|
11
|
+
/** The root DOM element for this sticky note. */
|
|
12
|
+
element: HTMLDivElement;
|
|
13
|
+
private _ownerCanvas;
|
|
14
|
+
private _id;
|
|
15
|
+
private _x;
|
|
16
|
+
private _y;
|
|
17
|
+
private _width;
|
|
18
|
+
private _height;
|
|
19
|
+
private _name;
|
|
20
|
+
private _body;
|
|
21
|
+
private _color;
|
|
22
|
+
private _headerElement;
|
|
23
|
+
private _titleElement;
|
|
24
|
+
private _bodyElement;
|
|
25
|
+
private _resizeHandle;
|
|
26
|
+
private _mouseStartX;
|
|
27
|
+
private _mouseStartY;
|
|
28
|
+
private _isDragging;
|
|
29
|
+
private _isResizing;
|
|
30
|
+
private _resizeStartW;
|
|
31
|
+
private _resizeStartH;
|
|
32
|
+
/** Unique ID for this sticky note */
|
|
33
|
+
get id(): number;
|
|
34
|
+
/** X position in canvas space */
|
|
35
|
+
get x(): number;
|
|
36
|
+
/** X position in canvas space */
|
|
37
|
+
set x(value: number);
|
|
38
|
+
/** Y position in canvas space */
|
|
39
|
+
get y(): number;
|
|
40
|
+
/** Y position in canvas space */
|
|
41
|
+
set y(value: number);
|
|
42
|
+
/** Width in pixels */
|
|
43
|
+
get width(): number;
|
|
44
|
+
/** Width in pixels */
|
|
45
|
+
set width(value: number);
|
|
46
|
+
/** Height in pixels */
|
|
47
|
+
get height(): number;
|
|
48
|
+
/** Height in pixels */
|
|
49
|
+
set height(value: number);
|
|
50
|
+
/** Display name */
|
|
51
|
+
get name(): string;
|
|
52
|
+
/** Display name */
|
|
53
|
+
set name(value: string);
|
|
54
|
+
/** Body text content */
|
|
55
|
+
get body(): string;
|
|
56
|
+
/** Body text content */
|
|
57
|
+
set body(value: string);
|
|
58
|
+
/** Background color CSS value */
|
|
59
|
+
get color(): string;
|
|
60
|
+
/** Background color CSS value */
|
|
61
|
+
set color(value: string);
|
|
62
|
+
/**
|
|
63
|
+
* Create a new sticky note on the canvas.
|
|
64
|
+
* @param canvas - the owning graph canvas component
|
|
65
|
+
*/
|
|
66
|
+
constructor(canvas: GraphCanvasComponent);
|
|
67
|
+
/**
|
|
68
|
+
* Mark this note as visually selected or deselected.
|
|
69
|
+
* @param selected - whether the note is selected
|
|
70
|
+
*/
|
|
71
|
+
setIsSelected(selected: boolean): void;
|
|
72
|
+
/**
|
|
73
|
+
* Serialize this sticky note to a plain data object.
|
|
74
|
+
* @returns the serialized data
|
|
75
|
+
*/
|
|
76
|
+
serialize(): IStickyNoteData;
|
|
77
|
+
/**
|
|
78
|
+
* Create a sticky note from serialized data.
|
|
79
|
+
* @param data - the serialized sticky note data
|
|
80
|
+
* @param canvas - the owning graph canvas
|
|
81
|
+
* @returns the new sticky note instance
|
|
82
|
+
*/
|
|
83
|
+
static Parse(data: IStickyNoteData, canvas: GraphCanvasComponent): GraphStickyNote;
|
|
84
|
+
/**
|
|
85
|
+
* Remove this sticky note from the canvas and clean up.
|
|
86
|
+
*/
|
|
87
|
+
dispose(): void;
|
|
88
|
+
private _onDragStart;
|
|
89
|
+
private _onDragMoveHandler;
|
|
90
|
+
private _onDragEndHandler;
|
|
91
|
+
private _onResizeStart;
|
|
92
|
+
private _onResizeMoveHandler;
|
|
93
|
+
private _onResizeEndHandler;
|
|
94
|
+
}
|