@yuneta/gobj-ui 7.23.84 → 7.23.85

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
@@ -1374,6 +1374,20 @@ screen every card is a smudge. Since `7.23.82` a record has **three views**
1374
1374
  popover's own scope: this node, the topic, every node), remembered as the
1375
1375
  topic's default and saved per node in `__graphs__` as `node_shape`.
1376
1376
 
1377
+ **The colours are remembered the same way** (since `7.23.85`): `apply` writes
1378
+ `fill`, `stroke` and `lineWidth` into the node's entry in `__graphs__` — and
1379
+ into the topic's defaults for the wider scopes — and the three views read
1380
+ them back through one `node_paint_of()`, while every repaint takes the colour
1381
+ from the style the node is wearing rather than from `desc.color`. Before
1382
+ that, the colour lived on the live style alone, which on an html card is
1383
+ UNDER the html: the first repaint (a selection, the focus, a theme switch, a
1384
+ pill appearing) rebuilt that html from the topic's colour and the choice was
1385
+ gone, and nothing of it ever reached the store. Choosing the topic's own
1386
+ colour back, with the stroke and line width that go with it, **forgets** the
1387
+ entry instead of writing it: the palette is assigned by position, so a
1388
+ colour written down would freeze today's palette on that card — the trap the
1389
+ sizes fell into in `7.23.80`.
1390
+
1377
1391
  In the view's toolbar (`C_YUI_TREEDB_GRAPH`), next to the fold pair: three
1378
1392
  push buttons in one group — a card, a line, a figure — the pressed one being
