@yuneta/gobj-ui 7.23.84 → 7.23.86

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.
@@ -2103,6 +2103,54 @@ function topic_defaults_of(gobj, topic_name)
2103
2103
  topic_props.defaults : null;
2104
2104
  }
2105
2105
 
2106
+ /************************************************************
2107
+ * What a node is PAINTED with: its own colours, then the
2108
+ * topic's default, then the topic's colour.
2109
+ *
2110
+ * A card is html, and its html was built with `desc.color`
2111
+ * every time it was repainted -- so a colour chosen in the node
2112
+ * properties popover lasted until the next selection, focus,
2113
+ * theme or pill change, and was never written to `__graphs__`
2114
+ * at all. Only the `shape` view kept it, because a figure is a
2115
+ * native G6 node and `style.fill` is what paints it. The FIGURE
2116
+ * was already remembered (`node_shape`); this is the wiring the
2117
+ * colour was missing.
2118
+ ************************************************************/
2119
+ function node_paint_of(gobj, desc, geometry)
2120
+ {
2121
+ let defaults = topic_defaults_of(gobj, desc.topic_name);
2122
+ let g = is_object(geometry)? geometry : {};
2123
+ let fill = g.fill || (defaults && defaults.fill) || desc.color;
2124
+ let stroke = g.stroke || (defaults && defaults.stroke) || getStrokeColor(fill);
2125
+ let line_width = g.lineWidth || (defaults && defaults.lineWidth) || 1;
2126
+ return {fill: fill, stroke: stroke, lineWidth: line_width};
2127
+ }
2128
+
2129
+ /************************************************************
2130
+ * Write a chosen paint into an entry of `__graphs__` -- a
2131
+ * node's or a topic's defaults.
2132
+ *
2133
+ * A colour nobody chose is not saved: the topic's own colour,
2134
+ * with the stroke and the line width that go with it, is what a
2135
+ * card wears anyway, and writing it down would freeze today's
2136
+ * palette on that card -- the trap the SIZES fell into in
2137
+ * 7.23.80, and the palette is assigned by POSITION (`ac_descs`),
2138
+ * so it moves when a topic is added. Choosing it back MEANS
2139
+ * forgetting the entry.
2140
+ ************************************************************/
2141
+ function paint_into(entry, desc, fill, stroke, line_width)
2142
+ {
2143
+ if(fill === desc.color && stroke === getStrokeColor(desc.color) && line_width === 1) {
2144
+ delete entry.fill;
2145
+ delete entry.stroke;
2146
+ delete entry.lineWidth;
2147
+ return;
2148
+ }
2149
+ entry.fill = fill;
2150
+ entry.stroke = stroke;
2151
+ entry.lineWidth = line_width;
2152
+ }
2153
+
2106
2154
  /************************************************************
2107
2155
  * The CARD: an html node, the tier's size, the ports, the
2108
2156
  * saved geometry on top. The flags (focus, selection, anchor)
@@ -2115,11 +2163,12 @@ function card_shape_of(gobj, desc, record, geometry, pills_html)
2115
2163
  let node_treedb_type = desc.node_treedb_type;
2116
2164
  let label = node_label(desc, record);
2117
2165
  let ports = build_ports(gobj, desc);
2166
+ let paint = node_paint_of(gobj, desc, geometry);
2118
2167
 
2119
2168
  let style = {
2120
- fill: desc.color,
2121
- stroke: getStrokeColor(desc.color),
2122
- lineWidth: 1,
2169
+ fill: paint.fill,
2170
+ stroke: paint.stroke,
2171
+ lineWidth: paint.lineWidth,
2123
2172
  lineDash: [],
2124
2173
  halo: false,
2125
2174
  labelText: "", /* a card says its name inside; the label is the square's */
@@ -2136,20 +2185,20 @@ function card_shape_of(gobj, desc, record, geometry, pills_html)
2136
2185
  // Pure child (LEAF): smallest tier. Rounded-rect chip,
2137
2186
  // same card language as entities, lighter.
2138
2187
  style.innerHTML = build_chip_innerHTML(
2139
- desc.color, priv.theme, record.icon, label, record.id
2188
+ paint.fill, priv.theme, record.icon, label, record.id
2140
2189
  );
