@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.
- package/lib/components/AccordionStep.vue +53 -42
- package/lib/components/AccordionWrapper.vue +25 -24
- package/lib/components/ActiveTextTruncate.vue +44 -22
- package/lib/components/AdvancedLinkForm.vue +96 -46
- package/lib/components/Brand.vue +30 -23
- package/lib/components/BrandExpansion.vue +12 -3
- package/lib/components/ConfirmButton.vue +30 -26
- package/lib/components/ContentPlaceholder.vue +11 -7
- package/lib/components/CustomPagination.vue +50 -32
- package/lib/components/DigitsInput.vue +64 -60
- package/lib/components/DonateForm.vue +112 -83
- package/lib/components/EmbedForm.vue +37 -21
- package/lib/components/EmbeddableFooter.vue +14 -10
- package/lib/components/FollowUsPopover.vue +42 -40
- package/lib/components/GenericFooter.vue +98 -23
- package/lib/components/GenericHeader.vue +66 -29
- package/lib/components/HapticCopy.vue +41 -29
- package/lib/components/ImddbHeader.vue +113 -92
- package/lib/components/OrdinalLegend.vue +43 -20
- package/lib/components/RangePicker.vue +63 -42
- package/lib/components/ResponsiveIframe.vue +9 -2
- package/lib/components/ScaleLegend.vue +56 -18
- package/lib/components/SecretInput.vue +7 -8
- package/lib/components/SelectableDropdown.vue +120 -74
- package/lib/components/SharingOptions.vue +93 -36
- package/lib/components/SharingOptionsLink.vue +11 -5
- package/lib/components/SignUpForm.vue +44 -23
- package/lib/components/SlideUpDown.vue +7 -2
- package/lib/components/TexturedDeck.vue +24 -14
- package/lib/components/TinyPagination.vue +35 -22
- package/lib/composables/chart.ts +174 -157
- package/lib/composables/resizeObserver.ts +29 -29
- package/lib/composables/sendEmail.ts +53 -42
- package/lib/config.default.ts +17 -10
- package/lib/config.ts +34 -27
- package/lib/datavisualisations/BarChart.vue +48 -42
- package/lib/datavisualisations/ColumnChart.vue +133 -89
- package/lib/datavisualisations/LineChart.vue +79 -57
- package/lib/datavisualisations/StackedBarChart.vue +116 -68
- package/lib/datavisualisations/StackedColumnChart.vue +196 -115
- package/lib/enums.ts +25 -15
- package/lib/i18n.ts +3 -3
- package/lib/keys.ts +2 -2
- package/lib/main.ts +14 -10
- package/lib/maps/ChoroplethMap.vue +299 -160
- package/lib/maps/ChoroplethMapAnnotation.vue +29 -18
- package/lib/maps/SymbolMap.vue +194 -123
- package/lib/shims-bootstrap-vue.d.ts +1 -1
- package/lib/shims-vue.d.ts +3 -3
- package/lib/styles/functions.scss +10 -6
- package/lib/styles/lib.scss +2 -4
- package/lib/styles/mixins.scss +8 -8
- package/lib/styles/utilities.scss +1 -1
- package/lib/styles/variables.scss +24 -18
- package/lib/types.ts +26 -10
- package/lib/utils/animation.ts +4 -4
- package/lib/utils/assets.ts +31 -28
- package/lib/utils/clipboard.ts +16 -10
- package/lib/utils/iframe-resizer.ts +18 -13
- package/lib/utils/placeholder.ts +54 -23
- package/lib/utils/placeholderTypes.ts +3 -3
- package/package.json +7 -2
package/lib/config.ts
CHANGED
|
@@ -2,66 +2,73 @@ import get from 'lodash/get'
|
|
|
2
2
|
import each from 'lodash/each'
|
|
3
3
|
import { reactive, ref } from 'vue'
|
|
4
4
|
import defaultValues from './config.default'
|
|
5
|
-
import {Ref} from
|
|
5
|
+
import { Ref } from '@vue/runtime-core'
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
type ConfigMap = { [key: string]: any };
|
|
7
|
+
type ConfigMap = { [key: string]: any }
|
|
9
8
|
|
|
10
9
|
export class Config {
|
|
11
|
-
_VALUES
|
|
12
|
-
_SCOPES
|
|
13
|
-
constructor
|
|
10
|
+
_VALUES: Ref<ConfigMap>
|
|
11
|
+
_SCOPES: Ref<ConfigMap>
|
|
12
|
+
constructor(values = {}) {
|
|
14
13
|
this._VALUES = ref({})
|
|
15
14
|
this._SCOPES = ref({})
|
|
16
15
|
this.merge(values)
|
|
17
|
-
return this
|
|
16
|
+
return this
|
|
18
17
|
}
|
|
19
|
-
merge
|
|
18
|
+
merge(values = {}) {
|
|
20
19
|
return each(values, (value, key) => {
|
|
21
20
|
this.set(key, value)
|
|
22
21
|
})
|
|
23
22
|
}
|
|
24
|
-
set
|
|
23
|
+
set(key: string, value: any) {
|
|
25
24
|
const levels = key.split('.')
|
|
26
25
|
this._VALUES.value = this._VALUES.value ?? {}
|
|
27
26
|
|
|
28
27
|
if (levels.length > 1) {
|
|
29
|
-
|
|
30
|
-
const scope = this.scope(levels.shift() as string);
|
|
28
|
+
const scope = this.scope(levels.shift() as string)
|
|
31
29
|
this._VALUES.value[key] = scope.set(levels.join('.'), value)
|
|
32
30
|
} else {
|
|
33
31
|
this._VALUES.value[key] = value
|
|
34
32
|
}
|
|
35
33
|
return value
|
|
36
34
|
}
|
|
37
|
-
get
|
|
35
|
+
get(key: string, defaultValue?: Object | null) {
|
|
38
36
|
return get(this._VALUES.value, key, defaultValue)
|
|
39
37
|
}
|
|
40
|
-
is
|
|
38
|
+
is(key: string) {
|
|
41
39
|
const value = this.get(key, null)
|
|
42
|
-
switch(value) {
|
|
43
|
-
case 1:
|
|
44
|
-
|
|
45
|
-
case
|
|
46
|
-
|
|
47
|
-
case
|
|
48
|
-
|
|
49
|
-
case '
|
|
50
|
-
|
|
51
|
-
|
|
40
|
+
switch (value) {
|
|
41
|
+
case 1:
|
|
42
|
+
return true
|
|
43
|
+
case true:
|
|
44
|
+
return true
|
|
45
|
+
case '1':
|
|
46
|
+
return true
|
|
47
|
+
case 'true':
|
|
48
|
+
return true
|
|
49
|
+
case 0:
|
|
50
|
+
return false
|
|
51
|
+
case false:
|
|
52
|
+
return false
|
|
53
|
+
case '0':
|
|
54
|
+
return false
|
|
55
|
+
case 'false':
|
|
56
|
+
return false
|
|
57
|
+
default:
|
|
58
|
+
return !!value
|
|
52
59
|
}
|
|
53
60
|
}
|
|
54
|
-
isnt
|
|
61
|
+
isnt(key: string) {
|
|
55
62
|
return !this.is(key)
|
|
56
63
|
}
|
|
57
|
-
scope
|
|
64
|
+
scope(name: string) {
|
|
58
65
|
this.scopes[name] = this.scopes[name] ?? new Config()
|
|
59
66
|
return this.scopes[name]
|
|
60
67
|
}
|
|
61
|
-
get values
|
|
68
|
+
get values() {
|
|
62
69
|
return this._VALUES.value
|
|
63
70
|
}
|
|
64
|
-
get scopes
|
|
71
|
+
get scopes() {
|
|
65
72
|
this._SCOPES.value = this._SCOPES.value ?? ref({})
|
|
66
73
|
return this._SCOPES.value
|
|
67
74
|
}
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
import * as d3 from 'd3'
|
|
3
3
|
import identity from 'lodash/identity'
|
|
4
4
|
import sortBy from 'lodash/sortBy'
|
|
5
|
-
import {defineComponent, computed, ref, watch} from
|
|
6
|
-
import {chartProps, getChartProps, useChart} from
|
|
7
|
-
|
|
5
|
+
import { defineComponent, computed, ref, watch } from 'vue'
|
|
6
|
+
import { chartProps, getChartProps, useChart } from '@/composables/chart'
|
|
8
7
|
|
|
9
8
|
export default defineComponent({
|
|
10
9
|
name: 'BarChart',
|
|
@@ -78,16 +77,17 @@ export default defineComponent({
|
|
|
78
77
|
*/
|
|
79
78
|
xAxisTickFormat: {
|
|
80
79
|
type: [Function, String],
|
|
81
|
-
default: ()=>identity
|
|
80
|
+
default: () => identity
|
|
82
81
|
},
|
|
83
82
|
...chartProps()
|
|
84
83
|
},
|
|
85
|
-
emits:[
|
|
86
|
-
setup(props,{emit}){
|
|
84
|
+
emits: ['loaded', 'resized'],
|
|
85
|
+
setup(props, { emit }) {
|
|
87
86
|
const el = ref(null)
|
|
88
|
-
const width=ref(0)
|
|
87
|
+
const width = ref(0)
|
|
89
88
|
const isLoaded = ref(false)
|
|
90
|
-
const {loadedData, elementsMaxBBox,dataHasHighlights,d3Formatter}=
|
|
89
|
+
const { loadedData, elementsMaxBBox, dataHasHighlights, d3Formatter } =
|
|
90
|
+
useChart(el, getChartProps(props), { emit }, isLoaded, onResize, null)
|
|
91
91
|
// onMounted(() => {
|
|
92
92
|
// window.addEventListener('resize', onResize)
|
|
93
93
|
// onResize()
|
|
@@ -100,7 +100,9 @@ export default defineComponent({
|
|
|
100
100
|
if (!loadedData.value) {
|
|
101
101
|
return []
|
|
102
102
|
}
|
|
103
|
-
return !props.sortBy
|
|
103
|
+
return !props.sortBy
|
|
104
|
+
? loadedData.value
|
|
105
|
+
: sortBy(sortedData.value, props.sortBy)
|
|
104
106
|
})
|
|
105
107
|
const labelWidth = computed(() => {
|
|
106
108
|
if (props.fixedLabelWidth) {
|
|
@@ -130,13 +132,13 @@ export default defineComponent({
|
|
|
130
132
|
const padded = computed(() => {
|
|
131
133
|
const widthP = width.value - margin.value.left - margin.value.right
|
|
132
134
|
const heightP = height.value - margin.value.top - margin.value.bottom
|
|
133
|
-
return { width:widthP, height:heightP }
|
|
135
|
+
return { width: widthP, height: heightP }
|
|
134
136
|
})
|
|
135
137
|
const scale = computed(() => {
|
|
136
138
|
const x = d3
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
139
|
+
.scaleLinear()
|
|
140
|
+
.domain([0, d3.max(sortedData.value, (d) => d.value)])
|
|
141
|
+
.range([0, padded.value.width - valueWidth.value])
|
|
140
142
|
return { x }
|
|
141
143
|
})
|
|
142
144
|
const bars = computed(() => {
|
|
@@ -161,15 +163,14 @@ export default defineComponent({
|
|
|
161
163
|
})
|
|
162
164
|
})
|
|
163
165
|
const height = computed(() => {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
)
|
|
166
|
+
return (props.barHeight + props.barGap) * sortedData.value.length
|
|
167
|
+
})
|
|
167
168
|
|
|
168
|
-
function formatXDatum(d){
|
|
169
|
-
return d3Formatter(d,props.xAxisTickFormat)
|
|
169
|
+
function formatXDatum(d) {
|
|
170
|
+
return d3Formatter(d, props.xAxisTickFormat)
|
|
170
171
|
}
|
|
171
172
|
function onResize() {
|
|
172
|
-
if(el.value){
|
|
173
|
+
if (el.value) {
|
|
173
174
|
width.value = el.value.offsetWidth
|
|
174
175
|
}
|
|
175
176
|
}
|
|
@@ -177,7 +178,7 @@ export default defineComponent({
|
|
|
177
178
|
d3.axisBottom().scale(scale.value.x)
|
|
178
179
|
}
|
|
179
180
|
|
|
180
|
-
watch(width,()=> {
|
|
181
|
+
watch(width, () => {
|
|
181
182
|
initialize()
|
|
182
183
|
})
|
|
183
184
|
|
|
@@ -195,47 +196,52 @@ export default defineComponent({
|
|
|
195
196
|
})
|
|
196
197
|
</script>
|
|
197
198
|
|
|
198
|
-
|
|
199
199
|
<template>
|
|
200
200
|
<div
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
201
|
+
ref="el"
|
|
202
|
+
class="bar-chart"
|
|
203
|
+
:style="{
|
|
204
204
|
'--bar-color': barColor,
|
|
205
205
|
'--bar-highlight-color': barHighlightColor
|
|
206
206
|
}"
|
|
207
|
-
|
|
207
|
+
:class="{
|
|
208
208
|
'bar-chart--has-highlights': dataHasHighlights,
|
|
209
209
|
'bar-chart--social-mode': socialMode
|
|
210
210
|
}"
|
|
211
211
|
>
|
|
212
212
|
<svg :width="width" :height="height">
|
|
213
|
-
<g
|
|
213
|
+
<g
|
|
214
|
+
:style="{ transform: `translate(0, ${margin.top}px)` }"
|
|
215
|
+
class="bar-chart__labels"
|
|
216
|
+
>
|
|
214
217
|
<text
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
218
|
+
v-for="(label, i) in labels"
|
|
219
|
+
:key="i"
|
|
220
|
+
:x="label.x"
|
|
221
|
+
:y="label.y"
|
|
222
|
+
text-anchor="end"
|
|
223
|
+
class="bar-chart__labels__item"
|
|
221
224
|
>
|
|
222
225
|
{{ label.label }}
|
|
223
226
|
</text>
|
|
224
227
|
</g>
|
|
225
|
-
<g
|
|
228
|
+
<g
|
|
229
|
+
:style="{ transform: `translate(${margin.left}px, ${margin.top}px)` }"
|
|
230
|
+
class="bar-chart__bars"
|
|
231
|
+
>
|
|
226
232
|
<g
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
233
|
+
v-for="(bar, i) in bars"
|
|
234
|
+
:key="i"
|
|
235
|
+
class="bar-chart__bars__item"
|
|
236
|
+
:class="{ 'bar-chart__bars__item--highlight': bar.highlight }"
|
|
231
237
|
>
|
|
232
238
|
<rect :width="bar.width" :height="bar.height" :x="bar.x" :y="bar.y" />
|
|
233
239
|
<text
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
240
|
+
class="bar-chart__bars__item__value"
|
|
241
|
+
:x="bar.width + valueGap"
|
|
242
|
+
:y="bar.y + bar.height / 2"
|
|
243
|
+
text-anchor="start"
|
|
244
|
+
dominant-baseline="middle"
|
|
239
245
|
>
|
|
240
246
|
{{ formatXDatum(bar.value) }}
|
|
241
247
|
</text>
|
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import {
|
|
3
|
-
|
|
2
|
+
import {
|
|
3
|
+
ComponentPublicInstance,
|
|
4
|
+
computed,
|
|
5
|
+
defineComponent,
|
|
6
|
+
PropType,
|
|
7
|
+
ref,
|
|
8
|
+
watchEffect,
|
|
9
|
+
onMounted
|
|
10
|
+
} from 'vue'
|
|
11
|
+
import { identity, iteratee, sortBy } from 'lodash'
|
|
4
12
|
import * as d3 from 'd3'
|
|
5
|
-
import {chartProps, getChartProps, useChart} from
|
|
13
|
+
import { chartProps, getChartProps, useChart } from '@/composables/chart'
|
|
6
14
|
|
|
7
15
|
type ColumnBar = {
|
|
8
|
-
datum: { [timeSerie: string]: any }
|
|
9
|
-
width: number
|
|
10
|
-
height: number
|
|
11
|
-
x: number
|
|
12
|
-
y: number
|
|
16
|
+
datum: { [timeSerie: string]: any }
|
|
17
|
+
width: number
|
|
18
|
+
height: number
|
|
19
|
+
x: number
|
|
20
|
+
y: number
|
|
13
21
|
}
|
|
14
22
|
//import chart from '../mixins/chart'
|
|
15
23
|
|
|
@@ -63,8 +71,8 @@ export default defineComponent({
|
|
|
63
71
|
* Function to apply to format x axis ticks
|
|
64
72
|
*/
|
|
65
73
|
xAxisTickFormat: {
|
|
66
|
-
type: [Function, String] as PropType<Function | string
|
|
67
|
-
default: ()=>identity
|
|
74
|
+
type: [Function, String] as PropType<Function | string>,
|
|
75
|
+
default: () => identity
|
|
68
76
|
},
|
|
69
77
|
/**
|
|
70
78
|
* Definition of x axis ticks
|
|
@@ -77,8 +85,8 @@ export default defineComponent({
|
|
|
77
85
|
* Function to apply to format y axis ticks
|
|
78
86
|
*/
|
|
79
87
|
yAxisTickFormat: {
|
|
80
|
-
type: [Function, String] as PropType<Function | string
|
|
81
|
-
default: ()=>identity
|
|
88
|
+
type: [Function, String] as PropType<Function | string>,
|
|
89
|
+
default: () => identity
|
|
82
90
|
},
|
|
83
91
|
/**
|
|
84
92
|
* Definition of y axis ticks
|
|
@@ -161,7 +169,7 @@ export default defineComponent({
|
|
|
161
169
|
},
|
|
162
170
|
...chartProps()
|
|
163
171
|
},
|
|
164
|
-
setup(props, {emit}) {
|
|
172
|
+
setup(props, { emit }) {
|
|
165
173
|
const width = ref(0)
|
|
166
174
|
const height = ref(0)
|
|
167
175
|
const shownTooltip = ref(-1)
|
|
@@ -173,13 +181,15 @@ export default defineComponent({
|
|
|
173
181
|
d3Formatter,
|
|
174
182
|
baseHeightRatio,
|
|
175
183
|
dataHasHighlights
|
|
176
|
-
} = useChart(el, getChartProps(props), {emit}, isLoaded, setSizes)
|
|
184
|
+
} = useChart(el, getChartProps(props), { emit }, isLoaded, setSizes)
|
|
177
185
|
|
|
178
186
|
const sortedData = computed((): any[] => {
|
|
179
187
|
if (!loadedData.value) {
|
|
180
188
|
return []
|
|
181
189
|
}
|
|
182
|
-
return !props.sortBy
|
|
190
|
+
return !props.sortBy
|
|
191
|
+
? loadedData.value
|
|
192
|
+
: sortBy(sortedData.value, props.sortBy)
|
|
183
193
|
})
|
|
184
194
|
|
|
185
195
|
const labelWidth = computed((): number => {
|
|
@@ -188,7 +198,7 @@ export default defineComponent({
|
|
|
188
198
|
}
|
|
189
199
|
const selector = '.column-chart__axis--y .tick text'
|
|
190
200
|
const defaultWidth = 100
|
|
191
|
-
return elementsMaxBBox({selector, defaultWidth}).width
|
|
201
|
+
return elementsMaxBBox({ selector, defaultWidth }).width
|
|
192
202
|
})
|
|
193
203
|
|
|
194
204
|
const labelHeight = computed((): number => {
|
|
@@ -197,60 +207,72 @@ export default defineComponent({
|
|
|
197
207
|
}
|
|
198
208
|
const selector = '.column-chart__axis--y .tick text'
|
|
199
209
|
const defaultHeight = 10
|
|
200
|
-
return elementsMaxBBox({selector, defaultHeight}).height
|
|
210
|
+
return elementsMaxBBox({ selector, defaultHeight }).height
|
|
201
211
|
})
|
|
202
212
|
|
|
203
213
|
const bucketHeight = computed((): number => {
|
|
204
|
-
|
|
205
214
|
if (props.noXAxis) {
|
|
206
215
|
return 0
|
|
207
216
|
}
|
|
208
217
|
const selector = '.column-chart__axis--x .tick text'
|
|
209
218
|
const defaultHeight = 10
|
|
210
|
-
return elementsMaxBBox({selector, defaultHeight}).height
|
|
219
|
+
return elementsMaxBBox({ selector, defaultHeight }).height
|
|
211
220
|
})
|
|
212
221
|
|
|
213
222
|
const bucketWidth = computed((): number => {
|
|
214
223
|
const selector = '.column-chart__axis--x .tick text'
|
|
215
224
|
const defaultWidth = 100
|
|
216
|
-
return elementsMaxBBox({selector, defaultWidth}).width
|
|
225
|
+
return elementsMaxBBox({ selector, defaultWidth }).width
|
|
217
226
|
})
|
|
218
227
|
|
|
219
|
-
const margin = computed(
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
228
|
+
const margin = computed(
|
|
229
|
+
(): { left: number; right: number; top: number; bottom: number } => {
|
|
230
|
+
return {
|
|
231
|
+
left: props.noYAxis ? 0 : labelWidth.value + 10,
|
|
232
|
+
right: 0,
|
|
233
|
+
top: labelHeight.value / 2,
|
|
234
|
+
bottom: props.noXAxis ? 0 : bucketHeight.value + 10
|
|
235
|
+
}
|
|
225
236
|
}
|
|
226
|
-
|
|
237
|
+
)
|
|
227
238
|
|
|
228
239
|
const padded = computed((): { width: number; height: number } => {
|
|
229
240
|
const widthP = width.value - margin.value.left - margin.value.right
|
|
230
241
|
const heightP = height.value - margin.value.top - margin.value.bottom
|
|
231
|
-
return {width: widthP, height: heightP}
|
|
242
|
+
return { width: widthP, height: heightP }
|
|
232
243
|
})
|
|
233
244
|
|
|
234
245
|
const scaleX = computed((): d3.ScaleBand<string> => {
|
|
235
246
|
return d3
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
247
|
+
.scaleBand()
|
|
248
|
+
.domain(sortedData.value.map(iteratee(props.timeseriesKey)))
|
|
249
|
+
.range([0, padded.value.width])
|
|
250
|
+
.padding(props.barPadding)
|
|
240
251
|
})
|
|
241
252
|
|
|
242
253
|
const scaleY = computed((): d3.ScaleLinear<number, number> => {
|
|
243
|
-
const maxValue =
|
|
244
|
-
|
|
254
|
+
const maxValue =
|
|
255
|
+
props.maxValue ?? d3.max(sortedData.value, iteratee(props.seriesName))
|
|
256
|
+
return d3
|
|
257
|
+
.scaleLinear()
|
|
258
|
+
.domain([0, maxValue])
|
|
259
|
+
.range([padded.value.height, 0])
|
|
245
260
|
})
|
|
246
261
|
|
|
247
262
|
const bars = computed((): ColumnBar[] => {
|
|
248
263
|
return sortedData.value.map((datum: any) => {
|
|
249
264
|
return {
|
|
250
265
|
datum,
|
|
251
|
-
width: Math.max(
|
|
252
|
-
|
|
253
|
-
|
|
266
|
+
width: Math.max(
|
|
267
|
+
1,
|
|
268
|
+
Math.abs(scaleX.value.bandwidth()) - props.barMargin
|
|
269
|
+
),
|
|
270
|
+
height: Math.abs(
|
|
271
|
+
padded.value.height - scaleY.value(datum[props.seriesName])
|
|
272
|
+
),
|
|
273
|
+
x:
|
|
274
|
+
(scaleX.value(datum[props.timeseriesKey]) ?? 0) +
|
|
275
|
+
props.barMargin / 2,
|
|
254
276
|
y: scaleY.value(datum[props.seriesName]) ?? 0
|
|
255
277
|
}
|
|
256
278
|
})
|
|
@@ -271,7 +293,8 @@ export default defineComponent({
|
|
|
271
293
|
|
|
272
294
|
const xAxisTickValues = computed((): string[] => {
|
|
273
295
|
// Either use the explicit `xAxisTicks` prop or use the data
|
|
274
|
-
const ticks =
|
|
296
|
+
const ticks =
|
|
297
|
+
props.xAxisTicks ?? sortedData.value.map(iteratee(props.timeseriesKey))
|
|
275
298
|
// Then filter out ticks according to `this.xAxisHiddenTicks`
|
|
276
299
|
return ticks.map((tick, i) => {
|
|
277
300
|
return (i + 1) % xAxisHiddenTicks.value ? null : tick
|
|
@@ -280,39 +303,41 @@ export default defineComponent({
|
|
|
280
303
|
|
|
281
304
|
const xAxis = computed((): d3.Axis<string> => {
|
|
282
305
|
return d3
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
306
|
+
.axisBottom(scaleX.value)
|
|
307
|
+
.tickFormat((d) => d3Formatter(d, props.xAxisTickFormat))
|
|
308
|
+
.tickValues(xAxisTickValues.value)
|
|
286
309
|
})
|
|
287
310
|
|
|
288
311
|
const yAxis = computed((): d3.Axis<d3.NumberValue> => {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
)
|
|
312
|
+
return d3
|
|
313
|
+
.axisLeft(scaleY.value)
|
|
314
|
+
.tickFormat((d) => d3Formatter(d, props.yAxisTickFormat))
|
|
315
|
+
.ticks(props.yAxisTicks)
|
|
316
|
+
})
|
|
295
317
|
|
|
296
318
|
function formatXDatum(d: any) {
|
|
297
|
-
return d3Formatter(d,props.xAxisTickFormat)
|
|
319
|
+
return d3Formatter(d, props.xAxisTickFormat)
|
|
298
320
|
}
|
|
299
321
|
|
|
300
322
|
function formatYDatum(d: any) {
|
|
301
|
-
return d3Formatter(d,props.yAxisTickFormat)
|
|
323
|
+
return d3Formatter(d, props.yAxisTickFormat)
|
|
302
324
|
}
|
|
303
325
|
|
|
304
326
|
function setSizes() {
|
|
305
327
|
width.value = (el.value as HTMLElement)?.offsetWidth ?? 0
|
|
306
|
-
height.value =
|
|
328
|
+
height.value =
|
|
329
|
+
props.fixedHeight !== null
|
|
330
|
+
? props.fixedHeight
|
|
331
|
+
: width.value * baseHeightRatio.value
|
|
307
332
|
}
|
|
308
333
|
|
|
309
|
-
function select({datum}: { datum: any }) {
|
|
334
|
+
function select({ datum }: { datum: any }) {
|
|
310
335
|
/**
|
|
311
336
|
* Fired when a column is selected
|
|
312
337
|
* @event click
|
|
313
338
|
* @param Mixed New step value.
|
|
314
339
|
*/
|
|
315
|
-
emit(
|
|
340
|
+
emit('select', datum)
|
|
316
341
|
}
|
|
317
342
|
|
|
318
343
|
function update() {
|
|
@@ -320,32 +345,32 @@ export default defineComponent({
|
|
|
320
345
|
return
|
|
321
346
|
}
|
|
322
347
|
d3.select(el.value)
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
348
|
+
.select('.column-chart__axis--x')
|
|
349
|
+
.call(xAxis.value as any)
|
|
350
|
+
.select('.domain')
|
|
351
|
+
.remove()
|
|
327
352
|
|
|
328
353
|
d3.select(el.value)
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
354
|
+
.select('.column-chart__axis--y')
|
|
355
|
+
.call(yAxis.value as any)
|
|
356
|
+
.selectAll('.tick line')
|
|
357
|
+
.attr('x2', padded.value.width)
|
|
333
358
|
}
|
|
334
359
|
|
|
335
|
-
function barTooltipStyle(bar: { x: number
|
|
360
|
+
function barTooltipStyle(bar: { x: number; y: number; width: number }) {
|
|
336
361
|
const top = `${bar.y + margin.value.top}px`
|
|
337
362
|
const left = `${bar.x + bar.width / 2 + margin.value.left}px`
|
|
338
|
-
return {top, left}
|
|
363
|
+
return { top, left }
|
|
339
364
|
}
|
|
340
365
|
|
|
341
366
|
function highlighted(datum: any): boolean {
|
|
342
|
-
return
|
|
367
|
+
return (
|
|
368
|
+
datum.highlight || props.highlights.includes(datum[props.timeseriesKey])
|
|
369
|
+
)
|
|
343
370
|
}
|
|
344
371
|
|
|
345
|
-
|
|
346
372
|
watchEffect(async () => {
|
|
347
373
|
update()
|
|
348
|
-
|
|
349
374
|
})
|
|
350
375
|
|
|
351
376
|
return {
|
|
@@ -369,39 +394,55 @@ export default defineComponent({
|
|
|
369
394
|
|
|
370
395
|
<template>
|
|
371
396
|
<div
|
|
372
|
-
|
|
373
|
-
|
|
397
|
+
ref="el"
|
|
398
|
+
:class="{
|
|
374
399
|
'column-chart--has-highlights': dataHasHighlights,
|
|
375
400
|
'column-chart--hover': hover,
|
|
376
401
|
'column-chart--stripped': stripped,
|
|
377
402
|
'column-chart--social-mode': socialMode
|
|
378
403
|
}"
|
|
379
|
-
|
|
380
|
-
|
|
404
|
+
:style="{
|
|
405
|
+
'--column-color': columnColor,
|
|
406
|
+
'--column-highlight-color': columnHighlightColor
|
|
407
|
+
}"
|
|
408
|
+
class="column-chart"
|
|
381
409
|
>
|
|
382
|
-
<svg
|
|
383
|
-
:height="height" :width="width">
|
|
410
|
+
<svg :height="height" :width="width">
|
|
384
411
|
<g :style="{ transform: `translate(${margin.left}px, ${margin.top}px)` }">
|
|
385
412
|
<g
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
413
|
+
v-if="!noXAxis"
|
|
414
|
+
:style="{ transform: `translate(0, ${padded.height}px)` }"
|
|
415
|
+
class="column-chart__axis column-chart__axis--x"
|
|
389
416
|
/>
|
|
390
|
-
<g v-if="!noYAxis" class="column-chart__axis column-chart__axis--y"/>
|
|
417
|
+
<g v-if="!noYAxis" class="column-chart__axis column-chart__axis--y" />
|
|
391
418
|
</g>
|
|
392
|
-
<g
|
|
419
|
+
<g
|
|
420
|
+
:style="{ transform: `translate(${margin.left}px, ${margin.top}px)` }"
|
|
421
|
+
class="column-chart__columns"
|
|
422
|
+
>
|
|
393
423
|
<g
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
:
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
424
|
+
v-for="(bar, index) in bars"
|
|
425
|
+
:key="index"
|
|
426
|
+
:class="{
|
|
427
|
+
'column-chart__columns__item--highlight': highlighted(bar.datum)
|
|
428
|
+
}"
|
|
429
|
+
:style="{ transform: `translate(${bar.x}px, 0px)` }"
|
|
430
|
+
class="column-chart__columns__item"
|
|
431
|
+
@click="select(bar)"
|
|
432
|
+
@mouseleave="shownTooltip = -1"
|
|
433
|
+
@mouseover="shownTooltip = index"
|
|
402
434
|
>
|
|
403
|
-
<rect
|
|
404
|
-
|
|
435
|
+
<rect
|
|
436
|
+
:height="padded.height"
|
|
437
|
+
:width="bar.width"
|
|
438
|
+
class="column-chart__columns__item__placeholder"
|
|
439
|
+
/>
|
|
440
|
+
<rect
|
|
441
|
+
:height="bar.height"
|
|
442
|
+
:width="bar.width"
|
|
443
|
+
:y="bar.y"
|
|
444
|
+
class="column-chart__columns__item__bar"
|
|
445
|
+
/>
|
|
405
446
|
</g>
|
|
406
447
|
</g>
|
|
407
448
|
</svg>
|
|
@@ -409,7 +450,10 @@ export default defineComponent({
|
|
|
409
450
|
<div v-for="(bar, index) in bars" :key="index">
|
|
410
451
|
<div :style="barTooltipStyle(bar)" class="column-chart__tooltips__item">
|
|
411
452
|
<transition name="fade">
|
|
412
|
-
<div
|
|
453
|
+
<div
|
|
454
|
+
v-if="shownTooltip === index"
|
|
455
|
+
class="column-chart__tooltips__item__wrapper"
|
|
456
|
+
>
|
|
413
457
|
<slot name="tooltip" v-bind="bar">
|
|
414
458
|
<h6 class="column-chart__tooltips__item__wrapper__heading mb-0">
|
|
415
459
|
{{ formatXDatum(bar.datum[timeseriesKey]) }}
|
|
@@ -426,7 +470,6 @@ export default defineComponent({
|
|
|
426
470
|
</div>
|
|
427
471
|
</template>
|
|
428
472
|
|
|
429
|
-
|
|
430
473
|
<style lang="scss">
|
|
431
474
|
@import '../styles/lib';
|
|
432
475
|
|
|
@@ -436,7 +479,8 @@ export default defineComponent({
|
|
|
436
479
|
|
|
437
480
|
position: relative;
|
|
438
481
|
|
|
439
|
-
&--has-highlights
|
|
482
|
+
&--has-highlights
|
|
483
|
+
&__columns__item:not(&__columns__item--highlight):not(:hover) {
|
|
440
484
|
opacity: var(--highlight-opacity);
|
|
441
485
|
filter: grayscale(30%);
|
|
442
486
|
}
|