@india-boundary-corrector/service-worker 0.2.0 → 0.2.2

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.
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  var IndiaBoundaryCorrector = (() => {
3
3
  // ../data/version.js
4
- var packageVersion = "0.2.0";
4
+ var packageVersion = "0.2.2";
5
5
 
6
6
  // ../data/index.js
7
7
  var import_meta = {};
@@ -99,12 +99,11 @@ var IndiaBoundaryCorrector = (() => {
99
99
  "https://{s}.basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}.png",
100
100
  "https://basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}.png"
101
101
  ],
102
- lineWidthStops: { "1": 0.5, "2": 0.75, "3": 0.75, "4": 1, "5": 1, "7": 1.5, "16": 2.5 },
102
+ lineWidthStops: { "1": 0.5, "2": 0.75, "3": 0.75, "4": 1, "5": 1, "7": 1.75, "16": 2.5 },
103
103
  lineStyles: [
104
104
  { color: "rgb(235, 214, 214)", layerSuffix: "ne", endZoom: 4, lineExtensionFactor: 0.1, delWidthFactor: 2.5 },
105
105
  { color: "rgb(235, 214, 214)", layerSuffix: "ne-disp", endZoom: 4, delWidthFactor: 0 },
106
- { color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.2, startZoom: 6, endZoom: 11, widthFraction: 5, lineExtensionFactor: 0.1 },
107
- { color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.2, startZoom: 12, widthFraction: 4, lineExtensionFactor: 0.1 },
106
+ { color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.1, startZoom: 6, lineWidthStops: { "6": 9, "10": 8, "14": 8 }, lineExtensionFactor: 0.1 },
108
107
  { color: "rgb(235, 214, 214)", layerSuffix: "osm", startZoom: 5, lineExtensionFactor: 0.1 },
109
108
  { color: "rgb(235, 214, 214)", layerSuffix: "osm-disp", startZoom: 5, delWidthFactor: 0 },
110
109
  { color: "rgb(235, 214, 214)", layerSuffix: "osm-internal", startZoom: 5, widthFraction: 0.5, dashArray: [2, 2], delWidthFactor: 2 },
@@ -127,12 +126,11 @@ var IndiaBoundaryCorrector = (() => {
127
126
  "https://{s}.basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}{r}.png",
128
127
  "https://basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}{r}.png"
129
128
  ],
130
- lineWidthStops: { "1": 0.75, "2": 0.75, "3": 0.75, "4": 1, "5": 1, "7": 1.5, "11": 2 },
129
+ lineWidthStops: { "1": 1, "3": 1, "4": 2, "5": 2, "6": 2.5, "7": 3, "8": 3, "10": 4, "11": 4, "12": 4 },
131
130
  lineStyles: [
132
131
  { color: "rgb(235, 214, 214)", layerSuffix: "ne", endZoom: 4, lineExtensionFactor: 0.1, delWidthFactor: 2.5 },
133
132
  { color: "rgb(235, 214, 214)", layerSuffix: "ne-disp", endZoom: 4, delWidthFactor: 0 },
134
- { color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.1, startZoom: 6, endZoom: 11, widthFraction: 5, lineExtensionFactor: 0.1 },
135
- { color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.1, startZoom: 12, widthFraction: 4, lineExtensionFactor: 0.1 },
133
+ { color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.1, startZoom: 6, lineWidthStops: { "6": 20, "8": 19, "10": 18, "12": 17 }, lineExtensionFactor: 0.1 },
136
134
  { color: "rgb(235, 214, 214)", layerSuffix: "osm", startZoom: 5, lineExtensionFactor: 0.1 },
137
135
  { color: "rgb(235, 214, 214)", layerSuffix: "osm-disp", startZoom: 5, delWidthFactor: 0 },
138
136
  { color: "rgb(235, 214, 214)", layerSuffix: "osm-internal", startZoom: 5, widthFraction: 0.5, dashArray: [4, 4], delWidthFactor: 2 },
@@ -143,15 +141,20 @@ var IndiaBoundaryCorrector = (() => {
143
141
  id: "open-topo",
144
142
  tileUrlTemplates: [
145
143
  "https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png",
146
- "https://tile.opentopomap.org/{z}/{x}/{y}.png"
144
+ "https://tile.opentopomap.org/{z}/{x}/{y}.png",
145
+ "https://{s}.tile.top-o-map.de/{z}/{x}/{y}.png",
146
+ "https://tile.top-o-map.de/{z}/{x}/{y}.png"
147
147
  ],
148
148
  lineWidthStops: { "4": 0.75, "5": 1, "6": 1.25, "7": 1.5, "8": 1.75, "9": 1.25, "10": 1.25, "13": 1.5 },
149
149
  lineStyles: [
150
150
  { color: "rgb(83, 83, 83)", layerSuffix: "ne", startZoom: 4, endZoom: 6 },
151
151
  { color: "rgb(173, 173, 173)", layerSuffix: "osm", startZoom: 7, endZoom: 8, alpha: 0.5, widthFraction: 4 },
152
152
  { color: "rgb(83, 83, 83)", layerSuffix: "osm", startZoom: 7, endZoom: 8 },
153
+ { color: "rgb(83, 83, 83)", layerSuffix: "osm-internal", widthFraction: 0.75, startZoom: 7, endZoom: 8 },
153
154
  { color: "rgb(199, 158, 204)", layerSuffix: "osm", startZoom: 9, widthFraction: 7, alpha: 0.6, lineExtensionFactor: 0.2 },
154
- { color: "rgb(175, 41, 203)", layerSuffix: "osm", startZoom: 9, lineExtensionFactor: 0.2 }
155
+ { color: "rgb(175, 41, 203)", layerSuffix: "osm", startZoom: 9, lineExtensionFactor: 0.2 },
156
+ { color: "rgb(199, 158, 204)", layerSuffix: "osm-internal", startZoom: 9, widthFraction: 2.25, alpha: 0.6, lineExtensionFactor: 0.2 },
157
+ { color: "rgb(175, 41, 203)", layerSuffix: "osm-internal", startZoom: 9, widthFactor: 0.75, lineExtensionFactor: 0.2 }
155
158
  ]
156
159
  },
157
160
  {
@@ -160,9 +163,8 @@ var IndiaBoundaryCorrector = (() => {
160
163
  "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
161
164
  "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
162
165
  ],
163
- lineWidthStops: { "1": 0.5, "2": 0.6, "3": 0.7, "4": 1, "10": 3.75 },
166
+ lineWidthStops: { "3": 0.7, "4": 1, "10": 3.75 },
164
167
  lineStyles: [
165
- { color: "rgb(200, 180, 200)", layerSuffix: "osm", startZoom: 1, endZoom: 3, delWidthFactor: 2.5, widthFraction: 1.5 },
166
168
  { color: "rgb(200, 180, 200)", layerSuffix: "osm", startZoom: 4, delWidthFactor: 1.5 },
167
169
  { color: "rgb(160, 120, 160)", layerSuffix: "osm", startZoom: 4, widthFraction: 0.333, dashArray: [30, 2, 8, 2], delWidthFactor: 0 },
168
170
  { color: "rgb(200, 180, 200)", layerSuffix: "osm-internal", startZoom: 4, widthFraction: 0.45 },
@@ -186,6 +188,39 @@ var IndiaBoundaryCorrector = (() => {
186
188
  var INFINITY = -1;
187
189
  var MIN_LINE_WIDTH = 0.1;
188
190
  var DEFAULT_LINE_WIDTH = 1;
191
+ function interpolateLineWidth(zoom, lineWidthStops) {
192
+ const zooms = Object.keys(lineWidthStops).map(Number).sort((a, b2) => a - b2);
193
+ if (lineWidthStops[zoom] !== void 0) {
194
+ return lineWidthStops[zoom];
195
+ }
196
+ if (zoom < zooms[0]) {
197
+ const z1 = zooms[0];
198
+ const z2 = zooms[1];
199
+ const w1 = lineWidthStops[z1];
200
+ const w2 = lineWidthStops[z2];
201
+ const slope = (w2 - w1) / (z2 - z1);
202
+ return Math.max(MIN_LINE_WIDTH, w1 + slope * (zoom - z1));
203
+ }
204
+ if (zoom > zooms[zooms.length - 1]) {
205
+ const z1 = zooms[zooms.length - 2];
206
+ const z2 = zooms[zooms.length - 1];
207
+ const w1 = lineWidthStops[z1];
208
+ const w2 = lineWidthStops[z2];
209
+ const slope = (w2 - w1) / (z2 - z1);
210
+ return Math.max(MIN_LINE_WIDTH, w2 + slope * (zoom - z2));
211
+ }
212
+ for (let i2 = 0; i2 < zooms.length - 1; i2++) {
213
+ if (zoom > zooms[i2] && zoom < zooms[i2 + 1]) {
214
+ const z1 = zooms[i2];
215
+ const z2 = zooms[i2 + 1];
216
+ const w1 = lineWidthStops[z1];
217
+ const w2 = lineWidthStops[z2];
218
+ const t = (zoom - z1) / (z2 - z1);
219
+ return w1 + t * (w2 - w1);
220
+ }
221
+ }
222
+ return DEFAULT_LINE_WIDTH;
223
+ }
189
224
  function templateToRegex(template) {
190
225
  const groups = [];
191
226
  const hasRetina = template.includes("{r}");
@@ -252,14 +287,33 @@ var IndiaBoundaryCorrector = (() => {
252
287
  if (/^[a-z]+$/.test(trimmed)) return true;
253
288
  return false;
254
289
  }
290
+ function validateLineWidthStops(lineWidthStops, prefix) {
291
+ if (!lineWidthStops || typeof lineWidthStops !== "object" || Array.isArray(lineWidthStops)) {
292
+ throw new Error(`${prefix}: lineWidthStops must be an object`);
293
+ }
294
+ const stopKeys = Object.keys(lineWidthStops);
295
+ if (stopKeys.length < 2) {
296
+ throw new Error(`${prefix}: lineWidthStops must have at least 2 entries`);
297
+ }
298
+ for (const key of stopKeys) {
299
+ const zoom = Number(key);
300
+ if (!Number.isInteger(zoom) || zoom < 0) {
301
+ throw new Error(`${prefix}: lineWidthStops keys must be non-negative integers, got "${key}"`);
302
+ }
303
+ if (typeof lineWidthStops[key] !== "number" || lineWidthStops[key] <= 0) {
304
+ throw new Error(`${prefix}: lineWidthStops values must be positive numbers`);
305
+ }
306
+ }
307
+ }
255
308
  var LineStyle = class _LineStyle {
256
309
  /**
257
310
  * Validate a LineStyle configuration object.
258
311
  * @param {Object} obj - The object to validate
259
312
  * @param {number} [index] - Optional index for error messages (when validating in an array)
313
+ * @param {boolean} [requireLineWidthStops=false] - Whether lineWidthStops is required
260
314
  * @throws {Error} If validation fails
261
315
  */
262
- static validateJSON(obj, index) {
316
+ static validateJSON(obj, index, requireLineWidthStops = false) {
263
317
  const prefix = index !== void 0 ? `lineStyles[${index}]` : "LineStyle";
264
318
  if (!obj || typeof obj !== "object") {
265
319
  throw new Error(`${prefix}: must be an object`);
@@ -294,22 +348,30 @@ var IndiaBoundaryCorrector = (() => {
294
348
  if (obj.delWidthFactor !== void 0 && (typeof obj.delWidthFactor !== "number" || obj.delWidthFactor < 0)) {
295
349
  throw new Error(`${prefix}: delWidthFactor must be a non-negative number`);
296
350
  }
351
+ if (requireLineWidthStops && obj.lineWidthStops === void 0) {
352
+ throw new Error(`${prefix}: lineWidthStops is required`);
353
+ }
354
+ if (obj.lineWidthStops !== void 0) {
355
+ validateLineWidthStops(obj.lineWidthStops, prefix);
356
+ }
297
357
  }
298
358
  /**
299
359
  * @param {Object} options
300
360
  * @param {string} options.color - CSS color string
301
361
  * @param {string} options.layerSuffix - Layer suffix (e.g., 'osm', 'ne', 'osm-disp')
362
+ * @param {Object<number, number>} options.lineWidthStops - Line width stops for this style
302
363
  * @param {number} [options.widthFraction=1.0] - Multiplier for base line width
303
364
  * @param {number[]} [options.dashArray] - Dash pattern for dashed lines
304
365
  * @param {number} [options.alpha=1.0] - Opacity (0-1)
305
366
  * @param {number} [options.startZoom=0] - Minimum zoom level for this style
306
367
  * @param {number} [options.endZoom=INFINITY] - Maximum zoom level for this style (INFINITY means no limit)
307
- * @param {number} [options.lineExtensionFactor=0.5] - Factor to extend lines by (multiplied by deletion line width)
368
+ * @param {number} [options.lineExtensionFactor=0.0] - Factor to extend lines by (multiplied by deletion line width)
308
369
  * @param {number} [options.delWidthFactor=1.5] - Factor to multiply line width for deletion blur
309
370
  */
310
- constructor({ color, layerSuffix, widthFraction = 1, dashArray, alpha = 1, startZoom = 0, endZoom = INFINITY, lineExtensionFactor = 0, delWidthFactor = 1.5 }) {
371
+ constructor({ color, layerSuffix, lineWidthStops, widthFraction = 1, dashArray, alpha = 1, startZoom = 0, endZoom = INFINITY, lineExtensionFactor = 0, delWidthFactor = 1.5 }) {
311
372
  this.color = color;
312
373
  this.layerSuffix = layerSuffix;
374
+ this.lineWidthStops = lineWidthStops;
313
375
  this.widthFraction = widthFraction;
314
376
  this.dashArray = dashArray;
315
377
  this.alpha = alpha;
@@ -318,6 +380,14 @@ var IndiaBoundaryCorrector = (() => {
318
380
  this.lineExtensionFactor = lineExtensionFactor;
319
381
  this.delWidthFactor = delWidthFactor;
320
382
  }
383
+ /**
384
+ * Get base line width for this style at a given zoom level.
385
+ * @param {number} zoom - Zoom level
386
+ * @returns {number}
387
+ */
388
+ getLineWidth(zoom) {
389
+ return interpolateLineWidth(zoom, this.lineWidthStops);
390
+ }
321
391
  /**
322
392
  * Check if this style is active at the given zoom level.
323
393
  * @param {number} z - Zoom level
@@ -334,6 +404,7 @@ var IndiaBoundaryCorrector = (() => {
334
404
  return {
335
405
  color: this.color,
336
406
  layerSuffix: this.layerSuffix,
407
+ lineWidthStops: this.lineWidthStops,
337
408
  widthFraction: this.widthFraction,
338
409
  dashArray: this.dashArray,
339
410
  alpha: this.alpha,
@@ -350,7 +421,7 @@ var IndiaBoundaryCorrector = (() => {
350
421
  * @returns {LineStyle}
351
422
  */
352
423
  static fromJSON(obj, index) {
353
- _LineStyle.validateJSON(obj, index);
424
+ _LineStyle.validateJSON(obj, index, true);
354
425
  return new _LineStyle(obj);
355
426
  }
356
427
  };
@@ -416,9 +487,13 @@ var IndiaBoundaryCorrector = (() => {
416
487
  this._compiledPatterns = templates.map((t) => templateToRegex(t));
417
488
  this._templatePatterns = templates.map((t) => templateToTemplateRegex(t));
418
489
  this.lineWidthStops = lineWidthStops;
419
- this.lineStyles = lineStyles.map(
420
- (style) => style instanceof LineStyle ? style : new LineStyle(style)
421
- );
490
+ this.lineStyles = lineStyles.map((style) => {
491
+ if (style instanceof LineStyle) {
492
+ return style;
493
+ }
494
+ const styleWithStops = style.lineWidthStops ? style : { ...style, lineWidthStops };
495
+ return new LineStyle(styleWithStops);
496
+ });
422
497
  }
423
498
  /**
424
499
  * Get line styles active at a given zoom level
@@ -437,45 +512,6 @@ var IndiaBoundaryCorrector = (() => {
437
512
  const activeStyles = this.getLineStylesForZoom(z2);
438
513
  return [...new Set(activeStyles.map((s) => s.layerSuffix))];
439
514
  }
440
- /**
441
- * Interpolate or extrapolate line width for a given zoom level.
442
- * Uses the lineWidthStops map to calculate the appropriate width.
443
- * @param {number} zoom - Zoom level
444
- * @returns {number}
445
- */
446
- getLineWidth(zoom) {
447
- const zooms = Object.keys(this.lineWidthStops).map(Number).sort((a, b2) => a - b2);
448
- if (this.lineWidthStops[zoom] !== void 0) {
449
- return this.lineWidthStops[zoom];
450
- }
451
- if (zoom < zooms[0]) {
452
- const z1 = zooms[0];
453
- const z2 = zooms[1];
454
- const w1 = this.lineWidthStops[z1];
455
- const w2 = this.lineWidthStops[z2];
456
- const slope = (w2 - w1) / (z2 - z1);
457
- return Math.max(MIN_LINE_WIDTH, w1 + slope * (zoom - z1));
458
- }
459
- if (zoom > zooms[zooms.length - 1]) {
460
- const z1 = zooms[zooms.length - 2];
461
- const z2 = zooms[zooms.length - 1];
462
- const w1 = this.lineWidthStops[z1];
463
- const w2 = this.lineWidthStops[z2];
464
- const slope = (w2 - w1) / (z2 - z1);
465
- return Math.max(MIN_LINE_WIDTH, w2 + slope * (zoom - z2));
466
- }
467
- for (let i2 = 0; i2 < zooms.length - 1; i2++) {
468
- if (zoom > zooms[i2] && zoom < zooms[i2 + 1]) {
469
- const z1 = zooms[i2];
470
- const z2 = zooms[i2 + 1];
471
- const w1 = this.lineWidthStops[z1];
472
- const w2 = this.lineWidthStops[z2];
473
- const t = (zoom - z1) / (z2 - z1);
474
- return w1 + t * (w2 - w1);
475
- }
476
- }
477
- return DEFAULT_LINE_WIDTH;
478
- }
479
515
  /**
480
516
  * Check if this config matches the given template URLs (with {z}/{x}/{y} placeholders)
481
517
  * @param {string | string[]} templates - Single template URL or array of template URLs
@@ -2929,12 +2965,11 @@ var IndiaBoundaryCorrector = (() => {
2929
2965
  "https://{s}.basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}.png",
2930
2966
  "https://basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}.png"
2931
2967
  ],
2932
- lineWidthStops: { "1": 0.5, "2": 0.75, "3": 0.75, "4": 1, "5": 1, "7": 1.5, "16": 2.5 },
2968
+ lineWidthStops: { "1": 0.5, "2": 0.75, "3": 0.75, "4": 1, "5": 1, "7": 1.75, "16": 2.5 },
2933
2969
  lineStyles: [
2934
2970
  { color: "rgb(235, 214, 214)", layerSuffix: "ne", endZoom: 4, lineExtensionFactor: 0.1, delWidthFactor: 2.5 },
2935
2971
  { color: "rgb(235, 214, 214)", layerSuffix: "ne-disp", endZoom: 4, delWidthFactor: 0 },
2936
- { color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.2, startZoom: 6, endZoom: 11, widthFraction: 5, lineExtensionFactor: 0.1 },
2937
- { color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.2, startZoom: 12, widthFraction: 4, lineExtensionFactor: 0.1 },
2972
+ { color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.1, startZoom: 6, lineWidthStops: { "6": 9, "10": 8, "14": 8 }, lineExtensionFactor: 0.1 },
2938
2973
  { color: "rgb(235, 214, 214)", layerSuffix: "osm", startZoom: 5, lineExtensionFactor: 0.1 },
2939
2974
  { color: "rgb(235, 214, 214)", layerSuffix: "osm-disp", startZoom: 5, delWidthFactor: 0 },
2940
2975
  { color: "rgb(235, 214, 214)", layerSuffix: "osm-internal", startZoom: 5, widthFraction: 0.5, dashArray: [2, 2], delWidthFactor: 2 },
@@ -2957,12 +2992,11 @@ var IndiaBoundaryCorrector = (() => {
2957
2992
  "https://{s}.basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}{r}.png",
2958
2993
  "https://basemaps.cartocdn.com/rastertiles/voyager_labels_under/{z}/{x}/{y}{r}.png"
2959
2994
  ],
2960
- lineWidthStops: { "1": 0.75, "2": 0.75, "3": 0.75, "4": 1, "5": 1, "7": 1.5, "11": 2 },
2995
+ lineWidthStops: { "1": 1, "3": 1, "4": 2, "5": 2, "6": 2.5, "7": 3, "8": 3, "10": 4, "11": 4, "12": 4 },
2961
2996
  lineStyles: [
2962
2997
  { color: "rgb(235, 214, 214)", layerSuffix: "ne", endZoom: 4, lineExtensionFactor: 0.1, delWidthFactor: 2.5 },
2963
2998
  { color: "rgb(235, 214, 214)", layerSuffix: "ne-disp", endZoom: 4, delWidthFactor: 0 },
2964
- { color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.1, startZoom: 6, endZoom: 11, widthFraction: 5, lineExtensionFactor: 0.1 },
2965
- { color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.1, startZoom: 12, widthFraction: 4, lineExtensionFactor: 0.1 },
2999
+ { color: "rgb(235, 214, 214)", layerSuffix: "osm", alpha: 0.1, startZoom: 6, lineWidthStops: { "6": 20, "8": 19, "10": 18, "12": 17 }, lineExtensionFactor: 0.1 },
2966
3000
  { color: "rgb(235, 214, 214)", layerSuffix: "osm", startZoom: 5, lineExtensionFactor: 0.1 },
2967
3001
  { color: "rgb(235, 214, 214)", layerSuffix: "osm-disp", startZoom: 5, delWidthFactor: 0 },
2968
3002
  { color: "rgb(235, 214, 214)", layerSuffix: "osm-internal", startZoom: 5, widthFraction: 0.5, dashArray: [4, 4], delWidthFactor: 2 },
@@ -2973,15 +3007,20 @@ var IndiaBoundaryCorrector = (() => {
2973
3007
  id: "open-topo",
2974
3008
  tileUrlTemplates: [
2975
3009
  "https://{s}.tile.opentopomap.org/{z}/{x}/{y}.png",
2976
- "https://tile.opentopomap.org/{z}/{x}/{y}.png"
3010
+ "https://tile.opentopomap.org/{z}/{x}/{y}.png",
3011
+ "https://{s}.tile.top-o-map.de/{z}/{x}/{y}.png",
3012
+ "https://tile.top-o-map.de/{z}/{x}/{y}.png"
2977
3013
  ],
2978
3014
  lineWidthStops: { "4": 0.75, "5": 1, "6": 1.25, "7": 1.5, "8": 1.75, "9": 1.25, "10": 1.25, "13": 1.5 },
2979
3015
  lineStyles: [
2980
3016
  { color: "rgb(83, 83, 83)", layerSuffix: "ne", startZoom: 4, endZoom: 6 },
2981
3017
  { color: "rgb(173, 173, 173)", layerSuffix: "osm", startZoom: 7, endZoom: 8, alpha: 0.5, widthFraction: 4 },
2982
3018
  { color: "rgb(83, 83, 83)", layerSuffix: "osm", startZoom: 7, endZoom: 8 },
3019
+ { color: "rgb(83, 83, 83)", layerSuffix: "osm-internal", widthFraction: 0.75, startZoom: 7, endZoom: 8 },
2983
3020
  { color: "rgb(199, 158, 204)", layerSuffix: "osm", startZoom: 9, widthFraction: 7, alpha: 0.6, lineExtensionFactor: 0.2 },
2984
- { color: "rgb(175, 41, 203)", layerSuffix: "osm", startZoom: 9, lineExtensionFactor: 0.2 }
3021
+ { color: "rgb(175, 41, 203)", layerSuffix: "osm", startZoom: 9, lineExtensionFactor: 0.2 },
3022
+ { color: "rgb(199, 158, 204)", layerSuffix: "osm-internal", startZoom: 9, widthFraction: 2.25, alpha: 0.6, lineExtensionFactor: 0.2 },
3023
+ { color: "rgb(175, 41, 203)", layerSuffix: "osm-internal", startZoom: 9, widthFactor: 0.75, lineExtensionFactor: 0.2 }
2985
3024
  ]
2986
3025
  },
2987
3026
  {
@@ -2990,9 +3029,8 @@ var IndiaBoundaryCorrector = (() => {
2990
3029
  "https://tile.openstreetmap.org/{z}/{x}/{y}.png",
2991
3030
  "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
2992
3031
  ],
2993
- lineWidthStops: { "1": 0.5, "2": 0.6, "3": 0.7, "4": 1, "10": 3.75 },
3032
+ lineWidthStops: { "3": 0.7, "4": 1, "10": 3.75 },
2994
3033
  lineStyles: [
2995
- { color: "rgb(200, 180, 200)", layerSuffix: "osm", startZoom: 1, endZoom: 3, delWidthFactor: 2.5, widthFraction: 1.5 },
2996
3034
  { color: "rgb(200, 180, 200)", layerSuffix: "osm", startZoom: 4, delWidthFactor: 1.5 },
2997
3035
  { color: "rgb(160, 120, 160)", layerSuffix: "osm", startZoom: 4, widthFraction: 0.333, dashArray: [30, 2, 8, 2], delWidthFactor: 0 },
2998
3036
  { color: "rgb(200, 180, 200)", layerSuffix: "osm-internal", startZoom: 4, widthFraction: 0.45 },
@@ -3016,6 +3054,39 @@ var IndiaBoundaryCorrector = (() => {
3016
3054
  var INFINITY2 = -1;
3017
3055
  var MIN_LINE_WIDTH2 = 0.1;
3018
3056
  var DEFAULT_LINE_WIDTH2 = 1;
3057
+ function interpolateLineWidth2(zoom, lineWidthStops) {
3058
+ const zooms = Object.keys(lineWidthStops).map(Number).sort((a, b2) => a - b2);
3059
+ if (lineWidthStops[zoom] !== void 0) {
3060
+ return lineWidthStops[zoom];
3061
+ }
3062
+ if (zoom < zooms[0]) {
3063
+ const z1 = zooms[0];
3064
+ const z2 = zooms[1];
3065
+ const w1 = lineWidthStops[z1];
3066
+ const w2 = lineWidthStops[z2];
3067
+ const slope = (w2 - w1) / (z2 - z1);
3068
+ return Math.max(MIN_LINE_WIDTH2, w1 + slope * (zoom - z1));
3069
+ }
3070
+ if (zoom > zooms[zooms.length - 1]) {
3071
+ const z1 = zooms[zooms.length - 2];
3072
+ const z2 = zooms[zooms.length - 1];
3073
+ const w1 = lineWidthStops[z1];
3074
+ const w2 = lineWidthStops[z2];
3075
+ const slope = (w2 - w1) / (z2 - z1);
3076
+ return Math.max(MIN_LINE_WIDTH2, w2 + slope * (zoom - z2));
3077
+ }
3078
+ for (let i2 = 0; i2 < zooms.length - 1; i2++) {
3079
+ if (zoom > zooms[i2] && zoom < zooms[i2 + 1]) {
3080
+ const z1 = zooms[i2];
3081
+ const z2 = zooms[i2 + 1];
3082
+ const w1 = lineWidthStops[z1];
3083
+ const w2 = lineWidthStops[z2];
3084
+ const t = (zoom - z1) / (z2 - z1);
3085
+ return w1 + t * (w2 - w1);
3086
+ }
3087
+ }
3088
+ return DEFAULT_LINE_WIDTH2;
3089
+ }
3019
3090
  function templateToRegex2(template) {
3020
3091
  const groups = [];
3021
3092
  const hasRetina = template.includes("{r}");
@@ -3082,14 +3153,33 @@ var IndiaBoundaryCorrector = (() => {
3082
3153
  if (/^[a-z]+$/.test(trimmed)) return true;
3083
3154
  return false;
3084
3155
  }
3156
+ function validateLineWidthStops2(lineWidthStops, prefix) {
3157
+ if (!lineWidthStops || typeof lineWidthStops !== "object" || Array.isArray(lineWidthStops)) {
3158
+ throw new Error(`${prefix}: lineWidthStops must be an object`);
3159
+ }
3160
+ const stopKeys = Object.keys(lineWidthStops);
3161
+ if (stopKeys.length < 2) {
3162
+ throw new Error(`${prefix}: lineWidthStops must have at least 2 entries`);
3163
+ }
3164
+ for (const key of stopKeys) {
3165
+ const zoom = Number(key);
3166
+ if (!Number.isInteger(zoom) || zoom < 0) {
3167
+ throw new Error(`${prefix}: lineWidthStops keys must be non-negative integers, got "${key}"`);
3168
+ }
3169
+ if (typeof lineWidthStops[key] !== "number" || lineWidthStops[key] <= 0) {
3170
+ throw new Error(`${prefix}: lineWidthStops values must be positive numbers`);
3171
+ }
3172
+ }
3173
+ }
3085
3174
  var LineStyle2 = class _LineStyle2 {
3086
3175
  /**
3087
3176
  * Validate a LineStyle configuration object.
3088
3177
  * @param {Object} obj - The object to validate
3089
3178
  * @param {number} [index] - Optional index for error messages (when validating in an array)
3179
+ * @param {boolean} [requireLineWidthStops=false] - Whether lineWidthStops is required
3090
3180
  * @throws {Error} If validation fails
3091
3181
  */
3092
- static validateJSON(obj, index) {
3182
+ static validateJSON(obj, index, requireLineWidthStops = false) {
3093
3183
  const prefix = index !== void 0 ? `lineStyles[${index}]` : "LineStyle";
3094
3184
  if (!obj || typeof obj !== "object") {
3095
3185
  throw new Error(`${prefix}: must be an object`);
@@ -3124,22 +3214,30 @@ var IndiaBoundaryCorrector = (() => {
3124
3214
  if (obj.delWidthFactor !== void 0 && (typeof obj.delWidthFactor !== "number" || obj.delWidthFactor < 0)) {
3125
3215
  throw new Error(`${prefix}: delWidthFactor must be a non-negative number`);
3126
3216
  }
3217
+ if (requireLineWidthStops && obj.lineWidthStops === void 0) {
3218
+ throw new Error(`${prefix}: lineWidthStops is required`);
3219
+ }
3220
+ if (obj.lineWidthStops !== void 0) {
3221
+ validateLineWidthStops2(obj.lineWidthStops, prefix);
3222
+ }
3127
3223
  }
3128
3224
  /**
3129
3225
  * @param {Object} options
3130
3226
  * @param {string} options.color - CSS color string
3131
3227
  * @param {string} options.layerSuffix - Layer suffix (e.g., 'osm', 'ne', 'osm-disp')
3228
+ * @param {Object<number, number>} options.lineWidthStops - Line width stops for this style
3132
3229
  * @param {number} [options.widthFraction=1.0] - Multiplier for base line width
3133
3230
  * @param {number[]} [options.dashArray] - Dash pattern for dashed lines
3134
3231
  * @param {number} [options.alpha=1.0] - Opacity (0-1)
3135
3232
  * @param {number} [options.startZoom=0] - Minimum zoom level for this style
3136
3233
  * @param {number} [options.endZoom=INFINITY] - Maximum zoom level for this style (INFINITY means no limit)
3137
- * @param {number} [options.lineExtensionFactor=0.5] - Factor to extend lines by (multiplied by deletion line width)
3234
+ * @param {number} [options.lineExtensionFactor=0.0] - Factor to extend lines by (multiplied by deletion line width)
3138
3235
  * @param {number} [options.delWidthFactor=1.5] - Factor to multiply line width for deletion blur
3139
3236
  */
3140
- constructor({ color, layerSuffix, widthFraction = 1, dashArray, alpha = 1, startZoom = 0, endZoom = INFINITY2, lineExtensionFactor = 0, delWidthFactor = 1.5 }) {
3237
+ constructor({ color, layerSuffix, lineWidthStops, widthFraction = 1, dashArray, alpha = 1, startZoom = 0, endZoom = INFINITY2, lineExtensionFactor = 0, delWidthFactor = 1.5 }) {
3141
3238
  this.color = color;
3142
3239
  this.layerSuffix = layerSuffix;
3240
+ this.lineWidthStops = lineWidthStops;
3143
3241
  this.widthFraction = widthFraction;
3144
3242
  this.dashArray = dashArray;
3145
3243
  this.alpha = alpha;
@@ -3148,6 +3246,14 @@ var IndiaBoundaryCorrector = (() => {
3148
3246
  this.lineExtensionFactor = lineExtensionFactor;
3149
3247
  this.delWidthFactor = delWidthFactor;
3150
3248
  }
3249
+ /**
3250
+ * Get base line width for this style at a given zoom level.
3251
+ * @param {number} zoom - Zoom level
3252
+ * @returns {number}
3253
+ */
3254
+ getLineWidth(zoom) {
3255
+ return interpolateLineWidth2(zoom, this.lineWidthStops);
3256
+ }
3151
3257
  /**
3152
3258
  * Check if this style is active at the given zoom level.
3153
3259
  * @param {number} z - Zoom level
@@ -3164,6 +3270,7 @@ var IndiaBoundaryCorrector = (() => {
3164
3270
  return {
3165
3271
  color: this.color,
3166
3272
  layerSuffix: this.layerSuffix,
3273
+ lineWidthStops: this.lineWidthStops,
3167
3274
  widthFraction: this.widthFraction,
3168
3275
  dashArray: this.dashArray,
3169
3276
  alpha: this.alpha,
@@ -3180,7 +3287,7 @@ var IndiaBoundaryCorrector = (() => {
3180
3287
  * @returns {LineStyle}
3181
3288
  */
3182
3289
  static fromJSON(obj, index) {
3183
- _LineStyle2.validateJSON(obj, index);
3290
+ _LineStyle2.validateJSON(obj, index, true);
3184
3291
  return new _LineStyle2(obj);
3185
3292
  }
3186
3293
  };
@@ -3246,9 +3353,13 @@ var IndiaBoundaryCorrector = (() => {
3246
3353
  this._compiledPatterns = templates.map((t) => templateToRegex2(t));
3247
3354
  this._templatePatterns = templates.map((t) => templateToTemplateRegex2(t));
3248
3355
  this.lineWidthStops = lineWidthStops;
3249
- this.lineStyles = lineStyles.map(
3250
- (style) => style instanceof LineStyle2 ? style : new LineStyle2(style)
3251
- );
3356
+ this.lineStyles = lineStyles.map((style) => {
3357
+ if (style instanceof LineStyle2) {
3358
+ return style;
3359
+ }
3360
+ const styleWithStops = style.lineWidthStops ? style : { ...style, lineWidthStops };
3361
+ return new LineStyle2(styleWithStops);
3362
+ });
3252
3363
  }
3253
3364
  /**
3254
3365
  * Get line styles active at a given zoom level
@@ -3267,45 +3378,6 @@ var IndiaBoundaryCorrector = (() => {
3267
3378
  const activeStyles = this.getLineStylesForZoom(z2);
3268
3379
  return [...new Set(activeStyles.map((s) => s.layerSuffix))];
3269
3380
  }
3270
- /**
3271
- * Interpolate or extrapolate line width for a given zoom level.
3272
- * Uses the lineWidthStops map to calculate the appropriate width.
3273
- * @param {number} zoom - Zoom level
3274
- * @returns {number}
3275
- */
3276
- getLineWidth(zoom) {
3277
- const zooms = Object.keys(this.lineWidthStops).map(Number).sort((a, b2) => a - b2);
3278
- if (this.lineWidthStops[zoom] !== void 0) {
3279
- return this.lineWidthStops[zoom];
3280
- }
3281
- if (zoom < zooms[0]) {
3282
- const z1 = zooms[0];
3283
- const z2 = zooms[1];
3284
- const w1 = this.lineWidthStops[z1];
3285
- const w2 = this.lineWidthStops[z2];
3286
- const slope = (w2 - w1) / (z2 - z1);
3287
- return Math.max(MIN_LINE_WIDTH2, w1 + slope * (zoom - z1));
3288
- }
3289
- if (zoom > zooms[zooms.length - 1]) {
3290
- const z1 = zooms[zooms.length - 2];
3291
- const z2 = zooms[zooms.length - 1];
3292
- const w1 = this.lineWidthStops[z1];
3293
- const w2 = this.lineWidthStops[z2];
3294
- const slope = (w2 - w1) / (z2 - z1);
3295
- return Math.max(MIN_LINE_WIDTH2, w2 + slope * (zoom - z2));
3296
- }
3297
- for (let i2 = 0; i2 < zooms.length - 1; i2++) {
3298
- if (zoom > zooms[i2] && zoom < zooms[i2 + 1]) {
3299
- const z1 = zooms[i2];
3300
- const z2 = zooms[i2 + 1];
3301
- const w1 = this.lineWidthStops[z1];
3302
- const w2 = this.lineWidthStops[z2];
3303
- const t = (zoom - z1) / (z2 - z1);
3304
- return w1 + t * (w2 - w1);
3305
- }
3306
- }
3307
- return DEFAULT_LINE_WIDTH2;
3308
- }
3309
3381
  /**
3310
3382
  * Check if this config matches the given template URLs (with {z}/{x}/{y} placeholders)
3311
3383
  * @param {string | string[]} templates - Single template URL or array of template URLs
@@ -3781,12 +3853,13 @@ var IndiaBoundaryCorrector = (() => {
3781
3853
  const canvas = this._canvas;
3782
3854
  const ctx = canvas.getContext("2d", { willReadFrequently: true });
3783
3855
  ctx.drawImage(imageBitmap, 0, 0, tileSize, tileSize);
3784
- const baseLineWidth = layerConfig.getLineWidth(zoom);
3785
3856
  const delLineWidthBySuffix = {};
3786
3857
  for (const suffix of layerSuffixes) {
3787
3858
  const stylesForSuffix = activeLineStyles.filter((s) => s.layerSuffix === suffix);
3788
- const maxProduct = Math.max(...stylesForSuffix.map((s) => s.widthFraction * s.delWidthFactor));
3789
- delLineWidthBySuffix[suffix] = baseLineWidth * maxProduct;
3859
+ const maxDelWidth = Math.max(...stylesForSuffix.map(
3860
+ (s) => s.getLineWidth(zoom) * s.widthFraction * s.delWidthFactor
3861
+ ));
3862
+ delLineWidthBySuffix[suffix] = maxDelWidth;
3790
3863
  }
3791
3864
  for (const suffix of layerSuffixes) {
3792
3865
  const delLineWidth = delLineWidthBySuffix[suffix];
@@ -3801,7 +3874,7 @@ var IndiaBoundaryCorrector = (() => {
3801
3874
  }
3802
3875
  }
3803
3876
  for (const style of activeLineStyles) {
3804
- const { color, layerSuffix, widthFraction, dashArray, alpha, lineExtensionFactor } = style;
3877
+ const { color, widthFraction, dashArray, alpha, lineExtensionFactor, layerSuffix } = style;
3805
3878
  const addLayerName = `to-add-${layerSuffix}`;
3806
3879
  let addFeatures = corrections[addLayerName] || [];
3807
3880
  if (addFeatures.length > 0) {
@@ -3809,7 +3882,7 @@ var IndiaBoundaryCorrector = (() => {
3809
3882
  if (lineExtensionFactor > 0) {
3810
3883
  addFeatures = extendFeaturesByFactor(addFeatures, lineExtensionFactor, delLineWidth, tileSize);
3811
3884
  }
3812
- const lineWidth = baseLineWidth * widthFraction;
3885
+ const lineWidth = style.getLineWidth(zoom) * widthFraction;
3813
3886
  drawFeatures(ctx, addFeatures, color, lineWidth, tileSize, dashArray, alpha);
3814
3887
  }
3815
3888
  }