@yuneta/gobj-ui 7.23.25 → 7.23.27
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/dist/gobj-ui.cjs.js +107 -18
- package/dist/gobj-ui.es.js +107 -18
- package/package.json +1 -1
- package/src/c_yui_gobj_tree_js.js +52 -18
- package/src/c_yui_json.css +0 -27
- package/src/c_yui_json_graph.js +130 -21
- package/src/lib_graph.css +67 -0
- package/src/yui_graph_camera.js +54 -12
package/dist/gobj-ui.cjs.js
CHANGED
|
@@ -9710,23 +9710,41 @@ function yui_graph_update_anchor($container, state) {
|
|
|
9710
9710
|
* an error worth a log line per notch, they are all "there is
|
|
9711
9711
|
* nothing to centre right now".
|
|
9712
9712
|
************************************************************/
|
|
9713
|
+
var __centring__ = /* @__PURE__ */ new WeakMap();
|
|
9713
9714
|
async function yui_graph_center_on(graph, node_id) {
|
|
9714
9715
|
if (!graph || !node_id) return false;
|
|
9716
|
+
let st = __centring__.get(graph);
|
|
9717
|
+
if (st && st.running) {
|
|
9718
|
+
st.again = node_id;
|
|
9719
|
+
return true;
|
|
9720
|
+
}
|
|
9721
|
+
__centring__.set(graph, {
|
|
9722
|
+
running: true,
|
|
9723
|
+
again: null
|
|
9724
|
+
});
|
|
9715
9725
|
try {
|
|
9716
9726
|
if (typeof graph.getElementData === "function" && !graph.getElementData(node_id)) return false;
|
|
9717
9727
|
if (typeof graph.getElementPosition !== "function" || typeof graph.getViewportByCanvas !== "function" || typeof graph.getCanvasCenter !== "function" || typeof graph.translateTo !== "function") return false;
|
|
9718
9728
|
for (let i = 0; i < 3; i++) {
|
|
9729
|
+
let z = graph.getZoom() || 1;
|
|
9719
9730
|
let at = graph.getViewportByCanvas(graph.getElementPosition(node_id));
|
|
9720
9731
|
let want = graph.getCanvasCenter();
|
|
9721
9732
|
let dx = want[0] - at[0];
|
|
9722
9733
|
let dy = want[1] - at[1];
|
|
9723
9734
|
if (Math.abs(dx) < 1 && Math.abs(dy) < 1) break;
|
|
9724
|
-
let
|
|
9725
|
-
await graph.translateTo([
|
|
9735
|
+
let n = graph.getElementPosition(node_id);
|
|
9736
|
+
await graph.translateTo([(want[0] - n[0]) * z, (want[1] - n[1]) * z]);
|
|
9726
9737
|
}
|
|
9727
9738
|
return true;
|
|
9728
9739
|
} catch (e) {
|
|
9729
9740
|
return false;
|
|
9741
|
+
} finally {
|
|
9742
|
+
let pending = __centring__.get(graph);
|
|
9743
|
+
__centring__.set(graph, {
|
|
9744
|
+
running: false,
|
|
9745
|
+
again: null
|
|
9746
|
+
});
|
|
9747
|
+
if (pending && pending.again) yui_graph_center_on(graph, pending.again);
|
|
9730
9748
|
}
|
|
9731
9749
|
}
|
|
9732
9750
|
/************************************************************
|
|
@@ -10573,7 +10591,8 @@ var PRIVATE_DATA$11 = {
|
|
|
10573
10591
|
anchor_id: "",
|
|
10574
10592
|
anchor_path: "",
|
|
10575
10593
|
anchor_state: "off",
|
|
10576
|
-
last_zoom: 1
|
|
10594
|
+
last_zoom: 1,
|
|
10595
|
+
center_posted: false
|
|
10577
10596
|
};
|
|
10578
10597
|
var __gclass__$11 = null;
|
|
10579
10598
|
var __layout_registered__$1 = false;
|
|
@@ -10941,11 +10960,7 @@ function build_graph$3(gobj) {
|
|
|
10941
10960
|
}
|
|
10942
10961
|
},
|
|
10943
10962
|
layout: layout_cfg.g6_layout,
|
|
10944
|
-
behaviors:
|
|
10945
|
-
"drag-canvas",
|
|
10946
|
-
"zoom-canvas",
|
|
10947
|
-
"drag-element"
|
|
10948
|
-
]
|
|
10963
|
+
behaviors: BEHAVIORS_READING$1.slice()
|
|
10949
10964
|
});
|
|
10950
10965
|
if (priv.theme) graph.setTheme(priv.theme);
|
|
10951
10966
|
graph.on(_antv_g6.NodeEvent.CLICK, (evt) => {
|
|
@@ -10961,7 +10976,10 @@ function build_graph$3(gobj) {
|
|
|
10961
10976
|
}
|
|
10962
10977
|
if (z === priv.last_zoom) return;
|
|
10963
10978
|
priv.last_zoom = z;
|
|
10964
|
-
if (priv.anchor_state === "on" && priv.anchor_id
|
|
10979
|
+
if (priv.anchor_state === "on" && priv.anchor_id && !priv.center_posted) {
|
|
10980
|
+
priv.center_posted = true;
|
|
10981
|
+
(0, _yuneta_gobj_js.gobj_post_event)(gobj, "EV_CENTER_ANCHOR", {}, gobj);
|
|
10982
|
+
}
|
|
10965
10983
|
});
|
|
10966
10984
|
graph.on(_antv_g6.CanvasEvent.CLICK, (evt) => {});
|
|
10967
10985
|
if (typeof ResizeObserver !== "undefined") {
|
|
@@ -11052,6 +11070,16 @@ function build_cell_html(key, value, type, dark, matched, fold) {
|
|
|
11052
11070
|
* forever. `+3` and `−` need no language.
|
|
11053
11071
|
************************************************************/
|
|
11054
11072
|
var FOLD_SPACER = `<span style="width:24px; flex:0 0 auto;"></span>`;
|
|
11073
|
+
var ZOOM_CANVAS$1 = {
|
|
11074
|
+
type: "zoom-canvas",
|
|
11075
|
+
animation: false
|
|
11076
|
+
};
|
|
11077
|
+
var BEHAVIORS_READING$1 = [
|
|
11078
|
+
"drag-canvas",
|
|
11079
|
+
ZOOM_CANVAS$1,
|
|
11080
|
+
"drag-element"
|
|
11081
|
+
];
|
|
11082
|
+
var BEHAVIORS_PICKING$1 = ["drag-canvas", ZOOM_CANVAS$1];
|
|
11055
11083
|
var CARD_HEADER_H$1 = 24;
|
|
11056
11084
|
var CARD_ROW_H$1 = 22;
|
|
11057
11085
|
function fold_toggle_html(path, foldable, folded, branches, colors) {
|
|
@@ -11188,7 +11216,7 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id, parent_port)
|
|
|
11188
11216
|
let min_width = Math.max(180, label.length * 9);
|
|
11189
11217
|
let card_height = CARD_HEADER_H$1 + lines.length * CARD_ROW_H$1;
|
|
11190
11218
|
let node_html = `
|
|
11191
|
-
<div style="
|
|
11219
|
+
<div class="JSON_CARD" data-json-path="${(0, _yuneta_gobj_js.escapeHtml)(path)}" style="
|
|
11192
11220
|
min-width: ${min_width}px;
|
|
11193
11221
|
background: ${colors.bg};
|
|
11194
11222
|
border: ${border_width}px ${is_dict ? "dashed" : "solid"} ${border_color};
|
|
@@ -11292,6 +11320,7 @@ function load_json(gobj) {
|
|
|
11292
11320
|
});
|
|
11293
11321
|
graph.render().then(() => {
|
|
11294
11322
|
reanchor$1(gobj);
|
|
11323
|
+
paint_anchor_mark(gobj);
|
|
11295
11324
|
if (preserve_view) {
|
|
11296
11325
|
yui_graph_update_zoom((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container"), priv.graph);
|
|
11297
11326
|
return;
|
|
@@ -11613,10 +11642,49 @@ function reanchor$1(gobj) {
|
|
|
11613
11642
|
yui_graph_update_anchor((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container"), priv.anchor_state);
|
|
11614
11643
|
}
|
|
11615
11644
|
/************************************************************
|
|
11645
|
+
* Reading, or picking the node to anchor.
|
|
11646
|
+
*
|
|
11647
|
+
* Two visible consequences and one invisible: the cursor says
|
|
11648
|
+
* a click is expected, the mount says which mode it is in for
|
|
11649
|
+
* anyone reading the DOM, and node dragging stands aside so a
|
|
11650
|
+
* click that drifts is still a click.
|
|
11651
|
+
************************************************************/
|
|
11652
|
+
function set_picking_mode$1(gobj, picking) {
|
|
11653
|
+
let graph = gobj.priv.graph;
|
|
11654
|
+
if (graph && typeof graph.setBehaviors === "function") graph.setBehaviors((picking ? BEHAVIORS_PICKING$1 : BEHAVIORS_READING$1).slice());
|
|
11655
|
+
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
11656
|
+
if ($container) {
|
|
11657
|
+
let $mount = $container.querySelector(".json-graph-container");
|
|
11658
|
+
if ($mount) $mount.classList.toggle("JSON_GRAPH_PICKING", !!picking);
|
|
11659
|
+
}
|
|
11660
|
+
}
|
|
11661
|
+
/************************************************************
|
|
11662
|
+
* Mark the card the camera is holding.
|
|
11663
|
+
*
|
|
11664
|
+
* A class on the card's own element and not a G6 node state:
|
|
11665
|
+
* G6 paints no state style on an html node, so `setElementState`
|
|
11666
|
+
* would select it correctly and show nothing.
|
|
11667
|
+
*
|
|
11668
|
+
* Re-applied after every rebuild, because the cards are new DOM
|
|
11669
|
+
* each time and the mark would otherwise survive only until the
|
|
11670
|
+
* next fold.
|
|
11671
|
+
************************************************************/
|
|
11672
|
+
function paint_anchor_mark(gobj) {
|
|
11673
|
+
let priv = gobj.priv;
|
|
11674
|
+
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
11675
|
+
if (!$container) return;
|
|
11676
|
+
for (let $card of $container.querySelectorAll(".JSON_CARD_ANCHORED")) $card.classList.remove("JSON_CARD_ANCHORED");
|
|
11677
|
+
if (priv.anchor_state !== "on" || !priv.anchor_path) return;
|
|
11678
|
+
let $it = $container.querySelector(".JSON_CARD[data-json-path=\"" + CSS.escape(priv.anchor_path) + "\"]");
|
|
11679
|
+
if ($it) $it.classList.add("JSON_CARD_ANCHORED");
|
|
11680
|
+
}
|
|
11681
|
+
/************************************************************
|
|
11616
11682
|
* Centre on the anchor, one cycle after it was chosen.
|
|
11617
11683
|
************************************************************/
|
|
11618
11684
|
function ac_center_anchor$2(gobj, event, kw, src) {
|
|
11619
11685
|
let priv = gobj.priv;
|
|
11686
|
+
priv.center_posted = false;
|
|
11687
|
+
paint_anchor_mark(gobj);
|
|
11620
11688
|
if (priv.anchor_state === "on" && priv.anchor_id) yui_graph_center_on(priv.graph, priv.anchor_id);
|
|
11621
11689
|
return 0;
|
|
11622
11690
|
}
|
|
@@ -11637,6 +11705,8 @@ function ac_toggle_anchor$2(gobj, event, kw, src) {
|
|
|
11637
11705
|
priv.anchor_path = "";
|
|
11638
11706
|
}
|
|
11639
11707
|
yui_graph_update_anchor((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container"), priv.anchor_state);
|
|
11708
|
+
paint_anchor_mark(gobj);
|
|
11709
|
+
set_picking_mode$1(gobj, priv.anchor_state === "arming");
|
|
11640
11710
|
return 0;
|
|
11641
11711
|
}
|
|
11642
11712
|
/************************************************************
|
|
@@ -11703,6 +11773,7 @@ function ac_node_click$4(gobj, event, kw, src) {
|
|
|
11703
11773
|
priv.anchor_path = nodedata && nodedata.data ? nodedata.data.path : "";
|
|
11704
11774
|
priv.anchor_state = "on";
|
|
11705
11775
|
yui_graph_update_anchor((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container"), priv.anchor_state);
|
|
11776
|
+
set_picking_mode$1(gobj, false);
|
|
11706
11777
|
(0, _yuneta_gobj_js.gobj_post_event)(gobj, "EV_CENTER_ANCHOR", {}, gobj);
|
|
11707
11778
|
return 0;
|
|
11708
11779
|
}
|
|
@@ -13169,6 +13240,16 @@ var attrs_table$9 = [
|
|
|
13169
13240
|
(0, _yuneta_gobj_js.SDATA)(_yuneta_gobj_js.data_type_t.DTP_INTEGER, "collapse_threshold", 0, 10, "Auto-collapse a node whose direct children exceed this number. 0 disables auto-collapse."),
|
|
13170
13241
|
(0, _yuneta_gobj_js.SDATA_END)()
|
|
13171
13242
|
];
|
|
13243
|
+
var ZOOM_CANVAS = {
|
|
13244
|
+
type: "zoom-canvas",
|
|
13245
|
+
animation: false
|
|
13246
|
+
};
|
|
13247
|
+
var BEHAVIORS_READING = [
|
|
13248
|
+
"drag-canvas",
|
|
13249
|
+
ZOOM_CANVAS,
|
|
13250
|
+
"drag-element"
|
|
13251
|
+
];
|
|
13252
|
+
var BEHAVIORS_PICKING = ["drag-canvas", ZOOM_CANVAS];
|
|
13172
13253
|
var PRIVATE_DATA$9 = {
|
|
13173
13254
|
canvas_id: "",
|
|
13174
13255
|
graph: null,
|
|
@@ -13458,7 +13539,7 @@ function build_ui$8(gobj) {
|
|
|
13458
13539
|
{
|
|
13459
13540
|
id: priv.canvas_id,
|
|
13460
13541
|
class: "gobj-tree-container",
|
|
13461
|
-
style: "height:100%; min-height:0; border: 1px solid var(--bulma-border-weak); border-radius:0.2rem;
|
|
13542
|
+
style: "height:100%; min-height:0; border: 1px solid var(--bulma-border-weak); border-radius:0.2rem;"
|
|
13462
13543
|
},
|
|
13463
13544
|
[]
|
|
13464
13545
|
]]
|
|
@@ -13650,11 +13731,7 @@ function build_graph$2(gobj) {
|
|
|
13650
13731
|
}
|
|
13651
13732
|
},
|
|
13652
13733
|
layout: layout_cfg.g6_layout,
|
|
13653
|
-
behaviors:
|
|
13654
|
-
"drag-canvas",
|
|
13655
|
-
"zoom-canvas",
|
|
13656
|
-
"drag-element"
|
|
13657
|
-
]
|
|
13734
|
+
behaviors: BEHAVIORS_READING.slice()
|
|
13658
13735
|
});
|
|
13659
13736
|
if (priv.theme) graph.setTheme(priv.theme);
|
|
13660
13737
|
graph.on("aftertransform", () => {
|
|
@@ -14526,6 +14603,16 @@ function ac_center_anchor$1(gobj, event, kw, src) {
|
|
|
14526
14603
|
return 0;
|
|
14527
14604
|
}
|
|
14528
14605
|
/************************************************************
|
|
14606
|
+
* Reading, or picking the node to anchor.
|
|
14607
|
+
************************************************************/
|
|
14608
|
+
function set_picking_mode(gobj, picking) {
|
|
14609
|
+
let graph = gobj.priv.graph;
|
|
14610
|
+
if (graph && typeof graph.setBehaviors === "function") graph.setBehaviors((picking ? BEHAVIORS_PICKING : BEHAVIORS_READING).slice());
|
|
14611
|
+
let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
|
|
14612
|
+
let $mount = $container ? $container.querySelector(".gobj-tree-container") : null;
|
|
14613
|
+
if ($mount) $mount.classList.toggle("GOBJ_TREE_PICKING", !!picking);
|
|
14614
|
+
}
|
|
14615
|
+
/************************************************************
|
|
14529
14616
|
* Arm the anchor, or let it go.
|
|
14530
14617
|
*
|
|
14531
14618
|
* Three states and one button, so a press ADVANCES: with no
|
|
@@ -14542,6 +14629,7 @@ function ac_toggle_anchor$1(gobj, event, kw, src) {
|
|
|
14542
14629
|
priv.anchor_name = "";
|
|
14543
14630
|
}
|
|
14544
14631
|
yui_graph_update_anchor((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container"), priv.anchor_state);
|
|
14632
|
+
set_picking_mode(gobj, priv.anchor_state === "arming");
|
|
14545
14633
|
return 0;
|
|
14546
14634
|
}
|
|
14547
14635
|
/************************************************************
|
|
@@ -14610,6 +14698,7 @@ function ac_node_click$3(gobj, event, kw, src) {
|
|
|
14610
14698
|
priv.anchor_name = node_data.full_name || "";
|
|
14611
14699
|
priv.anchor_state = "on";
|
|
14612
14700
|
yui_graph_update_anchor((0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container"), priv.anchor_state);
|
|
14701
|
+
set_picking_mode(gobj, false);
|
|
14613
14702
|
(0, _yuneta_gobj_js.gobj_post_event)(gobj, "EV_CENTER_ANCHOR", {}, gobj);
|
|
14614
14703
|
return 0;
|
|
14615
14704
|
}
|
|
@@ -37605,7 +37694,7 @@ Text.PARSED_STYLE_LIST = new Set([].concat(_toConsumableArray(DisplayObject.PARS
|
|
|
37605
37694
|
* * register property @see https://developer.mozilla.org/en-US/docs/Web/API/CSS/RegisterProperty
|
|
37606
37695
|
* * CSS Layout API
|
|
37607
37696
|
*/
|
|
37608
|
-
var CSS = {
|
|
37697
|
+
var CSS$1 = {
|
|
37609
37698
|
/**
|
|
37610
37699
|
* <number>
|
|
37611
37700
|
* @see https://drafts.csswg.org/css-values-4/#number-value
|
|
@@ -47654,7 +47743,7 @@ var e = 1e-4;
|
|
|
47654
47743
|
syntax: PropertySyntax.ANGLE
|
|
47655
47744
|
}
|
|
47656
47745
|
].forEach(function(property) {
|
|
47657
|
-
CSS.registerProperty(property);
|
|
47746
|
+
CSS$1.registerProperty(property);
|
|
47658
47747
|
});
|
|
47659
47748
|
var polarToCartesian = function polarToCartesian(centerX, centerY, radius, angleInRadian) {
|
|
47660
47749
|
return {
|
package/dist/gobj-ui.es.js
CHANGED
|
@@ -9705,23 +9705,41 @@ function yui_graph_update_anchor($container, state) {
|
|
|
9705
9705
|
* an error worth a log line per notch, they are all "there is
|
|
9706
9706
|
* nothing to centre right now".
|
|
9707
9707
|
************************************************************/
|
|
9708
|
+
var __centring__ = /* @__PURE__ */ new WeakMap();
|
|
9708
9709
|
async function yui_graph_center_on(graph, node_id) {
|
|
9709
9710
|
if (!graph || !node_id) return false;
|
|
9711
|
+
let st = __centring__.get(graph);
|
|
9712
|
+
if (st && st.running) {
|
|
9713
|
+
st.again = node_id;
|
|
9714
|
+
return true;
|
|
9715
|
+
}
|
|
9716
|
+
__centring__.set(graph, {
|
|
9717
|
+
running: true,
|
|
9718
|
+
again: null
|
|
9719
|
+
});
|
|
9710
9720
|
try {
|
|
9711
9721
|
if (typeof graph.getElementData === "function" && !graph.getElementData(node_id)) return false;
|
|
9712
9722
|
if (typeof graph.getElementPosition !== "function" || typeof graph.getViewportByCanvas !== "function" || typeof graph.getCanvasCenter !== "function" || typeof graph.translateTo !== "function") return false;
|
|
9713
9723
|
for (let i = 0; i < 3; i++) {
|
|
9724
|
+
let z = graph.getZoom() || 1;
|
|
9714
9725
|
let at = graph.getViewportByCanvas(graph.getElementPosition(node_id));
|
|
9715
9726
|
let want = graph.getCanvasCenter();
|
|
9716
9727
|
let dx = want[0] - at[0];
|
|
9717
9728
|
let dy = want[1] - at[1];
|
|
9718
9729
|
if (Math.abs(dx) < 1 && Math.abs(dy) < 1) break;
|
|
9719
|
-
let
|
|
9720
|
-
await graph.translateTo([
|
|
9730
|
+
let n = graph.getElementPosition(node_id);
|
|
9731
|
+
await graph.translateTo([(want[0] - n[0]) * z, (want[1] - n[1]) * z]);
|
|
9721
9732
|
}
|
|
9722
9733
|
return true;
|
|
9723
9734
|
} catch (e) {
|
|
9724
9735
|
return false;
|
|
9736
|
+
} finally {
|
|
9737
|
+
let pending = __centring__.get(graph);
|
|
9738
|
+
__centring__.set(graph, {
|
|
9739
|
+
running: false,
|
|
9740
|
+
again: null
|
|
9741
|
+
});
|
|
9742
|
+
if (pending && pending.again) yui_graph_center_on(graph, pending.again);
|
|
9725
9743
|
}
|
|
9726
9744
|
}
|
|
9727
9745
|
/************************************************************
|
|
@@ -10568,7 +10586,8 @@ var PRIVATE_DATA$11 = {
|
|
|
10568
10586
|
anchor_id: "",
|
|
10569
10587
|
anchor_path: "",
|
|
10570
10588
|
anchor_state: "off",
|
|
10571
|
-
last_zoom: 1
|
|
10589
|
+
last_zoom: 1,
|
|
10590
|
+
center_posted: false
|
|
10572
10591
|
};
|
|
10573
10592
|
var __gclass__$11 = null;
|
|
10574
10593
|
var __layout_registered__$1 = false;
|
|
@@ -10936,11 +10955,7 @@ function build_graph$3(gobj) {
|
|
|
10936
10955
|
}
|
|
10937
10956
|
},
|
|
10938
10957
|
layout: layout_cfg.g6_layout,
|
|
10939
|
-
behaviors:
|
|
10940
|
-
"drag-canvas",
|
|
10941
|
-
"zoom-canvas",
|
|
10942
|
-
"drag-element"
|
|
10943
|
-
]
|
|
10958
|
+
behaviors: BEHAVIORS_READING$1.slice()
|
|
10944
10959
|
});
|
|
10945
10960
|
if (priv.theme) graph.setTheme(priv.theme);
|
|
10946
10961
|
graph.on(NodeEvent.CLICK, (evt) => {
|
|
@@ -10956,7 +10971,10 @@ function build_graph$3(gobj) {
|
|
|
10956
10971
|
}
|
|
10957
10972
|
if (z === priv.last_zoom) return;
|
|
10958
10973
|
priv.last_zoom = z;
|
|
10959
|
-
if (priv.anchor_state === "on" && priv.anchor_id
|
|
10974
|
+
if (priv.anchor_state === "on" && priv.anchor_id && !priv.center_posted) {
|
|
10975
|
+
priv.center_posted = true;
|
|
10976
|
+
gobj_post_event(gobj, "EV_CENTER_ANCHOR", {}, gobj);
|
|
10977
|
+
}
|
|
10960
10978
|
});
|
|
10961
10979
|
graph.on(CanvasEvent.CLICK, (evt) => {});
|
|
10962
10980
|
if (typeof ResizeObserver !== "undefined") {
|
|
@@ -11047,6 +11065,16 @@ function build_cell_html(key, value, type, dark, matched, fold) {
|
|
|
11047
11065
|
* forever. `+3` and `−` need no language.
|
|
11048
11066
|
************************************************************/
|
|
11049
11067
|
var FOLD_SPACER = `<span style="width:24px; flex:0 0 auto;"></span>`;
|
|
11068
|
+
var ZOOM_CANVAS$1 = {
|
|
11069
|
+
type: "zoom-canvas",
|
|
11070
|
+
animation: false
|
|
11071
|
+
};
|
|
11072
|
+
var BEHAVIORS_READING$1 = [
|
|
11073
|
+
"drag-canvas",
|
|
11074
|
+
ZOOM_CANVAS$1,
|
|
11075
|
+
"drag-element"
|
|
11076
|
+
];
|
|
11077
|
+
var BEHAVIORS_PICKING$1 = ["drag-canvas", ZOOM_CANVAS$1];
|
|
11050
11078
|
var CARD_HEADER_H$1 = 24;
|
|
11051
11079
|
var CARD_ROW_H$1 = 22;
|
|
11052
11080
|
function fold_toggle_html(path, foldable, folded, branches, colors) {
|
|
@@ -11183,7 +11211,7 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id, parent_port)
|
|
|
11183
11211
|
let min_width = Math.max(180, label.length * 9);
|
|
11184
11212
|
let card_height = CARD_HEADER_H$1 + lines.length * CARD_ROW_H$1;
|
|
11185
11213
|
let node_html = `
|
|
11186
|
-
<div style="
|
|
11214
|
+
<div class="JSON_CARD" data-json-path="${escapeHtml(path)}" style="
|
|
11187
11215
|
min-width: ${min_width}px;
|
|
11188
11216
|
background: ${colors.bg};
|
|
11189
11217
|
border: ${border_width}px ${is_dict ? "dashed" : "solid"} ${border_color};
|
|
@@ -11287,6 +11315,7 @@ function load_json(gobj) {
|
|
|
11287
11315
|
});
|
|
11288
11316
|
graph.render().then(() => {
|
|
11289
11317
|
reanchor$1(gobj);
|
|
11318
|
+
paint_anchor_mark(gobj);
|
|
11290
11319
|
if (preserve_view) {
|
|
11291
11320
|
yui_graph_update_zoom(gobj_read_attr(gobj, "$container"), priv.graph);
|
|
11292
11321
|
return;
|
|
@@ -11608,10 +11637,49 @@ function reanchor$1(gobj) {
|
|
|
11608
11637
|
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
11609
11638
|
}
|
|
11610
11639
|
/************************************************************
|
|
11640
|
+
* Reading, or picking the node to anchor.
|
|
11641
|
+
*
|
|
11642
|
+
* Two visible consequences and one invisible: the cursor says
|
|
11643
|
+
* a click is expected, the mount says which mode it is in for
|
|
11644
|
+
* anyone reading the DOM, and node dragging stands aside so a
|
|
11645
|
+
* click that drifts is still a click.
|
|
11646
|
+
************************************************************/
|
|
11647
|
+
function set_picking_mode$1(gobj, picking) {
|
|
11648
|
+
let graph = gobj.priv.graph;
|
|
11649
|
+
if (graph && typeof graph.setBehaviors === "function") graph.setBehaviors((picking ? BEHAVIORS_PICKING$1 : BEHAVIORS_READING$1).slice());
|
|
11650
|
+
let $container = gobj_read_attr(gobj, "$container");
|
|
11651
|
+
if ($container) {
|
|
11652
|
+
let $mount = $container.querySelector(".json-graph-container");
|
|
11653
|
+
if ($mount) $mount.classList.toggle("JSON_GRAPH_PICKING", !!picking);
|
|
11654
|
+
}
|
|
11655
|
+
}
|
|
11656
|
+
/************************************************************
|
|
11657
|
+
* Mark the card the camera is holding.
|
|
11658
|
+
*
|
|
11659
|
+
* A class on the card's own element and not a G6 node state:
|
|
11660
|
+
* G6 paints no state style on an html node, so `setElementState`
|
|
11661
|
+
* would select it correctly and show nothing.
|
|
11662
|
+
*
|
|
11663
|
+
* Re-applied after every rebuild, because the cards are new DOM
|
|
11664
|
+
* each time and the mark would otherwise survive only until the
|
|
11665
|
+
* next fold.
|
|
11666
|
+
************************************************************/
|
|
11667
|
+
function paint_anchor_mark(gobj) {
|
|
11668
|
+
let priv = gobj.priv;
|
|
11669
|
+
let $container = gobj_read_attr(gobj, "$container");
|
|
11670
|
+
if (!$container) return;
|
|
11671
|
+
for (let $card of $container.querySelectorAll(".JSON_CARD_ANCHORED")) $card.classList.remove("JSON_CARD_ANCHORED");
|
|
11672
|
+
if (priv.anchor_state !== "on" || !priv.anchor_path) return;
|
|
11673
|
+
let $it = $container.querySelector(".JSON_CARD[data-json-path=\"" + CSS.escape(priv.anchor_path) + "\"]");
|
|
11674
|
+
if ($it) $it.classList.add("JSON_CARD_ANCHORED");
|
|
11675
|
+
}
|
|
11676
|
+
/************************************************************
|
|
11611
11677
|
* Centre on the anchor, one cycle after it was chosen.
|
|
11612
11678
|
************************************************************/
|
|
11613
11679
|
function ac_center_anchor$2(gobj, event, kw, src) {
|
|
11614
11680
|
let priv = gobj.priv;
|
|
11681
|
+
priv.center_posted = false;
|
|
11682
|
+
paint_anchor_mark(gobj);
|
|
11615
11683
|
if (priv.anchor_state === "on" && priv.anchor_id) yui_graph_center_on(priv.graph, priv.anchor_id);
|
|
11616
11684
|
return 0;
|
|
11617
11685
|
}
|
|
@@ -11632,6 +11700,8 @@ function ac_toggle_anchor$2(gobj, event, kw, src) {
|
|
|
11632
11700
|
priv.anchor_path = "";
|
|
11633
11701
|
}
|
|
11634
11702
|
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
11703
|
+
paint_anchor_mark(gobj);
|
|
11704
|
+
set_picking_mode$1(gobj, priv.anchor_state === "arming");
|
|
11635
11705
|
return 0;
|
|
11636
11706
|
}
|
|
11637
11707
|
/************************************************************
|
|
@@ -11698,6 +11768,7 @@ function ac_node_click$4(gobj, event, kw, src) {
|
|
|
11698
11768
|
priv.anchor_path = nodedata && nodedata.data ? nodedata.data.path : "";
|
|
11699
11769
|
priv.anchor_state = "on";
|
|
11700
11770
|
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
11771
|
+
set_picking_mode$1(gobj, false);
|
|
11701
11772
|
gobj_post_event(gobj, "EV_CENTER_ANCHOR", {}, gobj);
|
|
11702
11773
|
return 0;
|
|
11703
11774
|
}
|
|
@@ -13164,6 +13235,16 @@ var attrs_table$9 = [
|
|
|
13164
13235
|
SDATA(data_type_t.DTP_INTEGER, "collapse_threshold", 0, 10, "Auto-collapse a node whose direct children exceed this number. 0 disables auto-collapse."),
|
|
13165
13236
|
SDATA_END()
|
|
13166
13237
|
];
|
|
13238
|
+
var ZOOM_CANVAS = {
|
|
13239
|
+
type: "zoom-canvas",
|
|
13240
|
+
animation: false
|
|
13241
|
+
};
|
|
13242
|
+
var BEHAVIORS_READING = [
|
|
13243
|
+
"drag-canvas",
|
|
13244
|
+
ZOOM_CANVAS,
|
|
13245
|
+
"drag-element"
|
|
13246
|
+
];
|
|
13247
|
+
var BEHAVIORS_PICKING = ["drag-canvas", ZOOM_CANVAS];
|
|
13167
13248
|
var PRIVATE_DATA$9 = {
|
|
13168
13249
|
canvas_id: "",
|
|
13169
13250
|
graph: null,
|
|
@@ -13453,7 +13534,7 @@ function build_ui$8(gobj) {
|
|
|
13453
13534
|
{
|
|
13454
13535
|
id: priv.canvas_id,
|
|
13455
13536
|
class: "gobj-tree-container",
|
|
13456
|
-
style: "height:100%; min-height:0; border: 1px solid var(--bulma-border-weak); border-radius:0.2rem;
|
|
13537
|
+
style: "height:100%; min-height:0; border: 1px solid var(--bulma-border-weak); border-radius:0.2rem;"
|
|
13457
13538
|
},
|
|
13458
13539
|
[]
|
|
13459
13540
|
]]
|
|
@@ -13645,11 +13726,7 @@ function build_graph$2(gobj) {
|
|
|
13645
13726
|
}
|
|
13646
13727
|
},
|
|
13647
13728
|
layout: layout_cfg.g6_layout,
|
|
13648
|
-
behaviors:
|
|
13649
|
-
"drag-canvas",
|
|
13650
|
-
"zoom-canvas",
|
|
13651
|
-
"drag-element"
|
|
13652
|
-
]
|
|
13729
|
+
behaviors: BEHAVIORS_READING.slice()
|
|
13653
13730
|
});
|
|
13654
13731
|
if (priv.theme) graph.setTheme(priv.theme);
|
|
13655
13732
|
graph.on("aftertransform", () => {
|
|
@@ -14521,6 +14598,16 @@ function ac_center_anchor$1(gobj, event, kw, src) {
|
|
|
14521
14598
|
return 0;
|
|
14522
14599
|
}
|
|
14523
14600
|
/************************************************************
|
|
14601
|
+
* Reading, or picking the node to anchor.
|
|
14602
|
+
************************************************************/
|
|
14603
|
+
function set_picking_mode(gobj, picking) {
|
|
14604
|
+
let graph = gobj.priv.graph;
|
|
14605
|
+
if (graph && typeof graph.setBehaviors === "function") graph.setBehaviors((picking ? BEHAVIORS_PICKING : BEHAVIORS_READING).slice());
|
|
14606
|
+
let $container = gobj_read_attr(gobj, "$container");
|
|
14607
|
+
let $mount = $container ? $container.querySelector(".gobj-tree-container") : null;
|
|
14608
|
+
if ($mount) $mount.classList.toggle("GOBJ_TREE_PICKING", !!picking);
|
|
14609
|
+
}
|
|
14610
|
+
/************************************************************
|
|
14524
14611
|
* Arm the anchor, or let it go.
|
|
14525
14612
|
*
|
|
14526
14613
|
* Three states and one button, so a press ADVANCES: with no
|
|
@@ -14537,6 +14624,7 @@ function ac_toggle_anchor$1(gobj, event, kw, src) {
|
|
|
14537
14624
|
priv.anchor_name = "";
|
|
14538
14625
|
}
|
|
14539
14626
|
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
14627
|
+
set_picking_mode(gobj, priv.anchor_state === "arming");
|
|
14540
14628
|
return 0;
|
|
14541
14629
|
}
|
|
14542
14630
|
/************************************************************
|
|
@@ -14605,6 +14693,7 @@ function ac_node_click$3(gobj, event, kw, src) {
|
|
|
14605
14693
|
priv.anchor_name = node_data.full_name || "";
|
|
14606
14694
|
priv.anchor_state = "on";
|
|
14607
14695
|
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
14696
|
+
set_picking_mode(gobj, false);
|
|
14608
14697
|
gobj_post_event(gobj, "EV_CENTER_ANCHOR", {}, gobj);
|
|
14609
14698
|
return 0;
|
|
14610
14699
|
}
|
|
@@ -37600,7 +37689,7 @@ Text.PARSED_STYLE_LIST = new Set([].concat(_toConsumableArray(DisplayObject.PARS
|
|
|
37600
37689
|
* * register property @see https://developer.mozilla.org/en-US/docs/Web/API/CSS/RegisterProperty
|
|
37601
37690
|
* * CSS Layout API
|
|
37602
37691
|
*/
|
|
37603
|
-
var CSS = {
|
|
37692
|
+
var CSS$1 = {
|
|
37604
37693
|
/**
|
|
37605
37694
|
* <number>
|
|
37606
37695
|
* @see https://drafts.csswg.org/css-values-4/#number-value
|
|
@@ -47649,7 +47738,7 @@ var e = 1e-4;
|
|
|
47649
47738
|
syntax: PropertySyntax.ANGLE
|
|
47650
47739
|
}
|
|
47651
47740
|
].forEach(function(property) {
|
|
47652
|
-
CSS.registerProperty(property);
|
|
47741
|
+
CSS$1.registerProperty(property);
|
|
47653
47742
|
});
|
|
47654
47743
|
var polarToCartesian = function polarToCartesian(centerX, centerY, radius, angleInRadian) {
|
|
47655
47744
|
return {
|
package/package.json
CHANGED
|
@@ -90,6 +90,36 @@ SDATA(data_type_t.DTP_INTEGER, "collapse_threshold", 0, 10, "Auto-collapse a no
|
|
|
90
90
|
SDATA_END()
|
|
91
91
|
];
|
|
92
92
|
|
|
93
|
+
/*
|
|
94
|
+
* What the graph listens for while you are READING it, and while you
|
|
95
|
+
* are PICKING the node to anchor.
|
|
96
|
+
*
|
|
97
|
+
* The difference is `drag-element`: with it on, a click that drifts
|
|
98
|
+
* two pixels -- which is every click a hand makes -- becomes a drag,
|
|
99
|
+
* G6 fires no `node:click`, and the pick silently does not happen.
|
|
100
|
+
* Swapped with `setBehaviors()` and not with a behavior's `enable`,
|
|
101
|
+
* which REPLACES the behavior's own default test rather than adding
|
|
102
|
+
* to it.
|
|
103
|
+
*/
|
|
104
|
+
/*
|
|
105
|
+
* `zoom-canvas` with NO animation, and that is two rules at once.
|
|
106
|
+
*
|
|
107
|
+
* The house rule first: nothing in this GUI slides or fades, and G6's
|
|
108
|
+
* 200ms zoom easing is a transition nobody chose -- it comes with the
|
|
109
|
+
* behavior's defaults.
|
|
110
|
+
*
|
|
111
|
+
* And it is what makes an anchor possible on the WHEEL. `aftertransform`
|
|
112
|
+
* fires while that easing is still running, so the re-centring measured
|
|
113
|
+
* a camera that was still moving: measured, its passes went -272, then
|
|
114
|
+
* +411 the other side, then +183 -- oscillating, because between two
|
|
115
|
+
* reads the easing had moved the ground. With the zoom instantaneous
|
|
116
|
+
* the camera is still by the time anything measures it.
|
|
117
|
+
*/
|
|
118
|
+
const ZOOM_CANVAS = {type: 'zoom-canvas', animation: false};
|
|
119
|
+
|
|
120
|
+
const BEHAVIORS_READING = ['drag-canvas', ZOOM_CANVAS, 'drag-element'];
|
|
121
|
+
const BEHAVIORS_PICKING = ['drag-canvas', ZOOM_CANVAS];
|
|
122
|
+
|
|
93
123
|
let PRIVATE_DATA = {
|
|
94
124
|
canvas_id: "",
|
|
95
125
|
graph: null,
|
|
@@ -408,13 +438,7 @@ function build_ui(gobj)
|
|
|
408
438
|
['div', {class: 'C_YUI_GOBJ_TREE_JS', style: 'height:100%; display:flex; flex-direction:column; position:relative;'}, [
|
|
409
439
|
['div', {class: 'is-flex-grow-0 is-flex toolbar_yui_gobj_tree'}, $toolbar],
|
|
410
440
|
['div', {class: 'is-flex-grow-1', style: 'height:100%; min-height:0; overflow:hidden;'}, [
|
|
411
|
-
|
|
412
|
-
* stylesheet of its own: G6 puts `touch-action: none` on its canvas and
|
|
413
|
-
* nothing on the html nodes over it, so without this a finger dragging a
|
|
414
|
-
* card makes a page scroll and stops dead after ~20px; and a card is
|
|
415
|
-
* text, so a mouse drag would start a selection. Same two rules
|
|
416
|
-
* `lib_graph.css` carries for the treedb graph. */
|
|
417
|
-
['div', {id: priv.canvas_id, class: 'gobj-tree-container', style: 'height:100%; min-height:0; border: 1px solid var(--bulma-border-weak); border-radius:0.2rem; touch-action:none; -webkit-user-select:none; user-select:none;'}, [
|
|
441
|
+
['div', {id: priv.canvas_id, class: 'gobj-tree-container', style: 'height:100%; min-height:0; border: 1px solid var(--bulma-border-weak); border-radius:0.2rem;'}, [
|
|
418
442
|
]]
|
|
419
443
|
]]
|
|
420
444
|
]]
|
|
@@ -654,17 +678,7 @@ function build_graph(gobj)
|
|
|
654
678
|
|
|
655
679
|
layout: layout_cfg.g6_layout,
|
|
656
680
|
|
|
657
|
-
behaviors:
|
|
658
|
-
'drag-canvas',
|
|
659
|
-
'zoom-canvas',
|
|
660
|
-
/* Move a card by dragging it. The position is not kept --
|
|
661
|
-
* this tree is rebuilt from the live gobj tree on every
|
|
662
|
-
* refresh -- and it is still worth having: pulling two
|
|
663
|
-
* cards apart to read the lines between them is the whole
|
|
664
|
-
* use of it. `enable` REPLACES a behavior's default rather
|
|
665
|
-
* than adding to it, so it is not passed. */
|
|
666
|
-
'drag-element',
|
|
667
|
-
],
|
|
681
|
+
behaviors: BEHAVIORS_READING.slice(),
|
|
668
682
|
});
|
|
669
683
|
|
|
670
684
|
if(priv.theme) {
|
|
@@ -2014,6 +2028,24 @@ function ac_center_anchor(gobj, event, kw, src)
|
|
|
2014
2028
|
return 0;
|
|
2015
2029
|
}
|
|
2016
2030
|
|
|
2031
|
+
/************************************************************
|
|
2032
|
+
* Reading, or picking the node to anchor.
|
|
2033
|
+
************************************************************/
|
|
2034
|
+
function set_picking_mode(gobj, picking)
|
|
2035
|
+
{
|
|
2036
|
+
let graph = gobj.priv.graph;
|
|
2037
|
+
|
|
2038
|
+
if(graph && typeof graph.setBehaviors === "function") {
|
|
2039
|
+
graph.setBehaviors((picking? BEHAVIORS_PICKING: BEHAVIORS_READING).slice());
|
|
2040
|
+
}
|
|
2041
|
+
|
|
2042
|
+
let $container = gobj_read_attr(gobj, "$container");
|
|
2043
|
+
let $mount = $container? $container.querySelector('.gobj-tree-container'): null;
|
|
2044
|
+
if($mount) {
|
|
2045
|
+
$mount.classList.toggle('GOBJ_TREE_PICKING', !!picking);
|
|
2046
|
+
}
|
|
2047
|
+
}
|
|
2048
|
+
|
|
2017
2049
|
/************************************************************
|
|
2018
2050
|
* Arm the anchor, or let it go.
|
|
2019
2051
|
*
|
|
@@ -2035,6 +2067,7 @@ function ac_toggle_anchor(gobj, event, kw, src)
|
|
|
2035
2067
|
}
|
|
2036
2068
|
|
|
2037
2069
|
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
2070
|
+
set_picking_mode(gobj, priv.anchor_state === "arming");
|
|
2038
2071
|
return 0;
|
|
2039
2072
|
}
|
|
2040
2073
|
|
|
@@ -2139,6 +2172,7 @@ function ac_node_click(gobj, event, kw, src)
|
|
|
2139
2172
|
priv.anchor_name = node_data.full_name || "";
|
|
2140
2173
|
priv.anchor_state = "on";
|
|
2141
2174
|
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
2175
|
+
set_picking_mode(gobj, false);
|
|
2142
2176
|
|
|
2143
2177
|
/* POSTED, not made here: a camera move issued inside G6's click
|
|
2144
2178
|
* dispatch is swallowed -- see the note in yui_graph_center_on.
|
package/src/c_yui_json.css
CHANGED
|
@@ -293,33 +293,6 @@
|
|
|
293
293
|
z-index: 1;
|
|
294
294
|
}
|
|
295
295
|
|
|
296
|
-
/*
|
|
297
|
-
* The graph mount, once its cards can be DRAGGED.
|
|
298
|
-
*
|
|
299
|
-
* Two problems, both of them the browser's rather than G6's, and both
|
|
300
|
-
* already paid for once in the treedb graph (`lib_graph.css`):
|
|
301
|
-
*
|
|
302
|
-
* G6 puts `touch-action: none` on its CANVAS and NOTHING on the html
|
|
303
|
-
* nodes, which are ordinary DIVs layered over it. So a finger landing
|
|
304
|
-
* on a card made a page scroll: two `pointermove`s through, then the
|
|
305
|
-
* browser decided the gesture was a scroll and killed the stream with
|
|
306
|
-
* `pointercancel` -- the card followed for about 20px and stopped dead
|
|
307
|
-
* while the page slid.
|
|
308
|
-
*
|
|
309
|
-
* And a card is text: dragging one starts a text selection, and the
|
|
310
|
-
* wash stays until the next click somewhere else. Nothing on this
|
|
311
|
-
* canvas is prose.
|
|
312
|
-
*
|
|
313
|
-
* On the CONTAINER and not the cards: every layer G6 stacks in here is
|
|
314
|
-
* a DIV over a canvas that already refuses the browser's gestures, and
|
|
315
|
-
* they have to agree.
|
|
316
|
-
*/
|
|
317
|
-
.C_YUI_JSON .json-graph-container {
|
|
318
|
-
touch-action: none;
|
|
319
|
-
-webkit-user-select: none;
|
|
320
|
-
user-select: none;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
296
|
/*
|
|
324
297
|
* Disable any transition a host stylesheet might inject.
|
|
325
298
|
*/
|
package/src/c_yui_json_graph.js
CHANGED
|
@@ -205,6 +205,7 @@ let PRIVATE_DATA = {
|
|
|
205
205
|
anchor_path: "", // its path, so a rebuild can find it again
|
|
206
206
|
anchor_state: "off", // "off" | "arming" | "on"
|
|
207
207
|
last_zoom: 1, // tells a wheel zoom from a drag in aftertransform
|
|
208
|
+
center_posted: false, // one re-centring in flight, never a queue of them
|
|
208
209
|
};
|
|
209
210
|
|
|
210
211
|
let __gclass__ = null;
|
|
@@ -692,24 +693,7 @@ function build_graph(gobj)
|
|
|
692
693
|
|
|
693
694
|
layout: layout_cfg.g6_layout,
|
|
694
695
|
|
|
695
|
-
behaviors:
|
|
696
|
-
'drag-canvas',
|
|
697
|
-
'zoom-canvas',
|
|
698
|
-
/*
|
|
699
|
-
* Move a card by dragging it. The position is NOT kept:
|
|
700
|
-
* the graph is rebuilt from the document on every refresh,
|
|
701
|
-
* fold and layout change, and there is nothing here to
|
|
702
|
-
* save it to -- this is a viewer over a value somebody
|
|
703
|
-
* handed it, not a document of its own. Deliberate: being
|
|
704
|
-
* able to pull two cards apart to read the lines between
|
|
705
|
-
* them is worth having even when it lasts one session.
|
|
706
|
-
*
|
|
707
|
-
* No `enable`: a behavior's `enable` REPLACES the default,
|
|
708
|
-
* it does not add to it, and the default here is exactly
|
|
709
|
-
* what is wanted.
|
|
710
|
-
*/
|
|
711
|
-
'drag-element',
|
|
712
|
-
],
|
|
696
|
+
behaviors: BEHAVIORS_READING.slice(),
|
|
713
697
|
});
|
|
714
698
|
|
|
715
699
|
if(priv.theme) {
|
|
@@ -748,8 +732,22 @@ function build_graph(gobj)
|
|
|
748
732
|
return;
|
|
749
733
|
}
|
|
750
734
|
priv.last_zoom = z;
|
|
751
|
-
|
|
752
|
-
|
|
735
|
+
|
|
736
|
+
/*
|
|
737
|
+
* POSTED, like the pick. This runs inside G6's own transform
|
|
738
|
+
* emit, and a camera move made there behaves the way one made
|
|
739
|
+
* inside its click dispatch does: measured, the centring runs,
|
|
740
|
+
* its three passes each fire back here, and the card still ends
|
|
741
|
+
* up hundreds of pixels off -- while the same call from a zoom
|
|
742
|
+
* BUTTON, which lands after the zoom promise resolved, centres
|
|
743
|
+
* exactly. One turn later is out of that stack.
|
|
744
|
+
*
|
|
745
|
+
* At most one in flight: a wheel gesture is a burst of notches,
|
|
746
|
+
* and the queue is not a work queue.
|
|
747
|
+
*/
|
|
748
|
+
if(priv.anchor_state === "on" && priv.anchor_id && !priv.center_posted) {
|
|
749
|
+
priv.center_posted = true;
|
|
750
|
+
gobj_post_event(gobj, "EV_CENTER_ANCHOR", {}, gobj);
|
|
753
751
|
}
|
|
754
752
|
});
|
|
755
753
|
|
|
@@ -899,6 +897,39 @@ function build_cell_html(key, value, type, dark, matched, fold)
|
|
|
899
897
|
************************************************************/
|
|
900
898
|
const FOLD_SPACER = `<span style="width:24px; flex:0 0 auto;"></span>`;
|
|
901
899
|
|
|
900
|
+
/*
|
|
901
|
+
* What the graph listens for while you are READING it, and while you
|
|
902
|
+
* are PICKING the node to anchor.
|
|
903
|
+
*
|
|
904
|
+
* The difference is `drag-element`, and dropping it is not a detail:
|
|
905
|
+
* with it on, a click that drifts two pixels -- which is every click a
|
|
906
|
+
* hand makes -- becomes a drag, G6 fires no `node:click`, and the pick
|
|
907
|
+
* silently does not happen. Measured: an instant click anchors, the
|
|
908
|
+
* same click with 2px of movement does not.
|
|
909
|
+
*
|
|
910
|
+
* Swapped with `setBehaviors()` and not with a behavior's `enable`,
|
|
911
|
+
* which REPLACES the behavior's own default test rather than adding to
|
|
912
|
+
* it -- the trap that made a card drag pan the canvas in 7.23.10.
|
|
913
|
+
*/
|
|
914
|
+
/*
|
|
915
|
+
* `zoom-canvas` with NO animation, and that is two rules at once.
|
|
916
|
+
*
|
|
917
|
+
* The house rule first: nothing in this GUI slides or fades, and G6's
|
|
918
|
+
* 200ms zoom easing is a transition nobody chose -- it comes with the
|
|
919
|
+
* behavior's defaults.
|
|
920
|
+
*
|
|
921
|
+
* And it is what makes an anchor possible on the WHEEL. `aftertransform`
|
|
922
|
+
* fires while that easing is still running, so the re-centring measured
|
|
923
|
+
* a camera that was still moving: measured, its passes went -272, then
|
|
924
|
+
* +411 the other side, then +183 -- oscillating, because between two
|
|
925
|
+
* reads the easing had moved the ground. With the zoom instantaneous
|
|
926
|
+
* the camera is still by the time anything measures it.
|
|
927
|
+
*/
|
|
928
|
+
const ZOOM_CANVAS = {type: 'zoom-canvas', animation: false};
|
|
929
|
+
|
|
930
|
+
const BEHAVIORS_READING = ['drag-canvas', ZOOM_CANVAS, 'drag-element'];
|
|
931
|
+
const BEHAVIORS_PICKING = ['drag-canvas', ZOOM_CANVAS];
|
|
932
|
+
|
|
902
933
|
/*
|
|
903
934
|
* The card's geometry, in ONE place.
|
|
904
935
|
*
|
|
@@ -1152,8 +1183,21 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id, parent_port)
|
|
|
1152
1183
|
let min_width = Math.max(180, label.length * 9);
|
|
1153
1184
|
let card_height = CARD_HEADER_H + lines.length * CARD_ROW_H;
|
|
1154
1185
|
|
|
1186
|
+
/*
|
|
1187
|
+
* The card carries its NAME and its PLACE in the document.
|
|
1188
|
+
*
|
|
1189
|
+
* `JSON_CARD` because a gclass that builds DOM has to leave a tree
|
|
1190
|
+
* somebody can read in the Inspector, and until now every card here
|
|
1191
|
+
* was an anonymous `<div>` among the anonymous `<div>`s G6 stacks.
|
|
1192
|
+
*
|
|
1193
|
+
* `data-json-path` because the anchor has to be able to find the
|
|
1194
|
+
* card it is holding: G6 paints no state style on an html node, so
|
|
1195
|
+
* the mark cannot be a node state and has to be a class on this
|
|
1196
|
+
* element -- and the path is what survives a rebuild, where the
|
|
1197
|
+
* node id does not.
|
|
1198
|
+
*/
|
|
1155
1199
|
let node_html = `
|
|
1156
|
-
<div style="
|
|
1200
|
+
<div class="JSON_CARD" data-json-path="${escapeHtml(path)}" style="
|
|
1157
1201
|
min-width: ${min_width}px;
|
|
1158
1202
|
background: ${colors.bg};
|
|
1159
1203
|
border: ${border_width}px ${is_dict ? 'dashed' : 'solid'} ${border_color};
|
|
@@ -1348,6 +1392,7 @@ function load_json(gobj)
|
|
|
1348
1392
|
/* Ids are generated per build: point the anchor at its path
|
|
1349
1393
|
* again before anybody asks the camera to go there. */
|
|
1350
1394
|
reanchor(gobj);
|
|
1395
|
+
paint_anchor_mark(gobj);
|
|
1351
1396
|
|
|
1352
1397
|
if(preserve_view) {
|
|
1353
1398
|
yui_graph_update_zoom(gobj_read_attr(gobj, "$container"), priv.graph);
|
|
@@ -1820,6 +1865,65 @@ function reanchor(gobj)
|
|
|
1820
1865
|
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
1821
1866
|
}
|
|
1822
1867
|
|
|
1868
|
+
/************************************************************
|
|
1869
|
+
* Reading, or picking the node to anchor.
|
|
1870
|
+
*
|
|
1871
|
+
* Two visible consequences and one invisible: the cursor says
|
|
1872
|
+
* a click is expected, the mount says which mode it is in for
|
|
1873
|
+
* anyone reading the DOM, and node dragging stands aside so a
|
|
1874
|
+
* click that drifts is still a click.
|
|
1875
|
+
************************************************************/
|
|
1876
|
+
function set_picking_mode(gobj, picking)
|
|
1877
|
+
{
|
|
1878
|
+
let priv = gobj.priv;
|
|
1879
|
+
let graph = priv.graph;
|
|
1880
|
+
|
|
1881
|
+
if(graph && typeof graph.setBehaviors === "function") {
|
|
1882
|
+
graph.setBehaviors((picking? BEHAVIORS_PICKING: BEHAVIORS_READING).slice());
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
let $container = gobj_read_attr(gobj, "$container");
|
|
1886
|
+
if($container) {
|
|
1887
|
+
let $mount = $container.querySelector('.json-graph-container');
|
|
1888
|
+
if($mount) {
|
|
1889
|
+
$mount.classList.toggle('JSON_GRAPH_PICKING', !!picking);
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1894
|
+
/************************************************************
|
|
1895
|
+
* Mark the card the camera is holding.
|
|
1896
|
+
*
|
|
1897
|
+
* A class on the card's own element and not a G6 node state:
|
|
1898
|
+
* G6 paints no state style on an html node, so `setElementState`
|
|
1899
|
+
* would select it correctly and show nothing.
|
|
1900
|
+
*
|
|
1901
|
+
* Re-applied after every rebuild, because the cards are new DOM
|
|
1902
|
+
* each time and the mark would otherwise survive only until the
|
|
1903
|
+
* next fold.
|
|
1904
|
+
************************************************************/
|
|
1905
|
+
function paint_anchor_mark(gobj)
|
|
1906
|
+
{
|
|
1907
|
+
let priv = gobj.priv;
|
|
1908
|
+
let $container = gobj_read_attr(gobj, "$container");
|
|
1909
|
+
|
|
1910
|
+
if(!$container) {
|
|
1911
|
+
return;
|
|
1912
|
+
}
|
|
1913
|
+
for(let $card of $container.querySelectorAll('.JSON_CARD_ANCHORED')) {
|
|
1914
|
+
$card.classList.remove('JSON_CARD_ANCHORED');
|
|
1915
|
+
}
|
|
1916
|
+
if(priv.anchor_state !== "on" || !priv.anchor_path) {
|
|
1917
|
+
return;
|
|
1918
|
+
}
|
|
1919
|
+
let $it = $container.querySelector(
|
|
1920
|
+
'.JSON_CARD[data-json-path="' + CSS.escape(priv.anchor_path) + '"]'
|
|
1921
|
+
);
|
|
1922
|
+
if($it) {
|
|
1923
|
+
$it.classList.add('JSON_CARD_ANCHORED');
|
|
1924
|
+
}
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1823
1927
|
/************************************************************
|
|
1824
1928
|
* Centre on the anchor, one cycle after it was chosen.
|
|
1825
1929
|
************************************************************/
|
|
@@ -1827,6 +1931,8 @@ function ac_center_anchor(gobj, event, kw, src)
|
|
|
1827
1931
|
{
|
|
1828
1932
|
let priv = gobj.priv;
|
|
1829
1933
|
|
|
1934
|
+
priv.center_posted = false;
|
|
1935
|
+
paint_anchor_mark(gobj);
|
|
1830
1936
|
if(priv.anchor_state === "on" && priv.anchor_id) {
|
|
1831
1937
|
yui_graph_center_on(priv.graph, priv.anchor_id);
|
|
1832
1938
|
}
|
|
@@ -1854,6 +1960,8 @@ function ac_toggle_anchor(gobj, event, kw, src)
|
|
|
1854
1960
|
}
|
|
1855
1961
|
|
|
1856
1962
|
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
1963
|
+
paint_anchor_mark(gobj);
|
|
1964
|
+
set_picking_mode(gobj, priv.anchor_state === "arming");
|
|
1857
1965
|
return 0;
|
|
1858
1966
|
}
|
|
1859
1967
|
|
|
@@ -1945,6 +2053,7 @@ function ac_node_click(gobj, event, kw, src)
|
|
|
1945
2053
|
priv.anchor_path = (nodedata && nodedata.data)? nodedata.data.path: "";
|
|
1946
2054
|
priv.anchor_state = "on";
|
|
1947
2055
|
yui_graph_update_anchor(gobj_read_attr(gobj, "$container"), priv.anchor_state);
|
|
2056
|
+
set_picking_mode(gobj, false);
|
|
1948
2057
|
|
|
1949
2058
|
/*
|
|
1950
2059
|
* The camera move is POSTED, not made here.
|
package/src/lib_graph.css
CHANGED
|
@@ -256,6 +256,73 @@
|
|
|
256
256
|
* pressed button hands it back to Bulma's rule and the toggle appears
|
|
257
257
|
* to switch off under the pointer.
|
|
258
258
|
*/
|
|
259
|
+
/*
|
|
260
|
+
* THE OTHER TWO GRAPHS' MOUNTS.
|
|
261
|
+
*
|
|
262
|
+
* They live here, unscoped, and that is the point: these rules first
|
|
263
|
+
* shipped inside `c_yui_json.css` under a `.C_YUI_JSON` ancestor, and
|
|
264
|
+
* a host that mounts `C_YUI_JSON_GRAPH` DIRECTLY -- which the demo
|
|
265
|
+
* does, and any host wanting only the graph -- has no such ancestor.
|
|
266
|
+
* Every one of them silently did nothing there: no crosshair while
|
|
267
|
+
* picking, no mark on the anchored card, and no `touch-action`, so a
|
|
268
|
+
* finger dragging a card made a page scroll. A gclass's stylesheet
|
|
269
|
+
* cannot assume the gclass that usually hosts it.
|
|
270
|
+
*
|
|
271
|
+
* `lib_graph.css` is reached through `lib_graph.js`, which the camera
|
|
272
|
+
* module imports and every one of these graphs uses, so it is loaded
|
|
273
|
+
* wherever a graph is.
|
|
274
|
+
*/
|
|
275
|
+
|
|
276
|
+
/*
|
|
277
|
+
* Picking the node to anchor: the pointer says a click is expected,
|
|
278
|
+
* which is otherwise announced only by a button at the far end of a
|
|
279
|
+
* toolbar. `!important` because G6 writes `cursor` onto its own
|
|
280
|
+
* elements from its style props, and a mode has to win over a default.
|
|
281
|
+
*/
|
|
282
|
+
.json-graph-container.JSON_GRAPH_PICKING,
|
|
283
|
+
.json-graph-container.JSON_GRAPH_PICKING *,
|
|
284
|
+
.gobj-tree-container.GOBJ_TREE_PICKING,
|
|
285
|
+
.gobj-tree-container.GOBJ_TREE_PICKING * {
|
|
286
|
+
cursor: crosshair !important;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/*
|
|
290
|
+
* The card the camera is holding.
|
|
291
|
+
*
|
|
292
|
+
* It has to say so ON THE CARD: the toolbar knows an anchor is set,
|
|
293
|
+
* and knowing WHICH node it is was left to the reader remembering
|
|
294
|
+
* what they clicked -- not a mark, a memory test.
|
|
295
|
+
*
|
|
296
|
+
* An outline and not a fill: the card's own colours already mean
|
|
297
|
+
* things (a dashed border is a dict, a solid one a list, the header
|
|
298
|
+
* carries the group's hue), so repainting any of them would say two
|
|
299
|
+
* things down one channel. `outline` draws OUTSIDE the box, so it
|
|
300
|
+
* cannot move a single row.
|
|
301
|
+
*
|
|
302
|
+
* Amber, the same "this one, right now" the toolbar's arming state
|
|
303
|
+
* uses, and not one of the palette's action colours -- it is not an
|
|
304
|
+
* action.
|
|
305
|
+
*/
|
|
306
|
+
.JSON_CARD_ANCHORED {
|
|
307
|
+
outline: 3px solid #fa8c16;
|
|
308
|
+
outline-offset: 2px;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/*
|
|
312
|
+
* Once the cards can be DRAGGED. Two problems, both the browser's:
|
|
313
|
+
* G6 puts `touch-action: none` on its CANVAS and nothing on the html
|
|
314
|
+
* nodes, which are ordinary DIVs layered over it, so a finger landing
|
|
315
|
+
* on a card made a page scroll -- two `pointermove`s, then
|
|
316
|
+
* `pointercancel`, the card dead after ~20px while the page slid. And
|
|
317
|
+
* a card is text, so a mouse drag started a selection.
|
|
318
|
+
*/
|
|
319
|
+
.json-graph-container,
|
|
320
|
+
.gobj-tree-container {
|
|
321
|
+
touch-action: none;
|
|
322
|
+
-webkit-user-select: none;
|
|
323
|
+
user-select: none;
|
|
324
|
+
}
|
|
325
|
+
|
|
259
326
|
.button.pressed_state,
|
|
260
327
|
.button.pressed_state:hover {
|
|
261
328
|
background-color: var(--bulma-text, #2e333d);
|
package/src/yui_graph_camera.js
CHANGED
|
@@ -233,11 +233,35 @@ export function yui_graph_update_anchor($container, state)
|
|
|
233
233
|
* an error worth a log line per notch, they are all "there is
|
|
234
234
|
* nothing to centre right now".
|
|
235
235
|
************************************************************/
|
|
236
|
+
const __centring__ = new WeakMap();
|
|
237
|
+
|
|
236
238
|
export async function yui_graph_center_on(graph, node_id)
|
|
237
239
|
{
|
|
238
240
|
if(!graph || !node_id) {
|
|
239
241
|
return false;
|
|
240
242
|
}
|
|
243
|
+
|
|
244
|
+
/*
|
|
245
|
+
* ONE centring at a time, per graph.
|
|
246
|
+
*
|
|
247
|
+
* This runs on every zoom notch, and one run is several awaited
|
|
248
|
+
* camera moves. A wheel gesture is a BURST of notches, so without
|
|
249
|
+
* this the runs overlap: each one measures a position another one
|
|
250
|
+
* is in the middle of changing, and they walk the camera around
|
|
251
|
+
* instead of converging -- which reads as a graph that pans and
|
|
252
|
+
* never centres.
|
|
253
|
+
*
|
|
254
|
+
* A request that arrives mid-run is not dropped, it is remembered:
|
|
255
|
+
* the last one wins and runs once at the end, which is the only
|
|
256
|
+
* one whose answer is still true.
|
|
257
|
+
*/
|
|
258
|
+
let st = __centring__.get(graph);
|
|
259
|
+
if(st && st.running) {
|
|
260
|
+
st.again = node_id;
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
__centring__.set(graph, {running: true, again: null});
|
|
264
|
+
|
|
241
265
|
try {
|
|
242
266
|
if(typeof graph.getElementData === "function" && !graph.getElementData(node_id)) {
|
|
243
267
|
return false;
|
|
@@ -250,7 +274,7 @@ export async function yui_graph_center_on(graph, node_id)
|
|
|
250
274
|
}
|
|
251
275
|
|
|
252
276
|
/*
|
|
253
|
-
*
|
|
277
|
+
* MOVE BY THE CLOSED FORM, then check -- up to three times.
|
|
254
278
|
*
|
|
255
279
|
* Not the arithmetic anybody would write first, and the reason
|
|
256
280
|
* is worth keeping. The obvious call is `graph.focusElement()`,
|
|
@@ -263,18 +287,26 @@ export async function yui_graph_center_on(graph, node_id)
|
|
|
263
287
|
* one shot lands short or long by a factor nobody should have
|
|
264
288
|
* to name.
|
|
265
289
|
*
|
|
266
|
-
*
|
|
267
|
-
*
|
|
268
|
-
*
|
|
269
|
-
*
|
|
270
|
-
*
|
|
271
|
-
*
|
|
272
|
-
*
|
|
290
|
+
* Guessing at that factor does not work: stepping by the
|
|
291
|
+
* measured pixel gap OSCILLATES -- measured, its passes went
|
|
292
|
+
* -272, then +411 the other side, then +183, with the zoom
|
|
293
|
+
* stable throughout, so it is not an animation racing the
|
|
294
|
+
* reads. The factor is read off G6's own
|
|
295
|
+
* `getTranslateOptions()` instead: an absolute translate puts
|
|
296
|
+
* the camera at `canvasCentre - T/zoom`, and the camera is
|
|
297
|
+
* what lands on the viewport centre, so
|
|
298
|
+
*
|
|
299
|
+
* T = (canvasCentre - nodeWorldPosition) * zoom
|
|
273
300
|
*
|
|
274
|
-
*
|
|
275
|
-
*
|
|
301
|
+
* which lands exactly, in one pass, at any zoom.
|
|
302
|
+
*
|
|
303
|
+
* The loop stays as a guard: it costs one measurement when the
|
|
304
|
+
* first move was right, and it is what would catch this going
|
|
305
|
+
* wrong again rather than shipping a graph that drifts. The
|
|
306
|
+
* 1px floor stops it chasing the rounding.
|
|
276
307
|
*/
|
|
277
308
|
for(let i = 0; i < 3; i++) {
|
|
309
|
+
let z = graph.getZoom() || 1;
|
|
278
310
|
let at = graph.getViewportByCanvas(graph.getElementPosition(node_id));
|
|
279
311
|
let want = graph.getCanvasCenter();
|
|
280
312
|
let dx = want[0] - at[0];
|
|
@@ -283,12 +315,22 @@ export async function yui_graph_center_on(graph, node_id)
|
|
|
283
315
|
if(Math.abs(dx) < 1 && Math.abs(dy) < 1) {
|
|
284
316
|
break;
|
|
285
317
|
}
|
|
286
|
-
|
|
287
|
-
|
|
318
|
+
/* Closed form, read off G6's own `getTranslateOptions()`:
|
|
319
|
+
* an ABSOLUTE translate puts the camera at
|
|
320
|
+
* `canvasCentre - T/zoom`, and the camera is what lands on
|
|
321
|
+
* the viewport centre. So T = (centre - node) * zoom. */
|
|
322
|
+
let n = graph.getElementPosition(node_id);
|
|
323
|
+
await graph.translateTo([(want[0] - n[0]) * z, (want[1] - n[1]) * z]);
|
|
288
324
|
}
|
|
289
325
|
return true;
|
|
290
326
|
} catch(e) {
|
|
291
327
|
return false; /* the element is gone, or the graph is between renders */
|
|
328
|
+
} finally {
|
|
329
|
+
let pending = __centring__.get(graph);
|
|
330
|
+
__centring__.set(graph, {running: false, again: null});
|
|
331
|
+
if(pending && pending.again) {
|
|
332
|
+
yui_graph_center_on(graph, pending.again);
|
|
333
|
+
}
|
|
292
334
|
}
|
|
293
335
|
}
|
|
294
336
|
|