@tekkare/romulus 0.1.64 → 0.1.66

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.63",
7
+ "version": "0.1.65",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "0.8.4",
10
10
  "unbuild": "2.0.0"
@@ -275,5 +275,5 @@ onBeforeUnmount(() => {
275
275
  </template>
276
276
 
277
277
  <style scoped>
278
- .rm-fbar{margin-inline:calc((min(var(--oip-content-max, 100%), 100%) - var(--oip-main-w, 100%))/2);position:sticky;width:var(--oip-main-w,100%);z-index:91;--rm-fbar-field-h:32px;backdrop-filter:blur(12px);background:rgba(245,245,249,.8);border-bottom:1px solid var(--border-default);display:flex;flex-direction:column;font-family:var(--font-sans)}.rm-fbar__views{align-items:center;display:flex;flex:0 0 auto}.rm-fbar__views:empty{display:none}.rm-fbar__row{align-items:flex-start;display:flex;gap:12px;padding-block:8px;padding-inline:max(32px,(100% - var(--oip-content-max,100%))/2 + 32px)}.rm-fbar--open .rm-fbar__row:not(:has(~.rm-fbar__rail-row)){border-bottom:1px solid var(--border-default)}.rm-fbar__toggle :deep(p),.rm-fbar__toggle :deep(span){font-size:inherit;font-weight:inherit;line-height:inherit;margin:0}.rm-fbar__toggle{align-items:center;background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-pill);color:var(--text-primary);cursor:pointer;display:flex;flex:0 0 auto;font-family:inherit;font-size:var(--font-14);font-weight:var(--weight-medium);gap:6px;height:var(--rm-fbar-field-h);justify-content:center;padding:0 14px}.rm-fbar__toggle:hover{background:var(--bg-surface-3)}.rm-fbar__toggle.is-active,.rm-fbar__toggle.is-active:hover{background:var(--color-primary);border-color:var(--color-primary);color:var(--color-text-inverse)}.rm-fbar__toggle.is-active .rm-fbar__badge{background:var(--color-text-inverse);color:var(--color-primary)}.rm-fbar__badge{align-items:center;background:var(--color-primary);border-radius:16px;color:var(--color-text-inverse);display:inline-flex;font-size:var(--font-11);font-weight:var(--weight-bold);justify-content:center;min-width:18px;padding:0 5px}.rm-fbar__view{align-items:center;display:flex;flex:0 0 auto}.rm-fbar__advanced{align-items:center;background:none;border:none;border-left:1px solid var(--border-default);color:var(--color-primary);cursor:pointer;display:inline-flex;font-family:inherit;font-size:var(--font-13);font-weight:var(--weight-medium);height:var(--rm-fbar-field-h);padding:0 0 0 12px;position:absolute;right:14px;text-decoration-line:underline;top:0;white-space:nowrap;z-index:2}.rm-fbar__advanced.is-active,.rm-fbar__advanced:hover{color:var(--color-primary-hover,var(--color-primary));text-decoration-thickness:2px}.rm-fbar__rail-row{display:flex;padding-bottom:8px;padding-inline:max(32px,(100% - var(--oip-content-max,100%))/2 + 32px)}.rm-fbar--open .rm-fbar__rail-row{border-bottom:1px solid var(--border-default)}.rm-fbar__rail{align-items:center;display:flex;flex:0 1 auto;min-width:0;overflow-x:auto;scrollbar-width:thin}.rm-fbar__rail:empty{display:none}.rm-fbar__search{align-items:center;display:flex;flex:1 1 auto;gap:8px;min-width:0;position:relative}.rm-fbar__search:empty{display:none}.rm-fbar__search :deep(.search-bar-wrapper){flex:1 1 auto;min-width:0}.rm-fbar__search :deep(.search-bar){background:var(--bg-surface);box-sizing:border-box;display:flex;height:var(--rm-fbar-field-h);width:100%}.rm-fbar__search :deep(.filters_input_search){border-radius:var(--radius-pill);box-sizing:border-box;height:auto;min-height:var(--rm-fbar-field-h);padding-right:calc(var(--rm-fbar-advanced-w, 0px) + 12px);width:100%}.rm-fbar__search :deep(.research_tags:not(:has(*))){display:none}.rm-fbar__search :deep(.select_shortcut){box-sizing:border-box;font-size:var(--font-11);height:24px;padding-block:0}.rm-fbar__search :deep(.select_shortcut:hover){background:var(--bg-surface-3)!important;border-color:var(--border-default)!important;color:inherit!important}.rm-fbar__search :deep(.select_shortcut:hover svg){color:inherit!important}.rm-fbar__search :deep(.remove_search_section){border-left:none;border-radius:0 var(--radius-pill) var(--radius-pill) 0}.rm-fbar__search :deep(.remove_search_section:hover){background:transparent!important}.rm-fbar__search :deep(.remove_search_section:hover svg){color:var(--text-primary)!important}.rm-fbar__search :deep(.filters_input_search.no_bottom){border-bottom:1.5px solid var(--color-primary)!important;border-radius:var(--radius-pill)}.rm-fbar__search :deep(.search_suggestions){border:1px solid var(--border-default);border-radius:var(--radius-2xl);box-shadow:var(--shadow-lg);left:0;padding:6px;right:0;top:calc(100% + 6px);width:auto}.rm-fbar__search :deep(.sugg_container>*){border-radius:var(--radius-lg)}.rm-fbar__search :deep(.sugg_container>.selected){background:color-mix(in srgb,var(--color-primary) 6%,transparent)!important}.rm-fbar__panel{--rm-filter-col:224px;--rm-fbar-panel-field-h:40px;align-items:end;display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(0,var(--rm-filter-col)));justify-content:center;padding-block:16px 20px;padding-inline:56px}.rm-fbar__panel--wide{align-items:stretch;display:flex;flex-direction:column;gap:12px}.rm-fbar__filters{display:contents}.rm-fbar__filters :deep(.filter-chip),.rm-fbar__filters :deep(.filter-complex__trigger),.rm-fbar__filters :deep(.rm-number__box){border-radius:var(--radius-lg);height:var(--rm-fbar-panel-field-h);width:100%}.rm-fbar__panel-head{align-items:baseline;display:flex;gap:16px;grid-column:1/-1;width:100%}.rm-fbar__customize{grid-column:1/-1}.rm-fbar__panel :deep(.filters_row_break){grid-column:1/-1}.rm-fbar__panel-title{font-size:var(--font-18);font-weight:800;margin:0}.rm-fbar__action{background:none;border:none;cursor:pointer;font-family:inherit;font-size:var(--font-14);font-weight:var(--weight-medium);padding:0;text-decoration-line:underline}.rm-fbar__action--save{color:var(--color-primary)}.rm-fbar__action--clear{color:var(--text-secondary)}
278
+ .rm-fbar{margin-inline:calc((min(var(--oip-content-max, 100%), 100%) - var(--oip-main-w, 100%))/2);position:sticky;width:var(--oip-main-w,100%);z-index:91;--rm-fbar-field-h:32px;backdrop-filter:blur(12px);background:rgba(245,245,249,.8);border-bottom:1px solid var(--border-default);display:flex;flex-direction:column;font-family:var(--font-sans)}.rm-fbar__views{align-items:center;display:flex;flex:0 0 auto}.rm-fbar__views:empty{display:none}.rm-fbar__row{align-items:flex-start;display:flex;gap:12px;padding-block:8px;padding-inline:max(32px,(100% - var(--oip-content-max,100%))/2 + 32px)}.rm-fbar--open .rm-fbar__row:not(:has(~.rm-fbar__rail-row)){border-bottom:1px solid var(--border-default)}.rm-fbar__toggle :deep(p),.rm-fbar__toggle :deep(span){font-size:inherit;font-weight:inherit;line-height:inherit;margin:0}.rm-fbar__toggle{align-items:center;background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-pill);color:var(--text-primary);cursor:pointer;display:flex;flex:0 0 auto;font-family:inherit;font-size:var(--font-14);font-weight:var(--weight-medium);gap:6px;height:var(--rm-fbar-field-h);justify-content:center;padding:0 14px}.rm-fbar__toggle:hover{background:var(--bg-surface-3)}.rm-fbar__toggle.is-active,.rm-fbar__toggle.is-active:hover{background:var(--color-primary);border-color:var(--color-primary);color:var(--color-text-inverse)}.rm-fbar__toggle.is-active .rm-fbar__badge{background:var(--color-text-inverse);color:var(--color-primary)}.rm-fbar__badge{align-items:center;background:var(--color-primary);border-radius:16px;color:var(--color-text-inverse);display:inline-flex;font-size:var(--font-11);font-weight:var(--weight-bold);justify-content:center;min-width:18px;padding:0 5px}.rm-fbar__view{align-items:center;display:flex;flex:0 0 auto}.rm-fbar__advanced{align-items:center;background:none;border:none;border-left:1px solid var(--border-default);color:var(--color-primary);cursor:pointer;display:inline-flex;font-family:inherit;font-size:var(--font-13);font-weight:var(--weight-medium);height:var(--rm-fbar-field-h);padding:0 0 0 12px;position:absolute;right:14px;text-decoration-line:underline;top:0;white-space:nowrap;z-index:2}.rm-fbar__advanced.is-active,.rm-fbar__advanced:hover{color:var(--color-primary-hover,var(--color-primary));text-decoration-thickness:2px}.rm-fbar__rail-row{display:flex;padding-bottom:8px;padding-inline:max(32px,(100% - var(--oip-content-max,100%))/2 + 32px)}.rm-fbar--open .rm-fbar__rail-row{border-bottom:1px solid var(--border-default)}.rm-fbar__rail{align-items:center;display:flex;flex:0 1 auto;min-width:0;overflow-x:auto;scrollbar-width:thin}.rm-fbar__rail:empty{display:none}.rm-fbar__search{align-items:center;display:flex;flex:1 1 auto;gap:8px;min-width:0;position:relative}.rm-fbar__search:empty{display:none}.rm-fbar__search :deep(.search-bar-wrapper){flex:1 1 auto;min-width:0}.rm-fbar__search :deep(.search-bar){background:var(--bg-surface);box-sizing:border-box;display:flex;height:var(--rm-fbar-field-h);width:100%}.rm-fbar__search :deep(.filters_input_search){border-radius:var(--radius-pill);box-sizing:border-box;height:auto;min-height:var(--rm-fbar-field-h);padding-right:calc(var(--rm-fbar-advanced-w, 0px) + 12px);width:100%}.rm-fbar__search :deep(.research_tags:not(:has(*))){display:none}.rm-fbar__search :deep(.select_shortcut){box-sizing:border-box;font-size:var(--font-11);height:24px;padding-block:0}.rm-fbar__search :deep(.select_shortcut:hover){background:var(--bg-surface-3)!important;border-color:var(--border-default)!important;color:inherit!important}.rm-fbar__search :deep(.select_shortcut:hover svg){color:inherit!important}.rm-fbar__search :deep(.remove_search_section){border-left:none;border-radius:0 var(--radius-pill) var(--radius-pill) 0}.rm-fbar__search :deep(.remove_search_section:hover){background:transparent!important}.rm-fbar__search :deep(.remove_search_section:hover svg){color:var(--text-primary)!important}.rm-fbar__search :deep(.filters_input_search.no_bottom){border-bottom:1.5px solid var(--color-primary)!important;border-radius:var(--radius-pill)}.rm-fbar__search :deep(.search_suggestions){border:1px solid var(--border-default);border-radius:var(--radius-2xl);box-shadow:var(--shadow-lg);left:0;padding:6px;right:0;top:calc(100% + 6px);width:auto}.rm-fbar__search :deep(.sugg_container>*){border-radius:var(--radius-lg)}.rm-fbar__search :deep(.sugg_container>.selected){background:color-mix(in srgb,var(--color-primary) 6%,transparent)!important}.rm-fbar__panel{--rm-filter-col:224px;--rm-fbar-panel-field-h:40px;align-items:end;display:grid;gap:16px;grid-template-columns:repeat(auto-fit,minmax(0,var(--rm-filter-col)));justify-content:center;padding-block:16px 20px;padding-inline:56px}.rm-fbar__panel--wide{align-items:stretch;display:flex;flex-direction:column;gap:12px}.rm-fbar__filters{display:contents}.rm-fbar__filters :deep(.filter-chip),.rm-fbar__filters :deep(.filter-complex__trigger),.rm-fbar__filters :deep(.rm-number__box){border-radius:var(--radius-lg);height:var(--rm-fbar-panel-field-h);width:100%}.rm-fbar__panel-head{align-items:baseline;display:flex;gap:16px;grid-column:1/-1;width:100%}.rm-fbar__customize{grid-column:1/-1}.rm-fbar__panel :deep(.filters_row_break){grid-column:1/-1}.rm-fbar__panel-title{font-size:var(--font-18);font-weight:800;margin:0}.rm-fbar__action{background:none;border:none;cursor:pointer;font-family:inherit;font-size:var(--font-14);font-weight:var(--weight-medium);padding:0;text-decoration-line:underline}.rm-fbar__action--save{color:var(--color-primary)}.rm-fbar__action--clear{color:var(--color-danger)}.rm-fbar__action--clear:hover{opacity:.8;text-decoration-thickness:2px}
279
279
  </style>
