@petrarca/sonnet-graph 0.4.2 → 0.6.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/dist/index.d.ts CHANGED
@@ -1,10 +1,13 @@
1
1
  import * as zustand from 'zustand';
2
2
  import { UseBoundStore, StoreApi } from 'zustand';
3
- import * as react from 'react';
4
- import react__default, { ReactNode } from 'react';
3
+ import * as React from 'react';
4
+ import React__default, { ReactNode } from 'react';
5
5
  import { GraphEdge, GraphNode } from 'reagraph';
6
6
  import cytoscape from 'cytoscape';
7
7
  import * as react_jsx_runtime from 'react/jsx-runtime';
8
+ import { z } from 'zod';
9
+ import { JsonSchema, UISchema } from '@petrarca/sonnet-core/schema';
10
+ import { WidgetRegistry } from '@petrarca/sonnet-forms';
8
11
 
9
12
  /**
10
13
  * Visual Graph Model - Domain types combining API data with UI enrichment.
@@ -426,6 +429,9 @@ interface GraphFilterStore {
426
429
  clearNodeLabelFilters: () => void;
427
430
  setNodeLabelFilters: (labels: string[]) => void;
428
431
  toggleAllLabelsDisabled: () => void;
432
+ setAllLabelsDisabled: (disabled: boolean) => void;
433
+ /** Atomically update both allLabelsDisabled and nodeLabelFilters in one write. */
434
+ setNodeFilterState: (disabled: boolean, filters: string[]) => void;
429
435
  edgeLabelFilters: string[];
430
436
  allEdgeLabelsDisabled: boolean;
431
437
  toggleEdgeLabelFilter: (label: string, allAvailableLabels?: string[], edgeToNodeLabels?: Record<string, string[]>) => void;
@@ -685,9 +691,9 @@ interface WorkspaceStores {
685
691
 
686
692
  /**
687
693
  * Context for providing graph stores to visualization components.
688
- * Must be set by the host application (e.g., explorer, Atlas).
694
+ * Must be set by the host application (e.g., a graph explorer or consumer app).
689
695
  */
690
- declare const GraphStoresContext: react.Context<WorkspaceStores | null>;
696
+ declare const GraphStoresContext: React.Context<WorkspaceStores | null>;
691
697
  /** Get GraphFilter store from context. */
692
698
  declare function useWorkspaceGraphFilter(): UseBoundStore<StoreApi<GraphFilterStore>>;
693
699
  /** Get GraphData store from context. */
@@ -697,6 +703,9 @@ declare function useWorkspaceGraphExploration(): UseBoundStore<StoreApi<GraphExp
697
703
  /** Get Selection store from context. */
698
704
  declare function useWorkspaceSelection(): UseBoundStore<StoreApi<SelectionStore>>;
699
705
 
706
+ declare function useStableRef<T extends (...args: never[]) => unknown>(fn: T): T;
707
+ declare function useStableRef<T extends (...args: never[]) => unknown>(fn: T | undefined): T | undefined;
708
+
700
709
  /**
701
710
  * Result type for useLiveGraphData hook.
702
711
  *
@@ -825,7 +834,7 @@ type GraphRendererContextType = {
825
834
  declare function useGraphRenderer(): GraphRendererContextType;
826
835
 
827
836
  type ProviderProps = {
828
- children: react__default.ReactNode;
837
+ children: React__default.ReactNode;
829
838
  /**
830
839
  * Initial renderer to use. Defaults to 'cytoscape'.
831
840
  * The host application controls which renderer is active — typically
@@ -838,7 +847,7 @@ type ProviderProps = {
838
847
  */
839
848
  onRendererChange?: (renderer: GraphRenderer) => void;
840
849
  };
841
- declare function GraphRendererProvider({ children, defaultRenderer, onRendererChange, }: ProviderProps): react__default.ReactElement;
850
+ declare function GraphRendererProvider({ children, defaultRenderer, onRendererChange, }: ProviderProps): React__default.ReactElement;
842
851
 
