@yuneta/gobj-ui 7.23.1 → 7.23.2

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.
@@ -3513,7 +3513,7 @@ function composed_title(gobj) {
3513
3513
  * Below the mobile breakpoint the window is a full-screen
3514
3514
  * sheet (no float / drag / resize).
3515
3515
  ************************************************************/
3516
- function is_mobile$2() {
3516
+ function is_mobile$3() {
3517
3517
  return (window.innerWidth || document.documentElement.offsetWidth) <= MOBILE_MAX;
3518
3518
  }
3519
3519
  /************************************************************
@@ -3546,7 +3546,7 @@ function do_minimize(gobj) {
3546
3546
  ************************************************************/
3547
3547
  function build_ui$15(gobj) {
3548
3548
  ensure_window_style();
3549
- let mobile = is_mobile$2();
3549
+ let mobile = is_mobile$3();
3550
3550
  let header = gobj_read_attr(gobj, "header");
3551
3551
  if (is_gobj(header)) header = gobj_read_attr(header, "$container");
3552
3552
  if (!header) header = build_default_header(gobj);
@@ -3884,7 +3884,7 @@ function min$1(gobj) {
3884
3884
  * handlers moving
3885
3885
  ************************************************************/
3886
3886
  function mvStart(gobj, evt) {
3887
- if (is_mobile$2()) return;
3887
+ if (is_mobile$3()) return;
3888
3888
  let $container = gobj_read_attr(gobj, "$container");
3889
3889
  let window_rect = $container.getBoundingClientRect();
3890
3890
  let x = evt.screenX;
@@ -4043,7 +4043,7 @@ function do_center(gobj, x, y, width, height) {
4043
4043
  function handleResize(gobj) {
4044
4044
  let $container = gobj_read_attr(gobj, "$container");
4045
4045
  if (!$container) return;
4046
- if (is_mobile$2()) {
4046
+ if (is_mobile$3()) {
4047
4047
  $container.classList.add("is-mobile-sheet");
4048
4048
  let vw = window.innerWidth || document.documentElement.offsetWidth;
4049
4049
  let vh = window.innerHeight || document.documentElement.offsetHeight;
@@ -9474,6 +9474,56 @@ var FOLD_SWALLOWED_EVENTS = [
9474
9474
  "mousedown",
9475
9475
  "click"
9476
9476
  ];
9477
+ var LAYOUTS$1 = {
9478
+ "json-tree": {
9479
+ label: "vertical tree",
9480
+ g6_layout: { type: "json-tree-layout" },
9481
+ edge_type: "cubic-vertical"
9482
+ },
9483
+ "dagre-tb": {
9484
+ label: "dagre top-down",
9485
+ g6_layout: {
9486
+ type: "antv-dagre",
9487
+ rankdir: "TB",
9488
+ nodesep: 20,
9489
+ ranksep: 40
9490
+ },
9491
+ edge_type: "polyline"
9492
+ },
9493
+ "dagre-lr": {
9494
+ label: "dagre left-right",
9495
+ g6_layout: {
9496
+ type: "antv-dagre",
9497
+ rankdir: "LR",
9498
+ nodesep: 20,
9499
+ ranksep: 40
9500
+ },
9501
+ edge_type: "polyline"
9502
+ }
9503
+ };
9504
+ var DEFAULT_LAYOUT = "json-tree";
9505
+ function get_layout_cfg$1(key) {
9506
+ return LAYOUTS$1[key] || LAYOUTS$1[DEFAULT_LAYOUT];
9507
+ }
9508
+ /************************************************************
9509
+ * A layout's label, with every key SPELLED OUT inside t().
9510
+ *
9511
+ * Never t(LAYOUTS[key].label) nor a `data-i18n` fed from that
9512
+ * table: the apps' validate-locales scans for t("literal"),
9513
+ * so a key reached through a variable is a key it cannot
9514
+ * demand — and i18next answers an undefined key with the key
9515
+ * itself, which renders in lower-case English and never
9516
+ * changes language. Twice already in this component's
9517
+ * history (7.20.0 `tree view`, and this table on its first
9518
+ * draft).
9519
+ ************************************************************/
9520
+ function layout_label(key) {
9521
+ switch (key) {
9522
+ case "dagre-tb": return t("dagre top-down");
9523
+ case "dagre-lr": return t("dagre left-right");
9524
+ default: return t("vertical tree");
9525
+ }
9526
+ }
9477
9527
  /***************************************************************
9478
9528
  * Data
9479
9529
  ***************************************************************/
@@ -9484,6 +9534,7 @@ var attrs_table$11 = [
9484
9534
  SDATA(data_type_t.DTP_POINTER, "$container", 0, null, "Container element"),
9485
9535
  SDATA(data_type_t.DTP_STRING, "canvas_id", 0, "", "Canvas ID"),
9486
9536
  SDATA(data_type_t.DTP_STRING, "wide", 0, "36px", "Height of header"),
9537
+ SDATA(data_type_t.DTP_STRING, "layout", 0, "json-tree", "Layout key (see LAYOUTS)"),
9487
9538
  SDATA_END()
9488
9539
  ];
9489
9540
  var PRIVATE_DATA$11 = {
@@ -9499,6 +9550,7 @@ var PRIVATE_DATA$11 = {
9499
9550
  match_count: 0,
9500
9551
  find_timer: null,
9501
9552
  fold_listener: null,
9553
+ $layout_select: null,
9502
9554
  $find_input: null,
9503
9555
  $find_result: null,
9504
9556
  $find_count: null
@@ -9673,6 +9725,7 @@ function build_ui$10(gobj) {
9673
9725
  };
9674
9726
  for (let type of FOLD_SWALLOWED_EVENTS) $mount.addEventListener(type, priv.fold_listener, true);
9675
9727
  } else log_error(`${gobj_short_name(gobj)}: no canvas mount, fold handles are dead`);
9728
+ priv.$layout_select = $container.querySelector(".JSON_GRAPH_LAYOUT");
9676
9729
  priv.$find_input = $container.querySelector(".JSON_GRAPH_FIND_INPUT");
9677
9730
  priv.$find_result = $container.querySelector(".JSON_GRAPH_FIND_RESULT");
9678
9731
  priv.$find_count = $container.querySelector(".JSON_GRAPH_FIND_COUNT");
@@ -9830,7 +9883,42 @@ function make_toolbar$3(gobj) {
9830
9883
  } }
9831
9884
  ]);
9832
9885
  }
9833
- let right_items = [graph_fold_button(gobj, "EV_EXPAND_ALL", "expand all", true), graph_fold_button(gobj, "EV_COLLAPSE_ALL", "collapse all", false)];
9886
+ let current_layout = gobj_read_str_attr(gobj, "layout") || DEFAULT_LAYOUT;
9887
+ let options = Object.keys(LAYOUTS$1).map(function(key) {
9888
+ let attrs = {
9889
+ value: key,
9890
+ "data-i18n": LAYOUTS$1[key].label
9891
+ };
9892
+ if (key === current_layout) attrs.selected = "selected";
9893
+ return [
9894
+ "option",
9895
+ attrs,
9896
+ layout_label(key)
9897
+ ];
9898
+ });
9899
+ let right_items = [
9900
+ createElement2([
9901
+ "select",
9902
+ {
9903
+ class: "JSON_GRAPH_LAYOUT select",
9904
+ style: {
9905
+ height: toolbar_wide,
9906
+ "margin-left": "0.5em"
9907
+ },
9908
+ title: t("layout"),
9909
+ "data-i18n-title": "layout",
9910
+ "aria-label": t("layout"),
9911
+ "data-i18n-aria-label": "layout"
9912
+ },
9913
+ options,
9914
+ { change: (evt) => {
9915
+ evt.stopPropagation();
9916
+ gobj_send_event(gobj, "EV_CHANGE_LAYOUT", { layout: evt.target.value }, gobj);
9917
+ } }
9918
+ ]),
9919
+ graph_fold_button(gobj, "EV_EXPAND_ALL", "expand all", true),
9920
+ graph_fold_button(gobj, "EV_COLLAPSE_ALL", "collapse all", false)
9921
+ ];
9834
9922
  const $toolbar = yui_toolbar({}, [
9835
9923
  [
9836
9924
  "div",
@@ -9856,6 +9944,7 @@ function make_toolbar$3(gobj) {
9856
9944
  ************************************************************/
9857
9945
  function build_graph$3(gobj) {
9858
9946
  let priv = gobj.priv;
9947
+ let layout_cfg = get_layout_cfg$1(gobj_read_str_attr(gobj, "layout"));
9859
9948
  const graph = priv.graph = new Graph({
9860
9949
  container: priv.canvas_id,
9861
9950
  animation: false,
@@ -9863,14 +9952,14 @@ function build_graph$3(gobj) {
9863
9952
  zoomRange: [.1, 4],
9864
9953
  node: { style: { labelPlacement: "center" } },
9865
9954
  edge: {
9866
- type: "cubic-vertical",
9955
+ type: layout_cfg.edge_type,
9867
9956
  style: {
9868
9957
  stroke: "#999",
9869
9958
  lineWidth: 1,
9870
9959
  endArrow: true
9871
9960
  }
9872
9961
  },
9873
- layout: { type: "json-tree-layout" },
9962
+ layout: layout_cfg.g6_layout,
9874
9963
  behaviors: ["drag-canvas", "zoom-canvas"]
9875
9964
  });
9876
9965
  if (priv.theme) graph.setTheme(priv.theme);
@@ -10297,6 +10386,34 @@ function ac_refresh$5(gobj, event, kw, src) {
10297
10386
  }
10298
10387
  /************************************************************
10299
10388
  * {theme: "dark"|"light"} — the app switched theme.
10389
+ * EV_CHANGE_LAYOUT { layout }
10390
+ *
10391
+ * The layout AND the edge type move together — a vertical
10392
+ * layout with horizontal cubics draws every edge the wrong way
10393
+ * round — and then the graph is rebuilt and refitted, because a
10394
+ * new layout is a new shape and the old camera framed the old
10395
+ * one.
10396
+ ************************************************************/
10397
+ function ac_change_layout$1(gobj, event, kw, src) {
10398
+ let priv = gobj.priv;
10399
+ let key = kw && kw.layout || "";
10400
+ if (!LAYOUTS$1[key]) {
10401
+ log_error(`${gobj_short_name(gobj)}: unknown layout '${key}'`);
10402
+ return -1;
10403
+ }
10404
+ if (key === gobj_read_str_attr(gobj, "layout")) return 0;
10405
+ gobj_write_str_attr(gobj, "layout", key);
10406
+ if (priv.$layout_select && priv.$layout_select.value !== key) priv.$layout_select.value = key;
10407
+ let cfg = get_layout_cfg$1(key);
10408
+ if (priv.graph) priv.graph.setOptions({
10409
+ layout: cfg.g6_layout,
10410
+ edge: { type: cfg.edge_type }
10411
+ });
10412
+ refresh_json(gobj);
10413
+ update_find_result(gobj);
10414
+ return 0;
10415
+ }
10416
+ /************************************************************
10300
10417
  * EV_TOGGLE_FOLD { path } — fold or unfold ONE card.
10301
10418
  *
10302
10419
  * The camera does not move: folding one branch is a local
@@ -10511,6 +10628,11 @@ function create_gclass$11(gclass_name) {
10511
10628
  ac_toggle_fold,
10512
10629
  null
10513
10630
  ],
10631
+ [
10632
+ "EV_CHANGE_LAYOUT",
10633
+ ac_change_layout$1,
10634
+ null
10635
+ ],
10514
10636
  [
10515
10637
  "EV_EXPAND_ALL",
10516
10638
  ac_expand_all$2,
@@ -10572,6 +10694,7 @@ function create_gclass$11(gclass_name) {
10572
10694
  ["EV_REFRESH", 0],
10573
10695
  ["EV_FIND_NODES", 0],
10574
10696
  ["EV_TOGGLE_FOLD", 0],
10697
+ ["EV_CHANGE_LAYOUT", 0],
10575
10698
  ["EV_EXPAND_ALL", 0],
10576
10699
  ["EV_COLLAPSE_ALL", 0],
10577
10700
  ["EV_THEME", 0],
@@ -10905,12 +11028,13 @@ function mt_start$10(gobj) {
10905
11028
  /***************************************************************
10906
11029
  * Framework Method: Stop
10907
11030
  ***************************************************************/
10908
- function mt_stop$10(gobj) {}
11031
+ function mt_stop$10(gobj) {
11032
+ teardown_graph_child(gobj);
11033
+ }
10909
11034
  /***************************************************************
10910
11035
  * Framework Method: Destroy
10911
11036
  ***************************************************************/
10912
11037
  function mt_destroy$10(gobj) {
10913
- teardown_graph_child(gobj);
10914
11038
  destroy_ui$5(gobj);
10915
11039
  }
10916
11040
  /***************************
@@ -16210,7 +16334,7 @@ function treedb_delete_node$1(gobj, treedb_name, topic_name, record, options) {
16210
16334
  /************************************************************
16211
16335
  * True on a phone-width viewport (Bulma's mobile breakpoint).
16212
16336
  ************************************************************/
16213
- function is_mobile$1() {
16337
+ function is_mobile$2() {
16214
16338
  return typeof window !== "undefined" && window.innerWidth <= 768;
16215
16339
  }
16216
16340
  /************************************************************
@@ -16229,7 +16353,7 @@ function open_json_viewer$1(gobj) {
16229
16353
  yui_shell_show_error(yui_shell_of(gobj), "raw json viewer unavailable", { t });
16230
16354
  return;
16231
16355
  }
16232
- let mobile = is_mobile$1();
16356
+ let mobile = is_mobile$2();
16233
16357
  let shell = yui_shell_of(gobj);
16234
16358
  let jv = gobj_create_service(`treedb-topics-json-${clean_name(gobj_name(gobj))}`, "C_YUI_JSON", { subscriber: gobj }, gobj);
16235
16359
  if (!jv) {
@@ -17442,10 +17566,102 @@ var PRIVATE_DATA$5 = {
17442
17566
  form_modal: null,
17443
17567
  schema_gobj: null,
17444
17568
  schema_modal: null,
17569
+ schema_win: null,
17445
17570
  cell_json_gobj: null,
17446
- cell_json_modal: null
17571
+ cell_json_modal: null,
17572
+ cell_json_win: null
17447
17573
  };
17448
17574
  var __gclass__$5 = null;
17575
+ function is_mobile$1() {
17576
+ return typeof window !== "undefined" && window.innerWidth <= 768;
17577
+ }
17578
+ /************************************************************
17579
+ * Present a JSON viewer's $container.
17580
+ *
17581
+ * On a LAPTOP a floating C_YUI_WINDOW: a JSON document is
17582
+ * something you read WHILE looking at the table behind it —
17583
+ * you move it, you resize it, you maximise it when the
17584
+ * document is big. A modal can do none of that, and it
17585
+ * darkens exactly the rows you opened the cell from.
17586
+ *
17587
+ * On a phone the modal sheet stays: there is no room to
17588
+ * arrange anything, and the sheet already carries the shell's
17589
+ * Escape / Back handling.
17590
+ *
17591
+ * Returns {win, modal} — exactly one of them is set.
17592
+ ************************************************************/
17593
+ function present_json_popup(gobj, $box, opts) {
17594
+ let shell = yui_shell_of(gobj);
17595
+ if (!shell) {
17596
+ log_error(`${gobj_short_name(gobj)}: no shell, cannot present the json`);
17597
+ return null;
17598
+ }
17599
+ if (is_mobile$1()) return {
17600
+ modal: yui_shell_show_modal(shell, $box, {
17601
+ dialog: true,
17602
+ logical_class: opts.logical_class + "_SHEET",
17603
+ title_prefix: opts.title_prefix,
17604
+ title: opts.title,
17605
+ t,
17606
+ on_close: opts.on_close
17607
+ }),
17608
+ win: null
17609
+ };
17610
+ let win = gobj_create_service(opts.name, "C_YUI_WINDOW", {
17611
+ $parent: popup_mount_layer(gobj),
17612
+ subscriber: null,
17613
+ modal: false,
17614
+ showMax: true,
17615
+ showFooter: false,
17616
+ resizable: true,
17617
+ center: true,
17618
+ auto_save_size_and_position: true,
17619
+ width: 720,
17620
+ height: 620,
17621
+ logical_class: opts.logical_class + "_WINDOW",
17622
+ title_prefix: opts.title_prefix,
17623
+ title: opts.title,
17624
+ icon: opts.icon,
17625
+ body: $box,
17626
+ manager: null,
17627
+ on_close: function() {
17628
+ if (gobj_is_destroying(gobj)) return;
17629
+ opts.forget_window();
17630
+ opts.on_close();
17631
+ }
17632
+ }, gobj);
17633
+ if (!win) {
17634
+ log_error(`${gobj_short_name(gobj)}: cannot create the json window`);
17635
+ return null;
17636
+ }
17637
+ gobj_start(win);
17638
+ return {
17639
+ win,
17640
+ modal: null
17641
+ };
17642
+ }
17643
+ /************************************************************
17644
+ * Retire a presenting window: reference cleared FIRST, then
17645
+ * stop, then destroy.
17646
+ *
17647
+ * The order is the whole content of this function. The ✕ of
17648
+ * the window calls back into the teardown that calls this, so
17649
+ * clearing the reference first is what stops the recursion.
17650
+ * And it is STOP then destroy because the window was started
17651
+ * on open: handing a running gobj to gobj_destroy() makes the
17652
+ * framework rescue it and say so — "Destroying a RUNNING
17653
+ * gobj" — which is a caller's bug, not a framework message.
17654
+ * Same lesson `c_tranger_view.close_json_viewer` carries.
17655
+ ************************************************************/
17656
+ function retire_popup_window(win) {
17657
+ if (!win) return;
17658
+ try {
17659
+ if (gobj_is_running(win)) gobj_stop(win);
17660
+ gobj_destroy(win);
17661
+ } catch (e) {
17662
+ log_warning(`${GCLASS_NAME$5}: json window already gone: ${e}`);
17663
+ }
17664
+ }
17449
17665
  function popup_mount_layer(gobj) {
17450
17666
  let $layer = yui_shell_popup_layer(yui_shell_of(gobj));
17451
17667
  if ($layer) return $layer;
@@ -18616,8 +18832,7 @@ function open_schema_dialog(gobj) {
18616
18832
  log_error(`${gobj_short_name(gobj)}: no desc, no schema to show`);
18617
18833
  return;
18618
18834
  }
18619
- let shell = yui_shell_of(gobj);
18620
- if (!shell) {
18835
+ if (!yui_shell_of(gobj)) {
18621
18836
  log_error(`${gobj_short_name(gobj)}: no shell, cannot open the schema view`);
18622
18837
  return;
18623
18838
  }
@@ -18634,16 +18849,25 @@ function open_schema_dialog(gobj) {
18634
18849
  teardown_schema_child(gobj);
18635
18850
  return;
18636
18851
  }
18637
- priv.schema_modal = yui_shell_show_modal(shell, $box, {
18638
- dialog: true,
18639
- logical_class: "TREEDB_SCHEMA_SHEET",
18852
+ let presented = present_json_popup(gobj, $box, {
18853
+ name: "schemawin_" + clean_name(gobj_name(gobj)),
18854
+ logical_class: "TREEDB_SCHEMA",
18640
18855
  title_prefix: gobj_read_str_attr(gobj, "topic_name"),
18641
18856
  title: "schema",
18642
- t,
18857
+ icon: "yi-table",
18858
+ forget_window: function() {
18859
+ priv.schema_win = null;
18860
+ },
18643
18861
  on_close: function() {
18644
18862
  teardown_schema_child(gobj);
18645
18863
  }
18646
18864
  });
18865
+ if (!presented) {
18866
+ teardown_schema_child(gobj);
18867
+ return;
18868
+ }
18869
+ priv.schema_modal = presented.modal;
18870
+ priv.schema_win = presented.win;
18647
18871
  gobj_send_event(json_view, "EV_SET_JSON", { json: desc }, gobj);
18648
18872
  }
18649
18873
  /************************************************************
@@ -18658,6 +18882,9 @@ function teardown_schema_child(gobj) {
18658
18882
  gobj_destroy(priv.schema_gobj);
18659
18883
  priv.schema_gobj = null;
18660
18884
  }
18885
+ let win = priv.schema_win;
18886
+ priv.schema_win = null;
18887
+ retire_popup_window(win);
18661
18888
  priv.schema_modal = null;
18662
18889
  }
18663
18890
  /************************************************************
@@ -18704,8 +18931,7 @@ function open_cell_json_dialog(gobj, row_id, col_id) {
18704
18931
  log_error(`${gobj_short_name(gobj)}: row '${row_id}' has no col '${col_id}'`);
18705
18932
  return;
18706
18933
  }
18707
- let shell = yui_shell_of(gobj);
18708
- if (!shell) {
18934
+ if (!yui_shell_of(gobj)) {
18709
18935
  log_error(`${gobj_short_name(gobj)}: no shell, cannot open the cell json`);
18710
18936
  return;
18711
18937
  }
@@ -18722,16 +18948,25 @@ function open_cell_json_dialog(gobj, row_id, col_id) {
18722
18948
  teardown_cell_json_child(gobj);
18723
18949
  return;
18724
18950
  }
18725
- priv.cell_json_modal = yui_shell_show_modal(shell, $box, {
18726
- dialog: true,
18727
- logical_class: "TREEDB_CELL_JSON_SHEET",
18951
+ let presented = present_json_popup(gobj, $box, {
18952
+ name: "cellwin_" + clean_name(gobj_name(gobj)),
18953
+ logical_class: "TREEDB_CELL_JSON",
18728
18954
  title_prefix: String(row_id),
18729
18955
  title: col_id,
18730
- t,
18956
+ icon: "yi-js-square",
18957
+ forget_window: function() {
18958
+ priv.cell_json_win = null;
18959
+ },
18731
18960
  on_close: function() {
18732
18961
  teardown_cell_json_child(gobj);
18733
18962
  }
18734
18963
  });
18964
+ if (!presented) {
18965
+ teardown_cell_json_child(gobj);
18966
+ return;
18967
+ }
18968
+ priv.cell_json_modal = presented.modal;
18969
+ priv.cell_json_win = presented.win;
18735
18970
  gobj_send_event(json_view, "EV_SET_JSON", { json: value }, gobj);
18736
18971
  }
18737
18972
  /************************************************************
@@ -18746,6 +18981,9 @@ function teardown_cell_json_child(gobj) {
18746
18981
  gobj_destroy(priv.cell_json_gobj);
18747
18982
  priv.cell_json_gobj = null;
18748
18983
  }
18984
+ let win = priv.cell_json_win;
18985
+ priv.cell_json_win = null;
18986
+ retire_popup_window(win);
18749
18987
  priv.cell_json_modal = null;
18750
18988
  }
18751
18989
  /************************************************************
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuneta/gobj-ui",
3
- "version": "7.23.1",
3
+ "version": "7.23.2",
4
4
  "type": "module",
5
5
  "main": "dist/gobj-ui.cjs.js",
6
6
  "module": "dist/gobj-ui.es.js",
package/src/c_yui_json.js CHANGED
@@ -227,6 +227,21 @@ function mt_start(gobj)
227
227
  ***************************************************************/
228
228
  function mt_stop(gobj)
229
229
  {
230
+ /*
231
+ * The graph child dies with the parent's RUNNING state, not with
232
+ * its destruction, and the difference is not cosmetic:
233
+ * gobj_destroy() destroys the children BEFORE calling mt_destroy(),
234
+ * so tearing it down there arrived after the framework had already
235
+ * destroyed it — while it was still running. Closing the window
236
+ * logged "Destroying a RUNNING gobj" for the child and then
237
+ * "gobj NULL or DESTROYED" for this gobj's own attempt to stop it.
238
+ *
239
+ * Here it is stopped and destroyed while everything is still whole,
240
+ * and gobj_destroy() finds no child left to rescue. A later
241
+ * gobj_start + a switch back to the graph rebuilds it, which is the
242
+ * same lazy path a first entry takes.
243
+ */
244
+ teardown_graph_child(gobj);
230
245
  }
231
246
 
232
247
  /***************************************************************
@@ -234,7 +249,6 @@ function mt_stop(gobj)
234
249
  ***************************************************************/
235
250
  function mt_destroy(gobj)
236
251
  {
237
- teardown_graph_child(gobj);
238
252
  destroy_ui(gobj);
239
253
  }
240
254