@tekkare/romulus 0.1.154 → 0.1.156
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/AppHeader.vue +6 -0
- package/dist/runtime/components/BarChart.vue +15 -4
- package/dist/runtime/components/DropdownSelect.vue +22 -3
- package/dist/runtime/components/PageHeader.vue +2 -0
- package/dist/runtime/utils/chart.d.ts +20 -2
- package/dist/runtime/utils/chart.js +13 -3
- package/package.json +1 -1
package/dist/module.json
CHANGED
|
@@ -68,6 +68,12 @@ export interface RmHeaderTab {
|
|
|
68
68
|
* paquet de lignes.
|
|
69
69
|
*/
|
|
70
70
|
count?: number | string
|
|
71
|
+
/**
|
|
72
|
+
* Phrase d'aide, montree au survol et annoncee par le titre accessible :
|
|
73
|
+
* ce que l'onglet contient quand son libelle ne suffit pas (« Diagnostics
|
|
74
|
+
* enregistres lors du sejour »). Absente, l'onglet n'en porte pas.
|
|
75
|
+
*/
|
|
76
|
+
hint?: string
|
|
71
77
|
}
|
|
72
78
|
|
|
73
79
|
withDefaults(defineProps<{
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<script setup lang="ts">
|
|
7
7
|
import { computed } from 'vue'
|
|
8
8
|
import { useChartTheme } from '../composables/useChartTheme'
|
|
9
|
-
import { rmBarHorizontalOption, rmBarVerticalOption, type RmSeriesInput, RM_CHART_HEIGHTS } from '../utils/chart'
|
|
9
|
+
import { rmBarHorizontalOption, rmBarVerticalOption, type RmBarLabelFormatter, type RmSeriesInput, RM_CHART_HEIGHTS } from '../utils/chart'
|
|
10
10
|
|
|
11
11
|
const props = withDefaults(defineProps<{
|
|
12
12
|
/** Categories de l'axe : annees, libelles d'indicateur. */
|
|
@@ -15,8 +15,12 @@ const props = withDefaults(defineProps<{
|
|
|
15
15
|
horizontal?: boolean
|
|
16
16
|
height?: keyof typeof RM_CHART_HEIGHTS | number
|
|
17
17
|
description?: string
|
|
18
|
-
/**
|
|
19
|
-
|
|
18
|
+
/**
|
|
19
|
+
* Etiquette de chaque barre : en bout de barre a l'horizontale, au-dessus a
|
|
20
|
+
* la verticale. Sans elle, la valeur se lit sur l'axe et dans l'infobulle,
|
|
21
|
+
* ce qui suffit des que les barres sont nombreuses.
|
|
22
|
+
*/
|
|
23
|
+
labelFormatter?: RmBarLabelFormatter
|
|
20
24
|
}>(), {
|
|
21
25
|
horizontal: false,
|
|
22
26
|
height: 'standard',
|
|
@@ -36,7 +40,14 @@ const option = computed(() =>
|
|
|
36
40
|
decal.value,
|
|
37
41
|
props.labelFormatter,
|
|
38
42
|
)
|
|
39
|
-
: rmBarVerticalOption(
|
|
43
|
+
: rmBarVerticalOption(
|
|
44
|
+
props.categories,
|
|
45
|
+
props.series,
|
|
46
|
+
theme.value,
|
|
47
|
+
palette.value.cat,
|
|
48
|
+
decal.value,
|
|
49
|
+
props.labelFormatter,
|
|
50
|
+
),
|
|
40
51
|
)
|
|
41
52
|
</script>
|
|
42
53
|
|
|
@@ -55,6 +55,13 @@ const props = withDefaults(defineProps<{
|
|
|
55
55
|
filterSearch?: boolean
|
|
56
56
|
/** Le panneau se ferme des qu'une valeur est prise. */
|
|
57
57
|
closeOnClick?: boolean
|
|
58
|
+
/**
|
|
59
|
+
* Options montrees mais non selectionnables. Elles restent dans la liste a
|
|
60
|
+
* dessein : une mesure absente d'un jeu (un montant sur un perimetre qui
|
|
61
|
+
* n'en porte pas) se lit mieux grisee que disparue, sinon le lecteur croit
|
|
62
|
+
* l'avoir mal cherchee.
|
|
63
|
+
*/
|
|
64
|
+
disabledOptions?: string[]
|
|
58
65
|
lang?: 'fr' | 'en'
|
|
59
66
|
}>(), {
|
|
60
67
|
search: true,
|
|
@@ -66,6 +73,7 @@ const props = withDefaults(defineProps<{
|
|
|
66
73
|
searchPlaceholder: undefined,
|
|
67
74
|
filterSearch: true,
|
|
68
75
|
closeOnClick: true,
|
|
76
|
+
disabledOptions: () => [],
|
|
69
77
|
lang: 'fr',
|
|
70
78
|
})
|
|
71
79
|
|
|
@@ -91,6 +99,11 @@ const activeIndex = ref(-1)
|
|
|
91
99
|
const rootRef = ref<HTMLElement>()
|
|
92
100
|
const searchRef = ref<HTMLInputElement>()
|
|
93
101
|
|
|
102
|
+
/** Cette option est-elle montree sans etre prenable ? */
|
|
103
|
+
function isDisabled(option: string): boolean {
|
|
104
|
+
return props.disabledOptions.includes(option)
|
|
105
|
+
}
|
|
106
|
+
|
|
94
107
|
const visibleOptions = computed(() => {
|
|
95
108
|
const needle = searchTerm.value.trim().toLowerCase()
|
|
96
109
|
if (!needle || !props.filterSearch) return props.options
|
|
@@ -165,6 +178,7 @@ async function toggle() {
|
|
|
165
178
|
}
|
|
166
179
|
|
|
167
180
|
function pick(option: string) {
|
|
181
|
+
if (isDisabled(option)) return
|
|
168
182
|
selected.value = option
|
|
169
183
|
emit('change', option)
|
|
170
184
|
if (props.closeOnClick) close()
|
|
@@ -256,9 +270,14 @@ onUnmounted(() => {
|
|
|
256
270
|
:key="option"
|
|
257
271
|
role="option"
|
|
258
272
|
class="rm-dsel__option"
|
|
259
|
-
:class="{
|
|
273
|
+
:class="{
|
|
274
|
+
'is-selected': option === selected,
|
|
275
|
+
'is-active': index === activeIndex && !isDisabled(option),
|
|
276
|
+
'is-disabled': isDisabled(option),
|
|
277
|
+
}"
|
|
260
278
|
:aria-selected="option === selected"
|
|
261
|
-
|
|
279
|
+
:aria-disabled="isDisabled(option) || undefined"
|
|
280
|
+
@click="isDisabled(option) ? undefined : pick(option)"
|
|
262
281
|
@mousemove="activeIndex = index"
|
|
263
282
|
>
|
|
264
283
|
<component
|
|
@@ -274,5 +293,5 @@ onUnmounted(() => {
|
|
|
274
293
|
</template>
|
|
275
294
|
|
|
276
295
|
<style scoped>
|
|
277
|
-
.rm-dsel{align-items:stretch;display:flex;flex-direction:column;gap:var(--space-4);position:relative;width:196px}.rm-dsel__label{color:var(--text-secondary);font-size:var(--font-12,12px);line-height:14px}.rm-dsel__field{align-items:center;background:var(--bg-surface);border:1.5px solid var(--border-default);border-radius:var(--radius-md,8px);box-sizing:border-box;color:var(--text-primary);cursor:pointer;display:flex;font-family:inherit;font-size:var(--font-14,14px);font-weight:700;gap:var(--space-4);line-height:16px;padding:var(--space-12);text-align:left;width:100%}.rm-dsel__field:hover:not(.is-disabled){border-color:rgba(var(--brand-rgb),.3)}.rm-dsel__field.is-open{border-color:var(--color-primary)}.rm-dsel__field.is-disabled{background:var(--bg-surface-2);color:var(--text-muted);cursor:not-allowed}.rm-dsel__field:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.rm-dsel__value-slot{display:block;flex:1;min-width:0}.rm-dsel__value{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rm-dsel__value.is-empty{color:var(--text-muted);font-style:italic;font-weight:400}.rm-dsel__field :deep(svg){color:var(--text-secondary);flex-shrink:0}.rm-dsel__panel{background:var(--bg-surface);border:1.5px solid var(--border-default);border-radius:var(--radius-lg,12px);box-shadow:var(--r-shadow-lg,0 8px 24px rgba(0,0,0,.12));box-sizing:border-box;display:flex;flex-direction:column;left:0;margin-top:8px;max-height:500px;max-width:420px;min-width:max(230px,100%);padding:var(--space-16);position:absolute;top:100%;z-index:12}.rm-dsel__panel--up{bottom:100%;margin-bottom:8px;margin-top:0;top:auto}.rm-dsel__search{align-items:center;background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-md,8px);display:flex;gap:var(--space-8);padding:var(--space-8) var(--space-12)}.rm-dsel__search :deep(svg){color:var(--text-muted);flex-shrink:0}.rm-dsel__search-input{background:none;border:none;color:var(--text-primary);font-family:inherit;font-size:var(--font-14,14px);width:100%}.rm-dsel__search-input::-moz-placeholder{color:var(--text-muted);font-size:var(--font-12,12px)}.rm-dsel__search-input::placeholder{color:var(--text-muted);font-size:var(--font-12,12px)}.rm-dsel__search-input:focus-visible{outline:none}.rm-dsel__loading{display:flex;flex-direction:column;gap:var(--space-10);padding-top:var(--space-8)}.rm-dsel__sr{height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;clip:rect(0,0,0,0);border:0;white-space:nowrap}.rm-dsel__state{color:var(--text-secondary);font-size:var(--font-14,14px);font-style:italic;padding-top:var(--space-16);text-align:center}.rm-dsel__list{display:flex;flex-direction:column;list-style:none;margin:0;min-height:10px;overflow-y:auto;padding:0}.rm-dsel__list:not(:only-child){margin-top:16px}.rm-dsel__option{align-items:center;border-radius:var(--radius-sm,4px);cursor:pointer;display:flex;font-size:var(--font-14,14px);gap:var(--space-8);line-height:160%;margin:4px 0;min-height:24px;padding:var(--space-2) var(--space-4)}.rm-dsel__option :deep(svg){color:var(--text-muted);flex-shrink:0}.rm-dsel__option.is-active{background:rgba(var(--brand-rgb),.05)}.rm-dsel__option.is-selected{font-weight:700}.rm-dsel__option.is-active :deep(svg),.rm-dsel__option.is-selected :deep(svg){color:var(--color-primary)}
|
|
296
|
+
.rm-dsel{align-items:stretch;display:flex;flex-direction:column;gap:var(--space-4);position:relative;width:196px}.rm-dsel__label{color:var(--text-secondary);font-size:var(--font-12,12px);line-height:14px}.rm-dsel__field{align-items:center;background:var(--bg-surface);border:1.5px solid var(--border-default);border-radius:var(--radius-md,8px);box-sizing:border-box;color:var(--text-primary);cursor:pointer;display:flex;font-family:inherit;font-size:var(--font-14,14px);font-weight:700;gap:var(--space-4);line-height:16px;padding:var(--space-12);text-align:left;width:100%}.rm-dsel__field:hover:not(.is-disabled){border-color:rgba(var(--brand-rgb),.3)}.rm-dsel__field.is-open{border-color:var(--color-primary)}.rm-dsel__field.is-disabled{background:var(--bg-surface-2);color:var(--text-muted);cursor:not-allowed}.rm-dsel__field:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.rm-dsel__value-slot{display:block;flex:1;min-width:0}.rm-dsel__value{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rm-dsel__value.is-empty{color:var(--text-muted);font-style:italic;font-weight:400}.rm-dsel__field :deep(svg){color:var(--text-secondary);flex-shrink:0}.rm-dsel__panel{background:var(--bg-surface);border:1.5px solid var(--border-default);border-radius:var(--radius-lg,12px);box-shadow:var(--r-shadow-lg,0 8px 24px rgba(0,0,0,.12));box-sizing:border-box;display:flex;flex-direction:column;left:0;margin-top:8px;max-height:500px;max-width:420px;min-width:max(230px,100%);padding:var(--space-16);position:absolute;top:100%;z-index:12}.rm-dsel__panel--up{bottom:100%;margin-bottom:8px;margin-top:0;top:auto}.rm-dsel__search{align-items:center;background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-md,8px);display:flex;gap:var(--space-8);padding:var(--space-8) var(--space-12)}.rm-dsel__search :deep(svg){color:var(--text-muted);flex-shrink:0}.rm-dsel__search-input{background:none;border:none;color:var(--text-primary);font-family:inherit;font-size:var(--font-14,14px);width:100%}.rm-dsel__search-input::-moz-placeholder{color:var(--text-muted);font-size:var(--font-12,12px)}.rm-dsel__search-input::placeholder{color:var(--text-muted);font-size:var(--font-12,12px)}.rm-dsel__search-input:focus-visible{outline:none}.rm-dsel__loading{display:flex;flex-direction:column;gap:var(--space-10);padding-top:var(--space-8)}.rm-dsel__sr{height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;clip:rect(0,0,0,0);border:0;white-space:nowrap}.rm-dsel__state{color:var(--text-secondary);font-size:var(--font-14,14px);font-style:italic;padding-top:var(--space-16);text-align:center}.rm-dsel__list{display:flex;flex-direction:column;list-style:none;margin:0;min-height:10px;overflow-y:auto;padding:0}.rm-dsel__list:not(:only-child){margin-top:16px}.rm-dsel__option.is-disabled{color:var(--text-muted);cursor:not-allowed}.rm-dsel__option{align-items:center;border-radius:var(--radius-sm,4px);cursor:pointer;display:flex;font-size:var(--font-14,14px);gap:var(--space-8);line-height:160%;margin:4px 0;min-height:24px;padding:var(--space-2) var(--space-4)}.rm-dsel__option :deep(svg){color:var(--text-muted);flex-shrink:0}.rm-dsel__option.is-active{background:rgba(var(--brand-rgb),.05)}.rm-dsel__option.is-selected{font-weight:700}.rm-dsel__option.is-active :deep(svg),.rm-dsel__option.is-selected :deep(svg){color:var(--color-primary)}
|
|
278
297
|
</style>
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
| `tabs: string[]` | `tabs: RmHeaderTab[]` | `{ key, label, active }` |
|
|
15
15
|
| `index_menu` (a partir de 1) | `active` porte par l'onglet | cote fr_drugs_app, `app/utils/headerTabs.ts` fait le pont |
|
|
16
16
|
| `@updateMenu` / `@update:Menu` | `@tab` | rend la cle, pas l'indice |
|
|
17
|
+
| `header-tooltips: string[]` | `hint` porte par l'onglet | Auriga prenait un tableau parallele a celui des onglets, ou un trou se lisait `null` : l'aide vit desormais sur l'onglet qu'elle decrit |
|
|
17
18
|
| `sur-titre dans #Title` | `eyebrow` | ATTENTION : le slot `#title` impose sa police et sa taille, un petit libelle pose dedans ressort en serif 32 px |
|
|
18
19
|
|
|
19
20
|
Il porte aussi les onglets de la page, sous le titre : c'etait la derniere
|
|
@@ -84,6 +85,7 @@ const router = useRouter()
|
|
|
84
85
|
type="button"
|
|
85
86
|
role="tab"
|
|
86
87
|
:aria-selected="tab.active ? 'true' : 'false'"
|
|
88
|
+
:title="tab.hint || undefined"
|
|
87
89
|
@click="emit('tab', tab.key)"
|
|
88
90
|
>
|
|
89
91
|
{{ tab.label }}
|
|
@@ -177,7 +177,13 @@ export interface RmSeriesInput {
|
|
|
177
177
|
axis?: 0 | 1;
|
|
178
178
|
}
|
|
179
179
|
/** Bar chart vertical, une ou plusieurs series, empilable. */
|
|
180
|
-
|
|
180
|
+
/**
|
|
181
|
+
* Etiquette d'une barre. L'index est donne parce que la valeur seule ne suffit
|
|
182
|
+
* pas toujours : une part se lit contre un total que l'appelant tient a cote
|
|
183
|
+
* (« 1 240 (18 %) »), et c'est l'index qui la retrouve.
|
|
184
|
+
*/
|
|
185
|
+
export type RmBarLabelFormatter = (value: number, index: number) => string;
|
|
186
|
+
export declare function rmBarVerticalOption(categories: (string | number)[], series: RmSeriesInput[], theme: RmChartTheme, palette: string[], decal?: boolean, formatter?: RmBarLabelFormatter): {
|
|
181
187
|
tooltip: {
|
|
182
188
|
trigger: string;
|
|
183
189
|
backgroundColor: string;
|
|
@@ -282,6 +288,17 @@ export declare function rmBarVerticalOption(categories: (string | number)[], ser
|
|
|
282
288
|
color: string;
|
|
283
289
|
borderRadius: number[];
|
|
284
290
|
};
|
|
291
|
+
label: {
|
|
292
|
+
show: boolean;
|
|
293
|
+
position: string;
|
|
294
|
+
fontSize: number;
|
|
295
|
+
color: string;
|
|
296
|
+
fontFamily: string;
|
|
297
|
+
formatter: (p: {
|
|
298
|
+
value: number;
|
|
299
|
+
dataIndex: number;
|
|
300
|
+
}) => string;
|
|
301
|
+
} | undefined;
|
|
285
302
|
}[];
|
|
286
303
|
backgroundColor: string;
|
|
287
304
|
animation: boolean;
|
|
@@ -296,7 +313,7 @@ export declare function rmBarVerticalOption(categories: (string | number)[], ser
|
|
|
296
313
|
};
|
|
297
314
|
};
|
|
298
315
|
/** Bar chart horizontal, avec valeur affichee en bout de barre. */
|
|
299
|
-
export declare function rmBarHorizontalOption(labels: string[], values: (number | null)[], theme: RmChartTheme, palette: string[], decal?: boolean, formatter?:
|
|
316
|
+
export declare function rmBarHorizontalOption(labels: string[], values: (number | null)[], theme: RmChartTheme, palette: string[], decal?: boolean, formatter?: RmBarLabelFormatter): {
|
|
300
317
|
grid: {
|
|
301
318
|
left: number;
|
|
302
319
|
right: number;
|
|
@@ -356,6 +373,7 @@ export declare function rmBarHorizontalOption(labels: string[], values: (number
|
|
|
356
373
|
fontFamily: string;
|
|
357
374
|
formatter: ((p: {
|
|
358
375
|
value: number;
|
|
376
|
+
dataIndex: number;
|
|
359
377
|
}) => string) | undefined;
|
|
360
378
|
};
|
|
361
379
|
}[];
|
|
@@ -140,7 +140,7 @@ const axisCommon = (theme) => ({
|
|
|
140
140
|
axisLine: { lineStyle: { color: theme.axisLine } },
|
|
141
141
|
splitLine: { lineStyle: { color: theme.splitLine } }
|
|
142
142
|
});
|
|
143
|
-
export function rmBarVerticalOption(categories, series, theme, palette, decal = false) {
|
|
143
|
+
export function rmBarVerticalOption(categories, series, theme, palette, decal = false, formatter) {
|
|
144
144
|
return {
|
|
145
145
|
...rmBaseOption(theme, decal),
|
|
146
146
|
tooltip: { ...rmBaseOption(theme, decal).tooltip, trigger: rmTooltipTrigger(series.length) },
|
|
@@ -155,7 +155,17 @@ export function rmBarVerticalOption(categories, series, theme, palette, decal =
|
|
|
155
155
|
name: s.name,
|
|
156
156
|
stack: s.stack,
|
|
157
157
|
data: s.data,
|
|
158
|
-
itemStyle: { color: s.color ?? rmSeriesColor(palette, i), borderRadius: [3, 3, 0, 0] }
|
|
158
|
+
itemStyle: { color: s.color ?? rmSeriesColor(palette, i), borderRadius: [3, 3, 0, 0] },
|
|
159
|
+
// L'etiquette ne se pose que si l'appelant la demande : sur une serie
|
|
160
|
+
// longue elle se chevaucherait, et l'axe dit deja la valeur.
|
|
161
|
+
label: formatter ? {
|
|
162
|
+
show: true,
|
|
163
|
+
position: "top",
|
|
164
|
+
fontSize: 11,
|
|
165
|
+
color: theme.mutedColor,
|
|
166
|
+
fontFamily: FONT,
|
|
167
|
+
formatter: (p) => formatter(p.value, p.dataIndex)
|
|
168
|
+
} : void 0
|
|
159
169
|
}))
|
|
160
170
|
};
|
|
161
171
|
}
|
|
@@ -178,7 +188,7 @@ export function rmBarHorizontalOption(labels, values, theme, palette, decal = fa
|
|
|
178
188
|
fontSize: 11,
|
|
179
189
|
color: theme.mutedColor,
|
|
180
190
|
fontFamily: FONT,
|
|
181
|
-
formatter: formatter ? (p) => formatter(p.value) : void 0
|
|
191
|
+
formatter: formatter ? (p) => formatter(p.value, p.dataIndex) : void 0
|
|
182
192
|
}
|
|
183
193
|
}]
|
|
184
194
|
};
|