ontologyviewer 0.1.2 → 0.2.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.ja.md +10 -7
- package/README.md +10 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/locale.d.ts +3 -0
- package/dist/locale.d.ts.map +1 -1
- package/dist/meta.json +31 -12
- package/dist/ontologyviewer.css +45 -0
- package/dist/ontologyviewer.esm.min.mjs +57 -10
- package/dist/ontologyviewer.esm.min.mjs.map +4 -4
- package/dist/ontologyviewer.esm.mjs +130 -14
- package/dist/ontologyviewer.esm.mjs.map +4 -4
- package/dist/rdf/compactTriples.d.ts +58 -0
- package/dist/rdf/compactTriples.d.ts.map +1 -0
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/viewer.d.ts.map +1 -1
- package/package.json +1 -1
|
@@ -46094,6 +46094,72 @@ function isKnownVocabularyIri(iri) {
|
|
|
46094
46094
|
return KNOWN_VOCABULARY_NAMESPACES.some((ns) => iri.startsWith(ns));
|
|
46095
46095
|
}
|
|
46096
46096
|
|
|
46097
|
+
// src/rdf/compactTriples.ts
|
|
46098
|
+
function compactTriples(graph) {
|
|
46099
|
+
const hasOutgoing = /* @__PURE__ */ new Set();
|
|
46100
|
+
const hasIncoming = /* @__PURE__ */ new Set();
|
|
46101
|
+
for (const edge of graph.edges) {
|
|
46102
|
+
hasOutgoing.add(edge.source);
|
|
46103
|
+
hasIncoming.add(edge.target);
|
|
46104
|
+
}
|
|
46105
|
+
const byId = new Map(graph.nodes.map((node) => [node.id, node]));
|
|
46106
|
+
const foldedIds = /* @__PURE__ */ new Set();
|
|
46107
|
+
for (const node of graph.nodes) {
|
|
46108
|
+
if (hasOutgoing.has(node.id) || !hasIncoming.has(node.id)) {
|
|
46109
|
+
continue;
|
|
46110
|
+
}
|
|
46111
|
+
const isLeafAnnotation = node.kind === "literal" || !node.isBlankNode && isKnownVocabularyIri(node.id);
|
|
46112
|
+
if (isLeafAnnotation) {
|
|
46113
|
+
foldedIds.add(node.id);
|
|
46114
|
+
}
|
|
46115
|
+
}
|
|
46116
|
+
if (foldedIds.size === 0) {
|
|
46117
|
+
return {
|
|
46118
|
+
nodes: graph.nodes,
|
|
46119
|
+
edges: graph.edges,
|
|
46120
|
+
foldedFacts: /* @__PURE__ */ new Map(),
|
|
46121
|
+
removedNodeCount: 0,
|
|
46122
|
+
removedEdgeCount: 0
|
|
46123
|
+
};
|
|
46124
|
+
}
|
|
46125
|
+
const foldedFacts = /* @__PURE__ */ new Map();
|
|
46126
|
+
const edges3 = [];
|
|
46127
|
+
for (const edge of graph.edges) {
|
|
46128
|
+
if (!foldedIds.has(edge.target)) {
|
|
46129
|
+
edges3.push(edge);
|
|
46130
|
+
continue;
|
|
46131
|
+
}
|
|
46132
|
+
if (edge.predicate === RDFS_LABEL || edge.predicate === RDFS_COMMENT) {
|
|
46133
|
+
continue;
|
|
46134
|
+
}
|
|
46135
|
+
const fact = `${factPredicateLabel(edge.predicateLabel)}: ${factObjectLabel(byId.get(edge.target))}`;
|
|
46136
|
+
const existing = foldedFacts.get(edge.source);
|
|
46137
|
+
if (!existing) {
|
|
46138
|
+
foldedFacts.set(edge.source, [fact]);
|
|
46139
|
+
} else if (!existing.includes(fact)) {
|
|
46140
|
+
existing.push(fact);
|
|
46141
|
+
}
|
|
46142
|
+
}
|
|
46143
|
+
const nodes3 = graph.nodes.filter((node) => !foldedIds.has(node.id));
|
|
46144
|
+
return {
|
|
46145
|
+
nodes: nodes3,
|
|
46146
|
+
edges: edges3,
|
|
46147
|
+
foldedFacts,
|
|
46148
|
+
removedNodeCount: graph.nodes.length - nodes3.length,
|
|
46149
|
+
removedEdgeCount: graph.edges.length - edges3.length
|
|
46150
|
+
};
|
|
46151
|
+
}
|
|
46152
|
+
function factPredicateLabel(predicateLabel) {
|
|
46153
|
+
const colon = predicateLabel.indexOf(":");
|
|
46154
|
+
return colon >= 0 ? predicateLabel.slice(colon + 1) : predicateLabel;
|
|
46155
|
+
}
|
|
46156
|
+
function factObjectLabel(node) {
|
|
46157
|
+
if (!node) {
|
|
46158
|
+
return "";
|
|
46159
|
+
}
|
|
46160
|
+
return node.kind === "literal" ? node.literalValue ?? node.label : node.label;
|
|
46161
|
+
}
|
|
46162
|
+
|
|
46097
46163
|
// src/rdf/graphModel.ts
|
|
46098
46164
|
function buildGraphModel(quads) {
|
|
46099
46165
|
const nodes3 = /* @__PURE__ */ new Map();
|
|
@@ -46669,6 +46735,9 @@ function relativeLuminance(color) {
|
|
|
46669
46735
|
var EN = {
|
|
46670
46736
|
schemaView: "Schema",
|
|
46671
46737
|
triplesView: "Triples",
|
|
46738
|
+
compactTriples: "Compact",
|
|
46739
|
+
compactTriplesHint: "Fold labels, comments, and standard vocabulary terms into the nodes that reference them.",
|
|
46740
|
+
compactTriplesActiveHint: "Compact view is on. Click to show labels, comments, and vocabulary terms as separate nodes.",
|
|
46672
46741
|
searchPlaceholder: "Search classes, relations, properties\u2026",
|
|
46673
46742
|
noResults: "No results",
|
|
46674
46743
|
properties: "properties",
|
|
@@ -46699,6 +46768,9 @@ var EN = {
|
|
|
46699
46768
|
var JA = {
|
|
46700
46769
|
schemaView: "\u30B9\u30AD\u30FC\u30DE",
|
|
46701
46770
|
triplesView: "\u30C8\u30EA\u30D7\u30EB",
|
|
46771
|
+
compactTriples: "\u7C21\u7D04",
|
|
46772
|
+
compactTriplesHint: "\u30E9\u30D9\u30EB\u30FB\u30B3\u30E1\u30F3\u30C8\u30FB\u6A19\u6E96\u8A9E\u5F59\u306E\u7528\u8A9E\u3092\u3001\u305D\u308C\u3092\u53C2\u7167\u3057\u3066\u3044\u308B\u30CE\u30FC\u30C9\u306B\u7573\u307F\u8FBC\u307F\u307E\u3059\u3002",
|
|
46773
|
+
compactTriplesActiveHint: "\u7C21\u7D04\u8868\u793A\u304C\u6709\u52B9\u3067\u3059\u3002\u30AF\u30EA\u30C3\u30AF\u3059\u308B\u3068\u3001\u30E9\u30D9\u30EB\u30FB\u30B3\u30E1\u30F3\u30C8\u30FB\u8A9E\u5F59\u306E\u7528\u8A9E\u3092\u500B\u5225\u306E\u30CE\u30FC\u30C9\u3068\u3057\u3066\u8868\u793A\u3057\u307E\u3059\u3002",
|
|
46702
46774
|
searchPlaceholder: "\u30AF\u30E9\u30B9\u30FB\u95A2\u4FC2\u30FB\u30D7\u30ED\u30D1\u30C6\u30A3\u3092\u691C\u7D22\u2026",
|
|
46703
46775
|
noResults: "\u7D50\u679C\u306A\u3057",
|
|
46704
46776
|
properties: "\u30D7\u30ED\u30D1\u30C6\u30A3",
|
|
@@ -46894,6 +46966,7 @@ function createViewer(sourceElement, initialTurtle, options2, onDestroy) {
|
|
|
46894
46966
|
let graph = { nodes: [], edges: [] };
|
|
46895
46967
|
let currentView = options2.defaultView ?? "schema";
|
|
46896
46968
|
let currentLayout = options2.layout ?? "fcose";
|
|
46969
|
+
let compactTriplesEnabled = options2.compactTriples ?? true;
|
|
46897
46970
|
let dark = isDarkTheme(options2.theme ?? "auto");
|
|
46898
46971
|
let cy;
|
|
46899
46972
|
let destroyed2 = false;
|
|
@@ -46999,7 +47072,7 @@ function createViewer(sourceElement, initialTurtle, options2, onDestroy) {
|
|
|
46999
47072
|
destroyCy();
|
|
47000
47073
|
focusedId = void 0;
|
|
47001
47074
|
const view = effectiveView();
|
|
47002
|
-
const elements = view === "schema" ? schemaElements(schema) : graphElements(graph);
|
|
47075
|
+
const elements = view === "schema" ? schemaElements(schema) : graphElements(graph, compactTriplesEnabled);
|
|
47003
47076
|
cy = cytoscape2({
|
|
47004
47077
|
container: dom.graph,
|
|
47005
47078
|
elements,
|
|
@@ -47143,6 +47216,9 @@ function createViewer(sourceElement, initialTurtle, options2, onDestroy) {
|
|
|
47143
47216
|
dom.triplesButton.classList.toggle("active", currentView === "triples");
|
|
47144
47217
|
dom.schemaButton.setAttribute("aria-pressed", String(currentView === "schema"));
|
|
47145
47218
|
dom.triplesButton.setAttribute("aria-pressed", String(currentView === "triples"));
|
|
47219
|
+
dom.compactToggle.hidden = effectiveView() !== "triples";
|
|
47220
|
+
dom.compactCheckbox.checked = compactTriplesEnabled;
|
|
47221
|
+
dom.compactToggle.title = compactTriplesEnabled ? messages.compactTriplesActiveHint : messages.compactTriplesHint;
|
|
47146
47222
|
}
|
|
47147
47223
|
function updateStats() {
|
|
47148
47224
|
dom.stats.textContent = `${messages.entities}: ${schema.entities.length} \xB7 ${messages.relations}: ${schema.relations.length} \xB7 ${messages.triples}: ${graph.edges.length}`;
|
|
@@ -47261,6 +47337,12 @@ function createViewer(sourceElement, initialTurtle, options2, onDestroy) {
|
|
|
47261
47337
|
clearInspector();
|
|
47262
47338
|
renderGraph();
|
|
47263
47339
|
}, { signal });
|
|
47340
|
+
dom.compactCheckbox.addEventListener("change", () => {
|
|
47341
|
+
compactTriplesEnabled = dom.compactCheckbox.checked;
|
|
47342
|
+
updateViewButtons();
|
|
47343
|
+
clearInspector();
|
|
47344
|
+
renderGraph();
|
|
47345
|
+
}, { signal });
|
|
47264
47346
|
dom.search.addEventListener("input", performSearch, { signal });
|
|
47265
47347
|
dom.search.addEventListener("keydown", (event3) => {
|
|
47266
47348
|
if (event3.key !== "Escape") return;
|
|
@@ -47311,6 +47393,13 @@ function createDom(doc, root2, messages, options2) {
|
|
|
47311
47393
|
const schemaButton = button(doc, messages.schemaView, "ov-btn-schema");
|
|
47312
47394
|
const triplesButton = button(doc, messages.triplesView, "ov-btn-triples");
|
|
47313
47395
|
viewToggle.append(schemaButton, triplesButton);
|
|
47396
|
+
const compactToggle = element3(doc, "label", "ov-compact-toggle");
|
|
47397
|
+
const compactCheckbox = doc.createElement("input");
|
|
47398
|
+
compactCheckbox.type = "checkbox";
|
|
47399
|
+
compactCheckbox.className = "ov-compact-checkbox";
|
|
47400
|
+
const compactText = element3(doc, "span", "ov-compact-text");
|
|
47401
|
+
compactText.textContent = messages.compactTriples;
|
|
47402
|
+
compactToggle.append(compactCheckbox, compactText);
|
|
47314
47403
|
const search = doc.createElement("input");
|
|
47315
47404
|
search.type = "search";
|
|
47316
47405
|
search.className = "ov-search";
|
|
@@ -47336,7 +47425,7 @@ function createDom(doc, root2, messages, options2) {
|
|
|
47336
47425
|
button(doc, messages.layout, "ov-btn-layout", "\u21BB"),
|
|
47337
47426
|
button(doc, messages.exportPng, "ov-btn-export", "\u21E9")
|
|
47338
47427
|
);
|
|
47339
|
-
toolbar.append(viewToggle, search, layout4, controls);
|
|
47428
|
+
toolbar.append(viewToggle, compactToggle, search, layout4, controls);
|
|
47340
47429
|
const searchResults = element3(doc, "div", "ov-search-dropdown");
|
|
47341
47430
|
searchResults.setAttribute("role", "listbox");
|
|
47342
47431
|
searchResults.hidden = true;
|
|
@@ -47368,7 +47457,7 @@ function createDom(doc, root2, messages, options2) {
|
|
|
47368
47457
|
footer.append(stats, legend);
|
|
47369
47458
|
root2.append(toolbar, searchResults, body, footer);
|
|
47370
47459
|
const zoomLabelElement = controls.querySelector(".ov-btn-reset-zoom") ?? controls;
|
|
47371
|
-
return { toolbar, schemaButton, triplesButton, search, searchResults, layout: layout4, zoomLabel: zoomLabelElement, stage, graph, message, inspector, stats, legend };
|
|
47460
|
+
return { toolbar, schemaButton, triplesButton, compactToggle, compactCheckbox, search, searchResults, layout: layout4, zoomLabel: zoomLabelElement, stage, graph, message, inspector, stats, legend };
|
|
47372
47461
|
}
|
|
47373
47462
|
function schemaElements(schema) {
|
|
47374
47463
|
const nodes3 = schema.entities.map((entity) => {
|
|
@@ -47406,12 +47495,28 @@ function schemaElements(schema) {
|
|
|
47406
47495
|
}
|
|
47407
47496
|
return [...nodes3, ...edges3];
|
|
47408
47497
|
}
|
|
47409
|
-
function graphElements(graph) {
|
|
47498
|
+
function graphElements(graph, compact) {
|
|
47499
|
+
const folded = compact ? compactTriples(graph) : void 0;
|
|
47500
|
+
const nodes3 = folded?.nodes ?? graph.nodes;
|
|
47501
|
+
const edges3 = folded?.edges ?? graph.edges;
|
|
47410
47502
|
return [
|
|
47411
|
-
...
|
|
47412
|
-
|
|
47503
|
+
...nodes3.map((node) => ({
|
|
47504
|
+
data: {
|
|
47505
|
+
id: node.id,
|
|
47506
|
+
label: node.label,
|
|
47507
|
+
// `label` stays the bare name so search keeps matching it; the folded
|
|
47508
|
+
// form is a separate field used only by the stylesheet.
|
|
47509
|
+
tripleLabel: tripleLabelFor(node.label, folded?.foldedFacts.get(node.id)),
|
|
47510
|
+
kind: node.kind
|
|
47511
|
+
}
|
|
47512
|
+
})),
|
|
47513
|
+
...edges3.map((edge) => ({ data: { id: edge.id, source: edge.source, target: edge.target, edgeLabel: edge.predicateLabel } }))
|
|
47413
47514
|
];
|
|
47414
47515
|
}
|
|
47516
|
+
function tripleLabelFor(label, facts) {
|
|
47517
|
+
return facts && facts.length > 0 ? `${label}
|
|
47518
|
+
${facts.join("\n")}` : label;
|
|
47519
|
+
}
|
|
47415
47520
|
function schemaStyles(dark) {
|
|
47416
47521
|
const canvas = dark ? "#1e1e1e" : "#ffffff";
|
|
47417
47522
|
return [
|
|
@@ -47443,13 +47548,18 @@ function schemaStyles(dark) {
|
|
|
47443
47548
|
function triplesStyles(dark) {
|
|
47444
47549
|
return [
|
|
47445
47550
|
{ selector: "node", style: {
|
|
47446
|
-
|
|
47551
|
+
// `tripleLabel` carries the folded statements as extra lines, so the box
|
|
47552
|
+
// must wrap and size to its content — with the previous `ellipsis` wrap
|
|
47553
|
+
// and fixed 154x54 box they were silently clipped away.
|
|
47554
|
+
label: "data(tripleLabel)",
|
|
47447
47555
|
"text-valign": "center",
|
|
47448
47556
|
"text-halign": "center",
|
|
47449
|
-
"text-wrap": "
|
|
47450
|
-
"text-max-width": "
|
|
47451
|
-
width:
|
|
47452
|
-
height:
|
|
47557
|
+
"text-wrap": "wrap",
|
|
47558
|
+
"text-max-width": "150px",
|
|
47559
|
+
width: "label",
|
|
47560
|
+
height: "label",
|
|
47561
|
+
padding: "10px",
|
|
47562
|
+
"min-width": "120px",
|
|
47453
47563
|
shape: "round-rectangle",
|
|
47454
47564
|
"font-size": 11,
|
|
47455
47565
|
"border-width": 1.5,
|
|
@@ -47460,8 +47570,6 @@ function triplesStyles(dark) {
|
|
|
47460
47570
|
{ selector: "node[kind = 'class']", style: { "background-color": dark ? "#18324b" : "#dbeafe", "border-color": "#3b82f6" } },
|
|
47461
47571
|
{ selector: "node[kind = 'property']", style: { "background-color": dark ? "#3b1f3b" : "#fce7f3", "border-color": "#a855f7" } },
|
|
47462
47572
|
{ selector: "node[kind = 'literal']", style: {
|
|
47463
|
-
width: 138,
|
|
47464
|
-
height: 44,
|
|
47465
47573
|
"font-size": 10,
|
|
47466
47574
|
"border-style": "dashed",
|
|
47467
47575
|
"background-color": dark ? "#38331f" : "#fef9c3",
|
|
@@ -47676,6 +47784,13 @@ function matchingElements(root2, selector) {
|
|
|
47676
47784
|
matches33.push(...root2.querySelectorAll(selector));
|
|
47677
47785
|
return matches33;
|
|
47678
47786
|
}
|
|
47787
|
+
function parseBoolean(value) {
|
|
47788
|
+
if (value === void 0) return void 0;
|
|
47789
|
+
const normalized = value.trim().toLowerCase();
|
|
47790
|
+
if (normalized === "false" || normalized === "0" || normalized === "off") return false;
|
|
47791
|
+
if (normalized === "" || normalized === "true" || normalized === "1" || normalized === "on") return true;
|
|
47792
|
+
return void 0;
|
|
47793
|
+
}
|
|
47679
47794
|
function resolveOptions(element4, options2) {
|
|
47680
47795
|
const data4 = element4.dataset;
|
|
47681
47796
|
const optionBaseIri = options2.baseIri ?? options2.baseIRI;
|
|
@@ -47685,6 +47800,7 @@ function resolveOptions(element4, options2) {
|
|
|
47685
47800
|
locale: validLocale(options2.locale) ?? validLocale(data4.locale) ?? "auto",
|
|
47686
47801
|
layout: validLayout(options2.layout) ?? validLayout(data4.layout) ?? "fcose",
|
|
47687
47802
|
defaultView: validView(options2.defaultView) ?? validView(data4.defaultView) ?? "schema",
|
|
47803
|
+
compactTriples: options2.compactTriples ?? parseBoolean(data4.compactTriples) ?? true,
|
|
47688
47804
|
baseIri: safeBaseIri(optionBaseIri ?? data4.baseIri, element4.ownerDocument.baseURI),
|
|
47689
47805
|
storageKey: safeStorageKey(options2.storageKey ?? data4.storageKey),
|
|
47690
47806
|
injectStyles: options2.injectStyles,
|
|
@@ -47698,7 +47814,7 @@ function injectDefaultStyles(doc) {
|
|
|
47698
47814
|
styledDocuments.add(doc);
|
|
47699
47815
|
return;
|
|
47700
47816
|
}
|
|
47701
|
-
const css = true ? '/* ontologyviewer.css \u2014 all selectors are scoped to the generated root. */\n.ontologyviewer-root {\n --ov-bg: #fff;\n --ov-fg: #1f2937;\n --ov-muted: #64748b;\n --ov-border: #d7dde5;\n --ov-toolbar-bg: #f8fafc;\n --ov-input-bg: #fff;\n --ov-hover: #eef2f7;\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 600px;\n min-height: 320px;\n overflow: hidden;\n border: 1px solid var(--ov-border);\n border-radius: 10px;\n color: var(--ov-fg);\n background: var(--ov-bg);\n font: 14px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;\n container-type: inline-size;\n box-sizing: border-box;\n}\n.ontologyviewer-root *, .ontologyviewer-root *::before, .ontologyviewer-root *::after { box-sizing: border-box; }\n.ontologyviewer-root [hidden] { display: none !important; }\n.ontologyviewer-root.ov-dark {\n --ov-bg: #1e1e1e;\n --ov-fg: #d4d4d4;\n --ov-muted: #a8a8a8;\n --ov-border: #454545;\n --ov-toolbar-bg: #252526;\n --ov-input-bg: #313131;\n --ov-hover: #2a2d2e;\n}\n.ontologyviewer-root button,\n.ontologyviewer-root input,\n.ontologyviewer-root select { font: inherit; }\n.ontologyviewer-root button:focus-visible,\n.ontologyviewer-root input:focus-visible,\n.ontologyviewer-root select:focus-visible,\n.ontologyviewer-root summary:focus-visible { outline: 2px solid #1685d1; outline-offset: 2px; }\n.ontologyviewer-root .ov-toolbar {\n z-index: 5;\n display: flex;\n flex: 0 0 auto;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n border-bottom: 1px solid var(--ov-border);\n background: var(--ov-toolbar-bg);\n}\n.ontologyviewer-root .ov-view-toggle,\n.ontologyviewer-root .ov-controls { display: flex; align-items: center; gap: 4px; }\n.ontologyviewer-root .ov-view-toggle button,\n.ontologyviewer-root .ov-controls button,\n.ontologyviewer-root .ov-layout-select,\n.ontologyviewer-root .ov-inspector-close {\n min-height: 32px;\n padding: 4px 9px;\n border: 1px solid var(--ov-border);\n border-radius: 6px;\n color: var(--ov-fg);\n background: var(--ov-bg);\n cursor: pointer;\n}\n.ontologyviewer-root button:hover,\n.ontologyviewer-root .ov-layout-select:hover { background: var(--ov-hover); }\n.ontologyviewer-root .ov-view-toggle button.active {\n border-color: #0878bd;\n color: #fff;\n background: #0878bd;\n}\n.ontologyviewer-root .ov-search {\n flex: 1 1 250px;\n min-width: 130px;\n height: 34px;\n padding: 5px 9px;\n border: 1px solid var(--ov-border);\n border-radius: 7px;\n color: var(--ov-fg);\n background: var(--ov-input-bg);\n}\n.ontologyviewer-root .ov-layout-select { height: 34px; }\n.ontologyviewer-root .ov-body { display: flex; flex: 1 1 auto; min-height: 0; }\n.ontologyviewer-root .ov-stage { position: relative; flex: 1 1 auto; min-width: 0; min-height: 260px; }\n/* Cytoscape forces its container to position: relative; explicit dimensions prevent a zero-height graph. */\n.ontologyviewer-root .ov-graph { position: absolute; inset: 0; width: 100%; height: 100%; }\n.ontologyviewer-root .ov-message {\n position: absolute;\n inset: 0;\n display: grid;\n place-items: center;\n padding: 24px;\n text-align: center;\n}\n.ontologyviewer-root .ov-error { color: #b42318; background: #fff5f4; }\n.ontologyviewer-root.ov-dark .ov-error { color: #ff8a80; background: #2e1b1a; }\n.ontologyviewer-root .ov-inspector {\n position: relative;\n flex: 0 0 300px;\n width: 300px;\n overflow: auto;\n padding: 14px;\n border-left: 1px solid var(--ov-border);\n background: var(--ov-bg);\n}\n.ontologyviewer-root .ov-inspector-close {\n position: absolute;\n top: 6px;\n right: 6px;\n display: none;\n min-width: 30px;\n padding: 2px 7px;\n font-size: 20px;\n}\n.ontologyviewer-root .ov-inspector h3 { margin: 0 30px 8px 0; font-size: 16px; }\n.ontologyviewer-root .ov-inspector h4 { margin: 14px 0 5px; font-size: 13px; }\n.ontologyviewer-root .ov-inspector p { overflow-wrap: anywhere; }\n.ontologyviewer-root .ov-inspector dl {\n display: grid;\n grid-template-columns: max-content minmax(0, 1fr);\n gap: 4px 10px;\n margin: 10px 0;\n}\n.ontologyviewer-root .ov-inspector dt { font-weight: 600; }\n.ontologyviewer-root .ov-inspector dd { margin: 0; overflow-wrap: anywhere; }\n.ontologyviewer-root .ov-inspector ul { margin: 5px 0; padding-left: 20px; }\n.ontologyviewer-root .ov-inspector-empty { color: var(--ov-muted); text-align: center; }\n.ontologyviewer-root .ov-inspector-desc { color: var(--ov-muted); }\n.ontologyviewer-root .ov-prop-list { list-style: none; padding: 0 !important; }\n.ontologyviewer-root .ov-prop-list li { padding: 3px 0; border-bottom: 1px solid var(--ov-border); }\n.ontologyviewer-root .ov-footer {\n display: flex;\n flex: 0 0 auto;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 5px 10px;\n border-top: 1px solid var(--ov-border);\n color: var(--ov-muted);\n font-size: 12px;\n}\n.ontologyviewer-root .ov-legend summary { cursor: pointer; }\n.ontologyviewer-root .ov-legend-content { display: flex; gap: 12px; padding-top: 5px; }\n.ontologyviewer-root .ov-legend-item::before {\n display: inline-block;\n width: 18px;\n margin-right: 5px;\n border-top: 3px solid #64748b;\n content: "";\n vertical-align: middle;\n}\n.ontologyviewer-root .ov-subclass::before { border-color: #b180d7; }\n.ontologyviewer-root .ov-broader::before { border-color: #16875c; }\n.ontologyviewer-root .ov-inferred::before { border-top-style: dashed; }\n.ontologyviewer-root .ov-search-dropdown {\n position: absolute;\n z-index: 20;\n top: 51px;\n left: 120px;\n width: min(520px, calc(100% - 240px));\n max-height: 260px;\n overflow: auto;\n padding: 5px;\n border: 1px solid var(--ov-border);\n border-radius: 8px;\n background: var(--ov-bg);\n box-shadow: 0 10px 30px rgb(0 0 0 / 20%);\n}\n.ontologyviewer-root .ov-search-item {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n width: 100%;\n padding: 8px;\n border: 0;\n border-radius: 5px;\n color: var(--ov-fg);\n background: transparent;\n text-align: left;\n cursor: pointer;\n}\n.ontologyviewer-root .ov-search-meta { color: var(--ov-muted); font-size: 11px; }\n.ontologyviewer-root .ov-search-empty { margin: 0; padding: 10px; color: var(--ov-muted); }\n\n@container (max-width: 759px) {\n .ontologyviewer-root .ov-toolbar { flex-wrap: wrap; }\n .ontologyviewer-root .ov-search { order: 3; flex-basis: 100%; }\n .ontologyviewer-root .ov-body { display: block; position: relative; }\n .ontologyviewer-root .ov-stage { height: 100%; }\n .ontologyviewer-root .ov-inspector {\n position: absolute;\n z-index: 10;\n right: 0;\n bottom: 0;\n left: 0;\n width: auto;\n max-height: 52%;\n border-top: 1px solid var(--ov-border);\n border-left: 0;\n box-shadow: 0 -8px 24px rgb(0 0 0 / 22%);\n }\n .ontologyviewer-root .ov-inspector-close { display: block; }\n .ontologyviewer-root .ov-search-dropdown { top: 92px; left: 10px; width: calc(100% - 20px); }\n .ontologyviewer-root .ov-footer { align-items: flex-start; }\n}\n\n/* Cytoscape normally injects this fixed rule as an inline style. Keeping it in\n the external bundle lets strict-CSP users avoid that injection. */\n.ontologyviewer-root .__________cytoscape_container { position: relative; }\n' : "";
|
|
47817
|
+
const css = true ? '/* ontologyviewer.css \u2014 all selectors are scoped to the generated root. */\n.ontologyviewer-root {\n --ov-bg: #fff;\n --ov-fg: #1f2937;\n --ov-muted: #64748b;\n --ov-border: #d7dde5;\n --ov-toolbar-bg: #f8fafc;\n --ov-input-bg: #fff;\n --ov-hover: #eef2f7;\n position: relative;\n display: flex;\n flex-direction: column;\n width: 100%;\n height: 600px;\n min-height: 320px;\n overflow: hidden;\n border: 1px solid var(--ov-border);\n border-radius: 10px;\n color: var(--ov-fg);\n background: var(--ov-bg);\n font: 14px/1.45 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;\n container-type: inline-size;\n box-sizing: border-box;\n}\n.ontologyviewer-root *, .ontologyviewer-root *::before, .ontologyviewer-root *::after { box-sizing: border-box; }\n.ontologyviewer-root [hidden] { display: none !important; }\n.ontologyviewer-root.ov-dark {\n --ov-bg: #1e1e1e;\n --ov-fg: #d4d4d4;\n --ov-muted: #a8a8a8;\n --ov-border: #454545;\n --ov-toolbar-bg: #252526;\n --ov-input-bg: #313131;\n --ov-hover: #2a2d2e;\n}\n.ontologyviewer-root button,\n.ontologyviewer-root input,\n.ontologyviewer-root select { font: inherit; }\n.ontologyviewer-root button:focus-visible,\n.ontologyviewer-root input:focus-visible,\n.ontologyviewer-root select:focus-visible,\n.ontologyviewer-root summary:focus-visible { outline: 2px solid #1685d1; outline-offset: 2px; }\n.ontologyviewer-root .ov-toolbar {\n z-index: 5;\n display: flex;\n flex: 0 0 auto;\n align-items: center;\n gap: 8px;\n padding: 8px 10px;\n border-bottom: 1px solid var(--ov-border);\n background: var(--ov-toolbar-bg);\n}\n.ontologyviewer-root .ov-view-toggle,\n.ontologyviewer-root .ov-controls { display: flex; align-items: center; gap: 4px; }\n.ontologyviewer-root .ov-view-toggle button,\n.ontologyviewer-root .ov-controls button,\n.ontologyviewer-root .ov-layout-select,\n.ontologyviewer-root .ov-inspector-close {\n min-height: 32px;\n padding: 4px 9px;\n border: 1px solid var(--ov-border);\n border-radius: 6px;\n color: var(--ov-fg);\n background: var(--ov-bg);\n cursor: pointer;\n}\n.ontologyviewer-root button:hover,\n.ontologyviewer-root .ov-layout-select:hover { background: var(--ov-hover); }\n.ontologyviewer-root .ov-view-toggle button.active {\n border-color: #0878bd;\n color: #fff;\n background: #0878bd;\n}\n/* Compaction toggle. A checkbox rather than a pressed button, because\n schema/triples is an exclusive selection while this is an independent on/off\n \u2014 and a checkbox shows its state without depending on colour. Styled as a\n toolbar chip so it sits at the same height as the buttons beside it. */\n.ontologyviewer-root .ov-compact-toggle {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n min-height: 32px;\n padding: 4px 10px 4px 8px;\n border: 1px solid var(--ov-border);\n border-radius: 6px;\n color: var(--ov-fg);\n background: var(--ov-bg);\n cursor: pointer;\n user-select: none;\n white-space: nowrap;\n}\n.ontologyviewer-root .ov-compact-toggle:hover { background: var(--ov-hover); }\n.ontologyviewer-root .ov-compact-toggle[hidden] { display: none; }\n.ontologyviewer-root .ov-compact-checkbox {\n width: 14px;\n height: 14px;\n margin: 0;\n accent-color: #0878bd;\n cursor: pointer;\n}\n/* Keyboard focus lands on the input, so raise the ring to the whole chip.\n Scoped to :focus-visible so a mouse click does not leave a blue ring behind\n that reads as "still enabled" on an unchecked control. */\n.ontologyviewer-root .ov-compact-toggle:has(.ov-compact-checkbox:focus-visible) {\n outline: 2px solid #0878bd;\n outline-offset: 1px;\n}\n/* Checked state also shifts the chip itself, so the setting reads at a glance\n from across the toolbar rather than only from the 14px box. */\n.ontologyviewer-root .ov-compact-toggle:has(.ov-compact-checkbox:checked) {\n border-color: #0878bd;\n color: #0878bd;\n font-weight: 600;\n}\n.ontologyviewer-root.ov-dark .ov-compact-toggle:has(.ov-compact-checkbox:checked) {\n border-color: #4aa3dd;\n color: #7dc4f0;\n}\n.ontologyviewer-root .ov-search {\n flex: 1 1 250px;\n min-width: 130px;\n height: 34px;\n padding: 5px 9px;\n border: 1px solid var(--ov-border);\n border-radius: 7px;\n color: var(--ov-fg);\n background: var(--ov-input-bg);\n}\n.ontologyviewer-root .ov-layout-select { height: 34px; }\n.ontologyviewer-root .ov-body { display: flex; flex: 1 1 auto; min-height: 0; }\n.ontologyviewer-root .ov-stage { position: relative; flex: 1 1 auto; min-width: 0; min-height: 260px; }\n/* Cytoscape forces its container to position: relative; explicit dimensions prevent a zero-height graph. */\n.ontologyviewer-root .ov-graph { position: absolute; inset: 0; width: 100%; height: 100%; }\n.ontologyviewer-root .ov-message {\n position: absolute;\n inset: 0;\n display: grid;\n place-items: center;\n padding: 24px;\n text-align: center;\n}\n.ontologyviewer-root .ov-error { color: #b42318; background: #fff5f4; }\n.ontologyviewer-root.ov-dark .ov-error { color: #ff8a80; background: #2e1b1a; }\n.ontologyviewer-root .ov-inspector {\n position: relative;\n flex: 0 0 300px;\n width: 300px;\n overflow: auto;\n padding: 14px;\n border-left: 1px solid var(--ov-border);\n background: var(--ov-bg);\n}\n.ontologyviewer-root .ov-inspector-close {\n position: absolute;\n top: 6px;\n right: 6px;\n display: none;\n min-width: 30px;\n padding: 2px 7px;\n font-size: 20px;\n}\n.ontologyviewer-root .ov-inspector h3 { margin: 0 30px 8px 0; font-size: 16px; }\n.ontologyviewer-root .ov-inspector h4 { margin: 14px 0 5px; font-size: 13px; }\n.ontologyviewer-root .ov-inspector p { overflow-wrap: anywhere; }\n.ontologyviewer-root .ov-inspector dl {\n display: grid;\n grid-template-columns: max-content minmax(0, 1fr);\n gap: 4px 10px;\n margin: 10px 0;\n}\n.ontologyviewer-root .ov-inspector dt { font-weight: 600; }\n.ontologyviewer-root .ov-inspector dd { margin: 0; overflow-wrap: anywhere; }\n.ontologyviewer-root .ov-inspector ul { margin: 5px 0; padding-left: 20px; }\n.ontologyviewer-root .ov-inspector-empty { color: var(--ov-muted); text-align: center; }\n.ontologyviewer-root .ov-inspector-desc { color: var(--ov-muted); }\n.ontologyviewer-root .ov-prop-list { list-style: none; padding: 0 !important; }\n.ontologyviewer-root .ov-prop-list li { padding: 3px 0; border-bottom: 1px solid var(--ov-border); }\n.ontologyviewer-root .ov-footer {\n display: flex;\n flex: 0 0 auto;\n align-items: center;\n justify-content: space-between;\n gap: 12px;\n padding: 5px 10px;\n border-top: 1px solid var(--ov-border);\n color: var(--ov-muted);\n font-size: 12px;\n}\n.ontologyviewer-root .ov-legend summary { cursor: pointer; }\n.ontologyviewer-root .ov-legend-content { display: flex; gap: 12px; padding-top: 5px; }\n.ontologyviewer-root .ov-legend-item::before {\n display: inline-block;\n width: 18px;\n margin-right: 5px;\n border-top: 3px solid #64748b;\n content: "";\n vertical-align: middle;\n}\n.ontologyviewer-root .ov-subclass::before { border-color: #b180d7; }\n.ontologyviewer-root .ov-broader::before { border-color: #16875c; }\n.ontologyviewer-root .ov-inferred::before { border-top-style: dashed; }\n.ontologyviewer-root .ov-search-dropdown {\n position: absolute;\n z-index: 20;\n top: 51px;\n left: 120px;\n width: min(520px, calc(100% - 240px));\n max-height: 260px;\n overflow: auto;\n padding: 5px;\n border: 1px solid var(--ov-border);\n border-radius: 8px;\n background: var(--ov-bg);\n box-shadow: 0 10px 30px rgb(0 0 0 / 20%);\n}\n.ontologyviewer-root .ov-search-item {\n display: flex;\n justify-content: space-between;\n gap: 12px;\n width: 100%;\n padding: 8px;\n border: 0;\n border-radius: 5px;\n color: var(--ov-fg);\n background: transparent;\n text-align: left;\n cursor: pointer;\n}\n.ontologyviewer-root .ov-search-meta { color: var(--ov-muted); font-size: 11px; }\n.ontologyviewer-root .ov-search-empty { margin: 0; padding: 10px; color: var(--ov-muted); }\n\n@container (max-width: 759px) {\n .ontologyviewer-root .ov-toolbar { flex-wrap: wrap; }\n .ontologyviewer-root .ov-search { order: 3; flex-basis: 100%; }\n .ontologyviewer-root .ov-body { display: block; position: relative; }\n .ontologyviewer-root .ov-stage { height: 100%; }\n .ontologyviewer-root .ov-inspector {\n position: absolute;\n z-index: 10;\n right: 0;\n bottom: 0;\n left: 0;\n width: auto;\n max-height: 52%;\n border-top: 1px solid var(--ov-border);\n border-left: 0;\n box-shadow: 0 -8px 24px rgb(0 0 0 / 22%);\n }\n .ontologyviewer-root .ov-inspector-close { display: block; }\n .ontologyviewer-root .ov-search-dropdown { top: 92px; left: 10px; width: calc(100% - 20px); }\n .ontologyviewer-root .ov-footer { align-items: flex-start; }\n}\n\n/* Cytoscape normally injects this fixed rule as an inline style. Keeping it in\n the external bundle lets strict-CSP users avoid that injection. */\n.ontologyviewer-root .__________cytoscape_container { position: relative; }\n' : "";
|
|
47702
47818
|
if (!css) return;
|
|
47703
47819
|
const style3 = doc.createElement("style");
|
|
47704
47820
|
style3.setAttribute("data-ontologyviewer-styles", "");
|