@decidables/discountable-elements 0.5.0 → 0.6.0

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.
@@ -13059,54 +13059,90 @@ class HTDCurves extends DecidablesMixinResizeable(DiscountableElement) {
13059
13059
  /* shape-rendering: crispEdges; */
13060
13060
  }
13061
13061
 
13062
- .curve {
13063
- fill: none;
13064
- stroke: var(---color-element-emphasis);
13065
- stroke-width: 2;
13062
+ .option .interactive {
13063
+ filter: url("#shadow-2");
13066
13064
  }
13067
13065
 
13068
- .curve.interactive {
13069
- cursor: nwse-resize;
13070
-
13071
- filter: url("#shadow-2");
13072
- outline: none;
13066
+ .option .interactive:hover {
13067
+ filter: url("#shadow-4");
13073
13068
  }
13074
13069
 
13075
- .curve.interactive:hover {
13070
+ .option .body.interactive:has(~ .point:hover) {
13076
13071
  filter: url("#shadow-4");
13077
13072
  }
13078
13073
 
13079
- .curve.interactive:active {
13074
+ .option .interactive:active {
13080
13075
  filter: url("#shadow-8");
13081
13076
  }
13082
13077
 
13083
- :host(.keyboard) .curve.interactive:focus {
13078
+ .option .body.interactive:has(~ .point:active) {
13084
13079
  filter: url("#shadow-8");
13085
13080
  }
13086
13081
 
13087
- .bar {
13088
- fill: none;
13089
- stroke: var(---color-element-emphasis);
13090
- stroke-width: 2;
13082
+ :host(.keyboard) .option .interactive:focus-within {
13083
+ filter: url("#shadow-8");
13091
13084
  }
13092
13085
 
13093
- .bar.interactive {
13094
- cursor: ew-resize;
13095
-
13096
- filter: url("#shadow-2");
13086
+ :host(.keyboard) .option .body.interactive:has(~ .point:focus-within) {
13087
+ filter: url("#shadow-8");
13088
+ }
13089
+
13090
+ .gradient.sooner stop {
13091
+ stop-color: var(---color-sooner);
13092
+ }
13093
+
13094
+ .gradient.later stop {
13095
+ stop-color: var(---color-later);
13096
+ }
13097
+
13098
+ .stop-0,
13099
+ .stop-before {
13100
+ stop-opacity: 0;
13101
+ }
13102
+
13103
+ .stop-after,
13104
+ .stop-100 {
13105
+ stop-opacity: 1;
13106
+ }
13107
+
13108
+ .fill {
13109
+ fill: var(---color-element-enabled);
13110
+ fill-opacity: 0.5;
13111
+ stroke: none;
13112
+ }
13113
+
13114
+ .interactive .fill {
13115
+ cursor: move;
13116
+
13097
13117
  outline: none;
13098
13118
  }
13099
13119
 
13100
- .bar.interactive:hover {
13101
- filter: url("#shadow-4");
13120
+ .sooner .fill {
13121
+ fill: var(---color-sooner);
13102
13122
  }
13103
13123
 
13104
- .bar.interactive:active {
13105
- filter: url("#shadow-8");
13124
+ .later .fill {
13125
+ fill: var(---color-later);
13106
13126
  }
13107
13127
 
13108
- :host(.keyboard) .bar.interactive:focus {
13109
- filter: url("#shadow-8");
13128
+ .trial.sooner .fill {
13129
+ fill: url("#sooner-gradient");
13130
+ }
13131
+
13132
+ .trial.later .fill {
13133
+ fill: url("#later-gradient");
13134
+ }
13135
+
13136
+ .bar {
13137
+ fill: none;
13138
+ stroke: var(---color-element-emphasis);
13139
+ stroke-width: 2;
13140
+ }
13141
+
13142
+ .interactive .bar {
13143
+ cursor: ew-resize;
13144
+
13145
+ outline: none;
13110
13146
  }
13111
13147
 
13112
13148
  .point .mark {
@@ -13124,38 +13160,22 @@ class HTDCurves extends DecidablesMixinResizeable(DiscountableElement) {
13124
13160
  fill: var(---color-text-inverse);
13125
13161
  }
13126
13162
 
13127
- .point.interactive {
13163
+ .point.interact {
13128
13164
  cursor: ns-resize;
13129
13165
 
13130
- filter: url("#shadow-2");
13131
13166
  outline: none;
13132
-
13133
- /* HACK: This gets Safari to correctly apply the filter! */
13134
- /* https://github.com/emilbjorklund/svg-weirdness/issues/27 */
13135
- stroke: #000000;
13136
- stroke-opacity: 0;
13137
- stroke-width: 0;
13138
13167
  }
13139
13168
 
13140
- .point.interactive:hover {
13141
- filter: url("#shadow-4");
13142
-
13143
- /* HACK: This gets Safari to correctly apply the filter! */
13144
- stroke: #ff0000;
13145
- }
13146
-
13147
- .point.interactive:active {
13148
- filter: url("#shadow-8");
13149
-
13150
- /* HACK: This gets Safari to correctly apply the filter! */
13151
- stroke: #00ff00;
13169
+ .curve {
13170
+ fill: none;
13171
+ stroke: var(---color-element-emphasis);
13172
+ stroke-width: 2;
13152
13173
  }
13153
13174
 
13154
- :host(.keyboard) .point.interactive:focus {
13155
- filter: url("#shadow-8");
13175
+ .curve.interactive {
13176
+ cursor: nwse-resize;
13156
13177
 
13157
- /* HACK: This gets Safari to correctly apply the filter! */
13158
- stroke: #0000ff;
13178
+ outline: none;
13159
13179
  }
13160
13180
 
13161
13181
  /* Make larger targets for touch users */
@@ -13232,6 +13252,18 @@ class HTDCurves extends DecidablesMixinResizeable(DiscountableElement) {
13232
13252
  // ENTER
13233
13253
  const svgEnter = svgUpdate.enter().append('svg').classed('main', true);
13234
13254
  svgEnter.html(DiscountableElement.svgDefs);
13255
+ // Gradients for fill animations
13256
+ const svgDefs = svgEnter.append('defs');
13257
+ const soonerGradient = svgDefs.append('linearGradient').classed('gradient sooner', true).attr('id', 'sooner-gradient');
13258
+ soonerGradient.append('stop').classed('stop-0', true).attr('offset', '0');
13259
+ soonerGradient.append('stop').classed('stop-before animation', true).attr('offset', '1');
13260
+ soonerGradient.append('stop').classed('stop-after animation', true).attr('offset', '1');
13261
+ soonerGradient.append('stop').classed('stop-100', true).attr('offset', '1');
13262
+ const laterGradient = svgDefs.append('linearGradient').classed('gradient later', true).attr('id', 'later-gradient');
13263
+ laterGradient.append('stop').classed('stop-0', true).attr('offset', '0');
13264
+ laterGradient.append('stop').classed('stop-before animation', true).attr('offset', '1');
13265
+ laterGradient.append('stop').classed('stop-after animation', true).attr('offset', '1');
13266
+ laterGradient.append('stop').classed('stop-100', true).attr('offset', '1');
13235
13267
  // MERGE
13236
13268
  const svgMerge = svgEnter.merge(svgUpdate).attr('viewBox', `0 0 ${elementWidth} ${elementHeight}`);
13237
13269
 
@@ -13308,42 +13340,39 @@ class HTDCurves extends DecidablesMixinResizeable(DiscountableElement) {
13308
13340
  return datum.name;
13309
13341
  });
13310
13342
  // ENTER
13311
- const optionEnter = optionUpdate.enter().append('g').classed('option', true);
13312
- // Curve
13313
- const curveEnter = optionEnter.append('g').classed('curve', true).attr('clip-path', 'url(#clip-htd-curves)');
13314
- curveEnter.append('path').classed('path', true).attr('d', datum => {
13315
- const curve = range$1(xScale(datum.d), xScale(0), -1).map(range => {
13316
- return {
13317
- d: xScale.invert(range),
13318
- v: HTDMath.adk2v(datum.a, datum.d - xScale.invert(range), this.k)
13319
- };
13320
- });
13321
- return line(curve);
13322
- }).attr('stroke-dasharray', (datum, index, nodes) => {
13343
+ const optionEnter = optionUpdate.enter().append('g').attr('class', datum => {
13344
+ const labelClass = datum.label === 's' ? 'sooner' : datum.label === 'l' ? 'later' : '';
13345
+ const trialClass = datum.trial ? 'trial' : '';
13346
+ return `option ${labelClass} ${trialClass}`;
13347
+ });
13348
+ // Body (Fill, Bar, Point)
13349
+ const bodyEnter = optionEnter.append('g').classed('body', true);
13350
+ // Fill
13351
+ const fillEnter = bodyEnter.append('g').classed('fill', true).attr('clip-path', 'url(#clip-htd-curves)').each(datum => {
13323
13352
  if (datum.trial) {
13324
- const length = nodes[index].getTotalLength();
13325
- return `0,${length}`;
13353
+ svgMerge.selectAll('.gradient .animation').attr('offset', 1);
13326
13354
  }
13327
- return 'none';
13328
13355
  });
13329
- curveEnter.append('path').classed('path touch', true).attr('d', datum => {
13356
+ fillEnter.append('path').classed('region', true).attr('d', datum => {
13330
13357
  const curve = range$1(xScale(datum.d), xScale(0), -1).map(range => {
13331
13358
  return {
13332
13359
  d: xScale.invert(range),
13333
13360
  v: HTDMath.adk2v(datum.a, datum.d - xScale.invert(range), this.k)
13334
13361
  };
13335
13362
  });
13336
- return line(curve);
13337
- }).attr('stroke-dasharray', (datum, index, nodes) => {
13338
- if (datum.trial) {
13339
- const length = nodes[index].getTotalLength();
13340
- return `0,${length}`;
13341
- }
13342
- return 'none';
13363
+ return line([...curve, {
13364
+ d: 0,
13365
+ v: 0
13366
+ }, {
13367
+ d: datum.d,
13368
+ v: 0
13369
+ }]);
13343
13370
  });
13344
13371
  // Bar
13345
- const barEnter = optionEnter.append('g').classed('bar', true);
13346
- barEnter.append('line').classed('line', true).attr('x1', datum => {
13372
+ const barEnter = bodyEnter.append('g').classed('bar', true);
13373
+ barEnter.append('line').classed('line', true);
13374
+ barEnter.append('line').classed('line touch', true);
13375
+ barEnter.selectAll('.line').attr('x1', datum => {
13347
13376
  return xScale(datum.d);
13348
13377
  }).attr('x2', datum => {
13349
13378
  return xScale(datum.d);
@@ -13356,12 +13385,21 @@ class HTDCurves extends DecidablesMixinResizeable(DiscountableElement) {
13356
13385
  }
13357
13386
  return 'none';
13358
13387
  });
13359
- barEnter.append('line').classed('line touch', true).attr('x1', datum => {
13360
- return xScale(datum.d);
13361
- }).attr('x2', datum => {
13362
- return xScale(datum.d);
13363
- }).attr('y1', yScale(0)).attr('y2', datum => {
13364
- return yScale(datum.a);
13388
+ // Point
13389
+ const pointEnter = bodyEnter.append('g').classed('point', true);
13390
+ pointEnter.append('circle').classed('mark touch', true);
13391
+ // Curve
13392
+ const curveEnter = optionEnter.append('g').classed('curve', true).attr('clip-path', 'url(#clip-htd-curves)');
13393
+ curveEnter.append('path').classed('path', true);
13394
+ curveEnter.append('path').classed('path touch', true);
13395
+ curveEnter.selectAll('.path').attr('d', datum => {
13396
+ const curve = range$1(xScale(datum.d), xScale(0), -1).map(range => {
13397
+ return {
13398
+ d: xScale.invert(range),
13399
+ v: HTDMath.adk2v(datum.a, datum.d - xScale.invert(range), this.k)
13400
+ };
13401
+ });
13402
+ return line(curve);
13365
13403
  }).attr('stroke-dasharray', (datum, index, nodes) => {
13366
13404
  if (datum.trial) {
13367
13405
  const length = nodes[index].getTotalLength();
@@ -13369,8 +13407,11 @@ class HTDCurves extends DecidablesMixinResizeable(DiscountableElement) {
13369
13407
  }
13370
13408
  return 'none';
13371
13409
  });
13372
- // Point
13373
- const pointEnter = optionEnter.append('g').classed('point', true).attr('transform', datum => {
13410
+ // Point (again)
13411
+ const topPointEnter = optionEnter.append('g').classed('point top-point', true);
13412
+ topPointEnter.append('circle').classed('mark touch', true);
13413
+ topPointEnter.append('text').classed('label', true);
13414
+ optionEnter.selectAll('.point').attr('transform', datum => {
13374
13415
  return `translate(${xScale(datum.d)}, ${yScale(datum.a)})`;
13375
13416
  }).attr('opacity', datum => {
13376
13417
  if (datum.trial) {
@@ -13378,33 +13419,37 @@ class HTDCurves extends DecidablesMixinResizeable(DiscountableElement) {
13378
13419
  }
13379
13420
  return 1;
13380
13421
  });
13381
- pointEnter.append('circle').classed('mark touch', true);
13382
- pointEnter.append('text').classed('label', true);
13422
+
13383
13423
  // MERGE
13384
13424
  const optionMerge = optionEnter.merge(optionUpdate);
13385
13425
 
13386
13426
  // Interactive options
13387
- // Curve
13388
- optionMerge.filter((datum, index, nodes) => {
13389
- return this.interactive && !select(nodes[index]).select('.curve').classed('interactive');
13390
- }).select('.curve').classed('interactive', true).attr('tabindex', 0)
13427
+ // Body (Fill, Bar, Point)
13428
+ const bodyMergeInteractive = optionMerge.filter((datum, index, nodes) => {
13429
+ return this.interactive && !datum.trial && !select(nodes[index]).select('.body').classed('interactive');
13430
+ }).select('.body');
13431
+ bodyMergeInteractive.classed('interactive', true);
13432
+ // Fill
13433
+ bodyMergeInteractive.select('.fill').attr('tabindex', 0)
13391
13434
  // Drag interaction
13392
- .call(drag().subject(event => {
13435
+ .call(drag().subject((event, datum) => {
13393
13436
  return {
13394
- x: event.x,
13395
- y: event.y
13437
+ x: xScale(datum.d),
13438
+ y: yScale(datum.a)
13396
13439
  };
13397
13440
  }).on('start', event => {
13398
13441
  const element = event.currentTarget;
13399
13442
  select(element).classed('dragging', true);
13400
13443
  }).on('drag', (event, datum) => {
13401
13444
  this.drag = true;
13402
- const dragD = datum.d - xScale.invert(event.x);
13403
- const d = dragD < 0 ? 0 : dragD > datum.d ? datum.d : dragD;
13404
- const dragV = yScale.invert(event.y);
13405
- const v = dragV <= 0 ? 0.001 : dragV > datum.a ? datum.a : dragV;
13406
- const k = HTDMath.adv2k(datum.a, d, v);
13407
- this.k = k < HTDMath.k.MIN ? HTDMath.k.MIN : k > HTDMath.k.MAX ? HTDMath.k.MAX : k;
13445
+ const d = xScale.invert(event.x);
13446
+ const a = yScale.invert(event.y);
13447
+ datum.d = d < this.scale.time.min ? this.scale.time.min : d > this.scale.time.max ? this.scale.time.max : this.scale.time.round(d);
13448
+ datum.a = a < this.scale.value.min ? this.scale.value.min : a > this.scale.value.max ? this.scale.value.max : this.scale.value.round(a);
13449
+ if (datum.name === 'default') {
13450
+ this.d = datum.d;
13451
+ this.a = datum.a;
13452
+ }
13408
13453
  this.alignState();
13409
13454
  this.requestUpdate();
13410
13455
  this.dispatchEvent(new CustomEvent('htd-curves-change', {
@@ -13423,24 +13468,33 @@ class HTDCurves extends DecidablesMixinResizeable(DiscountableElement) {
13423
13468
  }))
13424
13469
  // Keyboard interaction
13425
13470
  .on('keydown', (event, datum) => {
13426
- if (['ArrowUp', 'ArrowDown', 'ArrowRight', 'ArrowLeft'].includes(event.key)) {
13427
- let {
13428
- k
13429
- } = this;
13471
+ if (['ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight'].includes(event.key)) {
13472
+ let keyA = datum.a;
13473
+ let keyD = datum.d;
13430
13474
  switch (event.key) {
13431
13475
  case 'ArrowUp':
13432
- case 'ArrowLeft':
13433
- k *= event.shiftKey ? 0.95 : 0.85;
13476
+ keyA += event.shiftKey ? 1 : 5;
13434
13477
  break;
13435
13478
  case 'ArrowDown':
13479
+ keyA -= event.shiftKey ? 1 : 5;
13480
+ break;
13436
13481
  case 'ArrowRight':
13437
- k *= event.shiftKey ? 1 / 0.95 : 1 / 0.85;
13482
+ keyD += event.shiftKey ? 1 : 5;
13483
+ break;
13484
+ case 'ArrowLeft':
13485
+ keyD -= event.shiftKey ? 1 : 5;
13438
13486
  break;
13439
13487
  // no-op
13440
13488
  }
13441
- k = k < HTDMath.k.MIN ? HTDMath.k.MIN : k > HTDMath.k.MAX ? HTDMath.k.MAX : k;
13442
- if (k !== this.k) {
13443
- this.k = k;
13489
+ keyD = keyD < this.scale.time.min ? this.scale.time.min : keyD > this.scale.time.max ? this.scale.time.max : keyD;
13490
+ keyA = keyA < this.scale.value.min ? this.scale.value.min : keyA > this.scale.value.max ? this.scale.value.max : keyA;
13491
+ if (keyD !== datum.d || keyA !== datum.a) {
13492
+ datum.d = keyD;
13493
+ datum.a = keyA;
13494
+ if (datum.name === 'default') {
13495
+ this.d = datum.d;
13496
+ this.a = datum.a;
13497
+ }
13444
13498
  this.alignState();
13445
13499
  this.requestUpdate();
13446
13500
  this.dispatchEvent(new CustomEvent('htd-curves-change', {
@@ -13458,9 +13512,7 @@ class HTDCurves extends DecidablesMixinResizeable(DiscountableElement) {
13458
13512
  }
13459
13513
  });
13460
13514
  // Bar
13461
- optionMerge.filter((datum, index, nodes) => {
13462
- return this.interactive && !datum.trial && !select(nodes[index]).select('.bar').classed('interactive');
13463
- }).select('.bar').classed('interactive', true).attr('tabindex', 0)
13515
+ bodyMergeInteractive.select('.bar')
13464
13516
  // Drag interaction
13465
13517
  .call(drag().subject((event, datum) => {
13466
13518
  return {
@@ -13530,8 +13582,8 @@ class HTDCurves extends DecidablesMixinResizeable(DiscountableElement) {
13530
13582
  });
13531
13583
  // Point
13532
13584
  optionMerge.filter((datum, index, nodes) => {
13533
- return this.interactive && !datum.trial && !select(nodes[index]).select('.point').classed('interactive');
13534
- }).select('.point').classed('interactive', true).attr('tabindex', 0)
13585
+ return this.interactive && !datum.trial && !select(nodes[index]).select('.top-point').classed('interact');
13586
+ }).select('.top-point').classed('interact', true)
13535
13587
  // Drag interaction
13536
13588
  .call(drag().subject((event, datum) => {
13537
13589
  return {
@@ -13599,26 +13651,125 @@ class HTDCurves extends DecidablesMixinResizeable(DiscountableElement) {
13599
13651
  event.preventDefault();
13600
13652
  }
13601
13653
  });
13654
+ // Curve
13655
+ optionMerge.filter((datum, index, nodes) => {
13656
+ return this.interactive && !select(nodes[index]).select('.curve').classed('interactive');
13657
+ }).select('.curve').classed('interactive', true).attr('tabindex', 0)
13658
+ // Drag interaction
13659
+ .call(drag().subject(event => {
13660
+ return {
13661
+ x: event.x,
13662
+ y: event.y
13663
+ };
13664
+ }).on('start', event => {
13665
+ const element = event.currentTarget;
13666
+ select(element).classed('dragging', true);
13667
+ }).on('drag', (event, datum) => {
13668
+ this.drag = true;
13669
+ const dragD = datum.d - xScale.invert(event.x);
13670
+ const d = dragD < 0 ? 0 : dragD > datum.d ? datum.d : dragD;
13671
+ const dragV = yScale.invert(event.y);
13672
+ const v = dragV <= 0 ? 0.001 : dragV > datum.a ? datum.a : dragV;
13673
+ const k = HTDMath.adv2k(datum.a, d, v);
13674
+ this.k = k < HTDMath.k.MIN ? HTDMath.k.MIN : k > HTDMath.k.MAX ? HTDMath.k.MAX : k;
13675
+ this.alignState();
13676
+ this.requestUpdate();
13677
+ this.dispatchEvent(new CustomEvent('htd-curves-change', {
13678
+ detail: {
13679
+ name: datum.name,
13680
+ a: datum.a,
13681
+ d: datum.d,
13682
+ k: this.k,
13683
+ label: datum.label
13684
+ },
13685
+ bubbles: true
13686
+ }));
13687
+ }).on('end', event => {
13688
+ const element = event.currentTarget;
13689
+ select(element).classed('dragging', false);
13690
+ }))
13691
+ // Keyboard interaction
13692
+ .on('keydown', (event, datum) => {
13693
+ if (['ArrowUp', 'ArrowDown', 'ArrowRight', 'ArrowLeft'].includes(event.key)) {
13694
+ let {
13695
+ k
13696
+ } = this;
13697
+ switch (event.key) {
13698
+ case 'ArrowUp':
13699
+ case 'ArrowLeft':
13700
+ k *= event.shiftKey ? 0.95 : 0.85;
13701
+ break;
13702
+ case 'ArrowDown':
13703
+ case 'ArrowRight':
13704
+ k *= event.shiftKey ? 1 / 0.95 : 1 / 0.85;
13705
+ break;
13706
+ // no-op
13707
+ }
13708
+ k = k < HTDMath.k.MIN ? HTDMath.k.MIN : k > HTDMath.k.MAX ? HTDMath.k.MAX : k;
13709
+ if (k !== this.k) {
13710
+ this.k = k;
13711
+ this.alignState();
13712
+ this.requestUpdate();
13713
+ this.dispatchEvent(new CustomEvent('htd-curves-change', {
13714
+ detail: {
13715
+ name: datum.name,
13716
+ a: datum.a,
13717
+ d: datum.d,
13718
+ k: this.k,
13719
+ label: datum.label
13720
+ },
13721
+ bubbles: true
13722
+ }));
13723
+ }
13724
+ event.preventDefault();
13725
+ }
13726
+ });
13602
13727
 
13603
13728
  // Non-interactive options
13729
+ // Body (Fill, Bar, Point)
13730
+ const bodyMergeNoninteractive = optionMerge.filter((datum, index, nodes) => {
13731
+ return (!this.interactive || datum.trial) && select(nodes[index]).select('.body').classed('interactive');
13732
+ });
13733
+ bodyMergeNoninteractive.classed('interactive', false);
13734
+ // Fill
13735
+ bodyMergeNoninteractive.select('.fill').attr('tabindex', null).on('drag', null).on('keydown', null);
13736
+ // Bar
13737
+ bodyMergeNoninteractive.select('.bar').on('drag', null).on('keydown', null);
13738
+ // Point
13739
+ optionMerge.filter((datum, index, nodes) => {
13740
+ return (!this.interactive || datum.trial) && select(nodes[index]).select('.top-point').classed('interact');
13741
+ }).select('.top-point').classed('interact', false).on('drag', null).on('keydown', null);
13604
13742
  // Curve
13605
13743
  optionMerge.filter((datum, index, nodes) => {
13606
13744
  return !this.interactive && select(nodes[index]).select('.curve').classed('interactive');
13607
13745
  }).select('.curve').classed('interactive', false).attr('tabindex', null).on('drag', null).on('keydown', null);
13608
- // Bar
13609
- optionMerge.filter((datum, index, nodes) => {
13610
- return (!this.interactive || datum.trial) && select(nodes[index]).select('.bar').classed('interactive');
13611
- }).select('.bar').classed('interactive', false).attr('tabindex', null).on('drag', null).on('keydown', null);
13612
- // Point
13613
- optionMerge.filter((datum, index, nodes) => {
13614
- return (!this.interactive || datum.trial) && select(nodes[index]).select('.point').classed('interactive');
13615
- }).select('.point').classed('interactive', false).attr('tabindex', null).on('drag', null).on('keydown', null);
13616
13746
 
13617
13747
  // Trial Animation
13748
+ // Fill
13749
+ optionMerge.filter(datum => {
13750
+ return datum.new;
13751
+ }).each(() => {
13752
+ svgMerge.selectAll('.gradient .animation').transition().duration(transitionDuration).delay(transitionDuration + transitionDuration / 10).ease(linear$1).attrTween('offset', () => {
13753
+ return interpolate$1(1, 0);
13754
+ });
13755
+ });
13756
+ // Bar
13757
+ optionMerge.filter(datum => {
13758
+ return datum.new;
13759
+ }).selectAll('.bar .line').transition().duration(transitionDuration).ease(linear$1).attrTween('stroke-dasharray', (datum, index, nodes) => {
13760
+ const length = nodes[index].getTotalLength();
13761
+ return interpolate$1(`0,${length}`, `${length},${length}`);
13762
+ });
13763
+ // Point
13764
+ optionMerge.filter(datum => {
13765
+ return datum.new;
13766
+ }).selectAll('.point').transition().duration(transitionDuration / 10).delay(transitionDuration).ease(linear$1).attrTween('opacity', () => {
13767
+ return interpolate$1(0, 1);
13768
+ });
13618
13769
  // Curve
13619
13770
  optionMerge.filter(datum => {
13620
13771
  return datum.new;
13621
- }).select('.curve .path').transition().duration(transitionDuration).delay(transitionDuration + transitionDuration / 10).ease(linear$1).attrTween('stroke-dasharray', (datum, index, nodes) => {
13772
+ }).selectAll('.curve .path').transition().duration(transitionDuration).delay(transitionDuration + transitionDuration / 10).ease(linear$1).attrTween('stroke-dasharray', (datum, index, nodes) => {
13622
13773
  const length = nodes[index].getTotalLength();
13623
13774
  return interpolate$1(`0,${length}`, `${length},${0}`);
13624
13775
  }).on('end', datum => {
@@ -13635,50 +13786,16 @@ class HTDCurves extends DecidablesMixinResizeable(DiscountableElement) {
13635
13786
  bubbles: true
13636
13787
  }));
13637
13788
  });
13638
- optionMerge.filter(datum => {
13639
- return datum.new;
13640
- }).select('.curve .path.touch').transition().duration(transitionDuration).delay(transitionDuration + transitionDuration / 10).ease(linear$1).attrTween('stroke-dasharray', (datum, index, nodes) => {
13641
- const length = nodes[index].getTotalLength();
13642
- return interpolate$1(`0,${length}`, `${length},${0}`);
13643
- });
13644
- // Bar
13645
- optionMerge.filter(datum => {
13646
- return datum.new;
13647
- }).select('.bar .line').transition().duration(transitionDuration).ease(linear$1).attrTween('stroke-dasharray', (datum, index, nodes) => {
13648
- const length = nodes[index].getTotalLength();
13649
- return interpolate$1(`0,${length}`, `${length},${length}`);
13650
- });
13651
- optionMerge.filter(datum => {
13652
- return datum.new;
13653
- }).select('.bar .line.touch').transition().duration(transitionDuration).ease(linear$1).attrTween('stroke-dasharray', (datum, index, nodes) => {
13654
- const length = nodes[index].getTotalLength();
13655
- return interpolate$1(`0,${length}`, `${length},${length}`);
13656
- });
13657
- // Point
13658
- optionMerge.filter(datum => {
13659
- return datum.new;
13660
- }).select('.point').transition().duration(transitionDuration / 10).delay(transitionDuration).ease(linear$1).attrTween('opacity', () => {
13661
- return interpolate$1(0, 1);
13662
- });
13663
13789
 
13664
13790
  // All options
13665
- optionUpdate.select('.curve .path').transition().duration(this.drag ? 0 : this.firstUpdate ? transitionDuration * 2 : transitionDuration).ease(cubicOut).attrTween('d', (datum, index, elements) => {
13666
- const element = elements[index];
13667
- const interpolateA = interpolate$1(element.a !== undefined ? element.a : datum.a, datum.a);
13668
- const interpolateD = interpolate$1(element.d !== undefined ? element.d : datum.d, datum.d);
13669
- return time => {
13670
- element.a = interpolateA(time);
13671
- element.d = interpolateD(time);
13672
- const curve = range$1(xScale(element.d), xScale(0), -1).map(range => {
13673
- return {
13674
- d: xScale.invert(range),
13675
- v: HTDMath.adk2v(element.a, element.d - xScale.invert(range), this.k)
13676
- };
13677
- });
13678
- return line(curve);
13679
- };
13680
- });
13681
- optionUpdate.select('.curve .path.touch').transition().duration(this.drag ? 0 : this.firstUpdate ? transitionDuration * 2 : transitionDuration).ease(cubicOut).attrTween('d', (datum, index, elements) => {
13791
+ optionMerge.filter(datum => {
13792
+ return datum.label === 's';
13793
+ }).raise();
13794
+ optionMerge.filter(datum => {
13795
+ return datum.label === 'l';
13796
+ }).lower();
13797
+ // Fill
13798
+ optionUpdate.select('.fill .region').transition().duration(this.drag ? 0 : this.firstUpdate ? transitionDuration * 2 : transitionDuration).ease(cubicOut).attrTween('d', (datum, index, elements) => {
13682
13799
  const element = elements[index];
13683
13800
  const interpolateA = interpolate$1(element.a !== undefined ? element.a : datum.a, datum.a);
13684
13801
  const interpolateD = interpolate$1(element.d !== undefined ? element.d : datum.d, datum.d);
@@ -13691,10 +13808,17 @@ class HTDCurves extends DecidablesMixinResizeable(DiscountableElement) {
13691
13808
  v: HTDMath.adk2v(element.a, element.d - xScale.invert(range), this.k)
13692
13809
  };
13693
13810
  });
13694
- return line(curve);
13811
+ return line([...curve, {
13812
+ d: 0,
13813
+ v: 0
13814
+ }, {
13815
+ d: element.d,
13816
+ v: 0
13817
+ }]);
13695
13818
  };
13696
13819
  });
13697
- optionUpdate.select('.bar .line').transition().duration(this.drag ? 0 : this.firstUpdate ? transitionDuration * 2 : transitionDuration).ease(cubicOut).attrTween('x1', (datum, index, elements) => {
13820
+ // Bar
13821
+ optionUpdate.selectAll('.bar .line').transition().duration(this.drag ? 0 : this.firstUpdate ? transitionDuration * 2 : transitionDuration).ease(cubicOut).attrTween('x1', (datum, index, elements) => {
13698
13822
  const element = elements[index];
13699
13823
  const interpolateD = interpolate$1(element.d !== undefined ? element.d : datum.d, datum.d);
13700
13824
  return time => {
@@ -13716,41 +13840,37 @@ class HTDCurves extends DecidablesMixinResizeable(DiscountableElement) {
13716
13840
  return `${yScale(element.a)}`;
13717
13841
  };
13718
13842
  });
13719
- optionUpdate.select('.bar .line.touch').transition().duration(this.drag ? 0 : this.firstUpdate ? transitionDuration * 2 : transitionDuration).ease(cubicOut).attrTween('x1', (datum, index, elements) => {
13720
- const element = elements[index];
13721
- const interpolateD = interpolate$1(element.d !== undefined ? element.d : datum.d, datum.d);
13722
- return time => {
13723
- element.d = interpolateD(time);
13724
- return `${xScale(element.d)}`;
13725
- };
13726
- }).attrTween('x2', (datum, index, elements) => {
13843
+ // Point
13844
+ optionUpdate.selectAll('.point').transition().duration(this.drag ? 0 : this.firstUpdate ? transitionDuration * 2 : transitionDuration).ease(cubicOut).attrTween('transform', (datum, index, elements) => {
13727
13845
  const element = elements[index];
13728
13846
  const interpolateD = interpolate$1(element.d !== undefined ? element.d : datum.d, datum.d);
13729
- return time => {
13730
- element.d = interpolateD(time);
13731
- return `${xScale(element.d)}`;
13732
- };
13733
- }).attrTween('y2', (datum, index, elements) => {
13734
- const element = elements[index];
13735
13847
  const interpolateA = interpolate$1(element.a !== undefined ? element.a : datum.a, datum.a);
13736
13848
  return time => {
13849
+ element.d = interpolateD(time);
13737
13850
  element.a = interpolateA(time);
13738
- return `${yScale(element.a)}`;
13851
+ return `translate(${xScale(element.d)}, ${yScale(element.a)})`;
13739
13852
  };
13740
13853
  });
13741
- optionUpdate.select('.point').transition().duration(this.drag ? 0 : this.firstUpdate ? transitionDuration * 2 : transitionDuration).ease(cubicOut).attrTween('transform', (datum, index, elements) => {
13854
+ optionMerge.select('.point .label').text(datum => {
13855
+ return datum.label;
13856
+ });
13857
+ // Curve
13858
+ optionUpdate.selectAll('.curve .path').transition().duration(this.drag ? 0 : this.firstUpdate ? transitionDuration * 2 : transitionDuration).ease(cubicOut).attrTween('d', (datum, index, elements) => {
13742
13859
  const element = elements[index];
13743
- const interpolateD = interpolate$1(element.d !== undefined ? element.d : datum.d, datum.d);
13744
13860
  const interpolateA = interpolate$1(element.a !== undefined ? element.a : datum.a, datum.a);
13861
+ const interpolateD = interpolate$1(element.d !== undefined ? element.d : datum.d, datum.d);
13745
13862
  return time => {
13746
- element.d = interpolateD(time);
13747
13863
  element.a = interpolateA(time);
13748
- return `translate(${xScale(element.d)}, ${yScale(element.a)})`;
13864
+ element.d = interpolateD(time);
13865
+ const curve = range$1(xScale(element.d), xScale(0), -1).map(range => {
13866
+ return {
13867
+ d: xScale.invert(range),
13868
+ v: HTDMath.adk2v(element.a, element.d - xScale.invert(range), this.k)
13869
+ };
13870
+ });
13871
+ return line(curve);
13749
13872
  };
13750
13873
  });
13751
- optionMerge.select('.point .label').text(datum => {
13752
- return datum.label;
13753
- });
13754
13874
  // EXIT
13755
13875
  // NOTE: Could add a transition here
13756
13876
  optionUpdate.exit().remove();