@decidables/accumulable-elements 0.3.4 → 0.3.6

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/CHANGELOG.md CHANGED
@@ -3,6 +3,23 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [0.3.6](https://github.com/decidables/decidables/compare/@decidables/accumulable-elements@0.3.5...@decidables/accumulable-elements@0.3.6) (2025-11-30)
7
+
8
+ **Note:** Version bump only for package @decidables/accumulable-elements
9
+
10
+
11
+
12
+
13
+
14
+ ## [0.3.5](https://github.com/decidables/decidables/compare/@decidables/accumulable-elements@0.3.4...@decidables/accumulable-elements@0.3.5) (2025-11-21)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * **accumulable-elements:** in `ddm-model`, improved arrows on dimension lines for measures ([a3b8ac4](https://github.com/decidables/decidables/commit/a3b8ac462223960c9caa72a4c1f399e008b1c439))
20
+
21
+
22
+
6
23
  ## [0.3.4](https://github.com/decidables/decidables/compare/@decidables/accumulable-elements@0.3.3...@decidables/accumulable-elements@0.3.4) (2025-11-13)
7
24
 
8
25
 
package/README.md CHANGED
@@ -1079,7 +1079,7 @@ export default class AccumulableElementSomething extends AccumulableElement {
1079
1079
  - `gulpfile.js` (Tasks for *gulp*)
1080
1080
  - `package.json` (Package config for *yarn* and *npm*)
1081
1081
  - `README.md` (This file)
1082
- - `rollup-stats.html` (Report on js bundle composition and size) **\[autogenerated\]**
1082
+ - `rollup-stats.auto.html` (Report on js bundle composition and size) **\[autogenerated\]**
1083
1083
 
1084
1084
  ## [License](https://github.com/decidables/decidables/blob/main/LICENSE.md)
1085
1085
 
@@ -8105,8 +8105,13 @@ class DDMModel extends DecidablesMixinResizeable(AccumulableElement) {
8105
8105
  }
8106
8106
  }
8107
8107
 
8108
- .measure {
8109
- stroke-width: 2;
8108
+ .measure .line.short {
8109
+ stroke-width: 0;
8110
+ }
8111
+
8112
+ .measure .markers {
8113
+ fill: none;
8114
+ stroke-width: 0;
8110
8115
  }
8111
8116
 
8112
8117
  .measure .label {
@@ -8124,12 +8129,6 @@ class DDMModel extends DecidablesMixinResizeable(AccumulableElement) {
8124
8129
  text-anchor: end;
8125
8130
  }
8126
8131
 
8127
- /* Hack to avoid lack of context-stroke and context-fill in Safari */
8128
- .measure-arrow.a {
8129
- fill: var(---color-a);
8130
- stroke: var(---color-a);
8131
- }
8132
-
8133
8132
  .measure.z .line {
8134
8133
  stroke: var(---color-z);
8135
8134
  }
@@ -8141,12 +8140,6 @@ class DDMModel extends DecidablesMixinResizeable(AccumulableElement) {
8141
8140
  text-anchor: start;
8142
8141
  }
8143
8142
 
8144
- /* Hack to avoid lack of context-stroke and context-fill in Safari */
8145
- .measure-arrow.z {
8146
- fill: var(---color-z);
8147
- stroke: var(---color-z);
8148
- }
8149
-
8150
8143
  .measure.v .line {
8151
8144
  stroke: var(---color-v);
8152
8145
  }
@@ -8156,12 +8149,6 @@ class DDMModel extends DecidablesMixinResizeable(AccumulableElement) {
8156
8149
  text-anchor: start;
8157
8150
  }
8158
8151
 
8159
- /* Hack to avoid lack of context-stroke and context-fill in Safari */
8160
- .measure-arrow.v {
8161
- fill: var(---color-v);
8162
- stroke: var(---color-v);
8163
- }
8164
-
8165
8152
  .measure.t0 .line {
8166
8153
  stroke: var(---color-t0);
8167
8154
  }
@@ -8171,6 +8158,37 @@ class DDMModel extends DecidablesMixinResizeable(AccumulableElement) {
8171
8158
  text-anchor: middle;
8172
8159
  }
8173
8160
 
8161
+ .measure-arrow {
8162
+ fill: context-stroke;
8163
+ stroke: context-stroke;
8164
+ }
8165
+
8166
+ .measure-arrow .arrow {
8167
+ stroke-width: 1;
8168
+ }
8169
+
8170
+ .measure-arrow.capped .cap {
8171
+ stroke-width: 2;
8172
+ }
8173
+
8174
+ /* Hack to avoid lack of context-stroke and context-fill in Safari */
8175
+ .measure-arrow.a {
8176
+ fill: var(---color-a);
8177
+ stroke: var(---color-a);
8178
+ }
8179
+
8180
+ /* Hack to avoid lack of context-stroke and context-fill in Safari */
8181
+ .measure-arrow.z {
8182
+ fill: var(---color-z);
8183
+ stroke: var(---color-z);
8184
+ }
8185
+
8186
+ /* Hack to avoid lack of context-stroke and context-fill in Safari */
8187
+ .measure-arrow.v {
8188
+ fill: var(---color-v);
8189
+ stroke: var(---color-v);
8190
+ }
8191
+
8174
8192
  /* Hack to avoid lack of context-stroke and context-fill in Safari */
8175
8193
  .measure-arrow.t0 {
8176
8194
  fill: var(---color-t0);
@@ -8437,19 +8455,19 @@ class DDMModel extends DecidablesMixinResizeable(AccumulableElement) {
8437
8455
  // Arrowhead marker for measures
8438
8456
  const measureArrow = parameter => {
8439
8457
  /* Hack to avoid lack of context-stroke and context-fill in Safari */
8440
- svgDefs.append('marker').attr('id', `measure-arrow-${parameter}`).attr('class', `measure-arrow ${parameter}`).attr('orient', 'auto-start-reverse').attr('markerUnits', 'userSpaceOnUse').attr('viewBox', '-5 -5 10 10').attr('refX', '2').attr('refY', '0').attr('markerWidth', '10').attr('markerHeight', '10').append('path').attr('stroke', 'context-stroke').attr('fill', 'context-stroke').attr('d', 'M -3 -3 l 6 3 l -6 3 z');
8458
+ svgDefs.append('marker').attr('id', `measure-arrow-${parameter}`).attr('class', `measure-arrow ${parameter}`).attr('orient', 'auto-start-reverse').attr('markerUnits', 'userSpaceOnUse').attr('viewBox', '-10 -6 12 12').attr('refX', '0').attr('refY', '0').attr('markerWidth', '12').attr('markerHeight', '12').append('path').attr('class', 'arrow').attr('d', 'M -7 -3 l 6 3 l -6 3 z');
8441
8459
  };
8442
- const measureArrowCap = parameter => {
8460
+ const measureCappedArrow = parameter => {
8443
8461
  /* Hack to avoid lack of context-stroke and context-fill in Safari */
8444
- const marker = svgDefs.append('marker').attr('id', `measure-arrow-cap-${parameter}`).attr('class', `measure-arrow cap ${parameter}`).attr('orient', 'auto-start-reverse').attr('markerUnits', 'userSpaceOnUse').attr('viewBox', '-5 -5 10 10').attr('refX', '2').attr('refY', '0').attr('markerWidth', '10').attr('markerHeight', '10');
8445
- marker.append('path').attr('stroke', 'context-stroke').attr('fill', 'context-stroke').attr('d', 'M -3 -3 l 6 3 l -6 3 z');
8446
- marker.append('path').attr('stroke', 'context-stroke').attr('fill', 'context-stroke').attr('stroke-width', '2').attr('d', 'M 4 -4 l 0 8');
8462
+ const marker = svgDefs.append('marker').attr('id', `measure-capped-arrow-${parameter}`).attr('class', `measure-arrow capped ${parameter}`).attr('orient', 'auto-start-reverse').attr('markerUnits', 'userSpaceOnUse').attr('viewBox', '-10 -6 12 12').attr('refX', '0').attr('refY', '0').attr('markerWidth', '12').attr('markerHeight', '12');
8463
+ marker.append('path').attr('class', 'arrow').attr('d', 'M -7 -3 l 6 3 l -6 3 z');
8464
+ marker.append('path').attr('class', 'cap').attr('d', 'M 0 -4 l 0 8');
8447
8465
  };
8448
8466
  measureArrow('a');
8449
8467
  measureArrow('z');
8450
- measureArrowCap('v');
8468
+ measureCappedArrow('v');
8451
8469
  measureArrow('t0');
8452
- measureArrowCap('t0');
8470
+ measureCappedArrow('t0');
8453
8471
  // Flat markers for SDs
8454
8472
  const sdCap = outcome => {
8455
8473
  /* Hack to avoid lack of context-stroke and context-fill in Safari */
@@ -9045,20 +9063,27 @@ class DDMModel extends DecidablesMixinResizeable(AccumulableElement) {
9045
9063
  // EXIT
9046
9064
  t0zUpdate.exit().remove();
9047
9065
 
9066
+ // Measures
9067
+ const markerCorrection = 2;
9068
+
9048
9069
  // a Measure
9049
9070
  // DATA-JOIN
9050
9071
  const aUpdate = evidenceOverlayerMerge.selectAll('.measure.a').data(this.measures ? [this.a] : []);
9051
9072
  // ENTER
9052
9073
  const aEnter = aUpdate.enter().append('g').classed('measure a', true);
9053
- aEnter.append('line').classed('line', true)
9074
+ aEnter.append('line').classed('line', true);
9075
+ aEnter.append('line').classed('markers', true)
9054
9076
  /* Hack to avoid lack of context-stroke and context-fill in Safari */.attr('marker-start', 'url(#measure-arrow-a)').attr('marker-end', 'url(#measure-arrow-a)');
9055
9077
  const aLabel = aEnter.append('text').classed('label', true);
9056
9078
  aLabel.append('tspan').classed('a math-var', true).text('a');
9057
9079
  aLabel.append('tspan').classed('equals', true).text(' = ');
9058
9080
  aLabel.append('tspan').classed('value', true);
9059
9081
  // MERGE
9082
+ const aLength = Math.abs(evidenceScale(this.bounds.upper) - evidenceScale(this.bounds.lower));
9083
+ const aShort = aLength <= markerCorrection * 2;
9060
9084
  const aMerge = aEnter.merge(aUpdate);
9061
- aMerge.select('.line').transition().duration(this.drag ? 0 : transitionDuration).ease(cubicOut).attr('x1', timeScale(this.scale.time.max) - this.rem * 0.75).attr('y1', evidenceScale(this.bounds.upper) + 2).attr('x2', timeScale(this.scale.time.max) - this.rem * 0.75).attr('y2', evidenceScale(this.bounds.lower) - 2);
9085
+ aMerge.select('.line').classed('short', aShort).transition().duration(this.drag ? 0 : transitionDuration).ease(cubicOut).attr('x1', timeScale(this.scale.time.max) - this.rem * 0.75).attr('y1', evidenceScale(this.bounds.upper) + markerCorrection).attr('x2', timeScale(this.scale.time.max) - this.rem * 0.75).attr('y2', evidenceScale(this.bounds.lower) - markerCorrection);
9086
+ aMerge.select('.markers').transition().duration(this.drag ? 0 : transitionDuration).ease(cubicOut).attr('x1', timeScale(this.scale.time.max) - this.rem * 0.75).attr('y1', evidenceScale(this.bounds.upper)).attr('x2', timeScale(this.scale.time.max) - this.rem * 0.75).attr('y2', evidenceScale(this.bounds.lower));
9062
9087
  const aLabelMerge = aMerge.select('.label').transition().duration(this.drag ? 0 : transitionDuration).ease(cubicOut).attr('x', timeScale(this.scale.time.max)).attr('y', evidenceScale(this.bounds.upper) - this.rem * 0.25);
9063
9088
  aLabelMerge.select('.value').text(format('.2f')(this.a));
9064
9089
  // EXIT
@@ -9069,15 +9094,19 @@ class DDMModel extends DecidablesMixinResizeable(AccumulableElement) {
9069
9094
  const zUpdate = evidenceOverlayerMerge.selectAll('.measure.z').data(this.measures ? [this.z] : []);
9070
9095
  // ENTER
9071
9096
  const zEnter = zUpdate.enter().append('g').classed('measure z', true);
9072
- zEnter.append('line').classed('line', true)
9097
+ zEnter.append('line').classed('line', true);
9098
+ zEnter.append('line').classed('markers', true)
9073
9099
  /* Hack to avoid lack of context-stroke and context-fill in Safari */.attr('marker-start', 'url(#measure-arrow-z)').attr('marker-end', 'url(#measure-arrow-z)');
9074
9100
  const zLabel = zEnter.append('text').classed('label', true);
9075
9101
  zLabel.append('tspan').classed('z math-var', true).text('z');
9076
9102
  zLabel.append('tspan').classed('equals', true).text(' = ');
9077
9103
  zLabel.append('tspan').classed('value', true);
9078
9104
  // MERGE
9105
+ const zLength = Math.abs(evidenceScale(this.startingPoint) - evidenceScale(this.bounds.lower));
9106
+ const zShort = zLength <= markerCorrection * 2;
9079
9107
  const zMerge = zEnter.merge(zUpdate);
9080
- zMerge.select('.line').transition().duration(this.drag ? 0 : transitionDuration).ease(cubicOut).attr('x1', timeScale(this.scale.time.min) + this.rem * 0.75).attr('y1', evidenceScale(this.startingPoint) + 2).attr('x2', timeScale(this.scale.time.min) + this.rem * 0.75).attr('y2', evidenceScale(this.bounds.lower) - 2);
9108
+ zMerge.select('.line').classed('short', zShort).transition().duration(this.drag ? 0 : transitionDuration).ease(cubicOut).attr('x1', timeScale(this.scale.time.min) + this.rem * 0.75).attr('y1', evidenceScale(this.startingPoint) + markerCorrection).attr('x2', timeScale(this.scale.time.min) + this.rem * 0.75).attr('y2', evidenceScale(this.bounds.lower) - markerCorrection);
9109
+ zMerge.select('.markers').transition().duration(this.drag ? 0 : transitionDuration).ease(cubicOut).attr('x1', timeScale(this.scale.time.min) + this.rem * 0.75).attr('y1', evidenceScale(this.startingPoint)).attr('x2', timeScale(this.scale.time.min) + this.rem * 0.75).attr('y2', evidenceScale(this.bounds.lower));
9081
9110
  const zLabelMerge = zMerge.select('.label').transition().duration(this.drag ? 0 : transitionDuration).ease(cubicOut).attr('x', timeScale(this.scale.time.min)).attr('y', evidenceScale(this.bounds.lower) + this.rem * 0.125);
9082
9111
  zLabelMerge.select('.value').text(format('.0%')(this.z));
9083
9112
  // EXIT
@@ -9088,22 +9117,37 @@ class DDMModel extends DecidablesMixinResizeable(AccumulableElement) {
9088
9117
  const vUpdate = evidenceOverlayerMerge.selectAll('.measure.v').data(this.measures ? [this.v] : []);
9089
9118
  // ENTER
9090
9119
  const vEnter = vUpdate.enter().append('g').classed('measure v', true);
9091
- vEnter.append('path').classed('line', true)
9092
- /* Hack to avoid lack of context-stroke and context-fill in Safari */.attr('marker-start', 'url(#measure-arrow-cap-v)').attr('marker-end', 'url(#measure-arrow-cap-v)');
9120
+ vEnter.append('path').classed('line', true);
9121
+ vEnter.append('path').classed('markers', true)
9122
+ /* Hack to avoid lack of context-stroke and context-fill in Safari */.attr('marker-start', 'url(#measure-capped-arrow-v)').attr('marker-end', 'url(#measure-capped-arrow-v)');
9093
9123
  const vLabel = vEnter.append('text').classed('label', true);
9094
9124
  vLabel.append('tspan').classed('v math-var', true).text('v');
9095
9125
  vLabel.append('tspan').classed('equals', true).text(' = ');
9096
9126
  vLabel.append('tspan').classed('value', true);
9097
9127
  // MERGE
9128
+ // Full path
9098
9129
  const driftHypotenuse = timeScale(200) - timeScale(0) + this.rem * 0.75;
9099
- const driftCorrection = 2 / driftHypotenuse;
9100
- const driftAngle = Math.atan(this.v / 1000 * scaleRatio) - driftCorrection;
9130
+ const driftAngle = Math.atan(this.v / 1000 * scaleRatio);
9101
9131
  const driftX = Math.cos(driftAngle) * driftHypotenuse;
9102
9132
  const driftY = Math.sin(driftAngle) * driftHypotenuse;
9133
+ // Corrected path
9134
+ const driftCorrection = markerCorrection / driftHypotenuse;
9135
+ const driftAngleCorrected = Math.atan(this.v / 1000 * scaleRatio) - driftCorrection;
9136
+ const driftStartX = Math.cos(driftCorrection) * driftHypotenuse;
9137
+ const driftStartY = Math.sin(driftCorrection) * driftHypotenuse;
9138
+ const driftEndX = Math.cos(driftAngleCorrected) * driftHypotenuse;
9139
+ const driftEndY = Math.sin(driftAngleCorrected) * driftHypotenuse;
9140
+ // Short path?
9141
+ const vLength = driftAngleCorrected * driftHypotenuse;
9142
+ const vShort = vLength <= markerCorrection * 2;
9103
9143
  const vMerge = vEnter.merge(vUpdate);
9104
- vMerge.select('.line').transition().duration(this.drag ? 0 : transitionDuration).ease(cubicOut).attr('d', `
9105
- M ${timeScale(this.t0 + 200) + this.rem * 0.75}, ${evidenceScale(this.startingPoint) - 2}
9106
- A ${timeScale(200) - timeScale(0)} ${timeScale(200) - timeScale(0)} 0 0 0 ${timeScale(this.t0) + driftX} ${evidenceScale(this.startingPoint) - driftY}
9144
+ vMerge.select('.line').classed('short', vShort).transition().duration(this.drag ? 0 : transitionDuration).ease(cubicOut).attr('d', `
9145
+ M ${timeScale(this.t0) + driftStartX}, ${evidenceScale(this.startingPoint) - driftStartY}
9146
+ A ${timeScale(200) - timeScale(0) + this.rem * 0.75} ${timeScale(200) - timeScale(0) + this.rem * 0.75} 0 0 0 ${timeScale(this.t0) + driftEndX} ${evidenceScale(this.startingPoint) - driftEndY}
9147
+ `);
9148
+ vMerge.select('.markers').transition().duration(this.drag ? 0 : transitionDuration).ease(cubicOut).attr('d', `
9149
+ M ${timeScale(this.t0 + 200) + this.rem * 0.75}, ${evidenceScale(this.startingPoint)}
9150
+ A ${timeScale(200) - timeScale(0) + this.rem * 0.75} ${timeScale(200) - timeScale(0) + this.rem * 0.75} 0 0 0 ${timeScale(this.t0) + driftX} ${evidenceScale(this.startingPoint) - driftY}
9107
9151
  `);
9108
9152
  const vLabelMerge = vMerge.select('.label').transition().duration(this.drag ? 0 : transitionDuration).ease(cubicOut).attr('x', timeScale(this.t0 + 200) + this.rem * 0.5).attr('y', evidenceScale(this.bounds.upper) - this.rem * 0.25);
9109
9153
  vLabelMerge.select('.value').text(format('.2f')(this.v));
@@ -9115,15 +9159,19 @@ class DDMModel extends DecidablesMixinResizeable(AccumulableElement) {
9115
9159
  const t0Update = evidenceOverlayerMerge.selectAll('.measure.t0').data(this.measures ? [this.t0] : []);
9116
9160
  // ENTER
9117
9161
  const t0Enter = t0Update.enter().append('g').classed('measure t0', true);
9118
- t0Enter.append('line').classed('line', true)
9119
- /* Hack to avoid lack of context-stroke and context-fill in Safari */.attr('marker-start', 'url(#measure-arrow-t0)').attr('marker-end', 'url(#measure-arrow-cap-t0)');
9162
+ t0Enter.append('line').classed('line', true);
9163
+ t0Enter.append('line').classed('markers', true)
9164
+ /* Hack to avoid lack of context-stroke and context-fill in Safari */.attr('marker-start', 'url(#measure-arrow-t0)').attr('marker-end', 'url(#measure-capped-arrow-t0)');
9120
9165
  const t0Label = t0Enter.append('text').classed('label', true);
9121
9166
  t0Label.append('tspan').classed('t0 math-var', true).text('t₀');
9122
9167
  t0Label.append('tspan').classed('equals', true).text(' = ');
9123
9168
  t0Label.append('tspan').classed('value', true);
9124
9169
  // MERGE
9170
+ const t0Length = Math.abs(timeScale(0) - timeScale(this.t0));
9171
+ const t0Short = t0Length <= markerCorrection * 2;
9125
9172
  const t0Merge = t0Enter.merge(t0Update);
9126
- t0Merge.select('.line').transition().duration(this.drag ? 0 : transitionDuration).ease(cubicOut).attr('x1', timeScale(0) + 2).attr('y1', evidenceScale(this.startingPoint) - this.rem * 0.75).attr('x2', timeScale(this.t0) - 2).attr('y2', evidenceScale(this.startingPoint) - this.rem * 0.75);
9173
+ t0Merge.select('.line').classed('short', t0Short).transition().duration(this.drag ? 0 : transitionDuration).ease(cubicOut).attr('x1', timeScale(0) + markerCorrection).attr('y1', evidenceScale(this.startingPoint) - this.rem * 0.75).attr('x2', timeScale(this.t0) - markerCorrection).attr('y2', evidenceScale(this.startingPoint) - this.rem * 0.75);
9174
+ t0Merge.select('.markers').transition().duration(this.drag ? 0 : transitionDuration).ease(cubicOut).attr('x1', timeScale(0)).attr('y1', evidenceScale(this.startingPoint) - this.rem * 0.75).attr('x2', timeScale(this.t0)).attr('y2', evidenceScale(this.startingPoint) - this.rem * 0.75);
9127
9175
  const t0LabelMerge = t0Merge.select('.label').transition().duration(this.drag ? 0 : transitionDuration).ease(cubicOut).attr('x', timeScale(this.t0) + this.rem * 0.25).attr('y', evidenceScale(this.bounds.upper) - this.rem * 0.25);
9128
9176
  t0LabelMerge.select('.value').text(format('d')(this.t0));
9129
9177
  // EXIT