@@ -1,103 +1,83 @@
1
1
  <!--
2
- RmLangSelect - choix de la langue, drapeau puis nom.
2
+ RmLangSelect - bascule de langue, un drapeau par langue dans une capsule.
3
3
 
4
- Reprend `arg-lang-select` d'Auriga : la langue courante s'affiche, le clic
5
- deroule les autres. Trois choses changent.
4
+ Meme dessin que la bascule du rail (`.rm-lang` de shell.css) : les langues
5
+ sont toutes posees, celle qui vaut est en couleur, les autres en gris, et un
6
+ pouce blanc glisse sous la langue active. Rien ne se deroule : a deux ou trois
7
+ langues, un menu demande deux gestes la ou la bascule en demande un, et cache
8
+ la moitie du choix entre les deux.
6
9
 
7
- C'est un `<button aria-expanded>` suivi d'une liste `role="listbox"`, et
8
- Echap referme. Auriga posait un `<div @click>` sans role ni etat, injoignable
9
- au clavier.
10
+ Les drapeaux passent par `RmFlag`, pas par l'emoji : sous Windows, Segoe UI
11
+ Emoji ne ligature pas les indicateurs regionaux et Chrome affiche « FR » dans
12
+ deux carres.
10
13
 
11
- La langue courante est un `v-model` sur l'iso, plus une copie interne : une
12
- langue changee par la route ou par un autre menu se refletait mal.
13
-
14
- `collapsed` remplace le `sidebarOpen` a trois etats (`true`, `false`, `null`)
15
- d'Auriga, qui melangeait « barre repliee » et « pas dans une barre » dans la
16
- meme valeur.
14
+ Le gris n'est pas le seul signal : la langue active porte `aria-pressed` et
15
+ son pouce, si bien qu'elle se repere sans distinguer les couleurs.
17
16
  -->
