odoro 1.0.9 → 2.0.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 +94 -0
- package/client.d.ts +90 -16
- package/dist/build-LZAUDJST.js +5 -0
- package/dist/{chunk-34RGOZFA.js → chunk-4D56Z7G3.js} +49 -50
- package/dist/{chunk-JMEHF3KN.js → chunk-7ZB5MAM6.js} +4 -4
- package/dist/{chunk-LHZGX5ML.js → chunk-OMHEQVIW.js} +295 -160
- package/dist/{chunk-3SZIN6VG.js → chunk-P3DJITWE.js} +10 -10
- package/dist/{chunk-ZVL7EXJO.js → chunk-PRWVZ2SM.js} +22 -14
- package/dist/chunk-Q2KCMTB5.js +741 -0
- package/dist/chunk-QOVBLN7A.js +241 -0
- package/dist/chunk-WWTDEV4Y.js +604 -0
- package/dist/cli.d.ts +12 -13
- package/dist/cli.js +84 -63
- package/dist/{commands-4JRBD55Z.js → commands-EUGVLQWL.js} +44 -45
- package/dist/{commands-AHMXBWQQ.js → commands-GYA7NTCX.js} +124 -124
- package/dist/{create-CYVSVDAD.js → create-QX5LEWMS.js} +158 -154
- package/dist/index.d.ts +603 -151
- package/dist/index.js +6 -6
- package/dist/{package-EIDLKAA6.js → package-T4Z7OBOH.js} +5 -5
- package/dist/preview-P4WY5GEY.js +4 -0
- package/dist/registry/index.d.ts +75 -76
- package/dist/registry/index.js +1 -1
- package/dist/{server-4UGN3SFS.js → server-2WP562EV.js} +3 -3
- package/package.json +5 -5
- package/templates/react-ts/README.md +71 -35
- package/templates/react-ts/_env.example +9 -0
- package/templates/react-ts/_variants/with-engine/src/background.tsx +118 -0
- package/templates/react-ts/_variants/without-libs/src/App.tsx +380 -0
- package/templates/react-ts/_variants/without-libs/src/background.tsx +24 -0
- package/templates/react-ts/_variants/without-libs/src/entry-server.tsx +39 -0
- package/templates/react-ts/_variants/without-libs/src/main.tsx +26 -0
- package/templates/{react-ts-server/_variantes/sans-libs/client → react-ts/_variants/without-libs}/src/styles.css +137 -137
- package/templates/react-ts/{_variantes/sans-routeur → _variants/without-router}/src/App.tsx +141 -141
- package/templates/react-ts/_variants/without-router/src/entry-server.tsx +39 -0
- package/templates/react-ts/index.html +4 -4
- package/templates/react-ts/odoro.config.ts +5 -0
- package/templates/react-ts/src/App.tsx +219 -209
- package/templates/react-ts/src/background.tsx +66 -0
- package/templates/react-ts/src/entry-server.tsx +85 -0
- package/templates/react-ts/src/main.tsx +13 -4
- package/templates/react-ts/src/router.tsx +65 -45
- package/templates/react-ts/src/styles.css +5 -5
- package/templates/react-ts-server/Dockerfile +9 -9
- package/templates/react-ts-server/README.md +97 -45
- package/templates/react-ts-server/_env.example +31 -33
- package/templates/react-ts-server/_variants/with-engine/client/src/background.tsx +118 -0
- package/templates/react-ts-server/_variants/without-libs/client/src/App.tsx +380 -0
- package/templates/react-ts-server/_variants/without-libs/client/src/background.tsx +24 -0
- package/templates/react-ts-server/_variants/without-libs/client/src/entry-server.tsx +39 -0
- package/templates/react-ts-server/_variants/without-libs/client/src/main.tsx +26 -0
- package/templates/{react-ts/_variantes/sans-libs → react-ts-server/_variants/without-libs/client}/src/styles.css +137 -137
- package/templates/react-ts-server/{_variantes/sans-routeur → _variants/without-router}/client/src/App.tsx +141 -141
- package/templates/react-ts-server/_variants/without-router/client/src/entry-server.tsx +39 -0
- package/templates/react-ts-server/client/index.html +4 -4
- package/templates/react-ts-server/client/src/App.tsx +228 -210
- package/templates/react-ts-server/client/src/account.tsx +267 -0
- package/templates/react-ts-server/client/src/auth.tsx +139 -0
- package/templates/react-ts-server/client/src/background.tsx +66 -0
- package/templates/react-ts-server/client/src/entry-server.tsx +92 -0
- package/templates/react-ts-server/client/src/main.tsx +17 -5
- package/templates/react-ts-server/client/src/router.tsx +77 -45
- package/templates/react-ts-server/client/src/styles.css +5 -5
- package/templates/react-ts-server/odoro.config.ts +7 -4
- package/templates/react-ts-server/package.json +2 -0
- package/templates/react-ts-server/scripts/dev.mjs +14 -14
- package/templates/react-ts-server/server/src/main.ts +119 -45
- package/templates/react-ts-server/server/src/modules/auth/index.ts +238 -0
- package/templates/react-ts-server/server/src/modules/auth/password.ts +122 -0
- package/templates/react-ts-server/server/src/modules/auth/store.ts +193 -0
- package/templates/react-ts-server/server/src/modules/health/index.ts +45 -46
- package/dist/build-JFQHODAT.js +0 -5
- package/dist/chunk-22KJTV2R.js +0 -380
- package/dist/chunk-DL3NPC4H.js +0 -113
- package/dist/chunk-TQUJ3MFS.js +0 -268
- package/dist/preview-7DKEAQOQ.js +0 -4
- package/templates/react-ts/_variantes/avec-moteur/src/fond.tsx +0 -118
- package/templates/react-ts/_variantes/sans-libs/src/App.tsx +0 -382
- package/templates/react-ts/_variantes/sans-libs/src/fond.tsx +0 -23
- package/templates/react-ts/_variantes/sans-libs/src/main.tsx +0 -17
- package/templates/react-ts/src/fond.tsx +0 -66
- package/templates/react-ts-server/_variantes/avec-moteur/client/src/fond.tsx +0 -118
- package/templates/react-ts-server/_variantes/sans-libs/client/src/App.tsx +0 -382
- package/templates/react-ts-server/_variantes/sans-libs/client/src/fond.tsx +0 -23
- package/templates/react-ts-server/_variantes/sans-libs/client/src/main.tsx +0 -17
- package/templates/react-ts-server/client/src/fond.tsx +0 -66
package/dist/chunk-TQUJ3MFS.js
DELETED
|
@@ -1,268 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { relative, resolve } from 'path';
|
|
3
|
-
import { build } from 'esbuild';
|
|
4
|
-
|
|
5
|
-
// src/shared/ecouter.ts
|
|
6
|
-
var ESSAIS = 10;
|
|
7
|
-
async function ecouter(server, port, host, essais = ESSAIS) {
|
|
8
|
-
for (let decalage = 0; decalage < essais; decalage += 1) {
|
|
9
|
-
const candidat = port + decalage;
|
|
10
|
-
const pris = await new Promise((resolve2, reject) => {
|
|
11
|
-
const surErreur = (cause) => {
|
|
12
|
-
server.removeListener("listening", surEcoute);
|
|
13
|
-
if (cause.code === "EADDRINUSE") {
|
|
14
|
-
resolve2(true);
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
reject(cause);
|
|
18
|
-
};
|
|
19
|
-
const surEcoute = () => {
|
|
20
|
-
server.removeListener("error", surErreur);
|
|
21
|
-
resolve2(false);
|
|
22
|
-
};
|
|
23
|
-
server.once("error", surErreur);
|
|
24
|
-
server.once("listening", surEcoute);
|
|
25
|
-
server.listen(candidat, host);
|
|
26
|
-
});
|
|
27
|
-
if (!pris) {
|
|
28
|
-
const adresse = server.address();
|
|
29
|
-
const obtenu = typeof adresse === "object" && adresse !== null ? adresse.port : candidat;
|
|
30
|
-
return decalage === 0 ? { port: obtenu } : { port: obtenu, demande: port };
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
throw new Error(
|
|
34
|
-
`[odoro] Aucun port libre entre ${String(port)} et ${String(port + essais - 1)}.`
|
|
35
|
-
);
|
|
36
|
-
}
|
|
37
|
-
var DEPS_PREFIX = "/@deps/";
|
|
38
|
-
var INTERNAL_PREFIX = "/@odoro/";
|
|
39
|
-
var SOURCE_EXTENSIONS = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"];
|
|
40
|
-
var STYLE_EXTENSIONS = [".css"];
|
|
41
|
-
var ASSET_EXTENSIONS = [
|
|
42
|
-
".svg",
|
|
43
|
-
".png",
|
|
44
|
-
".jpg",
|
|
45
|
-
".jpeg",
|
|
46
|
-
".gif",
|
|
47
|
-
".webp",
|
|
48
|
-
".avif",
|
|
49
|
-
".ico",
|
|
50
|
-
".woff",
|
|
51
|
-
".woff2",
|
|
52
|
-
".mp4",
|
|
53
|
-
".webm"
|
|
54
|
-
];
|
|
55
|
-
function depFileName(specifier) {
|
|
56
|
-
return `${specifier.replace(/^@/, "").split("/").join("_")}.js`;
|
|
57
|
-
}
|
|
58
|
-
function isBareSpecifier(specifier) {
|
|
59
|
-
return !specifier.startsWith(".") && !specifier.startsWith("/") && !specifier.startsWith("\\") && !/^[a-zA-Z]:[\\/]/.test(specifier) && !specifier.startsWith("data:") && !specifier.startsWith("http:") && !specifier.startsWith("https:");
|
|
60
|
-
}
|
|
61
|
-
function hasExtension(path, extensions) {
|
|
62
|
-
const clean = path.split("?")[0] ?? path;
|
|
63
|
-
return extensions.some((extension) => clean.toLowerCase().endsWith(extension));
|
|
64
|
-
}
|
|
65
|
-
function fileToUrl(file, root) {
|
|
66
|
-
const relativePath = relative(root, file).split("\\").join("/");
|
|
67
|
-
if (!relativePath.startsWith("..")) return `/${relativePath}`;
|
|
68
|
-
return `/@fs/${file.split("\\").join("/").replace(/^\//, "")}`;
|
|
69
|
-
}
|
|
70
|
-
function urlToFile(url, root) {
|
|
71
|
-
const path = (url.split("?")[0] ?? url).split("#")[0] ?? url;
|
|
72
|
-
if (path.startsWith("/@fs/")) {
|
|
73
|
-
const absolute = path.slice("/@fs/".length);
|
|
74
|
-
return /^[a-zA-Z]:/.test(absolute) ? absolute : `/${absolute}`;
|
|
75
|
-
}
|
|
76
|
-
return resolve(root, `.${path}`);
|
|
77
|
-
}
|
|
78
|
-
function applyAlias(specifier, config) {
|
|
79
|
-
for (const [prefix, target] of Object.entries(config.alias)) {
|
|
80
|
-
if (specifier === prefix || specifier.startsWith(`${prefix}/`)) {
|
|
81
|
-
return resolve(
|
|
82
|
-
config.root,
|
|
83
|
-
target,
|
|
84
|
-
specifier.slice(prefix.length).replace(/^\//, "")
|
|
85
|
-
);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
return specifier;
|
|
89
|
-
}
|
|
90
|
-
function externalizeImports(config, dependencies) {
|
|
91
|
-
return {
|
|
92
|
-
name: "odoro-externalize",
|
|
93
|
-
setup(builder) {
|
|
94
|
-
builder.onResolve({ filter: /.*/ }, async (args) => {
|
|
95
|
-
if (args.kind === "entry-point") return null;
|
|
96
|
-
if (args.pluginData?.resolving === true) {
|
|
97
|
-
return null;
|
|
98
|
-
}
|
|
99
|
-
if (args.path.startsWith(INTERNAL_PREFIX) || args.path.startsWith(DEPS_PREFIX)) {
|
|
100
|
-
return { path: args.path, external: true };
|
|
101
|
-
}
|
|
102
|
-
const aliased = applyAlias(args.path, config);
|
|
103
|
-
const isFileLike = hasExtension(aliased, STYLE_EXTENSIONS) || hasExtension(aliased, ASSET_EXTENSIONS);
|
|
104
|
-
if (isBareSpecifier(aliased) && !isFileLike) {
|
|
105
|
-
return { path: `${DEPS_PREFIX}${depFileName(aliased)}`, external: true };
|
|
106
|
-
}
|
|
107
|
-
const resolved = await builder.resolve(aliased, {
|
|
108
|
-
kind: "import-statement",
|
|
109
|
-
resolveDir: args.resolveDir,
|
|
110
|
-
importer: args.importer,
|
|
111
|
-
pluginData: { resolving: true }
|
|
112
|
-
});
|
|
113
|
-
if (resolved.errors.length > 0) {
|
|
114
|
-
return { path: args.path, external: true };
|
|
115
|
-
}
|
|
116
|
-
dependencies.add(resolved.path);
|
|
117
|
-
const url = fileToUrl(resolved.path, config.root);
|
|
118
|
-
return {
|
|
119
|
-
path: hasExtension(url, ASSET_EXTENSIONS) ? `${url}?import` : url,
|
|
120
|
-
external: true
|
|
121
|
-
};
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
|
-
async function transformModule(file, config, env) {
|
|
127
|
-
const dependencies = /* @__PURE__ */ new Set();
|
|
128
|
-
const result = await build({
|
|
129
|
-
entryPoints: [file],
|
|
130
|
-
bundle: true,
|
|
131
|
-
write: false,
|
|
132
|
-
format: "esm",
|
|
133
|
-
platform: "browser",
|
|
134
|
-
target: "es2022",
|
|
135
|
-
sourcemap: "inline",
|
|
136
|
-
jsx: "automatic",
|
|
137
|
-
jsxDev: true,
|
|
138
|
-
logLevel: "silent",
|
|
139
|
-
absWorkingDir: config.root,
|
|
140
|
-
define: {
|
|
141
|
-
"import.meta.env": JSON.stringify(env),
|
|
142
|
-
"process.env.NODE_ENV": JSON.stringify("development"),
|
|
143
|
-
...config.define
|
|
144
|
-
},
|
|
145
|
-
plugins: [externalizeImports(config, dependencies)]
|
|
146
|
-
});
|
|
147
|
-
const code = result.outputFiles[0]?.text;
|
|
148
|
-
if (code === void 0) {
|
|
149
|
-
throw new Error(`[odoro] La compilation de "${file}" n'a produit aucun code.`);
|
|
150
|
-
}
|
|
151
|
-
return { code, dependencies: [...dependencies] };
|
|
152
|
-
}
|
|
153
|
-
var IDENTIFIANT = /^[A-Za-z_$][A-Za-z0-9_$]*$/;
|
|
154
|
-
var RESERVES = /* @__PURE__ */ new Set([
|
|
155
|
-
"arguments",
|
|
156
|
-
"await",
|
|
157
|
-
"break",
|
|
158
|
-
"case",
|
|
159
|
-
"catch",
|
|
160
|
-
"class",
|
|
161
|
-
"const",
|
|
162
|
-
"continue",
|
|
163
|
-
"debugger",
|
|
164
|
-
"default",
|
|
165
|
-
"delete",
|
|
166
|
-
"do",
|
|
167
|
-
"else",
|
|
168
|
-
"enum",
|
|
169
|
-
"eval",
|
|
170
|
-
"export",
|
|
171
|
-
"extends",
|
|
172
|
-
"false",
|
|
173
|
-
"finally",
|
|
174
|
-
"for",
|
|
175
|
-
"function",
|
|
176
|
-
"if",
|
|
177
|
-
"implements",
|
|
178
|
-
"import",
|
|
179
|
-
"in",
|
|
180
|
-
"instanceof",
|
|
181
|
-
"interface",
|
|
182
|
-
"let",
|
|
183
|
-
"new",
|
|
184
|
-
"null",
|
|
185
|
-
"package",
|
|
186
|
-
"private",
|
|
187
|
-
"protected",
|
|
188
|
-
"public",
|
|
189
|
-
"return",
|
|
190
|
-
"static",
|
|
191
|
-
"super",
|
|
192
|
-
"switch",
|
|
193
|
-
"this",
|
|
194
|
-
"throw",
|
|
195
|
-
"true",
|
|
196
|
-
"try",
|
|
197
|
-
"typeof",
|
|
198
|
-
"var",
|
|
199
|
-
"void",
|
|
200
|
-
"while",
|
|
201
|
-
"with",
|
|
202
|
-
"yield"
|
|
203
|
-
]);
|
|
204
|
-
function wrapJson(json) {
|
|
205
|
-
let valeur;
|
|
206
|
-
try {
|
|
207
|
-
valeur = JSON.parse(json);
|
|
208
|
-
} catch {
|
|
209
|
-
return 'throw new SyntaxError("JSON illisible")';
|
|
210
|
-
}
|
|
211
|
-
const lignes = ["export default " + json.trim()];
|
|
212
|
-
if (typeof valeur === "object" && valeur !== null && !Array.isArray(valeur)) {
|
|
213
|
-
for (const [cle, contenu] of Object.entries(valeur)) {
|
|
214
|
-
if (!IDENTIFIANT.test(cle) || RESERVES.has(cle)) continue;
|
|
215
|
-
lignes.push("export const " + cle + " = " + JSON.stringify(contenu));
|
|
216
|
-
}
|
|
217
|
-
}
|
|
218
|
-
return lignes.join("\n");
|
|
219
|
-
}
|
|
220
|
-
var DESTINATIONS_RESSOURCE = /* @__PURE__ */ new Set([
|
|
221
|
-
"script",
|
|
222
|
-
"style",
|
|
223
|
-
"image",
|
|
224
|
-
"font",
|
|
225
|
-
"audio",
|
|
226
|
-
"video",
|
|
227
|
-
"track",
|
|
228
|
-
"manifest",
|
|
229
|
-
"worker",
|
|
230
|
-
"sharedworker",
|
|
231
|
-
"serviceworker"
|
|
232
|
-
]);
|
|
233
|
-
function estUneRessource(entetes) {
|
|
234
|
-
const destination = entetes["sec-fetch-dest"];
|
|
235
|
-
return typeof destination === "string" && DESTINATIONS_RESSOURCE.has(destination);
|
|
236
|
-
}
|
|
237
|
-
function feuilleDemandee(entetes, url) {
|
|
238
|
-
if (url.includes("?direct")) return true;
|
|
239
|
-
if (entetes["sec-fetch-dest"] === "style") return true;
|
|
240
|
-
const accepte = entetes["accept"];
|
|
241
|
-
return typeof accepte === "string" && accepte.includes("text/css");
|
|
242
|
-
}
|
|
243
|
-
function wrapStyle(url, css) {
|
|
244
|
-
return `const id = ${JSON.stringify(`odoro-style:${url}`)}
|
|
245
|
-
const css = ${JSON.stringify(css)}
|
|
246
|
-
|
|
247
|
-
let element = document.querySelector(\`style[data-odoro-id="\${id}"]\`)
|
|
248
|
-
if (element === null) {
|
|
249
|
-
element = document.createElement('style')
|
|
250
|
-
element.setAttribute('data-odoro-id', id)
|
|
251
|
-
document.head.appendChild(element)
|
|
252
|
-
}
|
|
253
|
-
element.textContent = css
|
|
254
|
-
|
|
255
|
-
import.meta.hot?.accept()
|
|
256
|
-
import.meta.hot?.dispose(() => {
|
|
257
|
-
// La feuille suivante recreera l'element : le retirer evite d'empiler les
|
|
258
|
-
// regles mortes a chaque rechargement.
|
|
259
|
-
element?.remove()
|
|
260
|
-
})
|
|
261
|
-
`;
|
|
262
|
-
}
|
|
263
|
-
function wrapAsset(url) {
|
|
264
|
-
return `export default ${JSON.stringify(url)}
|
|
265
|
-
`;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
export { ASSET_EXTENSIONS, DEPS_PREFIX, INTERNAL_PREFIX, SOURCE_EXTENSIONS, STYLE_EXTENSIONS, applyAlias, depFileName, ecouter, estUneRessource, feuilleDemandee, fileToUrl, hasExtension, isBareSpecifier, transformModule, urlToFile, wrapAsset, wrapJson, wrapStyle };
|
package/dist/preview-7DKEAQOQ.js
DELETED
|
@@ -1,118 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Le fond decoratif, en surface WebGL.
|
|
3
|
-
*
|
|
4
|
-
* Cette version remplace le degrade statique parce que le moteur a ete retenu a
|
|
5
|
-
* la creation. Le reste de la page est inchange : elle place `<Fond />` et ne
|
|
6
|
-
* sait pas ce qu'il y a derriere.
|
|
7
|
-
*
|
|
8
|
-
* ## Ce que le moteur apporte, et qu'un degrade ne peut pas
|
|
9
|
-
*
|
|
10
|
-
* **Un arbitre.** La surface est demandee au gestionnaire du moteur, qui la
|
|
11
|
-
* refuse si le navigateur n'a pas WebGL, si trop de contextes sont deja
|
|
12
|
-
* ouverts, ou si l'appareil ne suivrait pas. Le refus est une valeur, pas une
|
|
13
|
-
* exception : on affiche alors le degrade, et la page tient.
|
|
14
|
-
*
|
|
15
|
-
* **Le mouvement reduit.** Sous cette preference, rien n'est monte : le fond
|
|
16
|
-
* n'apportait que son mouvement, et la carte graphique n'a pas a s'allumer pour
|
|
17
|
-
* un visiteur qui a demande le calme.
|
|
18
|
-
*
|
|
19
|
-
* **Les couleurs du theme.** Les teintes sont lues dans les jetons, pas ecrites
|
|
20
|
-
* dans le nuanceur. Une bascule clair / sombre les relit, et changer
|
|
21
|
-
* `--o-palette-brand-500` repeint le fond sans toucher a ce fichier.
|
|
22
|
-
*
|
|
23
|
-
* ## Pourquoi des styles en ligne
|
|
24
|
-
*
|
|
25
|
-
* Ce fichier est pose quel que soit le reste : un projet qui a decoche les
|
|
26
|
-
* bibliotheques n'a pas les classes `o-*`, et une classe absente ne peint rien
|
|
27
|
-
* — le fond aurait alors une hauteur nulle, sans que rien ne le signale. Les
|
|
28
|
-
* quelques regles de placement sont donc ecrites ou elles sont sures.
|
|
29
|
-
*
|
|
30
|
-
* @module
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
import {
|
|
34
|
-
AURORA_FRAGMENT,
|
|
35
|
-
readTokenColour,
|
|
36
|
-
useMotionState,
|
|
37
|
-
useShaderSurface,
|
|
38
|
-
type ShaderColour,
|
|
39
|
-
} from '@odoro-cli/engine'
|
|
40
|
-
import { useEffect, useMemo, useState, type ReactElement } from 'react'
|
|
41
|
-
|
|
42
|
-
/** Les jetons lus pour teinter la nappe. */
|
|
43
|
-
const TEINTES = ['--o-palette-brand-500', '--o-palette-brand-300', '--o-theme-bg'] as const
|
|
44
|
-
|
|
45
|
-
/** Le degrade servi tant que la surface n'est pas la — ou pour toujours. */
|
|
46
|
-
function Degrade(): ReactElement {
|
|
47
|
-
return (
|
|
48
|
-
<div
|
|
49
|
-
style={{
|
|
50
|
-
position: 'absolute',
|
|
51
|
-
inset: 0,
|
|
52
|
-
opacity: 0.28,
|
|
53
|
-
filter: 'blur(64px)',
|
|
54
|
-
background:
|
|
55
|
-
'radial-gradient(60% 60% at 50% 0%, var(--o-palette-brand-500, #3b82f6), transparent)',
|
|
56
|
-
}}
|
|
57
|
-
/>
|
|
58
|
-
)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
/** Une nappe animee derriere le haut de la page. */
|
|
62
|
-
export function Fond(): ReactElement {
|
|
63
|
-
const { quality, reduced } = useMotionState()
|
|
64
|
-
const [hote, setHote] = useState<HTMLElement | null>(null)
|
|
65
|
-
const [teintes, setTeintes] = useState<readonly ShaderColour[]>([])
|
|
66
|
-
|
|
67
|
-
// Relues quand l'hote apparait et quand le theme bascule — ce dernier cas
|
|
68
|
-
// passe par la politique de mouvement, qui se renouvelle a chaque etat.
|
|
69
|
-
useEffect(() => {
|
|
70
|
-
if (hote === null) return
|
|
71
|
-
setTeintes(TEINTES.map((jeton) => readTokenColour(jeton, hote)))
|
|
72
|
-
}, [hote, reduced, quality])
|
|
73
|
-
|
|
74
|
-
const uniforms = useMemo(() => {
|
|
75
|
-
const [a, b, c] = teintes
|
|
76
|
-
if (a === undefined || b === undefined || c === undefined) return undefined
|
|
77
|
-
// Le fond du theme domine, la marque n'est qu'un reflet : ces trois
|
|
78
|
-
// couleurs vont dans un melange, et deux teintes de marque sur trois
|
|
79
|
-
// donneraient une nappe pleine page plutot qu'un halo.
|
|
80
|
-
return { uColorA: c, uColorB: c, uColorC: a, uSpeed: 0.1, uScale: 1.4, uOctaves: 3 }
|
|
81
|
-
}, [teintes])
|
|
82
|
-
|
|
83
|
-
const { ref, ready, refused } = useShaderSurface<HTMLDivElement>({
|
|
84
|
-
fragment: AURORA_FRAGMENT,
|
|
85
|
-
uniforms: uniforms ?? {},
|
|
86
|
-
name: 'fond-accueil',
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
const repli = !ready || refused !== undefined || uniforms === undefined
|
|
90
|
-
|
|
91
|
-
return (
|
|
92
|
-
<div
|
|
93
|
-
aria-hidden="true"
|
|
94
|
-
ref={(element) => {
|
|
95
|
-
setHote(element)
|
|
96
|
-
ref.current = element
|
|
97
|
-
}}
|
|
98
|
-
style={{
|
|
99
|
-
position: 'absolute',
|
|
100
|
-
insetInline: 0,
|
|
101
|
-
top: 0,
|
|
102
|
-
height: '42rem',
|
|
103
|
-
overflow: 'hidden',
|
|
104
|
-
pointerEvents: 'none',
|
|
105
|
-
// Un fond decoratif se remarque quand on le cherche, pas avant. A
|
|
106
|
-
// pleine intensite la nappe passe devant le titre qu'elle est censee
|
|
107
|
-
// porter ; a un cinquieme, elle le souligne.
|
|
108
|
-
opacity: 0.2,
|
|
109
|
-
// Le bas se dissout dans la page : une surface qui s'arrete net dessine
|
|
110
|
-
// une ligne horizontale que rien ne justifie.
|
|
111
|
-
maskImage: 'linear-gradient(to bottom, black 45%, transparent)',
|
|
112
|
-
WebkitMaskImage: 'linear-gradient(to bottom, black 45%, transparent)',
|
|
113
|
-
}}
|
|
114
|
-
>
|
|
115
|
-
{repli ? <Degrade /> : null}
|
|
116
|
-
</div>
|
|
117
|
-
)
|
|
118
|
-
}
|