@tekkare/romulus 0.1.161 → 0.1.163

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
@@ -4,7 +4,7 @@
4
4
  "compatibility": {
5
5
  "nuxt": ">=3.16.0"
6
6
  },
7
- "version": "0.1.160",
7
+ "version": "0.1.162",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "0.8.4",
10
10
  "unbuild": "2.0.0"
@@ -30,7 +30,10 @@ import { useRmCardActions } from '../composables/useRmCardActions'
30
30
  const props = withDefaults(defineProps<{
31
31
  /** Langue du menu. Le reste de la carte garde la sienne. */
32
32
  lang?: 'fr' | 'en'
33
- /** Lien copie par « Copier le lien direct ». A defaut, l'URL courante. */
33
+ /**
34
+ * Lien copie par « Copier le lien de la page ». A defaut, le permalien du
35
+ * cadre (`provideRmExportDefaults`), puis l'URL courante.
36
+ */
34
37
  link?: string
35
38
  /** Nom du fichier et de l'onglet. A defaut, le titre lu dans la carte. */
36
39
  name?: string
@@ -83,7 +86,7 @@ const WORDS = {
83
86
  csv: 'Données CSV',
84
87
  xlsx: 'Excel (XLSX)',
85
88
  shareSection: 'Partager',
86
- copyLink: 'Copier le lien direct',
89
+ copyLink: 'Copier le lien de la page',
87
90
  fullscreen: 'Plein écran',
88
91
  working: 'Préparation…',
89
92
  copied: 'Lien copié',
@@ -97,7 +100,7 @@ const WORDS = {
97
100
  csv: 'CSV data',
98
101
  xlsx: 'Excel (XLSX)',
99
102
  shareSection: 'Share',
100
- copyLink: 'Copy direct link',
103
+ copyLink: 'Copy page link',
101
104
  fullscreen: 'Fullscreen',
102
105
  working: 'Preparing…',
103
106
  copied: 'Link copied',
@@ -29,6 +29,11 @@ const props = withDefaults(defineProps<{
29
29
  description: undefined,
30
30
  })
31
31
 
32
+ const emit = defineEmits<{
33
+ /** La legende a masque ou remontre une serie : l'etat de chaque entree. */
34
+ legendSelectChanged: [selected: Record<string, boolean>]
35
+ }>()
36
+
32
37
  /**
33
38
  * ECharts arrive en import dynamique : le premier graphe d'une session attend
34
39
  * le telechargement du morceau, plusieurs centaines de kilooctets, pendant
@@ -44,7 +49,7 @@ let echartsModule: typeof import('echarts') | null = null
44
49
 
45
50
  const el = ref<HTMLElement | null>(null)
46
51
  const pending = ref(echartsModule === null)
47
- const chart = shallowRef<{ setOption: (o: unknown, n?: boolean) => void, resize: () => void, dispose: () => void } | null>(null)
52
+ const chart = shallowRef<{ setOption: (o: unknown, n?: boolean) => void, resize: () => void, dispose: () => void, on: (event: string, handler: (params: any) => void) => void } | null>(null)
48
53
  let observer: ResizeObserver | null = null
49
54
 
50
55
  const heightPx = () =>
@@ -57,6 +62,9 @@ onMounted(async () => {
57
62
  if (!el.value) return
58
63
  chart.value = echartsModule.init(el.value, undefined, { renderer: 'svg' })
59
64
  chart.value.setOption(props.option)
65
+ chart.value.on('legendselectchanged', (params: { selected?: Record<string, boolean> }) => {
66
+ emit('legendSelectChanged', params?.selected ?? {})
67
+ })
60
68
  pending.value = false
61
69
 
62
70
  // ResizeObserver plutot qu'un listener global sur window : un graphe dans un
@@ -293,5 +293,5 @@ onUnmounted(() => {
293
293
  </template>
294
294
 
295
295
  <style scoped>
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)}
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:min(480px,calc(100vw - 32px));min-width:max(230px,100%);padding:var(--space-16);position:absolute;top:100%;width:-moz-max-content;width:max-content;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:flex-start;border-radius:var(--radius-sm,4px);cursor:pointer;display:flex;flex-shrink:0;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;margin-top:3px}.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)}
297
297
  </style>
@@ -376,6 +376,7 @@ function toggle(list: string[], key: string) {
376
376
  }
377
377
 
378
378
  function applyTemplate(template: RmExportTemplate | null) {
379
+ if (template?.disabled) return
379
380
  if (!template) {
380
381
  templateKey.value = null
381
382
  mode.value = 'wizard'
@@ -496,13 +497,17 @@ const recentDate = (at: string | Date) =>
496
497
  v-for="template in templates"
497
498
  :key="template.key"
498
499
  class="rm-export__template"
500
+ :class="{ 'rm-export__template--off': template.disabled }"
499
501
  type="button"
502
+ :disabled="template.disabled"
503
+ :aria-disabled="template.disabled || undefined"
504
+ :title="template.disabled ? template.disabledHint : undefined"
500
505
  @click="applyTemplate(template)"
501
506
  >
502
507
  <RmIcon :name="template.icon" :size="26" weight="fill" :color="template.color" />
503
508
  <span class="rm-export__template-body">
504
509
  <span class="rm-export__template-name">{{ template.name }}</span>
505
- <span class="rm-export__template-meta">{{ template.meta }}</span>
510
+ <span class="rm-export__template-meta">{{ template.disabled ? (template.disabledHint || template.meta) : template.meta }}</span>
506
511
  </span>
507
512
  </button>
508
513
  <button
@@ -838,5 +843,5 @@ const recentDate = (at: string | Date) =>
838
843
  </template>
839
844
 
840
845
  <style scoped>
841
- .rm-export{display:flex;flex-direction:column}.rm-export__tabs{border-bottom:1px solid var(--border-default);display:flex;margin-bottom:var(--space-16)}.rm-export__tab{align-items:center;background:none;border:none;border-bottom:3px solid transparent;color:var(--text-muted);cursor:pointer;display:inline-flex;font-family:inherit;font-size:var(--font-14);font-weight:600;gap:var(--space-6);padding:var(--space-12) var(--space-16)}.rm-export__tab--active{border-bottom-color:var(--color-primary);color:var(--color-secondary)}.rm-export__tab:disabled{cursor:not-allowed;opacity:.5}.rm-export__desc,.rm-export__lead{color:var(--text-secondary);font-size:12.5px;line-height:1.55;margin:0 0 var(--space-16)}.rm-export__eyebrow{align-items:center;color:var(--text-muted);display:flex;font-size:10.5px;font-weight:700;gap:var(--space-6);letter-spacing:.1em;margin:0 0 var(--space-8);text-transform:uppercase}.rm-export__hint{color:var(--text-muted);display:block;font-size:11.5px;line-height:1.45;margin:var(--space-8) 0 0}.rm-export__notice{color:var(--color-success)}.rm-export__error,.rm-export__notice{font-size:var(--font-12);margin:var(--space-8) 0 0}.rm-export__error{color:var(--color-danger)}.rm-export__templates{display:grid;gap:var(--space-8)}.rm-export__template{align-items:center;background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-xl);cursor:pointer;display:flex;font-family:inherit;gap:var(--space-12);padding:var(--space-12) var(--space-16);text-align:left;transition:border-color var(--duration-fast),background var(--duration-fast),transform var(--duration-fast)}.rm-export__template:hover{background:var(--bg-hover);border-color:var(--color-secondary);transform:translateY(-1px)}.rm-export__template--custom{background:transparent;border-style:dashed}.rm-export__template-body{display:flex;flex-direction:column;min-width:0}.rm-export__template-name{color:var(--text-primary);font-size:13.5px;font-weight:700;line-height:1.2}.rm-export__template-meta{color:var(--text-muted);font-size:var(--font-11);line-height:1.35;margin-top:3px}.rm-export__wizard{background:var(--bg-surface-2);border:1px solid var(--border-default);border-radius:var(--radius-2xl);padding:var(--space-16) var(--space-20)}.rm-export__wizard-head{align-items:center;border-bottom:1px solid var(--border-soft);display:flex;gap:var(--space-12);margin-bottom:var(--space-16);padding-bottom:var(--space-12)}.rm-export__back{align-items:center;background:none;border:none;color:var(--color-secondary);cursor:pointer;display:inline-flex;font-family:inherit;font-size:var(--font-12);font-weight:600;gap:var(--space-4);padding:0}.rm-export__back:hover{text-decoration:underline;text-underline-offset:3px}.rm-export__stepper{align-items:center;display:flex;gap:var(--space-4);margin-bottom:var(--space-20)}.rm-export__step{background:none;border:none;border-radius:var(--radius-pill);cursor:pointer;font-family:inherit;gap:var(--space-6);padding:var(--space-4) var(--space-8)}.rm-export__step,.rm-export__step-num{align-items:center;display:inline-flex}.rm-export__step-num{background:var(--bg-surface-3);border:1.5px solid var(--border-default);border-radius:50%;font-weight:700;height:22px;justify-content:center;transition:background var(--duration-fast),color var(--duration-fast),border-color var(--duration-fast);width:22px}.rm-export__step-label,.rm-export__step-num{color:var(--text-muted);font-size:var(--font-12)}.rm-export__step-label{font-weight:600}.rm-export__step:hover .rm-export__step-label{color:var(--text-primary)}.rm-export__step--active .rm-export__step-num{background:var(--color-primary);border-color:var(--color-primary);box-shadow:var(--shadow-focus);color:#fff}.rm-export__step--active .rm-export__step-label{color:var(--color-secondary)}.rm-export__step--done .rm-export__step-num{background:var(--color-secondary);border-color:var(--color-secondary);color:#fff}.rm-export__step--done .rm-export__step-label{color:var(--text-secondary)}.rm-export__step-divider{background:var(--border-default);border-radius:var(--radius-pill);flex:1;height:1.5px}.rm-export__panel{animation:rm-export-in var(--duration-base) var(--ease-out)}@keyframes rm-export-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.rm-export__formats{display:grid;gap:var(--space-8)}.rm-export__format{align-items:flex-start;background:var(--bg-surface);border:1.5px solid var(--border-default);border-radius:var(--radius-xl);cursor:pointer;display:flex;gap:var(--space-12);padding:var(--space-12) var(--space-16);transition:border-color var(--duration-fast),background var(--duration-fast),transform var(--duration-fast)}.rm-export__format:hover{border-color:var(--color-secondary);transform:translateY(-1px)}.rm-export__format--active{background:var(--bg-hover);border-color:var(--color-primary);box-shadow:var(--shadow-focus)}.rm-export__format--active .rm-export__format-name{color:var(--color-primary)}.rm-export__format--off{cursor:not-allowed;opacity:.55}.rm-export__format--off:hover{border-color:var(--border-default);transform:none}.rm-export__format input[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:var(--bg-surface);border:1.5px solid var(--border-default);border-radius:50%;cursor:inherit;flex-shrink:0;height:18px;margin:1px 0 0;position:relative;width:18px}.rm-export__format input[type=radio]:checked{border-color:var(--color-primary)}.rm-export__format input[type=radio]:checked:after{background:var(--color-primary);border-radius:50%;content:"";inset:3px;position:absolute}.rm-export__format-text{display:flex;flex-direction:column;min-width:0}.rm-export__format-name{color:var(--text-primary);font-size:var(--font-14);font-weight:700;line-height:1.2}.rm-export__format-desc{color:var(--text-muted);font-size:11.5px;line-height:1.45;margin-top:3px}.rm-export__format-meta{border-top:1px solid var(--border-soft);color:var(--text-muted);font-size:var(--font-10);font-weight:700;letter-spacing:.08em;margin-top:var(--space-8);padding-top:var(--space-8);text-transform:uppercase}.rm-export__row{margin-bottom:var(--space-20)}.rm-export__row:last-child{margin-bottom:0}.rm-export__label{color:var(--text-secondary);display:block;font-size:var(--font-11);font-weight:700;letter-spacing:.06em;margin-bottom:var(--space-8);text-transform:uppercase}.rm-export__sub{margin-top:var(--space-12)}.rm-export__input{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-md);color:var(--text-primary);font-family:inherit;font-size:var(--font-13);padding:var(--space-8) var(--space-12);width:100%}.rm-export__input:focus{border-color:var(--color-primary);box-shadow:var(--shadow-focus);outline:none}.rm-export__checks{display:grid;gap:var(--space-6)}.rm-export__check{align-items:center;color:var(--text-primary);cursor:pointer;display:flex;font-size:12.5px;gap:var(--space-8)}.rm-export__check--off{cursor:not-allowed;opacity:.5}.rm-export__check input[type=checkbox]{accent-color:var(--color-primary);cursor:inherit;height:15px;width:15px}.rm-export__chips{display:flex;flex-wrap:wrap;gap:var(--space-6)}.rm-export__chip{align-items:center;border:1px solid var(--border-default);border-radius:var(--radius-pill);cursor:pointer;display:inline-flex;font-family:inherit;font-size:11.5px;font-weight:600;gap:var(--space-4);padding:3px var(--space-8)}.rm-export__chip--on{background:var(--bg-hover);border-color:var(--color-primary);color:var(--color-primary)}.rm-export__chip--off{background:var(--bg-surface);color:var(--text-muted)}.rm-export__chip--off:hover{border-color:var(--color-secondary);color:var(--color-secondary)}.rm-export__recap{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-xl);margin-top:var(--space-16);padding:var(--space-16)}.rm-export__recap-row{align-items:flex-start;border-bottom:1px solid var(--border-soft);color:var(--color-secondary);display:flex;gap:var(--space-12);padding:var(--space-8) 0}.rm-export__recap-row:last-child{border-bottom:none}.rm-export__recap-row>div{flex:1;min-width:0}.rm-export__recap-k{color:var(--text-muted);font-size:10.5px;font-weight:700;letter-spacing:.08em;margin-bottom:2px;text-transform:uppercase}.rm-export__recap-v{color:var(--text-primary);font-size:var(--font-13);font-weight:600;word-break:break-word}.rm-export__footer{align-items:center;border-top:1px solid var(--border-default);display:flex;gap:var(--space-8);margin-top:var(--space-20);padding-top:var(--space-16)}.rm-export__progress{color:var(--text-muted);flex:1;font-size:var(--font-12);text-align:center}.rm-export__progress b{color:var(--text-primary)}.rm-export__history{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-xl);padding:var(--space-16)}.rm-export__history-row{align-items:center;color:var(--color-primary);display:flex;gap:var(--space-8);padding:var(--space-6) 0}.rm-export__history-body{display:flex;flex:1;flex-direction:column;min-width:0}.rm-export__history-name{color:var(--text-primary);font-size:12.5px;font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rm-export__history-meta{color:var(--text-muted);font-size:var(--font-11)}.rm-export__tab-count{background:var(--bg-surface-3);border-radius:var(--radius-pill);color:var(--text-secondary);font-size:10.5px;padding:1px var(--space-6)}
846
+ .rm-export{display:flex;flex-direction:column}.rm-export__tabs{border-bottom:1px solid var(--border-default);display:flex;margin-bottom:var(--space-16)}.rm-export__tab{align-items:center;background:none;border:none;border-bottom:3px solid transparent;color:var(--text-muted);cursor:pointer;display:inline-flex;font-family:inherit;font-size:var(--font-14);font-weight:600;gap:var(--space-6);padding:var(--space-12) var(--space-16)}.rm-export__tab--active{border-bottom-color:var(--color-primary);color:var(--color-secondary)}.rm-export__tab:disabled{cursor:not-allowed;opacity:.5}.rm-export__desc,.rm-export__lead{color:var(--text-secondary);font-size:12.5px;line-height:1.55;margin:0 0 var(--space-16)}.rm-export__eyebrow{align-items:center;color:var(--text-muted);display:flex;font-size:10.5px;font-weight:700;gap:var(--space-6);letter-spacing:.1em;margin:0 0 var(--space-8);text-transform:uppercase}.rm-export__hint{color:var(--text-muted);display:block;font-size:11.5px;line-height:1.45;margin:var(--space-8) 0 0}.rm-export__notice{color:var(--color-success)}.rm-export__error,.rm-export__notice{font-size:var(--font-12);margin:var(--space-8) 0 0}.rm-export__error{color:var(--color-danger)}.rm-export__templates{display:grid;gap:var(--space-8)}.rm-export__template{align-items:center;background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-xl);cursor:pointer;display:flex;font-family:inherit;gap:var(--space-12);padding:var(--space-12) var(--space-16);text-align:left;transition:border-color var(--duration-fast),background var(--duration-fast),transform var(--duration-fast)}.rm-export__template:hover{background:var(--bg-hover);border-color:var(--color-secondary);transform:translateY(-1px)}.rm-export__template--custom{background:transparent;border-style:dashed}.rm-export__template--off{cursor:not-allowed;opacity:.55}.rm-export__template-body{display:flex;flex-direction:column;min-width:0}.rm-export__template-name{color:var(--text-primary);font-size:13.5px;font-weight:700;line-height:1.2}.rm-export__template-meta{color:var(--text-muted);font-size:var(--font-11);line-height:1.35;margin-top:3px}.rm-export__wizard{background:var(--bg-surface-2);border:1px solid var(--border-default);border-radius:var(--radius-2xl);padding:var(--space-16) var(--space-20)}.rm-export__wizard-head{align-items:center;border-bottom:1px solid var(--border-soft);display:flex;gap:var(--space-12);margin-bottom:var(--space-16);padding-bottom:var(--space-12)}.rm-export__back{align-items:center;background:none;border:none;color:var(--color-secondary);cursor:pointer;display:inline-flex;font-family:inherit;font-size:var(--font-12);font-weight:600;gap:var(--space-4);padding:0}.rm-export__back:hover{text-decoration:underline;text-underline-offset:3px}.rm-export__stepper{align-items:center;display:flex;gap:var(--space-4);margin-bottom:var(--space-20)}.rm-export__step{background:none;border:none;border-radius:var(--radius-pill);cursor:pointer;font-family:inherit;gap:var(--space-6);padding:var(--space-4) var(--space-8)}.rm-export__step,.rm-export__step-num{align-items:center;display:inline-flex}.rm-export__step-num{background:var(--bg-surface-3);border:1.5px solid var(--border-default);border-radius:50%;font-weight:700;height:22px;justify-content:center;transition:background var(--duration-fast),color var(--duration-fast),border-color var(--duration-fast);width:22px}.rm-export__step-label,.rm-export__step-num{color:var(--text-muted);font-size:var(--font-12)}.rm-export__step-label{font-weight:600}.rm-export__step:hover .rm-export__step-label{color:var(--text-primary)}.rm-export__step--active .rm-export__step-num{background:var(--color-primary);border-color:var(--color-primary);box-shadow:var(--shadow-focus);color:#fff}.rm-export__step--active .rm-export__step-label{color:var(--color-secondary)}.rm-export__step--done .rm-export__step-num{background:var(--color-secondary);border-color:var(--color-secondary);color:#fff}.rm-export__step--done .rm-export__step-label{color:var(--text-secondary)}.rm-export__step-divider{background:var(--border-default);border-radius:var(--radius-pill);flex:1;height:1.5px}.rm-export__panel{animation:rm-export-in var(--duration-base) var(--ease-out)}@keyframes rm-export-in{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}.rm-export__formats{display:grid;gap:var(--space-8)}.rm-export__format{align-items:flex-start;background:var(--bg-surface);border:1.5px solid var(--border-default);border-radius:var(--radius-xl);cursor:pointer;display:flex;gap:var(--space-12);padding:var(--space-12) var(--space-16);transition:border-color var(--duration-fast),background var(--duration-fast),transform var(--duration-fast)}.rm-export__format:hover{border-color:var(--color-secondary);transform:translateY(-1px)}.rm-export__format--active{background:var(--bg-hover);border-color:var(--color-primary);box-shadow:var(--shadow-focus)}.rm-export__format--active .rm-export__format-name{color:var(--color-primary)}.rm-export__format--off{cursor:not-allowed;opacity:.55}.rm-export__format--off:hover{border-color:var(--border-default);transform:none}.rm-export__format input[type=radio]{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:var(--bg-surface);border:1.5px solid var(--border-default);border-radius:50%;cursor:inherit;flex-shrink:0;height:18px;margin:1px 0 0;position:relative;width:18px}.rm-export__format input[type=radio]:checked{border-color:var(--color-primary)}.rm-export__format input[type=radio]:checked:after{background:var(--color-primary);border-radius:50%;content:"";inset:3px;position:absolute}.rm-export__format-text{display:flex;flex-direction:column;min-width:0}.rm-export__format-name{color:var(--text-primary);font-size:var(--font-14);font-weight:700;line-height:1.2}.rm-export__format-desc{color:var(--text-muted);font-size:11.5px;line-height:1.45;margin-top:3px}.rm-export__format-meta{border-top:1px solid var(--border-soft);color:var(--text-muted);font-size:var(--font-10);font-weight:700;letter-spacing:.08em;margin-top:var(--space-8);padding-top:var(--space-8);text-transform:uppercase}.rm-export__row{margin-bottom:var(--space-20)}.rm-export__row:last-child{margin-bottom:0}.rm-export__label{color:var(--text-secondary);display:block;font-size:var(--font-11);font-weight:700;letter-spacing:.06em;margin-bottom:var(--space-8);text-transform:uppercase}.rm-export__sub{margin-top:var(--space-12)}.rm-export__input{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-md);color:var(--text-primary);font-family:inherit;font-size:var(--font-13);padding:var(--space-8) var(--space-12);width:100%}.rm-export__input:focus{border-color:var(--color-primary);box-shadow:var(--shadow-focus);outline:none}.rm-export__checks{display:grid;gap:var(--space-6)}.rm-export__check{align-items:center;color:var(--text-primary);cursor:pointer;display:flex;font-size:12.5px;gap:var(--space-8)}.rm-export__check--off{cursor:not-allowed;opacity:.5}.rm-export__check input[type=checkbox]{accent-color:var(--color-primary);cursor:inherit;height:15px;width:15px}.rm-export__chips{display:flex;flex-wrap:wrap;gap:var(--space-6)}.rm-export__chip{align-items:center;border:1px solid var(--border-default);border-radius:var(--radius-pill);cursor:pointer;display:inline-flex;font-family:inherit;font-size:11.5px;font-weight:600;gap:var(--space-4);padding:3px var(--space-8)}.rm-export__chip--on{background:var(--bg-hover);border-color:var(--color-primary);color:var(--color-primary)}.rm-export__chip--off{background:var(--bg-surface);color:var(--text-muted)}.rm-export__chip--off:hover{border-color:var(--color-secondary);color:var(--color-secondary)}.rm-export__recap{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-xl);margin-top:var(--space-16);padding:var(--space-16)}.rm-export__recap-row{align-items:flex-start;border-bottom:1px solid var(--border-soft);color:var(--color-secondary);display:flex;gap:var(--space-12);padding:var(--space-8) 0}.rm-export__recap-row:last-child{border-bottom:none}.rm-export__recap-row>div{flex:1;min-width:0}.rm-export__recap-k{color:var(--text-muted);font-size:10.5px;font-weight:700;letter-spacing:.08em;margin-bottom:2px;text-transform:uppercase}.rm-export__recap-v{color:var(--text-primary);font-size:var(--font-13);font-weight:600;word-break:break-word}.rm-export__footer{align-items:center;border-top:1px solid var(--border-default);display:flex;gap:var(--space-8);margin-top:var(--space-20);padding-top:var(--space-16)}.rm-export__progress{color:var(--text-muted);flex:1;font-size:var(--font-12);text-align:center}.rm-export__progress b{color:var(--text-primary)}.rm-export__history{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-xl);padding:var(--space-16)}.rm-export__history-row{align-items:center;color:var(--color-primary);display:flex;gap:var(--space-8);padding:var(--space-6) 0}.rm-export__history-body{display:flex;flex:1;flex-direction:column;min-width:0}.rm-export__history-name{color:var(--text-primary);font-size:12.5px;font-weight:600;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rm-export__history-meta{color:var(--text-muted);font-size:var(--font-11)}.rm-export__tab-count{background:var(--bg-surface-3);border-radius:var(--radius-pill);color:var(--text-secondary);font-size:10.5px;padding:1px var(--space-6)}
842
847
  </style>
@@ -3,9 +3,9 @@
3
3
  prix et de decisions discretes.
4
4
  -->
5
5
  <script setup lang="ts">
6
- import { computed } from 'vue'
6
+ import { computed, ref } from 'vue'
7
7
  import { useChartTheme } from '../composables/useChartTheme'
8
- import { rmLineOption, type RmSeriesInput, RM_CHART_HEIGHTS } from '../utils/chart'
8
+ import { rmLineOption, type RmSeriesInput, RM_CHART_HEIGHTS, RM_LINE_LABEL_MAX_SERIES } from '../utils/chart'
9
9
  import { rmCompact, rmNumber } from '../utils/format'
10
10
 
11
11
  const props = withDefaults(defineProps<{
@@ -27,9 +27,11 @@ const props = withDefaults(defineProps<{
27
27
  axisLabels?: [string, string]
28
28
  /**
29
29
  * Etiquette chaque point de sa valeur, en pastille de la couleur de la
30
- * serie. Laisse libre, elle se pose jusqu'a cinq courbes et se retire
31
- * au-dela, ou les pastilles se chevauchent. `true` ou `false` tranche a la
32
- * place de la regle.
30
+ * serie. Laisse libre, elle se pose tant que les courbes VISIBLES ne
31
+ * depassent pas le seuil (`RM_LINE_LABEL_MAX_SERIES`) et se retire au-dela,
32
+ * ou les pastilles se chevauchent : masquer des courbes depuis la legende
33
+ * fait donc apparaitre les chiffres de celles qui restent. `true` ou `false`
34
+ * tranche a la place de la regle.
33
35
  */
34
36
  valueLabels?: boolean
35
37
  /**
@@ -74,22 +76,43 @@ const formatter = computed(() => {
74
76
  return undefined
75
77
  })
76
78
 
77
- const option = computed(() =>
78
- rmLineOption(props.categories, props.series, theme.value, palette.value.cat, {
79
+ /**
80
+ * Ce que la legende a masque. L'option est reconstruite a chaque changement
81
+ * (pour poser ou retirer les etiquettes) et remplacee sans fusion, ce qui
82
+ * remettrait toutes les courbes visibles : la selection est donc recopiee
83
+ * dans l'option, pour que le graphe reste tel que le lecteur l'a regle.
84
+ */
85
+ const legendSelected = ref<Record<string, boolean>>({})
86
+ const hiddenCount = computed(
87
+ () => Object.values(legendSelected.value).filter(shown => shown === false).length,
88
+ )
89
+ const visibleCount = computed(() => Math.max(0, props.series.length - hiddenCount.value))
90
+
91
+ const option = computed(() => {
92
+ const built = rmLineOption(props.categories, props.series, theme.value, palette.value.cat, {
79
93
  area: props.area,
80
94
  step: props.step,
81
95
  smooth: props.smooth,
82
96
  decal: decal.value,
83
97
  axisLabels: props.axisLabels,
84
- valueLabels: props.valueLabels,
98
+ valueLabels: props.valueLabels ?? visibleCount.value <= RM_LINE_LABEL_MAX_SERIES,
85
99
  hideValueAxis: props.hideValueAxis,
86
100
  legendPosition: props.legendPosition,
87
101
  startAtZero: props.startAtZero,
88
102
  valueFormatter: formatter.value,
89
- }),
90
- )
103
+ }) as Record<string, any>
104
+ if (built.legend && Object.keys(legendSelected.value).length) {
105
+ built.legend = { ...built.legend, selected: { ...legendSelected.value } }
106
+ }
107
+ return built
108
+ })
91
109
  </script>
92
110
 
93
111
  <template>
94
- <RmChart :option="option" :height="height" :description="description" />
112
+ <RmChart
113
+ :option="option"
114
+ :height="height"
115
+ :description="description"
116
+ @legend-select-changed="legendSelected = $event"
117
+ />
95
118
  </template>
@@ -113,14 +113,26 @@ const sectionOf = (path?: string) => {
113
113
  return collapsibles.value[0]?.key ?? null
114
114
  }
115
115
 
116
- const openSection = ref<string | null>(sectionOf(props.activePath))
116
+ /**
117
+ * Groupes deployes. Plusieurs a la fois : l'accordeon (un seul ouvert)
118
+ * refermait le groupe qu'on lisait des qu'on en ouvrait un autre, et il
119
+ * fallait cliquer partout pour voir l'ensemble de la navigation. Le groupe de
120
+ * la page courante s'ouvre a l'arrivee et le reste, les autres se plient et se
121
+ * deplient a la demande.
122
+ */
123
+ const openSections = ref<Set<string>>(new Set(sectionOf(props.activePath) ? [sectionOf(props.activePath)!] : []))
117
124
  // La cible se deduit des sections autant que du chemin : les deux arrivent
118
125
  // ensemble a la navigation, et les droits d'acces peuvent recomposer la liste
119
126
  // en cours de route.
120
127
  watch(() => sectionOf(props.activePath), (key) => {
121
- if (key && key !== openSection.value) openSection.value = key
128
+ if (key && !openSections.value.has(key)) openSections.value.add(key)
122
129
  })
123
130
 
131
+ function toggleSection(key: string) {
132
+ if (openSections.value.has(key)) openSections.value.delete(key)
133
+ else openSections.value.add(key)
134
+ }
135
+
124
136
  const isCollapsible = (s: RmNavSection) => !!s.label && s.collapsible !== false
125
137
 
126
138
  /**
@@ -131,12 +143,11 @@ const isCollapsible = (s: RmNavSection) => !!s.label && s.collapsible !== false
131
143
  * fermer les autres groupes, dont les entrees quittaient le DOM : le rail ne
132
144
  * montrait que le groupe de la page courante, quelques filets nus en dessous,
133
145
  * et aucun moyen d'atteindre le reste de la navigation ni de le deplier. Tous
134
- * les groupes sont donc ouverts en mode replie ce que l'accordeon evite est
135
- * un long defilement de groupes libelles, or une entree repliee ne fait
146
+ * les groupes sont donc ouverts en mode replie : une entree repliee ne fait
136
147
  * qu'une pastille de 26px.
137
148
  */
138
149
  const isOpen = (s: RmNavSection) =>
139
- !isCollapsible(s) || props.collapsed || openSection.value === s.key
150
+ !isCollapsible(s) || props.collapsed || openSections.value.has(s.key)
140
151
  const isActive = (item: RmNavItem) => item.active ?? (!!item.to && item.to === props.activePath)
141
152
 
142
153
  /**
@@ -220,7 +231,7 @@ watch(() => props.collapsed, hideTip)
220
231
  class="rm-sb__label"
221
232
  type="button"
222
233
  :aria-expanded="isOpen(section)"
223
- @click="openSection = openSection === section.key ? null : section.key"
234
+ @click="toggleSection(section.key)"
224
235
  >
225
236
  <span class="rm-sb__label-text">{{ section.label }}</span>
226
237
  <svg class="rm-sb__chev" viewBox="0 0 12 12" fill="none" stroke="currentColor" stroke-width="1.5">
@@ -1,5 +1,12 @@
1
1
  <!--
2
- Ligne de provenance : « Source : HAS - ... - Mise a jour : 3 septembre 2026 ».
2
+ Ligne de provenance : « Source : HAS · Vérifié le 3 septembre 2026 ».
3
+
4
+ Deux usages. Avec `source` (et `verified`), la ligne ecrit elle-meme la
5
+ phrase, dans les memes mots et le meme ordre que le pied de RmChartCard :
6
+ une page qui melange cartes de graphiques et cartes de tableaux disait
7
+ « Vérifié le » sur les unes et « Dernière MAJ » sur les autres pour la meme
8
+ date, et le lecteur y voyait deux notions. Sans `source`, le slot passe tel
9
+ quel, pour les provenances qui ne sont pas un jeu date (un referentiel).
3
10
 
4
11
  Un bouton discret : cliquer ouvre le tiroir Sources de l'app (emit `click`).
5
12
  Par defaut en gris, la provenance se lit apres le contenu ; `tone="primary"`
@@ -7,22 +14,59 @@
7
14
  tableau) et n'a rien a concurrencer.
8
15
  -->
9
16
  <script setup lang="ts">
10
- withDefaults(
17
+ import { computed } from 'vue'
18
+ import { rmDate } from '../utils/format'
19
+
20
+ const props = withDefaults(
11
21
  defineProps<{
12
22
  tone?: 'muted' | 'primary'
23
+ /** Organisme et jeu de donnees, tels que le referentiel les nomme. */
24
+ source?: string
25
+ /** Date de verification du jeu : Date, timestamp, ISO ou texte deja formate. */
26
+ verified?: Date | string | number
27
+ lang?: 'fr' | 'en'
13
28
  }>(),
