@tekkare/romulus 0.1.94 → 0.1.96
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 +1 -1
- package/dist/runtime/assets/styles/base.css +1 -1
- package/dist/runtime/assets/styles/chrome.css +1 -1
- package/dist/runtime/assets/styles/components.css +1 -1
- package/dist/runtime/assets/styles/shell.css +1 -1
- package/dist/runtime/assets/styles/tokens.css +1 -1
- package/dist/runtime/components/A11yPanel.vue +81 -12
- package/dist/runtime/components/AccordionMenu.vue +1 -1
- package/dist/runtime/components/ActionBar.vue +1 -1
- package/dist/runtime/components/AdvancedSearch.vue +1 -1
- package/dist/runtime/components/AiChat.vue +1 -1
- package/dist/runtime/components/AppFooter.vue +1 -1
- package/dist/runtime/components/AppSidebar.vue +1 -1
- package/dist/runtime/components/Breadcrumb.vue +1 -1
- package/dist/runtime/components/Button.vue +1 -1
- package/dist/runtime/components/ChaptersNav.vue +1 -1
- package/dist/runtime/components/Checkbox.vue +1 -1
- package/dist/runtime/components/CircleAmount.vue +1 -1
- package/dist/runtime/components/ComplexSelect.vue +1 -1
- package/dist/runtime/components/Drawer.vue +1 -1
- package/dist/runtime/components/DropdownSelect.vue +1 -1
- package/dist/runtime/components/EmptyState.vue +1 -1
- package/dist/runtime/components/ExportPanel.vue +1 -1
- package/dist/runtime/components/FileRow.vue +1 -1
- package/dist/runtime/components/FilterBar.vue +1 -1
- package/dist/runtime/components/FilterCheckbox.vue +1 -1
- package/dist/runtime/components/FilterComplex.vue +1 -1
- package/dist/runtime/components/FilterDropdown.vue +1 -1
- package/dist/runtime/components/FilterTabs.vue +1 -1
- package/dist/runtime/components/HybridTable.vue +1 -1
- package/dist/runtime/components/KpiBar.vue +1 -1
- package/dist/runtime/components/LangSelect.vue +1 -1
- package/dist/runtime/components/LoadingState.vue +1 -1
- package/dist/runtime/components/MainLayout.vue +1 -1
- package/dist/runtime/components/MenuItem.vue +1 -1
- package/dist/runtime/components/MenuLink.vue +1 -1
- package/dist/runtime/components/Modal.vue +1 -1
- package/dist/runtime/components/MultipleSelect.vue +1 -1
- package/dist/runtime/components/NavLink.vue +1 -1
- package/dist/runtime/components/Notes.vue +1 -1
- package/dist/runtime/components/NumberInput.vue +1 -1
- package/dist/runtime/components/PageHeader.vue +1 -1
- package/dist/runtime/components/Pill.vue +1 -1
- package/dist/runtime/components/PillTabs.vue +1 -1
- package/dist/runtime/components/ProductCard.vue +1 -1
- package/dist/runtime/components/ResultCard.vue +1 -1
- package/dist/runtime/components/ResultsLine.vue +1 -1
- package/dist/runtime/components/SavedViewCard.vue +1 -1
- package/dist/runtime/components/SavedViews.vue +1 -1
- package/dist/runtime/components/SearchBar.vue +1 -1
- package/dist/runtime/components/SectionCard.vue +1 -1
- package/dist/runtime/components/Segmented.vue +23 -4
- package/dist/runtime/components/SimpleBar.vue +1 -1
- package/dist/runtime/components/SourceCard.vue +1 -1
- package/dist/runtime/components/SourceLine.vue +1 -1
- package/dist/runtime/components/SubMenu.vue +1 -1
- package/dist/runtime/components/Switch.vue +1 -1
- package/dist/runtime/components/TabBar.vue +1 -1
- package/dist/runtime/components/Table.vue +1 -1
- package/dist/runtime/components/TableCard.vue +1 -1
- package/dist/runtime/components/Tabs.vue +28 -2
- package/dist/runtime/components/Tag.vue +1 -1
- package/dist/runtime/components/TagRow.vue +1 -1
- package/dist/runtime/components/TermsGate.vue +307 -0
- package/dist/runtime/components/Toolbar.vue +1 -1
- package/dist/runtime/components/ToolbarContent.vue +1 -1
- package/dist/runtime/components/ToolbarSources.vue +1 -1
- package/dist/runtime/components/Tooltip.vue +1 -1
- package/dist/runtime/components/ViewPill.vue +1 -1
- package/dist/runtime/components/ViewSelect.vue +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
RmTermsGate - conditions d'utilisation a accepter avant d'entrer.
|
|
3
|
+
|
|
4
|
+
Surface bloquante posee une fois dans l'application. Elle parait a la
|
|
5
|
+
premiere connexion, puis a chaque nouvelle version publiee, et ne se ferme
|
|
6
|
+
que par l'acceptation ou le refus. Le refus n'est pas une fermeture : il
|
|
7
|
+
emet `declined`, a l'application de deconnecter.
|
|
8
|
+
|
|
9
|
+
Elle ne sait ni s'authentifier ni appeler un serveur : l'application fournit
|
|
10
|
+
son propre client par `api`, ce qui laisse le composant hors de toute
|
|
11
|
+
plomberie d'authentification et permet de le monter dans n'importe quel
|
|
12
|
+
portail.
|
|
13
|
+
|
|
14
|
+
Les pages `/auth` sont sautees expres : l'accueil de premiere connexion y
|
|
15
|
+
vit deja, et deux ecrans bloquants se superposeraient.
|
|
16
|
+
|
|
17
|
+
ORIGINE AURIGA
|
|
18
|
+
--------------
|
|
19
|
+
Remplace `<arg-terms-gate>` (`argTermsGate.vue`). Les props et les
|
|
20
|
+
evenements gardent leur nom, `lang` est nouveau :
|
|
21
|
+
|
|
22
|
+
| Auriga | Romulus | Note |
|
|
23
|
+
|------------|------------|--------------------------------------------|
|
|
24
|
+
| `api` | `api` | meme contrat : `get()` et `accept(id)` |
|
|
25
|
+
| `enabled` | `enabled` | inchange |
|
|
26
|
+
| - | `lang` | Auriga n'ecrivait qu'en anglais |
|
|
27
|
+
| `@accepted`| `@accepted`| meme charge `{ version }` |
|
|
28
|
+
| `@declined`| `@declined`| inchange |
|
|
29
|
+
|
|
30
|
+
Repris a l'occasion : les couleurs viennent des tokens et non des variables
|
|
31
|
+
Auriga (`--primary`, `--darkest`, `--white`), `--z-modal` remplace le `1000`
|
|
32
|
+
en dur, la carte est un vrai `role="dialog"` avec piege a focus, et le
|
|
33
|
+
bouton de refus n'est plus un `<button>` nu sans etat visible.
|
|
34
|
+
-->
|
|
35
|
+
<script setup lang="ts">
|
|
36
|
+
import { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'
|
|
37
|
+
import { useRoute } from '#app'
|
|
38
|
+
import { useRmDialog } from '../composables/useRmDialog'
|
|
39
|
+
|
|
40
|
+
/** Une version publiee des conditions, telle que l'API la rend. */
|
|
41
|
+
export interface RmTermsVersion {
|
|
42
|
+
id: string
|
|
43
|
+
version: string
|
|
44
|
+
title: string | null
|
|
45
|
+
url: string
|
|
46
|
+
summary: string | null
|
|
47
|
+
publishedAt: string
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Ce que l'application doit savoir faire pour alimenter la porte. */
|
|
51
|
+
export interface RmTermsApi {
|
|
52
|
+
get: () => Promise<{
|
|
53
|
+
current: RmTermsVersion | null
|
|
54
|
+
accepted: boolean
|
|
55
|
+
previouslyAccepted?: boolean
|
|
56
|
+
}>
|
|
57
|
+
accept: (termsVersionId: string) => Promise<unknown>
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const props = withDefaults(
|
|
61
|
+
defineProps<{
|
|
62
|
+
/** Client de l'application. Voir `RmTermsApi`. */
|
|
63
|
+
api: RmTermsApi
|
|
64
|
+
/** Ne consulter l'API qu'une fois le lecteur authentifie. */
|
|
65
|
+
enabled?: boolean
|
|
66
|
+
lang?: 'fr' | 'en'
|
|
67
|
+
}>(),
|
|
68
|
+
{ enabled: true, lang: 'fr' },
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
const emit = defineEmits<{
|
|
72
|
+
accepted: [payload: { version: string }]
|
|
73
|
+
declined: []
|
|
74
|
+
}>()
|
|
75
|
+
|
|
76
|
+
const WORDS = {
|
|
77
|
+
fr: {
|
|
78
|
+
eyebrow: 'Conditions d’utilisation',
|
|
79
|
+
eyebrowUpdated: 'Conditions d’utilisation mises à jour',
|
|
80
|
+
title: 'Avant de continuer',
|
|
81
|
+
titleUpdated: 'Merci de relire les nouvelles conditions',
|
|
82
|
+
intro: 'Merci de lire et d’accepter nos conditions d’utilisation pour commencer à utiliser la plateforme.',
|
|
83
|
+
introUpdated: 'Nos conditions d’utilisation ont changé. Merci de lire et d’accepter la nouvelle version pour continuer à utiliser la plateforme.',
|
|
84
|
+
fallbackTitle: 'Conditions d’utilisation',
|
|
85
|
+
version: 'Version',
|
|
86
|
+
read: 'Lire le document complet',
|
|
87
|
+
check: 'J’ai lu et j’accepte les conditions d’utilisation.',
|
|
88
|
+
accept: 'Accepter et continuer',
|
|
89
|
+
saving: 'Enregistrement…',
|
|
90
|
+
decline: 'Refuser et se déconnecter',
|
|
91
|
+
stale: 'Une version plus récente vient d’être publiée. Rechargement…',
|
|
92
|
+
failed: 'Impossible d’enregistrer votre acceptation. Merci de réessayer.',
|
|
93
|
+
},
|
|
94
|
+
en: {
|
|
95
|
+
eyebrow: 'Terms of use',
|
|
96
|
+
eyebrowUpdated: 'Terms of use updated',
|
|
97
|
+
title: 'Before you continue',
|
|
98
|
+
titleUpdated: 'Please review the new terms',
|
|
99
|
+
intro: 'Please read and accept our terms of use to start using the platform.',
|
|
100
|
+
introUpdated: 'Our terms of use have changed. Please read and accept the new version to keep using the platform.',
|
|
101
|
+
fallbackTitle: 'Terms of use',
|
|
102
|
+
version: 'Version',
|
|
103
|
+
read: 'Read the full document',
|
|
104
|
+
check: 'I have read and I accept the terms of use.',
|
|
105
|
+
accept: 'Accept and continue',
|
|
106
|
+
saving: 'Saving…',
|
|
107
|
+
decline: 'Decline and sign out',
|
|
108
|
+
stale: 'A newer version was just published. Reloading…',
|
|
109
|
+
failed: 'Could not record your acceptance. Please try again.',
|
|
110
|
+
},
|
|
111
|
+
} as const
|
|
112
|
+
|
|
113
|
+
const t = computed(() => WORDS[props.lang] ?? WORDS.fr)
|
|
114
|
+
|
|
115
|
+
/** Par onglet : une fois accepte, ne pas rappeler l'API a chaque navigation. */
|
|
116
|
+
const CACHE_KEY = 'terms_accepted'
|
|
117
|
+
|
|
118
|
+
/** Les pages d'authentification ont leurs propres ecrans bloquants. */
|
|
119
|
+
const IGNORED_PREFIX = '/auth'
|
|
120
|
+
|
|
121
|
+
const route = useRoute()
|
|
122
|
+
const open = ref(false)
|
|
123
|
+
const terms = ref<RmTermsVersion | null>(null)
|
|
124
|
+
const updated = ref(false)
|
|
125
|
+
const checked = ref(false)
|
|
126
|
+
const saving = ref(false)
|
|
127
|
+
const error = ref('')
|
|
128
|
+
const surface = ref<HTMLElement | null>(null)
|
|
129
|
+
|
|
130
|
+
// Le piege a focus et le retour du focus a la fermeture viennent de la, mais
|
|
131
|
+
// pas `Escape` : une porte qui se ferme sur une touche ne bloque rien.
|
|
132
|
+
useRmDialog({ open, surface, close: () => {} })
|
|
133
|
+
|
|
134
|
+
const publishedLabel = computed(() => {
|
|
135
|
+
if (!terms.value?.publishedAt) return ''
|
|
136
|
+
const date = new Date(terms.value.publishedAt)
|
|
137
|
+
return Number.isNaN(date.getTime())
|
|
138
|
+
? ''
|
|
139
|
+
: date.toLocaleDateString(props.lang === 'fr' ? 'fr-FR' : 'en-GB')
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
function cache(value: boolean) {
|
|
143
|
+
try {
|
|
144
|
+
if (value) sessionStorage.setItem(CACHE_KEY, '1')
|
|
145
|
+
else sessionStorage.removeItem(CACHE_KEY)
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
// navigation privee ou stockage coupe : on redemandera au prochain passage
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function cached() {
|
|
153
|
+
try {
|
|
154
|
+
return !!sessionStorage.getItem(CACHE_KEY)
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
return false
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async function check() {
|
|
162
|
+
if (!import.meta.client || !props.enabled || open.value || cached()) return
|
|
163
|
+
if (route.path.startsWith(IGNORED_PREFIX)) return
|
|
164
|
+
try {
|
|
165
|
+
const status = await props.api.get()
|
|
166
|
+
if (status?.accepted) {
|
|
167
|
+
cache(true)
|
|
168
|
+
return
|
|
169
|
+
}
|
|
170
|
+
// Rien de publie : personne n'est arrete.
|
|
171
|
+
if (!status?.current) return
|
|
172
|
+
terms.value = status.current
|
|
173
|
+
updated.value = !!status.previouslyAccepted
|
|
174
|
+
open.value = true
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
// Au mieux : une panne passagere de l'API ne doit pas enfermer le lecteur
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async function accept() {
|
|
182
|
+
if (!terms.value || !checked.value) return
|
|
183
|
+
error.value = ''
|
|
184
|
+
saving.value = true
|
|
185
|
+
try {
|
|
186
|
+
await props.api.accept(terms.value.id)
|
|
187
|
+
cache(true)
|
|
188
|
+
open.value = false
|
|
189
|
+
emit('accepted', { version: terms.value.version })
|
|
190
|
+
}
|
|
191
|
+
catch (e: any) {
|
|
192
|
+
const code = e?.statusCode || e?.response?.status
|
|
193
|
+
if (code === 409) {
|
|
194
|
+
// Une version plus recente est arrivee pendant que la porte etait ouverte
|
|
195
|
+
error.value = t.value.stale
|
|
196
|
+
setTimeout(() => window.location.reload(), 1200)
|
|
197
|
+
}
|
|
198
|
+
else {
|
|
199
|
+
error.value = e?.data?.message || t.value.failed
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
finally {
|
|
203
|
+
saving.value = false
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function decline() {
|
|
208
|
+
cache(false)
|
|
209
|
+
emit('declined')
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Rien ne doit defiler derriere une surface qui bloque l'application.
|
|
213
|
+
let previousOverflow = ''
|
|
214
|
+
watch(open, (value) => {
|
|
215
|
+
if (!import.meta.client) return
|
|
216
|
+
if (value) {
|
|
217
|
+
previousOverflow = document.body.style.overflow
|
|
218
|
+
document.body.style.overflow = 'hidden'
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
document.body.style.overflow = previousOverflow
|
|
222
|
+
}
|
|
223
|
+
})
|
|
224
|
+
|
|
225
|
+
watch(() => props.enabled, check)
|
|
226
|
+
watch(() => route.path, check)
|
|
227
|
+
onMounted(check)
|
|
228
|
+
onBeforeUnmount(() => {
|
|
229
|
+
if (import.meta.client && open.value) document.body.style.overflow = previousOverflow
|
|
230
|
+
})
|
|
231
|
+
</script>
|
|
232
|
+
|
|
233
|
+
<template>
|
|
234
|
+
<Teleport to="body">
|
|
235
|
+
<div v-if="open" class="rm-terms-gate">
|
|
236
|
+
<div
|
|
237
|
+
ref="surface"
|
|
238
|
+
class="rm-terms-gate__card"
|
|
239
|
+
role="dialog"
|
|
240
|
+
aria-modal="true"
|
|
241
|
+
aria-labelledby="rm-terms-gate-title"
|
|
242
|
+
>
|
|
243
|
+
<span class="rm-terms-gate__eyebrow">
|
|
244
|
+
{{ updated ? t.eyebrowUpdated : t.eyebrow }}
|
|
245
|
+
</span>
|
|
246
|
+
|
|
247
|
+
<h2 id="rm-terms-gate-title" class="rm-terms-gate__title">
|
|
248
|
+
{{ updated ? t.titleUpdated : t.title }}
|
|
249
|
+
</h2>
|
|
250
|
+
|
|
251
|
+
<p class="rm-terms-gate__intro">
|
|
252
|
+
{{ updated ? t.introUpdated : t.intro }}
|
|
253
|
+
</p>
|
|
254
|
+
|
|
255
|
+
<div class="rm-terms-gate__doc">
|
|
256
|
+
<div class="rm-terms-gate__doc-head">
|
|
257
|
+
<strong>{{ terms?.title || t.fallbackTitle }}</strong>
|
|
258
|
+
<span class="rm-terms-gate__version">
|
|
259
|
+
{{ t.version }} {{ terms?.version
|
|
260
|
+
}}<template v-if="publishedLabel">, {{ publishedLabel }}</template>
|
|
261
|
+
</span>
|
|
262
|
+
</div>
|
|
263
|
+
<p v-if="terms?.summary" class="rm-terms-gate__summary">{{ terms.summary }}</p>
|
|
264
|
+
<a
|
|
265
|
+
v-if="terms?.url"
|
|
266
|
+
:href="terms.url"
|
|
267
|
+
target="_blank"
|
|
268
|
+
rel="noopener"
|
|
269
|
+
class="rm-terms-gate__link"
|
|
270
|
+
>
|
|
271
|
+
{{ t.read }}
|
|
272
|
+
<RmIcon name="ArrowSquareOut" :size="14" color="var(--color-primary)" />
|
|
273
|
+
</a>
|
|
274
|
+
</div>
|
|
275
|
+
|
|
276
|
+
<label class="rm-terms-gate__check">
|
|
277
|
+
<input v-model="checked" type="checkbox" :disabled="saving">
|
|
278
|
+
<span>{{ t.check }}</span>
|
|
279
|
+
</label>
|
|
280
|
+
|
|
281
|
+
<!-- `alert` et non `status` : l'echec arrete l'action en cours, il doit
|
|
282
|
+
couper ce que le lecteur d'ecran est en train de dire. -->
|
|
283
|
+
<p v-if="error" class="rm-terms-gate__error" role="alert">{{ error }}</p>
|
|
284
|
+
|
|
285
|
+
<RmButton
|
|
286
|
+
variant="primary"
|
|
287
|
+
block
|
|
288
|
+
:disabled="!checked || saving"
|
|
289
|
+
:loading="saving"
|
|
290
|
+
@click="accept"
|
|
291
|
+
>
|
|
292
|
+
{{ saving ? t.saving : t.accept }}
|
|
293
|
+
</RmButton>
|
|
294
|
+
|
|
295
|
+
<div class="rm-terms-gate__decline">
|
|
296
|
+
<RmButton variant="text" block :disabled="saving" @click="decline">
|
|
297
|
+
{{ t.decline }}
|
|
298
|
+
</RmButton>
|
|
299
|
+
</div>
|
|
300
|
+
</div>
|
|
301
|
+
</div>
|
|
302
|
+
</Teleport>
|
|
303
|
+
</template>
|
|
304
|
+
|
|
305
|
+
<style scoped>
|
|
306
|
+
.rm-terms-gate{align-items:center;backdrop-filter:blur(12px);background:rgba(0,0,0,.6);display:flex;inset:0;justify-content:center;padding:var(--space-24);position:fixed;z-index:var(--z-modal)}.rm-terms-gate__card{background:var(--bg-surface);border-radius:var(--radius-2xl);box-shadow:var(--shadow-lg);font-family:var(--font-sans);max-height:calc(100vh - 48px);max-width:480px;overflow-y:auto;padding:var(--space-24);width:100%}.rm-terms-gate__eyebrow{color:var(--color-primary);display:inline-block;font-size:var(--font-13);font-weight:600;margin-bottom:var(--space-8)}.rm-terms-gate__title{color:var(--text-primary);font-size:var(--font-18);font-weight:700;margin:0 0 var(--space-8)}.rm-terms-gate__intro{color:var(--text-secondary);font-size:var(--font-14);line-height:1.6;margin:0 0 var(--space-20)}.rm-terms-gate__doc{border:1px solid var(--border-default);border-radius:var(--radius-lg);display:flex;flex-direction:column;gap:var(--space-8);margin-bottom:var(--space-16);padding:var(--space-16)}.rm-terms-gate__doc-head{color:var(--text-primary);display:flex;flex-direction:column;font-size:var(--font-14);gap:var(--space-2)}.rm-terms-gate__version{color:var(--text-muted);font-size:var(--font-12);font-weight:400}.rm-terms-gate__summary{color:var(--text-secondary);font-size:var(--font-14);line-height:1.6;margin:0;white-space:pre-line}.rm-terms-gate__link{align-items:center;color:var(--color-primary);display:inline-flex;font-size:var(--font-14);font-weight:600;gap:var(--space-6);text-decoration:none}.rm-terms-gate__link:hover{text-decoration:underline}.rm-terms-gate__check{align-items:flex-start;color:var(--text-primary);cursor:pointer;display:flex;font-size:var(--font-14);gap:var(--space-8);line-height:1.5;margin-bottom:var(--space-16)}.rm-terms-gate__check input{accent-color:var(--color-primary);cursor:pointer;flex-shrink:0;height:18px;margin:2px 0 0;width:18px}.rm-terms-gate__decline{margin-top:var(--space-8)}.rm-terms-gate__error{color:var(--color-danger);font-size:var(--font-13);margin:0 0 var(--space-12)}
|
|
307
|
+
</style>
|
|
@@ -74,5 +74,5 @@ function open(item: RmToolbarItem) {
|
|
|
74
74
|
</template>
|
|
75
75
|
|
|
76
76
|
<style scoped>
|
|
77
|
-
.rm-toolbar{align-items:flex-start;border:1px solid var(--border-default);border-radius:var(--radius-md,8px);display:inline-flex;flex-direction:column;gap:
|
|
77
|
+
.rm-toolbar{align-items:flex-start;border:1px solid var(--border-default);border-radius:var(--radius-md,8px);display:inline-flex;flex-direction:column;gap:var(--space-4);padding:var(--space-4)}.rm-toolbar__item{align-items:center;background:none;border:none;border-radius:var(--radius-sm,4px);cursor:pointer;display:flex;gap:var(--space-8);justify-content:flex-end;padding:var(--space-10)}.rm-toolbar__item:hover{background:var(--bg-hover)}.rm-toolbar__item:focus-visible{outline:2px solid var(--color-primary);outline-offset:-2px}.rm-toolbar__mark{display:flex;position:relative}.rm-toolbar__count{align-items:center;background:var(--color-danger);border-radius:var(--radius-pill,30px);color:var(--color-text-inverse);display:flex;font-size:var(--font-10,10px);font-weight:900;height:16px;justify-content:center;line-height:normal;position:absolute;right:-5px;top:-5px;width:16px}
|
|
78
78
|
</style>
|
|
@@ -90,5 +90,5 @@ function labelOf(name: string) {
|
|
|
90
90
|
</template>
|
|
91
91
|
|
|
92
92
|
<style scoped>
|
|
93
|
-
.rm-tbc{height:100%}.rm-tbc,.rm-tbc__rail{align-items:flex-start;display:flex}.rm-tbc__rail{align-self:stretch;background:var(--bg-surface-2);flex-direction:column;gap:
|
|
93
|
+
.rm-tbc{height:100%}.rm-tbc,.rm-tbc__rail{align-items:flex-start;display:flex}.rm-tbc__rail{align-self:stretch;background:var(--bg-surface-2);flex-direction:column;gap:var(--space-16);padding:var(--space-24) 0;width:160px}.rm-tbc__close{align-items:center;background:var(--bg-surface-3);border:none;border-radius:var(--radius-md,8px);color:var(--text-secondary);cursor:pointer;display:flex;font-family:inherit;font-size:var(--font-14,14px);gap:var(--space-6);line-height:1.6;margin:0 16px;padding:var(--space-6) var(--space-12) var(--space-6) var(--space-8)}.rm-tbc__close:hover{background:var(--bg-hover)}.rm-tbc__tab{align-items:center;align-self:stretch;background:none;border:none;border-bottom:2px solid transparent;color:var(--text-secondary);cursor:pointer;display:flex;font-family:inherit;font-size:var(--font-14,14px);font-weight:500;gap:var(--space-4);justify-content:space-between;line-height:normal;padding:0 var(--space-16) var(--space-4)}.rm-tbc__tab.is-active{border-bottom-color:var(--color-primary);color:var(--text-primary)}.rm-tbc__tab.is-active :deep(svg){color:var(--color-primary)}.rm-tbc__tab:focus-visible{outline:2px solid var(--color-primary);outline-offset:-2px}.rm-tbc__tab-left{align-items:center;display:flex;gap:var(--space-4)}.rm-tbc__count{align-items:center;background:var(--color-danger);border-radius:var(--radius-pill,30px);color:var(--color-text-inverse);display:flex;font-size:var(--font-10,10px);font-weight:900;height:16px;justify-content:center;line-height:normal;width:16px}.rm-tbc__panel{align-items:flex-start;align-self:stretch;background:var(--bg-surface);border-left:1px solid var(--border-default);display:flex;flex:1;flex-direction:column;gap:var(--space-24);min-width:0;overflow-y:auto;padding:var(--space-24);scrollbar-width:thin}
|
|
94
94
|
</style>
|
|
@@ -66,5 +66,5 @@ const t = computed(() => WORDS[props.lang])
|
|
|
66
66
|
</template>
|
|
67
67
|
|
|
68
68
|
<style scoped>
|
|
69
|
-
.rm-tbs{align-self:stretch;display:flex;flex-direction:column;gap:
|
|
69
|
+
.rm-tbs{align-self:stretch;display:flex;flex-direction:column;gap:var(--space-16)}.rm-tbs__title{color:var(--text-primary);font-family:var(--font-serif);font-size:var(--font-18,18px);font-weight:700;margin:0}.rm-tbs__legal{color:var(--text-secondary);display:flex;flex-direction:column;font-size:var(--font-12,12px);gap:var(--space-8);line-height:1.6}.rm-tbs__legal p{margin:0}.rm-tbs__link{color:var(--color-primary);text-decoration:underline;text-underline-offset:3px}.rm-tbs__list{align-self:stretch;display:flex;flex-direction:column;gap:var(--space-12)}
|
|
70
70
|
</style>
|
|
@@ -63,5 +63,5 @@ const id = `rm-tooltip-${useId()}`
|
|
|
63
63
|
</template>
|
|
64
64
|
|
|
65
65
|
<style scoped>
|
|
66
|
-
.rm-tooltip{display:inline-flex;position:relative;width:-moz-fit-content;width:fit-content}.rm-tooltip__bubble{background:var(--r-color-gray-900);border-radius:var(--radius-sm,4px);color:var(--r-color-white);display:-webkit-box;font-size:var(--font-13,13px);font-weight:400;-webkit-line-clamp:4;line-height:1.6;max-width:220px;padding:
|
|
66
|
+
.rm-tooltip{display:inline-flex;position:relative;width:-moz-fit-content;width:fit-content}.rm-tooltip__bubble{background:var(--r-color-gray-900);border-radius:var(--radius-sm,4px);color:var(--r-color-white);display:-webkit-box;font-size:var(--font-13,13px);font-weight:400;-webkit-line-clamp:4;line-height:1.6;max-width:220px;padding:var(--space-4) var(--space-12);position:absolute;text-align:left;white-space:pre-line;width:-moz-max-content;width:max-content;z-index:60;-webkit-box-orient:vertical;opacity:0;overflow:hidden;transition:opacity var(--duration-fast,.15s) var(--ease-out,ease);visibility:hidden}.rm-tooltip__bubble--full{display:block;overflow:visible}.rm-tooltip:focus-within .rm-tooltip__bubble,.rm-tooltip:hover .rm-tooltip__bubble{opacity:1;visibility:visible}.rm-tooltip__bubble--top{bottom:calc(100% + 6px);left:50%;transform:translateX(-50%)}.rm-tooltip__bubble--bottom{left:50%;top:calc(100% + 6px);transform:translateX(-50%)}.rm-tooltip__bubble--right{left:calc(100% + 8px);top:50%;transform:translateY(-50%)}.rm-tooltip__bubble--left{right:calc(100% + 8px);top:50%;transform:translateY(-50%)}
|
|
67
67
|
</style>
|
|
@@ -209,5 +209,5 @@ onBeforeUnmount(() => {
|
|
|
209
209
|
</template>
|
|
210
210
|
|
|
211
211
|
<style scoped>
|
|
212
|
-
.rm-vpill{position:relative}.rm-vpill,.rm-vpill__pill{align-items:center;display:flex}.rm-vpill__pill{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-pill);color:var(--text-primary);cursor:pointer;font-family:var(--font-sans);font-size:var(--font-14);font-weight:var(--weight-medium);gap:
|
|
212
|
+
.rm-vpill{position:relative}.rm-vpill,.rm-vpill__pill{align-items:center;display:flex}.rm-vpill__pill{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-pill);color:var(--text-primary);cursor:pointer;font-family:var(--font-sans);font-size:var(--font-14);font-weight:var(--weight-medium);gap:var(--space-6);height:var(--rm-fbar-field-h,32px);padding:0 14px;white-space:nowrap}.rm-vpill__pill:hover{background:var(--bg-surface-3)}.rm-vpill__pill.is-open{border-color:var(--color-primary);color:var(--color-primary)}.rm-vpill__icon{color:currentColor;flex-shrink:0}.rm-vpill__key{color:var(--text-muted);font-weight:var(--weight-normal)}.rm-vpill__value{max-width:220px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rm-vpill__pill.has-unsaved{border-color:var(--color-warning)}.rm-vpill__dot{border-radius:50%;flex-shrink:0;height:8px;width:8px}.rm-vpill__dot--applied{animation:rm-vpill-pulse-applied 2s ease-out infinite;background:var(--color-success)}.rm-vpill__dot--unsaved{animation:rm-vpill-pulse 2s ease-out infinite;background:var(--color-warning)}@keyframes rm-vpill-pulse{0%{box-shadow:0 0 0 0 rgba(217,119,6,.6)}70%{box-shadow:0 0 0 6px rgba(217,119,6,0)}to{box-shadow:0 0 0 0 rgba(217,119,6,0)}}@keyframes rm-vpill-pulse-applied{0%{box-shadow:0 0 0 0 rgba(22,163,74,.55)}70%{box-shadow:0 0 0 6px rgba(22,163,74,0)}to{box-shadow:0 0 0 0 rgba(22,163,74,0)}}@media (prefers-reduced-motion:reduce){.rm-vpill__dot,.rm-vpill__unsaved-dot:before{animation:none}}.rm-vpill__caret{color:var(--text-muted);flex-shrink:0}.rm-vpill__menu{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:8px;box-shadow:var(--shadow-lg);box-sizing:border-box;font-family:var(--font-sans);left:0;max-width:460px;min-width:320px;padding:var(--space-6);position:absolute;top:calc(100% + 6px);z-index:60}.rm-vpill__unsaved{align-items:center;background:var(--color-warning-bg);border-radius:var(--radius-md);color:var(--color-warning);display:flex;font-size:var(--font-12);gap:var(--space-8);padding:var(--space-8) var(--space-12)}.rm-vpill__unsaved-dot{align-items:center;display:inline-flex;flex-shrink:0;height:14px;justify-content:center;width:14px}.rm-vpill__unsaved-dot:before{animation:rm-vpill-pulse 2s ease-out infinite;background:var(--color-warning);border-radius:50%;content:"";height:7px;width:7px}.rm-vpill__unsaved-label{flex:1;font-weight:var(--weight-semibold)}.rm-vpill__unsaved-cta{background:transparent;border:none;color:var(--color-warning);cursor:pointer;font-family:inherit;font-size:inherit;font-weight:var(--weight-bold);padding:0;text-decoration:underline;text-underline-offset:2px}.rm-vpill__unsaved-cta:hover{color:var(--text-primary)}.rm-vpill__divider{background:var(--border-soft);height:1px;margin:6px -6px}.rm-vpill__section{color:var(--text-muted);font-size:var(--font-10);font-weight:var(--weight-bold);letter-spacing:.08em;margin:0;padding:var(--space-8) var(--space-12) var(--space-4) 34px;text-align:left;text-transform:uppercase}.rm-vpill__item{align-items:center;background:none;border:none;border-radius:var(--radius-md);color:var(--text-secondary);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;transition:background .1s,color .1s;width:100%}.rm-vpill__item:hover{background:var(--bg-hover);color:var(--text-primary)}.rm-vpill__item.is-active{background:var(--bg-hover);color:var(--color-secondary);font-weight:var(--weight-semibold)}.rm-vpill__name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rm-vpill__item--view .rm-vpill__check{color:var(--color-secondary);flex-shrink:0;opacity:0;transition:opacity .1s}.rm-vpill__item--view.is-active .rm-vpill__check{opacity:1}
|
|
213
213
|
</style>
|
|
@@ -77,5 +77,5 @@ onBeforeUnmount(() => {
|
|
|
77
77
|
</template>
|
|
78
78
|
|
|
79
79
|
<style scoped>
|
|
80
|
-
.rm-vsel{position:relative}.rm-vsel,.rm-vsel__pill{align-items:center;display:flex}.rm-vsel__pill{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-pill);color:var(--text-primary);cursor:pointer;font-family:var(--font-sans);font-size:var(--font-14);font-weight:var(--weight-medium);gap:
|
|
80
|
+
.rm-vsel{position:relative}.rm-vsel,.rm-vsel__pill{align-items:center;display:flex}.rm-vsel__pill{background:var(--bg-surface);border:1px solid var(--border-default);border-radius:var(--radius-pill);color:var(--text-primary);cursor:pointer;font-family:var(--font-sans);font-size:var(--font-14);font-weight:var(--weight-medium);gap:var(--space-6);height:var(--rm-fbar-field-h,32px);padding:0 14px;white-space:nowrap}.rm-vsel__pill:hover{background:var(--bg-surface-3)}.rm-vsel__pill.is-open{border-color:var(--color-primary);color:var(--color-primary)}.rm-vsel__label{color:var(--text-muted);font-weight:var(--weight-normal)}.rm-vsel__caret{transition:transform var(--duration-fast)}.rm-vsel__pill.is-open .rm-vsel__caret{transform:rotate(180deg)}.rm-vsel__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;gap:var(--space-2);left:0;min-width:180px;padding:var(--space-6);position:absolute;top:calc(100% + 6px);z-index:120}.rm-vsel__option{align-items:center;background:none;border:none;border-radius:var(--radius-md);color:var(--text-primary);cursor:pointer;display:flex;font-family:var(--font-sans);font-size:var(--font-14);gap:var(--space-8);padding:var(--space-8) var(--space-10);text-align:left}.rm-vsel__option:hover{background:var(--bg-surface-3)}.rm-vsel__option.is-active{color:var(--color-primary);font-weight:var(--weight-semibold)}
|
|
81
81
|
</style>
|