@icij/murmur-next 4.0.1 → 4.0.4

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.
Files changed (62) hide show
  1. package/lib/components/AccordionStep.vue +53 -42
  2. package/lib/components/AccordionWrapper.vue +25 -24
  3. package/lib/components/ActiveTextTruncate.vue +44 -22
  4. package/lib/components/AdvancedLinkForm.vue +96 -46
  5. package/lib/components/Brand.vue +30 -23
  6. package/lib/components/BrandExpansion.vue +12 -3
  7. package/lib/components/ConfirmButton.vue +30 -26
  8. package/lib/components/ContentPlaceholder.vue +11 -7
  9. package/lib/components/CustomPagination.vue +50 -32
  10. package/lib/components/DigitsInput.vue +64 -60
  11. package/lib/components/DonateForm.vue +112 -83
  12. package/lib/components/EmbedForm.vue +37 -21
  13. package/lib/components/EmbeddableFooter.vue +14 -10
  14. package/lib/components/FollowUsPopover.vue +42 -40
  15. package/lib/components/GenericFooter.vue +98 -23
  16. package/lib/components/GenericHeader.vue +66 -29
  17. package/lib/components/HapticCopy.vue +41 -29
  18. package/lib/components/ImddbHeader.vue +113 -92
  19. package/lib/components/OrdinalLegend.vue +43 -20
  20. package/lib/components/RangePicker.vue +63 -42
  21. package/lib/components/ResponsiveIframe.vue +9 -2
  22. package/lib/components/ScaleLegend.vue +56 -18
  23. package/lib/components/SecretInput.vue +7 -8
  24. package/lib/components/SelectableDropdown.vue +120 -74
  25. package/lib/components/SharingOptions.vue +93 -36
  26. package/lib/components/SharingOptionsLink.vue +11 -5
  27. package/lib/components/SignUpForm.vue +44 -23
  28. package/lib/components/SlideUpDown.vue +7 -2
  29. package/lib/components/TexturedDeck.vue +24 -14
  30. package/lib/components/TinyPagination.vue +35 -22
  31. package/lib/composables/chart.ts +174 -157
  32. package/lib/composables/resizeObserver.ts +29 -29
  33. package/lib/composables/sendEmail.ts +53 -42
  34. package/lib/config.default.ts +17 -10
  35. package/lib/config.ts +34 -27
  36. package/lib/datavisualisations/BarChart.vue +48 -42
  37. package/lib/datavisualisations/ColumnChart.vue +133 -89
  38. package/lib/datavisualisations/LineChart.vue +79 -57
  39. package/lib/datavisualisations/StackedBarChart.vue +116 -68
  40. package/lib/datavisualisations/StackedColumnChart.vue +196 -115
  41. package/lib/enums.ts +25 -15
  42. package/lib/i18n.ts +3 -3
  43. package/lib/keys.ts +2 -2
  44. package/lib/main.ts +14 -10
  45. package/lib/maps/ChoroplethMap.vue +299 -160
  46. package/lib/maps/ChoroplethMapAnnotation.vue +29 -18
  47. package/lib/maps/SymbolMap.vue +194 -123
  48. package/lib/shims-bootstrap-vue.d.ts +1 -1
  49. package/lib/shims-vue.d.ts +3 -3
  50. package/lib/styles/functions.scss +10 -6
  51. package/lib/styles/lib.scss +2 -4
  52. package/lib/styles/mixins.scss +8 -8
  53. package/lib/styles/utilities.scss +1 -1
  54. package/lib/styles/variables.scss +24 -18
  55. package/lib/types.ts +26 -10
  56. package/lib/utils/animation.ts +4 -4
  57. package/lib/utils/assets.ts +31 -28
  58. package/lib/utils/clipboard.ts +16 -10
  59. package/lib/utils/iframe-resizer.ts +18 -13
  60. package/lib/utils/placeholder.ts +54 -23
  61. package/lib/utils/placeholderTypes.ts +3 -3
  62. package/package.json +7 -2
@@ -1,12 +1,22 @@
1
1
  <script lang="ts">
2
- import {clamp, debounce, get, kebabCase, keys, max, min, pickBy, values} from 'lodash'
2
+ import {
3
+ clamp,
4
+ debounce,
5
+ get,
6
+ kebabCase,
7
+ keys,
8
+ max,
9
+ min,
10
+ pickBy,
11
+ values
12
+ } from 'lodash'
3
13
 
4
14
  import * as d3 from 'd3'
