@lystech/sections 0.4.6 → 0.5.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 +36 -0
- package/dist/SectionsProvider.d.ts +19 -0
- package/dist/SignatureLystech.d.ts +9 -2
- package/dist/constantes.d.ts +14 -0
- package/dist/editeur/TexteEnPlace.d.ts +6 -1
- package/dist/editeur/styles.d.ts +1 -1
- package/dist/editeur.js +540 -485
- package/dist/index.d.ts +1 -0
- package/dist/index.js +179 -158
- package/dist/jeton.d.ts +14 -0
- package/dist/morceaux/constantes-BPZxUYge.js +19 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -93,6 +93,42 @@ si la personne est administratrice : un lien qui fuite ne peut pas ouvrir la
|
|
|
93
93
|
console. Le droit est relu dans les rôles à chaque requête, donc retirer un
|
|
94
94
|
accès ferme les jetons déjà émis sur-le-champ.
|
|
95
95
|
|
|
96
|
+
### Des gestes propres au site : `appelEdition`
|
|
97
|
+
|
|
98
|
+
Un site peut offrir, à la personne connectée, des gestes que l'éditeur
|
|
99
|
+
générique ne connaît pas — retirer un résultat, masquer un évènement. Le
|
|
100
|
+
contexte fournit un appel qui porte le jeton, sans jamais en livrer la valeur :
|
|
101
|
+
|
|
102
|
+
```tsx
|
|
103
|
+
const ctx = useSectionsContext();
|
|
104
|
+
if (ctx?.modeEdition) {
|
|
105
|
+
const r = await ctx.appelEdition("/results/site/droits");
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Seuls les chemins de l'API sont acceptés. Un `401` fait sortir du mode édition
|
|
110
|
+
(jeton expiré) ; un `403` revient tel quel. C'est la ROUTE qui décide de ce que
|
|
111
|
+
le jeton ouvre : plafonné à l'éditeur partout, il n'obtient plus qu'en de rares
|
|
112
|
+
routes qui le disent explicitement (ex. `/results/site`, admins seulement).
|
|
113
|
+
|
|
114
|
+
### Des boutons qui restent des boutons
|
|
115
|
+
|
|
116
|
+
En mode « modifier », cliquer un texte le corrige au lieu de l'actionner — mais
|
|
117
|
+
seulement un texte qui a un bloc déclaré où s'enregistrer. Pour qu'une zone
|
|
118
|
+
reste actionnable quoi qu'il arrive (une suppression et sa confirmation), posez
|
|
119
|
+
`CLASSE_HORS_EDITION` dessus — et sur `rootClassName` des fenêtres surgissantes,
|
|
120
|
+
qui se rendent hors de l'arbre :
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
<section className={CLASSE_HORS_EDITION}>…</section>
|
|
124
|
+
<Popconfirm rootClassName={CLASSE_HORS_EDITION} …>
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Un site qui signe déjà
|
|
128
|
+
|
|
129
|
+
`<SignatureLystech mention={null} />` ne garde que le bouton « Connexion » —
|
|
130
|
+
pour un pied de page qui porte déjà sa propre mention de Lystech.
|
|
131
|
+
|
|
96
132
|
## Sites prérendus
|
|
97
133
|
|
|
98
134
|
Un site généré au build affiche les replis du code dans son HTML, puis bascule
|
|
@@ -35,6 +35,25 @@ type Contexte = {
|
|
|
35
35
|
* marchait.
|
|
36
36
|
*/
|
|
37
37
|
declarerRepli: (blockType: string, defaut: unknown) => void;
|
|
38
|
+
/**
|
|
39
|
+
* APPELER L'API LYSTECH AU NOM DE LA PERSONNE CONNECTÉE.
|
|
40
|
+
*
|
|
41
|
+
* Pour les gestes propres à un site — retirer un résultat, masquer un
|
|
42
|
+
* évènement — que l'éditeur générique ne connaît pas. Le site ne reçoit
|
|
43
|
+
* jamais la valeur du jeton : il obtient un appel qui le porte, et c'est
|
|
44
|
+
* le paquet qui décide où il part. Seuls les chemins de l'API sont
|
|
45
|
+
* acceptés (« /results/site/droits ») : collé à `apiBaseUrl`, un chemin ne
|
|
46
|
+
* peut pas changer de serveur.
|
|
47
|
+
*
|
|
48
|
+
* Le serveur reste seul juge de ce que le jeton autorise : ce que l'appel
|
|
49
|
+
* ouvre, c'est ce que la route accepte pour cette personne, pas plus.
|
|
50
|
+
*
|
|
51
|
+
* Un 401 veut dire que le jeton ne vaut plus rien : on sort du mode
|
|
52
|
+
* édition, comme l'éditeur le fait pour ses propres appels. Un 403, lui,
|
|
53
|
+
* est une réponse normale (« pas pour vous ») et revient telle quelle.
|
|
54
|
+
* Hors mode édition, l'appel échoue sans rien envoyer.
|
|
55
|
+
*/
|
|
56
|
+
appelEdition: (chemin: string, init?: RequestInit) => Promise<Response>;
|
|
38
57
|
};
|
|
39
58
|
export declare function SectionsProvider({ site, page, langue, apiBaseUrl, sectionsInitiales, sourceTexte, pagesPartagees, children, }: {
|
|
40
59
|
/** Sous-domaine de l'organisation (ex. « armoise »). */
|
|
@@ -1,10 +1,17 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
1
2
|
export declare function SignatureLystech({ site, apiBaseUrl, className, mention, connexion, methodes, }: {
|
|
2
3
|
/** Sous-domaine de l'organisation. Pris du fournisseur si omis. */
|
|
3
4
|
site?: string | undefined;
|
|
4
5
|
apiBaseUrl?: string | undefined;
|
|
5
6
|
className?: string | undefined;
|
|
6
|
-
/**
|
|
7
|
-
|
|
7
|
+
/**
|
|
8
|
+
* Les mots de la mention, si le site en préfère d'autres.
|
|
9
|
+
*
|
|
10
|
+
* `null` la retire : pour un site qui signe déjà à sa façon (un logo, une
|
|
11
|
+
* phrase à lui), il ne reste que « Connexion » — deux liens vers Lystech
|
|
12
|
+
* côte à côte, c'est un de trop.
|
|
13
|
+
*/
|
|
14
|
+
mention?: ReactNode | undefined;
|
|
8
15
|
connexion?: string | undefined;
|
|
9
16
|
/**
|
|
10
17
|
* Les facons de se connecter proposees a la personne qui edite.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LA ZONE QUE L'ÉDITION EN PLACE NE TOUCHE PAS.
|
|
3
|
+
*
|
|
4
|
+
* En mode « modifier », un clic sur un texte du site le corrige au lieu de
|
|
5
|
+
* l'actionner. C'est voulu pour un titre ou un lien de menu ; c'est une panne
|
|
6
|
+
* pour un bouton qui doit AGIR même en mode édition — une suppression, sa
|
|
7
|
+
* confirmation. Un élément portant cette classe (ou dans un parent qui la
|
|
8
|
+
* porte) n'est jamais repéré : ses clics passent.
|
|
9
|
+
*
|
|
10
|
+
* Une classe plutôt qu'un attribut : les fenêtres surgissantes des
|
|
11
|
+
* bibliothèques (antd, etc.) se rendent hors de l'arbre, et n'acceptent en
|
|
12
|
+
* général qu'un nom de classe (`rootClassName`).
|
|
13
|
+
*/
|
|
14
|
+
export declare const CLASSE_HORS_EDITION = "lystech-hors-edition";
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
import { SourceTexte } from '../sourceTexte';
|
|
2
|
-
export declare function TexteEnPlace({ source, actif, surModification, }: {
|
|
2
|
+
export declare function TexteEnPlace({ source, actif, modifiable, surModification, }: {
|
|
3
3
|
source: SourceTexte;
|
|
4
4
|
/** Faux pendant qu'un panneau est ouvert : on ne veut pas deux modes. */
|
|
5
5
|
actif: boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Ce texte a-t-il un bloc où s'enregistrer ? Change quand le catalogue
|
|
8
|
+
* arrive : avant lui, rien n'est repéré — c'est le bon défaut.
|
|
9
|
+
*/
|
|
10
|
+
modifiable: (ns: string, chemin: string) => boolean;
|
|
6
11
|
surModification: (ns: string, chemin: string, langue: string, valeur: string) => void | Promise<void>;
|
|
7
12
|
}): import("react").JSX.Element | null;
|
package/dist/editeur/styles.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export declare const CSS = "\n:host {\n all: initial;\n --fond: #16181d;\n --fond-clair: #21242b;\n --bord: #333844;\n --texte: #f2f3f5;\n --texte-doux: #a3a9b6;\n --accent: #3ba58d;\n --accent-sombre: #2d8570;\n --danger: #d9776a;\n font-family: ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto,\n \"Helvetica Neue\", Arial, sans-serif;\n font-size: 14px;\n line-height: 1.45;\n color: var(--texte);\n}\n\n* { box-sizing: border-box; }\n\n/* LE CALQUE LAISSE PASSER LES CLICS. Un conteneur fixe en plein \u00E9cran qui\n intercepte tout rendrait le site inutilisable derri\u00E8re lui : on ne pourrait\n plus naviguer, ni m\u00EAme faire d\u00E9filer correctement. Seuls ses ENFANTS\n reprennent les clics. */\n.calque {\n position: fixed;\n inset: 0;\n pointer-events: none;\n z-index: 2147483000;\n}\n.calque > * { pointer-events: auto; }\n\n/* ---------------------------------------------------------- CADRES ------ */\n\n.cadre {\n position: fixed;\n border: 2px dashed rgba(59, 165, 141, 0.55);\n border-radius: 6px;\n pointer-events: none;\n transition: border-color 120ms ease;\n}\n.cadre--actif { border-color: var(--accent); border-style: solid; }\n\n.pastille {\n position: fixed;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 5px 10px;\n border: 0;\n border-radius: 999px;\n background: var(--accent);\n color: #06120e;\n font-size: 12px;\n font-weight: 650;\n letter-spacing: 0.01em;\n cursor: pointer;\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);\n}\n.pastille:hover { background: #45bda2; }\n.pastille:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }\n\n/* ------------------------------------------------------------ BARRE ----- */\n\n.barre {\n position: fixed;\n left: 50%;\n bottom: 18px;\n transform: translateX(-50%);\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 9px 14px;\n border: 1px solid var(--bord);\n border-radius: 999px;\n background: var(--fond);\n box-shadow: 0 8px 30px rgba(0, 0, 0, 0.45);\n max-width: calc(100vw - 24px);\n}\n.barre__point {\n width: 8px; height: 8px; border-radius: 50%;\n background: var(--accent);\n flex: none;\n}\n.barre__texte { font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.barre__texte b { font-weight: 650; }\n.barre__compte { color: var(--texte-doux); font-size: 12px; white-space: nowrap; }\n\n/* ----------------------------------------------------------- PANNEAU ---- */\n\n.panneau {\n position: fixed;\n top: 0; right: 0; bottom: 0;\n width: min(420px, 100vw);\n display: flex;\n flex-direction: column;\n background: var(--fond);\n border-left: 1px solid var(--bord);\n box-shadow: -12px 0 40px rgba(0, 0, 0, 0.4);\n}\n@media (max-width: 520px) {\n .panneau { top: auto; height: 78vh; border-left: 0; border-top: 1px solid var(--bord); }\n}\n\n.panneau__tete {\n display: flex; align-items: flex-start; gap: 10px;\n padding: 16px 16px 12px;\n border-bottom: 1px solid var(--bord);\n}\n.panneau__titre { font-size: 15px; font-weight: 650; margin: 0; }\n.panneau__sous { margin: 3px 0 0; font-size: 12px; color: var(--texte-doux); }\n.panneau__corps { flex: 1; overflow-y: auto; padding: 14px 16px 18px; }\n.panneau__pied {\n display: flex; gap: 8px; align-items: center;\n padding: 12px 16px;\n border-top: 1px solid var(--bord);\n background: var(--fond-clair);\n}\n.panneau__pied .espace { flex: 1; }\n\n/* --------------------------------------------------- CONNEXION ---------- */\n\n/* Le voile PREND les clics, lui : une boite de dialogue qui demande un mot de\n passe ne doit pas laisser cliquer la page derriere elle. C'est l'exception\n a la regle du calque, et elle est volontaire. */\n.voile {\n position: fixed;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 16px;\n background: rgba(8, 10, 14, 0.62);\n backdrop-filter: blur(2px);\n}\n\n.fenetre {\n position: relative;\n width: min(408px, 100%);\n max-height: 92vh;\n overflow-y: auto;\n padding: 30px 28px 20px;\n border: 1px solid var(--bord);\n border-radius: 18px;\n /* Une lueur d'accent dans le coin superieur : de la presence, sans le\n degrade violet-bleu qu'on voit sur une page d'accueil sur deux. */\n background:\n radial-gradient(120% 90% at 50% -20%, rgba(59, 165, 141, 0.16), transparent 62%),\n var(--fond);\n box-shadow: 0 28px 70px rgba(0, 0, 0, 0.55);\n text-align: center;\n}\n\n.fenetre__fermer {\n position: absolute; top: 12px; right: 12px;\n width: 30px; height: 30px;\n display: inline-flex; align-items: center; justify-content: center;\n border: 0; border-radius: 8px;\n background: transparent; color: var(--texte-doux);\n font: inherit; font-size: 14px; cursor: pointer;\n}\n.fenetre__fermer:hover { background: var(--fond-clair); color: var(--texte); }\n\n/* ------------------------------------------------------------ MARQUE ---- */\n\n.marque {\n display: inline-flex; align-items: center; gap: 8px;\n margin-bottom: 18px;\n}\n.marque img { width: 22px; height: 22px; display: block; }\n.marque__mot {\n font-size: 12px; font-weight: 600;\n letter-spacing: 0.18em; text-transform: uppercase;\n color: #6fd3bd;\n}\n\n.fenetre__titre {\n margin: 0 0 6px;\n font-size: 20px; font-weight: 640; letter-spacing: -0.01em;\n color: var(--texte);\n}\n.fenetre__sous {\n margin: 0 auto 22px;\n max-width: 30ch;\n font-size: 13px; line-height: 1.5; color: var(--texte-doux);\n}\n.fenetre__corps { text-align: left; }\n\n/* ------------------------------------------------------ FOURNISSEURS ---- */\n\n.fournisseurs { display: flex; flex-direction: column; gap: 10px; }\n\n.fournisseur {\n display: flex; align-items: center; justify-content: center; gap: 10px;\n width: 100%; padding: 12px 16px;\n border: 1px solid transparent; border-radius: 10px;\n font: inherit; font-size: 14px; font-weight: 600;\n cursor: pointer;\n transition: transform 90ms ease, filter 90ms ease;\n}\n.fournisseur:hover { filter: brightness(1.06); }\n.fournisseur:active { transform: translateY(1px); }\n.fournisseur:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }\n.fournisseur[disabled] { opacity: 0.55; cursor: default; transform: none; filter: none; }\n.fournisseur .logo { width: 18px; height: 18px; flex: none; display: block; }\n\n/* LES COULEURS DE CHAQUE MARQUE, telles qu'elles les publient. Un bouton\n Google repeint aux couleurs du site devient moins reconnaissable \u2014 et un\n bouton de connexion qu'on ne reconnait pas est un bouton sur lequel on\n hesite a cliquer. */\n.fournisseur--google { background: #fff; color: #1f1f1f; border-color: #dadce0; }\n.fournisseur--facebook { background: #1877f2; color: #fff; }\n\n.bouton--large { width: 100%; padding: 12px 16px; font-size: 14px; }\n\n@media (prefers-reduced-motion: reduce) {\n .fournisseur { transition: none; }\n}\n\n/* ------------------------------------------------------------ CHAMPS ---- */\n\n.champ { margin-bottom: 16px; }\n.champ__etiquette {\n display: block; margin-bottom: 5px;\n font-size: 12px; font-weight: 600; color: var(--texte);\n}\n.champ__aide { margin: 4px 0 0; font-size: 11.5px; color: var(--texte-doux); }\n.champ__langue {\n display: inline-block; margin: 0 0 4px;\n font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em;\n text-transform: uppercase; color: var(--texte-doux);\n}\n\n/* TOUS les types de champs, pas seulement ceux auxquels on pensait. Un\n type oublie \u2014 \u00AB password \u00BB, \u00AB email \u00BB \u2014 retombe sur le style brut du\n navigateur : une ligne blanche au milieu d'un panneau sombre. */\ninput[type=\"text\"], input[type=\"url\"], input[type=\"number\"], input[type=\"date\"],\ninput[type=\"password\"], input[type=\"email\"], input[type=\"tel\"], input[type=\"search\"],\nselect, textarea {\n width: 100%;\n padding: 8px 10px;\n border: 1px solid var(--bord);\n border-radius: 6px;\n background: var(--fond-clair);\n color: var(--texte);\n font: inherit;\n font-size: 13px;\n}\ntextarea { min-height: 92px; resize: vertical; line-height: 1.5; }\ninput:focus, select:focus, textarea:focus {\n outline: none; border-color: var(--accent);\n box-shadow: 0 0 0 3px rgba(59, 165, 141, 0.18);\n}\n\n.bascule { display: flex; align-items: center; gap: 8px; }\n.bascule input { width: 16px; height: 16px; accent-color: var(--accent); }\n\n.vignette {\n margin-top: 8px; max-height: 110px; border-radius: 6px;\n border: 1px solid var(--bord); display: block;\n}\n\n/* --------------------------------------------------------- LISTES ------- */\n\n.liste__item {\n border: 1px solid var(--bord); border-radius: 8px;\n padding: 12px; margin-bottom: 10px; background: var(--fond-clair);\n}\n.liste__tete {\n display: flex; align-items: center; justify-content: space-between;\n margin-bottom: 8px;\n}\n.liste__rang { font-size: 11px; font-weight: 700; color: var(--texte-doux); }\n\n/* --------------------------------------------------------- BOUTONS ------ */\n\n.bouton {\n display: inline-flex; align-items: center; justify-content: center; gap: 6px;\n padding: 8px 14px; border-radius: 7px; border: 1px solid transparent;\n font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;\n background: var(--fond-clair); color: var(--texte); border-color: var(--bord);\n}\n.bouton:hover { background: #2a2e37; }\n.bouton:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }\n.bouton--principal { background: var(--accent); border-color: var(--accent); color: #06120e; }\n.bouton--principal:hover { background: #45bda2; }\n.bouton--discret { background: transparent; border-color: transparent; color: var(--texte-doux); }\n.bouton--discret:hover { background: var(--fond-clair); color: var(--texte); }\n.bouton[disabled] { opacity: 0.5; cursor: default; }\n.bouton--icone { padding: 6px 9px; }\n\n.message {\n margin: 0 0 12px; padding: 9px 11px; border-radius: 7px;\n font-size: 12.5px; border: 1px solid;\n}\n.message--erreur { background: rgba(217, 119, 106, 0.12); border-color: rgba(217, 119, 106, 0.4); color: #f0b3a9; }\n.message--ok { background: rgba(59, 165, 141, 0.12); border-color: rgba(59, 165, 141, 0.4); color: #8fd9c6; }\n.message--info { background: var(--fond-clair); border-color: var(--bord); color: var(--texte-doux); }\n\n@media (prefers-reduced-motion: reduce) {\n * { transition: none !important; animation: none !important; }\n}\n";
|
|
1
|
+
export declare const CSS = "\n:host {\n all: initial;\n --fond: #16181d;\n --fond-clair: #21242b;\n --bord: #333844;\n --texte: #f2f3f5;\n --texte-doux: #a3a9b6;\n --accent: #3ba58d;\n --accent-sombre: #2d8570;\n --danger: #d9776a;\n font-family: ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto,\n \"Helvetica Neue\", Arial, sans-serif;\n font-size: 14px;\n line-height: 1.45;\n color: var(--texte);\n}\n\n* { box-sizing: border-box; }\n\n/* LE CALQUE LAISSE PASSER LES CLICS. Un conteneur fixe en plein \u00E9cran qui\n intercepte tout rendrait le site inutilisable derri\u00E8re lui : on ne pourrait\n plus naviguer, ni m\u00EAme faire d\u00E9filer correctement. Seuls ses ENFANTS\n reprennent les clics. */\n.calque {\n position: fixed;\n inset: 0;\n pointer-events: none;\n z-index: 2147483000;\n}\n.calque > * { pointer-events: auto; }\n\n/* ---------------------------------------------------------- CADRES ------ */\n\n.cadre {\n position: fixed;\n border: 2px dashed rgba(59, 165, 141, 0.55);\n border-radius: 6px;\n pointer-events: none;\n transition: border-color 120ms ease;\n}\n.cadre--actif { border-color: var(--accent); border-style: solid; }\n\n.pastille {\n position: fixed;\n display: inline-flex;\n align-items: center;\n gap: 6px;\n padding: 5px 10px;\n border: 0;\n border-radius: 999px;\n background: var(--accent);\n color: #06120e;\n font-size: 12px;\n font-weight: 650;\n letter-spacing: 0.01em;\n cursor: pointer;\n box-shadow: 0 2px 10px rgba(0, 0, 0, 0.35);\n}\n.pastille:hover { background: #45bda2; }\n.pastille:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }\n\n/* ------------------------------------------------------------ BARRE ----- */\n\n.barre {\n position: fixed;\n left: 50%;\n bottom: 18px;\n transform: translateX(-50%);\n display: flex;\n align-items: center;\n gap: 14px;\n padding: 9px 14px;\n border: 1px solid var(--bord);\n border-radius: 999px;\n background: var(--fond);\n box-shadow: 0 8px 30px rgba(0, 0, 0, 0.45);\n max-width: calc(100vw - 24px);\n}\n.barre__point {\n width: 8px; height: 8px; border-radius: 50%;\n background: var(--accent);\n flex: none;\n}\n.barre__texte { font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.barre__texte b { font-weight: 650; }\n.barre__compte { color: var(--texte-doux); font-size: 12px; white-space: nowrap; }\n\n/* ----------------------------------------------------------- PANNEAU ---- */\n\n.panneau {\n position: fixed;\n top: 0; right: 0; bottom: 0;\n width: min(420px, 100vw);\n display: flex;\n flex-direction: column;\n background: var(--fond);\n border-left: 1px solid var(--bord);\n box-shadow: -12px 0 40px rgba(0, 0, 0, 0.4);\n}\n@media (max-width: 520px) {\n .panneau { top: auto; height: 78vh; border-left: 0; border-top: 1px solid var(--bord); }\n}\n\n.panneau__tete {\n display: flex; align-items: flex-start; gap: 10px;\n padding: 16px 16px 12px;\n border-bottom: 1px solid var(--bord);\n}\n.panneau__titre { font-size: 15px; font-weight: 650; margin: 0; }\n.panneau__sous { margin: 3px 0 0; font-size: 12px; color: var(--texte-doux); }\n.panneau__corps { flex: 1; overflow-y: auto; padding: 14px 16px 18px; }\n.panneau__pied {\n display: flex; gap: 8px; align-items: center;\n padding: 12px 16px;\n border-top: 1px solid var(--bord);\n background: var(--fond-clair);\n}\n.panneau__pied .espace { flex: 1; }\n\n/* --------------------------------------------------- CONNEXION ---------- */\n\n/* LA CONNEXION EST CLAIRE, AUX COULEURS DE LYSTECH. L'\u00E9diteur reste un outil\n sombre qui s'efface derri\u00E8re le travail ; la connexion, elle, est l'instant\n o\u00F9 quelqu'un d\u00E9cide de faire confiance. Il doit y reconna\u00EEtre Lystech \u2014 la\n fleur, son p\u00E9trole et son turquoise, sur du blanc \u2014 et non une bo\u00EEte noire\n pos\u00E9e sur son site.\n\n Le th\u00E8me se red\u00E9finit ICI, sur le voile : les boutons, messages et champs\n partag\u00E9s avec l'\u00E9diteur suivent ces variables sans une r\u00E8gle de plus, et\n l'\u00E9diteur garde les siennes. Clair quel que soit le th\u00E8me du syst\u00E8me :\n c'est un choix de marque. */\n.voile {\n --fond: #ffffff;\n --fond-clair: #f4f7f8;\n --bord: #dfe6e9;\n --texte: #0b1f26;\n --texte-doux: #52666f;\n --petrole: #084050;\n --petrole-survol: #0b5468;\n --turquoise: #10b8b0;\n --focus: #0c8f89;\n\n position: fixed;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 16px;\n /* Le voile PREND les clics, lui : une bo\u00EEte de dialogue qui demande une\n identit\u00E9 ne doit pas laisser cliquer la page derri\u00E8re elle. C'est\n l'exception \u00E0 la r\u00E8gle du calque, et elle est volontaire. Teint\u00E9 p\u00E9trole\n plut\u00F4t que noir : on assombrit le site sans l'\u00E9teindre. */\n background: rgba(8, 44, 56, 0.34);\n backdrop-filter: blur(4px) saturate(115%);\n color: var(--texte);\n}\n\n.fenetre {\n position: relative;\n width: min(400px, 100%);\n max-height: 92vh;\n overflow-y: auto;\n padding: 34px 30px 26px;\n border: 1px solid rgba(8, 64, 80, 0.10);\n border-radius: 20px;\n /* La lueur turquoise de la fleur, \u00E0 peine, en haut de la carte. */\n background:\n radial-gradient(90% 60% at 50% -12%, rgba(16, 184, 176, 0.13), transparent 70%),\n var(--fond);\n box-shadow:\n 0 1px 2px rgba(8, 64, 80, 0.06),\n 0 28px 64px -18px rgba(8, 44, 56, 0.45);\n text-align: center;\n}\n\n.fenetre__fermer {\n position: absolute; top: 14px; right: 14px;\n width: 32px; height: 32px;\n display: inline-flex; align-items: center; justify-content: center;\n border: 0; border-radius: 9px;\n background: transparent; color: var(--texte-doux);\n font: inherit; font-size: 14px; cursor: pointer;\n}\n.fenetre__fermer:hover { background: var(--fond-clair); color: var(--texte); }\n.fenetre__fermer:focus-visible { outline: 2px solid var(--focus); outline-offset: 2px; }\n\n/* ------------------------------------------------------------ MARQUE ---- */\n\n.marque {\n display: inline-flex; flex-direction: column; align-items: center; gap: 8px;\n margin-bottom: 18px;\n}\n.marque img {\n width: 44px; height: 44px; display: block;\n filter: drop-shadow(0 6px 14px rgba(16, 184, 176, 0.28));\n}\n.marque__mot {\n font-size: 11.5px; font-weight: 700;\n letter-spacing: 0.24em; text-transform: uppercase;\n color: var(--petrole);\n}\n\n.fenetre__titre {\n margin: 0 0 8px;\n font-size: 21px; font-weight: 700; letter-spacing: -0.015em;\n color: var(--texte);\n text-wrap: balance;\n}\n.fenetre__sous {\n margin: 0 auto 24px;\n max-width: 36ch;\n font-size: 13.5px; line-height: 1.55; color: var(--texte-doux);\n text-wrap: balance;\n}\n.fenetre__corps { text-align: left; }\n\n/* ------------------------------------------------------ FOURNISSEURS ---- */\n\n.fournisseurs { display: flex; flex-direction: column; gap: 10px; }\n\n.fournisseur {\n display: flex; align-items: center; justify-content: center; gap: 10px;\n width: 100%; min-height: 46px; padding: 12px 16px;\n border: 1px solid transparent; border-radius: 12px;\n font: inherit; font-size: 14px; font-weight: 600;\n cursor: pointer;\n transition: transform 90ms ease, background-color 120ms ease, box-shadow 120ms ease;\n}\n.fournisseur:active { transform: translateY(1px); }\n.fournisseur:focus-visible { outline: 2px solid var(--focus); outline-offset: 3px; }\n.fournisseur[disabled] { opacity: 0.55; cursor: default; transform: none; }\n.fournisseur .logo { width: 18px; height: 18px; flex: none; display: block; }\n\n/* LES COULEURS DE CHAQUE MARQUE, telles qu'elles les publient. Un bouton\n Google repeint aux couleurs du site devient moins reconnaissable \u2014 et un\n bouton de connexion qu'on ne reconna\u00EEt pas est un bouton sur lequel on\n h\u00E9site \u00E0 cliquer. */\n.fournisseur--google {\n background: #fff; color: #1f1f1f; border-color: #dadce0;\n box-shadow: 0 1px 2px rgba(8, 64, 80, 0.06);\n}\n.fournisseur--google:hover:not([disabled]) { background: #f6f9fa; border-color: #c9d3d8; }\n.fournisseur--facebook { background: #1877f2; color: #fff; }\n.fournisseur--facebook:hover:not([disabled]) { background: #166fe5; }\n\n.bouton--large { width: 100%; padding: 12px 16px; font-size: 14px; }\n\n/* Les boutons et messages PARTAG\u00C9S avec l'\u00E9diteur, en version claire. */\n.voile .bouton {\n min-height: 44px; border-radius: 12px;\n background: #fff; color: var(--texte); border-color: #cfd9dd;\n}\n.voile .bouton:hover { background: var(--fond-clair); }\n.voile .bouton:focus-visible { outline-color: var(--focus); }\n.voile .bouton--principal { background: var(--petrole); border-color: var(--petrole); color: #fff; }\n.voile .bouton--principal:hover { background: var(--petrole-survol); }\n\n.voile .message { font-size: 13px; line-height: 1.5; border-radius: 10px; }\n.voile .message--erreur { background: #fdf0ee; border-color: #f4c7bf; color: #a3321f; }\n.voile .message--ok { background: #e8f7f5; border-color: #a9e2dc; color: #0a5c57; }\n.voile .message--info { background: var(--fond-clair); border-color: var(--bord); color: #3a5159; }\n\n@media (prefers-reduced-motion: reduce) {\n .fournisseur { transition: none; }\n}\n\n/* ------------------------------------------------------------ CHAMPS ---- */\n\n.champ { margin-bottom: 16px; }\n.champ__etiquette {\n display: block; margin-bottom: 5px;\n font-size: 12px; font-weight: 600; color: var(--texte);\n}\n.champ__aide { margin: 4px 0 0; font-size: 11.5px; color: var(--texte-doux); }\n.champ__langue {\n display: inline-block; margin: 0 0 4px;\n font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em;\n text-transform: uppercase; color: var(--texte-doux);\n}\n\n/* TOUS les types de champs, pas seulement ceux auxquels on pensait. Un\n type oublie \u2014 \u00AB password \u00BB, \u00AB email \u00BB \u2014 retombe sur le style brut du\n navigateur : une ligne blanche au milieu d'un panneau sombre. */\ninput[type=\"text\"], input[type=\"url\"], input[type=\"number\"], input[type=\"date\"],\ninput[type=\"password\"], input[type=\"email\"], input[type=\"tel\"], input[type=\"search\"],\nselect, textarea {\n width: 100%;\n padding: 8px 10px;\n border: 1px solid var(--bord);\n border-radius: 6px;\n background: var(--fond-clair);\n color: var(--texte);\n font: inherit;\n font-size: 13px;\n}\ntextarea { min-height: 92px; resize: vertical; line-height: 1.5; }\ninput:focus, select:focus, textarea:focus {\n outline: none; border-color: var(--accent);\n box-shadow: 0 0 0 3px rgba(59, 165, 141, 0.18);\n}\n\n.bascule { display: flex; align-items: center; gap: 8px; }\n.bascule input { width: 16px; height: 16px; accent-color: var(--accent); }\n\n.vignette {\n margin-top: 8px; max-height: 110px; border-radius: 6px;\n border: 1px solid var(--bord); display: block;\n}\n\n/* --------------------------------------------------------- LISTES ------- */\n\n.liste__item {\n border: 1px solid var(--bord); border-radius: 8px;\n padding: 12px; margin-bottom: 10px; background: var(--fond-clair);\n}\n.liste__tete {\n display: flex; align-items: center; justify-content: space-between;\n margin-bottom: 8px;\n}\n.liste__rang { font-size: 11px; font-weight: 700; color: var(--texte-doux); }\n\n/* --------------------------------------------------------- BOUTONS ------ */\n\n.bouton {\n display: inline-flex; align-items: center; justify-content: center; gap: 6px;\n padding: 8px 14px; border-radius: 7px; border: 1px solid transparent;\n font: inherit; font-size: 13px; font-weight: 600; cursor: pointer;\n background: var(--fond-clair); color: var(--texte); border-color: var(--bord);\n}\n.bouton:hover { background: #2a2e37; }\n.bouton:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }\n.bouton--principal { background: var(--accent); border-color: var(--accent); color: #06120e; }\n.bouton--principal:hover { background: #45bda2; }\n.bouton--discret { background: transparent; border-color: transparent; color: var(--texte-doux); }\n.bouton--discret:hover { background: var(--fond-clair); color: var(--texte); }\n.bouton[disabled] { opacity: 0.5; cursor: default; }\n.bouton--icone { padding: 6px 9px; }\n\n.message {\n margin: 0 0 12px; padding: 9px 11px; border-radius: 7px;\n font-size: 12.5px; border: 1px solid;\n}\n.message--erreur { background: rgba(217, 119, 106, 0.12); border-color: rgba(217, 119, 106, 0.4); color: #f0b3a9; }\n.message--ok { background: rgba(59, 165, 141, 0.12); border-color: rgba(59, 165, 141, 0.4); color: #8fd9c6; }\n.message--info { background: var(--fond-clair); border-color: var(--bord); color: var(--texte-doux); }\n\n@media (prefers-reduced-motion: reduce) {\n * { transition: none !important; animation: none !important; }\n}\n";
|
|
2
2
|
export declare const CSS_EN_PLACE = "\n/* --------------------------------------------------------- CHOIX -------- */\n\n/* Quand un meme texte vient de plusieurs cles, on demande laquelle plutot que\n de deviner \u2014 et de modifier la mauvaise sans que personne le voie. */\n.choix {\n position: fixed;\n width: 260px;\n padding: 12px;\n border: 1px solid var(--bord);\n border-radius: 10px;\n background: var(--fond);\n box-shadow: 0 14px 40px rgba(0, 0, 0, 0.45);\n}\n.choix__titre { margin: 0 0 2px; font-size: 12.5px; font-weight: 650; }\n.choix__aide { margin: 0 0 10px; font-size: 11.5px; color: var(--texte-doux); }\n.choix__option {\n display: flex; flex-direction: column; align-items: flex-start; gap: 2px;\n width: 100%; margin-bottom: 6px; padding: 7px 9px;\n border: 1px solid var(--bord); border-radius: 7px;\n background: var(--fond-clair); color: var(--texte);\n font: inherit; text-align: left; cursor: pointer;\n}\n.choix__option:hover { background: #2a2e37; border-color: var(--accent); }\n.choix__chemin { font-size: 12px; font-weight: 600; }\n.choix__ns { font-size: 10.5px; color: var(--texte-doux); }\n\n/* ------------------------------------------------------- RANGEES -------- */\n\n.rangee {\n display: flex; align-items: center; justify-content: space-between; gap: 10px;\n width: 100%; margin-bottom: 6px; padding: 10px 12px;\n border: 1px solid var(--bord); border-radius: 8px;\n background: var(--fond-clair); color: var(--texte);\n font: inherit; text-align: left; cursor: pointer;\n}\n.rangee:hover { background: #2a2e37; border-color: var(--accent); }\n.rangee__nom { font-size: 13px; font-weight: 600; }\n.rangee__info { font-size: 11.5px; color: var(--texte-doux); white-space: nowrap; }\n\n/* ------------------------------------------------------ FLOTTANT -------- */\n\n/* Un message au-dessus de la barre, pour confirmer sans ouvrir de panneau. */\n.flottant {\n position: fixed;\n left: 50%; bottom: 76px;\n transform: translateX(-50%);\n max-width: min(460px, calc(100vw - 24px));\n}\n.flottant .message { margin: 0; box-shadow: 0 8px 26px rgba(0,0,0,.4); }\n";
|
|
3
3
|
export declare const CSS_MODE = "\n/* ON NE DOIT JAMAIS SE DEMANDER SI ON EST EN MODE EDITION. Une barre en bas\n se confond avec un bandeau de temoins ; un lisere qui borde tout l'ecran,\n present sur chaque page, ne se confond avec rien. Il ne prend aucun clic. */\n.cadre-global {\n position: fixed;\n inset: 0;\n pointer-events: none;\n border: 2px solid var(--accent);\n border-radius: 4px;\n box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.25);\n opacity: 0.85;\n}\n\n/* EN MODE CIRCULER, le cadre change d'allure. On est toujours connecte \u2014 le\n dire reste necessaire \u2014 mais les clics rendent la main aux liens, et rien\n ne serait plus desagreable que de croire qu'on edite alors qu'on navigue,\n ou l'inverse. Trait interrompu et plus efface : present, mais en retrait. */\n.cadre-global--circuler {\n border-style: dashed;\n border-color: var(--texte-doux);\n opacity: 0.5;\n}\n\n/* La sortie est rouge au survol seulement : visible quand on la cherche,\n discrete le reste du temps \u2014 c'est le geste qu'on fait une fois. */\n.bouton--sortie { color: var(--texte-doux); background: transparent; border-color: transparent; }\n.bouton--sortie:hover { background: rgba(217, 119, 106, 0.16); color: var(--danger); }\n";
|