@carto/api-client 0.5.14 → 0.5.15-alpha.raster-1

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.
@@ -8335,6 +8335,250 @@ var basemap_styles_default = {
8335
8335
  DARK_MATTER_NOLABELS: getStyleUrl("dark-matter-nolabels")
8336
8336
  };
8337
8337
 
8338
+ // src/fetch-map/vec-expr-evaluator.ts
8339
+ import jsep from "jsep";
8340
+ function createVecExprEvaluator(expression) {
8341
+ try {
8342
+ const parsed = compile(expression);
8343
+ const evalFun = (context) => evaluate(parsed, context);
8344
+ evalFun.symbols = getSymbols(parsed);
8345
+ return evalFun;
8346
+ } catch {
8347
+ return null;
8348
+ }
8349
+ }
8350
+ function evaluateVecExpr(expression, context) {
8351
+ try {
8352
+ return createVecExprEvaluator(expression)?.(context);
8353
+ } catch {
8354
+ return null;
8355
+ }
8356
+ }
8357
+ var ErrorCode = /* @__PURE__ */ ((ErrorCode2) => {
8358
+ ErrorCode2[ErrorCode2["InvalidSyntax"] = 0] = "InvalidSyntax";
8359
+ ErrorCode2[ErrorCode2["UnknownIdentifier"] = 1] = "UnknownIdentifier";
8360
+ return ErrorCode2;
8361
+ })(ErrorCode || {});
8362
+ function validateVecExprSyntax(expression, context) {
8363
+ let parsed;
8364
+ try {
8365
+ parsed = compile(expression);
8366
+ } catch (e) {
8367
+ return {
8368
+ valid: false,
8369
+ errorCode: 0 /* InvalidSyntax */,
8370
+ errorMessage: e && "message" in e ? String(e.message) : String(e)
8371
+ };
8372
+ }
8373
+ return validate(parsed, context);
8374
+ }
8375
+ function createResultArray(typeTemplate, length2 = typeTemplate.length) {
8376
+ return new Array(length2);
8377
+ }
8378
+ function isVecLike(a) {
8379
+ return Array.isArray(a) || ArrayBuffer.isView(a);
8380
+ }
8381
+ var createBinopVec = (scalarBinOp) => (left, right) => {
8382
+ const length2 = Math.min(left.length, right.length);
8383
+ const r = createResultArray(left, length2);
8384
+ for (let i = 0; i < length2; i++) {
8385
+ r[i] = scalarBinOp(left[i], right[i]);
8386
+ }
8387
+ return r;
8388
+ };
8389
+ var createBinopVecNum = (scalarBinOp) => (left, right) => {
8390
+ const length2 = left.length;
8391
+ const r = createResultArray(left, length2);
8392
+ for (let i = 0; i < length2; i++) {
8393
+ r[i] = scalarBinOp(left[i], right);
8394
+ }
8395
+ return r;
8396
+ };
8397
+ var createBinopNumVec = (scalarBinOp) => (left, right) => {
8398
+ const length2 = right.length;
8399
+ const r = createResultArray(right, length2);
8400
+ for (let i = 0; i < length2; i++) {
8401
+ r[i] = scalarBinOp(left, right[i]);
8402
+ }
8403
+ return r;
8404
+ };
8405
+ var createUnopVec = (scalarUnop) => (a) => {
8406
+ const length2 = a.length;
8407
+ const r = createResultArray(a, length2);
8408
+ for (let i = 0; i < length2; i++) {
8409
+ r[i] = scalarUnop(a[i]);
8410
+ }
8411
+ return r;
8412
+ };
8413
+ function mapDictValues(dict, fun) {
8414
+ return Object.keys(dict).reduce(
8415
+ (acc, key) => {
8416
+ acc[key] = fun(dict[key]);
8417
+ return acc;
8418
+ },
8419
+ {}
8420
+ );
8421
+ }
8422
+ var binopsNum = {
8423
+ "||": (a, b) => a || b,
8424
+ "&&": (a, b) => a && b,
8425
+ "|": (a, b) => a | b,
8426
+ "^": (a, b) => a ^ b,
8427
+ "&": (a, b) => a & b,
8428
+ "==": (a, b) => Number(a == b),
8429
+ "!=": (a, b) => Number(a != b),
8430
+ "===": (a, b) => Number(a === b),
8431
+ "!==": (a, b) => Number(a !== b),
8432
+ "<": (a, b) => Number(a < b),
8433
+ ">": (a, b) => Number(a > b),
8434
+ "<=": (a, b) => Number(a <= b),
8435
+ ">=": (a, b) => Number(a >= b),
8436
+ "<<": (a, b) => a << b,
8437
+ ">>": (a, b) => a >> b,
8438
+ ">>>": (a, b) => a >>> b,
8439
+ "+": (a, b) => a + b,
8440
+ "-": (a, b) => a - b,
8441
+ "*": (a, b) => a * b,
8442
+ "/": (a, b) => a / b,
8443
+ "%": (a, b) => a % b
8444
+ };
8445
+ var unopsNum = {
8446
+ "-": (a) => -a,
8447
+ "+": (a) => +a,
8448
+ "~": (a) => ~a,
8449
+ "!": (a) => Number(!a)
8450
+ };
8451
+ var binopsVector = mapDictValues(binopsNum, createBinopVec);
8452
+ var binopsNumVec = mapDictValues(binopsNum, createBinopNumVec);
8453
+ var binopsVecNum = mapDictValues(binopsNum, createBinopVecNum);
8454
+ var unopsVector = mapDictValues(unopsNum, createUnopVec);
8455
+ function getBinop(operator, left, right) {
8456
+ const isLeftVec = isVecLike(left);
8457
+ const isRightVec = isVecLike(right);
8458
+ if (isLeftVec && isRightVec) {
8459
+ return binopsVector[operator];
8460
+ } else if (isLeftVec) {
8461
+ return binopsVecNum[operator];
8462
+ } else if (isRightVec) {
8463
+ return binopsNumVec[operator];
8464
+ } else {
8465
+ return binopsNum[operator];
8466
+ }
8467
+ }
8468
+ function evaluate(_node, context) {
8469
+ const node = _node;
8470
+ switch (node.type) {
8471
+ case "BinaryExpression": {
8472
+ const left = evaluate(node.left, context);
8473
+ const right = evaluate(node.right, context);
8474
+ const binopFun = getBinop(node.operator, left, right);
8475
+ return binopFun(left, right);
8476
+ }
8477
+ case "ConditionalExpression": {
8478
+ const val = evaluate(node.test, context);
8479
+ if (isVecLike(val)) {
8480
+ const length2 = val.length;
8481
+ const consequentVal = evaluate(node.consequent, context);
8482
+ const alternateVal = evaluate(node.alternate, context);
8483
+ const r = createResultArray(val);
8484
+ for (let i = 0; i < length2; i++) {
8485
+ const entryVal = val[i] ? consequentVal : alternateVal;
8486
+ r[i] = isVecLike(entryVal) ? entryVal[i] ?? NaN : entryVal;
8487
+ }
8488
+ return r;
8489
+ } else {
8490
+ return val ? evaluate(node.consequent, context) : evaluate(node.alternate, context);
8491
+ }
8492
+ }
8493
+ case "Identifier":
8494
+ return context[node.name];
8495
+ case "Literal":
8496
+ return node.value;
8497
+ case "UnaryExpression": {
8498
+ const val = evaluate(node.argument, context);
8499
+ const unopFun = isVecLike(val) ? unopsVector[node.operator] : unopsNum[node.operator];
8500
+ return unopFun(val);
8501
+ }
8502
+ default:
8503
+ return void 0;
8504
+ }
8505
+ }
8506
+ var validResult = { valid: true };
8507
+ function visit(_node, visitor) {
8508
+ const node = _node;
8509
+ visitor(node);
8510
+ switch (node.type) {
8511
+ case "BinaryExpression": {
8512
+ visit(node.left, visitor);
8513
+ visit(node.right, visitor);
8514
+ break;
8515
+ }
8516
+ case "ConditionalExpression": {
8517
+ visit(node.test, visitor);
8518
+ visit(node.consequent, visitor);
8519
+ visit(node.alternate, visitor);
8520
+ break;
8521
+ }
8522
+ case "UnaryExpression": {
8523
+ visit(node.argument, visitor);
8524
+ break;
8525
+ }
8526
+ }
8527
+ }
8528
+ var supportedExpressionTypes = [
8529
+ "BinaryExpression",
8530
+ "UnaryExpression",
8531
+ "ConditionalExpression",
8532
+ "LogicalExpression",
8533
+ "Identifier",
8534
+ "Literal"
8535
+ ];
8536
+ function validate(_node, context) {
8537
+ const node = _node;
8538
+ const errors = [];
8539
+ visit(node, (node2) => {
8540
+ if (!supportedExpressionTypes.includes(node2.type)) {
8541
+ errors.push({
8542
+ valid: false,
8543
+ errorCode: 0 /* InvalidSyntax */,
8544
+ errorMessage: `Not allowed`
8545
+ });
8546
+ return;
8547
+ }
8548
+ if (node2.type === "Identifier") {
8549
+ if (!Object.prototype.hasOwnProperty.call(context, node2.name)) {
8550
+ return errors.push({
8551
+ valid: false,
8552
+ errorCode: 1 /* UnknownIdentifier */,
8553
+ errorMessage: `"${node2.name}" not found`
8554
+ });
8555
+ }
8556
+ }
8557
+ if (node2.type === "Literal") {
8558
+ if (typeof node2.value !== "number") {
8559
+ return errors.push({
8560
+ valid: false,
8561
+ errorCode: 0 /* InvalidSyntax */,
8562
+ errorMessage: `Only number literals are supported`
8563
+ });
8564
+ }
8565
+ }
8566
+ });
8567
+ return errors.length ? errors[0] : validResult;
8568
+ }
8569
+ function getSymbols(node) {
8570
+ const symbols = /* @__PURE__ */ new Set();
8571
+ visit(node, (node2) => {
8572
+ if (node2.type === "Identifier") {
8573
+ symbols.add(node2.name);
8574
+ }
8575
+ });
8576
+ return Array.from(symbols);
8577
+ }
8578
+ function compile(expression) {
8579
+ return jsep(expression);
8580
+ }
8581
+
8338
8582
  // node_modules/d3-array/src/ascending.js
