@tekkare/romulus 0.1.159 → 0.1.160
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
|
@@ -162,22 +162,52 @@ const t = computed(() => WORDS[props.lang])
|
|
|
162
162
|
const isOpen = ref(false)
|
|
163
163
|
const removeSearch = ref('')
|
|
164
164
|
const activePreset = ref<string>()
|
|
165
|
-
const alignRight = ref(false)
|
|
166
165
|
const rootRef = ref<HTMLElement>()
|
|
166
|
+
const panelRef = ref<HTMLElement>()
|
|
167
167
|
const addRef = ref<HTMLInputElement>()
|
|
168
168
|
|
|
169
169
|
/** Largeur du panneau, tenue en phase avec la regle `.rm-csel__panel`. */
|
|
170
170
|
const PANEL_WIDTH = 820
|
|
171
171
|
|
|
172
|
+
/** Marge gardee contre les bords de la fenetre. */
|
|
173
|
+
const PANEL_GAP = 8
|
|
174
|
+
|
|
172
175
|
/**
|
|
173
|
-
* Le panneau
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
+
* Le panneau est pose sur la fenetre, pas dans le champ : depose dans le flux,
|
|
177
|
+
* il etait coupe des que le filtre vivait dans un conteneur qui defile (un
|
|
178
|
+
* tiroir, une carte a debordement cache), et aucun reglage de `overflow` chez
|
|
179
|
+
* l'appelant ne le rattrapait.
|
|
180
|
+
*
|
|
181
|
+
* Il sort donc par un `Teleport` et se positionne a la main, sous le champ,
|
|
182
|
+
* cale a gauche par defaut et sur le bord droit du champ quand il depasserait
|
|
183
|
+
* de l'ecran.
|
|
176
184
|
*/
|
|
185
|
+
const panelStyle = ref<Record<string, string>>({})
|
|
186
|
+
|
|
177
187
|
function placePanel() {
|
|
178
188
|
const rect = rootRef.value?.getBoundingClientRect()
|
|
179
189
|
if (!rect) return
|
|
180
|
-
|
|
190
|
+
|
|
191
|
+
const width = Math.min(PANEL_WIDTH, window.innerWidth - PANEL_GAP * 2)
|
|
192
|
+
const left = rect.left + width > window.innerWidth - PANEL_GAP
|
|
193
|
+
? Math.max(PANEL_GAP, rect.right - width)
|
|
194
|
+
: rect.left
|
|
195
|
+
|
|
196
|
+
// Sous le champ, sauf quand il ne reste rien dessous : le panneau se pose
|
|
197
|
+
// alors au-dessus, et sa hauteur se borne a la place reellement libre.
|
|
198
|
+
const below = window.innerHeight - rect.bottom - PANEL_GAP * 2
|
|
199
|
+
const above = rect.top - PANEL_GAP * 2
|
|
200
|
+
const flip = below < 320 && above > below
|
|
201
|
+
|
|
202
|
+
panelStyle.value = {
|
|
203
|
+
position: 'fixed',
|
|
204
|
+
left: `${left}px`,
|
|
205
|
+
width: `${width}px`,
|
|
206
|
+
maxHeight: `${Math.max(240, flip ? above : below)}px`,
|
|
207
|
+
...(flip
|
|
208
|
+
? { bottom: `${window.innerHeight - rect.top + PANEL_GAP}px` }
|
|
209
|
+
: { top: `${rect.bottom + PANEL_GAP}px` }),
|
|
210
|
+
}
|
|
181
211
|
}
|
|
182
212
|
|
|
183
213
|
/** Les chaines nues valent libelle et valeur a la fois. */
|
|
@@ -227,13 +257,31 @@ watch(addInput, (value) => {
|
|
|
227
257
|
}, 500)
|
|
228
258
|
})
|
|
229
259
|
|
|
260
|
+
/**
|
|
261
|
+
* Le panneau suit le champ tant qu'il est ouvert : pose sur la fenetre, il
|
|
262
|
+
* resterait sinon la ou le champ etait avant que la page (ou le tiroir) ne
|
|
263
|
+
* defile.
|
|
264
|
+
*/
|
|
265
|
+
function trackPanel() {
|
|
266
|
+
window.addEventListener('scroll', placePanel, true)
|
|
267
|
+
window.addEventListener('resize', placePanel)
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function untrackPanel() {
|
|
271
|
+
window.removeEventListener('scroll', placePanel, true)
|
|
272
|
+
window.removeEventListener('resize', placePanel)
|
|
273
|
+
}
|
|
274
|
+
|
|
230
275
|
function close() {
|
|
231
276
|
isOpen.value = false
|
|
232
277
|
document.removeEventListener('click', onDocumentClick)
|
|
278
|
+
untrackPanel()
|
|
233
279
|
}
|
|
234
280
|
|
|
235
281
|
function onDocumentClick(event: MouseEvent) {
|
|
236
|
-
|
|
282
|
+
const target = event.target as Node
|
|
283
|
+
if (rootRef.value?.contains(target) || panelRef.value?.contains(target)) return
|
|
284
|
+
close()
|
|
237
285
|
}
|
|
238
286
|
|
|
239
287
|
async function toggle() {
|
|
@@ -242,6 +290,7 @@ async function toggle() {
|
|
|
242
290
|
|
|
243
291
|
isOpen.value = true
|
|
244
292
|
placePanel()
|
|
293
|
+
trackPanel()
|
|
245
294
|
rmPanelOpened(close)
|
|
246
295
|
document.addEventListener('click', onDocumentClick)
|
|
247
296
|
await nextTick()
|
|
@@ -292,6 +341,7 @@ onUnmounted(() => {
|
|
|
292
341
|
unregister?.()
|
|
293
342
|
clearTimeout(debounceId)
|
|
294
343
|
document.removeEventListener('click', onDocumentClick)
|
|
344
|
+
untrackPanel()
|
|
295
345
|
})
|
|
296
346
|
</script>
|
|
297
347
|
|
|
@@ -324,11 +374,14 @@ onUnmounted(() => {
|
|
|
324
374
|
<PhCaretDown :size="16" />
|
|
325
375
|
</button>
|
|
326
376
|
|
|
377
|
+
<Teleport to="body">
|
|
327
378
|
<div
|
|
328
379
|
v-show="isOpen"
|
|
380
|
+
ref="panelRef"
|
|
329
381
|
class="rm-csel__panel"
|
|
330
|
-
:
|
|
382
|
+
:style="panelStyle"
|
|
331
383
|
@click.stop
|
|
384
|
+
@keydown.escape="close"
|
|
332
385
|
>
|
|
333
386
|
<div class="rm-csel__column">
|
|
334
387
|
<div v-if="presets && presets.length > 0" class="rm-csel__presets">
|
|
@@ -437,9 +490,10 @@ onUnmounted(() => {
|
|
|
437
490
|
</div>
|
|
438
491
|
</div>
|
|
439
492
|
</div>
|
|
493
|
+
</Teleport>
|
|
440
494
|
</div>
|
|
441
495
|
</template>
|
|
442
496
|
|
|
443
497
|
<style scoped>
|
|
444
|
-
.rm-csel{align-items:stretch;flex-direction:column;position:relative;width:196px}.rm-csel,.rm-csel__label{display:flex;gap:var(--space-4)}.rm-csel__label{align-items:center;color:var(--text-secondary);font-size:var(--font-12,12px);line-height:14px}.rm-csel__info{background:none;border:none;color:var(--text-muted);cursor:pointer;display:flex;padding:0}.rm-csel__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-csel__field:hover:not(.is-disabled){border-color:rgba(var(--brand-rgb),.3)}.rm-csel__field.is-open{border-color:var(--color-primary)}.rm-csel__field.is-disabled{background:var(--bg-surface-2);color:var(--text-muted);cursor:not-allowed}.rm-csel__field:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.rm-csel__value-slot{display:block;flex:1;min-width:0}.rm-csel__value{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rm-csel__value.is-empty{color:var(--text-muted);font-style:italic;font-weight:400}.rm-csel__field :deep(svg){color:var(--text-secondary);flex-shrink:0}.rm-csel__count{align-items:center;background:rgba(var(--brand-rgb),.1);border-radius:50%;color:var(--color-primary);display:flex;flex-shrink:0;font-size:var(--font-12,12px);font-weight:600;height:20px;justify-content:center;width:20px}.rm-csel__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;
|
|
498
|
+
.rm-csel{align-items:stretch;flex-direction:column;position:relative;width:196px}.rm-csel,.rm-csel__label{display:flex;gap:var(--space-4)}.rm-csel__label{align-items:center;color:var(--text-secondary);font-size:var(--font-12,12px);line-height:14px}.rm-csel__info{background:none;border:none;color:var(--text-muted);cursor:pointer;display:flex;padding:0}.rm-csel__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-csel__field:hover:not(.is-disabled){border-color:rgba(var(--brand-rgb),.3)}.rm-csel__field.is-open{border-color:var(--color-primary)}.rm-csel__field.is-disabled{background:var(--bg-surface-2);color:var(--text-muted);cursor:not-allowed}.rm-csel__field:focus-visible{outline:2px solid var(--color-primary);outline-offset:2px}.rm-csel__value-slot{display:block;flex:1;min-width:0}.rm-csel__value{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rm-csel__value.is-empty{color:var(--text-muted);font-style:italic;font-weight:400}.rm-csel__field :deep(svg){color:var(--text-secondary);flex-shrink:0}.rm-csel__count{align-items:center;background:rgba(var(--brand-rgb),.1);border-radius:50%;color:var(--color-primary);display:flex;flex-shrink:0;font-size:var(--font-12,12px);font-weight:600;height:20px;justify-content:center;width:20px}.rm-csel__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;max-height:calc(100vh - 32px);max-width:calc(100vw - 16px);overflow:hidden;position:fixed;z-index:var(--z-popover,1000)}.rm-csel__column{display:flex;flex:1;flex-direction:column;gap:var(--space-8);min-width:0;padding:var(--space-16)}.rm-csel__column--right{border-left:1px solid var(--border-soft);flex:0 0 300px}.rm-csel__presets{border-bottom:1px solid var(--border-soft);display:flex;flex-direction:column;gap:var(--space-8);padding-bottom:var(--space-8)}.rm-csel__pills{display:flex;flex-wrap:wrap;gap:var(--space-4)}.rm-csel__pill{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:9999px;color:var(--text-secondary);cursor:pointer;font-family:inherit;font-size:var(--font-12,12px);padding:var(--space-4) var(--space-10)}.rm-csel__pill.is-active,.rm-csel__pill:hover{border-color:var(--color-primary);color:var(--color-primary)}.rm-csel__pill.is-active{background:rgba(var(--brand-rgb),.1);font-weight:700}.rm-csel__head{align-items:center;display:flex;gap:var(--space-8);justify-content:space-between}.rm-csel__section{color:var(--text-secondary);font-size:var(--font-12,12px);font-weight:700;margin:0}.rm-csel__action{background:none;border:none;color:var(--color-primary);cursor:pointer;font-family:inherit;font-size:var(--font-12,12px);font-weight:600;padding:0}.rm-csel__action:disabled{color:var(--text-muted);cursor:not-allowed}.rm-csel__action:hover:not(:disabled){text-decoration:underline}.rm-csel__action--clear:not(:disabled){color:var(--color-danger)}.rm-csel__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-6) var(--space-10)}.rm-csel__search :deep(svg){color:var(--text-muted);flex-shrink:0}.rm-csel__search-input{background:none;border:none;color:var(--text-primary);font-family:inherit;font-size:var(--font-13,13px);width:100%}.rm-csel__search-input::-moz-placeholder{color:var(--text-muted);font-size:var(--font-12,12px)}.rm-csel__search-input::placeholder{color:var(--text-muted);font-size:var(--font-12,12px)}.rm-csel__search-input:focus-visible{outline:none}.rm-csel__state{color:var(--text-secondary);font-size:var(--font-13,13px);font-style:italic;padding-top:var(--space-8)}.rm-csel__loading{display:flex;flex-direction:column;gap:var(--space-10);padding-top:var(--space-8)}.rm-csel__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-csel__list{display:flex;flex-direction:column;gap:var(--space-4);height:260px;overflow-x:hidden;overflow-y:auto;scrollbar-width:thin}.rm-csel__option{align-items:flex-start;background:none;border:none;border-radius:var(--radius-sm,4px);color:var(--text-primary);cursor:pointer;display:flex;font-family:inherit;font-size:var(--font-13,13px);gap:var(--space-8);line-height:150%;min-width:0;padding:var(--space-2) var(--space-4);text-align:left}.rm-csel__option span{min-width:0;overflow-wrap:anywhere}.rm-csel__option :deep(svg){background:var(--bg-surface);border-radius:50%;flex-shrink:0;margin-top:3px}.rm-csel__hint{color:var(--text-muted);flex-shrink:0;font-size:var(--font-11,11px);white-space:nowrap}.rm-csel__option:hover{background:rgba(var(--brand-rgb),.05)}.rm-csel__option:focus-visible{outline:2px solid var(--color-primary);outline-offset:-2px}.rm-csel__option--add :deep(svg){color:var(--color-primary)}.rm-csel__option--remove :deep(svg){color:var(--color-danger)}@media (max-width:767px){.rm-csel__panel{flex-direction:column}.rm-csel__column--right{border-left:none;border-top:1px solid var(--border-soft)}.rm-csel__list{height:180px}}
|
|
445
499
|
</style>
|