14
- { tone: 'muted' },
29
+ { tone: 'muted', source: undefined, verified: undefined, lang: 'fr' },
15
30
  )
16
31
 
32
+ /** Memes mots que le pied de RmChartCard. */
33
+ const WORDS = {
34
+ fr: { source: 'Source :', verified: 'Vérifié le' },
35
+ en: { source: 'Source:', verified: 'Verified on' },
36
+ } as const
37
+ const t = computed(() => WORDS[props.lang])
38
+
39
+ /**
40
+ * Une chaine deja formatee (« 31 août 2026 ») passe telle quelle : la reparser
41
+ * inventerait un jour que la source ne donne pas. Seule une date technique
42
+ * (Date, timestamp, ISO) est mise au format long. Meme regle que RmChartCard.
43
+ */
44
+ const ISO_DATE = /^\d{4}-\d{2}-\d{2}/
45
+ const verifiedText = computed(() => {
46
+ const raw = props.verified
47
+ if (raw === undefined || raw === null || raw === '') return ''
48
+ if (typeof raw === 'string' && !ISO_DATE.test(raw)) return raw
49
+ const parsed = new Date(raw)
50
+ if (Number.isNaN(parsed.getTime())) return String(raw)
51
+ return props.lang === 'en'
52
+ ? parsed.toLocaleDateString('en-US', { day: 'numeric', month: 'long', year: 'numeric' })
53
+ : rmDate(parsed)
54
+ })
55
+
17
56
  const emit = defineEmits<{ click: [event: MouseEvent] }>()