8339
8583
  function ascending(a, b) {
8340
8584
  return a == null || b == null ? NaN : a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
@@ -8962,6 +9206,12 @@ var sharedPropMap = {
8962
9206
  wireframe: "wireframe"
8963
9207
  }
8964
9208
  };
9209
+ var rasterPropsMap = {
9210
+ isVisible: "visible",
9211
+ visConfig: {
9212
+ opacity: "opacity"
9213
+ }
9214
+ };
8965
9215
  var customMarkersPropsMap = {
8966
9216
  color: "getIconColor",
8967
9217
  visConfig: {
@@ -9005,6 +9255,12 @@ function getLayerProps(type, config2, dataset) {
9005
9255
  `Outdated layer type: ${type}. Please open map in CARTO Builder to automatically migrate.`
9006
9256
  );
9007
9257
  }
9258
+ if (type === "raster") {
9259
+ return {
9260
+ propMap: rasterPropsMap,
9261
+ defaultProps: {}
9262
+ };
9263
+ }
9008
9264
  let basePropMap = sharedPropMap;
9009
9265
  if (config2.visConfig?.customMarkers) {
9010
9266
  basePropMap = mergePropMaps(basePropMap, customMarkersPropsMap);
@@ -9025,16 +9281,19 @@ function getLayerProps(type, config2, dataset) {
9025
9281
  }
9026
9282
  function domainFromAttribute(attribute, scaleType, scaleLength) {
9027
9283
  if (scaleType === "ordinal" || scaleType === "point") {
9284
+ if (!attribute.categories) {
9285
+ return [0, 1];
9286
+ }
9028
9287
  return attribute.categories.map((c) => c.category).filter((c) => c !== void 0 && c !== null);
9029
9288
  }
9030
9289
  if (scaleType === "quantile" && attribute.quantiles) {
9031
- return attribute.quantiles.global ? attribute.quantiles.global[scaleLength] : attribute.quantiles[scaleLength];
9290
+ return "global" in attribute.quantiles ? attribute.quantiles.global[scaleLength] : attribute.quantiles[scaleLength];
9032
9291
  }
9033
9292
  let { min: min2 } = attribute;
9034
9293
  if (scaleType === "log" && min2 === 0) {
9035
9294
  min2 = 1e-5;
9036
9295
  }
9037
- return [min2, attribute.max];
9296
+ return [min2 ?? 0, attribute.max ?? 1];
9038
9297
  }
9039
9298
  function domainFromValues(values, scaleType) {
9040
9299
  if (scaleType === "ordinal" || scaleType === "point") {
@@ -9055,12 +9314,14 @@ function calculateDomain(data, name, scaleType, scaleLength) {
9055
9314
  if (data.tilestats) {
9056
9315
  const { attributes } = data.tilestats.layers[0];
9057
9316
  const attribute = attributes.find((a) => a.attribute === name);
9058
- return domainFromAttribute(attribute, scaleType, scaleLength);
9317
+ if (attribute) {
9318
+ return domainFromAttribute(attribute, scaleType, scaleLength);
9319
+ }
9059
9320
  }
9060
9321
  return [0, 1];
9061
9322
  }
9062
9323
  function normalizeAccessor(accessor, data) {
9063
- if (data.features || data.tilestats) {
9324
+ if (data.features || data.tilestats || data.raster_metadata) {
9064
9325
  return (object, info) => {
9065
9326
  if (object) {
9066
9327
  return accessor(object.properties || object.__source.object.properties);
@@ -9112,7 +9373,6 @@ function getColorAccessor({ name, colorColumn }, scaleType, { aggregation, range
9112
9373
  return { accessor: normalizeAccessor(accessor, data), scale: scale2 };
9113
9374
  }
9114
9375
  function calculateLayerScale(name, scaleType, range, data) {
9115
- const scale2 = SCALE_FUNCS[scaleType]();
9116
9376
  let domain = [];
9117
9377
  let scaleColor = [];
9118
9378
  if (scaleType !== "identity") {
@@ -9130,9 +9390,13 @@ function calculateLayerScale(name, scaleType, range, data) {
9130
9390
  domain = domain.slice(0, scaleColor.length);
9131
9391
  }
9132
9392
  }
9393
+ return createColorScale(scaleType, domain, scaleColor, UNKNOWN_COLOR);
9394
+ }
9395
+ function createColorScale(scaleType, domain, range, unknown) {
9396
+ const scale2 = SCALE_FUNCS[scaleType]();
9133
9397
  scale2.domain(domain);
9134
- scale2.range(scaleColor);
9135
- scale2.unknown(UNKNOWN_COLOR);
9398
+ scale2.range(range);
9399
+ scale2.unknown(unknown);
9136
9400
  return scale2;
9137
9401
  }
9138
9402
  var FALLBACK_ICON = "data:image/svg+xml;charset=utf-8;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTAwIDEwMCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4NCiAgPGNpcmNsZSBjeD0iNTAiIGN5PSI1MCIgcj0iNTAiLz4NCjwvc3ZnPg==";
@@ -9247,13 +9511,419 @@ function calculateClusterTextFontSize(radius) {
9247
9511
  return 11;
9248
9512
  }
9249
9513
 
9514
+ // src/fetch-map/raster-layer.ts
9515
+ var UNKNOWN_COLOR2 = [134, 141, 145];
9516
+ var RASTER_COLOR_BANDS = ["red", "green", "blue"];
9517
+ function getHasDataPredicate(noData) {
9518
+ if (noData === "nan") {
9519
+ return (v2) => !isNaN(v2);
9520
+ }
9521
+ if (typeof noData === "string") {
9522
+ noData = parseFloat(noData);
9523
+ }
9524
+ if (typeof noData === "number") {
9525
+ return (v2) => v2 !== noData && !isNaN(v2);
9526
+ }
9527
+ return () => true;
9528
+ }
9529
+ function createRasterColumnLayerDataTransform(transform) {
9530
+ return (data) => {
9531
+ if (!data || !("data" in data) || !data?.data?.cells?.numericProps) {
9532
+ return data;
9533
+ }
9534
+ return transform(data);
9535
+ };
9536
+ }
9537
+ function createEvaluationContext(numericProps, noData) {
9538
+ const hasData = getHasDataPredicate(noData);
9539
+ const bands = Object.entries(numericProps).map(([bandName, { value }]) => ({
9540
+ bandName,
9541
+ values: value,
9542
+ copied: false
9543
+ }));
9544
+ const length2 = bands[0].values.length;
9545
+ for (let i = 0; i < length2; i++) {
9546
+ let hasSomeData = false;
9547
+ for (let j = 0; j < bands.length; j++) {
9548
+ hasSomeData = hasSomeData || hasData(bands[j].values[i]);
9549
+ }
9550
+ if (!hasSomeData) {
9551
+ for (let j = 0; j < bands.length; j++) {
9552
+ if (!bands[j].copied) {
9553
+ bands[j].copied = true;
9554
+ bands[j].values = Array.from(bands[j].values);
9555
+ }
9556
+ bands[j].values[i] = NaN;
9557
+ }
9558
+ }
9559
+ }
9560
+ const context = bands.reduce(
9561
+ (agg, { bandName, values }) => {
9562
+ agg[bandName] = values;
9563
+ return agg;
9564
+ },
9565
+ {}
9566
+ );
9567
+ return context;
9568
+ }
9569
+ function createExprDataTransform({
9570
+ colorBand,
9571
+ rasterMetadata,
9572
+ usedSymbols
9573
+ }) {
9574
+ if (!colorBand || !colorBand.type || colorBand.type === "none") {
9575
+ return void 0;
9576
+ }
9577
+ const expr = colorBand?.type === "expression" ? colorBand.value : void 0;
9578
+ const vecExprEvaluator = expr ? createVecExprEvaluator(expr) : void 0;
9579
+ const dataTransform = createRasterColumnLayerDataTransform(
9580
+ (dataWrapped) => {
9581
+ const data = dataWrapped.data;
9582
+ if (expr) {
9583
+ const cachedResult = dataWrapped.customExpressionResults?.[expr];
9584
+ if (cachedResult) {
9585
+ return dataWrapped;
9586
+ }
9587
+ }
9588
+ let context = dataWrapped.expressionEvalContext;
9589
+ if (!context) {
9590
+ const usedNumericProps = usedSymbols.reduce(
9591
+ (acc, symbol) => {
9592
+ acc[symbol] = data.cells.numericProps[symbol];
9593
+ return acc;
9594
+ },
9595
+ {}
9596
+ );
9597
+ context = createEvaluationContext(
9598
+ usedNumericProps,
9599
+ rasterMetadata.nodata
9600
+ );
9601
+ dataWrapped = {
9602
+ ...dataWrapped,
9603
+ expressionEvalContext: context
9604
+ };
9605
+ }
9606
+ if (!vecExprEvaluator || !expr) return dataWrapped;
9607
+ const evalResult = vecExprEvaluator(context);
9608
+ return {
9609
+ ...dataWrapped,
9610
+ customExpressionResults: {
9611
+ ...dataWrapped.customExpressionResults,
9612
+ [expr]: evalResult
9613
+ }
9614
+ };
9615
+ }
9616
+ );
9617
+ return dataTransform;
9618
+ }
9619
+ function combineDataTransforms(dataTransforms) {
9620
+ const actualTransforms = dataTransforms.filter((v2) => v2);
9621
+ if (actualTransforms.length === 0) return void 0;
9622
+ if (actualTransforms.length === 1) return actualTransforms[0];
9623
+ return (data) => actualTransforms.reduce(
9624
+ (aggData, transformFun) => transformFun(aggData),
9625
+ data
9626
+ );
9627
+ }
9628
+ function createRgbToColorBufferDataTransform({
9629
+ bandDefs,
9630
+ attribute
9631
+ }) {
9632
+ return createRasterColumnLayerDataTransform(
9633
+ (dataWrapped) => {
9634
+ const length2 = dataWrapped.length;
9635
+ const getBandBufferOrValue = (colorBand) => {
9636
+ if (colorBand?.type === "expression") {
9637
+ return dataWrapped.customExpressionResults?.[colorBand.value];
9638
+ }
9639
+ if (colorBand?.type === "band") {
9640
+ return dataWrapped.expressionEvalContext?.[colorBand.value];
9641
+ }
9642
+ return 0;
9643
+ };
9644
+ const red = getBandBufferOrValue(bandDefs.red);
9645
+ const green = getBandBufferOrValue(bandDefs.green);
9646
+ const blue = getBandBufferOrValue(bandDefs.blue);
9647
+ const colorBuffer = new Uint8Array(length2 * 4);
9648
+ for (let inputIndex = 0, outputIndex = 0; inputIndex < length2; inputIndex++, outputIndex += 4) {
9649
+ const redRaw = typeof red === "number" ? red : red ? red[inputIndex] : NaN;
9650
+ const greenRaw = typeof green === "number" ? green : green ? green[inputIndex] : NaN;
9651
+ const blueRaw = typeof blue === "number" ? blue : blue ? blue[inputIndex] : NaN;
9652
+ if (isNaN(redRaw) && isNaN(greenRaw) && isNaN(blueRaw)) {
9653
+ bufferSetRgba(colorBuffer, outputIndex, 0, 0, 0, 0);
9654
+ } else {
9655
+ bufferSetRgba(
9656
+ colorBuffer,
9657
+ outputIndex,
9658
+ redRaw,
9659
+ greenRaw,
9660
+ blueRaw,
9661
+ 255
9662
+ );
9663
+ }
9664
+ }
9665
+ dataWrapped.customExpressionResults = void 0;
9666
+ dataWrapped.expressionEvalContext = void 0;
9667
+ return {
9668
+ ...dataWrapped,
9669
+ attributes: {
9670
+ [attribute]: colorBuffer
9671
+ }
9672
+ };
9673
+ }
9674
+ );
9675
+ }
9676
+ function getUsedSymbols(colorBands) {
9677
+ return Array.from(
9678
+ colorBands.reduce((symbols, band) => {
9679
+ if (band.type === "expression") {
9680
+ const expressionSymbols = createVecExprEvaluator(band.value)?.symbols || [];
9681
+ expressionSymbols.forEach((symbol) => symbols.add(symbol));
9682
+ }
9683
+ if (band.type === "band") {
9684
+ symbols.add(band.value);
9685
+ }
9686
+ return symbols;
9687
+ }, /* @__PURE__ */ new Set())
9688
+ );
9689
+ }
9690
+ function getRasterTileLayerStylePropsRgb({
9691
+ layerConfig,
9692
+ rasterMetadata,
9693
+ visualChannels
9694
+ }) {
9695
+ const { visConfig } = layerConfig;
9696
+ const { colorBands } = visConfig;
9697
+ const bandDefs = {
9698
+ red: colorBands?.find((band) => band.band === "red"),
9699
+ green: colorBands?.find((band) => band.band === "green"),
9700
+ blue: colorBands?.find((band) => band.band === "blue")
9701
+ };
9702
+ const rgbToInstanceFillColorsDataTransform = createRgbToColorBufferDataTransform({
9703
+ bandDefs,
9704
+ attribute: "instanceFillColors"
9705
+ });
9706
+ const usedSymbols = colorBands ? getUsedSymbols(colorBands) : [];
9707
+ const bandTransforms = RASTER_COLOR_BANDS.map(
9708
+ (band) => createExprDataTransform({
9709
+ colorBand: bandDefs[band],
9710
+ rasterMetadata,
9711
+ usedSymbols
9712
+ })
9713
+ );
9714
+ const combinedDataTransform = combineDataTransforms([
9715
+ ...bandTransforms,
9716
+ rgbToInstanceFillColorsDataTransform
9717
+ ]);
9718
+ return {
9719
+ dataTransform: combinedDataTransform,
9720
+ updateTriggers: getRasterTileLayerUpdateTriggers({
9721
+ layerConfig,
9722
+ visualChannels
9723
+ })
9724
+ };
9725
+ }
9726
+ function createBandColorScaleDataTransform({
9727
+ bandName,
9728
+ scaleFun,
9729
+ nodata,
9730
+ attribute
9731
+ }) {
9732
+ const hasData = getHasDataPredicate(nodata);
9733
+ return createRasterColumnLayerDataTransform(
9734
+ (dataWrapped) => {
9735
+ const length2 = dataWrapped.length;
9736
+ const bandBuffer = dataWrapped.data.cells.numericProps[bandName].value;
9737
+ const colorBuffer = new Uint8Array(length2 * 4);
9738
+ for (let i = 0; i < length2; i++) {
9739
+ const rawValue = bandBuffer[i];
9740
+ if (!hasData(rawValue)) {
9741
+ bufferSetRgba(colorBuffer, i * 4, 0, 0, 0, 0);
9742
+ } else {
9743
+ const colorRgb = scaleFun(rawValue);
9744
+ bufferSetRgba(
9745
+ colorBuffer,
9746
+ i * 4,
9747
+ colorRgb[0],
9748
+ colorRgb[1],
9749
+ colorRgb[2],
9750
+ 255
9751
+ );
9752
+ }
9753
+ }
9754
+ return {
9755
+ ...dataWrapped,
9756
+ attributes: {
9757
+ [attribute]: colorBuffer
9758
+ }
9759
+ };
9760
+ }
9761
+ );
9762
+ }
9763
+ function domainFromRasterMetadataBand(band, scaleType, colorRange) {
9764
+ if (scaleType === "ordinal") {
9765
+ return colorRange.colorMap?.map(([value]) => value) || [];
9766
+ }
9767
+ if (scaleType === "custom") {
9768
+ if (colorRange.uiCustomScaleType === "logarithmic") {
9769
+ if (colorRange.colorMap) {
9770
+ return colorRange.colorMap?.map(([value]) => value) || [];
9771
+ }
9772
+ return [band.stats.min, band.stats.max];
9773
+ } else {
9774
+ return colorRange.colorMap?.map(([value]) => value) || [];
9775
+ }
9776
+ }
9777
+ const scaleLength = colorRange.colors.length;
9778
+ if (scaleType === "quantile") {
9779
+ const quantiles = band.stats.quantiles?.[scaleLength];
9780
+ if (!quantiles) {
9781
+ return [0, 1];
9782
+ }
9783
+ return [band.stats.min, ...quantiles, band.stats.max];
9784
+ }
9785
+ return [band.stats.min, band.stats.max];
9786
+ }
9787
+ function getRasterTileLayerStylePropsScaledBand({
9788
+ layerConfig,
9789
+ rasterMetadata,
9790
+ visualChannels
9791
+ }) {
9792
+ const { visConfig } = layerConfig;
9793
+ const { colorField } = visualChannels;
9794
+ const { rasterStyleType } = visConfig;
9795
+ const colorRange = rasterStyleType === "ColorRange" ? visConfig.colorRange : visConfig.uniqueValuesColorRange;
9796
+ const scaleType = rasterStyleType === "ColorRange" ? visualChannels.colorScale : "ordinal";
9797
+ const bandInfo = rasterMetadata.bands.find(
9798
+ (band) => band.name === colorField?.name
9799
+ );
9800
+ if (!colorField?.name || !scaleType || !colorRange || !bandInfo) {
9801
+ return {};
9802
+ }
9803
+ const domain = domainFromRasterMetadataBand(bandInfo, scaleType, colorRange);
9804
+ const scaleFun = createColorScale(
9805
+ scaleType,
9806
+ domain,
9807
+ colorRange.colors.map(hexToRGB),
9808
+ UNKNOWN_COLOR2
9809
+ );
9810
+ const bandColorScaleDataTransform = createBandColorScaleDataTransform({
9811
+ bandName: bandInfo.name,
9812
+ scaleFun,
9813
+ nodata: bandInfo?.nodata ?? rasterMetadata.nodata,
9814
+ attribute: "instanceFillColors"
9815
+ });
9816
+ return {
9817
+ dataTransform: bandColorScaleDataTransform,
9818
+ updateTriggers: getRasterTileLayerUpdateTriggers({
9819
+ layerConfig,
9820
+ visualChannels
9821
+ })
9822
+ };
9823
+ }
9824
+ function getRasterTileLayerStyleProps({
9825
+ layerConfig,
9826
+ visualChannels,
9827
+ rasterMetadata
9828
+ }) {
9829
+ const { visConfig } = layerConfig;
9830
+ const { rasterStyleType } = visConfig;
9831
+ if (rasterStyleType === "Rgb") {
9832
+ return getRasterTileLayerStylePropsRgb({
9833
+ layerConfig,
9834
+ rasterMetadata,
9835
+ visualChannels
9836
+ });
9837
+ } else {
9838
+ return getRasterTileLayerStylePropsScaledBand({
9839
+ layerConfig,
9840
+ rasterMetadata,
9841
+ visualChannels
9842
+ });
9843
+ }
9844
+ }
9845
+ function getRasterTileLayerUpdateTriggers({
9846
+ layerConfig,
9847
+ visualChannels
9848
+ }) {
9849
+ const { visConfig } = layerConfig;
9850
+ const { rasterStyleType } = visConfig;
9851
+ const getFillColorUpdateTriggers = {
9852
+ rasterStyleType
9853
+ };
9854
+ if (rasterStyleType === "ColorRange") {
9855
+ getFillColorUpdateTriggers.colorRange = visConfig.colorRange?.colors;
9856
+ getFillColorUpdateTriggers.colorMap = visConfig.colorRange?.colorMap;
9857
+ getFillColorUpdateTriggers.colorScale = visualChannels.colorScale;
9858
+ getFillColorUpdateTriggers.colorFieldId = visualChannels.colorField?.name;
9859
+ } else if (rasterStyleType === "UniqueValues") {
9860
+ getFillColorUpdateTriggers.colorMap = visConfig.uniqueValuesColorRange?.colorMap;
9861
+ getFillColorUpdateTriggers.colorFieldId = visualChannels.colorField?.name;
9862
+ } else if (rasterStyleType === "Rgb") {
9863
+ getFillColorUpdateTriggers.colorBands = visConfig.colorBands;
9864
+ }
9865
+ return {
9866
+ getFillColor: getFillColorUpdateTriggers
9867
+ };
9868
+ }
9869
+ function bufferSetRgba(target, index, r, g, b, a) {
9870
+ target[index + 0] = r;
9871
+ target[index + 1] = g;
9872
+ target[index + 2] = b;
9873
+ target[index + 3] = a;
9874
+ }
9875
+ function hexToRGB(hexColor) {
9876
+ const r = parseInt(hexColor.slice(1, 3), 16);
9877
+ const g = parseInt(hexColor.slice(3, 5), 16);
9878
+ const b = parseInt(hexColor.slice(5, 7), 16);
9879
+ return [r, g, b];
9880
+ }
9881
+
9250
9882
  // src/fetch-map/parse-map.ts
9883
+ function getLayerDescriptor({
9884
+ mapConfig,
9885
+ layer,
9886
+ dataset
9887
+ }) {
9888
+ const { filters, visState } = mapConfig;
9889
+ const { layerBlending, interactionConfig } = visState;
9890
+ const { id, type, config: config2, visualChannels } = layer;
9891
+ const { data, id: datasetId } = dataset;
9892
+ const { propMap, defaultProps: defaultProps2 } = getLayerProps(type, config2, dataset);
9893
+ const styleProps = createStyleProps(config2, propMap);
9894
+ const { channelProps, scales } = createChannelProps(
9895
+ id,
9896
+ type,
9897
+ config2,
9898
+ visualChannels,
9899
+ data,
9900
+ dataset
9901
+ );
9902
+ const layerDescriptor = {
9903
+ type,
9904
+ filters: isEmptyObject(filters) || isRemoteCalculationSupported(dataset) ? void 0 : filters[datasetId],
9905
+ props: {
9906
+ id,
9907
+ data,
9908
+ ...defaultProps2,
9909
+ ...createInteractionProps(interactionConfig),
9910
+ ...styleProps,
9911
+ ...channelProps,
9912
+ ...createParametersProp(layerBlending, styleProps.parameters || {}),
9913
+ // Must come after style
9914
+ ...createLoadOptions(data.accessToken)
9915
+ },
9916
+ scales
9917
+ };
9918
+ return layerDescriptor;
9919
+ }
9251
9920
  function parseMap(json) {
9252
9921
  const { keplerMapConfig, datasets, token } = json;
9253
9922
  assert2(keplerMapConfig.version === "v1", "Only support Kepler v1");
9254
- const config2 = keplerMapConfig.config;
9255
- const { filters, mapState, mapStyle, popupSettings, legendSettings } = config2;
9256
- const { layers, layerBlending, interactionConfig } = config2.visState;
9923
+ const mapConfig = keplerMapConfig.config;
9924
+ const { mapState, mapStyle, popupSettings, legendSettings, visState } = mapConfig;
9925
+ const { layers } = visState;
9926
+ const layersReverse = [...layers].reverse();
9257
9927
  return {
9258
9928
  id: json.id,
9259
9929
  title: json.title,
@@ -9266,45 +9936,19 @@ function parseMap(json) {
9266
9936
  popupSettings,
9267
9937
  legendSettings,
9268
9938
  token,
9269
- layers: layers.reverse().map(({ id, type, config: config3, visualChannels }) => {
9939
+ layers: layersReverse.map((layer) => {
9270
9940
  try {
9271
- const { dataId } = config3;
9941
+ const { dataId } = layer.config;
9272
9942
  const dataset = datasets.find(
9273
9943
  (d) => d.id === dataId
9274
9944
  );
9275
9945
  assert2(dataset, `No dataset matching dataId: ${dataId}`);
9276
- const { data } = dataset;
9277
- assert2(data, `No data loaded for dataId: ${dataId}`);
9278
- const { propMap, defaultProps: defaultProps2 } = getLayerProps(type, config3, dataset);
9279
- const styleProps = createStyleProps(config3, propMap);
9280
- const { channelProps, scales } = createChannelProps(
9281
- id,
9282
- type,
9283
- config3,
9284
- visualChannels,
9285
- data,
9946
+ const layerDescriptor = getLayerDescriptor({
9947
+ mapConfig,
9948
+ layer,
9286
9949
  dataset
9287
- );
9288
- const layer = {
9289
- type,
9290
- filters: isEmptyObject(filters) || isRemoteCalculationSupported(dataset) ? void 0 : filters[dataId],
9291
- props: {
9292
- id,
9293
- data,
9294
- ...defaultProps2,
9295
- ...createInteractionProps(interactionConfig),
9296
- ...styleProps,
9297
- ...channelProps,
9298
- ...createParametersProp(
9299
- layerBlending,
9300
- styleProps.parameters || {}
9301
- ),
9302
- // Must come after style
9303
- ...createLoadOptions(token)
9304
- },
9305
- scales
9306
- };
9307
- return layer;
9950
+ });
9951
+ return layerDescriptor;
9308
9952
  } catch (e) {
9309
9953
  console.error(e.message);
9310
9954
  return void 0;
@@ -9383,11 +10027,52 @@ function createChannelProps(id, layerType, config2, visualChannels, data, datase
9383
10027
  radiusScale,
9384
10028
  strokeColorField,
9385
10029
  strokeColorScale,
10030
+ sizeField: strokeWidthField,
10031
+ sizeScale: strokeWidthScale,
9386
10032
  weightField
9387
10033
  } = visualChannels;
10034
+ if (layerType === "raster") {
10035
+ const rasterMetadata = data.raster_metadata;
10036
+ if (!rasterMetadata) {
10037
+ return {
10038
+ channelProps: {},
10039
+ scales: {}
10040
+ };
10041
+ }
10042
+ const rasterStyleType = config2.visConfig.rasterStyleType;
10043
+ if (rasterStyleType === "Rgb") {
10044
+ return {
10045
+ channelProps: getRasterTileLayerStylePropsRgb({
10046
+ layerConfig: config2,
10047
+ rasterMetadata,
10048
+ visualChannels
10049
+ }),
10050
+ scales: {}
10051
+ };
10052
+ } else {
10053
+ return {
10054
+ channelProps: getRasterTileLayerStylePropsScaledBand({
10055
+ layerConfig: config2,
10056
+ visualChannels,
10057
+ rasterMetadata
10058
+ }),
10059
+ scales: {
10060
+ ...colorField && {
10061
+ fillColor: {
10062
+ field: colorField,
10063
+ type: "ordinal",
10064
+ domain: [],
10065
+ range: []
10066
+ }
10067
+ }
10068
+ }
10069
+ };
10070
+ }
10071
+ }
9388
10072
  const { heightField, heightScale } = visualChannels;
9389
10073
  const { textLabel, visConfig } = config2;
9390
10074
  const result = {};
10075
+ const updateTriggers = {};
9391
10076
  const scales = {};
9392
10077
  if (colorField) {
9393
10078
  const { colorAggregation: aggregation, colorRange: range } = visConfig;
@@ -9399,7 +10084,7 @@ function createChannelProps(id, layerType, config2, visualChannels, data, datase
9399
10084
  data
9400
10085
  );
9401
10086
  result.getFillColor = accessor;
9402
- scales.fillColor = {
10087
+ scales.fillColor = updateTriggers.getFillColor = {
9403
10088
  field: colorField,
9404
10089
  type: colorScale,
9405
10090
  ...domainAndRangeFromScale(scale2)
@@ -9418,6 +10103,7 @@ function createChannelProps(id, layerType, config2, visualChannels, data, datase
9418
10103
  result.getWeight = (d) => {
9419
10104
  return d.properties[aggregationExpAlias];
9420
10105
  };
10106
+ updateTriggers.getWeight = aggregationExpAlias;
9421
10107
  result.getPointRadius = (d, info) => {
9422
10108
  return calculateClusterRadius(
9423
10109
  d.properties,
@@ -9426,11 +10112,16 @@ function createChannelProps(id, layerType, config2, visualChannels, data, datase
9426
10112
  aggregationExpAlias
9427
10113
  );
9428
10114
  };
10115
+ updateTriggers.getPointRadius = {
10116
+ aggregationExpAlias,
10117
+ radiusRange: visConfig.radiusRange
10118
+ };
9429
10119
  result.textCharacterSet = "auto";
9430
10120
  result.textFontFamily = "Inter, sans";
9431
10121
  result.textFontSettings = { sdf: true };
9432
10122
  result.textFontWeight = 600;
9433
10123
  result.getText = (d) => TEXT_NUMBER_FORMATTER.format(d.properties[aggregationExpAlias]);
10124
+ updateTriggers.getText = aggregationExpAlias;
9434
10125
  result.getTextColor = config2.textLabel[TEXT_LABEL_INDEX].color;
9435
10126
  result.textOutlineColor = [
9436
10127
  ...config2.textLabel[TEXT_LABEL_INDEX].outlineColor,
@@ -9447,6 +10138,10 @@ function createChannelProps(id, layerType, config2, visualChannels, data, datase
9447
10138
  );
9448
10139
  return calculateClusterTextFontSize(radius);
9449
10140
  };
10141
+ updateTriggers.getTextSize = {
10142
+ aggregationExpAlias,
10143
+ radiusRange: visConfig.radiusRange
10144
+ };
9450
10145
  }
9451
10146
  if (radiusField) {
9452
10147
  const { accessor, scale: scale2 } = getSizeAccessor(
@@ -9457,7 +10152,7 @@ function createChannelProps(id, layerType, config2, visualChannels, data, datase
9457
10152
  data
9458
10153
  );
9459
10154
  result.getPointRadius = accessor;
9460
- scales.pointRadius = {
10155
+ scales.pointRadius = updateTriggers.getPointRadius = {
9461
10156
  field: radiusField,
9462
10157
  type: radiusScale || "identity",
9463
10158
  ...domainAndRangeFromScale(scale2)
@@ -9474,12 +10169,27 @@ function createChannelProps(id, layerType, config2, visualChannels, data, datase
9474
10169
  data
9475
10170
  );
9476
10171
  result.getLineColor = accessor;
9477
- scales.lineColor = {
10172
+ scales.lineColor = updateTriggers.getLineColor = {
9478
10173
  field: strokeColorField,
9479
10174
  type: strokeColorScale,
9480
10175
  ...domainAndRangeFromScale(scale2)
9481
10176
  };
9482
10177
  }
10178
+ if (strokeWidthField) {
10179
+ const { accessor, scale: scale2 } = getSizeAccessor(
10180
+ strokeWidthField,
10181
+ strokeWidthScale,
10182
+ visConfig.sizeAggregation,
10183
+ visConfig.sizeRange,
10184
+ data
10185
+ );
10186
+ result.getLineWidth = accessor;
10187
+ scales.lineWidth = updateTriggers.getLineWidth = {
10188
+ field: strokeWidthField,
10189
+ type: strokeWidthScale || "identity",
10190
+ ...domainAndRangeFromScale(scale2)
10191
+ };
10192
+ }
9483
10193
  if (heightField && visConfig.enable3d) {
9484
10194
  const { accessor, scale: scale2 } = getSizeAccessor(
9485
10195
  heightField,
@@ -9489,7 +10199,7 @@ function createChannelProps(id, layerType, config2, visualChannels, data, datase
9489
10199
  data
9490
10200
  );
9491
10201
  result.getElevation = accessor;
9492
- scales.elevation = {
10202
+ scales.elevation = updateTriggers.getElevation = {
9493
10203
  field: heightField,
9494
10204
  type: heightScale || "identity",
9495
10205
  ...domainAndRangeFromScale(scale2)
@@ -9504,7 +10214,7 @@ function createChannelProps(id, layerType, config2, visualChannels, data, datase
9504
10214
  data
9505
10215
  );
9506
10216
  result.getWeight = accessor;
9507
- scales.weight = {
10217
+ scales.weight = updateTriggers.getWeight = {
9508
10218
  field: weightField,
9509
10219
  type: "identity",
9510
10220
  ...domainAndRangeFromScale(scale2)
@@ -9525,6 +10235,12 @@ function createChannelProps(id, layerType, config2, visualChannels, data, datase
9525
10235
  { fallbackUrl: customMarkersUrl, maxIconSize, useMaskedIcons },
9526
10236
  data
9527
10237
  );
10238
+ updateTriggers.getIcon = {
10239
+ customMarkersUrl,
10240
+ customMarkersRange,
10241
+ maxIconSize,
10242
+ useMaskedIcons
10243
+ };
9528
10244
  result._subLayerProps = {
9529
10245
  "points-icon": {
9530
10246
  loadOptions: {
@@ -9541,9 +10257,11 @@ function createChannelProps(id, layerType, config2, visualChannels, data, datase
9541
10257
  };
9542
10258
  if (getFillColor && useMaskedIcons) {
9543
10259
  result.getIconColor = getFillColor;
10260
+ updateTriggers.getIconColor = updateTriggers.getFillColor;
9544
10261
  }
9545
10262
  if (getPointRadius) {
9546
10263
  result.getIconSize = getPointRadius;
10264
+ updateTriggers.getIconSize = updateTriggers.getPointRadius;
9547
10265
  }
9548
10266
  if (visualChannels.rotationField) {
9549
10267
  const { accessor } = getSizeAccessor(
@@ -9554,6 +10272,7 @@ function createChannelProps(id, layerType, config2, visualChannels, data, datase
9554
10272
  data
9555
10273
  );
9556
10274
  result.getIconAngle = negateAccessor(accessor);
10275
+ updateTriggers.getIconAngle = updateTriggers.getRotationField;
9557
10276
  }
9558
10277
  } else if (layerType === "tileset") {
9559
10278
  result.pointType = "circle";
@@ -9598,7 +10317,13 @@ function createChannelProps(id, layerType, config2, visualChannels, data, datase
9598
10317
  }
9599
10318
  };
9600
10319
  }
9601
- return { channelProps: result, scales };
10320
+ return {
10321
+ channelProps: {
10322
+ ...result,
10323
+ updateTriggers
10324
+ },
10325
+ scales
10326
+ };
9602
10327
  }
9603
10328
  function createLoadOptions(accessToken) {
9604
10329
  return {
@@ -10245,9 +10970,15 @@ export {
10245
10970
  WidgetSource,
10246
10971
  WidgetTableSource,
10247
10972
  WidgetTilesetSource,
10973
+ ErrorCode as _ErrorCode,
10974
+ applyLayerGroupFilters as _applyLayerGroupFilters,
10248
10975
  _buildFeatureFilter,
10976
+ createVecExprEvaluator as _createVecExprEvaluator,
10249
10977
  domainFromValues as _domainFromValues,
10978
+ evaluateVecExpr as _evaluateVecExpr,
10250
10979
  _getHexagonResolution,
10980
+ getRasterTileLayerStyleProps as _getRasterTileLayerStyleProps,
10981
+ validateVecExprSyntax as _validateVecExprSyntax,
10251
10982
  addFilter,
10252
10983
  aggregate,
10253
10984
  aggregationFunctions,
@@ -10260,9 +10991,11 @@ export {
10260
10991
  buildStatsUrl,
10261
10992
  calculateClusterRadius,
10262
10993
  calculateClusterTextFontSize,
10994
+ calculateLayerScale,
10263
10995
  clearDefaultRequestCache,
10264
10996
  clearFilters,
10265
10997
  configureSource,
10998
+ createColorScale,
10266
10999
  createPolygonSpatialFilter,
10267
11000
  createViewportSpatialFilter,
10268
11001
  fetchBasemapProps,
@@ -10277,6 +11010,7 @@ export {
10277
11010
  getDefaultAggregationExpColumnAliasForLayerType,
10278
11011
  getFilter,
10279
11012
  getIconUrlAccessor,
11013
+ getLayerDescriptor,
10280
11014
  getLayerProps,
10281
11015
  getMaxMarkerSize,
10282
11016
  getSizeAccessor,