18
17
  <script setup lang="ts">
19
- import { computed, ref, onMounted, onUnmounted } from 'vue'
18
+ import { computed } from 'vue'
20
19
 
21
20
  export interface RmLang {
22
- /** Code ISO du pays, pour le drapeau (`fr`, `gb`...). */
23
- iso: string
24
- /** Nom affiche. */
25
- title: string
21
+ /** Code de langue, ce que porte le modele (`fr`, `en`). */
22
+ code: string
23
+ /** Code ISO 3166-1 alpha-2 du drapeau (`fr`, `gb`). Sans lui, `code` sert. */
24
+ iso?: string
25
+ /** Nom de la langue, lu a voix haute et pose en infobulle. */
26
+ label: string
26
27
  }
27
28
 
28
29
  const props = withDefaults(defineProps<{
29
30
  langs: RmLang[]
30
- /** Barre laterale repliee : le drapeau seul, sans le nom. */
31
- collapsed?: boolean
32
- /** Intitule du bouton pour les technologies d'assistance. */
31
+ /** Cote a cote plutot qu'empile, pour un pied de page ou une barre. */
32
+ horizontal?: boolean
33
+ /** Intitule du groupe pour les technologies d'assistance. */
33
34
  label?: string
34
35
  }>(), {
35
- collapsed: false,
36
+ horizontal: false,
36
37
  label: 'Langue',
37
38
  })
