@lab-anssi/ui-kit 1.61.3 → 1.62.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.
- package/README.md +102 -21
- package/dist/assets/assets.d.ts +1 -0
- package/dist/assets/assets.js +1 -0
- package/dist/assets/dsfr-icons.css +1 -0
- package/dist/composants/Alerte.svelte +83 -0
- package/dist/composants/Alerte.svelte.d.ts +32 -0
- package/dist/composants/AncresParcours.svelte +132 -0
- package/dist/composants/AncresParcours.svelte.d.ts +11 -0
- package/dist/composants/BandeauPage.svelte +218 -0
- package/dist/composants/BandeauPage.svelte.d.ts +58 -0
- package/dist/composants/BlocFonctionnalites.svelte +570 -0
- package/dist/composants/BlocFonctionnalites.svelte.d.ts +105 -0
- package/dist/composants/Bouton.svelte +156 -0
- package/dist/composants/Bouton.svelte.d.ts +36 -0
- package/dist/composants/CentreAide.svelte +223 -0
- package/dist/composants/CentreAide.svelte.d.ts +41 -0
- package/dist/composants/FiltresCatalogue.svelte +147 -0
- package/dist/composants/FiltresCatalogue.svelte.d.ts +15 -0
- package/dist/composants/Icone.svelte +42 -0
- package/dist/composants/Icone.svelte.d.ts +7 -0
- package/dist/composants/Lien.svelte +233 -0
- package/dist/composants/Lien.svelte.d.ts +39 -0
- package/dist/composants/MultiSelect.svelte +931 -0
- package/dist/composants/MultiSelect.svelte.d.ts +51 -0
- package/dist/composants/Reactions.svelte +360 -0
- package/dist/composants/Reactions.svelte.d.ts +23 -0
- package/dist/composants/ResumePssi.svelte +92 -0
- package/dist/composants/ResumePssi.svelte.d.ts +6 -0
- package/dist/composants/Tag.svelte +113 -0
- package/dist/composants/Tag.svelte.d.ts +35 -0
- package/dist/composants/blog/BandeauTitre.svelte +150 -0
- package/dist/composants/blog/BandeauTitre.svelte.d.ts +29 -0
- package/dist/composants/blog/CarteArticle.svelte +69 -0
- package/dist/composants/blog/CarteArticle.svelte.d.ts +8 -0
- package/dist/composants/blog/IconeChevronBas.svelte +22 -0
- package/dist/composants/blog/IconeChevronBas.svelte.d.ts +26 -0
- package/dist/composants/blog/IconeMenuLateral.svelte +15 -0
- package/dist/composants/blog/IconeMenuLateral.svelte.d.ts +26 -0
- package/dist/composants/blog/ListeArticles.svelte +62 -0
- package/dist/composants/blog/ListeArticles.svelte.d.ts +9 -0
- package/dist/composants/blog/ListeDeroulante.svelte +57 -0
- package/dist/composants/blog/ListeDeroulante.svelte.d.ts +10 -0
- package/dist/composants/blog/PageCrisp.svelte +244 -0
- package/dist/composants/blog/PageCrisp.svelte.d.ts +8 -0
- package/dist/composants/blog/SommaireBureau.svelte +64 -0
- package/dist/composants/blog/SommaireBureau.svelte.d.ts +9 -0
- package/dist/composants/blog/SommaireMobile.svelte +115 -0
- package/dist/composants/blog/SommaireMobile.svelte.d.ts +9 -0
- package/dist/composants/carrousel-tuiles/CarrouselTuiles.svelte +184 -0
- package/dist/composants/carrousel-tuiles/CarrouselTuiles.svelte.d.ts +34 -0
- package/dist/composants/carrousel-tuiles/IconeFlecheDroite.svelte +16 -0
- package/dist/composants/carrousel-tuiles/IconeFlecheDroite.svelte.d.ts +26 -0
- package/dist/composants/carrousel-tuiles/IconeFlecheGauche.svelte +12 -0
- package/dist/composants/carrousel-tuiles/IconeFlecheGauche.svelte.d.ts +26 -0
- package/dist/composants/carrousel-tuiles/Tuile.svelte +72 -0
- package/dist/composants/carrousel-tuiles/Tuile.svelte.d.ts +10 -0
- package/dist/composants/icones/Fleche.svelte +25 -0
- package/dist/composants/icones/Fleche.svelte.d.ts +6 -0
- package/dist/composants/icones/LienExterne.svelte +20 -0
- package/dist/composants/icones/LienExterne.svelte.d.ts +6 -0
- package/dist/composants/marelle/Etape.svelte +165 -0
- package/dist/composants/marelle/Etape.svelte.d.ts +32 -0
- package/dist/composants/marelle/Marelle.svelte +97 -0
- package/dist/composants/marelle/Marelle.svelte.d.ts +44 -0
- package/dist/composants/mes-services-cyber/bandeau/Bandeau.svelte +158 -0
- package/dist/composants/mes-services-cyber/bandeau/Bandeau.svelte.d.ts +3 -0
- package/dist/composants/mes-services-cyber/lien/LienDiagnosticCyber.svelte +125 -0
- package/dist/composants/mes-services-cyber/lien/LienDiagnosticCyber.svelte.d.ts +7 -0
- package/dist/composants/pied-de-page/NavigationPiedDePage.svelte +62 -0
- package/dist/composants/pied-de-page/NavigationPiedDePage.svelte.d.ts +6 -0
- package/dist/composants/suite-cyber/AccueilSuiteCyber.svelte +96 -0
- package/dist/composants/suite-cyber/AccueilSuiteCyber.svelte.d.ts +6 -0
- package/dist/composants/suite-cyber/LiensSuiteCyber.svelte +99 -0
- package/dist/composants/suite-cyber/LiensSuiteCyber.svelte.d.ts +14 -0
- package/dist/composants/suite-cyber/SuiteCyber.svelte +296 -0
- package/dist/composants/suite-cyber/SuiteCyber.svelte.d.ts +6 -0
- package/dist/composants/vitrines-produits/briques/Brique.svelte +50 -0
- package/dist/composants/vitrines-produits/briques/Brique.svelte.d.ts +9 -0
- package/dist/composants/vitrines-produits/briques/BriqueContenuADeuxColonnes.svelte +144 -0
- package/dist/composants/vitrines-produits/briques/BriqueContenuADeuxColonnes.svelte.d.ts +29 -0
- package/dist/composants/vitrines-produits/briques/BriqueHero.svelte +246 -0
- package/dist/composants/vitrines-produits/briques/BriqueHero.svelte.d.ts +31 -0
- package/dist/composants/vitrines-produits/briques/BriqueTitreMultimedia.svelte +50 -0
- package/dist/composants/vitrines-produits/briques/BriqueTitreMultimedia.svelte.d.ts +25 -0
- package/dist/composants/vitrines-produits/briques/LecteurVideo.svelte +14 -0
- package/dist/composants/vitrines-produits/briques/LecteurVideo.svelte.d.ts +9 -0
- package/dist/composants/vitrines-produits/briques/PresentationANSSI.svelte +148 -0
- package/dist/composants/vitrines-produits/briques/PresentationANSSI.svelte.d.ts +37 -0
- package/dist/composants/vitrines-produits/briques/RejoindreLaCommunaute.svelte +139 -0
- package/dist/composants/vitrines-produits/briques/RejoindreLaCommunaute.svelte.d.ts +36 -0
- package/dist/composants/vitrines-produits/briques/temoignages/IconeTemoignage.svelte +18 -0
- package/dist/composants/vitrines-produits/briques/temoignages/IconeTemoignage.svelte.d.ts +26 -0
- package/dist/composants/vitrines-produits/briques/temoignages/Temoignages.svelte +168 -0
- package/dist/composants/vitrines-produits/briques/temoignages/Temoignages.svelte.d.ts +13 -0
- package/dist/directives/actions.svelte.d.ts +32 -0
- package/dist/directives/actions.svelte.js +158 -0
- package/dist/dsfr/DsfrAccordion.svelte +889 -0
- package/dist/dsfr/DsfrAccordion.svelte.d.ts +40 -0
- package/dist/dsfr/DsfrAlert.svelte +2097 -0
- package/dist/dsfr/DsfrAlert.svelte.d.ts +36 -0
- package/dist/dsfr/DsfrBadge.svelte +532 -0
- package/dist/dsfr/DsfrBadge.svelte.d.ts +41 -0
- package/dist/dsfr/DsfrBadgesGroup.svelte +610 -0
- package/dist/dsfr/DsfrBadgesGroup.svelte.d.ts +25 -0
- package/dist/dsfr/DsfrBreadcrumb.svelte +657 -0
- package/dist/dsfr/DsfrBreadcrumb.svelte.d.ts +25 -0
- package/dist/dsfr/DsfrButton.svelte +1821 -0
- package/dist/dsfr/DsfrButton.svelte.d.ts +68 -0
- package/dist/dsfr/DsfrButtonsGroup.svelte +1896 -0
- package/dist/dsfr/DsfrButtonsGroup.svelte.d.ts +36 -0
- package/dist/dsfr/DsfrCallout.svelte +242 -0
- package/dist/dsfr/DsfrCallout.svelte.d.ts +46 -0
- package/dist/dsfr/DsfrCard.svelte +10223 -0
- package/dist/dsfr/DsfrCard.svelte.d.ts +102 -0
- package/dist/dsfr/DsfrCheckbox.svelte +1280 -0
- package/dist/dsfr/DsfrCheckbox.svelte.d.ts +69 -0
- package/dist/dsfr/DsfrCheckboxesGroup.svelte +1532 -0
- package/dist/dsfr/DsfrCheckboxesGroup.svelte.d.ts +73 -0
- package/dist/dsfr/DsfrConnect.svelte +511 -0
- package/dist/dsfr/DsfrConnect.svelte.d.ts +15 -0
- package/dist/dsfr/DsfrContainer.svelte +894 -0
- package/dist/dsfr/DsfrContainer.svelte.d.ts +31 -0
- package/dist/dsfr/DsfrContent.svelte +1140 -0
- package/dist/dsfr/DsfrContent.svelte.d.ts +60 -0
- package/dist/dsfr/DsfrDropdown.svelte +335 -0
- package/dist/dsfr/DsfrDropdown.svelte.d.ts +73 -0
- package/dist/dsfr/DsfrFooter.svelte +2370 -0
- package/dist/dsfr/DsfrFooter.svelte.d.ts +77 -0
- package/dist/dsfr/DsfrHeader.svelte +4162 -0
- package/dist/dsfr/DsfrHeader.svelte.d.ts +131 -0
- package/dist/dsfr/DsfrHighlight.svelte +294 -0
- package/dist/dsfr/DsfrHighlight.svelte.d.ts +33 -0
- package/dist/dsfr/DsfrInput.svelte +1270 -0
- package/dist/dsfr/DsfrInput.svelte.d.ts +86 -0
- package/dist/dsfr/DsfrLabel.svelte +438 -0
- package/dist/dsfr/DsfrLabel.svelte.d.ts +65 -0
- package/dist/dsfr/DsfrLink.svelte +1007 -0
- package/dist/dsfr/DsfrLink.svelte.d.ts +66 -0
- package/dist/dsfr/DsfrLogo.svelte +228 -0
- package/dist/dsfr/DsfrLogo.svelte.d.ts +11 -0
- package/dist/dsfr/DsfrMessagesGroup.svelte +260 -0
- package/dist/dsfr/DsfrMessagesGroup.svelte.d.ts +46 -0
- package/dist/dsfr/DsfrModal.svelte +2983 -0
- package/dist/dsfr/DsfrModal.svelte.d.ts +56 -0
- package/dist/dsfr/DsfrNavigation.svelte +7626 -0
- package/dist/dsfr/DsfrNotice.svelte +2948 -0
- package/dist/dsfr/DsfrNotice.svelte.d.ts +37 -0
- package/dist/dsfr/DsfrPagination.svelte +1036 -0
- package/dist/dsfr/DsfrPagination.svelte.d.ts +35 -0
- package/dist/dsfr/DsfrQuote.svelte +646 -0
- package/dist/dsfr/DsfrQuote.svelte.d.ts +29 -0
- package/dist/dsfr/DsfrRadio.svelte +1307 -0
- package/dist/dsfr/DsfrRadio.svelte.d.ts +37 -0
- package/dist/dsfr/DsfrRadiosGroup.svelte +1629 -0
- package/dist/dsfr/DsfrRadiosGroup.svelte.d.ts +76 -0
- package/dist/dsfr/DsfrRange.svelte +1329 -0
- package/dist/dsfr/DsfrRange.svelte.d.ts +77 -0
- package/dist/dsfr/DsfrSearch.svelte +2015 -0
- package/dist/dsfr/DsfrSearch.svelte.d.ts +51 -0
- package/dist/dsfr/DsfrSegmented.svelte +422 -0
- package/dist/dsfr/DsfrSegmented.svelte.d.ts +34 -0
- package/dist/dsfr/DsfrSelect.svelte +1068 -0
- package/dist/dsfr/DsfrSelect.svelte.d.ts +86 -0
- package/dist/dsfr/DsfrShare.svelte +2228 -0
- package/dist/dsfr/DsfrShare.svelte.d.ts +40 -0
- package/dist/dsfr/DsfrSideMenu.svelte +1211 -0
- package/dist/dsfr/DsfrSideMenu.svelte.d.ts +34 -0
- package/dist/dsfr/DsfrSkipLink.svelte +990 -0
- package/dist/dsfr/DsfrSkipLink.svelte.d.ts +13 -0
- package/dist/dsfr/DsfrStepper.svelte +340 -0
- package/dist/dsfr/DsfrStepper.svelte.d.ts +18 -0
- package/dist/dsfr/DsfrTable.svelte +829 -0
- package/dist/dsfr/DsfrTable.svelte.d.ts +202 -0
- package/dist/dsfr/DsfrTabnav.svelte +1149 -0
- package/dist/dsfr/DsfrTabnav.svelte.d.ts +36 -0
- package/dist/dsfr/DsfrTabs.svelte +925 -0
- package/dist/dsfr/DsfrTabs.svelte.d.ts +28 -0
- package/dist/dsfr/DsfrTag.svelte +1269 -0
- package/dist/dsfr/DsfrTag.svelte.d.ts +59 -0
- package/dist/dsfr/DsfrTagsGroup.svelte +1351 -0
- package/dist/dsfr/DsfrTagsGroup.svelte.d.ts +37 -0
- package/dist/dsfr/DsfrTextarea.svelte +1385 -0
- package/dist/dsfr/DsfrTextarea.svelte.d.ts +72 -0
- package/dist/dsfr/DsfrTile.svelte +7645 -0
- package/dist/dsfr/DsfrTile.svelte.d.ts +79 -0
- package/dist/dsfr/DsfrToggle.svelte +1453 -0
- package/dist/dsfr/DsfrToggle.svelte.d.ts +56 -0
- package/dist/dsfr/DsfrTooltip.svelte +396 -0
- package/dist/dsfr/DsfrTooltip.svelte.d.ts +36 -0
- package/dist/dsfr/DsfrTranscription.svelte +2962 -0
- package/dist/dsfr/DsfrTranscription.svelte.d.ts +39 -0
- package/dist/dsfr/DsfrTranslate.svelte +1384 -0
- package/dist/dsfr/DsfrTranslate.svelte.d.ts +19 -0
- package/dist/dsfr/DsfrUser.svelte +736 -0
- package/dist/dsfr/DsfrUser.svelte.d.ts +65 -0
- package/dist/index.d.ts +79 -0
- package/dist/index.js +79 -0
- package/dist/styles/apparence-bouton.scss +154 -0
- package/dist/styles/dsfr-icons.css +1 -0
- package/dist/styles/dsfr-icons.scss +4 -0
- package/dist/styles/dsfr-variables.scss +28 -0
- package/dist/styles/mixins-dsfr.scss +226 -0
- package/dist/styles/mixins.scss +51 -0
- package/dist/types/commun.d.ts +63 -0
- package/dist/types/commun.js +1 -0
- package/dist/types/global.d.ts +24 -0
- package/dist/types/global.js +9 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.js +1 -0
- package/dist/ui-kit-components.json +142 -100
- package/dist/utilitaires/createFormValidation.svelte.d.ts +34 -0
- package/dist/utilitaires/createFormValidation.svelte.js +183 -0
- package/dist/utilitaires/icons-stylesheet.d.ts +370 -0
- package/dist/utilitaires/icons-stylesheet.js +33 -0
- package/dist/utilitaires/index.d.ts +14 -0
- package/dist/utilitaires/index.js +26 -0
- package/dist/web-types.json +149 -101
- package/dist/webcomponents/lab-anssi-ui-kit.iife.js +36 -9
- package/dist/webcomponents/lab-anssi-ui-kit.jsx.d.ts +42 -24
- package/package.json +49 -43
- package/dist/index.html +0 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
type Option = {
|
|
2
|
+
id: string;
|
|
3
|
+
value: string;
|
|
4
|
+
label: string;
|
|
5
|
+
};
|
|
6
|
+
interface Props {
|
|
7
|
+
/** Attribut id de la liste déroulante */
|
|
8
|
+
id: string;
|
|
9
|
+
/** Libellé de la liste déroulante */
|
|
10
|
+
label: string;
|
|
11
|
+
/** Options de la liste déroulante */
|
|
12
|
+
options?: Option[];
|
|
13
|
+
/** Texte additionnel sous le label */
|
|
14
|
+
hint?: string;
|
|
15
|
+
/** Texte avant sélection d'une option */
|
|
16
|
+
placeholder?: string;
|
|
17
|
+
/** Désactive la liste déroulante */
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
/** Valeur des checkboxes */
|
|
20
|
+
values?: string[];
|
|
21
|
+
/** Statut du message */
|
|
22
|
+
status?: "default" | "valid" | "error";
|
|
23
|
+
/** Texte du message d'erreur */
|
|
24
|
+
errorMessage?: string;
|
|
25
|
+
/** Texte du message de succès */
|
|
26
|
+
validMessage?: string;
|
|
27
|
+
/** Callback appelé lors du changement de valeur (déprécié, utiliser onvalueschanged) */
|
|
28
|
+
onvaluechanged?: (values: string[]) => void;
|
|
29
|
+
/** Callback appelé lors du changement des valeurs sélectionnées */
|
|
30
|
+
onvalueschanged?: (values: string[]) => void;
|
|
31
|
+
}
|
|
32
|
+
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> {
|
|
33
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
34
|
+
$$bindings?: Bindings;
|
|
35
|
+
} & Exports;
|
|
36
|
+
(internal: unknown, props: Props & {
|
|
37
|
+
$$events?: Events;
|
|
38
|
+
$$slots?: Slots;
|
|
39
|
+
}): Exports & {
|
|
40
|
+
$set?: any;
|
|
41
|
+
$on?: any;
|
|
42
|
+
};
|
|
43
|
+
z_$$bindings?: Bindings;
|
|
44
|
+
}
|
|
45
|
+
declare const MultiSelect: $$__sveltets_2_IsomorphicComponent<Props, {
|
|
46
|
+
[evt: string]: CustomEvent<any>;
|
|
47
|
+
}, {
|
|
48
|
+
'messages-group': {};
|
|
49
|
+
}, {}, "">;
|
|
50
|
+
type MultiSelect = InstanceType<typeof MultiSelect>;
|
|
51
|
+
export default MultiSelect;
|
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
<svelte:options
|
|
2
|
+
customElement={{
|
|
3
|
+
tag: "lab-anssi-reactions",
|
|
4
|
+
props: {
|
|
5
|
+
reactions: { attribute: "reactions", type: "Array" },
|
|
6
|
+
variant: { attribute: "variant", type: "String" },
|
|
7
|
+
tooltipTexte: { attribute: "tooltip-texte", type: "String" },
|
|
8
|
+
tooltipId: { attribute: "tooltip-id", type: "String" },
|
|
9
|
+
},
|
|
10
|
+
}}
|
|
11
|
+
/>
|
|
12
|
+
|
|
13
|
+
<script lang="ts">let { reactions = [], variant = "tertiaire-sans-bordure", tooltipTexte, tooltipId, onajouteReaction, onsupprimeReaction } = $props();
|
|
14
|
+
let tooltipShown = $state(false);
|
|
15
|
+
let popoverShown = $state(false);
|
|
16
|
+
let popoverElement = null;
|
|
17
|
+
let tooltipElement = $state(null);
|
|
18
|
+
let triggerButton = null;
|
|
19
|
+
/**
|
|
20
|
+
* Positionne dynamiquement le popover au-dessus du bouton déclencheur.
|
|
21
|
+
*
|
|
22
|
+
* @param {ToggleEvent} event - L'événement de bascule du popover.
|
|
23
|
+
*/
|
|
24
|
+
function handlePopover(event) {
|
|
25
|
+
if (!popoverElement) return;
|
|
26
|
+
const GAP = 4;
|
|
27
|
+
const popoverId = popoverElement.getAttribute("id");
|
|
28
|
+
if (!popoverId) return;
|
|
29
|
+
const parent = popoverElement.closest(".lab-anssi-reactions");
|
|
30
|
+
const button = parent?.querySelector(`[popovertarget="${popoverId}"]`);
|
|
31
|
+
if (!button) return;
|
|
32
|
+
if (event.newState === "open") {
|
|
33
|
+
popoverShown = true;
|
|
34
|
+
// Récupération des dimensions
|
|
35
|
+
const buttonRect = button.getBoundingClientRect();
|
|
36
|
+
const popoverRect = popoverElement.getBoundingClientRect();
|
|
37
|
+
const viewportHeight = window.innerHeight;
|
|
38
|
+
// Marges de sécurité
|
|
39
|
+
const VERTICAL_MARGIN = 8;
|
|
40
|
+
// Position par défaut : au-dessus et aligné à gauche du bouton
|
|
41
|
+
let top = buttonRect.top - popoverRect.height - GAP;
|
|
42
|
+
let left = buttonRect.left;
|
|
43
|
+
// Ajustement vertical : si pas assez de place en haut, placer en bas
|
|
44
|
+
if (top < VERTICAL_MARGIN) {
|
|
45
|
+
top = buttonRect.bottom + GAP;
|
|
46
|
+
if (top + popoverRect.height > viewportHeight - VERTICAL_MARGIN) {
|
|
47
|
+
top = Math.max(VERTICAL_MARGIN, (viewportHeight - popoverRect.height) / 2);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
// Application des positions finales
|
|
51
|
+
popoverElement.style.top = `${top}px`;
|
|
52
|
+
popoverElement.style.left = `${left}px`;
|
|
53
|
+
popoverElement.style.opacity = "1";
|
|
54
|
+
} else {
|
|
55
|
+
popoverShown = false;
|
|
56
|
+
popoverElement.style.opacity = "0";
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Gère la position du popover lors du défilement de la page.
|
|
61
|
+
* Recalcule et ajuste automatiquement la position verticale du popover
|
|
62
|
+
* pour qu'il reste visible dans la fenêtre d'affichage.
|
|
63
|
+
* Masque également le tooltip si celui-ci est affiché.
|
|
64
|
+
*
|
|
65
|
+
* @returns {void}
|
|
66
|
+
*/
|
|
67
|
+
function handlePopoverScroll() {
|
|
68
|
+
tooltipShown = false;
|
|
69
|
+
if (!popoverShown || !popoverElement || !triggerButton) return;
|
|
70
|
+
const GAP = 4;
|
|
71
|
+
// Récupération des nouvelles dimensions après scroll
|
|
72
|
+
const buttonRect = triggerButton.getBoundingClientRect();
|
|
73
|
+
const popoverRect = popoverElement.getBoundingClientRect();
|
|
74
|
+
const viewportHeight = window.innerHeight;
|
|
75
|
+
const VERTICAL_MARGIN = 8;
|
|
76
|
+
// Recalcul de la position verticale
|
|
77
|
+
let newTop = buttonRect.top - popoverRect.height - GAP;
|
|
78
|
+
// Ajustement vertical si nécessaire
|
|
79
|
+
if (newTop < VERTICAL_MARGIN) {
|
|
80
|
+
newTop = buttonRect.bottom + GAP;
|
|
81
|
+
if (newTop + popoverRect.height > viewportHeight - VERTICAL_MARGIN) {
|
|
82
|
+
newTop = Math.max(VERTICAL_MARGIN, (viewportHeight - popoverRect.height) / 2);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Application de la nouvelle position
|
|
86
|
+
popoverElement.style.top = `${newTop}px`;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Gère le clic sur un bouton de réaction.
|
|
90
|
+
*
|
|
91
|
+
* @param {MouseEvent} event - L'événement de clic provenant du bouton de réaction.
|
|
92
|
+
* @fires supprimeReaction - Émis lorsque la réaction est désactivée (détail : bouton.id).
|
|
93
|
+
* @fires ajouteReaction - Émis lorsque la réaction est activée (détail : bouton.id).
|
|
94
|
+
*/
|
|
95
|
+
function gestionClicReaction(event) {
|
|
96
|
+
const bouton = event.currentTarget;
|
|
97
|
+
const id = bouton.id;
|
|
98
|
+
// Trouve la réaction et récupère son état actuel
|
|
99
|
+
const reaction = reactions.find((reaction) => reaction.id === id);
|
|
100
|
+
const estActif = !!reaction?.actif;
|
|
101
|
+
const nouveauActif = !estActif;
|
|
102
|
+
// Met à jour le tableau de façon réactive
|
|
103
|
+
reactions = reactions.map((reaction) => reaction.id === id ? {
|
|
104
|
+
...reaction,
|
|
105
|
+
actif: nouveauActif
|
|
106
|
+
} : reaction);
|
|
107
|
+
// Émet un événement en fonction de l'état de la réaction
|
|
108
|
+
if (estActif) {
|
|
109
|
+
onsupprimeReaction?.(id);
|
|
110
|
+
$host()?.dispatchEvent(new CustomEvent("supprimeReaction", {
|
|
111
|
+
detail: id,
|
|
112
|
+
bubbles: true
|
|
113
|
+
}));
|
|
114
|
+
} else {
|
|
115
|
+
onajouteReaction?.(id);
|
|
116
|
+
$host()?.dispatchEvent(new CustomEvent("ajouteReaction", {
|
|
117
|
+
detail: id,
|
|
118
|
+
bubbles: true
|
|
119
|
+
}));
|
|
120
|
+
}
|
|
121
|
+
popoverElement?.hidePopover();
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Gère l'affichage et le positionnement d'un tooltip lors d'un survol de souris.
|
|
125
|
+
*
|
|
126
|
+
* @param {MouseEvent} event - Événement souris du gestionnaire de survol
|
|
127
|
+
* @returns {void}
|
|
128
|
+
*/
|
|
129
|
+
function handleTooltip() {
|
|
130
|
+
if (!tooltipElement || !triggerButton || popoverShown) return;
|
|
131
|
+
const buttonRect = triggerButton.getBoundingClientRect();
|
|
132
|
+
const buttonRectCenter = buttonRect.left + buttonRect.width * .5;
|
|
133
|
+
tooltipElement.style.display = "block";
|
|
134
|
+
const tooltipRect = tooltipElement.getBoundingClientRect();
|
|
135
|
+
// Dimensions de la fenêtre
|
|
136
|
+
const viewportWidth = window.innerWidth;
|
|
137
|
+
// Position par défaut : au-dessus et centré
|
|
138
|
+
let top = buttonRect.top - tooltipRect.height;
|
|
139
|
+
let left = buttonRect.left + buttonRect.width / 2 - tooltipRect.width / 2;
|
|
140
|
+
// Ajustement horizontal : éviter que le tooltip sorte des côtés
|
|
141
|
+
const HORIZONTAL_MARGIN = 8;
|
|
142
|
+
if (left < HORIZONTAL_MARGIN) {
|
|
143
|
+
left = HORIZONTAL_MARGIN;
|
|
144
|
+
} else if (left + tooltipRect.width > viewportWidth - HORIZONTAL_MARGIN) {
|
|
145
|
+
left = viewportWidth - tooltipRect.width - HORIZONTAL_MARGIN;
|
|
146
|
+
}
|
|
147
|
+
// Ajustement vertical : si pas assez de place en haut, placer en bas
|
|
148
|
+
const VERTICAL_MARGIN = 8;
|
|
149
|
+
if (top < VERTICAL_MARGIN) {
|
|
150
|
+
top = buttonRect.bottom;
|
|
151
|
+
// Ajouter une classe pour inverser la flèche si nécessaire
|
|
152
|
+
tooltipElement.classList.remove("fr-placement--top");
|
|
153
|
+
tooltipElement.classList.add("fr-placement--bottom");
|
|
154
|
+
} else {
|
|
155
|
+
tooltipElement.classList.remove("fr-placement--bottom");
|
|
156
|
+
tooltipElement.classList.add("fr-placement--top");
|
|
157
|
+
}
|
|
158
|
+
// Application des positions finales
|
|
159
|
+
tooltipElement.style.top = `${top}px`;
|
|
160
|
+
tooltipElement.style.left = `${left}px`;
|
|
161
|
+
// Calcul de la position de la flèche en fonction du décalage horizontal
|
|
162
|
+
const tooltipCenter = left + tooltipRect.width / 2;
|
|
163
|
+
const arrowPosition = buttonRectCenter - tooltipCenter;
|
|
164
|
+
// Limiter la position de la flèche dans les limites du tooltip
|
|
165
|
+
const maxArrowOffset = tooltipRect.width / 2 - 16;
|
|
166
|
+
const clampedArrowPosition = Math.max(-maxArrowOffset, Math.min(maxArrowOffset, arrowPosition));
|
|
167
|
+
tooltipElement.style.setProperty("--arrow-x", `${clampedArrowPosition.toFixed(2)}px`);
|
|
168
|
+
tooltipShown = true;
|
|
169
|
+
}
|
|
170
|
+
</script>
|
|
171
|
+
|
|
172
|
+
<svelte:window onscroll={handlePopoverScroll} />
|
|
173
|
+
|
|
174
|
+
{#snippet boutonReaction({ id, emoji, compteur, actif = false }: Reaction)}
|
|
175
|
+
<button
|
|
176
|
+
{id}
|
|
177
|
+
type="button"
|
|
178
|
+
class="lab-anssi-reactions__bouton"
|
|
179
|
+
onclick={gestionClicReaction}
|
|
180
|
+
aria-pressed={actif}
|
|
181
|
+
>
|
|
182
|
+
{#if !compteur}
|
|
183
|
+
<span class="lab-anssi-reactions__label">Réagir avec l'emoji</span>
|
|
184
|
+
{/if}
|
|
185
|
+
|
|
186
|
+
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
|
|
187
|
+
<span class="lab-anssi-reactions__emoji">{@html emoji}</span>
|
|
188
|
+
|
|
189
|
+
{#if compteur}
|
|
190
|
+
<span class="lab-anssi-reactions__compteur">{compteur}</span>
|
|
191
|
+
{/if}
|
|
192
|
+
</button>
|
|
193
|
+
{/snippet}
|
|
194
|
+
|
|
195
|
+
<div class={["lab-anssi-reactions", `lab-anssi-reactions--${variant}`]}>
|
|
196
|
+
<div class="lab-anssi-reactions__conteneur">
|
|
197
|
+
<button
|
|
198
|
+
type="button"
|
|
199
|
+
class="lab-anssi-reactions__declencheur"
|
|
200
|
+
popovertarget="popoverReactions"
|
|
201
|
+
aria-describedby={tooltipId}
|
|
202
|
+
onclick={() => (tooltipShown = false)}
|
|
203
|
+
onblur={() => (tooltipShown = false)}
|
|
204
|
+
onmouseout={() => (tooltipShown = false)}
|
|
205
|
+
onfocus={handleTooltip}
|
|
206
|
+
onmouseover={handleTooltip}
|
|
207
|
+
bind:this={triggerButton}
|
|
208
|
+
>
|
|
209
|
+
<span class="lab-anssi-reactions__icone">
|
|
210
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" aria-hidden="true"
|
|
211
|
+
><path
|
|
212
|
+
d="M15 18H18V15H20V18H23V20H20V23H18V20H15V18M12 17.5C9.67 17.5 7.69 16.04 6.89 14H15.69C14.5 14.78 13.62 15.97 13.23 17.36C12.83 17.45 12.42 17.5 12 17.5M8.5 11C7.67 11 7 10.33 7 9.5C7 8.67 7.67 8 8.5 8C9.33 8 10 8.67 10 9.5C10 10.33 9.33 11 8.5 11M15.5 11C14.67 11 14 10.33 14 9.5C14 8.67 14.67 8 15.5 8C16.33 8 17 8.67 17 9.5C17 10.33 16.33 11 15.5 11M12 20L13.07 19.93C13.18 20.61 13.4 21.26 13.72 21.85C13.16 21.95 12.58 22 12 22C6.47 22 2 17.5 2 12C2 6.5 6.47 2 12 2C17.5 2 22 6.5 22 12C22 12.59 21.95 13.16 21.85 13.72C21.26 13.4 20.62 13.18 19.93 13.07L20 12C20 7.58 16.42 4 12 4C7.58 4 4 7.58 4 12C4 16.42 7.58 20 12 20Z"
|
|
213
|
+
/></svg
|
|
214
|
+
>
|
|
215
|
+
</span>
|
|
216
|
+
<span class="lab-anssi-reactions__action">Ajouter une réaction</span>
|
|
217
|
+
</button>
|
|
218
|
+
{#if tooltipTexte}
|
|
219
|
+
<span
|
|
220
|
+
class="fr-tooltip fr-placement fr-placement--start"
|
|
221
|
+
class:fr-tooltip--shown={tooltipShown}
|
|
222
|
+
id={tooltipId}
|
|
223
|
+
role="tooltip"
|
|
224
|
+
bind:this={tooltipElement}
|
|
225
|
+
>
|
|
226
|
+
{tooltipTexte}
|
|
227
|
+
</span>
|
|
228
|
+
{/if}
|
|
229
|
+
|
|
230
|
+
{#each reactions as reaction (reaction.id)}
|
|
231
|
+
{#if reaction.compteur}
|
|
232
|
+
{@render boutonReaction(reaction)}
|
|
233
|
+
{/if}
|
|
234
|
+
{/each}
|
|
235
|
+
</div>
|
|
236
|
+
|
|
237
|
+
<div
|
|
238
|
+
id="popoverReactions"
|
|
239
|
+
class="lab-anssi-reactions__popover"
|
|
240
|
+
popover
|
|
241
|
+
ontoggle={handlePopover}
|
|
242
|
+
bind:this={popoverElement}
|
|
243
|
+
>
|
|
244
|
+
<div class="lab-anssi-reactions__conteneur">
|
|
245
|
+
{#each reactions as { id, emoji, actif } (id)}
|
|
246
|
+
{@render boutonReaction({ id, emoji, actif })}
|
|
247
|
+
{/each}
|
|
248
|
+
</div>
|
|
249
|
+
</div>
|
|
250
|
+
</div>
|
|
251
|
+
|
|
252
|
+
<style>/*!
|
|
253
|
+
* DSFR v1.14.4 | SPDX-License-Identifier: MIT | License-Filename: LICENSE.md | restricted use (see terms and conditions)
|
|
254
|
+
*/.fr-tooltip{--arrow-x:0;background-position:calc(50% + var(--arrow-x)) calc(100% - .5rem),calc(50% + var(--arrow-x)) calc(100% - .375rem),50% calc(100% - .75rem),50% calc(100% - .75rem);background-repeat:no-repeat;background-size:.5rem .375rem,.5rem .375rem,100% 1px,100% calc(100% - .75rem);color:var(--text-default-grey);display:block;font-size:.75rem;line-height:1.25rem;max-width:min(24rem,calc(66.66667vw - 1.33333rem));opacity:1;padding:.5rem .5rem 1.25rem;text-align:left;transition:opacity 0s .15s,visibility 0s .15s;visibility:visible;white-space:normal}.fr-tooltip:not(.fr-tooltip--shown){display:none;opacity:0}.fr-tooltip--hidding{opacity:0}.fr-tooltip.fr-placement--bottom{background-position-y:.5rem,.375rem,.75rem,.75rem;padding-bottom:.5rem;padding-top:1.25rem}.fr-tooltip.fr-placement{background-image:linear-gradient(90deg,var(--background-overlap-grey),var(--background-overlap-grey));filter:drop-shadow(var(--overlap-shadow));z-index:calc(var(--ground) + 1000)}@supports (background:conic-gradient(white,black)){.fr-tooltip.fr-placement--top{background-image:conic-gradient(from -33.69deg at 50% 100%,transparent 0deg,var(--background-overlap-grey) 0deg,var(--background-overlap-grey) 67.38deg,transparent 67.38deg),conic-gradient(from -33.69deg at 50% 100%,transparent 0deg,var(--border-default-grey) 0deg,var(--border-default-grey) 67.38deg,transparent 67.38deg),linear-gradient(90deg,var(--border-default-grey),var(--border-default-grey)),linear-gradient(90deg,var(--background-overlap-grey),var(--background-overlap-grey))}.fr-tooltip.fr-placement--bottom{background-image:conic-gradient(from 146.31deg at 50% 0,transparent 0deg,var(--background-overlap-grey) 0deg,var(--background-overlap-grey) 67.38deg,transparent 67.38deg),conic-gradient(from 146.31deg at 50% 0,transparent 0deg,var(--border-default-grey) 0deg,var(--border-default-grey) 67.38deg,transparent 67.38deg),linear-gradient(90deg,var(--border-default-grey),var(--border-default-grey)),linear-gradient(90deg,var(--background-overlap-grey),var(--background-overlap-grey))}}@media (min-width:36em){
|
|
255
|
+
/*! media sm */}@media (min-width:48em){
|
|
256
|
+
/*! media md */}@media (min-width:62em){
|
|
257
|
+
/*! media lg */}@media (min-width:78em){
|
|
258
|
+
/*! media xl */}@media (-ms-high-contrast:active),(forced-colors:active){.fr-tooltip{background:canvas;outline:1px solid}.fr-tooltip.fr-placement{padding:.5rem}}.fr-placement {
|
|
259
|
+
position: fixed;
|
|
260
|
+
width: max-content;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.lab-anssi-reactions {
|
|
264
|
+
box-sizing: border-box;
|
|
265
|
+
}
|
|
266
|
+
.lab-anssi-reactions__conteneur {
|
|
267
|
+
display: flex;
|
|
268
|
+
align-items: center;
|
|
269
|
+
gap: var(--gap, 4px);
|
|
270
|
+
}
|
|
271
|
+
.lab-anssi-reactions__declencheur, .lab-anssi-reactions__bouton {
|
|
272
|
+
--active-tint: var(--active);
|
|
273
|
+
--hover-tint: var(--hover);
|
|
274
|
+
appearance: none;
|
|
275
|
+
background-color: var(--background-color, transparent);
|
|
276
|
+
border: 1px solid var(--border-color, transparent);
|
|
277
|
+
cursor: pointer;
|
|
278
|
+
font: inherit;
|
|
279
|
+
}
|
|
280
|
+
.lab-anssi-reactions__declencheur:hover, .lab-anssi-reactions__bouton:hover {
|
|
281
|
+
--background-color: var(--hover-tint);
|
|
282
|
+
}
|
|
283
|
+
.lab-anssi-reactions__declencheur:active, .lab-anssi-reactions__bouton:active {
|
|
284
|
+
--background-color: var(--active-tint);
|
|
285
|
+
}
|
|
286
|
+
.lab-anssi-reactions__declencheur {
|
|
287
|
+
color: #666666;
|
|
288
|
+
padding: 4px;
|
|
289
|
+
position: relative;
|
|
290
|
+
}
|
|
291
|
+
.lab-anssi-reactions__icone svg {
|
|
292
|
+
fill: currentColor;
|
|
293
|
+
display: block;
|
|
294
|
+
height: 24px;
|
|
295
|
+
width: 24px;
|
|
296
|
+
}
|
|
297
|
+
.lab-anssi-reactions__action {
|
|
298
|
+
clip-path: inset(100%);
|
|
299
|
+
clip: rect(1px, 1px, 1px, 1px);
|
|
300
|
+
height: 1px;
|
|
301
|
+
overflow: hidden;
|
|
302
|
+
position: absolute;
|
|
303
|
+
white-space: nowrap;
|
|
304
|
+
padding: 0;
|
|
305
|
+
width: 1px;
|
|
306
|
+
}
|
|
307
|
+
.lab-anssi-reactions__bouton {
|
|
308
|
+
font-size: 14px;
|
|
309
|
+
font-weight: 500;
|
|
310
|
+
line-height: 24px;
|
|
311
|
+
padding: 4px 8px;
|
|
312
|
+
display: flex;
|
|
313
|
+
align-items: center;
|
|
314
|
+
justify-content: center;
|
|
315
|
+
}
|
|
316
|
+
.lab-anssi-reactions__bouton[aria-pressed=true] {
|
|
317
|
+
background-color: var(--background-action-low-blue-france);
|
|
318
|
+
color: var(--text-action-high-blue-france);
|
|
319
|
+
}
|
|
320
|
+
.lab-anssi-reactions__bouton[aria-pressed=true]:hover {
|
|
321
|
+
background-color: var(--background-action-low-blue-france-hover);
|
|
322
|
+
}
|
|
323
|
+
.lab-anssi-reactions__bouton[aria-pressed=true]:active {
|
|
324
|
+
background-color: var(--background-action-low-blue-france-active);
|
|
325
|
+
}
|
|
326
|
+
.lab-anssi-reactions__label {
|
|
327
|
+
clip-path: inset(100%);
|
|
328
|
+
clip: rect(1px, 1px, 1px, 1px);
|
|
329
|
+
height: 1px;
|
|
330
|
+
overflow: hidden;
|
|
331
|
+
position: absolute;
|
|
332
|
+
white-space: nowrap;
|
|
333
|
+
padding: 0;
|
|
334
|
+
width: 1px;
|
|
335
|
+
}
|
|
336
|
+
.lab-anssi-reactions__popover:popover-open {
|
|
337
|
+
border-width: 0;
|
|
338
|
+
background-color: #fff;
|
|
339
|
+
padding: 6px;
|
|
340
|
+
border-radius: 4px;
|
|
341
|
+
box-shadow: var(--raised-shadow);
|
|
342
|
+
margin: 0;
|
|
343
|
+
opacity: 0;
|
|
344
|
+
}
|
|
345
|
+
.lab-anssi-reactions__popover .lab-anssi-reactions__bouton {
|
|
346
|
+
font-size: 18px;
|
|
347
|
+
}
|
|
348
|
+
.lab-anssi-reactions--tertiaire > .lab-anssi-reactions__conteneur {
|
|
349
|
+
--gap: 8px;
|
|
350
|
+
}
|
|
351
|
+
.lab-anssi-reactions--tertiaire > .lab-anssi-reactions__conteneur .lab-anssi-reactions__declencheur, .lab-anssi-reactions--tertiaire > .lab-anssi-reactions__conteneur .lab-anssi-reactions__bouton {
|
|
352
|
+
--border-color: var(--border-default-grey);
|
|
353
|
+
}
|
|
354
|
+
.lab-anssi-reactions--tertiaire > .lab-anssi-reactions__conteneur .lab-anssi-reactions__declencheur[aria-pressed=true], .lab-anssi-reactions--tertiaire > .lab-anssi-reactions__conteneur .lab-anssi-reactions__bouton[aria-pressed=true] {
|
|
355
|
+
--border-color: var(--border-action-high-blue-france);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.fr-tooltip {
|
|
359
|
+
pointer-events: none;
|
|
360
|
+
}</style>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
type Reaction = {
|
|
2
|
+
id: string;
|
|
3
|
+
emoji: string;
|
|
4
|
+
compteur?: number | null;
|
|
5
|
+
actif?: boolean;
|
|
6
|
+
};
|
|
7
|
+
interface Props {
|
|
8
|
+
/** Liste des réactions */
|
|
9
|
+
reactions?: Reaction[];
|
|
10
|
+
/** Style des boutons de réaction<br>Valeurs :<br>- tertiaire : boutons avec bordure<br>- tertiaire-sans-bordure : boutons sans bordure */
|
|
11
|
+
variant?: "tertiaire" | "tertiaire-sans-bordure";
|
|
12
|
+
/** Contenu de l'infobulle */
|
|
13
|
+
tooltipTexte?: string;
|
|
14
|
+
/** Identifiant de l'infobulle */
|
|
15
|
+
tooltipId?: string;
|
|
16
|
+
/** Callback appelé lorsqu'une réaction est ajoutée */
|
|
17
|
+
onajouteReaction?: (id: string) => void;
|
|
18
|
+
/** Callback appelé lorsqu'une réaction est supprimée */
|
|
19
|
+
onsupprimeReaction?: (id: string) => void;
|
|
20
|
+
}
|
|
21
|
+
declare const Reactions: import("svelte").Component<Props, {}, "">;
|
|
22
|
+
type Reactions = ReturnType<typeof Reactions>;
|
|
23
|
+
export default Reactions;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<svelte:options customElement="lab-anssi-resume-pssi" />
|
|
2
|
+
|
|
3
|
+
<script lang="ts">let { nomService } = $props();
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
<p>
|
|
7
|
+
{nomService} est hébergé chez
|
|
8
|
+
<a href="https://www.clever-cloud.com/" rel="noopener" target="_blank"> Clever Cloud </a>
|
|
9
|
+
prenant appui sur
|
|
10
|
+
<a href="https://www.cloud-temple.com/notre-approche-secnumcloud/" rel="noopener" target="_blank">
|
|
11
|
+
Cloud Temple
|
|
12
|
+
</a>
|
|
13
|
+
qualifié SecNumCloud.
|
|
14
|
+
</p>
|
|
15
|
+
<p>
|
|
16
|
+
L'ANSSI soumet {nomService} à un rythme d'homologation soutenu dans le cadre d'une démarche de renforcement
|
|
17
|
+
continu de la sécurité du service numérique, dont plusieurs éléments clés mais non exhaustifs sont résumés
|
|
18
|
+
ci-dessous.
|
|
19
|
+
</p>
|
|
20
|
+
<h2>Gouvernance</h2>
|
|
21
|
+
<p>
|
|
22
|
+
Nous auditons régulièrement nos fournisseurs en termes de configuration et d'architecture et
|
|
23
|
+
maintenons un contact étroit avec eux pour améliorer en continu leur sécurité et donc celle de vos
|
|
24
|
+
données.
|
|
25
|
+
</p>
|
|
26
|
+
<p>
|
|
27
|
+
Nous auditons également régulièrement nos services (audits de code et tests d'intrusion) par des
|
|
28
|
+
prestataires qualifiés (PASSI).
|
|
29
|
+
</p>
|
|
30
|
+
<p>
|
|
31
|
+
Nous réalisons et tenons à jour une analyse de risques de nos services en prenant appui sur la
|
|
32
|
+
méthode EBIOS Risk Manager.
|
|
33
|
+
</p>
|
|
34
|
+
<p>
|
|
35
|
+
Nous maintenons une classification de l'ensemble des données que nous conservons, selon leur
|
|
36
|
+
sensibilité, afin d'assurer une protection adaptée.
|
|
37
|
+
</p>
|
|
38
|
+
<p>
|
|
39
|
+
Nous maintenons un dossier d’architecture technique détaillé de nos services et de leurs
|
|
40
|
+
interconnexions.
|
|
41
|
+
</p>
|
|
42
|
+
<p>
|
|
43
|
+
Les membres de nos équipes sont sensibilisés aux bonnes pratiques de sécurité, quels que soient
|
|
44
|
+
les profils (technique, produit, design, déploiement), au travers de formations en continu ou de
|
|
45
|
+
la réalisation de campagnes anti-phishing.
|
|
46
|
+
</p>
|
|
47
|
+
<h2>Protection</h2>
|
|
48
|
+
<p>Vos données sont protégées par un chiffrement multi-couches, système et applicatif.</p>
|
|
49
|
+
<p>
|
|
50
|
+
Chaque membre de notre équipe est équipé de clés d'authentification matérielle et
|
|
51
|
+
l’authentification multi-facteur est généralisée à tous les accès, permettant de mettre en œuvre
|
|
52
|
+
une authentification forte sur l'ensemble de nos services.
|
|
53
|
+
</p>
|
|
54
|
+
<p>
|
|
55
|
+
Nous limitons les accès au strict nécessaire et cloisonnons de façon rigoureuse les activités
|
|
56
|
+
d'administration, en particulier au niveau technique : utilisation de comptes dédiés et
|
|
57
|
+
séparés selon leurs usages ; postes d'administration durcis et réservés à ce seul
|
|
58
|
+
usage ; clés d’authentification nominatives.
|
|
59
|
+
</p>
|
|
60
|
+
<p>Nous n’installons et n’utilisons que les applications strictement nécessaires.</p>
|
|
61
|
+
<p>Les droits des administrateurs techniques et métiers sont restreints au strict nécessaire.</p>
|
|
62
|
+
<h2>Défense</h2>
|
|
63
|
+
<p>
|
|
64
|
+
La sécurité de nos services est surveillée en continu : détection de défiguration, scans
|
|
65
|
+
automatisés, veille active sur les risques émergents.
|
|
66
|
+
</p>
|
|
67
|
+
<p>
|
|
68
|
+
L'ensemble des actions est historisé de façon nominative pour simplifier l'analyse en cas
|
|
69
|
+
d'incident.
|
|
70
|
+
</p>
|
|
71
|
+
<p>
|
|
72
|
+
Nous mettons en œuvre et testons régulièrement notre procédure de gestion des incidents de
|
|
73
|
+
sécurité.
|
|
74
|
+
</p>
|
|
75
|
+
<h2>Résilience</h2>
|
|
76
|
+
<p>
|
|
77
|
+
Vos données sont sauvegardées de façon sécurisée et pérenne sur un environnement totalement séparé
|
|
78
|
+
de la plate-forme de production.
|
|
79
|
+
</p>
|
|
80
|
+
<p>
|
|
81
|
+
En cas d'incident majeur, nous sommes capables de reconstruire totalement l'application en
|
|
82
|
+
production dans un délai très court.
|
|
83
|
+
</p>
|
|
84
|
+
|
|
85
|
+
<style>a {
|
|
86
|
+
display: inline-flex;
|
|
87
|
+
color: #000091;
|
|
88
|
+
border: none;
|
|
89
|
+
text-decoration: underline;
|
|
90
|
+
text-underline-offset: 4px;
|
|
91
|
+
text-decoration-thickness: 1px;
|
|
92
|
+
}</style>
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
<svelte:options
|
|
2
|
+
customElement={{
|
|
3
|
+
tag: "lab-anssi-tag",
|
|
4
|
+
props: {
|
|
5
|
+
couleurFond: { reflect: false, type: "String", attribute: "couleur-fond" },
|
|
6
|
+
couleurTexte: { reflect: false, type: "String", attribute: "couleur-texte" },
|
|
7
|
+
label: { reflect: false, type: "String", attribute: "label" },
|
|
8
|
+
taille: { reflect: false, type: "String", attribute: "taille" },
|
|
9
|
+
type: { reflect: false, type: "String", attribute: "type" },
|
|
10
|
+
presse: { reflect: false, type: "Boolean", attribute: "presse" },
|
|
11
|
+
},
|
|
12
|
+
}}
|
|
13
|
+
/>
|
|
14
|
+
|
|
15
|
+
<script lang="ts">let { label = undefined, couleurTexte, couleurFond, taille = "sm", type = "defaut", presse = false } = $props();
|
|
16
|
+
let selectionne = $derived(presse);
|
|
17
|
+
const bascule = () => {
|
|
18
|
+
selectionne = !selectionne;
|
|
19
|
+
};
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
{#if type === "defaut"}
|
|
23
|
+
<span class="tag {taille}" style:background={couleurFond} style:color={couleurTexte}>
|
|
24
|
+
<slot>{label}</slot>
|
|
25
|
+
</span>
|
|
26
|
+
{:else}
|
|
27
|
+
<button
|
|
28
|
+
class="tag {taille}"
|
|
29
|
+
aria-pressed={selectionne}
|
|
30
|
+
style:background={couleurFond}
|
|
31
|
+
style:color={couleurTexte}
|
|
32
|
+
onclick={bascule}
|
|
33
|
+
>
|
|
34
|
+
<slot>{label}</slot>
|
|
35
|
+
</button>
|
|
36
|
+
{/if}
|
|
37
|
+
|
|
38
|
+
<style>.tag {
|
|
39
|
+
color: var(--tag-couleur-texte);
|
|
40
|
+
background-color: var(--tag-couleur-fond);
|
|
41
|
+
font-weight: 400;
|
|
42
|
+
display: inline-block;
|
|
43
|
+
width: fit-content;
|
|
44
|
+
white-space: nowrap;
|
|
45
|
+
max-width: 100%;
|
|
46
|
+
box-sizing: border-box;
|
|
47
|
+
overflow: hidden;
|
|
48
|
+
text-overflow: ellipsis;
|
|
49
|
+
}
|
|
50
|
+
.tag.sm {
|
|
51
|
+
font-size: 0.75rem;
|
|
52
|
+
line-height: 1.25rem;
|
|
53
|
+
padding: 2px 8px;
|
|
54
|
+
border-radius: 12px;
|
|
55
|
+
}
|
|
56
|
+
.tag.md {
|
|
57
|
+
font-size: 0.875rem;
|
|
58
|
+
line-height: 1.5rem;
|
|
59
|
+
padding: 4px 12px;
|
|
60
|
+
border-radius: 16px;
|
|
61
|
+
}
|
|
62
|
+
.tag:focus-visible {
|
|
63
|
+
outline: 2px solid #0a76f6;
|
|
64
|
+
outline-offset: 2px;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
button.tag {
|
|
68
|
+
color: var(--tag-selectionnable-couleur-texte);
|
|
69
|
+
background-color: var(--tag-selectionnable-couleur-fond);
|
|
70
|
+
border: none;
|
|
71
|
+
display: inline-flex;
|
|
72
|
+
position: relative;
|
|
73
|
+
overflow: visible;
|
|
74
|
+
text-wrap: auto;
|
|
75
|
+
text-align: left;
|
|
76
|
+
cursor: pointer;
|
|
77
|
+
font-family: inherit;
|
|
78
|
+
}
|
|
79
|
+
button.tag:hover {
|
|
80
|
+
background-color: var(--tag-selectionnable-couleur-fond-survol);
|
|
81
|
+
}
|
|
82
|
+
button.tag:active {
|
|
83
|
+
background-color: var(--tag-selectionnable-couleur-fond-clique);
|
|
84
|
+
}
|
|
85
|
+
button.tag[aria-pressed=true] {
|
|
86
|
+
color: var(--tag-selectionne-couleur-texte);
|
|
87
|
+
background-color: transparent;
|
|
88
|
+
background-image: radial-gradient(circle at 100% 0.25rem, transparent 0.578125rem, var(--tag-selectionne-couleur-fond) 0.625rem);
|
|
89
|
+
}
|
|
90
|
+
button.tag[aria-pressed=true]:hover {
|
|
91
|
+
background-image: radial-gradient(circle at 100% 0.25rem, transparent 0.578125rem, var(--tag-selectionne-couleur-fond-survol) 0.625rem);
|
|
92
|
+
}
|
|
93
|
+
button.tag[aria-pressed=true]:active {
|
|
94
|
+
background-image: radial-gradient(circle at 100% 0.25rem, transparent 0.578125rem, var(--tag-selectionne-couleur-fond-clique) 0.625rem);
|
|
95
|
+
}
|
|
96
|
+
button.tag[aria-pressed=true]::after {
|
|
97
|
+
-webkit-mask-image: url("https://lab-anssi-ui-kit-prod-s3-assets.cellar-c2.services.clever-cloud.com/icones/dsfr/system/checkbox-circle-line.svg");
|
|
98
|
+
mask-image: url("https://lab-anssi-ui-kit-prod-s3-assets.cellar-c2.services.clever-cloud.com/icones/dsfr/system/checkbox-circle-line.svg");
|
|
99
|
+
background-color: var(--tag-selectionnable-couleur-texte);
|
|
100
|
+
--icon-size: 1rem;
|
|
101
|
+
content: "";
|
|
102
|
+
display: inline-block;
|
|
103
|
+
flex: 0 0 auto;
|
|
104
|
+
height: var(--icon-size);
|
|
105
|
+
margin: -0.5rem;
|
|
106
|
+
-webkit-mask-size: 100% 100%;
|
|
107
|
+
mask-size: 100% 100%;
|
|
108
|
+
position: absolute;
|
|
109
|
+
right: 0;
|
|
110
|
+
top: 4px;
|
|
111
|
+
vertical-align: calc((0.75em - var(--icon-size)) * 0.5);
|
|
112
|
+
width: var(--icon-size);
|
|
113
|
+
}</style>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
label?: string;
|
|
3
|
+
couleurTexte: string | undefined;
|
|
4
|
+
couleurFond: string | undefined;
|
|
5
|
+
taille?: "sm" | "md";
|
|
6
|
+
type?: "defaut" | "selectionnable";
|
|
7
|
+
presse?: boolean;
|
|
8
|
+
}
|
|
9
|
+
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> {
|
|
10
|
+
new (options: import('svelte').ComponentConstructorOptions<Props>): import('svelte').SvelteComponent<Props, Events, Slots> & {
|
|
11
|
+
$$bindings?: Bindings;
|
|
12
|
+
} & Exports;
|
|
13
|
+
(internal: unknown, props: Props & {
|
|
14
|
+
$$events?: Events;
|
|
15
|
+
$$slots?: Slots;
|
|
16
|
+
}): Exports & {
|
|
17
|
+
$set?: any;
|
|
18
|
+
$on?: any;
|
|
19
|
+
};
|
|
20
|
+
z_$$bindings?: Bindings;
|
|
21
|
+
}
|
|
22
|
+
type $$__sveltets_2_PropsWithChildren<Props, Slots> = Props & (Slots extends {
|
|
23
|
+
default: any;
|
|
24
|
+
} ? Props extends Record<string, never> ? any : {
|
|
25
|
+
children?: any;
|
|
26
|
+
} : {});
|
|
27
|
+
declare const Tag: $$__sveltets_2_IsomorphicComponent<$$__sveltets_2_PropsWithChildren<Props, {
|
|
28
|
+
default: {};
|
|
29
|
+
}>, {
|
|
30
|
+
[evt: string]: CustomEvent<any>;
|
|
31
|
+
}, {
|
|
32
|
+
default: {};
|
|
33
|
+
}, {}, "">;
|
|
34
|
+
type Tag = InstanceType<typeof Tag>;
|
|
35
|
+
export default Tag;
|