1379
1393
  the view that is on (`full` / `compact` / `shape`, persisted as `node_mode`;
@@ -55656,6 +55656,52 @@ function topic_defaults_of(gobj, topic_name) {
55656
55656
  return (0, _yuneta_gobj_js.is_object)(topic_props) && (0, _yuneta_gobj_js.is_object)(topic_props.defaults) ? topic_props.defaults : null;
55657
55657
  }
55658
55658
  /************************************************************
55659
+ * What a node is PAINTED with: its own colours, then the
55660
+ * topic's default, then the topic's colour.
55661
+ *
55662
+ * A card is html, and its html was built with `desc.color`
55663
+ * every time it was repainted -- so a colour chosen in the node
55664
+ * properties popover lasted until the next selection, focus,
55665
+ * theme or pill change, and was never written to `__graphs__`
55666
+ * at all. Only the `shape` view kept it, because a figure is a
55667
+ * native G6 node and `style.fill` is what paints it. The FIGURE
55668
+ * was already remembered (`node_shape`); this is the wiring the
55669
+ * colour was missing.
55670
+ ************************************************************/
55671
+ function node_paint_of(gobj, desc, geometry) {
55672
+ let defaults = topic_defaults_of(gobj, desc.topic_name);
55673
+ let g = (0, _yuneta_gobj_js.is_object)(geometry) ? geometry : {};
55674
+ let fill = g.fill || defaults && defaults.fill || desc.color;
55675
+ return {
55676
+ fill,
55677
+ stroke: g.stroke || defaults && defaults.stroke || getStrokeColor(fill),
55678
+ lineWidth: g.lineWidth || defaults && defaults.lineWidth || 1
55679
+ };
55680
+ }
55681
+ /************************************************************
55682
+ * Write a chosen paint into an entry of `__graphs__` -- a
55683
+ * node's or a topic's defaults.
55684
+ *
55685
+ * A colour nobody chose is not saved: the topic's own colour,
55686
+ * with the stroke and the line width that go with it, is what a
55687
+ * card wears anyway, and writing it down would freeze today's
55688
+ * palette on that card -- the trap the SIZES fell into in
55689
+ * 7.23.80, and the palette is assigned by POSITION (`ac_descs`),
55690
+ * so it moves when a topic is added. Choosing it back MEANS
55691
+ * forgetting the entry.
55692
+ ************************************************************/
55693
+ function paint_into(entry, desc, fill, stroke, line_width) {
55694
+ if (fill === desc.color && stroke === getStrokeColor(desc.color) && line_width === 1) {
55695
+ delete entry.fill;
55696
+ delete entry.stroke;
55697
+ delete entry.lineWidth;
55698
+ return;
55699
+ }
55700
+ entry.fill = fill;
55701
+ entry.stroke = stroke;
55702
+ entry.lineWidth = line_width;
55703
+ }
55704
+ /************************************************************
55659
55705
  * The CARD: an html node, the tier's size, the ports, the
55660
55706
  * saved geometry on top. The flags (focus, selection, anchor)
55661
55707
  * are not painted here: repaint_cards() reads them where they
@@ -55666,10 +55712,11 @@ function card_shape_of(gobj, desc, record, geometry, pills_html) {
55666
55712
  let node_treedb_type = desc.node_treedb_type;
55667
55713
  let label = node_label(desc, record);
55668
55714
  let ports = build_ports(gobj, desc);
55715
+ let paint = node_paint_of(gobj, desc, geometry);
55669
55716
  let style = {
55670
- fill: desc.color,
55671
- stroke: getStrokeColor(desc.color),
55672
- lineWidth: 1,
55717
+ fill: paint.fill,
55718
+ stroke: paint.stroke,
55719
+ lineWidth: paint.lineWidth,
55673
55720
  lineDash: [],
55674
55721
  halo: false,
55675
55722
  labelText: ""
@@ -55678,9 +55725,9 @@ function card_shape_of(gobj, desc, record, geometry, pills_html) {
55678
55725
  style.size = size;
55679
55726
  style.dx = -size[0] / 2;
55680
55727
  style.dy = -size[1] / 2;
55681
- if (node_treedb_type === "child") style.innerHTML = build_chip_innerHTML(desc.color, priv.theme, record.icon, label, record.id);
55682
- else if (node_treedb_type === "extended") style.innerHTML = build_node_innerHTML(desc.color, priv.theme, record.icon, label, desc.topic_name, true, record.id, false, false, false, pills_html);
55683
- else style.innerHTML = build_node_innerHTML(desc.color, priv.theme, record.icon, label, desc.topic_name, false, record.id, false, false, false, pills_html);
55728
+ if (node_treedb_type === "child") style.innerHTML = build_chip_innerHTML(paint.fill, priv.theme, record.icon, label, record.id);
55729
+ else if (node_treedb_type === "extended") style.innerHTML = build_node_innerHTML(paint.fill, priv.theme, record.icon, label, desc.topic_name, true, record.id, false, false, false, pills_html);
55730
+ else style.innerHTML = build_node_innerHTML(paint.fill, priv.theme, record.icon, label, desc.topic_name, false, record.id, false, false, false, pills_html);
55684
55731
  let topic_props = priv._graph_properties[desc.topic_name];
55685
55732
  let topic_defaults = (0, _yuneta_gobj_js.is_object)(topic_props) && (0, _yuneta_gobj_js.is_object)(topic_props.defaults) ? topic_props.defaults : null;
55686
55733
  if (topic_defaults) {
@@ -55752,17 +55799,18 @@ function pill_shape_of(gobj, desc, record, geometry) {
55752
55799
  let priv = gobj.priv;
55753
55800
  let size = PILL_SIZE[desc.node_treedb_type] || PILL_SIZE.hierarchical;
55754
55801
  let ports = build_ports(gobj, desc);
55802
+ let paint = node_paint_of(gobj, desc, geometry);
55755
55803
  let style = {
55756
- fill: desc.color,
55757
- stroke: getStrokeColor(desc.color),
55758
- lineWidth: 1,
55804
+ fill: paint.fill,
55805
+ stroke: paint.stroke,
55806
+ lineWidth: paint.lineWidth,
55759
55807
  lineDash: [],
55760
55808
  halo: false,
55761
55809
  labelText: "",
55762
55810
  size: [...size],
55763
55811
  dx: -size[0] / 2,
55764
55812
  dy: -size[1] / 2,
55765
- innerHTML: build_chip_innerHTML(desc.color, priv.theme, record.icon, node_label(desc, record), record.id)
55813
+ innerHTML: build_chip_innerHTML(paint.fill, priv.theme, record.icon, node_label(desc, record), record.id)
55766
55814
  };
55767
55815
  dress_ports(gobj, style, ports, geometry, topic_defaults_of(gobj, desc.topic_name), PORT_R_PILL, true);
55768
55816
  return {
@@ -55773,7 +55821,7 @@ function pill_shape_of(gobj, desc, record, geometry) {
55773
55821
  function pill_innerHTML_of(gobj, nd, theme, highlight, selected, anchored) {
55774
55822
  let desc = nd.data.desc;
55775
55823
  let record = nd.data.record || {};
55776
- return build_chip_innerHTML(desc.color, theme, record.icon, node_label(desc, record), record.id, highlight, selected, anchored);
55824
+ return build_chip_innerHTML(node_fill_of(nd), theme, record.icon, node_label(desc, record), record.id, highlight, selected, anchored);
55777
55825
  }
55778
55826
  function node_figure_of(gobj, desc, geometry) {
55779
55827
  let shape = geometry ? geometry.node_shape : null;
@@ -55800,8 +55848,9 @@ function figure_shape_of(gobj, desc, record, geometry, flags) {
55800
55848
  let side = SHAPE_SIZE[tier] || SHAPE_SIZE.hierarchical;
55801
55849
  let labels = (0, _yuneta_gobj_js.gobj_read_bool_attr)(gobj, "node_labels");
55802
55850
  let figure = node_figure_of(gobj, desc, geometry || {});
55803
- let stroke = getStrokeColor(desc.color);
55804
- let line_width = 1.5;
55851
+ let paint = node_paint_of(gobj, desc, geometry);
55852
+ let stroke = paint.stroke;
55853
+ let line_width = Math.max(paint.lineWidth, 1.5);
55805
55854
  if (f.selected) {
55806
55855
  stroke = SELECT_RING;
55807
55856
  line_width = 3;
@@ -55819,7 +55868,7 @@ function figure_shape_of(gobj, desc, record, geometry, flags) {
55819
55868
  let style = {
55820
55869
  size: [side, side],
55821
55870
  radius: figure === "square" ? Math.round(side / 5) : 0,
55822
- fill: desc.color,
55871
+ fill: paint.fill,
55823
55872
  stroke,
55824
55873
  lineWidth: line_width,
55825
55874
  lineDash: dash,
@@ -58644,39 +58693,23 @@ function show_node_popover(gobj) {
58644
58693
  let rect = get_node_viewport_rect(gobj, node_id);
58645
58694
  if (!rect) return;
58646
58695
  const popover = create_popover_base(rect.right + floating_popover_dx(), rect.top + floating_icon_dy(), "g6-node-popover", "#d9d9d9", 180);
58647
- let node_graph_type = nodeData.data && nodeData.data.desc ? nodeData.data.desc.node_treedb_type : null;
58648
- let undo_node = () => {
58649
- let restoreStyle = {
58650
- fill: origFill,
58651
- stroke: origStroke,
58652
- lineWidth: origLW
58653
- };
58654
- if (node_graph_type === "hierarchical") {
58655
- let record = nodeData.data.record || {};
58656
- restoreStyle.innerHTML = build_node_innerHTML(origFill, priv.theme, record.icon, node_label(nodeData.data.desc, record), nodeData.data.desc.topic_name, false, record.id, false, false, false, pills_html_of(gobj, nodeData));
58657
- }
58696
+ let paint_node = (fill, stroke, lw) => {
58658
58697
  graph.updateNodeData([{
58659
58698
  id: node_id,
58660
- style: restoreStyle
58699
+ style: {
58700
+ fill,
58701
+ stroke,
58702
+ lineWidth: lw
58703
+ }
58661
58704
  }]);
58705
+ repaint_cards(gobj, /* @__PURE__ */ new Set([node_id]));
58662
58706
  graph.draw();
