@yuneta/gobj-ui 7.2.5 → 7.4.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 +291 -40
- package/dist/gobj-ui.es.js +291 -40
- package/package.json +1 -1
- package/src/c_g6_nodes_tree.js +187 -44
- package/src/c_yui_treedb_graph.js +171 -7
package/dist/gobj-ui.es.js
CHANGED
|
@@ -18581,6 +18581,8 @@ var PRIVATE_DATA$4 = {
|
|
|
18581
18581
|
topics: [],
|
|
18582
18582
|
records: {},
|
|
18583
18583
|
gobj_nodes_tree: null,
|
|
18584
|
+
find_timer: null,
|
|
18585
|
+
focus_topic: "",
|
|
18584
18586
|
gobj_treedb_tables: null,
|
|
18585
18587
|
hook_data_viewer: null,
|
|
18586
18588
|
json_gobj: null,
|
|
@@ -18655,6 +18657,11 @@ function mt_stop$4(gobj) {
|
|
|
18655
18657
|
* Framework Method: Destroy
|
|
18656
18658
|
***************************************************************/
|
|
18657
18659
|
function mt_destroy$4(gobj) {
|
|
18660
|
+
let priv = gobj.priv;
|
|
18661
|
+
if (priv.find_timer) {
|
|
18662
|
+
clearTimeout(priv.find_timer);
|
|
18663
|
+
priv.find_timer = null;
|
|
18664
|
+
}
|
|
18658
18665
|
destroy_ui$1(gobj);
|
|
18659
18666
|
}
|
|
18660
18667
|
/***************************
|
|
@@ -18674,26 +18681,37 @@ function build_ui$4(gobj) {
|
|
|
18674
18681
|
class: "C_YUI_TREEDB_GRAPH",
|
|
18675
18682
|
style: `height:100%; display:flex; flex-direction:column;`
|
|
18676
18683
|
},
|
|
18677
|
-
[
|
|
18678
|
-
|
|
18679
|
-
|
|
18680
|
-
|
|
18681
|
-
|
|
18682
|
-
|
|
18683
|
-
|
|
18684
|
-
class: `GRAPH_BODY is-flex-grow-1 ${padding}`,
|
|
18685
|
-
style: "height:100%; min-height:0; overflow:hidden;"
|
|
18686
|
-
},
|
|
18687
|
-
[[
|
|
18684
|
+
[
|
|
18685
|
+
[
|
|
18686
|
+
"div",
|
|
18687
|
+
{ class: "GRAPH_TOOLBAR_ROW is-flex-grow-0 is-flex is-align-items-center" },
|
|
18688
|
+
$back ? [$back, $toolbar] : [$toolbar]
|
|
18689
|
+
],
|
|
18690
|
+
[
|
|
18688
18691
|
"div",
|
|
18689
18692
|
{
|
|
18690
|
-
|
|
18691
|
-
|
|
18692
|
-
style: "height:100%; min-height:0;border: 1px solid var(--bulma-border-weak);border-radius:0.2rem;"
|
|
18693
|
+
class: "GRAPH_LEGEND is-hidden is-flex-grow-0",
|
|
18694
|
+
style: "display:flex; flex-wrap:wrap; align-items:center; gap:.4rem; padding:.35rem .5rem;"
|
|
18693
18695
|
},
|
|
18694
18696
|
[]
|
|
18695
|
-
]
|
|
18696
|
-
|
|
18697
|
+
],
|
|
18698
|
+
[
|
|
18699
|
+
"div",
|
|
18700
|
+
{
|
|
18701
|
+
class: `GRAPH_BODY is-flex-grow-1 ${padding}`,
|
|
18702
|
+
style: "height:100%; min-height:0; overflow:hidden;"
|
|
18703
|
+
},
|
|
18704
|
+
[[
|
|
18705
|
+
"div",
|
|
18706
|
+
{
|
|
18707
|
+
id: priv.canvas_id,
|
|
18708
|
+
class: `GRAPH_CANVAS graph-container`,
|
|
18709
|
+
style: "height:100%; min-height:0;border: 1px solid var(--bulma-border-weak);border-radius:0.2rem;"
|
|
18710
|
+
},
|
|
18711
|
+
[]
|
|
18712
|
+
]]
|
|
18713
|
+
]
|
|
18714
|
+
]
|
|
18697
18715
|
]);
|
|
18698
18716
|
gobj_write_attr(gobj, "$container", $container);
|
|
18699
18717
|
refresh_language($container, t);
|
|
@@ -18761,7 +18779,7 @@ function destroy_ui$1(gobj) {
|
|
|
18761
18779
|
*
|
|
18762
18780
|
************************************************************/
|
|
18763
18781
|
function make_toolbar(gobj) {
|
|
18764
|
-
gobj.priv;
|
|
18782
|
+
let priv = gobj.priv;
|
|
18765
18783
|
let modes = gobj_read_attr(gobj, "operation_modes");
|
|
18766
18784
|
if (gobj_read_bool_attr(gobj, "readonly")) modes = modes.filter((mode) => mode !== "edition");
|
|
18767
18785
|
let left_items = [
|
|
@@ -18826,6 +18844,29 @@ function make_toolbar(gobj) {
|
|
|
18826
18844
|
gobj_send_event(gobj, "EV_REFRESH_TREEDB", { evt }, gobj);
|
|
18827
18845
|
} }
|
|
18828
18846
|
],
|
|
18847
|
+
[
|
|
18848
|
+
"button",
|
|
18849
|
+
{
|
|
18850
|
+
class: "GRAPH_LEGEND_BTN button ml-2",
|
|
18851
|
+
title: t("legend"),
|
|
18852
|
+
"aria-label": t("legend"),
|
|
18853
|
+
"data-i18n-title": "legend",
|
|
18854
|
+
"data-i18n-aria-label": "legend"
|
|
18855
|
+
},
|
|
18856
|
+
[["i", { class: "yi-square" }], [
|
|
18857
|
+
"span",
|
|
18858
|
+
{
|
|
18859
|
+
class: "is-hidden-mobile",
|
|
18860
|
+
style: "padding-left:5px;",
|
|
18861
|
+
i18n: "legend"
|
|
18862
|
+
},
|
|
18863
|
+
"legend"
|
|
18864
|
+
]],
|
|
18865
|
+
{ click: (evt) => {
|
|
18866
|
+
evt.stopPropagation();
|
|
18867
|
+
gobj_send_event(gobj, "EV_TOGGLE_LEGEND", {}, gobj);
|
|
18868
|
+
} }
|
|
18869
|
+
],
|
|
18829
18870
|
[
|
|
18830
18871
|
"button",
|
|
18831
18872
|
{
|
|
@@ -18870,7 +18911,12 @@ function make_toolbar(gobj) {
|
|
|
18870
18911
|
]],
|
|
18871
18912
|
{ input: (evt) => {
|
|
18872
18913
|
evt.stopPropagation();
|
|
18873
|
-
|
|
18914
|
+
let text = evt.target.value.trim();
|
|
18915
|
+
if (priv.find_timer) clearTimeout(priv.find_timer);
|
|
18916
|
+
priv.find_timer = setTimeout(function() {
|
|
18917
|
+
priv.find_timer = null;
|
|
18918
|
+
gobj_send_event(gobj, "EV_FIND_NODES", { text }, gobj);
|
|
18919
|
+
}, 250);
|
|
18874
18920
|
} }
|
|
18875
18921
|
], [
|
|
18876
18922
|
"div",
|
|
@@ -19830,6 +19876,86 @@ function ac_set_operation_mode$1(gobj, event, kw, src) {
|
|
|
19830
19876
|
* until its data is loaded).
|
|
19831
19877
|
************************************************************/
|
|
19832
19878
|
/************************************************************
|
|
19879
|
+
* Fill the legend strip with one entry per topic: a swatch in the
|
|
19880
|
+
* topic's colour and its name. The colours belong to the graph child —
|
|
19881
|
+
* it assigns them from its palette when the schema arrives — so they
|
|
19882
|
+
* are read from there and never guessed twice.
|
|
19883
|
+
*
|
|
19884
|
+
* An entry is a BUTTON: clicking it focuses that topic, clicking the
|
|
19885
|
+
* focused one clears the focus. The focus travels the same way a topic
|
|
19886
|
+
* card's graph icon travels — as EV_TOPIC_SELECTED, which the host turns
|
|
19887
|
+
* into the URL, so what you are looking at stays linkable.
|
|
19888
|
+
************************************************************/
|
|
19889
|
+
function refresh_legend(gobj) {
|
|
19890
|
+
let priv = gobj.priv;
|
|
19891
|
+
let $container = gobj_read_attr(gobj, "$container");
|
|
19892
|
+
if (!$container) return;
|
|
19893
|
+
let $legend = $container.querySelector(".GRAPH_LEGEND");
|
|
19894
|
+
if (!$legend) return;
|
|
19895
|
+
let descs = priv.gobj_nodes_tree ? gobj_read_attr(priv.gobj_nodes_tree, "descs") : null;
|
|
19896
|
+
$legend.textContent = "";
|
|
19897
|
+
if (!descs) return;
|
|
19898
|
+
for (const [topic_name, desc] of Object.entries(descs)) {
|
|
19899
|
+
if (topic_name.substring(0, 2) === "__") continue;
|
|
19900
|
+
if (!desc || !desc.color) continue;
|
|
19901
|
+
let focused = priv.focus_topic === topic_name;
|
|
19902
|
+
let $item = createElement2([
|
|
19903
|
+
"button",
|
|
19904
|
+
{
|
|
19905
|
+
class: "GRAPH_LEGEND_ITEM button is-small" + (focused ? " is-primary" : ""),
|
|
19906
|
+
title: topic_name,
|
|
19907
|
+
"aria-label": topic_name,
|
|
19908
|
+
"aria-pressed": focused ? "true" : "false"
|
|
19909
|
+
},
|
|
19910
|
+
[["span", {
|
|
19911
|
+
class: "GRAPH_LEGEND_SWATCH",
|
|
19912
|
+
style: `display:inline-block; width:.8rem; height:.8rem; border-radius:3px; margin-right:.4rem; background:${desc.color}; border:1px solid rgba(0,0,0,.25);`
|
|
19913
|
+
}], [
|
|
19914
|
+
"span",
|
|
19915
|
+
{},
|
|
19916
|
+
topic_name
|
|
19917
|
+
]],
|
|
19918
|
+
{ click: (evt) => {
|
|
19919
|
+
evt.stopPropagation();
|
|
19920
|
+
gobj_send_event(gobj, "EV_LEGEND_TOPIC", { topic: topic_name }, gobj);
|
|
19921
|
+
} }
|
|
19922
|
+
]);
|
|
19923
|
+
$legend.appendChild($item);
|
|
19924
|
+
}
|
|
19925
|
+
}
|
|
19926
|
+
/************************************************************
|
|
19927
|
+
*
|
|
19928
|
+
************************************************************/
|
|
19929
|
+
function ac_toggle_legend(gobj, event, kw, src) {
|
|
19930
|
+
let $container = gobj_read_attr(gobj, "$container");
|
|
19931
|
+
if (!$container) return 0;
|
|
19932
|
+
let $legend = $container.querySelector(".GRAPH_LEGEND");
|
|
19933
|
+
if (!$legend) {
|
|
19934
|
+
log_error(`${gobj_short_name(gobj)}: no legend strip to toggle`);
|
|
19935
|
+
return -1;
|
|
19936
|
+
}
|
|
19937
|
+
if ($legend.classList.contains("is-hidden")) {
|
|
19938
|
+
refresh_legend(gobj);
|
|
19939
|
+
$legend.classList.remove("is-hidden");
|
|
19940
|
+
} else $legend.classList.add("is-hidden");
|
|
19941
|
+
return 0;
|
|
19942
|
+
}
|
|
19943
|
+
/************************************************************
|
|
19944
|
+
* A legend entry was clicked: focus that topic, or clear the focus if
|
|
19945
|
+
* it was already the focused one. Published UP rather than applied
|
|
19946
|
+
* here, so the URL follows — the host owns the route.
|
|
19947
|
+
************************************************************/
|
|
19948
|
+
function ac_legend_topic(gobj, event, kw, src) {
|
|
19949
|
+
let priv = gobj.priv;
|
|
19950
|
+
let topic = kw && kw.topic || "";
|
|
19951
|
+
if (!topic) {
|
|
19952
|
+
log_error(`${gobj_short_name(gobj)}: legend click with no topic`);
|
|
19953
|
+
return -1;
|
|
19954
|
+
}
|
|
19955
|
+
gobj_publish_event(gobj, "EV_TOPIC_SELECTED", { topic: priv.focus_topic === topic ? "" : topic });
|
|
19956
|
+
return 0;
|
|
19957
|
+
}
|
|
19958
|
+
/************************************************************
|
|
19833
19959
|
* Forward the find down to the graph child.
|
|
19834
19960
|
************************************************************/
|
|
19835
19961
|
function ac_find_nodes$1(gobj, event, kw, src) {
|
|
@@ -19858,7 +19984,11 @@ function ac_find_result(gobj, event, kw, src) {
|
|
|
19858
19984
|
}
|
|
19859
19985
|
function ac_set_focus_topic(gobj, event, kw, src) {
|
|
19860
19986
|
let priv = gobj.priv;
|
|
19861
|
-
|
|
19987
|
+
priv.focus_topic = kw && kw.topic || "";
|
|
19988
|
+
if (priv.gobj_nodes_tree) gobj_send_event(priv.gobj_nodes_tree, "EV_FOCUS_TOPIC", { topic: priv.focus_topic }, gobj);
|
|
19989
|
+
let $container = gobj_read_attr(gobj, "$container");
|
|
19990
|
+
let $legend = $container ? $container.querySelector(".GRAPH_LEGEND") : null;
|
|
19991
|
+
if ($legend && !$legend.classList.contains("is-hidden")) refresh_legend(gobj);
|
|
19862
19992
|
return 0;
|
|
19863
19993
|
}
|
|
19864
19994
|
/************************************************************
|
|
@@ -20026,6 +20156,16 @@ function create_gclass$4(gclass_name) {
|
|
|
20026
20156
|
ac_find_nodes$1,
|
|
20027
20157
|
null
|
|
20028
20158
|
],
|
|
20159
|
+
[
|
|
20160
|
+
"EV_TOGGLE_LEGEND",
|
|
20161
|
+
ac_toggle_legend,
|
|
20162
|
+
null
|
|
20163
|
+
],
|
|
20164
|
+
[
|
|
20165
|
+
"EV_LEGEND_TOPIC",
|
|
20166
|
+
ac_legend_topic,
|
|
20167
|
+
null
|
|
20168
|
+
],
|
|
20029
20169
|
[
|
|
20030
20170
|
"EV_FIND_RESULT",
|
|
20031
20171
|
ac_find_result,
|
|
@@ -20074,6 +20214,9 @@ function create_gclass$4(gclass_name) {
|
|
|
20074
20214
|
["EV_SET_FOCUS_TOPIC", 0],
|
|
20075
20215
|
["EV_FIND_NODES", 0],
|
|
20076
20216
|
["EV_FIND_RESULT", 0],
|
|
20217
|
+
["EV_TOGGLE_LEGEND", 0],
|
|
20218
|
+
["EV_LEGEND_TOPIC", 0],
|
|
20219
|
+
["EV_TOPIC_SELECTED", event_flag_t.EVF_OUTPUT_EVENT | event_flag_t.EVF_NO_WARN_SUBS],
|
|
20077
20220
|
["EV_OPERATION_MODE_CHANGED", event_flag_t.EVF_OUTPUT_EVENT | event_flag_t.EVF_NO_WARN_SUBS],
|
|
20078
20221
|
["EV_RECORD_WRITTEN", event_flag_t.EVF_OUTPUT_EVENT | event_flag_t.EVF_NO_WARN_SUBS],
|
|
20079
20222
|
["EV_SHOW", 0],
|
|
@@ -52629,6 +52772,8 @@ ensure_drag_canvas_patch();
|
|
|
52629
52772
|
* Constants
|
|
52630
52773
|
***************************************************************/
|
|
52631
52774
|
var GCLASS_NAME$1 = "C_G6_NODES_TREE";
|
|
52775
|
+
var HIGHLIGHT_COLOR = "#f0a020";
|
|
52776
|
+
var HIGHLIGHT_HALO = "rgba(240,160,32,0.35)";
|
|
52632
52777
|
/***************************************************************
|
|
52633
52778
|
* Internal layout and operation mode definitions
|
|
52634
52779
|
***************************************************************/
|
|
@@ -52678,6 +52823,7 @@ var attrs_table$1 = [
|
|
|
52678
52823
|
SDATA(data_type_t.DTP_BOOLEAN, "with_gridline", 0, true, "Use gridline plugin"),
|
|
52679
52824
|
SDATA(data_type_t.DTP_BOOLEAN, "with_fullscreen", 0, true, "Use fullscreen plugin"),
|
|
52680
52825
|
SDATA(data_type_t.DTP_BOOLEAN, "with_toolbar", 0, true, "Use toolbar plugin"),
|
|
52826
|
+
SDATA(data_type_t.DTP_INTEGER, "minimap_min_nodes", 0, 30, "Show the minimap from this many nodes on (0 = never). A minimap of a graph that fits on screen is decoration; one of two hundred cards is the only way to know where you are"),
|
|
52681
52827
|
SDATA(data_type_t.DTP_STRING, "toolbar_position", 0, "right-top", "Toolbar position: top-left, top-right, bottom-left, bottom-right, left-top, right-top"),
|
|
52682
52828
|
SDATA(data_type_t.DTP_LIST, "layout_names", sdata_flag_t.SDF_RD, JSON.stringify(Object.keys(_layouts)), "Available layout names (read-only, for parent to query)"),
|
|
52683
52829
|
SDATA(data_type_t.DTP_STRING, "hook_port_position", 0, "bottom", "Hook port position"),
|
|
@@ -53905,10 +54051,12 @@ function graph_focus_topic(gobj, topic) {
|
|
|
53905
54051
|
if (ids.length === 0) log_warning(`${gobj_short_name(gobj)}: focus topic '${topic}' has no nodes`);
|
|
53906
54052
|
for (let id of ids) states[id] = ["active"];
|
|
53907
54053
|
}
|
|
54054
|
+
let prev_ids = priv._focus_ids || [];
|
|
53908
54055
|
priv._focus_ids = ids;
|
|
53909
54056
|
priv._focus_topic = topic || null;
|
|
53910
54057
|
try {
|
|
53911
54058
|
if (typeof graph.setElementState === "function") graph.setElementState(states);
|
|
54059
|
+
apply_node_highlight(gobj, prev_ids, ids);
|
|
53912
54060
|
if (ids.length && typeof graph.focusElement === "function") graph.focusElement(ids);
|
|
53913
54061
|
} catch (e) {
|
|
53914
54062
|
log_error(`${gobj_short_name(gobj)}: focus topic apply failed: ${e}`);
|
|
@@ -53965,10 +54113,12 @@ function graph_find_nodes(gobj, term) {
|
|
|
53965
54113
|
}
|
|
53966
54114
|
for (let id of ids) states[id] = ["active"];
|
|
53967
54115
|
}
|
|
54116
|
+
let prev_ids = priv._focus_ids || [];
|
|
53968
54117
|
priv._focus_ids = ids;
|
|
53969
54118
|
priv._focus_topic = null;
|
|
53970
54119
|
try {
|
|
53971
54120
|
if (typeof graph.setElementState === "function") graph.setElementState(states);
|
|
54121
|
+
apply_node_highlight(gobj, prev_ids, ids);
|
|
53972
54122
|
if (ids.length && typeof graph.focusElement === "function") graph.focusElement(ids);
|
|
53973
54123
|
} catch (e) {
|
|
53974
54124
|
log_error(`${gobj_short_name(gobj)}: find apply failed: ${e}`);
|
|
@@ -55512,27 +55662,121 @@ function show_node_detail_popover(gobj, node_id) {
|
|
|
55512
55662
|
* not re-themed by setTheme()) are regenerated; structural
|
|
55513
55663
|
* junction diamonds get their neutral fill/stroke re-themed.
|
|
55514
55664
|
************************************************************/
|
|
55515
|
-
|
|
55665
|
+
/************************************************************
|
|
55666
|
+
* Show or hide the minimap, deciding by the SIZE of the graph.
|
|
55667
|
+
*
|
|
55668
|
+
* A minimap of a graph that already fits on screen is decoration; one
|
|
55669
|
+
* of two hundred cards is the only way to know where you are. So it is
|
|
55670
|
+
* not a preference the reader has to find and set — it appears when
|
|
55671
|
+
* there is something to be lost in, from `minimap_min_nodes` on.
|
|
55672
|
+
*
|
|
55673
|
+
* Its shapes are drawn by hand. G6's minimap clones each element's key
|
|
55674
|
+
* shape into its own canvas, and every node here is an `html` node
|
|
55675
|
+
* whose key shape is a DOM element — the same reason the `active`
|
|
55676
|
+
* state never painted (see HIGHLIGHT_COLOR). A block in the topic's
|
|
55677
|
+
* colour is also what a minimap of cards SHOULD show: at that scale a
|
|
55678
|
+
* card is a rectangle anyway.
|
|
55679
|
+
************************************************************/
|
|
55680
|
+
function refresh_minimap(gobj) {
|
|
55516
55681
|
let graph = gobj.priv.graph;
|
|
55517
55682
|
if (!graph) return;
|
|
55683
|
+
let threshold = gobj_read_integer_attr(gobj, "minimap_min_nodes");
|
|
55684
|
+
let n = 0;
|
|
55685
|
+
try {
|
|
55686
|
+
let data = graph.getData() || {};
|
|
55687
|
+
n = is_array(data.nodes) ? data.nodes.length : 0;
|
|
55688
|
+
} catch (e) {
|
|
55689
|
+
n = 0;
|
|
55690
|
+
}
|
|
55691
|
+
if (!threshold || n < threshold) {
|
|
55692
|
+
graph_remove_plugin(gobj, "minimap");
|
|
55693
|
+
return;
|
|
55694
|
+
}
|
|
55695
|
+
if (graph_get_plugin(gobj, "minimap")) return;
|
|
55696
|
+
graph_add_plugin(gobj, "minimap", {
|
|
55697
|
+
size: [200, 140],
|
|
55698
|
+
position: "bottom-left",
|
|
55699
|
+
shape: (id, element_type, element) => {
|
|
55700
|
+
if (element_type !== "node") return element;
|
|
55701
|
+
try {
|
|
55702
|
+
let nd = graph.getNodeData(id);
|
|
55703
|
+
let size = nd && nd.style && nd.style.size || [120, 60];
|
|
55704
|
+
let color = nd && nd.data && nd.data.desc && nd.data.desc.color || "#94a3b8";
|
|
55705
|
+
return new Rect({ style: {
|
|
55706
|
+
x: -size[0] / 2,
|
|
55707
|
+
y: -size[1] / 2,
|
|
55708
|
+
width: size[0],
|
|
55709
|
+
height: size[1],
|
|
55710
|
+
fill: color,
|
|
55711
|
+
radius: 4
|
|
55712
|
+
} });
|
|
55713
|
+
} catch (e) {
|
|
55714
|
+
log_error(`${gobj_short_name(gobj)}: minimap shape failed: ${e}`);
|
|
55715
|
+
return element;
|
|
55716
|
+
}
|
|
55717
|
+
}
|
|
55718
|
+
});
|
|
55719
|
+
}
|
|
55720
|
+
/************************************************************
|
|
55721
|
+
* The innerHTML of ONE node, in the given theme and highlight state.
|
|
55722
|
+
* The three treedb tiers (hierarchical / extended / child) each have
|
|
55723
|
+
* their own card, and both the theme refresh and the highlight need the
|
|
55724
|
+
* same three-way choice — it lived inline in the theme refresh and is
|
|
55725
|
+
* shared now. Returns null for a node that carries no desc.
|
|
55726
|
+
************************************************************/
|
|
55727
|
+
function node_innerHTML_of(nd, theme, highlight) {
|
|
55728
|
+
if (!nd || !nd.data || !nd.data.desc) return null;
|
|
55729
|
+
let desc = nd.data.desc;
|
|
55730
|
+
let record = nd.data.record || {};
|
|
55731
|
+
let label = node_label(desc, record);
|
|
55732
|
+
switch (desc.node_treedb_type) {
|
|
55733
|
+
case "child": return build_chip_innerHTML(desc.color, theme, record.icon, label, record.id, highlight);
|
|
55734
|
+
case "extended": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, true, record.id, highlight);
|
|
55735
|
+
case "hierarchical": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, false, record.id, highlight);
|
|
55736
|
+
}
|
|
55737
|
+
return null;
|
|
55738
|
+
}
|
|
55739
|
+
/************************************************************
|
|
55740
|
+
* Repaint the cards whose highlight state CHANGES: the ones that had it
|
|
55741
|
+
* and lose it, plus the ones that gain it. Only those — a treedb graph
|
|
55742
|
+
* is redrawn per keystroke of the find box otherwise.
|
|
55743
|
+
************************************************************/
|
|
55744
|
+
function apply_node_highlight(gobj, prev_ids, next_ids) {
|
|
55745
|
+
let priv = gobj.priv;
|
|
55746
|
+
let graph = priv.graph;
|
|
55747
|
+
if (!graph) return;
|
|
55748
|
+
let next = new Set(next_ids || []);
|
|
55749
|
+
let touched = /* @__PURE__ */ new Set([...prev_ids || [], ...next]);
|
|
55750
|
+
if (touched.size === 0) return;
|
|
55751
|
+
let updates = [];
|
|
55752
|
+
for (let id of touched) {
|
|
55753
|
+
let html = node_innerHTML_of(graph.getNodeData(id), priv.theme, next.has(id));
|
|
55754
|
+
if (html !== null) updates.push({
|
|
55755
|
+
id,
|
|
55756
|
+
style: { innerHTML: html }
|
|
55757
|
+
});
|
|
55758
|
+
}
|
|
55759
|
+
if (!updates.length) return;
|
|
55760
|
+
try {
|
|
55761
|
+
graph.updateNodeData(updates);
|
|
55762
|
+
graph.draw();
|
|
55763
|
+
} catch (e) {
|
|
55764
|
+
log_error(`${gobj_short_name(gobj)}: cannot repaint the highlight: ${e}`);
|
|
55765
|
+
}
|
|
55766
|
+
}
|
|
55767
|
+
function refresh_html_nodes_theme(gobj, theme) {
|
|
55768
|
+
let priv = gobj.priv;
|
|
55769
|
+
let graph = priv.graph;
|
|
55770
|
+
if (!graph) return;
|
|
55518
55771
|
let nodes = graph.getData().nodes || [];
|
|
55772
|
+
let highlighted = new Set(priv._focus_ids || []);
|
|
55519
55773
|
let updates = [];
|
|
55520
55774
|
for (let i = 0; i < nodes.length; i++) {
|
|
55521
|
-
let
|
|
55522
|
-
|
|
55523
|
-
|
|
55524
|
-
|
|
55525
|
-
|
|
55526
|
-
id: nodes[i].id,
|
|
55527
|
-
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) }
|
|
55528
|
-
});
|
|
55529
|
-
else if (tt === "child") updates.push({
|
|
55530
|
-
id: nodes[i].id,
|
|
55531
|
-
style: { innerHTML: build_chip_innerHTML(nd.data.desc.color, theme, record.icon, node_label(nd.data.desc, record), record.id) }
|
|
55532
|
-
});
|
|
55533
|
-
else if (tt === "extended") updates.push({
|
|
55534
|
-
id: nodes[i].id,
|
|
55535
|
-
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) }
|
|
55775
|
+
let id = nodes[i].id;
|
|
55776
|
+
let html = node_innerHTML_of(graph.getNodeData(id), theme, highlighted.has(id));
|
|
55777
|
+
if (html !== null) updates.push({
|
|
55778
|
+
id,
|
|
55779
|
+
style: { innerHTML: html }
|
|
55536
55780
|
});
|
|
55537
55781
|
}
|
|
55538
55782
|
if (updates.length > 0) graph.updateNodeData(updates);
|
|
@@ -55564,12 +55808,13 @@ function refresh_default_edges_theme(gobj, theme) {
|
|
|
55564
55808
|
* but lighter (1px border, no shadow, single line). The name is
|
|
55565
55809
|
* always legible (ellipsis + native title tooltip on overflow).
|
|
55566
55810
|
************************************************************/
|
|
55567
|
-
function build_chip_innerHTML(color, theme, icon, label, key) {
|
|
55811
|
+
function build_chip_innerHTML(color, theme, icon, label, key, highlight) {
|
|
55568
55812
|
let title = key || label;
|
|
55569
55813
|
let dark = theme === "dark";
|
|
55570
55814
|
let bg = dark ? `color-mix(in srgb, ${color} 30%, #2c3542)` : `color-mix(in srgb, ${color} 10%, ${dark ? "#1b2230" : "#ffffff"})`;
|
|
55571
55815
|
let border = dark ? `color-mix(in srgb, ${color} 85%, #ffffff)` : color;
|
|
55572
55816
|
let text_color = dark ? "#e8eaed" : "#0f172a";
|
|
55817
|
+
if (highlight) border = HIGHLIGHT_COLOR;
|
|
55573
55818
|
let icon_html = "";
|
|
55574
55819
|
if (icon) icon_html = `<img src="${safeSrc(icon)}" alt="" style="
|
|
55575
55820
|
width: 16px; height: 16px; object-fit: contain;
|
|
@@ -55581,7 +55826,8 @@ function build_chip_innerHTML(color, theme, icon, label, key) {
|
|
|
55581
55826
|
width: 100%;
|
|
55582
55827
|
height: 100%;
|
|
55583
55828
|
background: ${bg};
|
|
55584
|
-
border: 1px solid ${border};
|
|
55829
|
+
border: ${highlight ? "3px" : "1px"} solid ${border};
|
|
55830
|
+
${highlight ? `box-shadow: 0 0 0 4px ${HIGHLIGHT_HALO};` : ""}
|
|
55585
55831
|
border-radius: 8px;
|
|
55586
55832
|
color: ${text_color};
|
|
55587
55833
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
@@ -55607,7 +55853,7 @@ function build_chip_innerHTML(color, theme, icon, label, key) {
|
|
|
55607
55853
|
* colour is kept (per-topic differentiation) but softened via
|
|
55608
55854
|
* color-mix instead of a harsh saturated fill. Theme-aware.
|
|
55609
55855
|
************************************************************/
|
|
55610
|
-
function build_node_innerHTML(color, theme, icon, label, topic_name, structural, key) {
|
|
55856
|
+
function build_node_innerHTML(color, theme, icon, label, topic_name, structural, key, highlight) {
|
|
55611
55857
|
let title = key || label;
|
|
55612
55858
|
let dark = theme === "dark";
|
|
55613
55859
|
let surface = dark ? "#1b2230" : "#ffffff";
|
|
@@ -55621,6 +55867,10 @@ function build_node_innerHTML(color, theme, icon, label, topic_name, structural,
|
|
|
55621
55867
|
border = dark ? `color-mix(in srgb, ${color} 85%, #ffffff)` : color;
|
|
55622
55868
|
border_style = "solid";
|
|
55623
55869
|
}
|
|
55870
|
+
if (highlight) {
|
|
55871
|
+
border = HIGHLIGHT_COLOR;
|
|
55872
|
+
border_style = "solid";
|
|
55873
|
+
}
|
|
55624
55874
|
let title_color = dark ? "#e8eaed" : "#0f172a";
|
|
55625
55875
|
let sub_color = dark ? "#9aa4b2" : "#64748b";
|
|
55626
55876
|
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)";
|
|
@@ -55643,9 +55893,9 @@ function build_node_innerHTML(color, theme, icon, label, topic_name, structural,
|
|
|
55643
55893
|
width: 100%;
|
|
55644
55894
|
height: 100%;
|
|
55645
55895
|
background: ${bg};
|
|
55646
|
-
border: 1.5px ${border_style} ${border};
|
|
55896
|
+
border: ${highlight ? "3px" : "1.5px"} ${border_style} ${border};
|
|
55647
55897
|
border-radius: 10px;
|
|
55648
|
-
box-shadow: ${shadow};
|
|
55898
|
+
box-shadow: ${highlight ? `0 0 0 4px ${HIGHLIGHT_HALO}, ${shadow}` : shadow};
|
|
55649
55899
|
color: ${title_color};
|
|
55650
55900
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
55651
55901
|
display: flex;
|
|
@@ -56264,6 +56514,7 @@ function ac_load_data(gobj, event, kw, src) {
|
|
|
56264
56514
|
graph_layout(gobj).then(() => {
|
|
56265
56515
|
if (priv.edit_mode) graph_add_plugin(gobj, "history");
|
|
56266
56516
|
else graph_remove_plugin(gobj, "history");
|
|
56517
|
+
refresh_minimap(gobj);
|
|
56267
56518
|
if (priv._pending_focus_topic !== null) {
|
|
56268
56519
|
let ft = priv._pending_focus_topic;
|
|
56269
56520
|
priv._pending_focus_topic = null;
|