@tekkare/romulus 0.1.59 → 0.1.61
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
CHANGED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
RmTagRow - une rangee d'etiquettes sur une seule ligne, le reste compte.
|
|
3
|
+
|
|
4
|
+
Reprend `arg-tags-row` d'Auriga : les etiquettes qui tiennent s'affichent, les
|
|
5
|
+
autres deviennent « +N » avec la liste complete en bulle. Une carte de
|
|
6
|
+
resultat porte parfois quinze laboratoires ; les laisser passer a la ligne
|
|
7
|
+
ferait grandir la carte au point de repousser ce qui suit.
|
|
8
|
+
|
|
9
|
+
Le tri se fait sur la position reelle des etiquettes dans le DOM : on les
|
|
10
|
+
pose toutes, puis on garde celles qui sont restees sur la premiere ligne.
|
|
11
|
+
Auriga mesurait le texte au canvas avec « 12px Figtree » ecrit en dur, ce qui
|
|
12
|
+
se decalait des que la police n'etait pas chargee ou pas celle-la.
|
|
13
|
+
-->
|
|
14
|
+
<script setup lang="ts">
|
|
15
|
+
import { computed, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
|
16
|
+
import type { RmTagVariant } from './Tag.vue'
|
|
17
|
+
|
|
18
|
+
const props = withDefaults(defineProps<{
|
|
19
|
+
tags: string[]
|
|
20
|
+
variant?: RmTagVariant
|
|
21
|
+
/** Cote ou sort la bulle du compteur. */
|
|
22
|
+
tooltipDir?: 'top' | 'right' | 'bottom' | 'left'
|
|
23
|
+
}>(), {
|
|
24
|
+
variant: 'gray',
|
|
25
|
+
tooltipDir: 'bottom',
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
const rowRef = ref<HTMLElement>()
|
|
29
|
+
const visibleCount = ref(props.tags.length)
|
|
30
|
+
|
|
31
|
+
const shown = computed(() => props.tags.slice(0, visibleCount.value))
|
|
32
|
+
const hidden = computed(() => props.tags.slice(visibleCount.value))
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Compte les etiquettes restees sur la premiere ligne. La rangee est mesuree
|
|
36
|
+
* en affichage complet : sans cette remise a zero, un redimensionnement qui
|
|
37
|
+
* elargit la carte ne reafficherait jamais ce qui avait ete masque.
|
|
38
|
+
*/
|
|
39
|
+
async function measure() {
|
|
40
|
+
visibleCount.value = props.tags.length
|
|
41
|
+
await nextTick()
|
|
42
|
+
const row = rowRef.value
|
|
43
|
+
if (!row) return
|
|
44
|
+
const items = [...row.querySelectorAll<HTMLElement>('[data-rm-tag]')]
|
|
45
|
+
if (items.length === 0) return
|
|
46
|
+
|
|
47
|
+
const firstTop = items[0].offsetTop
|
|
48
|
+
// Au moins une etiquette reste, meme trop large : « +15 » tout seul ne dit
|
|
49
|
+
// plus de quoi la carte parle.
|
|
50
|
+
let count = 1
|
|
51
|
+
for (let i = 1; i < items.length; i++) {
|
|
52
|
+
if (items[i].offsetTop > firstTop) break
|
|
53
|
+
count++
|
|
54
|
+
}
|
|
55
|
+
visibleCount.value = count
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
let observer: ResizeObserver | undefined
|
|
59
|
+
|
|
60
|
+
onMounted(() => {
|
|
61
|
+
measure()
|
|
62
|
+
if (typeof ResizeObserver !== 'undefined' && rowRef.value) {
|
|
63
|
+
observer = new ResizeObserver(() => measure())
|
|
64
|
+
observer.observe(rowRef.value)
|
|
65
|
+
}
|
|
66
|
+
})
|
|
67
|
+
onBeforeUnmount(() => observer?.disconnect())
|
|
68
|
+
watch(() => props.tags, measure, { deep: true })
|
|
69
|
+
</script>
|
|
70
|
+
|
|
71
|
+
<template>
|
|
72
|
+
<div class="rm-tag-row">
|
|
73
|
+
<div ref="rowRef" class="rm-tag-row__items">
|
|
74
|
+
<RmTag v-for="tag in shown" :key="tag" data-rm-tag :variant="variant">{{ tag }}</RmTag>
|
|
75
|
+
</div>
|
|
76
|
+
<RmTooltip v-if="hidden.length > 0" :text="hidden.join('\n')" :dir="tooltipDir" full>
|
|
77
|
+
<span class="rm-tag-row__more">+{{ hidden.length }}</span>
|
|
78
|
+
</RmTooltip>
|
|
79
|
+
</div>
|
|
80
|
+
</template>
|
|
81
|
+
|
|
82
|
+
<style scoped>
|
|
83
|
+
.rm-tag-row{align-items:center;display:flex;gap:8px;width:100%}.rm-tag-row__items{display:flex;flex:1;flex-wrap:wrap;gap:8px;max-height:24px;min-width:0;overflow:hidden}.rm-tag-row__more{color:var(--text-secondary);font-size:var(--font-12,12px);white-space:nowrap}
|
|
84
|
+
</style>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ref } from "vue";
|
|
1
|
+
import { ref, toRaw } from "vue";
|
|
2
2
|
const view = ref(null);
|
|
3
3
|
export function useRmFilterBarView() {
|
|
4
4
|
let mine = null;
|
|
@@ -9,7 +9,7 @@ export function useRmFilterBarView() {
|
|
|
9
9
|
view.value = next;
|
|
10
10
|
},
|
|
11
11
|
clear: () => {
|
|
12
|
-
if (view.value === mine) view.value = null;
|
|
12
|
+
if (view.value && toRaw(view.value) === mine) view.value = null;
|
|
13
13
|
mine = null;
|
|
14
14
|
}
|
|
15
15
|
};
|
|
@@ -94,6 +94,48 @@ export declare function rmBaseOption(theme: RmChartTheme, decal?: boolean): {
|
|
|
94
94
|
borderWidth: number;
|
|
95
95
|
};
|
|
96
96
|
};
|
|
97
|
+
export declare function rmLegend(theme: RmChartTheme, count: number, position?: 'top' | 'bottom'): {
|
|
98
|
+
pageIconSize?: number | undefined;
|
|
99
|
+
pageIconColor?: string | undefined;
|
|
100
|
+
pageIconInactiveColor?: string | undefined;
|
|
101
|
+
pageTextStyle?: {
|
|
102
|
+
color: string;
|
|
103
|
+
fontSize: number;
|
|
104
|
+
fontFamily: string;
|
|
105
|
+
} | undefined;
|
|
106
|
+
type: string;
|
|
107
|
+
tooltip: {
|
|
108
|
+
show: boolean;
|
|
109
|
+
};
|
|
110
|
+
formatter: (name: string) => string;
|
|
111
|
+
textStyle: {
|
|
112
|
+
color: string;
|
|
113
|
+
fontSize: number;
|
|
114
|
+
fontFamily: string;
|
|
115
|
+
};
|
|
116
|
+
bottom: number;
|
|
117
|
+
left: string;
|
|
118
|
+
} | {
|
|
119
|
+
pageIconSize?: number | undefined;
|
|
120
|
+
pageIconColor?: string | undefined;
|
|
121
|
+
pageIconInactiveColor?: string | undefined;
|
|
122
|
+
pageTextStyle?: {
|
|
123
|
+
color: string;
|
|
124
|
+
fontSize: number;
|
|
125
|
+
fontFamily: string;
|
|
126
|
+
} | undefined;
|
|
127
|
+
type: string;
|
|
128
|
+
tooltip: {
|
|
129
|
+
show: boolean;
|
|
130
|
+
};
|
|
131
|
+
formatter: (name: string) => string;
|
|
132
|
+
textStyle: {
|
|
133
|
+
color: string;
|
|
134
|
+
fontSize: number;
|
|
135
|
+
fontFamily: string;
|
|
136
|
+
};
|
|
137
|
+
top: number;
|
|
138
|
+
};
|
|
97
139
|
/**
|
|
98
140
|
* Axe de valeurs, avec son libelle d'unite au-dessus quand il est fourni.
|
|
99
141
|
*
|
|
@@ -136,13 +178,46 @@ export interface RmSeriesInput {
|
|
|
136
178
|
/** Bar chart vertical, une ou plusieurs series, empilable. */
|
|
137
179
|
export declare function rmBarVerticalOption(categories: (string | number)[], series: RmSeriesInput[], theme: RmChartTheme, palette: string[], decal?: boolean): {
|
|
138
180
|
legend: {
|
|
181
|
+
pageIconSize?: number | undefined;
|
|
182
|
+
pageIconColor?: string | undefined;
|
|
183
|
+
pageIconInactiveColor?: string | undefined;
|
|
184
|
+
pageTextStyle?: {
|
|
185
|
+
color: string;
|
|
186
|
+
fontSize: number;
|
|
187
|
+
fontFamily: string;
|
|
188
|
+
} | undefined;
|
|
189
|
+
type: string;
|
|
190
|
+
tooltip: {
|
|
191
|
+
show: boolean;
|
|
192
|
+
};
|
|
193
|
+
formatter: (name: string) => string;
|
|
194
|
+
textStyle: {
|
|
195
|
+
color: string;
|
|
196
|
+
fontSize: number;
|
|
197
|
+
fontFamily: string;
|
|
198
|
+
};
|
|
139
199
|
bottom: number;
|
|
140
200
|
left: string;
|
|
201
|
+
} | {
|
|
202
|
+
pageIconSize?: number | undefined;
|
|
203
|
+
pageIconColor?: string | undefined;
|
|
204
|
+
pageIconInactiveColor?: string | undefined;
|
|
205
|
+
pageTextStyle?: {
|
|
206
|
+
color: string;
|
|
207
|
+
fontSize: number;
|
|
208
|
+
fontFamily: string;
|
|
209
|
+
} | undefined;
|
|
210
|
+
type: string;
|
|
211
|
+
tooltip: {
|
|
212
|
+
show: boolean;
|
|
213
|
+
};
|
|
214
|
+
formatter: (name: string) => string;
|
|
141
215
|
textStyle: {
|
|
142
216
|
color: string;
|
|
143
217
|
fontSize: number;
|
|
144
218
|
fontFamily: string;
|
|
145
219
|
};
|
|
220
|
+
top: number;
|
|
146
221
|
} | undefined;
|
|
147
222
|
grid: {
|
|
148
223
|
bottom: number;
|
|
@@ -369,6 +444,19 @@ export declare function rmLineOption(categories: (string | number)[], series: Rm
|
|
|
369
444
|
borderWidth: number;
|
|
370
445
|
};
|
|
371
446
|
legend: {
|
|
447
|
+
pageIconSize?: number | undefined;
|
|
448
|
+
pageIconColor?: string | undefined;
|
|
449
|
+
pageIconInactiveColor?: string | undefined;
|
|
450
|
+
pageTextStyle?: {
|
|
451
|
+
color: string;
|
|
452
|
+
fontSize: number;
|
|
453
|
+
fontFamily: string;
|
|
454
|
+
} | undefined;
|
|
455
|
+
type: string;
|
|
456
|
+
tooltip: {
|
|
457
|
+
show: boolean;
|
|
458
|
+
};
|
|
459
|
+
formatter: (name: string) => string;
|
|
372
460
|
textStyle: {
|
|
373
461
|
color: string;
|
|
374
462
|
fontSize: number;
|
|
@@ -377,6 +465,19 @@ export declare function rmLineOption(categories: (string | number)[], series: Rm
|
|
|
377
465
|
bottom: number;
|
|
378
466
|
left: string;
|
|
379
467
|
} | {
|
|
468
|
+
pageIconSize?: number | undefined;
|
|
469
|
+
pageIconColor?: string | undefined;
|
|
470
|
+
pageIconInactiveColor?: string | undefined;
|
|
471
|
+
pageTextStyle?: {
|
|
472
|
+
color: string;
|
|
473
|
+
fontSize: number;
|
|
474
|
+
fontFamily: string;
|
|
475
|
+
} | undefined;
|
|
476
|
+
type: string;
|
|
477
|
+
tooltip: {
|
|
478
|
+
show: boolean;
|
|
479
|
+
};
|
|
480
|
+
formatter: (name: string) => string;
|
|
380
481
|
textStyle: {
|
|
381
482
|
color: string;
|
|
382
483
|
fontSize: number;
|
|
@@ -601,12 +702,46 @@ export declare function rmDonutOption(data: {
|
|
|
601
702
|
borderWidth: number;
|
|
602
703
|
};
|
|
603
704
|
legend: {
|
|
705
|
+
pageIconSize?: number | undefined;
|
|
706
|
+
pageIconColor?: string | undefined;
|
|
707
|
+
pageIconInactiveColor?: string | undefined;
|
|
708
|
+
pageTextStyle?: {
|
|
709
|
+
color: string;
|
|
710
|
+
fontSize: number;
|
|
711
|
+
fontFamily: string;
|
|
712
|
+
} | undefined;
|
|
713
|
+
type: string;
|
|
714
|
+
tooltip: {
|
|
715
|
+
show: boolean;
|
|
716
|
+
};
|
|
717
|
+
formatter: (name: string) => string;
|
|
718
|
+
textStyle: {
|
|
719
|
+
color: string;
|
|
720
|
+
fontSize: number;
|
|
721
|
+
fontFamily: string;
|
|
722
|
+
};
|
|
604
723
|
bottom: number;
|
|
724
|
+
left: string;
|
|
725
|
+
} | {
|
|
726
|
+
pageIconSize?: number | undefined;
|
|
727
|
+
pageIconColor?: string | undefined;
|
|
728
|
+
pageIconInactiveColor?: string | undefined;
|
|
729
|
+
pageTextStyle?: {
|
|
730
|
+
color: string;
|
|
731
|
+
fontSize: number;
|
|
732
|
+
fontFamily: string;
|
|
733
|
+
} | undefined;
|
|
734
|
+
type: string;
|
|
735
|
+
tooltip: {
|
|
736
|
+
show: boolean;
|
|
737
|
+
};
|
|
738
|
+
formatter: (name: string) => string;
|
|
605
739
|
textStyle: {
|
|
606
740
|
color: string;
|
|
607
741
|
fontSize: number;
|
|
608
742
|
fontFamily: string;
|
|
609
743
|
};
|
|
744
|
+
top: number;
|
|
610
745
|
};
|
|
611
746
|
series: {
|
|
612
747
|
type: string;
|
|
@@ -90,6 +90,27 @@ export function rmBaseOption(theme, decal = false) {
|
|
|
90
90
|
}
|
|
91
91
|
};
|
|
92
92
|
}
|
|
93
|
+
const LEGEND_MAX_INLINE = 6;
|
|
94
|
+
const LEGEND_NAME_MAX = 38;
|
|
95
|
+
const LEGEND_NAME_TAIL = 12;
|
|
96
|
+
const rmLegendName = (name) => name.length > LEGEND_NAME_MAX ? `${name.slice(0, LEGEND_NAME_MAX - LEGEND_NAME_TAIL - 1)}\u2026${name.slice(-LEGEND_NAME_TAIL)}` : name;
|
|
97
|
+
export function rmLegend(theme, count, position = "bottom") {
|
|
98
|
+
const scroll = count > LEGEND_MAX_INLINE;
|
|
99
|
+
return {
|
|
100
|
+
...position === "bottom" ? { bottom: 0, left: "center" } : { top: 0 },
|
|
101
|
+
type: scroll ? "scroll" : "plain",
|
|
102
|
+
// Le nom complet, non ecrete, au survol de l'entree.
|
|
103
|
+
tooltip: { show: true },
|
|
104
|
+
formatter: rmLegendName,
|
|
105
|
+
textStyle: { color: theme.mutedColor, fontSize: 11, fontFamily: FONT },
|
|
106
|
+
...scroll ? {
|
|
107
|
+
pageIconSize: 10,
|
|
108
|
+
pageIconColor: theme.mutedColor,
|
|
109
|
+
pageIconInactiveColor: theme.axisLine,
|
|
110
|
+
pageTextStyle: { color: theme.mutedColor, fontSize: 11, fontFamily: FONT }
|
|
111
|
+
} : {}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
93
114
|
export function rmSeriesColor(palette, index) {
|
|
94
115
|
const base = palette[index % palette.length];
|
|
95
116
|
const cycle = Math.floor(index / palette.length);
|
|
@@ -120,7 +141,7 @@ const axisCommon = (theme) => ({
|
|
|
120
141
|
export function rmBarVerticalOption(categories, series, theme, palette, decal = false) {
|
|
121
142
|
return {
|
|
122
143
|
...rmBaseOption(theme, decal),
|
|
123
|
-
legend: series.length > 1 ?
|
|
144
|
+
legend: series.length > 1 ? rmLegend(theme, series.length) : void 0,
|
|
124
145
|
// La legende passee sous le graphe prend sa place dans la gouttiere basse,
|
|
125
146
|
// sinon elle recouvre les libelles de l'axe des abscisses.
|
|
126
147
|
grid: { ...rmBaseOption(theme, decal).grid, bottom: series.length > 1 ? 56 : 36 },
|
|
@@ -190,10 +211,7 @@ export function rmLineOption(categories, series, theme, palette, options = {}) {
|
|
|
190
211
|
} : base.tooltip,
|
|
191
212
|
// Legende obligatoire en double axe : sans elle, rien ne dit quelle courbe
|
|
192
213
|
// se lit sur quel axe.
|
|
193
|
-
legend: series.length > 1 || dual ?
|
|
194
|
-
...bottomLegend ? { bottom: 0, left: "center" } : { top: 0 },
|
|
195
|
-
textStyle: { color: theme.mutedColor, fontSize: 11, fontFamily: FONT }
|
|
196
|
-
} : void 0,
|
|
214
|
+
legend: series.length > 1 || dual ? rmLegend(theme, series.length, legendPosition) : void 0,
|
|
197
215
|
grid: {
|
|
198
216
|
// Sans graduation a gauche, la gouttiere de 48 px ne sert plus qu'a
|
|
199
217
|
// laisser depasser la premiere pastille de valeur.
|
|
@@ -275,7 +293,7 @@ export function rmDonutOption(data, theme, palette, decal = false) {
|
|
|
275
293
|
...rmBaseOption(theme, decal),
|
|
276
294
|
grid: void 0,
|
|
277
295
|
tooltip: { ...rmBaseOption(theme, decal).tooltip, trigger: "item" },
|
|
278
|
-
legend:
|
|
296
|
+
legend: rmLegend(theme, data.length),
|
|
279
297
|
series: [{
|
|
280
298
|
type: "pie",
|
|
281
299
|
radius: ["45%", "70%"],
|