@lystech/sections 0.2.0 → 0.4.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/dist/editeur.js CHANGED
@@ -1,50 +1,248 @@
1
- import { jsxs as p, jsx as o, Fragment as V } from "react/jsx-runtime";
2
- import { createRoot as H } from "react-dom/client";
3
- import { useState as g, useEffect as T, useCallback as S, useMemo as Q, useRef as W } from "react";
4
- function X({
1
+ import { jsx as e, jsxs as m, Fragment as te } from "react/jsx-runtime";
2
+ import { createRoot as ne } from "react-dom/client";
3
+ import { useState as L, useRef as B, useEffect as J, useCallback as F, useMemo as K } from "react";
4
+ function de({
5
5
  jeton: n,
6
6
  site: t,
7
- apiBaseUrl: s,
7
+ apiBaseUrl: i,
8
8
  surJetonRefuse: r
9
9
  }) {
10
- const c = {
10
+ const a = {
11
11
  "Content-Type": "application/json",
12
12
  Authorization: "Bearer " + n
13
13
  };
14
- function b(e, a) {
15
- if (a && (e.status === 401 || e.status === 403) && r(), !e.ok) throw new Error(String(e.status));
14
+ function d(o, c) {
15
+ if (c && (o.status === 401 || o.status === 403) && r(), !o.ok) throw new Error(String(o.status));
16
16
  }
17
- async function d(e, a = !0) {
18
- const u = await fetch(s + e, {
19
- headers: a ? c : void 0
17
+ async function l(o, c = !0) {
18
+ const h = await fetch(i + o, {
19
+ headers: c ? a : void 0
20
20
  });
21
- return b(u, a), await u.json();
21
+ return d(h, c), await h.json();
22
22
  }
23
- async function l(e, a, u) {
24
- const m = await fetch(s + e, {
25
- method: a,
26
- headers: c,
27
- body: u === void 0 ? void 0 : JSON.stringify(u)
23
+ async function b(o, c, h) {
24
+ const g = await fetch(i + o, {
25
+ method: c,
26
+ headers: a,
27
+ body: h === void 0 ? void 0 : JSON.stringify(h)
28
28
  });
29
- return b(m, !0), await m.json();
29
+ return d(g, !0), await g.json();
30
30
  }
31
31
  return {
32
32
  /** Les blocs que le site a déclaré savoir afficher. Route publique. */
33
- schemas: () => d("/site-sections/public/" + encodeURIComponent(t) + "/schemas", !1),
33
+ schemas: () => l("/site-sections/public/" + encodeURIComponent(t) + "/schemas", !1),
34
34
  /** Ce qui existe sur une page, brouillons compris. */
35
- pourPage: (e) => d("/site-sections?page=" + encodeURIComponent(e)),
36
- creer: (e, a, u) => l("/site-sections", "POST", { page: e, blockType: a, draft: u }),
37
- enregistrerBrouillon: (e, a) => l("/site-sections/" + e + "/draft", "PUT", { draft: a }),
38
- publier: (e) => l("/site-sections/" + e + "/publish", "POST"),
35
+ pourPage: (o) => l("/site-sections?page=" + encodeURIComponent(o)),
36
+ creer: (o, c, h) => b("/site-sections", "POST", { page: o, blockType: c, draft: h }),
37
+ enregistrerBrouillon: (o, c) => b("/site-sections/" + o + "/draft", "PUT", { draft: c }),
38
+ publier: (o) => b("/site-sections/" + o + "/publish", "POST"),
39
39
  /** Ramène le brouillon à ce qui est en ligne. */
40
- annuler: (e) => l("/site-sections/" + e + "/revert", "POST")
40
+ annuler: (o) => b("/site-sections/" + o + "/revert", "POST")
41
41
  };
42
42
  }
43
- function Z(n, t) {
44
- const s = n && typeof n == "object" && !Array.isArray(n) ? Object.keys(n).filter((c) => /^[a-z]{2}(-[A-Za-z]{2})?$/.test(c)) : [], r = t.slice(0, 2);
45
- return Array.from(/* @__PURE__ */ new Set([r, ...s]));
43
+ const pe = {
44
+ apiKey: "AIzaSyCpAeHlt1wZvM5KtYg7X7MDVnWVJT86gvc",
45
+ authDomain: "lystech.firebaseapp.com",
46
+ projectId: "lystech",
47
+ storageBucket: "lystech.appspot.com",
48
+ messagingSenderId: "237347321732",
49
+ appId: "1:237347321732:web:7f9586d48e488d73ddcfd1"
50
+ };
51
+ function fe() {
52
+ return /* @__PURE__ */ m("span", { className: "marque", children: [
53
+ /* @__PURE__ */ e("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ e(
54
+ "path",
55
+ {
56
+ d: "M12 2c2.6 2.4 3.9 4.9 3.9 7.5 0 1.6-.5 3-1.6 4.2 1.9-.3 3.4-1.1 4.6-2.4-.2 3.4-2.3 5.9-6.1 7.3V22h-1.6v-3.4C7.4 17.2 5.3 14.7 5.1 11.3c1.2 1.3 2.7 2.1 4.6 2.4-1.1-1.2-1.6-2.6-1.6-4.2C8.1 6.9 9.4 4.4 12 2z",
57
+ fill: "currentColor"
58
+ }
59
+ ) }),
60
+ /* @__PURE__ */ e("span", { className: "marque__mot", children: "Lystech" })
61
+ ] });
62
+ }
63
+ function me() {
64
+ return /* @__PURE__ */ m("svg", { viewBox: "0 0 18 18", "aria-hidden": "true", focusable: "false", className: "logo", children: [
65
+ /* @__PURE__ */ e("path", { fill: "#4285F4", d: "M17.64 9.2c0-.64-.06-1.25-.16-1.84H9v3.48h4.84a4.14 4.14 0 0 1-1.8 2.72v2.26h2.91c1.7-1.57 2.69-3.88 2.69-6.62z" }),
66
+ /* @__PURE__ */ e("path", { fill: "#34A853", d: "M9 18c2.43 0 4.47-.8 5.96-2.18l-2.91-2.26c-.81.54-1.84.86-3.05.86-2.34 0-4.33-1.58-5.04-3.71H.96v2.33A9 9 0 0 0 9 18z" }),
67
+ /* @__PURE__ */ e("path", { fill: "#FBBC05", d: "M3.96 10.71a5.41 5.41 0 0 1 0-3.42V4.96H.96a9 9 0 0 0 0 8.08l3-2.33z" }),
68
+ /* @__PURE__ */ e("path", { fill: "#EA4335", d: "M9 3.58c1.32 0 2.5.45 3.44 1.35l2.58-2.59C13.46.89 11.43 0 9 0A9 9 0 0 0 .96 4.96l3 2.33C4.67 5.16 6.66 3.58 9 3.58z" })
69
+ ] });
70
+ }
71
+ function be() {
72
+ return /* @__PURE__ */ e("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", focusable: "false", className: "logo", children: /* @__PURE__ */ e(
73
+ "path",
74
+ {
75
+ fill: "#fff",
76
+ d: "M22 12.06C22 6.5 17.52 2 12 2S2 6.5 2 12.06c0 5.02 3.66 9.18 8.44 9.94v-7.03H7.9v-2.91h2.54V9.85c0-2.52 1.49-3.91 3.77-3.91 1.09 0 2.24.2 2.24.2v2.46h-1.26c-1.24 0-1.63.78-1.63 1.57v1.89h2.78l-.45 2.91h-2.33V22c4.78-.76 8.44-4.92 8.44-9.94z"
77
+ }
78
+ ) });
79
+ }
80
+ function xe({
81
+ site: n,
82
+ apiBaseUrl: t,
83
+ methodes: i = ["google", "facebook"],
84
+ surJeton: r,
85
+ surFermer: a
86
+ }) {
87
+ const [d, l] = L({ nom: "repos" }), b = (g) => {
88
+ switch (g) {
89
+ case "auth/popup-blocked":
90
+ return "Votre navigateur a bloqué la fenêtre de connexion. Autorisez les fenêtres pour ce site, puis réessayez.";
91
+ case "auth/popup-closed-by-user":
92
+ case "auth/cancelled-popup-request":
93
+ return "Connexion annulée.";
94
+ case "auth/unauthorized-domain":
95
+ return "Ce domaine n'est pas encore autorisé côté Lystech. Prévenez la personne qui gère le site.";
96
+ case "auth/account-exists-with-different-credential":
97
+ return "Cette adresse est déjà associée à un autre mode de connexion. Essayez l'autre bouton.";
98
+ case "auth/network-request-failed":
99
+ return "Connexion au réseau impossible. Vérifiez votre lien Internet.";
100
+ default:
101
+ return "La connexion a échoué. Réessayez dans un instant.";
102
+ }
103
+ }, o = async (g, C = !1) => {
104
+ const E = await fetch(t + "/site-sections/edit-login/third-party", {
105
+ method: "POST",
106
+ headers: { "Content-Type": "application/json" },
107
+ body: JSON.stringify({
108
+ site: n,
109
+ token: g,
110
+ tokenType: "firebase",
111
+ demanderAcces: C
112
+ })
113
+ });
114
+ if (E.status === 429) {
115
+ l({
116
+ nom: "erreur",
117
+ texte: "Trop de tentatives. Réessayez dans quelques minutes."
118
+ });
119
+ return;
120
+ }
121
+ const v = await E.json().catch(() => null);
122
+ if (v?.ok && v?.token) {
123
+ r(v.token);
124
+ return;
125
+ }
126
+ switch (v?.raison) {
127
+ case "sans_acces":
128
+ l({ nom: "sans-acces", jeton: g });
129
+ return;
130
+ case "demande_envoyee":
131
+ l({ nom: "demande-envoyee" });
132
+ return;
133
+ case "trop_de_demandes":
134
+ l({
135
+ nom: "erreur",
136
+ texte: "Trop de demandes aujourd'hui. Réessayez demain."
137
+ });
138
+ return;
139
+ case "aucun_compte":
140
+ l({ nom: "aucun-compte", adresse: "" });
141
+ return;
142
+ case "adresse_non_verifiee":
143
+ l({
144
+ nom: "erreur",
145
+ texte: "Votre fournisseur n'a pas confirmé cette adresse courriel. Vérifiez-la chez lui, puis réessayez."
146
+ });
147
+ return;
148
+ default:
149
+ l({
150
+ nom: "erreur",
151
+ texte: "La connexion a échoué. Réessayez dans un instant."
152
+ });
153
+ }
154
+ }, c = async (g) => {
155
+ l({ nom: "envoi", quoi: g });
156
+ try {
157
+ const [{ initializeApp: C, getApps: E }, v] = await Promise.all([
158
+ import("./morceaux/index.esm-B4AB50RA.js"),
159
+ import("./morceaux/index.esm-B4hL1FOE.js")
160
+ ]), R = E().find((_) => _.name === "lystech-edition") ?? C(pe, "lystech-edition"), q = g === "google" ? new v.GoogleAuthProvider() : new v.FacebookAuthProvider(), w = await (await v.signInWithPopup(v.getAuth(R), q)).user.getIdToken();
161
+ await o(w);
162
+ } catch (C) {
163
+ l({ nom: "erreur", texte: b(String(C?.code ?? "")) });
164
+ }
165
+ }, h = d.nom === "envoi";
166
+ return /* @__PURE__ */ e("div", { className: "voile", role: "dialog", "aria-modal": "true", "aria-label": "Modifier ce site", children: /* @__PURE__ */ m("div", { className: "fenetre", children: [
167
+ /* @__PURE__ */ e(
168
+ "button",
169
+ {
170
+ type: "button",
171
+ className: "fenetre__fermer",
172
+ onClick: a,
173
+ "aria-label": "Fermer",
174
+ children: "✕"
175
+ }
176
+ ),
177
+ /* @__PURE__ */ m("div", { className: "fenetre__tete", children: [
178
+ /* @__PURE__ */ e(fe, {}),
179
+ /* @__PURE__ */ e("h2", { className: "fenetre__titre", children: "Modifier ce site" }),
180
+ /* @__PURE__ */ e("p", { className: "fenetre__sous", children: "Vous vous connectez à Lystech. Cet accès ne sert qu'à modifier le contenu de ce site." })
181
+ ] }),
182
+ /* @__PURE__ */ m("div", { className: "fenetre__corps", children: [
183
+ d.nom === "erreur" && /* @__PURE__ */ e("p", { className: "message message--erreur", children: d.texte }),
184
+ d.nom === "aucun-compte" && /* @__PURE__ */ e("p", { className: "message message--info", children: "Aucun compte Lystech ne correspond à cette adresse. Adressez-vous à la personne responsable du site." }),
185
+ d.nom === "sans-acces" && /* @__PURE__ */ e("p", { className: "message message--info", children: "Vous êtes bien reconnu, mais vous n'avez pas encore le droit de modifier ce site. Vous pouvez le demander : la personne responsable recevra un courriel." }),
186
+ d.nom === "demande-envoyee" && /* @__PURE__ */ e("p", { className: "message message--ok", children: "Demande envoyée. La personne responsable du site vous répondra." }),
187
+ d.nom === "sans-acces" ? /* @__PURE__ */ e(
188
+ "button",
189
+ {
190
+ type: "button",
191
+ className: "bouton bouton--principal bouton--large",
192
+ onClick: () => {
193
+ o(d.jeton, !0);
194
+ },
195
+ children: "Demander l'accès"
196
+ }
197
+ ) : d.nom === "demande-envoyee" || d.nom === "aucun-compte" ? /* @__PURE__ */ e(
198
+ "button",
199
+ {
200
+ type: "button",
201
+ className: "bouton bouton--large",
202
+ onClick: a,
203
+ children: "Fermer"
204
+ }
205
+ ) : /* @__PURE__ */ m("div", { className: "fournisseurs", children: [
206
+ i.includes("google") && /* @__PURE__ */ m(
207
+ "button",
208
+ {
209
+ type: "button",
210
+ className: "fournisseur fournisseur--google",
211
+ disabled: h,
212
+ onClick: () => {
213
+ c("google");
214
+ },
215
+ children: [
216
+ /* @__PURE__ */ e(me, {}),
217
+ /* @__PURE__ */ e("span", { children: d.nom === "envoi" && d.quoi === "google" ? "Connexion…" : "Continuer avec Google" })
218
+ ]
219
+ }
220
+ ),
221
+ i.includes("facebook") && /* @__PURE__ */ m(
222
+ "button",
223
+ {
224
+ type: "button",
225
+ className: "fournisseur fournisseur--facebook",
226
+ disabled: h,
227
+ onClick: () => {
228
+ c("facebook");
229
+ },
230
+ children: [
231
+ /* @__PURE__ */ e(be, {}),
232
+ /* @__PURE__ */ e("span", { children: d.nom === "envoi" && d.quoi === "facebook" ? "Connexion…" : "Continuer avec Facebook" })
233
+ ]
234
+ }
235
+ )
236
+ ] })
237
+ ] }),
238
+ /* @__PURE__ */ e("p", { className: "fenetre__pied", children: "Votre mot de passe reste chez votre fournisseur : ce site ne le voit jamais." })
239
+ ] }) });
240
+ }
241
+ function he(n, t) {
242
+ const i = n && typeof n == "object" && !Array.isArray(n) ? Object.keys(n).filter((a) => /^[a-z]{2}(-[A-Za-z]{2})?$/.test(a)) : [], r = t.slice(0, 2);
243
+ return Array.from(/* @__PURE__ */ new Set([r, ...i]));
46
244
  }
47
- function $(n) {
245
+ function ge(n) {
48
246
  switch (n.type) {
49
247
  case "number":
50
248
  return 0;
@@ -56,164 +254,164 @@ function $(n) {
56
254
  return "";
57
255
  }
58
256
  }
59
- function j({ champ: n, valeur: t, changer: s }) {
257
+ function Z({ champ: n, valeur: t, changer: i }) {
60
258
  switch (n.type) {
61
259
  case "richText":
62
- return /* @__PURE__ */ o(
260
+ return /* @__PURE__ */ e(
63
261
  "textarea",
64
262
  {
65
263
  value: String(t ?? ""),
66
- onChange: (r) => s(r.target.value)
264
+ onChange: (r) => i(r.target.value)
67
265
  }
68
266
  );
69
267
  case "number":
70
- return /* @__PURE__ */ o(
268
+ return /* @__PURE__ */ e(
71
269
  "input",
72
270
  {
73
271
  type: "number",
74
272
  value: t === "" || t == null ? "" : String(t),
75
- onChange: (r) => s(r.target.value === "" ? "" : Number(r.target.value))
273
+ onChange: (r) => i(r.target.value === "" ? "" : Number(r.target.value))
76
274
  }
77
275
  );
78
276
  case "boolean":
79
- return /* @__PURE__ */ p("label", { className: "bascule", children: [
80
- /* @__PURE__ */ o(
277
+ return /* @__PURE__ */ m("label", { className: "bascule", children: [
278
+ /* @__PURE__ */ e(
81
279
  "input",
82
280
  {
83
281
  type: "checkbox",
84
282
  checked: t === !0,
85
- onChange: (r) => s(r.target.checked)
283
+ onChange: (r) => i(r.target.checked)
86
284
  }
87
285
  ),
88
- /* @__PURE__ */ o("span", { children: t === !0 ? "Oui" : "Non" })
286
+ /* @__PURE__ */ e("span", { children: t === !0 ? "Oui" : "Non" })
89
287
  ] });
90
288
  case "date":
91
- return /* @__PURE__ */ o(
289
+ return /* @__PURE__ */ e(
92
290
  "input",
93
291
  {
94
292
  type: "date",
95
293
  value: String(t ?? "").slice(0, 10),
96
- onChange: (r) => s(r.target.value)
294
+ onChange: (r) => i(r.target.value)
97
295
  }
98
296
  );
99
297
  case "choice":
100
- return /* @__PURE__ */ p(
298
+ return /* @__PURE__ */ m(
101
299
  "select",
102
300
  {
103
301
  value: String(t ?? ""),
104
- onChange: (r) => s(r.target.value),
302
+ onChange: (r) => i(r.target.value),
105
303
  children: [
106
- /* @__PURE__ */ o("option", { value: "", children: "—" }),
107
- (n.options ?? []).map((r) => /* @__PURE__ */ o("option", { value: r, children: r }, r))
304
+ /* @__PURE__ */ e("option", { value: "", children: "—" }),
305
+ (n.options ?? []).map((r) => /* @__PURE__ */ e("option", { value: r, children: r }, r))
108
306
  ]
109
307
  }
110
308
  );
111
309
  case "url":
112
- return /* @__PURE__ */ o(
310
+ return /* @__PURE__ */ e(
113
311
  "input",
114
312
  {
115
313
  type: "url",
116
314
  value: String(t ?? ""),
117
- onChange: (r) => s(r.target.value),
315
+ onChange: (r) => i(r.target.value),
118
316
  placeholder: "https://"
119
317
  }
120
318
  );
121
319
  case "image":
122
- return /* @__PURE__ */ p(V, { children: [
123
- /* @__PURE__ */ o(
320
+ return /* @__PURE__ */ m(te, { children: [
321
+ /* @__PURE__ */ e(
124
322
  "input",
125
323
  {
126
324
  type: "url",
127
325
  value: String(t ?? ""),
128
- onChange: (r) => s(r.target.value),
326
+ onChange: (r) => i(r.target.value),
129
327
  placeholder: "https://…"
130
328
  }
131
329
  ),
132
- String(t ?? "").startsWith("http") && /* @__PURE__ */ o("img", { className: "vignette", src: String(t), alt: "" })
330
+ String(t ?? "").startsWith("http") && /* @__PURE__ */ e("img", { className: "vignette", src: String(t), alt: "" })
133
331
  ] });
134
332
  default:
135
- return /* @__PURE__ */ o(
333
+ return /* @__PURE__ */ e(
136
334
  "input",
137
335
  {
138
336
  type: "text",
139
337
  value: String(t ?? ""),
140
- onChange: (r) => s(r.target.value)
338
+ onChange: (r) => i(r.target.value)
141
339
  }
142
340
  );
143
341
  }
144
342
  }
145
- function P({ champ: n, valeur: t, changer: s, langue: r }) {
343
+ function oe({ champ: n, valeur: t, changer: i, langue: r }) {
146
344
  if (n.type === "list") {
147
- const c = Array.isArray(t) ? t : [], b = n.of ?? [], d = (l, e, a) => {
148
- const u = c.map((m, _) => _ === l ? { ...m, [e]: a } : m);
149
- s(u);
345
+ const a = Array.isArray(t) ? t : [], d = n.of ?? [], l = (b, o, c) => {
346
+ const h = a.map((g, C) => C === b ? { ...g, [o]: c } : g);
347
+ i(h);
150
348
  };
151
- return /* @__PURE__ */ p("div", { className: "champ", children: [
152
- /* @__PURE__ */ o("span", { className: "champ__etiquette", children: n.label }),
153
- n.help && /* @__PURE__ */ o("p", { className: "champ__aide", children: n.help }),
154
- c.map((l, e) => /* @__PURE__ */ p("div", { className: "liste__item", children: [
155
- /* @__PURE__ */ p("div", { className: "liste__tete", children: [
156
- /* @__PURE__ */ o("span", { className: "liste__rang", children: e + 1 }),
157
- /* @__PURE__ */ p("span", { style: { display: "flex", gap: 4 }, children: [
158
- /* @__PURE__ */ o(
349
+ return /* @__PURE__ */ m("div", { className: "champ", children: [
350
+ /* @__PURE__ */ e("span", { className: "champ__etiquette", children: n.label }),
351
+ n.help && /* @__PURE__ */ e("p", { className: "champ__aide", children: n.help }),
352
+ a.map((b, o) => /* @__PURE__ */ m("div", { className: "liste__item", children: [
353
+ /* @__PURE__ */ m("div", { className: "liste__tete", children: [
354
+ /* @__PURE__ */ e("span", { className: "liste__rang", children: o + 1 }),
355
+ /* @__PURE__ */ m("span", { style: { display: "flex", gap: 4 }, children: [
356
+ /* @__PURE__ */ e(
159
357
  "button",
160
358
  {
161
359
  type: "button",
162
360
  className: "bouton bouton--icone bouton--discret",
163
361
  title: "Monter",
164
- disabled: e === 0,
362
+ disabled: o === 0,
165
363
  onClick: () => {
166
- const a = [...c];
167
- [a[e - 1], a[e]] = [a[e], a[e - 1]], s(a);
364
+ const c = [...a];
365
+ [c[o - 1], c[o]] = [c[o], c[o - 1]], i(c);
168
366
  },
169
367
  children: "↑"
170
368
  }
171
369
  ),
172
- /* @__PURE__ */ o(
370
+ /* @__PURE__ */ e(
173
371
  "button",
174
372
  {
175
373
  type: "button",
176
374
  className: "bouton bouton--icone bouton--discret",
177
375
  title: "Descendre",
178
- disabled: e === c.length - 1,
376
+ disabled: o === a.length - 1,
179
377
  onClick: () => {
180
- const a = [...c];
181
- [a[e], a[e + 1]] = [a[e + 1], a[e]], s(a);
378
+ const c = [...a];
379
+ [c[o], c[o + 1]] = [c[o + 1], c[o]], i(c);
182
380
  },
183
381
  children: "↓"
184
382
  }
185
383
  ),
186
- /* @__PURE__ */ o(
384
+ /* @__PURE__ */ e(
187
385
  "button",
188
386
  {
189
387
  type: "button",
190
388
  className: "bouton bouton--icone bouton--discret",
191
389
  title: "Retirer",
192
- onClick: () => s(c.filter((a, u) => u !== e)),
390
+ onClick: () => i(a.filter((c, h) => h !== o)),
193
391
  children: "✕"
194
392
  }
195
393
  )
196
394
  ] })
197
395
  ] }),
198
- b.map((a) => /* @__PURE__ */ o(
199
- P,
396
+ d.map((c) => /* @__PURE__ */ e(
397
+ oe,
200
398
  {
201
- champ: a,
399
+ champ: c,
202
400
  langue: r,
203
- valeur: l?.[a.key],
204
- changer: (u) => d(e, a.key, u)
401
+ valeur: b?.[c.key],
402
+ changer: (h) => l(o, c.key, h)
205
403
  },
206
- a.key
404
+ c.key
207
405
  ))
208
- ] }, e)),
209
- /* @__PURE__ */ o(
406
+ ] }, o)),
407
+ /* @__PURE__ */ e(
210
408
  "button",
211
409
  {
212
410
  type: "button",
213
411
  className: "bouton",
214
- onClick: () => s([
215
- ...c,
216
- Object.fromEntries(b.map((l) => [l.key, $(l)]))
412
+ onClick: () => i([
413
+ ...a,
414
+ Object.fromEntries(d.map((b) => [b.key, ge(b)]))
217
415
  ]),
218
416
  children: "+ Ajouter"
219
417
  }
@@ -221,264 +419,535 @@ function P({ champ: n, valeur: t, changer: s, langue: r }) {
221
419
  ] });
222
420
  }
223
421
  if (n.localized) {
224
- const c = Z(t, r), b = t && typeof t == "object" && !Array.isArray(t) ? t : {};
225
- return /* @__PURE__ */ p("div", { className: "champ", children: [
226
- /* @__PURE__ */ o("span", { className: "champ__etiquette", children: n.label }),
227
- n.help && /* @__PURE__ */ o("p", { className: "champ__aide", children: n.help }),
228
- c.map((d) => /* @__PURE__ */ p("div", { style: { marginBottom: 8 }, children: [
229
- /* @__PURE__ */ o("span", { className: "champ__langue", children: d }),
230
- /* @__PURE__ */ o(
231
- j,
422
+ const a = he(t, r), d = t && typeof t == "object" && !Array.isArray(t) ? t : {};
423
+ return /* @__PURE__ */ m("div", { className: "champ", children: [
424
+ /* @__PURE__ */ e("span", { className: "champ__etiquette", children: n.label }),
425
+ n.help && /* @__PURE__ */ e("p", { className: "champ__aide", children: n.help }),
426
+ a.map((l) => /* @__PURE__ */ m("div", { style: { marginBottom: 8 }, children: [
427
+ /* @__PURE__ */ e("span", { className: "champ__langue", children: l }),
428
+ /* @__PURE__ */ e(
429
+ Z,
232
430
  {
233
431
  champ: n,
234
- valeur: b[d],
235
- changer: (l) => s({ ...b, [d]: l })
432
+ valeur: d[l],
433
+ changer: (b) => i({ ...d, [l]: b })
236
434
  }
237
435
  )
238
- ] }, d))
436
+ ] }, l))
239
437
  ] });
240
438
  }
241
- return /* @__PURE__ */ p("div", { className: "champ", children: [
242
- /* @__PURE__ */ o("label", { className: "champ__etiquette", children: n.label }),
243
- /* @__PURE__ */ o(j, { champ: n, valeur: t, changer: s }),
244
- n.help && /* @__PURE__ */ o("p", { className: "champ__aide", children: n.help })
439
+ return /* @__PURE__ */ m("div", { className: "champ", children: [
440
+ /* @__PURE__ */ e("label", { className: "champ__etiquette", children: n.label }),
441
+ /* @__PURE__ */ e(Z, { champ: n, valeur: t, changer: i }),
442
+ n.help && /* @__PURE__ */ e("p", { className: "champ__aide", children: n.help })
245
443
  ] });
246
444
  }
247
- function G(n, t) {
248
- const s = n.haut - 12, r = t + 8, c = n.haut + n.hauteur - 34;
249
- return Math.min(Math.max(s, r), Math.max(r, c));
250
- }
251
- function K() {
252
- let n = 0;
253
- return document.querySelectorAll("header, nav, [class*='header'], [class*='nav']").forEach((t) => {
254
- const s = getComputedStyle(t);
255
- if (s.position !== "fixed" && s.position !== "sticky") return;
256
- const r = t.getBoundingClientRect();
257
- r.top <= 4 && r.height > 0 && r.height < 200 && (n = Math.max(n, r.bottom));
258
- }), n;
259
- }
260
- function Y() {
261
- const [n, t] = g([]), [s, r] = g(0), c = W("");
262
- return T(() => {
263
- let b = 0;
264
- const d = () => {
265
- const a = [];
266
- document.querySelectorAll("[data-lystech-section]").forEach((_) => {
267
- const y = _.getAttribute("data-lystech-section");
268
- if (!y) return;
269
- const x = _.getBoundingClientRect();
270
- x.width < 8 || x.height < 8 || a.push({
271
- blockType: y,
272
- haut: x.top,
273
- gauche: x.left,
274
- largeur: x.width,
275
- hauteur: x.height
445
+ const ve = ["lystech-editeur-hote", "lystech-connexion-hote"];
446
+ function ye(n) {
447
+ const t = /* @__PURE__ */ new Map();
448
+ for (const [i, r] of Object.entries(n))
449
+ for (const [a, d] of Object.entries(r)) {
450
+ const l = String(d ?? "").trim();
451
+ if (l.length < 2 || l.includes("{{")) continue;
452
+ const b = t.get(l);
453
+ b ? b.push({ ns: i, chemin: a }) : t.set(l, [{ ns: i, chemin: a }]);
454
+ }
455
+ return t;
456
+ }
457
+ function _e(n) {
458
+ const t = /* @__PURE__ */ new Map(), i = document.body.querySelectorAll("*");
459
+ for (const r of i) {
460
+ if (ve.some((l) => r.id === l || r.closest("#" + l)) || r.children.length > 0) continue;
461
+ const a = (r.textContent ?? "").trim();
462
+ if (a.length < 2) continue;
463
+ const d = n.get(a);
464
+ d && t.set(r, { valeur: a, candidats: d });
465
+ }
466
+ return t;
467
+ }
468
+ function we({
469
+ source: n,
470
+ actif: t,
471
+ surModification: i
472
+ }) {
473
+ const r = B(/* @__PURE__ */ new Map()), a = B(null), [d, l] = L(null), b = B(n);
474
+ b.current = n;
475
+ const o = B(i);
476
+ return o.current = i, J(() => {
477
+ if (!t) return;
478
+ const c = b.current.langueCourante(), h = ye(b.current.dictionnaire(c)), g = () => {
479
+ r.current = _e(h);
480
+ };
481
+ g();
482
+ let C;
483
+ const E = new MutationObserver(() => {
484
+ a.current || (clearTimeout(C), C = setTimeout(g, 250));
485
+ });
486
+ E.observe(document.body, { childList: !0, subtree: !0 });
487
+ const v = "outline:2px dashed rgba(59,165,141,.85);outline-offset:3px;border-radius:3px;cursor:text;", R = (p) => {
488
+ const s = p.target;
489
+ !(s instanceof HTMLElement) || a.current || r.current.has(s) && (s.dataset.lysStyleAvant || (s.dataset.lysStyleAvant = s.getAttribute("style") ?? ""), s.setAttribute(
490
+ "style",
491
+ (s.dataset.lysStyleAvant ?? "") + v
492
+ ));
493
+ }, q = (p) => {
494
+ const s = p.target;
495
+ if (!(s instanceof HTMLElement) || a.current?.el === s || s.dataset.lysStyleAvant === void 0) return;
496
+ const N = s.dataset.lysStyleAvant;
497
+ delete s.dataset.lysStyleAvant, N ? s.setAttribute("style", N) : s.removeAttribute("style");
498
+ }, I = (p, s) => {
499
+ const N = p.getAttribute("style") ?? "";
500
+ a.current = {
501
+ el: p,
502
+ avant: (p.textContent ?? "").trim(),
503
+ ns: s.ns,
504
+ chemin: s.chemin,
505
+ styleAvant: p.dataset.lysStyleAvant ?? N
506
+ }, p.setAttribute("contenteditable", "plaintext-only"), p.setAttribute(
507
+ "style",
508
+ (p.dataset.lysStyleAvant ?? "") + "outline:2px solid #3ba58d;outline-offset:3px;border-radius:3px;"
509
+ ), p.focus();
510
+ const P = window.getSelection(), D = document.createRange();
511
+ D.selectNodeContents(p), P?.removeAllRanges(), P?.addRange(D);
512
+ }, w = async (p) => {
513
+ const s = a.current;
514
+ if (!s) return;
515
+ a.current = null;
516
+ const N = (s.el.textContent ?? "").trim();
517
+ s.el.removeAttribute("contenteditable");
518
+ const P = s.el.dataset.lysStyleAvant;
519
+ if (delete s.el.dataset.lysStyleAvant, P ? s.el.setAttribute("style", P) : s.el.removeAttribute("style"), p || N === s.avant) {
520
+ p && (s.el.textContent = s.avant);
521
+ return;
522
+ }
523
+ const D = b.current.langueCourante();
524
+ b.current.poser(D, s.ns, s.chemin, N), await o.current(s.ns, s.chemin, D, N);
525
+ }, _ = (p) => {
526
+ const s = p.target;
527
+ if (!(s instanceof HTMLElement)) return;
528
+ if (a.current) {
529
+ if (a.current.el === s) return;
530
+ w(!1);
531
+ }
532
+ const N = r.current.get(s);
533
+ if (N) {
534
+ if (p.preventDefault(), p.stopPropagation(), N.candidats.length === 1) {
535
+ I(s, N.candidats[0]);
536
+ return;
537
+ }
538
+ l({
539
+ el: s,
540
+ candidats: N.candidats,
541
+ x: p.clientX,
542
+ y: p.clientY
276
543
  });
277
- });
278
- const u = K(), m = JSON.stringify(a) + "|" + u;
279
- m !== c.current && (c.current = m, t(a), r(u));
280
- }, l = () => {
281
- cancelAnimationFrame(b), b = requestAnimationFrame(d);
544
+ }
545
+ }, O = (p) => {
546
+ a.current && (p.key === "Escape" ? (p.preventDefault(), w(!0)) : p.key === "Enter" && !p.shiftKey && (p.preventDefault(), w(!1)));
547
+ }, H = () => {
548
+ a.current && w(!1);
282
549
  };
283
- d(), window.addEventListener("scroll", l, !0), window.addEventListener("resize", l);
284
- const e = new MutationObserver(l);
285
- return e.observe(document.body, { childList: !0, subtree: !0 }), () => {
286
- cancelAnimationFrame(b), window.removeEventListener("scroll", l, !0), window.removeEventListener("resize", l), e.disconnect();
550
+ document.addEventListener("mouseover", R, !0), document.addEventListener("mouseout", q, !0), document.addEventListener("click", _, !0);
551
+ const U = (p) => {
552
+ if (!a.current) return;
553
+ const s = p.inputType;
554
+ (s === "insertParagraph" || s === "insertLineBreak") && (p.preventDefault(), w(!1));
287
555
  };
288
- }, []), { ancres: n, enTete: s };
556
+ return document.addEventListener("beforeinput", U, !0), document.addEventListener("keydown", O, !0), document.addEventListener("focusout", H, !0), window.__lysChoisir = (p, s) => {
557
+ l(null), I(s, p);
558
+ }, () => {
559
+ clearTimeout(C), E.disconnect(), document.removeEventListener("mouseover", R, !0), document.removeEventListener("mouseout", q, !0), document.removeEventListener("click", _, !0), document.removeEventListener("beforeinput", U, !0), document.removeEventListener("keydown", O, !0), document.removeEventListener("focusout", H, !0), a.current && w(!0), delete window.__lysChoisir;
560
+ };
561
+ }, [t]), d ? /* @__PURE__ */ m(
562
+ "div",
563
+ {
564
+ className: "choix",
565
+ style: {
566
+ top: Math.min(d.y + 10, window.innerHeight - 200),
567
+ left: Math.min(d.x, window.innerWidth - 280)
568
+ },
569
+ children: [
570
+ /* @__PURE__ */ e("p", { className: "choix__titre", children: "Ce texte apparaît à plusieurs endroits." }),
571
+ /* @__PURE__ */ e("p", { className: "choix__aide", children: "Lequel corrigez-vous ?" }),
572
+ d.candidats.map((c) => /* @__PURE__ */ m(
573
+ "button",
574
+ {
575
+ type: "button",
576
+ className: "choix__option",
577
+ onClick: () => window.__lysChoisir?.(c, d.el),
578
+ children: [
579
+ /* @__PURE__ */ e("span", { className: "choix__chemin", children: c.chemin }),
580
+ /* @__PURE__ */ e("span", { className: "choix__ns", children: c.ns })
581
+ ]
582
+ },
583
+ c.ns + ":" + c.chemin
584
+ )),
585
+ /* @__PURE__ */ e(
586
+ "button",
587
+ {
588
+ type: "button",
589
+ className: "bouton bouton--discret",
590
+ onClick: () => l(null),
591
+ children: "Annuler"
592
+ }
593
+ )
594
+ ]
595
+ }
596
+ ) : null;
289
597
  }
290
- function ee({ api: n, pont: t }) {
291
- const [s, r] = g([]), [c, b] = g([]), [d, l] = g(t.page), [e, a] = g(null), [u, m] = g({}), [_, y] = g(!1), [x, w] = g(!1), [z, f] = g(null), { ancres: I, enTete: R } = Y();
292
- T(() => (t.surChangementDePage = (i) => {
293
- l(i), a(null);
598
+ const $ = /^i18n:([^:]+):(.*)$/, G = "commun";
599
+ function ee(n, t) {
600
+ return JSON.stringify(n ?? {}) === JSON.stringify(t ?? {});
601
+ }
602
+ function Ne({ api: n, pont: t }) {
603
+ const [i, r] = L([]), [a, d] = L([]), [l, b] = L(t.page), [o, c] = L(null), [h, g] = L({}), [C, E] = L(!1), [v, R] = L("modifier"), [q, I] = L(!1), [w, _] = L(
604
+ null
605
+ );
606
+ J(() => (t.surChangementDePage = (u) => {
607
+ b(u), c(null), E(!1);
294
608
  }, () => {
295
609
  t.surChangementDePage = void 0;
296
610
  }), [t]);
297
- const C = S(async () => {
611
+ const O = F(async () => {
298
612
  try {
299
- const i = await n.pourPage(d);
300
- return b(i), i;
613
+ const [u, f] = await Promise.all([
614
+ n.pourPage(l),
615
+ l === G ? Promise.resolve([]) : n.pourPage(G)
616
+ ]), x = [...u, ...f];
617
+ return d(x), x;
301
618
  } catch {
302
- return f({ ton: "erreur", texte: "Impossible de lire le contenu du site." }), [];
619
+ return _({
620
+ ton: "erreur",
621
+ texte: "Impossible de lire le contenu du site."
622
+ }), [];
303
623
  }
304
- }, [n, d]);
305
- T(() => {
624
+ }, [n, l]);
625
+ J(() => {
306
626
  n.schemas().then(r).catch(() => r([]));
307
- }, [n]), T(() => {
308
- C();
309
- }, [C]);
310
- const A = S(
311
- (i) => s.find((h) => h.blockType === i),
312
- [s]
313
- ), E = Q(
314
- () => I.filter((i) => A(i.blockType)),
315
- [I, A]
316
- ), U = S(
317
- (i) => {
318
- const h = c.find((N) => N.blockType === i), v = h?.draft ?? h?.data ?? {};
319
- m({ ...v }), a(i), y(!1), f(
320
- h?.draft && JSON.stringify(h.draft) !== JSON.stringify(h.data ?? {}) ? { ton: "info", texte: "Un brouillon non publié est en cours." } : null
321
- );
627
+ }, [n]), J(() => {
628
+ O();
629
+ }, [O]);
630
+ const H = F(
631
+ (u, f) => {
632
+ let x = null, A = -1;
633
+ for (const T of i) {
634
+ const y = $.exec(T.blockType);
635
+ if (!y || y[1] !== u) continue;
636
+ const k = y[2];
637
+ (k === "" || f === k || f.startsWith(k + ".")) && k.length > A && (x = T, A = k.length);
638
+ }
639
+ if (!x) return null;
640
+ const S = $.exec(x.blockType)?.[2] ?? "", z = S ? f.slice(S.length + 1) : f;
641
+ return { bloc: x, champ: z };
322
642
  },
323
- [c]
324
- ), q = S(() => {
325
- e && t.poserApercu(e, null), a(null), y(!1), f(null);
326
- }, [e, t]), L = S(
327
- (i, h) => {
328
- m((v) => {
329
- const N = { ...v, [i]: h };
330
- return e && t.poserApercu(e, N), N;
331
- }), y(!0);
643
+ [i]
644
+ ), U = F(
645
+ (u) => i.find((f) => f.blockType === u),
646
+ [i]
647
+ ), p = K(
648
+ () => i.filter((u) => {
649
+ const f = u.pages ?? [];
650
+ return f.includes(l) || f.includes(G);
651
+ }),
652
+ [i, l]
653
+ ), s = K(
654
+ () => a.filter((u) => u.draft && !ee(u.draft, u.data)),
655
+ [a]
656
+ ), N = F(
657
+ async (u, f, x, A) => {
658
+ const S = H(u, f);
659
+ if (!S) {
660
+ _({
661
+ ton: "erreur",
662
+ texte: `Ce texte (${u}:${f}) n'appartient à aucun bloc déclaré.`
663
+ });
664
+ return;
665
+ }
666
+ const z = a.find((M) => M.blockType === S.bloc.blockType), T = z?.draft ?? z?.data ?? {}, y = T[S.champ], k = y && typeof y == "object" && !Array.isArray(y) ? { ...y, [x]: A } : { [x]: A }, j = { ...T, [S.champ]: k };
667
+ try {
668
+ if (z?.UID)
669
+ await n.enregistrerBrouillon(z.UID, j);
670
+ else {
671
+ const M = S.bloc.pages?.[0] ?? l;
672
+ await n.creer(M, S.bloc.blockType, j);
673
+ }
674
+ await O(), _(null);
675
+ } catch {
676
+ _({
677
+ ton: "erreur",
678
+ texte: "Enregistrement impossible. Votre texte est toujours à l'écran."
679
+ });
680
+ }
332
681
  },
333
- [e, t]
334
- ), O = S(async () => {
335
- if (!e) return null;
336
- const i = c.find((v) => v.blockType === e);
337
- return i?.UID ? (await n.enregistrerBrouillon(i.UID, u), i.UID) : (await n.creer(d, e, u)).UID;
338
- }, [n, e, d, c, u]), M = async () => {
339
- w(!0), f(null);
682
+ [n, H, l, O, a]
683
+ ), P = async () => {
684
+ if (!s.length) return;
685
+ I(!0), _(null);
686
+ const u = s.length;
340
687
  try {
341
- await O(), await C(), y(!1), f({ ton: "ok", texte: "Brouillon enregistré. Rien n'a encore changé pour vos visiteurs." });
688
+ for (const f of s) await n.publier(f.UID);
689
+ await O(), t.recharger(), _({
690
+ ton: "ok",
691
+ texte: u === 1 ? "Publié. Vos visiteurs le voient maintenant." : `${u} modifications publiées.`
692
+ });
342
693
  } catch {
343
- f({ ton: "erreur", texte: "L'enregistrement a échoué. Votre texte est toujours là — réessayez." });
694
+ _({
695
+ ton: "erreur",
696
+ texte: "La publication a échoué. Rien n'a été mis en ligne."
697
+ });
344
698
  } finally {
345
- w(!1);
699
+ I(!1);
346
700
  }
347
- }, B = async () => {
348
- w(!0), f(null);
701
+ }, D = async () => {
702
+ I(!0);
349
703
  try {
350
- const i = await O();
351
- if (!i) throw new Error("sans identifiant");
352
- await n.publier(i), await C(), e && t.poserApercu(e, null), t.recharger(), y(!1), f({ ton: "ok", texte: "Publié. Vos visiteurs le voient maintenant." });
353
- } catch {
354
- f({ ton: "erreur", texte: "La publication a échoué. Rien n'a été mis en ligne." });
704
+ for (const f of s) await n.annuler(f.UID);
705
+ const u = await O();
706
+ if (t.sourceTexte) {
707
+ const { appliquerAuxTextes: f } = await import("./morceaux/sourceTexte-BMPMpNg9.js");
708
+ f(
709
+ u.map((x) => ({ blockType: x.blockType, data: x.data })),
710
+ t.sourceTexte
711
+ );
712
+ }
713
+ _({
714
+ ton: "info",
715
+ texte: "Modifications abandonnées. On est revenu à ce qui est en ligne."
716
+ });
355
717
  } finally {
356
- w(!1);
718
+ I(!1);
719
+ }
720
+ }, se = (u) => {
721
+ const f = a.find((T) => T.blockType === u), x = f?.draft ?? f?.data ?? {}, A = U(u), S = $.exec(u), z = {};
722
+ if (S && A && t.sourceTexte) {
723
+ const T = S[1], y = S[2], k = t.sourceTexte.langues(), j = {};
724
+ for (const M of k)
725
+ j[M] = t.sourceTexte.dictionnaire(M)[T] ?? {};
726
+ for (const M of A.fields) {
727
+ const ue = y ? y + "." + M.key : M.key, X = {};
728
+ for (const W of k) {
729
+ const Y = j[W]?.[ue];
730
+ typeof Y == "string" && (X[W] = Y);
731
+ }
732
+ Object.keys(X).length && (z[M.key] = X);
733
+ }
734
+ }
735
+ for (const [T, y] of Object.entries(x)) {
736
+ const k = z[T], j = y && typeof y == "object" && !Array.isArray(y) && k && typeof k == "object" && !Array.isArray(k);
737
+ z[T] = j ? { ...k, ...y } : y;
357
738
  }
358
- }, F = async () => {
359
- if (!e) return;
360
- const i = c.find((h) => h.blockType === e);
361
- w(!0);
739
+ g(z), c(u), E(!1), _(null);
740
+ }, ie = (u, f) => g((x) => ({ ...x, [u]: f })), ce = async () => {
741
+ if (o) {
742
+ I(!0);
743
+ try {
744
+ const u = a.find((x) => x.blockType === o);
745
+ if (u?.UID) await n.enregistrerBrouillon(u.UID, h);
746
+ else {
747
+ const x = U(o)?.pages?.[0] ?? l;
748
+ await n.creer(x, o, h);
749
+ }
750
+ const f = await O();
751
+ if (t.sourceTexte) {
752
+ const { appliquerAuxTextes: x } = await import("./morceaux/sourceTexte-BMPMpNg9.js");
753
+ x(
754
+ f.map((A) => ({ blockType: A.blockType, data: A.draft ?? A.data })),
755
+ t.sourceTexte
756
+ );
757
+ }
758
+ _({
759
+ ton: "ok",
760
+ texte: "Enregistré. Rien n'a encore changé pour vos visiteurs."
761
+ });
762
+ } catch {
763
+ _({ ton: "erreur", texte: "L'enregistrement a échoué." });
764
+ } finally {
765
+ I(!1);
766
+ }
767
+ }
768
+ }, le = () => {
362
769
  try {
363
- i?.UID && await n.annuler(i.UID);
364
- const v = (await C()).find((N) => N.blockType === e);
365
- m({ ...v?.data ?? {} }), t.poserApercu(e, null), y(!1), f({ ton: "info", texte: "Brouillon abandonné. On est revenu à ce qui est en ligne." });
770
+ window.localStorage.setItem("lystech-edit-sortie", "1"), window.localStorage.removeItem("lystech-edit");
366
771
  } catch {
367
- f({ ton: "erreur", texte: "Impossible d'abandonner le brouillon." });
368
- } finally {
369
- w(!1);
370
772
  }
371
- }, J = () => {
372
773
  try {
373
774
  window.sessionStorage.removeItem("lystech-edit");
374
775
  } catch {
375
776
  }
376
777
  window.location.reload();
377
- }, k = e ? A(e) : void 0;
378
- return /* @__PURE__ */ p("div", { className: "calque", children: [
379
- E.map((i) => /* @__PURE__ */ p("div", { children: [
380
- /* @__PURE__ */ o(
381
- "div",
778
+ }, V = o ? U(o) : void 0, Q = !o && !C;
779
+ return /* @__PURE__ */ m("div", { className: "calque", children: [
780
+ /* @__PURE__ */ e("div", { className: "cadre-global", "aria-hidden": "true" }),
781
+ t.sourceTexte && /* @__PURE__ */ e(
782
+ we,
783
+ {
784
+ source: t.sourceTexte,
785
+ actif: Q && !q && v === "modifier",
786
+ surModification: N
787
+ }
788
+ ),
789
+ Q && /* @__PURE__ */ m("div", { className: "barre", children: [
790
+ /* @__PURE__ */ e("span", { className: "barre__point" }),
791
+ /* @__PURE__ */ e("span", { className: "barre__texte", children: v === "modifier" ? "Cliquez un texte pour le corriger" : "Navigation libre — les clics ouvrent les liens" }),
792
+ /* @__PURE__ */ e(
793
+ "button",
382
794
  {
383
- className: "cadre" + (e === i.blockType ? " cadre--actif" : ""),
384
- style: {
385
- top: i.haut - 4,
386
- left: i.gauche - 4,
387
- width: i.largeur + 8,
388
- height: i.hauteur + 8
795
+ type: "button",
796
+ className: "bouton " + (v === "circuler" ? "bouton--principal" : ""),
797
+ onClick: () => R((u) => u === "modifier" ? "circuler" : "modifier"),
798
+ title: v === "modifier" ? "Passer en navigation pour changer de page" : "Revenir a la modification des textes",
799
+ children: v === "modifier" ? "Circuler" : "Modifier"
800
+ }
801
+ ),
802
+ s.length > 0 ? /* @__PURE__ */ m(te, { children: [
803
+ /* @__PURE__ */ e("span", { className: "barre__compte", children: s.length === 1 ? "1 modification non publiée" : `${s.length} modifications non publiées` }),
804
+ /* @__PURE__ */ e(
805
+ "button",
806
+ {
807
+ type: "button",
808
+ className: "bouton bouton--principal",
809
+ onClick: P,
810
+ disabled: q,
811
+ children: "Publier"
812
+ }
813
+ ),
814
+ /* @__PURE__ */ e(
815
+ "button",
816
+ {
817
+ type: "button",
818
+ className: "bouton bouton--discret",
819
+ onClick: D,
820
+ disabled: q,
821
+ children: "Abandonner"
389
822
  }
823
+ )
824
+ ] }) : /* @__PURE__ */ e("span", { className: "barre__compte", children: "tout est publié" }),
825
+ /* @__PURE__ */ e(
826
+ "button",
827
+ {
828
+ type: "button",
829
+ className: "bouton bouton--icone bouton--discret",
830
+ onClick: () => E(!0),
831
+ title: "Tous les contenus",
832
+ "aria-label": "Tous les contenus",
833
+ children: "⋮"
390
834
  }
391
835
  ),
392
- /* @__PURE__ */ p(
836
+ /* @__PURE__ */ e(
393
837
  "button",
394
838
  {
395
839
  type: "button",
396
- className: "pastille",
397
- style: { top: G(i, R), left: i.gauche + 6 },
398
- onClick: () => U(i.blockType),
399
- children: [
400
- "✎ ",
401
- A(i.blockType)?.label ?? i.blockType
402
- ]
840
+ className: "bouton bouton--icone bouton--sortie",
841
+ onClick: le,
842
+ title: "Quitter le mode édition",
843
+ "aria-label": "Quitter le mode édition",
844
+ children: "✕"
403
845
  }
404
846
  )
405
- ] }, i.blockType)),
406
- !e && /* @__PURE__ */ p("div", { className: "barre", children: [
407
- /* @__PURE__ */ o("span", { className: "barre__point" }),
408
- /* @__PURE__ */ p("span", { className: "barre__texte", children: [
409
- "Mode édition — ",
410
- /* @__PURE__ */ o("b", { children: t.site })
411
- ] }),
412
- /* @__PURE__ */ o("span", { className: "barre__compte", children: E.length === 0 ? "aucune section sur cette page" : E.length === 1 ? "1 section modifiable" : E.length + " sections modifiables" }),
413
- /* @__PURE__ */ o("button", { type: "button", className: "bouton bouton--discret", onClick: J, children: "Quitter" })
414
847
  ] }),
415
- e && k && /* @__PURE__ */ p("div", { className: "panneau", role: "dialog", "aria-label": "Modifier " + k.label, children: [
416
- /* @__PURE__ */ p("div", { className: "panneau__tete", children: [
417
- /* @__PURE__ */ p("div", { style: { flex: 1 }, children: [
418
- /* @__PURE__ */ o("h2", { className: "panneau__titre", children: k.label }),
419
- k.description && /* @__PURE__ */ o("p", { className: "panneau__sous", children: k.description })
848
+ w && Q && /* @__PURE__ */ e("div", { className: "flottant", children: /* @__PURE__ */ e("p", { className: "message message--" + w.ton, children: w.texte }) }),
849
+ C && /* @__PURE__ */ m("div", { className: "panneau", role: "dialog", "aria-label": "Tous les contenus", children: [
850
+ /* @__PURE__ */ m("div", { className: "panneau__tete", children: [
851
+ /* @__PURE__ */ m("div", { style: { flex: 1 }, children: [
852
+ /* @__PURE__ */ e("h2", { className: "panneau__titre", children: "Tous les contenus" }),
853
+ /* @__PURE__ */ e("p", { className: "panneau__sous", children: "Y compris ce qui ne s'affiche pas dans la page : titre de l'onglet, description dans les moteurs de recherche, textes contenant une valeur calculée." })
420
854
  ] }),
421
- /* @__PURE__ */ o(
855
+ /* @__PURE__ */ e(
422
856
  "button",
423
857
  {
424
858
  type: "button",
425
859
  className: "bouton bouton--icone bouton--discret",
426
- onClick: q,
860
+ onClick: () => E(!1),
427
861
  "aria-label": "Fermer",
428
862
  children: "✕"
429
863
  }
430
864
  )
431
865
  ] }),
432
- /* @__PURE__ */ p("div", { className: "panneau__corps", children: [
433
- z && /* @__PURE__ */ o("p", { className: "message message--" + z.ton, children: z.texte }),
434
- k.fields.map((i) => /* @__PURE__ */ o(
435
- P,
436
- {
437
- champ: i,
438
- langue: t.langue,
439
- valeur: u[i.key],
440
- changer: (h) => L(i.key, h)
441
- },
442
- i.key
443
- ))
444
- ] }),
445
- /* @__PURE__ */ p("div", { className: "panneau__pied", children: [
446
- /* @__PURE__ */ o(
447
- "button",
448
- {
449
- type: "button",
450
- className: "bouton bouton--discret",
451
- onClick: F,
452
- disabled: x,
453
- children: "Abandonner"
454
- }
455
- ),
456
- /* @__PURE__ */ o("span", { className: "espace" }),
457
- /* @__PURE__ */ o(
458
- "button",
459
- {
460
- type: "button",
461
- className: "bouton",
462
- onClick: M,
463
- disabled: x || !_,
464
- children: "Enregistrer"
465
- }
466
- ),
467
- /* @__PURE__ */ o(
468
- "button",
469
- {
470
- type: "button",
471
- className: "bouton bouton--principal",
472
- onClick: B,
473
- disabled: x,
474
- children: "Publier"
475
- }
476
- )
866
+ /* @__PURE__ */ m("div", { className: "panneau__corps", children: [
867
+ p.length === 0 && /* @__PURE__ */ e("p", { className: "message message--info", children: "Aucun contenu déclaré pour cette page." }),
868
+ p.map((u) => {
869
+ const f = a.find((A) => A.blockType === u.blockType), x = f?.draft && !ee(f.draft, f.data);
870
+ return /* @__PURE__ */ m(
871
+ "button",
872
+ {
873
+ type: "button",
874
+ className: "rangee",
875
+ onClick: () => se(u.blockType),
876
+ children: [
877
+ /* @__PURE__ */ e("span", { className: "rangee__nom", children: u.label }),
878
+ /* @__PURE__ */ e("span", { className: "rangee__info", children: x ? "non publié" : `${u.fields.length} textes` })
879
+ ]
880
+ },
881
+ u.blockType
882
+ );
883
+ })
477
884
  ] })
478
- ] })
885
+ ] }),
886
+ o && V && /* @__PURE__ */ m(
887
+ "div",
888
+ {
889
+ className: "panneau",
890
+ role: "dialog",
891
+ "aria-label": "Modifier " + V.label,
892
+ children: [
893
+ /* @__PURE__ */ m("div", { className: "panneau__tete", children: [
894
+ /* @__PURE__ */ m("div", { style: { flex: 1 }, children: [
895
+ /* @__PURE__ */ e("h2", { className: "panneau__titre", children: V.label }),
896
+ V.description && /* @__PURE__ */ e("p", { className: "panneau__sous", children: V.description })
897
+ ] }),
898
+ /* @__PURE__ */ e(
899
+ "button",
900
+ {
901
+ type: "button",
902
+ className: "bouton bouton--icone bouton--discret",
903
+ onClick: () => c(null),
904
+ "aria-label": "Fermer",
905
+ children: "✕"
906
+ }
907
+ )
908
+ ] }),
909
+ /* @__PURE__ */ m("div", { className: "panneau__corps", children: [
910
+ w && /* @__PURE__ */ e("p", { className: "message message--" + w.ton, children: w.texte }),
911
+ V.fields.map((u) => /* @__PURE__ */ e(
912
+ oe,
913
+ {
914
+ champ: u,
915
+ langue: t.langue,
916
+ valeur: h[u.key],
917
+ changer: (f) => ie(u.key, f)
918
+ },
919
+ u.key
920
+ ))
921
+ ] }),
922
+ /* @__PURE__ */ m("div", { className: "panneau__pied", children: [
923
+ /* @__PURE__ */ e(
924
+ "button",
925
+ {
926
+ type: "button",
927
+ className: "bouton bouton--discret",
928
+ onClick: () => c(null),
929
+ disabled: q,
930
+ children: "Fermer"
931
+ }
932
+ ),
933
+ /* @__PURE__ */ e("span", { className: "espace" }),
934
+ /* @__PURE__ */ e(
935
+ "button",
936
+ {
937
+ type: "button",
938
+ className: "bouton bouton--principal",
939
+ onClick: ce,
940
+ disabled: q,
941
+ children: "Enregistrer"
942
+ }
943
+ )
944
+ ] })
945
+ ]
946
+ }
947
+ )
479
948
  ] });
480
949
  }
481
- const te = `
950
+ const ke = `
482
951
  :host {
483
952
  all: initial;
484
953
  --fond: #16181d;
@@ -598,6 +1067,113 @@ const te = `
598
1067
  }
599
1068
  .panneau__pied .espace { flex: 1; }
600
1069
 
1070
+ /* --------------------------------------------------- CONNEXION ---------- */
1071
+
1072
+ /* Le voile PREND les clics, lui : une boite de dialogue qui demande un mot de
1073
+ passe ne doit pas laisser cliquer la page derriere elle. C'est l'exception
1074
+ a la regle du calque, et elle est volontaire. */
1075
+ .voile {
1076
+ position: fixed;
1077
+ inset: 0;
1078
+ display: flex;
1079
+ align-items: center;
1080
+ justify-content: center;
1081
+ padding: 16px;
1082
+ background: rgba(8, 10, 14, 0.62);
1083
+ backdrop-filter: blur(2px);
1084
+ }
1085
+
1086
+ .fenetre {
1087
+ position: relative;
1088
+ width: min(408px, 100%);
1089
+ max-height: 92vh;
1090
+ overflow-y: auto;
1091
+ padding: 30px 28px 20px;
1092
+ border: 1px solid var(--bord);
1093
+ border-radius: 18px;
1094
+ /* Une lueur d'accent dans le coin superieur : de la presence, sans le
1095
+ degrade violet-bleu qu'on voit sur une page d'accueil sur deux. */
1096
+ background:
1097
+ radial-gradient(120% 90% at 50% -20%, rgba(59, 165, 141, 0.16), transparent 62%),
1098
+ var(--fond);
1099
+ box-shadow: 0 28px 70px rgba(0, 0, 0, 0.55);
1100
+ text-align: center;
1101
+ }
1102
+
1103
+ .fenetre__fermer {
1104
+ position: absolute; top: 12px; right: 12px;
1105
+ width: 30px; height: 30px;
1106
+ display: inline-flex; align-items: center; justify-content: center;
1107
+ border: 0; border-radius: 8px;
1108
+ background: transparent; color: var(--texte-doux);
1109
+ font: inherit; font-size: 14px; cursor: pointer;
1110
+ }
1111
+ .fenetre__fermer:hover { background: var(--fond-clair); color: var(--texte); }
1112
+
1113
+ /* ------------------------------------------------------------ MARQUE ---- */
1114
+
1115
+ .marque {
1116
+ display: inline-flex; align-items: center; gap: 7px;
1117
+ margin-bottom: 16px;
1118
+ color: var(--accent);
1119
+ }
1120
+ .marque svg { width: 20px; height: 20px; display: block; }
1121
+ .marque__mot {
1122
+ font-size: 12px; font-weight: 600;
1123
+ letter-spacing: 0.16em; text-transform: uppercase;
1124
+ color: var(--texte-doux);
1125
+ }
1126
+
1127
+ .fenetre__titre {
1128
+ margin: 0 0 6px;
1129
+ font-size: 20px; font-weight: 640; letter-spacing: -0.01em;
1130
+ color: var(--texte);
1131
+ }
1132
+ .fenetre__sous {
1133
+ margin: 0 auto 22px;
1134
+ max-width: 30ch;
1135
+ font-size: 13px; line-height: 1.5; color: var(--texte-doux);
1136
+ }
1137
+ .fenetre__corps { text-align: left; }
1138
+ .fenetre__pied {
1139
+ margin: 18px 0 0;
1140
+ padding-top: 14px;
1141
+ border-top: 1px solid var(--bord);
1142
+ font-size: 11.5px; line-height: 1.5; color: var(--texte-doux);
1143
+ text-align: center;
1144
+ }
1145
+
1146
+ /* ------------------------------------------------------ FOURNISSEURS ---- */
1147
+
1148
+ .fournisseurs { display: flex; flex-direction: column; gap: 10px; }
1149
+
1150
+ .fournisseur {
1151
+ display: flex; align-items: center; justify-content: center; gap: 10px;
1152
+ width: 100%; padding: 12px 16px;
1153
+ border: 1px solid transparent; border-radius: 10px;
1154
+ font: inherit; font-size: 14px; font-weight: 600;
1155
+ cursor: pointer;
1156
+ transition: transform 90ms ease, filter 90ms ease;
1157
+ }
1158
+ .fournisseur:hover { filter: brightness(1.06); }
1159
+ .fournisseur:active { transform: translateY(1px); }
1160
+ .fournisseur:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
1161
+ .fournisseur[disabled] { opacity: 0.55; cursor: default; transform: none; filter: none; }
1162
+ .fournisseur .logo { width: 18px; height: 18px; flex: none; display: block; }
1163
+
1164
+ /* LES COULEURS DE CHAQUE MARQUE, telles qu'elles les publient. Un bouton
1165
+ Google repeint aux couleurs du site devient moins reconnaissable — et un
1166
+ bouton de connexion qu'on ne reconnait pas est un bouton sur lequel on
1167
+ hesite a cliquer. */
1168
+ .fournisseur--google { background: #fff; color: #1f1f1f; border-color: #dadce0; }
1169
+ .fournisseur--facebook { background: #1877f2; color: #fff; }
1170
+
1171
+ .bouton--large { width: 100%; padding: 12px 16px; font-size: 14px; }
1172
+
1173
+ @media (prefers-reduced-motion: reduce) {
1174
+ .fournisseur { transition: none; }
1175
+ }
1176
+
601
1177
  /* ------------------------------------------------------------ CHAMPS ---- */
602
1178
 
603
1179
  .champ { margin-bottom: 16px; }
@@ -612,7 +1188,11 @@ const te = `
612
1188
  text-transform: uppercase; color: var(--texte-doux);
613
1189
  }
614
1190
 
1191
+ /* TOUS les types de champs, pas seulement ceux auxquels on pensait. Un
1192
+ type oublie — « password », « email » — retombe sur le style brut du
1193
+ navigateur : une ligne blanche au milieu d'un panneau sombre. */
615
1194
  input[type="text"], input[type="url"], input[type="number"], input[type="date"],
1195
+ input[type="password"], input[type="email"], input[type="tel"], input[type="search"],
616
1196
  select, textarea {
617
1197
  width: 100%;
618
1198
  padding: 8px 10px;
@@ -677,43 +1257,145 @@ input:focus, select:focus, textarea:focus {
677
1257
  @media (prefers-reduced-motion: reduce) {
678
1258
  * { transition: none !important; animation: none !important; }
679
1259
  }
680
- `, D = "lystech-editeur-hote";
681
- function ae({
1260
+ `, Ce = `
1261
+ /* --------------------------------------------------------- CHOIX -------- */
1262
+
1263
+ /* Quand un meme texte vient de plusieurs cles, on demande laquelle plutot que
1264
+ de deviner — et de modifier la mauvaise sans que personne le voie. */
1265
+ .choix {
1266
+ position: fixed;
1267
+ width: 260px;
1268
+ padding: 12px;
1269
+ border: 1px solid var(--bord);
1270
+ border-radius: 10px;
1271
+ background: var(--fond);
1272
+ box-shadow: 0 14px 40px rgba(0, 0, 0, 0.45);
1273
+ }
1274
+ .choix__titre { margin: 0 0 2px; font-size: 12.5px; font-weight: 650; }
1275
+ .choix__aide { margin: 0 0 10px; font-size: 11.5px; color: var(--texte-doux); }
1276
+ .choix__option {
1277
+ display: flex; flex-direction: column; align-items: flex-start; gap: 2px;
1278
+ width: 100%; margin-bottom: 6px; padding: 7px 9px;
1279
+ border: 1px solid var(--bord); border-radius: 7px;
1280
+ background: var(--fond-clair); color: var(--texte);
1281
+ font: inherit; text-align: left; cursor: pointer;
1282
+ }
1283
+ .choix__option:hover { background: #2a2e37; border-color: var(--accent); }
1284
+ .choix__chemin { font-size: 12px; font-weight: 600; }
1285
+ .choix__ns { font-size: 10.5px; color: var(--texte-doux); }
1286
+
1287
+ /* ------------------------------------------------------- RANGEES -------- */
1288
+
1289
+ .rangee {
1290
+ display: flex; align-items: center; justify-content: space-between; gap: 10px;
1291
+ width: 100%; margin-bottom: 6px; padding: 10px 12px;
1292
+ border: 1px solid var(--bord); border-radius: 8px;
1293
+ background: var(--fond-clair); color: var(--texte);
1294
+ font: inherit; text-align: left; cursor: pointer;
1295
+ }
1296
+ .rangee:hover { background: #2a2e37; border-color: var(--accent); }
1297
+ .rangee__nom { font-size: 13px; font-weight: 600; }
1298
+ .rangee__info { font-size: 11.5px; color: var(--texte-doux); white-space: nowrap; }
1299
+
1300
+ /* ------------------------------------------------------ FLOTTANT -------- */
1301
+
1302
+ /* Un message au-dessus de la barre, pour confirmer sans ouvrir de panneau. */
1303
+ .flottant {
1304
+ position: fixed;
1305
+ left: 50%; bottom: 76px;
1306
+ transform: translateX(-50%);
1307
+ max-width: min(460px, calc(100vw - 24px));
1308
+ }
1309
+ .flottant .message { margin: 0; box-shadow: 0 8px 26px rgba(0,0,0,.4); }
1310
+ `, Ae = `
1311
+ /* ON NE DOIT JAMAIS SE DEMANDER SI ON EST EN MODE EDITION. Une barre en bas
1312
+ se confond avec un bandeau de temoins ; un lisere qui borde tout l'ecran,
1313
+ present sur chaque page, ne se confond avec rien. Il ne prend aucun clic. */
1314
+ .cadre-global {
1315
+ position: fixed;
1316
+ inset: 0;
1317
+ pointer-events: none;
1318
+ border: 2px solid var(--accent);
1319
+ border-radius: 4px;
1320
+ box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.25);
1321
+ opacity: 0.85;
1322
+ }
1323
+
1324
+ /* La sortie est rouge au survol seulement : visible quand on la cherche,
1325
+ discrete le reste du temps — c'est le geste qu'on fait une fois. */
1326
+ .bouton--sortie { color: var(--texte-doux); background: transparent; border-color: transparent; }
1327
+ .bouton--sortie:hover { background: rgba(217, 119, 106, 0.16); color: var(--danger); }
1328
+ `, Se = "lystech-editeur-hote", Ee = "lystech-connexion-hote";
1329
+ function re(n) {
1330
+ document.getElementById(n)?.remove();
1331
+ const t = document.createElement("div");
1332
+ t.id = n, document.body.appendChild(t);
1333
+ const i = t.attachShadow({ mode: "open" }), r = document.createElement("style");
1334
+ r.textContent = ke + Ce + Ae, i.appendChild(r);
1335
+ const a = document.createElement("div");
1336
+ return i.appendChild(a), { hote: t, point: a };
1337
+ }
1338
+ function ae(n, t) {
1339
+ let i = n;
1340
+ return () => {
1341
+ const r = i;
1342
+ i = null, setTimeout(() => {
1343
+ r?.unmount(), t.remove();
1344
+ }, 0);
1345
+ };
1346
+ }
1347
+ function qe({
1348
+ site: n,
1349
+ apiBaseUrl: t,
1350
+ methodes: i,
1351
+ surJeton: r
1352
+ }) {
1353
+ const { hote: a, point: d } = re(Ee), l = ne(d), b = () => o();
1354
+ l.render(
1355
+ /* @__PURE__ */ e(
1356
+ xe,
1357
+ {
1358
+ site: n,
1359
+ apiBaseUrl: t,
1360
+ ...i ? { methodes: i } : {},
1361
+ surJeton: (c) => {
1362
+ o(), r(c);
1363
+ },
1364
+ surFermer: b
1365
+ }
1366
+ )
1367
+ );
1368
+ const o = ae(l, a);
1369
+ return o;
1370
+ }
1371
+ function Ie({
682
1372
  jeton: n,
683
1373
  site: t,
684
- apiBaseUrl: s,
1374
+ apiBaseUrl: i,
685
1375
  pont: r
686
1376
  }) {
687
- document.getElementById(D)?.remove();
688
- const c = document.createElement("div");
689
- c.id = D, document.body.appendChild(c);
690
- const b = c.attachShadow({ mode: "open" }), d = document.createElement("style");
691
- d.textContent = te, b.appendChild(d);
692
- const l = document.createElement("div");
693
- b.appendChild(l);
694
- let e = H(l);
695
- const a = () => {
1377
+ const { hote: a, point: d } = re(Se), l = ne(d), b = () => {
1378
+ try {
1379
+ window.localStorage.setItem("lystech-edit-sortie", "1"), window.localStorage.removeItem("lystech-edit");
1380
+ } catch {
1381
+ }
696
1382
  try {
697
1383
  window.sessionStorage.removeItem("lystech-edit");
698
1384
  } catch {
699
1385
  }
700
1386
  window.location.reload();
701
1387
  };
702
- return e.render(
703
- /* @__PURE__ */ o(
704
- ee,
1388
+ return l.render(
1389
+ /* @__PURE__ */ e(
1390
+ Ne,
705
1391
  {
706
- api: X({ jeton: n, site: t, apiBaseUrl: s, surJetonRefuse: a }),
1392
+ api: de({ jeton: n, site: t, apiBaseUrl: i, surJetonRefuse: b }),
707
1393
  pont: r
708
1394
  }
709
1395
  )
710
- ), () => {
711
- const u = e;
712
- e = null, setTimeout(() => {
713
- u?.unmount(), c.remove();
714
- }, 0);
715
- };
1396
+ ), ae(l, a);
716
1397
  }
717
1398
  export {
718
- ae as monterEditeur
1399
+ qe as monterConnexion,
1400
+ Ie as monterEditeur
719
1401
  };