@tekkare/romulus 0.1.206 → 0.1.207
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/dist/module.json +1 -1
- package/dist/runtime/components/BarChart.vue +8 -0
- package/dist/runtime/components/ChoroplethMap.vue +11 -1
- package/dist/runtime/components/LineChart.vue +9 -0
- package/dist/runtime/utils/chart.d.ts +59 -17
- package/dist/runtime/utils/chart.js +20 -11
- package/package.json +1 -1
package/dist/module.json
CHANGED
|
@@ -21,11 +21,17 @@ const props = withDefaults(defineProps<{
|
|
|
21
21
|
* ce qui suffit des que les barres sont nombreuses.
|
|
22
22
|
*/
|
|
23
23
|
labelFormatter?: RmBarLabelFormatter
|
|
24
|
+
/**
|
|
25
|
+
* Formate l'axe des valeurs et l'infobulle. Independant de `labelFormatter`,
|
|
26
|
+
* qui seul decide si les barres portent une etiquette.
|
|
27
|
+
*/
|
|
28
|
+
valueFormatter?: (value: number) => string
|
|
24
29
|
}>(), {
|
|
25
30
|
horizontal: false,
|
|
26
31
|
height: 'standard',
|
|
27
32
|
description: undefined,
|
|
28
33
|
labelFormatter: undefined,
|
|
34
|
+
valueFormatter: undefined,
|
|
29
35
|
})
|
|
30
36
|
|
|
31
37
|
const { theme, palette, decal } = useChartTheme()
|
|
@@ -39,6 +45,7 @@ const option = computed(() =>
|
|
|
39
45
|
palette.value.cat,
|
|
40
46
|
decal.value,
|
|
41
47
|
props.labelFormatter,
|
|
48
|
+
props.valueFormatter,
|
|
42
49
|
)
|
|
43
50
|
: rmBarVerticalOption(
|
|
44
51
|
props.categories,
|
|
@@ -47,6 +54,7 @@ const option = computed(() =>
|
|
|
47
54
|
palette.value.cat,
|
|
48
55
|
decal.value,
|
|
49
56
|
props.labelFormatter,
|
|
57
|
+
props.valueFormatter,
|
|
50
58
|
),
|
|
51
59
|
)
|
|
52
60
|
</script>
|
|
@@ -58,6 +58,11 @@ const props = withDefaults(
|
|
|
58
58
|
/** Hauteur du dessin, en pixels. */
|
|
59
59
|
height?: number
|
|
60
60
|
lang?: 'fr' | 'en'
|
|
61
|
+
/**
|
|
62
|
+
* Formate les valeurs de l'infobulle et des bornes de la legende, a la
|
|
63
|
+
* place du format de la langue. Pour une app qui a sa regle d'arrondi.
|
|
64
|
+
*/
|
|
65
|
+
valueFormatter?: (value: number) => string
|
|
61
66
|
}>(),
|
|
62
67
|
{
|
|
63
68
|
data: () => [],
|
|
@@ -67,6 +72,7 @@ const props = withDefaults(
|
|
|
67
72
|
compact: false,
|
|
68
73
|
height: 500,
|
|
69
74
|
lang: 'fr',
|
|
75
|
+
valueFormatter: undefined,
|
|
70
76
|
},
|
|
71
77
|
)
|
|
72
78
|
|
|
@@ -186,7 +192,11 @@ const T = computed(() =>
|
|
|
186
192
|
/** Dégradé de la légende, dans l'ordre de lecture de l'échelle. */
|
|
187
193
|
const legendGradient = computed(() => `linear-gradient(90deg, ${ramp.value.join(', ')})`)
|
|
188
194
|
|
|
189
|
-
const fmt = computed(() =>
|
|
195
|
+
const fmt = computed(() =>
|
|
196
|
+
props.valueFormatter
|
|
197
|
+
? { format: props.valueFormatter }
|
|
198
|
+
: new Intl.NumberFormat(props.lang === 'en' ? 'en-US' : 'fr-FR'),
|
|
199
|
+
)
|
|
190
200
|
</script>
|
|
191
201
|
|
|
192
202
|
<template>
|
|
@@ -52,6 +52,12 @@ const props = withDefaults(defineProps<{
|
|
|
52
52
|
* nombre entier avec ses separateurs de milliers.
|
|
53
53
|
*/
|
|
54
54
|
numberFormat?: 'compact' | 'plain'
|
|
55
|
+
/**
|
|
56
|
+
* Formateur de l'appelant, pour l'axe, les etiquettes ET l'infobulle. Passe
|
|
57
|
+
* avant `numberFormat` : une app qui a sa propre regle d'arrondi la veut
|
|
58
|
+
* partout, y compris au survol.
|
|
59
|
+
*/
|
|
60
|
+
valueFormatter?: (value: number) => string
|
|
55
61
|
height?: keyof typeof RM_CHART_HEIGHTS | number
|
|
56
62
|
description?: string
|
|
57
63
|
}>(), {
|
|
@@ -64,6 +70,7 @@ const props = withDefaults(defineProps<{
|
|
|
64
70
|
legendPosition: 'bottom',
|
|
65
71
|
startAtZero: false,
|
|
66
72
|
numberFormat: undefined,
|
|
73
|
+
valueFormatter: undefined,
|
|
67
74
|
height: 'standard',
|
|
68
75
|
description: undefined,
|
|
69
76
|
})
|
|
@@ -71,6 +78,7 @@ const props = withDefaults(defineProps<{
|
|
|
71
78
|
const { theme, palette, decal } = useChartTheme()
|
|
72
79
|
|
|
73
80
|
const formatter = computed(() => {
|
|
81
|
+
if (props.valueFormatter) return props.valueFormatter
|
|
74
82
|
if (props.numberFormat === 'compact') return rmCompact
|
|
75
83
|
if (props.numberFormat === 'plain') return rmNumber
|
|
76
84
|
return undefined
|
|
@@ -100,6 +108,7 @@ const option = computed(() => {
|
|
|
100
108
|
legendPosition: props.legendPosition,
|
|
101
109
|
startAtZero: props.startAtZero,
|
|
102
110
|
valueFormatter: formatter.value,
|
|
111
|
+
tooltipFormatter: props.valueFormatter,
|
|
103
112
|
}) as Record<string, any>
|
|
104
113
|
if (built.legend && Object.keys(legendSelected.value).length) {
|
|
105
114
|
built.legend = { ...built.legend, selected: { ...legendSelected.value } }
|
|
@@ -200,8 +200,24 @@ export interface RmSeriesInput {
|
|
|
200
200
|
* (« 1 240 (18 %) »), et c'est l'index qui la retrouve.
|
|
201
201
|
*/
|
|
202
202
|
export type RmBarLabelFormatter = (value: number, index: number) => string;
|
|
203
|
-
export declare function rmBarVerticalOption(categories: (string | number)[], series: RmSeriesInput[], theme: RmChartTheme, palette: string[], decal?: boolean, formatter?: RmBarLabelFormatter): {
|
|
203
|
+
export declare function rmBarVerticalOption(categories: (string | number)[], series: RmSeriesInput[], theme: RmChartTheme, palette: string[], decal?: boolean, formatter?: RmBarLabelFormatter, valueFormatter?: (value: number) => string): {
|
|
204
204
|
tooltip: {
|
|
205
|
+
valueFormatter: (value: unknown) => string;
|
|
206
|
+
trigger: string;
|
|
207
|
+
backgroundColor: string;
|
|
208
|
+
textStyle: {
|
|
209
|
+
color: string;
|
|
210
|
+
fontFamily: string;
|
|
211
|
+
fontSize: number;
|
|
212
|
+
};
|
|
213
|
+
borderColor: string;
|
|
214
|
+
borderWidth: number;
|
|
215
|
+
appendTo: string;
|
|
216
|
+
confine: boolean;
|
|
217
|
+
enterable: boolean;
|
|
218
|
+
extraCssText: string;
|
|
219
|
+
} | {
|
|
220
|
+
valueFormatter?: undefined;
|
|
205
221
|
trigger: string;
|
|
206
222
|
backgroundColor: string;
|
|
207
223
|
textStyle: {
|
|
@@ -270,6 +286,7 @@ export declare function rmBarVerticalOption(categories: (string | number)[], ser
|
|
|
270
286
|
show: boolean;
|
|
271
287
|
};
|
|
272
288
|
axisLabel: {
|
|
289
|
+
formatter?: ((value: number) => string) | undefined;
|
|
273
290
|
fontSize: number;
|
|
274
291
|
color: string;
|
|
275
292
|
fontFamily: string;
|
|
@@ -284,6 +301,7 @@ export declare function rmBarVerticalOption(categories: (string | number)[], ser
|
|
|
284
301
|
};
|
|
285
302
|
yAxis: {
|
|
286
303
|
axisLabel: {
|
|
304
|
+
formatter?: ((value: number) => string) | undefined;
|
|
287
305
|
fontSize: number;
|
|
288
306
|
color: string;
|
|
289
307
|
fontFamily: string;
|
|
@@ -334,7 +352,38 @@ export declare function rmBarVerticalOption(categories: (string | number)[], ser
|
|
|
334
352
|
};
|
|
335
353
|
};
|
|
336
354
|
/** Bar chart horizontal, avec valeur affichee en bout de barre. */
|
|
337
|
-
export declare function rmBarHorizontalOption(labels: string[], values: (number | null)[], theme: RmChartTheme, palette: string[], decal?: boolean, formatter?: RmBarLabelFormatter): {
|
|
355
|
+
export declare function rmBarHorizontalOption(labels: string[], values: (number | null)[], theme: RmChartTheme, palette: string[], decal?: boolean, formatter?: RmBarLabelFormatter, valueFormatter?: (value: number) => string): {
|
|
356
|
+
tooltip: {
|
|
357
|
+
valueFormatter: (value: unknown) => string;
|
|
358
|
+
trigger: string;
|
|
359
|
+
backgroundColor: string;
|
|
360
|
+
textStyle: {
|
|
361
|
+
color: string;
|
|
362
|
+
fontFamily: string;
|
|
363
|
+
fontSize: number;
|
|
364
|
+
};
|
|
365
|
+
borderColor: string;
|
|
366
|
+
borderWidth: number;
|
|
367
|
+
appendTo: string;
|
|
368
|
+
confine: boolean;
|
|
369
|
+
enterable: boolean;
|
|
370
|
+
extraCssText: string;
|
|
371
|
+
} | {
|
|
372
|
+
valueFormatter?: undefined;
|
|
373
|
+
trigger: string;
|
|
374
|
+
backgroundColor: string;
|
|
375
|
+
textStyle: {
|
|
376
|
+
color: string;
|
|
377
|
+
fontFamily: string;
|
|
378
|
+
fontSize: number;
|
|
379
|
+
};
|
|
380
|
+
borderColor: string;
|
|
381
|
+
borderWidth: number;
|
|
382
|
+
appendTo: string;
|
|
383
|
+
confine: boolean;
|
|
384
|
+
enterable: boolean;
|
|
385
|
+
extraCssText: string;
|
|
386
|
+
};
|
|
338
387
|
grid: {
|
|
339
388
|
left: number;
|
|
340
389
|
right: number;
|
|
@@ -344,6 +393,7 @@ export declare function rmBarHorizontalOption(labels: string[], values: (number
|
|
|
344
393
|
};
|
|
345
394
|
xAxis: {
|
|
346
395
|
axisLabel: {
|
|
396
|
+
formatter?: ((value: number) => string) | undefined;
|
|
347
397
|
fontSize: number;
|
|
348
398
|
color: string;
|
|
349
399
|
fontFamily: string;
|
|
@@ -365,6 +415,7 @@ export declare function rmBarHorizontalOption(labels: string[], values: (number
|
|
|
365
415
|
show: boolean;
|
|
366
416
|
};
|
|
367
417
|
axisLabel: {
|
|
418
|
+
formatter?: ((value: number) => string) | undefined;
|
|
368
419
|
fontSize: number;
|
|
369
420
|
color: string;
|
|
370
421
|
fontFamily: string;
|
|
@@ -409,21 +460,6 @@ export declare function rmBarHorizontalOption(labels: string[], values: (number
|
|
|
409
460
|
textStyle: {
|
|
410
461
|
fontFamily: string;
|
|
411
462
|
};
|
|
412
|
-
tooltip: {
|
|
413
|
-
trigger: string;
|
|
414
|
-
backgroundColor: string;
|
|
415
|
-
textStyle: {
|
|
416
|
-
color: string;
|
|
417
|
-
fontFamily: string;
|
|
418
|
-
fontSize: number;
|
|
419
|
-
};
|
|
420
|
-
borderColor: string;
|
|
421
|
-
borderWidth: number;
|
|
422
|
-
appendTo: string;
|
|
423
|
-
confine: boolean;
|
|
424
|
-
enterable: boolean;
|
|
425
|
-
extraCssText: string;
|
|
426
|
-
};
|
|
427
463
|
};
|
|
428
464
|
/** Line ou area chart. `step` produit la marche d'escalier des series de prix. */
|
|
429
465
|
/**
|
|
@@ -471,6 +507,11 @@ export declare function rmLineOption(categories: (string | number)[], series: Rm
|
|
|
471
507
|
startAtZero?: boolean;
|
|
472
508
|
/** Formate les valeurs, dans les etiquettes comme dans l'infobulle. */
|
|
473
509
|
valueFormatter?: (value: number) => string;
|
|
510
|
+
/**
|
|
511
|
+
* Formate l'infobulle a la place de `rmNumber`. Une app qui impose sa
|
|
512
|
+
* propre regle d'arrondi la veut aussi au survol, pas seulement sur l'axe.
|
|
513
|
+
*/
|
|
514
|
+
tooltipFormatter?: (value: number) => string;
|
|
474
515
|
}): {
|
|
475
516
|
animation: boolean;
|
|
476
517
|
tooltip: {
|
|
@@ -544,6 +585,7 @@ export declare function rmLineOption(categories: (string | number)[], series: Rm
|
|
|
544
585
|
};
|
|
545
586
|
boundaryGap: boolean;
|
|
546
587
|
axisLabel: {
|
|
588
|
+
formatter?: ((value: number) => string) | undefined;
|
|
547
589
|
fontSize: number;
|
|
548
590
|
color: string;
|
|
549
591
|
fontFamily: string;
|
|
@@ -150,21 +150,26 @@ const valueAxis = (theme, label, hidden = false, formatter) => ({
|
|
|
150
150
|
axisTick: hidden ? { show: false } : void 0,
|
|
151
151
|
splitLine: { lineStyle: { color: theme.splitLine } }
|
|
152
152
|
});
|
|
153
|
-
const axisCommon = (theme) => ({
|
|
154
|
-
axisLabel: { fontSize: 11, color: theme.mutedColor, fontFamily: FONT },
|
|
153
|
+
const axisCommon = (theme, formatter) => ({
|
|
154
|
+
axisLabel: { fontSize: 11, color: theme.mutedColor, fontFamily: FONT, ...formatter ? { formatter } : {} },
|
|
155
155
|
axisLine: { lineStyle: { color: theme.axisLine } },
|
|
156
156
|
splitLine: { lineStyle: { color: theme.splitLine } }
|
|
157
157
|
});
|
|
158
|
-
|
|
158
|
+
const rmTooltipValue = (formatter) => formatter ? { valueFormatter: (value) => typeof value === "number" ? formatter(value) : "" } : {};
|
|
159
|
+
export function rmBarVerticalOption(categories, series, theme, palette, decal = false, formatter, valueFormatter) {
|
|
159
160
|
return {
|
|
160
161
|
...rmBaseOption(theme, decal),
|
|
161
|
-
tooltip: {
|
|
162
|
+
tooltip: {
|
|
163
|
+
...rmBaseOption(theme, decal).tooltip,
|
|
164
|
+
trigger: rmTooltipTrigger(series.length),
|
|
165
|
+
...rmTooltipValue(valueFormatter)
|
|
166
|
+
},
|
|
162
167
|
legend: series.length > 1 ? rmLegend(theme, series.length, "bottom", series.map((s) => String(s.name ?? ""))) : void 0,
|
|
163
168
|
// La legende passee sous le graphe prend sa place dans la gouttiere basse,
|
|
164
169
|
// sinon elle recouvre les libelles de l'axe des abscisses.
|
|
165
170
|
grid: { ...rmBaseOption(theme, decal).grid, bottom: series.length > 1 ? 56 : 36 },
|
|
166
171
|
xAxis: { type: "category", data: categories, ...axisCommon(theme), splitLine: { show: false } },
|
|
167
|
-
yAxis: { type: "value", ...axisCommon(theme) },
|
|
172
|
+
yAxis: { type: "value", ...axisCommon(theme, valueFormatter) },
|
|
168
173
|
series: series.map((s, i) => ({
|
|
169
174
|
type: "bar",
|
|
170
175
|
name: s.name,
|
|
@@ -184,11 +189,12 @@ export function rmBarVerticalOption(categories, series, theme, palette, decal =
|
|
|
184
189
|
}))
|
|
185
190
|
};
|
|
186
191
|
}
|
|
187
|
-
export function rmBarHorizontalOption(labels, values, theme, palette, decal = false, formatter) {
|
|
192
|
+
export function rmBarHorizontalOption(labels, values, theme, palette, decal = false, formatter, valueFormatter) {
|
|
188
193
|
return {
|
|
189
194
|
...rmBaseOption(theme, decal),
|
|
195
|
+
tooltip: { ...rmBaseOption(theme, decal).tooltip, ...rmTooltipValue(valueFormatter) },
|
|
190
196
|
grid: { left: 140, right: 60, top: 16, bottom: 24, containLabel: true },
|
|
191
|
-
xAxis: { type: "value", ...axisCommon(theme) },
|
|
197
|
+
xAxis: { type: "value", ...axisCommon(theme, valueFormatter) },
|
|
192
198
|
yAxis: { type: "category", data: labels, ...axisCommon(theme), splitLine: { show: false } },
|
|
193
199
|
series: [{
|
|
194
200
|
type: "bar",
|
|
@@ -203,7 +209,9 @@ export function rmBarHorizontalOption(labels, values, theme, palette, decal = fa
|
|
|
203
209
|
fontSize: 11,
|
|
204
210
|
color: theme.mutedColor,
|
|
205
211
|
fontFamily: FONT,
|
|
206
|
-
|
|
212
|
+
// L'etiquette est toujours posee ici : sans formateur d'etiquette, elle
|
|
213
|
+
// suit au moins celui des valeurs plutot que le nombre brut.
|
|
214
|
+
formatter: formatter ? (p) => formatter(p.value, p.dataIndex) : valueFormatter ? (p) => valueFormatter(p.value) : void 0
|
|
207
215
|
}
|
|
208
216
|
}]
|
|
209
217
|
};
|
|
@@ -220,7 +228,8 @@ export function rmLineOption(categories, series, theme, palette, options = {}) {
|
|
|
220
228
|
hideValueAxis = false,
|
|
221
229
|
legendPosition = "bottom",
|
|
222
230
|
startAtZero = false,
|
|
223
|
-
valueFormatter
|
|
231
|
+
valueFormatter,
|
|
232
|
+
tooltipFormatter
|
|
224
233
|
} = options;
|
|
225
234
|
const labelled = valueLabels ?? series.length <= RM_LINE_LABEL_MAX_SERIES;
|
|
226
235
|
const AREA_MAX_SERIES = 10;
|
|
@@ -228,7 +237,7 @@ export function rmLineOption(categories, series, theme, palette, options = {}) {
|
|
|
228
237
|
const dual = series.some((s) => s.axis === 1);
|
|
229
238
|
const bottomLegend = legendPosition === "bottom";
|
|
230
239
|
const format = (value) => valueFormatter ? valueFormatter(value) : String(value);
|
|
231
|
-
const tooltipFormat = (value) => valueFormatter ? rmNumber(value) : String(value);
|
|
240
|
+
const tooltipFormat = (value) => tooltipFormatter ? tooltipFormatter(value) : valueFormatter ? rmNumber(value) : String(value);
|
|
232
241
|
const values = series.flatMap((s) => s.data).filter((v) => typeof v === "number");
|
|
233
242
|
const floorAtZero = startAtZero && values.length > 0 && Math.min(...values) >= 0;
|
|
234
243
|
const base = rmBaseOption(theme, decal);
|
|
@@ -241,7 +250,7 @@ export function rmLineOption(categories, series, theme, palette, options = {}) {
|
|
|
241
250
|
tooltip: {
|
|
242
251
|
...base.tooltip,
|
|
243
252
|
trigger: rmTooltipTrigger(series.length),
|
|
244
|
-
...valueFormatter ? { valueFormatter: (value) => typeof value === "number" ? tooltipFormat(value) : "" } : {}
|
|
253
|
+
...valueFormatter || tooltipFormatter ? { valueFormatter: (value) => typeof value === "number" ? tooltipFormat(value) : "" } : {}
|
|
245
254
|
},
|
|
246
255
|
// Legende obligatoire en double axe : sans elle, rien ne dit quelle courbe
|
|
247
256
|
// se lit sur quel axe.
|