@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.
- package/CHANGELOG.md +17 -0
- package/lib/discountableElements.esm.js +308 -188
- package/lib/discountableElements.esm.js.map +1 -1
- package/lib/discountableElements.esm.min.js +75 -55
- package/lib/discountableElements.esm.min.js.map +1 -1
- package/lib/discountableElements.umd.js +308 -188
- package/lib/discountableElements.umd.js.map +1 -1
- package/lib/discountableElements.umd.min.js +76 -56
- package/lib/discountableElements.umd.min.js.map +1 -1
- package/package.json +4 -4
- package/src/colors.yml +2 -2
- package/src/components/htd-curves.js +398 -267
|
@@ -13059,54 +13059,90 @@ class HTDCurves extends DecidablesMixinResizeable(DiscountableElement) {
|
|
|
13059
13059
|
/* shape-rendering: crispEdges; */
|
|
13060
13060
|
}
|
|
13061
13061
|
|
|
13062
|
-
.
|
|
13063
|
-
|
|
13064
|
-
stroke: var(---color-element-emphasis);
|
|
13065
|
-
stroke-width: 2;
|
|
13062
|
+
.option .interactive {
|
|
13063
|
+
filter: url("#shadow-2");
|
|
13066
13064
|
}
|
|
13067
13065
|
|
|
13068
|
-
.
|
|
13069
|
-
|
|
13070
|
-
|
|
13071
|
-
filter: url("#shadow-2");
|
|
13072
|
-
outline: none;
|
|
13066
|
+
.option .interactive:hover {
|
|
13067
|
+
filter: url("#shadow-4");
|
|
13073
13068
|
}
|
|
13074
13069
|
|
|
13075
|
-
.
|
|
13070
|
+
.option .body.interactive:has(~ .point:hover) {
|
|
13076
13071
|
filter: url("#shadow-4");
|
|
13077
13072
|
}
|
|
13078
13073
|
|
|
13079
|
-
.
|
|
13074
|
+
.option .interactive:active {
|
|
13080
13075
|
filter: url("#shadow-8");
|
|
13081
13076
|
}
|
|
13082
13077
|
|
|
13083
|
-
|
|
13078
|
+
.option .body.interactive:has(~ .point:active) {
|
|
13084
13079
|
filter: url("#shadow-8");
|
|
13085
13080
|
}
|
|
13086
13081
|
|
|
13087
|
-
.
|
|
13088
|
-
|
|
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
|
-
.
|
|
13094
|
-
|
|
13095
|
-
|
|
13096
|
-
|
|
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
|
-
.
|
|
13101
|
-
|
|
13120
|
+
.sooner .fill {
|
|
13121
|
+
fill: var(---color-sooner);
|
|
13102
13122
|
}
|
|
13103
13123
|
|
|
13104
|
-
.
|
|
13105
|
-
|
|
13124
|
+
.later .fill {
|
|
13125
|
+
fill: var(---color-later);
|
|
13106
13126
|
}
|
|
13107
13127
|
|
|
13108
|
-
|
|
13109
|
-
|
|
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.
|
|
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
|
-
.
|
|
13141
|
-
|
|
13142
|
-
|
|
13143
|
-
|
|
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
|
-
|
|
13155
|
-
|
|
13175
|
+
.curve.interactive {
|
|
13176
|
+
cursor: nwse-resize;
|
|
13156
13177
|
|
|
13157
|
-
|
|
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').
|
|
13312
|
-
|
|
13313
|
-
|
|
13314
|
-
|
|
13315
|
-
|
|
13316
|
-
|
|
13317
|
-
|
|
13318
|
-
|
|
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
|
-
|
|
13325
|
-
return `0,${length}`;
|
|
13353
|
+
svgMerge.selectAll('.gradient .animation').attr('offset', 1);
|
|
13326
13354
|
}
|
|
13327
|
-
return 'none';
|
|
13328
13355
|
});
|
|
13329
|
-
|
|
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
|
-
|
|
13338
|
-
|
|
13339
|
-
|
|
13340
|
-
|
|
13341
|
-
|
|
13342
|
-
|
|
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 =
|
|
13346
|
-
barEnter.append('line').classed('line', true)
|
|
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
|
-
|
|
13360
|
-
|
|
13361
|
-
|
|
13362
|
-
|
|
13363
|
-
|
|
13364
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
//
|
|
13388
|
-
optionMerge.filter((datum, index, nodes) => {
|
|
13389
|
-
return this.interactive && !select(nodes[index]).select('.
|
|
13390
|
-
}).select('.
|
|
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:
|
|
13395
|
-
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
|
|
13403
|
-
const
|
|
13404
|
-
|
|
13405
|
-
|
|
13406
|
-
|
|
13407
|
-
|
|
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', '
|
|
13427
|
-
let
|
|
13428
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
13442
|
-
|
|
13443
|
-
|
|
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
|
-
|
|
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('
|
|
13534
|
-
}).select('.point').classed('
|
|
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
|
-
}).
|
|
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
|
-
|
|
13666
|
-
|
|
13667
|
-
|
|
13668
|
-
|
|
13669
|
-
return
|
|
13670
|
-
|
|
13671
|
-
|
|
13672
|
-
|
|
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
|
-
|
|
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
|
-
|
|
13720
|
-
|
|
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
|
|
13851
|
+
return `translate(${xScale(element.d)}, ${yScale(element.a)})`;
|
|
13739
13852
|
};
|
|
13740
13853
|
});
|
|
13741
|
-
|
|
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
|
-
|
|
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();
|