58663
58707
  };
58708
+ let undo_node = () => {
58709
+ paint_node(origFill, origStroke, origLW);
58710
+ };
58664
58711
  function preview_node() {
58665
- let fill = fillInput.value;
58666
- let updateStyle = {
58667
- fill,
58668
- stroke: strokeInput.value,
58669
- lineWidth: parseInt(lwInput.value) || 1
58670
- };
58671
- if (node_graph_type === "hierarchical") {
58672
- let record = nodeData.data.record || {};
58673
- updateStyle.innerHTML = build_node_innerHTML(fill, priv.theme, record.icon, node_label(nodeData.data.desc, record), nodeData.data.desc.topic_name, false, record.id, false, false, false, pills_html_of(gobj, nodeData));
58674
- }
58675
- graph.updateNodeData([{
58676
- id: node_id,
58677
- style: updateStyle
58678
- }]);
58679
- graph.draw();
58712
+ paint_node(fillInput.value, strokeInput.value, parseInt(lwInput.value) || 1);
58680
58713
  }
58681
58714
  create_form_label(popover, "fill color");
58682
58715
  let fillInput = create_form_color_input(popover, currentFill, preview_node);
@@ -58915,15 +58948,19 @@ function refresh_minimap(gobj) {
58915
58948
  * same three-way choice — it lived inline in the theme refresh and is
58916
58949
  * shared now. Returns null for a node that carries no desc.
58917
58950
  ************************************************************/
58951
+ function node_fill_of(nd) {
58952
+ return nd && nd.style && nd.style.fill || nd.data.desc.color;
58953
+ }
58918
58954
  function node_innerHTML_of(nd, theme, highlight, selected, anchored, pills_html) {
58919
58955
  if (!nd || !nd.data || !nd.data.desc) return null;
58920
58956
  let desc = nd.data.desc;
58921
58957
  let record = nd.data.record || {};
58922
58958
  let label = node_label(desc, record);
58959
+ let fill = node_fill_of(nd);
58923
58960
  switch (desc.node_treedb_type) {
58924
- case "child": return build_chip_innerHTML(desc.color, theme, record.icon, label, record.id, highlight, selected, anchored);
58925
- case "extended": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, true, record.id, highlight, selected, anchored, pills_html);
58926
- case "hierarchical": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, false, record.id, highlight, selected, anchored, pills_html);
58961
+ case "child": return build_chip_innerHTML(fill, theme, record.icon, label, record.id, highlight, selected, anchored);
58962
+ case "extended": return build_node_innerHTML(fill, theme, record.icon, label, desc.topic_name, true, record.id, highlight, selected, anchored, pills_html);
58963
+ case "hierarchical": return build_node_innerHTML(fill, theme, record.icon, label, desc.topic_name, false, record.id, highlight, selected, anchored, pills_html);
58927
58964
  }
