@yuneta/gobj-ui 7.2.4 → 7.3.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 +9 -0
- package/dist/gobj-ui.cjs.js +93 -28
- package/dist/gobj-ui.es.js +93 -28
- package/package.json +1 -1
- package/src/c_g6_nodes_tree.js +106 -43
- package/src/c_yui_treedb_graph.js +22 -6
- package/src/c_yui_treedb_topic_with_form.js +26 -8
package/README.md
CHANGED
|
@@ -582,6 +582,15 @@ Two details that are not decoration:
|
|
|
582
582
|
The find and the topic focus **share the highlight**: starting one clears the
|
|
583
583
|
other. Two amber sets at once would say nothing about either.
|
|
584
584
|
|
|
585
|
+
The highlight is painted **into the card's own html**, not with G6's `active`
|
|
586
|
+
element state. That state is an amber `stroke` + `halo`, both properties of a
|
|
587
|
+
node's KEY SHAPE — and every node here is an `html` node, whose key shape is a
|
|
588
|
+
DOM element. There was nothing for either property to paint on, so the amber
|
|
589
|
+
had never appeared, for the topic focus either. Only the cards whose state
|
|
590
|
+
changes are repainted, and a theme switch carries the highlight across (it
|
|
591
|
+
rebuilds every card, and rebuilding them without it would clear what is on
|
|
592
|
+
screen).
|
|
593
|
+
|
|
585
594
|
Wiring: the box sends `EV_FIND_NODES {text}` to the view, which forwards it to
|
|
586
595
|
`C_G6_NODES_TREE`; the graph answers `EV_FIND_RESULT {term, matches}`, which the
|
|
587
596
|
view declares like every other event its child publishes.
|
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -16954,11 +16954,12 @@ function create_tabulator(gobj) {
|
|
|
16954
16954
|
}
|
|
16955
16955
|
let tabulator = new tabulator_tables.TabulatorFull($table_el, Object.assign({}, tabulator_settings, yui_tabulator_lang(i18next.t), { placeholder: (0, i18next.t)("no data available", { defaultValue: "No data available" }) }));
|
|
16956
16956
|
if (with_checkbox) $table_el.classList.add("yui-no-row-hover");
|
|
16957
|
-
function update_rowcount() {
|
|
16957
|
+
function update_rowcount(explicit_count) {
|
|
16958
16958
|
let $rc = tabulator.element && tabulator.element.querySelector(".yui-tabulator-rowcount");
|
|
16959
16959
|
if (!$rc) return;
|
|
16960
16960
|
let n = 0;
|
|
16961
|
-
|
|
16961
|
+
if (typeof explicit_count === "number") n = explicit_count;
|
|
16962
|
+
else try {
|
|
16962
16963
|
n = tabulator.getDataCount("active");
|
|
16963
16964
|
} catch (e) {
|
|
16964
16965
|
n = 0;
|
|
@@ -16966,8 +16967,8 @@ function create_tabulator(gobj) {
|
|
|
16966
16967
|
$rc.textContent = `${n} ${(0, i18next.t)("rows")}`;
|
|
16967
16968
|
let single_page = true;
|
|
16968
16969
|
try {
|
|
16969
|
-
let
|
|
16970
|
-
single_page =
|
|
16970
|
+
let size = tabulator.getPageSize();
|
|
16971
|
+
single_page = !size || n <= size;
|
|
16971
16972
|
} catch (e) {
|
|
16972
16973
|
single_page = true;
|
|
16973
16974
|
}
|
|
@@ -16984,7 +16985,9 @@ function create_tabulator(gobj) {
|
|
|
16984
16985
|
});
|
|
16985
16986
|
tabulator.on("dataProcessed", update_rowcount);
|
|
16986
16987
|
tabulator.on("dataChanged", update_rowcount);
|
|
16987
|
-
tabulator.on("dataFiltered",
|
|
16988
|
+
tabulator.on("dataFiltered", function(filters, rows) {
|
|
16989
|
+
update_rowcount(Array.isArray(rows) ? rows.length : void 0);
|
|
16990
|
+
});
|
|
16988
16991
|
tabulator.on("rowSelected", function(row) {
|
|
16989
16992
|
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_SELECT_ROWS", { rows: [row.getData()] }, gobj);
|
|
16990
16993
|
});
|
|
@@ -18591,6 +18594,7 @@ var PRIVATE_DATA$4 = {
|
|
|
18591
18594
|
topics: [],
|
|
18592
18595
|
records: {},
|
|
18593
18596
|
gobj_nodes_tree: null,
|
|
18597
|
+
find_timer: null,
|
|
18594
18598
|
gobj_treedb_tables: null,
|
|
18595
18599
|
hook_data_viewer: null,
|
|
18596
18600
|
json_gobj: null,
|
|
@@ -18665,6 +18669,11 @@ function mt_stop$4(gobj) {
|
|
|
18665
18669
|
* Framework Method: Destroy
|
|
18666
18670
|
***************************************************************/
|
|
18667
18671
|
function mt_destroy$4(gobj) {
|
|
18672
|
+
let priv = gobj.priv;
|
|
18673
|
+
if (priv.find_timer) {
|
|
18674
|
+
clearTimeout(priv.find_timer);
|
|
18675
|
+
priv.find_timer = null;
|
|
18676
|
+
}
|
|
18668
18677
|
destroy_ui$1(gobj);
|
|
18669
18678
|
}
|
|
18670
18679
|
/***************************
|
|
@@ -18771,7 +18780,7 @@ function destroy_ui$1(gobj) {
|
|
|
18771
18780
|
*
|
|
18772
18781
|
************************************************************/
|
|
18773
18782
|
function make_toolbar(gobj) {
|
|
18774
|
-
gobj.priv;
|
|
18783
|
+
let priv = gobj.priv;
|
|
18775
18784
|
let modes = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "operation_modes");
|
|
18776
18785
|
if ((0, _yuneta_gobj_js.gobj_read_bool_attr)(gobj, "readonly")) modes = modes.filter((mode) => mode !== "edition");
|
|
18777
18786
|
let left_items = [
|
|
@@ -18880,7 +18889,12 @@ function make_toolbar(gobj) {
|
|
|
18880
18889
|
]],
|
|
18881
18890
|
{ input: (evt) => {
|
|
18882
18891
|
evt.stopPropagation();
|
|
18883
|
-
|
|
18892
|
+
let text = evt.target.value.trim();
|
|
18893
|
+
if (priv.find_timer) clearTimeout(priv.find_timer);
|
|
18894
|
+
priv.find_timer = setTimeout(function() {
|
|
18895
|
+
priv.find_timer = null;
|
|
18896
|
+
(0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_FIND_NODES", { text }, gobj);
|
|
18897
|
+
}, 250);
|
|
18884
18898
|
} }
|
|
18885
18899
|
], [
|
|
18886
18900
|
"div",
|
|
@@ -52639,6 +52653,8 @@ ensure_drag_canvas_patch();
|
|
|
52639
52653
|
* Constants
|
|
52640
52654
|
***************************************************************/
|
|
52641
52655
|
var GCLASS_NAME$1 = "C_G6_NODES_TREE";
|
|
52656
|
+
var HIGHLIGHT_COLOR = "#f0a020";
|
|
52657
|
+
var HIGHLIGHT_HALO = "rgba(240,160,32,0.35)";
|
|
52642
52658
|
/***************************************************************
|
|
52643
52659
|
* Internal layout and operation mode definitions
|
|
52644
52660
|
***************************************************************/
|
|
@@ -53915,10 +53931,12 @@ function graph_focus_topic(gobj, topic) {
|
|
|
53915
53931
|
if (ids.length === 0) (0, _yuneta_gobj_js.log_warning)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: focus topic '${topic}' has no nodes`);
|
|
53916
53932
|
for (let id of ids) states[id] = ["active"];
|
|
53917
53933
|
}
|
|
53934
|
+
let prev_ids = priv._focus_ids || [];
|
|
53918
53935
|
priv._focus_ids = ids;
|
|
53919
53936
|
priv._focus_topic = topic || null;
|
|
53920
53937
|
try {
|
|
53921
53938
|
if (typeof graph.setElementState === "function") graph.setElementState(states);
|
|
53939
|
+
apply_node_highlight(gobj, prev_ids, ids);
|
|
53922
53940
|
if (ids.length && typeof graph.focusElement === "function") graph.focusElement(ids);
|
|
53923
53941
|
} catch (e) {
|
|
53924
53942
|
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: focus topic apply failed: ${e}`);
|
|
@@ -53975,10 +53993,12 @@ function graph_find_nodes(gobj, term) {
|
|
|
53975
53993
|
}
|
|
53976
53994
|
for (let id of ids) states[id] = ["active"];
|
|
53977
53995
|
}
|
|
53996
|
+
let prev_ids = priv._focus_ids || [];
|
|
53978
53997
|
priv._focus_ids = ids;
|
|
53979
53998
|
priv._focus_topic = null;
|
|
53980
53999
|
try {
|
|
53981
54000
|
if (typeof graph.setElementState === "function") graph.setElementState(states);
|
|
54001
|
+
apply_node_highlight(gobj, prev_ids, ids);
|
|
53982
54002
|
if (ids.length && typeof graph.focusElement === "function") graph.focusElement(ids);
|
|
53983
54003
|
} catch (e) {
|
|
53984
54004
|
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: find apply failed: ${e}`);
|
|
@@ -55522,27 +55542,66 @@ function show_node_detail_popover(gobj, node_id) {
|
|
|
55522
55542
|
* not re-themed by setTheme()) are regenerated; structural
|
|
55523
55543
|
* junction diamonds get their neutral fill/stroke re-themed.
|
|
55524
55544
|
************************************************************/
|
|
55545
|
+
/************************************************************
|
|
55546
|
+
* The innerHTML of ONE node, in the given theme and highlight state.
|
|
55547
|
+
* The three treedb tiers (hierarchical / extended / child) each have
|
|
55548
|
+
* their own card, and both the theme refresh and the highlight need the
|
|
55549
|
+
* same three-way choice — it lived inline in the theme refresh and is
|
|
55550
|
+
* shared now. Returns null for a node that carries no desc.
|
|
55551
|
+
************************************************************/
|
|
55552
|
+
function node_innerHTML_of(nd, theme, highlight) {
|
|
55553
|
+
if (!nd || !nd.data || !nd.data.desc) return null;
|
|
55554
|
+
let desc = nd.data.desc;
|
|
55555
|
+
let record = nd.data.record || {};
|
|
55556
|
+
let label = node_label(desc, record);
|
|
55557
|
+
switch (desc.node_treedb_type) {
|
|
55558
|
+
case "child": return build_chip_innerHTML(desc.color, theme, record.icon, label, record.id, highlight);
|
|
55559
|
+
case "extended": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, true, record.id, highlight);
|
|
55560
|
+
case "hierarchical": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, false, record.id, highlight);
|
|
55561
|
+
}
|
|
55562
|
+
return null;
|
|
55563
|
+
}
|
|
55564
|
+
/************************************************************
|
|
55565
|
+
* Repaint the cards whose highlight state CHANGES: the ones that had it
|
|
55566
|
+
* and lose it, plus the ones that gain it. Only those — a treedb graph
|
|
55567
|
+
* is redrawn per keystroke of the find box otherwise.
|
|
55568
|
+
************************************************************/
|
|
55569
|
+
function apply_node_highlight(gobj, prev_ids, next_ids) {
|
|
55570
|
+
let priv = gobj.priv;
|
|
55571
|
+
let graph = priv.graph;
|
|
55572
|
+
if (!graph) return;
|
|
55573
|
+
let next = new Set(next_ids || []);
|
|
55574
|
+
let touched = /* @__PURE__ */ new Set([...prev_ids || [], ...next]);
|
|
55575
|
+
if (touched.size === 0) return;
|
|
55576
|
+
let updates = [];
|
|
55577
|
+
for (let id of touched) {
|
|
55578
|
+
let html = node_innerHTML_of(graph.getNodeData(id), priv.theme, next.has(id));
|
|
55579
|
+
if (html !== null) updates.push({
|
|
55580
|
+
id,
|
|
55581
|
+
style: { innerHTML: html }
|
|
55582
|
+
});
|
|
55583
|
+
}
|
|
55584
|
+
if (!updates.length) return;
|
|
55585
|
+
try {
|
|
55586
|
+
graph.updateNodeData(updates);
|
|
55587
|
+
graph.draw();
|
|
55588
|
+
} catch (e) {
|
|
55589
|
+
(0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: cannot repaint the highlight: ${e}`);
|
|
55590
|
+
}
|
|
55591
|
+
}
|
|
55525
55592
|
function refresh_html_nodes_theme(gobj, theme) {
|
|
55526
|
-
let
|
|
55593
|
+
let priv = gobj.priv;
|
|
55594
|
+
let graph = priv.graph;
|
|
55527
55595
|
if (!graph) return;
|
|
55528
55596
|
let nodes = graph.getData().nodes || [];
|
|
55597
|
+
let highlighted = new Set(priv._focus_ids || []);
|
|
55529
55598
|
let updates = [];
|
|
55530
55599
|
for (let i = 0; i < nodes.length; i++) {
|
|
55531
|
-
let
|
|
55532
|
-
|
|
55533
|
-
|
|
55534
|
-
|
|
55535
|
-
|
|
55536
|
-
id: nodes[i].id,
|
|
55537
|
-
style: { innerHTML: build_node_innerHTML(nd.data.desc.color, theme, record.icon, node_label(nd.data.desc, record), nd.data.desc.topic_name, false, record.id) }
|
|
55538
|
-
});
|
|
55539
|
-
else if (tt === "child") updates.push({
|
|
55540
|
-
id: nodes[i].id,
|
|
55541
|
-
style: { innerHTML: build_chip_innerHTML(nd.data.desc.color, theme, record.icon, node_label(nd.data.desc, record), record.id) }
|
|
55542
|
-
});
|
|
55543
|
-
else if (tt === "extended") updates.push({
|
|
55544
|
-
id: nodes[i].id,
|
|
55545
|
-
style: { innerHTML: build_node_innerHTML(nd.data.desc.color, theme, record.icon, node_label(nd.data.desc, record), nd.data.desc.topic_name, true, record.id) }
|
|
55600
|
+
let id = nodes[i].id;
|
|
55601
|
+
let html = node_innerHTML_of(graph.getNodeData(id), theme, highlighted.has(id));
|
|
55602
|
+
if (html !== null) updates.push({
|
|
55603
|
+
id,
|
|
55604
|
+
style: { innerHTML: html }
|
|
55546
55605
|
});
|
|
55547
55606
|
}
|
|
55548
55607
|
if (updates.length > 0) graph.updateNodeData(updates);
|
|
@@ -55574,12 +55633,13 @@ function refresh_default_edges_theme(gobj, theme) {
|
|
|
55574
55633
|
* but lighter (1px border, no shadow, single line). The name is
|
|
55575
55634
|
* always legible (ellipsis + native title tooltip on overflow).
|
|
55576
55635
|
************************************************************/
|
|
55577
|
-
function build_chip_innerHTML(color, theme, icon, label, key) {
|
|
55636
|
+
function build_chip_innerHTML(color, theme, icon, label, key, highlight) {
|
|
55578
55637
|
let title = key || label;
|
|
55579
55638
|
let dark = theme === "dark";
|
|
55580
55639
|
let bg = dark ? `color-mix(in srgb, ${color} 30%, #2c3542)` : `color-mix(in srgb, ${color} 10%, ${dark ? "#1b2230" : "#ffffff"})`;
|
|
55581
55640
|
let border = dark ? `color-mix(in srgb, ${color} 85%, #ffffff)` : color;
|
|
55582
55641
|
let text_color = dark ? "#e8eaed" : "#0f172a";
|
|
55642
|
+
if (highlight) border = HIGHLIGHT_COLOR;
|
|
55583
55643
|
let icon_html = "";
|
|
55584
55644
|
if (icon) icon_html = `<img src="${(0, _yuneta_gobj_js.safeSrc)(icon)}" alt="" style="
|
|
55585
55645
|
width: 16px; height: 16px; object-fit: contain;
|
|
@@ -55591,7 +55651,8 @@ function build_chip_innerHTML(color, theme, icon, label, key) {
|
|
|
55591
55651
|
width: 100%;
|
|
55592
55652
|
height: 100%;
|
|
55593
55653
|
background: ${bg};
|
|
55594
|
-
border: 1px solid ${border};
|
|
55654
|
+
border: ${highlight ? "3px" : "1px"} solid ${border};
|
|
55655
|
+
${highlight ? `box-shadow: 0 0 0 4px ${HIGHLIGHT_HALO};` : ""}
|
|
55595
55656
|
border-radius: 8px;
|
|
55596
55657
|
color: ${text_color};
|
|
55597
55658
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
@@ -55617,7 +55678,7 @@ function build_chip_innerHTML(color, theme, icon, label, key) {
|
|
|
55617
55678
|
* colour is kept (per-topic differentiation) but softened via
|
|
55618
55679
|
* color-mix instead of a harsh saturated fill. Theme-aware.
|
|
55619
55680
|
************************************************************/
|
|
55620
|
-
function build_node_innerHTML(color, theme, icon, label, topic_name, structural, key) {
|
|
55681
|
+
function build_node_innerHTML(color, theme, icon, label, topic_name, structural, key, highlight) {
|
|
55621
55682
|
let title = key || label;
|
|
55622
55683
|
let dark = theme === "dark";
|
|
55623
55684
|
let surface = dark ? "#1b2230" : "#ffffff";
|
|
@@ -55631,6 +55692,10 @@ function build_node_innerHTML(color, theme, icon, label, topic_name, structural,
|
|
|
55631
55692
|
border = dark ? `color-mix(in srgb, ${color} 85%, #ffffff)` : color;
|
|
55632
55693
|
border_style = "solid";
|
|
55633
55694
|
}
|
|
55695
|
+
if (highlight) {
|
|
55696
|
+
border = HIGHLIGHT_COLOR;
|
|
55697
|
+
border_style = "solid";
|
|
55698
|
+
}
|
|
55634
55699
|
let title_color = dark ? "#e8eaed" : "#0f172a";
|
|
55635
55700
|
let sub_color = dark ? "#9aa4b2" : "#64748b";
|
|
55636
55701
|
let shadow = dark ? "0 1px 3px rgba(0,0,0,0.45), 0 1px 2px rgba(0,0,0,0.30)" : "0 1px 3px rgba(15,23,42,0.12), 0 1px 2px rgba(15,23,42,0.06)";
|
|
@@ -55653,9 +55718,9 @@ function build_node_innerHTML(color, theme, icon, label, topic_name, structural,
|
|
|
55653
55718
|
width: 100%;
|
|
55654
55719
|
height: 100%;
|
|
55655
55720
|
background: ${bg};
|
|
55656
|
-
border: 1.5px ${border_style} ${border};
|
|
55721
|
+
border: ${highlight ? "3px" : "1.5px"} ${border_style} ${border};
|
|
55657
55722
|
border-radius: 10px;
|
|
55658
|
-
box-shadow: ${shadow};
|
|
55723
|
+
box-shadow: ${highlight ? `0 0 0 4px ${HIGHLIGHT_HALO}, ${shadow}` : shadow};
|
|
55659
55724
|
color: ${title_color};
|
|
55660
55725
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
55661
55726
|
display: flex;
|
package/dist/gobj-ui.es.js
CHANGED
|
@@ -16949,11 +16949,12 @@ function create_tabulator(gobj) {
|
|
|
16949
16949
|
}
|
|
16950
16950
|
let tabulator = new TabulatorFull($table_el, Object.assign({}, tabulator_settings, yui_tabulator_lang(t), { placeholder: t("no data available", { defaultValue: "No data available" }) }));
|
|
16951
16951
|
if (with_checkbox) $table_el.classList.add("yui-no-row-hover");
|
|
16952
|
-
function update_rowcount() {
|
|
16952
|
+
function update_rowcount(explicit_count) {
|
|
16953
16953
|
let $rc = tabulator.element && tabulator.element.querySelector(".yui-tabulator-rowcount");
|
|
16954
16954
|
if (!$rc) return;
|
|
16955
16955
|
let n = 0;
|
|
16956
|
-
|
|
16956
|
+
if (typeof explicit_count === "number") n = explicit_count;
|
|
16957
|
+
else try {
|
|
16957
16958
|
n = tabulator.getDataCount("active");
|
|
16958
16959
|
} catch (e) {
|
|
16959
16960
|
n = 0;
|
|
@@ -16961,8 +16962,8 @@ function create_tabulator(gobj) {
|
|
|
16961
16962
|
$rc.textContent = `${n} ${t("rows")}`;
|
|
16962
16963
|
let single_page = true;
|
|
16963
16964
|
try {
|
|
16964
|
-
let
|
|
16965
|
-
single_page =
|
|
16965
|
+
let size = tabulator.getPageSize();
|
|
16966
|
+
single_page = !size || n <= size;
|
|
16966
16967
|
} catch (e) {
|
|
16967
16968
|
single_page = true;
|
|
16968
16969
|
}
|
|
@@ -16979,7 +16980,9 @@ function create_tabulator(gobj) {
|
|
|
16979
16980
|
});
|
|
16980
16981
|
tabulator.on("dataProcessed", update_rowcount);
|
|
16981
16982
|
tabulator.on("dataChanged", update_rowcount);
|
|
16982
|
-
tabulator.on("dataFiltered",
|
|
16983
|
+
tabulator.on("dataFiltered", function(filters, rows) {
|
|
16984
|
+
update_rowcount(Array.isArray(rows) ? rows.length : void 0);
|
|
16985
|
+
});
|
|
16983
16986
|
tabulator.on("rowSelected", function(row) {
|
|
16984
16987
|
gobj_send_event(gobj, "EV_SELECT_ROWS", { rows: [row.getData()] }, gobj);
|
|
16985
16988
|
});
|
|
@@ -18578,6 +18581,7 @@ var PRIVATE_DATA$4 = {
|
|
|
18578
18581
|
topics: [],
|
|
18579
18582
|
records: {},
|
|
18580
18583
|
gobj_nodes_tree: null,
|
|
18584
|
+
find_timer: null,
|
|
18581
18585
|
gobj_treedb_tables: null,
|
|
18582
18586
|
hook_data_viewer: null,
|
|
18583
18587
|
json_gobj: null,
|
|
@@ -18652,6 +18656,11 @@ function mt_stop$4(gobj) {
|
|
|
18652
18656
|
* Framework Method: Destroy
|
|
18653
18657
|
***************************************************************/
|
|
18654
18658
|
function mt_destroy$4(gobj) {
|
|
18659
|
+
let priv = gobj.priv;
|
|
18660
|
+
if (priv.find_timer) {
|
|
18661
|
+
clearTimeout(priv.find_timer);
|
|
18662
|
+
priv.find_timer = null;
|
|
18663
|
+
}
|
|
18655
18664
|
destroy_ui$1(gobj);
|
|
18656
18665
|
}
|
|
18657
18666
|
/***************************
|
|
@@ -18758,7 +18767,7 @@ function destroy_ui$1(gobj) {
|
|
|
18758
18767
|
*
|
|
18759
18768
|
************************************************************/
|
|
18760
18769
|
function make_toolbar(gobj) {
|
|
18761
|
-
gobj.priv;
|
|
18770
|
+
let priv = gobj.priv;
|
|
18762
18771
|
let modes = gobj_read_attr(gobj, "operation_modes");
|
|
18763
18772
|
if (gobj_read_bool_attr(gobj, "readonly")) modes = modes.filter((mode) => mode !== "edition");
|
|
18764
18773
|
let left_items = [
|
|
@@ -18867,7 +18876,12 @@ function make_toolbar(gobj) {
|
|
|
18867
18876
|
]],
|
|
18868
18877
|
{ input: (evt) => {
|
|
18869
18878
|
evt.stopPropagation();
|
|
18870
|
-
|
|
18879
|
+
let text = evt.target.value.trim();
|
|
18880
|
+
if (priv.find_timer) clearTimeout(priv.find_timer);
|
|
18881
|
+
priv.find_timer = setTimeout(function() {
|
|
18882
|
+
priv.find_timer = null;
|
|
18883
|
+
gobj_send_event(gobj, "EV_FIND_NODES", { text }, gobj);
|
|
18884
|
+
}, 250);
|
|
18871
18885
|
} }
|
|
18872
18886
|
], [
|
|
18873
18887
|
"div",
|
|
@@ -52626,6 +52640,8 @@ ensure_drag_canvas_patch();
|
|
|
52626
52640
|
* Constants
|
|
52627
52641
|
***************************************************************/
|
|
52628
52642
|
var GCLASS_NAME$1 = "C_G6_NODES_TREE";
|
|
52643
|
+
var HIGHLIGHT_COLOR = "#f0a020";
|
|
52644
|
+
var HIGHLIGHT_HALO = "rgba(240,160,32,0.35)";
|
|
52629
52645
|
/***************************************************************
|
|
52630
52646
|
* Internal layout and operation mode definitions
|
|
52631
52647
|
***************************************************************/
|
|
@@ -53902,10 +53918,12 @@ function graph_focus_topic(gobj, topic) {
|
|
|
53902
53918
|
if (ids.length === 0) log_warning(`${gobj_short_name(gobj)}: focus topic '${topic}' has no nodes`);
|
|
53903
53919
|
for (let id of ids) states[id] = ["active"];
|
|
53904
53920
|
}
|
|
53921
|
+
let prev_ids = priv._focus_ids || [];
|
|
53905
53922
|
priv._focus_ids = ids;
|
|
53906
53923
|
priv._focus_topic = topic || null;
|
|
53907
53924
|
try {
|
|
53908
53925
|
if (typeof graph.setElementState === "function") graph.setElementState(states);
|
|
53926
|
+
apply_node_highlight(gobj, prev_ids, ids);
|
|
53909
53927
|
if (ids.length && typeof graph.focusElement === "function") graph.focusElement(ids);
|
|
53910
53928
|
} catch (e) {
|
|
53911
53929
|
log_error(`${gobj_short_name(gobj)}: focus topic apply failed: ${e}`);
|
|
@@ -53962,10 +53980,12 @@ function graph_find_nodes(gobj, term) {
|
|
|
53962
53980
|
}
|
|
53963
53981
|
for (let id of ids) states[id] = ["active"];
|
|
53964
53982
|
}
|
|
53983
|
+
let prev_ids = priv._focus_ids || [];
|
|
53965
53984
|
priv._focus_ids = ids;
|
|
53966
53985
|
priv._focus_topic = null;
|
|
53967
53986
|
try {
|
|
53968
53987
|
if (typeof graph.setElementState === "function") graph.setElementState(states);
|
|
53988
|
+
apply_node_highlight(gobj, prev_ids, ids);
|
|
53969
53989
|
if (ids.length && typeof graph.focusElement === "function") graph.focusElement(ids);
|
|
53970
53990
|
} catch (e) {
|
|
53971
53991
|
log_error(`${gobj_short_name(gobj)}: find apply failed: ${e}`);
|
|
@@ -55509,27 +55529,66 @@ function show_node_detail_popover(gobj, node_id) {
|
|
|
55509
55529
|
* not re-themed by setTheme()) are regenerated; structural
|
|
55510
55530
|
* junction diamonds get their neutral fill/stroke re-themed.
|
|
55511
55531
|
************************************************************/
|
|
55532
|
+
/************************************************************
|
|
55533
|
+
* The innerHTML of ONE node, in the given theme and highlight state.
|
|
55534
|
+
* The three treedb tiers (hierarchical / extended / child) each have
|
|
55535
|
+
* their own card, and both the theme refresh and the highlight need the
|
|
55536
|
+
* same three-way choice — it lived inline in the theme refresh and is
|
|
55537
|
+
* shared now. Returns null for a node that carries no desc.
|
|
55538
|
+
************************************************************/
|
|
55539
|
+
function node_innerHTML_of(nd, theme, highlight) {
|
|
55540
|
+
if (!nd || !nd.data || !nd.data.desc) return null;
|
|
55541
|
+
let desc = nd.data.desc;
|
|
55542
|
+
let record = nd.data.record || {};
|
|
55543
|
+
let label = node_label(desc, record);
|
|
55544
|
+
switch (desc.node_treedb_type) {
|
|
55545
|
+
case "child": return build_chip_innerHTML(desc.color, theme, record.icon, label, record.id, highlight);
|
|
55546
|
+
case "extended": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, true, record.id, highlight);
|
|
55547
|
+
case "hierarchical": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, false, record.id, highlight);
|
|
55548
|
+
}
|
|
55549
|
+
return null;
|
|
55550
|
+
}
|
|
55551
|
+
/************************************************************
|
|
55552
|
+
* Repaint the cards whose highlight state CHANGES: the ones that had it
|
|
55553
|
+
* and lose it, plus the ones that gain it. Only those — a treedb graph
|
|
55554
|
+
* is redrawn per keystroke of the find box otherwise.
|
|
55555
|
+
************************************************************/
|
|
55556
|
+
function apply_node_highlight(gobj, prev_ids, next_ids) {
|
|
55557
|
+
let priv = gobj.priv;
|
|
55558
|
+
let graph = priv.graph;
|
|
55559
|
+
if (!graph) return;
|
|
55560
|
+
let next = new Set(next_ids || []);
|
|
55561
|
+
let touched = /* @__PURE__ */ new Set([...prev_ids || [], ...next]);
|
|
55562
|
+
if (touched.size === 0) return;
|
|
55563
|
+
let updates = [];
|
|
55564
|
+
for (let id of touched) {
|
|
55565
|
+
let html = node_innerHTML_of(graph.getNodeData(id), priv.theme, next.has(id));
|
|
55566
|
+
if (html !== null) updates.push({
|
|
55567
|
+
id,
|
|
55568
|
+
style: { innerHTML: html }
|
|
55569
|
+
});
|
|
55570
|
+
}
|
|
55571
|
+
if (!updates.length) return;
|
|
55572
|
+
try {
|
|
55573
|
+
graph.updateNodeData(updates);
|
|
55574
|
+
graph.draw();
|
|
55575
|
+
} catch (e) {
|
|
55576
|
+
log_error(`${gobj_short_name(gobj)}: cannot repaint the highlight: ${e}`);
|
|
55577
|
+
}
|
|
55578
|
+
}
|
|
55512
55579
|
function refresh_html_nodes_theme(gobj, theme) {
|
|
55513
|
-
let
|
|
55580
|
+
let priv = gobj.priv;
|
|
55581
|
+
let graph = priv.graph;
|
|
55514
55582
|
if (!graph) return;
|
|
55515
55583
|
let nodes = graph.getData().nodes || [];
|
|
55584
|
+
let highlighted = new Set(priv._focus_ids || []);
|
|
55516
55585
|
let updates = [];
|
|
55517
55586
|
for (let i = 0; i < nodes.length; i++) {
|
|
55518
|
-
let
|
|
55519
|
-
|
|
55520
|
-
|
|
55521
|
-
|
|
55522
|
-
|
|
55523
|
-
id: nodes[i].id,
|
|
55524
|
-
style: { innerHTML: build_node_innerHTML(nd.data.desc.color, theme, record.icon, node_label(nd.data.desc, record), nd.data.desc.topic_name, false, record.id) }
|
|
55525
|
-
});
|
|
55526
|
-
else if (tt === "child") updates.push({
|
|
55527
|
-
id: nodes[i].id,
|
|
55528
|
-
style: { innerHTML: build_chip_innerHTML(nd.data.desc.color, theme, record.icon, node_label(nd.data.desc, record), record.id) }
|
|
55529
|
-
});
|
|
55530
|
-
else if (tt === "extended") updates.push({
|
|
55531
|
-
id: nodes[i].id,
|
|
55532
|
-
style: { innerHTML: build_node_innerHTML(nd.data.desc.color, theme, record.icon, node_label(nd.data.desc, record), nd.data.desc.topic_name, true, record.id) }
|
|
55587
|
+
let id = nodes[i].id;
|
|
55588
|
+
let html = node_innerHTML_of(graph.getNodeData(id), theme, highlighted.has(id));
|
|
55589
|
+
if (html !== null) updates.push({
|
|
55590
|
+
id,
|
|
55591
|
+
style: { innerHTML: html }
|
|
55533
55592
|
});
|
|
55534
55593
|
}
|
|
55535
55594
|
if (updates.length > 0) graph.updateNodeData(updates);
|
|
@@ -55561,12 +55620,13 @@ function refresh_default_edges_theme(gobj, theme) {
|
|
|
55561
55620
|
* but lighter (1px border, no shadow, single line). The name is
|
|
55562
55621
|
* always legible (ellipsis + native title tooltip on overflow).
|
|
55563
55622
|
************************************************************/
|
|
55564
|
-
function build_chip_innerHTML(color, theme, icon, label, key) {
|
|
55623
|
+
function build_chip_innerHTML(color, theme, icon, label, key, highlight) {
|
|
55565
55624
|
let title = key || label;
|
|
55566
55625
|
let dark = theme === "dark";
|
|
55567
55626
|
let bg = dark ? `color-mix(in srgb, ${color} 30%, #2c3542)` : `color-mix(in srgb, ${color} 10%, ${dark ? "#1b2230" : "#ffffff"})`;
|
|
55568
55627
|
let border = dark ? `color-mix(in srgb, ${color} 85%, #ffffff)` : color;
|
|
55569
55628
|
let text_color = dark ? "#e8eaed" : "#0f172a";
|
|
55629
|
+
if (highlight) border = HIGHLIGHT_COLOR;
|
|
55570
55630
|
let icon_html = "";
|
|
55571
55631
|
if (icon) icon_html = `<img src="${safeSrc(icon)}" alt="" style="
|
|
55572
55632
|
width: 16px; height: 16px; object-fit: contain;
|
|
@@ -55578,7 +55638,8 @@ function build_chip_innerHTML(color, theme, icon, label, key) {
|
|
|
55578
55638
|
width: 100%;
|
|
55579
55639
|
height: 100%;
|
|
55580
55640
|
background: ${bg};
|
|
55581
|
-
border: 1px solid ${border};
|
|
55641
|
+
border: ${highlight ? "3px" : "1px"} solid ${border};
|
|
55642
|
+
${highlight ? `box-shadow: 0 0 0 4px ${HIGHLIGHT_HALO};` : ""}
|
|
55582
55643
|
border-radius: 8px;
|
|
55583
55644
|
color: ${text_color};
|
|
55584
55645
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
@@ -55604,7 +55665,7 @@ function build_chip_innerHTML(color, theme, icon, label, key) {
|
|
|
55604
55665
|
* colour is kept (per-topic differentiation) but softened via
|
|
55605
55666
|
* color-mix instead of a harsh saturated fill. Theme-aware.
|
|
55606
55667
|
************************************************************/
|
|
55607
|
-
function build_node_innerHTML(color, theme, icon, label, topic_name, structural, key) {
|
|
55668
|
+
function build_node_innerHTML(color, theme, icon, label, topic_name, structural, key, highlight) {
|
|
55608
55669
|
let title = key || label;
|
|
55609
55670
|
let dark = theme === "dark";
|
|
55610
55671
|
let surface = dark ? "#1b2230" : "#ffffff";
|
|
@@ -55618,6 +55679,10 @@ function build_node_innerHTML(color, theme, icon, label, topic_name, structural,
|
|
|
55618
55679
|
border = dark ? `color-mix(in srgb, ${color} 85%, #ffffff)` : color;
|
|
55619
55680
|
border_style = "solid";
|
|
55620
55681
|
}
|
|
55682
|
+
if (highlight) {
|
|
55683
|
+
border = HIGHLIGHT_COLOR;
|
|
55684
|
+
border_style = "solid";
|
|
55685
|
+
}
|
|
55621
55686
|
let title_color = dark ? "#e8eaed" : "#0f172a";
|
|
55622
55687
|
let sub_color = dark ? "#9aa4b2" : "#64748b";
|
|
55623
55688
|
let shadow = dark ? "0 1px 3px rgba(0,0,0,0.45), 0 1px 2px rgba(0,0,0,0.30)" : "0 1px 3px rgba(15,23,42,0.12), 0 1px 2px rgba(15,23,42,0.06)";
|
|
@@ -55640,9 +55705,9 @@ function build_node_innerHTML(color, theme, icon, label, topic_name, structural,
|
|
|
55640
55705
|
width: 100%;
|
|
55641
55706
|
height: 100%;
|
|
55642
55707
|
background: ${bg};
|
|
55643
|
-
border: 1.5px ${border_style} ${border};
|
|
55708
|
+
border: ${highlight ? "3px" : "1.5px"} ${border_style} ${border};
|
|
55644
55709
|
border-radius: 10px;
|
|
55645
|
-
box-shadow: ${shadow};
|
|
55710
|
+
box-shadow: ${highlight ? `0 0 0 4px ${HIGHLIGHT_HALO}, ${shadow}` : shadow};
|
|
55646
55711
|
color: ${title_color};
|
|
55647
55712
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
55648
55713
|
display: flex;
|
package/package.json
CHANGED
package/src/c_g6_nodes_tree.js
CHANGED
|
@@ -140,6 +140,14 @@ ensure_drag_canvas_patch();
|
|
|
140
140
|
***************************************************************/
|
|
141
141
|
const GCLASS_NAME = "C_G6_NODES_TREE";
|
|
142
142
|
|
|
143
|
+
/* The highlight of a focused topic / a find match. It is drawn INTO the
|
|
144
|
+
* node's own html, not with G6's `active` element state: every node here
|
|
145
|
+
* is an `html` node, whose key shape is a DOM element — the state's
|
|
146
|
+
* `stroke` / `halo` have nothing to paint on and the amber never
|
|
147
|
+
* appeared, for the topic focus either. */
|
|
148
|
+
const HIGHLIGHT_COLOR = "#f0a020";
|
|
149
|
+
const HIGHLIGHT_HALO = "rgba(240,160,32,0.35)";
|
|
150
|
+
|
|
143
151
|
/***************************************************************
|
|
144
152
|
* Internal layout and operation mode definitions
|
|
145
153
|
***************************************************************/
|
|
@@ -2113,6 +2121,7 @@ function graph_focus_topic(gobj, topic)
|
|
|
2113
2121
|
states[id] = ['active'];
|
|
2114
2122
|
}
|
|
2115
2123
|
}
|
|
2124
|
+
let prev_ids = priv._focus_ids || [];
|
|
2116
2125
|
priv._focus_ids = ids;
|
|
2117
2126
|
priv._focus_topic = topic || null;
|
|
2118
2127
|
|
|
@@ -2120,6 +2129,7 @@ function graph_focus_topic(gobj, topic)
|
|
|
2120
2129
|
if(typeof graph.setElementState === "function") {
|
|
2121
2130
|
graph.setElementState(states);
|
|
2122
2131
|
}
|
|
2132
|
+
apply_node_highlight(gobj, prev_ids, ids);
|
|
2123
2133
|
if(ids.length && typeof graph.focusElement === "function") {
|
|
2124
2134
|
graph.focusElement(ids);
|
|
2125
2135
|
}
|
|
@@ -2194,6 +2204,7 @@ function graph_find_nodes(gobj, term)
|
|
|
2194
2204
|
}
|
|
2195
2205
|
}
|
|
2196
2206
|
|
|
2207
|
+
let prev_ids = priv._focus_ids || [];
|
|
2197
2208
|
priv._focus_ids = ids;
|
|
2198
2209
|
priv._focus_topic = null; /* a find takes over the highlight */
|
|
2199
2210
|
|
|
@@ -2201,6 +2212,7 @@ function graph_find_nodes(gobj, term)
|
|
|
2201
2212
|
if(typeof graph.setElementState === "function") {
|
|
2202
2213
|
graph.setElementState(states);
|
|
2203
2214
|
}
|
|
2215
|
+
apply_node_highlight(gobj, prev_ids, ids);
|
|
2204
2216
|
if(ids.length && typeof graph.focusElement === "function") {
|
|
2205
2217
|
graph.focusElement(ids);
|
|
2206
2218
|
}
|
|
@@ -4469,6 +4481,79 @@ function show_node_detail_popover(gobj, node_id)
|
|
|
4469
4481
|
* not re-themed by setTheme()) are regenerated; structural
|
|
4470
4482
|
* junction diamonds get their neutral fill/stroke re-themed.
|
|
4471
4483
|
************************************************************/
|
|
4484
|
+
/************************************************************
|
|
4485
|
+
* The innerHTML of ONE node, in the given theme and highlight state.
|
|
4486
|
+
* The three treedb tiers (hierarchical / extended / child) each have
|
|
4487
|
+
* their own card, and both the theme refresh and the highlight need the
|
|
4488
|
+
* same three-way choice — it lived inline in the theme refresh and is
|
|
4489
|
+
* shared now. Returns null for a node that carries no desc.
|
|
4490
|
+
************************************************************/
|
|
4491
|
+
function node_innerHTML_of(nd, theme, highlight)
|
|
4492
|
+
{
|
|
4493
|
+
if(!nd || !nd.data || !nd.data.desc) {
|
|
4494
|
+
return null;
|
|
4495
|
+
}
|
|
4496
|
+
let desc = nd.data.desc;
|
|
4497
|
+
let record = nd.data.record || {};
|
|
4498
|
+
let label = node_label(desc, record);
|
|
4499
|
+
|
|
4500
|
+
switch(desc.node_treedb_type) {
|
|
4501
|
+
case 'child':
|
|
4502
|
+
return build_chip_innerHTML(
|
|
4503
|
+
desc.color, theme, record.icon, label, record.id, highlight
|
|
4504
|
+
);
|
|
4505
|
+
case 'extended':
|
|
4506
|
+
return build_node_innerHTML(
|
|
4507
|
+
desc.color, theme, record.icon, label,
|
|
4508
|
+
desc.topic_name, true, record.id, highlight
|
|
4509
|
+
);
|
|
4510
|
+
case 'hierarchical':
|
|
4511
|
+
return build_node_innerHTML(
|
|
4512
|
+
desc.color, theme, record.icon, label,
|
|
4513
|
+
desc.topic_name, false, record.id, highlight
|
|
4514
|
+
);
|
|
4515
|
+
}
|
|
4516
|
+
return null;
|
|
4517
|
+
}
|
|
4518
|
+
|
|
4519
|
+
/************************************************************
|
|
4520
|
+
* Repaint the cards whose highlight state CHANGES: the ones that had it
|
|
4521
|
+
* and lose it, plus the ones that gain it. Only those — a treedb graph
|
|
4522
|
+
* is redrawn per keystroke of the find box otherwise.
|
|
4523
|
+
************************************************************/
|
|
4524
|
+
function apply_node_highlight(gobj, prev_ids, next_ids)
|
|
4525
|
+
{
|
|
4526
|
+
let priv = gobj.priv;
|
|
4527
|
+
let graph = priv.graph;
|
|
4528
|
+
if(!graph) {
|
|
4529
|
+
return;
|
|
4530
|
+
}
|
|
4531
|
+
|
|
4532
|
+
let next = new Set(next_ids || []);
|
|
4533
|
+
let touched = new Set([...(prev_ids || []), ...next]);
|
|
4534
|
+
if(touched.size === 0) {
|
|
4535
|
+
return;
|
|
4536
|
+
}
|
|
4537
|
+
|
|
4538
|
+
let updates = [];
|
|
4539
|
+
for(let id of touched) {
|
|
4540
|
+
let nd = graph.getNodeData(id);
|
|
4541
|
+
let html = node_innerHTML_of(nd, priv.theme, next.has(id));
|
|
4542
|
+
if(html !== null) {
|
|
4543
|
+
updates.push({id: id, style: {innerHTML: html}});
|
|
4544
|
+
}
|
|
4545
|
+
}
|
|
4546
|
+
if(!updates.length) {
|
|
4547
|
+
return;
|
|
4548
|
+
}
|
|
4549
|
+
try {
|
|
4550
|
+
graph.updateNodeData(updates);
|
|
4551
|
+
graph.draw();
|
|
4552
|
+
} catch(e) {
|
|
4553
|
+
log_error(`${gobj_short_name(gobj)}: cannot repaint the highlight: ${e}`);
|
|
4554
|
+
}
|
|
4555
|
+
}
|
|
4556
|
+
|
|
4472
4557
|
function refresh_html_nodes_theme(gobj, theme)
|
|
4473
4558
|
{
|
|
4474
4559
|
let priv = gobj.priv;
|
|
@@ -4477,46 +4562,16 @@ function refresh_html_nodes_theme(gobj, theme)
|
|
|
4477
4562
|
return;
|
|
4478
4563
|
}
|
|
4479
4564
|
let nodes = graph.getData().nodes || [];
|
|
4565
|
+
/* The highlight is part of the card's html, so a theme switch that
|
|
4566
|
+
* rebuilt every card without it would silently CLEAR the focus or the
|
|
4567
|
+
* find that is on screen. Carry it across. */
|
|
4568
|
+
let highlighted = new Set(priv._focus_ids || []);
|
|
4480
4569
|
let updates = [];
|
|
4481
4570
|
for(let i = 0; i < nodes.length; i++) {
|
|
4482
|
-
let
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
let tt = nd.data.desc.node_treedb_type;
|
|
4487
|
-
let record = nd.data.record || {};
|
|
4488
|
-
if(tt === 'hierarchical') {
|
|
4489
|
-
updates.push({
|
|
4490
|
-
id: nodes[i].id,
|
|
4491
|
-
style: {
|
|
4492
|
-
innerHTML: build_node_innerHTML(
|
|
4493
|
-
nd.data.desc.color, theme, record.icon,
|
|
4494
|
-
node_label(nd.data.desc, record),
|
|
4495
|
-
nd.data.desc.topic_name, false, record.id
|
|
4496
|
-
)
|
|
4497
|
-
}
|
|
4498
|
-
});
|
|
4499
|
-
} else if(tt === 'child') {
|
|
4500
|
-
updates.push({
|
|
4501
|
-
id: nodes[i].id,
|
|
4502
|
-
style: {
|
|
4503
|
-
innerHTML: build_chip_innerHTML(
|
|
4504
|
-
nd.data.desc.color, theme, record.icon,
|
|
4505
|
-
node_label(nd.data.desc, record), record.id
|
|
4506
|
-
)
|
|
4507
|
-
}
|
|
4508
|
-
});
|
|
4509
|
-
} else if(tt === 'extended') {
|
|
4510
|
-
updates.push({
|
|
4511
|
-
id: nodes[i].id,
|
|
4512
|
-
style: {
|
|
4513
|
-
innerHTML: build_node_innerHTML(
|
|
4514
|
-
nd.data.desc.color, theme, record.icon,
|
|
4515
|
-
node_label(nd.data.desc, record),
|
|
4516
|
-
nd.data.desc.topic_name, true, record.id
|
|
4517
|
-
)
|
|
4518
|
-
}
|
|
4519
|
-
});
|
|
4571
|
+
let id = nodes[i].id;
|
|
4572
|
+
let html = node_innerHTML_of(graph.getNodeData(id), theme, highlighted.has(id));
|
|
4573
|
+
if(html !== null) {
|
|
4574
|
+
updates.push({id: id, style: {innerHTML: html}});
|
|
4520
4575
|
}
|
|
4521
4576
|
}
|
|
4522
4577
|
if(updates.length > 0) {
|
|
@@ -4559,7 +4614,7 @@ function refresh_default_edges_theme(gobj, theme)
|
|
|
4559
4614
|
* but lighter (1px border, no shadow, single line). The name is
|
|
4560
4615
|
* always legible (ellipsis + native title tooltip on overflow).
|
|
4561
4616
|
************************************************************/
|
|
4562
|
-
function build_chip_innerHTML(color, theme, icon, label, key)
|
|
4617
|
+
function build_chip_innerHTML(color, theme, icon, label, key, highlight)
|
|
4563
4618
|
{
|
|
4564
4619
|
let title = key || label;
|
|
4565
4620
|
let dark = (theme === "dark");
|
|
@@ -4571,6 +4626,9 @@ function build_chip_innerHTML(color, theme, icon, label, key)
|
|
|
4571
4626
|
? `color-mix(in srgb, ${color} 85%, #ffffff)`
|
|
4572
4627
|
: color;
|
|
4573
4628
|
let text_color = dark ? "#e8eaed" : "#0f172a";
|
|
4629
|
+
if(highlight) {
|
|
4630
|
+
border = HIGHLIGHT_COLOR;
|
|
4631
|
+
}
|
|
4574
4632
|
|
|
4575
4633
|
let icon_html = "";
|
|
4576
4634
|
if(icon) {
|
|
@@ -4586,7 +4644,8 @@ function build_chip_innerHTML(color, theme, icon, label, key)
|
|
|
4586
4644
|
width: 100%;
|
|
4587
4645
|
height: 100%;
|
|
4588
4646
|
background: ${bg};
|
|
4589
|
-
border: 1px solid ${border};
|
|
4647
|
+
border: ${highlight? "3px" : "1px"} solid ${border};
|
|
4648
|
+
${highlight? `box-shadow: 0 0 0 4px ${HIGHLIGHT_HALO};` : ""}
|
|
4590
4649
|
border-radius: 8px;
|
|
4591
4650
|
color: ${text_color};
|
|
4592
4651
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
@@ -4613,7 +4672,7 @@ function build_chip_innerHTML(color, theme, icon, label, key)
|
|
|
4613
4672
|
* colour is kept (per-topic differentiation) but softened via
|
|
4614
4673
|
* color-mix instead of a harsh saturated fill. Theme-aware.
|
|
4615
4674
|
************************************************************/
|
|
4616
|
-
function build_node_innerHTML(color, theme, icon, label, topic_name, structural, key)
|
|
4675
|
+
function build_node_innerHTML(color, theme, icon, label, topic_name, structural, key, highlight)
|
|
4617
4676
|
{
|
|
4618
4677
|
let title = key || label;
|
|
4619
4678
|
let dark = (theme === "dark");
|
|
@@ -4639,6 +4698,10 @@ function build_node_innerHTML(color, theme, icon, label, topic_name, structural,
|
|
|
4639
4698
|
: color;
|
|
4640
4699
|
border_style = "solid";
|
|
4641
4700
|
}
|
|
4701
|
+
if(highlight) {
|
|
4702
|
+
border = HIGHLIGHT_COLOR;
|
|
4703
|
+
border_style = "solid";
|
|
4704
|
+
}
|
|
4642
4705
|
let title_color = dark ? "#e8eaed" : "#0f172a";
|
|
4643
4706
|
let sub_color = dark ? "#9aa4b2" : "#64748b";
|
|
4644
4707
|
let shadow = dark
|
|
@@ -4670,9 +4733,9 @@ function build_node_innerHTML(color, theme, icon, label, topic_name, structural,
|
|
|
4670
4733
|
width: 100%;
|
|
4671
4734
|
height: 100%;
|
|
4672
4735
|
background: ${bg};
|
|
4673
|
-
border: 1.5px ${border_style} ${border};
|
|
4736
|
+
border: ${highlight? "3px" : "1.5px"} ${border_style} ${border};
|
|
4674
4737
|
border-radius: 10px;
|
|
4675
|
-
box-shadow: ${shadow};
|
|
4738
|
+
box-shadow: ${highlight? `0 0 0 4px ${HIGHLIGHT_HALO}, ${shadow}` : shadow};
|
|
4676
4739
|
color: ${title_color};
|
|
4677
4740
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
4678
4741
|
display: flex;
|
|
@@ -147,6 +147,7 @@ let PRIVATE_DATA = {
|
|
|
147
147
|
topics: [],
|
|
148
148
|
records: {},
|
|
149
149
|
gobj_nodes_tree: null,
|
|
150
|
+
find_timer: null, // rate-limits the find box (see make_toolbar)
|
|
150
151
|
gobj_treedb_tables: null,
|
|
151
152
|
hook_data_viewer: null,
|
|
152
153
|
json_gobj: null, /* C_YUI_JSON viewer of the raw tranger (or null) */
|
|
@@ -310,6 +311,14 @@ function mt_stop(gobj)
|
|
|
310
311
|
***************************************************************/
|
|
311
312
|
function mt_destroy(gobj)
|
|
312
313
|
{
|
|
314
|
+
let priv = gobj.priv;
|
|
315
|
+
/* The find box rate-limits itself with a timer; a view torn down
|
|
316
|
+
* between the keystroke and the send would fire an event into a
|
|
317
|
+
* destroyed gobj. */
|
|
318
|
+
if(priv.find_timer) {
|
|
319
|
+
clearTimeout(priv.find_timer);
|
|
320
|
+
priv.find_timer = null;
|
|
321
|
+
}
|
|
313
322
|
destroy_ui(gobj);
|
|
314
323
|
}
|
|
315
324
|
|
|
@@ -530,14 +539,21 @@ function make_toolbar(gobj)
|
|
|
530
539
|
['i', {class: 'yi-magnifying-glass'}]
|
|
531
540
|
]]
|
|
532
541
|
], {
|
|
542
|
+
/* Rate-limited, not delayed for effect: a match repaints the
|
|
543
|
+
* cards it lands on, and on a large treedb the first letter
|
|
544
|
+
* typed can match hundreds. This is input plumbing — the
|
|
545
|
+
* event still carries every action to the FSM, just not one
|
|
546
|
+
* per keystroke. */
|
|
533
547
|
input: (evt) => {
|
|
534
548
|
evt.stopPropagation();
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
549
|
+
let text = evt.target.value.trim();
|
|
550
|
+
if(priv.find_timer) {
|
|
551
|
+
clearTimeout(priv.find_timer);
|
|
552
|
+
}
|
|
553
|
+
priv.find_timer = setTimeout(function() {
|
|
554
|
+
priv.find_timer = null;
|
|
555
|
+
gobj_send_event(gobj, "EV_FIND_NODES", {text: text}, gobj);
|
|
556
|
+
}, 250);
|
|
541
557
|
}
|
|
542
558
|
}],
|
|
543
559
|
/* Two spans, not one string: the number is DATA and "matches" is
|
|
@@ -1082,24 +1082,40 @@ function create_tabulator(gobj)
|
|
|
1082
1082
|
/* Keep the footer in sync with the visible (active) row count,
|
|
1083
1083
|
* and hide the pagination chrome while everything fits in one
|
|
1084
1084
|
* page (it comes back as soon as a second page exists). */
|
|
1085
|
-
|
|
1085
|
+
/* `explicit_count` is for the ONE caller that cannot ask the table:
|
|
1086
|
+
* `dataFiltered` is dispatched from INSIDE Tabulator's filter(), which
|
|
1087
|
+
* only RETURNS the surviving rows to the pipeline afterwards — so
|
|
1088
|
+
* `getDataCount("active")` still answers the pre-filter set there and
|
|
1089
|
+
* the footer claimed "5 rows" over four. The event hands us the rows
|
|
1090
|
+
* it just kept; that is the number. Every other caller passes nothing
|
|
1091
|
+
* and the table is asked. The `typeof` guard matters because
|
|
1092
|
+
* `dataProcessed` / `dataChanged` are registered directly and hand a
|
|
1093
|
+
* DATA ARRAY as their first argument. */
|
|
1094
|
+
function update_rowcount(explicit_count) {
|
|
1086
1095
|
let $rc = tabulator.element &&
|
|
1087
1096
|
tabulator.element.querySelector(".yui-tabulator-rowcount");
|
|
1088
1097
|
if(!$rc) {
|
|
1089
1098
|
return;
|
|
1090
1099
|
}
|
|
1091
1100
|
let n = 0;
|
|
1092
|
-
|
|
1093
|
-
n =
|
|
1094
|
-
}
|
|
1095
|
-
|
|
1101
|
+
if(typeof explicit_count === "number") {
|
|
1102
|
+
n = explicit_count;
|
|
1103
|
+
} else {
|
|
1104
|
+
try {
|
|
1105
|
+
n = tabulator.getDataCount("active");
|
|
1106
|
+
} catch(e) {
|
|
1107
|
+
n = 0;
|
|
1108
|
+
}
|
|
1096
1109
|
}
|
|
1097
1110
|
$rc.textContent = `${n} ${t("rows")}`;
|
|
1098
1111
|
|
|
1112
|
+
/* Derived from the count and the page size rather than read from
|
|
1113
|
+
* getPageMax(), which is stale in the filter path for the same
|
|
1114
|
+
* reason. getPageSize() throws with pagination off -> one page. */
|
|
1099
1115
|
let single_page = true;
|
|
1100
1116
|
try {
|
|
1101
|
-
let
|
|
1102
|
-
single_page =
|
|
1117
|
+
let size = tabulator.getPageSize();
|
|
1118
|
+
single_page = !size || n <= size;
|
|
1103
1119
|
} catch(e) {
|
|
1104
1120
|
single_page = true;
|
|
1105
1121
|
}
|
|
@@ -1123,7 +1139,9 @@ function create_tabulator(gobj)
|
|
|
1123
1139
|
* box; a filter per column made it a claim you read on every keystroke. */
|
|
1124
1140
|
tabulator.on("dataProcessed", update_rowcount);
|
|
1125
1141
|
tabulator.on("dataChanged", update_rowcount);
|
|
1126
|
-
tabulator.on("dataFiltered",
|
|
1142
|
+
tabulator.on("dataFiltered", function(filters, rows) {
|
|
1143
|
+
update_rowcount(Array.isArray(rows)? rows.length : undefined);
|
|
1144
|
+
});
|
|
1127
1145
|
tabulator.on("rowSelected", function(row) {
|
|
1128
1146
|
gobj_send_event(gobj, "EV_SELECT_ROWS", {rows: [row.getData()]}, gobj);
|
|
1129
1147
|
});
|