843
852
  interface GraphVisualizerProps {
844
853
  /** Callback when a node is copied (e.g. to clipboard). Decouples renderers from clipboard store. */
@@ -866,7 +875,19 @@ type Props = {
866
875
  };
867
876
  declare function EdgeInfoCard({ edge }: Props): react_jsx_runtime.JSX.Element;
868
877
 
869
- declare function Overview(): react_jsx_runtime.JSX.Element | null;
878
+ /** A named group of node labels shown as its own legend sub-section. */
879
+ interface NodeLabelBucket {
880
+ title: string;
881
+ /** Node labels in this bucket; only those present in the graph are shown. */
882
+ labels: string[];
883
+ }
884
+ interface OverviewProps {
885
+ /** Split the node section into named buckets (default: one "Node Labels"). */
886
+ nodeBuckets?: NodeLabelBucket[];
887
+ /** Heading for the edge (arrow) section. Default "Relations". */
888
+ edgeSectionTitle?: string;
889
+ }
890
+ declare function Overview({ nodeBuckets, edgeSectionTitle }?: OverviewProps): react_jsx_runtime.JSX.Element | null;
870
891
 
871
892
  interface GraphA11yListProps {
872
893
  /** Render on-screen instead of visually-hidden (still a11y-present). */
@@ -879,4 +900,1045 @@ interface GraphA11yListProps {
879
900
  }
880
901
  declare function GraphA11yList({ visible, rowHeight, maxHeight, className, }: GraphA11yListProps): react_jsx_runtime.JSX.Element;
881
902
 
882
- export { ActionPanel, type ActionPanelState, type ActionPanelStore, type ColorPalette, EMPTY_NORMALIZED, EdgeInfoCard, type EdgeVisual, type ExpandOptions, type ExpandResult, GraphA11yList, type GraphA11yListProps, type GraphDataHook, type GraphDataStore, type GraphDisplayConfig, type GraphExplorationDeps, type GraphExplorationStore, type GraphFilterStore, type GraphFocusAction, type GraphFocusStore, type GraphProperties, type GraphProperty, type GraphRenderer, GraphRendererProvider, type GraphStatistics, type WorkspaceStores as GraphStoreBundle, GraphStoresContext, GraphVisualizer, type GraphVisualizerProps, type LabelDisplayMap, type LiveGraphDataResult, NodeInfoCard, type NodeVisual, type NormalizedGraph, Overview, type RawGraphEdge, type RawGraphNode, type SelectionStore, type StoreFactory, type VisualGraphEdge, type VisualGraphNode, type VisualGraphNormalized, type WorkspaceStores, buildColorPalette, buildColorPaletteFromNodes, createActionPanelStore, createGraphDataStore, createGraphExplorationStore, createGraphFilterStore, createGraphFocusStore, createSelectionStore, enrichEdge, enrichEdges, enrichNode, enrichNodes, extractDisplayLabel, isRawGraphNode, isVisualEdge, isVisualNode, normalizeGraph, toCytoscapeEdge, toCytoscapeNode, toReagraphEdge, toReagraphNode, useActionPanelStore, useCytoscapeData, useGraphFocus, useGraphRenderer, useLiveGraphData, useReagraphData, useWorkspaceGraphData, useWorkspaceGraphExploration, useWorkspaceGraphFilter, useWorkspaceSelection };
903
+ /**
904
+ * Graph model (metamodel) types.
905
+ *
906
+ * A graph model is a list of type schemas, each a JSON Schema carrying an
907
+ * `x-graph` extension that declares whether it is a node or edge type, its
908
+ * graph label, and (for node types) the valid outbound relations. This mirrors
909
+ * the shape consumed by cypher-graphdb-core, so a model authored here is a
910
+ * valid model there.
911
+ *
912
+ * The model is the source of truth. It is rendered as a graph of node-types and
913
+ * relation-edges via `modelToGraph` + `GraphVisualizer`; there is no reverse
914
+ * conversion.
915
+ */
916
+ /** Relation cardinality. Binary only, matching the core model. */
917
+ type Cardinality = "ONE_TO_ONE" | "ONE_TO_MANY";
918
+ /**
919
+ * A valid outbound relation from a node type. Directional: the triple is
920
+ * (owning type, rel_type_name, to_type_name). Asymmetry is the default --
921
+ * declare the reverse relation explicitly if it is also valid.
922
+ */
923
+ interface GraphRelation {
924
+ /** Relation/edge label, e.g. "partOf". */
925
+ rel_type_name: string;
926
+ /** Target node-type label. */
927
+ to_type_name: string;
928
+ /** Binary cardinality. Defaults to ONE_TO_MANY when omitted. */
929
+ cardinality?: Cardinality;
930
+ /** Whether the relation is surfaced as a form field (consumer hint). */
931
+ form_field?: boolean;
932
+ description?: string;
933
+ }
934
+ /** Optional display configuration for a type (how instances are labelled). */
935
+ interface GraphModelDisplay {
936
+ labelTemplate?: string;
937
+ labelProperty?: string;
938
+ fallbackProperty?: string;
939
+ sortProperty?: string;
940
+ sortOrder?: "ASC" | "DESC";
941
+ filterProperty?: string;
942
+ }
943
+ /** The `x-graph` extension on a type schema. */
944
+ interface XGraph {
945
+ /** NODE types carry relations; EDGE types define relationship properties. */
946
+ type: "NODE" | "EDGE";
947
+ /** The authoritative graph label, e.g. "Hospital" or "partOf". */
948
+ label: string;
949
+ /** Allowed outbound relations (node types only). */
950
+ relations?: GraphRelation[];
951
+ /** Parent type labels this type inherits from. */
952
+ inherits_from?: string[];
953
+ display?: GraphModelDisplay;
954
+ /** Free-form metadata preserved on round-trip. */
955
+ metadata?: Record<string, unknown>;
956
+ source?: string;
957
+ }
958
+ /**
959
+ * A single property definition within a type schema. A pragmatic subset of
960
+ * JSON Schema; unknown keys are preserved.
961
+ */
962
+ interface GraphModelProperty {
963
+ type?: string | string[];
964
+ title?: string;
965
+ description?: string;
966
+ enum?: Array<string | number>;
967
+ format?: string;
968
+ default?: unknown;
969
+ items?: GraphModelProperty;
970
+ [key: string]: unknown;
971
+ }
972
+ /**
973
+ * One type in the model: a JSON Schema object with an `x-graph` extension.
974
+ * Additional `x-*` extension keys are allowed and preserved.
975
+ */
976
+ interface GraphTypeSchema {
977
+ title?: string;
978
+ type: "object";
979
+ properties?: Record<string, GraphModelProperty>;
980
+ required?: string[];
981
+ "x-graph": XGraph;
982
+ [key: string]: unknown;
983
+ }
984
+ /** A graph model: the list of node/edge type schemas. */
985
+ type GraphModel = GraphTypeSchema[];
986
+ /** Type guard: is this type schema a node type (vs an edge type). */
987
+ declare function isNodeType(schema: GraphTypeSchema): boolean;
988
+ /** Type guard: is this type schema an edge type (vs a node type). */
989
+ declare function isEdgeType(schema: GraphTypeSchema): boolean;
990
+ /** The graph label of a type schema (x-graph.label, falling back to title). */
991
+ declare function typeLabel(schema: GraphTypeSchema): string;
992
+
993
+ /**
994
+ * Convert a graph model (metamodel) into renderable nodes and edges.
995
+ *
996
+ * Forward conversion only: a `GraphModel` becomes a graph of node-type nodes
997
+ * and relation/inheritance edges, suitable for `enrichNodes` / `enrichEdges`
998
+ * and `GraphVisualizer`. The model JSON is the source of truth; there is no
999
+ * reverse conversion.
1000
+ *
1001
+ * Ports cypher-graphdb-core's `json_schemas_to_graph` with two deliberate
1002
+ * differences:
1003
+ * - Node/edge ids are derived deterministically from type/relation names so
1004
+ * the same model always yields the same ids (required for visualizer merge,
1005
+ * dedup, and stable selection).
1006
+ * - A node's `label_` is the type label itself (e.g. "Hospital"), so the
1007
+ * legend colours and filters by type. `x-graph.type` still distinguishes
1008
+ * node from edge type schemas.
1009
+ */
1010
+
1011
+ /** The output of modelToGraph: renderable nodes + edges. */
1012
+ interface ModelGraph {
1013
+ nodes: RawGraphNode[];
1014
+ edges: RawGraphEdge[];
1015
+ }
1016
+ /**
1017
+ * Convert a graph model into renderable nodes and edges.
1018
+ *
1019
+ * Both node types and edge types become canvas nodes. Node types carry the
1020
+ * `x-graph.relations[*]` arrows between them (plus `inherits_from` arrows).
1021
+ * Edge types are rendered as standalone nodes (the catalog of relationship
1022
+ * types); they are not connected by arrows. Relation arrows only connect node
1023
+ * types, so relations whose target is not a node type are skipped.
1024
+ */
1025
+ declare function modelToGraph(model: GraphModel): ModelGraph;
1026
+
1027
+ /**
1028
+ * Canvas label-filter reconciliation for the model editor.
1029
+ *
1030
+ * The graph filter is an allowlist of node labels: empty = show all; non-empty
1031
+ * = show only those labels. The model editor uses it to optionally hide
1032
+ * edge-type nodes (showEdgeTypes) while keeping the user's show/hide choices
1033
+ * stable across model edits.
1034
+ */
1035
+
1036
+ /**
1037
+ * Reconcile the node-label allowlist after a model load.
1038
+ *
1039
+ * - baselineReset (first load or showEdgeTypes toggled): set the baseline --
1040
+ * show all (empty) when showEdgeTypes is true, otherwise allow only
1041
+ * node-type labels so edge types are hidden.
1042
+ * - Otherwise (a model edit): preserve the user's current filter, but drop
1043
+ * labels that no longer exist and add any new node-type labels so a
1044
+ * just-created node type is visible. An empty filter ("show all") stays
1045
+ * empty -- we never spontaneously start hiding what the user chose to show.
1046
+ */
1047
+ declare function reconcileFilter(current: string[], model: GraphModel, baselineReset: boolean, showEdgeTypes: boolean): string[];
1048
+
1049
+ /**
1050
+ * GraphModelEditor capabilities -- a single structure that gates what can be
1051
+ * edited. Consumers pass `capabilities` to tailor the editor (e.g. an
1052
+ * organization-model profile that hides node properties). `readOnly` is a
1053
+ * shorthand for the fully-locked capabilities.
1054
+ *
1055
+ * This module is the single source of truth: the Zod schema below defines the
1056
+ * shape, the TypeScript type is inferred from it (`z.infer`), the JSON Schema
1057
+ * is generated from it (see `capabilities.schema.ts` / the generate script),
1058
+ * and `validateCapabilities` validates hand-authored / external JSON at the
1059
+ * boundary. Every field is optional and defaults to the most permissive value,
1060
+ * so adding a new capability never tightens an existing consumer's profile
1061
+ * (forward compatible).
1062
+ */
1063
+
1064
+ /**
1065
+ * Mode for a section that can be edited, shown read-only, or dropped entirely.
1066
+ * "hidden" omits the section (meaningful only where there is a section to drop,
1067
+ * e.g. properties -- not for node types, which are the canvas nodes).
1068
+ */
1069
+ type EditMode$1 = "edit" | "readonly" | "hidden";
1070
+ /** Mode for a structural area that is always present (cannot be hidden). */
1071
+ type EditableMode = "edit" | "readonly";
1072
+ /**
1073
+ * Mode for the edge-type catalog when creating relations.
1074
+ * - "edit": pick an existing edge type or create a new one inline.
1075
+ * - "catalog": pick only from existing edge types (the catalog passed in the
1076
+ * model); creating new edge types is not allowed.
1077
+ * - "readonly": no changes (view only).
1078
+ */
1079
+ type EdgeTypeMode = "edit" | "catalog" | "readonly";
1080
+ /**
1081
+ * The capabilities schema. Each field is optional with a permissive default;
1082
+ * `.meta({ description })` is carried through to the generated JSON Schema.
1083
+ */
1084
+ declare const capabilitiesSchema: z.ZodObject<{
1085
+ nodeTypes: z.ZodDefault<z.ZodEnum<{
1086
+ edit: "edit";
1087
+ readonly: "readonly";
1088
+ }>>;
1089
+ edgeTypes: z.ZodDefault<z.ZodEnum<{
1090
+ edit: "edit";
1091
+ readonly: "readonly";
1092
+ catalog: "catalog";
1093
+ }>>;
1094
+ nodeProperties: z.ZodDefault<z.ZodEnum<{
1095
+ hidden: "hidden";
1096
+ edit: "edit";
1097
+ readonly: "readonly";
1098
+ }>>;
1099
+ edgeProperties: z.ZodDefault<z.ZodEnum<{
1100
+ hidden: "hidden";
1101
+ edit: "edit";
1102
+ readonly: "readonly";
1103
+ }>>;
1104
+ relations: z.ZodDefault<z.ZodEnum<{
1105
+ edit: "edit";
1106
+ readonly: "readonly";
1107
+ }>>;
1108
+ showEdgeTypes: z.ZodDefault<z.ZodBoolean>;
1109
+ }, z.core.$strip>;
1110
+ /**
1111
+ * The capabilities a consumer may pass. Inferred from the schema; with all
1112
+ * fields optional on input (defaults are applied by resolveCapabilities).
1113
+ */
1114
+ type GraphModelCapabilities = z.input<typeof capabilitiesSchema>;
1115
+ /** The fully-resolved capabilities (every field present). */
1116
+ type ResolvedCapabilities = z.output<typeof capabilitiesSchema>;
1117
+ /**
1118
+ * Resolve the effective capabilities: readOnly wins (everything locked),
1119
+ * otherwise parse the provided capabilities (applying per-field defaults).
1120
+ * Invalid input falls back to the permissive defaults rather than throwing --
1121
+ * use validateCapabilities to surface errors at a boundary.
1122
+ */
1123
+ declare function resolveCapabilities(capabilities: GraphModelCapabilities | undefined, readOnly: boolean | undefined): ResolvedCapabilities;
1124
+ /** Result of validating an untrusted capabilities object. */
1125
+ type CapabilitiesValidation = {
1126
+ ok: true;
1127
+ value: ResolvedCapabilities;
1128
+ } | {
1129
+ ok: false;
1130
+ errors: string[];
1131
+ };
1132
+ /**
1133
+ * Validate a hand-authored / external capabilities object (e.g. parsed from a
1134
+ * per-tenant config JSON). Returns the resolved value or a list of readable
1135
+ * error messages. Does not throw.
1136
+ */
1137
+ declare function validateCapabilities(input: unknown): CapabilitiesValidation;
1138
+
1139
+ /**
1140
+ * GraphModelEditor -- view and edit a graph model (metamodel).
1141
+ *
1142
+ * A controlled component over the model JSON: pass a `GraphModel` in, render it
1143
+ * as a graph of node-types and relation-edges via `GraphVisualizer`, and (when
1144
+ * authoring lands) emit an edited model through `onChange`. Read-only is a mode
1145
+ * of the same component.
1146
+ *
1147
+ * Rendering reuses the existing visualizer: the model is converted with
1148
+ * `modelToGraph`, enriched, and pushed into a per-instance workspace store.
1149
+ */
1150
+
1151
+ interface GraphModelEditorProps {
1152
+ /** The graph model to view/edit. Controlled. */
1153
+ value: GraphModel;
1154
+ /**
1155
+ * Called with the edited model. Omit (or set readOnly) for a view-only
1156
+ * editor.
1157
+ */
1158
+ onChange?: (model: GraphModel) => void;
1159
+ /** View-only: no edit affordances, onChange never fires. Shorthand for
1160
+ * fully-locked capabilities. */
1161
+ readOnly?: boolean;
1162
+ /** Fine-grained gating of what can be edited. Merged onto full-edit
1163
+ * defaults; readOnly overrides to fully locked. */
1164
+ capabilities?: GraphModelCapabilities;
1165
+ /** Allowed x-ui-widget values offered when editing a property. */
1166
+ widgetOptions?: string[];
1167
+ /** Default graph renderer. */
1168
+ defaultRenderer?: GraphRenderer;
1169
+ /** Hide the side panel (node/edge detail + overview legend). */
1170
+ hideActionPanel?: boolean;
1171
+ }
1172
+ declare function GraphModelEditor({ value, readOnly, capabilities, onChange, widgetOptions, defaultRenderer, hideActionPanel, }: GraphModelEditorProps): React__default.ReactElement;
1173
+
1174
+ /**
1175
+ * Type-view parser: turn a graph model + a selection into clean, readable
1176
+ * structured data for the detail panel.
1177
+ *
1178
+ * The model JSON is low-level (JSON Schema + x-graph). This module resolves a
1179
+ * selected node type or relation arrow into a flat shape the panel renders --
1180
+ * hiding mechanics (gid_, raw nested schema) and joining a relation arrow to
1181
+ * its hidden edge type so the relation's properties surface on the arrow.
1182
+ */
1183
+
1184
+ /** One property of a type, flattened for display. */
1185
+ interface PropertyView {
1186
+ /** Property key. */
1187
+ name: string;
1188
+ /** JSON Schema type (e.g. "string", "integer"); "object" when absent. */
1189
+ type: string;
1190
+ required: boolean;
1191
+ title?: string;
1192
+ description?: string;
1193
+ /** x-ui-widget, if set on the property. */
1194
+ widget?: string;
1195
+ enum?: Array<string | number>;
1196
+ }
1197
+ /** One relation declared on a node type, flattened for display. */
1198
+ interface RelationView {
1199
+ relType: string;
1200
+ target: string;
1201
+ cardinality: Cardinality;
1202
+ description?: string;
1203
+ }
1204
+ /** View of a selected node type. */
1205
+ interface NodeTypeView {
1206
+ kind: "node";
1207
+ label: string;
1208
+ description?: string;
1209
+ properties: PropertyView[];
1210
+ relations: RelationView[];
1211
+ }
1212
+ /**
1213
+ * View of a selected edge type (a catalog entry). An edge type carries only
1214
+ * identity and properties -- it has no relations of its own (relations are
1215
+ * declared on node types and reference an edge type by label).
1216
+ */
1217
+ interface EdgeTypeView {
1218
+ kind: "edge";
1219
+ label: string;
1220
+ description?: string;
1221
+ properties: PropertyView[];
1222
+ }
1223
+ /**
1224
+ * View of a selected relation arrow. Properties are joined from the relation's
1225
+ * hidden edge type (the edge-type schema whose label === relType), if one
1226
+ * exists; otherwise the relation simply has no properties yet.
1227
+ */
1228
+ interface RelationDetailView {
1229
+ kind: "relation";
1230
+ relType: string;
1231
+ source: string;
1232
+ target: string;
1233
+ cardinality: Cardinality;
1234
+ description?: string;
1235
+ /** Whether a hidden edge type backs this relation's properties. */
1236
+ hasEdgeType: boolean;
1237
+ properties: PropertyView[];
1238
+ }
1239
+ /** Human-readable label for a cardinality value. */
1240
+ declare function cardinalityLabel(c: Cardinality): string;
1241
+ /** Find a type schema by its graph label. */
1242
+ declare function findType(model: GraphModel, label: string): GraphTypeSchema | undefined;
1243
+ /** Find the (hidden) edge type backing a relation type, if any. */
1244
+ declare function findEdgeType(model: GraphModel, relType: string): GraphTypeSchema | undefined;
1245
+ /**
1246
+ * Resolve a selected relation edge into (source, relType, target).
1247
+ *
1248
+ * The converter sets each relation edge's `label_` to the relation type and its
1249
+ * `gid_` to `schema:rel:<source>\0<target>`, using NUL as a separator so node
1250
+ * type labels that contain colons parse unambiguously. INHERITS_FROM_ edges are
1251
+ * not relations and resolve to null.
1252
+ */
1253
+ declare function resolveRelationEdge(edge: {
1254
+ label_: string;
1255
+ properties_?: Record<string, unknown>;
1256
+ }): {
1257
+ source: string;
1258
+ relType: string;
1259
+ target: string;
1260
+ } | null;
1261
+ /** Build the view for a selected node type. Returns null if not a node type. */
1262
+ declare function nodeTypeView(model: GraphModel, label: string): NodeTypeView | null;
1263
+ /**
1264
+ * Build the view for a selected edge type. Returns null if the label does not
1265
+ * resolve to an edge type. An edge type's properties are the relation
1266
+ * properties shared by every relation of this type.
1267
+ */
1268
+ declare function edgeTypeView(model: GraphModel, label: string): EdgeTypeView | null;
1269
+ /**
1270
+ * Build the view for a selected relation arrow. `source` is the owning node
1271
+ * type label, `relType` the relation type, `target` the target node label.
1272
+ * Properties are joined from the hidden edge type, if present.
1273
+ */
1274
+ declare function relationView(model: GraphModel, source: string, relType: string, target: string): RelationDetailView | null;
1275
+
1276
+ /**
1277
+ * TypeDetailPanel -- detail for a selected metamodel element.
1278
+ *
1279
+ * Renders either a node type (Identity + Properties + Relations) or a relation
1280
+ * arrow (Identity + endpoints + Properties joined from the relation's hidden
1281
+ * edge type). Uniform Properties presentation for both. When not readOnly and
1282
+ * capabilities allow, properties can be added / edited / deleted; mutations
1283
+ * edit the model and are emitted via onChange.
1284
+ */
1285
+
1286
+ interface TypeDetailPanelProps {
1287
+ model: GraphModel;
1288
+ /** The selected element: a node type, an edge type, or a relation arrow. */
1289
+ selection: {
1290
+ kind: "node";
1291
+ label: string;
1292
+ } | {
1293
+ kind: "edge";
1294
+ label: string;
1295
+ } | {
1296
+ kind: "relation";
1297
+ source: string;
1298
+ relType: string;
1299
+ target: string;
1300
+ };
1301
+ onChange?: (model: GraphModel) => void;
1302
+ readOnly?: boolean;
1303
+ /** Resolved capabilities (gating per area). */
1304
+ capabilities?: ResolvedCapabilities;
1305
+ /** Allowed x-ui-widget values offered in the property form. */
1306
+ widgetOptions?: string[];
1307
+ }
1308
+ declare function TypeDetailPanel({ model, selection, onChange, readOnly, capabilities, widgetOptions, }: TypeDetailPanelProps): React__default.ReactElement | null;
1309
+
1310
+ /**
1311
+ * ModelActionPanel -- selection-aware detail panel for the model editor.
1312
+ *
1313
+ * Renders, from the current model + workspace selection:
1314
+ * - a relation's detail when a relation arrow is selected,
1315
+ * - two node types selected => a "Create relation" prompt (select-two-then-link),
1316
+ * - a single node type's detail when one node is selected,
1317
+ * - the Overview legend when nothing is selected.
1318
+ *
1319
+ * Editing flows through onChange (controlled). Replaces the generic ActionPanel
1320
+ * inside GraphModelEditor; the instance-graph ActionPanel is unchanged.
1321
+ */
1322
+
1323
+ interface ModelActionPanelProps {
1324
+ model: GraphModel;
1325
+ onChange?: (model: GraphModel) => void;
1326
+ readOnly?: boolean;
1327
+ capabilities?: GraphModelCapabilities;
1328
+ widgetOptions?: string[];
1329
+ }
1330
+ declare function ModelActionPanel({ model, onChange, readOnly, capabilities, widgetOptions, }: ModelActionPanelProps): React__default.ReactElement;
1331
+
1332
+ /**
1333
+ * Pure model mutations. Each takes a GraphModel and returns a new GraphModel
1334
+ * (immutable); GraphModelEditor is controlled, so callers pass the result to
1335
+ * onChange. No mutation touches the input.
1336
+ *
1337
+ * Properties live on a type schema's `properties` (+ `required`). A relation's
1338
+ * properties live on its hidden edge type (the EDGE schema whose label === the
1339
+ * relation type); that edge type is created lazily when a relation gains its
1340
+ * first property and removed when it loses its last.
1341
+ */
1342
+
1343
+ /** A property definition as edited in the form. */
1344
+ interface PropertyInput {
1345
+ name: string;
1346
+ type: string;
1347
+ required: boolean;
1348
+ title?: string;
1349
+ description?: string;
1350
+ widget?: string;
1351
+ enum?: Array<string | number>;
1352
+ }
1353
+ /**
1354
+ * Add or update a property on a node type. `prevName` set => rename/update that
1355
+ * property; omitted => add `input.name`.
1356
+ */
1357
+ declare function setNodeProperty(model: GraphModel, typeLabel_: string, input: PropertyInput, prevName?: string): GraphModel;
1358
+ /** Delete a property from a node type. */
1359
+ declare function deleteNodeProperty(model: GraphModel, typeLabel_: string, name: string): GraphModel;
1360
+ /**
1361
+ * Add or update a property on a relation. Properties are stored on the
1362
+ * relation's hidden edge type, which is created lazily here if absent.
1363
+ */
1364
+ declare function setRelationProperty(model: GraphModel, relType: string, input: PropertyInput, prevName?: string): GraphModel;
1365
+ /**
1366
+ * Delete a property from a relation. If that was the relation's last property,
1367
+ * the now-empty hidden edge type is removed entirely.
1368
+ */
1369
+ declare function deleteRelationProperty(model: GraphModel, relType: string, name: string): GraphModel;
1370
+ /**
1371
+ * Add or update a property on an edge type selected directly (by its label).
1372
+ * Unlike setRelationProperty this never creates the edge type -- it must
1373
+ * already exist -- and is used when an edge-type node is selected on the canvas.
1374
+ */
1375
+ declare function setEdgeTypeProperty(model: GraphModel, edgeLabel: string, input: PropertyInput, prevName?: string): GraphModel;
1376
+ /**
1377
+ * Delete a property from an edge type selected directly. Unlike
1378
+ * deleteRelationProperty this keeps the edge type even when it becomes empty:
1379
+ * an explicitly-created edge type stays in the catalog with no properties.
1380
+ */
1381
+ declare function deleteEdgeTypeProperty(model: GraphModel, edgeLabel: string, name: string): GraphModel;
1382
+ /** Add a new, empty edge type to the catalog. No-op if the label exists. */
1383
+ declare function addEdgeType(model: GraphModel, label: string): GraphModel;
1384
+ /** A relation definition as edited in the form. */
1385
+ interface RelationInput {
1386
+ relType: string;
1387
+ target: string;
1388
+ cardinality: Cardinality;
1389
+ description?: string;
1390
+ }
1391
+ /**
1392
+ * Add a relation to a node type's x-graph.relations. No-op if an identical
1393
+ * (relType, target) relation already exists on that source.
1394
+ */
1395
+ declare function addRelation(model: GraphModel, source: string, input: RelationInput): GraphModel;
1396
+ /** Update an existing relation (matched by source + prev relType/target). */
1397
+ declare function updateRelation(model: GraphModel, source: string, prevRelType: string, prevTarget: string, input: RelationInput): GraphModel;
1398
+ /** Add a new, empty node type. No-op if the label already exists. */
1399
+ declare function addNodeType(model: GraphModel, label: string): GraphModel;
1400
+ /**
1401
+ * Rename a node type, updating every reference: the type's own label/title and
1402
+ * any relation `to_type_name` (and `inherits_from`) that pointed at the old
1403
+ * label. No-op if newLabel already exists.
1404
+ */
1405
+ declare function renameNodeType(model: GraphModel, oldLabel: string, newLabel: string): GraphModel;
1406
+ /**
1407
+ * Delete a node type and clean up references: removes the type, plus any
1408
+ * relations (on other types) that target it and any inherits_from entries.
1409
+ */
1410
+ declare function deleteNodeType(model: GraphModel, label: string): GraphModel;
1411
+ /** Remove a relation from a node type. */
1412
+ declare function deleteRelation(model: GraphModel, source: string, relType: string, target: string): GraphModel;
1413
+ /**
1414
+ * Rename an edge type, updating every relation `rel_type_name` that referenced
1415
+ * the old label so those relations keep pointing at the (now renamed) edge
1416
+ * type. No-op if newLabel already exists or there is no such edge type.
1417
+ */
1418
+ declare function renameEdgeType(model: GraphModel, oldLabel: string, newLabel: string): GraphModel;
1419
+ /**
1420
+ * Delete an edge type from the catalog. Relations that referenced it remain as
1421
+ * bare-label relations (edge types are optional); only the catalog entry and
1422
+ * its shared properties are removed.
1423
+ */
1424
+ declare function deleteEdgeType(model: GraphModel, label: string): GraphModel;
1425
+
1426
+ /**
1427
+ * PropertyFormSheet -- add/edit a single property definition.
1428
+ *
1429
+ * A property definition (name, type, required, title, description, widget) is
1430
+ * itself a small object, so it is edited with a schema-driven form
1431
+ * (JsonSchemaFormRenderer) over a property meta-schema, inside a Sheet. The
1432
+ * widget choice (x-ui-widget) is the extensibility hook; consumers can extend
1433
+ * the allowed widget list via `widgetOptions`.
1434
+ */
1435
+
1436
+ interface PropertyFormSheetProps {
1437
+ open: boolean;
1438
+ onOpenChange: (open: boolean) => void;
1439
+ /** The property being edited; omit for add. */
1440
+ property?: PropertyView;
1441
+ /** Owner label for the title (a type or relation name). */
1442
+ ownerLabel: string;
1443
+ /** Allowed x-ui-widget values; "default" is always included first. */
1444
+ widgetOptions?: string[];
1445
+ /** Called with the property input on save; the sheet closes after. */
1446
+ onSave: (input: PropertyInput, prevName?: string) => void;
1447
+ }
1448
+ declare function PropertyFormSheet({ open, onOpenChange, property, ownerLabel, widgetOptions, onSave, }: PropertyFormSheetProps): React__default.ReactElement;
1449
+
1450
+ /**
1451
+ * RelationFormSheet -- create or edit a relation between two node types.
1452
+ *
1453
+ * Used by the select-two-then-link flow (create) and the relation edit action.
1454
+ * The endpoints are fixed by the selection / existing relation; the form edits
1455
+ * the relation type, direction (swap source/target), and cardinality.
1456
+ */
1457
+
1458
+ interface RelationFormSheetProps {
1459
+ open: boolean;
1460
+ onOpenChange: (open: boolean) => void;
1461
+ /** The two endpoints; the first is the initial source. */
1462
+ nodeA: string;
1463
+ nodeB: string;
1464
+ /** Existing relation values when editing. */
1465
+ initial?: {
1466
+ relType: string;
1467
+ cardinality: Cardinality;
1468
+ };
1469
+ /**
1470
+ * Existing edge-type labels (the catalog) offered for the relation type.
1471
+ * The user selects one of these; in "edit" mode a new one can be created.
1472
+ */
1473
+ edgeTypeOptions: string[];
1474
+ /**
1475
+ * Edge-type governance. "edit": select or create; "catalog": select only
1476
+ * from edgeTypeOptions; "readonly": no create. Default "edit".
1477
+ */
1478
+ edgeTypeMode?: EdgeTypeMode;
1479
+ /** Save handler: (source, target, input). Sheet closes after. */
1480
+ onSave: (source: string, target: string, input: RelationInput) => void;
1481
+ }
1482
+ declare function RelationFormSheet({ open, onOpenChange, nodeA, nodeB, initial, edgeTypeOptions, edgeTypeMode, onSave, }: RelationFormSheetProps): React__default.ReactElement;
1483
+
1484
+ /**
1485
+ * NodeTypeNameSheet -- name input for adding or renaming a node type.
1486
+ */
1487
+
1488
+ interface NodeTypeNameSheetProps {
1489
+ open: boolean;
1490
+ onOpenChange: (open: boolean) => void;
1491
+ /** Current label when renaming; omit for add. */
1492
+ initial?: string;
1493
+ /** Existing labels, to prevent duplicates. */
1494
+ existing: string[];
1495
+ /** The kind of type being named (affects wording). Default "node". */
1496
+ noun?: "node" | "edge";
1497
+ onSave: (label: string) => void;
1498
+ }
1499
+ declare function NodeTypeNameSheet({ open, onOpenChange, initial, existing, noun, onSave, }: NodeTypeNameSheetProps): React__default.ReactElement;
1500
+
1501
+ /**
1502
+ * GraphMutationPort -- the core write seam for instance editing.
1503
+ *
1504
+ * The write analog of the read-side injected dependencies
1505
+ * (`GraphExplorationDeps` / `GraphDataHook`). The library's editing components
1506
+ * call only this port; they never see HTTP, auth, Cypher, or a cache. Each
1507
+ * consumer implements the port against its own backend (the explorer wraps its
1508
+ * existing `graphService`; a new consumer wraps its own graph REST API).
1509
+ *
1510
+ * Node/edge ids are numeric, matching `RawGraphNode.id_` / `RawGraphEdge.id_`
1511
+ * and the explorer's `graphService` today. (If a future consumer keys nodes by
1512
+ * string, this would widen to `number | string`.)
1513
+ *
1514
+ * The port is EVENT-FREE: it `await`s and returns the mutation result; it does
1515
+ * not own a cache and emits no events. The consumer wraps the port to patch its
1516
+ * own cache (the explorer keeps its React-Query patching in its wrapper).
1517
+ *
1518
+ * Relations stay ATOMIC: `createNodeWithRelations` / `updateNodeWithRelations`
1519
+ * are single port methods, not decomposed into node + edge calls in the
1520
+ * library. The backend already exposes transactional endpoints for these;
1521
+ * decomposing would lose atomicity.
1522
+ */
1523
+
1524
+ /** A node create request: a label and its properties. */
1525
+ interface CreateNodeInput {
1526
+ label_: string;
1527
+ properties_: GraphProperties;
1528
+ }
1529
+ /** A node update request: id, label, and the full property set. */
1530
+ interface UpdateNodeInput {
1531
+ id_: number;
1532
+ label_: string;
1533
+ properties_: GraphProperties;
1534
+ }
1535
+ /** An edge create request between two nodes. */
1536
+ interface CreateEdgeInput {
1537
+ label_: string;
1538
+ start_id_: number;
1539
+ end_id_: number;
1540
+ properties_?: GraphProperties;
1541
+ }
1542
+ /**
1543
+ * An edge update request. Carries the full edge identity (label and endpoints),
1544
+ * not just the id, so a consumer can build a REST PUT body or run a query
1545
+ * without re-fetching the edge. The editor always has these (it edits an
1546
+ * existing edge it already holds), so the port stays self-sufficient. The
1547
+ * backend is free to ignore the fields it does not need.
1548
+ */
1549
+ interface UpdateEdgeInput {
1550
+ id_: number;
1551
+ label_: string;
1552
+ start_id_: number;
1553
+ end_id_: number;
1554
+ properties_: GraphProperties;
1555
+ }
1556
+ /**
1557
+ * Relations grouped by relation/edge type: rel_type -> target node ids.
1558
+ * Matches the `__rel_*` form-field shape after extraction.
1559
+ */
1560
+ type RelationMap = Record<string, number[]>;
1561
+ /** A node-with-relations create request (atomic). */
1562
+ interface CreateNodeWithRelationsInput {
1563
+ label_: string;
1564
+ properties_: GraphProperties;
1565
+ relations: RelationMap;
1566
+ }
1567
+ /** A node-with-relations update request (atomic; backend diffs the edges). */
1568
+ interface UpdateNodeWithRelationsInput {
1569
+ id_: number;
1570
+ label_: string;
1571
+ properties_: GraphProperties;
1572
+ relations: RelationMap;
1573
+ }
1574
+ /** Result of creating a node with relations: the node and the created edges. */
1575
+ interface CreateNodeWithRelationsResult {
1576
+ node: RawGraphNode;
1577
+ edges: RawGraphEdge[];
1578
+ }
1579
+ /** Result of updating a node with relations: the node and the edge diff. */
1580
+ interface UpdateNodeWithRelationsResult {
1581
+ node: RawGraphNode;
1582
+ edges: {
1583
+ deleted: number[];
1584
+ created: RawGraphEdge[];
1585
+ };
1586
+ }
1587
+ /**
1588
+ * The injected write interface. Shapes mirror the explorer's `graphService`
1589
+ * almost one-to-one, which is what makes a consumer's adapter a thin wrapper.
1590
+ */
1591
+ interface GraphMutationPort {
1592
+ createNode(input: CreateNodeInput): Promise<RawGraphNode>;
1593
+ updateNode(input: UpdateNodeInput): Promise<RawGraphNode>;
1594
+ deleteNode(id: number): Promise<void>;
1595
+ createEdge(input: CreateEdgeInput): Promise<RawGraphEdge>;
1596
+ updateEdge(input: UpdateEdgeInput): Promise<RawGraphEdge>;
1597
+ deleteEdge(id: number): Promise<void>;
1598
+ /** Create a node and its relations in one server-side transaction. */
1599
+ createNodeWithRelations(input: CreateNodeWithRelationsInput): Promise<CreateNodeWithRelationsResult>;
1600
+ /** Update a node and diff its relations in one server-side transaction. */
1601
+ updateNodeWithRelations(input: UpdateNodeWithRelationsInput): Promise<UpdateNodeWithRelationsResult>;
1602
+ /** Reads needed by edit / delete flows. */
1603
+ getInboundEdges(id: number): Promise<RawGraphEdge[]>;
1604
+ getOutboundEdges(id: number): Promise<RawGraphEdge[]>;
1605
+ /** All edges between two nodes, in both directions. */
1606
+ getPairEdges(a: number, b: number): Promise<RawGraphEdge[]>;
1607
+ /**
1608
+ * Fetch nodes by id -- used by the delete-node dialog to resolve the display
1609
+ * names of dependent (neighbour) nodes. Mirrors the explorer's
1610
+ * graphService.getNodes.
1611
+ */
1612
+ getNodes(ids: number[]): Promise<RawGraphNode[]>;
1613
+ }
1614
+
1615
+ /**
1616
+ * GraphSchemaProvider -- the schema (type) seam for instance editing.
1617
+ *
1618
+ * The edit forms are schema-driven: they need the JSON Schema for a node label
1619
+ * or edge type, plus its relation definitions, to build the form. Inject a
1620
+ * provider; the library uses it only to build forms.
1621
+ *
1622
+ * This is a NEW, dedicated async interface, not an extension of the
1623
+ * model-editor's controlled-value provider. `GraphModelEditor` works on an
1624
+ * in-memory `GraphModel` (a controlled `value` prop) the host already holds;
1625
+ * instance editing instead needs to FETCH a node/edge schema by label on
1626
+ * demand (async), a different shape and lifecycle. A host that already has the
1627
+ * full model in memory can implement the provider as a synchronous lookup
1628
+ * wrapped in `Promise.resolve`.
1629
+ */
1630
+
1631
+ /** Relation cardinality. Binary, matching the model. Drives single vs multi
1632
+ * select for the relation form field. */
1633
+ type RelationCardinality = "ONE_TO_ONE" | "ONE_TO_MANY";
1634
+ /**
1635
+ * A relation definition surfaced to the instance-editing form layer.
1636
+ *
1637
+ * Structural own type -- not an alias of `GraphRelation` -- so the
1638
+ * instance-editing seam is decoupled from the model-editor's internal types.
1639
+ * Consumers implementing `GraphSchemaProvider` only need to satisfy this shape.
1640
+ */
1641
+ interface RelationDef {
1642
+ /** The relation/edge label, e.g. "USES_TECHNOLOGY". */
1643
+ rel_type_name: string;
1644
+ /** The target node-type label, e.g. "Technology". */
1645
+ to_type_name: string;
1646
+ /**
1647
+ * Whether this relation is surfaced as an editable form field. Only relations
1648
+ * with `form_field === true` become `__rel_*` fields in the node form
1649
+ * (matching the explorer). Defaults to not-a-field.
1650
+ */
1651
+ form_field?: boolean;
1652
+ /**
1653
+ * Binary cardinality. ONE_TO_ONE renders a single-select; ONE_TO_MANY (or
1654
+ * omitted) renders a multi-select.
1655
+ */
1656
+ cardinality?: RelationCardinality;
1657
+ /** Optional explicit form-field title; defaults to a Title-Cased label. */
1658
+ title?: string;
1659
+ /**
1660
+ * Optional widget hint for the relation field (the `x-ui-widget` value).
1661
+ * Defaults to "entity-select". The explorer overrides this with
1662
+ * "cypher-select"; the widget itself is supplied app-level via the registry.
1663
+ */
1664
+ widget?: string;
1665
+ }
1666
+ /**
1667
+ * The injected schema source. All lookups are async (returning Promises) so a
1668
+ * provider can fetch from a `/schemas` endpoint, a model store, or resolve
1669
+ * synchronously from an in-memory model.
1670
+ */
1671
+ interface GraphSchemaProvider {
1672
+ /** The JSON Schema for a node label, used to render its property form. */
1673
+ getNodeSchema(label: string): Promise<JsonSchema | null>;
1674
+ /** The JSON Schema for an edge type, used to render its property form. */
1675
+ getEdgeSchema(type: string): Promise<JsonSchema | null>;
1676
+ /** The node labels a consumer may create (populates the label selector). */
1677
+ listNodeLabels(): Promise<string[]>;
1678
+ /** The outbound relation definitions for a node label (the form relations). */
1679
+ relationsFor(label: string): Promise<RelationDef[]>;
1680
+ }
1681
+
1682
+ /**
1683
+ * Graph instance-editing capabilities -- a single structure that gates what a
1684
+ * consumer can do with a live data graph. Distinct from `GraphModelCapabilities`
1685
+ * (which gates the metamodel/schema editor): this profile governs the viewer +
1686
+ * instance editor (editing node/edge DATA, not types).
1687
+ *
1688
+ * This profile is the RBAC/ABAC seam: the host resolves a user's
1689
+ * role/attributes into a `GraphCapabilities` object and passes it in; the
1690
+ * library enables only what the resolved capabilities allow and never sees
1691
+ * roles, policies, or auth.
1692
+ *
1693
+ * This module is the single source of truth: the Zod schema below defines the
1694
+ * shape, the TypeScript types are inferred from it (`z.input` / `z.output`),
1695
+ * and `validateGraphCapabilities` validates hand-authored / external JSON at
1696
+ * the boundary. Every field is optional and defaults to `"readonly"` (no
1697
+ * editing affordances) so existing viewers are unaffected until a consumer
1698
+ * opts in by passing a capabilities profile. The viewer areas are reserved for
1699
+ * a follow-on refactor and default fully permissive; v1 ships the editing
1700
+ * areas.
1701
+ */
1702
+
1703
+ /** Mode for an editable area: allow the action or not. */
1704
+ type EditMode = "edit" | "readonly";
1705
+ /**
1706
+ * The capabilities schema. Each field is optional with a permissive default;
1707
+ * `.meta({ description })` is carried through to any generated JSON Schema.
1708
+ *
1709
+ * Editing areas (v1): node CRUD, edge CRUD, property editing. Viewer areas are
1710
+ * reserved (designed-for, not yet wired) so they slot in without a breaking
1711
+ * change.
1712
+ */
1713
+ declare const graphCapabilitiesSchema: z.ZodObject<{
1714
+ createNode: z.ZodDefault<z.ZodEnum<{
1715
+ edit: "edit";
1716
+ readonly: "readonly";
1717
+ }>>;
1718
+ updateNode: z.ZodDefault<z.ZodEnum<{
1719
+ edit: "edit";
1720
+ readonly: "readonly";
1721
+ }>>;
1722
+ deleteNode: z.ZodDefault<z.ZodEnum<{
1723
+ edit: "edit";
1724
+ readonly: "readonly";
1725
+ }>>;
1726
+ createEdge: z.ZodDefault<z.ZodEnum<{
1727
+ edit: "edit";
1728
+ readonly: "readonly";
1729
+ }>>;
1730
+ updateEdge: z.ZodDefault<z.ZodEnum<{
1731
+ edit: "edit";
1732
+ readonly: "readonly";
1733
+ }>>;
1734
+ deleteEdge: z.ZodDefault<z.ZodEnum<{
1735
+ edit: "edit";
1736
+ readonly: "readonly";
1737
+ }>>;
1738
+ }, z.core.$strip>;
1739
+ /**
1740
+ * The capabilities a consumer may pass. Inferred from the schema; with all
1741
+ * fields optional on input (defaults are applied by resolveGraphCapabilities).
1742
+ */
1743
+ type GraphCapabilities = z.input<typeof graphCapabilitiesSchema>;
1744
+ /** The fully-resolved capabilities (every field present). */
1745
+ type ResolvedGraphCapabilities = z.output<typeof graphCapabilitiesSchema>;
1746
+ /**
1747
+ * Resolve the effective capabilities: readOnly wins (everything read-only),
1748
+ * otherwise parse the provided capabilities (applying per-field defaults of
1749
+ * "readonly"). Invalid input falls back to the read-only defaults rather than
1750
+ * throwing -- use validateGraphCapabilities to surface errors at a boundary.
1751
+ */
1752
+ declare function resolveGraphCapabilities(capabilities: GraphCapabilities | undefined, readOnly: boolean | undefined): ResolvedGraphCapabilities;
1753
+ /** Result of validating an untrusted capabilities object. */
1754
+ type GraphCapabilitiesValidation = {
1755
+ ok: true;
1756
+ value: ResolvedGraphCapabilities;
1757
+ } | {
1758
+ ok: false;
1759
+ errors: string[];
1760
+ };
1761
+ /**
1762
+ * Validate a hand-authored / external capabilities object (e.g. parsed from a
1763
+ * per-tenant config JSON or produced by an authorization layer). Returns the
1764
+ * resolved value or a list of readable error messages. Does not throw.
1765
+ */
1766
+ declare function validateGraphCapabilities(input: unknown): GraphCapabilitiesValidation;
1767
+
1768
+ /**
1769
+ * Relation form-field utilities.
1770
+ *
1771
+ * The schema-driven node form represents editable relations as synthetic
1772
+ * `__rel_<type>__` fields (a multi-select of target node ids). These helpers
1773
+ * convert between that flat form shape and the structured
1774
+ * `{ properties, relations }` the mutation port expects.
1775
+ *
1776
+ * Relocated from the cypher-graphdb explorer (`services/nodeFormUtils.ts`) so
1777
+ * every consumer of the shared editor gets the same relation handling. The
1778
+ * functions are pure -- no I/O. Reads of a node's existing relations go through
1779
+ * the injected `GraphMutationPort` (getInboundEdges / getOutboundEdges), not a
1780
+ * hardcoded backend call.
1781
+ */
1782
+
1783
+ /** A per-field UI schema map, as JsonSchemaFormRenderer's `uiSchema` prop. */
1784
+ type FieldUiSchema = {
1785
+ [fieldName: string]: UISchema;
1786
+ };
1787
+ /** Whether a form key is a synthetic relation field. */
1788
+ declare function isRelationField(key: string): boolean;
1789
+ /** The form-field name for a relation type (`USES` -> `__rel_uses__`). */
1790
+ declare function relationFieldName(relationType: string): string;
1791
+ /** The relation type for a form-field name (`__rel_uses__` -> `USES`). */
1792
+ declare function relationTypeFromField(fieldName: string): string;
1793
+ /**
1794
+ * Group a node's edges into a relation map (rel_type -> target node ids),
1795
+ * relative to the node. The target is the other end of each edge.
1796
+ */
1797
+ declare function groupEdgesByRelation(nodeId: number, edges: RawGraphEdge[]): RelationMap;
1798
+ /**
1799
+ * Build initial form data from a node's properties and its relations, including
1800
+ * a `__rel_*` field for every editable relation type. `editableRelationTypes`
1801
+ * is the set of relation types that should appear as form fields (typically
1802
+ * those marked `form_field` in the model); an empty list yields properties
1803
+ * only.
1804
+ */
1805
+ declare function initializeFormData(properties: GraphProperties, relations: RelationMap, editableRelationTypes: string[]): Record<string, unknown>;
1806
+ /**
1807
+ * Split form data into `{ properties, relations }`, converting `__rel_*` fields
1808
+ * back to relation type names and numeric ids.
1809
+ */
1810
+ declare function extractRelationFields(formData: Record<string, unknown>): {
1811
+ properties: GraphProperties;
1812
+ relations: RelationMap;
1813
+ };
1814
+ /** Whether any form key is a relation field (decides the atomic save path). */
1815
+ declare function hasRelationFields(formData: Record<string, unknown>): boolean;
1816
+ /** Title-case a relation type for a default field title ("USES_TECHNOLOGY" ->
1817
+ * "Uses Technology"). Matches the explorer's formatting. */
1818
+ declare function relationTitle(relationType: string): string;
1819
+ /** A relation is editable (becomes a form field) when form_field === true,
1820
+ * matching the explorer. */
1821
+ declare function editableRelations(relations: RelationDef[]): RelationDef[];
1822
+ /** Whether a node/edge schema declares any properties (gates "Edit edge" the
1823
+ * same way the explorer's hasProperties does). */
1824
+ declare function hasProperties(schema: JsonSchema | null | undefined): boolean;
1825
+ /**
1826
+ * Enrich a node schema with a `__rel_*` field per editable relation, returning
1827
+ * a new `{ schema, uiSchema }`. Mirrors the explorer's enrichment:
1828
+ * - field type is `array of integer` (multi) for ONE_TO_MANY / unset
1829
+ * cardinality, or `integer` (single) for ONE_TO_ONE;
1830
+ * - the field title is the relation's title or a Title-Cased label;
1831
+ * - the uiSchema carries `x-ui-widget` (default "entity-select") plus
1832
+ * `x-ui-options` describing the target type and selection mode.
1833
+ *
1834
+ * The widget COMPONENT stays app-level (supplied via the form widget registry);
1835
+ * this only produces the schema/uiSchema that drives it.
1836
+ */
1837
+ declare function enrichSchemaWithRelations(baseSchema: JsonSchema, relations: RelationDef[]): {
1838
+ schema: JsonSchema;
1839
+ uiSchema: FieldUiSchema;
1840
+ };
1841
+
1842
+ /**
1843
+ * GraphEditToolbar -- the selection-driven CRUD toolbar for instance editing.
1844
+ *
1845
+ * Reads the current selection from the workspace selection store (the same
1846
+ * store the viewer owns), gates each action behind the resolved
1847
+ * `GraphCapabilities`, and owns the edit dialogs (node form, edge form, delete
1848
+ * confirm). Relocated from the explorer's `CrudActions`, but library-native:
1849
+ * it drives everything through the injected `GraphMutationPort` +
1850
+ * `GraphSchemaProvider` and is slot-injectable via `ActionPanel actions={...}`.
1851
+ *
1852
+ * Override tiers: pass your own toolbar into `ActionPanel` to replace it
1853
+ * entirely (tier 3), or drive the exported dialogs / port directly (tier 4).
1854
+ */
1855
+
1856
+ interface GraphEditToolbarProps {
1857
+ port: GraphMutationPort;
1858
+ schemaProvider: GraphSchemaProvider;
1859
+ /** Capability profile. Defaults to read-only (no affordances shown). */
1860
+ capabilities?: GraphCapabilities;
1861
+ /** Force read-only regardless of capabilities. */
1862
+ readOnly?: boolean;
1863
+ /** Form widgets shared by the node + edge forms. */
1864
+ widgets?: WidgetRegistry;
1865
+ /** Called after any successful mutation so the consumer can refresh. */
1866
+ onMutated?: () => void;
1867
+ }
1868
+ declare function GraphEditToolbar({ port, schemaProvider, capabilities, readOnly, widgets, onMutated, }: GraphEditToolbarProps): React__default.ReactElement | null;
1869
+
1870
+ /**
1871
+ * NodeFormSheet -- create or edit a graph node (instance data).
1872
+ *
1873
+ * Schema-driven: the node's JSON Schema and editable relations come from the
1874
+ * injected `GraphSchemaProvider`; the form is rendered with
1875
+ * `JsonSchemaFormRenderer`. Editable relations are surfaced as `__rel_*` form
1876
+ * fields (see relationFields.ts). Saving goes through the injected
1877
+ * `GraphMutationPort`: when relations are present the atomic
1878
+ * create/updateNodeWithRelations methods are used, otherwise the plain
1879
+ * create/updateNode methods.
1880
+ *
1881
+ * The component is I/O-free beyond the port + provider it is given, and emits
1882
+ * no events: it `await`s the port and calls `onSaved` so the consumer can patch
1883
+ * its own cache.
1884
+ */
1885
+
1886
+ interface NodeFormSheetProps {
1887
+ open: boolean;
1888
+ onOpenChange: (open: boolean) => void;
1889
+ /** The node being edited; omit for create. */
1890
+ node?: RawGraphNode | null;
1891
+ port: GraphMutationPort;
1892
+ schemaProvider: GraphSchemaProvider;
1893
+ /** Form widgets (e.g. a product reference-select). Defaults to the built-ins. */
1894
+ widgets?: WidgetRegistry;
1895
+ /** Called with the saved node after a successful create/update. */
1896
+ onSaved?: (node: RawGraphNode) => void;
1897
+ }
1898
+ declare function NodeFormSheet({ open, onOpenChange, node, port, schemaProvider, widgets, onSaved, }: NodeFormSheetProps): React__default.ReactElement;
1899
+
1900
+ /**
1901
+ * EdgeFormSheet -- manage the edges between two selected nodes.
1902
+ *
1903
+ * Lists the existing edges between the pair (loaded via the port's
1904
+ * `getPairEdges`), the edge types that may still be created between them
1905
+ * (derived from the schema provider's relations), and renders a schema-driven
1906
+ * property form when creating or editing an edge. All writes go through the
1907
+ * injected `GraphMutationPort`; the component emits no events and calls
1908
+ * `onChanged` so the consumer can patch its own cache and re-read the pair.
1909
+ */
1910
+
1911
+ interface EdgeFormSheetProps {
1912
+ open: boolean;
1913
+ onOpenChange: (open: boolean) => void;
1914
+ /** The two endpoints; the first is the edge source. */
1915
+ nodeA: RawGraphNode;
1916
+ nodeB: RawGraphNode;
1917
+ port: GraphMutationPort;
1918
+ schemaProvider: GraphSchemaProvider;
1919
+ widgets?: WidgetRegistry;
1920
+ /** Called after any edge create / update / delete succeeds. */
1921
+ onChanged?: () => void;
1922
+ }
1923
+ declare function EdgeFormSheet({ open, onOpenChange, nodeA, nodeB, port, schemaProvider, widgets, onChanged, }: EdgeFormSheetProps): React__default.ReactElement;
1924
+
1925
+ /**
1926
+ * DeleteNodeDialog -- confirm deleting a node, warning about dependent edges.
1927
+ *
1928
+ * Loads the node's inbound/outbound edges through the injected
1929
+ * `GraphMutationPort` so the user sees what will be removed. Deleting goes
1930
+ * through `port.deleteNode`; the component emits no events and calls
1931
+ * `onDeleted` so the consumer can patch its own cache.
1932
+ */
1933
+
1934
+ interface DeleteNodeDialogProps {
1935
+ open: boolean;
1936
+ onOpenChange: (open: boolean) => void;
1937
+ node: RawGraphNode;
1938
+ port: GraphMutationPort;
1939
+ /** Called with the deleted node id after a successful delete. */
1940
+ onDeleted?: (id: number) => void;
1941
+ }
1942
+ declare function DeleteNodeDialog({ open, onOpenChange, node, port, onDeleted, }: DeleteNodeDialogProps): React__default.ReactElement;
1943
+
1944
+ export { ActionPanel, type ActionPanelState, type ActionPanelStore, type CapabilitiesValidation, type Cardinality, type ColorPalette, type CreateEdgeInput, type CreateNodeInput, type CreateNodeWithRelationsInput, type CreateNodeWithRelationsResult, DeleteNodeDialog, type DeleteNodeDialogProps, EMPTY_NORMALIZED, EdgeFormSheet, type EdgeFormSheetProps, EdgeInfoCard, type EdgeTypeMode, type EdgeTypeView, type EdgeVisual, type EditMode$1 as EditMode, type EditableMode, type ExpandOptions, type ExpandResult, GraphA11yList, type GraphA11yListProps, type GraphCapabilities, type GraphCapabilitiesValidation, type GraphDataHook, type GraphDataStore, type GraphDisplayConfig, type EditMode as GraphEditMode, GraphEditToolbar, type GraphEditToolbarProps, type GraphExplorationDeps, type GraphExplorationStore, type GraphFilterStore, type GraphFocusAction, type GraphFocusStore, type GraphModel, type GraphModelCapabilities, type GraphModelDisplay, GraphModelEditor, type GraphModelEditorProps, type GraphModelProperty, type GraphMutationPort, type GraphProperties, type GraphProperty, type GraphRelation, type GraphRenderer, GraphRendererProvider, type GraphSchemaProvider, type GraphStatistics, type WorkspaceStores as GraphStoreBundle, GraphStoresContext, type GraphTypeSchema, GraphVisualizer, type GraphVisualizerProps, type LabelDisplayMap, type LiveGraphDataResult, ModelActionPanel, type ModelActionPanelProps, type ModelGraph, NodeFormSheet, type NodeFormSheetProps, NodeInfoCard, NodeTypeNameSheet, type NodeTypeNameSheetProps, type NodeTypeView, type NodeVisual, type NormalizedGraph, Overview, PropertyFormSheet, type PropertyFormSheetProps, type PropertyInput, type PropertyView, type RawGraphEdge, type RawGraphNode, type RelationCardinality, type RelationDef, type RelationDetailView, RelationFormSheet, type RelationFormSheetProps, type RelationInput, type RelationMap, type RelationView, type ResolvedCapabilities, type ResolvedGraphCapabilities, type SelectionStore, type StoreFactory, TypeDetailPanel, type TypeDetailPanelProps, type UpdateEdgeInput, type UpdateNodeInput, type UpdateNodeWithRelationsInput, type UpdateNodeWithRelationsResult, type VisualGraphEdge, type VisualGraphNode, type VisualGraphNormalized, type WorkspaceStores, type XGraph, addEdgeType, addNodeType, addRelation, buildColorPalette, buildColorPaletteFromNodes, capabilitiesSchema, cardinalityLabel, createActionPanelStore, createGraphDataStore, createGraphExplorationStore, createGraphFilterStore, createGraphFocusStore, createSelectionStore, deleteEdgeType, deleteEdgeTypeProperty, deleteNodeProperty, deleteNodeType, deleteRelation, deleteRelationProperty, edgeTypeView, editableRelations, enrichEdge, enrichEdges, enrichNode, enrichNodes, enrichSchemaWithRelations, extractDisplayLabel, extractRelationFields, findEdgeType, findType, graphCapabilitiesSchema, groupEdgesByRelation, hasProperties, hasRelationFields, initializeFormData, isEdgeType, isNodeType, isRawGraphNode, isRelationField, isVisualEdge, isVisualNode, modelToGraph, nodeTypeView, normalizeGraph, reconcileFilter, relationFieldName, relationTitle, relationTypeFromField, relationView, renameEdgeType, renameNodeType, resolveCapabilities, resolveGraphCapabilities, resolveRelationEdge, setEdgeTypeProperty, setNodeProperty, setRelationProperty, toCytoscapeEdge, toCytoscapeNode, toReagraphEdge, toReagraphNode, typeLabel, updateRelation, useActionPanelStore, useCytoscapeData, useGraphFocus, useGraphRenderer, useLiveGraphData, useReagraphData, useStableRef, useWorkspaceGraphData, useWorkspaceGraphExploration, useWorkspaceGraphFilter, useWorkspaceSelection, validateCapabilities, validateGraphCapabilities };