mapshaper 0.7.74 → 0.7.76

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/mapshaper.js CHANGED
@@ -71333,7 +71333,7 @@ ${css.join('\n')}
71333
71333
  return new Rgb(o.r, o.g, o.b, o.opacity);
71334
71334
  }
71335
71335
 
71336
- function rgb$1(r, g, b, opacity) {
71336
+ function rgb(r, g, b, opacity) {
71337
71337
  return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
71338
71338
  }
71339
71339
 
@@ -71344,7 +71344,7 @@ ${css.join('\n')}
71344
71344
  this.opacity = +opacity;
71345
71345
  }
71346
71346
 
71347
- define(Rgb, rgb$1, extend(Color, {
71347
+ define(Rgb, rgb, extend(Color, {
71348
71348
  brighter(k) {
71349
71349
  k = k == null ? brighter : Math.pow(brighter, k);
71350
71350
  return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
@@ -71606,11 +71606,11 @@ ${css.join('\n')}
71606
71606
  return d ? linear(a, d) : constant(isNaN(a) ? b : a);
71607
71607
  }
71608
71608
 
71609
- var rgb = (function rgbGamma(y) {
71609
+ var interpolateRgb = (function rgbGamma(y) {
71610
71610
  var color = gamma(y);
71611
71611
 
71612
- function rgb(start, end) {
71613
- var r = color((start = rgb$1(start)).r, (end = rgb$1(end)).r),
71612
+ function rgb$1(start, end) {
71613
+ var r = color((start = rgb(start)).r, (end = rgb(end)).r),
71614
71614
  g = color(start.g, end.g),
71615
71615
  b = color(start.b, end.b),
71616
71616
  opacity = nogamma(start.opacity, end.opacity);
@@ -71623,9 +71623,9 @@ ${css.join('\n')}
71623
71623
  };
71624
71624
  }
71625
71625
 
71626
- rgb.gamma = rgbGamma;
71626
+ rgb$1.gamma = rgbGamma;
71627
71627
 
71628
- return rgb;
71628
+ return rgb$1;
71629
71629
  })(1);
71630
71630
 
71631
71631
  function rgbSpline(spline) {
@@ -71636,7 +71636,7 @@ ${css.join('\n')}
71636
71636
  b = new Array(n),
71637
71637
  i, color;
71638
71638
  for (i = 0; i < n; ++i) {
71639
- color = rgb$1(colors[i]);
71639
+ color = rgb(colors[i]);
71640
71640
  r[i] = color.r || 0;
71641
71641
  g[i] = color.g || 0;
71642
71642
  b[i] = color.b || 0;
@@ -71789,8 +71789,8 @@ ${css.join('\n')}
71789
71789
  var t = typeof b, c;
71790
71790
  return b == null || t === "boolean" ? constant(b)
71791
71791
  : (t === "number" ? number
71792
- : t === "string" ? ((c = color(b)) ? (b = c, rgb) : string)
71793
- : b instanceof color ? rgb
71792
+ : t === "string" ? ((c = color(b)) ? (b = c, interpolateRgb) : string)
71793
+ : b instanceof color ? interpolateRgb
71794
71794
  : b instanceof Date ? date
71795
71795
  : isNumberArray(b) ? numberArray
71796
71796
  : Array.isArray(b) ? genericArray
@@ -71825,6 +71825,16 @@ ${css.join('\n')}
71825
71825
  cubehelix$1(hue);
71826
71826
  var cubehelixLong = cubehelix$1(nogamma);
71827
71827
 
71828
+ function piecewise(interpolate, values) {
71829
+ if (values === undefined) values = interpolate, interpolate = d3_interpolate;
71830
+ var i = 0, n = values.length - 1, v = values[0], I = new Array(n < 0 ? 0 : n);
71831
+ while (i < n) I[i] = interpolate(v, v = values[++i]);
71832
+ return function(t) {
71833
+ var i = Math.max(0, Math.min(n - 1, Math.floor(t *= n)));
71834
+ return I[i](t - i);
71835
+ };
71836
+ }
71837
+
71828
71838
  // OKLab conversion (Björn Ottosson, https://bottosson.github.io/posts/oklab/)
71829
71839
  // RGB objects use 0-255 channels, as returned by parseColor().
71830
71840
 
@@ -73968,7 +73978,7 @@ ${css.join('\n')}
73968
73978
  return c$1 + "";
73969
73979
  }
73970
73980
 
73971
- var c = rgb$1(),
73981
+ var c = rgb(),
73972
73982
  pi_1_3 = Math.PI / 3,
73973
73983
  pi_2_3 = Math.PI * 2 / 3;
73974
73984
 
@@ -74084,6 +74094,59 @@ ${css.join('\n')}
74084
74094
  schemeYlOrRd: scheme$6
74085
74095
  });
74086
74096
 
74097
+ // Scientific colour maps, version 8.0.1, by Fabio Crameri
74098
+ // https://www.fabiocrameri.ch/colourmaps/ (https://doi.org/10.5281/zenodo.8409685)
74099
+ //
74100
+ // Each ramp is 33 evenly spaced colors (as packed hex), sampled from the
74101
+ // 256-color version, which they reproduce to within 0.008 OKLab deltaE; the
74102
+ // odd count gives diverging ramps a color at their center. batlowS is the
74103
+ // first 20 swatches of batlow's categorical palette.
74104
+ //
74105
+ // The Scientific colour maps are licensed under a MIT License
74106
+ // Copyright (c) 2023, Fabio Crameri
74107
+ // Permission is hereby granted, free of charge, to any person obtaining a
74108
+ // copy of this software and associated documentation files (the "Software"),
74109
+ // to deal in the Software without restriction, including without limitation
74110
+ // the rights to use, copy, modify, merge, publish, distribute, sublicense,
74111
+ // and/or sell copies of the Software, and to permit persons to whom the
74112
+ // Software is furnished to do so, subject to the following conditions:
74113
+ // The above copyright notice and this permission notice shall be included in
74114
+ // all copies or substantial portions of the Software.
74115
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
74116
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
74117
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
74118
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
74119
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
74120
+ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
74121
+ // DEALINGS IN THE SOFTWARE.
74122
+
74123
+ var crameriSequential = {
74124
+ batlow: '01195908255b0d315d0f3b5f114360134b611652621b59622260612a655e356a59406f544d734d597646667a3f737e3881823290862da08a2bb08d2ebf9035ce923fdb954ce8985bf29d6cf8a27efca891fdaea3fdb4b4fdbac5fcc0d6fbc6e8faccfa',
74125
+ batlowW: '01195908255b0d315d0f3b5f114360134a611651621a5862205f6228655f326a5c3d6f5749745155794b627d446f823e7d87388c8c339d9232ae9838be9d44cca154d7a565e0a875e8ac84efb094f5b8a6fbc3bafed1ceffdfddffebeafff5f5fffefe',
74126
+ acton: '260d402d17493420523a2a5a413362473b6a4d4472534c79595481615b876a608b74628d7d638e87648e91648f9c658fa76690b36791bf6a93c97097cf789fd482a7d78db0da97b9dda2c2e0accae3b6d2e5c0dae8cae1ead3e8ecdbeeeee3f4f0eafa',
74127
+ bamako: '003b47043d45083f430c424010453e14483b194b381f4e342552312b562d325b29395f2440642048691b516f16597410627a0b6b7f057584017f87008a8900948c019f9108a99815b4a122bfa930cab240d4bb52ddc465e6cc78efd58af7dd9cffe5ad',
74128
+ bilbao: '4c0001580b1064161a6e202478292e8232398b3b4293444a994e509c56549f5d56a16458a26a59a4705aa6765ca77c5da9825eaa885fac8e61ae9463b09c66b4a46eb8ac7bbcb389bfb897c2bda4c5c2b0c9c7bccfcdc8d7d7d5e3e3e2f1f1f1ffffff',
74129
+ davos: '00054a031256081c610e276c1431761a3c802146892850902f5a9636639a3e6b9c46729d4e789d557e9b5d84996489966c8d937392907b978d839d8a8ba38895aa87a0b289adbc8dbcc894cbd49fdadfade6e9bceff0cbf6f6d9faf9e6fcfcf3fefefe',
74130
+ devon: '2c1a4c2b21542a285b29306329376a283f7227477b274f8429588f2c5f9a3265a5386bb04271bc4e78c65e80cf6e87d67d8edd8c95e29a9ce7a6a3ebb0aaeeb7b1f0beb8f2c4bff3cbc6f4d1cdf6d7d4f7dedbf8e4e2faebe9fbf2f0fcf8f8feffffff',
74131
+ lajolla: '191900201c04271e082f210d3724114127164c2b1c592f22663429753931853d3895423fa64644b64a48c54f4ad1564cd95f4ede6a4fe1744fe37e50e58751e79152e99a52eba353edad54efb755f1c159f4cd62f7d972fae588fcef9ffef7b6fffecb',
74132
+ lapaz: '1a0c641d176b1f207122297824327e263a842842892a4a8e2c52932f5a9733629b386a9e3d71a04378a24a7fa35286a45b8ca36591a27096a07a9b9e859e9b90a1999ba496a7a895b4ac96c2b299d0baa1dec4aceaceb9f3d8c8f9e1d6fceae5fef2f3',
74133
+ oslo: '010101050a100a121a0d18240e1e2e0f2439112a4413314f15395b1840671c4773214f7f26568c2d5e993667a54270b14f7abc5c83c3678bc77292c97c99ca859fca8fa4c998aac9a2b0caacb7cbb7bfcdc2c7d1ced1d7dadcdfe6e7e9f3f3f4ffffff',
74134
+ tokyo: '1c0e3429123837163d441d415024465b2d4963364c683f4e6b47506e4e506f5351705951715d52716152726652736a53746f53757554767c54778355798c567b95587e9f5b81ab5f87b7668fc3709ad17da8dd8eb8e9a2c9f1b4d8f7c5e5fad2effcdd',
74135
+ turku: '0000000e0e0d18181620201d28282330302a39382f41413549493951513e5a59426261456a6a4973724d7c7a51878355928b5a9e9360ab9a66b79f6dc2a373cca579d5a780dda887e4aa90ebae9af2b4a5f7bbb1fbc3bdfdccc8fed5d3ffdddcffe6e6'
74136
+ };
74137
+
74138
+ var crameriDiverging = {
74139
+ bam: '65024b77175d88266e97357da5428cb25099bd5ea5c76db0d17ebbd990c6e0a2d0e6b4d9ecc5e2f1d4e9f4e1eef6ebf1f6f1f1f3f3ecedf2e3e4eed4d7e7c1c7deaab4d191a0c3798cb5657aa6546999465a8c3a4c802f3e7425306819205a0d0d4c00',
74140
+ broc: '2c1a4c2b26582a3164293e70294a7d2d588939669449749f5a82a86c8fb27e9dbc91acc5a4bacfb7c8d9cad7e3dde5ebebeeecedeee0e7e7ceddddbcd4d4a9c9c995bbbb82abab709b9b618b8b547b7b476c6c3a5d5d2d4e4e2140401632330c262600',
74141
+ cork: '2c194c2b26592a3265283f71284b7e2d588a38669446729e567ea6668bae7798b889a6c19db4cbb1c4d6c7d4e1dbe4ebe6edecdfeae0cedfcebbd2bba8c5a794b89481ab816e9e6e5d935c4c884c3c7c3c2d702c20621e18541414450e1137090f2903',
74142
+ roma: '7e1700862c068e3c0c964b129d5818a3651ea97223af7e2ab68c32bd9a3cc4aa4acaba5cd0c971d2d789d1e19fcbe8b3c1eac2b2e9cda1e4d48ddcd778d2d764c5d452b8d044aacc399dc63190c12b83bc2677b7226ab11e5dab184fa511409f033198',
74143
+ vik: '001261021f69022b710237790344810450890c5e921b6d9b2f7ca6478db1609dbc79adc792bdd2acccdcc5dbe5dce5e9ece5e1eedacfe9cbb9e2bba4dcab8fd59c7bcf8e68c97f55c37243bc6331b3531fa5400e932e06832106741506660a07590008'
74144
+ };
74145
+
74146
+ var crameriCategorical = {
74147
+ batlowS: '011959faccfa828231226061f29d6d4d734d114360c09036fdb4b4dd954d356a59fcbfd6175262677b3ea18a2b0d315dfca890fbc6e82b655eb18d2f'
74148
+ };
74149
+
74087
74150
  var index = {
74088
74151
  categorical: [],
74089
74152
  sequential: [],
@@ -74092,10 +74155,29 @@ ${css.join('\n')}
74092
74155
  all: []
74093
74156
  };
74094
74157
  var ramps;
74158
+ // interpolators of the ramps that are stored as stops (not from d3)
74159
+ var stopInterpolators;
74160
+ // scheme name -> where the scheme comes from (see getColorSchemeGroups())
74161
+ var sources;
74162
+ // the order of the sources in lists of schemes
74163
+ var sourceOrder = ['ColorBrewer', 'Tableau', 'Matplotlib', 'Crameri', 'd3'];
74164
+ // Schemes are listed by their designers, as far as they're known. 'd3' is
74165
+ // d3-scale-chromatic's own schemes, and others that it brings in: Turbo
74166
+ // (Google) and CubehelixDefault (D. A. Green's cubehelix).
74167
+ var d3Sources = {
74168
+ ColorBrewer: 'Accent,Dark2,Paired,Pastel1,Pastel2,Set1,Set2,Set3,' +
74169
+ 'Blues,Greens,Greys,Purples,Reds,Oranges,BuGn,BuPu,GnBu,OrRd,PuBuGn,PuBu,PuRd,RdPu,YlGnBu,YlGn,YlOrBr,YlOrRd,' +
74170
+ 'BrBG,PRGn,PiYG,PuOr,RdBu,RdGy,RdYlBu,RdYlGn,Spectral',
74171
+ Tableau: 'Tableau10,Tableau20',
74172
+ Matplotlib: 'Cividis,Viridis,Magma,Inferno,Plasma',
74173
+ d3: 'Category10,Category20,Category20b,Category20c,CubehelixDefault,Rainbow,Warm,Cool,Sinebow,Turbo'
74174
+ };
74095
74175
 
74096
74176
  function initSchemes() {
74097
74177
  if (ramps) return;
74098
74178
  ramps = {};
74179
+ stopInterpolators = {};
74180
+ sources = {};
74099
74181
  addSchemesFromD3('categorical', 'Category10,Accent,Dark2,Paired,Pastel1,Pastel2,Set1,Set2,Set3,Tableau10');
74100
74182
  addSchemesFromD3('sequential', 'Blues,Greens,Greys,Purples,Reds,Oranges,BuGn,BuPu,GnBu,OrRd,PuBuGn,PuBu,PuRd,RdPu,YlGnBu,YlGn,YlOrBr,YlOrRd');
74101
74183
  addSchemesFromD3('rainbow', 'Cividis,CubehelixDefault,Rainbow,Warm,Cool,Sinebow,Turbo,Viridis,Magma,Inferno,Plasma');
@@ -74109,9 +74191,29 @@ ${css.join('\n')}
74109
74191
  '3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9');
74110
74192
  addCategoricalScheme('Tableau20',
74111
74193
  '4c78a89ecae9f58518ffbf7954a24b88d27ab79a20f2cf5b43989483bcb6e45756ff9d9879706ebab0acd67195fcbfd2b279a2d6a5c99e765fd8b5a5');
74194
+ Object.keys(d3Sources).forEach(function(source) {
74195
+ d3Sources[source].split(',').forEach(function(name) {
74196
+ sources[name] = source;
74197
+ });
74198
+ });
74199
+ addStoppedSchemes('sequential', crameriSequential, 'Crameri');
74200
+ addStoppedSchemes('diverging', crameriDiverging, 'Crameri');
74201
+ Object.keys(crameriCategorical).forEach(function(name) {
74202
+ addCategoricalScheme(name, crameriCategorical[name]);
74203
+ sources[name] = 'Crameri';
74204
+ });
74112
74205
  index.all = [].concat(index.sequential, index.rainbow, index.diverging, index.categorical);
74113
74206
  }
74114
74207
 
74208
+ // Ramps stored as evenly spaced colors, interpolated linearly between them
74209
+ function addStoppedSchemes(type, schemes, source) {
74210
+ Object.keys(schemes).forEach(function(name) {
74211
+ index[type].push(name);
74212
+ stopInterpolators[name] = piecewise(interpolateRgb, unpackRamp(schemes[name]));
74213
+ sources[name] = source;
74214
+ });
74215
+ }
74216
+
74115
74217
  function standardName(name) {
74116
74218
  if (!name) return null;
74117
74219
  var lcname = name.toLowerCase();
@@ -74173,12 +74275,15 @@ ${css.join('\n')}
74173
74275
  }
74174
74276
 
74175
74277
  function printColorSchemeNames() {
74278
+ var types = [['categorical', 'Categorical'], ['sequential', 'Sequential'],
74279
+ ['diverging', 'Diverging'], ['rainbow', 'Multi-hue/rainbow']];
74176
74280
  initSchemes();
74177
- print('Built-in color schemes (from d3):');
74178
- print ('Categorical\n' + formatStringsAsGrid(index.categorical));
74179
- print ('\nSequential\n' + formatStringsAsGrid(index.sequential));
74180
- print ('\nDiverging\n' + formatStringsAsGrid(index.diverging));
74181
- print ('\nMulti-hue/rainbow\n' + formatStringsAsGrid(index.rainbow));
74281
+ print('Built-in color schemes');
74282
+ types.forEach(function(type) {
74283
+ getColorSchemeGroups(type[0]).forEach(function(group) {
74284
+ print('\n' + type[1] + ' (' + group.source + ')\n' + formatStringsAsGrid(group.names));
74285
+ });
74286
+ });
74182
74287
  }
74183
74288
 
74184
74289
  // type: categorical, sequential, rainbow or diverging
@@ -74188,6 +74293,19 @@ ${css.join('\n')}
74188
74293
  return index[type].concat();
74189
74294
  }
74190
74295
 
74296
+ // The schemes of one or more types, by source: [{source, names}]
74297
+ // (sources: ColorBrewer, Tableau, Matplotlib, Crameri, d3)
74298
+ function getColorSchemeGroups(types) {
74299
+ var names = [].concat(types).reduce(function(memo, type) {
74300
+ return memo.concat(getColorSchemeNames(type));
74301
+ }, []);
74302
+ return sourceOrder.map(function(source) {
74303
+ return {source: source, names: names.filter(function(name) { return sources[name] == source; })};
74304
+ }).filter(function(group) {
74305
+ return group.names.length > 0;
74306
+ });
74307
+ }
74308
+
74191
74309
  function pickRandomColorScheme(type) {
74192
74310
  initSchemes();
74193
74311
  var names = index[type];
@@ -74267,7 +74385,7 @@ ${css.join('\n')}
74267
74385
  initSchemes();
74268
74386
  name = standardName(name);
74269
74387
  var ramps = d3Scales['scheme' + name];
74270
- var interpolate = d3Scales['interpolate' + name];
74388
+ var interpolate = d3Scales['interpolate' + name] || stopInterpolators[name];
74271
74389
  var ramp;
74272
74390
  if (!ramps && !interpolate) {
74273
74391
  stop$1('Unknown color scheme name:', name);
@@ -74286,6 +74404,26 @@ ${css.join('\n')}
74286
74404
  return ramp;
74287
74405
  }
74288
74406
 
74407
+ // n colors from part of a ramp, evenly spaced from start to end (0-1).
74408
+ // base: interpolate between the colors of the scheme's set of this size, if
74409
+ // it has one (ColorBrewer's hand-picked sets), so that a section of a set
74410
+ // keeps its colors; otherwise the scheme's own interpolator is used
74411
+ function getColorRampSection(name, n, start, end, base) {
74412
+ initSchemes();
74413
+ name = standardName(name);
74414
+ var sets = d3Scales['scheme' + name];
74415
+ var interpolate = d3Scales['interpolate' + name] || stopInterpolators[name];
74416
+ var colors = [];
74417
+ if (!interpolate || index.categorical.includes(name)) {
74418
+ stop$1('Not a sequential or diverging color scheme:', name);
74419
+ }
74420
+ if (sets && sets[base]) interpolate = piecewise(interpolateRgb, sets[base]);
74421
+ for (var i=0; i<n; i++) {
74422
+ colors.push(interpolate(n > 1 ? start + (end - start) * i / (n - 1) : (start + end) / 2));
74423
+ }
74424
+ return colors;
74425
+ }
74426
+
74289
74427
  function getInterpolatedRamp(interpolate, n) {
74290
74428
  if (n > 0 === false || !utils.isInteger(n)) {
74291
74429
  error('Expected a positive integer');
@@ -74302,6 +74440,8 @@ ${css.join('\n')}
74302
74440
  getCategoricalColorScheme: getCategoricalColorScheme,
74303
74441
  getCategoricalColors: getCategoricalColors,
74304
74442
  getColorRamp: getColorRamp,
74443
+ getColorRampSection: getColorRampSection,
74444
+ getColorSchemeGroups: getColorSchemeGroups,
74305
74445
  getColorSchemeNames: getColorSchemeNames,
74306
74446
  getRandomizedCategoricalColorScheme: getRandomizedCategoricalColorScheme,
74307
74447
  isCategoricalColorScheme: isCategoricalColorScheme,
@@ -87771,7 +87911,7 @@ ${css.join('\n')}
87771
87911
  return name == 'rectangle' || name == 'rectangles' || name == 'filter' && opts.cleanup;
87772
87912
  }
87773
87913
 
87774
- var version = "0.7.74";
87914
+ var version = "0.7.76";
87775
87915
 
87776
87916
  // Parse command line args into commands and run them
87777
87917
  // Function takes an optional Node-style callback. A Promise is returned if no callback is given.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mapshaper",
3
- "version": "0.7.74",
3
+ "version": "0.7.76",
4
4
  "description": "A tool for editing geospatial data for mapping and GIS.",
5
5
  "keywords": [
6
6
  "shapefile",
@@ -5177,7 +5177,7 @@
5177
5177
  var recipe = getRasterViewRecipe(grid, view && view.recipe);
5178
5178
  var stats = getRasterViewScalingStats(raster, recipe);
5179
5179
  var sourceRange = recipe.scaling == 'none' ? getPixelTypeRange(grid.pixelType) : null;
5180
- var displayRange = getDisplayRange(recipe.scaleRange);
5180
+ var displayRange = getDisplayRange$1(recipe.scaleRange);
5181
5181
  var offset = pixelId * grid.bands;
5182
5182
  var color = [0, 1, 2].map(function(band) {
5183
5183
  return scaleSample(grid.samples[offset + band], stats && stats[band], sourceRange, displayRange);
@@ -5204,7 +5204,7 @@
5204
5204
  var pixels = new Uint8ClampedArray(width * height * 4);
5205
5205
  var stats = statsArg || getScalingStats(samples, bands, noData, recipe);
5206
5206
  var sourceRange = recipe.scaling == 'none' ? getPixelTypeRange(grid.pixelType) : null;
5207
- var displayRange = getDisplayRange(recipe.scaleRange);
5207
+ var displayRange = getDisplayRange$1(recipe.scaleRange);
5208
5208
  var src, dest, val, isNoData, j, sample;
5209
5209
  for (var y = 0; y < height; y++) {
5210
5210
  for (var x = 0; x < width; x++) {
@@ -5642,7 +5642,7 @@
5642
5642
  return range;
5643
5643
  }
5644
5644
 
5645
- function getDisplayRange(scaleRange) {
5645
+ function getDisplayRange$1(scaleRange) {
5646
5646
  return [
5647
5647
  scaleRange[0] / 100 * 255,
5648
5648
  scaleRange[1] / 100 * 255
@@ -9921,7 +9921,7 @@
9921
9921
  }
9922
9922
  line.show();
9923
9923
  input.node().focus();
9924
- });
9924
+ }, {typed: true});
9925
9925
  }
9926
9926
  toHistory(str);
9927
9927
  }
@@ -10029,8 +10029,14 @@
10029
10029
 
10030
10030
  }
10031
10031
 
10032
+ // runOpts.session see createCommandSession()
10033
+ // runOpts.typed the commands were typed into the console. Commands that
10034
+ // the GUI runs for a panel or tool are run as if with -quiet,
10035
+ // so their messages don't fill the console (errors still
10036
+ // reach the caller).
10032
10037
  function runMapshaperCommands(str, done, runOpts) {
10033
10038
  var session = runOpts && runOpts.session || null;
10039
+ var quiet = !(runOpts && runOpts.typed);
10034
10040
  var commands;
10035
10041
  if (activeSession && activeSession != session) {
10036
10042
  activeSession.finish().then(function() {
@@ -10049,7 +10055,7 @@
10049
10055
  return done(e, {});
10050
10056
  }
10051
10057
  if (commands.length === 0) return done();
10052
- applyParsedCommands(commands, str, session, function(err, flags) {
10058
+ applyParsedCommands(commands, str, session, quiet, function(err, flags) {
10053
10059
  if (flags) {
10054
10060
  model.updated(flags); // info commands do not return flags
10055
10061
  }
@@ -10075,7 +10081,7 @@
10075
10081
  });
10076
10082
  }
10077
10083
 
10078
- function applyParsedCommands(commands, commandString, session, done) {
10084
+ function applyParsedCommands(commands, commandString, session, quiet, done) {
10079
10085
  var active = model.getActiveLayer(),
10080
10086
  prevArcs = active?.dataset.arcs,
10081
10087
  prevTable = active?.layer.data,
@@ -10094,7 +10100,9 @@
10094
10100
  // so they can snapshot the pre-command state of the active layer.
10095
10101
  gui.dispatchEvent('command_start', {commands: commands});
10096
10102
  try {
10097
- internal.runParsedCommands(commands, job, onCommandsDone);
10103
+ // -quiet is a setting, read and removed by runParsedCommands()
10104
+ internal.runParsedCommands(quiet ? [{name: 'quiet', options: {}}].concat(commands) : commands,
10105
+ job, onCommandsDone);
10098
10106
  } catch(e) {
10099
10107
  if (undoTransaction) {
10100
10108
  clearActiveUndoTransaction(undoTransaction);
@@ -10296,13 +10304,16 @@
10296
10304
  // can differ -- warnings shouldn't read as red "something went wrong",
10297
10305
  // they're just heads-ups about how the input was interpreted.
10298
10306
  function consoleWarn() {
10299
- var msg = GUI.formatMessageArgs(arguments);
10300
- toLog(msg, 'console-warn');
10307
+ if (internal.getStashedVar('QUIET')) return;
10308
+ toLog(GUI.formatMessageArgs(arguments), 'console-warn');
10301
10309
  }
10302
10310
 
10311
+ // Like the CLI, -quiet (which the GUI's own commands run with, see
10312
+ // runMapshaperCommands()) silences messages and warnings, not errors
10303
10313
  function consoleMessage() {
10304
10314
  var structured = getStructuredConsoleMessage(arguments);
10305
10315
  var msg;
10316
+ if (internal.getStashedVar('QUIET')) return;
10306
10317
  if (internal.loggingEnabled()) {
10307
10318
  if (structured) {
10308
10319
  toLogNode(renderStructuredConsoleMessage(structured), 'console-message');
@@ -21063,6 +21074,10 @@
21063
21074
  // diverging schemes, of classes:
21064
21075
  // the total, or per side)
21065
21076
  // preset: name or null, reversed: boolean, (presets)
21077
+ // range: {start, end, base} or null (presets: the part of the ramp
21078
+ // the tiles are taken from, 0-1
21079
+ // in the preset's own direction;
21080
+ // see getSchemeRange())
21066
21081
  // pins: [{t, color}] or null, (custom sequential ramps)
21067
21082
  // vibrance, longHue (custom sequential ramps, see
21068
21083
  // getOklchInterpolator())
@@ -21126,7 +21141,7 @@
21126
21141
  var minSchemeColors = 2;
21127
21142
  var maxSchemeColors = 12;
21128
21143
  var maxCategoricalColors = 20;
21129
- var defaultCategoricalPreset = 'Tableau10';
21144
+ var defaultCategoricalPreset = 'batlowS';
21130
21145
  var defaultNonAdjacentColors = 5;
21131
21146
  var defaultDivergingPreset = 'RdBu';
21132
21147
  var defaultDivergingClasses = 7;
@@ -21138,7 +21153,8 @@
21138
21153
  // (-classify's vibrance= is the same, scaled to 0-1)
21139
21154
  var defaultVibrance = 0;
21140
21155
  var maxVibrance = internal.MAX_VIBRANCE_CHROMA;
21141
- var defaultEnds = ['#344a72', '#f0d26b'];
21156
+ // the default sequential ramp: cream to blue, through green and teal
21157
+ var defaultEnds = ['#fff8da', '#2d4d8e'];
21142
21158
  // Cyclic ramps start and end on the same hue, which reads as a category
21143
21159
  // rather than an order.
21144
21160
  var excludedPresets = ['Rainbow', 'Sinebow'];
@@ -21149,19 +21165,33 @@
21149
21165
  var layerSchemes = new WeakMap();
21150
21166
 
21151
21167
  function getSequentialPresetNames() {
21152
- return internal.getColorSchemeNames('sequential')
21153
- .concat(internal.getColorSchemeNames('rainbow'))
21154
- .filter(function(name) {
21155
- return !excludedPresets.includes(name);
21156
- });
21168
+ return flattenGroups(getPresetGroups('sequential'));
21157
21169
  }
21158
21170
 
21159
21171
  function getDivergingPresetNames() {
21160
- return internal.getColorSchemeNames('diverging');
21172
+ return flattenGroups(getPresetGroups('diverging'));
21161
21173
  }
21162
21174
 
21163
21175
  function getCategoricalPresetNames() {
21164
- return internal.getColorSchemeNames('categorical');
21176
+ return flattenGroups(getPresetGroups('categorical'));
21177
+ }
21178
+
21179
+ // The presets of a scheme type, by source, for the palette menu:
21180
+ // [{source, names}]. Sequential presets include -classify's multi-hue
21181
+ // ('rainbow') schemes.
21182
+ function getPresetGroups(type) {
21183
+ var types = type == 'sequential' ? ['sequential', 'rainbow'] : [type];
21184
+ return internal.getColorSchemeGroups(types).map(function(group) {
21185
+ return {source: group.source, names: group.names.filter(function(name) {
21186
+ return !excludedPresets.includes(name);
21187
+ })};
21188
+ }).filter(function(group) {
21189
+ return group.names.length > 0;
21190
+ });
21191
+ }
21192
+
21193
+ function flattenGroups(groups) {
21194
+ return groups.reduce(function(memo, group) { return memo.concat(group.names); }, []);
21165
21195
  }
21166
21196
 
21167
21197
  // The scheme a panel tab starts with on a layer
@@ -21594,7 +21624,8 @@
21594
21624
  });
21595
21625
  }
21596
21626
  if (scheme.preset) {
21597
- colors = getPresetColors(scheme.preset, getRampSize(scheme));
21627
+ colors = scheme.range ? getPresetSection(scheme, getRampSize(scheme), scheme.range) :
21628
+ getPresetColors(scheme.preset, getRampSize(scheme));
21598
21629
  if (scheme.reversed) colors.reverse();
21599
21630
  return colors.map(function(color) {
21600
21631
  return {color: color, pinned: false, adjusted: false};
@@ -21628,6 +21659,88 @@
21628
21659
  return internal.getColorRamp(name, n).map(toHex);
21629
21660
  }
21630
21661
 
21662
+ // The part of a sequential or diverging preset that its tiles are taken
21663
+ // from: {start, end, base}, 0-1 in the preset's own direction (before
21664
+ // reversing). A diverging range is the same on both sides of the center.
21665
+ // base is the number of tiles when the range was first narrowed: a preset
21666
+ // with a hand-picked set of that size (ColorBrewer's) is interpolated
21667
+ // between the set's colors, so that removing an end tile leaves the others
21668
+ // as they were.
21669
+ var minRangeSpan = 0.1;
21670
+
21671
+ function getSchemeRange(scheme) {
21672
+ return scheme.range || {start: 0, end: 1, base: getRampSize(scheme)};
21673
+ }
21674
+
21675
+ function hasSchemeRange(scheme) {
21676
+ return !!scheme.preset && scheme.type != 'categorical';
21677
+ }
21678
+
21679
+ // The range as positions along the tiles, left to right: [left, right]
21680
+ function getDisplayRange(scheme) {
21681
+ var range = getSchemeRange(scheme);
21682
+ return scheme.reversed ? [1 - range.end, 1 - range.start] : [range.start, range.end];
21683
+ }
21684
+
21685
+ // Moves one end of the range, given as a position along the tiles (0-1,
21686
+ // left to right); a diverging range moves at both ends.
21687
+ // side: 'left' or 'right'
21688
+ function setSchemeRangeEnd(scheme, side, pos) {
21689
+ var display = getDisplayRange(scheme);
21690
+ var left = display[0], right = display[1];
21691
+ pos = clamp$4(+pos || 0, 0, 1);
21692
+ if (scheme.type == 'diverging') {
21693
+ left = side == 'left' ? pos : 1 - pos;
21694
+ left = clamp$4(left, 0, (1 - minRangeSpan) / 2);
21695
+ right = 1 - left;
21696
+ } else if (side == 'left') {
21697
+ left = Math.min(pos, right - minRangeSpan);
21698
+ } else {
21699
+ right = Math.max(pos, left + minRangeSpan);
21700
+ }
21701
+ return setDisplayRange(scheme, left, right);
21702
+ }
21703
+
21704
+ function resetSchemeRange(scheme) {
21705
+ return Object.assign({}, scheme, {range: null});
21706
+ }
21707
+
21708
+ // Takes the tile at one end of a sequential preset away, keeping the colors
21709
+ // of the others: the range ends where the next tile was.
21710
+ // side: 'left' or 'right'
21711
+ function removeEndTile(scheme, side) {
21712
+ var display, step;
21713
+ if (!canRemoveEndTile(scheme)) return scheme;
21714
+ display = getDisplayRange(scheme);
21715
+ step = (display[1] - display[0]) / (scheme.n - 1);
21716
+ if (side == 'left') display[0] += step;
21717
+ else display[1] -= step;
21718
+ return Object.assign(setDisplayRange(scheme, display[0], display[1]), {n: scheme.n - 1});
21719
+ }
21720
+
21721
+ function canRemoveEndTile(scheme) {
21722
+ return hasSchemeRange(scheme) && scheme.type == 'sequential' &&
21723
+ scheme.n > getMinSchemeColors(scheme);
21724
+ }
21725
+
21726
+ function setDisplayRange(scheme, left, right) {
21727
+ var base = getSchemeRange(scheme).base;
21728
+ var start = scheme.reversed ? 1 - right : left;
21729
+ var end = scheme.reversed ? 1 - left : right;
21730
+ if (start <= 0 && end >= 1) return resetSchemeRange(scheme);
21731
+ return Object.assign({}, scheme, {range: {start: Math.max(start, 0), end: Math.min(end, 1), base: base}});
21732
+ }
21733
+
21734
+ // The whole of a preset, left to right, as the range's strip shows it
21735
+ function getRangeStripColors(scheme, n) {
21736
+ var colors = getPresetSection(scheme, n, {start: 0, end: 1, base: getSchemeRange(scheme).base});
21737
+ return scheme.reversed ? colors.reverse() : colors;
21738
+ }
21739
+
21740
+ function getPresetSection(scheme, n, range) {
21741
+ return internal.getColorRampSection(scheme.preset, n, range.start, range.end, range.base).map(toHex);
21742
+ }
21743
+
21631
21744
  // All the swatches of a categorical scheme, in order: the first n are used
21632
21745
  function getCategoricalPalette(scheme) {
21633
21746
  var colors;
@@ -21671,7 +21784,7 @@
21671
21784
  next.n = clampColorCount(next, next.n, count);
21672
21785
  return next;
21673
21786
  }
21674
- return Object.assign({}, scheme, {preset: name, reversed: false, pins: null});
21787
+ return Object.assign({}, scheme, {preset: name, reversed: false, pins: null, range: null});
21675
21788
  }
21676
21789
 
21677
21790
  // A preset as a custom ramp, pinned at its ends, for editing.
@@ -21685,6 +21798,7 @@
21685
21798
  return Object.assign({}, scheme, {
21686
21799
  preset: null,
21687
21800
  reversed: false,
21801
+ range: null,
21688
21802
  pins: scheme.type == 'diverging' ?
21689
21803
  [{t: 0, color: colors[0]}, {t: 0.5, color: colors[(colors.length - 1) / 2]},
21690
21804
  {t: 1, color: colors[colors.length - 1]}] :
@@ -21969,6 +22083,7 @@
21969
22083
  var paletteBtn, paletteMenu, countField, tileRow, gradientEl, tilesEl, picker, fieldRow, fieldSelect, methodSelect,
21970
22084
  noFieldsNote, selectionNote, controlsEl, vibranceRow, vibranceInput,
21971
22085
  longHueBtn, continuousBtn, reverseBtn, shuffleBtn, dropMarker, nullControl, nullCount, countLabel,
22086
+ rangeEl, rangeStrip, rangeShades, rangeHandles,
21972
22087
  divergingEl, pivotSelect, pivotInput, pivotNote, neutralToggle, splitSelect;
21973
22088
  // set while a tile is being dragged, so that letting go isn't a click
21974
22089
  var tileDrag = null;
@@ -22126,6 +22241,7 @@
22126
22241
  changeScheme(setSchemeVibrance(scheme, val / 1000));
22127
22242
  });
22128
22243
  vibranceInput = vibranceRow.findChild('input');
22244
+ initRangeControl(vibranceRow);
22129
22245
  longHueBtn = addIconButton(vibranceRow, 'Go the long way around the color wheel', longHueIcon, function() {
22130
22246
  changeScheme(setSchemeLongHue(scheme, !scheme.longHue));
22131
22247
  }).addClass('long-hue-btn');
@@ -22326,6 +22442,7 @@
22326
22442
  var input = El('input').attr('type', 'range').attr('min', min).attr('max', max).attr('step', step)
22327
22443
  .attr('aria-label', label).appendTo(row)
22328
22444
  .on('input', function() {
22445
+ showSliderFill(input);
22329
22446
  onInput(+input.node().value);
22330
22447
  })
22331
22448
  .on('change', releaseFocus);
@@ -22340,12 +22457,109 @@
22340
22457
  return btn;
22341
22458
  }
22342
22459
 
22460
+ // The part of a preset that the tiles are taken from: a strip of the whole
22461
+ // ramp, shaded outside the part in use, with a handle at each end of it
22462
+ function initRangeControl(row) {
22463
+ var label = El('span').addClass('color-scheme-hint-label color-scheme-range-part')
22464
+ .attr('data-tooltip', 'Use part of the color ramp\n(double-click the strip to use all of it)')
22465
+ .appendTo(row).text('Range')
22466
+ .on('mouseenter', function() { keepTooltipInWindow(label.node()); });
22467
+ rangeEl = El('div').addClass('color-scheme-range color-scheme-range-part').appendTo(row)
22468
+ .on('pointerdown', startRangeDrag)
22469
+ .on('dblclick', function() {
22470
+ changeScheme(resetSchemeRange(scheme));
22471
+ });
22472
+ rangeStrip = El('div').addClass('color-scheme-range-strip').appendTo(rangeEl);
22473
+ rangeShades = ['left', 'right'].map(function(side) {
22474
+ return El('div').addClass('color-scheme-range-shade ' + side).appendTo(rangeEl);
22475
+ });
22476
+ rangeHandles = ['left', 'right'].map(function(side) {
22477
+ return El('div').addClass('color-scheme-range-handle').attr('role', 'slider').attr('tabindex', '0')
22478
+ .attr('aria-label', side == 'left' ? 'Start of range' : 'End of range')
22479
+ .attr('aria-valuemin', '0').attr('aria-valuemax', '100')
22480
+ .appendTo(rangeEl)
22481
+ .on('keydown', function(e) {
22482
+ onRangeKey(e, side);
22483
+ });
22484
+ });
22485
+ }
22486
+
22487
+ function renderRange() {
22488
+ var display, colors;
22489
+ if (!hasSchemeRange(scheme)) return;
22490
+ display = getDisplayRange(scheme);
22491
+ colors = getRangeStripColors(scheme, 33);
22492
+ rangeStrip.css('background-image', 'linear-gradient(to right, ' + colors.join(', ') + ')');
22493
+ rangeShades[0].css('width', pct(display[0]));
22494
+ rangeShades[1].css('width', pct(1 - display[1]));
22495
+ rangeHandles.forEach(function(handle, i) {
22496
+ handle.css('left', pct(display[i])).attr('aria-valuenow', String(Math.round(display[i] * 100)));
22497
+ });
22498
+ }
22499
+
22500
+ function pct(val) {
22501
+ return round(val * 100) + '%';
22502
+ }
22503
+
22504
+ // Dragging a handle (or pressing the strip, which takes the nearer handle
22505
+ // there) moves that end of the range
22506
+ function startRangeDrag(e) {
22507
+ var box = rangeStrip.node().getBoundingClientRect();
22508
+ var display = getDisplayRange(scheme);
22509
+ var pos = getPos(e);
22510
+ var side = e.target == rangeHandles[0].node() ? 'left' :
22511
+ e.target == rangeHandles[1].node() ? 'right' :
22512
+ Math.abs(pos - display[0]) <= Math.abs(pos - display[1]) ? 'left' : 'right';
22513
+ if (e.button !== 0 || !(box.width > 0)) return;
22514
+ e.preventDefault();
22515
+ picker.hide();
22516
+ move(e);
22517
+ document.addEventListener('pointermove', move);
22518
+ document.addEventListener('pointerup', finish);
22519
+ document.addEventListener('pointercancel', finish);
22520
+
22521
+ // in steps of half a percent, so that a drag runs fewer commands
22522
+ function getPos(e) {
22523
+ return Math.round((e.clientX - box.left) / box.width * 200) / 200;
22524
+ }
22525
+
22526
+ function move(e) {
22527
+ var next = setSchemeRangeEnd(scheme, side, getPos(e));
22528
+ if (getDisplayRange(next).join() != getDisplayRange(scheme).join()) changeScheme(next);
22529
+ }
22530
+
22531
+ function finish() {
22532
+ document.removeEventListener('pointermove', move);
22533
+ document.removeEventListener('pointerup', finish);
22534
+ document.removeEventListener('pointercancel', finish);
22535
+ }
22536
+ }
22537
+
22538
+ function onRangeKey(e, side) {
22539
+ var step = e.shiftKey ? 0.05 : 0.01;
22540
+ var display = getDisplayRange(scheme);
22541
+ var pos = side == 'left' ? display[0] : display[1];
22542
+ if (e.key == 'ArrowLeft' || e.key == 'ArrowDown') {
22543
+ pos -= step;
22544
+ } else if (e.key == 'ArrowRight' || e.key == 'ArrowUp') {
22545
+ pos += step;
22546
+ } else {
22547
+ return;
22548
+ }
22549
+ e.preventDefault();
22550
+ e.stopPropagation();
22551
+ changeScheme(setSchemeRangeEnd(scheme, side, pos));
22552
+ }
22553
+
22343
22554
  // Presets and categorical schemes have no interpolated tiles for vibrance
22344
- // or the hue path to change; the row keeps only the reverse button for them.
22555
+ // or the hue path to change; the row keeps only the reverse button for them,
22556
+ // and for sequential and diverging presets, the range.
22345
22557
  function renderVibrance() {
22346
22558
  var vibrance = getSchemeVibrance(scheme);
22347
22559
  setSliderValue(vibranceInput, Math.round(vibrance * 1000));
22348
22560
  vibranceRow.classed('preset', !!scheme.preset || scheme.type == 'categorical');
22561
+ vibranceRow.classed('ranged', hasSchemeRange(scheme));
22562
+ renderRange();
22349
22563
  reverseBtn.classed('hidden', scheme.type == 'categorical');
22350
22564
  shuffleBtn.classed('hidden', scheme.type != 'categorical');
22351
22565
  // each half of a diverging ramp runs from a low-chroma center, where the
@@ -22360,6 +22574,16 @@
22360
22574
 
22361
22575
  function setSliderValue(input, val) {
22362
22576
  if (input.node().value != val) input.node().value = val;
22577
+ showSliderFill(input);
22578
+ }
22579
+
22580
+ // the track is filled up to the center of the handle, which travels the
22581
+ // track's width less its 12px box (see page.css)
22582
+ function showSliderFill(input) {
22583
+ var el = input.node();
22584
+ var min = +el.min, max = +el.max;
22585
+ var fill = max > min ? (el.value - min) / (max - min) : 0;
22586
+ el.style.setProperty('--fill', 'calc(6px + (100% - 12px) * ' + round(fill * 1000) / 1000 + ')');
22363
22587
  }
22364
22588
 
22365
22589
  function renderFieldOptions(fields) {
@@ -22389,6 +22613,8 @@
22389
22613
  var classLabels = categorical ? null : continuous ? getStopLabels() : getClassLabels(tileUse);
22390
22614
  var groups = categorical && scheme.method == 'categorical' ?
22391
22615
  getSwatchCategories(getCategories(targetLayer, scheme.field), used) : null;
22616
+ // the end tiles of a sequential preset can be taken away
22617
+ var removable = canRemoveEndTile(scheme);
22392
22618
  var n, perRow;
22393
22619
  // a categorical scheme shows its whole palette, and marks the swatches
22394
22620
  // in use
@@ -22423,6 +22649,14 @@
22423
22649
  startTileDrag(e, i);
22424
22650
  });
22425
22651
  }
22652
+ if (removable && (i === 0 || i == n - 1)) {
22653
+ El('button').addClass('color-scheme-tile-remove').attr('type', 'button')
22654
+ .attr('aria-label', 'Remove this color').text('×').appendTo(tileEl)
22655
+ .on('click', function(e) {
22656
+ e.stopPropagation();
22657
+ changeScheme(removeEndTile(scheme, i === 0 ? 'left' : 'right'));
22658
+ });
22659
+ }
22426
22660
  if (groups && inUse || classLabels && classLabels[i]) {
22427
22661
  tileEl.attr('data-tooltip', groups ? formatCategories(groups[i]) : classLabels[i])
22428
22662
  .on('mouseenter', function() { keepTooltipInWindow(tileEl.node()); });
@@ -22674,16 +22908,17 @@
22674
22908
 
22675
22909
  function renderPaletteMenu() {
22676
22910
  var categorical = scheme.type == 'categorical';
22677
- var names = categorical ? getCategoricalPresetNames() :
22678
- scheme.type == 'diverging' ? getDivergingPresetNames() : getSequentialPresetNames();
22679
22911
  paletteMenu.empty();
22680
22912
  addPaletteItem('Custom', getSchemeColors(makeSchemeCustom(scheme)), !scheme.preset, function() {
22681
22913
  changeScheme(makeSchemeCustom(scheme));
22682
22914
  });
22683
- names.forEach(function(name) {
22684
- var colors = categorical ? getCategoricalPresetColors(name) : getPresetColors(name, 7);
22685
- addPaletteItem(name, colors, scheme.preset == name, function() {
22686
- changeScheme(choosePreset(scheme, name, getCategoryCount()));
22915
+ getPresetGroups(scheme.type).forEach(function(group) {
22916
+ El('div').addClass('color-scheme-palette-heading').appendTo(paletteMenu).text(group.source);
22917
+ group.names.forEach(function(name) {
22918
+ var colors = categorical ? getCategoricalPresetColors(name) : getPresetColors(name, 7);
22919
+ addPaletteItem(name, colors, scheme.preset == name, function() {
22920
+ changeScheme(choosePreset(scheme, name, getCategoryCount()));
22921
+ });
22687
22922
  });
22688
22923
  });
22689
22924
  }
@@ -26293,9 +26528,20 @@
26293
26528
  _self.dispatchEvent('leave');
26294
26529
  }
26295
26530
 
26531
+ // mouseover and mouseout can arrive after a quick move has already pressed
26532
+ // and released the button somewhere else -- a click on a panel over the map
26533
+ // then looked like a click on the map. A press or release is over the area
26534
+ // if it lands on the area itself.
26535
+ function updateHover(e) {
26536
+ var over = !!e.target && element.contains(e.target);
26537
+ if (over && !_isOver) onAreaEnter();
26538
+ else if (!over && _isOver) onAreaOut();
26539
+ }
26540
+
26296
26541
  function onMouseUp(e) {
26297
- var evt = procMouseEvent(e),
26298
- elapsed, dx, dy;
26542
+ var evt, elapsed, dx, dy;
26543
+ updateHover(e);
26544
+ evt = procMouseEvent(e);
26299
26545
  _self.dispatchEvent('mouseup', evt);
26300
26546
  if (_dragging) {
26301
26547
  stopDragging(evt);
@@ -26317,6 +26563,7 @@
26317
26563
  }
26318
26564
 
26319
26565
  function onMouseDown(e) {
26566
+ updateHover(e);
26320
26567
  if (e.button != 2 && e.which != 3) { // ignore right-click
26321
26568
  _downEvt = procMouseEvent(e);
26322
26569
  }
package/www/mapshaper.js CHANGED
@@ -71333,7 +71333,7 @@ ${css.join('\n')}
71333
71333
  return new Rgb(o.r, o.g, o.b, o.opacity);
71334
71334
  }
71335
71335
 
71336
- function rgb$1(r, g, b, opacity) {
71336
+ function rgb(r, g, b, opacity) {
71337
71337
  return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
71338
71338
  }
71339
71339
 
@@ -71344,7 +71344,7 @@ ${css.join('\n')}
71344
71344
  this.opacity = +opacity;
71345
71345
  }
71346
71346
 
71347
- define(Rgb, rgb$1, extend(Color, {
71347
+ define(Rgb, rgb, extend(Color, {
71348
71348
  brighter(k) {
71349
71349
  k = k == null ? brighter : Math.pow(brighter, k);
71350
71350
  return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
@@ -71606,11 +71606,11 @@ ${css.join('\n')}
71606
71606
  return d ? linear(a, d) : constant(isNaN(a) ? b : a);
71607
71607
  }
71608
71608
 
71609
- var rgb = (function rgbGamma(y) {
71609
+ var interpolateRgb = (function rgbGamma(y) {
71610
71610
  var color = gamma(y);
71611
71611
 
71612
- function rgb(start, end) {
71613
- var r = color((start = rgb$1(start)).r, (end = rgb$1(end)).r),
71612
+ function rgb$1(start, end) {
71613
+ var r = color((start = rgb(start)).r, (end = rgb(end)).r),
71614
71614
  g = color(start.g, end.g),
71615
71615
  b = color(start.b, end.b),
71616
71616
  opacity = nogamma(start.opacity, end.opacity);
@@ -71623,9 +71623,9 @@ ${css.join('\n')}
71623
71623
  };
71624
71624
  }
71625
71625
 
71626
- rgb.gamma = rgbGamma;
71626
+ rgb$1.gamma = rgbGamma;
71627
71627
 
71628
- return rgb;
71628
+ return rgb$1;
71629
71629
  })(1);
71630
71630
 
71631
71631
  function rgbSpline(spline) {
@@ -71636,7 +71636,7 @@ ${css.join('\n')}
71636
71636
  b = new Array(n),
71637
71637
  i, color;
71638
71638
  for (i = 0; i < n; ++i) {
71639
- color = rgb$1(colors[i]);
71639
+ color = rgb(colors[i]);
71640
71640
  r[i] = color.r || 0;
71641
71641
  g[i] = color.g || 0;
71642
71642
  b[i] = color.b || 0;
@@ -71789,8 +71789,8 @@ ${css.join('\n')}
71789
71789
  var t = typeof b, c;
71790
71790
  return b == null || t === "boolean" ? constant(b)
71791
71791
  : (t === "number" ? number
71792
- : t === "string" ? ((c = color(b)) ? (b = c, rgb) : string)
71793
- : b instanceof color ? rgb
71792
+ : t === "string" ? ((c = color(b)) ? (b = c, interpolateRgb) : string)
71793
+ : b instanceof color ? interpolateRgb
71794
71794
  : b instanceof Date ? date
71795
71795
  : isNumberArray(b) ? numberArray
71796
71796
  : Array.isArray(b) ? genericArray
@@ -71825,6 +71825,16 @@ ${css.join('\n')}
71825
71825
  cubehelix$1(hue);
71826
71826
  var cubehelixLong = cubehelix$1(nogamma);
71827
71827
 
71828
+ function piecewise(interpolate, values) {
71829
+ if (values === undefined) values = interpolate, interpolate = d3_interpolate;
71830
+ var i = 0, n = values.length - 1, v = values[0], I = new Array(n < 0 ? 0 : n);
71831
+ while (i < n) I[i] = interpolate(v, v = values[++i]);
71832
+ return function(t) {
71833
+ var i = Math.max(0, Math.min(n - 1, Math.floor(t *= n)));
71834
+ return I[i](t - i);
71835
+ };
71836
+ }
71837
+
71828
71838
  // OKLab conversion (Björn Ottosson, https://bottosson.github.io/posts/oklab/)
71829
71839
  // RGB objects use 0-255 channels, as returned by parseColor().
71830
71840
 
@@ -73968,7 +73978,7 @@ ${css.join('\n')}
73968
73978
  return c$1 + "";
73969
73979
  }
73970
73980
 
73971
- var c = rgb$1(),
73981
+ var c = rgb(),
73972
73982
  pi_1_3 = Math.PI / 3,
73973
73983
  pi_2_3 = Math.PI * 2 / 3;
73974
73984
 
@@ -74084,6 +74094,59 @@ ${css.join('\n')}
74084
74094
  schemeYlOrRd: scheme$6
74085
74095
  });
74086
74096
 
74097
+ // Scientific colour maps, version 8.0.1, by Fabio Crameri
74098
+ // https://www.fabiocrameri.ch/colourmaps/ (https://doi.org/10.5281/zenodo.8409685)
74099
+ //
74100
+ // Each ramp is 33 evenly spaced colors (as packed hex), sampled from the
74101
+ // 256-color version, which they reproduce to within 0.008 OKLab deltaE; the
74102
+ // odd count gives diverging ramps a color at their center. batlowS is the
74103
+ // first 20 swatches of batlow's categorical palette.
74104
+ //
74105
+ // The Scientific colour maps are licensed under a MIT License
74106
+ // Copyright (c) 2023, Fabio Crameri
74107
+ // Permission is hereby granted, free of charge, to any person obtaining a
74108
+ // copy of this software and associated documentation files (the "Software"),
74109
+ // to deal in the Software without restriction, including without limitation
74110
+ // the rights to use, copy, modify, merge, publish, distribute, sublicense,
74111
+ // and/or sell copies of the Software, and to permit persons to whom the
74112
+ // Software is furnished to do so, subject to the following conditions:
74113
+ // The above copyright notice and this permission notice shall be included in
74114
+ // all copies or substantial portions of the Software.
74115
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
74116
+ // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
74117
+ // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
74118
+ // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
74119
+ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
74120
+ // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
74121
+ // DEALINGS IN THE SOFTWARE.
74122
+
74123
+ var crameriSequential = {
74124
+ batlow: '01195908255b0d315d0f3b5f114360134b611652621b59622260612a655e356a59406f544d734d597646667a3f737e3881823290862da08a2bb08d2ebf9035ce923fdb954ce8985bf29d6cf8a27efca891fdaea3fdb4b4fdbac5fcc0d6fbc6e8faccfa',
74125
+ batlowW: '01195908255b0d315d0f3b5f114360134a611651621a5862205f6228655f326a5c3d6f5749745155794b627d446f823e7d87388c8c339d9232ae9838be9d44cca154d7a565e0a875e8ac84efb094f5b8a6fbc3bafed1ceffdfddffebeafff5f5fffefe',
74126
+ acton: '260d402d17493420523a2a5a413362473b6a4d4472534c79595481615b876a608b74628d7d638e87648e91648f9c658fa76690b36791bf6a93c97097cf789fd482a7d78db0da97b9dda2c2e0accae3b6d2e5c0dae8cae1ead3e8ecdbeeeee3f4f0eafa',
74127
+ bamako: '003b47043d45083f430c424010453e14483b194b381f4e342552312b562d325b29395f2440642048691b516f16597410627a0b6b7f057584017f87008a8900948c019f9108a99815b4a122bfa930cab240d4bb52ddc465e6cc78efd58af7dd9cffe5ad',
74128
+ bilbao: '4c0001580b1064161a6e202478292e8232398b3b4293444a994e509c56549f5d56a16458a26a59a4705aa6765ca77c5da9825eaa885fac8e61ae9463b09c66b4a46eb8ac7bbcb389bfb897c2bda4c5c2b0c9c7bccfcdc8d7d7d5e3e3e2f1f1f1ffffff',
74129
+ davos: '00054a031256081c610e276c1431761a3c802146892850902f5a9636639a3e6b9c46729d4e789d557e9b5d84996489966c8d937392907b978d839d8a8ba38895aa87a0b289adbc8dbcc894cbd49fdadfade6e9bceff0cbf6f6d9faf9e6fcfcf3fefefe',
74130
+ devon: '2c1a4c2b21542a285b29306329376a283f7227477b274f8429588f2c5f9a3265a5386bb04271bc4e78c65e80cf6e87d67d8edd8c95e29a9ce7a6a3ebb0aaeeb7b1f0beb8f2c4bff3cbc6f4d1cdf6d7d4f7dedbf8e4e2faebe9fbf2f0fcf8f8feffffff',
74131
+ lajolla: '191900201c04271e082f210d3724114127164c2b1c592f22663429753931853d3895423fa64644b64a48c54f4ad1564cd95f4ede6a4fe1744fe37e50e58751e79152e99a52eba353edad54efb755f1c159f4cd62f7d972fae588fcef9ffef7b6fffecb',
74132
+ lapaz: '1a0c641d176b1f207122297824327e263a842842892a4a8e2c52932f5a9733629b386a9e3d71a04378a24a7fa35286a45b8ca36591a27096a07a9b9e859e9b90a1999ba496a7a895b4ac96c2b299d0baa1dec4aceaceb9f3d8c8f9e1d6fceae5fef2f3',
74133
+ oslo: '010101050a100a121a0d18240e1e2e0f2439112a4413314f15395b1840671c4773214f7f26568c2d5e993667a54270b14f7abc5c83c3678bc77292c97c99ca859fca8fa4c998aac9a2b0caacb7cbb7bfcdc2c7d1ced1d7dadcdfe6e7e9f3f3f4ffffff',
74134
+ tokyo: '1c0e3429123837163d441d415024465b2d4963364c683f4e6b47506e4e506f5351705951715d52716152726652736a53746f53757554767c54778355798c567b95587e9f5b81ab5f87b7668fc3709ad17da8dd8eb8e9a2c9f1b4d8f7c5e5fad2effcdd',
74135
+ turku: '0000000e0e0d18181620201d28282330302a39382f41413549493951513e5a59426261456a6a4973724d7c7a51878355928b5a9e9360ab9a66b79f6dc2a373cca579d5a780dda887e4aa90ebae9af2b4a5f7bbb1fbc3bdfdccc8fed5d3ffdddcffe6e6'
74136
+ };
74137
+
74138
+ var crameriDiverging = {
74139
+ bam: '65024b77175d88266e97357da5428cb25099bd5ea5c76db0d17ebbd990c6e0a2d0e6b4d9ecc5e2f1d4e9f4e1eef6ebf1f6f1f1f3f3ecedf2e3e4eed4d7e7c1c7deaab4d191a0c3798cb5657aa6546999465a8c3a4c802f3e7425306819205a0d0d4c00',
74140
+ broc: '2c1a4c2b26582a3164293e70294a7d2d588939669449749f5a82a86c8fb27e9dbc91acc5a4bacfb7c8d9cad7e3dde5ebebeeecedeee0e7e7ceddddbcd4d4a9c9c995bbbb82abab709b9b618b8b547b7b476c6c3a5d5d2d4e4e2140401632330c262600',
74141
+ cork: '2c194c2b26592a3265283f71284b7e2d588a38669446729e567ea6668bae7798b889a6c19db4cbb1c4d6c7d4e1dbe4ebe6edecdfeae0cedfcebbd2bba8c5a794b89481ab816e9e6e5d935c4c884c3c7c3c2d702c20621e18541414450e1137090f2903',
74142
+ roma: '7e1700862c068e3c0c964b129d5818a3651ea97223af7e2ab68c32bd9a3cc4aa4acaba5cd0c971d2d789d1e19fcbe8b3c1eac2b2e9cda1e4d48ddcd778d2d764c5d452b8d044aacc399dc63190c12b83bc2677b7226ab11e5dab184fa511409f033198',
74143
+ vik: '001261021f69022b710237790344810450890c5e921b6d9b2f7ca6478db1609dbc79adc792bdd2acccdcc5dbe5dce5e9ece5e1eedacfe9cbb9e2bba4dcab8fd59c7bcf8e68c97f55c37243bc6331b3531fa5400e932e06832106741506660a07590008'
74144
+ };
74145
+
74146
+ var crameriCategorical = {
74147
+ batlowS: '011959faccfa828231226061f29d6d4d734d114360c09036fdb4b4dd954d356a59fcbfd6175262677b3ea18a2b0d315dfca890fbc6e82b655eb18d2f'
74148
+ };
74149
+
74087
74150
  var index = {
74088
74151
  categorical: [],
74089
74152
  sequential: [],
@@ -74092,10 +74155,29 @@ ${css.join('\n')}
74092
74155
  all: []
74093
74156
  };
74094
74157
  var ramps;
74158
+ // interpolators of the ramps that are stored as stops (not from d3)
74159
+ var stopInterpolators;
74160
+ // scheme name -> where the scheme comes from (see getColorSchemeGroups())
74161
+ var sources;
74162
+ // the order of the sources in lists of schemes
74163
+ var sourceOrder = ['ColorBrewer', 'Tableau', 'Matplotlib', 'Crameri', 'd3'];
74164
+ // Schemes are listed by their designers, as far as they're known. 'd3' is
74165
+ // d3-scale-chromatic's own schemes, and others that it brings in: Turbo
74166
+ // (Google) and CubehelixDefault (D. A. Green's cubehelix).
74167
+ var d3Sources = {
74168
+ ColorBrewer: 'Accent,Dark2,Paired,Pastel1,Pastel2,Set1,Set2,Set3,' +
74169
+ 'Blues,Greens,Greys,Purples,Reds,Oranges,BuGn,BuPu,GnBu,OrRd,PuBuGn,PuBu,PuRd,RdPu,YlGnBu,YlGn,YlOrBr,YlOrRd,' +
74170
+ 'BrBG,PRGn,PiYG,PuOr,RdBu,RdGy,RdYlBu,RdYlGn,Spectral',
74171
+ Tableau: 'Tableau10,Tableau20',
74172
+ Matplotlib: 'Cividis,Viridis,Magma,Inferno,Plasma',
74173
+ d3: 'Category10,Category20,Category20b,Category20c,CubehelixDefault,Rainbow,Warm,Cool,Sinebow,Turbo'
74174
+ };
74095
74175
 
74096
74176
  function initSchemes() {
74097
74177
  if (ramps) return;
74098
74178
  ramps = {};
74179
+ stopInterpolators = {};
74180
+ sources = {};
74099
74181
  addSchemesFromD3('categorical', 'Category10,Accent,Dark2,Paired,Pastel1,Pastel2,Set1,Set2,Set3,Tableau10');
74100
74182
  addSchemesFromD3('sequential', 'Blues,Greens,Greys,Purples,Reds,Oranges,BuGn,BuPu,GnBu,OrRd,PuBuGn,PuBu,PuRd,RdPu,YlGnBu,YlGn,YlOrBr,YlOrRd');
74101
74183
  addSchemesFromD3('rainbow', 'Cividis,CubehelixDefault,Rainbow,Warm,Cool,Sinebow,Turbo,Viridis,Magma,Inferno,Plasma');
@@ -74109,9 +74191,29 @@ ${css.join('\n')}
74109
74191
  '3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9');
74110
74192
  addCategoricalScheme('Tableau20',
74111
74193
  '4c78a89ecae9f58518ffbf7954a24b88d27ab79a20f2cf5b43989483bcb6e45756ff9d9879706ebab0acd67195fcbfd2b279a2d6a5c99e765fd8b5a5');
74194
+ Object.keys(d3Sources).forEach(function(source) {
74195
+ d3Sources[source].split(',').forEach(function(name) {
74196
+ sources[name] = source;
74197
+ });
74198
+ });
74199
+ addStoppedSchemes('sequential', crameriSequential, 'Crameri');
74200
+ addStoppedSchemes('diverging', crameriDiverging, 'Crameri');
74201
+ Object.keys(crameriCategorical).forEach(function(name) {
74202
+ addCategoricalScheme(name, crameriCategorical[name]);
74203
+ sources[name] = 'Crameri';
74204
+ });
74112
74205
  index.all = [].concat(index.sequential, index.rainbow, index.diverging, index.categorical);
74113
74206
  }
74114
74207
 
74208
+ // Ramps stored as evenly spaced colors, interpolated linearly between them
74209
+ function addStoppedSchemes(type, schemes, source) {
74210
+ Object.keys(schemes).forEach(function(name) {
74211
+ index[type].push(name);
74212
+ stopInterpolators[name] = piecewise(interpolateRgb, unpackRamp(schemes[name]));
74213
+ sources[name] = source;
74214
+ });
74215
+ }
74216
+
74115
74217
  function standardName(name) {
74116
74218
  if (!name) return null;
74117
74219
  var lcname = name.toLowerCase();
@@ -74173,12 +74275,15 @@ ${css.join('\n')}
74173
74275
  }
74174
74276
 
74175
74277
  function printColorSchemeNames() {
74278
+ var types = [['categorical', 'Categorical'], ['sequential', 'Sequential'],
74279
+ ['diverging', 'Diverging'], ['rainbow', 'Multi-hue/rainbow']];
74176
74280
  initSchemes();
74177
- print('Built-in color schemes (from d3):');
74178
- print ('Categorical\n' + formatStringsAsGrid(index.categorical));
74179
- print ('\nSequential\n' + formatStringsAsGrid(index.sequential));
74180
- print ('\nDiverging\n' + formatStringsAsGrid(index.diverging));
74181
- print ('\nMulti-hue/rainbow\n' + formatStringsAsGrid(index.rainbow));
74281
+ print('Built-in color schemes');
74282
+ types.forEach(function(type) {
74283
+ getColorSchemeGroups(type[0]).forEach(function(group) {
74284
+ print('\n' + type[1] + ' (' + group.source + ')\n' + formatStringsAsGrid(group.names));
74285
+ });
74286
+ });
74182
74287
  }
74183
74288
 
74184
74289
  // type: categorical, sequential, rainbow or diverging
@@ -74188,6 +74293,19 @@ ${css.join('\n')}
74188
74293
  return index[type].concat();
74189
74294
  }
74190
74295
 
74296
+ // The schemes of one or more types, by source: [{source, names}]
74297
+ // (sources: ColorBrewer, Tableau, Matplotlib, Crameri, d3)
74298
+ function getColorSchemeGroups(types) {
74299
+ var names = [].concat(types).reduce(function(memo, type) {
74300
+ return memo.concat(getColorSchemeNames(type));
74301
+ }, []);
74302
+ return sourceOrder.map(function(source) {
74303
+ return {source: source, names: names.filter(function(name) { return sources[name] == source; })};
74304
+ }).filter(function(group) {
74305
+ return group.names.length > 0;
74306
+ });
74307
+ }
74308
+
74191
74309
  function pickRandomColorScheme(type) {
74192
74310
  initSchemes();
74193
74311
  var names = index[type];
@@ -74267,7 +74385,7 @@ ${css.join('\n')}
74267
74385
  initSchemes();
74268
74386
  name = standardName(name);
74269
74387
  var ramps = d3Scales['scheme' + name];
74270
- var interpolate = d3Scales['interpolate' + name];
74388
+ var interpolate = d3Scales['interpolate' + name] || stopInterpolators[name];
74271
74389
  var ramp;
74272
74390
  if (!ramps && !interpolate) {
74273
74391
  stop$1('Unknown color scheme name:', name);
@@ -74286,6 +74404,26 @@ ${css.join('\n')}
74286
74404
  return ramp;
74287
74405
  }
74288
74406
 
74407
+ // n colors from part of a ramp, evenly spaced from start to end (0-1).
74408
+ // base: interpolate between the colors of the scheme's set of this size, if
74409
+ // it has one (ColorBrewer's hand-picked sets), so that a section of a set
74410
+ // keeps its colors; otherwise the scheme's own interpolator is used
74411
+ function getColorRampSection(name, n, start, end, base) {
74412
+ initSchemes();
74413
+ name = standardName(name);
74414
+ var sets = d3Scales['scheme' + name];
74415
+ var interpolate = d3Scales['interpolate' + name] || stopInterpolators[name];
74416
+ var colors = [];
74417
+ if (!interpolate || index.categorical.includes(name)) {
74418
+ stop$1('Not a sequential or diverging color scheme:', name);
74419
+ }
74420
+ if (sets && sets[base]) interpolate = piecewise(interpolateRgb, sets[base]);
74421
+ for (var i=0; i<n; i++) {
74422
+ colors.push(interpolate(n > 1 ? start + (end - start) * i / (n - 1) : (start + end) / 2));
74423
+ }
74424
+ return colors;
74425
+ }
74426
+
74289
74427
  function getInterpolatedRamp(interpolate, n) {
74290
74428
  if (n > 0 === false || !utils.isInteger(n)) {
74291
74429
  error('Expected a positive integer');
@@ -74302,6 +74440,8 @@ ${css.join('\n')}
74302
74440
  getCategoricalColorScheme: getCategoricalColorScheme,
74303
74441
  getCategoricalColors: getCategoricalColors,
74304
74442
  getColorRamp: getColorRamp,
74443
+ getColorRampSection: getColorRampSection,
74444
+ getColorSchemeGroups: getColorSchemeGroups,
74305
74445
  getColorSchemeNames: getColorSchemeNames,
74306
74446
  getRandomizedCategoricalColorScheme: getRandomizedCategoricalColorScheme,
74307
74447
  isCategoricalColorScheme: isCategoricalColorScheme,
@@ -87771,7 +87911,7 @@ ${css.join('\n')}
87771
87911
  return name == 'rectangle' || name == 'rectangles' || name == 'filter' && opts.cleanup;
87772
87912
  }
87773
87913
 
87774
- var version = "0.7.74";
87914
+ var version = "0.7.76";
87775
87915
 
87776
87916
  // Parse command line args into commands and run them
87777
87917
  // Function takes an optional Node-style callback. A Promise is returned if no callback is given.
package/www/page.css CHANGED
@@ -3315,6 +3315,7 @@ body.pan.panning .map-layers:not(.drawing) {
3315
3315
  }
3316
3316
 
3317
3317
  .label-editing-status,
3318
+ .label-style-selection-row,
3318
3319
  .label-style-panel .label-style-row.label-style-selection-row > span {
3319
3320
  font-size: 12px;
3320
3321
  color: #555;
@@ -4758,6 +4759,13 @@ body.dragging-color-picker * {
4758
4759
  background-color: var(--lt-theme-col);
4759
4760
  }
4760
4761
 
4762
+ .color-scheme-palette-heading {
4763
+ padding: 7px 8px 2px;
4764
+ font-size: 11px;
4765
+ color: #888;
4766
+ cursor: default;
4767
+ }
4768
+
4761
4769
  .color-scheme-tile-row {
4762
4770
  margin-top: 10px;
4763
4771
  }
@@ -4966,23 +4974,162 @@ body.dragging-color-picker * {
4966
4974
  cursor: default;
4967
4975
  }
4968
4976
 
4977
+ /* Gray like the fields and buttons, and the same at rest, on hover and while
4978
+ dragged. --fill (set by the script) is how far the light gray part of the
4979
+ track goes. The handle is a 12px box, which sets how far it travels, drawn
4980
+ as a 16px circle by its box-shadow rings, so that at either end it covers
4981
+ the end of the track. */
4969
4982
  .color-scheme-slider-row input[type=range] {
4983
+ -webkit-appearance: none;
4984
+ appearance: none;
4970
4985
  flex: 1;
4971
4986
  min-width: 0;
4972
- margin: 0 5px 0 2px;
4973
- accent-color: var(--theme-col);
4987
+ height: 18px;
4988
+ margin: 0 7px 0 4px;
4989
+ background: transparent;
4990
+ cursor: pointer;
4991
+ }
4992
+
4993
+ .color-scheme-slider-row input[type=range]:focus {
4994
+ outline: none;
4995
+ }
4996
+
4997
+ .color-scheme-slider-row input[type=range]::-webkit-slider-runnable-track {
4998
+ box-sizing: border-box;
4999
+ height: 7px;
5000
+ border: 1px solid var(--label-field-border);
5001
+ border-radius: 3.5px;
5002
+ background: linear-gradient(to right, #dadada var(--fill, 0%), white var(--fill, 0%));
5003
+ }
5004
+
5005
+ .color-scheme-slider-row input[type=range]::-moz-range-track {
5006
+ box-sizing: border-box;
5007
+ height: 7px;
5008
+ border: 1px solid var(--label-field-border);
5009
+ border-radius: 3.5px;
5010
+ background: white;
5011
+ }
5012
+
5013
+ .color-scheme-slider-row input[type=range]::-moz-range-progress {
5014
+ height: 5px;
5015
+ border-radius: 3.5px 0 0 3.5px;
5016
+ background: #dadada;
4974
5017
  }
4975
5018
 
4976
- /* Presets have only the reverse button in the vibrance row */
5019
+ .color-scheme-slider-row input[type=range]::-webkit-slider-thumb {
5020
+ -webkit-appearance: none;
5021
+ width: 12px;
5022
+ height: 12px;
5023
+ margin-top: -3.5px;
5024
+ border: none;
5025
+ border-radius: 50%;
5026
+ background: white;
5027
+ box-shadow: 0 0 0 1px white, 0 0 0 2px #888;
5028
+ }
5029
+
5030
+ .color-scheme-slider-row input[type=range]::-moz-range-thumb {
5031
+ width: 12px;
5032
+ height: 12px;
5033
+ border: none;
5034
+ border-radius: 50%;
5035
+ background: white;
5036
+ box-shadow: 0 0 0 1px white, 0 0 0 2px #888;
5037
+ }
5038
+
5039
+ .color-scheme-slider-row input[type=range]:focus-visible::-webkit-slider-thumb {
5040
+ box-shadow: 0 0 0 1px white, 0 0 0 2px #888, 0 0 0 4px var(--theme-col);
5041
+ }
5042
+
5043
+ .color-scheme-slider-row input[type=range]:focus-visible::-moz-range-thumb {
5044
+ box-shadow: 0 0 0 1px white, 0 0 0 2px #888, 0 0 0 4px var(--theme-col);
5045
+ }
5046
+
5047
+ /* Presets have only the reverse button in the vibrance row, and sequential
5048
+ and diverging presets, the range */
4977
5049
  .color-scheme-slider-row.preset {
4978
5050
  justify-content: flex-end;
4979
5051
  }
4980
5052
 
4981
- .color-scheme-slider-row.preset > :not(.color-scheme-icon-btn),
4982
- .color-scheme-slider-row.preset > .long-hue-btn {
5053
+ .color-scheme-slider-row.preset > :not(.color-scheme-icon-btn):not(.color-scheme-range-part),
5054
+ .color-scheme-slider-row.preset > .long-hue-btn,
5055
+ .color-scheme-slider-row:not(.ranged) > .color-scheme-range-part {
4983
5056
  display: none;
4984
5057
  }
4985
5058
 
5059
+ /* A strip of the whole preset, shaded outside the part the tiles use */
5060
+ .color-scheme-range {
5061
+ position: relative;
5062
+ flex: 1;
5063
+ min-width: 0;
5064
+ height: 12px;
5065
+ margin: 0 9px 0 6px;
5066
+ cursor: pointer;
5067
+ touch-action: none;
5068
+ }
5069
+
5070
+ .color-scheme-range-strip {
5071
+ position: absolute;
5072
+ inset: 0;
5073
+ border-radius: 2px;
5074
+ box-shadow: inset 0 0 0 1px rgba(0,0,0,0.12);
5075
+ }
5076
+
5077
+ .color-scheme-range-shade {
5078
+ position: absolute;
5079
+ top: 0;
5080
+ bottom: 0;
5081
+ background-color: rgba(255, 255, 255, 0.75);
5082
+ }
5083
+
5084
+ .color-scheme-range-shade.left {
5085
+ left: 0;
5086
+ }
5087
+
5088
+ .color-scheme-range-shade.right {
5089
+ right: 0;
5090
+ }
5091
+
5092
+ .color-scheme-range-handle {
5093
+ position: absolute;
5094
+ top: -4px;
5095
+ bottom: -4px;
5096
+ width: 4px;
5097
+ margin-left: -3px;
5098
+ border: 1px solid #444;
5099
+ border-radius: 2px;
5100
+ background-color: white;
5101
+ cursor: ew-resize;
5102
+ }
5103
+
5104
+ .color-scheme-range-handle:focus-visible {
5105
+ outline: 2px solid var(--theme-col);
5106
+ outline-offset: 1px;
5107
+ }
5108
+
5109
+ /* Takes an end tile of a sequential preset away, shown over the tile on hover */
5110
+ .color-scheme-tile-remove {
5111
+ display: none;
5112
+ position: absolute;
5113
+ top: 2px;
5114
+ right: 2px;
5115
+ width: 14px;
5116
+ height: 14px;
5117
+ padding: 0;
5118
+ border: none;
5119
+ border-radius: 50%;
5120
+ background-color: rgba(255, 255, 255, 0.85);
5121
+ box-shadow: 0 0 0 1px rgba(0,0,0,0.2);
5122
+ color: #333;
5123
+ font-size: 12px;
5124
+ line-height: 14px;
5125
+ text-align: center;
5126
+ cursor: pointer;
5127
+ }
5128
+
5129
+ .color-scheme-tile:hover > .color-scheme-tile-remove {
5130
+ display: block;
5131
+ }
5132
+
4986
5133
  .color-scheme-icon-btn {
4987
5134
  position: relative;
4988
5135
  flex: none;