@tekkare/romulus 0.1.90 → 0.1.92

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.89",
7
+ "version": "0.1.91",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "0.8.4",
10
10
  "unbuild": "2.0.0"
@@ -13,6 +13,13 @@
13
13
  restauree au demarrage, ou a une bascule declenchee ailleurs (la bascule
14
14
  jour / nuit du rail), d'etre reprise sans rien a synchroniser.
15
15
 
16
+ La simulation du daltonisme se retire par `cvd-simulation`. C'est un outil
17
+ de test, adresse a qui fabrique les ecrans : sa phrase dit « verifier que
18
+ VOS visualisations restent lisibles ». Sur le poste de quelqu'un qui lit des
19
+ donnees, elle propose de degrader l'affichage sans rien reparer, et se
20
+ confond avec le reglage juste en dessous, qui lui aide vraiment. Les apps la
21
+ gardent donc en local et en preproduction, et la retirent en production.
22
+
16
23
  Trois reglages absents du panneau, alors que le composable les expose :
17
24
 
18
25
  - La taille du texte et la densite d'affichage, tant que le CSS ne les
@@ -31,9 +38,15 @@ const props = withDefaults(defineProps<{
31
38
  lang?: 'fr' | 'en'
32
39
  /** Chapeau du panneau. Vide, rien ne sort. */
33
40
  description?: string
41
+ /**
42
+ * Rangee « Simuler le daltonisme ». Vraie par defaut, comme dans le design
43
+ * system ; a passer a faux la ou l'app est servie a ses utilisateurs.
44
+ */
45
+ cvdSimulation?: boolean
34
46
  }>(), {
35
47
  lang: 'fr',
36
48
  description: undefined,
49
+ cvdSimulation: true,
37
50
  })
38
51
 
