@decidables/discountable-elements 0.3.3 → 0.3.4
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 +8 -0
- package/lib/discountableElements.esm.js +107 -83
- package/lib/discountableElements.esm.js.map +1 -1
- package/lib/discountableElements.esm.min.js +28 -28
- package/lib/discountableElements.esm.min.js.map +1 -1
- package/lib/discountableElements.umd.js +107 -83
- package/lib/discountableElements.umd.js.map +1 -1
- package/lib/discountableElements.umd.min.js +28 -28
- package/lib/discountableElements.umd.min.js.map +1 -1
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,14 @@
|
|
|
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.4](https://github.com/decidables/decidables/compare/@decidables/discountable-elements@0.3.3...@decidables/discountable-elements@0.3.4) (2024-01-09)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @decidables/discountable-elements
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
6
14
|
## [0.3.3](https://github.com/decidables/decidables/compare/@decidables/discountable-elements@0.3.2...@decidables/discountable-elements@0.3.3) (2023-12-31)
|
|
7
15
|
|
|
8
16
|
**Note:** Version bump only for package @decidables/discountable-elements
|
|
@@ -732,7 +732,6 @@ function* numbers(values, valueof) {
|
|
|
732
732
|
const ascendingBisect = bisector(ascending$1);
|
|
733
733
|
const bisectRight = ascendingBisect.right;
|
|
734
734
|
bisector(number$4).center;
|
|
735
|
-
var bisect = bisectRight;
|
|
736
735
|
|
|
737
736
|
function count(values, valueof) {
|
|
738
737
|
let count = 0;
|
|
@@ -6049,7 +6048,6 @@ function areaPoint(x, y) {
|
|
|
6049
6048
|
function areaRingEnd() {
|
|
6050
6049
|
areaPoint(x00$2, y00$2);
|
|
6051
6050
|
}
|
|
6052
|
-
var pathArea = areaStream;
|
|
6053
6051
|
|
|
6054
6052
|
var x0$2 = Infinity,
|
|
6055
6053
|
y0$2 = x0$2,
|
|
@@ -6073,7 +6071,6 @@ function boundsPoint(x, y) {
|
|
|
6073
6071
|
if (y < y0$2) y0$2 = y;
|
|
6074
6072
|
if (y > y1) y1 = y;
|
|
6075
6073
|
}
|
|
6076
|
-
var boundsStream$1 = boundsStream;
|
|
6077
6074
|
|
|
6078
6075
|
// TODO Enforce positive area for exterior, negative area for interior?
|
|
6079
6076
|
|
|
@@ -6156,7 +6153,6 @@ function centroidPointRing(x, y) {
|
|
|
6156
6153
|
Z2 += z * 3;
|
|
6157
6154
|
centroidPoint(x0$1 = x, y0$1 = y);
|
|
6158
6155
|
}
|
|
6159
|
-
var pathCentroid = centroidStream;
|
|
6160
6156
|
|
|
6161
6157
|
function PathContext(context) {
|
|
6162
6158
|
this._context = context;
|
|
@@ -6239,7 +6235,6 @@ function lengthPoint(x, y) {
|
|
|
6239
6235
|
lengthSum.add(sqrt$1(x0 * x0 + y0 * y0));
|
|
6240
6236
|
x0 = x, y0 = y;
|
|
6241
6237
|
}
|
|
6242
|
-
var pathMeasure = lengthStream;
|
|
6243
6238
|
|
|
6244
6239
|
// Simple caching for constant-radius points.
|
|
6245
6240
|
let cacheDigits, cacheAppend, cacheRadius, cacheCircle;
|
|
@@ -6341,20 +6336,20 @@ function geoPath (projection, context) {
|
|
|
6341
6336
|
return contextStream.result();
|
|
6342
6337
|
}
|
|
6343
6338
|
path.area = function (object) {
|
|
6344
|
-
geoStream(object, projectionStream(
|
|
6345
|
-
return
|
|
6339
|
+
geoStream(object, projectionStream(areaStream));
|
|
6340
|
+
return areaStream.result();
|
|
6346
6341
|
};
|
|
6347
6342
|
path.measure = function (object) {
|
|
6348
|
-
geoStream(object, projectionStream(
|
|
6349
|
-
return
|
|
6343
|
+
geoStream(object, projectionStream(lengthStream));
|
|
6344
|
+
return lengthStream.result();
|
|
6350
6345
|
};
|
|
6351
6346
|
path.bounds = function (object) {
|
|
6352
|
-
geoStream(object, projectionStream(boundsStream
|
|
6353
|
-
return boundsStream
|
|
6347
|
+
geoStream(object, projectionStream(boundsStream));
|
|
6348
|
+
return boundsStream.result();
|
|
6354
6349
|
};
|
|
6355
6350
|
path.centroid = function (object) {
|
|
6356
|
-
geoStream(object, projectionStream(
|
|
6357
|
-
return
|
|
6351
|
+
geoStream(object, projectionStream(centroidStream));
|
|
6352
|
+
return centroidStream.result();
|
|
6358
6353
|
};
|
|
6359
6354
|
path.projection = function (_) {
|
|
6360
6355
|
if (!arguments.length) return projection;
|
|
@@ -6425,8 +6420,8 @@ function fit(projection, fitBounds, object) {
|
|
|
6425
6420
|
var clip = projection.clipExtent && projection.clipExtent();
|
|
6426
6421
|
projection.scale(150).translate([0, 0]);
|
|
6427
6422
|
if (clip != null) projection.clipExtent(null);
|
|
6428
|
-
geoStream(object, projection.stream(boundsStream
|
|
6429
|
-
fitBounds(boundsStream
|
|
6423
|
+
geoStream(object, projection.stream(boundsStream));
|
|
6424
|
+
fitBounds(boundsStream.result());
|
|
6430
6425
|
if (clip != null) projection.clipExtent(clip);
|
|
6431
6426
|
return projection;
|
|
6432
6427
|
}
|
|
@@ -7298,7 +7293,7 @@ function polymap(domain, range, interpolate) {
|
|
|
7298
7293
|
r[i] = interpolate(range[i], range[i + 1]);
|
|
7299
7294
|
}
|
|
7300
7295
|
return function (x) {
|
|
7301
|
-
var i =
|
|
7296
|
+
var i = bisectRight(domain, x, 1, j) - 1;
|
|
7302
7297
|
return r[i](d[i](x));
|
|
7303
7298
|
};
|
|
7304
7299
|
}
|
|
@@ -7656,7 +7651,7 @@ function quantile() {
|
|
|
7656
7651
|
return scale;
|
|
7657
7652
|
}
|
|
7658
7653
|
function scale(x) {
|
|
7659
|
-
return x == null || isNaN(x = +x) ? unknown : range[
|
|
7654
|
+
return x == null || isNaN(x = +x) ? unknown : range[bisectRight(thresholds, x)];
|
|
7660
7655
|
}
|
|
7661
7656
|
scale.invertExtent = function (y) {
|
|
7662
7657
|
var i = range.indexOf(y);
|
|
@@ -7690,7 +7685,7 @@ function threshold() {
|
|
|
7690
7685
|
unknown,
|
|
7691
7686
|
n = 1;
|
|
7692
7687
|
function scale(x) {
|
|
7693
|
-
return x != null && x <= x ? range[
|
|
7688
|
+
return x != null && x <= x ? range[bisectRight(domain, x, 0, n)] : unknown;
|
|
7694
7689
|
}
|
|
7695
7690
|
scale.domain = function (_) {
|
|
7696
7691
|
return arguments.length ? (domain = Array.from(_), n = Math.min(domain.length, range.length - 1), scale) : domain.slice();
|
|
@@ -13616,17 +13611,19 @@ for (const [name, interval] of utcIntervals) {
|
|
|
13616
13611
|
interval[intervalDuration] = durations.get(name);
|
|
13617
13612
|
interval[intervalType] = "utc";
|
|
13618
13613
|
}
|
|
13614
|
+
const utcFormatIntervals = [["year", utcYear, "utc"], ["month", utcMonth, "utc"], ["day", unixDay, "utc", 6 * durationMonth], ["hour", utcHour, "utc", 3 * durationDay], ["minute", utcMinute, "utc", 6 * durationHour], ["second", second$1, "utc", 30 * durationMinute]];
|
|
13615
|
+
const timeFormatIntervals = [["year", timeYear, "time"], ["month", timeMonth, "time"], ["day", timeDay, "time", 6 * durationMonth], ["hour", timeHour, "time", 3 * durationDay], ["minute", timeMinute, "time", 6 * durationHour], ["second", second$1, "time", 30 * durationMinute]];
|
|
13619
13616
|
|
|
13620
13617
|
// An interleaved array of UTC and local time intervals, in descending order
|
|
13621
13618
|
// from largest to smallest, used to determine the most specific standard time
|
|
13622
13619
|
// format for a given array of dates. This is a subset of the tick intervals
|
|
13623
13620
|
// listed above; we only need the breakpoints where the format changes.
|
|
13624
|
-
const formatIntervals = [[
|
|
13621
|
+
const formatIntervals = [utcFormatIntervals[0], timeFormatIntervals[0], utcFormatIntervals[1], timeFormatIntervals[1], utcFormatIntervals[2], timeFormatIntervals[2],
|
|
13625
13622
|
// Below day, local time typically has an hourly offset from UTC and hence the
|
|
13626
13623
|
// two are aligned and indistinguishable; therefore, we only consider UTC, and
|
|
13627
13624
|
// we don’t consider these if the domain only has a single value.
|
|
13628
|
-
|
|
13629
|
-
function
|
|
13625
|
+
...utcFormatIntervals.slice(3)];
|
|
13626
|
+
function parseTimeInterval(input) {
|
|
13630
13627
|
let name = `${input}`.toLowerCase();
|
|
13631
13628
|
if (name.endsWith("s")) name = name.slice(0, -1); // drop plural
|
|
13632
13629
|
let period = 1;
|
|
@@ -13645,22 +13642,26 @@ function parseInterval(input, intervals, type) {
|
|
|
13645
13642
|
period *= 6;
|
|
13646
13643
|
break;
|
|
13647
13644
|
}
|
|
13648
|
-
let interval =
|
|
13645
|
+
let interval = utcIntervals.get(name);
|
|
13649
13646
|
if (!interval) throw new Error(`unknown interval: ${input}`);
|
|
13647
|
+
if (period > 1 && !interval.every) throw new Error(`non-periodic interval: ${name}`);
|
|
13648
|
+
return [name, period];
|
|
13649
|
+
}
|
|
13650
|
+
function maybeTimeInterval(input) {
|
|
13651
|
+
return asInterval(parseTimeInterval(input), "time");
|
|
13652
|
+
}
|
|
13653
|
+
function maybeUtcInterval(input) {
|
|
13654
|
+
return asInterval(parseTimeInterval(input), "utc");
|
|
13655
|
+
}
|
|
13656
|
+
function asInterval([name, period], type) {
|
|
13657
|
+
let interval = (type === "time" ? timeIntervals : utcIntervals).get(name);
|
|
13650
13658
|
if (period > 1) {
|
|
13651
|
-
if (!interval.every) throw new Error(`non-periodic interval: ${name}`);
|
|
13652
13659
|
interval = interval.every(period);
|
|
13653
13660
|
interval[intervalDuration] = durations.get(name) * period;
|
|
13654
13661
|
interval[intervalType] = type;
|
|
13655
13662
|
}
|
|
13656
13663
|
return interval;
|
|
13657
13664
|
}
|
|
13658
|
-
function maybeTimeInterval(interval) {
|
|
13659
|
-
return parseInterval(interval, timeIntervals, "time");
|
|
13660
|
-
}
|
|
13661
|
-
function maybeUtcInterval(interval) {
|
|
13662
|
-
return parseInterval(interval, utcIntervals, "utc");
|
|
13663
|
-
}
|
|
13664
13665
|
|
|
13665
13666
|
// If the given interval is a standard time interval, we may be able to promote
|
|
13666
13667
|
// it a larger aligned time interval, rather than showing every nth tick.
|
|
@@ -13702,17 +13703,20 @@ function getTimeTemplate(anchor) {
|
|
|
13702
13703
|
return anchor === "left" || anchor === "right" ? (f1, f2) => `\n${f1}\n${f2}` // extra newline to keep f1 centered
|
|
13703
13704
|
: anchor === "top" ? (f1, f2) => `${f2}\n${f1}` : (f1, f2) => `${f1}\n${f2}`;
|
|
13704
13705
|
}
|
|
13706
|
+
function getFormatIntervals(type) {
|
|
13707
|
+
return type === "time" ? timeFormatIntervals : type === "utc" ? utcFormatIntervals : formatIntervals;
|
|
13708
|
+
}
|
|
13705
13709
|
|
|
13706
13710
|
// Given an array of dates, returns the largest compatible standard time
|
|
13707
13711
|
// interval. If no standard interval is compatible (other than milliseconds,
|
|
13708
13712
|
// which is universally compatible), returns undefined.
|
|
13709
|
-
function inferTimeFormat(dates, anchor) {
|
|
13713
|
+
function inferTimeFormat(type, dates, anchor) {
|
|
13710
13714
|
const step = max(pairs(dates, (a, b) => Math.abs(b - a))); // maybe undefined!
|
|
13711
13715
|
if (step < 1000) return formatTimeInterval("millisecond", "utc", anchor);
|
|
13712
|
-
for (const [name, interval,
|
|
13716
|
+
for (const [name, interval, intervalType, maxStep] of getFormatIntervals(type)) {
|
|
13713
13717
|
if (step > maxStep) break; // e.g., 52 weeks
|
|
13714
13718
|
if (name === "hour" && !step) break; // e.g., domain with a single date
|
|
13715
|
-
if (dates.every(d => interval.floor(d) >= d)) return formatTimeInterval(name,
|
|
13719
|
+
if (dates.every(d => interval.floor(d) >= d)) return formatTimeInterval(name, intervalType, anchor);
|
|
13716
13720
|
}
|
|
13717
13721
|
}
|
|
13718
13722
|
function formatConditional(format1, format2, template) {
|
|
@@ -15634,7 +15638,9 @@ function getGeometryChannels(channel) {
|
|
|
15634
15638
|
return [x, y];
|
|
15635
15639
|
}
|
|
15636
15640
|
|
|
15637
|
-
|
|
15641
|
+
// TODO https://github.com/d3/d3-scale-chromatic/pull/51
|
|
15642
|
+
const schemeObservable10 = ["#4269d0", "#efb118", "#ff725c", "#6cc5b0", "#3ca951", "#ff8ab7", "#a463f2", "#97bbf5", "#9c6b4e", "#9498a0"];
|
|
15643
|
+
const categoricalSchemes = new Map([["accent", schemeAccent], ["category10", schemeCategory10], ["dark2", schemeDark2], ["observable10", schemeObservable10], ["paired", schemePaired], ["pastel1", schemePastel1], ["pastel2", schemePastel2], ["set1", schemeSet1], ["set2", schemeSet2], ["set3", schemeSet3], ["tableau10", schemeTableau10]]);
|
|
15638
15644
|
function isCategoricalScheme(scheme) {
|
|
15639
15645
|
return scheme != null && categoricalSchemes.has(`${scheme}`.toLowerCase());
|
|
15640
15646
|
}
|
|
@@ -16217,7 +16223,7 @@ function createScaleOrdinal(key, channels, {
|
|
|
16217
16223
|
if (range !== undefined) scheme = undefined; // Don’t re-apply scheme.
|
|
16218
16224
|
}
|
|
16219
16225
|
if (scheme === undefined && range === undefined) {
|
|
16220
|
-
scheme = type === "ordinal" ? "turbo" : "
|
|
16226
|
+
scheme = type === "ordinal" ? "turbo" : "observable10";
|
|
16221
16227
|
}
|
|
16222
16228
|
if (scheme !== undefined) {
|
|
16223
16229
|
if (range !== undefined) {
|
|
@@ -16296,8 +16302,7 @@ function inferHint(channels, key) {
|
|
|
16296
16302
|
} of channels) {
|
|
16297
16303
|
const candidate = hint?.[key];
|
|
16298
16304
|
if (candidate === undefined) continue; // no hint here
|
|
16299
|
-
if (value === undefined) value = candidate;
|
|
16300
|
-
// first hint
|
|
16305
|
+
if (value === undefined) value = candidate; // first hint
|
|
16301
16306
|
else if (value !== candidate) return; // inconsistent hint
|
|
16302
16307
|
}
|
|
16303
16308
|
return value;
|
|
@@ -16437,6 +16442,13 @@ function inferScaleLabel(channels = [], scale) {
|
|
|
16437
16442
|
};
|
|
16438
16443
|
}
|
|
16439
16444
|
|
|
16445
|
+
// Determines whether the scale points in the “positive” (right or down) or
|
|
16446
|
+
// “negative” (left or up) direction; if the scale order cannot be determined,
|
|
16447
|
+
// returns NaN; used to assign an appropriate label arrow.
|
|
16448
|
+
function inferScaleOrder(scale) {
|
|
16449
|
+
return Math.sign(orderof(scale.domain())) * Math.sign(orderof(scale.range()));
|
|
16450
|
+
}
|
|
16451
|
+
|
|
16440
16452
|
// Returns the dimensions of the outer frame; this is subdivided into facets
|
|
16441
16453
|
// with the margins of each facet collapsing into the outer margins.
|
|
16442
16454
|
function outerDimensions(dimensions) {
|
|
@@ -16661,6 +16673,9 @@ function createScale(key, channels = [], options = {}) {
|
|
|
16661
16673
|
function formatScaleType(type) {
|
|
16662
16674
|
return typeof type === "symbol" ? type.description : type;
|
|
16663
16675
|
}
|
|
16676
|
+
function maybeScaleType(type) {
|
|
16677
|
+
return typeof type === "string" ? `${type}`.toLowerCase() : type;
|
|
16678
|
+
}
|
|
16664
16679
|
|
|
16665
16680
|
// A special type symbol when the x and y scales are replaced with a projection.
|
|
16666
16681
|
const typeProjection = {
|
|
@@ -16674,6 +16689,8 @@ function inferScaleType(key, channels, {
|
|
|
16674
16689
|
pivot,
|
|
16675
16690
|
projection
|
|
16676
16691
|
}) {
|
|
16692
|
+
type = maybeScaleType(type);
|
|
16693
|
+
|
|
16677
16694
|
// The facet scales are always band scales; this cannot be changed.
|
|
16678
16695
|
if (key === "fx" || key === "fy") return "band";
|
|
16679
16696
|
|
|
@@ -16685,9 +16702,8 @@ function inferScaleType(key, channels, {
|
|
|
16685
16702
|
// If a channel dictates a scale type, make sure that it is consistent with
|
|
16686
16703
|
// the user-specified scale type (if any) and all other channels. For example,
|
|
16687
16704
|
// barY requires x to be a band scale and disallows any other scale type.
|
|
16688
|
-
for (const {
|
|
16689
|
-
|
|
16690
|
-
} of channels) {
|
|
16705
|
+
for (const channel of channels) {
|
|
16706
|
+
const t = maybeScaleType(channel.type);
|
|
16691
16707
|
if (t === undefined) continue;else if (type === undefined) type = t;else if (type !== t) throw new Error(`scale incompatible with channel: ${type} !== ${t}`);
|
|
16692
16708
|
}
|
|
16693
16709
|
|
|
@@ -16785,6 +16801,7 @@ function coerceType(channels, {
|
|
|
16785
16801
|
}, coerceValues) {
|
|
16786
16802
|
for (const c of channels) {
|
|
16787
16803
|
if (c.value !== undefined) {
|
|
16804
|
+
if (domain === undefined) domain = c.value?.domain; // promote channel domain
|
|
16788
16805
|
c.value = coerceValues(c.value);
|
|
16789
16806
|
}
|
|
16790
16807
|
}
|
|
@@ -17710,15 +17727,14 @@ function legendRamp(color, options) {
|
|
|
17710
17727
|
if (tickFormat === null) tickFormat = () => null;
|
|
17711
17728
|
const svg = create("svg", context).attr("class", `${className}-ramp`).attr("font-family", "system-ui, sans-serif").attr("font-size", 10).attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).call(svg =>
|
|
17712
17729
|
// Warning: if you edit this, change defaultClassName.
|
|
17713
|
-
svg.append("style").text(
|
|
17730
|
+
svg.append("style").text(`:where(.${className}-ramp) {
|
|
17714
17731
|
display: block;
|
|
17715
|
-
background: white;
|
|
17716
17732
|
height: auto;
|
|
17717
17733
|
height: intrinsic;
|
|
17718
17734
|
max-width: 100%;
|
|
17719
17735
|
overflow: visible;
|
|
17720
17736
|
}
|
|
17721
|
-
.${className}-ramp text {
|
|
17737
|
+
:where(.${className}-ramp text) {
|
|
17722
17738
|
white-space: pre;
|
|
17723
17739
|
}`)).call(applyInlineStyles, style);
|
|
17724
17740
|
let tickAdjust = g => g.selectAll(".tick line").attr("y1", marginTop + marginBottom - height);
|
|
@@ -17820,6 +17836,12 @@ function maybeMarker(marker) {
|
|
|
17820
17836
|
return markerCircleFill;
|
|
17821
17837
|
case "circle-stroke":
|
|
17822
17838
|
return markerCircleStroke;
|
|
17839
|
+
case "tick":
|
|
17840
|
+
return markerTick("auto");
|
|
17841
|
+
case "tick-x":
|
|
17842
|
+
return markerTick(90);
|
|
17843
|
+
case "tick-y":
|
|
17844
|
+
return markerTick(0);
|
|
17823
17845
|
}
|
|
17824
17846
|
throw new Error(`invalid marker: ${marker}`);
|
|
17825
17847
|
}
|
|
@@ -17830,10 +17852,13 @@ function markerDot(color, context) {
|
|
|
17830
17852
|
return create("svg:marker", context).attr("viewBox", "-5 -5 10 10").attr("markerWidth", 6.67).attr("markerHeight", 6.67).attr("fill", color).attr("stroke", "none").call(marker => marker.append("circle").attr("r", 2.5)).node();
|
|
17831
17853
|
}
|
|
17832
17854
|
function markerCircleFill(color, context) {
|
|
17833
|
-
return create("svg:marker", context).attr("viewBox", "-5 -5 10 10").attr("markerWidth", 6.67).attr("markerHeight", 6.67).attr("fill", color).attr("stroke", "
|
|
17855
|
+
return create("svg:marker", context).attr("viewBox", "-5 -5 10 10").attr("markerWidth", 6.67).attr("markerHeight", 6.67).attr("fill", color).attr("stroke", "var(--plot-background)").attr("stroke-width", 1.5).call(marker => marker.append("circle").attr("r", 3)).node();
|
|
17834
17856
|
}
|
|
17835
17857
|
function markerCircleStroke(color, context) {
|
|
17836
|
-
return create("svg:marker", context).attr("viewBox", "-5 -5 10 10").attr("markerWidth", 6.67).attr("markerHeight", 6.67).attr("fill", "
|
|
17858
|
+
return create("svg:marker", context).attr("viewBox", "-5 -5 10 10").attr("markerWidth", 6.67).attr("markerHeight", 6.67).attr("fill", "var(--plot-background)").attr("stroke", color).attr("stroke-width", 1.5).call(marker => marker.append("circle").attr("r", 3)).node();
|
|
17859
|
+
}
|
|
17860
|
+
function markerTick(orient) {
|
|
17861
|
+
return (color, context) => create("svg:marker", context).attr("viewBox", "-3 -3 6 6").attr("markerWidth", 6).attr("markerHeight", 6).attr("orient", orient).attr("stroke", color).call(marker => marker.append("path").attr("d", "M0,-3v6")).node();
|
|
17837
17862
|
}
|
|
17838
17863
|
let nextMarkerId = 0;
|
|
17839
17864
|
function applyMarkers(path, mark, {
|
|
@@ -17939,7 +17964,7 @@ function maybeIntervalK(k, maybeInsetK, options, trivial) {
|
|
|
17939
17964
|
...options,
|
|
17940
17965
|
[k]: undefined,
|
|
17941
17966
|
[`${k}1`]: v1 === undefined ? kv : v1,
|
|
17942
|
-
[`${k}2`]: v2 === undefined ? kv : v2
|
|
17967
|
+
[`${k}2`]: v2 === undefined && !(v1 === v2 && trivial) ? kv : v2
|
|
17943
17968
|
};
|
|
17944
17969
|
}
|
|
17945
17970
|
let D1, V1;
|
|
@@ -18577,7 +18602,7 @@ function defaultWidth(text, start = 0, end = text.length) {
|
|
|
18577
18602
|
function monospaceWidth(text, start = 0, end = text.length) {
|
|
18578
18603
|
let sum = 0;
|
|
18579
18604
|
for (let i = start; i < end; i = readCharacter(text, i)) {
|
|
18580
|
-
sum += isPictographic(text, i) ?
|
|
18605
|
+
sum += isPictographic(text, i) ? 126 : 63;
|
|
18581
18606
|
}
|
|
18582
18607
|
return sum;
|
|
18583
18608
|
}
|
|
@@ -19419,7 +19444,7 @@ function inferTextChannel(scale, data, ticks, tickFormat, anchor) {
|
|
|
19419
19444
|
// possible, or the default ISO format (2014-01-26). TODO We need a better way
|
|
19420
19445
|
// to infer whether the ordinal scale is UTC or local time.
|
|
19421
19446
|
function inferTickFormat(scale, data, ticks, tickFormat, anchor) {
|
|
19422
|
-
return typeof tickFormat === "function" ? tickFormat : tickFormat === undefined && data && isTemporal(data) ? inferTimeFormat(data, anchor) ?? formatDefault : scale.tickFormat ? scale.tickFormat(typeof ticks === "number" ? ticks : null, tickFormat) : tickFormat === undefined ? formatDefault : typeof tickFormat === "string" ? (isTemporal(scale.domain()) ? utcFormat : format$1)(tickFormat) : constant(tickFormat);
|
|
19447
|
+
return typeof tickFormat === "function" ? tickFormat : tickFormat === undefined && data && isTemporal(data) ? inferTimeFormat(scale.type, data, anchor) ?? formatDefault : scale.tickFormat ? scale.tickFormat(typeof ticks === "number" ? ticks : null, tickFormat) : tickFormat === undefined ? formatDefault : typeof tickFormat === "string" ? (isTemporal(scale.domain()) ? utcFormat : format$1)(tickFormat) : constant(tickFormat);
|
|
19423
19448
|
}
|
|
19424
19449
|
function inclusiveRange(interval, min, max) {
|
|
19425
19450
|
return interval.range(min, interval.offset(interval.floor(max)));
|
|
@@ -19455,13 +19480,6 @@ function inferFontVariant(scale) {
|
|
|
19455
19480
|
return scale.bandwidth && !scale.interval ? undefined : "tabular-nums";
|
|
19456
19481
|
}
|
|
19457
19482
|
|
|
19458
|
-
// Determines whether the scale points in the “positive” (right or down) or
|
|
19459
|
-
// “negative” (left or up) direction; if the scale order cannot be determined,
|
|
19460
|
-
// returns NaN; used to assign an appropriate label arrow.
|
|
19461
|
-
function inferScaleOrder(scale) {
|
|
19462
|
-
return Math.sign(orderof(scale.domain())) * Math.sign(orderof(scale.range()));
|
|
19463
|
-
}
|
|
19464
|
-
|
|
19465
19483
|
// Takes the scale label, and if this is not an ordinal scale and the label was
|
|
19466
19484
|
// inferred from an associated channel, adds an orientation-appropriate arrow.
|
|
19467
19485
|
function formatAxisLabel(k, scale, {
|
|
@@ -19553,29 +19571,29 @@ function legendItems(scale, options = {}, swatch) {
|
|
|
19553
19571
|
const swatches = create("div", context).attr("class", `${className}-swatches ${className}-swatches-${columns != null ? "columns" : "wrap"}`);
|
|
19554
19572
|
let extraStyle;
|
|
19555
19573
|
if (columns != null) {
|
|
19556
|
-
extraStyle =
|
|
19574
|
+
extraStyle = `:where(.${className}-swatches-columns .${className}-swatch) {
|
|
19557
19575
|
display: flex;
|
|
19558
19576
|
align-items: center;
|
|
19559
19577
|
break-inside: avoid;
|
|
19560
19578
|
padding-bottom: 1px;
|
|
19561
19579
|
}
|
|
19562
|
-
.${className}-swatches-columns .${className}-swatch::before {
|
|
19580
|
+
:where(.${className}-swatches-columns .${className}-swatch::before) {
|
|
19563
19581
|
flex-shrink: 0;
|
|
19564
19582
|
}
|
|
19565
|
-
.${className}-swatches-columns .${className}-swatch-label {
|
|
19583
|
+
:where(.${className}-swatches-columns .${className}-swatch-label) {
|
|
19566
19584
|
white-space: nowrap;
|
|
19567
19585
|
overflow: hidden;
|
|
19568
19586
|
text-overflow: ellipsis;
|
|
19569
19587
|
}`;
|
|
19570
19588
|
swatches.style("columns", columns).selectAll().data(scale.domain).enter().append("div").attr("class", `${className}-swatch`).call(swatch, scale, swatchWidth, swatchHeight).call(item => item.append("div").attr("class", `${className}-swatch-label`).attr("title", tickFormat).text(tickFormat));
|
|
19571
19589
|
} else {
|
|
19572
|
-
extraStyle =
|
|
19590
|
+
extraStyle = `:where(.${className}-swatches-wrap) {
|
|
19573
19591
|
display: flex;
|
|
19574
19592
|
align-items: center;
|
|
19575
19593
|
min-height: 33px;
|
|
19576
19594
|
flex-wrap: wrap;
|
|
19577
19595
|
}
|
|
19578
|
-
.${className}-swatches-wrap .${className}-swatch {
|
|
19596
|
+
:where(.${className}-swatches-wrap .${className}-swatch) {
|
|
19579
19597
|
display: inline-flex;
|
|
19580
19598
|
align-items: center;
|
|
19581
19599
|
margin-right: 1em;
|
|
@@ -19584,12 +19602,12 @@ function legendItems(scale, options = {}, swatch) {
|
|
|
19584
19602
|
return this.ownerDocument.createTextNode(tickFormat.apply(this, arguments));
|
|
19585
19603
|
});
|
|
19586
19604
|
}
|
|
19587
|
-
return swatches.call(div => div.insert("style", "*").text(
|
|
19605
|
+
return swatches.call(div => div.insert("style", "*").text(`:where(.${className}-swatches) {
|
|
19588
19606
|
font-family: system-ui, sans-serif;
|
|
19589
19607
|
font-size: 10px;
|
|
19590
19608
|
margin-bottom: 0.5em;
|
|
19591
19609
|
}
|
|
19592
|
-
.${className}-swatch > svg {
|
|
19610
|
+
:where(.${className}-swatch > svg) {
|
|
19593
19611
|
margin-right: 0.5em;
|
|
19594
19612
|
overflow: visible;
|
|
19595
19613
|
}
|
|
@@ -19742,7 +19760,7 @@ function frame(options) {
|
|
|
19742
19760
|
|
|
19743
19761
|
const defaults$2 = {
|
|
19744
19762
|
ariaLabel: "tip",
|
|
19745
|
-
fill: "
|
|
19763
|
+
fill: "var(--plot-background)",
|
|
19746
19764
|
stroke: "currentColor"
|
|
19747
19765
|
};
|
|
19748
19766
|
|
|
@@ -19766,6 +19784,7 @@ class Tip extends Mark {
|
|
|
19766
19784
|
y1,
|
|
19767
19785
|
y2,
|
|
19768
19786
|
anchor,
|
|
19787
|
+
preferredAnchor = "bottom",
|
|
19769
19788
|
monospace,
|
|
19770
19789
|
fontFamily = monospace ? "ui-monospace, monospace" : undefined,
|
|
19771
19790
|
fontSize,
|
|
@@ -19822,7 +19841,7 @@ class Tip extends Mark {
|
|
|
19822
19841
|
} // filter: defined
|
|
19823
19842
|
}, options, defaults$2);
|
|
19824
19843
|
this.anchor = maybeAnchor$1(anchor, "anchor");
|
|
19825
|
-
this.
|
|
19844
|
+
this.preferredAnchor = maybeAnchor$1(preferredAnchor, "preferredAnchor");
|
|
19826
19845
|
this.frameAnchor = maybeFrameAnchor(frameAnchor);
|
|
19827
19846
|
this.textAnchor = impliedString(textAnchor, "middle");
|
|
19828
19847
|
this.textPadding = +textPadding;
|
|
@@ -19970,8 +19989,8 @@ class Tip extends Mark {
|
|
|
19970
19989
|
const [k] = cut(value, w - widthof(label), widthof, ee);
|
|
19971
19990
|
if (k >= 0) {
|
|
19972
19991
|
// value is truncated
|
|
19973
|
-
value = value.slice(0, k).trimEnd() + ellipsis;
|
|
19974
19992
|
title = value.trim();
|
|
19993
|
+
value = value.slice(0, k).trimEnd() + ellipsis;
|
|
19975
19994
|
}
|
|
19976
19995
|
}
|
|
19977
19996
|
const line = selection.append("tspan").attr("x", 0).attr("dy", `${lineHeight}em`).text("\u200b"); // zwsp for double-click
|
|
@@ -19997,16 +20016,13 @@ class Tip extends Mark {
|
|
|
19997
20016
|
w = Math.round(w), h = Math.round(h); // crisp edges
|
|
19998
20017
|
let a = anchor; // use the specified anchor, if any
|
|
19999
20018
|
if (a === undefined) {
|
|
20000
|
-
a = mark.previousAnchor; // favor the previous anchor, if it fits
|
|
20001
20019
|
const x = px(i) + ox;
|
|
20002
20020
|
const y = py(i) + oy;
|
|
20003
|
-
const fitLeft = x + w + r * 2 < width;
|
|
20004
|
-
const fitRight = x - w - r * 2 > 0;
|
|
20005
|
-
const fitTop = y + h + m + r * 2
|
|
20021
|
+
const fitLeft = x + w + m + r * 2 < width;
|
|
20022
|
+
const fitRight = x - w - m - r * 2 > 0;
|
|
20023
|
+
const fitTop = y + h + m + r * 2 < height;
|
|
20006
20024
|
const fitBottom = y - h - m - r * 2 > 0;
|
|
20007
|
-
|
|
20008
|
-
const ay = (/^top-/.test(a) ? fitTop || !fitBottom : fitTop && !fitBottom) ? "top" : "bottom";
|
|
20009
|
-
a = mark.previousAnchor = `${ay}-${ax}`;
|
|
20025
|
+
a = fitLeft && fitRight ? fitTop && fitBottom ? mark.preferredAnchor : fitBottom ? "bottom" : "top" : fitTop && fitBottom ? fitLeft ? "left" : "right" : (fitLeft || fitRight) && (fitTop || fitBottom) ? `${fitBottom ? "bottom" : "top"}-${fitLeft ? "left" : "right"}` : mark.preferredAnchor;
|
|
20010
20026
|
}
|
|
20011
20027
|
const path = this.firstChild; // note: assumes exactly two children!
|
|
20012
20028
|
const text = this.lastChild; // note: assumes exactly two children!
|
|
@@ -20481,15 +20497,15 @@ function plot(options = {}) {
|
|
|
20481
20497
|
} = dimensions;
|
|
20482
20498
|
select(svg).attr("class", className).attr("fill", "currentColor").attr("font-family", "system-ui, sans-serif").attr("font-size", 10).attr("text-anchor", "middle").attr("width", width).attr("height", height).attr("viewBox", `0 0 ${width} ${height}`).attr("aria-label", ariaLabel).attr("aria-description", ariaDescription).call(svg =>
|
|
20483
20499
|
// Warning: if you edit this, change defaultClassName.
|
|
20484
|
-
svg.append("style").text(
|
|
20500
|
+
svg.append("style").text(`:where(.${className}) {
|
|
20501
|
+
--plot-background: white;
|
|
20485
20502
|
display: block;
|
|
20486
|
-
background: white;
|
|
20487
20503
|
height: auto;
|
|
20488
20504
|
height: intrinsic;
|
|
20489
20505
|
max-width: 100%;
|
|
20490
20506
|
}
|
|
20491
|
-
.${className} text,
|
|
20492
|
-
.${className} tspan {
|
|
20507
|
+
:where(.${className} text),
|
|
20508
|
+
:where(.${className} tspan) {
|
|
20493
20509
|
white-space: pre;
|
|
20494
20510
|
}`)).call(applyInlineStyles, style);
|
|
20495
20511
|
|
|
@@ -20775,11 +20791,13 @@ function inferTips(marks) {
|
|
|
20775
20791
|
pointer: tipOptions
|
|
20776
20792
|
};
|
|
20777
20793
|
let {
|
|
20778
|
-
pointer: p
|
|
20794
|
+
pointer: p,
|
|
20795
|
+
preferredAnchor: a
|
|
20779
20796
|
} = tipOptions;
|
|
20780
20797
|
p = /^x$/i.test(p) ? pointerX : /^y$/i.test(p) ? pointerY : pointer; // TODO validate?
|
|
20781
20798
|
tipOptions = p(derive(mark, tipOptions));
|
|
20782
20799
|
tipOptions.title = null; // prevent implicit title for primitive data
|
|
20800
|
+
if (a === undefined) tipOptions.preferredAnchor = p === pointerY ? "left" : "bottom";
|
|
20783
20801
|
const t = tip(mark.data, tipOptions);
|
|
20784
20802
|
t.facet = mark.facet; // inherit facet settings
|
|
20785
20803
|
t.facetAnchor = mark.facetAnchor; // inherit facet settings
|
|
@@ -21168,7 +21186,7 @@ gy,
|
|
|
21168
21186
|
const BX2 = bx && setBX2([]);
|
|
21169
21187
|
const BY1 = by && setBY1([]);
|
|
21170
21188
|
const BY2 = by && setBY2([]);
|
|
21171
|
-
const bin = bing(bx
|
|
21189
|
+
const bin = bing(bx, by, data);
|
|
21172
21190
|
let i = 0;
|
|
21173
21191
|
for (const o of outputs) o.initialize(data);
|
|
21174
21192
|
if (sort) sort.initialize(data);
|
|
@@ -21397,13 +21415,16 @@ function thresholdAuto(values, min, max) {
|
|
|
21397
21415
|
function isTimeThresholds(t) {
|
|
21398
21416
|
return isTimeInterval(t) || isIterable(t) && isTemporal(t);
|
|
21399
21417
|
}
|
|
21400
|
-
function bing(
|
|
21418
|
+
function bing(bx, by, data) {
|
|
21419
|
+
const EX = bx?.(data);
|
|
21420
|
+
const EY = by?.(data);
|
|
21401
21421
|
return EX && EY ? function* (I) {
|
|
21402
21422
|
const X = EX.bin(I); // first bin on x
|
|
21403
21423
|
for (const [ix, [x1, x2]] of EX.entries()) {
|
|
21404
21424
|
const Y = EY.bin(X[ix]); // then bin on y
|
|
21405
21425
|
for (const [iy, [y1, y2]] of EY.entries()) {
|
|
21406
21426
|
yield [Y[iy], {
|
|
21427
|
+
data,
|
|
21407
21428
|
x1,
|
|
21408
21429
|
y1,
|
|
21409
21430
|
x2,
|
|
@@ -21415,6 +21436,7 @@ function bing(EX, EY) {
|
|
|
21415
21436
|
const X = EX.bin(I);
|
|
21416
21437
|
for (const [i, [x1, x2]] of EX.entries()) {
|
|
21417
21438
|
yield [X[i], {
|
|
21439
|
+
data,
|
|
21418
21440
|
x1,
|
|
21419
21441
|
x2
|
|
21420
21442
|
}];
|
|
@@ -21423,6 +21445,7 @@ function bing(EX, EY) {
|
|
|
21423
21445
|
const Y = EY.bin(I);
|
|
21424
21446
|
for (const [i, [y1, y2]] of EY.entries()) {
|
|
21425
21447
|
yield [Y[i], {
|
|
21448
|
+
data,
|
|
21426
21449
|
y1,
|
|
21427
21450
|
y2
|
|
21428
21451
|
}];
|
|
@@ -21435,7 +21458,7 @@ function bin1(E, T, V) {
|
|
|
21435
21458
|
T = coerceNumbers(T); // for faster bisection
|
|
21436
21459
|
return I => {
|
|
21437
21460
|
const B = E.map(() => []);
|
|
21438
|
-
for (const i of I) B[
|
|
21461
|
+
for (const i of I) B[bisectRight(T, V[i]) - 1]?.push(i); // TODO quantization?
|
|
21439
21462
|
return B;
|
|
21440
21463
|
};
|
|
21441
21464
|
}
|
|
@@ -21984,11 +22007,13 @@ class Rect extends Mark {
|
|
|
21984
22007
|
x1: {
|
|
21985
22008
|
value: x1,
|
|
21986
22009
|
scale: "x",
|
|
22010
|
+
type: x1 != null && x2 == null ? "band" : undefined,
|
|
21987
22011
|
optional: true
|
|
21988
22012
|
},
|
|
21989
22013
|
y1: {
|
|
21990
22014
|
value: y1,
|
|
21991
22015
|
scale: "y",
|
|
22016
|
+
type: y1 != null && y2 == null ? "band" : undefined,
|
|
21992
22017
|
optional: true
|
|
21993
22018
|
},
|
|
21994
22019
|
x2: {
|
|
@@ -22039,10 +22064,9 @@ class Rect extends Mark {
|
|
|
22039
22064
|
rx,
|
|
22040
22065
|
ry
|
|
22041
22066
|
} = this;
|
|
22042
|
-
|
|
22043
|
-
|
|
22044
|
-
|
|
22045
|
-
}, 0, 0).call(g => g.selectAll().data(index).enter().append("rect").call(applyDirectStyles, this).attr("x", X1 && X2 && (projection || !isCollapsed(x)) ? i => Math.min(X1[i], X2[i]) + insetLeft : marginLeft + insetLeft).attr("y", Y1 && Y2 && (projection || !isCollapsed(y)) ? i => Math.min(Y1[i], Y2[i]) + insetTop : marginTop + insetTop).attr("width", X1 && X2 && (projection || !isCollapsed(x)) ? i => Math.max(0, Math.abs(X2[i] - X1[i]) - insetLeft - insetRight) : width - marginRight - marginLeft - insetRight - insetLeft).attr("height", Y1 && Y2 && (projection || !isCollapsed(y)) ? i => Math.max(0, Math.abs(Y1[i] - Y2[i]) - insetTop - insetBottom) : height - marginTop - marginBottom - insetTop - insetBottom).call(applyAttr, "rx", rx).call(applyAttr, "ry", ry).call(applyChannelStyles, this, channels)).node();
|
|
22067
|
+
const bx = (x?.bandwidth ? x.bandwidth() : 0) - insetLeft - insetRight;
|
|
22068
|
+
const by = (y?.bandwidth ? y.bandwidth() : 0) - insetTop - insetBottom;
|
|
22069
|
+
return create("svg:g", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, {}, 0, 0).call(g => g.selectAll().data(index).enter().append("rect").call(applyDirectStyles, this).attr("x", X1 && (projection || !isCollapsed(x)) ? X2 ? i => Math.min(X1[i], X2[i]) + insetLeft : i => X1[i] + insetLeft : marginLeft + insetLeft).attr("y", Y1 && (projection || !isCollapsed(y)) ? Y2 ? i => Math.min(Y1[i], Y2[i]) + insetTop : i => Y1[i] + insetTop : marginTop + insetTop).attr("width", X1 && (projection || !isCollapsed(x)) ? X2 ? i => Math.max(0, Math.abs(X2[i] - X1[i]) + bx) : bx : width - marginRight - marginLeft - insetRight - insetLeft).attr("height", Y1 && (projection || !isCollapsed(y)) ? Y2 ? i => Math.max(0, Math.abs(Y1[i] - Y2[i]) + by) : by : height - marginTop - marginBottom - insetTop - insetBottom).call(applyAttr, "rx", rx).call(applyAttr, "ry", ry).call(applyChannelStyles, this, channels)).node();
|
|
22046
22070
|
}
|
|
22047
22071
|
}
|
|
22048
22072
|
function rectY(data, options = {}) {
|