2141
2190
  } else if(node_treedb_type === 'extended') {
2142
2191
  // Extended (structural / INTERMEDIATE): middle tier. Card
2143
2192
  // with name; "structural" style (neutral grey, dashed
2144
2193
  // border) to read as a container/junction.
2145
2194
  style.innerHTML = build_node_innerHTML(
2146
- desc.color, priv.theme, record.icon, label,
2195
+ paint.fill, priv.theme, record.icon, label,
2147
2196
  desc.topic_name, true, record.id, false, false, false, pills_html
2148
2197
  );
2149
2198
  } else {
2150
2199
  // Hierarchical entity (ROOT / container): largest tier.
2151
2200
  style.innerHTML = build_node_innerHTML(
2152
- desc.color, priv.theme, record.icon, label,
2201
+ paint.fill, priv.theme, record.icon, label,
2153
2202
  desc.topic_name, false, record.id, false, false, false, pills_html
2154
2203
  );
2155
2204
  }
@@ -2252,11 +2301,12 @@ function pill_shape_of(gobj, desc, record, geometry)
2252
2301
  let tier = desc.node_treedb_type;
2253
2302
  let size = PILL_SIZE[tier] || PILL_SIZE.hierarchical;
2254
2303
  let ports = build_ports(gobj, desc);
2304
+ let paint = node_paint_of(gobj, desc, geometry);
2255
2305
 
2256
2306
  let style = {
2257
- fill: desc.color,
2258
- stroke: getStrokeColor(desc.color),
2259
- lineWidth: 1,
2307
+ fill: paint.fill,
2308
+ stroke: paint.stroke,
2309
+ lineWidth: paint.lineWidth,
2260
2310
  lineDash: [],
2261
2311
  halo: false,
2262
2312
  labelText: "",
@@ -2264,7 +2314,7 @@ function pill_shape_of(gobj, desc, record, geometry)
2264
2314
  dx: -size[0] / 2,
2265
2315
  dy: -size[1] / 2,
2266
2316
  innerHTML: build_chip_innerHTML(
2267
- desc.color, priv.theme, record.icon, node_label(desc, record), record.id
2317
+ paint.fill, priv.theme, record.icon, node_label(desc, record), record.id
2268
2318
  ),
2269
2319
  };
2270
2320
  dress_ports(gobj, style, ports, geometry, topic_defaults_of(gobj, desc.topic_name),
@@ -2278,7 +2328,7 @@ function pill_innerHTML_of(gobj, nd, theme, highlight, selected, anchored)
2278
2328
  let desc = nd.data.desc;
2279
2329
  let record = nd.data.record || {};
2280
2330
  return build_chip_innerHTML(
2281
- desc.color, theme, record.icon, node_label(desc, record), record.id,
2331
+ node_fill_of(nd), theme, record.icon, node_label(desc, record), record.id,
2282
2332
  highlight, selected, anchored
2283
2333
  );
2284
2334
  }
@@ -2315,9 +2365,10 @@ function figure_shape_of(gobj, desc, record, geometry, flags)
2315
2365
  let side = SHAPE_SIZE[tier] || SHAPE_SIZE.hierarchical;
2316
2366
  let labels = gobj_read_bool_attr(gobj, "node_labels");
2317
2367
  let figure = node_figure_of(gobj, desc, geometry || {});
2368
+ let paint = node_paint_of(gobj, desc, geometry);
2318
2369
 