58928
58965
  return null;
58929
58966
  }
@@ -59478,15 +59515,19 @@ function apply_node_properties(gobj, node_id, fill, stroke, lineWidth, scope, sh
59478
59515
  if (!nodeData || !nodeData.data) return;
59479
59516
  let source_topic = nodeData.data.desc ? nodeData.data.desc.topic_name : null;
59480
59517
  let updates = [];
59518
+ let repaint = /* @__PURE__ */ new Set();
59481
59519
  const nodes = graph.getData().nodes;
59482
59520
  let figure = shape && (0, _yuneta_gobj_js.str_in_list)(NODE_SHAPES, shape) ? shape : "";
59483
59521
  let reshaped = [];
59484
- if (figure && scope !== "this") {
59522
+ if (scope !== "this") {
59485
59523
  let topics = scope === "same_topic" ? [source_topic] : Object.keys(priv.descs || {});
59486
59524
  for (let topic_name of topics) {
59525
+ let desc = priv.descs[topic_name];
59526
+ if (!desc) continue;
59487
59527
  if (!(0, _yuneta_gobj_js.is_object)(priv._graph_properties[topic_name])) priv._graph_properties[topic_name] = {};
59488
59528
  let defaults = priv._graph_properties[topic_name].defaults || {};
59489
- defaults.node_shape = figure;
59529
+ if (figure) defaults.node_shape = figure;
59530
+ paint_into(defaults, desc, fill, stroke, lineWidth);
59490
59531
  priv._graph_properties[topic_name].defaults = defaults;
59491
59532
  }
59492
59533
  }
@@ -59495,27 +59536,27 @@ function apply_node_properties(gobj, node_id, fill, stroke, lineWidth, scope, sh
59495
59536
  if (!nd || !nd.data || !nd.data.desc) continue;
59496
59537
  if (scope === "this" && nodes[i].id !== node_id) continue;
59497
59538
  if (scope === "same_topic" && nd.data.desc.topic_name !== source_topic) continue;
59539
+ let entry = node_props_entry(gobj, nd);
59498
59540
  if (figure) {
59499
- node_props_entry(gobj, nd).node_shape = figure;
59541
+ entry.node_shape = figure;
59500
59542
  if (node_mode_of(gobj, nodes[i].id) === "shape") reshaped.push(nodes[i].id);
59501
59543
  }
59544
+ paint_into(entry, nd.data.desc, fill, stroke, lineWidth);
59502
59545
  let updateStyle = {
59503
59546
  fill,
59504
59547
  stroke,
59505
59548
  lineWidth
59506
59549
  };
59507
- if (nd.data.desc.node_treedb_type === "hierarchical") {
59508
- let record = nd.data.record || {};
59509
- updateStyle.innerHTML = build_node_innerHTML(fill, priv.theme, record.icon, node_label(nd.data.desc, record), nd.data.desc.topic_name, false, record.id, false, false, false, pills_html_of(gobj, nd));
59510
- }
59511
59550
  updates.push({
59512
59551
  id: nodes[i].id,
59513
59552
  style: updateStyle
59514
59553
  });
59554
+ repaint.add(nodes[i].id);
59515
59555
  }
59516
59556
  if (updates.length > 0) {
59517
59557
  graph.updateNodeData(updates);
59518
59558
  if (reshaped.length) reshape_nodes(gobj, reshaped);
59559
+ repaint_cards(gobj, repaint);
59519
59560
  graph.draw().then(() => {
59520
59561
  mark_graph_dirty(gobj);
59521
59562
  });
@@ -55651,6 +55651,52 @@ function topic_defaults_of(gobj, topic_name) {
55651
55651
  return is_object(topic_props) && is_object(topic_props.defaults) ? topic_props.defaults : null;
55652
55652
  }
55653
55653
  /************************************************************
55654
+ * What a node is PAINTED with: its own colours, then the
55655
+ * topic's default, then the topic's colour.
55656
+ *
55657
+ * A card is html, and its html was built with `desc.color`
55658
+ * every time it was repainted -- so a colour chosen in the node
55659
+ * properties popover lasted until the next selection, focus,
55660
+ * theme or pill change, and was never written to `__graphs__`
55661
+ * at all. Only the `shape` view kept it, because a figure is a
55662
+ * native G6 node and `style.fill` is what paints it. The FIGURE
55663
+ * was already remembered (`node_shape`); this is the wiring the
55664
+ * colour was missing.
55665
+ ************************************************************/
55666
+ function node_paint_of(gobj, desc, geometry) {
55667
+ let defaults = topic_defaults_of(gobj, desc.topic_name);
55668
+ let g = is_object(geometry) ? geometry : {};
55669
+ let fill = g.fill || defaults && defaults.fill || desc.color;
55670
+ return {
55671
+ fill,
55672
+ stroke: g.stroke || defaults && defaults.stroke || getStrokeColor(fill),
55673
+ lineWidth: g.lineWidth || defaults && defaults.lineWidth || 1
55674
+ };
55675
+ }
55676
+ /************************************************************
55677
+ * Write a chosen paint into an entry of `__graphs__` -- a
55678
+ * node's or a topic's defaults.
55679
+ *
55680
+ * A colour nobody chose is not saved: the topic's own colour,
55681
+ * with the stroke and the line width that go with it, is what a
55682
+ * card wears anyway, and writing it down would freeze today's
55683
+ * palette on that card -- the trap the SIZES fell into in
55684
+ * 7.23.80, and the palette is assigned by POSITION (`ac_descs`),
55685
+ * so it moves when a topic is added. Choosing it back MEANS
55686
+ * forgetting the entry.
55687
+ ************************************************************/
55688
+ function paint_into(entry, desc, fill, stroke, line_width) {
55689
+ if (fill === desc.color && stroke === getStrokeColor(desc.color) && line_width === 1) {
55690
+ delete entry.fill;
55691
+ delete entry.stroke;
55692
+ delete entry.lineWidth;
55693
+ return;
55694
+ }
55695
+ entry.fill = fill;
55696
+ entry.stroke = stroke;
55697
+ entry.lineWidth = line_width;
55698
+ }
55699
+ /************************************************************
55654
55700
  * The CARD: an html node, the tier's size, the ports, the
55655
55701
  * saved geometry on top. The flags (focus, selection, anchor)
55656
55702
  * are not painted here: repaint_cards() reads them where they
@@ -55661,10 +55707,11 @@ function card_shape_of(gobj, desc, record, geometry, pills_html) {
55661
55707
  let node_treedb_type = desc.node_treedb_type;
55662
55708
  let label = node_label(desc, record);
55663
55709
  let ports = build_ports(gobj, desc);
55710
+ let paint = node_paint_of(gobj, desc, geometry);
55664
55711
  let style = {
55665
- fill: desc.color,
55666
- stroke: getStrokeColor(desc.color),
55667
- lineWidth: 1,
55712
+ fill: paint.fill,
55713
+ stroke: paint.stroke,
55714
+ lineWidth: paint.lineWidth,
55668
55715
  lineDash: [],
55669
55716
  halo: false,
55670
55717
  labelText: ""
@@ -55673,9 +55720,9 @@ function card_shape_of(gobj, desc, record, geometry, pills_html) {
55673
55720
  style.size = size;
55674
55721
  style.dx = -size[0] / 2;
55675
55722
  style.dy = -size[1] / 2;
55676
- if (node_treedb_type === "child") style.innerHTML = build_chip_innerHTML(desc.color, priv.theme, record.icon, label, record.id);
55677
- else if (node_treedb_type === "extended") style.innerHTML = build_node_innerHTML(desc.color, priv.theme, record.icon, label, desc.topic_name, true, record.id, false, false, false, pills_html);
55678
- else style.innerHTML = build_node_innerHTML(desc.color, priv.theme, record.icon, label, desc.topic_name, false, record.id, false, false, false, pills_html);
55723
+ if (node_treedb_type === "child") style.innerHTML = build_chip_innerHTML(paint.fill, priv.theme, record.icon, label, record.id);
55724
+ else if (node_treedb_type === "extended") style.innerHTML = build_node_innerHTML(paint.fill, priv.theme, record.icon, label, desc.topic_name, true, record.id, false, false, false, pills_html);
55725
+ else style.innerHTML = build_node_innerHTML(paint.fill, priv.theme, record.icon, label, desc.topic_name, false, record.id, false, false, false, pills_html);
55679
55726
  let topic_props = priv._graph_properties[desc.topic_name];
55680
55727
  let topic_defaults = is_object(topic_props) && is_object(topic_props.defaults) ? topic_props.defaults : null;
55681
55728
  if (topic_defaults) {
@@ -55747,17 +55794,18 @@ function pill_shape_of(gobj, desc, record, geometry) {
55747
55794
  let priv = gobj.priv;
55748
55795
  let size = PILL_SIZE[desc.node_treedb_type] || PILL_SIZE.hierarchical;
55749
55796
  let ports = build_ports(gobj, desc);
55797
+ let paint = node_paint_of(gobj, desc, geometry);
55750
55798
  let style = {
55751
- fill: desc.color,
55752
- stroke: getStrokeColor(desc.color),
55753
- lineWidth: 1,
55799
+ fill: paint.fill,
55800
+ stroke: paint.stroke,
55801
+ lineWidth: paint.lineWidth,
55754
55802
  lineDash: [],
55755
55803
  halo: false,
55756
55804
  labelText: "",
55757
55805
  size: [...size],
55758
55806
  dx: -size[0] / 2,
55759
55807
  dy: -size[1] / 2,
55760
- innerHTML: build_chip_innerHTML(desc.color, priv.theme, record.icon, node_label(desc, record), record.id)
55808
+ innerHTML: build_chip_innerHTML(paint.fill, priv.theme, record.icon, node_label(desc, record), record.id)
55761
55809
  };
55762
55810
  dress_ports(gobj, style, ports, geometry, topic_defaults_of(gobj, desc.topic_name), PORT_R_PILL, true);
55763
55811
  return {
@@ -55768,7 +55816,7 @@ function pill_shape_of(gobj, desc, record, geometry) {
55768
55816
  function pill_innerHTML_of(gobj, nd, theme, highlight, selected, anchored) {
55769
55817
  let desc = nd.data.desc;
55770
55818
  let record = nd.data.record || {};
55771
- return build_chip_innerHTML(desc.color, theme, record.icon, node_label(desc, record), record.id, highlight, selected, anchored);
55819
+ return build_chip_innerHTML(node_fill_of(nd), theme, record.icon, node_label(desc, record), record.id, highlight, selected, anchored);
55772
55820
  }
55773
55821
  function node_figure_of(gobj, desc, geometry) {
55774
55822
  let shape = geometry ? geometry.node_shape : null;
@@ -55795,8 +55843,9 @@ function figure_shape_of(gobj, desc, record, geometry, flags) {
55795
55843
  let side = SHAPE_SIZE[tier] || SHAPE_SIZE.hierarchical;
55796
55844
  let labels = gobj_read_bool_attr(gobj, "node_labels");
55797
55845
  let figure = node_figure_of(gobj, desc, geometry || {});
55798
- let stroke = getStrokeColor(desc.color);
55799
- let line_width = 1.5;
55846
+ let paint = node_paint_of(gobj, desc, geometry);
55847
+ let stroke = paint.stroke;
55848
+ let line_width = Math.max(paint.lineWidth, 1.5);
55800
55849
  if (f.selected) {
55801
55850
  stroke = SELECT_RING;
55802
55851
  line_width = 3;
@@ -55814,7 +55863,7 @@ function figure_shape_of(gobj, desc, record, geometry, flags) {
55814
55863
  let style = {
55815
55864
  size: [side, side],
55816
55865
  radius: figure === "square" ? Math.round(side / 5) : 0,
55817
- fill: desc.color,
55866
+ fill: paint.fill,
55818
55867
  stroke,
55819
55868
  lineWidth: line_width,
55820
55869
  lineDash: dash,
@@ -58639,39 +58688,23 @@ function show_node_popover(gobj) {
58639
58688
  let rect = get_node_viewport_rect(gobj, node_id);
58640
58689
  if (!rect) return;
58641
58690
  const popover = create_popover_base(rect.right + floating_popover_dx(), rect.top + floating_icon_dy(), "g6-node-popover", "#d9d9d9", 180);
58642
- let node_graph_type = nodeData.data && nodeData.data.desc ? nodeData.data.desc.node_treedb_type : null;
58643
- let undo_node = () => {
58644
- let restoreStyle = {
58645
- fill: origFill,
58646
- stroke: origStroke,
58647
- lineWidth: origLW
58648
- };
58649
- if (node_graph_type === "hierarchical") {
58650
- let record = nodeData.data.record || {};
58651
- restoreStyle.innerHTML = build_node_innerHTML(origFill, priv.theme, record.icon, node_label(nodeData.data.desc, record), nodeData.data.desc.topic_name, false, record.id, false, false, false, pills_html_of(gobj, nodeData));
58652
- }
58691
+ let paint_node = (fill, stroke, lw) => {
58653
58692
  graph.updateNodeData([{
58654
58693
  id: node_id,
58655
- style: restoreStyle
58694
+ style: {
58695
+ fill,
58696
+ stroke,
58697
+ lineWidth: lw
58698
+ }
58656
58699
  }]);
58700
+ repaint_cards(gobj, /* @__PURE__ */ new Set([node_id]));
58657
58701
  graph.draw();
58658
58702
  };
58703
+ let undo_node = () => {
58704
+ paint_node(origFill, origStroke, origLW);
58705
+ };
58659
58706
  function preview_node() {
58660
- let fill = fillInput.value;
58661
- let updateStyle = {
58662
- fill,
58663
- stroke: strokeInput.value,
58664
- lineWidth: parseInt(lwInput.value) || 1
58665
- };
58666
- if (node_graph_type === "hierarchical") {
58667
- let record = nodeData.data.record || {};
58668
- updateStyle.innerHTML = build_node_innerHTML(fill, priv.theme, record.icon, node_label(nodeData.data.desc, record), nodeData.data.desc.topic_name, false, record.id, false, false, false, pills_html_of(gobj, nodeData));
58669
- }
58670
- graph.updateNodeData([{
58671
- id: node_id,
58672
- style: updateStyle
58673
- }]);
58674
- graph.draw();
58707
+ paint_node(fillInput.value, strokeInput.value, parseInt(lwInput.value) || 1);
58675
58708
  }
58676
58709
  create_form_label(popover, "fill color");
58677
58710
  let fillInput = create_form_color_input(popover, currentFill, preview_node);
@@ -58910,15 +58943,19 @@ function refresh_minimap(gobj) {
58910
58943
  * same three-way choice — it lived inline in the theme refresh and is
58911
58944
  * shared now. Returns null for a node that carries no desc.
58912
58945
  ************************************************************/
58946
+ function node_fill_of(nd) {
58947
+ return nd && nd.style && nd.style.fill || nd.data.desc.color;
58948
+ }
58913
58949
  function node_innerHTML_of(nd, theme, highlight, selected, anchored, pills_html) {
58914
58950
  if (!nd || !nd.data || !nd.data.desc) return null;
58915
58951
  let desc = nd.data.desc;
58916
58952
  let record = nd.data.record || {};
58917
58953
  let label = node_label(desc, record);
58954
+ let fill = node_fill_of(nd);
58918
58955
  switch (desc.node_treedb_type) {
58919
- case "child": return build_chip_innerHTML(desc.color, theme, record.icon, label, record.id, highlight, selected, anchored);
58920
- case "extended": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, true, record.id, highlight, selected, anchored, pills_html);
58921
- case "hierarchical": return build_node_innerHTML(desc.color, theme, record.icon, label, desc.topic_name, false, record.id, highlight, selected, anchored, pills_html);
58956
+ case "child": return build_chip_innerHTML(fill, theme, record.icon, label, record.id, highlight, selected, anchored);
58957
+ case "extended": return build_node_innerHTML(fill, theme, record.icon, label, desc.topic_name, true, record.id, highlight, selected, anchored, pills_html);
58958
+ case "hierarchical": return build_node_innerHTML(fill, theme, record.icon, label, desc.topic_name, false, record.id, highlight, selected, anchored, pills_html);
58922
58959
  }
58923
58960
  return null;
58924
58961
  }
@@ -59473,15 +59510,19 @@ function apply_node_properties(gobj, node_id, fill, stroke, lineWidth, scope, sh
59473
59510
  if (!nodeData || !nodeData.data) return;
59474
59511
  let source_topic = nodeData.data.desc ? nodeData.data.desc.topic_name : null;
59475
59512
  let updates = [];
59513
+ let repaint = /* @__PURE__ */ new Set();
59476
59514
  const nodes = graph.getData().nodes;
59477
59515
  let figure = shape && str_in_list(NODE_SHAPES, shape) ? shape : "";
59478
59516
  let reshaped = [];
59479
- if (figure && scope !== "this") {
59517
+ if (scope !== "this") {
59480
59518
  let topics = scope === "same_topic" ? [source_topic] : Object.keys(priv.descs || {});
59481
59519
  for (let topic_name of topics) {
59520
+ let desc = priv.descs[topic_name];
59521
+ if (!desc) continue;
59482
59522
  if (!is_object(priv._graph_properties[topic_name])) priv._graph_properties[topic_name] = {};
59483
59523
  let defaults = priv._graph_properties[topic_name].defaults || {};
59484
- defaults.node_shape = figure;
59524
+ if (figure) defaults.node_shape = figure;
59525
+ paint_into(defaults, desc, fill, stroke, lineWidth);
59485
59526
  priv._graph_properties[topic_name].defaults = defaults;
59486
59527
  }
59487
59528
  }
@@ -59490,27 +59531,27 @@ function apply_node_properties(gobj, node_id, fill, stroke, lineWidth, scope, sh
59490
59531
  if (!nd || !nd.data || !nd.data.desc) continue;
59491
59532
  if (scope === "this" && nodes[i].id !== node_id) continue;
59492
59533
  if (scope === "same_topic" && nd.data.desc.topic_name !== source_topic) continue;
59534
+ let entry = node_props_entry(gobj, nd);
59493
59535
  if (figure) {
59494
- node_props_entry(gobj, nd).node_shape = figure;
59536
+ entry.node_shape = figure;
59495
59537
  if (node_mode_of(gobj, nodes[i].id) === "shape") reshaped.push(nodes[i].id);
59496
59538
  }
59539
+ paint_into(entry, nd.data.desc, fill, stroke, lineWidth);
59497
59540
  let updateStyle = {
59498
59541
  fill,
59499
59542
  stroke,
59500
59543
  lineWidth
59501
59544
  };
59502
- if (nd.data.desc.node_treedb_type === "hierarchical") {
59503
- let record = nd.data.record || {};
59504
- updateStyle.innerHTML = build_node_innerHTML(fill, priv.theme, record.icon, node_label(nd.data.desc, record), nd.data.desc.topic_name, false, record.id, false, false, false, pills_html_of(gobj, nd));
59505
- }
59506
59545
  updates.push({
59507
59546
  id: nodes[i].id,
59508
59547
  style: updateStyle
59509
59548
  });
59549
+ repaint.add(nodes[i].id);
59510
59550
  }
59511
59551
  if (updates.length > 0) {
59512
59552
  graph.updateNodeData(updates);
59513
59553
  if (reshaped.length) reshape_nodes(gobj, reshaped);
59554
+ repaint_cards(gobj, repaint);
59514
59555
  graph.draw().then(() => {
59515
59556
  mark_graph_dirty(gobj);
59516
59557
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yuneta/gobj-ui",
3
- "version": "7.23.84",
3
+ "version": "7.23.85",
4
4
  "type": "module",
5
5
  "main": "dist/gobj-ui.cjs.js",
6
6
  "module": "dist/gobj-ui.es.js",
@@ -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
  });