38
39
 
39
40
  const selected = defineModel<string>({ default: '' })
40
41
 
41
- const isOpen = ref(false)
42
- const wrapperRef = ref<HTMLElement>()
43
-
44
- const current = computed(() => props.langs.find(lang => lang.iso === selected.value))
45
- const others = computed(() => props.langs.filter(lang => lang.iso !== selected.value))
46
-
47
- function pick(lang: RmLang) {
48
- selected.value = lang.iso
49
- isOpen.value = false
50
- }
51
-
52
- function onClickOutside(event: Event) {
53
- if (wrapperRef.value && !wrapperRef.value.contains(event.target as Node)) isOpen.value = false
54
- }
42
+ /** Rang de la langue active : c'est lui qui place le pouce. */
43
+ const activeIndex = computed(() =>
44
+ Math.max(0, props.langs.findIndex(lang => lang.code === selected.value)),
45
+ )
55
46
 
56
- function onKeydown(event: KeyboardEvent) {
57
- if (event.key === 'Escape' && isOpen.value) isOpen.value = false
58
- }
47
+ /** 32px de pastille plus 2px de gouttiere. */
48
+ const STEP = 34
59
49
 
60
- onMounted(() => {
61
- document.addEventListener('click', onClickOutside)
62
- document.addEventListener('keydown', onKeydown)
63
- })
64
- onUnmounted(() => {
65
- document.removeEventListener('click', onClickOutside)
66
- document.removeEventListener('keydown', onKeydown)
67
- })
50
+ const thumbStyle = computed(() => ({
51
+ transform: props.horizontal
52
+ ? `translateX(${activeIndex.value * STEP}px)`
53
+ : `translateY(${activeIndex.value * STEP}px)`,
54
+ }))
68
55
  </script>
