@tekkare/romulus 0.1.74 → 0.1.76

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.73",
7
+ "version": "0.1.75",
8
8
  "builder": {
9
9
  "@nuxt/module-builder": "0.8.4",
10
10
  "unbuild": "2.0.0"
@@ -26,7 +26,8 @@
26
26
  commentaire dans Auriga, et aucune page ne l'appelait.
27
27
  -->
28
28
  <script setup lang="ts">
29
- import { computed, nextTick, onUnmounted, ref, watch } from 'vue'
29
+ import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
30
+ import { rmPanelOpened, rmPanelRegister } from '../utils/panels'
30
31
 
31
32
  export interface RmComplexSelectPreset {
32
33
  label: string
@@ -179,6 +180,7 @@ async function toggle() {
179
180
  if (isOpen.value) return close()
180
181
 
181
182
  isOpen.value = true
183
+ rmPanelOpened(close)
182
184
  document.addEventListener('click', onDocumentClick)
183
185
  await nextTick()
184
186
  addRef.value?.focus()
@@ -219,7 +221,13 @@ function applyPreset(preset: RmComplexSelectPreset) {
219
221
  activePreset.value = preset.label
220
222
  }
221
223
 
224
+ let unregister: (() => void) | undefined
225
+ onMounted(() => {
226
+ unregister = rmPanelRegister(close)
227
+ })
228
+
222
229
  onUnmounted(() => {
230
+ unregister?.()
223
231
  clearTimeout(debounceId)
224
232
  document.removeEventListener('click', onDocumentClick)
225
233
  })
@@ -241,7 +249,7 @@ onUnmounted(() => {
241
249
  :disabled="disabled"
242
250
  :aria-expanded="isOpen"
243
251
  aria-haspopup="true"
244
- @click.stop="toggle"
252
+ @click="toggle"
245
253
  >
246
254
  <RmTooltip :text="summary" :disabled="selected.length === 0" class="rm-csel__value-slot">
247
255
  <span class="rm-csel__value" :class="{ 'is-empty': selected.length === 0 }">
@@ -26,7 +26,8 @@
26
26
  JSON de locale au montage.
27
27
  -->
28
28
  <script setup lang="ts">
29
- import { computed, nextTick, onUnmounted, ref, watch } from 'vue'
29
+ import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
30
+ import { rmPanelOpened, rmPanelRegister } from '../utils/panels'
30
31
 
31
32
  const props = withDefaults(defineProps<{
32
33
  /** Intitule pose au-dessus du champ. */
@@ -120,6 +121,7 @@ async function toggle() {
120
121
  if (isOpen.value) return close()
121
122
 
122
123
  isOpen.value = true
124
+ rmPanelOpened(close)
123
125
  searchTerm.value = ''
124
126
  activeIndex.value = props.options.indexOf(selected.value ?? '')
125
127
  document.addEventListener('click', onDocumentClick)
@@ -155,7 +157,13 @@ function onKeydown(event: KeyboardEvent) {
155
157
  }
156
158
  }
157
159
 
160
+ let unregister: (() => void) | undefined
161
+ onMounted(() => {
162
+ unregister = rmPanelRegister(close)
163
+ })
164
+
158
165
  onUnmounted(() => {
166
+ unregister?.()
159
167
  clearTimeout(debounceId)
160
168
  document.removeEventListener('click', onDocumentClick)
161
169
  })
@@ -172,7 +180,7 @@ onUnmounted(() => {
172
180
  :disabled="disabled"
173
181
  :aria-expanded="isOpen"
174
182
  aria-haspopup="listbox"
175
- @click.stop="toggle"
183
+ @click="toggle"
176
184
  >
177
185
  <RmTooltip :text="selected ?? ''" :disabled="!selected" class="rm-dsel__value-slot">
178
186
  <span class="rm-dsel__value" :class="{ 'is-empty': !selected }">
@@ -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(--color-danger)}.rm-fbar__action--clear:hover{opacity:.8;text-decoration-thickness:2px}
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:8px;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>
@@ -15,6 +15,7 @@
15
15
  -->
16
16
  <script setup lang="ts">
17
17
  import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
18
+ import { rmPanelOpened, rmPanelRegister } from '../utils/panels'
18
19
  import {
19
20
  PhCaretDown,
20
21
  PhMagnifyingGlass,
@@ -263,6 +264,7 @@ function clearAll() {
263
264
 
264
265
  function toggle() {
265
266
  isOpen.value = !isOpen.value
267
+ if (isOpen.value) rmPanelOpened(close)
266
268
  if (!isOpen.value) {
267
269
  addInput.value = ''
268
270
  addSearch.value = ''
@@ -291,11 +293,14 @@ function onKeydown(e: KeyboardEvent) {
291
293
  if (e.key === 'Escape' && isOpen.value) close()
292
294
  }
293
295
 
296
+ let unregister: (() => void) | undefined
294
297
  onMounted(() => {
298
+ unregister = rmPanelRegister(close)
295
299
  document.addEventListener('click', onClickOutside)
296
300
  document.addEventListener('keydown', onKeydown)
297
301
  })
298
302
  onUnmounted(() => {
303
+ unregister?.()
299
304
  clearTimeout(debounce)
300
305
  document.removeEventListener('click', onClickOutside)
301
306
  document.removeEventListener('keydown', onKeydown)
@@ -2,6 +2,7 @@
2
2
  import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
3
3
  import { PhCaretDown, PhCheck, PhMagnifyingGlass } from '@phosphor-icons/vue'
4
4
  import type { Component } from 'vue'
5
+ import { rmPanelOpened, rmPanelRegister } from '../utils/panels'
5
6
 
6
7
  export interface FilterDropdownOption {
7
8
  label: string
@@ -101,8 +102,13 @@ const rows = computed<DropdownRow[]>(() => {
101
102
  return out
102
103
  })
103
104
 
105
+ function close() {
106
+ isOpen.value = false
107
+ }
108
+
104
109
  function toggle() {
105
110
  isOpen.value = !isOpen.value
111
+ if (isOpen.value) rmPanelOpened(close)
106
112
  }
107
113
 
108
114
  // La recherche repart vide a chaque ouverture, et prend le curseur : sinon le
@@ -151,8 +157,15 @@ function onClickOutside(e: Event) {
151
157
  }
152
158
  }
153
159
 
154
- onMounted(() => document.addEventListener('click', onClickOutside))
155
- onUnmounted(() => document.removeEventListener('click', onClickOutside))
160
+ let unregister: (() => void) | undefined
161
+ onMounted(() => {
162
+ unregister = rmPanelRegister(close)
163
+ document.addEventListener('click', onClickOutside)
164
+ })
165
+ onUnmounted(() => {
166
+ unregister?.()
167
+ document.removeEventListener('click', onClickOutside)
168
+ })
156
169
  </script>
157
170
 
158
171
  <template>
@@ -24,7 +24,8 @@
24
24
  identifiant cassait des que la liste etait filtree.
25
25
  -->
26
26
  <script setup lang="ts">
27
- import { computed, nextTick, onUnmounted, ref, watch } from 'vue'
27
+ import { computed, nextTick, onMounted, onUnmounted, ref, watch } from 'vue'
28
+ import { rmPanelOpened, rmPanelRegister } from '../utils/panels'
28
29
 
29
30
  const props = withDefaults(defineProps<{
30
31
  /** Intitule pose au-dessus du champ. */
@@ -134,6 +135,7 @@ async function toggle() {
134
135
  if (isOpen.value) return close()
135
136
 
136
137
  isOpen.value = true
138
+ rmPanelOpened(close)
137
139
  searchTerm.value = ''
138
140
  document.addEventListener('click', onDocumentClick)
139
141
  if (!props.search) return
@@ -156,7 +158,13 @@ function toggleAll() {
156
158
  commit(allSelected.value ? [] : [...props.options])
157
159
  }
158
160
 
161
+ let unregister: (() => void) | undefined
162
+ onMounted(() => {
163
+ unregister = rmPanelRegister(close)
164
+ })
165
+
159
166
  onUnmounted(() => {
167
+ unregister?.()
160
168
  clearTimeout(debounceId)
161
169
  document.removeEventListener('click', onDocumentClick)
162
170
  })
@@ -178,7 +186,7 @@ onUnmounted(() => {
178
186
  :disabled="disabled"
179
187
  :aria-expanded="isOpen"
180
188
  aria-haspopup="true"
181
- @click.stop="toggle"
189
+ @click="toggle"
182
190
  >
183
191
  <RmTooltip :text="summary" :disabled="selected.length === 0" class="rm-msel__value-slot">
184
192
  <span class="rm-msel__value" :class="{ 'is-empty': selected.length === 0 }">
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Inscrit un panneau. A appeler au montage, cote client seulement : sur le
3
+ * serveur le registre est partage par toutes les requetes et personne ne le
4
+ * vide.
5
+ */
6
+ export declare function rmPanelRegister(close: () => void): () => boolean;
7
+ /** Ferme tous les panneaux sauf celui qui vient de s'ouvrir. */
8
+ export declare function rmPanelOpened(self: () => void): void;
@@ -0,0 +1,10 @@
1
+ const closers = /* @__PURE__ */ new Set();
2
+ export function rmPanelRegister(close) {
3
+ closers.add(close);
4
+ return () => closers.delete(close);
5
+ }
6
+ export function rmPanelOpened(self) {
7
+ closers.forEach((close) => {
8
+ if (close !== self) close();
9
+ });
10
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tekkare/romulus",
3
- "version": "0.1.74",
3
+ "version": "0.1.76",
4
4
  "description": "Romulus Design System - Nuxt module by Tekkare",
5
5
  "license": "MIT",
6
6
  "type": "module",