@lab-anssi/ui-kit 1.13.0 → 1.14.1

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.
@@ -0,0 +1,3 @@
1
+ <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M12 22C6.477 22 2 17.523 2 12C2 6.477 6.477 2 12 2C17.523 2 22 6.477 22 12C22 17.523 17.523 22 12 22ZM12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM11 15H13V17H11V15ZM13 13.355V14H11V12.5C11 11.9477 11.4477 11.5 12 11.5C12.7902 11.5 13.4448 10.887 13.4967 10.0985C13.5486 9.31006 12.9799 8.61655 12.1966 8.51295C11.4133 8.40935 10.6839 8.93117 10.529 9.706L8.567 9.313C8.90349 7.63124 10.4087 6.44085 12.1228 6.50102C13.8368 6.56119 15.2549 7.8542 15.4726 9.55541C15.6904 11.2566 14.6436 12.8651 13 13.355Z" fill="#0D0C21"/>
3
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M2 13.2823H14V14.6156H2V13.2823ZM8.66667 9.39697L12.714 5.34897L13.6567 6.29164L8 11.949L2.34333 6.29231L3.286 5.34897L7.33333 9.39564V1.94897H8.66667V9.39697Z" fill="black"/>
3
+ </svg>
package/dist/index.d.ts CHANGED
@@ -14,3 +14,4 @@ export { default as BriqueContenuADeuxColonnes } from "./lab/vitrines-produits/b
14
14
  export { default as PresentationANSSI } from "./lab/vitrines-produits/briques/PresentationANSSI.svelte";
15
15
  export { default as RejoindreLaCommunaute } from "./lab/vitrines-produits/briques/RejoindreLaCommunaute.svelte";
16
16
  export { default as BandeauTitre } from "./lab/blog/BandeauTitre.svelte";
17
+ export { default as PageCrisp } from "./lab/blog/PageCrisp.svelte";
package/dist/index.js CHANGED
@@ -14,3 +14,4 @@ export { default as BriqueContenuADeuxColonnes } from "./lab/vitrines-produits/b
14
14
  export { default as PresentationANSSI } from "./lab/vitrines-produits/briques/PresentationANSSI.svelte";
15
15
  export { default as RejoindreLaCommunaute } from "./lab/vitrines-produits/briques/RejoindreLaCommunaute.svelte";
16
16
  export { default as BandeauTitre } from "./lab/blog/BandeauTitre.svelte";
