@yuneta/gobj-ui 7.23.157 → 7.23.158

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
@@ -1254,23 +1254,38 @@ construction rather than by a check in twenty places.
1254
1254
  ### Finding a node in the graph
1255
1255
 
1256
1256
  `C_YUI_TREEDB_GRAPH` carries a find box in the middle of its toolbar. It
1257
- matches the term against the node's **label**, its id and its topic name, puts
1258
- every match in the same amber `active` state the topic focus uses, and centres
1259
- the viewport on them.
1260
-
1261
- Two details that are not decoration:
1262
-
1257
+ matches the term against the node's **label**, its id and its topic name, and
1258
+ puts every match **on screen** in the same amber `active` state the topic focus
1259
+ uses. It changes nothing else: no group is opened, no layout runs, the camera
1260
+ does not move. Emptying the box takes the amber off and leaves the graph
1261
+ exactly as it was.
1262
+
1263
+ Details that are not decoration:
1264
+
1265
+ - it **only looks** (since `7.23.158`). It used to search the whole treedb and
1266
+ unfold a page of the matches it found, so every keystroke re-laid the graph
1267
+ out, and the groups it opened stayed open when the box was cleared. Opening
1268
+ up to a topic is the legend's focus button, which still searches the whole
1269
+ treedb and unfolds what it needs.
1270
+ - the term **stays live**. It is repainted after every change of what is on
1271
+ screen (a group opened by hand, a fold level, a refresh, a hidden topic), so
1272
+ newly shown matches arrive lit and the count follows the screen.
1273
+ - **Enter** centres the next lit card, **Shift+Enter** the previous one, in
1274
+ reading order (top to bottom, then left to right). That is the one camera
1275
+ move of the find, and the reader asks for it. The count then reads `k/N`.
1263
1276
  - it matches the **label**, not only the id. On a topic keyed by `rowid`,
1264
1277
  `uuid` or `qualified` the id is a counter or a path and the name a human
1265
1278
  knows the record by lives in a secondary key — the same reason `node_label()`
1266
1279
  exists.
1267
- - it **says how many** it found. A graph that did not move looks identical
1268
- whether nothing matched or the only match was already on screen, so the count
1269
- is shown next to the box (hidden while the box is empty; a typed term that
1270
- matches nothing shows `0`, which is an answer).
1280
+ - it **says how many** it found, and how many more it did NOT light:
1281
+ `12 matches (+513 not shown, +40 in hidden topics)`. A graph with no amber
1282
+ looks identical whether nothing matched or the matches are folded away, so
1283
+ the count is shown next to the box (hidden while the box is empty; a typed
1284
+ term that matches nothing shows `0`, which is an answer).
1271
1285
 
1272
1286
  The find and the topic focus **share the highlight**: starting one clears the
1273
- other. Two amber sets at once would say nothing about either.
1287
+ other (a topic focus also empties the box). Two amber sets at once would say
1288
+ nothing about either.
1274
1289
 
1275
1290
  The highlight is painted **into the card's own html**, not with G6's `active`
1276
1291
  element state. That state is an amber `stroke` + `halo`, both properties of a
@@ -1281,9 +1296,12 @@ changes are repainted, and a theme switch carries the highlight across (it
1281
1296
  rebuilds every card, and rebuilding them without it would clear what is on
1282
1297
  screen).
1283
1298
 
