@lystech/sections 0.8.0 → 0.9.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.
- package/README.md +65 -0
- package/dist/BoutonEdition.d.ts +13 -0
- package/dist/BoutonEditionCorps.d.ts +12 -0
- package/dist/SectionsProvider.d.ts +24 -1
- package/dist/catalogue.d.ts +12 -0
- package/dist/constantes.d.ts +15 -0
- package/dist/editeur/MarquesBoutique.d.ts +24 -16
- package/dist/editeur/boutique/Collections.d.ts +5 -8
- package/dist/editeur/boutique/FicheCollection.d.ts +23 -0
- package/dist/editeur/boutique/FicheProduit.d.ts +15 -6
- package/dist/editeur/boutique/ListeVirtuelle.d.ts +13 -0
- package/dist/editeur/boutique/ModuleBoutique.d.ts +34 -3
- package/dist/editeur/boutique/Publier.d.ts +15 -0
- package/dist/editeur/boutique/Selecteur.d.ts +10 -0
- package/dist/editeur/boutique/api.d.ts +48 -0
- package/dist/editeur/boutique/commun.d.ts +19 -0
- package/dist/editeur/boutique/styles.d.ts +1 -1
- package/dist/editeur/styles.d.ts +1 -1
- package/dist/editeur.js +2 -2
- package/dist/index.d.ts +5 -3
- package/dist/index.js +226 -183
- package/dist/morceaux/{ApercuMobile-RzxSOXyF.js → ApercuMobile-CSoo4dpM.js} +1 -1
- package/dist/morceaux/BoutonEditionCorps-B57eJtJn.js +112 -0
- package/dist/morceaux/ModuleBoutique-CgqcQjIb.js +1509 -0
- package/dist/morceaux/{constantes-BwBWlNYy.js → constantes-BAdpe1ss.js} +8 -6
- package/dist/morceaux/index-C_uFDnBO.js +2217 -0
- package/package.json +1 -1
- package/dist/morceaux/ModuleBoutique-BYBYDBN0.js +0 -867
- package/dist/morceaux/index-BicM0J3j.js +0 -2096
package/README.md
CHANGED
|
@@ -228,6 +228,71 @@ trouve le reconnaît, ne monte pas l'éditeur et reçoit les brouillons par
|
|
|
228
228
|
`postMessage` (même origine seulement). `useSectionsContext()?.modeApercu`
|
|
229
229
|
permet à un site de couper ce qui n'a pas de sens dans un aperçu.
|
|
230
230
|
|
|
231
|
+
## La grille, les collections, les brouillons (0.9)
|
|
232
|
+
|
|
233
|
+
### Une carte « + » dans la grille
|
|
234
|
+
|
|
235
|
+
En mode édition, pour une personne qui administre la boutique, une carte
|
|
236
|
+
**« + Ajouter un bijou »** apparaît **au bout de la grille de produits**, à la
|
|
237
|
+
taille exacte d'une carte. Rien à poser côté site : l'éditeur trouve la grille
|
|
238
|
+
à partir des cartes marquées par `marqueProduit`. Un visiteur, ou un éditeur
|
|
239
|
+
de textes sans droit sur le catalogue, n'a jamais cette carte dans sa page.
|
|
240
|
+
|
|
241
|
+
Au clic : **« Ajouter un bijou existant »** (recherche, vignettes, plusieurs à
|
|
242
|
+
la fois, ceux déjà présents marqués) ou **« Créer un nouveau bijou »**, rangé
|
|
243
|
+
d'office dans la collection affichée. Hors d'une collection : la création
|
|
244
|
+
seule.
|
|
245
|
+
|
|
246
|
+
### Marquer la collection affichée : `marqueCollection`
|
|
247
|
+
|
|
248
|
+
```tsx
|
|
249
|
+
import { marqueCollection } from "@lystech/sections";
|
|
250
|
+
|
|
251
|
+
<div className="collection" {...marqueCollection(c.UID, c.UID === choisie?.UID)}>…</div>
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Le deuxième argument dit « c'est elle que la grille montre ». L'éditeur y pose
|
|
255
|
+
un **crayon** (nom, description, qui peut commander, ses bijoux) et un **« + »**
|
|
256
|
+
(y ajouter des bijoux), et la carte « + » de la grille la garnit. La barre de
|
|
257
|
+
l'éditeur gagne une entrée **Collections**.
|
|
258
|
+
|
|
259
|
+
### Des brouillons, publiés quand on veut
|
|
260
|
+
|
|
261
|
+
Un **nouveau** bijou est rangé **en brouillon** — jamais visible, jamais
|
|
262
|
+
vendable, gardé sur le serveur (il survit au navigateur fermé et suit
|
|
263
|
+
l'artisane d'un appareil à l'autre). « Enregistrer et suivant » vide la fiche
|
|
264
|
+
pour le bijou d'après sans fermer le panneau ; les photos partent en
|
|
265
|
+
arrière-plan. Une nouvelle collection naît aussi en brouillon : on la nomme, on
|
|
266
|
+
la garnit (bijoux existants et nouveaux), sans qu'elle apparaisse.
|
|
267
|
+
|
|
268
|
+
**Publier (N)**, dans la barre, liste les brouillons (et les textes modifiés) :
|
|
269
|
+
on décoche ce qui n'est pas prêt ; ce qui ne peut pas partir (nom de moins de 3
|
|
270
|
+
lettres, pas de prix, pas de photo) le dit sur sa ligne. Chaque élément est
|
|
271
|
+
publié pour lui-même : un échec n'annule pas les autres, un double clic ne crée
|
|
272
|
+
pas de doublon. Pour une collection, on choisit à ce moment-là comment
|
|
273
|
+
l'ouvrir. Corriger un bijou **déjà en ligne** reste, lui, immédiat.
|
|
274
|
+
|
|
275
|
+
### Le crayon flottant : `BoutonEdition` et `connexionPropre`
|
|
276
|
+
|
|
277
|
+
Un site qui a **sa propre connexion** (une boutique @lystech/core) n'a pas
|
|
278
|
+
besoin de la fenêtre « Connexion » du pied de page :
|
|
279
|
+
|
|
280
|
+
```tsx
|
|
281
|
+
<SectionsProvider site="bijouxunyk" page={page} connexionPropre session={{ cle, entetes }}>
|
|
282
|
+
…
|
|
283
|
+
<BoutonEdition connecte={isLoggedIn} />
|
|
284
|
+
</SectionsProvider>
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
`connexionPropre` retire « Connexion » de `SignatureLystech` (défaut : non,
|
|
288
|
+
rien ne change pour les autres sites). `BoutonEdition` ne rend **rien** tant
|
|
289
|
+
que personne n'est connecté — ni code téléchargé, ni requête. Connecté, une
|
|
290
|
+
question au serveur (« puis-je éditer CE site ? ») ; si oui, un crayon rond de
|
|
291
|
+
56 px en bas de l'écran (`coin="gauche"` par défaut, à l'opposé du panier). Au
|
|
292
|
+
clic, le serveur délivre un jeton d'édition **à la session déjà ouverte**, pour
|
|
293
|
+
l'organisation de ce site seulement, et l'éditeur se monte sur la page, sans
|
|
294
|
+
recharger. En mode édition, le crayon disparaît.
|
|
295
|
+
|
|
231
296
|
## Sections par audience (0.8)
|
|
232
297
|
|
|
233
298
|
Une section peut viser une **audience** : tout le monde, clients connectés,
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type BoutonEditionProps = {
|
|
2
|
+
/** La personne est connectée par la connexion du site (ex. `useAuth().isLoggedIn`). */
|
|
3
|
+
connecte: boolean;
|
|
4
|
+
/**
|
|
5
|
+
* Si le site le sait déjà (rôles chargés), on n'interroge pas le serveur.
|
|
6
|
+
* Indicatif seulement : c'est le serveur qui délivre (ou non) le jeton.
|
|
7
|
+
*/
|
|
8
|
+
peutEditer?: boolean | undefined;
|
|
9
|
+
/** Le coin du bas où se poser — l'opposé du panier ou du bouton d'aide. */
|
|
10
|
+
coin?: "gauche" | "droite" | undefined;
|
|
11
|
+
libelle?: string | undefined;
|
|
12
|
+
};
|
|
13
|
+
export declare function BoutonEdition(props: BoutonEditionProps): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export default function BoutonEditionCorps({ connecte, peutEditer, coin, libelle, }: {
|
|
2
|
+
/** La personne est connectée par la connexion du site (ex. `useAuth().isLoggedIn`). */
|
|
3
|
+
connecte: boolean;
|
|
4
|
+
/**
|
|
5
|
+
* Si le site le sait déjà (rôles chargés), on n'interroge pas le serveur.
|
|
6
|
+
* Indicatif seulement : c'est le serveur qui délivre (ou non) le jeton.
|
|
7
|
+
*/
|
|
8
|
+
peutEditer?: boolean | undefined;
|
|
9
|
+
/** Le coin du bas où se poser — l'opposé du panier ou du bouton d'aide. */
|
|
10
|
+
coin?: "gauche" | "droite" | undefined;
|
|
11
|
+
libelle?: string | undefined;
|
|
12
|
+
}): import("react").JSX.Element | null;
|
|
@@ -74,6 +74,23 @@ type Contexte = {
|
|
|
74
74
|
* par le serveur.
|
|
75
75
|
*/
|
|
76
76
|
visiteur: Visiteur | null;
|
|
77
|
+
/**
|
|
78
|
+
* ENTRER EN MODE ÉDITION avec un jeton obtenu par le site (le crayon
|
|
79
|
+
* flottant, `BoutonEdition`) : le jeton est rangé comme après une
|
|
80
|
+
* connexion, et l'éditeur se monte sur la page courante, SANS recharger.
|
|
81
|
+
*/
|
|
82
|
+
entrerEnEdition: (jeton: string) => void;
|
|
83
|
+
/**
|
|
84
|
+
* Le site a SA PROPRE connexion (une boutique @lystech/core) : on n'y
|
|
85
|
+
* propose pas la fenêtre de connexion de l'éditeur (« Connexion » de
|
|
86
|
+
* `SignatureLystech`) — le crayon flottant prend le relais.
|
|
87
|
+
*/
|
|
88
|
+
connexionPropre: boolean;
|
|
89
|
+
/**
|
|
90
|
+
* APPELER L'API AU NOM DU VISITEUR CONNECTÉ (sa session : cookie, et les
|
|
91
|
+
* en-têtes de `session`). Seuls les chemins de l'API sont acceptés.
|
|
92
|
+
*/
|
|
93
|
+
appelSession: (chemin: string, init?: RequestInit) => Promise<Response>;
|
|
77
94
|
};
|
|
78
95
|
/**
|
|
79
96
|
* LA SESSION DU VISITEUR, pour que le serveur reconnaisse un membre.
|
|
@@ -87,7 +104,7 @@ export type SessionSections = {
|
|
|
87
104
|
cle?: string | null | undefined;
|
|
88
105
|
entetes?: Record<string, string> | undefined;
|
|
89
106
|
};
|
|
90
|
-
export declare function SectionsProvider({ site, page, langue, apiBaseUrl, sectionsInitiales, sourceTexte, pagesPartagees, session, children, }: {
|
|
107
|
+
export declare function SectionsProvider({ site, page, langue, apiBaseUrl, sectionsInitiales, sourceTexte, pagesPartagees, session, connexionPropre, children, }: {
|
|
91
108
|
/** Sous-domaine de l'organisation (ex. « armoise »). */
|
|
92
109
|
site: string;
|
|
93
110
|
/** La page dont on veut les sections (ex. « accueil »). */
|
|
@@ -130,6 +147,12 @@ export declare function SectionsProvider({ site, page, langue, apiBaseUrl, secti
|
|
|
130
147
|
* de session suffit quand le site et l'API le partagent.
|
|
131
148
|
*/
|
|
132
149
|
session?: SessionSections | undefined;
|
|
150
|
+
/**
|
|
151
|
+
* Le site a sa propre connexion (défaut : non). Vrai : la fenêtre de
|
|
152
|
+
* connexion de l'éditeur n'est plus offerte dans le pied de page ; on entre
|
|
153
|
+
* en édition par le crayon flottant (`BoutonEdition`) une fois connecté.
|
|
154
|
+
*/
|
|
155
|
+
connexionPropre?: boolean | undefined;
|
|
133
156
|
children: ReactNode;
|
|
134
157
|
}): import("react").JSX.Element;
|
|
135
158
|
/**
|
package/dist/catalogue.d.ts
CHANGED
|
@@ -3,6 +3,18 @@ export type MarqueProduit = {
|
|
|
3
3
|
};
|
|
4
4
|
/** Les attributs à poser sur la carte d'un produit. */
|
|
5
5
|
export declare function marqueProduit(UID: string): MarqueProduit;
|
|
6
|
+
export type MarqueCollection = {
|
|
7
|
+
"data-lystech-collection": string;
|
|
8
|
+
"data-lystech-collection-affichee"?: "";
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Les attributs à poser sur l'élément qui montre une collection (un onglet du
|
|
12
|
+
* bandeau, l'en-tête de sa page). `affichee` : vrai pour celle dont la grille
|
|
13
|
+
* de la page montre les bijoux — la carte « + » de la grille y ajoute.
|
|
14
|
+
*
|
|
15
|
+
* <div className="collection" {...marqueCollection(c.UID, c.UID === choisie?.UID)}>
|
|
16
|
+
*/
|
|
17
|
+
export declare function marqueCollection(UID: string, affichee?: boolean): MarqueCollection;
|
|
6
18
|
/** Ce que l'éditeur dit d'un changement — pour relire juste ce qu'il faut, si on veut. */
|
|
7
19
|
export type ChangementCatalogue = {
|
|
8
20
|
quoi: "produit" | "photo" | "collection";
|
package/dist/constantes.d.ts
CHANGED
|
@@ -21,6 +21,21 @@ export declare const CLASSE_HORS_EDITION = "lystech-hors-edition";
|
|
|
21
21
|
* attribut inerte. `marqueProduit(UID)` l'écrit pour vous.
|
|
22
22
|
*/
|
|
23
23
|
export declare const ATTR_PRODUIT = "data-lystech-produit";
|
|
24
|
+
/**
|
|
25
|
+
* LE MARQUAGE D'UNE COLLECTION : `data-lystech-collection="<UID>"`, posé par
|
|
26
|
+
* le site sur l'élément qui la montre (l'onglet du bandeau, l'en-tête d'une
|
|
27
|
+
* page de collection). En mode édition, l'éditeur y pose un crayon (modifier
|
|
28
|
+
* la collection) et un « + » (y ajouter des bijoux). `marqueCollection(UID,
|
|
29
|
+
* affichee)` l'écrit pour vous.
|
|
30
|
+
*/
|
|
31
|
+
export declare const ATTR_COLLECTION = "data-lystech-collection";
|
|
32
|
+
/**
|
|
33
|
+
* « CETTE COLLECTION EST CELLE QUI S'AFFICHE » : `data-lystech-collection-affichee`,
|
|
34
|
+
* posé avec la marque quand la grille de la page montre ses bijoux. C'est
|
|
35
|
+
* elle que la carte « + » de la grille garnit ; sans elle (une page qui n'est
|
|
36
|
+
* pas une collection), la carte ne propose que de créer un bijou.
|
|
37
|
+
*/
|
|
38
|
+
export declare const ATTR_COLLECTION_AFFICHEE = "data-lystech-collection-affichee";
|
|
24
39
|
/**
|
|
25
40
|
* L'ÉVÉNEMENT QUI DIT « LE CATALOGUE A CHANGÉ » — émis sur `window` par
|
|
26
41
|
* l'éditeur après chaque enregistrement d'un produit, d'une photo ou d'une
|
|
@@ -1,18 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
top: number;
|
|
3
|
-
left: number;
|
|
4
|
-
width: number;
|
|
5
|
-
height: number;
|
|
6
|
-
};
|
|
1
|
+
export declare const ATTR_AJOUT = "data-lystech-ajout";
|
|
7
2
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
3
|
+
* LA GRILLE d'un ensemble de cartes : on remonte depuis chaque carte jusqu'au
|
|
4
|
+
* premier parent qui en contient une autre. Ce parent est la grille ; l'enfant
|
|
5
|
+
* par lequel on y est arrivé est la « case » de la carte (la carte elle-même,
|
|
6
|
+
* ou l'enveloppe que le site met autour). On garde la grille qui montre le
|
|
7
|
+
* plus de cartes : celle du catalogue, pas un « vous aimerez aussi ».
|
|
12
8
|
*/
|
|
13
|
-
export declare function
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
9
|
+
export declare function trouverGrille(cartes: HTMLElement[]): {
|
|
10
|
+
grille: HTMLElement;
|
|
11
|
+
caseModele: HTMLElement;
|
|
12
|
+
} | null;
|
|
13
|
+
export type CibleCollection = {
|
|
14
|
+
UID: string;
|
|
15
|
+
nom: string;
|
|
16
|
+
} | null;
|
|
17
|
+
export declare const MarquesBoutique: import('react').NamedExoticComponent<{
|
|
18
|
+
/** Crayons sur les cartes et la collection (aucun panneau ouvert). */
|
|
19
|
+
crayons: boolean;
|
|
20
|
+
/** La carte « + » dans la grille (droit catalogue + mode « modifier »). */
|
|
21
|
+
carte: boolean;
|
|
22
|
+
ouvrirProduit: (UID: string) => void;
|
|
23
|
+
/** Le « + » : ajouter à la collection affichée (ou créer, sans collection). */
|
|
24
|
+
ouvrirAjout: (collection: CibleCollection) => void;
|
|
25
|
+
ouvrirCollection: (UID: string) => void;
|
|
26
|
+
}>;
|
|
@@ -1,11 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
export declare function Collections({ api, collections, produits, majCollection, majProduits, signaler, }: {
|
|
1
|
+
import { ApiBoutique, Collection, CollectionBrouillon } from './api';
|
|
2
|
+
export declare function Collections({ api, collections, brouillons, surOuvrir, surCree, }: {
|
|
4
3
|
api: ApiBoutique;
|
|
5
4
|
collections: Collection[];
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
majProduits: () => void;
|
|
10
|
-
signaler: (c: ChangementCatalogue) => void;
|
|
5
|
+
brouillons: CollectionBrouillon[];
|
|
6
|
+
surOuvrir: (UID: string) => void;
|
|
7
|
+
surCree: (c: CollectionBrouillon) => void;
|
|
11
8
|
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ChangementCatalogue } from '../../catalogue';
|
|
2
|
+
import { ApiBoutique, Collection, CollectionBrouillon, NiveauAcces, Produit, ProduitBrouillon } from './api';
|
|
3
|
+
export declare const NIVEAUX: Array<{
|
|
4
|
+
acces: NiveauAcces;
|
|
5
|
+
titre: string;
|
|
6
|
+
aide: string;
|
|
7
|
+
}>;
|
|
8
|
+
export declare function FicheCollection({ api, collection, produits, brouillonsProduits, signaler, surRetour, majCollection, majProduits, majBrouillons, surAjouterExistants, surCreer, surOuvrirProduit, annonce, }: {
|
|
9
|
+
/** Un message à montrer en ouvrant la fiche (« 3 bijoux ajoutés »). */
|
|
10
|
+
annonce?: string | null;
|
|
11
|
+
api: ApiBoutique;
|
|
12
|
+
collection: Collection | CollectionBrouillon;
|
|
13
|
+
produits: Produit[] | null;
|
|
14
|
+
brouillonsProduits: ProduitBrouillon[];
|
|
15
|
+
signaler: (c: ChangementCatalogue) => void;
|
|
16
|
+
surRetour: () => void;
|
|
17
|
+
majCollection: (c: Collection | CollectionBrouillon) => void;
|
|
18
|
+
majProduits: () => void;
|
|
19
|
+
majBrouillons: () => void;
|
|
20
|
+
surAjouterExistants: () => void;
|
|
21
|
+
surCreer: () => void;
|
|
22
|
+
surOuvrirProduit: (UID: string) => void;
|
|
23
|
+
}): import("react").JSX.Element;
|
|
@@ -1,13 +1,22 @@
|
|
|
1
1
|
import { ChangementCatalogue } from '../../catalogue';
|
|
2
|
-
import { ApiBoutique,
|
|
3
|
-
|
|
2
|
+
import { ApiBoutique, Produit, ProduitBrouillon } from './api';
|
|
3
|
+
import { CollectionChoix } from './commun';
|
|
4
|
+
export declare function FicheProduit({ api, produit, collections, collectionDefaut, surEnregistre, surSupprime, surRetour, surFermer, envoyerEnArrierePlan, photosEnCours, compteBrouillons, signaler, annonce, }: {
|
|
4
5
|
api: ApiBoutique;
|
|
5
|
-
/** null = nouveau bijou. */
|
|
6
|
-
produit: Produit | null;
|
|
7
|
-
collections:
|
|
8
|
-
|
|
6
|
+
/** null = nouveau bijou (en brouillon, en rafale). */
|
|
7
|
+
produit: Produit | ProduitBrouillon | null;
|
|
8
|
+
collections: CollectionChoix[];
|
|
9
|
+
/** La collection où ranger d'office les nouveaux bijoux (celle de la page). */
|
|
10
|
+
collectionDefaut?: string | null;
|
|
11
|
+
surEnregistre: (p: Produit | ProduitBrouillon) => void;
|
|
9
12
|
surSupprime: (UID: string) => void;
|
|
10
13
|
surRetour: () => void;
|
|
14
|
+
surFermer?: () => void;
|
|
15
|
+
/** Envoyer des photos à un brouillon sans bloquer la fiche (rafale). */
|
|
16
|
+
envoyerEnArrierePlan?: (UID: string, fichiers: File[]) => void;
|
|
17
|
+
/** Photos encore en route (toutes fiches confondues). */
|
|
18
|
+
photosEnCours?: number;
|
|
19
|
+
compteBrouillons?: number;
|
|
11
20
|
signaler: (c: ChangementCatalogue) => void;
|
|
12
21
|
/** Un message à afficher en ouvrant la fiche (« Bijou créé »). */
|
|
13
22
|
annonce?: string | null;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { ReactNode, RefObject } from 'react';
|
|
2
|
+
export declare function ListeVirtuelle<T>({ items, hauteur, conteneur, cle, rendu, surplus, etiquette, }: {
|
|
3
|
+
items: T[];
|
|
4
|
+
/** Hauteur d'une rangée, marge comprise, en px. */
|
|
5
|
+
hauteur: number;
|
|
6
|
+
/** L'élément qui défile (le corps du panneau). */
|
|
7
|
+
conteneur: RefObject<HTMLElement | null>;
|
|
8
|
+
cle: (item: T) => string;
|
|
9
|
+
rendu: (item: T, index: number) => ReactNode;
|
|
10
|
+
surplus?: number;
|
|
11
|
+
/** Nom de la liste pour les lecteurs d'écran. */
|
|
12
|
+
etiquette?: string;
|
|
13
|
+
}): import("react").JSX.Element;
|
|
@@ -1,13 +1,44 @@
|
|
|
1
1
|
import { ChangementCatalogue } from '../../catalogue';
|
|
2
2
|
import { ApiBoutique } from './api';
|
|
3
|
-
|
|
3
|
+
export type CibleCollection = {
|
|
4
|
+
UID: string;
|
|
5
|
+
nom: string;
|
|
6
|
+
} | null;
|
|
7
|
+
/** Ce que l'éditeur demande d'ouvrir. `n` change à chaque demande, même identique. */
|
|
4
8
|
export type DemandeBoutique = {
|
|
5
|
-
cible: string | null;
|
|
6
9
|
n: number;
|
|
10
|
+
vue: "liste";
|
|
11
|
+
onglet?: "bijoux" | "collections";
|
|
12
|
+
} | {
|
|
13
|
+
n: number;
|
|
14
|
+
vue: "fiche";
|
|
15
|
+
UID: string;
|
|
16
|
+
} | {
|
|
17
|
+
n: number;
|
|
18
|
+
vue: "nouveau";
|
|
19
|
+
collection: string | null;
|
|
20
|
+
} | {
|
|
21
|
+
n: number;
|
|
22
|
+
vue: "ajout";
|
|
23
|
+
collection: CibleCollection;
|
|
24
|
+
} | {
|
|
25
|
+
n: number;
|
|
26
|
+
vue: "collection";
|
|
27
|
+
UID: string;
|
|
28
|
+
} | {
|
|
29
|
+
n: number;
|
|
30
|
+
vue: "publier";
|
|
7
31
|
};
|
|
8
|
-
|
|
32
|
+
declare function ModuleBoutique({ api, demande, surFermer, signaler, textes, publierTextes, surCompteBrouillons, }: {
|
|
9
33
|
api: ApiBoutique;
|
|
10
34
|
demande: DemandeBoutique;
|
|
11
35
|
surFermer: () => void;
|
|
12
36
|
signaler: (c: ChangementCatalogue) => void;
|
|
37
|
+
/** Textes du site en attente de publication (pour « Publier »). */
|
|
38
|
+
textes?: number;
|
|
39
|
+
publierTextes?: () => Promise<boolean>;
|
|
40
|
+
/** Le nombre de brouillons, pour la pastille de la barre de l'éditeur. */
|
|
41
|
+
surCompteBrouillons?: (n: number) => void;
|
|
13
42
|
}): import("react").JSX.Element;
|
|
43
|
+
declare const _default: import('react').MemoExoticComponent<typeof ModuleBoutique>;
|
|
44
|
+
export default _default;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { ApiBoutique, Brouillons, ResultatPublication } from './api';
|
|
2
|
+
export declare function Publier({ api, brouillons: frais, noms, textes, publierTextes, surPublie, surOuvrir, surRetour, }: {
|
|
3
|
+
api: ApiBoutique;
|
|
4
|
+
brouillons: Brouillons;
|
|
5
|
+
/** Noms des collections (en ligne et en brouillon), par UID. */
|
|
6
|
+
noms: Map<string, string>;
|
|
7
|
+
/** Textes du site modifiés, en attente (0 = aucun). */
|
|
8
|
+
textes: number;
|
|
9
|
+
publierTextes: () => Promise<boolean>;
|
|
10
|
+
/** Après publication : relire catalogue et brouillons. */
|
|
11
|
+
surPublie: (r: ResultatPublication[]) => void;
|
|
12
|
+
/** Ouvrir la fiche d'un brouillon à compléter. */
|
|
13
|
+
surOuvrir: (UID: string, type: "produit" | "collection") => void;
|
|
14
|
+
surRetour: () => void;
|
|
15
|
+
}): import("react").JSX.Element;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Produit } from './api';
|
|
2
|
+
export declare function Selecteur({ produits, deja, nomCollection, occupe, surValider, surAnnuler, }: {
|
|
3
|
+
produits: Produit[] | null;
|
|
4
|
+
/** UIDs déjà dans la collection. */
|
|
5
|
+
deja: Set<string>;
|
|
6
|
+
nomCollection: string;
|
|
7
|
+
occupe: boolean;
|
|
8
|
+
surValider: (UIDs: string[]) => void;
|
|
9
|
+
surAnnuler: () => void;
|
|
10
|
+
}): import("react").JSX.Element;
|
|
@@ -32,6 +32,40 @@ export type Collection = {
|
|
|
32
32
|
nbProduits: number;
|
|
33
33
|
image: string | null;
|
|
34
34
|
};
|
|
35
|
+
/** Un bijou en brouillon : la forme d'une fiche, plus ce qui manque pour publier. */
|
|
36
|
+
export type ProduitBrouillon = Produit & {
|
|
37
|
+
type: "produit";
|
|
38
|
+
brouillon: true;
|
|
39
|
+
/** Ce qui empêche de publier, en mots simples (vide = prêt). */
|
|
40
|
+
problemes: string[];
|
|
41
|
+
modifieLe?: string;
|
|
42
|
+
};
|
|
43
|
+
/** Une collection en brouillon : invisible, garnie de bijoux existants et de brouillons. */
|
|
44
|
+
export type CollectionBrouillon = Collection & {
|
|
45
|
+
type: "collection";
|
|
46
|
+
brouillon: true;
|
|
47
|
+
/** Les bijoux EXISTANTS qu'elle recevra. Les brouillons, eux, la citent. */
|
|
48
|
+
produits: string[];
|
|
49
|
+
problemes: string[];
|
|
50
|
+
modifieLe?: string;
|
|
51
|
+
};
|
|
52
|
+
export type Brouillons = {
|
|
53
|
+
produits: ProduitBrouillon[];
|
|
54
|
+
collections: CollectionBrouillon[];
|
|
55
|
+
};
|
|
56
|
+
/** Ce que le serveur dit de chaque élément publié. */
|
|
57
|
+
export type ResultatPublication = {
|
|
58
|
+
UID: string;
|
|
59
|
+
type?: "produit" | "collection";
|
|
60
|
+
ok: boolean;
|
|
61
|
+
/** Déjà publié par un clic précédent : rien n'a été recréé. */
|
|
62
|
+
deja?: boolean;
|
|
63
|
+
publieUID?: string;
|
|
64
|
+
nom?: string;
|
|
65
|
+
message?: string;
|
|
66
|
+
problemes?: string[];
|
|
67
|
+
};
|
|
68
|
+
export declare const estBrouillon: (UID: string | null | undefined) => boolean;
|
|
35
69
|
/** Ce qu'on envoie pour créer ou modifier — seulement ce qui change. */
|
|
36
70
|
export type SaisieProduit = {
|
|
37
71
|
nom?: string;
|
|
@@ -76,6 +110,20 @@ export declare function creerApiBoutique(brut: Brut): {
|
|
|
76
110
|
acces?: NiveauAcces;
|
|
77
111
|
}) => Promise<Collection>;
|
|
78
112
|
garnirCollection: (UID: string, ajouter: string[], retirer: string[]) => Promise<Collection>;
|
|
113
|
+
brouillons: () => Promise<Brouillons>;
|
|
114
|
+
/** `cle` : la même clé deux fois (double clic, réseau qui rejoue) ne crée qu'un brouillon. */
|
|
115
|
+
creerBrouillon: <T extends ProduitBrouillon | CollectionBrouillon>(type: T["type"], donnees: Record<string, unknown>, cle: string) => Promise<T>;
|
|
116
|
+
modifierBrouillon: <T extends ProduitBrouillon | CollectionBrouillon>(UID: string, donnees: Record<string, unknown>) => Promise<T>;
|
|
117
|
+
supprimerBrouillon: (UID: string) => Promise<{
|
|
118
|
+
supprime: boolean;
|
|
119
|
+
}>;
|
|
120
|
+
photoBrouillon: (UID: string, fichier: Blob, nom: string) => Promise<ProduitBrouillon>;
|
|
121
|
+
principaleBrouillon: (UID: string, photo: string) => Promise<ProduitBrouillon>;
|
|
122
|
+
retirerPhotoBrouillon: (UID: string, photo: string) => Promise<ProduitBrouillon>;
|
|
123
|
+
/** Publier : chaque élément pour lui-même, un échec n'annule pas les autres. */
|
|
124
|
+
publier: (UIDs: string[], ouvrir: Record<string, NiveauAcces>) => Promise<{
|
|
125
|
+
resultats: ResultatPublication[];
|
|
126
|
+
}>;
|
|
79
127
|
};
|
|
80
128
|
export type ApiBoutique = ReturnType<typeof creerApiBoutique>;
|
|
81
129
|
/** Un montant à la québécoise : « 58,50 $ ». */
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Collection, CollectionBrouillon, Produit } from './api';
|
|
2
|
+
/** « Éé » → « ee » : la recherche ignore accents et majuscules. */
|
|
3
|
+
export declare function sansAccents(s: string): string;
|
|
4
|
+
/**
|
|
5
|
+
* LA VIGNETTE D'UN BIJOU. Les photos du catalogue font ~2000 px : on demande
|
|
6
|
+
* au navigateur de ne les décoder qu'une fois à l'écran (`lazy`), sans bloquer
|
|
7
|
+
* le reste (`async`), à la taille d'affichage (largeur et hauteur posées — pas
|
|
8
|
+
* de saut de mise en page quand elle arrive).
|
|
9
|
+
*/
|
|
10
|
+
export declare const Vignette: import('react').NamedExoticComponent<{
|
|
11
|
+
src: string | undefined;
|
|
12
|
+
taille?: number;
|
|
13
|
+
}>;
|
|
14
|
+
export declare function photoPrincipale(p: Produit): string;
|
|
15
|
+
export declare function texteStock(p: Produit): string;
|
|
16
|
+
export declare function etatProduit(p: Produit): [string, string];
|
|
17
|
+
/** Une collection, vivante ou en brouillon, telle que les puces d'une fiche la montrent. */
|
|
18
|
+
export type CollectionChoix = Collection | CollectionBrouillon;
|
|
19
|
+
export declare const pluriel: (n: number, un: string, plusieurs: string) => string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const CSS_BOUTIQUE = "\n.panneau--boutique { width: min(440px, 100vw); }\n.panneau--boutique .bouton { min-height: 40px; }\n@media (max-width: 520px) {\n .panneau--boutique {\n top: auto; left: 0; right: 0; width: auto; height: 88vh; height: 88dvh;\n border-radius: 18px 18px 0 0;\n }\n .panneau--boutique .bouton { min-height: 44px; }\n .panneau--boutique .bouton--icone { min-width: 44px; }\n}\n.poignee { display: none; width: 44px; height: 5px; border-radius: 3px; background: #4a505d; margin: 8px auto 0; flex: none; }\n@media (max-width: 520px) { .poignee { display: block; } }\n\n.b-tete { display: flex; align-items: center; gap: 6px; padding: 10px 12px; border-bottom: 1px solid var(--bord); }\n.b-tete h2 { flex: 1; margin: 0; font-size: 16px; font-weight: 650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.b-tete .bouton--icone { min-width: 40px; min-height: 40px; font-size: 16px; }\n\n.b-onglets { display: flex; gap: 2px; padding: 0 12px; border-bottom: 1px solid var(--bord); }\n.b-onglets button {\n border: 0; background: transparent; color: var(--texte-doux); font: inherit; font-weight: 600;\n min-height: 44px; padding: 0 12px; cursor: pointer; border-bottom: 2px solid transparent;\n}\n.b-onglets button[aria-selected=\"true\"] { color: var(--texte); border-bottom-color: var(--accent); }\n.b-onglets button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }\n.b-onglets small { opacity: .65; margin-left: 4px; font-weight: 500; }\n\n.b-avis {\n margin: 0 0 12px; padding: 9px 11px; border-radius: 10px; font-size: 12.5px; line-height: 1.45;\n background: rgba(227, 181, 91, 0.1); border: 1px solid rgba(227, 181, 91, 0.35); color: #f1d9a6;\n}\n.b-ajout {\n width: 100%; min-height: 48px; margin-bottom: 12px; border-radius: 12px; cursor: pointer;\n border: 2px dashed var(--accent); background: transparent; color: #9fe3d1; font: inherit; font-weight: 650;\n}\n.b-ajout:hover, .b-ajout:focus-visible { background: rgba(59, 165, 141, 0.1); outline: none; }\n\n.b-recherche { min-height: 44px; border-radius: 10px !important; font-size: 14px !important; }\n.b-filtres { display: flex; gap: 6px; overflow-x: auto; padding: 10px 0 12px; scrollbar-width: none; }\n.b-puce {\n flex: none; display: inline-flex; align-items: center; gap: 4px; min-height: 36px; padding: 0 12px;\n border-radius: 999px; border: 1px solid var(--bord); background: transparent; color: var(--texte-doux);\n font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer;\n}\n.b-puce small { opacity: .7; font-weight: 500; }\n.b-puce[aria-pressed=\"true\"] { background: rgba(59, 165, 141, 0.16); border-color: var(--accent); color: #9fe3d1; }\n.b-puce:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }\n@media (max-width: 520px) { .b-puce { min-height: 44px; } }\n\n.b-rangee {\n display: flex; align-items: center; gap: 12px; width: 100%; min-height: 64px; margin-bottom: 6px; padding: 8px;\n border-radius: 12px; border: 1px solid var(--bord); background: var(--fond-clair); color: var(--texte);\n font: inherit; text-align: left; cursor: pointer;\n}\n.b-rangee:hover, .b-rangee:focus-visible { border-color: var(--accent); outline: none; }\n.b-vignette { width: 48px; height: 48px; flex: none; border-radius: 9px; object-fit: cover; background: #2a2e37; display: block; }\n.b-vignette--vide { display: grid; place-items: center; color: var(--texte-doux); font-size: 18px; }\n.b-rangee__texte { flex: 1; min-width: 0; }\n.b-rangee__nom { display: block; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.b-rangee__meta { display: block; font-size: 12px; color: var(--texte-doux); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.b-etiquette { flex: none; font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 999px; }\n.b-etiquette--vente { background: rgba(59, 165, 141, 0.18); color: #8fd9c6; }\n.b-etiquette--masque { background: rgba(163, 169, 182, 0.16); color: var(--texte-doux); }\n.b-etiquette--vendu { background: rgba(217, 119, 106, 0.18); color: #f0b3a9; }\n.b-vide { color: var(--texte-doux); font-size: 13px; padding: 18px 4px; text-align: center; }\n\n/* ---------------------------------------------------------- FICHE ------ */\n.b-section { margin-bottom: 18px; }\n.b-section > h3 { margin: 0 0 8px; font-size: 11.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--texte-doux); }\n.b-champ { margin-bottom: 12px; }\n.b-champ label, .b-champ .b-etiq { display: block; margin-bottom: 5px; font-size: 12.5px; font-weight: 600; }\n.b-champ label small { font-weight: 400; color: var(--texte-doux); }\n.panneau--boutique input[type=\"text\"], .panneau--boutique input[type=\"search\"], .panneau--boutique textarea {\n min-height: 44px; padding: 10px 12px; border-radius: 10px; font-size: 14px;\n}\n.b-champ--erreur input, .b-champ--erreur textarea { border-color: var(--danger) !important; }\n.b-erreur { margin: 4px 0 0; font-size: 12px; color: #f0b3a9; }\n.b-aide { margin: 4px 0 0; font-size: 11.5px; color: var(--texte-doux); }\n.b-deux { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }\n.b-prix { position: relative; }\n.b-prix span { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); color: var(--texte-doux); pointer-events: none; }\n.b-prix input { padding-right: 28px !important; }\n\n.b-seg { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }\n.b-seg button {\n min-height: 44px; border-radius: 10px; border: 1px solid var(--bord); background: var(--fond-clair);\n color: var(--texte-doux); font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer;\n}\n.b-seg button[aria-pressed=\"true\"] { border-color: var(--accent); color: #9fe3d1; background: rgba(59, 165, 141, 0.14); }\n.b-seg button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }\n\n.b-inter {\n display: flex; align-items: center; gap: 12px; width: 100%; min-height: 56px; padding: 10px 12px;\n border-radius: 12px; background: var(--fond-clair); border: 1px solid var(--bord); color: var(--texte);\n font: inherit; text-align: left; cursor: pointer;\n}\n.b-inter:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }\n.b-inter small { display: block; color: var(--texte-doux); font-size: 11.5px; font-weight: 400; }\n.b-rail { position: relative; width: 46px; height: 28px; flex: none; border-radius: 999px; background: #4a505d; transition: background .15s; }\n.b-rail::after { content: \"\"; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 50%; background: #fff; transition: left .15s; }\n[aria-checked=\"true\"] > .b-rail { background: var(--accent); }\n[aria-checked=\"true\"] > .b-rail::after { left: 21px; }\n\n.b-photos { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }\n.b-photo { position: relative; aspect-ratio: 1; border-radius: 10px; overflow: hidden; border: 2px solid transparent; background: #2a2e37; }\n.b-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }\n.b-photo--principale { border-color: var(--accent); }\n.b-photo__badge { position: absolute; left: 6px; bottom: 6px; background: var(--accent); color: #06120e; font-size: 10.5px; font-weight: 700; padding: 2px 6px; border-radius: 999px; }\n.b-photo__actions { position: absolute; top: 4px; right: 4px; display: flex; gap: 4px; }\n.b-photo__actions button {\n width: 36px; height: 36px; border-radius: 50%; border: 0; cursor: pointer;\n background: rgba(22, 24, 29, 0.85); color: #fff; font: inherit; font-size: 14px;\n}\n.b-photo__actions button:hover, .b-photo__actions button:focus-visible { background: var(--accent); color: #06120e; outline: none; }\n.b-photo--envoi::after { content: \"Envoi\u2026\"; position: absolute; inset: 0; display: grid; place-items: center; background: rgba(22,24,29,.6); color: #fff; font-size: 12px; }\n.b-depot {\n grid-column: 1 / -1; padding: 14px; border-radius: 12px; border: 2px dashed #4a505d;\n text-align: center; color: var(--texte-doux); font-size: 12.5px; transition: background .12s, border-color .12s;\n}\n.b-depot--survol { border-color: var(--accent); background: rgba(59, 165, 141, 0.1); color: #9fe3d1; }\n.b-depot__boutons { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-top: 8px; }\n.b-depot__boutons label { cursor: pointer; }\n.b-depot__boutons input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }\n.b-depot__boutons label:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 8px; }\n.b-camera { display: none !important; }\n@media (pointer: coarse) { .b-camera { display: inline-flex !important; } .b-glisser { display: none; } }\n\n.b-puces { display: flex; flex-wrap: wrap; gap: 6px; }\n.b-danger { border-top: 1px solid var(--bord); padding-top: 14px; }\n.b-danger p { margin: 0 0 8px; font-size: 12.5px; color: var(--texte-doux); }\n.bouton--danger { background: transparent; color: var(--danger); border-color: rgba(217, 119, 106, 0.5); }\n.bouton--danger:hover { background: rgba(217, 119, 106, 0.14); }\n.bouton--danger-plein { background: #b3261e; border-color: #b3261e; color: #fff; }\n.bouton--danger-plein:hover { background: #c9372e; }\n.b-confirmer { padding: 12px; border-radius: 12px; border: 1px solid rgba(217, 119, 106, 0.5); background: rgba(217, 119, 106, 0.08); }\n.b-confirmer p { margin: 0 0 10px; color: var(--texte); }\n.b-confirmer .rang { display: flex; gap: 8px; flex-wrap: wrap; }\n.b-bandeau { margin: 0 0 12px; padding: 9px 11px; border-radius: 10px; font-size: 12.5px; background: rgba(217, 119, 106, 0.12); border: 1px solid rgba(217, 119, 106, 0.4); color: #f0b3a9; }\n\n/* ------------------------------------------------------ COLLECTIONS ---- */\n.b-coll { border: 1px solid var(--bord); border-radius: 12px; background: var(--fond-clair); margin-bottom: 8px; }\n.b-coll__ligne { display: flex; align-items: center; gap: 10px; padding: 8px 8px 8px 12px; min-height: 64px; }\n.b-coll__texte { flex: 1; min-width: 0; border: 0; background: transparent; color: var(--texte); font: inherit; text-align: left; cursor: pointer; padding: 6px 0; min-height: 44px; }\n.b-coll__texte:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }\n.b-coll__nom { display: block; font-weight: 600; }\n.b-coll__meta { display: block; font-size: 12px; color: var(--texte-doux); }\n.b-coll .b-inter { width: auto; min-height: 44px; padding: 0 6px; border: 0; background: transparent; }\n.b-coll__corps { border-top: 1px solid var(--bord); padding: 10px 12px 12px; }\n.b-choix { display: grid; gap: 6px; margin-top: 8px; }\n.b-mini { display: flex; align-items: center; gap: 10px; padding: 6px 0; min-height: 52px; }\n.b-mini img, .b-mini .b-vignette { width: 40px; height: 40px; }\n.b-mini span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.b-coche { display: flex; align-items: center; gap: 10px; min-height: 48px; cursor: pointer; }\n.b-coche input { width: 20px; height: 20px; accent-color: var(--accent); flex: none; }\n.b-ligne-ajout { display: flex; gap: 8px; margin-top: 8px; }\n.b-ligne-ajout input { flex: 1; }\n\n@media (prefers-reduced-motion: reduce) { .b-rail, .b-rail::after, .b-depot { transition: none; } }\n";
|
|
1
|
+
export declare const CSS_BOUTIQUE = "\n.panneau--boutique { width: min(440px, 100vw); }\n.panneau--boutique .bouton { min-height: 40px; }\n@media (max-width: 520px) {\n .panneau--boutique {\n top: auto; left: 0; right: 0; width: auto; height: 88vh; height: 88dvh;\n border-radius: 18px 18px 0 0;\n }\n .panneau--boutique .bouton { min-height: 44px; }\n .panneau--boutique .bouton--icone { min-width: 44px; }\n}\n.poignee { display: none; width: 44px; height: 5px; border-radius: 3px; background: #4a505d; margin: 8px auto 0; flex: none; }\n@media (max-width: 520px) { .poignee { display: block; } }\n\n.b-tete { display: flex; align-items: center; gap: 6px; padding: 10px 12px; border-bottom: 1px solid var(--bord); }\n.b-tete h2 { flex: 1; margin: 0; font-size: 16px; font-weight: 650; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.b-tete .bouton--icone { min-width: 40px; min-height: 40px; font-size: 16px; }\n\n.b-onglets { display: flex; gap: 2px; padding: 0 12px; border-bottom: 1px solid var(--bord); }\n.b-onglets button {\n border: 0; background: transparent; color: var(--texte-doux); font: inherit; font-weight: 600;\n min-height: 44px; padding: 0 12px; cursor: pointer; border-bottom: 2px solid transparent;\n}\n.b-onglets button[aria-selected=\"true\"] { color: var(--texte); border-bottom-color: var(--accent); }\n.b-onglets button:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }\n.b-onglets small { opacity: .65; margin-left: 4px; font-weight: 500; }\n\n.b-avis {\n margin: 0 0 12px; padding: 9px 11px; border-radius: 10px; font-size: 12.5px; line-height: 1.45;\n background: rgba(227, 181, 91, 0.1); border: 1px solid rgba(227, 181, 91, 0.35); color: #f1d9a6;\n}\n.b-ajout {\n width: 100%; min-height: 48px; margin-bottom: 12px; border-radius: 12px; cursor: pointer;\n border: 2px dashed var(--accent); background: transparent; color: #9fe3d1; font: inherit; font-weight: 650;\n}\n.b-ajout:hover, .b-ajout:focus-visible { background: rgba(59, 165, 141, 0.1); outline: none; }\n\n.b-recherche { min-height: 44px; border-radius: 10px !important; font-size: 14px !important; }\n.b-filtres { display: flex; gap: 6px; overflow-x: auto; padding: 10px 0 12px; scrollbar-width: none; }\n.b-puce {\n flex: none; display: inline-flex; align-items: center; gap: 4px; min-height: 36px; padding: 0 12px;\n border-radius: 999px; border: 1px solid var(--bord); background: transparent; color: var(--texte-doux);\n font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer;\n}\n.b-puce small { opacity: .7; font-weight: 500; }\n.b-puce[aria-pressed=\"true\"] { background: rgba(59, 165, 141, 0.16); border-color: var(--accent); color: #9fe3d1; }\n.b-puce:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }\n@media (max-width: 520px) { .b-puce { min-height: 44px; } }\n\n.b-rangee {\n display: flex; align-items: center; gap: 12px; width: 100%; height: 64px; margin-bottom: 6px; padding: 8px;\n border-radius: 12px; border: 1px solid var(--bord); background: var(--fond-clair); color: var(--texte);\n font: inherit; text-align: left; cursor: pointer;\n}\n.b-rangee:hover, .b-rangee:focus-visible { border-color: var(--accent); outline: none; }\n.b-vignette { width: 48px; height: 48px; flex: none; border-radius: 9px; object-fit: cover; background: #2a2e37; display: block; }\n.b-vignette--vide { display: grid; place-items: center; color: var(--texte-doux); font-size: 18px; }\n.b-rangee__texte { flex: 1; min-width: 0; }\n.b-rangee__nom { display: block; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.b-rangee__meta { display: block; font-size: 12px; color: var(--texte-doux); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }\n.b-etiquette { flex: none; font-size: 11px; font-weight: 700; padding: 2px 8px; border-radius: 999px; }\n.b-etiquette--vente { background: rgba(59, 165, 141, 0.18); color: #8fd9c6; }\n.b-etiquette--masque { background: rgba(163, 169, 182, 0.16); color: var(--texte-doux); }\n.b-etiquette--vendu { background: rgba(217, 119, 106, 0.18); color: #f0b3a9; }\n.b-vide { color: var(--texte-doux); font-size: 13px; padding: 18px 4px; text-align: center; }\n\n/* ---------------------------------------------------------- FICHE ------ */\n.b-section { margin-bottom: 18px; }\n.b-section > h3 { margin: 0 0 8px; font-size: 11.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--texte-doux); }\n.b-champ { margin-bottom: 12px; }\n.b-champ label, .b-champ .b-etiq { display: block; margin-bottom: 5px; font-size: 12.5px; font-weight: 600; }\n.b-champ label small { font-weight: 400; color: var(--texte-doux); }\n.panneau--boutique input[type=\"text\"], .panneau--boutique input[type=\"search\"], .panneau--boutique textarea {\n min-height: 44px; padding: 10px 12px; border-radius: 10px; font-size: 14px;\n}\n.b-champ--erreur input, .b-champ--erreur textarea { border-color: var(--danger) !important; }\n.b-erreur { margin: 4px 0 0; font-size: 12px; color: #f0b3a9; }\n.b-aide { margin: 4px 0 0; font-size: 11.5px; color: var(--texte-doux); }\n.b-deux { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }\n.b-prix { position: relative; }\n.b-prix span { position: absolute; right: 12px; top: 50%; transform: translateY(-50%); color: var(--texte-doux); pointer-events: none; }\n.b-prix input { padding-right: 28px !important; }\n\n.b-seg { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }\n.b-seg button {\n min-height: 44px; border-radius: 10px; border: 1px solid var(--bord); background: var(--fond-clair);\n color: var(--texte-doux); font: inherit; font-size: 12.5px; font-weight: 600; cursor: pointer;\n}\n.b-seg button[aria-pressed=\"true\"] { border-color: var(--accent); color: #9fe3d1; background: rgba(59, 165, 141, 0.14); }\n.b-seg button:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }\n\n.b-inter {\n display: flex; align-items: center; gap: 12px; width: 100%; min-height: 56px; padding: 10px 12px;\n border-radius: 12px; background: var(--fond-clair); border: 1px solid var(--bord); color: var(--texte);\n font: inherit; text-align: left; cursor: pointer;\n}\n.b-inter:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }\n.b-inter small { display: block; color: var(--texte-doux); font-size: 11.5px; font-weight: 400; }\n.b-rail { position: relative; width: 46px; height: 28px; flex: none; border-radius: 999px; background: #4a505d; transition: background .15s; }\n.b-rail::after { content: \"\"; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px; border-radius: 50%; background: #fff; transition: left .15s; }\n[aria-checked=\"true\"] > .b-rail { background: var(--accent); }\n[aria-checked=\"true\"] > .b-rail::after { left: 21px; }\n\n.b-photos { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }\n.b-photo { position: relative; aspect-ratio: 1; border-radius: 10px; overflow: hidden; border: 2px solid transparent; background: #2a2e37; }\n.b-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }\n.b-photo--principale { border-color: var(--accent); }\n.b-photo__badge { position: absolute; left: 6px; bottom: 6px; background: var(--accent); color: #06120e; font-size: 10.5px; font-weight: 700; padding: 2px 6px; border-radius: 999px; }\n.b-photo__actions { position: absolute; top: 4px; right: 4px; display: flex; gap: 4px; }\n.b-photo__actions button {\n width: 36px; height: 36px; border-radius: 50%; border: 0; cursor: pointer;\n background: rgba(22, 24, 29, 0.85); color: #fff; font: inherit; font-size: 14px;\n}\n.b-photo__actions button:hover, .b-photo__actions button:focus-visible { background: var(--accent); color: #06120e; outline: none; }\n.b-photo--envoi::after { content: \"Envoi\u2026\"; position: absolute; inset: 0; display: grid; place-items: center; background: rgba(22,24,29,.6); color: #fff; font-size: 12px; }\n.b-depot {\n grid-column: 1 / -1; padding: 14px; border-radius: 12px; border: 2px dashed #4a505d;\n text-align: center; color: var(--texte-doux); font-size: 12.5px; transition: background .12s, border-color .12s;\n}\n.b-depot--survol { border-color: var(--accent); background: rgba(59, 165, 141, 0.1); color: #9fe3d1; }\n.b-depot__boutons { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-top: 8px; }\n.b-depot__boutons label { cursor: pointer; }\n.b-depot__boutons input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }\n.b-depot__boutons label:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 8px; }\n.b-camera { display: none !important; }\n@media (pointer: coarse) { .b-camera { display: inline-flex !important; } .b-glisser { display: none; } }\n\n.b-puces { display: flex; flex-wrap: wrap; gap: 6px; }\n.b-danger { border-top: 1px solid var(--bord); padding-top: 14px; }\n.b-danger p { margin: 0 0 8px; font-size: 12.5px; color: var(--texte-doux); }\n.bouton--danger { background: transparent; color: var(--danger); border-color: rgba(217, 119, 106, 0.5); }\n.bouton--danger:hover { background: rgba(217, 119, 106, 0.14); }\n.bouton--danger-plein { background: #b3261e; border-color: #b3261e; color: #fff; }\n.bouton--danger-plein:hover { background: #c9372e; }\n.b-confirmer { padding: 12px; border-radius: 12px; border: 1px solid rgba(217, 119, 106, 0.5); background: rgba(217, 119, 106, 0.08); }\n.b-confirmer p { margin: 0 0 10px; color: var(--texte); }\n.b-confirmer .rang { display: flex; gap: 8px; flex-wrap: wrap; }\n.b-bandeau { margin: 0 0 12px; padding: 9px 11px; border-radius: 10px; font-size: 12.5px; background: rgba(217, 119, 106, 0.12); border: 1px solid rgba(217, 119, 106, 0.4); color: #f0b3a9; }\n\n/* ------------------------------------------------------ COLLECTIONS ---- */\n.b-coll { border: 1px solid var(--bord); border-radius: 12px; background: var(--fond-clair); margin-bottom: 8px; }\n.b-coll__ligne { display: flex; align-items: center; gap: 10px; padding: 8px 8px 8px 12px; min-height: 64px; }\n.b-coll__texte { flex: 1; min-width: 0; border: 0; background: transparent; color: var(--texte); font: inherit; text-align: left; cursor: pointer; padding: 6px 0; min-height: 44px; }\n.b-coll__texte:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 6px; }\n.b-coll__nom { display: block; font-weight: 600; }\n.b-coll__meta { display: block; font-size: 12px; color: var(--texte-doux); }\n.b-coll .b-inter { width: auto; min-height: 44px; padding: 0 6px; border: 0; background: transparent; }\n.b-coll__corps { border-top: 1px solid var(--bord); padding: 10px 12px 12px; }\n.b-choix { display: grid; gap: 6px; margin-top: 8px; }\n.b-mini { display: flex; align-items: center; gap: 10px; padding: 6px 0; min-height: 52px; }\n.b-mini img, .b-mini .b-vignette { width: 40px; height: 40px; }\n.b-mini span { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.b-coche { display: flex; align-items: center; gap: 10px; min-height: 48px; cursor: pointer; }\n.b-coche input { width: 20px; height: 20px; accent-color: var(--accent); flex: none; }\n.b-ligne-ajout { display: flex; gap: 8px; margin-top: 8px; }\n.b-ligne-ajout input { flex: 1; }\n\n/* ------------------------------------------------------- BROUILLONS ---- */\n.b-etiquette--brouillon { background: rgba(227, 181, 91, 0.18); color: #f1d9a6; }\n.b-avis--brouillon { background: rgba(59, 165, 141, 0.1); border-color: rgba(59, 165, 141, 0.4); color: #bfeadf; }\n.b-intertitre { margin: 14px 0 8px; font-size: 11.5px; letter-spacing: .07em; text-transform: uppercase; color: var(--texte-doux); }\n.b-lien { border: 0; background: none; padding: 0 2px; color: #9fe3d1; font: inherit; font-weight: 650; text-decoration: underline; cursor: pointer; min-height: 32px; }\n.b-lien:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }\n.b-alerte { margin: 8px 12px 0; }\n.b-aide--attention { color: #f1d9a6; }\n.b-tete .bouton--principal { min-height: 40px; }\n.panneau--boutique .panneau__pied { flex-wrap: wrap; }\n@media (max-width: 520px) {\n .panneau--boutique .panneau__pied { padding-bottom: calc(10px + env(safe-area-inset-bottom, 0px)); }\n .panneau--boutique .panneau__pied .bouton { flex: 1 1 auto; }\n .panneau--boutique .panneau__pied .espace { display: none; }\n}\n\n/* ------------------------------------------------- CHOIX DU \u00AB + \u00BB ------ */\n.b-choix-grand { display: grid; gap: 10px; }\n.b-gros-choix {\n display: flex; align-items: flex-start; gap: 14px; width: 100%; min-height: 88px; padding: 14px;\n border-radius: 14px; border: 1px solid var(--bord); background: var(--fond-clair); color: var(--texte);\n font: inherit; text-align: left; cursor: pointer;\n}\n.b-gros-choix:hover, .b-gros-choix:focus-visible { border-color: var(--accent); outline: none; background: #262a32; }\n.b-gros-choix b { display: block; font-size: 15px; margin-bottom: 3px; }\n.b-gros-choix small { display: block; color: var(--texte-doux); font-size: 12.5px; line-height: 1.45; }\n.b-gros-choix__icone { flex: none; display: grid; place-items: center; width: 44px; height: 44px; border-radius: 12px; background: rgba(59, 165, 141, 0.16); color: #9fe3d1; font-size: 22px; }\n\n/* --------------------------------------------------------- S\u00C9LECTEUR --- */\n.b-choisir {\n display: flex; align-items: center; gap: 12px; height: 58px; padding: 0 8px; border-radius: 12px;\n border: 1px solid transparent; cursor: pointer;\n}\n.b-choisir:hover { background: var(--fond-clair); }\n.b-choisir:focus-within { border-color: var(--accent); }\n.b-choisir input { width: 22px; height: 22px; flex: none; accent-color: var(--accent); }\n.b-choisir--coche { background: rgba(59, 165, 141, 0.1); }\n.b-choisir--deja { opacity: .6; cursor: default; }\n\n/* ------------------------------------------------- FICHE COLLECTION ---- */\n.b-niveaux { border: 0; margin: 0 0 6px; padding: 0; display: grid; gap: 6px; }\n.b-niveaux legend { margin-bottom: 6px; font-size: 12.5px; font-weight: 600; padding: 0; }\n.b-niveau {\n display: flex; align-items: flex-start; gap: 10px; min-height: 52px; padding: 10px 12px; border-radius: 12px;\n border: 1px solid var(--bord); background: var(--fond-clair); cursor: pointer;\n}\n.b-niveau input { width: 18px; height: 18px; margin: 2px 0 0; accent-color: var(--accent); flex: none; }\n.b-niveau b { display: block; font-size: 13.5px; }\n.b-niveau small { display: block; color: var(--texte-doux); font-size: 12px; }\n.b-niveau--choisi { border-color: var(--accent); background: rgba(59, 165, 141, 0.1); }\n.b-niveau:focus-within { outline: 2px solid var(--accent); outline-offset: 2px; }\n.b-mini { height: 58px; padding: 0; }\n.b-mini__ouvrir {\n flex: 1; min-width: 0; display: flex; align-items: center; gap: 10px; min-height: 48px; padding: 0 4px;\n border: 0; border-radius: 8px; background: transparent; color: var(--texte); font: inherit; text-align: left; cursor: pointer;\n}\n.b-mini__ouvrir:hover, .b-mini__ouvrir:focus-visible { background: var(--fond-clair); outline: none; }\n.b-mini__ouvrir > span:not(.b-etiquette):not(.b-vignette) { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n\n/* ------------------------------------------------------------ PUBLIER --- */\n.b-pub { border: 1px solid var(--bord); border-radius: 12px; background: var(--fond-clair); margin-bottom: 8px; padding: 6px 10px 8px; }\n.b-pub__ligne { display: flex; align-items: center; gap: 10px; min-height: 52px; cursor: pointer; }\n.b-pub__ligne input { width: 22px; height: 22px; flex: none; accent-color: var(--accent); }\n.b-pub__etat { font-size: 12px; padding-left: 32px; }\n.b-pub__etat:empty { display: none; }\n.b-pub__ok { color: #8fd9c6; font-weight: 650; }\n.b-pub__erreur { color: #f0b3a9; }\n.b-pub--ok { border-color: rgba(59, 165, 141, 0.6); }\n.b-pub--echec { border-color: rgba(217, 119, 106, 0.6); }\n.b-pub__ouvrir { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; padding: 6px 0 0 32px; font-size: 12.5px; color: var(--texte-doux); }\n.b-pub__ouvrir select { min-height: 40px; border-radius: 10px; border: 1px solid var(--bord); background: var(--fond); color: var(--texte); font: inherit; padding: 0 8px; max-width: 100%; }\n\n@media (prefers-reduced-motion: reduce) { .b-rail, .b-rail::after, .b-depot { transition: none; } }\n";
|
package/dist/editeur/styles.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
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/* --------------------------------------------------------- SAISIE ------- */\n\n/* Une valeur marqu\u00E9e par le site (un prix, un num\u00E9ro) se corrige dans une\n saisie pos\u00E9e EXACTEMENT dessus, dans la police de la page : on \u00E9crit l\u00E0 o\u00F9\n on lisait. Le libell\u00E9 au-dessus dit quel champ on touche \u2014 \u00AB S\u00E9ance\n d'acupuncture \u00BB, pas \u00AB seance \u00BB. */\n.saisie {\n position: fixed;\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 4px;\n}\n.saisie__libelle,\n.saisie__aide,\n.saisie__erreur {\n padding: 3px 8px;\n border-radius: 6px;\n font: 600 11px/1.35 ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, sans-serif;\n white-space: nowrap;\n}\n.saisie__libelle { background: var(--fond); color: var(--texte); }\n.saisie__aide { background: rgba(22, 24, 29, 0.82); color: var(--texte-doux); font-weight: 500; }\n.saisie__erreur { background: #b3261e; color: #fff; }\n.saisie__champ {\n min-width: 0;\n padding: 2px 8px;\n border: 2px solid var(--accent);\n border-radius: 6px;\n background: #fff;\n color: #111;\n line-height: 1.2;\n box-shadow: 0 10px 28px rgba(0, 0, 0, 0.28);\n outline: none;\n}\n.saisie__champ:focus { box-shadow: 0 0 0 3px rgba(59, 165, 141, 0.35), 0 10px 28px rgba(0, 0, 0, 0.28); }\n.saisie__champ:disabled { opacity: 0.7; }\n\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
|
-
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\n.barre__pastille {\n display: inline-block; min-width: 18px; padding: 0 5px; border-radius: 999px;\n background: rgba(6, 18, 14, 0.25); font-size: 11px; line-height: 18px; text-align: center;\n}\n\n/* LA BARRE AU T\u00C9L\u00C9PHONE. Une pilule de 600 px ne tient pas dans 390 : elle\n devient une bande pleine largeur, en bas, et chaque bouton fait au moins\n 44 px \u2014 la taille d'un doigt, pas d'un pointeur. On tait ce qui se lit\n ailleurs (la phrase d'aide, le compte, que la pastille du bouton Publier\n porte d\u00E9j\u00E0). L'aper\u00E7u mobile n'a pas de sens sur un t\u00E9l\u00E9phone. */\n@media (max-width: 640px) {\n .barre {\n left: 8px; right: 8px; bottom: 8px; transform: none;\n max-width: none; gap: 6px; padding: 6px;\n border-radius: 18px; justify-content: space-between;\n padding-bottom: calc(6px + env(safe-area-inset-bottom, 0px));\n }\n .barre .bouton { min-height: 44px; padding: 8px 12px; }\n .barre .bouton--icone { min-width: 44px; }\n .barre__texte, .barre__compte, .barre__point, .bouton--bureau-seul { display: none; }\n .flottant { bottom: 84px; }\n}\n\n/* ------------------------------------------------ BOUTIQUE SUR LA PAGE --- */\n\n/* LE CRAYON d'une carte produit : rond, sombre, 44 px \u2014 visible sur toutes\n les photos, claires comme fonc\u00E9es. */\n.crayon {\n position:
|
|
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\n.barre__pastille {\n display: inline-block; min-width: 18px; padding: 0 5px; border-radius: 999px;\n background: rgba(6, 18, 14, 0.25); font-size: 11px; line-height: 18px; text-align: center;\n}\n\n/* LA BARRE AU T\u00C9L\u00C9PHONE. Une pilule de 600 px ne tient pas dans 390 : elle\n devient une bande pleine largeur, en bas, et chaque bouton fait au moins\n 44 px \u2014 la taille d'un doigt, pas d'un pointeur. On tait ce qui se lit\n ailleurs (la phrase d'aide, le compte, que la pastille du bouton Publier\n porte d\u00E9j\u00E0). L'aper\u00E7u mobile n'a pas de sens sur un t\u00E9l\u00E9phone. */\n@media (max-width: 640px) {\n .barre {\n left: 8px; right: 8px; bottom: 8px; transform: none;\n max-width: none; gap: 6px; padding: 6px;\n border-radius: 18px; justify-content: space-between;\n padding-bottom: calc(6px + env(safe-area-inset-bottom, 0px));\n }\n .barre .bouton { min-height: 44px; padding: 8px 12px; }\n .barre .bouton--icone { min-width: 44px; }\n .barre__texte, .barre__compte, .barre__point, .bouton--bureau-seul, .barre__libelle { display: none; }\n /* Filet : si un site ajoute de quoi d\u00E9border, la barre d\u00E9file au lieu de\n pousser \u00AB Quitter \u00BB hors de l'\u00E9cran. */\n .barre { overflow-x: auto; scrollbar-width: none; }\n .flottant { bottom: 84px; }\n}\n\n/* ------------------------------------------------ BOUTIQUE SUR LA PAGE --- */\n\n/* LA COUCHE DES CRAYONS, aux coordonn\u00E9es du DOCUMENT : d\u00E9filer la page ne\n fait que la d\u00E9placer (un transform), sans aucun rendu. */\n.marques { position: absolute; top: 0; left: 0; width: 0; height: 0; will-change: transform; }\n\n/* LE CRAYON d'une carte produit : rond, sombre, 44 px \u2014 visible sur toutes\n les photos, claires comme fonc\u00E9es. */\n.crayon {\n position: absolute; width: 44px; height: 44px; border-radius: 50%; border: 0;\n display: grid; place-items: center; cursor: pointer;\n background: var(--fond); color: #fff;\n box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);\n}\n.crayon svg { width: 18px; height: 18px; }\n.crayon:hover, .crayon:focus-visible { background: var(--accent); color: #06120e; outline: 2px solid #fff; outline-offset: 2px; }\n\n/* CRAYON ET \u00AB + \u00BB D'UNE COLLECTION, c\u00F4te \u00E0 c\u00F4te. */\n.marque-coll { position: absolute; display: flex; gap: 6px; }\n.marque-coll .crayon { position: static; }\n.crayon--plus { background: var(--accent); color: #06120e; font: 400 26px/1 ui-sans-serif, system-ui, sans-serif; }\n.crayon--plus:hover, .crayon--plus:focus-visible { background: #45bda2; }\n\n/* --------------------------------------------------- APER\u00C7U MOBILE ------ */\n.apercu {\n position: fixed; inset: 0; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;\n background: rgba(16, 18, 22, 0.82); backdrop-filter: blur(3px);\n}\n.apercu__barre {\n display: flex; align-items: center; gap: 10px; padding: 6px 6px 6px 14px;\n background: var(--fond); border: 1px solid var(--bord); border-radius: 999px; font-size: 12.5px;\n}\n.apercu__tel { padding: 12px; border-radius: 44px; background: #0b0c0f; box-shadow: 0 30px 70px rgba(0, 0, 0, 0.55); }\n.apercu__tel iframe { display: block; border: 0; border-radius: 32px; background: #fff; }\n";
|
package/dist/editeur.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import "react/jsx-runtime";
|
|
2
2
|
import "react-dom/client";
|
|
3
|
-
import "./morceaux/constantes-
|
|
4
|
-
import { a as i, b as n } from "./morceaux/index-
|
|
3
|
+
import "./morceaux/constantes-BAdpe1ss.js";
|
|
4
|
+
import { a as i, b as n } from "./morceaux/index-C_uFDnBO.js";
|
|
5
5
|
export {
|
|
6
6
|
i as monterConnexion,
|
|
7
7
|
n as monterEditeur
|