17
+ export { default as PageCrisp } from "./lab/blog/PageCrisp.svelte";
@@ -0,0 +1,19 @@
1
+ <svg
2
+ width="16"
3
+ height="16"
4
+ viewBox="0 0 16 16"
5
+ fill="none"
6
+ xmlns="http://www.w3.org/2000/svg"
7
+ class="chevron"
8
+ >
9
+ <path
10
+ fill-rule="evenodd"
11
+ clip-rule="evenodd"
12
+ d="M7.99999 8.78096L11.3 5.48096L12.2427 6.42362L7.99999 10.6663L3.75732 6.42362L4.69999 5.48096L7.99999 8.78096Z"
13
+ fill="black"
14
+ />
15
+ </svg>
16
+
17
+ <style>path {
18
+ fill: var(--sommaire-actif-couleur);
19
+ }</style>
@@ -0,0 +1,25 @@
1
+ /** @typedef {typeof __propDef.props} IconeChevronBasProps */
2
+ /** @typedef {typeof __propDef.events} IconeChevronBasEvents */
3
+ /** @typedef {typeof __propDef.slots} IconeChevronBasSlots */
4
+ export default class IconeChevronBas extends SvelteComponent<{
5
+ [x: string]: never;
6
+ }, {
7
+ [evt: string]: CustomEvent<any>;
8
+ }, {}> {
9
+ }
10
+ export type IconeChevronBasProps = typeof __propDef.props;
11
+ export type IconeChevronBasEvents = typeof __propDef.events;
12
+ export type IconeChevronBasSlots = typeof __propDef.slots;
13
+ import { SvelteComponent } from "svelte";
14
+ declare const __propDef: {
15
+ props: {
16
+ [x: string]: never;
17
+ };
18
+ events: {
19
+ [evt: string]: CustomEvent<any>;
20
+ };
21
+ slots: {};
22
+ exports?: undefined;
23
+ bindings?: undefined;
24
+ };
25
+ export {};
@@ -0,0 +1,12 @@
1
+ <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path
3
+ fill-rule="evenodd"
4
+ clip-rule="evenodd"
5
+ d="M2 2.66626H14V3.99959H2V2.66626ZM2 7.33293H10V8.66626H2V7.33293ZM2 11.9996H14V13.3329H2V11.9996Z"
6
+ fill="black"
7
+ />
8
+ </svg>
9
+
10
+ <style>path {
11
+ fill: var(--sommaire-actif-couleur);
12
+ }</style>
@@ -0,0 +1,25 @@
1
+ /** @typedef {typeof __propDef.props} IconeMenuLateralProps */
2
+ /** @typedef {typeof __propDef.events} IconeMenuLateralEvents */
3
+ /** @typedef {typeof __propDef.slots} IconeMenuLateralSlots */
4
+ export default class IconeMenuLateral extends SvelteComponent<{
5
+ [x: string]: never;
6
+ }, {
7
+ [evt: string]: CustomEvent<any>;
8
+ }, {}> {
9
+ }
10
+ export type IconeMenuLateralProps = typeof __propDef.props;
11
+ export type IconeMenuLateralEvents = typeof __propDef.events;
12
+ export type IconeMenuLateralSlots = typeof __propDef.slots;
13
+ import { SvelteComponent } from "svelte";
14
+ declare const __propDef: {
15
+ props: {
16
+ [x: string]: never;
17
+ };
18
+ events: {
19
+ [evt: string]: CustomEvent<any>;
20
+ };
21
+ slots: {};
22
+ exports?: undefined;
23
+ bindings?: undefined;
24
+ };
25
+ export {};
@@ -0,0 +1,247 @@
1
+ <svelte:options
2
+ customElement={{
3
+ tag: "lab-anssi-page-crisp",
4
+ props: {
5
+ contenu: { reflect: false, type: "String", attribute: "contenu" },
6
+ tableDesMatieres: { reflect: false, type: "Array", attribute: "table-des-matieres" },
7
+ },
8
+ }}
9
+ />
10
+
11
+ <script>import SommaireMobile from "./SommaireMobile.svelte";
12
+ import { onDestroy, tick } from "svelte";
13
+ import SommaireBureau from "./SommaireBureau.svelte";
14
+ export let contenu;
15
+ export let tableDesMatieres;
16
+ let composant;
17
+ let observateurDIntersection;
18
+ const observeLesSections = () => {
19
+ observateurDIntersection = new IntersectionObserver(
20
+ (sections) => {
21
+ sections.forEach((section) => {
22
+ const titreDeLaSection = section.target.querySelector("h2");
23
+ const lesLiens = composant.querySelectorAll(
24
+ `.sommaire ul li a[href='#${titreDeLaSection.id}']`
25
+ );
26
+ if (!lesLiens) return;
27
+ if (section.isIntersecting) {
28
+ lesLiens.forEach((l) => l.parentElement.classList.add("actif"));
29
+ const menuMobileVisible = composant.querySelector("#section-active");
30
+ if (menuMobileVisible) menuMobileVisible.textContent = titreDeLaSection.textContent;
31
+ } else lesLiens.forEach((l) => l.parentElement.classList.remove("actif"));
32
+ });
33
+ },
34
+ { rootMargin: "-30% 0% -62% 0%" }
35
+ );
36
+ const lesSections = composant.querySelectorAll("article .contenu section");
37
+ lesSections.forEach((s) => observateurDIntersection.observe(s));
38
+ };
39
+ $: if (contenu) tick().then(observeLesSections);
40
+ const attendChargementImages = async () => {
41
+ const images = composant.querySelectorAll("img");
42
+ await Promise.all(
43
+ Array.from(images).map((image) => {
44
+ if (image.complete) return Promise.resolve();
45
+ return new Promise((res) => {
46
+ image.addEventListener("load", res);
47
+ image.addEventListener("error", res);
48
+ });
49
+ })
50
+ );
51
+ };
52
+ const scroll = (cible) => {
53
+ if (cible) {
54
+ tick().then(async () => {
55
+ const ancre = composant && composant.querySelector(cible);
56
+ if (ancre) {
57
+ await attendChargementImages();
58
+ ancre.scrollIntoView(true);
59
+ }
60
+ });
61
+ }
62
+ };
63
+ $: if (contenu) scroll(window.location.hash);
64
+ const ancreOuverte = (evenement) => scroll(`#${evenement.detail}`);
65
+ onDestroy(() => {
66
+ const lesSections = composant.querySelectorAll("section");
67
+ lesSections.forEach((s) => {
68
+ if (observateurDIntersection) observateurDIntersection.unobserve(s);
69
+ });
70
+ });
71
+ </script>
72
+
73
+ <div bind:this={composant}>
74
+ <SommaireMobile {tableDesMatieres} on:ancreOuverte={ancreOuverte} />
75
+
76
+ <article>
77
+ <SommaireBureau {tableDesMatieres} on:ancreOuverte={ancreOuverte} />
78
+ <div class="contenu">
79
+ <!-- eslint-disable-next-line svelte/no-at-html-tags-->
80
+ {@html contenu}
81
+ </div>
82
+ </article>
83
+ </div>
84
+
85
+ <style>article {
86
+ font-family: Marianne, sans-serif;
87
+ color: #3a3a3a;
88
+ display: flex;
89
+ flex-direction: column;
90
+ max-width: 1200px;
91
+ margin: 0 auto;
92
+ padding: 48px 16px 72px;
93
+ }
94
+ @media (min-width: 932px) {
95
+ article {
96
+ padding: 48px 24px 72px;
97
+ flex-direction: row;
98
+ gap: 24px;
99
+ }
100
+ }
101
+ article .contenu {
102
+ display: flex;
103
+ flex-direction: column;
104
+ gap: 72px;
105
+ }
106
+ article .contenu :global(section) {
107
+ display: flex;
108
+ flex-direction: column;
109
+ gap: 32px;
110
+ }
111
+ article .contenu :global(p) {
112
+ margin: 0;
113
+ font-size: 1rem;
114
+ line-height: 1.5rem;
115
+ font-weight: 400;
116
+ }
117
+ article .contenu :global(h2) {
118
+ color: #161616;
119
+ font-size: 1.75rem;
120
+ line-height: 2.25rem;
121
+ font-weight: 700;
122
+ margin: 0;
123
+ scroll-margin-top: 50px; /* Hauteur de la barre de navigation */
124
+ }
125
+ @media (min-width: 576px) {
126
+ article .contenu :global(h2) {
127
+ font-size: 2rem;
128
+ line-height: 2.5rem;
129
+ }
130
+ }
131
+ @media (min-width: 932px) {
132
+ article .contenu :global(h2) {
133
+ scroll-margin-top: 0;
134
+ }
135
+ }
136
+ article .contenu :global(h3) {
137
+ color: #161616;
138
+ font-size: 1.375rem;
139
+ line-height: 1.75rem;
140
+ font-weight: 700;
141
+ margin: 0;
142
+ }
143
+ @media (min-width: 576px) {
144
+ article .contenu :global(h3) {
145
+ font-size: 1.5rem;
146
+ line-height: 2rem;
147
+ }
148
+ }
149
+ article .contenu :global(h4) {
150
+ color: #161616;
151
+ font-size: 1.125rem;
152
+ line-height: 1.5rem;
153
+ font-weight: 700;
154
+ margin: 0;
155
+ }
156
+ @media (min-width: 576px) {
157
+ article .contenu :global(h4) {
158
+ font-size: 1.25rem;
159
+ line-height: 1.75rem;
160
+ }
161
+ }
162
+ article .contenu :global(img),
163
+ article .contenu :global(video) {
164
+ width: 100%;
165
+ }
166
+ article .contenu :global(video) {
167
+ border-radius: 10px;
168
+ }
169
+ article .contenu :global(.conteneur-video .legende) {
170
+ font-style: italic;
171
+ text-align: center;
172
+ margin: 0;
173
+ padding: 0;
174
+ }
175
+ article .contenu :global(.information) {
176
+ background: #e8edff;
177
+ padding: 16px 16px 16px 24px;
178
+ border-radius: 4px;
179
+ color: #0163cb;
180
+ border-left: 4px solid #0163cb;
181
+ font-size: 0.875rem;
182
+ line-height: 1.5rem;
183
+ display: flex;
184
+ flex-direction: column;
185
+ }
186
+ article .contenu :global(.information):before {
187
+ content: "Information";
188
+ font-weight: bold;
189
+ }
190
+ article .contenu :global(.aide) {
191
+ background: #f6f6f6;
192
+ position: relative;
193
+ padding: 24px 24px 24px 64px;
194
+ border-radius: 4px;
195
+ font-size: 0.875rem;
196
+ line-height: 1.5rem;
197
+ }
198
+ article .contenu :global(.aide):before {
199
+ content: "";
200
+ display: block;
201
+ background-image: url("https://lab-anssi-ui-kit-prod-s3-assets.cellar-c2.services.clever-cloud.com/icones/aide.svg");
202
+ width: 24px;
203
+ height: 24px;
204
+ position: absolute;
205
+ top: 24px;
206
+ left: 24px;
207
+ }
208
+ article .contenu :global(a) {
209
+ color: var(--couleur-lien);
210
+ text-decoration: underline;
211
+ text-underline-offset: 4px;
212
+ text-decoration-thickness: 1px;
213
+ }
214
+ article .contenu :global(a):hover {
215
+ text-decoration-thickness: 2px;
216
+ }
217
+ article .contenu :global(a.telechargement) {
218
+ display: inline-flex;
219
+ align-items: center;
220
+ gap: 8px;
221
+ text-decoration: none;
222
+ position: relative;
223
+ }
224
+ article .contenu :global(a.telechargement):after {
225
+ content: "";
226
+ display: block;
227
+ background: url("https://lab-anssi-ui-kit-prod-s3-assets.cellar-c2.services.clever-cloud.com/icones/telecharger.svg");
228
+ filter: var(--filtre-couleur-primaire);
229
+ width: 16px;
230
+ height: 16px;
231
+ }
232
+ article .contenu :global(a.telechargement):before {
233
+ content: "";
234
+ position: absolute;
235
+ bottom: 0;
236
+ left: 0;
237
+ width: 100%;
238
+ height: 1px;
239
+ background-color: var(--couleur-lien);
240
+ }
241
+ article .contenu :global(a.telechargement):hover:before {
242
+ bottom: -1px;
243
+ height: 2px;
244
+ }
245
+ article .contenu :global(ul li) {
246
+ padding-bottom: 8px;
247
+ }</style>
@@ -0,0 +1,20 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import type { TableDesMatieres } from "../../types";
3
+ declare const __propDef: {
4
+ props: {
5
+ contenu: string;
6
+ tableDesMatieres: TableDesMatieres;
7
+ };
8
+ events: {
9
+ [evt: string]: CustomEvent<any>;
10
+ };
11
+ slots: {};
12
+ exports?: {} | undefined;
13
+ bindings?: string | undefined;
14
+ };
15
+ export type PageCrispProps = typeof __propDef.props;
16
+ export type PageCrispEvents = typeof __propDef.events;
17
+ export type PageCrispSlots = typeof __propDef.slots;
18
+ export default class PageCrisp extends SvelteComponent<PageCrispProps, PageCrispEvents, PageCrispSlots> {
19
+ }
20
+ export {};
@@ -0,0 +1,69 @@
1
+ <script>import { createEventDispatcher } from "svelte";
2
+ export let tableDesMatieres;
3
+ const emets = createEventDispatcher();
4
+ const ouvreEntree = (ancre) => {
5
+ emets("ancreOuverte", ancre);
6
+ };
7
+ </script>
8
+
9
+ <div class="sommaire sommaire-deplie">
10
+ <ul>
11
+ {#each tableDesMatieres as entree (entree.id)}
12
+ <li>
13
+ <a href={`#${entree.id}`} on:click={() => ouvreEntree(entree.id)}>
14
+ <!-- eslint-disable-next-line svelte/no-at-html-tags -->
15
+ {@html entree.texte}
16
+ </a>
17
+ </li>
18
+ {/each}
19
+ </ul>
20
+ </div>
21
+
22
+ <style>.sommaire-deplie {
23
+ display: none;
24
+ width: 282px;
25
+ flex: 0 0 auto;
26
+ align-self: flex-start;
27
+ font-family: Marianne, sans-serif;
28
+ }
29
+ @media (min-width: 932px) {
30
+ .sommaire-deplie {
31
+ display: flex;
32
+ flex-direction: column;
33
+ position: sticky;
34
+ top: 0;
35
+ }
36
+ }
37
+ .sommaire-deplie ul {
38
+ list-style-type: none;
39
+ padding: 0;
40
+ margin: 0 0 40px;
41
+ }
42
+ .sommaire-deplie ul li {
43
+ padding-top: 12px;
44
+ padding-bottom: 12px;
45
+ }
46
+ .sommaire-deplie ul li.actif {
47
+ font-weight: bold;
48
+ }
49
+ .sommaire-deplie ul li.actif a {
50
+ color: var(--sommaire-actif-couleur);
51
+ border-left: 2px solid var(--sommaire-actif-indicateur-couleur);
52
+ padding-left: 6px;
53
+ font-size: 1rem;
54
+ font-style: normal;
55
+ font-weight: 700;
56
+ line-height: 1.5rem;
57
+ }
58
+ .sommaire-deplie ul li a {
59
+ color: #161616;
60
+ border-bottom: none;
61
+ text-decoration: none;
62
+ padding-left: 8px;
63
+ display: inline-block;
64
+ }
65
+ .sommaire-deplie span {
66
+ margin-bottom: 16px;
67
+ font-size: 0.85rem;
68
+ line-height: 1.5rem;
69
+ }</style>
@@ -0,0 +1,21 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import type { TableDesMatieres } from "../../types";
3
+ declare const __propDef: {
4
+ props: {
5
+ tableDesMatieres: TableDesMatieres;
6
+ };
7
+ events: {
8
+ ancreOuverte: CustomEvent<string>;
9
+ } & {
10
+ [evt: string]: CustomEvent<any>;
11
+ };
12
+ slots: {};
13
+ exports?: {} | undefined;
14
+ bindings?: string | undefined;
15
+ };
16
+ export type SommaireBureauProps = typeof __propDef.props;
17
+ export type SommaireBureauEvents = typeof __propDef.events;
18
+ export type SommaireBureauSlots = typeof __propDef.slots;
19
+ export default class SommaireBureau extends SvelteComponent<SommaireBureauProps, SommaireBureauEvents, SommaireBureauSlots> {
20
+ }
21
+ export {};
@@ -0,0 +1,114 @@
1
+ <script>import { createEventDispatcher } from "svelte";
2
+ import IconeMenuLateral from "./IconeMenuLateral.svelte";
3
+ import IconeChevronBas from "./IconeChevronBas.svelte";
4
+ export let tableDesMatieres;
5
+ let detailsElement;
6
+ const emets = createEventDispatcher();
7
+ const ouvreEntree = (ancre) => {
8
+ detailsElement.open = false;
9
+ emets("ancreOuverte", ancre);
10
+ };
11
+ </script>
12
+
13
+ <div class="sommaire sommaire-replie">
14
+ <details bind:this={detailsElement}>
15
+ <summary>
16
+ <div class="entete-filtres">
17
+ <IconeMenuLateral />
18
+ <span id="section-active" class="titre-menu">
19
+ {tableDesMatieres[0]?.texte}
20
+ </span>
21
+ <IconeChevronBas />
22
+ </div>
23
+ </summary>
24
+
25
+ <ul>
26
+ {#each tableDesMatieres as entree (entree.id)}
27
+ <li>
28
+ <a href={`#${entree.id}`} on:click={() => ouvreEntree(entree.id)}>
29
+ <!-- eslint-disable-next-line svelte/no-at-html-tags -->
30
+ {@html entree.texte}</a
31
+ >
32
+ </li>
33
+ {/each}
34
+ </ul>
35
+ </details>
36
+ </div>
37
+
38
+ <style>.sommaire-replie {
39
+ border-top: 1px solid #ddd;
40
+ border-bottom: 1px solid #ddd;
41
+ background: white;
42
+ position: sticky;
43
+ top: 0;
44
+ z-index: 2;
45
+ font-family: Marianne, sans-serif;
46
+ }
47
+ @media (min-width: 932px) {
48
+ .sommaire-replie {
49
+ display: none;
50
+ }
51
+ }
52
+ .sommaire-replie:has(details[open]) {
53
+ position: fixed;
54
+ top: 0;
55
+ height: 100vh;
56
+ width: 100%;
57
+ box-sizing: border-box;
58
+ overflow: auto;
59
+ }
60
+ .sommaire-replie details .entete-filtres {
61
+ padding: 12px 16px;
62
+ background: var(--sommaire-mobile-fond);
63
+ color: var(--sommaire-actif-couleur);
64
+ font-size: 1rem;
65
+ font-style: normal;
66
+ font-weight: 500;
67
+ line-height: 1.5rem;
68
+ }
69
+ .sommaire-replie details ul {
70
+ list-style-type: none;
71
+ margin: 0;
72
+ padding: 16px;
73
+ }
74
+ .sommaire-replie details ul li {
75
+ border-bottom: 1px solid #ddd;
76
+ padding-top: 12px;
77
+ padding-bottom: 12px;
78
+ }
79
+ .sommaire-replie details ul li.actif a {
80
+ color: var(--sommaire-actif-couleur);
81
+ border-left: 2px solid var(--sommaire-actif-indicateur-couleur);
82
+ padding-left: 14px;
83
+ border-bottom: none;
84
+ }
85
+ .sommaire-replie details ul li a {
86
+ color: #161616;
87
+ text-decoration: none;
88
+ padding-left: 16px;
89
+ display: inline-block;
90
+ border-bottom: none;
91
+ font-size: 1rem;
92
+ font-weight: 700;
93
+ line-height: 1.5rem;
94
+ }
95
+ .sommaire-replie details[open] summary .entete-filtres :global(.chevron) {
96
+ transform: rotate(180deg);
97
+ }
98
+ .sommaire-replie details summary {
99
+ list-style: none;
100
+ }
101
+ .sommaire-replie details summary::marker {
102
+ content: "";
103
+ }
104
+ .sommaire-replie details summary::-webkit-details-marker {
105
+ display: none;
106
+ }
107
+ .sommaire-replie details summary .entete-filtres {
108
+ display: flex;
109
+ align-items: center;
110
+ gap: 8px;
111
+ }
112
+ .sommaire-replie details .titre-menu {
113
+ flex-grow: 1;
114
+ }</style>
@@ -0,0 +1,21 @@
1
+ import { SvelteComponent } from "svelte";
2
+ import type { TableDesMatieres } from "../../types";
3
+ declare const __propDef: {
4
+ props: {
5
+ tableDesMatieres: TableDesMatieres;
6
+ };
7
+ events: {
8
+ ancreOuverte: CustomEvent<string>;
9
+ } & {
10
+ [evt: string]: CustomEvent<any>;
11
+ };
12
+ slots: {};
13
+ exports?: {} | undefined;
14
+ bindings?: string | undefined;
15
+ };
16
+ export type SommaireMobileProps = typeof __propDef.props;
17
+ export type SommaireMobileEvents = typeof __propDef.events;
18
+ export type SommaireMobileSlots = typeof __propDef.slots;
19
+ export default class SommaireMobile extends SvelteComponent<SommaireMobileProps, SommaireMobileEvents, SommaireMobileSlots> {
20
+ }
21
+ export {};
package/dist/types.d.ts CHANGED
@@ -46,4 +46,9 @@ export type Tag = {
46
46
  couleurTexte: string;
47
47
  couleurFond: string;
48
48
  };
49
+ export type TableDesMatieres = {
50
+ profondeur: number;
51
+ texte: string;
52
+ id: string;
53
+ }[];
49
54
  export {};