@lab-anssi/ui-kit 1.61.3 → 1.62.0

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.
Files changed (221) hide show
  1. package/README.md +102 -21
  2. package/dist/assets/assets.d.ts +1 -0
  3. package/dist/assets/assets.js +1 -0
  4. package/dist/assets/dsfr-icons.css +1 -0
  5. package/dist/composants/Alerte.svelte +83 -0
  6. package/dist/composants/Alerte.svelte.d.ts +32 -0
  7. package/dist/composants/AncresParcours.svelte +132 -0
  8. package/dist/composants/AncresParcours.svelte.d.ts +11 -0
  9. package/dist/composants/BandeauPage.svelte +218 -0
  10. package/dist/composants/BandeauPage.svelte.d.ts +58 -0
  11. package/dist/composants/BlocFonctionnalites.svelte +570 -0
  12. package/dist/composants/BlocFonctionnalites.svelte.d.ts +105 -0
  13. package/dist/composants/Bouton.svelte +156 -0
  14. package/dist/composants/Bouton.svelte.d.ts +36 -0
  15. package/dist/composants/CentreAide.svelte +223 -0
  16. package/dist/composants/CentreAide.svelte.d.ts +41 -0
  17. package/dist/composants/FiltresCatalogue.svelte +147 -0
  18. package/dist/composants/FiltresCatalogue.svelte.d.ts +15 -0
  19. package/dist/composants/Icone.svelte +42 -0
  20. package/dist/composants/Icone.svelte.d.ts +7 -0
  21. package/dist/composants/Lien.svelte +233 -0
  22. package/dist/composants/Lien.svelte.d.ts +39 -0
  23. package/dist/composants/MultiSelect.svelte +931 -0
  24. package/dist/composants/MultiSelect.svelte.d.ts +51 -0
  25. package/dist/composants/Reactions.svelte +360 -0
  26. package/dist/composants/Reactions.svelte.d.ts +23 -0
  27. package/dist/composants/ResumePssi.svelte +92 -0
  28. package/dist/composants/ResumePssi.svelte.d.ts +6 -0
  29. package/dist/composants/Tag.svelte +113 -0
  30. package/dist/composants/Tag.svelte.d.ts +35 -0
  31. package/dist/composants/blog/BandeauTitre.svelte +150 -0
  32. package/dist/composants/blog/BandeauTitre.svelte.d.ts +29 -0
  33. package/dist/composants/blog/CarteArticle.svelte +69 -0
  34. package/dist/composants/blog/CarteArticle.svelte.d.ts +8 -0
  35. package/dist/composants/blog/IconeChevronBas.svelte +22 -0
  36. package/dist/composants/blog/IconeChevronBas.svelte.d.ts +26 -0
  37. package/dist/composants/blog/IconeMenuLateral.svelte +15 -0
  38. package/dist/composants/blog/IconeMenuLateral.svelte.d.ts +26 -0
  39. package/dist/composants/blog/ListeArticles.svelte +62 -0
  40. package/dist/composants/blog/ListeArticles.svelte.d.ts +9 -0
  41. package/dist/composants/blog/ListeDeroulante.svelte +57 -0
  42. package/dist/composants/blog/ListeDeroulante.svelte.d.ts +10 -0
  43. package/dist/composants/blog/PageCrisp.svelte +244 -0
  44. package/dist/composants/blog/PageCrisp.svelte.d.ts +8 -0
  45. package/dist/composants/blog/SommaireBureau.svelte +64 -0
  46. package/dist/composants/blog/SommaireBureau.svelte.d.ts +9 -0
  47. package/dist/composants/blog/SommaireMobile.svelte +115 -0
  48. package/dist/composants/blog/SommaireMobile.svelte.d.ts +9 -0
  49. package/dist/composants/carrousel-tuiles/CarrouselTuiles.svelte +184 -0
  50. package/dist/composants/carrousel-tuiles/CarrouselTuiles.svelte.d.ts +34 -0
  51. package/dist/composants/carrousel-tuiles/IconeFlecheDroite.svelte +16 -0
  52. package/dist/composants/carrousel-tuiles/IconeFlecheDroite.svelte.d.ts +26 -0
  53. package/dist/composants/carrousel-tuiles/IconeFlecheGauche.svelte +12 -0
  54. package/dist/composants/carrousel-tuiles/IconeFlecheGauche.svelte.d.ts +26 -0
  55. package/dist/composants/carrousel-tuiles/Tuile.svelte +72 -0
  56. package/dist/composants/carrousel-tuiles/Tuile.svelte.d.ts +10 -0
  57. package/dist/composants/icones/Fleche.svelte +25 -0
  58. package/dist/composants/icones/Fleche.svelte.d.ts +6 -0
  59. package/dist/composants/icones/LienExterne.svelte +20 -0
  60. package/dist/composants/icones/LienExterne.svelte.d.ts +6 -0
  61. package/dist/composants/marelle/Etape.svelte +165 -0
  62. package/dist/composants/marelle/Etape.svelte.d.ts +32 -0
  63. package/dist/composants/marelle/Marelle.svelte +97 -0
  64. package/dist/composants/marelle/Marelle.svelte.d.ts +44 -0
  65. package/dist/composants/mes-services-cyber/bandeau/Bandeau.svelte +158 -0
  66. package/dist/composants/mes-services-cyber/bandeau/Bandeau.svelte.d.ts +3 -0
  67. package/dist/composants/mes-services-cyber/lien/LienDiagnosticCyber.svelte +125 -0
  68. package/dist/composants/mes-services-cyber/lien/LienDiagnosticCyber.svelte.d.ts +7 -0
  69. package/dist/composants/pied-de-page/NavigationPiedDePage.svelte +62 -0
  70. package/dist/composants/pied-de-page/NavigationPiedDePage.svelte.d.ts +6 -0
  71. package/dist/composants/suite-cyber/AccueilSuiteCyber.svelte +96 -0
  72. package/dist/composants/suite-cyber/AccueilSuiteCyber.svelte.d.ts +6 -0
  73. package/dist/composants/suite-cyber/LiensSuiteCyber.svelte +99 -0
  74. package/dist/composants/suite-cyber/LiensSuiteCyber.svelte.d.ts +14 -0
  75. package/dist/composants/suite-cyber/SuiteCyber.svelte +296 -0
  76. package/dist/composants/suite-cyber/SuiteCyber.svelte.d.ts +6 -0
  77. package/dist/composants/vitrines-produits/briques/Brique.svelte +50 -0
  78. package/dist/composants/vitrines-produits/briques/Brique.svelte.d.ts +9 -0
  79. package/dist/composants/vitrines-produits/briques/BriqueContenuADeuxColonnes.svelte +144 -0
  80. package/dist/composants/vitrines-produits/briques/BriqueContenuADeuxColonnes.svelte.d.ts +29 -0
  81. package/dist/composants/vitrines-produits/briques/BriqueHero.svelte +246 -0
  82. package/dist/composants/vitrines-produits/briques/BriqueHero.svelte.d.ts +31 -0
  83. package/dist/composants/vitrines-produits/briques/BriqueTitreMultimedia.svelte +50 -0
  84. package/dist/composants/vitrines-produits/briques/BriqueTitreMultimedia.svelte.d.ts +25 -0
  85. package/dist/composants/vitrines-produits/briques/LecteurVideo.svelte +14 -0
  86. package/dist/composants/vitrines-produits/briques/LecteurVideo.svelte.d.ts +9 -0
  87. package/dist/composants/vitrines-produits/briques/PresentationANSSI.svelte +148 -0
  88. package/dist/composants/vitrines-produits/briques/PresentationANSSI.svelte.d.ts +37 -0
  89. package/dist/composants/vitrines-produits/briques/RejoindreLaCommunaute.svelte +139 -0
  90. package/dist/composants/vitrines-produits/briques/RejoindreLaCommunaute.svelte.d.ts +36 -0
  91. package/dist/composants/vitrines-produits/briques/temoignages/IconeTemoignage.svelte +18 -0
  92. package/dist/composants/vitrines-produits/briques/temoignages/IconeTemoignage.svelte.d.ts +26 -0
  93. package/dist/composants/vitrines-produits/briques/temoignages/Temoignages.svelte +168 -0
  94. package/dist/composants/vitrines-produits/briques/temoignages/Temoignages.svelte.d.ts +13 -0
  95. package/dist/directives/actions.svelte.d.ts +32 -0
  96. package/dist/directives/actions.svelte.js +158 -0
  97. package/dist/dsfr/DsfrAccordion.svelte +889 -0
  98. package/dist/dsfr/DsfrAccordion.svelte.d.ts +40 -0
  99. package/dist/dsfr/DsfrAlert.svelte +2097 -0
  100. package/dist/dsfr/DsfrAlert.svelte.d.ts +36 -0
  101. package/dist/dsfr/DsfrBadge.svelte +532 -0
  102. package/dist/dsfr/DsfrBadge.svelte.d.ts +41 -0
  103. package/dist/dsfr/DsfrBadgesGroup.svelte +610 -0
  104. package/dist/dsfr/DsfrBadgesGroup.svelte.d.ts +25 -0
  105. package/dist/dsfr/DsfrBreadcrumb.svelte +657 -0
  106. package/dist/dsfr/DsfrBreadcrumb.svelte.d.ts +25 -0
  107. package/dist/dsfr/DsfrButton.svelte +1821 -0
  108. package/dist/dsfr/DsfrButton.svelte.d.ts +68 -0
  109. package/dist/dsfr/DsfrButtonsGroup.svelte +1896 -0
  110. package/dist/dsfr/DsfrButtonsGroup.svelte.d.ts +36 -0
  111. package/dist/dsfr/DsfrCallout.svelte +242 -0
  112. package/dist/dsfr/DsfrCallout.svelte.d.ts +46 -0
  113. package/dist/dsfr/DsfrCard.svelte +10223 -0
  114. package/dist/dsfr/DsfrCard.svelte.d.ts +102 -0
  115. package/dist/dsfr/DsfrCheckbox.svelte +1280 -0
  116. package/dist/dsfr/DsfrCheckbox.svelte.d.ts +69 -0
  117. package/dist/dsfr/DsfrCheckboxesGroup.svelte +1532 -0
  118. package/dist/dsfr/DsfrCheckboxesGroup.svelte.d.ts +73 -0
  119. package/dist/dsfr/DsfrConnect.svelte +511 -0
  120. package/dist/dsfr/DsfrConnect.svelte.d.ts +15 -0
  121. package/dist/dsfr/DsfrContainer.svelte +894 -0
  122. package/dist/dsfr/DsfrContainer.svelte.d.ts +31 -0
  123. package/dist/dsfr/DsfrContent.svelte +1140 -0
  124. package/dist/dsfr/DsfrContent.svelte.d.ts +60 -0
  125. package/dist/dsfr/DsfrDropdown.svelte +335 -0
  126. package/dist/dsfr/DsfrDropdown.svelte.d.ts +73 -0
  127. package/dist/dsfr/DsfrFooter.svelte +2370 -0
  128. package/dist/dsfr/DsfrFooter.svelte.d.ts +77 -0
  129. package/dist/dsfr/DsfrHeader.svelte +4162 -0
  130. package/dist/dsfr/DsfrHeader.svelte.d.ts +131 -0
  131. package/dist/dsfr/DsfrHighlight.svelte +294 -0
  132. package/dist/dsfr/DsfrHighlight.svelte.d.ts +33 -0
  133. package/dist/dsfr/DsfrInput.svelte +1270 -0
  134. package/dist/dsfr/DsfrInput.svelte.d.ts +86 -0
  135. package/dist/dsfr/DsfrLabel.svelte +438 -0
  136. package/dist/dsfr/DsfrLabel.svelte.d.ts +65 -0
  137. package/dist/dsfr/DsfrLink.svelte +1007 -0
  138. package/dist/dsfr/DsfrLink.svelte.d.ts +66 -0
  139. package/dist/dsfr/DsfrLogo.svelte +228 -0
  140. package/dist/dsfr/DsfrLogo.svelte.d.ts +11 -0
  141. package/dist/dsfr/DsfrMessagesGroup.svelte +260 -0
  142. package/dist/dsfr/DsfrMessagesGroup.svelte.d.ts +46 -0
  143. package/dist/dsfr/DsfrModal.svelte +2983 -0
  144. package/dist/dsfr/DsfrModal.svelte.d.ts +56 -0
  145. package/dist/dsfr/DsfrNavigation.svelte +7626 -0
  146. package/dist/dsfr/DsfrNotice.svelte +2948 -0
  147. package/dist/dsfr/DsfrNotice.svelte.d.ts +37 -0
  148. package/dist/dsfr/DsfrPagination.svelte +1036 -0
  149. package/dist/dsfr/DsfrPagination.svelte.d.ts +35 -0
  150. package/dist/dsfr/DsfrQuote.svelte +646 -0
  151. package/dist/dsfr/DsfrQuote.svelte.d.ts +29 -0
  152. package/dist/dsfr/DsfrRadio.svelte +1307 -0
  153. package/dist/dsfr/DsfrRadio.svelte.d.ts +37 -0
  154. package/dist/dsfr/DsfrRadiosGroup.svelte +1629 -0
  155. package/dist/dsfr/DsfrRadiosGroup.svelte.d.ts +76 -0
  156. package/dist/dsfr/DsfrRange.svelte +1329 -0
  157. package/dist/dsfr/DsfrRange.svelte.d.ts +77 -0
  158. package/dist/dsfr/DsfrSearch.svelte +2015 -0
  159. package/dist/dsfr/DsfrSearch.svelte.d.ts +51 -0
  160. package/dist/dsfr/DsfrSegmented.svelte +422 -0
  161. package/dist/dsfr/DsfrSegmented.svelte.d.ts +34 -0
  162. package/dist/dsfr/DsfrSelect.svelte +1068 -0
  163. package/dist/dsfr/DsfrSelect.svelte.d.ts +86 -0
  164. package/dist/dsfr/DsfrShare.svelte +2228 -0
  165. package/dist/dsfr/DsfrShare.svelte.d.ts +40 -0
  166. package/dist/dsfr/DsfrSideMenu.svelte +1211 -0
  167. package/dist/dsfr/DsfrSideMenu.svelte.d.ts +34 -0
  168. package/dist/dsfr/DsfrSkipLink.svelte +990 -0
  169. package/dist/dsfr/DsfrSkipLink.svelte.d.ts +13 -0
  170. package/dist/dsfr/DsfrStepper.svelte +340 -0
  171. package/dist/dsfr/DsfrStepper.svelte.d.ts +18 -0
  172. package/dist/dsfr/DsfrTable.svelte +829 -0
  173. package/dist/dsfr/DsfrTable.svelte.d.ts +202 -0
  174. package/dist/dsfr/DsfrTabnav.svelte +1149 -0
  175. package/dist/dsfr/DsfrTabnav.svelte.d.ts +36 -0
  176. package/dist/dsfr/DsfrTabs.svelte +926 -0
  177. package/dist/dsfr/DsfrTabs.svelte.d.ts +28 -0
  178. package/dist/dsfr/DsfrTag.svelte +1269 -0
  179. package/dist/dsfr/DsfrTag.svelte.d.ts +59 -0
  180. package/dist/dsfr/DsfrTagsGroup.svelte +1351 -0
  181. package/dist/dsfr/DsfrTagsGroup.svelte.d.ts +37 -0
  182. package/dist/dsfr/DsfrTextarea.svelte +1385 -0
  183. package/dist/dsfr/DsfrTextarea.svelte.d.ts +72 -0
  184. package/dist/dsfr/DsfrTile.svelte +7645 -0
  185. package/dist/dsfr/DsfrTile.svelte.d.ts +79 -0
  186. package/dist/dsfr/DsfrToggle.svelte +1453 -0
  187. package/dist/dsfr/DsfrToggle.svelte.d.ts +56 -0
  188. package/dist/dsfr/DsfrTooltip.svelte +396 -0
  189. package/dist/dsfr/DsfrTooltip.svelte.d.ts +36 -0
  190. package/dist/dsfr/DsfrTranscription.svelte +2962 -0
  191. package/dist/dsfr/DsfrTranscription.svelte.d.ts +39 -0
  192. package/dist/dsfr/DsfrTranslate.svelte +1384 -0
  193. package/dist/dsfr/DsfrTranslate.svelte.d.ts +19 -0
  194. package/dist/dsfr/DsfrUser.svelte +736 -0
  195. package/dist/dsfr/DsfrUser.svelte.d.ts +65 -0
  196. package/dist/index.d.ts +79 -0
  197. package/dist/index.js +79 -0
  198. package/dist/styles/apparence-bouton.scss +154 -0
  199. package/dist/styles/dsfr-icons.css +1 -0
  200. package/dist/styles/dsfr-icons.scss +4 -0
  201. package/dist/styles/dsfr-variables.scss +28 -0
  202. package/dist/styles/mixins-dsfr.scss +226 -0
  203. package/dist/styles/mixins.scss +51 -0
  204. package/dist/types/commun.d.ts +63 -0
  205. package/dist/types/commun.js +1 -0
  206. package/dist/types/global.d.ts +24 -0
  207. package/dist/types/global.js +9 -0
  208. package/dist/types/index.d.ts +2 -0
  209. package/dist/types/index.js +1 -0
  210. package/dist/ui-kit-components.json +142 -100
  211. package/dist/utilitaires/createFormValidation.svelte.d.ts +34 -0
  212. package/dist/utilitaires/createFormValidation.svelte.js +183 -0
  213. package/dist/utilitaires/icons-stylesheet.d.ts +370 -0
  214. package/dist/utilitaires/icons-stylesheet.js +33 -0
  215. package/dist/utilitaires/index.d.ts +14 -0
  216. package/dist/utilitaires/index.js +26 -0
  217. package/dist/web-types.json +149 -101
  218. package/dist/webcomponents/lab-anssi-ui-kit.iife.js +36 -9
  219. package/dist/webcomponents/lab-anssi-ui-kit.jsx.d.ts +42 -24
  220. package/package.json +49 -43
  221. package/dist/index.html +0 -0