1284
- Wiring: the box sends `EV_FIND_NODES {text}` to the view, which forwards it to
1285
- `C_G6_NODES_TREE`; the graph answers `EV_FIND_RESULT {term, matches}`, which the
1286
- view declares like every other event its child publishes.
1299
+ Wiring: the box sends `EV_FIND_NODES {text}` to the view, and Enter sends
1300
+ `EV_FIND_NEXT {back}`; the view forwards both to `C_G6_NODES_TREE`. The graph
1301
+ answers `EV_FIND_RESULT {term, matches, folded_matches, hidden_matches,
1302
+ current}`, which the view declares like every other event its child publishes.
1303
+ Consumer i18n keys: `matches` (counted), `not shown`, `hidden topics`,
1304
+ `find on screen` (the box's title and name).
1287
1305
 
1288
1306
  ### The graph opens FOLDED, like a JSON viewer
1289
1307
 
@@ -56720,8 +56720,9 @@ var PRIVATE_DATA$4 = {
56720
56720
  _selected_paint_ids: [],
56721
56721
  _pending_focus_topic: null,
56722
56722
  _pending_focus_all: false,
56723
- _find_hidden_matches: 0,
56724
- _pending_find: null,
56723
+ _find_term: "",
56724
+ _find_current: "",
56725
+ _find_found: null,
56725
56726
  _layout_asked: "",
56726
56727
  _nodes_total: 0,
56727
56728
  _nodes_placed: 0,
@@ -58676,6 +58677,14 @@ function graph_focus_topic(gobj, topic, reveal_all) {
58676
58677
  }
58677
58678
  let model = priv._fold_model;
58678
58679
  let state = priv._fold_state;
58680
+ if ((0, _yuneta_gobj_js.empty_string)(topic) && priv._find_term) {
58681
+ priv._focus_topic = null;
58682
+ return;
58683
+ }
58684
+ if (!(0, _yuneta_gobj_js.empty_string)(topic)) {
58685
+ priv._find_term = "";
58686
+ priv._find_current = "";
58687
+ }
58679
58688
  let keys = [];
58680
58689
  if (!(0, _yuneta_gobj_js.empty_string)(topic)) {
58681
58690
  for (let node of model.nodes.values()) if (node.topic_name === topic) keys.push(node.key);
@@ -58691,17 +58700,17 @@ function graph_focus_topic(gobj, topic, reveal_all) {
58691
58700
  }
58692
58701
  priv._focus_topic = topic || null;
58693
58702
  reconcile_fold(gobj, {}).then(() => {
58694
- apply_focus_ids(gobj, keys, "focus topic");
58703
+ apply_focus_ids(gobj, keys, "focus topic", true);
58695
58704
  });
58696
58705
  }
58697
58706
  /************************************************************
58698
- * Paint the highlight on these records (by model key) and put
58699
- * the first of them in the middle. Shared by the find and the
58700
- * topic focus, after the reconcile that brought them on screen.
58701
- * Keys that are still off screen are skipped: a match beyond the
58702
- * page a reveal opened is counted, not painted.
58707
+ * Paint the highlight on these records (by model key) and, with
58708
+ * `center`, put the first of them in the middle. Shared by the
58709
+ * find and the topic focus. Keys that are not on screen are
58710
+ * skipped: a match beyond the page a reveal opened is counted,
58711
+ * not painted.
58703
58712
  ************************************************************/
58704
- function apply_focus_ids(gobj, keys, what) {
58713
+ function apply_focus_ids(gobj, keys, what, center) {
58705
58714
  let priv = gobj.priv;
58706
58715
  let graph = priv.graph;
58707
58716
  if (!graph) return;
@@ -58726,7 +58735,7 @@ function apply_focus_ids(gobj, keys, what) {
58726
58735
  try {
58727
58736
  if (typeof graph.setElementState === "function") graph.setElementState(states);
58728
58737
  apply_node_highlight(gobj, prev_ids, ids);
58729
- if (ids.length) yui_graph_center_on(graph, ids[0]);
58738
+ if (center && ids.length) yui_graph_center_on(graph, ids[0]);
58730
58739
  } catch (e) {
58731
58740
  (0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: ${what} apply failed: ${e}`);
58732
58741
  }
@@ -58737,61 +58746,139 @@ function node_id_of_key(gobj, key) {
58737
58746
  return build_node_name(gobj, key.slice(0, i), key.slice(i + 1));
58738
58747
  }
58739
58748
  /************************************************************
58740
- * Find the nodes whose name, id or topic contains `term`, highlight
58741
- * them with the same amber 'active' state the topic focus uses, and
58742
- * centre the viewport on them. Returns how many matched, which is the
58743
- * half the toolbar needs: a search that finds nothing must SAY so,
58744
- * because a graph that did not move is also what a graph looks like
58745
- * when the match is off-screen.
58749
+ * The find box: highlight the cards ON SCREEN whose name, id or
58750
+ * topic contains `term`, and change nothing else -- no group is
58751
+ * opened, no layout runs, the camera does not move. The graph the
58752
+ * reader arranged is the graph they are searching; emptying the
58753
+ * box takes the amber off and leaves it exactly as it was.
58754
+ *
58755
+ * It used to search the whole treedb and unfold a page of what it
58756
+ * found, which re-laid the graph out on every keystroke and left
58757
+ * the unfolded groups behind when the box was cleared. Opening up
58758
+ * to a topic is the legend's focus (graph_focus_topic); this only
58759
+ * LOOKS.
58760
+ *
58761
+ * The term is kept and repainted after every reconcile (see
58762
+ * reconcile_fold_now): a group opened by hand shows its matches
58763
+ * already lit, and the count follows what is on screen.
58746
58764
  *
58747
58765
  * It shares the highlight slot with graph_focus_topic on purpose —
58748
- * two amber sets at once would say nothing about either. An empty
58749
- * term clears it. Matching reads the node's LABEL and not only its
58750
- * id: on a topic keyed by rowid or by a qualified path, the id is a
58751
- * counter and the name a human knows is elsewhere (see node_label).
58766
+ * two amber sets at once would say nothing about either. Matching
58767
+ * reads the node's LABEL and not only its id: on a topic keyed by
58768
+ * rowid or by a qualified path, the id is a counter and the name a
58769
+ * human knows is elsewhere (see node_label).
58752
58770
  ************************************************************/
58753
58771
  function graph_find_nodes(gobj, term) {
58754
58772
  let priv = gobj.priv;
58755
- if (!priv.graph || !priv.graph_rendered || !priv._fold_model) {
58756
- priv._pending_find = term;
58757
- return 0;
58773
+ let next = (0, _yuneta_gobj_js.empty_string)(term) ? "" : String(term);
58774
+ let was = priv._find_term;
58775
+ priv._find_term = next;
58776
+ priv._find_current = "";
58777
+ priv._find_found = null;
58778
+ let ready = priv.graph && priv.graph_rendered && priv._fold_model;
58779
+ if (!next) {
58780
+ if (was && ready && !priv._focus_topic) apply_focus_ids(gobj, [], "find", false);
58781
+ publish_find_result(gobj);
58782
+ return;
58758
58783
  }
58784
+ priv._focus_topic = null;
58785
+ if (!ready) return;
58786
+ refresh_find(gobj, fold_visible_set(priv._fold_model, priv._fold_state));
58787
+ }
58788
+ /************************************************************
58789
+ * Repaint the find's highlight over the `visible` set and publish
58790
+ * the count. A no-op while no term is live, so the topic focus
58791
+ * keeps the slot.
58792
+ ************************************************************/
58793
+ function refresh_find(gobj, visible) {
58794
+ let priv = gobj.priv;
58795
+ if (!priv._find_term) return;
58796
+ let found = find_matches(gobj, priv._find_term, visible);
58797
+ apply_focus_ids(gobj, found.keys, "find", false);
58798
+ if (priv._find_current && (priv._focus_ids || []).indexOf(priv._find_current) < 0) priv._find_current = "";
58799
+ priv._find_found = found;
58800
+ publish_find_result(gobj);
58801
+ }
58802
+ /************************************************************
58803
+ * The records matching `term`: the keys ON SCREEN, and how many
58804
+ * more match that are NOT -- folded away in the fold model, or in
58805
+ * a hidden topic. Those two are only counted: "0" alone would read
58806
+ * as "does not exist" when it means "is not on screen".
58807
+ ************************************************************/
58808
+ function find_matches(gobj, term, visible) {
58809
+ let priv = gobj.priv;
58759
58810
  let model = priv._fold_model;
58760
- let state = priv._fold_state;
58761
- let keys = [];
58762
- let hidden_matches = 0;
58763
- if (!(0, _yuneta_gobj_js.empty_string)(term)) {
58764
- let needle = String(term).toLowerCase();
58765
- let matches = (topic_name, record) => {
58766
- let label = "";
58767
- try {
58768
- label = node_label(priv.descs[topic_name] || {}, record) || "";
58769
- } catch (e) {
58770
- label = "";
58771
- }
58772
- return [
58773
- label,
58774
- record.id,
58775
- topic_name
58776
- ].filter((v) => typeof v === "string").join(" ").toLowerCase().includes(needle);
58777
- };
58778
- for (let node of model.nodes.values()) if (matches(node.topic_name, node.record || {})) keys.push(node.key);
58779
- for (let topic_name of model.hidden) for (let record of priv.records[topic_name] || []) if ((0, _yuneta_gobj_js.is_object)(record) && matches(topic_name, record)) hidden_matches++;
58811
+ let found = {
58812
+ keys: [],
58813
+ folded: 0,
58814
+ hidden: 0
58815
+ };
58816
+ if (!model || (0, _yuneta_gobj_js.empty_string)(term)) return found;
58817
+ let needle = String(term).toLowerCase();
58818
+ let matches = (topic_name, record) => {
58819
+ let label = "";
58820
+ try {
58821
+ label = node_label(priv.descs[topic_name] || {}, record) || "";
58822
+ } catch (e) {
58823
+ label = "";
58824
+ }
58825
+ return [
58826
+ label,
58827
+ record.id,
58828
+ topic_name
58829
+ ].filter((v) => typeof v === "string").join(" ").toLowerCase().includes(needle);
58830
+ };
58831
+ for (let node of model.nodes.values()) if (matches(node.topic_name, node.record || {})) {
58832
+ if (visible.has(node.key)) found.keys.push(node.key);
58833
+ else found.folded++;
58780
58834
  }
58781
- priv._find_hidden_matches = hidden_matches;
58782
- let visible = fold_visible_set(model, state);
58783
- let revealed = 0;
58784
- for (let key of keys) {
58785
- if (visible.has(key)) continue;
58786
- if (revealed >= state.page_size) break;
58787
- fold_reveal(model, state, key);
58788
- revealed++;
58835
+ for (let topic_name of model.hidden) for (let record of priv.records[topic_name] || []) if ((0, _yuneta_gobj_js.is_object)(record) && matches(topic_name, record)) found.hidden++;
58836
+ return found;
58837
+ }
58838
+ /************************************************************
58839
+ * The lit cards in reading order: top to bottom, then left to
58840
+ * right. The order Enter walks, and the one the "k/N" counts in.
58841
+ ************************************************************/
58842
+ function find_order(gobj) {
58843
+ let priv = gobj.priv;
58844
+ let graph = priv.graph;
58845
+ let ids = (priv._focus_ids || []).slice();
58846
+ if (!graph) return ids;
58847
+ let pos = {};
58848
+ for (let id of ids) {
58849
+ let p = null;
58850
+ try {
58851
+ p = graph.getElementPosition(id);
58852
+ } catch (e) {
58853
+ p = null;
58854
+ }
58855
+ pos[id] = p || [0, 0];
58789
58856
  }
58790
- priv._focus_topic = null;
58791
- reconcile_fold(gobj, {}).then(() => {
58792
- apply_focus_ids(gobj, keys, "find");
58793
- });
58794
- return keys.length;
58857
+ ids.sort((a, b) => pos[a][1] - pos[b][1] || pos[a][0] - pos[b][0]);
58858
+ return ids;
58859
+ }
58860
+ /************************************************************
58861
+ * Enter in the find box: centre the next lit card (`back`: the
58862
+ * previous one). The one camera move of the find, and the reader
58863
+ * asks for it: the highlight alone cannot take anybody to a match
58864
+ * that is outside the frame.
58865
+ ************************************************************/
58866
+ function graph_find_step(gobj, back) {
58867
+ let priv = gobj.priv;
58868
+ let graph = priv.graph;
58869
+ if (!graph || !priv._find_term) return;
58870
+ let ids = find_order(gobj);
58871
+ if (ids.length === 0) return;
58872
+ let i = ids.indexOf(priv._find_current);
58873
+ if (i < 0) i = back ? ids.length - 1 : 0;
58874
+ else i = (i + (back ? ids.length - 1 : 1)) % ids.length;
58875
+ priv._find_current = ids[i];
58876
+ try {
58877
+ yui_graph_center_on(graph, ids[i]);
58878
+ } catch (e) {
58879
+ (0, _yuneta_gobj_js.log_error)(`${(0, _yuneta_gobj_js.gobj_short_name)(gobj)}: find step failed: ${e}`);
58880
+ }
58881
+ publish_find_result(gobj);
58795
58882
  }
58796
58883
  async function graph_zoom_in(gobj) {
58797
58884
  let graph = gobj.priv.graph;
@@ -62683,6 +62770,7 @@ async function reconcile_fold_now(gobj, opts) {
62683
62770
  history_resume(gobj);
62684
62771
  }
62685
62772
  publish_legend_state(gobj, visible);
62773
+ refresh_find(gobj, visible);
62686
62774
  return changed;
62687
62775
  }
62688
62776
  /************************************************************
@@ -63064,11 +63152,6 @@ function ac_load_data(gobj, event, kw, src) {
63064
63152
  priv._pending_focus_all = false;
63065
63153
  graph_focus_topic(gobj, ft, all);
63066
63154
  }
63067
- if (priv._pending_find !== null) {
63068
- let term = priv._pending_find;
63069
- priv._pending_find = null;
63070
- publish_find_result(gobj, term, graph_find_nodes(gobj, term));
63071
- }
63072
63155
  });
63073
63156
  }
63074
63157
  return 0;
@@ -63637,23 +63720,45 @@ function ac_node_dblclick(gobj, event, kw, src) {
63637
63720
  return 0;
63638
63721
  }
63639
63722
  /************************************************************
63640
- * Tell whoever asked how many nodes the term matched. The count is
63641
- * the answer to the question the box asks; without it "nothing moved"
63642
- * and "nothing matched" look the same.
63723
+ * Tell whoever asked how many cards the term lit. The count is the
63724
+ * answer to the question the box asks; without it "nothing lit" and
63725
+ * "nothing matched" look the same.
63726
+ *
63727
+ * matches lit cards (on screen)
63728
+ * folded_matches matches folded away, not on screen
63729
+ * hidden_matches matches in hidden topics
63730
+ * current 1-based place of the card Enter centred on
63731
+ * among the lit ones (reading order), 0 = none
63643
63732
  ************************************************************/
63644
- function publish_find_result(gobj, term, matches) {
63733
+ function publish_find_result(gobj) {
63734
+ let priv = gobj.priv;
63735
+ let found = priv._find_found || {
63736
+ keys: [],
63737
+ folded: 0,
63738
+ hidden: 0
63739
+ };
63740
+ let current = 0;
63741
+ if (priv._find_term && priv._find_current) current = find_order(gobj).indexOf(priv._find_current) + 1;
63645
63742
  (0, _yuneta_gobj_js.gobj_publish_event)(gobj, "EV_FIND_RESULT", {
63646
- term,
63647
- matches,
63648
- hidden_matches: gobj.priv._find_hidden_matches || 0
63743
+ term: priv._find_term,
63744
+ matches: priv._find_term ? (priv._focus_ids || []).length : 0,
63745
+ folded_matches: found.folded,
63746
+ hidden_matches: found.hidden,
63747
+ current
63649
63748
  });
63650
63749
  }
63651
63750
  /************************************************************
63652
63751
  *
63653
63752
  ************************************************************/
63654
63753
  function ac_find_nodes$1(gobj, event, kw, src) {
63655
- let term = kw && kw.text || "";
63656
- publish_find_result(gobj, term, graph_find_nodes(gobj, term));
63754
+ graph_find_nodes(gobj, kw && kw.text || "");
63755
+ return 0;
63756
+ }
63757
+ /************************************************************
63758
+ * Enter in the find box: {back: true} for Shift+Enter.
63759
+ ************************************************************/
63760
+ function ac_find_next$1(gobj, event, kw, src) {
63761
+ graph_find_step(gobj, !!(kw && kw.back));
63657
63762
  return 0;
63658
63763
  }
63659
63764
  function ac_center(gobj, event, kw, src) {
@@ -64114,6 +64219,11 @@ function create_gclass$4(gclass_name) {
64114
64219
  ac_find_nodes$1,
64115
64220
  null
64116
64221
  ],
64222
+ [
64223
+ "EV_FIND_NEXT",
64224
+ ac_find_next$1,
64225
+ null
64226
+ ],
64117
64227
  [
64118
64228
  "EV_TOGGLE_FOLD",
64119
64229
  ac_toggle_fold,
@@ -64269,6 +64379,7 @@ function create_gclass$4(gclass_name) {
64269
64379
  ["EV_ZOOM_SELECTION", 0],
64270
64380
  ["EV_FOCUS_TOPIC", 0],
64271
64381
  ["EV_FIND_NODES", 0],
64382
+ ["EV_FIND_NEXT", 0],
64272
64383
  ["EV_FIND_RESULT", _yuneta_gobj_js.event_flag_t.EVF_OUTPUT_EVENT],
64273
64384
  ["EV_LAYOUT_AUTOSET", _yuneta_gobj_js.event_flag_t.EVF_OUTPUT_EVENT],
64274
64385
  ["EV_CAMERA_CHANGED", _yuneta_gobj_js.event_flag_t.EVF_OUTPUT_EVENT | _yuneta_gobj_js.event_flag_t.EVF_NO_WARN_SUBS],
@@ -65061,19 +65172,34 @@ function make_toolbar(gobj) {
65061
65172
  type: "text",
65062
65173
  placeholder: (0, i18next.t)("search"),
65063
65174
  "data-i18n-placeholder": "search",
65064
- "aria-label": (0, i18next.t)("search"),
65065
- "data-i18n-aria-label": "search"
65175
+ title: (0, i18next.t)("find on screen"),
65176
+ "data-i18n-title": "find on screen",
65177
+ "aria-label": (0, i18next.t)("find on screen"),
65178
+ "data-i18n-aria-label": "find on screen"
65066
65179
  },
65067
65180
  [],
65068
- { input: (evt) => {
65069
- evt.stopPropagation();
65070
- let text = evt.target.value.trim();
65071
- if (priv.find_timer) clearTimeout(priv.find_timer);
65072
- priv.find_timer = setTimeout(function() {
65073
- priv.find_timer = null;
65074
- (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_FIND_NODES", { text }, gobj);
65075
- }, 250);
65076
- } }
65181
+ {
65182
+ input: (evt) => {
65183
+ evt.stopPropagation();
65184
+ let text = evt.target.value.trim();
65185
+ if (priv.find_timer) clearTimeout(priv.find_timer);
65186
+ priv.find_timer = setTimeout(function() {
65187
+ priv.find_timer = null;
65188
+ (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_FIND_NODES", { text }, gobj);
65189
+ }, 250);
65190
+ },
65191
+ keydown: (evt) => {
65192
+ if (evt.key !== "Enter" || evt.isComposing) return;
65193
+ evt.preventDefault();
65194
+ evt.stopPropagation();
65195
+ if (priv.find_timer) {
65196
+ clearTimeout(priv.find_timer);
65197
+ priv.find_timer = null;
65198
+ (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_FIND_NODES", { text: evt.target.value.trim() }, gobj);
65199
+ }
65200
+ (0, _yuneta_gobj_js.gobj_send_event)(gobj, "EV_FIND_NEXT", { back: evt.shiftKey }, gobj);
65201
+ }
65202
+ }
65077
65203
  ]);
65078
65204
  let $find_control = (0, _yuneta_gobj_js.createElement2)([
65079
65205
  "div",
@@ -66402,6 +66528,14 @@ function ac_find_nodes(gobj, event, kw, src) {
66402
66528
  return 0;
66403
66529
  }
66404
66530
  /************************************************************
66531
+ * Enter in the find box: forward the step down to the graph child.
66532
+ ************************************************************/
66533
+ function ac_find_next(gobj, event, kw, src) {
66534
+ let priv = gobj.priv;
66535
+ if (priv.gobj_nodes_tree) (0, _yuneta_gobj_js.gobj_send_event)(priv.gobj_nodes_tree, "EV_FIND_NEXT", { back: !!(kw && kw.back) }, gobj);
66536
+ return 0;
66537
+ }
66538
+ /************************************************************
66405
66539
  * One press of the fold stepper (EV_EXPAND_LEVEL /
66406
66540
  * EV_COLLAPSE_LEVEL): the level moves by one, is SAVED (the
66407
66541
  * reader's, per treedb) and reaches the G6 child, which owns
@@ -66485,12 +66619,33 @@ function refresh_find_result(gobj) {
66485
66619
  return 0;
66486
66620
  }
66487
66621
  let text = (0, i18next.t)("matches", { count: kw && kw.matches || 0 });
66622
+ let current = kw && kw.current || 0;
66623
+ if (current > 0) text = `${current}/${text}`;
66624
+ let extra = [];
66625
+ let folded = kw && kw.folded_matches || 0;
66626
+ if (folded > 0) extra.push(`+${folded} ${(0, i18next.t)("not shown")}`);
66488
66627
  let hidden = kw && kw.hidden_matches || 0;
66489
- if (hidden > 0) text += ` (+${hidden} ${(0, i18next.t)("hidden topics")})`;
66628
+ if (hidden > 0) extra.push(`+${hidden} ${(0, i18next.t)("hidden topics")}`);
66629
+ if (extra.length) text += ` (${extra.join(", ")})`;
66490
66630
  $count.textContent = text;
66491
66631
  $result.classList.remove("is-hidden");
66492
66632
  return 0;
66493
66633
  }
66634
+ function clear_find_box(gobj) {
66635
+ let priv = gobj.priv;
66636
+ if (priv.find_timer) {
66637
+ clearTimeout(priv.find_timer);
66638
+ priv.find_timer = null;
66639
+ }
66640
+ let $container = (0, _yuneta_gobj_js.gobj_read_attr)(gobj, "$container");
66641
+ let $input = $container ? $container.querySelector(".GRAPH_FIND_INPUT") : null;
66642
+ if ($input) {
66643
+ $input.value = "";
66644
+ refresh_clear($input);
66645
+ }
66646
+ priv._find_result = null;
66647
+ refresh_find_result(gobj);
66648
+ }
66494
66649
  function ac_set_focus_topic(gobj, event, kw, src) {
66495
66650
  let priv = gobj.priv;
66496
66651
  priv.focus_topic = kw && kw.topic || "";
@@ -66501,6 +66656,7 @@ function ac_set_focus_topic(gobj, event, kw, src) {
66501
66656
  set_legend_list_attr(gobj, "hidden_topics", "EV_SET_HIDDEN_TOPICS", hidden);
66502
66657
  }
66503
66658
  }
66659
+ if (priv.focus_topic) clear_find_box(gobj);
66504
66660
  if (priv.gobj_nodes_tree) (0, _yuneta_gobj_js.gobj_send_event)(priv.gobj_nodes_tree, "EV_FOCUS_TOPIC", {
66505
66661
  topic: priv.focus_topic,
66506
66662
  reveal: kw && kw.reveal || "page"
@@ -66678,6 +66834,11 @@ function create_gclass$3(gclass_name) {
66678
66834
  ac_find_nodes,
66679
66835
  null
66680
66836
  ],
66837
+ [
66838
+ "EV_FIND_NEXT",
66839
+ ac_find_next,
66840
+ null
66841
+ ],
66681
66842
  [
66682
66843
  "EV_EXPAND_LEVEL",
66683
66844
  ac_fold_level_step,
@@ -66776,6 +66937,7 @@ function create_gclass$3(gclass_name) {
66776
66937
  ["EV_SET_OPERATION_MODE", 0],
66777
66938
  ["EV_SET_FOCUS_TOPIC", 0],
66778
66939
  ["EV_FIND_NODES", 0],
66940
+ ["EV_FIND_NEXT", 0],
66779
66941
  ["EV_EXPAND_LEVEL", 0],
66780
66942
  ["EV_COLLAPSE_LEVEL", 0],
66781
66943
  ["EV_SET_NODE_MODE", 0],