@carto/api-client 0.5.31 → 0.5.32-alpha.02a4470.133
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3 -0
- package/build/api-client.cjs +527 -3
- package/build/api-client.cjs.map +1 -1
- package/build/api-client.d.cts +42 -5
- package/build/api-client.d.ts +42 -5
- package/build/api-client.js +520 -3
- package/build/api-client.js.map +1 -1
- package/package.json +2 -2
- package/src/fetch-map/layer-map.ts +48 -0
- package/src/fetch-map/parse-map.ts +133 -10
- package/src/fetch-map/pattern-atlas.ts +461 -0
- package/src/fetch-map/patterns/checker-large.png +0 -0
- package/src/fetch-map/patterns/checker-large.svg +1 -0
- package/src/fetch-map/patterns/checker-medium.png +0 -0
- package/src/fetch-map/patterns/checker-medium.svg +1 -0
- package/src/fetch-map/patterns/checker-small.png +0 -0
- package/src/fetch-map/patterns/checker-small.svg +1 -0
- package/src/fetch-map/patterns/cross-hatch-large.png +0 -0
- package/src/fetch-map/patterns/cross-hatch-large.svg +1 -0
- package/src/fetch-map/patterns/cross-hatch-medium.png +0 -0
- package/src/fetch-map/patterns/cross-hatch-medium.svg +1 -0
- package/src/fetch-map/patterns/cross-hatch-small.png +0 -0
- package/src/fetch-map/patterns/cross-hatch-small.svg +1 -0
- package/src/fetch-map/patterns/diag-left-large.png +0 -0
- package/src/fetch-map/patterns/diag-left-large.svg +1 -0
- package/src/fetch-map/patterns/diag-left-medium.png +0 -0
- package/src/fetch-map/patterns/diag-left-medium.svg +1 -0
- package/src/fetch-map/patterns/diag-left-small.png +0 -0
- package/src/fetch-map/patterns/diag-left-small.svg +1 -0
- package/src/fetch-map/patterns/diag-right-large.png +0 -0
- package/src/fetch-map/patterns/diag-right-large.svg +1 -0
- package/src/fetch-map/patterns/diag-right-medium.png +0 -0
- package/src/fetch-map/patterns/diag-right-medium.svg +1 -0
- package/src/fetch-map/patterns/diag-right-small.png +0 -0
- package/src/fetch-map/patterns/diag-right-small.svg +1 -0
- package/src/fetch-map/patterns/dots-large.png +0 -0
- package/src/fetch-map/patterns/dots-large.svg +1 -0
- package/src/fetch-map/patterns/dots-medium.png +0 -0
- package/src/fetch-map/patterns/dots-medium.svg +1 -0
- package/src/fetch-map/patterns/dots-small.png +0 -0
- package/src/fetch-map/patterns/dots-small.svg +1 -0
- package/src/fetch-map/patterns/hlines-large.png +0 -0
- package/src/fetch-map/patterns/hlines-large.svg +1 -0
- package/src/fetch-map/patterns/hlines-medium.png +0 -0
- package/src/fetch-map/patterns/hlines-medium.svg +1 -0
- package/src/fetch-map/patterns/hlines-small.png +0 -0
- package/src/fetch-map/patterns/hlines-small.svg +1 -0
- package/src/fetch-map/patterns/solid.png +0 -0
- package/src/fetch-map/patterns/solid.svg +1 -0
- package/src/fetch-map/patterns/vlines-large.png +0 -0
- package/src/fetch-map/patterns/vlines-large.svg +1 -0
- package/src/fetch-map/patterns/vlines-medium.png +0 -0
- package/src/fetch-map/patterns/vlines-medium.svg +1 -0
- package/src/fetch-map/patterns/vlines-small.png +0 -0
- package/src/fetch-map/patterns/vlines-small.svg +1 -0
- package/src/fetch-map/types.ts +44 -0
- package/src/global.d.ts +10 -0
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"homepage": "https://github.com/CartoDB/carto-api-client#readme",
|
|
9
9
|
"author": "Don McCurdy <donmccurdy@carto.com>",
|
|
10
10
|
"packageManager": "yarn@4.3.1",
|
|
11
|
-
"version": "0.5.
|
|
11
|
+
"version": "0.5.32-alpha.02a4470.133",
|
|
12
12
|
"license": "MIT",
|
|
13
13
|
"publishConfig": {
|
|
14
14
|
"access": "public"
|
|
@@ -125,7 +125,7 @@
|
|
|
125
125
|
"typescript": "~5.9.2",
|
|
126
126
|
"typescript-eslint": "^8.26.1",
|
|
127
127
|
"vite": "^7.3.2",
|
|
128
|
-
"vitest": "3.2.
|
|
128
|
+
"vitest": "3.2.6"
|
|
129
129
|
},
|
|
130
130
|
"resolutions": {
|
|
131
131
|
"@carto/api-client": "portal:./",
|
|
@@ -32,6 +32,8 @@ import type {
|
|
|
32
32
|
ColorRange,
|
|
33
33
|
CustomMarkersRange,
|
|
34
34
|
Dataset,
|
|
35
|
+
FillPatternRange,
|
|
36
|
+
LineStyleRange,
|
|
35
37
|
MapLayerConfig,
|
|
36
38
|
VisConfig,
|
|
37
39
|
VisualChannelField,
|
|
@@ -510,6 +512,52 @@ export function getIconUrlAccessor(
|
|
|
510
512
|
return normalizeAccessor(accessor, data);
|
|
511
513
|
}
|
|
512
514
|
|
|
515
|
+
export function getLineStyleAccessor(
|
|
516
|
+
field: VisualChannelField,
|
|
517
|
+
range: LineStyleRange,
|
|
518
|
+
data: any
|
|
519
|
+
) {
|
|
520
|
+
const fallback = range.othersDashArray ?? [0, 0];
|
|
521
|
+
const mapping: Record<string, [number, number]> = {};
|
|
522
|
+
for (const {value, dashArray} of range.dashArrayMap) {
|
|
523
|
+
mapping[value] = dashArray;
|
|
524
|
+
}
|
|
525
|
+
const accessor = (properties: any) =>
|
|
526
|
+
mapping[properties[field.name]] ?? fallback;
|
|
527
|
+
return {
|
|
528
|
+
accessor: normalizeAccessor(accessor, data),
|
|
529
|
+
domain: range.dashArrayMap.map(({value}) => value),
|
|
530
|
+
range: range.dashArrayMap.map(({dashArray}) => dashArray),
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
export function getFillPatternAccessor(
|
|
535
|
+
field: VisualChannelField,
|
|
536
|
+
range: FillPatternRange,
|
|
537
|
+
density: 'small' | 'medium' | 'large' | undefined,
|
|
538
|
+
data: any
|
|
539
|
+
) {
|
|
540
|
+
const d = density ?? 'medium';
|
|
541
|
+
// `solid` / `none` are density-agnostic atlas cells; every other pattern resolves to
|
|
542
|
+
// `${pattern}-${density}`.
|
|
543
|
+
const toKey = (pattern: string) =>
|
|
544
|
+
pattern === 'solid' || pattern === 'none' ? pattern : `${pattern}-${d}`;
|
|
545
|
+
// Always resolve to a real key — an unmapped key would sample atlas bounds [0,0,0,0]
|
|
546
|
+
// (the wrong (0,0) sprite). `none` is a real transparent cell = "paints nothing".
|
|
547
|
+
const fallback = toKey(range.othersPattern ?? 'none');
|
|
548
|
+
const mapping: Record<string, string> = {};
|
|
549
|
+
for (const {value, pattern} of range.patternMap) {
|
|
550
|
+
mapping[value] = toKey(pattern);
|
|
551
|
+
}
|
|
552
|
+
const accessor = (properties: any) =>
|
|
553
|
+
mapping[properties[field.name]] ?? fallback;
|
|
554
|
+
return {
|
|
555
|
+
accessor: normalizeAccessor(accessor, data),
|
|
556
|
+
domain: range.patternMap.map(({value}) => value),
|
|
557
|
+
range: range.patternMap.map(({pattern}) => pattern),
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
|
|
513
561
|
export function getMaxMarkerSize(
|
|
514
562
|
visConfig: VisConfig,
|
|
515
563
|
visualChannels: VisualChannels
|
|
@@ -10,6 +10,8 @@ import {
|
|
|
10
10
|
getTextAccessor,
|
|
11
11
|
opacityToAlpha,
|
|
12
12
|
getIconUrlAccessor,
|
|
13
|
+
getLineStyleAccessor,
|
|
14
|
+
getFillPatternAccessor,
|
|
13
15
|
negateAccessor,
|
|
14
16
|
getMaxMarkerSize,
|
|
15
17
|
type LayerType,
|
|
@@ -32,6 +34,12 @@ import type {
|
|
|
32
34
|
VisualChannelField,
|
|
33
35
|
} from './types.js';
|
|
34
36
|
import {isRemoteCalculationSupported} from './utils.js';
|
|
37
|
+
import {
|
|
38
|
+
getPatternAtlas,
|
|
39
|
+
getPatternAtlasMapping,
|
|
40
|
+
getPatternScaleAdjustment,
|
|
41
|
+
getPatternTextureParameters,
|
|
42
|
+
} from './pattern-atlas.js';
|
|
35
43
|
import {
|
|
36
44
|
getRasterTileLayerStylePropsRgb,
|
|
37
45
|
getRasterTileLayerStylePropsScaledBand,
|
|
@@ -48,7 +56,8 @@ export type Scale = {
|
|
|
48
56
|
|
|
49
57
|
/** Domain of the user to construct d3 scale */
|
|
50
58
|
scaleDomain?: string[] | number[];
|
|
51
|
-
|
|
59
|
+
// `number[][]` carries per-category `[dash, gap]` tuples for the `lineStyle` scale.
|
|
60
|
+
range?: string[] | number[] | number[][];
|
|
52
61
|
};
|
|
53
62
|
|
|
54
63
|
export type ScaleKey =
|
|
@@ -57,7 +66,9 @@ export type ScaleKey =
|
|
|
57
66
|
| 'lineColor'
|
|
58
67
|
| 'lineWidth'
|
|
59
68
|
| 'elevation'
|
|
60
|
-
| 'weight'
|
|
69
|
+
| 'weight'
|
|
70
|
+
| 'lineStyle'
|
|
71
|
+
| 'fillPattern';
|
|
61
72
|
|
|
62
73
|
export type Scales = Partial<Record<ScaleKey, Scale>>;
|
|
63
74
|
|
|
@@ -377,6 +388,14 @@ function createChannelProps(
|
|
|
377
388
|
|
|
378
389
|
const scales: Record<string, Scale> = {};
|
|
379
390
|
|
|
391
|
+
const isVectorTile = layerType === 'mvt' || layerType === 'tileset';
|
|
392
|
+
const geometry = data.tilestats?.layers?.[0]?.geometry;
|
|
393
|
+
const isLine =
|
|
394
|
+
geometry === 'Line' ||
|
|
395
|
+
geometry === 'LineString' ||
|
|
396
|
+
geometry === 'MultiLineString';
|
|
397
|
+
const isPolygon = geometry === 'Polygon' || geometry === 'MultiPolygon';
|
|
398
|
+
|
|
380
399
|
// fill color
|
|
381
400
|
{
|
|
382
401
|
const {colorField, colorScale} = visualChannels;
|
|
@@ -559,6 +578,117 @@ function createChannelProps(
|
|
|
559
578
|
}
|
|
560
579
|
}
|
|
561
580
|
|
|
581
|
+
// stroke dash style — only VectorTileLayer (mvt/tileset) carries dashes; H3/Quadbin excluded.
|
|
582
|
+
{
|
|
583
|
+
// A line is always stroked; a polygon border only when `stroked`. Points are excluded.
|
|
584
|
+
const strokeVisible = isLine || (isPolygon && Boolean(visConfig.stroked));
|
|
585
|
+
if (isVectorTile && strokeVisible) {
|
|
586
|
+
const {lineStyleField, lineStyleScale} = visualChannels;
|
|
587
|
+
const {lineStyleRange} = visConfig;
|
|
588
|
+
|
|
589
|
+
// Fixed preset (used when no column drives the style).
|
|
590
|
+
if (visConfig.lineStyle && visConfig.lineStyle !== 'solid') {
|
|
591
|
+
if (visConfig.lineStyle === 'dotted') {
|
|
592
|
+
result.lineCapRounded = true;
|
|
593
|
+
}
|
|
594
|
+
result.lineStyle = visConfig.lineStyle;
|
|
595
|
+
if (visConfig.dashArray) {
|
|
596
|
+
result.dashArray = visConfig.dashArray;
|
|
597
|
+
result.getDashArray = visConfig.dashArray;
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
// Data-driven — mirrors getLineColor/getFillColor: computed whenever the field/scale/range
|
|
602
|
+
// are set, independent of the fixed `lineStyle`. Overrides the constant accessor above.
|
|
603
|
+
if (lineStyleField && lineStyleScale && lineStyleRange) {
|
|
604
|
+
const {accessor, ...scaleProps} = getLineStyleAccessor(
|
|
605
|
+
lineStyleField,
|
|
606
|
+
lineStyleRange,
|
|
607
|
+
data
|
|
608
|
+
);
|
|
609
|
+
result.getDashArray = accessor;
|
|
610
|
+
scales.lineStyle = updateTriggers.getDashArray = {
|
|
611
|
+
field: lineStyleField,
|
|
612
|
+
type: lineStyleScale,
|
|
613
|
+
...scaleProps,
|
|
614
|
+
};
|
|
615
|
+
// Round caps so per-category dotted values ([0, gap]) render as dots, not squares.
|
|
616
|
+
const dashArrays = [
|
|
617
|
+
...lineStyleRange.dashArrayMap.map(({dashArray}) => dashArray),
|
|
618
|
+
...(lineStyleRange.othersDashArray
|
|
619
|
+
? [lineStyleRange.othersDashArray]
|
|
620
|
+
: []),
|
|
621
|
+
];
|
|
622
|
+
if (dashArrays.some(([dash]) => dash === 0)) {
|
|
623
|
+
result.lineCapRounded = true;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
// fill pattern — Phase 2. The pattern is a stencil tinted by the existing fillColor
|
|
630
|
+
// (mask:true) — no separate pattern-color channel. The consumer attaches
|
|
631
|
+
// FillStyleExtension unconditionally and reads `fillPatternEnabled` as the on/off
|
|
632
|
+
// switch, mirroring how MaskExtension is gated by `maskId`. Data only — no extension
|
|
633
|
+
// instantiation here. Applies to any filled polygon layer (mvt/tileset + H3/Quadbin);
|
|
634
|
+
// the stroke-dash block above is the VectorTile-only one (per OQ 10).
|
|
635
|
+
{
|
|
636
|
+
const fillPatternEnabled = Boolean(
|
|
637
|
+
visConfig.filled && visConfig.fillPatternEnabled
|
|
638
|
+
);
|
|
639
|
+
result.fillPatternEnabled = fillPatternEnabled;
|
|
640
|
+
|
|
641
|
+
// Pattern props are emitted for every filled layer, even with the pattern off:
|
|
642
|
+
// removing them on a live layer transitions the async `fillPatternAtlas` prop to
|
|
643
|
+
// null, which crashes deck's layer matching (null image transform) and blanks the
|
|
644
|
+
// layer. A disabled layer samples the opaque `solid` cell instead — under
|
|
645
|
+
// fillPatternMask the mask multiplies by 1, i.e. a plain fill.
|
|
646
|
+
if (visConfig.filled) {
|
|
647
|
+
result.fillPatternAtlas = getPatternAtlas();
|
|
648
|
+
result.fillPatternMapping = getPatternAtlasMapping();
|
|
649
|
+
result.fillPatternMask = true;
|
|
650
|
+
const textureParameters = getPatternTextureParameters();
|
|
651
|
+
if (textureParameters) {
|
|
652
|
+
// Merged into the atlas texture's sampler by deck's image-prop transform.
|
|
653
|
+
result.textureParameters = textureParameters;
|
|
654
|
+
}
|
|
655
|
+
// Scale compensated for the atlas cell size — see getPatternScaleAdjustment.
|
|
656
|
+
result.getFillPatternScale =
|
|
657
|
+
(visConfig.fillPatternSize ?? 1) * getPatternScaleAdjustment();
|
|
658
|
+
|
|
659
|
+
const {fillPatternField, fillPatternScale} = visualChannels;
|
|
660
|
+
const {fillPatternRange, fillPatternDensity} = visConfig;
|
|
661
|
+
|
|
662
|
+
if (!fillPatternEnabled) {
|
|
663
|
+
result.getFillPattern = () => 'solid';
|
|
664
|
+
updateTriggers.getFillPattern = 'solid';
|
|
665
|
+
} else if (fillPatternField && fillPatternScale && fillPatternRange) {
|
|
666
|
+
// Flat prop for legend consumers (fallback when there is no by-column scale).
|
|
667
|
+
result.fillPattern = visConfig.fillPattern;
|
|
668
|
+
const {accessor, ...scaleProps} = getFillPatternAccessor(
|
|
669
|
+
fillPatternField,
|
|
670
|
+
fillPatternRange,
|
|
671
|
+
fillPatternDensity,
|
|
672
|
+
data
|
|
673
|
+
);
|
|
674
|
+
result.getFillPattern = accessor;
|
|
675
|
+
scales.fillPattern = updateTriggers.getFillPattern = {
|
|
676
|
+
field: fillPatternField,
|
|
677
|
+
type: fillPatternScale,
|
|
678
|
+
...scaleProps,
|
|
679
|
+
};
|
|
680
|
+
} else {
|
|
681
|
+
// Single mode: one real pattern (never solid/none) for every feature.
|
|
682
|
+
result.fillPattern = visConfig.fillPattern;
|
|
683
|
+
const key = `${visConfig.fillPattern}-${fillPatternDensity ?? 'medium'}`;
|
|
684
|
+
result.getFillPattern = () => key;
|
|
685
|
+
updateTriggers.getFillPattern = key;
|
|
686
|
+
}
|
|
687
|
+
// getFillColor is left exactly as the fillColor channel set it; under
|
|
688
|
+
// fillPatternMask:true that IS the pattern tint.
|
|
689
|
+
}
|
|
690
|
+
}
|
|
691
|
+
|
|
562
692
|
// height / elevation
|
|
563
693
|
{
|
|
564
694
|
const {heightField, heightScale} = visualChannels;
|
|
@@ -704,14 +834,7 @@ function createChannelProps(
|
|
|
704
834
|
// point labels at line midpoints / polygon centroids via `autoLabels`. The
|
|
705
835
|
// optional `uniqueIdProperty` dedupes features that span multiple tiles so
|
|
706
836
|
// each feature gets one label instead of one-per-tile.
|
|
707
|
-
|
|
708
|
-
const isLineOrPolygon =
|
|
709
|
-
geometry === 'Polygon' ||
|
|
710
|
-
geometry === 'MultiPolygon' ||
|
|
711
|
-
geometry === 'Line' ||
|
|
712
|
-
geometry === 'LineString' ||
|
|
713
|
-
geometry === 'MultiLineString';
|
|
714
|
-
if (isLineOrPolygon && (layerType === 'tileset' || layerType === 'mvt')) {
|
|
837
|
+
if ((isLine || isPolygon) && isVectorTile) {
|
|
715
838
|
const uniqueIdProperty = visConfig.textLabelUniqueIdField;
|
|
716
839
|
result.autoLabels = uniqueIdProperty ? {uniqueIdProperty} : true;
|
|
717
840
|
result.pointType = 'text';
|