@yuneta/gobj-ui 7.23.6 → 7.23.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -459,10 +459,11 @@ written in every editor that offers it and never drawn. Fold is the chevron
459
459
  pair, from the lazy tree viewer's own toolbar. The readout hangs off G6's
460
460
  `aftertransform`, the one hook that also covers the wheel.
461
461
 
462
- Both graph toolbars are arranged the same way (`7.23.6`): camera and refresh in
463
- the centre, layout picker and the fold pair on the right. The middle is the
464
- camera — a fold changes the DOCUMENT, not the view of it, and among the camera
465
- buttons it read as two more of them.
462
+ Both graph toolbars are arranged the same way (`7.23.7`): the **global**
463
+ expand/collapse leftmost, ahead of the find box; camera and refresh in the
464
+ centre; the layout picker on the right. The **per-node** fold is a different
465
+ control and lives elsewhere — on the right of each card's own header, last,
466
+ where the gobj tree puts its `+N` / `−`.
466
467
 
467
468
  The graph carries **its own** toolbar, a **layout picker**
468
469
  (`EV_CHANGE_LAYOUT {layout}`: `vertical tree`, `dagre top-down`,
@@ -9912,24 +9912,17 @@ function destroy_ui$6(gobj) {
9912
9912
  function make_toolbar$3(gobj) {
9913
9913
  let priv = gobj.priv;
9914
9914
  let toolbar_wide = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "wide");
9915
- let left_items = [[
9916
- "div",
9915
+ let $find_input = (0, _yuneta_gobj_js.createElement2)([
9916
+ "input",
9917
9917
  {
9918
- class: "JSON_GRAPH_FIND control has-icons-left",
9919
- style: "margin-right:.5rem; max-width:12rem; min-width:7rem;"
9920
- },
9921
- [["input", {
9922
9918
  class: "JSON_GRAPH_FIND_INPUT input",
9923
9919
  type: "text",
9924
9920
  placeholder: (0, i18next.t)("search"),
9925
9921
  "data-i18n-placeholder": "search",
9926
9922
  "aria-label": (0, i18next.t)("search"),
9927
9923
  "data-i18n-aria-label": "search"
9928
- }], [
9929
- "span",
9930
- { class: "icon is-left" },
9931
- [["i", { class: "yi-magnifying-glass" }]]
9932
- ]],
9924
+ },
9925
+ [],
9933
9926
  { input: (evt) => {
9934
9927
  evt.stopPropagation();
9935
9928
  let text = evt.target.value.trim();
@@ -9939,7 +9932,21 @@ function make_toolbar$3(gobj) {
9939
9932
  (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_FIND_NODES", { text }, gobj);
9940
9933
  }, 250);
9941
9934
  } }
9942
- ], [
9935
+ ]);
9936
+ let $find_control = (0, _yuneta_gobj_js.createElement2)([
9937
+ "div",
9938
+ {
9939
+ class: "JSON_GRAPH_FIND control has-icons-left",
9940
+ style: "margin-right:.5rem; max-width:12rem; min-width:7rem;"
9941
+ },
9942
+ [$find_input, [
9943
+ "span",
9944
+ { class: "icon is-left" },
9945
+ [["i", { class: "yi-magnifying-glass" }]]
9946
+ ]]
9947
+ ]);
9948
+ attach_clear($find_control, $find_input);
9949
+ let left_items = yui_graph_fold_items(gobj, toolbar_wide).concat([$find_control, [
9943
9950
  "div",
9944
9951
  {
9945
9952
  class: "JSON_GRAPH_FIND_RESULT is-hidden",
@@ -9954,7 +9961,7 @@ function make_toolbar$3(gobj) {
9954
9961
  { i18n: "matches" },
9955
9962
  "matches"
9956
9963
  ]]
9957
- ]];
9964
+ ]]);
9958
9965
  let center_items = [];
9959
9966
  center_items = yui_graph_camera_items(gobj, priv.graph, toolbar_wide);
9960
9967
  center_items.push(yui_graph_refresh_item(gobj, toolbar_wide));
@@ -9989,7 +9996,7 @@ function make_toolbar$3(gobj) {
9989
9996
  evt.stopPropagation();
9990
9997
  (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_CHANGE_LAYOUT", { layout: evt.target.value }, gobj);
9991
9998
  } }
9992
- ])].concat(yui_graph_fold_items(gobj, toolbar_wide));
9999
+ ])];
9993
10000
  const $toolbar = yui_toolbar({}, [
9994
10001
  [
9995
10002
  "div",
@@ -10098,6 +10105,11 @@ function build_cell_html(key, value, type, dark, matched) {
10098
10105
  * innerHTML string, so there is no other way to hang a
10099
10106
  * handler on it.
10100
10107
  *
10108
+ * On the RIGHT of the header, and last, where the gobj tree
10109
+ * puts its own — with a spacer of the same width on the left
10110
+ * so the label stays centred on its own axis instead of
10111
+ * drifting by the width of a chip that only some cards have.
10112
+ *
10101
10113
  * A filled CHIP, the same one the gobj tree draws
10102
10114
  * (`c_yui_gobj_tree_js.js`, render_toggle_html): background,
10103
10115
  * border, radius, and `+N` / `−` rather than a triangle. It
@@ -10111,8 +10123,9 @@ function build_cell_html(key, value, type, dark, matched) {
10111
10123
  * where it could carry no i18n key and would sit in English
10112
10124
  * forever. `+3` and `−` need no language.
10113
10125
  ************************************************************/
10126
+ var FOLD_SPACER = `<span style="width:24px; flex:0 0 auto;"></span>`;
10114
10127
  function fold_toggle_html(path, foldable, folded, branches, colors) {
10115
- if (!foldable) return `<span style="width:24px; flex:0 0 auto;"></span>`;
10128
+ if (!foldable) return FOLD_SPACER;
10116
10129
  let label = folded ? "+" + branches : "&#8722;";
10117
10130
  return `<span data-fold-path="${(0, _yuneta_gobj_js.escapeHtml)(path)}" style="
10118
10131
  flex: 0 0 auto;
@@ -10243,7 +10256,7 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id) {
10243
10256
  display: flex;
10244
10257
  align-items: center;
10245
10258
  gap: 6px;
10246
- ">${fold_toggle_html(path, foldable, folded, pending_complex.length, colors)}<span style="flex:1 1 auto; text-align:center;">${(0, _yuneta_gobj_js.escapeHtml)(label)}</span></div>
10259
+ ">${FOLD_SPACER}<span style="flex:1 1 auto; text-align:center;">${(0, _yuneta_gobj_js.escapeHtml)(label)}</span>${fold_toggle_html(path, foldable, folded, pending_complex.length, colors)}</div>
10247
10260
  ${content_html}
10248
10261
  </div>`;
10249
10262
  let node = {
@@ -11234,14 +11247,10 @@ function make_toolbar$2(gobj) {
11234
11247
  [["i", { class: "yi-magnifying-glass" }]]
11235
11248
  ]]
11236
11249
  ]);
11250
+ left_items.push(icon_button(gobj, "yi-chevron-right", "EV_EXPAND_ALL", "expand loaded"), icon_button(gobj, "yi-chevron-right", "EV_COLLAPSE_ALL", "collapse all"));
11237
11251
  attach_clear($search_control, $search_input);
11238
11252
  left_items.push($search_control);
11239
- let right_items = [
11240
- view_mode_switch(gobj),
11241
- icon_button(gobj, "yi-chevron-right", "EV_EXPAND_ALL", "expand loaded"),
11242
- icon_button(gobj, "yi-chevron-right", "EV_COLLAPSE_ALL", "collapse all"),
11243
- icon_button(gobj, "yi-copy", "EV_COPY_ALL", "copy json")
11244
- ];
11253
+ let right_items = [view_mode_switch(gobj), icon_button(gobj, "yi-copy", "EV_COPY_ALL", "copy json")];
11245
11254
  const $toolbar = yui_toolbar({}, [
11246
11255
  [
11247
11256
  "div",
@@ -12606,7 +12615,7 @@ function make_toolbar$1(gobj) {
12606
12615
  let priv = gobj.priv;
12607
12616
  let toolbar_wide = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "wide");
12608
12617
  let current_layout = (0, _yuneta_gobj_js.gobj_read_str_attr)(gobj, "layout");
12609
- let left_items = [];
12618
+ let left_items = yui_graph_fold_items(gobj, toolbar_wide);
12610
12619
  let center_items = [];
12611
12620
  let right_items = [];
12612
12621
  center_items = yui_graph_camera_items(gobj, priv.graph, toolbar_wide);
@@ -12639,7 +12648,6 @@ function make_toolbar$1(gobj) {
12639
12648
  ]);
12640
12649
  priv.$layout_select = $select;
12641
12650
  right_items.push($select);
12642
- right_items.push(...yui_graph_fold_items(gobj, toolbar_wide));
12643
12651
  const $toolbar = yui_toolbar({}, [
12644
12652
  [
12645
12653
  "div",
@@ -52595,24 +52603,17 @@ function make_toolbar(gobj) {
52595
52603
  } }
52596
52604
  ]
52597
52605
  ];
52598
- let center_items = [[
52599
- "div",
52606
+ let $find_input = (0, _yuneta_gobj_js.createElement2)([
52607
+ "input",
52600
52608
  {
52601
- class: "GRAPH_FIND control has-icons-left",
52602
- style: "margin-right:.5rem; max-width:12rem; min-width:7rem;"
52603
- },
52604
- [["input", {
52605
52609
  class: "GRAPH_FIND_INPUT input",
52606
52610
  type: "text",
52607
52611
  placeholder: (0, i18next.t)("search"),
52608
52612
  "data-i18n-placeholder": "search",
52609
52613
  "aria-label": (0, i18next.t)("search"),
52610
52614
  "data-i18n-aria-label": "search"
52611
- }], [
52612
- "span",
52613
- { class: "icon is-left" },
52614
- [["i", { class: "yi-magnifying-glass" }]]
52615
- ]],
52615
+ },
52616
+ [],
52616
52617
  { input: (evt) => {
52617
52618
  evt.stopPropagation();
52618
52619
  let text = evt.target.value.trim();
@@ -52622,22 +52623,20 @@ function make_toolbar(gobj) {
52622
52623
  (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_FIND_NODES", { text }, gobj);
52623
52624
  }, 250);
52624
52625
  } }
52625
- ], [
52626
+ ]);
52627
+ let $find_control = (0, _yuneta_gobj_js.createElement2)([
52626
52628
  "div",
52627
52629
  {
52628
- class: "GRAPH_FIND_RESULT is-hidden",
52629
- style: "display:flex; align-items:center; gap:.3rem; margin-right:.5rem; font-size:.85rem;"
52630
+ class: "GRAPH_FIND control has-icons-left",
52631
+ style: "margin-right:.5rem; max-width:12rem; min-width:7rem;"
52630
52632
  },
52631
- [[
52633
+ [$find_input, [
52632
52634
  "span",
52633
- { class: "GRAPH_FIND_COUNT" },
52634
- ""
52635
- ], [
52636
- "span",
52637
- { i18n: "matches" },
52638
- "matches"
52635
+ { class: "icon is-left" },
52636
+ [["i", { class: "yi-magnifying-glass" }]]
52639
52637
  ]]
52640
- ]];
52638
+ ]);
52639
+ attach_clear($find_control, $find_input);
52641
52640
  const $toolbar_header = yui_toolbar({}, [
52642
52641
  [
52643
52642
  "div",
@@ -52647,7 +52646,22 @@ function make_toolbar(gobj) {
52647
52646
  [
52648
52647
  "div",
52649
52648
  { class: "yui-horizontal-toolbar-section center" },
52650
- center_items
52649
+ [$find_control, [
52650
+ "div",
52651
+ {
52652
+ class: "GRAPH_FIND_RESULT is-hidden",
52653
+ style: "display:flex; align-items:center; gap:.3rem; margin-right:.5rem; font-size:.85rem;"
52654
+ },
52655
+ [[
52656
+ "span",
52657
+ { class: "GRAPH_FIND_COUNT" },
52658
+ ""
52659
+ ], [
52660
+ "span",
52661
+ { i18n: "matches" },
52662
+ "matches"
52663
+ ]]
52664
+ ]]
52651
52665
  ],
52652
52666
  [
52653
52667
  "div",
@@ -9907,24 +9907,17 @@ function destroy_ui$6(gobj) {
9907
9907
  function make_toolbar$3(gobj) {
9908
9908
  let priv = gobj.priv;
9909
9909
  let toolbar_wide = gobj_read_attr(gobj, "wide");
9910
- let left_items = [[
9911
- "div",
9910
+ let $find_input = createElement2([
9911
+ "input",
9912
9912
  {
9913
- class: "JSON_GRAPH_FIND control has-icons-left",
9914
- style: "margin-right:.5rem; max-width:12rem; min-width:7rem;"
9915
- },
9916
- [["input", {
9917
9913
  class: "JSON_GRAPH_FIND_INPUT input",
9918
9914
  type: "text",
9919
9915
  placeholder: t("search"),
9920
9916
  "data-i18n-placeholder": "search",
9921
9917
  "aria-label": t("search"),
9922
9918
  "data-i18n-aria-label": "search"
9923
- }], [
9924
- "span",
9925
- { class: "icon is-left" },
9926
- [["i", { class: "yi-magnifying-glass" }]]
9927
- ]],
9919
+ },
9920
+ [],
9928
9921
  { input: (evt) => {
9929
9922
  evt.stopPropagation();
9930
9923
  let text = evt.target.value.trim();
@@ -9934,7 +9927,21 @@ function make_toolbar$3(gobj) {
9934
9927
  gobj_send_event(gobj, "EV_FIND_NODES", { text }, gobj);
9935
9928
  }, 250);
9936
9929
  } }
9937
- ], [
9930
+ ]);
9931
+ let $find_control = createElement2([
9932
+ "div",
9933
+ {
9934
+ class: "JSON_GRAPH_FIND control has-icons-left",
9935
+ style: "margin-right:.5rem; max-width:12rem; min-width:7rem;"
9936
+ },
9937
+ [$find_input, [
9938
+ "span",
9939
+ { class: "icon is-left" },
9940
+ [["i", { class: "yi-magnifying-glass" }]]
9941
+ ]]
9942
+ ]);
9943
+ attach_clear($find_control, $find_input);
9944
+ let left_items = yui_graph_fold_items(gobj, toolbar_wide).concat([$find_control, [
9938
9945
  "div",
9939
9946
  {
9940
9947
  class: "JSON_GRAPH_FIND_RESULT is-hidden",
@@ -9949,7 +9956,7 @@ function make_toolbar$3(gobj) {
9949
9956
  { i18n: "matches" },
9950
9957
  "matches"
9951
9958
  ]]
9952
- ]];
9959
+ ]]);
9953
9960
  let center_items = [];
9954
9961
  center_items = yui_graph_camera_items(gobj, priv.graph, toolbar_wide);
9955
9962
  center_items.push(yui_graph_refresh_item(gobj, toolbar_wide));
@@ -9984,7 +9991,7 @@ function make_toolbar$3(gobj) {
9984
9991
  evt.stopPropagation();
9985
9992
  gobj_send_event(gobj, "EV_CHANGE_LAYOUT", { layout: evt.target.value }, gobj);
9986
9993
  } }
9987
- ])].concat(yui_graph_fold_items(gobj, toolbar_wide));
9994
+ ])];
9988
9995
  const $toolbar = yui_toolbar({}, [
9989
9996
  [
9990
9997
  "div",
@@ -10093,6 +10100,11 @@ function build_cell_html(key, value, type, dark, matched) {
10093
10100
  * innerHTML string, so there is no other way to hang a
10094
10101
  * handler on it.
10095
10102
  *
10103
+ * On the RIGHT of the header, and last, where the gobj tree
10104
+ * puts its own — with a spacer of the same width on the left
10105
+ * so the label stays centred on its own axis instead of
10106
+ * drifting by the width of a chip that only some cards have.
10107
+ *
10096
10108
  * A filled CHIP, the same one the gobj tree draws
10097
10109
  * (`c_yui_gobj_tree_js.js`, render_toggle_html): background,
10098
10110
  * border, radius, and `+N` / `−` rather than a triangle. It
@@ -10106,8 +10118,9 @@ function build_cell_html(key, value, type, dark, matched) {
10106
10118
  * where it could carry no i18n key and would sit in English
10107
10119
  * forever. `+3` and `−` need no language.
10108
10120
  ************************************************************/
10121
+ var FOLD_SPACER = `<span style="width:24px; flex:0 0 auto;"></span>`;
10109
10122
  function fold_toggle_html(path, foldable, folded, branches, colors) {
10110
- if (!foldable) return `<span style="width:24px; flex:0 0 auto;"></span>`;
10123
+ if (!foldable) return FOLD_SPACER;
10111
10124
  let label = folded ? "+" + branches : "&#8722;";
10112
10125
  return `<span data-fold-path="${escapeHtml(path)}" style="
10113
10126
  flex: 0 0 auto;
@@ -10238,7 +10251,7 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id) {
10238
10251
  display: flex;
10239
10252
  align-items: center;
10240
10253
  gap: 6px;
10241
- ">${fold_toggle_html(path, foldable, folded, pending_complex.length, colors)}<span style="flex:1 1 auto; text-align:center;">${escapeHtml(label)}</span></div>
10254
+ ">${FOLD_SPACER}<span style="flex:1 1 auto; text-align:center;">${escapeHtml(label)}</span>${fold_toggle_html(path, foldable, folded, pending_complex.length, colors)}</div>
10242
10255
  ${content_html}
10243
10256
  </div>`;
10244
10257
  let node = {
@@ -11229,14 +11242,10 @@ function make_toolbar$2(gobj) {
11229
11242
  [["i", { class: "yi-magnifying-glass" }]]
11230
11243
  ]]
11231
11244
  ]);
11245
+ left_items.push(icon_button(gobj, "yi-chevron-right", "EV_EXPAND_ALL", "expand loaded"), icon_button(gobj, "yi-chevron-right", "EV_COLLAPSE_ALL", "collapse all"));
11232
11246
  attach_clear($search_control, $search_input);
11233
11247
  left_items.push($search_control);
11234
- let right_items = [
11235
- view_mode_switch(gobj),
11236
- icon_button(gobj, "yi-chevron-right", "EV_EXPAND_ALL", "expand loaded"),
11237
- icon_button(gobj, "yi-chevron-right", "EV_COLLAPSE_ALL", "collapse all"),
11238
- icon_button(gobj, "yi-copy", "EV_COPY_ALL", "copy json")
11239
- ];
11248
+ let right_items = [view_mode_switch(gobj), icon_button(gobj, "yi-copy", "EV_COPY_ALL", "copy json")];
11240
11249
  const $toolbar = yui_toolbar({}, [
11241
11250
  [
11242
11251
  "div",
@@ -12601,7 +12610,7 @@ function make_toolbar$1(gobj) {
12601
12610
  let priv = gobj.priv;
12602
12611
  let toolbar_wide = gobj_read_attr(gobj, "wide");
12603
12612
  let current_layout = gobj_read_str_attr(gobj, "layout");
12604
- let left_items = [];
12613
+ let left_items = yui_graph_fold_items(gobj, toolbar_wide);
12605
12614
  let center_items = [];
12606
12615
  let right_items = [];
12607
12616
  center_items = yui_graph_camera_items(gobj, priv.graph, toolbar_wide);
@@ -12634,7 +12643,6 @@ function make_toolbar$1(gobj) {
12634
12643
  ]);
12635
12644
  priv.$layout_select = $select;
12636
12645
  right_items.push($select);
12637
- right_items.push(...yui_graph_fold_items(gobj, toolbar_wide));
12638
12646
  const $toolbar = yui_toolbar({}, [
12639
12647
  [
12640
12648
  "div",
@@ -52582,24 +52590,17 @@ function make_toolbar(gobj) {
52582
52590
  } }
52583
52591
  ]
52584
52592
  ];
52585
- let center_items = [[
52586
- "div",
52593
+ let $find_input = createElement2([
52594
+ "input",
52587
52595
  {
52588
- class: "GRAPH_FIND control has-icons-left",
52589
- style: "margin-right:.5rem; max-width:12rem; min-width:7rem;"
52590
- },
52591
- [["input", {
52592
52596
  class: "GRAPH_FIND_INPUT input",
52593
52597
  type: "text",
52594
52598
  placeholder: t("search"),
52595
52599
  "data-i18n-placeholder": "search",
52596
52600
  "aria-label": t("search"),
52597
52601
  "data-i18n-aria-label": "search"
52598
- }], [
52599
- "span",
52600
- { class: "icon is-left" },
52601
- [["i", { class: "yi-magnifying-glass" }]]
52602
- ]],
52602
+ },
52603
+ [],
52603
52604
  { input: (evt) => {
52604
52605
  evt.stopPropagation();
52605
52606
  let text = evt.target.value.trim();
@@ -52609,22 +52610,20 @@ function make_toolbar(gobj) {
52609
52610
  gobj_send_event(gobj, "EV_FIND_NODES", { text }, gobj);
52610
52611
  }, 250);
52611
52612
  } }
52612
- ], [
52613
+ ]);
52614
+ let $find_control = createElement2([
52613
52615
  "div",
52614
52616
  {
52615
- class: "GRAPH_FIND_RESULT is-hidden",
52616
- style: "display:flex; align-items:center; gap:.3rem; margin-right:.5rem; font-size:.85rem;"
52617
+ class: "GRAPH_FIND control has-icons-left",
52618
+ style: "margin-right:.5rem; max-width:12rem; min-width:7rem;"
52617
52619
  },
52618
- [[
52620
+ [$find_input, [
52619
52621
  "span",
52620
- { class: "GRAPH_FIND_COUNT" },
52621
- ""
52622
- ], [
52623
- "span",
52624
- { i18n: "matches" },
52625
- "matches"
52622
+ { class: "icon is-left" },
52623
+ [["i", { class: "yi-magnifying-glass" }]]
52626
52624
  ]]
52627
- ]];
52625
+ ]);
52626
+ attach_clear($find_control, $find_input);
52628
52627
  const $toolbar_header = yui_toolbar({}, [
52629
52628
  [
52630
52629
  "div",
@@ -52634,7 +52633,22 @@ function make_toolbar(gobj) {
52634
52633
  [
52635
52634
  "div",
52636
52635
  { class: "yui-horizontal-toolbar-section center" },
52637
- center_items
52636
+ [$find_control, [
52637
+ "div",
52638
+ {
52639
+ class: "GRAPH_FIND_RESULT is-hidden",
52640
+ style: "display:flex; align-items:center; gap:.3rem; margin-right:.5rem; font-size:.85rem;"
52641
+ },
52642
+ [[
52643
+ "span",
52644
+ { class: "GRAPH_FIND_COUNT" },
52645
+ ""
52646
+ ], [
52647
+ "span",
52648
+ { i18n: "matches" },
52649
+ "matches"
52650
+ ]]
52651
+ ]]
52638
52652
  ],
52639
52653
  [
52640
52654
  "div",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuneta/gobj-ui",
3
- "version": "7.23.6",
3
+ "version": "7.23.8",
4
4
  "type": "module",
5
5
  "main": "dist/gobj-ui.cjs.js",
6
6
  "module": "dist/gobj-ui.es.js",
@@ -537,7 +537,11 @@ function make_toolbar(gobj)
537
537
  let toolbar_wide = gobj_read_attr(gobj, "wide");
538
538
  let current_layout = gobj_read_str_attr(gobj, "layout");
539
539
 
540
- let left_items = [];
540
+ /* The GLOBAL fold opens the whole tree; it is not a camera control
541
+ * and not a per-node one, so it sits on its own at the left — ahead
542
+ * of a find box where the toolbar has one. The per-node handles
543
+ * live inside the cards, on the right of each header. */
544
+ let left_items = yui_graph_fold_items(gobj, toolbar_wide);
541
545
  let center_items = [];
542
546
  let right_items = [];
543
547
 
@@ -583,12 +587,6 @@ function make_toolbar(gobj)
583
587
  priv.$layout_select = $select;
584
588
  right_items.push($select);
585
589
 
586
- /* Fold on the RIGHT, past the layout picker — where the JSON graph
587
- * already put it. The camera is what the middle is for: the fold
588
- * pair changes the DOCUMENT, not the view of it, and sitting in the
589
- * middle it read as two more camera buttons. */
590
- right_items.push(...yui_graph_fold_items(gobj, toolbar_wide));
591
-
592
590
  const $toolbar = yui_toolbar({}, [
593
591
  ['div', {class: 'yui-horizontal-toolbar-section left'}, left_items],
594
592
  ['div', {class: 'yui-horizontal-toolbar-section center'}, center_items],
package/src/c_yui_json.js CHANGED
@@ -365,14 +365,20 @@ function make_toolbar(gobj)
365
365
  $search_input,
366
366
  ['span', {class: 'icon is-left'}, [['i', {class: 'yi-magnifying-glass'}]]]
367
367
  ]]);
368
+ /* The GLOBAL fold leads the row, ahead of the find box — the same
369
+ * place both graphs put theirs. It opens the whole document; the
370
+ * per-row toggles live in the rows. */
371
+ left_items.push(
372
+ icon_button(gobj, "yi-chevron-right", "EV_EXPAND_ALL", "expand loaded"),
373
+ icon_button(gobj, "yi-chevron-right", "EV_COLLAPSE_ALL", "collapse all")
374
+ );
375
+
368
376
  attach_clear($search_control, $search_input);
369
377
  left_items.push($search_control);
370
378
 
371
379
  let right_items = [
372
380
  view_mode_switch(gobj),
373
- icon_button(gobj, "yi-chevron-right", "EV_EXPAND_ALL", "expand loaded"),
374
- icon_button(gobj, "yi-chevron-right", "EV_COLLAPSE_ALL", "collapse all"),
375
- icon_button(gobj, "yi-copy", "EV_COPY_ALL", "copy json"),
381
+ icon_button(gobj, "yi-copy", "EV_COPY_ALL", "copy json"),
376
382
  ];
377
383
 
378
384
  const $toolbar = yui_toolbar({}, [
@@ -47,6 +47,7 @@ import {
47
47
  } from "@yuneta/gobj-js";
48
48
 
49
49
  import {yui_toolbar} from "./yui_toolbar.js";
50
+ import {attach_clear} from "./yui_inputs.js";
50
51
  import {
51
52
  yui_graph_camera_items,
52
53
  yui_graph_fold_items,
@@ -478,27 +479,25 @@ function make_toolbar(gobj)
478
479
  * looks the same whether nothing matched or the match was already
479
480
  * on screen.
480
481
  */
481
- let left_items = [
482
- ['div', {class: 'JSON_GRAPH_FIND control has-icons-left',
483
- style: 'margin-right:.5rem; max-width:12rem; min-width:7rem;'}, [
484
- ['input', {
485
- class: 'JSON_GRAPH_FIND_INPUT input',
486
- type: 'text',
487
- /* A placeholder is not a text node, so the data-i18n
488
- * walk cannot reach it: it needs its own key. */
489
- placeholder: t('search'),
490
- 'data-i18n-placeholder': 'search',
491
- 'aria-label': t('search'),
492
- 'data-i18n-aria-label': 'search'
493
- }],
494
- ['span', {class: 'icon is-left'}, [['i', {class: 'yi-magnifying-glass'}]]]
495
- ], {
482
+ /* Materialised, not a spec: attach_clear() hangs the NORM clear (✕)
483
+ * on a real element. Clearing dispatches a synthetic `input`, which
484
+ * goes through the same rate-limited handler and fires EV_FIND_NODES
485
+ * with an empty term — the box and the highlight clear together. */
486
+ let $find_input = createElement2(
487
+ ['input', {
488
+ class: 'JSON_GRAPH_FIND_INPUT input',
489
+ type: 'text',
490
+ /* A placeholder is not a text node, so the data-i18n walk
491
+ * cannot reach it: it needs its own key. */
492
+ placeholder: t('search'),
493
+ 'data-i18n-placeholder': 'search',
494
+ 'aria-label': t('search'),
495
+ 'data-i18n-aria-label': 'search'
496
+ }, [], {
496
497
  /* Rate-limited, not delayed for effect: every keystroke
497
498
  * REBUILDS the cards — an html node paints no G6 state, so
498
499
  * the highlight has to live in the card's own markup — and
499
- * the first letter typed can match most of a document.
500
- * Input plumbing: the action still crosses the FSM, just
501
- * not once per keystroke. */
500
+ * the first letter typed can match most of a document. */
502
501
  input: (evt) => {
503
502
  evt.stopPropagation();
504
503
  let text = evt.target.value.trim();
@@ -510,20 +509,39 @@ function make_toolbar(gobj)
510
509
  gobj_send_event(gobj, "EV_FIND_NODES", {text: text}, gobj);
511
510
  }, 250);
512
511
  }
513
- }],
512
+ }]);
513
+
514
+ let $find_control = createElement2(
515
+ ['div', {class: 'JSON_GRAPH_FIND control has-icons-left',
516
+ style: 'margin-right:.5rem; max-width:12rem; min-width:7rem;'}, [
517
+ $find_input,
518
+ ['span', {class: 'icon is-left'}, [['i', {class: 'yi-magnifying-glass'}]]]
519
+ ]]);
520
+ attach_clear($find_control, $find_input);
521
+
522
+ /*
523
+ * Left: the global fold leads the row, then find a node.
524
+ *
525
+ * A graph of a large document has no other way in — the only way to
526
+ * locate a key was to read every card. The count SAYS how many
527
+ * matched, because a graph that did not move looks the same whether
528
+ * nothing matched or the match was already on screen.
529
+ */
530
+ let left_items = yui_graph_fold_items(gobj, toolbar_wide).concat([
531
+ $find_control,
514
532
  /* Two spans, not one string: the number is DATA and "matches"
515
533
  * is the word, so a language switch re-translates the half that
516
- * is a word. Spaced with CSS because createElement2 trims text
517
- * nodes. `display:flex` inline and NOT the `is-flex` helper —
518
- * both Bulma helpers carry !important, so `is-hidden is-flex` on
519
- * one element is decided by stylesheet order. */
534
+ * is a word. `display:flex` inline and NOT the `is-flex`
535
+ * helper — both Bulma helpers carry !important, so
536
+ * `is-hidden is-flex` on one element is decided by stylesheet
537
+ * order. */
520
538
  ['div', {class: 'JSON_GRAPH_FIND_RESULT is-hidden',
521
539
  style: 'display:flex; align-items:center; gap:.3rem; ' +
522
540
  'margin-right:.5rem; font-size:.85rem;'}, [
523
541
  ['span', {class: 'JSON_GRAPH_FIND_COUNT'}, ''],
524
542
  ['span', {i18n: 'matches'}, 'matches']
525
543
  ]]
526
- ];
544
+ ]);
527
545
  let center_items = [];
528
546
 
529
547
  /*
@@ -573,8 +591,7 @@ function make_toolbar(gobj)
573
591
  }]
574
592
  );
575
593
 
576
- let right_items = [$layout_select].concat(
577
- yui_graph_fold_items(gobj, toolbar_wide));
594
+ let right_items = [$layout_select];
578
595
 
579
596
  const $toolbar = yui_toolbar({}, [
580
597
  ['div', {class: 'yui-horizontal-toolbar-section left'}, left_items],
@@ -731,6 +748,11 @@ function build_cell_html(key, value, type, dark, matched)
731
748
  * innerHTML string, so there is no other way to hang a
732
749
  * handler on it.
733
750
  *
751
+ * On the RIGHT of the header, and last, where the gobj tree
752
+ * puts its own — with a spacer of the same width on the left
753
+ * so the label stays centred on its own axis instead of
754
+ * drifting by the width of a chip that only some cards have.
755
+ *
734
756
  * A filled CHIP, the same one the gobj tree draws
735
757
  * (`c_yui_gobj_tree_js.js`, render_toggle_html): background,
736
758
  * border, radius, and `+N` / `−` rather than a triangle. It
@@ -744,12 +766,12 @@ function build_cell_html(key, value, type, dark, matched)
744
766
  * where it could carry no i18n key and would sit in English
745
767
  * forever. `+3` and `−` need no language.
746
768
  ************************************************************/
769
+ const FOLD_SPACER = `<span style="width:24px; flex:0 0 auto;"></span>`;
770
+
747
771
  function fold_toggle_html(path, foldable, folded, branches, colors)
748
772
  {
749
773
  if(!foldable) {
750
- /* A spacer the width of the chip, so the label of a leaf card
751
- * stays on the same axis as the label of a foldable one. */
752
- return `<span style="width:24px; flex:0 0 auto;"></span>`;
774
+ return FOLD_SPACER;
753
775
  }
754
776
 
755
777
  let label = folded? ("+" + branches): "&#8722;"; /* +N / − */
@@ -940,7 +962,7 @@ function build_json_nodes(gobj, path, kw, nodes, edges, parent_id)
940
962
  display: flex;
941
963
  align-items: center;
942
964
  gap: 6px;
943
- ">${fold_toggle_html(path, foldable, folded, pending_complex.length, colors)}<span style="flex:1 1 auto; text-align:center;">${escapeHtml(label)}</span></div>
965
+ ">${FOLD_SPACER}<span style="flex:1 1 auto; text-align:center;">${escapeHtml(label)}</span>${fold_toggle_html(path, foldable, folded, pending_complex.length, colors)}</div>
944
966
  ${content_html}
945
967
  </div>`;
946
968
 
@@ -78,6 +78,7 @@ import {
78
78
  } from "@yuneta/gobj-js";
79
79
 
80
80
  import {yui_toolbar} from "./yui_toolbar.js";
81
+ import {attach_clear} from "./yui_inputs.js";
81
82
  import {register_c_g6_nodes_tree} from "./c_g6_nodes_tree.js";
82
83
  import {
83
84
  removeChildElements,
@@ -548,23 +549,21 @@ function make_toolbar(gobj)
548
549
  * not move looks the same whether nothing matched or the match was
549
550
  * already on screen.
550
551
  */
551
- let center_items = [
552
- ['div', {class: 'GRAPH_FIND control has-icons-left',
553
- style: 'margin-right:.5rem; max-width:12rem; min-width:7rem;'}, [
554
- ['input', {
555
- class: 'GRAPH_FIND_INPUT input',
556
- type: 'text',
557
- /* A placeholder is not a text node, so the data-i18n walk
558
- * cannot reach it: it needs its own key. */
559
- placeholder: t('search'),
560
- 'data-i18n-placeholder': 'search',
561
- 'aria-label': t('search'),
562
- 'data-i18n-aria-label': 'search'
563
- }],
564
- ['span', {class: 'icon is-left'}, [
565
- ['i', {class: 'yi-magnifying-glass'}]
566
- ]]
567
- ], {
552
+ /* Materialised, not a spec: attach_clear() hangs the NORM clear (✕)
553
+ * on a real element. Clearing dispatches a synthetic `input`, which
554
+ * goes through the same rate-limited handler and fires EV_FIND_NODES
555
+ * with an empty term — the box and the highlight clear together. */
556
+ let $find_input = createElement2(
557
+ ['input', {
558
+ class: 'GRAPH_FIND_INPUT input',
559
+ type: 'text',
560
+ /* A placeholder is not a text node, so the data-i18n walk
561
+ * cannot reach it: it needs its own key. */
562
+ placeholder: t('search'),
563
+ 'data-i18n-placeholder': 'search',
564
+ 'aria-label': t('search'),
565
+ 'data-i18n-aria-label': 'search'
566
+ }, [], {
568
567
  /* Rate-limited, not delayed for effect: a match repaints the
569
568
  * cards it lands on, and on a large treedb the first letter
570
569
  * typed can match hundreds. This is input plumbing — the
@@ -581,7 +580,18 @@ function make_toolbar(gobj)
581
580
  gobj_send_event(gobj, "EV_FIND_NODES", {text: text}, gobj);
582
581
  }, 250);
583
582
  }
584
- }],
583
+ }]);
584
+
585
+ let $find_control = createElement2(
586
+ ['div', {class: 'GRAPH_FIND control has-icons-left',
587
+ style: 'margin-right:.5rem; max-width:12rem; min-width:7rem;'}, [
588
+ $find_input,
589
+ ['span', {class: 'icon is-left'}, [['i', {class: 'yi-magnifying-glass'}]]]
590
+ ]]);
591
+ attach_clear($find_control, $find_input);
592
+
593
+ let center_items = [
594
+ $find_control,
585
595
  /* Two spans, not one string: the number is DATA and "matches" is
586
596
  * the word, so a language switch re-translates the half that is a
587
597
  * word. Spaced with CSS because createElement2 trims text nodes. */