69
56
 
70
57
  <template>
71
- <div v-if="current" ref="wrapperRef" class="rm-lang">
58
+ <div
59
+ class="rm-lang"
60
+ :class="{ 'rm-lang--horizontal': horizontal }"
61
+ role="group"
62
+ :aria-label="label"
63
+ >
64
+ <span class="rm-lang__thumb" :style="thumbStyle" aria-hidden="true" />
72
65
  <button
66
+ v-for="lang in langs"
67
+ :key="lang.code"
73
68
  type="button"
74
- class="rm-lang__current"
75
- :aria-label="label"
76
- :aria-expanded="isOpen"
77
- @click="isOpen = !isOpen"
69
+ class="rm-lang__option"
70
+ :class="{ 'rm-lang__option--active': lang.code === selected }"
71
+ :title="lang.label"
72
+ :aria-label="lang.label"
73
+ :aria-pressed="lang.code === selected"
74
+ @click="selected = lang.code"
78
75
  >
79
- <RmFlag :code="current.iso" :height="18" :title="current.title" />
80
- <span v-if="!collapsed" class="rm-lang__name">{{ current.title }}</span>
81
- <RmIcon
82
- v-if="!collapsed"
83
- name="CaretDown"
84
- :size="14"
85
- class="rm-lang__caret"
86
- :class="{ 'is-open': isOpen }"
87
- />
76
+ <RmFlag :code="lang.iso || lang.code" :height="18" />
88
77
  </button>