2319
- let stroke = getStrokeColor(desc.color);
2320
- let line_width = 1.5;
2370
+ let stroke = paint.stroke;
2371
+ let line_width = Math.max(paint.lineWidth, 1.5);
2321
2372
  if(f.selected) {
2322
2373
  stroke = SELECT_RING;
2323
2374
  line_width = 3;
@@ -2340,7 +2391,7 @@ function figure_shape_of(gobj, desc, record, geometry, flags)
2340
2391
  let style = {
2341
2392
  size: [side, side],
2342
2393
  radius: (figure === 'square')? Math.round(side / 5) : 0,
2343
- fill: desc.color,
2394
+ fill: paint.fill,
2344
2395
  stroke: stroke,
2345
2396
  lineWidth: line_width,
2346
2397
  lineDash: dash,
@@ -6503,43 +6554,26 @@ function show_node_popover(gobj)
6503
6554
  'g6-node-popover', '#d9d9d9', 180
6504
6555
  );
6505
6556
 
6506
- let node_graph_type = nodeData.data && nodeData.data.desc ?
6507
- nodeData.data.desc.node_treedb_type : null;
6557
+ /* Paint the node with these colours, whatever it is wearing:
6558
+ * the style for a figure, and the html of a card or a pill,
6559
+ * which repaint_cards() rebuilds from the style it is given
6560
+ * here (node_fill_of). */
6561
+ let paint_node = (fill, stroke, lw) => {
6562
+ graph.updateNodeData([{
6563
+ id: node_id, style: {fill: fill, stroke: stroke, lineWidth: lw},
6564
+ }]);
6565
+ repaint_cards(gobj, new Set([node_id]));
6566
+ graph.draw();
6567
+ };
6508
6568
 
6509
6569
  /* What the preview writes, undone (see set_preview_undo). */
6510
6570
  let undo_node = () => {
6511
- let restoreStyle = { fill: origFill, stroke: origStroke, lineWidth: origLW };
6512
- if(node_graph_type === 'hierarchical') {
6513
- let record = nodeData.data.record || {};
6514
- restoreStyle.innerHTML = build_node_innerHTML(
6515
- origFill, priv.theme, record.icon,
6516
- node_label(nodeData.data.desc, record),
6517
- nodeData.data.desc.topic_name, false, record.id,
6518
- false, false, false, pills_html_of(gobj, nodeData)
6519
- );
6520
- }
6521
- graph.updateNodeData([{ id: node_id, style: restoreStyle }]);
6522
- graph.draw();
6571
+ paint_node(origFill, origStroke, origLW);
6523
6572
  };
6524
6573
 
6525
6574
  // Live preview
6526
6575
  function preview_node() {
6527
- let fill = fillInput.value;
6528
- let stroke = strokeInput.value;
6529
- let lw = parseInt(lwInput.value) || 1;
6530
- let updateStyle = { fill: fill, stroke: stroke, lineWidth: lw };
6531
-
6532
- if(node_graph_type === 'hierarchical') {
6533
- let record = nodeData.data.record || {};
6534
- updateStyle.innerHTML = build_node_innerHTML(
6535
- fill, priv.theme, record.icon,
6536
- node_label(nodeData.data.desc, record),
6537
- nodeData.data.desc.topic_name, false, record.id,
6538
- false, false, false, pills_html_of(gobj, nodeData)
6539
- );
6540
- }
6541
- graph.updateNodeData([{ id: node_id, style: updateStyle }]);
6542
- graph.draw();
6576
+ paint_node(fillInput.value, strokeInput.value, parseInt(lwInput.value) || 1);
6543
6577
  }
6544
6578
 
6545
6579
  // Fill color
@@ -6933,6 +6967,16 @@ function refresh_minimap(gobj)
6933
6967
  * same three-way choice — it lived inline in the theme refresh and is
6934
6968
  * shared now. Returns null for a node that carries no desc.
6935
6969
  ************************************************************/
6970
+ /* The colour a node is WEARING, from its live style: the shape
6971
+ * functions put the node's own paint there when it has one (see
6972
+ * node_paint_of), and a repaint has to keep it -- rebuilding the
6973
+ * html from `desc.color` is what threw away every colour applied
6974
+ * to a card at the first selection. */
6975
+ function node_fill_of(nd)
6976
+ {
6977
+ return (nd && nd.style && nd.style.fill) || nd.data.desc.color;
6978
+ }
6979
+
6936
6980
  function node_innerHTML_of(nd, theme, highlight, selected, anchored, pills_html)
6937
6981
  {
6938
6982
  if(!nd || !nd.data || !nd.data.desc) {
@@ -6941,22 +6985,23 @@ function node_innerHTML_of(nd, theme, highlight, selected, anchored, pills_html)
6941
6985
  let desc = nd.data.desc;
6942
6986
  let record = nd.data.record || {};
6943
6987
  let label = node_label(desc, record);
6988
+ let fill = node_fill_of(nd);
6944
6989
 
6945
6990
  switch(desc.node_treedb_type) {
6946
6991
  case 'child':
6947
6992
  return build_chip_innerHTML(
6948
- desc.color, theme, record.icon, label, record.id,
6993
+ fill, theme, record.icon, label, record.id,
6949
6994
  highlight, selected, anchored
6950
6995
  );
6951
6996
  case 'extended':
6952
6997
  return build_node_innerHTML(
6953
- desc.color, theme, record.icon, label,
6998
+ fill, theme, record.icon, label,
6954
6999
  desc.topic_name, true, record.id, highlight, selected, anchored,
6955
7000
  pills_html
6956
7001
  );
6957
7002
  case 'hierarchical':
6958
7003
  return build_node_innerHTML(
6959
- desc.color, theme, record.icon, label,
7004
+ fill, theme, record.icon, label,
6960
7005
  desc.topic_name, false, record.id, highlight, selected, anchored,
6961
7006
  pills_html
6962
7007
  );
@@ -7801,21 +7846,33 @@ function apply_node_properties(gobj, node_id, fill, stroke, lineWidth, scope, sh
7801
7846
 
7802
7847
  let source_topic = nodeData.data.desc ? nodeData.data.desc.topic_name : null;
7803
7848
  let updates = [];
7849
+ let repaint = new Set();
7804
7850
  const nodes = graph.getData().nodes;
7805
7851
 
7806
- /* The figure: written where Save reads it (the node's entry in
7807
- * `__graphs__`), and as the topic's default for the wider
7808
- * scopes, so a record that arrives later is born with it. */
7852
+ /* The figure AND the colours: written where Save reads them (the
7853
+ * node's entry in `__graphs__`), and as the topic's default for
7854
+ * the wider scopes, so a record that arrives later is born with
7855
+ * them. The colours used to be written on the live style alone,
7856
+ * which on an html card is under the html: the first repaint
7857
+ * rebuilt that html from the topic's colour and the choice was
7858
+ * gone, and nothing of it ever reached the store. */
7809
7859
  let figure = (shape && str_in_list(NODE_SHAPES, shape))? shape : "";
7810
7860
  let reshaped = [];
7811
- if(figure && scope !== 'this') {
7861
+ if(scope !== 'this') {
7812
7862
  let topics = (scope === 'same_topic')? [source_topic] : Object.keys(priv.descs || {});
7813
7863
  for(let topic_name of topics) {
7864
+ let desc = priv.descs[topic_name];
7865
+ if(!desc) {
7866
+ continue;
7867
+ }
7814
7868
  if(!is_object(priv._graph_properties[topic_name])) {
7815
7869
  priv._graph_properties[topic_name] = {};
7816
7870
  }
7817
7871
  let defaults = priv._graph_properties[topic_name].defaults || {};
7818
- defaults.node_shape = figure;
7872
+ if(figure) {
7873
+ defaults.node_shape = figure;
7874
+ }
7875
+ paint_into(defaults, desc, fill, stroke, lineWidth);
7819
7876
  priv._graph_properties[topic_name].defaults = defaults;
7820
7877
  }
7821
7878
  }
@@ -7833,24 +7890,21 @@ function apply_node_properties(gobj, node_id, fill, stroke, lineWidth, scope, sh
7833
7890
  continue;
7834
7891
  }
7835
7892
 
7893
+ let entry = node_props_entry(gobj, nd);
7836
7894
  if(figure) {
7837
- node_props_entry(gobj, nd).node_shape = figure;
7895
+ entry.node_shape = figure;
7838
7896
  if(node_mode_of(gobj, nodes[i].id) === 'shape') {
7839
7897
  reshaped.push(nodes[i].id);
7840
7898
  }
7841
7899
  }
7900
+ paint_into(entry, nd.data.desc, fill, stroke, lineWidth);
7842
7901
 
7902
+ /* The style for the figure, the html for the card and the
7903
+ * pill: every tier is repainted, and the repaint reads the
7904
+ * style it is given here (node_fill_of). */
7843
7905
  let updateStyle = { fill: fill, stroke: stroke, lineWidth: lineWidth };
7844
- if(nd.data.desc.node_treedb_type === 'hierarchical') {
7845
- let record = nd.data.record || {};
7846
- updateStyle.innerHTML = build_node_innerHTML(
7847
- fill, priv.theme, record.icon,
7848
- node_label(nd.data.desc, record),
7849
- nd.data.desc.topic_name, false, record.id,
7850
- false, false, false, pills_html_of(gobj, nd)
7851
- );
7852
- }
7853
7906
  updates.push({ id: nodes[i].id, style: updateStyle });
7907
+ repaint.add(nodes[i].id);
7854
7908
  }
7855
7909
 
7856
7910
  if(updates.length > 0) {
@@ -7858,6 +7912,7 @@ function apply_node_properties(gobj, node_id, fill, stroke, lineWidth, scope, sh
7858
7912
  if(reshaped.length) {
7859
7913
  reshape_nodes(gobj, reshaped);
7860
7914
  }
7915
+ repaint_cards(gobj, repaint);
7861
7916
  graph.draw().then(() => {
7862
7917
  mark_graph_dirty(gobj);
7863
7918
  });
@@ -62,6 +62,7 @@ import {
62
62
  yui_graph_update_anchor,
63
63
  yui_graph_center_on,
64
64
  yui_graph_fold_items,
65
+ yui_graph_icon,
65
66
  yui_graph_refresh_item,
66
67
  yui_graph_update_zoom,
67
68
  } from "./yui_graph_camera.js";
@@ -906,7 +907,7 @@ function make_find_items(gobj)
906
907
  style: 'margin-left:.5rem; margin-right:.5rem; ' +
907
908
  'max-width:12rem; min-width:7rem;'}, [
908
909
  $find_input,
909
- ['span', {class: 'icon is-left'}, [['i', {class: 'yi-magnifying-glass'}]]]
910
+ ['span', {class: 'icon is-left'}, [yui_graph_icon('yi-magnifying-glass')]]
910
911
  ]]);
911
912
  attach_clear($find_control, $find_input);
912
913
 
@@ -57,6 +57,7 @@ import {
57
57
  yui_graph_place_at,
58
58
  yui_graph_viewport_of,
59
59
  yui_graph_fold_items,
60
+ yui_graph_icon,
60
61
  yui_graph_refresh_item,
61
62
  yui_graph_update_zoom,
62
63
  } from "./yui_graph_camera.js";
@@ -585,7 +586,7 @@ function make_toolbar(gobj)
585
586
  ['div', {class: 'JSON_GRAPH_FIND control has-icons-left',
586
587
  style: 'margin-right:.5rem; max-width:12rem; min-width:7rem;'}, [
587
588
  $find_input,
588
- ['span', {class: 'icon is-left'}, [['i', {class: 'yi-magnifying-glass'}]]]
589
+ ['span', {class: 'icon is-left'}, [yui_graph_icon('yi-magnifying-glass')]]
589
590
  ]]);
590
591
  attach_clear($find_control, $find_input);
591
592
 
@@ -82,7 +82,11 @@ import {
82
82
  import {yui_toolbar} from "./yui_toolbar.js";
83
83
  import {attach_clear} from "./yui_inputs.js";
84
84
  import {register_c_g6_nodes_tree} from "./c_g6_nodes_tree.js";
85
- import {yui_graph_fold_items} from "./yui_graph_camera.js";
85
+ import {
86
+ yui_graph_fold_items,
87
+ yui_graph_icon,
88
+ YUI_GRAPH_ICON_SIZE,
89
+ } from "./yui_graph_camera.js";
86
90
  import {
87
91
  removeChildElements,
88
92
  disableElements,
@@ -574,7 +578,7 @@ function node_shape_items(gobj, wide)
574
578
  title: t(key), 'data-i18n-title': key,
575
579
  'aria-label': t(key), 'data-i18n-aria-label': key,
576
580
  'aria-pressed': 'false'},
577
- ['i', {style: 'font-size:1.5em; color:inherit;', class: NODE_MODE_ICONS[mode]}],
581
+ yui_graph_icon(NODE_MODE_ICONS[mode]),
578
582
  {
579
583
  click: (evt) => {
580
584
  evt.stopPropagation();
@@ -591,7 +595,7 @@ function node_shape_items(gobj, wide)
591
595
  title: t('node labels'), 'data-i18n-title': 'node labels',
592
596
  'aria-label': t('node labels'), 'data-i18n-aria-label': 'node labels',
593
597
  'aria-pressed': 'false'},
594
- ['i', {style: 'font-size:1.5em; color:inherit;', class: 'yi-font'}],
598
+ yui_graph_icon('yi-font'),
595
599
  {
596
600
  click: (evt) => {
597
601
  evt.stopPropagation();
@@ -693,7 +697,7 @@ function make_toolbar(gobj)
693
697
  }],
694
698
 
695
699
  ['button', {class: 'GRAPH_REFRESH button'}, [
696
- ['i', {class: 'yi-arrows-rotate'}],
700
+ yui_graph_icon('yi-arrows-rotate'),
697
701
  ['span', {class: 'is-hidden-mobile', style: 'padding-left:5px;', i18n: 'refresh'}, 'refresh']
698
702
  ], {
699
703
  click: (evt) => {
@@ -718,7 +722,7 @@ function make_toolbar(gobj)
718
722
  ['button', {class: 'button ml-2 TREEDB_JSON_BTN',
719
723
  title: t('raw json'), 'aria-label': t('raw json'),
720
724
  'data-i18n-title': 'raw json', 'data-i18n-aria-label': 'raw json'}, [
721
- ['i', {class: 'yi-eye'}],
725
+ yui_graph_icon('yi-eye'),
722
726
  ['span', {class: 'is-hidden-mobile', style: 'padding-left:5px;', i18n: 'raw json'}, 'raw json']
723
727
  ], {
724
728
  click: (evt) => {
@@ -775,7 +779,7 @@ function make_toolbar(gobj)
775
779
  ['div', {class: 'GRAPH_FIND control has-icons-left',
776
780
  style: 'margin-right:.5rem; max-width:12rem; min-width:7rem;'}, [
777
781
  $find_input,
778
- ['span', {class: 'icon is-left'}, [['i', {class: 'yi-magnifying-glass'}]]]
782
+ ['span', {class: 'icon is-left'}, [yui_graph_icon('yi-magnifying-glass')]]
779
783
  ]]);
780
784
  attach_clear($find_control, $find_input);
781
785
 
@@ -2453,19 +2457,20 @@ function ac_set_operation_mode(gobj, event, kw, src)
2453
2457
  * card's graph icon travels — as EV_TOPIC_SELECTED, which the host turns
2454
2458
  * into the URL, so what you are looking at stays linkable.
2455
2459
  ************************************************************/
2456
- /* The glyphs of a chip's small buttons: `is-small` sets a 0.75rem
2457
- * font and a star or a crosshair at that size is a speck. The BUTTON
2458
- * stays small so the strip keeps its height; the glyph inside grows. */
2459
- const LEGEND_GLYPH_STYLE = 'font-size:1.5em; line-height:1; color:inherit;';
2460
-
2461
- /* And the same for what a chip SAYS. The legend is a layer control --
2462
- * a gadget somebody uses, not a footnote somebody glances at -- and a
2463
- * topic name is the thing it is read for, so 0.75rem is the wrong
2464
- * size for it. The button stays `is-small` because the strip has to
2465
- * hold a chip per topic on one row; the name and the count come back
2466
- * up inside it, exactly as the glyphs did. */
2467
- const LEGEND_NAME_STYLE = 'font-size:1.2em; line-height:1.2;';
2468
- const LEGEND_COUNT_STYLE = 'margin-left:.4rem; font-size:1em;';
2460
+ /* The legend is the strip UNDER the toolbar, and the two are read as
2461
+ * one thing: what they say has to be the same size, or the lower one
2462
+ * reads as a footnote to the upper. `is-small` earns its place in the
2463
+ * PADDING -- a chip per topic has to fit on one row -- and nowhere
2464
+ * else, so the text and the glyphs are given back in `rem`, which is
2465
+ * measured against the page instead of against the 0.75rem the class
2466
+ * sets. In `em` they were 18px and 14.4px against the toolbar's 24px
2467
+ * and 16px: three sizes in two strips.
2468
+ *
2469
+ * The count is the one deliberate step down: it is the number beside
2470
+ * the name, not the name. */
2471
+ const LEGEND_GLYPH_STYLE = `font-size:${YUI_GRAPH_ICON_SIZE}; line-height:1; color:inherit;`;
2472
+ const LEGEND_NAME_STYLE = 'font-size:1rem; line-height:1.2;';
2473
+ const LEGEND_COUNT_STYLE = 'margin-left:.4rem; font-size:.875rem;';
2469
2474
 
2470
2475
  /* The focused chip is HIGHLIGHTED, not pressed. The body of a chip is
2471
2476
  * the show/hide toggle, and that is what its `aria-pressed` says;
@@ -2653,8 +2658,15 @@ function refresh_legend(gobj)
2653
2658
  }
2654
2659
 
2655
2660
  let $chip = createElement2(
2661
+ /* `align-items: stretch`: Bulma's `.buttons` centres its
2662
+ * children, so the star and the crosshair -- a glyph and
2663
+ * nothing else -- stood 20px tall beside a 30px chip body
2664
+ * that carries a swatch, a name and a count. In a
2665
+ * `has-addons` group that reads as three buttons of three
2666
+ * heights welded together. */
2656
2667
  ['div', {class: 'GRAPH_LEGEND_CHIP buttons has-addons',
2657
- style: 'margin:0; flex:0 0 auto; flex-wrap:nowrap;'},
2668
+ style: 'margin:0; flex:0 0 auto; flex-wrap:nowrap; ' +
2669
+ 'align-items:stretch;'},
2658
2670
  [$body].concat(extras.map((spec) => createElement2(spec)))]
2659
2671
  );
2660
2672
  $legend.appendChild($chip);
@@ -42,6 +42,35 @@ import {t} from "i18next";
42
42
  import {set_pressed_state} from "./lib_graph.js";
43
43
 
44
44
 
45
+ /************************************************************
46
+ * ONE size for every glyph of a graph's toolbar ROW, in
47
+ * `rem` and not `em`.
48
+ *
49
+ * In `em` the same declaration draws three different icons:
50
+ * `1.5em` is 24px inside a plain button, 18px inside an
51
+ * `is-small` one, and a labelled button left its icon at the
52
+ * inherited 16px -- so one row held 16px, 18px and 24px
53
+ * glyphs and looked like three toolbars pushed together.
54
+ * `rem` is measured against the page, so a chip that is
55
+ * deliberately shorter than a button still carries the same
56
+ * glyph.
57
+ *
58
+ * 20px against the row's 16px text: an icon-only button is
59
+ * legible at half its 40px height, and beside a label the
60
+ * glyph reads as a marker rather than as a second word.
61
+ ************************************************************/
62
+ export const YUI_GRAPH_ICON_SIZE = "1.25rem";
63
+
64
+ /* The `<i>` spec of a toolbar glyph, at that one size. */
65
+ export function yui_graph_icon(icon_class, extra_style)
66
+ {
67
+ return ['i', {
68
+ class: icon_class,
69
+ style: `font-size:${YUI_GRAPH_ICON_SIZE}; line-height:1; color:inherit;` +
70
+ (extra_style || ''),
71
+ }];
72
+ }
73
+
45
74
  /************************************************************
46
75
  * One icon button that fires `event_name`.
47
76
  ************************************************************/
@@ -51,8 +80,7 @@ function camera_button(gobj, icon, event_name, label_key, wide, extra_style)
51
80
  style: {height: wide, width: '2.5em'},
52
81
  title: t(label_key), 'data-i18n-title': label_key,
53
82
  'aria-label': t(label_key), 'data-i18n-aria-label': label_key},
54
- ['i', {style: 'font-size:1.5em; color:inherit;' + (extra_style || ''),
55
- class: icon}],
83
+ yui_graph_icon(icon, extra_style),
56
84
  {
57
85
  click: (evt) => {
58
86
  evt.stopPropagation();