5
- import {geoRobinson} from 'd3-geo-projection'
6
- import type {GeoProjection} from 'd3-geo'
7
- import {geoGraticule} from 'd3-geo'
8
- import {feature} from 'topojson'
9
- import {GeometryCollection} from "topojson-specification";
15
+ import { geoRobinson } from 'd3-geo-projection'
16
+ import type { GeoProjection } from 'd3-geo'
17
+ import { geoGraticule } from 'd3-geo'
18
+ import { feature } from 'topojson'
19
+ import { GeometryCollection } from 'topojson-specification'
10
20
 
11
21
  import {
12
22
  ComponentPublicInstance,
@@ -18,10 +28,15 @@ import {
18
28
  watch
19
29
  } from 'vue'
20
30
 
21
- import {ParentKey} from "@/keys";
22
- import {MapTransform, ParentMap} from "@/types";
31
+ import { ParentKey } from '@/keys'
32
+ import { MapTransform, ParentMap } from '@/types'
23
33
  import config from '../config'
24
- import {chartEmits, chartProps, getChartProps, useChart} from '@/composables/chart'
34
+ import {
35
+ chartEmits,
36
+ chartProps,
37
+ getChartProps,
38
+ useChart
39
+ } from '@/composables/chart'
25
40
  import ScaleLegend from '@/components/ScaleLegend.vue'
26
41
 
27
42
  export default defineComponent({
@@ -196,9 +211,8 @@ export default defineComponent({
196
211
  },
197
212
  ...chartProps()
198
213
  },
199
- emits: ["click", 'reset', 'zoomed', ...chartEmits],
200
- setup(props, {emit}) {
201
-
214
+ emits: ['click', 'reset', 'zoomed', ...chartEmits],
215
+ setup(props, { emit }) {
202
216
  const resizable = ref<ComponentPublicInstance<HTMLElement> | null>(null)
203
217
  const topojson = ref<any>(null)
204
218
  const topojsonPromise = ref<any | null>(null)
@@ -206,12 +220,25 @@ export default defineComponent({
206
220
  const featureCursor = ref<{ [cursor: string]: string } | null>(null)
207
221
  const featureZoom = ref<string | null>(null)
208
222
  const isLoaded = ref<boolean>(false)
209
- const mapTransform = ref<MapTransform>({k: 1, x: 0, y: 0, rotateX: 0, rotateY: 0})
223
+ const mapTransform = ref<MapTransform>({
224
+ k: 1,
225
+ x: 0,
226
+ y: 0,
227
+ rotateX: 0,
228
+ rotateY: 0
229
+ })
210
230
  const debouncedDraw = debounce(function () {
211
231
  draw()
212
232
  }, 10)
213
233
 
214
- const {loadedData} = useChart(resizable, getChartProps(props), {emit}, isLoaded, debouncedDraw, afterLoaded)
234
+ const { loadedData } = useChart(
235
+ resizable,
236
+ getChartProps(props),
237
+ { emit },
238
+ isLoaded,
239
+ debouncedDraw,
240
+ afterLoaded
241
+ )
215
242
 
216
243
  async function afterLoaded() {
217
244
  return new Promise<void>(async (resolve) => {
@@ -231,8 +258,8 @@ export default defineComponent({
231
258
  return [lng, lat]
232
259
  })
233
260
  const featureColorScaleEnd = computed(() => {
234
- const defaultColor = '#852308';
235
- const node = map.value?.node();
261
+ const defaultColor = '#852308'
262
+ const node = map.value?.node()
236
263
  if (isLoaded.value && node) {
237
264
  const computedStyle = window.getComputedStyle(node)
238
265
  return computedStyle.getPropertyValue('--primary') || defaultColor
@@ -242,8 +269,8 @@ export default defineComponent({
242
269
  const featureColorScaleStart = computed(() => {
243
270
  // `socialMode` is always different from null but accessing it will make
244
271
  // this computed property reactive.
245
- const defaultColor = '#fff';
246
- const node = map.value?.node();
272
+ const defaultColor = '#fff'
273
+ const node = map.value?.node()
247
274
  if (isLoaded.value && props.socialMode !== null && node) {
248
275
  const computedStyle = window.getComputedStyle(node)
249
276
  return computedStyle.getPropertyValue('color') || defaultColor
@@ -253,8 +280,10 @@ export default defineComponent({
253
280
  const featureColor = computed(() => {
254
281
  return (d: number) => {
255
282
  const id = get(d, props.topojsonObjectsPath)
256
- const hasIdProp = loadedData.value && id in loadedData.value;
257
- return hasIdProp ? featureColorScaleFunction.value(loadedData.value[id]) : undefined
283
+ const hasIdProp = loadedData.value && id in loadedData.value
284
+ return hasIdProp
285
+ ? featureColorScaleFunction.value(loadedData.value[id])
286
+ : undefined
258
287
  }
259
288
  })
260
289
  const featureColorScaleFunction = computed(() => {
@@ -270,9 +299,9 @@ export default defineComponent({
270
299
 
271
300
  const defaultFeatureColorScale = computed(() => {
272
301
  return d3
273
- .scaleSequential()
274
- .domain([Math.max(1, minValue.value), maxValue.value])
275
- .range([featureColorScaleStart.value, featureColorScaleEnd.value])
302
+ .scaleSequential()
303
+ .domain([Math.max(1, minValue.value), maxValue.value])
304
+ .range([featureColorScaleStart.value, featureColorScaleEnd.value])
276
305
  })
277
306
  const initialFeaturePath = computed(() => {
278
307
  return featurePath.value.projection(initialMapProjection.value)
@@ -283,9 +312,10 @@ export default defineComponent({
283
312
 
284
313
  const initialMapProjection = computed(() => {
285
314
  if (props.spherical) {
286
- return mapProjection.value.rotate(sphericalCenter.value)
287
- .fitHeight(mapHeight.value, geojson.value)
288
- .translate([mapWidth.value / 2, mapHeight.value / 2])
315
+ return mapProjection.value
316
+ .rotate(sphericalCenter.value)
317
+ .fitHeight(mapHeight.value, geojson.value)
318
+ .translate([mapWidth.value / 2, mapHeight.value / 2])
289
319
  }
290
320
  return mapProjection.value.center(planarCenter.value)
291
321
  })
@@ -299,9 +329,12 @@ export default defineComponent({
299
329
  return !!featureZoom.value
300
330
  })
301
331
 
302
-
303
332
  const geojson = computed(() => {
304
- const object = get(topojson.value, ['objects', props.topojsonObjects], null)
333
+ const object = get(
334
+ topojson.value,
335
+ ['objects', props.topojsonObjects],
336
+ null
337
+ )
305
338
  return feature(topojson.value, object as GeometryCollection)
306
339
  })
307
340
 
@@ -314,24 +347,27 @@ export default defineComponent({
314
347
  })
315
348
  const mapProjection = computed(() => {
316
349
  if (!props.projection) {
317
- throw new Error("props.projection is " + props.projection)
350
+ throw new Error('props.projection is ' + props.projection)
318
351
  }
319
- return props.projection().fitSize([mapWidth.value, mapHeight.value], geojson.value) as GeoProjection
352
+ return props
353
+ .projection()
354
+ .fitSize(
355
+ [mapWidth.value, mapHeight.value],
356
+ geojson.value
357
+ ) as GeoProjection
320
358
  })
321
359
  const rotatingMapProjection = computed(() => {
322
- const {rotateX = null, rotateY = null} = mapTransform.value
360
+ const { rotateX = null, rotateY = null } = mapTransform.value
323
361
  let proj
324
362
  let text
325
363
  if (rotateX !== null && rotateY !== null) {
326
- text="rotate"
327
- proj= mapProjection.value.rotate([rotateX, rotateY]) ?? null
328
- }else {
329
- text="normal"
330
- proj= mapProjection.value
331
-
364
+ text = 'rotate'
365
+ proj = mapProjection.value.rotate([rotateX, rotateY]) ?? null
366
+ } else {
367
+ text = 'normal'
368
+ proj = mapProjection.value
332
369
  }
333
370
  return proj
334
-
335
371
  })
336
372
 
337
373
  const mapCenter = computed(() => {
@@ -339,17 +375,20 @@ export default defineComponent({
339
375
  })
340
376
  const mapZoom = computed(() => {
341
377
  return d3
342
- .zoom()
343
- .scaleExtent([props.zoomMin, props.zoomMax])
344
- .translateExtent([
345
- [0, 0],
346
- [mapWidth.value, mapHeight.value]
347
- ])
348
- .on('zoom', mapZoomed)
378
+ .zoom()
379
+ .scaleExtent([props.zoomMin, props.zoomMax])
380
+ .translateExtent([
381
+ [0, 0],
382
+ [mapWidth.value, mapHeight.value]
383
+ ])
384
+ .on('zoom', mapZoomed)
349
385
  })
350
386
 
351
387
  const mapSphericalZoom = computed(() => {
352
- return d3.zoom(map.value).scaleExtent([props.zoomMin, props.zoomMax]).on('zoom', mapSphericalZoomed)
388
+ return d3
389
+ .zoom(map.value)
390
+ .scaleExtent([props.zoomMin, props.zoomMax])
391
+ .on('zoom', mapSphericalZoomed)
353
392
  })
354
393
  const mapRotate = computed(() => {
355
394
  return d3.drag(map.value).on('drag', mapRotated)
@@ -363,7 +402,13 @@ export default defineComponent({
363
402
  })
364
403
 
365
404
  const mapStyle = computed(() => {
366
- const {k = 0, x = 0, y = 0, rotateX = 0, rotateY = 0} = mapTransform.value
405
+ const {
406
+ k = 0,
407
+ x = 0,
408
+ y = 0,
409
+ rotateX = 0,
410
+ rotateY = 0
411
+ } = mapTransform.value
367
412
  return {
368
413
  '--map-height': props.height,
369
414
  '--map-color': props.color,
@@ -376,13 +421,15 @@ export default defineComponent({
376
421
  }
377
422
  })
378
423
 
379
- const map = computed((): d3.Selection<SVGElement, unknown, null, undefined> | null => {
380
- const selection = d3.select(resizable.value).select<SVGElement>('svg')
381
- if (!selection) {
382
- throw new Error("Empty SVG selection")
424
+ const map = computed(
425
+ (): d3.Selection<SVGElement, unknown, null, undefined> | null => {
426
+ const selection = d3.select(resizable.value).select<SVGElement>('svg')
427
+ if (!selection) {
428
+ throw new Error('Empty SVG selection')
429
+ }
430
+ return selection
383
431
  }
384
- return selection
385
- })
432
+ )
386
433
  const maxValue = computed(() => {
387
434
  if (props.max !== null) {
388
435
  return props.max
@@ -399,11 +446,11 @@ export default defineComponent({
399
446
  return props.spherical ? '50% 50%' : '0 0'
400
447
  })
401
448
 
402
- function setMapNodeSize({width, height}) {
403
- const node = map.value?.node();
449
+ function setMapNodeSize({ width, height }) {
450
+ const node = map.value?.node()
404
451
  if (node) {
405
- node["width"] = width
406
- node["height"] = height
452
+ node['width'] = width
453
+ node['height'] = height
407
454
  }
408
455
  }
409
456
 
@@ -416,7 +463,7 @@ export default defineComponent({
416
463
 
417
464
  function prepare() {
418
465
  if (!map.value) {
419
- throw new Error("Map is null")
466
+ throw new Error('Map is null')
420
467
  }
421
468
  // Set the map sizes
422
469
  mapRect.value = map.value.node()?.getBoundingClientRect() as DOMRect
@@ -454,35 +501,38 @@ export default defineComponent({
454
501
  }
455
502
 
456
503
  function drawOutline() {
457
- map.value?.select('.choropleth-map__main__outline')
458
- .append('path')
459
- .attr('d', initialFeaturePath.value({type: 'Sphere'}))
460
- .attr('stroke', props.outlineColor)
504
+ map.value
505
+ ?.select('.choropleth-map__main__outline')
506
+ .append('path')
507
+ .attr('d', initialFeaturePath.value({ type: 'Sphere' }))
508
+ .attr('stroke', props.outlineColor)
461
509
  }
462
510
 
463
511
  function drawGraticule() {
464
- map.value?.select('.choropleth-map__main__graticule')
465
- .append('path')
466
- .attr('d', initialGraticulePath.value)
467
- .attr('stroke', props.graticuleColor)
512
+ map.value
513
+ ?.select('.choropleth-map__main__graticule')
514
+ .append('path')
515
+ .attr('d', initialGraticulePath.value)
516
+ .attr('stroke', props.graticuleColor)
468
517
  }
469
518
 
470
519
  function drawFeatures() {
471
- const features = map.value?.select('.choropleth-map__main__features')
472
- .selectAll('.choropleth-map__main__features__item')
473
- .data(geojson.value.features)
474
- .enter()
475
- .append('path')
520
+ const features = map.value
521
+ ?.select('.choropleth-map__main__features')
522
+ .selectAll('.choropleth-map__main__features__item')
523
+ .data(geojson.value.features)
524
+ .enter()
525
+ .append('path')
476
526
  if (!features) {
477
- throw new Error("features is undefined")
527
+ throw new Error('features is undefined')
478
528
  }
479
529
  features
480
- .attr('class', featureClass)
481
- .attr('d', initialFeaturePath.value)
482
- .on('mouseover', featureMouseOver)
483
- .on('mouseleave', featureMouseLeave)
484
- .on('click', mapClicked)
485
- .style('color', featureColor.value)
530
+ .attr('class', featureClass)
531
+ .attr('d', initialFeaturePath.value)
532
+ .on('mouseover', featureMouseOver)
533
+ .on('mouseleave', featureMouseLeave)
534
+ .on('click', mapClicked)
535
+ .style('color', featureColor.value)
486
536
  }
487
537
 
488
538
  function update() {
@@ -490,10 +540,11 @@ export default defineComponent({
490
540
  if (!map.value) {
491
541
  return
492
542
  }
493
- map.value.selectAll('.choropleth-map__main__features__item')
494
- .data(geojson.value.features)
495
- .attr('class', featureClass)
496
- .style('color', featureColor.value)
543
+ map.value
544
+ .selectAll('.choropleth-map__main__features__item')
545
+ .data(geojson.value.features)
546
+ .attr('class', featureClass)
547
+ .style('color', featureColor.value)
497
548
  }
498
549
 
499
550
  function featureClass(d: string) {
@@ -529,7 +580,7 @@ export default defineComponent({
529
580
  async function loadTopojson() {
530
581
  if (!topojsonPromise.value) {
531
582
  if (!props.topojsonUrl?.length) {
532
- throw new Error("Empty topojsonUrl")
583
+ throw new Error('Empty topojsonUrl')
533
584
  }
534
585
  topojsonPromise.value = d3.json(props.topojsonUrl)
535
586
  topojson.value = await topojsonPromise.value
@@ -537,7 +588,6 @@ export default defineComponent({
537
588
  return topojsonPromise.value
538
589
  }
539
590
 
540
-
541
591
  async function mapClicked(event: MouseEvent, d: number) {
542
592
  /**
543
593
  * A click on a feature
@@ -562,19 +612,23 @@ export default defineComponent({
562
612
  emit('zoomed', d)
563
613
  }
564
614
 
565
- function mapSphericalZoomed({transform: {k}}: { transform: MapTransform }) {
615
+ function mapSphericalZoomed({
616
+ transform: { k }
617
+ }: {
618
+ transform: MapTransform
619
+ }) {
566
620
  const transform = `scale(${k})`
567
- mapTransform.value = {...mapTransform.value, k}
621
+ mapTransform.value = { ...mapTransform.value, k }
568
622
  applyTransformToTrackedElements(transform)
569
623
  }
570
624
 
571
- function mapZoomed({transform}: { transform: MapTransform }) {
625
+ function mapZoomed({ transform }: { transform: MapTransform }) {
572
626
  mapTransform.value = transform
573
627
  applyTransformToTrackedElements(transform)
574
628
  }
575
629
 
576
630
  function mapRotated(event: Event) {
577
- const {yaw, pitch} = calculateRotation(event)
631
+ const { yaw, pitch } = calculateRotation(event)
578
632
  applyRotation(yaw, pitch)
579
633
  }
580
634
 
@@ -584,40 +638,54 @@ export default defineComponent({
584
638
  const [rotateX, rotateY] = mapProjection.value.rotate()
585
639
  const yaw = rotateX + event.dx * k
586
640
  const pitch = rotateY - event.dy * k
587
- return {yaw, pitch}
641
+ return { yaw, pitch }
588
642
  }
589
643
 
590
644
  function applyTransformToTrackedElements(transform) {
591
- map.value?.selectAll('.choropleth-map__main__tracked').attr('transform', transform)
645
+ map.value
646
+ ?.selectAll('.choropleth-map__main__tracked')
647
+ .attr('transform', transform)
592
648
  }
593
649
 
594
650
  function applyRotation(rotateX: number, rotateY: number) {
595
- mapTransform.value = {...mapTransform.value, rotateX, rotateY}
596
- const featuresPaths = initialFeaturePath.value.projection(rotatingMapProjection.value)
651
+ mapTransform.value = { ...mapTransform.value, rotateX, rotateY }
652
+ const featuresPaths = initialFeaturePath.value.projection(
653
+ rotatingMapProjection.value
654
+ )
597
655
  const graticulePaths = featuresPaths(graticuleLines.value)
598
- map.value?.selectAll('g.choropleth-map__main__features path').attr('d', featuresPaths)
599
- map.value?.selectAll('g.choropleth-map__main__graticule path').attr('d', graticulePaths)
600
- }
601
-
602
- function applyZoomIdentity(zoomIdentity, pointer: number[] | null = null, transitionDuration = props.transitionDuration) {
603
- return map.value?.transition()
604
- .duration(transitionDuration)
605
- .call(mapZoom.value.transform, zoomIdentity, pointer)
606
- .end()
656
+ map.value
657
+ ?.selectAll('g.choropleth-map__main__features path')
658
+ .attr('d', featuresPaths)
659
+ map.value
660
+ ?.selectAll('g.choropleth-map__main__graticule path')
661
+ .attr('d', graticulePaths)
662
+ }
663
+
664
+ function applyZoomIdentity(
665
+ zoomIdentity,
666
+ pointer: number[] | null = null,
667
+ transitionDuration = props.transitionDuration
668
+ ) {
669
+ return map.value
670
+ ?.transition()
671
+ .duration(transitionDuration)
672
+ .call(mapZoom.value.transform, zoomIdentity, pointer)
673
+ .end()
607
674
  }
608
675
 
609
676
  function reapplyZoom() {
610
- mapTransform.value = {k: 1, x: 0, y: 0, rotateX: 0, rotateY: 0}
677
+ mapTransform.value = { k: 1, x: 0, y: 0, rotateX: 0, rotateY: 0 }
611
678
  applyZoomIdentity(d3.zoomIdentity)
612
679
  featureZoom.value = null
613
680
  emitResetEvent()
614
681
  }
615
682
 
616
683
  function resetZoom(_event: MouseEvent, _d: number) {
617
- map.value?.style('--map-scale', 1)
618
- .transition()
619
- .duration(props.transitionDuration)
620
- .call(mapZoom.value?.transform, d3.zoomIdentity)
684
+ map.value
685
+ ?.style('--map-scale', 1)
686
+ .transition()
687
+ .duration(props.transitionDuration)
688
+ .call(mapZoom.value?.transform, d3.zoomIdentity)
621
689
  featureZoom.value = null
622
690
  emitResetEvent()
623
691
  }
@@ -628,48 +696,64 @@ export default defineComponent({
628
696
  * @event reset
629
697
  */
630
698
  emit('reset')
631
-
632
699
  }
633
700
 
634
701
  function setFeaturesClasses() {
635
- map.value?.selectAll('.choropleth-map__main__features__item').attr('class', featureClass)
702
+ map.value
703
+ ?.selectAll('.choropleth-map__main__features__item')
704
+ .attr('class', featureClass)
636
705
  }
637
706
 
638
707
  function setFeatureZoom(d: any, pointer = [0, 0]) {
639
-
640
708
  featureZoom.value = get(d, props.topojsonObjectsPath)
641
709
  const [[x0, y0], [x1, y1]] = featurePath.value.bounds(d)
642
- const scale = Math.min(8, 0.9 / Math.max((x1 - x0) / mapWidth.value, (y1 - y0) / mapHeight.value))
710
+ const scale = Math.min(
711
+ 8,
712
+ 0.9 / Math.max((x1 - x0) / mapWidth.value, (y1 - y0) / mapHeight.value)
713
+ )
643
714
  const zoomIdentity = d3.zoomIdentity
644
- .translate(mapWidth.value / 2, mapHeight.value / 2)
645
- .scale(scale)
646
- .translate(-(x0 + x1) / 2, -(y0 + y1) / 2)
647
- return map.value?.style('--map-scale', scale)
648
- .transition()
649
- .duration(props.transitionDuration)
650
- .call(mapZoom.value?.transform, zoomIdentity, pointer)
651
- .end()
715
+ .translate(mapWidth.value / 2, mapHeight.value / 2)
716
+ .scale(scale)
717
+ .translate(-(x0 + x1) / 2, -(y0 + y1) / 2)
718
+ return map.value
719
+ ?.style('--map-scale', scale)
720
+ .transition()
721
+ .duration(props.transitionDuration)
722
+ .call(mapZoom.value?.transform, zoomIdentity, pointer)
723
+ .end()
652
724
  }
653
725
 
654
726
  function calculateFeatureZoomIdentity(d: any) {
655
727
  const [[x0, y0], [x1, y1]] = featurePath.value.bounds(d)
656
- const scale = Math.min(8, 0.9 / Math.max((x1 - x0) / mapWidth.value, (y1 - y0) / mapHeight.value))
728
+ const scale = Math.min(
729
+ 8,
730
+ 0.9 / Math.max((x1 - x0) / mapWidth.value, (y1 - y0) / mapHeight.value)
731
+ )
657
732
  const translateX = -(x0 + x1) / 2
658
733
  const translateY = -(y0 + y1) / 2
659
734
  return d3.zoomIdentity
660
- .translate(mapWidth.value / 2, mapHeight.value / 2)
661
- .scale(scale)
662
- .translate(translateX, translateY)
735
+ .translate(mapWidth.value / 2, mapHeight.value / 2)
736
+ .scale(scale)
737
+ .translate(translateX, translateY)
663
738
  }
664
739
 
665
740
  function applyFeatureZoom(d: any, pointer = [0, 0]) {
666
741
  const zoomIdentity = calculateFeatureZoomIdentity(d)
667
742
  featureZoom.value = get(d, props.topojsonObjectsPath)
668
- mapTransform.value = {k: zoomIdentity.k, x: zoomIdentity.x, y: zoomIdentity.y, rotateX: 0, rotateY: 0}
743
+ mapTransform.value = {
744
+ k: zoomIdentity.k,
745
+ x: zoomIdentity.x,
746
+ y: zoomIdentity.y,
747
+ rotateX: 0,
748
+ rotateY: 0
749
+ }
669
750
  return applyZoomIdentity(zoomIdentity, pointer)
670
751
  }
671
752
 
672
- function applyZoom(zoom: number, transitionDuration = props.transitionDuration) {
753
+ function applyZoom(
754
+ zoom: number,
755
+ transitionDuration = props.transitionDuration
756
+ ) {
673
757
  const zoomScale = clamp(zoom, props.zoomMin, props.zoomMax)
674
758
  if (props.spherical) {
675
759
  return setSphericalZoom(zoomScale, transitionDuration)
@@ -680,34 +764,58 @@ export default defineComponent({
680
764
 
681
765
  function setSphericalZoom(zoomScale: number, transitionDuration: number) {
682
766
  const zoomIdentity = d3.zoomIdentity.scale(zoomScale)
683
- mapTransform.value = {...mapTransform.value, k: zoomScale}
767
+ mapTransform.value = { ...mapTransform.value, k: zoomScale }
684
768
  return applyZoomIdentity(zoomIdentity, null, transitionDuration)
685
769
  }
686
770
 
687
771
  function setPlanarZoom(zoomScale: number, transitionDuration: number) {
688
-
689
772
  const [x, y] = mapProjection.value(mapCenter.value)
690
- const [translateX, translateY] = [mapWidth.value / 2 - zoomScale * x, mapHeight.value / 2 - zoomScale * y]
691
- const zoomIdentity = d3.zoomIdentity.translate(translateX, translateY).scale(zoomScale)
692
- mapTransform.value = {k: zoomScale, x: translateX, y: translateY, rotateX: 0, rotateY: 0}
773
+ const [translateX, translateY] = [
774
+ mapWidth.value / 2 - zoomScale * x,
775
+ mapHeight.value / 2 - zoomScale * y
776
+ ]
777
+ const zoomIdentity = d3.zoomIdentity
778
+ .translate(translateX, translateY)
779
+ .scale(zoomScale)
780
+ mapTransform.value = {
781
+ k: zoomScale,
782
+ x: translateX,
783
+ y: translateY,
784
+ rotateX: 0,
785
+ rotateY: 0
786
+ }
693
787
  return applyZoomIdentity(zoomIdentity, null, transitionDuration)
694
788
  }
695
789
 
696
- watch(() => props.socialMode, () => {
697
- draw()
698
- })
699
- watch(() => props.data, () => {
700
- update()
701
- })
702
- watch(() => featureZoom.value, () => {
703
- setFeaturesClasses()
704
- })
705
- watch(() => featureCursor.value, () => {
706
- setFeaturesClasses()
707
- })
790
+ watch(
791
+ () => props.socialMode,
792
+ () => {
793
+ draw()
794
+ }
795
+ )
796
+ watch(
797
+ () => props.data,
798
+ () => {
799
+ update()
800
+ }
801
+ )
802
+ watch(
803
+ () => featureZoom.value,
804
+ () => {
805
+ setFeaturesClasses()
806
+ }
807
+ )
808
+ watch(
809
+ () => featureCursor.value,
810
+ () => {
811
+ setFeaturesClasses()
812
+ }
813
+ )
708
814
 
709
815
  provide<ParentMap>(ParentKey, {
710
- mapRect, mapTransform, rotatingMapProjection
816
+ mapRect,
817
+ mapTransform,
818
+ rotatingMapProjection
711
819
  })
712
820
 
713
821
  return {
@@ -738,31 +846,58 @@ export default defineComponent({
738
846
  })
739
847
  </script>
740
848
  <template>
741
- <div ref="resizable" :class="mapClass" :style="mapStyle" class="choropleth-map" @click="draw">
742
- <svg :viewbox="`0 0 ${mapRect.width} ${mapRect.height}`" class="choropleth-map__main">
743
- <pattern id="diagonalHatch" height="1" patternTransform="rotate(45 0 0)" patternUnits="userSpaceOnUse" width="1">
744
- <rect :fill="featureColorScaleEnd" height="1" width="1"/>
745
- <line :style="{ stroke: featureColorScaleStart, strokeWidth: 1 }" x1="0" x2="0" y1="0" y2="1"/>
849
+ <div
850
+ ref="resizable"
851
+ :class="mapClass"
852
+ :style="mapStyle"
853
+ class="choropleth-map"
854
+ @click="draw"
855
+ >
856
+ <svg
857
+ :viewbox="`0 0 ${mapRect.width} ${mapRect.height}`"
858
+ class="choropleth-map__main"
859
+ >
860
+ <pattern
861
+ id="diagonalHatch"
862
+ height="1"
863
+ patternTransform="rotate(45 0 0)"
864
+ patternUnits="userSpaceOnUse"
865
+ width="1"
866
+ >
867
+ <rect :fill="featureColorScaleEnd" height="1" width="1" />
868
+ <line
869
+ :style="{ stroke: featureColorScaleStart, strokeWidth: 1 }"
870
+ x1="0"
871
+ x2="0"
872
+ y1="0"
873
+ y2="1"
874
+ />
746
875
  </pattern>
747
- <g :transform-origin="transformOrigin" class="choropleth-map__main__tracked">
876
+ <g
877
+ :transform-origin="transformOrigin"
878
+ class="choropleth-map__main__tracked"
879
+ >
748
880
  <g v-if="graticule" class="choropleth-map__main__graticule"></g>
749
881
  <g class="choropleth-map__main__features"></g>
750
882
  <g v-if="outline" class="choropleth-map__main__outline"></g>
751
- <slot v-if="isReady"/>
883
+ <slot v-if="isReady" />
752
884
  </g>
753
885
  </svg>
754
886
  <scale-legend
755
- v-if="!hideLegend && isReady"
756
- :color-scale="featureColorScaleFunction"
757
- :color-scale-end="featureColorScaleEnd"
758
- :color-scale-start="featureColorScaleStart"
759
- :cursor-value="cursorValue"
760
- :max="maxValue"
761
- :min="minValue"
762
- class="choropleth-map__legend"
887
+ v-if="!hideLegend && isReady"
888
+ :color-scale="featureColorScaleFunction"
889
+ :color-scale-end="featureColorScaleEnd"
890
+ :color-scale-start="featureColorScaleStart"
891
+ :cursor-value="cursorValue"
892
+ :max="maxValue"
893
+ :min="minValue"
894
+ class="choropleth-map__legend"
763
895
  >
764
896
  <template #cursor="{ value }">
765
- <slot name="legend-cursor" v-bind="{ value, identifier: featureCursor }"/>
897
+ <slot
898
+ name="legend-cursor"
899
+ v-bind="{ value, identifier: featureCursor }"
900
+ />
766
901
  </template>
767
902
  </scale-legend>
768
903
  </div>
@@ -799,7 +934,10 @@ export default defineComponent({
799
934
  stroke: currentColor;
800
935
  stroke-width: calc(1px / var(--map-scale, 1));
801
936
  fill: currentColor;
802
- transition: opacity 750ms, filter 750ms, fill 750ms;
937
+ transition:
938
+ opacity 750ms,
939
+ filter 750ms,
940
+ fill 750ms;
803
941
 
804
942
  .choropleth-map__main__features__item--empty {
805
943
  opacity: 0.8;
@@ -810,7 +948,8 @@ export default defineComponent({
810
948
  }
811
949
  }
812
950
 
813
- .choropleth-map--has-zoom &:not(.choropleth-map__main__features__item--zoomed) {
951
+ .choropleth-map--has-zoom
952
+ &:not(.choropleth-map__main__features__item--zoomed) {
814
953
  filter: grayscale(90%);
815
954
  }
816
955
  }