89
-
90
- <ul v-if="isOpen && others.length > 0" class="rm-lang__list" role="listbox" :aria-label="label">
91
- <li v-for="lang in others" :key="lang.iso" role="option" :aria-selected="false">
92
- <button type="button" class="rm-lang__option" @click="pick(lang)">
93
- <RmFlag :code="lang.iso" :height="18" :title="lang.title" />
94
- <span v-if="!collapsed">{{ lang.title }}</span>
95
- </button>
96
- </li>
97
- </ul>
98
78
  </div>
99
79
  </template>
100
80
 
101
81
  <style scoped>
102
- .rm-lang{position:relative}.rm-lang__current,.rm-lang__option{align-items:center;background:none;border:none;border-radius:var(--radius-md,8px);color:var(--text-primary);cursor:pointer;display:flex;font-size:var(--font-14,14px);gap:8px;padding:6px 8px;width:100%}.rm-lang__current:hover,.rm-lang__option:hover{background:var(--bg-hover)}.rm-lang__name{flex:1;text-align:left}.rm-lang__caret{color:var(--text-muted);transition:transform var(--duration-fast,.15s) var(--ease-in-out,ease)}.rm-lang__caret.is-open{transform:rotate(180deg)}.rm-lang__list{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-md,8px);bottom:calc(100% + 4px);box-shadow:0 4px 16px rgba(var(--shadow-rgb),.1);left:0;list-style:none;margin:0;min-width:100%;padding:4px;position:absolute;z-index:50}
82
+ .rm-lang{background:var(--rm-shell-subtle,var(--bg-surface-2));border:1px solid var(--rm-shell-accent,var(--color-primary));border-radius:9999px;display:grid;gap:2px;grid-template-rows:repeat(v-bind("langs.length"),1fr);padding:3px;position:relative;width:-moz-fit-content;width:fit-content}.rm-lang--horizontal{grid-auto-flow:column;grid-template-rows:1fr}.rm-lang__thumb{background:var(--rm-shell-surface,var(--bg-surface));border-radius:9999px;box-shadow:0 1px 4px rgba(var(--shadow-rgb,30 41 59),.16);height:32px;left:3px;position:absolute;top:3px;transition:transform .26s cubic-bezier(.34,1.56,.64,1);width:32px}.rm-lang__option{align-items:center;-webkit-appearance:none;-moz-appearance:none;appearance:none;background:none;border:none;border-radius:9999px;box-shadow:none;cursor:pointer;display:flex;filter:grayscale(1);height:32px;justify-content:center;margin:0;opacity:.5;padding:0;position:relative;transition:filter .18s ease,opacity .18s ease;width:32px}.rm-lang__option:hover{filter:grayscale(0);opacity:.85}.rm-lang__option--active{filter:grayscale(0);opacity:1}.rm-lang__option:focus-visible{outline:2px solid var(--rm-shell-accent,var(--color-primary));outline-offset:2px}@media (prefers-reduced-motion:reduce){.rm-lang__option,.rm-lang__thumb{transition:none}}
103
83
  </style>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tekkare/romulus",
3
- "version": "0.1.64",
3
+ "version": "0.1.66",
4
4
  "description": "Romulus Design System - Nuxt module by Tekkare",
5
5
  "license": "MIT",
6
6
  "type": "module",