@@ -0,0 +1,570 @@
1
+ <svelte:options
2
+ customElement={{
3
+ tag: "lab-anssi-fonctionnalites",
4
+ props: {
5
+ titre: { attribute: "titre", type: "String" },
6
+ description: { attribute: "description", type: "String" },
7
+ baliseTitre: { attribute: "balise-titre", type: "String" },
8
+ avecControleSegmente: { attribute: "avec-controle-segmente", type: "Boolean" },
9
+ elementsDuControleSegmente: { attribute: "elements-du-controle-segmente", type: "Array" },
10
+ tailleControleSegmente: { attribute: "taille-controle-segmente", type: "String" },
11
+ fonctionnalites: { attribute: "fonctionnalites", type: "Array" },
12
+ baliseDesSousTitres: { attribute: "balise-des-sous-titres", type: "String" },
13
+ cliquable: { attribute: "cliquable", type: "Boolean" },
14
+ avecCTA: { attribute: "avec-cta", type: "Boolean" },
15
+ orientationMedia: { attribute: "orientation-media", type: "String" },
16
+ imagePlaceholder: { attribute: "image-placeholder", type: "String" },
17
+ activeDefilement: { attribute: "active-defilement", type: "Boolean" },
18
+ delaiDefilement: { attribute: "delai-defilement", type: "Number" },
19
+ },
20
+ extend: withIconsStyleSheet,
21
+ }}
22
+ />
23
+
24
+ <script lang="ts">import { setThemeable, withIconsStyleSheet } from "../utilitaires";
25
+ import { createSlot } from "../directives/actions.svelte";
26
+ import "../dsfr/DsfrButton.svelte";
27
+ import DsfrBadge from "../dsfr/DsfrBadge.svelte";
28
+ import DsfrLink from "../dsfr/DsfrLink.svelte";
29
+ import "../dsfr/DsfrSegmented.svelte";
30
+ let { titre = undefined, description, baliseTitre = "h2", avecControleSegmente = false, tailleControleSegmente = "md", elementsDuControleSegmente = [], fonctionnalites, baliseDesSousTitres = "h3", cliquable = false, avecCTA = false, orientationMedia = "droite", imagePlaceholder, delaiDefilement = 5e3, activeDefilement = false } = $props();
31
+ setThemeable($host());
32
+ let indexActif = $state(0);
33
+ /**
34
+ * Vérifie si le tableau de fonctionnalités est un tableau multidimensionnel (tableau de tableaux)
35
+ *
36
+ * @param tableau - Le tableau de fonctionnalités à vérifier
37
+ *
38
+ * @returns true si le tableau est imbriqué, false sinon
39
+ */
40
+ function estUnTableauImbrique(tableau) {
41
+ return tableau.length > 0 && Array.isArray(tableau[0]);
42
+ }
43
+ const tableauDeFonctionnalites = $derived(estUnTableauImbrique(fonctionnalites) ? fonctionnalites : [fonctionnalites]);
44
+ const elementsModifiesDuControleSegmente = $derived(elementsDuControleSegmente.map((element, index) => ({
45
+ ...element,
46
+ value: element.value ? `liste-${element.value}` : `liste-${index + 1}`
47
+ })));
48
+ let valeurListeActive = $derived(elementsModifiesDuControleSegmente[0]?.value ?? "liste-1");
49
+ const indexListeActive = $derived(Math.max(0, elementsModifiesDuControleSegmente.findIndex((e) => e.value === valeurListeActive)));
50
+ const fonctionnaliteActive = $derived(tableauDeFonctionnalites[indexListeActive]?.[indexActif] ?? null);
51
+ const srcImageFonctionnaliteActive = $derived(cliquable ? fonctionnaliteActive?.illustration ?? imagePlaceholder : imagePlaceholder);
52
+ const legendeImageFonctionnaliteActive = $derived(cliquable ? fonctionnaliteActive?.titre ?? "" : "");
53
+ /**
54
+ * Met à jour la valeur active du contrôle segmenté.
55
+ *
56
+ * @param {string | number} controleSelectionne - La valeur du contrôle sélectionné
57
+ */
58
+ function selectionneUnControleSegmente(controleSelectionne) {
59
+ valeurListeActive = controleSelectionne.detail.toString();
60
+ }
61
+ let enPauseSurvol = $state(false);
62
+ let enPauseManuelle = $state(false);
63
+ let prefereMouvementReduit = $state(false);
64
+ let mediaCloneContainer = $state();
65
+ const hasMediaSlotContent = $derived(!$host()?.querySelector("[slot=\"media\"]") && !!fonctionnaliteActive?.id && !!$host()?.querySelector(`[slot="media-${fonctionnaliteActive.id}"]`));
66
+ $effect(() => {
67
+ const mediaQueryReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
68
+ prefereMouvementReduit = mediaQueryReducedMotion.matches;
69
+ const gereLaPreferenceMouvementReduit = (e) => {
70
+ prefereMouvementReduit = e.matches;
71
+ };
72
+ mediaQueryReducedMotion.addEventListener("change", gereLaPreferenceMouvementReduit);
73
+ return () => mediaQueryReducedMotion.removeEventListener("change", gereLaPreferenceMouvementReduit);
74
+ });
75
+ $effect(() => {
76
+ if (!cliquable || !activeDefilement || !delaiDefilement || delaiDefilement <= 0) return;
77
+ if (enPauseSurvol || enPauseManuelle || prefereMouvementReduit) return;
78
+ const nombreElements = (tableauDeFonctionnalites[indexListeActive] ?? []).length;
79
+ if (nombreElements <= 1) return;
80
+ const interval = setInterval(() => {
81
+ indexActif = (indexActif + 1) % nombreElements;
82
+ }, delaiDefilement);
83
+ return () => clearInterval(interval);
84
+ });
85
+ let rootElement;
86
+ $effect(() => {
87
+ const host = $host() ?? rootElement;
88
+ const activeId = fonctionnaliteActive?.id;
89
+ if (activeId) {
90
+ host.dataset.activeItem = activeId;
91
+ } else {
92
+ delete host.dataset.activeItem;
93
+ }
94
+ if (!mediaCloneContainer) return;
95
+ // eslint-disable-next-line svelte/no-dom-manipulating
96
+ mediaCloneContainer.innerHTML = "";
97
+ if (activeId) {
98
+ const source = host.querySelector(`[slot="media-${activeId}"]`);
99
+ if (source) {
100
+ const clone = source.cloneNode(true);
101
+ clone.removeAttribute("slot");
102
+ // eslint-disable-next-line svelte/no-dom-manipulating
103
+ mediaCloneContainer.appendChild(clone);
104
+ }
105
+ }
106
+ });
107
+ function pauseDefilement() {
108
+ enPauseSurvol = true;
109
+ }
110
+ function reprendDefilement() {
111
+ enPauseSurvol = false;
112
+ }
113
+ </script>
114
+
115
+ {#snippet illustrationFonctionnalite(fonctionnalite: Fonctionnalite, hasSlot: boolean)}
116
+ <figure
117
+ class={[
118
+ hasSlot ? "lab-anssi-fonctionnalites__visuel" : "lab-anssi-fonctionnalites__illustration",
119
+ ]}
120
+ >
121
+ <img src={fonctionnalite.illustration} class="lab-anssi-fonctionnalites__image" alt="" />
122
+ </figure>
123
+ {/snippet}
124
+
125
+ {#snippet unElementFonctionnalite(fonctionnalite: Fonctionnalite, index: number)}
126
+ <article
127
+ id={fonctionnalite.id}
128
+ class={[
129
+ "lab-anssi-fonctionnalites__element",
130
+ { "lab-anssi-fonctionnalites__element--cliquable": cliquable },
131
+ ]}
132
+ >
133
+ <div class="lab-anssi-fonctionnalites__wrap">
134
+ {#if fonctionnalite.rich && fonctionnalite.id}
135
+ <div use:createSlot={`badge-${fonctionnalite.id}`}>
136
+ {#if fonctionnalite.badge}
137
+ <DsfrBadge
138
+ label={fonctionnalite.badge.label}
139
+ size={fonctionnalite.badge.size}
140
+ accent={fonctionnalite.badge.accent}
141
+ status={fonctionnalite.badge.status}
142
+ hasIcon={fonctionnalite.badge.hasIcon || undefined}
143
+ hasNoIcon={fonctionnalite.badge.hasNoIcon || undefined}
144
+ icon={fonctionnalite.badge.icon}
145
+ ellipsis={fonctionnalite.badge.ellipsis || undefined}
146
+ type={fonctionnalite.badge.type}
147
+ />
148
+ {/if}
149
+ </div>
150
+ {:else if fonctionnalite.badge}
151
+ <DsfrBadge
152
+ label={fonctionnalite.badge.label}
153
+ size={fonctionnalite.badge.size}
154
+ accent={fonctionnalite.badge.accent}
155
+ status={fonctionnalite.badge.status}
156
+ hasIcon={fonctionnalite.badge.hasIcon || undefined}
157
+ hasNoIcon={fonctionnalite.badge.hasNoIcon || undefined}
158
+ icon={fonctionnalite.badge.icon}
159
+ ellipsis={fonctionnalite.badge.ellipsis || undefined}
160
+ type={fonctionnalite.badge.type}
161
+ />
162
+ {/if}
163
+
164
+ <svelte:element this={baliseDesSousTitres} class="lab-anssi-fonctionnalites__sous-titre">
165
+ {#if cliquable}
166
+ <button
167
+ type="button"
168
+ role="tab"
169
+ aria-selected={indexActif === index}
170
+ aria-controls={hasMediaSlotContent ? undefined : "activeImage"}
171
+ tabindex={indexActif === index ? 0 : -1}
172
+ class="lab-anssi-fonctionnalites__bouton"
173
+ onclick={() => (indexActif = index)}
174
+ >
175
+ {fonctionnalite.titre}
176
+ </button>
177
+ {:else}
178
+ {fonctionnalite.titre}
179
+ {/if}
180
+ </svelte:element>
181
+
182
+ {#if fonctionnalite.description}
183
+ <p class="lab-anssi-fonctionnalites__description">
184
+ {fonctionnalite.description}
185
+ </p>
186
+ {/if}
187
+
188
+ {#if fonctionnalite.rich && fonctionnalite.id}
189
+ <div use:createSlot={`lien-${fonctionnalite.id}`}>
190
+ {#if !cliquable && fonctionnalite.lien}
191
+ <DsfrLink
192
+ label={fonctionnalite.lien.label}
193
+ size="md"
194
+ id={fonctionnalite.lien.id}
195
+ disabled={fonctionnalite.lien.disabled || undefined}
196
+ blank={fonctionnalite.lien.blank || undefined}
197
+ href={fonctionnalite.lien.href}
198
+ download={fonctionnalite.lien.download || undefined}
199
+ hasIcon={fonctionnalite.lien.hasIcon || undefined}
200
+ icon={fonctionnalite.lien.icon}
201
+ iconPlace={fonctionnalite.lien.iconPlace}
202
+ neutral={fonctionnalite.lien.neutral || undefined}
203
+ />
204
+ {/if}
205
+ </div>
206
+ {:else if !cliquable && fonctionnalite.lien}
207
+ <DsfrLink
208
+ label={fonctionnalite.lien.label}
209
+ size="md"
210
+ id={fonctionnalite.lien.id}
211
+ disabled={fonctionnalite.lien.disabled || undefined}
212
+ blank={fonctionnalite.lien.blank || undefined}
213
+ href={fonctionnalite.lien.href}
214
+ download={fonctionnalite.lien.download || undefined}
215
+ hasIcon={fonctionnalite.lien.hasIcon || undefined}
216
+ icon={fonctionnalite.lien.icon}
217
+ iconPlace={fonctionnalite.lien.iconPlace}
218
+ neutral={fonctionnalite.lien.neutral || undefined}
219
+ />
220
+ {/if}
221
+ </div>
222
+
223
+ {#if cliquable}
224
+ {#if fonctionnalite.rich && fonctionnalite.id}
225
+ <div
226
+ use:createSlot={`media-${fonctionnalite.id}`}
227
+ class="lab-anssi-fonctionnalites__illustration"
228
+ >
229
+ {#if fonctionnalite.illustration}
230
+ {@render illustrationFonctionnalite(fonctionnalite, true)}
231
+ {/if}
232
+ </div>
233
+ {:else if fonctionnalite.illustration}
234
+ {@render illustrationFonctionnalite(fonctionnalite, false)}
235
+ {/if}
236
+ {/if}
237
+ </article>
238
+ {/snippet}
239
+
240
+ <div
241
+ class={[
242
+ "lab-anssi-fonctionnalites",
243
+ {
244
+ "lab-anssi-fonctionnalites--cliquable": cliquable,
245
+ "lab-anssi-fonctionnalites--media-gauche": orientationMedia === "gauche",
246
+ },
247
+ ]}
248
+ bind:this={rootElement}
249
+ >
250
+ <section class="lab-anssi-fonctionnalites__conteneur">
251
+ <header class="lab-anssi-fonctionnalites__entete">
252
+ <slot name="hautentete"></slot>
253
+
254
+ <slot name="titre">
255
+ <svelte:element this={baliseTitre} class="lab-anssi-fonctionnalites__titre">
256
+ {titre}
257
+ </svelte:element>
258
+ </slot>
259
+
260
+ <slot name="description">
261
+ {#if description}
262
+ <p class="lab-anssi-fonctionnalites__chapeau">
263
+ {description}
264
+ </p>
265
+ {/if}
266
+ </slot>
267
+ </header>
268
+
269
+ {#if avecControleSegmente && elementsModifiesDuControleSegmente.length > 0}
270
+ <dsfr-segmented
271
+ elements={elementsModifiesDuControleSegmente}
272
+ no-legend
273
+ onvaluechanged={selectionneUnControleSegmente}
274
+ size={tailleControleSegmente}
275
+ value={valeurListeActive}
276
+ ></dsfr-segmented>
277
+ {/if}
278
+
279
+ <div
280
+ class="lab-anssi-fonctionnalites__corps"
281
+ role="group"
282
+ onmouseenter={pauseDefilement}
283
+ onmouseleave={reprendDefilement}
284
+ onfocusin={pauseDefilement}
285
+ onfocusout={reprendDefilement}
286
+ >
287
+ {#if tableauDeFonctionnalites.length > 1}
288
+ {#each elementsModifiesDuControleSegmente as element, i (element.value)}
289
+ <div
290
+ id={element.value}
291
+ class={[
292
+ "lab-anssi-fonctionnalites__liste",
293
+ { actif: valeurListeActive === element.value },
294
+ ]}
295
+ aria-labelledby={element.id}
296
+ role="tabpanel"
297
+ tabindex="0"
298
+ >
299
+ {#each tableauDeFonctionnalites[i] ?? [] as fonctionnalite, j (j)}
300
+ {@render unElementFonctionnalite(fonctionnalite, j)}
301
+ {/each}
302
+ </div>
303
+ {/each}
304
+ {:else}
305
+ <div class="lab-anssi-fonctionnalites__liste" role="group">
306
+ {#each tableauDeFonctionnalites[0] ?? [] as fonctionnalite, k (k)}
307
+ {@render unElementFonctionnalite(fonctionnalite, k)}
308
+ {/each}
309
+ </div>
310
+ {/if}
311
+
312
+ <div class="lab-anssi-fonctionnalites__media">
313
+ <slot name="media">
314
+ {#if hasMediaSlotContent}
315
+ <div
316
+ bind:this={mediaCloneContainer}
317
+ class="lab-anssi-fonctionnalites__media-wrapper"
318
+ ></div>
319
+ {:else}
320
+ <figure class="lab-anssi-fonctionnalites__visuel">
321
+ <img
322
+ src={srcImageFonctionnaliteActive}
323
+ class="lab-anssi-fonctionnalites__image"
324
+ id="activeImage"
325
+ alt=""
326
+ />
327
+ {#if cliquable && legendeImageFonctionnaliteActive}
328
+ <figcaption class="fr-sr-only">{legendeImageFonctionnaliteActive}</figcaption>
329
+ {/if}
330
+ </figure>
331
+ {/if}
332
+ </slot>
333
+
334
+ {#if activeDefilement && cliquable}
335
+ <dsfr-button
336
+ label={enPauseManuelle
337
+ ? "Lancer le défilement automatique"
338
+ : "Mettre en pause le défilement automatique"}
339
+ class="lab-anssi-fonctionnalites__bouton-defilement"
340
+ kind="secondary"
341
+ size="sm"
342
+ has-icon
343
+ icon-place="only"
344
+ icon={enPauseManuelle ? "play-circle-line" : "pause-circle-line"}
345
+ onclick={() => (enPauseManuelle = !enPauseManuelle)}
346
+ onkeydown={(event: KeyboardEvent) => {
347
+ if (event.key === "Enter" || event.key === " ") {
348
+ event.preventDefault();
349
+ enPauseManuelle = !enPauseManuelle;
350
+ }
351
+ }}
352
+ role="button"
353
+ tabindex="0"
354
+ ></dsfr-button>
355
+ {/if}
356
+ </div>
357
+ </div>
358
+
359
+ {#if avecCTA}
360
+ <footer class="lab-anssi-fonctionnalites__pied">
361
+ <slot name="cta"></slot>
362
+ </footer>
363
+ {/if}
364
+ </section>
365
+ </div>
366
+
367
+ <style>:host(lab-anssi-fonctionnalites) {
368
+ display: block;
369
+ box-sizing: border-box;
370
+ }
371
+
372
+ .lab-anssi-fonctionnalites {
373
+ color: var(--text-default-grey);
374
+ padding: var(--padding-composant, 0);
375
+ }
376
+ .lab-anssi-fonctionnalites *,
377
+ .lab-anssi-fonctionnalites *::after,
378
+ .lab-anssi-fonctionnalites *::before {
379
+ box-sizing: inherit;
380
+ }
381
+ .lab-anssi-fonctionnalites__conteneur {
382
+ display: flex;
383
+ flex-direction: column;
384
+ gap: 3rem;
385
+ }
386
+ .lab-anssi-fonctionnalites__entete {
387
+ display: flex;
388
+ flex-direction: column;
389
+ gap: 1.5rem;
390
+ }
391
+ @media (min-width: 48em) {
392
+ .lab-anssi-fonctionnalites__entete {
393
+ flex: 0 0 66.6666666667%;
394
+ width: 66.6666666667%;
395
+ max-width: 66.6666666667%;
396
+ }
397
+ }
398
+ .lab-anssi-fonctionnalites__titre,
399
+ .lab-anssi-fonctionnalites :global(::slotted([slot="titre"])) {
400
+ color: var(--text-title-grey);
401
+ font-size: 2.5rem;
402
+ font-weight: bold;
403
+ line-height: 3rem;
404
+ margin-block: 0;
405
+ }
406
+ .lab-anssi-fonctionnalites__description, .lab-anssi-fonctionnalites__chapeau,
407
+ .lab-anssi-fonctionnalites :global(::slotted([slot="description"])) {
408
+ font-size: 1.125rem;
409
+ line-height: 1.75rem;
410
+ margin-block: 0;
411
+ }
412
+ .lab-anssi-fonctionnalites__corps {
413
+ display: flex;
414
+ flex-direction: column-reverse;
415
+ gap: 48px;
416
+ }
417
+ @media (min-width: 48em) {
418
+ .lab-anssi-fonctionnalites__corps {
419
+ align-items: center;
420
+ flex-direction: row;
421
+ gap: 1.5rem;
422
+ padding-block-end: 1rem;
423
+ }
424
+ }
425
+ .lab-anssi-fonctionnalites__liste, .lab-anssi-fonctionnalites__media {
426
+ flex: 1;
427
+ }
428
+ .lab-anssi-fonctionnalites__media {
429
+ display: flex;
430
+ align-items: center;
431
+ flex-direction: column;
432
+ justify-content: center;
433
+ }
434
+ .lab-anssi-fonctionnalites__media-wrapper {
435
+ width: 100%;
436
+ }
437
+ .lab-anssi-fonctionnalites [role=tabpanel]:not(.actif) {
438
+ display: none;
439
+ }
440
+ .lab-anssi-fonctionnalites__element {
441
+ position: relative;
442
+ box-shadow: inset 0 -1px 0 0 var(--border-default-grey);
443
+ }
444
+ @media (max-width: 61.98em) {
445
+ .lab-anssi-fonctionnalites__element:has(button[aria-selected=false]) .lab-anssi-fonctionnalites__illustration {
446
+ display: none;
447
+ }
448
+ }
449
+ @media (max-width: 61.98em) {
450
+ .lab-anssi-fonctionnalites__element:has(button[aria-selected=true]) {
451
+ padding-block-end: 1.5rem;
452
+ }
453
+ }
454
+ .lab-anssi-fonctionnalites__element:has(button[aria-selected=true]) .lab-anssi-fonctionnalites__wrap::after {
455
+ content: "";
456
+ position: absolute;
457
+ left: 0;
458
+ top: 1.5rem;
459
+ bottom: 1.5rem;
460
+ width: 0.25rem;
461
+ background-color: var(--border-active-alt-blue-france-lab, #000091);
462
+ }
463
+ .lab-anssi-fonctionnalites__element:has(button[aria-selected=true]) .lab-anssi-fonctionnalites__sous-titre {
464
+ color: var(--text-active-blue-france, #000091);
465
+ }
466
+ .lab-anssi-fonctionnalites__element--cliquable .lab-anssi-fonctionnalites__wrap {
467
+ padding-inline-start: 1.25rem;
468
+ }
469
+ .lab-anssi-fonctionnalites__element--cliquable:hover {
470
+ background-color: rgba(0, 0, 0, 0.04);
471
+ }
472
+ .lab-anssi-fonctionnalites__element--cliquable:active {
473
+ background-color: rgba(0, 0, 0, 0.08);
474
+ }
475
+ .lab-anssi-fonctionnalites__wrap {
476
+ padding: 1.5rem;
477
+ padding-inline-start: 0;
478
+ position: relative;
479
+ }
480
+ .lab-anssi-fonctionnalites__sous-titre {
481
+ color: var(--text-title-grey);
482
+ font-size: 1.25rem;
483
+ line-height: 1.75rem;
484
+ margin-block: 0 0.5rem;
485
+ }
486
+ .lab-anssi-fonctionnalites__sous-titre:not(:first-child) {
487
+ margin-block-start: 0.5rem;
488
+ }
489
+ .lab-anssi-fonctionnalites__description {
490
+ color: var(--text-default-grey);
491
+ margin-block: 0;
492
+ font-size: 1rem;
493
+ line-height: 1.5rem;
494
+ }
495
+ .lab-anssi-fonctionnalites__description:not(:last-child) {
496
+ margin-block-end: 1rem;
497
+ }
498
+ .lab-anssi-fonctionnalites__illustration {
499
+ margin: 0;
500
+ }
501
+ .lab-anssi-fonctionnalites__bouton {
502
+ background-color: transparent;
503
+ border-width: 0;
504
+ color: currentColor;
505
+ cursor: pointer;
506
+ font: inherit;
507
+ padding-inline: 0;
508
+ text-align: left;
509
+ }
510
+ .lab-anssi-fonctionnalites__bouton::after {
511
+ content: "";
512
+ position: absolute;
513
+ inset: 0;
514
+ }
515
+ .lab-anssi-fonctionnalites__visuel {
516
+ margin: 0;
517
+ }
518
+ .lab-anssi-fonctionnalites__placeholder, .lab-anssi-fonctionnalites__image {
519
+ display: block;
520
+ max-width: 100%;
521
+ height: auto;
522
+ }
523
+ .lab-anssi-fonctionnalites__pied {
524
+ display: flex;
525
+ justify-content: center;
526
+ }
527
+ .lab-anssi-fonctionnalites__bouton-defilement {
528
+ position: absolute;
529
+ bottom: 0;
530
+ right: 0;
531
+ }
532
+ @media (min-width: 48em) {
533
+ .lab-anssi-fonctionnalites__bouton-defilement {
534
+ position: static;
535
+ align-self: flex-end;
536
+ }
537
+ }
538
+ @media (max-width: 47.98em) {
539
+ .lab-anssi-fonctionnalites:has(.lab-anssi-fonctionnalites__bouton-defilement) {
540
+ padding-block-end: 4.5rem;
541
+ position: relative;
542
+ }
543
+ }
544
+ @media (min-width: 48em) {
545
+ .lab-anssi-fonctionnalites--media-gauche .lab-anssi-fonctionnalites__corps {
546
+ flex-direction: row-reverse;
547
+ }
548
+ }
549
+ @media (min-width: 48em) {
550
+ .lab-anssi-fonctionnalites--cliquable .lab-anssi-fonctionnalites__illustration {
551
+ display: none;
552
+ }
553
+ }
554
+ @media (max-width: 61.98em) {
555
+ .lab-anssi-fonctionnalites--cliquable .lab-anssi-fonctionnalites__media .lab-anssi-fonctionnalites__visuel,
556
+ .lab-anssi-fonctionnalites--cliquable .lab-anssi-fonctionnalites__media .lab-anssi-fonctionnalites__media-wrapper {
557
+ display: none;
558
+ }
559
+ }
560
+
561
+ .fr-sr-only {
562
+ clip-path: inset(100%);
563
+ clip: rect(1px, 1px, 1px, 1px);
564
+ height: 1px;
565
+ overflow: hidden;
566
+ position: absolute;
567
+ white-space: nowrap;
568
+ padding: 0;
569
+ width: 1px;
570
+ }</style>
@@ -0,0 +1,105 @@
1
+ import type { Accent, Size, Status } from "../types";
2
+ import "../dsfr/DsfrButton.svelte";
3
+ import "../dsfr/DsfrSegmented.svelte";
4
+ type BadgeSize = Extract<Size, "sm" | "md">;
5
+ type BadgeType = "default" | "accent" | "status";
6
+ interface Badge {
7
+ label: string;
8
+ accent?: Accent;
9
+ ellipsis?: boolean;
10
+ hasIcon?: boolean;
11
+ hasNoIcon?: boolean;
12
+ icon?: string;
13
+ size?: BadgeSize;
14
+ status?: Status;
15
+ type?: BadgeType;
16
+ }
17
+ type LinkSize = Extract<Size, "sm" | "md" | "lg">;
18
+ type IconPlace = "left" | "right";
19
+ interface Lien {
20
+ label: string;
21
+ size?: LinkSize;
22
+ id?: string;
23
+ disabled?: boolean;
24
+ blank?: boolean;
25
+ href?: string;
26
+ download?: string;
27
+ hasIcon?: boolean;
28
+ icon?: string;
29
+ iconPlace?: IconPlace;
30
+ neutral?: boolean;
31
+ }
32
+ interface Fonctionnalite {
33
+ titre: string;
34
+ description?: string;
35
+ id?: string;
36
+ illustration?: string;
37
+ badge?: Badge;
38
+ lien?: Lien;
39
+ rich?: boolean;
40
+ }
41
+ type Segmented = {
42
+ id: string;
43
+ label: string;
44
+ name: string;
45
+ checked?: boolean;
46
+ value?: string | number;
47
+ disabled?: boolean;
48
+ icon?: string;
49
+ };
50
+ interface Props {
51
+ /** Titre principal */
52
+ titre?: string;
53
+ /** Description du bloc fonctionnalités
54
+ * _(L'absence de contenu dans cette prop masque automatiquement la zone d'affichage associée)_
55
+ **/
56
+ description?: string;
57
+ /** Balise Hn du titre du composant (default: h3) */
58
+ baliseTitre?: "h2" | "h3" | "h4";
59
+ /** Permet d'afficher un contrôle segmenté pour filtrer les fonctionnalités */
60
+ avecControleSegmente?: boolean;
61
+ /** Taille du contrôle segmenté (default: md) */
62
+ tailleControleSegmente?: Extract<Size, "sm" | "md">;
63
+ /** Les éléments du contrôle segmenté */
64
+ elementsDuControleSegmente?: Segmented[];
65
+ /** Fonctionnalités de la carte */
66
+ fonctionnalites: Fonctionnalite[] | Fonctionnalite[][];
67
+ /** Balise Hn des sous-titres du composant (default: h3) */
68
+ baliseDesSousTitres?: "h3" | "h4" | "h5";
69
+ /** Permet de définir les items du composant comme "cliquable" ou non */
70
+ cliquable?: boolean;
71
+ /** Permet d'afficher un bouton dans le pied de page du composant */
72
+ avecCTA?: boolean;
73
+ /** Orientation du visuel par rapport aux items de fonctionnalités (default: droite) */
74
+ orientationMedia?: "droite" | "gauche";
75
+ /** Image "bouche trou" qui s'affiche dans le cadre de la version non cliquable */
76
+ imagePlaceholder?: string;
77
+ /** Délai en millisecondes entre chaque transition automatique (default: 5000) */
78
+ delaiDefilement?: number;
79
+ /** Active ou désactive le défilement automatique (default: false) */
80
+ activeDefilement?: boolean;
81
+ }
82
+ interface $$__sveltets_2_IsomorphicComponent<Props extends Record<string, any> = any, Events extends Record<string, any> = any, Slots extends Record<string, any> = any, Exports = {}, Bindings = string> {
83
+ new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
84
+ $$bindings?: Bindings;
85
+ } & Exports;
86
+ (internal: unknown, props: Props & {
87
+ $$events?: Events;
88
+ $$slots?: Slots;
89
+ }): Exports & {
90
+ $set?: any;
91
+ $on?: any;
92
+ };
93
+ z_$$bindings?: Bindings;
94
+ }
95
+ declare const BlocFonctionnalites: $$__sveltets_2_IsomorphicComponent<Props, {
96
+ [evt: string]: CustomEvent<any>;
97
+ }, {
98
+ hautentete: {};
99
+ titre: {};
100
+ description: {};
101
+ media: {};
102
+ cta: {};
103
+ }, {}, "">;
104
+ type BlocFonctionnalites = InstanceType<typeof BlocFonctionnalites>;
105
+ export default BlocFonctionnalites;