plotly.js 2.15.1 → 2.16.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.
@@ -1,5 +1,5 @@
1
1
  /**
2
- * plotly.js (mapbox) v2.15.1
2
+ * plotly.js (mapbox) v2.16.1
3
3
  * Copyright 2012-2022, Plotly, Inc.
4
4
  * All rights reserved.
5
5
  * Licensed under the MIT license
@@ -120428,6 +120428,21 @@ var attrs = module.exports = overrideAll({
120428
120428
  dflt: 0,
120429
120429
  },
120430
120430
 
120431
+ bounds: {
120432
+ west: {
120433
+ valType: 'number',
120434
+ },
120435
+ east: {
120436
+ valType: 'number',
120437
+ },
120438
+ south: {
120439
+ valType: 'number',
120440
+ },
120441
+ north: {
120442
+ valType: 'number',
120443
+ }
120444
+ },
120445
+
120431
120446
  layers: templatedArray('layer', {
120432
120447
  visible: {
120433
120448
  valType: 'boolean',
@@ -120573,6 +120588,19 @@ function handleDefaults(containerIn, containerOut, coerce, opts) {
120573
120588
  coerce('bearing');
120574
120589
  coerce('pitch');
120575
120590
 
120591
+ var west = coerce('bounds.west');
120592
+ var east = coerce('bounds.east');
120593
+ var south = coerce('bounds.south');
120594
+ var north = coerce('bounds.north');
120595
+ if(
120596
+ west === undefined ||
120597
+ east === undefined ||
120598
+ south === undefined ||
120599
+ north === undefined
120600
+ ) {
120601
+ delete containerOut.bounds;
120602
+ }
120603
+
120576
120604
  handleArrayContainerDefaults(containerIn, containerOut, {
120577
120605
  name: 'layers',
120578
120606
  handleItemDefaults: handleLayerDefaults
@@ -120738,6 +120766,9 @@ proto.createMap = function(calcData, fullLayout, resolve, reject) {
120738
120766
  // store access token associated with this map
120739
120767
  self.accessToken = opts.accesstoken;
120740
120768
 
120769
+ var bounds = opts.bounds;
120770
+ var maxBounds = bounds ? [[bounds.west, bounds.south], [bounds.east, bounds.north]] : null;
120771
+
120741
120772
  // create the map!
120742
120773
  var map = self.map = new mapboxgl.Map({
120743
120774
  container: self.div,
@@ -120747,6 +120778,7 @@ proto.createMap = function(calcData, fullLayout, resolve, reject) {
120747
120778
  zoom: opts.zoom,
120748
120779
  bearing: opts.bearing,
120749
120780
  pitch: opts.pitch,
120781
+ maxBounds: maxBounds,
120750
120782
 
120751
120783
  interactive: !self.isStatic,
120752
120784
  preserveDrawingBuffer: self.isStatic,
@@ -126915,6 +126947,9 @@ var proto = ChoroplethMapbox.prototype;
126915
126947
 
126916
126948
  proto.update = function(calcTrace) {
126917
126949
  this._update(convert(calcTrace));
126950
+
126951
+ // link ref for quick update during selections
126952
+ calcTrace[0].trace._glTrace = this;
126918
126953
  };
126919
126954
 
126920
126955
  proto.updateOnSelect = function(calcTrace) {
@@ -130732,6 +130767,7 @@ var colorScaleAttrs = _dereq_('../../components/colorscale/attributes');
130732
130767
 
130733
130768
  var extendFlat = _dereq_('../../lib/extend').extendFlat;
130734
130769
  var overrideAll = _dereq_('../../plot_api/edit_types').overrideAll;
130770
+ var mapboxLayoutAtributes = _dereq_('../../plots/mapbox/layout_attributes');
130735
130771
 
130736
130772
  var lineAttrs = scatterGeoAttrs.line;
130737
130773
  var markerAttrs = scatterGeoAttrs.marker;
@@ -130740,6 +130776,33 @@ module.exports = overrideAll({
130740
130776
  lon: scatterGeoAttrs.lon,
130741
130777
  lat: scatterGeoAttrs.lat,
130742
130778
 
130779
+ cluster: {
130780
+ enabled: {
130781
+ valType: 'boolean',
130782
+ },
130783
+ maxzoom: extendFlat({}, mapboxLayoutAtributes.layers.maxzoom, {
130784
+ }),
130785
+ step: {
130786
+ valType: 'number',
130787
+ arrayOk: true,
130788
+ dflt: -1,
130789
+ min: -1,
130790
+ },
130791
+ size: {
130792
+ valType: 'number',
130793
+ arrayOk: true,
130794
+ dflt: 20,
130795
+ min: 0,
130796
+ },
130797
+ color: {
130798
+ valType: 'color',
130799
+ arrayOk: true,
130800
+ },
130801
+ opacity: extendFlat({}, markerAttrs.opacity, {
130802
+ dflt: 1
130803
+ })
130804
+ },
130805
+
130743
130806
  // locations
130744
130807
  // locationmode
130745
130808
 
@@ -130842,11 +130905,12 @@ module.exports = function convert(gd, calcTrace) {
130842
130905
  var hasText = subTypes.hasText(trace);
130843
130906
  var hasCircles = (hasMarkers && trace.marker.symbol === 'circle');
130844
130907
  var hasSymbols = (hasMarkers && trace.marker.symbol !== 'circle');
130908
+ var hasCluster = trace.cluster && trace.cluster.enabled;
130845
130909
 
130846
- var fill = initContainer();
130847
- var line = initContainer();
130848
- var circle = initContainer();
130849
- var symbol = initContainer();
130910
+ var fill = initContainer('fill');
130911
+ var line = initContainer('line');
130912
+ var circle = initContainer('circle');
130913
+ var symbol = initContainer('symbol');
130850
130914
 
130851
130915
  var opts = {
130852
130916
  fill: fill,
@@ -130890,6 +130954,29 @@ module.exports = function convert(gd, calcTrace) {
130890
130954
  var circleOpts = makeCircleOpts(calcTrace);
130891
130955
  circle.geojson = circleOpts.geojson;
130892
130956
  circle.layout.visibility = 'visible';
130957
+ if(hasCluster) {
130958
+ circle.filter = ['!', ['has', 'point_count']];
130959
+ opts.cluster = {
130960
+ type: 'circle',
130961
+ filter: ['has', 'point_count'],
130962
+ layout: {visibility: 'visible'},
130963
+ paint: {
130964
+ 'circle-color': arrayifyAttribute(trace.cluster.color, trace.cluster.step),
130965
+ 'circle-radius': arrayifyAttribute(trace.cluster.size, trace.cluster.step),
130966
+ 'circle-opacity': arrayifyAttribute(trace.cluster.opacity, trace.cluster.step),
130967
+ },
130968
+ };
130969
+ opts.clusterCount = {
130970
+ type: 'symbol',
130971
+ filter: ['has', 'point_count'],
130972
+ paint: {},
130973
+ layout: {
130974
+ 'text-field': '{point_count_abbreviated}',
130975
+ 'text-font': ['Open Sans Regular', 'Arial Unicode MS Regular'],
130976
+ 'text-size': 12
130977
+ }
130978
+ };
130979
+ }
130893
130980
 
130894
130981
  Lib.extendFlat(circle.paint, {
130895
130982
  'circle-color': circleOpts.mcc,
@@ -130898,6 +130985,10 @@ module.exports = function convert(gd, calcTrace) {
130898
130985
  });
130899
130986
  }
130900
130987
 
130988
+ if(hasCircles && hasCluster) {
130989
+ circle.filter = ['!', ['has', 'point_count']];
130990
+ }
130991
+
130901
130992
  if(hasSymbols || hasText) {
130902
130993
  symbol.geojson = makeSymbolGeoJSON(calcTrace, gd);
130903
130994
 
@@ -130958,10 +131049,12 @@ module.exports = function convert(gd, calcTrace) {
130958
131049
  return opts;
130959
131050
  };
130960
131051
 
130961
- function initContainer() {
131052
+ function initContainer(type) {
130962
131053
  return {
131054
+ type: type,
130963
131055
  geojson: geoJsonUtils.makeBlank(),
130964
131056
  layout: { visibility: 'none' },
131057
+ filter: null,
130965
131058
  paint: {}
130966
131059
  };
130967
131060
  }
@@ -131016,7 +131109,8 @@ function makeCircleOpts(calcTrace) {
131016
131109
 
131017
131110
  features.push({
131018
131111
  type: 'Feature',
131019
- geometry: {type: 'Point', coordinates: lonlat},
131112
+ id: i + 1,
131113
+ geometry: { type: 'Point', coordinates: lonlat },
131020
131114
  properties: props
131021
131115
  });
131022
131116
  }
@@ -131140,6 +131234,20 @@ function isBADNUM(lonlat) {
131140
131234
  return lonlat[0] === BADNUM;
131141
131235
  }
131142
131236
 
131237
+ function arrayifyAttribute(values, step) {
131238
+ var newAttribute;
131239
+ if(Lib.isArrayOrTypedArray(values) && Lib.isArrayOrTypedArray(step)) {
131240
+ newAttribute = ['step', ['get', 'point_count'], values[0]];
131241
+
131242
+ for(var idx = 1; idx < values.length; idx++) {
131243
+ newAttribute.push(step[idx - 1], values[idx]);
131244
+ }
131245
+ } else {
131246
+ newAttribute = values;
131247
+ }
131248
+ return newAttribute;
131249
+ }
131250
+
131143
131251
  },{"../../components/colorscale":127,"../../components/drawing":137,"../../components/fx/helpers":151,"../../constants/numerical":236,"../../lib":258,"../../lib/geojson_utils":254,"../../lib/svg_text_utils":281,"../../plots/mapbox/convert_text_opts":339,"../scatter/make_bubble_size_func":397,"../scatter/subtypes":405,"fast-isnumeric":28}],412:[function(_dereq_,module,exports){
131144
131252
  'use strict';
131145
131253
 
@@ -131157,6 +131265,10 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
131157
131265
  return Lib.coerce(traceIn, traceOut, attributes, attr, dflt);
131158
131266
  }
131159
131267
 
131268
+ function coerce2(attr, dflt) {
131269
+ return Lib.coerce2(traceIn, traceOut, attributes, attr, dflt);
131270
+ }
131271
+
131160
131272
  var len = handleLonLatDefaults(traceIn, traceOut, coerce);
131161
131273
  if(!len) {
131162
131274
  traceOut.visible = false;
@@ -131189,6 +131301,21 @@ module.exports = function supplyDefaults(traceIn, traceOut, defaultColor, layout
131189
131301
  }
131190
131302
  }
131191
131303
 
131304
+ var clusterMaxzoom = coerce2('cluster.maxzoom');
131305
+ var clusterStep = coerce2('cluster.step');
131306
+ var clusterColor = coerce2('cluster.color', (traceOut.marker && traceOut.marker.color) || defaultColor);
131307
+ var clusterSize = coerce2('cluster.size');
131308
+ var clusterOpacity = coerce2('cluster.opacity');
131309
+
131310
+ var clusterEnabledDflt =
131311
+ clusterMaxzoom !== false ||
131312
+ clusterStep !== false ||
131313
+ clusterColor !== false ||
131314
+ clusterSize !== false ||
131315
+ clusterOpacity !== false;
131316
+
131317
+ coerce('cluster.enabled', clusterEnabledDflt);
131318
+
131192
131319
  if(subTypes.hasText(traceOut)) {
131193
131320
  handleTextDefaults(traceIn, traceOut, layout, coerce, {noSelect: true});
131194
131321
  }
@@ -131247,6 +131374,7 @@ var Lib = _dereq_('../../lib');
131247
131374
  var getTraceColor = _dereq_('../scatter/get_trace_color');
131248
131375
  var fillText = Lib.fillText;
131249
131376
  var BADNUM = _dereq_('../../constants/numerical').BADNUM;
131377
+ var LAYER_PREFIX = _dereq_('../../plots/mapbox/constants').traceLayerPrefix;
131250
131378
 
131251
131379
  function hoverPoints(pointData, xval, yval) {
131252
131380
  var cd = pointData.cd;
@@ -131254,6 +131382,14 @@ function hoverPoints(pointData, xval, yval) {
131254
131382
  var xa = pointData.xa;
131255
131383
  var ya = pointData.ya;
131256
131384
  var subplot = pointData.subplot;
131385
+ var clusteredPointsIds = [];
131386
+ var layer = LAYER_PREFIX + trace.uid + '-circle';
131387
+ var hasCluster = trace.cluster && trace.cluster.enabled;
131388
+
131389
+ if(hasCluster) {
131390
+ var elems = subplot.map.queryRenderedFeatures(null, {layers: [layer]});
131391
+ clusteredPointsIds = elems.map(function(elem) {return elem.id;});
131392
+ }
131257
131393
 
131258
131394
  // compute winding number about [-180, 180] globe
131259
131395
  var winding = (xval >= 0) ?
@@ -131267,6 +131403,7 @@ function hoverPoints(pointData, xval, yval) {
131267
131403
  function distFn(d) {
131268
131404
  var lonlat = d.lonlat;
131269
131405
  if(lonlat[0] === BADNUM) return Infinity;
131406
+ if(hasCluster && clusteredPointsIds.indexOf(d.i + 1) === -1) return Infinity;
131270
131407
 
131271
131408
  var lon = Lib.modHalf(lonlat[0], 360);
131272
131409
  var lat = lonlat[1];
@@ -131347,7 +131484,7 @@ module.exports = {
131347
131484
  getExtraText: getExtraText
131348
131485
  };
131349
131486
 
131350
- },{"../../components/fx":155,"../../constants/numerical":236,"../../lib":258,"../scatter/get_trace_color":390}],416:[function(_dereq_,module,exports){
131487
+ },{"../../components/fx":155,"../../constants/numerical":236,"../../lib":258,"../../plots/mapbox/constants":338,"../scatter/get_trace_color":390}],416:[function(_dereq_,module,exports){
131351
131488
  'use strict';
131352
131489
 
131353
131490
  module.exports = {
@@ -131379,27 +131516,36 @@ module.exports = {
131379
131516
  },{"../../plots/mapbox":340,"../scatter/marker_colorbar":398,"../scattergeo/calc":409,"./attributes":410,"./defaults":412,"./event_data":413,"./format_labels":414,"./hover":415,"./plot":417,"./select":418}],417:[function(_dereq_,module,exports){
131380
131517
  'use strict';
131381
131518
 
131519
+ var Lib = _dereq_('../../lib');
131382
131520
  var convert = _dereq_('./convert');
131383
131521
  var LAYER_PREFIX = _dereq_('../../plots/mapbox/constants').traceLayerPrefix;
131384
- var ORDER = ['fill', 'line', 'circle', 'symbol'];
131522
+ var ORDER = {
131523
+ cluster: ['cluster', 'clusterCount', 'circle'],
131524
+ nonCluster: ['fill', 'line', 'circle', 'symbol'],
131525
+ };
131385
131526
 
131386
- function ScatterMapbox(subplot, uid) {
131527
+ function ScatterMapbox(subplot, uid, clusterEnabled) {
131387
131528
  this.type = 'scattermapbox';
131388
131529
  this.subplot = subplot;
131389
131530
  this.uid = uid;
131531
+ this.clusterEnabled = clusterEnabled;
131390
131532
 
131391
131533
  this.sourceIds = {
131392
131534
  fill: 'source-' + uid + '-fill',
131393
131535
  line: 'source-' + uid + '-line',
131394
131536
  circle: 'source-' + uid + '-circle',
131395
- symbol: 'source-' + uid + '-symbol'
131537
+ symbol: 'source-' + uid + '-symbol',
131538
+ cluster: 'source-' + uid + '-circle',
131539
+ clusterCount: 'source-' + uid + '-circle',
131396
131540
  };
131397
131541
 
131398
131542
  this.layerIds = {
131399
131543
  fill: LAYER_PREFIX + uid + '-fill',
131400
131544
  line: LAYER_PREFIX + uid + '-line',
131401
131545
  circle: LAYER_PREFIX + uid + '-circle',
131402
- symbol: LAYER_PREFIX + uid + '-symbol'
131546
+ symbol: LAYER_PREFIX + uid + '-symbol',
131547
+ cluster: LAYER_PREFIX + uid + '-cluster',
131548
+ clusterCount: LAYER_PREFIX + uid + '-cluster-count',
131403
131549
  };
131404
131550
 
131405
131551
  // We could merge the 'fill' source with the 'line' source and
@@ -131413,11 +131559,20 @@ function ScatterMapbox(subplot, uid) {
131413
131559
 
131414
131560
  var proto = ScatterMapbox.prototype;
131415
131561
 
131416
- proto.addSource = function(k, opts) {
131417
- this.subplot.map.addSource(this.sourceIds[k], {
131562
+ proto.addSource = function(k, opts, cluster) {
131563
+ var sourceOpts = {
131418
131564
  type: 'geojson',
131419
- data: opts.geojson
131420
- });
131565
+ data: opts.geojson,
131566
+ };
131567
+
131568
+ if(cluster && cluster.enabled) {
131569
+ Lib.extendFlat(sourceOpts, {
131570
+ cluster: true,
131571
+ clusterMaxZoom: cluster.maxzoom,
131572
+ });
131573
+ }
131574
+
131575
+ this.subplot.map.addSource(this.sourceIds[k], sourceOpts);
131421
131576
  };
131422
131577
 
131423
131578
  proto.setSourceData = function(k, opts) {
@@ -131427,45 +131582,68 @@ proto.setSourceData = function(k, opts) {
131427
131582
  };
131428
131583
 
131429
131584
  proto.addLayer = function(k, opts, below) {
131430
- this.subplot.addLayer({
131431
- type: k,
131585
+ var source = {
131586
+ type: opts.type,
131432
131587
  id: this.layerIds[k],
131433
131588
  source: this.sourceIds[k],
131434
131589
  layout: opts.layout,
131435
- paint: opts.paint
131436
- }, below);
131590
+ paint: opts.paint,
131591
+ };
131592
+ if(opts.filter) {
131593
+ source.filter = opts.filter;
131594
+ }
131595
+ this.subplot.addLayer(source, below);
131437
131596
  };
131438
131597
 
131439
131598
  proto.update = function update(calcTrace) {
131599
+ var trace = calcTrace[0].trace;
131440
131600
  var subplot = this.subplot;
131441
131601
  var map = subplot.map;
131442
131602
  var optsAll = convert(subplot.gd, calcTrace);
131443
131603
  var below = subplot.belowLookup['trace-' + this.uid];
131444
131604
  var i, k, opts;
131605
+ var hasCluster = !!(trace.cluster && trace.cluster.enabled);
131606
+ var hadCluster = !!this.clusterEnabled;
131445
131607
 
131446
131608
  if(below !== this.below) {
131447
- for(i = ORDER.length - 1; i >= 0; i--) {
131448
- k = ORDER[i];
131609
+ var order = ORDER.nonCluster;
131610
+
131611
+ for(i = order.length - 1; i >= 0; i--) {
131612
+ k = order[i];
131449
131613
  map.removeLayer(this.layerIds[k]);
131450
131614
  }
131451
- for(i = 0; i < ORDER.length; i++) {
131452
- k = ORDER[i];
131615
+ for(i = 0; i < order.length; i++) {
131616
+ k = order[i];
131453
131617
  opts = optsAll[k];
131454
131618
  this.addLayer(k, opts, below);
131455
131619
  }
131456
131620
  this.below = below;
131457
- }
131458
-
131459
- for(i = 0; i < ORDER.length; i++) {
131460
- k = ORDER[i];
131461
- opts = optsAll[k];
131462
-
131463
- subplot.setOptions(this.layerIds[k], 'setLayoutProperty', opts.layout);
131464
-
131465
- if(opts.layout.visibility === 'visible') {
131466
- this.setSourceData(k, opts);
131467
- subplot.setOptions(this.layerIds[k], 'setPaintProperty', opts.paint);
131621
+ } else if(hasCluster && !hadCluster) {
131622
+ for(i = ORDER.nonCluster.length - 1; i >= 0; i--) {
131623
+ k = ORDER.nonCluster[i];
131624
+ map.removeLayer(this.layerIds[k]);
131625
+ map.removeSource(this.sourceIds[k]);
131626
+ }
131627
+ this.addSource('circle', optsAll.circle, trace.cluster);
131628
+ for(i = 0; i < ORDER.cluster.length; i++) {
131629
+ k = ORDER.cluster[i];
131630
+ opts = optsAll[k];
131631
+ this.addLayer(k, opts, below);
131632
+ }
131633
+ this.clusterEnabled = hasCluster;
131634
+ } else if(!hasCluster && hadCluster) {
131635
+ for(i = 0; i < ORDER.cluster.length; i++) {
131636
+ k = ORDER.cluster[i];
131637
+ map.removeLayer(this.layerIds[k]);
131638
+ }
131639
+ map.removeSource(this.sourceIds.circle);
131640
+ for(i = 0; i < ORDER.nonCluster.length; i++) {
131641
+ k = ORDER.nonCluster[i];
131642
+ opts = optsAll[k];
131643
+ this.addSource(k, opts, trace.cluster);
131644
+ this.addLayer(k, opts, below);
131468
131645
  }
131646
+ this.clusterEnabled = hasCluster;
131469
131647
  }
131470
131648
 
131471
131649
  // link ref for quick update during selections
@@ -131474,9 +131652,9 @@ proto.update = function update(calcTrace) {
131474
131652
 
131475
131653
  proto.dispose = function dispose() {
131476
131654
  var map = this.subplot.map;
131477
-
131478
- for(var i = ORDER.length - 1; i >= 0; i--) {
131479
- var k = ORDER[i];
131655
+ var order = this.clusterEnabled ? ORDER.cluster : ORDER.nonCluster;
131656
+ for(var i = order.length - 1; i >= 0; i--) {
131657
+ var k = order[i];
131480
131658
  map.removeLayer(this.layerIds[k]);
131481
131659
  map.removeSource(this.sourceIds[k]);
131482
131660
  }
@@ -131484,15 +131662,31 @@ proto.dispose = function dispose() {
131484
131662
 
131485
131663
  module.exports = function createScatterMapbox(subplot, calcTrace) {
131486
131664
  var trace = calcTrace[0].trace;
131487
- var scatterMapbox = new ScatterMapbox(subplot, trace.uid);
131665
+ var hasCluster = trace.cluster && trace.cluster.enabled;
131666
+ var scatterMapbox = new ScatterMapbox(
131667
+ subplot,
131668
+ trace.uid,
131669
+ hasCluster
131670
+ );
131671
+
131488
131672
  var optsAll = convert(subplot.gd, calcTrace);
131489
131673
  var below = scatterMapbox.below = subplot.belowLookup['trace-' + trace.uid];
131674
+ var i, k, opts;
131490
131675
 
131491
- for(var i = 0; i < ORDER.length; i++) {
131492
- var k = ORDER[i];
131493
- var opts = optsAll[k];
131494
- scatterMapbox.addSource(k, opts);
131495
- scatterMapbox.addLayer(k, opts, below);
131676
+ if(hasCluster) {
131677
+ scatterMapbox.addSource('circle', optsAll.circle, trace.cluster);
131678
+ for(i = 0; i < ORDER.cluster.length; i++) {
131679
+ k = ORDER.cluster[i];
131680
+ opts = optsAll[k];
131681
+ scatterMapbox.addLayer(k, opts, below);
131682
+ }
131683
+ } else {
131684
+ for(i = 0; i < ORDER.nonCluster.length; i++) {
131685
+ k = ORDER.nonCluster[i];
131686
+ opts = optsAll[k];
131687
+ scatterMapbox.addSource(k, opts, trace.cluster);
131688
+ scatterMapbox.addLayer(k, opts, below);
131689
+ }
131496
131690
  }
131497
131691
 
131498
131692
  // link ref for quick update during selections
@@ -131501,7 +131695,7 @@ module.exports = function createScatterMapbox(subplot, calcTrace) {
131501
131695
  return scatterMapbox;
131502
131696
  };
131503
131697
 
131504
- },{"../../plots/mapbox/constants":338,"./convert":411}],418:[function(_dereq_,module,exports){
131698
+ },{"../../lib":258,"../../plots/mapbox/constants":338,"./convert":411}],418:[function(_dereq_,module,exports){
131505
131699
  'use strict';
131506
131700
 
131507
131701
  var Lib = _dereq_('../../lib');
@@ -132616,7 +132810,7 @@ function getSortFunc(opts, d2c) {
132616
132810
  'use strict';
132617
132811
 
132618
132812
  // package version injected by `npm run preprocess`
132619
- exports.version = '2.15.1';
132813
+ exports.version = '2.16.1';
132620
132814
 
132621
132815
  },{}]},{},[9])(9)
132622
132816
  });