@yuneta/gobj-ui 7.21.1 → 7.23.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.
@@ -9468,6 +9468,12 @@ function ensure_drag_canvas_patch() {
9468
9468
  * Constants
9469
9469
  ***************************************************************/
9470
9470
  var GCLASS_NAME$11 = "C_YUI_JSON_GRAPH";
9471
+ var FOLD_SWALLOWED_EVENTS = [
9472
+ "pointerdown",
9473
+ "pointerup",
9474
+ "mousedown",
9475
+ "click"
9476
+ ];
9471
9477
  /***************************************************************
9472
9478
  * Data
9473
9479
  ***************************************************************/
@@ -9487,7 +9493,15 @@ var PRIVATE_DATA$11 = {
9487
9493
  theme: null,
9488
9494
  theme_observer: null,
9489
9495
  resize_observer: null,
9490
- _resize_raf: 0
9496
+ _resize_raf: 0,
9497
+ search: "",
9498
+ collapsed: null,
9499
+ match_count: 0,
9500
+ find_timer: null,
9501
+ fold_listener: null,
9502
+ $find_input: null,
9503
+ $find_result: null,
9504
+ $find_count: null
9491
9505
  };
9492
9506
  var __gclass__$11 = null;
9493
9507
  var __layout_registered__$1 = false;
@@ -9556,6 +9570,8 @@ function type_color(type, dark) {
9556
9570
  ***************************************************************/
9557
9571
  function mt_create$11(gobj) {
9558
9572
  let priv = gobj.priv;
9573
+ priv.collapsed = /* @__PURE__ */ new Set();
9574
+ priv.search = "";
9559
9575
  priv.canvas_id = "json-canvas-" + clean_name(gobj_name(gobj));
9560
9576
  gobj_write_str_attr(gobj, "canvas_id", priv.canvas_id);
9561
9577
  let subscriber = gobj_read_pointer_attr(gobj, "subscriber");
@@ -9585,6 +9601,10 @@ function mt_stop$11(gobj) {}
9585
9601
  * Framework Method: Destroy
9586
9602
  ***************************************************************/
9587
9603
  function mt_destroy$11(gobj) {
9604
+ if (gobj.priv.find_timer) {
9605
+ clearTimeout(gobj.priv.find_timer);
9606
+ gobj.priv.find_timer = null;
9607
+ }
9588
9608
  let priv = gobj.priv;
9589
9609
  if (priv.theme_observer) {
9590
9610
  priv.theme_observer.disconnect();
@@ -9641,25 +9661,118 @@ function build_ui$10(gobj) {
9641
9661
  ]]
9642
9662
  ]);
9643
9663
  gobj_write_attr(gobj, "$container", $container);
9664
+ let $mount = $container.querySelector("#" + priv.canvas_id);
9665
+ if ($mount) {
9666
+ priv.fold_listener = function(evt) {
9667
+ let $handle = evt.target && evt.target.closest ? evt.target.closest("[data-fold-path]") : null;
9668
+ if (!$handle) return;
9669
+ evt.stopPropagation();
9670
+ evt.preventDefault();
9671
+ if (evt.type !== "click") return;
9672
+ gobj_send_event(gobj, "EV_TOGGLE_FOLD", { path: $handle.getAttribute("data-fold-path") }, gobj);
9673
+ };
9674
+ for (let type of FOLD_SWALLOWED_EVENTS) $mount.addEventListener(type, priv.fold_listener, true);
9675
+ } else log_error(`${gobj_short_name(gobj)}: no canvas mount, fold handles are dead`);
9676
+ priv.$find_input = $container.querySelector(".JSON_GRAPH_FIND_INPUT");
9677
+ priv.$find_result = $container.querySelector(".JSON_GRAPH_FIND_RESULT");
9678
+ priv.$find_count = $container.querySelector(".JSON_GRAPH_FIND_COUNT");
9644
9679
  refresh_language($container, t);
9645
9680
  }
9646
9681
  /************************************************************
9647
9682
  * Destroy UI
9648
9683
  ************************************************************/
9649
9684
  function destroy_ui$6(gobj) {
9685
+ let priv = gobj.priv;
9650
9686
  let $container = gobj_read_attr(gobj, "$container");
9687
+ if (priv.fold_listener) {
9688
+ let $mount = $container ? $container.querySelector("#" + priv.canvas_id) : null;
9689
+ if ($mount) for (let type of FOLD_SWALLOWED_EVENTS) $mount.removeEventListener(type, priv.fold_listener, true);
9690
+ priv.fold_listener = null;
9691
+ }
9651
9692
  if ($container) {
9652
9693
  if ($container.parentNode) $container.parentNode.removeChild($container);
9653
9694
  gobj_write_attr(gobj, "$container", null);
9654
9695
  }
9655
9696
  }
9656
9697
  /************************************************************
9698
+ * One fold button. `open` rotates the chevron to the open
9699
+ * state, mirroring the per-node toggle of the lazy tree.
9700
+ ************************************************************/
9701
+ function graph_fold_button(gobj, event_name, label_key, open) {
9702
+ let icon_style = "font-size:1.5em; color:inherit;" + (open ? " transform: rotate(90deg);" : "");
9703
+ return [
9704
+ "button",
9705
+ {
9706
+ class: `button ${event_name}`,
9707
+ type: "button",
9708
+ style: {
9709
+ height: gobj_read_attr(gobj, "wide"),
9710
+ width: "2.5em"
9711
+ },
9712
+ title: t(label_key),
9713
+ "data-i18n-title": label_key,
9714
+ "aria-label": t(label_key),
9715
+ "data-i18n-aria-label": label_key
9716
+ },
9717
+ ["i", {
9718
+ style: icon_style,
9719
+ class: "yi-chevron-right"
9720
+ }],
9721
+ { click: (evt) => {
9722
+ evt.stopPropagation();
9723
+ gobj_send_event(gobj, event_name, {}, gobj);
9724
+ } }
9725
+ ];
9726
+ }
9727
+ /************************************************************
9657
9728
  * Toolbar
9658
9729
  ************************************************************/
9659
9730
  function make_toolbar$3(gobj) {
9660
- gobj.priv;
9731
+ let priv = gobj.priv;
9661
9732
  let toolbar_wide = gobj_read_attr(gobj, "wide");
9662
- let left_items = [];
9733
+ let left_items = [[
9734
+ "div",
9735
+ {
9736
+ class: "JSON_GRAPH_FIND control has-icons-left",
9737
+ style: "margin-right:.5rem; max-width:12rem; min-width:7rem;"
9738
+ },
9739
+ [["input", {
9740
+ class: "JSON_GRAPH_FIND_INPUT input",
9741
+ type: "text",
9742
+ placeholder: t("search"),
9743
+ "data-i18n-placeholder": "search",
9744
+ "aria-label": t("search"),
9745
+ "data-i18n-aria-label": "search"
9746
+ }], [
9747
+ "span",
9748
+ { class: "icon is-left" },
9749
+ [["i", { class: "yi-magnifying-glass" }]]
9750
+ ]],
9751
+ { input: (evt) => {
9752
+ evt.stopPropagation();
9753
+ let text = evt.target.value.trim();
9754
+ if (priv.find_timer) clearTimeout(priv.find_timer);
9755
+ priv.find_timer = setTimeout(function() {
9756
+ priv.find_timer = null;
9757
+ gobj_send_event(gobj, "EV_FIND_NODES", { text }, gobj);
9758
+ }, 250);
9759
+ } }
9760
+ ], [
9761
+ "div",
9762
+ {
9763
+ class: "JSON_GRAPH_FIND_RESULT is-hidden",
9764
+ style: "display:flex; align-items:center; gap:.3rem; margin-right:.5rem; font-size:.85rem;"
9765
+ },
9766
+ [[
9767
+ "span",
9768
+ { class: "JSON_GRAPH_FIND_COUNT" },
9769
+ ""
9770
+ ], [
9771
+ "span",
9772
+ { i18n: "matches" },
9773
+ "matches"
9774
+ ]]
9775
+ ]];
9663
9776
  let center_items = [];
9664
9777
  for (let item of [
9665
9778
  [
@@ -9717,6 +9830,7 @@ function make_toolbar$3(gobj) {
9717
9830
  } }
9718
9831
  ]);
9719
9832
  }
9833
+ let right_items = [graph_fold_button(gobj, "EV_EXPAND_ALL", "expand all", true), graph_fold_button(gobj, "EV_COLLAPSE_ALL", "collapse all", false)];
9720
9834
  const $toolbar = yui_toolbar({}, [
9721
9835
  [
9722
9836
  "div",
@@ -9731,7 +9845,7 @@ function make_toolbar$3(gobj) {
9731
9845
  [
9732
9846
  "div",
9733
9847
  { class: "yui-horizontal-toolbar-section right" },
9734
- []
9848
+ right_items
9735
9849
  ]
9736
9850
  ]);
9737
9851
  refresh_language($toolbar, t);
@@ -9782,7 +9896,7 @@ function build_graph$3(gobj) {
9782
9896
  /************************************************************
9783
9897
  * Build cell value HTML (matching old mx_json_viewer colors)
9784
9898
  ************************************************************/
9785
- function build_cell_html(key, value, type, dark) {
9899
+ function build_cell_html(key, value, type, dark, matched) {
9786
9900
  let color = type_color(type, dark);
9787
9901
  let key_color = json_card_style(GROUP_COLORS.dict, dark).key;
9788
9902
  let display_value = "";
@@ -9807,7 +9921,48 @@ function build_cell_html(key, value, type, dark) {
9807
9921
  break;
9808
9922
  default: display_value = String(value);
9809
9923
  }
9810
- return `<span style="color:${key_color}">• ${escapeHtml(String(key))}: </span><span style="color:${color}">${display_value}</span>`;
9924
+ let row = `<span style="color:${key_color}">• ${escapeHtml(String(key))}: </span><span style="color:${color}">${display_value}</span>`;
9925
+ if (matched) row = `<span style="background:${dark ? "#7a5d00" : "#ffe082"}; border-radius:2px; padding:0 2px;">${row}</span>`;
9926
+ return row;
9927
+ }
9928
+ /************************************************************
9929
+ * The per-node fold handle, drawn in the card's header.
9930
+ *
9931
+ * Only a card with a BRANCH gets one — a leaf has nothing to
9932
+ * fold, and a handle that does nothing is worse than none.
9933
+ * It carries the path in `data-fold-path`, which is what the
9934
+ * delegated listener in build_ui reads; the card is an
9935
+ * innerHTML string, so there is no other way to hang a
9936
+ * handler on it.
9937
+ *
9938
+ * Folded it shows the glyph AND the count of branches hidden
9939
+ * under it; open, just the glyph. No word, no title: a word
9940
+ * inside this string could carry no i18n key.
9941
+ ************************************************************/
9942
+ function fold_toggle_html(path, foldable, folded, branches) {
9943
+ if (!foldable) return `<span style="width:1.1em; flex:0 0 auto;"></span>`;
9944
+ let glyph = folded ? "&#9656;" : "&#9662;";
9945
+ let text = folded ? `${glyph} ${branches}` : glyph;
9946
+ return `<span data-fold-path="${escapeHtml(path)}" style="flex:0 0 auto; cursor:pointer; user-select:none; padding:0 .2em; min-width:1.1em; text-align:left;">${text}</span>`;
9947
+ }
9948
+ /************************************************************
9949
+ * Does this key/value pair match the find term?
9950
+ *
9951
+ * Scalars are matched on what the card SHOWS. A complex value
9952
+ * is not: its contents are a card of their own and match there,
9953
+ * so matching the `{3}` summary too would light up every
9954
+ * ancestor of every hit.
9955
+ ************************************************************/
9956
+ function cell_matches(key, value, type, needle) {
9957
+ if (empty_string(needle)) return false;
9958
+ if (String(key).toLowerCase().includes(needle)) return true;
9959
+ switch (type) {
9960
+ case "string":
9961
+ case "number":
9962
+ case "boolean": return String(value).toLowerCase().includes(needle);
9963
+ case "null": return "null".includes(needle);
9964
+ default: return false;
9965
+ }
9811
9966
  }
9812
9967
  /************************************************************
9813
9968
  * Get JSON type string
@@ -9853,12 +10008,21 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id) {
9853
10008
  let is_dict = is_object(kw);
9854
10009
  let is_list = is_array(kw);
9855
10010
  if (!is_dict && !is_list) return null;
10011
+ let priv = gobj.priv;
10012
+ let needle = priv.search || "";
9856
10013
  let dark = yui_is_dark();
9857
10014
  let lines = [];
9858
10015
  let pending_complex = [];
10016
+ let card_matched = false;
9859
10017
  let entries = is_dict ? Object.entries(kw) : kw.map((v, i) => [i, v]);
9860
10018
  for (let [key, value] of entries) {
9861
- let html = build_cell_html(key, value, get_json_type(value), dark);
10019
+ let type = get_json_type(value);
10020
+ let matched = cell_matches(key, value, type, needle);
10021
+ if (matched) {
10022
+ card_matched = true;
10023
+ priv.match_count++;
10024
+ }
10025
+ let html = build_cell_html(key, value, type, dark, matched);
9862
10026
  lines.push(html);
9863
10027
  if (is_object(value) && json_object_size(value) > 0 || is_array(value) && value.length > 0) pending_complex.push({
9864
10028
  key,
@@ -9866,14 +10030,18 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id) {
9866
10030
  });
9867
10031
  }
9868
10032
  let label = get_group_label(path) || (is_dict ? "{}" : "[]");
10033
+ let foldable = pending_complex.length > 0;
10034
+ let folded = foldable && priv.collapsed.has(path);
9869
10035
  let colors = json_card_style(is_dict ? GROUP_COLORS.dict : GROUP_COLORS.list, dark);
10036
+ let border_color = card_matched ? dark ? "#ffb300" : "#ff8f00" : colors.border;
10037
+ let border_width = card_matched ? 2 : 1;
9870
10038
  let content_html = lines.map((line) => `<div style="font-family:monospace; font-size:13px; padding:1px 6px; white-space:nowrap;">${line}</div>`).join("");
9871
10039
  let min_width = Math.max(180, label.length * 9);
9872
10040
  let node_html = `
9873
10041
  <div style="
9874
10042
  min-width: ${min_width}px;
9875
10043
  background: ${colors.bg};
9876
- border: 1px ${is_dict ? "dashed" : "solid"} ${colors.border};
10044
+ border: ${border_width}px ${is_dict ? "dashed" : "solid"} ${border_color};
9877
10045
  border-radius: ${is_dict ? "6px" : "0"};
9878
10046
  opacity: 0.9;
9879
10047
  overflow: hidden;
@@ -9884,8 +10052,10 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id) {
9884
10052
  font-weight: bold;
9885
10053
  font-size: 12px;
9886
10054
  padding: 3px 8px;
9887
- text-align: center;
9888
- ">${escapeHtml(label)}</div>
10055
+ display: flex;
10056
+ align-items: center;
10057
+ gap: 6px;
10058
+ ">${fold_toggle_html(path, foldable, folded, pending_complex.length)}<span style="flex:1 1 auto; text-align:center;">${escapeHtml(label)}</span></div>
9889
10059
  ${content_html}
9890
10060
  </div>`;
9891
10061
  let node = {
@@ -9911,6 +10081,7 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id) {
9911
10081
  lineWidth: 1
9912
10082
  }
9913
10083
  });
10084
+ if (folded) return group_id;
9914
10085
  for (let pending of pending_complex) build_json_nodes(gobj, add_segment(path, pending.key), pending.value, nodes, edges, group_id);
9915
10086
  return group_id;
9916
10087
  }
@@ -9927,6 +10098,7 @@ function load_json(gobj) {
9927
10098
  let path = gobj_read_str_attr(gobj, "path") || "`";
9928
10099
  if (empty_string(path)) path = "`";
9929
10100
  priv.node_counter = 0;
10101
+ priv.match_count = 0;
9930
10102
  let nodes = [];
9931
10103
  let edges = [];
9932
10104
  build_json_nodes(gobj, path, json, nodes, edges, null);
@@ -9943,6 +10115,42 @@ function load_json(gobj) {
9943
10115
  }
9944
10116
  }
9945
10117
  /************************************************************
10118
+ * Every path that HAS a branch to fold, in the same recursion
10119
+ * build_json_nodes uses — so "collapse all" can never name a
10120
+ * card that does not exist. The root is excluded: folding it
10121
+ * would leave an empty canvas.
10122
+ ************************************************************/
10123
+ function collect_foldable_paths(value, path, out, is_root) {
10124
+ let is_dict = is_object(value);
10125
+ let is_list = is_array(value);
10126
+ if (!is_dict && !is_list) return false;
10127
+ let has_branch = false;
10128
+ let entries = is_dict ? Object.entries(value) : value.map((v, i) => [i, v]);
10129
+ for (let [key, child] of entries) if (is_object(child) && json_object_size(child) > 0 || is_array(child) && child.length > 0) {
10130
+ has_branch = true;
10131
+ collect_foldable_paths(child, add_segment(path, key), out, false);
10132
+ }
10133
+ if (has_branch && !is_root) out.push(path);
10134
+ return has_branch;
10135
+ }
10136
+ /************************************************************
10137
+ * Show the find count, or hide the chip when there is no
10138
+ * term. Zero is a RESULT and must show: a graph that did not
10139
+ * move looks the same whether nothing matched or the match
10140
+ * was already on screen.
10141
+ ************************************************************/
10142
+ function update_find_result(gobj) {
10143
+ let priv = gobj.priv;
10144
+ if (!priv.$find_result || !priv.$find_count) return;
10145
+ if (empty_string(priv.search)) {
10146
+ priv.$find_result.classList.add("is-hidden");
10147
+ priv.$find_count.textContent = "";
10148
+ return;
10149
+ }
10150
+ priv.$find_count.textContent = String(priv.match_count);
10151
+ priv.$find_result.classList.remove("is-hidden");
10152
+ }
10153
+ /************************************************************
9946
10154
  * Clear and reload.
9947
10155
  * {preserve_view: true}
9948
10156
  * keep the current zoom and translate (no fitView) —
@@ -10064,6 +10272,70 @@ function ac_refresh$5(gobj, event, kw, src) {
10064
10272
  }
10065
10273
  /************************************************************
10066
10274
  * {theme: "dark"|"light"} — the app switched theme.
10275
+ * EV_TOGGLE_FOLD { path } — fold or unfold ONE card.
10276
+ *
10277
+ * The camera does not move: folding one branch is a local
10278
+ * edit of the picture, and refitting the whole graph for it
10279
+ * would throw away where the reader was looking. The toolbar
10280
+ * pair, which changes everything at once, does refit.
10281
+ ************************************************************/
10282
+ function ac_toggle_fold(gobj, event, kw, src) {
10283
+ let priv = gobj.priv;
10284
+ let path = kw && kw.path || "";
10285
+ if (empty_string(path)) {
10286
+ log_error(`${gobj_short_name(gobj)}: EV_TOGGLE_FOLD with no path`);
10287
+ return -1;
10288
+ }
10289
+ if (priv.collapsed.has(path)) priv.collapsed.delete(path);
10290
+ else priv.collapsed.add(path);
10291
+ refresh_json(gobj, { preserve_view: true });
10292
+ update_find_result(gobj);
10293
+ return 0;
10294
+ }
10295
+ /************************************************************
10296
+ * EV_FIND_NODES { text }
10297
+ *
10298
+ * The camera does NOT move: a find is a way of reading what is
10299
+ * already on screen, and a viewport that jumps on every
10300
+ * keystroke is unusable. The count says whether there is
10301
+ * anything to look for elsewhere.
10302
+ ************************************************************/
10303
+ function ac_find_nodes$2(gobj, event, kw, src) {
10304
+ let priv = gobj.priv;
10305
+ priv.search = (kw && kw.text || "").trim().toLowerCase();
10306
+ refresh_json(gobj, { preserve_view: true });
10307
+ update_find_result(gobj);
10308
+ return 0;
10309
+ }
10310
+ /************************************************************
10311
+ * EV_EXPAND_ALL
10312
+ ************************************************************/
10313
+ function ac_expand_all$2(gobj, event, kw, src) {
10314
+ let priv = gobj.priv;
10315
+ if (priv.collapsed.size === 0) return 0;
10316
+ priv.collapsed.clear();
10317
+ refresh_json(gobj);
10318
+ update_find_result(gobj);
10319
+ return 0;
10320
+ }
10321
+ /************************************************************
10322
+ * EV_COLLAPSE_ALL — fold every card but the root.
10323
+ ************************************************************/
10324
+ function ac_collapse_all$2(gobj, event, kw, src) {
10325
+ let priv = gobj.priv;
10326
+ let json_data = gobj_read_attr(gobj, "json_data");
10327
+ if (!json_data) return 0;
10328
+ let paths = [];
10329
+ let path = gobj_read_str_attr(gobj, "path") || "`";
10330
+ if (empty_string(path)) path = "`";
10331
+ collect_foldable_paths(json_data, path, paths, true);
10332
+ priv.collapsed = new Set(paths);
10333
+ refresh_json(gobj);
10334
+ update_find_result(gobj);
10335
+ return 0;
10336
+ }
10337
+ /************************************************************
10338
+ *
10067
10339
  ************************************************************/
10068
10340
  function ac_theme$3(gobj, event, kw, src) {
10069
10341
  let priv = gobj.priv;
@@ -10204,6 +10476,26 @@ function create_gclass$11(gclass_name) {
10204
10476
  ac_refresh$5,
10205
10477
  null
10206
10478
  ],
10479
+ [
10480
+ "EV_FIND_NODES",
10481
+ ac_find_nodes$2,
10482
+ null
10483
+ ],
10484
+ [
10485
+ "EV_TOGGLE_FOLD",
10486
+ ac_toggle_fold,
10487
+ null
10488
+ ],
10489
+ [
10490
+ "EV_EXPAND_ALL",
10491
+ ac_expand_all$2,
10492
+ null
10493
+ ],
10494
+ [
10495
+ "EV_COLLAPSE_ALL",
10496
+ ac_collapse_all$2,
10497
+ null
10498
+ ],
10207
10499
  [
10208
10500
  "EV_THEME",
10209
10501
  ac_theme$3,
@@ -10253,6 +10545,10 @@ function create_gclass$11(gclass_name) {
10253
10545
  const event_types = [
10254
10546
  ["EV_LOAD_DATA", 0],
10255
10547
  ["EV_REFRESH", 0],
10548
+ ["EV_FIND_NODES", 0],
10549
+ ["EV_TOGGLE_FOLD", 0],
10550
+ ["EV_EXPAND_ALL", 0],
10551
+ ["EV_COLLAPSE_ALL", 0],
10256
10552
  ["EV_THEME", 0],
10257
10553
  ["EV_ZOOM_IN", 0],
10258
10554
  ["EV_ZOOM_OUT", 0],
@@ -11454,11 +11750,20 @@ function ac_set_view_mode(gobj, event, kw, src) {
11454
11750
  /************************************************************
11455
11751
  * EV_JSON_ITEM_CLICKED — from the hosted graph child.
11456
11752
  *
11457
- * Republished under this gclass's own name so the host has ONE
11458
- * contract and never has to know the child exists.
11753
+ * It STOPS here, and that is deliberate. 7.21.0 republished
11754
+ * it "so the host has one contract", which got the framework
11755
+ * backwards: this viewer is a CHILD of its host and subscribes
11756
+ * it to everything it publishes, so a new output event is a
11757
+ * new MANDATORY declaration in every host's FSM. None of the
11758
+ * six that mount this viewer asked for node clicks, and every
11759
+ * one of them answered a click on a graph card with
11760
+ * "Event NOT DEFINED in state".
11761
+ *
11762
+ * A host that wants node clicks mounts C_YUI_JSON_GRAPH
11763
+ * itself — that gclass publishes them, and a host that mounts
11764
+ * it has declared them.
11459
11765
  ************************************************************/
11460
11766
  function ac_json_item_clicked(gobj, event, kw, src) {
11461
- gobj_publish_event(gobj, "EV_JSON_ITEM_CLICKED", kw);
11462
11767
  return 0;
11463
11768
  }
11464
11769
  /************************************************************
@@ -11631,7 +11936,7 @@ function create_gclass$10(gclass_name) {
11631
11936
  ["EV_COLLAPSE_ALL", 0],
11632
11937
  ["EV_COPY_ALL", 0],
11633
11938
  ["EV_SET_VIEW_MODE", 0],
11634
- ["EV_JSON_ITEM_CLICKED", event_flag_t.EVF_OUTPUT_EVENT | event_flag_t.EVF_NO_WARN_SUBS],
11939
+ ["EV_JSON_ITEM_CLICKED", 0],
11635
11940
  ["EV_LANGUAGE_CHANGED", 0],
11636
11941
  ["EV_REFRESH", 0],
11637
11942
  ["EV_SHOW", 0],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuneta/gobj-ui",
3
- "version": "7.21.1",
3
+ "version": "7.23.0",
4
4
  "type": "module",
5
5
  "main": "dist/gobj-ui.cjs.js",
6
6
  "module": "dist/gobj-ui.es.js",
@@ -47,28 +47,34 @@
47
47
  }
48
48
 
49
49
  /*
50
- * Who YIELDS when the toolbar runs out of room. The search box does:
51
- * it grows to `max-width` when there is space and shrinks to nothing
52
- * when there is not, while the buttons keep their size. A narrow
53
- * search box still accepts what you type; a button pushed past the
54
- * edge can only be reached by scrolling the toolbar, and the view
55
- * switch is the last control that should be hiding.
50
+ * Who YIELDS when the toolbar runs out of room — and how far.
56
51
  *
57
- * Measured at 390px: without this the search took 294 of 320 visible
58
- * pixels and every button sat outside.
52
+ * The search box yields, and the buttons keep their size: a button
53
+ * pushed past the edge is harder to reach than a narrower input. But
54
+ * it yields down to a FLOOR, not to nothing. Letting it shrink freely
55
+ * did make everything fit on a phone, and the result was worse than
56
+ * the overflow it cured: the box collapsed to 58px — the magnifier and
57
+ * no room to read what you typed — and, because nothing overflowed any
58
+ * more, `yui_toolbar` stopped offering its scroll arrows, so the row
59
+ * had no way to show you anything else either.
60
+ *
61
+ * With the floor the toolbar overflows again on a narrow screen, which
62
+ * is the state yui_toolbar is built for: the container is
63
+ * `overflow-x: auto` and the arrows appear.
59
64
  */
60
- .C_YUI_JSON .yui-horizontal-toolbar-section.left {
61
- flex: 1 1 auto;
62
- min-width: 0;
65
+ /* Neither section shrinks below its content. With `min-width: 0` here
66
+ * the left section shrank to 70px while the search box inside it kept
67
+ * its floor — so the input was painted UNDERNEATH the buttons, and the
68
+ * container, whose own children all fitted, reported no overflow to
69
+ * scroll. Sized to content, the container overflows honestly. */
70
+ .C_YUI_JSON .yui-horizontal-toolbar-section.left,
71
+ .C_YUI_JSON .yui-horizontal-toolbar-section.right {
72
+ flex: 0 0 auto;
63
73
  }
64
74
 
65
75
  .C_YUI_JSON .JSON_SEARCH_CONTROL {
66
76
  flex: 1 1 auto;
67
- min-width: 0;
68
- }
69
-
70
- .C_YUI_JSON .yui-horizontal-toolbar-section.right {
71
- flex: 0 0 auto;
77
+ min-width: 11rem;
72
78
  }
73
79
 
74
80
  .C_YUI_JSON .JSON_TREE {
package/src/c_yui_json.js CHANGED
@@ -1175,12 +1175,21 @@ function ac_set_view_mode(gobj, event, kw, src)
1175
1175
  /************************************************************
1176
1176
  * EV_JSON_ITEM_CLICKED — from the hosted graph child.
1177
1177
  *
1178
- * Republished under this gclass's own name so the host has ONE
1179
- * contract and never has to know the child exists.
1178
+ * It STOPS here, and that is deliberate. 7.21.0 republished
1179
+ * it "so the host has one contract", which got the framework
1180
+ * backwards: this viewer is a CHILD of its host and subscribes
1181
+ * it to everything it publishes, so a new output event is a
1182
+ * new MANDATORY declaration in every host's FSM. None of the
1183
+ * six that mount this viewer asked for node clicks, and every
1184
+ * one of them answered a click on a graph card with
1185
+ * "Event NOT DEFINED in state".
1186
+ *
1187
+ * A host that wants node clicks mounts C_YUI_JSON_GRAPH
1188
+ * itself — that gclass publishes them, and a host that mounts
1189
+ * it has declared them.
1180
1190
  ************************************************************/
1181
1191
  function ac_json_item_clicked(gobj, event, kw, src)
1182
1192
  {
1183
- gobj_publish_event(gobj, "EV_JSON_ITEM_CLICKED", kw);
1184
1193
  return 0;
1185
1194
  }
1186
1195
 
@@ -1307,7 +1316,7 @@ function create_gclass(gclass_name)
1307
1316
  ["EV_COLLAPSE_ALL", 0],
1308
1317
  ["EV_COPY_ALL", 0],
1309
1318
  ["EV_SET_VIEW_MODE", 0],
1310
- ["EV_JSON_ITEM_CLICKED", event_flag_t.EVF_OUTPUT_EVENT|event_flag_t.EVF_NO_WARN_SUBS],
1319
+ ["EV_JSON_ITEM_CLICKED", 0],
1311
1320
  ["EV_LANGUAGE_CHANGED", 0],
1312
1321
  ["EV_REFRESH", 0],
1313
1322
  ["EV_SHOW", 0],