@matdata/yasgui-graph-plugin 1.4.2 → 1.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/README.md CHANGED
@@ -13,9 +13,12 @@ A YASGUI plugin for visualizing SPARQL CONSTRUCT and DESCRIBE query results as i
13
13
  - 🟢 Light Green (#a6c8a6ff) = Literals
14
14
  - ⚪ Light Grey (#c5c5c5ff) = Blank nodes
15
15
  - 🟠 Orange (#e15b13ff) = rdf:type objects (classes)
16
+ - **🖼️ Node Icons & Images**: Render images or emoji/icons on nodes via `schema:image` / `schema:icon` properties (see [Node icons and images](#node-icons-and-images))
17
+ - **� Compact Mode**: Hide literal and class nodes; show rdf:type and datatype properties in enhanced tooltips instead
16
18
  - **🔍 Navigation**: Mouse wheel zoom, drag to pan, "Zoom to Fit" button
17
- - **✋ Drag & Drop**: Reorganize nodes by dragging them to new positions
18
- - **💬 Tooltips**: Hover for full URI/literal details (300ms delay)
19
+ - **✋ Drag & Drop**: Reorganize nodes by dragging them to new positions (nodes stay pinned after manual drag)
20
+ - **� Node Expansion**: Double-click any URI node to fetch and merge related triples via DESCRIBE queries (see [Expand Nodes with Double Click](#-expand-nodes-with-double-click))
21
+ - **�💬 Rich Tooltips**: Modern HTML tooltips with node type, value, namespace, and datatype information
19
22
  - **🌓 Theme Support**: Automatic light/dark mode detection and dynamic color switching
20
23
  - **⚡ Performance**: Handles up to 1,000 nodes with <2s render time
21
24
  - **♿ Accessible**: WCAG AA color contrast, keyboard navigation support
@@ -102,8 +105,9 @@ After running the query, click the **"Graph"** tab to see the visualization.
102
105
  - **Fit to View**: Click the "Zoom to Fit" button to center the entire graph
103
106
 
104
107
  ### Interaction
105
- - **Drag Nodes**: Click and drag any node to reposition it
106
- - **Tooltips**: Hover over nodes/edges for 300ms to see full details
108
+ - **Drag Nodes**: Click and drag any node to reposition it (nodes are automatically pinned in place after dragging)
109
+ - **Expand Nodes**: 🆕 Double-click any blue URI node to fetch and merge additional RDF triples for that resource (see [Node Expansion](#expand-nodes-with-double-click) below)
110
+ - **Tooltips**: Hover over nodes/edges to see rich HTML tooltips with type, value, namespace, and datatype information
107
111
 
108
112
  ### Understanding Colors
109
113
 
@@ -116,30 +120,222 @@ After running the query, click the **"Graph"** tab to see the visualization.
116
120
 
117
121
  ## ⚙️ Configuration
118
122
 
119
- The plugin uses sensible defaults but can be customized by extending the `GraphPlugin` class:
123
+ The plugin ships with sensible defaults and stores every change in **`localStorage`** so settings survive page reloads.
124
+
125
+ ### Settings panel
126
+
127
+ Click the **⚙ Settings** button (top-right of the graph) to open the settings panel.
128
+
129
+ | Setting | Values | Default | Description |
130
+ |---------|--------|---------|-------------|
131
+ | **Compact mode** | on / off | off | Hide literal and class nodes; show rdf:type and datatype properties in tooltips instead |
132
+ | **Arrow style** | Curved / Straight | Curved | Toggle between smooth curved edges and straight lines between nodes |
133
+ | **Predicate display** | Label / Icon / Hidden | Icon | Show the full prefixed URI on edges, a compact symbol/icon, or nothing |
134
+ | **Show literals** | on / off | on | Include or exclude literal value nodes (strings, numbers, dates, …) |
135
+ | **Show classes** | on / off | on | Include or exclude nodes that are objects of `rdf:type` triples (class nodes) |
136
+ | **Show blank nodes** | on / off | on | Include or exclude blank nodes (`_:b0`, `_:b1`, …) |
137
+ | **Show node labels** | on / off | on | Render the prefixed URI / literal text inside each node |
138
+ | **Enable physics** | on / off | on | Keep the force-directed layout simulation running so nodes keep adjusting |
139
+ | **Node size** | Small / Medium / Large | Medium | Set the radius of all nodes |
140
+
141
+ ### Predicate icons
142
+
143
+ When *Predicate display* is set to **Icon**, each edge displays a compact symbol instead of the full label. Symbols are defined for the 20+ most common predicates:
144
+
145
+ | Predicate | Symbol |
146
+ |-----------|--------|
147
+ | `rdf:type` | `a` |
148
+ | `rdfs:label` | `lbl` |
149
+ | `rdfs:comment` | `cmt` |
150
+ | `rdfs:subClassOf` | `⊂` |
151
+ | `rdfs:subPropertyOf` | `⊆` |
152
+ | `rdfs:domain` | `dom` |
153
+ | `rdfs:range` | `rng` |
154
+ | `rdfs:seeAlso` | `see` |
155
+ | `rdfs:isDefinedBy` | `idb` |
156
+ | `owl:sameAs` | `≡` |
157
+ | `owl:equivalentClass` | `≅` |
158
+ | `owl:inverseOf` | `⇄` |
159
+ | `owl:disjointWith` | `≠` |
160
+ | `skos:prefLabel` | `★` |
161
+ | `skos:altLabel` | `☆` |
162
+ | `skos:definition` | `def` |
163
+ | `skos:broader` | `↑` |
164
+ | `skos:narrower` | `↓` |
165
+ | `skos:related` | `↔` |
166
+ | `skos:note` | `note` |
167
+ | `skos:exactMatch` | `≡` |
168
+ | `skos:closeMatch` | `≈` |
169
+ | `dcterms:title` | `ttl` |
170
+ | `dcterms:description` | `dsc` |
171
+ | `dcterms:created` | `crt` |
172
+ | `dcterms:modified` | `mod` |
173
+ | `dcterms:creator` | `by` |
174
+ | `dcterms:subject` | `sbj` |
175
+ | `foaf:name` | `nm` |
176
+ | `foaf:knows` | `⟷` |
177
+ | `foaf:member` | `mbr` |
178
+ | `schema:name` | `nm` |
179
+ | `schema:description` | `dsc` |
180
+
181
+ For predicates not in the table the full prefixed label is used as a fallback.
182
+
183
+ ## 🖼️ Node icons and images
184
+
185
+ Any URI node can display an image or an icon instead of (or in addition to) the default coloured dot by attaching `schema:image` or `schema:icon` as a property directly in the SPARQL result.
186
+
187
+ | Property | Object | Effect |
188
+ |----------|--------|--------|
189
+ | `schema:image` (`https://schema.org/image`) | URL literal or URI | Node is rendered as a circular image |
190
+ | `schema:icon` (`https://schema.org/icon`) | emoji / short string | The string is used as the node's label |
191
+
192
+ `schema:icon` takes priority over `schema:image`. The corresponding `schema:icon`/`schema:image` triples are **not** rendered as separate nodes or edges, but their values **are** shown in the node tooltip. Similarly, any `rdfs:label` triple is consumed to determine the node's displayed label and is never drawn as an edge, even when predicate display is enabled.
193
+
194
+ ### Example – inline image on a resource
195
+
196
+ ```sparql
197
+ CONSTRUCT {
198
+ ex:alice schema:image <https://example.com/alice.png> .
199
+ ex:alice ex:knows ex:bob .
200
+ }
201
+ WHERE {}
202
+ ```
203
+
204
+ `ex:alice` will be drawn as a circular photograph.
205
+
206
+ ### Example – icon/emoji on a class
207
+
208
+ ```sparql
209
+ CONSTRUCT {
210
+ ex:alice rdf:type ex:Person .
211
+ ex:Person schema:icon "👤" .
212
+ }
213
+ WHERE {}
214
+ ```
215
+
216
+ `ex:alice` remains a normal dot node in regular mode.
217
+ In **compact mode** the class node (`ex:Person`) is hidden and Alice's node inherits the `👤` emoji as its label.
218
+
219
+ ### Compact mode visual inheritance
220
+
221
+ When compact mode is enabled, class nodes are hidden and the plugin resolves the image/icon to show on the resource node using the following priority:
222
+
223
+ 1. `schema:image` / `schema:icon` directly on the **resource** (highest priority)
224
+ 2. `schema:image` / `schema:icon` on the **rdf:type class**
225
+ 3. `schema:image` / `schema:icon` on a **rdfs:subClassOf superclass** (one hop)
226
+
227
+ ### Programmatic configuration
228
+
229
+ You can also pass initial settings when extending the class:
120
230
 
121
231
  ```javascript
122
232
  class CustomGraphPlugin extends GraphPlugin {
123
233
  constructor(yasr) {
124
234
  super(yasr);
125
- }
126
-
127
- // Override network options
128
- getNetworkOptions() {
129
- return {
130
- ...super.getNetworkOptions(),
131
- physics: {
132
- enabled: true,
133
- stabilization: { iterations: 100 } // Faster but less optimal layout
134
- }
135
- };
235
+ // Override defaults
236
+ this.settings.edgeStyle = 'straight';
237
+ this.settings.predicateDisplay = 'label';
238
+ this.settings.nodeSize = 'large';
136
239
  }
137
240
  }
138
241
 
139
242
  Yasgui.Yasr.registerPlugin('customGraph', CustomGraphPlugin);
140
243
  ```
141
244
 
142
- ## 🔧 Development
245
+ ## Expand Nodes with Double Click
246
+
247
+ The graph plugin supports **interactive node expansion** via double-clicking. This allows you to progressively explore RDF graphs by fetching additional triples for any URI node without redrawing the entire graph.
248
+
249
+ ### How It Works
250
+
251
+ 1. **Double-click a blue URI node** in the graph
252
+ 2. The node's border turns **orange and thickens** (loading state)
253
+ 3. A `DESCRIBE <uri>` query is sent to the SPARQL endpoint
254
+ 4. **New triples are merged** into the existing graph
255
+ 5. Node's border returns to normal width with **thicker border (3px) to indicate expansion**
256
+ 6. Graph layout and zoom level are **preserved**
257
+
258
+ ### Visual Feedback
259
+
260
+ | State | Border | Meaning |
261
+ |-------|--------|---------|
262
+ | **Default** | 2px | Node has not been expanded |
263
+ | **Loading** | 4px, orange | DESCRIBE query in progress |
264
+ | **Expanded** | 3px, normal color | Successfully expanded |
265
+
266
+ ### Supported Node Types
267
+
268
+ | Node Type | Can Expand? | Reason |
269
+ |-----------|-------|----|
270
+ | 🔵 **URI nodes** | ✅ Yes | DESCRIBE works on URIs |
271
+ | 🟢 **Literals** | ❌ No | Cannot run DESCRIBE on literal values |
272
+ | ⚪ **Blank nodes** | ❌ No | Blank nodes have no resolvable identity |
273
+
274
+ ### Example: Exploring a Knowledge Graph
275
+
276
+ **Initial Query**:
277
+ ```sparql
278
+ PREFIX ex: <http://example.org/>
279
+ PREFIX foaf: <http://xmlns.com/foaf/0.1/>
280
+
281
+ CONSTRUCT {
282
+ ex:alice foaf:knows ex:bob .
283
+ ex:alice foaf:name "Alice" .
284
+ ex:bob foaf:name "Bob" .
285
+ }
286
+ WHERE {}
287
+ ```
288
+
289
+ **Initial Graph**: 3 nodes (Alice, "Alice", Bob, "Bob"), 2 edges
290
+
291
+ **User Action**: Double-click the `ex:bob` node
292
+
293
+ **What Happens**:
294
+ - System executes: `DESCRIBE <http://example.org/bob>`
295
+ - Endpoint returns all triples about Bob (from your SPARQL endpoint)
296
+ - New nodes and edges appear in the graph
297
+ - Graph layout shifts smoothly to accommodate new nodes
298
+ - `ex:bob` node gets a thicker border
299
+
300
+ **Result**: You can now see Bob's relationships, properties, and connections without losing your current view
301
+
302
+ ### Requirements
303
+
304
+ The node expansion feature requires:
305
+
306
+ 1. **SPARQL 1.1 DESCRIBE support**: Your endpoint must support DESCRIBE queries
307
+ 2. **Query execution callback**: YASR must provide `yasr.executeQuery()` for background queries
308
+ 3. **RDF response format**: Endpoint must return results in RDF (JSON-LD, Turtle, N-Triples, etc.)
309
+
310
+ ### Limitations & Behavior
311
+
312
+ - Only new triples are added (existing triples are skipped if already in graph)
313
+ - Expansion is **one-level deep** - only triples directly about the URI are added
314
+ - For very large result sets (1000+ triples from DESCRIBE), performance may be affected
315
+ - Blank nodes returned by DESCRIBE may not connect properly if disconnected from existing nodes
316
+
317
+ ### Troubleshooting Expansion
318
+
319
+ **"Nothing happens when I double-click"**
320
+ - Ensure the node is blue (URI node, not literal or blank node)
321
+ - Check browser console for warnings about `yasr.executeQuery`
322
+ - Verify your SPARQL endpoint supports DESCRIBE queries
323
+
324
+ **"Graph becomes slow after many expansions"**
325
+ - Disable physics simulation in Settings panel for faster UI response
326
+ - Consider limiting query results with WHERE clause constraints
327
+ - Each expansion adds more triples to the visualization
328
+
329
+ **"New nodes don't appear where I expect"**
330
+ - The force-directed layout will position new nodes to minimize overlaps
331
+ - Disable Physics in Settings to lock positions if desired
332
+ - Manually drag new nodes to preferred positions
333
+
334
+ ### Demo
335
+
336
+ See [demo/expand.html](./demo/expand.html) for a working example with mock DESCRIBE responses and detailed logging.
337
+
338
+ ## �🔧 Development
143
339
 
144
340
  ### Build
145
341
 
@@ -163,6 +359,7 @@ Output:
163
359
  ### Code Quality
164
360
 
165
361
  ```bash
362
+ npm test # Run Jest unit tests
166
363
  npm run lint # ESLint check
167
364
  npm run format # Prettier format
168
365
  ```
@@ -170,6 +367,7 @@ npm run format # Prettier format
170
367
  ## 📚 Documentation
171
368
 
172
369
  - **[Quickstart Guide](./specs/001-construct-graph-viz/quickstart.md)** - Installation, usage, troubleshooting
370
+ - **[Node Expansion Feature](./specs/001-construct-graph-viz/EXPAND_FEATURE.md)** - Complete guide to double-click expansion (FR-001 through FR-009)
173
371
  - **[Data Model](./specs/001-construct-graph-viz/data-model.md)** - Entity definitions and relationships
174
372
  - **[Contracts](./specs/001-construct-graph-viz/contracts/)** - API specifications for YASR plugin and vis-network integration
175
373
  - **[Specification](./specs/001-construct-graph-viz/spec.md)** - Complete feature specification
@@ -210,19 +408,18 @@ Contributions welcome! Please follow the project constitution (`.specify/memory/
210
408
  **Current Version**: 0.1.0 (MVP)
211
409
 
212
410
  **Implemented Features** (v0.1.0):
213
- - ✅ Basic graph visualization (US1)
214
- - ✅ Navigation controls (US2)
215
- - ✅ Color-coded nodes
216
- - ✅ Prefix abbreviation
217
- - ✅ Blank node support
218
- - ✅ Performance optimization
219
-
220
- **Planned Features** (Future):
221
- - Enhanced tooltips with datatype display (US4)
222
- - Manual testing across all browsers (US3 verification)
223
- - Large graph optimization (>1k nodes)
224
- - Custom color schemes
225
- - ⏳ Layout algorithm selection
411
+ - ✅ **Basic graph visualization** (US1) - CONSTRUCT/DESCRIBE results as interactive graphs
412
+ - ✅ **Navigation controls** (US2) - Zoom, pan, "Fit to View" button
413
+ - ✅ **Color-coded nodes** - URIs, literals, blank nodes, rdf:type objects
414
+ - ✅ **Prefix abbreviation** - Display prefixed URIs instead of full URLs
415
+ - ✅ **Blank node support** - Handle anonymous RDF nodes
416
+ - ✅ **Drag & repositioning** - Manually adjust node positions
417
+ - ✅ **Rich tooltips** - Hover for detailed node/edge information
418
+ - ✅ **Theme support** - Light/dark mode detection and switching
419
+ - **Settings panel** - Configurable display options with localStorage persistence
420
+ - **Node icons & images** - Display images via schema:image property
421
+ - **Compact mode** - Hide literals and classes for cleaner visualization
422
+ - **Double-click expansion** (US5) - Fetch and merge related triples via DESCRIBE queries (see [Expand Nodes with Double Click](#-expand-nodes-with-double-click))
226
423
 
227
424
  ## 🐛 Troubleshooting
228
425
 
@@ -92,6 +92,63 @@
92
92
  .yasgui-graph-button:active {
93
93
  transform: translateY(1px);
94
94
  }
95
+ .yasgui-graph-settings-panel {
96
+ position: absolute;
97
+ top: 50px;
98
+ right: 10px;
99
+ z-index: 10001;
100
+ background: var(--yasgui-graph-button-bg, #4caf50);
101
+ background: var(--yasgui-bg-primary, #ffffff);
102
+ color: var(--yasgui-graph-text, #333333);
103
+ border: 1px solid var(--yasgui-border-color, #cccccc);
104
+ border-radius: 6px;
105
+ padding: 12px 14px;
106
+ min-width: 240px;
107
+ box-shadow: var(--yasgui-graph-shadow, 0 2px 8px rgba(0,0,0,0.2));
108
+ font-size: 13px;
109
+ }
110
+ .yasgui-graph-settings-title {
111
+ font-weight: 600;
112
+ font-size: 14px;
113
+ margin-bottom: 10px;
114
+ padding-bottom: 6px;
115
+ border-bottom: 1px solid var(--yasgui-border-color, #cccccc);
116
+ }
117
+ .yasgui-graph-settings-section {
118
+ font-size: 11px;
119
+ font-weight: 700;
120
+ text-transform: uppercase;
121
+ letter-spacing: 0.5px;
122
+ color: var(--yasgui-text-secondary, #888888);
123
+ margin: 10px 0 4px;
124
+ }
125
+ .yasgui-graph-settings-row {
126
+ display: flex;
127
+ align-items: center;
128
+ justify-content: space-between;
129
+ gap: 8px;
130
+ padding: 3px 0;
131
+ cursor: pointer;
132
+ }
133
+ .yasgui-graph-settings-row input[type=checkbox] {
134
+ cursor: pointer;
135
+ accent-color: var(--yasgui-accent-color, #4caf50);
136
+ }
137
+ .yasgui-graph-settings-select {
138
+ font-size: 12px;
139
+ padding: 2px 4px;
140
+ border: 1px solid var(--yasgui-border-color, #cccccc);
141
+ border-radius: 3px;
142
+ background: var(--yasgui-bg-primary, #ffffff);
143
+ color: var(--yasgui-text-primary, #333333);
144
+ cursor: pointer;
145
+ max-width: 140px;
146
+ }
147
+ .yasgui-graph-settings-button {
148
+ display: inline-flex;
149
+ align-items: center;
150
+ gap: 5px;
151
+ }
95
152
  .yasgui-graph-icon {
96
153
  display: inline-flex;
97
154
  align-items: center;
@@ -102,4 +159,62 @@
102
159
  height: 16px;
103
160
  fill: currentColor;
104
161
  }
162
+ .yasgui-graph-plugin-container .vis-tooltip {
163
+ display: none !important;
164
+ }
165
+ .yasgui-graph-tooltip-container {
166
+ position: absolute;
167
+ background-color: rgba(28, 28, 32, 0.95);
168
+ color: #f0f0f0;
169
+ border: 1px solid rgba(255, 255, 255, 0.12);
170
+ border-radius: 6px;
171
+ padding: 8px 10px;
172
+ font-size: 11px;
173
+ font-family:
174
+ ui-monospace,
175
+ "SFMono-Regular",
176
+ "Menlo",
177
+ "Consolas",
178
+ monospace;
179
+ max-width: 340px;
180
+ white-space: normal;
181
+ box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
182
+ pointer-events: auto;
183
+ z-index: 1000;
184
+ user-select: text;
185
+ cursor: text;
186
+ }
187
+ .yasgui-graph-tooltip {
188
+ display: flex;
189
+ flex-direction: column;
190
+ gap: 3px;
191
+ }
192
+ .yasgui-tooltip-type {
193
+ font-size: 9px;
194
+ font-weight: 700;
195
+ text-transform: uppercase;
196
+ letter-spacing: 0.6px;
197
+ color: rgba(255, 255, 255, 0.5);
198
+ padding-bottom: 5px;
199
+ border-bottom: 1px solid rgba(255, 255, 255, 0.12);
200
+ margin-bottom: 3px;
201
+ }
202
+ .yasgui-tooltip-row {
203
+ display: flex;
204
+ gap: 8px;
205
+ align-items: baseline;
206
+ line-height: 1.5;
207
+ }
208
+ .yasgui-tooltip-key {
209
+ font-size: 10px;
210
+ font-weight: 600;
211
+ color: rgba(255, 255, 255, 0.55);
212
+ min-width: 58px;
213
+ flex-shrink: 0;
214
+ }
215
+ .yasgui-tooltip-val {
216
+ font-size: 11px;
217
+ color: #e8e8e8;
218
+ word-break: break-all;
219
+ }
105
220
  /*# sourceMappingURL=yasgui-graph-plugin.cjs.css.map */
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../styles/index.css"],
4
- "sourcesContent": ["/* Color scheme variables using YASGUI CSS custom properties with fallbacks */\r\n:root {\r\n /* Graph-specific node colors (custom to this plugin) */\r\n --yasgui-graph-uri: #97c2fc;\r\n --yasgui-graph-literal: #a6c8a6ff;\r\n --yasgui-graph-blank-node: #c5c5c5ff;\r\n --yasgui-graph-type-object: #e15b13ff;\r\n\r\n /* Graph text and edges - using YASGUI variables with fallbacks */\r\n --yasgui-graph-text: var(--yasgui-text-primary, #000000);\r\n --yasgui-graph-edge: var(--yasgui-border-color, #cccccc);\r\n --yasgui-graph-edge-label: var(--yasgui-text-secondary, #666666);\r\n --yasgui-graph-edge-label-bg: var(--yasgui-bg-primary, rgba(255, 255, 255, 0.8));\r\n --yasgui-graph-background: var(--yasgui-bg-primary, #ffffff);\r\n\r\n /* UI elements - using YASGUI variables with fallbacks */\r\n --yasgui-graph-canvas-bg: var(--yasgui-bg-primary, #ffffff);\r\n --yasgui-graph-button-bg: var(--yasgui-accent-color, #4caf50);\r\n --yasgui-graph-button-hover: var(--yasgui-link-hover, #45a049);\r\n --yasgui-graph-button-text: var(--yasgui-button-text, #ffffff);\r\n --yasgui-graph-empty-text: var(--yasgui-text-secondary, #666666);\r\n --yasgui-graph-error-text: #f44336;\r\n\r\n /* Shadow */\r\n --yasgui-graph-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n\r\n /* Legacy variables for backward compatibility */\r\n --color-blank-node: #ffff00;\r\n --color-literal: #808080;\r\n --color-rdf-type: #00ff00;\r\n --color-uri: #0000ff;\r\n\r\n --color-blank-node-dark: #ffeb3b;\r\n --color-literal-dark: #9e9e9e;\r\n --color-rdf-type-dark: #4caf50;\r\n --color-uri-dark: #2196f3;\r\n\r\n --bg-light: #ffffff;\r\n --bg-dark: #1e1e1e;\r\n\r\n --text-light: #666666;\r\n --text-dark: #cccccc;\r\n --text-error: #f44336;\r\n\r\n --button-primary-bg: #4caf50;\r\n --button-primary-bg-hover: #45a049;\r\n --button-text: #ffffff;\r\n\r\n --box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n/* Dark theme colors */\r\n[data-theme='dark'],\r\n.dark-theme {\r\n /* Graph-specific node colors in dark mode */\r\n --yasgui-graph-uri: #97c2fc;\r\n --yasgui-graph-literal: #a6c8a6ff;\r\n --yasgui-graph-blank-node: #888888;\r\n --yasgui-graph-type-object: #e15b13ff;\r\n\r\n /* Override with YASGUI dark theme variables */\r\n --yasgui-graph-text: var(--yasgui-text-primary, #e0e0e0);\r\n --yasgui-graph-edge: var(--yasgui-border-color, #666666);\r\n --yasgui-graph-edge-label: var(--yasgui-text-secondary, #cccccc);\r\n --yasgui-graph-edge-label-bg: var(--yasgui-bg-secondary, rgba(30, 30, 30, 0.8));\r\n --yasgui-graph-background: var(--yasgui-bg-primary, #1e1e1e);\r\n --yasgui-graph-canvas-bg: var(--yasgui-bg-primary, #1e1e1e);\r\n --yasgui-graph-empty-text: var(--yasgui-text-secondary, #cccccc);\r\n}\r\n/* Graph plugin container */\r\n.yasgui-graph-plugin-container {\r\n width: 100%;\r\n height: 500px; /* Initial fixed height as workaround for viz-network bug */\r\n position: relative;\r\n overflow: hidden;\r\n}\r\n.yasgui-graph-plugin-container canvas {\r\n background-color: var(--yasgui-graph-canvas-bg);\r\n}\r\n.yasgui-graph-plugin-empty-state {\r\n padding: 20px;\r\n text-align: center;\r\n color: var(--yasgui-graph-empty-text);\r\n}\r\n.yasgui-graph-plugin-error {\r\n padding: 20px;\r\n color: var(--yasgui-graph-error-text);\r\n}\r\n/* Controls container */\r\n.yasgui-graph-controls {\r\n position: absolute;\r\n top: 10px;\r\n right: 10px;\r\n z-index: 10000;\r\n display: flex;\r\n gap: 10px;\r\n pointer-events: auto;\r\n}\r\n/* Button styles */\r\n.yasgui-graph-button {\r\n padding: 8px 12px;\r\n background: var(--yasgui-graph-button-bg);\r\n color: var(--yasgui-graph-button-text);\r\n border: none;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font-size: 14px;\r\n box-shadow: var(--yasgui-graph-shadow);\r\n transition: background 0.2s ease;\r\n}\r\n.yasgui-graph-button:hover {\r\n background: var(--yasgui-graph-button-hover);\r\n}\r\n.yasgui-graph-button:active {\r\n transform: translateY(1px);\r\n}\r\n/* Icon styles */\r\n.yasgui-graph-icon {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n.yasgui-graph-icon svg {\r\n width: 16px;\r\n height: 16px;\r\n fill: currentColor;\r\n}\r\n/* Main entry point for all styles */\r\n/* This file will be imported by the TypeScript code */\r\n"],
5
- "mappings": ";AACA;AAEE,sBAAoB;AACpB,0BAAwB;AACxB,6BAA2B;AAC3B,8BAA4B;AAG5B,uBAAqB,IAAI,qBAAqB,EAAE;AAChD,uBAAqB,IAAI,qBAAqB,EAAE;AAChD,6BAA2B,IAAI,uBAAuB,EAAE;AACxD,gCAA8B,IAAI,mBAAmB,EAAE,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;AAC3E,6BAA2B,IAAI,mBAAmB,EAAE;AAGpD,4BAA0B,IAAI,mBAAmB,EAAE;AACnD,4BAA0B,IAAI,qBAAqB,EAAE;AACrD,+BAA6B,IAAI,mBAAmB,EAAE;AACtD,8BAA4B,IAAI,oBAAoB,EAAE;AACtD,6BAA2B,IAAI,uBAAuB,EAAE;AACxD,6BAA2B;AAG3B,yBAAuB,EAAE,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AAG/C,sBAAoB;AACpB,mBAAiB;AACjB,oBAAkB;AAClB,eAAa;AAEb,2BAAyB;AACzB,wBAAsB;AACtB,yBAAuB;AACvB,oBAAkB;AAElB,cAAY;AACZ,aAAW;AAEX,gBAAc;AACd,eAAa;AACb,gBAAc;AAEd,uBAAqB;AACrB,6BAA2B;AAC3B,iBAAe;AAEf,gBAAc,EAAE,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AACxC;AAEA,CAAC;AACD,CAAC;AAEC,sBAAoB;AACpB,0BAAwB;AACxB,6BAA2B;AAC3B,8BAA4B;AAG5B,uBAAqB,IAAI,qBAAqB,EAAE;AAChD,uBAAqB,IAAI,qBAAqB,EAAE;AAChD,6BAA2B,IAAI,uBAAuB,EAAE;AACxD,gCAA8B,IAAI,qBAAqB,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;AAC1E,6BAA2B,IAAI,mBAAmB,EAAE;AACpD,4BAA0B,IAAI,mBAAmB,EAAE;AACnD,6BAA2B,IAAI,uBAAuB,EAAE;AAC1D;AAEA,CAAC;AACC,SAAO;AACP,UAAQ;AACR,YAAU;AACV,YAAU;AACZ;AACA,CANC,8BAM8B;AAC7B,oBAAkB,IAAI;AACxB;AACA,CAAC;AACC,WAAS;AACT,cAAY;AACZ,SAAO,IAAI;AACb;AACA,CAAC;AACC,WAAS;AACT,SAAO,IAAI;AACb;AAEA,CAAC;AACC,YAAU;AACV,OAAK;AACL,SAAO;AACP,WAAS;AACT,WAAS;AACT,OAAK;AACL,kBAAgB;AAClB;AAEA,CAAC;AACC,WAAS,IAAI;AACb,cAAY,IAAI;AAChB,SAAO,IAAI;AACX,UAAQ;AACR,iBAAe;AACf,UAAQ;AACR,aAAW;AACX,cAAY,IAAI;AAChB,cAAY,WAAW,KAAK;AAC9B;AACA,CAXC,mBAWmB;AAClB,cAAY,IAAI;AAClB;AACA,CAdC,mBAcmB;AAClB,aAAW,WAAW;AACxB;AAEA,CAAC;AACC,WAAS;AACT,eAAa;AACb,mBAAiB;AACnB;AACA,CALC,kBAKkB;AACjB,SAAO;AACP,UAAQ;AACR,QAAM;AACR;",
4
+ "sourcesContent": ["/* Color scheme variables using YASGUI CSS custom properties with fallbacks */\r\n:root {\r\n /* Graph-specific node colors (custom to this plugin) */\r\n --yasgui-graph-uri: #97c2fc;\r\n --yasgui-graph-literal: #a6c8a6ff;\r\n --yasgui-graph-blank-node: #c5c5c5ff;\r\n --yasgui-graph-type-object: #e15b13ff;\r\n\r\n /* Graph text and edges - using YASGUI variables with fallbacks */\r\n --yasgui-graph-text: var(--yasgui-text-primary, #000000);\r\n --yasgui-graph-edge: var(--yasgui-border-color, #cccccc);\r\n --yasgui-graph-edge-label: var(--yasgui-text-secondary, #666666);\r\n --yasgui-graph-edge-label-bg: var(--yasgui-bg-primary, rgba(255, 255, 255, 0.8));\r\n --yasgui-graph-background: var(--yasgui-bg-primary, #ffffff);\r\n\r\n /* UI elements - using YASGUI variables with fallbacks */\r\n --yasgui-graph-canvas-bg: var(--yasgui-bg-primary, #ffffff);\r\n --yasgui-graph-button-bg: var(--yasgui-accent-color, #4caf50);\r\n --yasgui-graph-button-hover: var(--yasgui-link-hover, #45a049);\r\n --yasgui-graph-button-text: var(--yasgui-button-text, #ffffff);\r\n --yasgui-graph-empty-text: var(--yasgui-text-secondary, #666666);\r\n --yasgui-graph-error-text: #f44336;\r\n\r\n /* Shadow */\r\n --yasgui-graph-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n\r\n /* Legacy variables for backward compatibility */\r\n --color-blank-node: #ffff00;\r\n --color-literal: #808080;\r\n --color-rdf-type: #00ff00;\r\n --color-uri: #0000ff;\r\n\r\n --color-blank-node-dark: #ffeb3b;\r\n --color-literal-dark: #9e9e9e;\r\n --color-rdf-type-dark: #4caf50;\r\n --color-uri-dark: #2196f3;\r\n\r\n --bg-light: #ffffff;\r\n --bg-dark: #1e1e1e;\r\n\r\n --text-light: #666666;\r\n --text-dark: #cccccc;\r\n --text-error: #f44336;\r\n\r\n --button-primary-bg: #4caf50;\r\n --button-primary-bg-hover: #45a049;\r\n --button-text: #ffffff;\r\n\r\n --box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);\r\n}\r\n/* Dark theme colors */\r\n[data-theme='dark'],\r\n.dark-theme {\r\n /* Graph-specific node colors in dark mode */\r\n --yasgui-graph-uri: #97c2fc;\r\n --yasgui-graph-literal: #a6c8a6ff;\r\n --yasgui-graph-blank-node: #888888;\r\n --yasgui-graph-type-object: #e15b13ff;\r\n\r\n /* Override with YASGUI dark theme variables */\r\n --yasgui-graph-text: var(--yasgui-text-primary, #e0e0e0);\r\n --yasgui-graph-edge: var(--yasgui-border-color, #666666);\r\n --yasgui-graph-edge-label: var(--yasgui-text-secondary, #cccccc);\r\n --yasgui-graph-edge-label-bg: var(--yasgui-bg-secondary, rgba(30, 30, 30, 0.8));\r\n --yasgui-graph-background: var(--yasgui-bg-primary, #1e1e1e);\r\n --yasgui-graph-canvas-bg: var(--yasgui-bg-primary, #1e1e1e);\r\n --yasgui-graph-empty-text: var(--yasgui-text-secondary, #cccccc);\r\n}\r\n/* Graph plugin container */\r\n.yasgui-graph-plugin-container {\r\n width: 100%;\r\n height: 500px; /* Initial fixed height as workaround for viz-network bug */\r\n position: relative;\r\n overflow: hidden;\r\n}\r\n.yasgui-graph-plugin-container canvas {\r\n background-color: var(--yasgui-graph-canvas-bg);\r\n}\r\n.yasgui-graph-plugin-empty-state {\r\n padding: 20px;\r\n text-align: center;\r\n color: var(--yasgui-graph-empty-text);\r\n}\r\n.yasgui-graph-plugin-error {\r\n padding: 20px;\r\n color: var(--yasgui-graph-error-text);\r\n}\r\n/* Controls container */\r\n.yasgui-graph-controls {\r\n position: absolute;\r\n top: 10px;\r\n right: 10px;\r\n z-index: 10000;\r\n display: flex;\r\n gap: 10px;\r\n pointer-events: auto;\r\n}\r\n/* Button styles */\r\n.yasgui-graph-button {\r\n padding: 8px 12px;\r\n background: var(--yasgui-graph-button-bg);\r\n color: var(--yasgui-graph-button-text);\r\n border: none;\r\n border-radius: 4px;\r\n cursor: pointer;\r\n font-size: 14px;\r\n box-shadow: var(--yasgui-graph-shadow);\r\n transition: background 0.2s ease;\r\n}\r\n.yasgui-graph-button:hover {\r\n background: var(--yasgui-graph-button-hover);\r\n}\r\n.yasgui-graph-button:active {\r\n transform: translateY(1px);\r\n}\r\n/* Settings panel */\r\n.yasgui-graph-settings-panel {\r\n position: absolute;\r\n top: 50px;\r\n right: 10px;\r\n z-index: 10001;\r\n background: var(--yasgui-graph-button-bg, #4caf50);\r\n background: var(--yasgui-bg-primary, #ffffff);\r\n color: var(--yasgui-graph-text, #333333);\r\n border: 1px solid var(--yasgui-border-color, #cccccc);\r\n border-radius: 6px;\r\n padding: 12px 14px;\r\n min-width: 240px;\r\n box-shadow: var(--yasgui-graph-shadow, 0 2px 8px rgba(0,0,0,0.2));\r\n font-size: 13px;\r\n}\r\n.yasgui-graph-settings-title {\r\n font-weight: 600;\r\n font-size: 14px;\r\n margin-bottom: 10px;\r\n padding-bottom: 6px;\r\n border-bottom: 1px solid var(--yasgui-border-color, #cccccc);\r\n}\r\n.yasgui-graph-settings-section {\r\n font-size: 11px;\r\n font-weight: 700;\r\n text-transform: uppercase;\r\n letter-spacing: 0.5px;\r\n color: var(--yasgui-text-secondary, #888888);\r\n margin: 10px 0 4px;\r\n}\r\n.yasgui-graph-settings-row {\r\n display: flex;\r\n align-items: center;\r\n justify-content: space-between;\r\n gap: 8px;\r\n padding: 3px 0;\r\n cursor: pointer;\r\n}\r\n.yasgui-graph-settings-row input[type='checkbox'] {\r\n cursor: pointer;\r\n accent-color: var(--yasgui-accent-color, #4caf50);\r\n}\r\n.yasgui-graph-settings-select {\r\n font-size: 12px;\r\n padding: 2px 4px;\r\n border: 1px solid var(--yasgui-border-color, #cccccc);\r\n border-radius: 3px;\r\n background: var(--yasgui-bg-primary, #ffffff);\r\n color: var(--yasgui-text-primary, #333333);\r\n cursor: pointer;\r\n max-width: 140px;\r\n}\r\n/* Settings button icon alignment */\r\n.yasgui-graph-settings-button {\r\n display: inline-flex;\r\n align-items: center;\r\n gap: 5px;\r\n}\r\n.yasgui-graph-icon {\r\n display: inline-flex;\r\n align-items: center;\r\n justify-content: center;\r\n}\r\n.yasgui-graph-icon svg {\r\n width: 16px;\r\n height: 16px;\r\n fill: currentColor;\r\n}\r\n/* Modern tooltip styles - override vis-network defaults */\r\n.yasgui-graph-plugin-container .vis-tooltip {\r\n display: none !important; /* Hide default vis-network tooltips */\r\n}\r\n/* Custom HTML tooltip container */\r\n.yasgui-graph-tooltip-container {\r\n position: absolute;\r\n background-color: rgba(28, 28, 32, 0.95);\r\n color: #f0f0f0;\r\n border: 1px solid rgba(255, 255, 255, 0.12);\r\n border-radius: 6px;\r\n padding: 8px 10px;\r\n font-size: 11px;\r\n font-family: ui-monospace, 'SFMono-Regular', 'Menlo', 'Consolas', monospace;\r\n max-width: 340px;\r\n white-space: normal;\r\n box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);\r\n pointer-events: auto;\r\n z-index: 1000;\r\n user-select: text;\r\n cursor: text;\r\n}\r\n.yasgui-graph-tooltip {\r\n display: flex;\r\n flex-direction: column;\r\n gap: 3px;\r\n}\r\n.yasgui-tooltip-type {\r\n font-size: 9px;\r\n font-weight: 700;\r\n text-transform: uppercase;\r\n letter-spacing: 0.6px;\r\n color: rgba(255, 255, 255, 0.5);\r\n padding-bottom: 5px;\r\n border-bottom: 1px solid rgba(255, 255, 255, 0.12);\r\n margin-bottom: 3px;\r\n}\r\n.yasgui-tooltip-row {\r\n display: flex;\r\n gap: 8px;\r\n align-items: baseline;\r\n line-height: 1.5;\r\n}\r\n.yasgui-tooltip-key {\r\n font-size: 10px;\r\n font-weight: 600;\r\n color: rgba(255, 255, 255, 0.55);\r\n min-width: 58px;\r\n flex-shrink: 0;\r\n}\r\n.yasgui-tooltip-val {\r\n font-size: 11px;\r\n color: #e8e8e8;\r\n word-break: break-all;\r\n}\r\n/* Main entry point for all styles */\r\n/* This file will be imported by the TypeScript code */\r\n"],
5
+ "mappings": ";AACA;AAEE,sBAAoB;AACpB,0BAAwB;AACxB,6BAA2B;AAC3B,8BAA4B;AAG5B,uBAAqB,IAAI,qBAAqB,EAAE;AAChD,uBAAqB,IAAI,qBAAqB,EAAE;AAChD,6BAA2B,IAAI,uBAAuB,EAAE;AACxD,gCAA8B,IAAI,mBAAmB,EAAE,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;AAC3E,6BAA2B,IAAI,mBAAmB,EAAE;AAGpD,4BAA0B,IAAI,mBAAmB,EAAE;AACnD,4BAA0B,IAAI,qBAAqB,EAAE;AACrD,+BAA6B,IAAI,mBAAmB,EAAE;AACtD,8BAA4B,IAAI,oBAAoB,EAAE;AACtD,6BAA2B,IAAI,uBAAuB,EAAE;AACxD,6BAA2B;AAG3B,yBAAuB,EAAE,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AAG/C,sBAAoB;AACpB,mBAAiB;AACjB,oBAAkB;AAClB,eAAa;AAEb,2BAAyB;AACzB,wBAAsB;AACtB,yBAAuB;AACvB,oBAAkB;AAElB,cAAY;AACZ,aAAW;AAEX,gBAAc;AACd,eAAa;AACb,gBAAc;AAEd,uBAAqB;AACrB,6BAA2B;AAC3B,iBAAe;AAEf,gBAAc,EAAE,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AACxC;AAEA,CAAC;AACD,CAAC;AAEC,sBAAoB;AACpB,0BAAwB;AACxB,6BAA2B;AAC3B,8BAA4B;AAG5B,uBAAqB,IAAI,qBAAqB,EAAE;AAChD,uBAAqB,IAAI,qBAAqB,EAAE;AAChD,6BAA2B,IAAI,uBAAuB,EAAE;AACxD,gCAA8B,IAAI,qBAAqB,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;AAC1E,6BAA2B,IAAI,mBAAmB,EAAE;AACpD,4BAA0B,IAAI,mBAAmB,EAAE;AACnD,6BAA2B,IAAI,uBAAuB,EAAE;AAC1D;AAEA,CAAC;AACC,SAAO;AACP,UAAQ;AACR,YAAU;AACV,YAAU;AACZ;AACA,CANC,8BAM8B;AAC7B,oBAAkB,IAAI;AACxB;AACA,CAAC;AACC,WAAS;AACT,cAAY;AACZ,SAAO,IAAI;AACb;AACA,CAAC;AACC,WAAS;AACT,SAAO,IAAI;AACb;AAEA,CAAC;AACC,YAAU;AACV,OAAK;AACL,SAAO;AACP,WAAS;AACT,WAAS;AACT,OAAK;AACL,kBAAgB;AAClB;AAEA,CAAC;AACC,WAAS,IAAI;AACb,cAAY,IAAI;AAChB,SAAO,IAAI;AACX,UAAQ;AACR,iBAAe;AACf,UAAQ;AACR,aAAW;AACX,cAAY,IAAI;AAChB,cAAY,WAAW,KAAK;AAC9B;AACA,CAXC,mBAWmB;AAClB,cAAY,IAAI;AAClB;AACA,CAdC,mBAcmB;AAClB,aAAW,WAAW;AACxB;AAEA,CAAC;AACC,YAAU;AACV,OAAK;AACL,SAAO;AACP,WAAS;AACT,cAAY,IAAI,wBAAwB,EAAE;AAC1C,cAAY,IAAI,mBAAmB,EAAE;AACrC,SAAO,IAAI,mBAAmB,EAAE;AAChC,UAAQ,IAAI,MAAM,IAAI,qBAAqB,EAAE;AAC7C,iBAAe;AACf,WAAS,KAAK;AACd,aAAW;AACX,cAAY,IAAI,qBAAqB,EAAE,EAAE,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5D,aAAW;AACb;AACA,CAAC;AACC,eAAa;AACb,aAAW;AACX,iBAAe;AACf,kBAAgB;AAChB,iBAAe,IAAI,MAAM,IAAI,qBAAqB,EAAE;AACtD;AACA,CAAC;AACC,aAAW;AACX,eAAa;AACb,kBAAgB;AAChB,kBAAgB;AAChB,SAAO,IAAI,uBAAuB,EAAE;AACpC,UAAQ,KAAK,EAAE;AACjB;AACA,CAAC;AACC,WAAS;AACT,eAAa;AACb,mBAAiB;AACjB,OAAK;AACL,WAAS,IAAI;AACb,UAAQ;AACV;AACA,CARC,0BAQ0B,KAAK,CAAC;AAC/B,UAAQ;AACR,gBAAc,IAAI,qBAAqB,EAAE;AAC3C;AACA,CAAC;AACC,aAAW;AACX,WAAS,IAAI;AACb,UAAQ,IAAI,MAAM,IAAI,qBAAqB,EAAE;AAC7C,iBAAe;AACf,cAAY,IAAI,mBAAmB,EAAE;AACrC,SAAO,IAAI,qBAAqB,EAAE;AAClC,UAAQ;AACR,aAAW;AACb;AAEA,CAAC;AACC,WAAS;AACT,eAAa;AACb,OAAK;AACP;AACA,CAAC;AACC,WAAS;AACT,eAAa;AACb,mBAAiB;AACnB;AACA,CALC,kBAKkB;AACjB,SAAO;AACP,UAAQ;AACR,QAAM;AACR;AAEA,CApHC,8BAoH8B,CAAC;AAC9B,WAAS;AACX;AAEA,CAAC;AACC,YAAU;AACV,oBAAkB,KAAK,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE;AACnC,SAAO;AACP,UAAQ,IAAI,MAAM,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;AACtC,iBAAe;AACf,WAAS,IAAI;AACb,aAAW;AACX;AAAA,IAAa,YAAY;AAAA,IAAE,gBAAgB;AAAA,IAAE,OAAO;AAAA,IAAE,UAAU;AAAA,IAAE;AAClE,aAAW;AACX,eAAa;AACb,cAAY,EAAE,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AACrC,kBAAgB;AAChB,WAAS;AACT,eAAa;AACb,UAAQ;AACV;AACA,CAAC;AACC,WAAS;AACT,kBAAgB;AAChB,OAAK;AACP;AACA,CAAC;AACC,aAAW;AACX,eAAa;AACb,kBAAgB;AAChB,kBAAgB;AAChB,SAAO,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;AAC3B,kBAAgB;AAChB,iBAAe,IAAI,MAAM,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;AAC7C,iBAAe;AACjB;AACA,CAAC;AACC,WAAS;AACT,OAAK;AACL,eAAa;AACb,eAAa;AACf;AACA,CAAC;AACC,aAAW;AACX,eAAa;AACb,SAAO,KAAK,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE;AAC3B,aAAW;AACX,eAAa;AACf;AACA,CAAC;AACC,aAAW;AACX,SAAO;AACP,cAAY;AACd;",
6
6
  "names": []
7
7
  }