39
52
  const {
@@ -131,7 +144,7 @@ const motionModel = computed({
131
144
  <div class="rm-a11y">
132
145
  <p class="rm-a11y__intro">{{ description ?? T.intro }}</p>
133
146
 
134
- <div class="rm-a11y__row">
147
+ <div v-if="cvdSimulation" class="rm-a11y__row">
135
148
  <div class="rm-a11y__head">
136
149
  <span class="rm-a11y__label"><i class="ph ph-eye" />{{ T.cvd }}</span>
137
150
  </div>
@@ -50,6 +50,19 @@ export interface RmSavedView {
50
50
  id: string
51
51
  title: string
52
52
  description?: string
53
+ /**
54
+ * Pastille d'icone posee devant le titre (nom Phosphor). Les vues
55
+ * enregistrees n'en ont pas : elle distingue les vues fournies, ou toute
56
+ * liste ou l'icone dit de quoi parle la vue.
57
+ */
58
+ icon?: string
59
+ /** Couleur de la pastille. */
60
+ tone?: 'primary' | 'success' | 'warning' | 'danger' | 'info'
61
+ /**
62
+ * Libelle du bouton d'activation, quand « Activer » ne decrit pas ce qui se
63
+ * passe (« Demarrer » pour une vue fournie, qui ouvre une analyse).
64
+ */
65
+ actionLabel?: string
53
66
  /** La vue est celle qui est appliquee a l'ecran. */
54
67
  active?: boolean
55
68
  /** La vue s'applique a l'ouverture de la page. */
@@ -213,6 +226,14 @@ function onCardClick() {
213
226
  </div>
214
227
 
215
228
  <div class="rm-view__head">
229
+ <span
230
+ v-if="view.icon"
231
+ class="rm-view__icon"
232
+ :class="`rm-view__icon--${view.tone ?? 'primary'}`"
233
+ >
234
+ <RmIcon :name="view.icon" :size="18" />
235
+ </span>
236
+
216
237
  <button
217
238
  v-if="starrable"
218
239
  type="button"
@@ -252,7 +273,7 @@ function onCardClick() {
252
273
  size="sm"
253
274
  @click="emit('activate', view.id)"
254
275
  >
255
- {{ T.activate }}
276
+ {{ view.actionLabel || T.activate }}
256
277
  </RmButton>
257
278
 
258
279
  <div v-if="menu.length" class="rm-view__menu-wrap">
@@ -345,5 +366,5 @@ function onCardClick() {
345
366
  </template>
346
367
 
347
368
  <style scoped>
348
- .rm-view{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-lg);color:var(--text-primary);cursor:pointer;font-family:var(--font-sans);padding:14px 18px;transition:border-color var(--duration-fast) var(--ease-out),box-shadow var(--duration-fast) var(--ease-out),background var(--duration-fast) var(--ease-out)}.rm-view:not(.rm-view--active):hover{background:var(--bg-hover);border-color:var(--color-accent-soft)}.rm-view--active{border-color:var(--color-secondary);box-shadow:0 0 0 3px rgba(var(--brand-rgb),.08);cursor:default}.rm-view__strip{background:var(--bg-hover);border-bottom:1px solid var(--border-soft);border-radius:7px 7px 0 0;color:var(--color-secondary);font-size:var(--font-11);font-weight:var(--weight-bold);gap:var(--space-8);letter-spacing:.06em;margin:-14px -18px var(--space-12);padding:var(--space-8) var(--space-16);text-transform:uppercase}.rm-view__head,.rm-view__strip{align-items:center;display:flex}.rm-view__head{gap:10px}.rm-view__star{align-items:center;background:transparent;border:1px solid transparent;border-radius:var(--radius-md);color:var(--text-muted);cursor:pointer;display:inline-flex;flex:0 0 auto;height:28px;justify-content:center;padding:0;width:28px}.rm-view__star:hover{background:var(--bg-hover)}.rm-view__star--on,.rm-view__star:hover{color:var(--color-warning)}.rm-view__title,.rm-view__title-edit{flex:1;font-size:var(--font-16);font-weight:var(--weight-bold);min-width:0}.rm-view__title-edit{background:var(--bg-surface);border:1px solid var(--color-secondary);border-radius:var(--radius-md);color:var(--text-primary);font-family:inherit;outline:none;padding:2px var(--space-8)}.rm-view__title-edit:focus{box-shadow:0 0 0 3px rgba(var(--brand-rgb),.12)}.rm-view__actions{align-items:center;display:flex;gap:var(--space-8)}.rm-view__badge{align-items:center;background:var(--color-success-bg);border-radius:var(--radius-pill);color:var(--color-success);display:inline-flex;font-size:var(--font-10);font-weight:var(--weight-bold);gap:var(--space-4);letter-spacing:.06em;padding:3px var(--space-8);text-transform:uppercase}.rm-view__menu-wrap{position:relative}.rm-view__more{align-items:center;background:transparent;border:none;border-radius:var(--radius-md);color:var(--text-muted);cursor:pointer;display:inline-flex;height:28px;justify-content:center;padding:0;width:28px}.rm-view__more:hover{background:var(--bg-hover);color:var(--text-primary)}.rm-view__menu-shade{inset:0;position:fixed;z-index:60}.rm-view__menu{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);display:flex;flex-direction:column;min-width:200px;padding:var(--space-4);position:absolute;right:0;top:calc(100% + 6px);z-index:61}.rm-view__menu-item{align-items:center;background:transparent;border:none;border-radius:var(--radius-md);color:var(--text-primary);cursor:pointer;display:flex;font-family:inherit;font-size:var(--font-13);gap:var(--space-8);padding:var(--space-8) var(--space-12);text-align:left;width:100%}.rm-view__menu-item:hover{background:var(--bg-hover);color:var(--color-secondary)}.rm-view__menu-item--danger{color:var(--color-danger)}.rm-view__menu-item--danger:hover{background:var(--color-danger-bg);color:var(--color-danger)}.rm-view__desc{color:var(--text-secondary);font-size:var(--font-13);margin:var(--space-8) 0 var(--space-12)}.rm-view__config{background:var(--bg-surface-2);border:1px solid var(--border-soft);border-radius:var(--radius-md);display:flex;flex-direction:column;gap:var(--space-6);margin:10px 0 var(--space-12);padding:10px 14px}.rm-view__row{align-items:flex-start;display:flex;flex-wrap:wrap;font-size:var(--font-12);gap:14px}.rm-view__row-key{color:var(--text-muted);display:inline-flex;flex-shrink:0;font-size:var(--font-10);font-weight:var(--weight-semibold);letter-spacing:.04em;min-width:96px;padding-top:4px;text-transform:uppercase}.rm-view__row-key,.rm-view__row-val{align-items:center;gap:var(--space-6)}.rm-view__row-val{color:var(--text-primary);display:flex;flex:1 1 200px;flex-wrap:wrap;padding:2px 0}.rm-view__pill{align-items:center;background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-md);display:inline-flex;font-size:var(--font-12);gap:var(--space-4);padding:5px 10px}.rm-view__pill-k{color:var(--color-primary);font-weight:var(--weight-semibold)}.rm-view__pill-tip{min-width:0}.rm-view__pill-tip :deep(.rm-tooltip__bubble){max-width:320px}.rm-view__pill-v{display:-webkit-box;-webkit-box-orient:vertical;color:var(--text-primary);font-weight:var(--weight-medium);-webkit-line-clamp:3;overflow:hidden}.rm-view__foot{border-top:1px solid var(--border-soft);color:var(--text-muted);display:flex;flex-wrap:wrap;font-size:var(--font-11);gap:var(--space-16);padding-top:10px}.rm-view__foot span{align-items:center;display:inline-flex;gap:var(--space-4)}.rm-view__confirm{align-items:center;background:var(--color-danger-bg);border:1px solid var(--color-danger);border-radius:var(--radius-md);color:var(--color-danger);display:flex;flex-wrap:wrap;font-size:var(--font-13);gap:var(--space-12);margin-top:var(--space-12);padding:var(--space-8) var(--space-12)}.rm-view__confirm>span{align-items:center;display:inline-flex;flex:1 1 220px;gap:var(--space-8)}.rm-view__confirm-actions{display:flex;flex-shrink:0;gap:var(--space-8)}
369
+ .rm-view{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-lg);color:var(--text-primary);cursor:pointer;font-family:var(--font-sans);padding:14px 18px;transition:border-color var(--duration-fast) var(--ease-out),box-shadow var(--duration-fast) var(--ease-out),background var(--duration-fast) var(--ease-out)}.rm-view:not(.rm-view--active):hover{background:var(--bg-hover);border-color:var(--color-accent-soft)}.rm-view--active{border-color:var(--color-secondary);box-shadow:0 0 0 3px rgba(var(--brand-rgb),.08);cursor:default}.rm-view__strip{background:var(--bg-hover);border-bottom:1px solid var(--border-soft);border-radius:7px 7px 0 0;color:var(--color-secondary);font-size:var(--font-11);font-weight:var(--weight-bold);gap:var(--space-8);letter-spacing:.06em;margin:-14px -18px var(--space-12);padding:var(--space-8) var(--space-16);text-transform:uppercase}.rm-view__head,.rm-view__strip{align-items:center;display:flex}.rm-view__head{gap:10px}.rm-view__icon{align-items:center;border-radius:var(--radius-md);display:inline-flex;flex:0 0 auto;height:34px;justify-content:center;width:34px}.rm-view__icon--primary{background:var(--bg-hover);color:var(--color-secondary)}.rm-view__icon--success{background:var(--color-success-bg);color:var(--color-success)}.rm-view__icon--warning{background:var(--color-warning-bg);color:var(--color-warning)}.rm-view__icon--danger{background:var(--color-danger-bg);color:var(--color-danger)}.rm-view__icon--info{background:var(--color-info-bg);color:var(--color-info)}.rm-view__star{align-items:center;background:transparent;border:1px solid transparent;border-radius:var(--radius-md);color:var(--text-muted);cursor:pointer;display:inline-flex;flex:0 0 auto;height:28px;justify-content:center;padding:0;width:28px}.rm-view__star:hover{background:var(--bg-hover)}.rm-view__star--on,.rm-view__star:hover{color:var(--color-warning)}.rm-view__title,.rm-view__title-edit{flex:1;font-size:var(--font-16);font-weight:var(--weight-bold);min-width:0}.rm-view__title-edit{background:var(--bg-surface);border:1px solid var(--color-secondary);border-radius:var(--radius-md);color:var(--text-primary);font-family:inherit;outline:none;padding:2px var(--space-8)}.rm-view__title-edit:focus{box-shadow:0 0 0 3px rgba(var(--brand-rgb),.12)}.rm-view__actions{align-items:center;display:flex;gap:var(--space-8)}.rm-view__badge{align-items:center;background:var(--color-success-bg);border-radius:var(--radius-pill);color:var(--color-success);display:inline-flex;font-size:var(--font-10);font-weight:var(--weight-bold);gap:var(--space-4);letter-spacing:.06em;padding:3px var(--space-8);text-transform:uppercase}.rm-view__menu-wrap{position:relative}.rm-view__more{align-items:center;background:transparent;border:none;border-radius:var(--radius-md);color:var(--text-muted);cursor:pointer;display:inline-flex;height:28px;justify-content:center;padding:0;width:28px}.rm-view__more:hover{background:var(--bg-hover);color:var(--text-primary)}.rm-view__menu-shade{inset:0;position:fixed;z-index:60}.rm-view__menu{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-lg);box-shadow:var(--shadow-lg);display:flex;flex-direction:column;min-width:200px;padding:var(--space-4);position:absolute;right:0;top:calc(100% + 6px);z-index:61}.rm-view__menu-item{align-items:center;background:transparent;border:none;border-radius:var(--radius-md);color:var(--text-primary);cursor:pointer;display:flex;font-family:inherit;font-size:var(--font-13);gap:var(--space-8);padding:var(--space-8) var(--space-12);text-align:left;width:100%}.rm-view__menu-item:hover{background:var(--bg-hover);color:var(--color-secondary)}.rm-view__menu-item--danger{color:var(--color-danger)}.rm-view__menu-item--danger:hover{background:var(--color-danger-bg);color:var(--color-danger)}.rm-view__desc{color:var(--text-secondary);font-size:var(--font-13);margin:var(--space-8) 0 var(--space-12)}.rm-view__config{background:var(--bg-surface-2);border:1px solid var(--border-soft);border-radius:var(--radius-md);display:flex;flex-direction:column;gap:var(--space-6);margin:10px 0 var(--space-12);padding:10px 14px}.rm-view__row{align-items:flex-start;display:flex;flex-wrap:wrap;font-size:var(--font-12);gap:14px}.rm-view__row-key{color:var(--text-muted);display:inline-flex;flex-shrink:0;font-size:var(--font-10);font-weight:var(--weight-semibold);letter-spacing:.04em;min-width:96px;padding-top:4px;text-transform:uppercase}.rm-view__row-key,.rm-view__row-val{align-items:center;gap:var(--space-6)}.rm-view__row-val{color:var(--text-primary);display:flex;flex:1 1 200px;flex-wrap:wrap;padding:2px 0}.rm-view__pill{align-items:center;background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-md);display:inline-flex;font-size:var(--font-12);gap:var(--space-4);padding:5px 10px}.rm-view__pill-k{color:var(--color-primary);font-weight:var(--weight-semibold)}.rm-view__pill-tip{min-width:0}.rm-view__pill-tip :deep(.rm-tooltip__bubble){max-width:320px}.rm-view__pill-v{display:-webkit-box;-webkit-box-orient:vertical;color:var(--text-primary);font-weight:var(--weight-medium);-webkit-line-clamp:3;overflow:hidden}.rm-view__foot{border-top:1px solid var(--border-soft);color:var(--text-muted);display:flex;flex-wrap:wrap;font-size:var(--font-11);gap:var(--space-16);padding-top:10px}.rm-view__foot span{align-items:center;display:inline-flex;gap:var(--space-4)}.rm-view__confirm{align-items:center;background:var(--color-danger-bg);border:1px solid var(--color-danger);border-radius:var(--radius-md);color:var(--color-danger);display:flex;flex-wrap:wrap;font-size:var(--font-13);gap:var(--space-12);margin-top:var(--space-12);padding:var(--space-8) var(--space-12)}.rm-view__confirm>span{align-items:center;display:inline-flex;flex:1 1 220px;gap:var(--space-8)}.rm-view__confirm-actions{display:flex;flex-shrink:0;gap:var(--space-8)}
349
370
  </style>
@@ -0,0 +1,54 @@
1
+ <!--
2
+ RmSnackBar - message bref sur l'action qui vient d'etre lancee, pose en bas
3
+ de l'ecran le temps qu'elle aboutisse : « Enregistrement », puis
4
+ « Enregistre ».
5
+
6
+ Il ne remplace pas RmCallout, qui commente un contenu et reste tant que la
7
+ condition dure. Celui-ci parle d'une action, pas d'un contenu, et il part.
8
+
9
+ Il se montre et se cache par `visible` plutot que par un `v-if` de
10
+ l'appelant : la glissade d'entree et celle de sortie font partie de l'objet,
11
+ et quatre pages qui le montent ne doivent pas reecrire quatre fois la meme
12
+ transition. Ce qu'il ne porte pas, c'est le minuteur : la duree d'affichage
13
+ appartient a ce qui declenche l'action, pas au bandeau qui la raconte.
14
+
15
+ La couleur de l'icone passe par la prop `color` de RmIcon et non par une
16
+ classe : le style scope de ce fichier n'atteint pas le `<svg>` monte
17
+ derriere `<ClientOnly>`, et l'icone retomberait sur la couleur du texte.
18
+ -->
19
+ <script setup lang="ts">
20
+ withDefaults(
21
+ defineProps<{
22
+ /** Le message. Court : c'est une ligne, pas un paragraphe. */
23
+ text: string
24
+ /** Affiche le bandeau. A false il glisse vers le bas et se demonte. */
25
+ visible?: boolean
26
+ /** Rotative devant le texte, pour une action encore en cours. */
27
+ loading?: boolean
28
+ /** Icone Phosphor devant le texte, quand l'action est retombee. */
29
+ icon?: string
30
+ /**
31
+ * Couleur de l'icone. Un token du theme (`var(--color-success)`) plutot
32
+ * qu'un hexadecimal, sinon le mode nuit ne suit pas.
33
+ */
34
+ iconColor?: string
35
+ }>(),
36
+ { visible: true, loading: false, icon: '', iconColor: 'var(--color-text-inverse)' },
37
+ )
38
+ </script>
39
+
40
+ <template>
41
+ <Transition name="rm-snackbar">
42
+ <!-- `status` et non `alert` : c'est le compte rendu d'une action voulue,
43
+ il ne doit pas couper ce que le lecteur d'ecran est en train de dire. -->
44
+ <div v-if="visible" class="rm-snackbar" role="status" aria-live="polite">
45
+ <div v-if="loading" class="rm-snackbar__spinner" />
46
+ <RmIcon v-else-if="icon" :name="icon" :size="20" :color="iconColor" />
47
+ <p class="rm-snackbar__text">{{ text }}</p>
48
+ </div>
49
+ </Transition>
50
+ </template>
51
+
52
+ <style scoped>
53
+ .rm-snackbar{align-items:center;background:#1e293b;border-radius:var(--radius-2xl);bottom:var(--space-16);box-shadow:var(--shadow-lg);display:flex;gap:var(--space-12);left:0;margin:0 auto;max-width:min(90vw,560px);padding:var(--space-12) var(--space-24);position:fixed;right:0;width:-moz-fit-content;width:fit-content;z-index:var(--z-toast)}.rm-snackbar__text{color:var(--color-text-inverse);font-family:var(--font-sans);font-size:var(--font-14);line-height:1.6;margin:0}.rm-snackbar__spinner{animation:rm-snackbar-spin .9s linear infinite;border:2px solid hsla(0,0%,100%,.25);border-radius:50%;border-top:2px solid var(--color-text-inverse);flex:none;height:20px;width:20px}@keyframes rm-snackbar-spin{to{transform:rotate(1turn)}}.rm-snackbar-enter-active,.rm-snackbar-leave-active{transition:transform var(--duration-base) cubic-bezier(.25,.46,.45,.94),opacity var(--duration-base) linear}.rm-snackbar-enter-from,.rm-snackbar-leave-to{opacity:0;transform:translateY(calc(100% + var(--space-16)))}@media (prefers-reduced-motion:reduce){.rm-snackbar-enter-active,.rm-snackbar-leave-active{transition:opacity var(--duration-fast) linear}.rm-snackbar-enter-from,.rm-snackbar-leave-to{transform:none}.rm-snackbar__spinner{animation-duration:3s}}
54
+ </style>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tekkare/romulus",
3
- "version": "0.1.90",
3
+ "version": "0.1.92",
4
4
  "description": "Romulus Design System - Nuxt module by Tekkare",
5
5
  "license": "MIT",
6
6
  "type": "module",