18
57
  </script>
19
58
 
20
59
  <template>
21
60
  <button type="button" class="rm-source" :class="`rm-source--${tone}`" @click="emit('click', $event)">
22
- <slot />
61
+ <template v-if="source">
62
+ <span class="rm-source__src">{{ t.source }} <b>{{ source }}</b></span>
63
+ <span v-if="verifiedText" class="rm-source__dot" aria-hidden="true">·</span>
64
+ <span v-if="verifiedText" class="rm-source__verified">{{ t.verified }} {{ verifiedText }}</span>
65
+ </template>
66
+ <slot v-else />
23
67
  </button>
24
68
  </template>
25
69
 
26
70
  <style scoped>
27
- .rm-source{align-items:center;background:none;border:none;cursor:pointer;display:inline-flex;flex-wrap:wrap;font-family:var(--font-sans);font-size:var(--font-12);font-weight:var(--weight-normal);gap:var(--space-4);line-height:14px;padding:0;text-align:left;transition:color var(--duration-fast) linear}.rm-source--muted{color:var(--text-muted)}.rm-source--muted:hover{color:var(--text-primary)}.rm-source--primary{color:var(--color-primary)}.rm-source--primary:hover{color:var(--color-primary-hover)}
71
+ .rm-source{align-items:center;background:none;border:none;cursor:pointer;display:inline-flex;flex-wrap:wrap;font-family:var(--font-sans);font-size:var(--font-12);font-weight:var(--weight-normal);gap:var(--space-4);line-height:14px;padding:0;text-align:left;transition:color var(--duration-fast) linear}.rm-source--muted{color:var(--text-muted)}.rm-source__src b{font-weight:var(--weight-medium)}.rm-source__dot{opacity:.6}.rm-source--muted:hover{color:var(--text-primary)}.rm-source--primary{color:var(--color-primary)}.rm-source--primary:hover{color:var(--color-primary-hover)}
28
72
  </style>
