@loradb/lora-graph-canvas 0.10.1 → 0.11.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/README.md +31 -0
- package/dist/LoraGraphCanvas.stories.d.ts +1 -0
- package/dist/engines/rafAnim.d.ts +5 -1
- package/dist/hooks/useGraphClipboard.d.ts +7 -1
- package/dist/hooks/useGraphDeleteGate.d.ts +38 -0
- package/dist/hooks/useGraphKeybindings.d.ts +7 -0
- package/dist/hooks/useImperativeGraphHandle.d.ts +2 -0
- package/dist/hooks/useMarqueeAndCursor.d.ts +5 -0
- package/dist/hooks/usePrefersReducedMotion.d.ts +10 -0
- package/dist/index.cjs +44 -44
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4811 -4453
- package/dist/index.js.map +1 -1
- package/dist/internal/runGuard.d.ts +7 -0
- package/dist/style.css +1 -1
- package/dist/tools/MarqueeOverlay.d.ts +8 -2
- package/dist/types.d.ts +41 -4
- package/package.json +1 -1
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { DeletionGuard, DeletionSource } from '../types';
|
|
2
|
+
/** Runs an optional deletion guard, returning `true` when the mutation
|
|
3
|
+
* should proceed. Empty batches short-circuit to `true` so callers can
|
|
4
|
+
* use the same code path whether or not anything is actually selected.
|
|
5
|
+
* A thrown error in the guard is swallowed as a cancel — a throwing
|
|
6
|
+
* host should not silently destroy data. */
|
|
7
|
+
export declare function runGuard<T>(guard: DeletionGuard<T> | undefined, items: T[], source: DeletionSource): Promise<boolean>;
|
package/dist/style.css
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
.graph-info-msg{top:50%;width:100%;text-align:center;color:#e6e6fa;opacity:.7;font-size:22px;position:absolute;font-family:Sans-serif}.scene-container .clickable{cursor:pointer}.scene-container .grabbable{cursor:move;cursor:grab;cursor:-moz-grab;cursor:-webkit-grab}.scene-container .grabbable:active{cursor:grabbing;cursor:-moz-grabbing;cursor:-webkit-grabbing}.lora-graph-canvas{--lgc-bg: transparent;--lgc-fg: #1c1f23;--lgc-border: #d8dde3;--lgc-accent: #4f8ef7;--lgc-toolbar-bg: rgba(255, 255, 255, .92);--lgc-toolbar-fg: var(--lgc-fg);--lgc-toolbar-border: var(--lgc-border);--lgc-tool-active-bg: rgba(79, 142, 247, .18);--lgc-tool-hover-bg: rgba(0, 0, 0, .05);--lgc-tooltip-bg: rgba(28, 31, 35, .9);--lgc-tooltip-fg: #ffffff;--lgc-menu-bg: #ffffff;--lgc-menu-fg: var(--lgc-fg);--lgc-menu-hover-bg: rgba(0, 0, 0, .06);--lgc-font: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;--lgc-font-size: 13px;position:relative;overflow:hidden;background:var(--lgc-bg);color:var(--lgc-fg);font-family:var(--lgc-font);font-size:var(--lgc-font-size)}.lora-graph-canvas .lgc-engine-mount{position:absolute;inset:0}.lora-graph-canvas .lgc-engine-mount>canvas{display:block}.lora-graph-canvas .lgc-toolbar{position:absolute;display:flex;gap:2px;padding:4px;background:var(--lgc-toolbar-bg);color:var(--lgc-toolbar-fg);border:1px solid var(--lgc-toolbar-border);border-radius:8px;backdrop-filter:blur(8px);box-shadow:0 1px 2px #0000000f;z-index:2}.lora-graph-canvas .lgc-toolbar--top,.lora-graph-canvas .lgc-toolbar--top-right,.lora-graph-canvas .lgc-toolbar--top-left{top:12px}.lora-graph-canvas .lgc-toolbar--top{left:50%;transform:translate(-50%)}.lora-graph-canvas .lgc-toolbar--top-right{right:12px}.lora-graph-canvas .lgc-toolbar--top-left{left:12px}.lora-graph-canvas .lgc-toolbar--bottom{bottom:12px;left:50%;transform:translate(-50%)}.lora-graph-canvas .lgc-tool{appearance:none;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:0;border-radius:6px;background:transparent;color:inherit;cursor:pointer;transition:background-color 90ms ease,color 90ms ease}.lora-graph-canvas .lgc-tool:hover{background:var(--lgc-tool-hover-bg)}.lora-graph-canvas .lgc-tool--active{background:var(--lgc-tool-active-bg);color:var(--lgc-accent)}.lora-graph-canvas .lgc-tool--disabled,.lora-graph-canvas .lgc-tool:disabled{opacity:.35;cursor:not-allowed}.lora-graph-canvas .lgc-tool--disabled:hover,.lora-graph-canvas .lgc-tool:disabled:hover{background:transparent}.lora-graph-canvas .lgc-tool:focus-visible{outline:2px solid var(--lgc-accent);outline-offset:1px}.lora-graph-canvas .lgc-selpanel{position:absolute;top:12px;left:12px;display:flex;align-items:center;gap:4px;padding:4px 6px 4px 10px;background:var(--lgc-toolbar-bg);color:var(--lgc-toolbar-fg);border:1px solid var(--lgc-toolbar-border);border-radius:8px;backdrop-filter:blur(8px);box-shadow:0 1px 2px #0000000f;font-size:12px;z-index:2}.lora-graph-canvas .lgc-selpanel-label{font-weight:500;white-space:nowrap}.lora-graph-canvas .lgc-selpanel-divider{width:1px;height:16px;background:var(--lgc-toolbar-border);margin:0 2px}.lora-graph-canvas .lgc-selpanel-btn{appearance:none;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:0;border-radius:4px;background:transparent;color:inherit;cursor:pointer;transition:background-color 90ms ease}.lora-graph-canvas .lgc-selpanel-btn:hover{background:var(--lgc-tool-hover-bg)}.lora-graph-canvas .lgc-selpanel-btn:disabled{opacity:.35;cursor:not-allowed}.lora-graph-canvas .lgc-selpanel-btn:disabled:hover{background:transparent}.lora-graph-canvas .lgc-options-menu{position:absolute;bottom:52px;right:12px;z-index:2}.lora-graph-canvas .lgc-options-trigger{appearance:none;display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;background:var(--lgc-toolbar-bg);color:var(--lgc-toolbar-fg);border:1px solid var(--lgc-toolbar-border);border-radius:8px;backdrop-filter:blur(8px);box-shadow:0 1px 2px #0000000f;cursor:pointer;transition:background-color 90ms ease}.lora-graph-canvas .lgc-options-trigger:hover{background:var(--lgc-tool-hover-bg)}.lora-graph-canvas .lgc-options-trigger:focus-visible{outline:2px solid var(--lgc-accent);outline-offset:1px}.lora-graph-canvas .lgc-options-panel{position:absolute;bottom:36px;right:0;min-width:220px;padding:6px;background:var(--lgc-menu-bg);color:var(--lgc-menu-fg);border:1px solid var(--lgc-toolbar-border);border-radius:8px;box-shadow:0 8px 24px #00000029;font-size:12px;line-height:1.3}.lora-graph-canvas .lgc-options-item{display:flex;align-items:flex-start;gap:8px;padding:6px 8px;border-radius:4px;cursor:pointer}.lora-graph-canvas .lgc-options-item:hover{background:var(--lgc-menu-hover-bg)}.lora-graph-canvas .lgc-options-item input[type=checkbox]{margin-top:2px}.lora-graph-canvas .lgc-options-item-text{display:flex;flex-direction:column;gap:2px}.lora-graph-canvas .lgc-options-item-label{font-weight:500}.lora-graph-canvas .lgc-options-item-hint{opacity:.65;font-size:11px}.lora-graph-canvas .lgc-options-select{margin-left:auto;font:inherit;font-size:11px;padding:2px 4px;background:var(--lgc-toolbar-bg);color:var(--lgc-toolbar-fg);border:1px solid var(--lgc-toolbar-border);border-radius:4px}.lora-graph-canvas .lgc-mode-toggle{position:absolute;bottom:12px;right:12px;display:inline-flex;align-items:center;gap:6px;padding:5px 10px;background:var(--lgc-toolbar-bg);color:var(--lgc-toolbar-fg);border:1px solid var(--lgc-toolbar-border);border-radius:8px;backdrop-filter:blur(8px);box-shadow:0 1px 2px #0000000f;font:inherit;font-size:11px;font-weight:600;letter-spacing:.04em;cursor:pointer;z-index:2;transition:background-color 90ms ease}.lora-graph-canvas .lgc-mode-toggle:hover{background:var(--lgc-tool-hover-bg)}.lora-graph-canvas .lgc-mode-toggle:focus-visible{outline:2px solid var(--lgc-accent);outline-offset:1px}.lora-graph-canvas .lgc-mode-toggle-label{font-variant-numeric:tabular-nums}.lora-graph-canvas .lgc-legend{position:absolute;bottom:12px;left:12px;display:flex;flex-direction:column;gap:2px;padding:6px;background:var(--lgc-toolbar-bg);color:var(--lgc-toolbar-fg);border:1px solid var(--lgc-toolbar-border);border-radius:8px;backdrop-filter:blur(8px);font-size:12px;z-index:2;max-height:40%;overflow-y:auto}.lora-graph-canvas .lgc-legend-item{appearance:none;display:flex;align-items:center;gap:8px;padding:2px 8px 2px 4px;border:0;border-radius:4px;background:transparent;color:inherit;cursor:pointer;text-align:left;font:inherit}.lora-graph-canvas .lgc-legend-item:hover{background:var(--lgc-tool-hover-bg)}.lora-graph-canvas .lgc-legend-item--hidden{opacity:.35;text-decoration:line-through}.lora-graph-canvas .lgc-legend-swatch{display:inline-block;width:12px;height:12px;border-radius:3px}.lora-graph-canvas .lgc-marquee{position:absolute;border:1px dashed var(--lgc-accent);background:color-mix(in srgb,var(--lgc-accent) 12%,transparent);border-radius:2px;z-index:2}.lora-graph-canvas .lgc-tooltip{position:absolute;max-width:280px;padding:4px 8px;background:var(--lgc-tooltip-bg);color:var(--lgc-tooltip-fg);border-radius:4px;font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;z-index:4;box-shadow:0 2px 6px #0000001f}.lora-graph-canvas .lgc-menu{position:absolute;min-width:180px;padding:4px;background:var(--lgc-menu-bg);color:var(--lgc-menu-fg);border:1px solid var(--lgc-toolbar-border);border-radius:8px;box-shadow:0 8px 24px #00000029;z-index:3}.lora-graph-canvas .lgc-menu-item{display:flex;align-items:center;gap:8px;padding:6px 10px;border-radius:4px;cursor:pointer;user-select:none}.lora-graph-canvas .lgc-menu-item:hover{background:var(--lgc-menu-hover-bg)}.lora-graph-canvas .lgc-menu-separator{height:1px;margin:4px 0;background:var(--lgc-toolbar-border)}
|
|
1
|
+
.graph-info-msg{top:50%;width:100%;text-align:center;color:#e6e6fa;opacity:.7;font-size:22px;position:absolute;font-family:Sans-serif}.scene-container .clickable{cursor:pointer}.scene-container .grabbable{cursor:move;cursor:grab;cursor:-moz-grab;cursor:-webkit-grab}.scene-container .grabbable:active{cursor:grabbing;cursor:-moz-grabbing;cursor:-webkit-grabbing}.lora-graph-canvas{--lgc-bg: transparent;--lgc-fg: #1c1f23;--lgc-border: #d8dde3;--lgc-accent: #4f8ef7;--lgc-toolbar-bg: rgba(255, 255, 255, .92);--lgc-toolbar-fg: var(--lgc-fg);--lgc-toolbar-border: var(--lgc-border);--lgc-tool-active-bg: rgba(79, 142, 247, .18);--lgc-tool-hover-bg: rgba(0, 0, 0, .05);--lgc-tooltip-bg: rgba(28, 31, 35, .9);--lgc-tooltip-fg: #ffffff;--lgc-menu-bg: #ffffff;--lgc-menu-fg: var(--lgc-fg);--lgc-menu-hover-bg: rgba(0, 0, 0, .06);--lgc-font: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;--lgc-font-size: 13px;position:relative;overflow:hidden;background:var(--lgc-bg);color:var(--lgc-fg);font-family:var(--lgc-font);font-size:var(--lgc-font-size)}.lora-graph-canvas .lgc-engine-mount{position:absolute;inset:0}.lora-graph-canvas .lgc-engine-mount>canvas{display:block}.lora-graph-canvas[data-tool=pan] .lgc-engine-mount{cursor:grab}.lora-graph-canvas[data-tool=pan] .lgc-engine-mount:active{cursor:grabbing}.lora-graph-canvas[data-tool=add-node] .lgc-engine-mount,.lora-graph-canvas[data-tool=add-link] .lgc-engine-mount{cursor:crosshair}.lora-graph-canvas[data-paused=true]{box-shadow:inset 0 2px 0 var(--lgc-accent)}.lora-graph-canvas .lgc-toolbar{position:absolute;display:flex;gap:2px;padding:4px;background:var(--lgc-toolbar-bg);color:var(--lgc-toolbar-fg);border:1px solid var(--lgc-toolbar-border);border-radius:8px;backdrop-filter:blur(8px);box-shadow:0 1px 2px #0000000f;z-index:2}.lora-graph-canvas .lgc-toolbar--top,.lora-graph-canvas .lgc-toolbar--top-right,.lora-graph-canvas .lgc-toolbar--top-left{top:12px}.lora-graph-canvas .lgc-toolbar--top{left:50%;transform:translate(-50%)}.lora-graph-canvas .lgc-toolbar--top-right{right:12px}.lora-graph-canvas .lgc-toolbar--top-left{left:12px}.lora-graph-canvas .lgc-toolbar--bottom{bottom:12px;left:50%;transform:translate(-50%)}.lora-graph-canvas .lgc-tool{appearance:none;display:inline-flex;align-items:center;justify-content:center;width:28px;height:28px;padding:0;border:0;border-radius:6px;background:transparent;color:inherit;cursor:pointer;transition:background-color 90ms ease,color 90ms ease}.lora-graph-canvas .lgc-tool:hover{background:var(--lgc-tool-hover-bg)}.lora-graph-canvas .lgc-tool--active{background:var(--lgc-tool-active-bg);color:var(--lgc-accent)}.lora-graph-canvas .lgc-tool--disabled,.lora-graph-canvas .lgc-tool:disabled{opacity:.35;cursor:not-allowed}.lora-graph-canvas .lgc-tool--disabled:hover,.lora-graph-canvas .lgc-tool:disabled:hover{background:transparent}.lora-graph-canvas .lgc-tool:focus-visible{outline:2px solid var(--lgc-accent);outline-offset:1px}.lora-graph-canvas .lgc-selpanel{position:absolute;top:12px;left:12px;display:flex;align-items:center;gap:4px;padding:4px 6px 4px 10px;background:var(--lgc-toolbar-bg);color:var(--lgc-toolbar-fg);border:1px solid var(--lgc-toolbar-border);border-radius:8px;backdrop-filter:blur(8px);box-shadow:0 1px 2px #0000000f;font-size:12px;z-index:2}.lora-graph-canvas .lgc-selpanel-label{font-weight:500;white-space:nowrap}.lora-graph-canvas .lgc-selpanel-divider{width:1px;height:16px;background:var(--lgc-toolbar-border);margin:0 2px}.lora-graph-canvas .lgc-selpanel-btn{appearance:none;display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:0;border-radius:4px;background:transparent;color:inherit;cursor:pointer;transition:background-color 90ms ease}.lora-graph-canvas .lgc-selpanel-btn:hover{background:var(--lgc-tool-hover-bg)}.lora-graph-canvas .lgc-selpanel-btn:disabled{opacity:.35;cursor:not-allowed}.lora-graph-canvas .lgc-selpanel-btn:disabled:hover{background:transparent}.lora-graph-canvas .lgc-options-menu{position:absolute;bottom:52px;right:12px;z-index:2}.lora-graph-canvas .lgc-options-trigger{appearance:none;display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;padding:0;background:var(--lgc-toolbar-bg);color:var(--lgc-toolbar-fg);border:1px solid var(--lgc-toolbar-border);border-radius:8px;backdrop-filter:blur(8px);box-shadow:0 1px 2px #0000000f;cursor:pointer;transition:background-color 90ms ease}.lora-graph-canvas .lgc-options-trigger:hover{background:var(--lgc-tool-hover-bg)}.lora-graph-canvas .lgc-options-trigger:focus-visible{outline:2px solid var(--lgc-accent);outline-offset:1px}.lora-graph-canvas .lgc-options-panel{position:absolute;bottom:36px;right:0;min-width:220px;padding:6px;background:var(--lgc-menu-bg);color:var(--lgc-menu-fg);border:1px solid var(--lgc-toolbar-border);border-radius:8px;box-shadow:0 8px 24px #00000029;font-size:12px;line-height:1.3}.lora-graph-canvas .lgc-options-item{display:flex;align-items:flex-start;gap:8px;padding:6px 8px;border-radius:4px;cursor:pointer}.lora-graph-canvas .lgc-options-item:hover{background:var(--lgc-menu-hover-bg)}.lora-graph-canvas .lgc-options-item input[type=checkbox]{margin-top:2px}.lora-graph-canvas .lgc-options-item-text{display:flex;flex-direction:column;gap:2px}.lora-graph-canvas .lgc-options-item-label{font-weight:500}.lora-graph-canvas .lgc-options-item-hint{opacity:.65;font-size:11px}.lora-graph-canvas .lgc-options-select{margin-left:auto;font:inherit;font-size:11px;padding:2px 4px;background:var(--lgc-toolbar-bg);color:var(--lgc-toolbar-fg);border:1px solid var(--lgc-toolbar-border);border-radius:4px}.lora-graph-canvas .lgc-mode-toggle{position:absolute;bottom:12px;right:12px;display:inline-flex;align-items:center;gap:6px;padding:5px 10px;background:var(--lgc-toolbar-bg);color:var(--lgc-toolbar-fg);border:1px solid var(--lgc-toolbar-border);border-radius:8px;backdrop-filter:blur(8px);box-shadow:0 1px 2px #0000000f;font:inherit;font-size:11px;font-weight:600;letter-spacing:.04em;cursor:pointer;z-index:2;transition:background-color 90ms ease}.lora-graph-canvas .lgc-mode-toggle:hover{background:var(--lgc-tool-hover-bg)}.lora-graph-canvas .lgc-mode-toggle:focus-visible{outline:2px solid var(--lgc-accent);outline-offset:1px}.lora-graph-canvas .lgc-mode-toggle-label{font-variant-numeric:tabular-nums}.lora-graph-canvas .lgc-legend{position:absolute;bottom:12px;left:12px;display:flex;flex-direction:column;gap:2px;padding:6px;background:var(--lgc-toolbar-bg);color:var(--lgc-toolbar-fg);border:1px solid var(--lgc-toolbar-border);border-radius:8px;backdrop-filter:blur(8px);font-size:12px;z-index:2;max-height:40%;overflow-y:auto}.lora-graph-canvas .lgc-legend-item{appearance:none;display:flex;align-items:center;gap:8px;padding:2px 8px 2px 4px;border:0;border-radius:4px;background:transparent;color:inherit;cursor:pointer;text-align:left;font:inherit}.lora-graph-canvas .lgc-legend-item:hover{background:var(--lgc-tool-hover-bg)}.lora-graph-canvas .lgc-legend-item--hidden{opacity:.35;text-decoration:line-through}.lora-graph-canvas .lgc-legend-swatch{display:inline-block;width:12px;height:12px;border-radius:3px}.lora-graph-canvas .lgc-marquee{position:absolute;border:1px dashed var(--lgc-accent);background:color-mix(in srgb,var(--lgc-accent) 12%,transparent);border-radius:2px;z-index:2}.lora-graph-canvas .lgc-marquee-count{position:absolute;right:-2px;bottom:-22px;display:inline-flex;align-items:center;justify-content:center;padding:1px 6px;font-size:11px;font-weight:600;color:#fff;background:var(--lgc-accent);border-radius:10px;pointer-events:none;font-variant-numeric:tabular-nums}.lora-graph-canvas .lgc-tooltip{position:absolute;max-width:280px;padding:4px 8px;background:var(--lgc-tooltip-bg);color:var(--lgc-tooltip-fg);border-radius:4px;font-size:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;z-index:4;box-shadow:0 2px 6px #0000001f}.lora-graph-canvas .lgc-menu{position:absolute;min-width:180px;padding:4px;background:var(--lgc-menu-bg);color:var(--lgc-menu-fg);border:1px solid var(--lgc-toolbar-border);border-radius:8px;box-shadow:0 8px 24px #00000029;z-index:3}.lora-graph-canvas .lgc-menu-item{display:flex;align-items:center;gap:8px;padding:6px 10px;border-radius:4px;cursor:pointer;user-select:none}.lora-graph-canvas .lgc-menu-item:hover{background:var(--lgc-menu-hover-bg)}.lora-graph-canvas .lgc-menu-separator{height:1px;margin:4px 0;background:var(--lgc-toolbar-border)}
|
|
@@ -6,8 +6,14 @@ export interface MarqueeRect {
|
|
|
6
6
|
}
|
|
7
7
|
export interface MarqueeOverlayProps {
|
|
8
8
|
rect: MarqueeRect | null;
|
|
9
|
+
/** Live count of nodes whose projected position falls inside the
|
|
10
|
+
* rectangle. Hidden when 0 or undefined — small rectangles in dead
|
|
11
|
+
* space shouldn't render an empty "0 nodes" pill. */
|
|
12
|
+
count?: number;
|
|
9
13
|
}
|
|
10
14
|
/** Renders the dashed selection rectangle while the user is dragging a
|
|
11
15
|
* marquee. Positioned absolutely inside the host. Hidden when `rect`
|
|
12
|
-
* is null.
|
|
13
|
-
|
|
16
|
+
* is null. Shows a live node-count badge in the bottom-right of the
|
|
17
|
+
* rectangle so the user can tell how many nodes they'd grab before
|
|
18
|
+
* releasing. */
|
|
19
|
+
export declare function MarqueeOverlay({ rect, count }: MarqueeOverlayProps): import("react/jsx-runtime").JSX.Element | null;
|
package/dist/types.d.ts
CHANGED
|
@@ -35,6 +35,16 @@ export interface GraphData<N extends NodeObject = NodeObject, L extends LinkObje
|
|
|
35
35
|
links: L[];
|
|
36
36
|
}
|
|
37
37
|
export type GraphMode = "2d" | "3d";
|
|
38
|
+
/** Where a delete originated. Hosts often want to gate UI-driven deletes
|
|
39
|
+
* (show a confirm modal) but trust `imperative` calls they made
|
|
40
|
+
* themselves, so the source string lets the guard short-circuit. */
|
|
41
|
+
export type DeletionSource = "keyboard" | "toolbar" | "selectionPanel" | "contextMenu" | "cut" | "imperative";
|
|
42
|
+
/** Returns `true` to allow the deletion, `false` to cancel. Can be
|
|
43
|
+
* async — the caller awaits it before mutating data. A thrown error
|
|
44
|
+
* is treated as a cancel. Called once per batch (not per item). */
|
|
45
|
+
export type DeletionGuard<T> = (items: T[], ctx: {
|
|
46
|
+
source: DeletionSource;
|
|
47
|
+
}) => boolean | Promise<boolean>;
|
|
38
48
|
/** Built-in tool identifiers. */
|
|
39
49
|
export type ToolId = "select" | "pan" | "add-node" | "add-link" | "delete" | "duplicate" | "select-all" | "fit" | "zoom-in" | "zoom-out" | "pause" | "resume" | "screenshot" | "export-json" | "import-json" | "toggle-mode";
|
|
40
50
|
/** Accepts a literal value, a property accessor string, or a function. */
|
|
@@ -253,6 +263,22 @@ export interface LoraGraphCanvasProps<N extends NodeObject = NodeObject, L exten
|
|
|
253
263
|
}) => void;
|
|
254
264
|
onRenderFramePre?: (ctx: CanvasRenderingContext2D, globalScale: number) => void;
|
|
255
265
|
onRenderFramePost?: (ctx: CanvasRenderingContext2D, globalScale: number) => void;
|
|
266
|
+
/** Optional async gate fired before nodes are removed. Receives every
|
|
267
|
+
* node in the batch (single-node deletes get a 1-length array). Resolve
|
|
268
|
+
* `true` to proceed, `false` to cancel. Throws are treated as cancel.
|
|
269
|
+
* Fires for: keyboard, toolbar, selection-panel, context-menu, cut,
|
|
270
|
+
* and `handle.removeNode(s)` calls — discriminate via `ctx.source`. */
|
|
271
|
+
onBeforeNodeDelete?: DeletionGuard<N>;
|
|
272
|
+
/** Same shape as `onBeforeNodeDelete` for links. */
|
|
273
|
+
onBeforeLinkDelete?: DeletionGuard<L>;
|
|
274
|
+
/** Fires after a node delete has been applied to the data. */
|
|
275
|
+
onNodeDeleted?: (nodes: N[], ctx: {
|
|
276
|
+
source: DeletionSource;
|
|
277
|
+
}) => void;
|
|
278
|
+
/** Fires after a link delete has been applied to the data. */
|
|
279
|
+
onLinkDeleted?: (links: L[], ctx: {
|
|
280
|
+
source: DeletionSource;
|
|
281
|
+
}) => void;
|
|
256
282
|
/** Fires when the user copies nodes (⌘C) — receives the snapshot. */
|
|
257
283
|
onCopy?: (nodes: N[]) => void;
|
|
258
284
|
/** Fires when the user cuts nodes (⌘X) — receives the snapshot
|
|
@@ -309,8 +335,14 @@ export interface LoraGraphCanvasHandle<N extends NodeObject = NodeObject, L exte
|
|
|
309
335
|
id?: string | number;
|
|
310
336
|
}>): N[];
|
|
311
337
|
updateNode(id: string | number, patch: Partial<N>): void;
|
|
312
|
-
|
|
313
|
-
|
|
338
|
+
/** Returns a promise that resolves to `true` when the node was removed.
|
|
339
|
+
* When the host passes `onBeforeNodeDelete`, the guard runs with
|
|
340
|
+
* `source: "imperative"` and may cancel — the promise resolves
|
|
341
|
+
* `false` and the graph is unchanged. Hosts that don't pass a guard
|
|
342
|
+
* can ignore the promise; the data mutation is observable on the
|
|
343
|
+
* same tick (only the resolved promise itself is async). */
|
|
344
|
+
removeNode(id: string | number): Promise<boolean>;
|
|
345
|
+
removeNodes(ids: Array<string | number>): Promise<boolean>;
|
|
314
346
|
addLink(link: {
|
|
315
347
|
source: string | number;
|
|
316
348
|
target: string | number;
|
|
@@ -320,7 +352,9 @@ export interface LoraGraphCanvasHandle<N extends NodeObject = NodeObject, L exte
|
|
|
320
352
|
source: string | number;
|
|
321
353
|
target: string | number;
|
|
322
354
|
} & Partial<L>>): L[];
|
|
323
|
-
|
|
355
|
+
/** Same gate semantics as `removeNode` — `onBeforeLinkDelete` runs with
|
|
356
|
+
* `source: "imperative"` and may cancel. */
|
|
357
|
+
removeLink(predicate: (l: L) => boolean): Promise<boolean>;
|
|
324
358
|
clear(): void;
|
|
325
359
|
getSelection(): Array<string | number>;
|
|
326
360
|
setSelection(ids: Array<string | number>): void;
|
|
@@ -334,7 +368,10 @@ export interface LoraGraphCanvasHandle<N extends NodeObject = NodeObject, L exte
|
|
|
334
368
|
zoomIn(step?: number): void;
|
|
335
369
|
zoomOut(step?: number): void;
|
|
336
370
|
copy(): N[];
|
|
337
|
-
|
|
371
|
+
/** Cut funnels through the same delete-gate as keyboard / toolbar
|
|
372
|
+
* cuts. A rejected guard resolves to an empty array and leaves the
|
|
373
|
+
* graph + clipboard untouched. */
|
|
374
|
+
cut(): Promise<N[]>;
|
|
338
375
|
paste(opts?: {
|
|
339
376
|
at?: {
|
|
340
377
|
x: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@loradb/lora-graph-canvas",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"description": "React graph canvas for LoraDB. Unified 2D/3D force-directed component with a built-in tool palette for adding, connecting, selecting, and removing nodes.",
|
|
5
5
|
"license": "BUSL-1.1",
|
|
6
6
|
"packageManager": "yarn@4.5.1",
|