@yuneta/gobj-ui 7.14.3 → 7.16.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 +90 -0
- package/dist/gobj-ui.cjs.js +260 -47
- package/dist/gobj-ui.es.js +260 -47
- package/package.json +1 -1
- package/src/c_g6_nodes_tree.js +431 -58
- package/src/lib_graph.css +70 -4
package/dist/gobj-ui.es.js
CHANGED
|
@@ -53689,11 +53689,22 @@ function inject_svg_icons() {
|
|
|
53689
53689
|
***********************************************************************/
|
|
53690
53690
|
/***************************************************************
|
|
53691
53691
|
* YuiToolbar — G6 Toolbar subclass that adds per-item className
|
|
53692
|
-
* and disabled support.
|
|
53692
|
+
* and disabled support, plus three item kinds G6 does not have.
|
|
53693
53693
|
*
|
|
53694
53694
|
* Each item in getItems() may carry:
|
|
53695
53695
|
* className — CSS class added to the div (e.g. 'EV_SAVE_GRAPH')
|
|
53696
53696
|
* disabled — boolean; sets the 'disabled' attribute initially
|
|
53697
|
+
* text — render this text instead of a sprite symbol; a
|
|
53698
|
+
* label is the only readable way to say `1:1`, and
|
|
53699
|
+
* every editor that offers actual-size writes it
|
|
53700
|
+
* readout — a text item that REPORTS instead of acting (the
|
|
53701
|
+
* zoom level); it is not a button
|
|
53702
|
+
* separator — a group divider, not an item
|
|
53703
|
+
*
|
|
53704
|
+
* The base class fires onClick only for elements whose class list
|
|
53705
|
+
* contains `g6-toolbar-item`, so a separator and a readout carry
|
|
53706
|
+
* their own class and are inert by construction, with no guard in
|
|
53707
|
+
* the click handler.
|
|
53697
53708
|
*
|
|
53698
53709
|
* With className set to the event name, the lib_graph.js state
|
|
53699
53710
|
* functions (set_submit_state, disableElements, …) work on toolbar
|
|
@@ -53703,9 +53714,15 @@ function inject_svg_icons() {
|
|
|
53703
53714
|
var YuiToolbar = class extends Toolbar {
|
|
53704
53715
|
async getDOMContent() {
|
|
53705
53716
|
return (await this.options.getItems()).map((item) => {
|
|
53717
|
+
if (item.separator) return `<div class="g6-toolbar-sep" aria-hidden="true"></div>`;
|
|
53706
53718
|
const extra_class = item.className ? ` ${item.className}` : "";
|
|
53719
|
+
const title = item.title ?? "";
|
|
53720
|
+
if (item.readout) return `<div class="g6-toolbar-readout${extra_class}" title="${title}" aria-label="${title}">${item.text ?? ""}</div>`;
|
|
53707
53721
|
const disabled = item.disabled ? " disabled" : "";
|
|
53708
|
-
|
|
53722
|
+
const is_text = item.text !== void 0;
|
|
53723
|
+
const kind_class = is_text ? " g6-toolbar-item-text" : "";
|
|
53724
|
+
const body = is_text ? `<span class="g6-toolbar-text">${item.text}</span>` : `<svg aria-hidden="true" focusable="false"><use xlink:href="#${item.id}"></use></svg>`;
|
|
53725
|
+
return `<div class="g6-toolbar-item${kind_class}${extra_class}" value="${item.value}" title="${title}" aria-label="${title}"${disabled}>${body}</div>`;
|
|
53709
53726
|
}).join("");
|
|
53710
53727
|
}
|
|
53711
53728
|
};
|
|
@@ -53717,6 +53734,7 @@ ensure_drag_canvas_patch();
|
|
|
53717
53734
|
var GCLASS_NAME$1 = "C_G6_NODES_TREE";
|
|
53718
53735
|
var HIGHLIGHT_COLOR = "#f0a020";
|
|
53719
53736
|
var HIGHLIGHT_HALO = "rgba(240,160,32,0.35)";
|
|
53737
|
+
var SELECT_RING = "rgba(59,130,246,0.95)";
|
|
53720
53738
|
/***************************************************************
|
|
53721
53739
|
* Internal layout and operation mode definitions
|
|
53722
53740
|
***************************************************************/
|
|
@@ -53828,6 +53846,7 @@ var PRIVATE_DATA$1 = {
|
|
|
53828
53846
|
_link_saved_styles: [],
|
|
53829
53847
|
_focus_topic: null,
|
|
53830
53848
|
_focus_ids: [],
|
|
53849
|
+
_selected_paint_ids: [],
|
|
53831
53850
|
_pending_focus_topic: null,
|
|
53832
53851
|
_pending_find: null,
|
|
53833
53852
|
_layout_asked: "",
|
|
@@ -54050,6 +54069,7 @@ function configure_events(gobj) {
|
|
|
54050
54069
|
update_edge_icon_position(gobj);
|
|
54051
54070
|
update_node_icon_position(gobj);
|
|
54052
54071
|
update_link_icon_position(gobj);
|
|
54072
|
+
update_zoom_readout(gobj);
|
|
54053
54073
|
});
|
|
54054
54074
|
priv._on_language_changed = () => {
|
|
54055
54075
|
update_toolbar(gobj);
|
|
@@ -54115,6 +54135,59 @@ function update_toolbar(gobj) {
|
|
|
54115
54135
|
configure_toolbar_edit(gobj);
|
|
54116
54136
|
if (graph_get_plugin(gobj, "toolbar-edit")) graph.updatePlugin({ key: "toolbar-edit" });
|
|
54117
54137
|
}
|
|
54138
|
+
/************************************************************
|
|
54139
|
+
* The floating toolbars follow the theme.
|
|
54140
|
+
*
|
|
54141
|
+
* They used to be pinned to a light background in BOTH themes,
|
|
54142
|
+
* with the icon colour pinned dark so it survived that -- two
|
|
54143
|
+
* light islands sitting over a dark canvas. The tokens do the
|
|
54144
|
+
* flipping now; the fallbacks are the old forced-light values, so
|
|
54145
|
+
* a host without Bulma gets exactly what it had.
|
|
54146
|
+
************************************************************/
|
|
54147
|
+
function toolbar_style(extra) {
|
|
54148
|
+
return Object.assign({
|
|
54149
|
+
backgroundColor: "var(--bulma-scheme-main, #f5f5f5)",
|
|
54150
|
+
color: "var(--bulma-text-strong, #333)",
|
|
54151
|
+
padding: "8px",
|
|
54152
|
+
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.15)",
|
|
54153
|
+
borderRadius: "8px",
|
|
54154
|
+
border: "1px solid var(--bulma-border-weak, #e8e8e8)",
|
|
54155
|
+
opacity: "0.85"
|
|
54156
|
+
}, extra || {});
|
|
54157
|
+
}
|
|
54158
|
+
/************************************************************
|
|
54159
|
+
* The zoom level as a percentage, the way every editor that
|
|
54160
|
+
* shows one writes it. Empty while the graph cannot be asked --
|
|
54161
|
+
* the toolbar is built before the first draw, and a viewport
|
|
54162
|
+
* that does not exist yet has no zoom to report.
|
|
54163
|
+
************************************************************/
|
|
54164
|
+
function zoom_percent_text(gobj) {
|
|
54165
|
+
let graph = gobj.priv.graph;
|
|
54166
|
+
if (!graph || typeof graph.getZoom !== "function") return "";
|
|
54167
|
+
let zoom;
|
|
54168
|
+
try {
|
|
54169
|
+
zoom = graph.getZoom();
|
|
54170
|
+
} catch (e) {
|
|
54171
|
+
return "";
|
|
54172
|
+
}
|
|
54173
|
+
if (!zoom) return "";
|
|
54174
|
+
return `${Math.round(zoom * 100)}%`;
|
|
54175
|
+
}
|
|
54176
|
+
/************************************************************
|
|
54177
|
+
* Repaint the zoom readout in place.
|
|
54178
|
+
*
|
|
54179
|
+
* The text node is patched instead of re-rendering the plugin:
|
|
54180
|
+
* the readout follows the wheel, and updatePlugin() rebuilds the
|
|
54181
|
+
* whole toolbar's innerHTML -- which would also drop the disabled
|
|
54182
|
+
* state of the edit buttons on every notch of the wheel.
|
|
54183
|
+
************************************************************/
|
|
54184
|
+
function update_zoom_readout(gobj) {
|
|
54185
|
+
let $container = gobj_read_attr(gobj, "$container");
|
|
54186
|
+
if (!$container) return;
|
|
54187
|
+
let $readout = $container.querySelector(".G6_ZOOM_LEVEL");
|
|
54188
|
+
if (!$readout) return;
|
|
54189
|
+
$readout.textContent = zoom_percent_text(gobj);
|
|
54190
|
+
}
|
|
54118
54191
|
function configure_toolbar(gobj) {
|
|
54119
54192
|
let priv = gobj.priv;
|
|
54120
54193
|
let toolbar_position = gobj_read_str_attr(gobj, "toolbar_position") || "top-left";
|
|
@@ -54123,17 +54196,10 @@ function configure_toolbar(gobj) {
|
|
|
54123
54196
|
type: "yui-toolbar",
|
|
54124
54197
|
className: "g6-toolbar-large",
|
|
54125
54198
|
position: toolbar_position,
|
|
54126
|
-
style: {
|
|
54127
|
-
backgroundColor: "#f5f5f5",
|
|
54128
|
-
color: "#333",
|
|
54129
|
-
padding: "8px",
|
|
54130
|
-
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.15)",
|
|
54131
|
-
borderRadius: "8px",
|
|
54132
|
-
border: "1px solid #e8e8e8",
|
|
54133
|
-
opacity: "0.85",
|
|
54199
|
+
style: toolbar_style({
|
|
54134
54200
|
marginTop: "12px",
|
|
54135
54201
|
marginLeft: "12px"
|
|
54136
|
-
},
|
|
54202
|
+
}),
|
|
54137
54203
|
getItems: () => {
|
|
54138
54204
|
let items = [
|
|
54139
54205
|
{
|
|
@@ -54148,6 +54214,13 @@ function configure_toolbar(gobj) {
|
|
|
54148
54214
|
className: "EV_ZOOM_OUT",
|
|
54149
54215
|
title: t("zoom out")
|
|
54150
54216
|
},
|
|
54217
|
+
{
|
|
54218
|
+
readout: true,
|
|
54219
|
+
className: "G6_ZOOM_LEVEL",
|
|
54220
|
+
text: zoom_percent_text(gobj),
|
|
54221
|
+
title: t("zoom level")
|
|
54222
|
+
},
|
|
54223
|
+
{ separator: true },
|
|
54151
54224
|
{
|
|
54152
54225
|
id: "g6-icon-fit",
|
|
54153
54226
|
value: "auto-fit",
|
|
@@ -54155,13 +54228,14 @@ function configure_toolbar(gobj) {
|
|
|
54155
54228
|
title: t("auto fit")
|
|
54156
54229
|
},
|
|
54157
54230
|
{
|
|
54158
|
-
|
|
54231
|
+
text: "1:1",
|
|
54159
54232
|
value: "reset",
|
|
54160
54233
|
className: "EV_ZOOM_RESET",
|
|
54161
|
-
title: t("
|
|
54234
|
+
title: t("actual size")
|
|
54162
54235
|
}
|
|
54163
54236
|
];
|
|
54164
54237
|
if (gobj_read_bool_attr(gobj, "with_fullscreen")) {
|
|
54238
|
+
items.push({ separator: true });
|
|
54165
54239
|
if (priv.is_fullscreen) items.push({
|
|
54166
54240
|
id: "g6-icon-fullscreen-exit",
|
|
54167
54241
|
value: "exit-fullscreen",
|
|
@@ -54217,15 +54291,7 @@ function configure_toolbar_edit(gobj) {
|
|
|
54217
54291
|
type: "yui-toolbar",
|
|
54218
54292
|
className: "g6-toolbar-large",
|
|
54219
54293
|
position: "left-top",
|
|
54220
|
-
style:
|
|
54221
|
-
backgroundColor: "#f5f5f5",
|
|
54222
|
-
color: "#333",
|
|
54223
|
-
padding: "8px",
|
|
54224
|
-
boxShadow: "0 2px 8px rgba(0, 0, 0, 0.15)",
|
|
54225
|
-
borderRadius: "8px",
|
|
54226
|
-
border: "1px solid #e8e8e8",
|
|
54227
|
-
opacity: "0.85"
|
|
54228
|
-
},
|
|
54294
|
+
style: toolbar_style(),
|
|
54229
54295
|
getItems: () => {
|
|
54230
54296
|
return [
|
|
54231
54297
|
{
|
|
@@ -54301,9 +54367,24 @@ function configure_behaviour(gobj) {
|
|
|
54301
54367
|
case "edition":
|
|
54302
54368
|
priv.edit_mode = true;
|
|
54303
54369
|
behaviors = [
|
|
54304
|
-
|
|
54370
|
+
{
|
|
54371
|
+
type: "drag-canvas",
|
|
54372
|
+
key: "drag-canvas",
|
|
54373
|
+
enable: (event) => !event.shiftKey
|
|
54374
|
+
},
|
|
54305
54375
|
"zoom-canvas",
|
|
54306
|
-
"drag-element"
|
|
54376
|
+
"drag-element",
|
|
54377
|
+
{
|
|
54378
|
+
type: "brush-select",
|
|
54379
|
+
key: "brush-select",
|
|
54380
|
+
trigger: ["shift"],
|
|
54381
|
+
enableElements: ["node"],
|
|
54382
|
+
immediately: false,
|
|
54383
|
+
onSelect: (states) => {
|
|
54384
|
+
let ids = Object.keys(states || {}).filter((id) => (states[id] || []).includes("selected"));
|
|
54385
|
+
gobj_send_event(gobj, "EV_BRUSH_SELECT", { ids }, gobj);
|
|
54386
|
+
}
|
|
54387
|
+
}
|
|
54307
54388
|
];
|
|
54308
54389
|
break;
|
|
54309
54390
|
case "operation":
|
|
@@ -55418,6 +55499,81 @@ function perform_history_op(gobj, is_redo) {
|
|
|
55418
55499
|
sync_history_to_backend(gobj, cmd ? cmd.original : null);
|
|
55419
55500
|
}
|
|
55420
55501
|
}
|
|
55502
|
+
/************************************************************
|
|
55503
|
+
* The selection.
|
|
55504
|
+
*
|
|
55505
|
+
* G6's `selected` element state IS the selection: `drag-element`
|
|
55506
|
+
* reads it (`getElementDataByState`) to decide what a drag moves,
|
|
55507
|
+
* so keeping the set anywhere else would be a second truth the
|
|
55508
|
+
* drag does not consult. What this gclass keeps is what is
|
|
55509
|
+
* PAINTED -- an html node draws no state style at all (its key
|
|
55510
|
+
* shape is a DOM element), so the ring lives in the card's own
|
|
55511
|
+
* html, exactly like the find highlight, and the painted set
|
|
55512
|
+
* exists to diff the repaint.
|
|
55513
|
+
************************************************************/
|
|
55514
|
+
function selected_node_ids(gobj) {
|
|
55515
|
+
let graph = gobj.priv.graph;
|
|
55516
|
+
if (!graph) return [];
|
|
55517
|
+
let data;
|
|
55518
|
+
try {
|
|
55519
|
+
data = graph.getElementDataByState("node", "selected") || [];
|
|
55520
|
+
} catch (e) {
|
|
55521
|
+
return [];
|
|
55522
|
+
}
|
|
55523
|
+
return data.map((nd) => nd.id);
|
|
55524
|
+
}
|
|
55525
|
+
/************************************************************
|
|
55526
|
+
* Move the ring to these nodes and off the ones that had it.
|
|
55527
|
+
************************************************************/
|
|
55528
|
+
function paint_selection(gobj, ids) {
|
|
55529
|
+
let priv = gobj.priv;
|
|
55530
|
+
let prev = priv._selected_paint_ids || [];
|
|
55531
|
+
let next = ids || [];
|
|
55532
|
+
priv._selected_paint_ids = next;
|
|
55533
|
+
repaint_cards(gobj, /* @__PURE__ */ new Set([...prev, ...next]));
|
|
55534
|
+
}
|
|
55535
|
+
/************************************************************
|
|
55536
|
+
* Select a SET of nodes: what a marquee and a shift-click do.
|
|
55537
|
+
*
|
|
55538
|
+
* It leaves `_selected_node_id` null even for a set of one,
|
|
55539
|
+
* because that field is not "the selection", it is "the node
|
|
55540
|
+
* opened for editing" -- the resize handles, the ports and the
|
|
55541
|
+
* popovers hang off it, and none of them means anything over a
|
|
55542
|
+
* set. Clicking a node is what opens one (`select_node`); a
|
|
55543
|
+
* marquee selects, it does not open.
|
|
55544
|
+
************************************************************/
|
|
55545
|
+
function set_selection(gobj, ids) {
|
|
55546
|
+
let graph = gobj.priv.graph;
|
|
55547
|
+
let next = [];
|
|
55548
|
+
for (let id of ids || []) try {
|
|
55549
|
+
if (graph.getNodeData(id)) next.push(id);
|
|
55550
|
+
} catch (e) {}
|
|
55551
|
+
deselect_node(gobj);
|
|
55552
|
+
if (!next.length) return;
|
|
55553
|
+
history_pause(gobj);
|
|
55554
|
+
try {
|
|
55555
|
+
let states = {};
|
|
55556
|
+
for (let id of next) states[id] = ["selected"];
|
|
55557
|
+
graph.setElementState(states);
|
|
55558
|
+
} catch (e) {
|
|
55559
|
+
log_error(`${gobj_short_name(gobj)}: cannot set the selection: ${e}`);
|
|
55560
|
+
}
|
|
55561
|
+
paint_selection(gobj, next);
|
|
55562
|
+
graph_draw(gobj).then(() => {
|
|
55563
|
+
history_resume(gobj);
|
|
55564
|
+
});
|
|
55565
|
+
}
|
|
55566
|
+
/************************************************************
|
|
55567
|
+
* Add a node to the selection, or take it out of it.
|
|
55568
|
+
************************************************************/
|
|
55569
|
+
function toggle_in_selection(gobj, node_id) {
|
|
55570
|
+
let priv = gobj.priv;
|
|
55571
|
+
let current = new Set(selected_node_ids(gobj));
|
|
55572
|
+
for (let id of priv._selected_paint_ids || []) current.add(id);
|
|
55573
|
+
if (current.has(node_id)) current.delete(node_id);
|
|
55574
|
+
else current.add(node_id);
|
|
55575
|
+
set_selection(gobj, [...current]);
|
|
55576
|
+
}
|
|
55421
55577
|
function select_node(gobj, node_id) {
|
|
55422
55578
|
let priv = gobj.priv;
|
|
55423
55579
|
let graph = priv.graph;
|
|
@@ -55427,6 +55583,7 @@ function select_node(gobj, node_id) {
|
|
|
55427
55583
|
graph.setElementState(node_id, ["selected"]);
|
|
55428
55584
|
} catch (e) {}
|
|
55429
55585
|
priv._selected_node_id = node_id;
|
|
55586
|
+
paint_selection(gobj, [node_id]);
|
|
55430
55587
|
show_resize_handles(gobj);
|
|
55431
55588
|
show_node_icon(gobj);
|
|
55432
55589
|
graph_draw(gobj).then(() => {
|
|
@@ -55442,12 +55599,17 @@ function deselect_node(gobj) {
|
|
|
55442
55599
|
hide_node_popover(gobj);
|
|
55443
55600
|
hide_delete_confirm(gobj);
|
|
55444
55601
|
hide_unlink_confirm(gobj);
|
|
55445
|
-
|
|
55602
|
+
let clearing = /* @__PURE__ */ new Set([...selected_node_ids(gobj), ...priv._selected_paint_ids || []]);
|
|
55603
|
+
if (priv._selected_node_id) clearing.add(priv._selected_node_id);
|
|
55604
|
+
if (clearing.size) {
|
|
55446
55605
|
history_pause(gobj);
|
|
55447
55606
|
try {
|
|
55448
|
-
|
|
55607
|
+
let states = {};
|
|
55608
|
+
for (let id of clearing) states[id] = [];
|
|
55609
|
+
graph.setElementState(states);
|
|
55449
55610
|
} catch (e) {}
|
|
55450
55611
|
priv._selected_node_id = null;
|
|
55612
|
+
paint_selection(gobj, []);
|
|
55451
55613
|
graph_draw(gobj).then(() => {
|
|
55452
55614
|
history_resume(gobj);
|
|
55453
55615
|
});
|
|
@@ -56734,33 +56896,36 @@ function refresh_minimap(gobj) {
|
|
|
56734
56896
|
* same three-way choice — it lived inline in the theme refresh and is
|
|
56735
56897
|
* shared now. Returns null for a node that carries no desc.
|
|
56736
56898
|
************************************************************/
|
|
56737
|
-
function node_innerHTML_of(nd, theme, highlight) {
|
|
56899
|
+
function node_innerHTML_of(nd, theme, highlight, selected) {
|
|
56738
56900
|
if (!nd || !nd.data || !nd.data.desc) return null;
|
|
56739
56901
|
let desc = nd.data.desc;
|
|
56740
56902
|
let record = nd.data.record || {};
|
|
56741
56903
|
let label = node_label(desc, record);
|
|
56742
56904
|
switch (desc.node_treedb_type) {
|
|
56743
|
-
case "child": return build_chip_innerHTML(desc.color, theme, record.icon, label, record.id, highlight);
|
|
56744
|
-
case "extended": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, true, record.id, highlight);
|
|
56745
|
-
case "hierarchical": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, false, record.id, highlight);
|
|
56905
|
+
case "child": return build_chip_innerHTML(desc.color, theme, record.icon, label, record.id, highlight, selected);
|
|
56906
|
+
case "extended": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, true, record.id, highlight, selected);
|
|
56907
|
+
case "hierarchical": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, false, record.id, highlight, selected);
|
|
56746
56908
|
}
|
|
56747
56909
|
return null;
|
|
56748
56910
|
}
|
|
56749
56911
|
/************************************************************
|
|
56750
|
-
* Repaint
|
|
56751
|
-
*
|
|
56752
|
-
*
|
|
56912
|
+
* Repaint these cards with the flags they carry RIGHT NOW.
|
|
56913
|
+
*
|
|
56914
|
+
* One place, because the flags are independent and each used to
|
|
56915
|
+
* be written by whoever repainted last: a find that repainted its
|
|
56916
|
+
* matches erased the selection ring off them, and a selection
|
|
56917
|
+
* repainted over a match erased the amber. Both are read here
|
|
56918
|
+
* from where they live.
|
|
56753
56919
|
************************************************************/
|
|
56754
|
-
function
|
|
56920
|
+
function repaint_cards(gobj, ids) {
|
|
56755
56921
|
let priv = gobj.priv;
|
|
56756
56922
|
let graph = priv.graph;
|
|
56757
|
-
if (!graph) return;
|
|
56758
|
-
let
|
|
56759
|
-
let
|
|
56760
|
-
if (touched.size === 0) return;
|
|
56923
|
+
if (!graph || !ids || !ids.size) return;
|
|
56924
|
+
let focus = new Set(priv._focus_ids || []);
|
|
56925
|
+
let selected = new Set(priv._selected_paint_ids || []);
|
|
56761
56926
|
let updates = [];
|
|
56762
|
-
for (let id of
|
|
56763
|
-
let html = node_innerHTML_of(graph.getNodeData(id), priv.theme,
|
|
56927
|
+
for (let id of ids) {
|
|
56928
|
+
let html = node_innerHTML_of(graph.getNodeData(id), priv.theme, focus.has(id), selected.has(id));
|
|
56764
56929
|
if (html !== null) updates.push({
|
|
56765
56930
|
id,
|
|
56766
56931
|
style: { innerHTML: html }
|
|
@@ -56771,19 +56936,32 @@ function apply_node_highlight(gobj, prev_ids, next_ids) {
|
|
|
56771
56936
|
graph.updateNodeData(updates);
|
|
56772
56937
|
graph.draw();
|
|
56773
56938
|
} catch (e) {
|
|
56774
|
-
log_error(`${gobj_short_name(gobj)}: cannot repaint the
|
|
56939
|
+
log_error(`${gobj_short_name(gobj)}: cannot repaint the cards: ${e}`);
|
|
56775
56940
|
}
|
|
56776
56941
|
}
|
|
56942
|
+
/************************************************************
|
|
56943
|
+
* Repaint the cards whose highlight state CHANGES: the ones that had it
|
|
56944
|
+
* and lose it, plus the ones that gain it. Only those — a treedb graph
|
|
56945
|
+
* is redrawn per keystroke of the find box otherwise.
|
|
56946
|
+
************************************************************/
|
|
56947
|
+
function apply_node_highlight(gobj, prev_ids, next_ids) {
|
|
56948
|
+
if (!gobj.priv.graph) return;
|
|
56949
|
+
let next = new Set(next_ids || []);
|
|
56950
|
+
let touched = /* @__PURE__ */ new Set([...prev_ids || [], ...next]);
|
|
56951
|
+
if (touched.size === 0) return;
|
|
56952
|
+
repaint_cards(gobj, touched);
|
|
56953
|
+
}
|
|
56777
56954
|
function refresh_html_nodes_theme(gobj, theme) {
|
|
56778
56955
|
let priv = gobj.priv;
|
|
56779
56956
|
let graph = priv.graph;
|
|
56780
56957
|
if (!graph) return;
|
|
56781
56958
|
let nodes = graph.getData().nodes || [];
|
|
56782
56959
|
let highlighted = new Set(priv._focus_ids || []);
|
|
56960
|
+
let selected = new Set(priv._selected_paint_ids || []);
|
|
56783
56961
|
let updates = [];
|
|
56784
56962
|
for (let i = 0; i < nodes.length; i++) {
|
|
56785
56963
|
let id = nodes[i].id;
|
|
56786
|
-
let html = node_innerHTML_of(graph.getNodeData(id), theme, highlighted.has(id));
|
|
56964
|
+
let html = node_innerHTML_of(graph.getNodeData(id), theme, highlighted.has(id), selected.has(id));
|
|
56787
56965
|
if (html !== null) updates.push({
|
|
56788
56966
|
id,
|
|
56789
56967
|
style: { innerHTML: html }
|
|
@@ -56813,12 +56991,29 @@ function refresh_default_edges_theme(gobj, theme) {
|
|
|
56813
56991
|
if (updates.length > 0) graph.updateEdgeData(updates);
|
|
56814
56992
|
}
|
|
56815
56993
|
/************************************************************
|
|
56994
|
+
* The rings a card can wear, composed into one `box-shadow`.
|
|
56995
|
+
*
|
|
56996
|
+
* A node can be a find match and be selected at the same time, so
|
|
56997
|
+
* neither ring may be written by overwriting the other: the amber
|
|
56998
|
+
* halo hugs the card and the blue selection ring is drawn outside
|
|
56999
|
+
* it, which is also the order that reads correctly when only one
|
|
57000
|
+
* of them is on.
|
|
57001
|
+
************************************************************/
|
|
57002
|
+
function ring_shadow(highlight, selected, base_shadow) {
|
|
57003
|
+
let rings = [];
|
|
57004
|
+
if (highlight) rings.push(`0 0 0 4px ${HIGHLIGHT_HALO}`);
|
|
57005
|
+
if (selected) rings.push(`0 0 0 ${highlight ? "7px" : "3px"} ${SELECT_RING}`);
|
|
57006
|
+
if (base_shadow) rings.push(base_shadow);
|
|
57007
|
+
if (!rings.length) return "";
|
|
57008
|
+
return `box-shadow: ${rings.join(", ")};`;
|
|
57009
|
+
}
|
|
57010
|
+
/************************************************************
|
|
56816
57011
|
* Build innerHTML for pure-child (leaf) nodes: a compact
|
|
56817
57012
|
* chip-card. Same colour/typography family as the entity card
|
|
56818
57013
|
* but lighter (1px border, no shadow, single line). The name is
|
|
56819
57014
|
* always legible (ellipsis + native title tooltip on overflow).
|
|
56820
57015
|
************************************************************/
|
|
56821
|
-
function build_chip_innerHTML(color, theme, icon, label, key, highlight) {
|
|
57016
|
+
function build_chip_innerHTML(color, theme, icon, label, key, highlight, selected) {
|
|
56822
57017
|
let title = key || label;
|
|
56823
57018
|
let dark = theme === "dark";
|
|
56824
57019
|
let bg = dark ? `color-mix(in srgb, ${color} 30%, #2c3542)` : `color-mix(in srgb, ${color} 10%, ${dark ? "#1b2230" : "#ffffff"})`;
|
|
@@ -56837,7 +57032,7 @@ function build_chip_innerHTML(color, theme, icon, label, key, highlight) {
|
|
|
56837
57032
|
height: 100%;
|
|
56838
57033
|
background: ${bg};
|
|
56839
57034
|
border: ${highlight ? "3px" : "1px"} solid ${border};
|
|
56840
|
-
${highlight
|
|
57035
|
+
${ring_shadow(highlight, selected, "")}
|
|
56841
57036
|
border-radius: 8px;
|
|
56842
57037
|
color: ${text_color};
|
|
56843
57038
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
@@ -56863,7 +57058,7 @@ function build_chip_innerHTML(color, theme, icon, label, key, highlight) {
|
|
|
56863
57058
|
* colour is kept (per-topic differentiation) but softened via
|
|
56864
57059
|
* color-mix instead of a harsh saturated fill. Theme-aware.
|
|
56865
57060
|
************************************************************/
|
|
56866
|
-
function build_node_innerHTML(color, theme, icon, label, topic_name, structural, key, highlight) {
|
|
57061
|
+
function build_node_innerHTML(color, theme, icon, label, topic_name, structural, key, highlight, selected) {
|
|
56867
57062
|
let title = key || label;
|
|
56868
57063
|
let dark = theme === "dark";
|
|
56869
57064
|
let surface = dark ? "#1b2230" : "#ffffff";
|
|
@@ -56905,7 +57100,7 @@ function build_node_innerHTML(color, theme, icon, label, topic_name, structural,
|
|
|
56905
57100
|
background: ${bg};
|
|
56906
57101
|
border: ${highlight ? "3px" : "1.5px"} ${border_style} ${border};
|
|
56907
57102
|
border-radius: 10px;
|
|
56908
|
-
|
|
57103
|
+
${ring_shadow(highlight, selected, shadow)}
|
|
56909
57104
|
color: ${title_color};
|
|
56910
57105
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
56911
57106
|
display: flex;
|
|
@@ -57826,6 +58021,17 @@ function ac_node_drag_end(gobj, event, kw, src) {
|
|
|
57826
58021
|
return 0;
|
|
57827
58022
|
}
|
|
57828
58023
|
/************************************************************
|
|
58024
|
+
* The rubber band let go: these are the nodes it enclosed.
|
|
58025
|
+
*
|
|
58026
|
+
* They arrive in the kw because `onSelect` runs BEFORE G6 writes
|
|
58027
|
+
* the state, so asking the graph here would answer the previous
|
|
58028
|
+
* selection.
|
|
58029
|
+
************************************************************/
|
|
58030
|
+
function ac_brush_select(gobj, event, kw, src) {
|
|
58031
|
+
set_selection(gobj, kw && kw.ids || []);
|
|
58032
|
+
return 0;
|
|
58033
|
+
}
|
|
58034
|
+
/************************************************************
|
|
57829
58035
|
* Node click - publish vertex clicked event
|
|
57830
58036
|
************************************************************/
|
|
57831
58037
|
function ac_node_click(gobj, event, kw, src) {
|
|
@@ -57840,7 +58046,8 @@ function ac_node_click(gobj, event, kw, src) {
|
|
|
57840
58046
|
topic_name: nodedata.data.desc.topic_name,
|
|
57841
58047
|
record: nodedata.data.record
|
|
57842
58048
|
});
|
|
57843
|
-
if (priv.edit_mode)
|
|
58049
|
+
if (priv.edit_mode && kw.evt.shiftKey) toggle_in_selection(gobj, node_id);
|
|
58050
|
+
else if (priv.edit_mode) {
|
|
57844
58051
|
let containerRect = priv.$container.getBoundingClientRect();
|
|
57845
58052
|
let canvasPoint = graph.getCanvasByViewport([kw.evt.client.x - containerRect.left, kw.evt.client.y - containerRect.top]);
|
|
57846
58053
|
let port_key = detect_port_click(gobj, node_id, canvasPoint[0], canvasPoint[1]);
|
|
@@ -58067,6 +58274,11 @@ function create_gclass$1(gclass_name) {
|
|
|
58067
58274
|
ac_node_drag_end,
|
|
58068
58275
|
null
|
|
58069
58276
|
],
|
|
58277
|
+
[
|
|
58278
|
+
"EV_BRUSH_SELECT",
|
|
58279
|
+
ac_brush_select,
|
|
58280
|
+
null
|
|
58281
|
+
],
|
|
58070
58282
|
[
|
|
58071
58283
|
"EV_ZOOM_IN",
|
|
58072
58284
|
ac_zoom_in,
|
|
@@ -58175,6 +58387,7 @@ function create_gclass$1(gclass_name) {
|
|
|
58175
58387
|
["EV_NODE_CONTEXT_MENU", 0],
|
|
58176
58388
|
["EV_CANVAS_CLICK", 0],
|
|
58177
58389
|
["EV_NODE_DRAG_END", 0],
|
|
58390
|
+
["EV_BRUSH_SELECT", 0],
|
|
58178
58391
|
["EV_ZOOM_IN", 0],
|
|
58179
58392
|
["EV_ZOOM_OUT", 0],
|
|
58180
58393
|
["EV_ZOOM_RESET", 0],
|