@@ -22,7 +22,7 @@ export interface RmCardActionContext {
22
22
  lang?: 'fr' | 'en';
23
23
  /** Nom du fichier et de l'onglet. A defaut, le titre lu dans la carte. */
24
24
  name?: string;
25
- /** Lien copie par « Copier le lien direct ». A defaut, l'URL courante. */
25
+ /** Lien copie par « Copier le lien de la page ». A defaut, le permalien du cadre, puis l'URL courante. */
26
26
  link?: string;
27
27
  /**
28
28
  * Ce que le pied de la carte dit de sa source. Ne sert que si ni la page
@@ -52,7 +52,10 @@ export function useRmCardActions() {
52
52
  ...defaults,
53
53
  title,
54
54
  charts: rmCardCharts(card).map((el) => ({ title, el })),
55
- permalink: absolute(context.link),
55
+ // Le lien de la carte, sinon celui du cadre : le permalien de la page
56
+ // porte la vue et les filtres, la ou l'URL courante ne dit rien de ce
57
+ // qui est affiche.
58
+ permalink: absolute(context.link) ?? defaults.permalink,
56
59
  ...provided,
57
60
  sheets,
58
61
  sources
@@ -401,6 +401,13 @@ export declare function rmBarHorizontalOption(labels: string[], values: (number
401
401
  };
402
402
  };
403
403
  /** Line ou area chart. `step` produit la marche d'escalier des series de prix. */
404
+ /**
405
+ * Nombre de courbes jusqu'auquel les valeurs s'ecrivent sur les points. Exporte
406
+ * pour que RmLineChart applique la meme regle aux courbes VISIBLES, une fois
407
+ * que la legende en a masque : masquer des courbes doit faire apparaitre les
408
+ * chiffres des restantes.
409
+ */
410
+ export declare const RM_LINE_LABEL_MAX_SERIES = 10;
404
411
  export declare function rmLineOption(categories: (string | number)[], series: RmSeriesInput[], theme: RmChartTheme, palette: string[], options?: {
405
412
  /**
406
413
  * Remplissage degrade sous la courbe. Non precise : automatique jusqu'a
@@ -440,6 +447,7 @@ export declare function rmLineOption(categories: (string | number)[], series: Rm
440
447
  /** Formate les valeurs, dans les etiquettes comme dans l'infobulle. */
441
448
  valueFormatter?: (value: number) => string;
442
449
  }): {
450
+ animation: boolean;
443
451
  tooltip: {
444
452
  valueFormatter?: ((value: unknown) => string) | undefined;
445
453
  trigger: string;
@@ -682,7 +690,6 @@ export declare function rmLineOption(categories: (string | number)[], series: Rm
682
690
  } | undefined;
683
691
  }[];
684
692
  backgroundColor: string;
685
- animation: boolean;
686
693
  aria: {
687
694
  enabled: boolean;
688
695
  decal: {
@@ -193,6 +193,7 @@ export function rmBarHorizontalOption(labels, values, theme, palette, decal = fa
193
193
  }]
194
194
  };
195
195
  }
196
+ export const RM_LINE_LABEL_MAX_SERIES = 10;
196
197
  export function rmLineOption(categories, series, theme, palette, options = {}) {
197
198
  const {
198
199
  area,
@@ -206,9 +207,8 @@ export function rmLineOption(categories, series, theme, palette, options = {}) {
206
207
  startAtZero = false,
207
208
  valueFormatter
208
209
  } = options;
209
- const LABEL_MAX_SERIES = 5;
210
- const labelled = valueLabels ?? series.length <= LABEL_MAX_SERIES;
211
- const AREA_MAX_SERIES = 5;
210
+ const labelled = valueLabels ?? series.length <= RM_LINE_LABEL_MAX_SERIES;
211
+ const AREA_MAX_SERIES = 10;
212
212
  const filled = area ?? series.length <= AREA_MAX_SERIES;
213
213
  const dual = series.some((s) => s.axis === 1);
214
214
  const bottomLegend = legendPosition === "bottom";
@@ -218,6 +218,10 @@ export function rmLineOption(categories, series, theme, palette, options = {}) {
218
218
  const base = rmBaseOption(theme, decal);
219
219
  return {
220
220
  ...base,
221
+ // Pas de trace progressif : le temps de l'animation, une courbe n'est
222
+ // dessinee qu'entre ses premiers points et le reste n'est que des ronds,
223
+ // ce qui se lit comme une donnee manquante. Les points arrivent en place.
224
+ animation: false,
221
225
  tooltip: {
222
226
  ...base.tooltip,
223
227
  trigger: rmTooltipTrigger(series.length),
@@ -193,6 +193,14 @@ export interface RmExportTemplate {
193
193
  icon: string;
194
194
  color?: string;
195
195
  config: Partial<RmExportConfig>;
196
+ /**
197
+ * Le modele reste affiche mais ne se lance pas : son format n'a rien a
198
+ * exporter sur cet ecran (pas de tableau, pas de graphique), ou pas encore.
199
+ * Cache, il disparaissait et reapparaissait au gre des chargements, et le
200
+ * lecteur croyait l'export en panne. `disabledHint` dit pourquoi.
201
+ */
202
+ disabled?: boolean;
203
+ disabledHint?: string;
196
204
  }
197
205
  /**
198
206
  * Ligne de l'onglet « Mes exports ».
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tekkare/romulus",
3
- "version": "0.1.161",
3
+ "version": "0.1.163",
4
4
  "description": "Romulus Design System - Nuxt module by Tekkare",
5
5
  "license": "MIT",
6
6
  "type": "module",