diff --git a/Cargo.lock b/Cargo.lock
index 3d4332a..b306375 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -479,9 +479,9 @@ dependencies = [
[[package]]
name = "ctutils"
-version = "0.4.2"
+version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d5515a3834141de9eafb9717ad39eea8247b5674e6066c404e8c4b365d2a29e"
+checksum = "38d28fb6aa7dd680b3ffd1a3e64e115c177bdba63c0ae7f9cd48129ff05c4fa0"
dependencies = [
"cmov",
]
@@ -2168,9 +2168,9 @@ checksum = "eec689c0bc40ff2458a5977b6619cb718087084a18e02a131c599b62d05e1a5f"
[[package]]
name = "rustls-webpki"
-version = "0.103.15"
+version = "0.103.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2"
+checksum = "4443b1b6d39d7c663139942cc4558262562d2c84123bb6282ef177009ca8b281"
dependencies = [
"aws-lc-rs",
"ring",
@@ -3235,9 +3235,9 @@ dependencies = [
[[package]]
name = "webpki-root-certs"
-version = "1.0.9"
+version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b96554aa2acc8ccdb7e1c9a58a7a68dd5d13bccc69cd124cb09406db612a1c9b"
+checksum = "e49d0e65abc00c142e8f9428da991da9f1a250c39be97459901eb12b9b49f62a"
dependencies = [
"rustls-pki-types",
]
@@ -3248,14 +3248,14 @@ version = "0.26.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
dependencies = [
- "webpki-roots 1.0.9",
+ "webpki-roots 1.0.11",
]
[[package]]
name = "webpki-roots"
-version = "1.0.9"
+version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7dcd9d09a39985f5344844e66b0c530a33843579125f23e21e9f0f220850f22a"
+checksum = "f5f280bbb2b287bc8e7de7e3852945a0ff50d1bbcb5ed42b6c7a568c546df171"
dependencies = [
"rustls-pki-types",
]
diff --git a/docs/roadmap.md b/docs/roadmap.md
index b6ff7a0..905ffef 100644
--- a/docs/roadmap.md
+++ b/docs/roadmap.md
@@ -91,6 +91,7 @@ Reportés : file d’attente des fusions hors connexion (supprimée, ADR 0041),
| Ricochets, PWA : moins de touchers ([ADR 0068](https://github.com/lunik/EtymoLogique/blob/master/docs/adr/0068-ricochets-moins-de-touchers-pour-decouper-et-assembler.md)) : la lame de découpe arrive, et repart après chaque coupe, sur une jointure tirée au hasard qui n’est jamais une coupe attendue ; *Assembler* envoie la réponse à la seconde brique posée, sans « Valider » ; tests du composant `Assembler` | fait |
| Ricochets, PWA : *Paires* envoie les réponses à la dernière paire reliée, sans « Valider les paires », comme *Découper* et *Assembler* ; la place du numéro de paire est réservée, les colonnes ne se redimensionnent plus à chaque paire reliée ; tests du composant `Paires` | fait |
| « En savoir plus » (I-16) : chemin des langues, relations, transformations, certitude et sources citées ; dépliée depuis la carte du codex (`plus=1`) | fait (Content publie les types de relation et de transformation dans les référentiels) |
+| Vue Réseau (App#91) : la constellation en deux rives (1ʳᵉ case à gauche, 2ᵉ à droite, une bande par fascicule débloqué, ordre alphabétique, rangées de 44 px), dernière découverte en Corail, barre de famille Rosée, antennes chiffrées dans la vue « Tous », famille suivie dans un panneau collé, liste en repli ; calculée côté client (`services/constellation.ts`), sans légendaire ni fascicule verrouillé | fait en local ; ADR et maquette à écrire dans Design |
### Exigence reportée à J6
diff --git a/web/package-lock.json b/web/package-lock.json
index c5f9c8a..1050295 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -1900,9 +1900,9 @@
}
},
"node_modules/@oxc-project/types": {
- "version": "0.151.0",
- "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.151.0.tgz",
- "integrity": "sha512-J1yXrIlNDZVzE3ada310xeAw7nH8yCAyLPuUIsjKatFPmfn5bS1oW+cM+QsGOtVWd5nhSpbwZWx/rue+r5Z+PA==",
+ "version": "0.155.0",
+ "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.155.0.tgz",
+ "integrity": "sha512-SeE8JPwW1xs1tHeNycjUtUBdhorRa8o4jlvjwk49R7/Z291i+4DQa7JJIgOm/TaYQZx+QrPQbVJ/9c8dMIZN8Q==",
"dev": true,
"license": "MIT",
"funding": {
@@ -2279,9 +2279,9 @@
}
},
"node_modules/@rolldown/binding-android-arm-eabi": {
- "version": "1.2.11",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.11.tgz",
- "integrity": "sha512-A5kXfGKvKWWZE0TtPrfsvT+q4Y5d1QG8gGUzpYjGydM+fARM9MuX90PrXYXe0XbsDVgyxxNzHo6giCj90bsFNw==",
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.15.tgz",
+ "integrity": "sha512-aLcgK9gIJ3YRvrrtfSBbRa27F5WrpiTaPulnFpsHPxpUHgFlSgnU4854MHwoRGEBhfRJDWCS2WQ7lIjskE9Olw==",
"cpu": [
"arm"
],
@@ -2296,9 +2296,9 @@
}
},
"node_modules/@rolldown/binding-android-arm64": {
- "version": "1.2.11",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.11.tgz",
- "integrity": "sha512-z6cTycz+iJ4PVkuL4HHW4DfTfoeU/2nqYYuSOrTmH7yHK5Y0LCOnA03V4ZNxavyVaU1oOqUgIg2klN/s+USGOA==",
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.15.tgz",
+ "integrity": "sha512-xD7DdZCrbThKuxNg7ooQmvp07ys4J/pnSEMTG3/OdOWl6daC67m/Q4fL78sRHMxTH/N4fGUbYhcPM0MF5WFHkg==",
"cpu": [
"arm64"
],
@@ -2313,9 +2313,9 @@
}
},
"node_modules/@rolldown/binding-darwin-arm64": {
- "version": "1.2.11",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.11.tgz",
- "integrity": "sha512-jShvqNtP6vDC6/A5JOAzbVV+DkgHqhl/ScVCJEbt+TUY6QYz7YnXcrg3sLtFBniro0f/Ld50ZwCWA6f7KYD1nQ==",
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.15.tgz",
+ "integrity": "sha512-m2WuQ6r0B4OTYxyPpNLtXaMRbRDUbG8YQV2Q3KTdSSK8Th6KHCnC8jVCJt8bvYeSB5WivkkNbc85mKadaSdOxA==",
"cpu": [
"arm64"
],
@@ -2330,9 +2330,9 @@
}
},
"node_modules/@rolldown/binding-darwin-x64": {
- "version": "1.2.11",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.11.tgz",
- "integrity": "sha512-f2i2xiNWq1Z1l2++q2fuhZRdLAT3aqxD6vRNm1RAxpUoBcdqNB3C0s1Bt+K+PbEx2F5F4gQp6hqKkphCY/xF9w==",
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.15.tgz",
+ "integrity": "sha512-5RtnsHM36nodM9WbMy+zip0LGS/G+y5wro5RHrpOlr4ac24+1zSi9kiV2MP1myZeZ/ifEHfulQcWjnAXzc2C2A==",
"cpu": [
"x64"
],
@@ -2347,9 +2347,9 @@
}
},
"node_modules/@rolldown/binding-freebsd-x64": {
- "version": "1.2.11",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.11.tgz",
- "integrity": "sha512-4Ir5FSOKIAMr4r0kExpt1s3bMgzJU3rA45AYOHtQpls0oNeqcYBKrWMlckrYH4KCfGLfkfn1tN1dmZPMVsdXow==",
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.15.tgz",
+ "integrity": "sha512-g3l09pyFqhu+135JKkbkwiKGQmwU5hUMUPJ4VdBADvuqR8d33L6H578rh8m7rtxbdp+VmX/+nzI7nvhSZlzpUQ==",
"cpu": [
"x64"
],
@@ -2364,9 +2364,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm-gnueabihf": {
- "version": "1.2.11",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.11.tgz",
- "integrity": "sha512-/gnRDM+39BROzAN/k1OZjDPnDMcZxB/0EUxKjONO5yVkNEvlsoMDrxGNKgZi/ttFriS2gwlDNzB65pvNbFOXIQ==",
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.15.tgz",
+ "integrity": "sha512-nIe3VugI97nGQtspPxDqA4sXMUpeiocKIP/CqpY/u/vgbT+alX+cVxu1C/oVBPKg4feNTmYovE91v4DgXvXNwQ==",
"cpu": [
"arm"
],
@@ -2381,9 +2381,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-gnu": {
- "version": "1.2.11",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.11.tgz",
- "integrity": "sha512-PFaK8HwvAHbaKbBcDNQihjMKYvFnA5hiENx/l5tphTDz1E0WFp32l0A7aq7lyUwGsRw/xSrNIy/gIK4thrSCrw==",
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.15.tgz",
+ "integrity": "sha512-iTBjXx+B5QSvgI89lJfmqh4wTh8NabR1YZIIN3hNx4zSG0EVfVqkOvLulNpG4251pbd6/IAmZ/LefVk1Y4rPhw==",
"cpu": [
"arm64"
],
@@ -2398,9 +2398,9 @@
}
},
"node_modules/@rolldown/binding-linux-arm64-musl": {
- "version": "1.2.11",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.11.tgz",
- "integrity": "sha512-AskzJUIKRLPxkruR1wLKewGbOw+EYfU/9lOrBFj4AFrEA8hPpKFnODWNu2WLaNs0QNkEb9QIJufmVZZIL/bJlg==",
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.15.tgz",
+ "integrity": "sha512-uN26XOnVR7rqQupG3V9oAG2EGGatWjcJHOeDOHUFCh4TBWmP2tHTFoVN13aYbwfm0aHqJAEmcwhAu6sooIjfqQ==",
"cpu": [
"arm64"
],
@@ -2415,9 +2415,9 @@
}
},
"node_modules/@rolldown/binding-linux-ppc64-gnu": {
- "version": "1.2.11",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.11.tgz",
- "integrity": "sha512-qlUGAheh2yh8afH7QBgx0PrRHN85hKnNd78x8MeMhXivuevgd8vgf6/CstOzmNKY/lLTHvNTrPy98cLnAugzJw==",
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.15.tgz",
+ "integrity": "sha512-9nWkcdd+H+XhaA3fQIwpHnKIrfx/PQ6rO0pivr78Og07tXlUlctBBJoEYLPfhTmCR/QxEVdn6uPjHV5SymPhdw==",
"cpu": [
"ppc64"
],
@@ -2432,9 +2432,9 @@
}
},
"node_modules/@rolldown/binding-linux-s390x-gnu": {
- "version": "1.2.11",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.11.tgz",
- "integrity": "sha512-secpEad+0vCbSfn8upFySkDskv+bGPk3THSDS9Y89yc4rb4kzqHp8Dmyd9BkQW4SnhNXBZCl/6CrO//hZahNJQ==",
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.15.tgz",
+ "integrity": "sha512-Ggh0ciFjLwIusLSLz7LZYEaGdxOAUJXI+Qu5JCbhPJJHEt8vP+IjRATTJheiJsdzzTYgUiHUiw3X1Ea3ZpMBdA==",
"cpu": [
"s390x"
],
@@ -2449,9 +2449,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-gnu": {
- "version": "1.2.11",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.11.tgz",
- "integrity": "sha512-mOVBT3dPpkWm8XBWPmU4bf+U6dYDLeMo/9ojUmis4N0L5uu10qra5vOyngZ7/PSdoE4G9KvRt4bloRxNjLas7A==",
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.15.tgz",
+ "integrity": "sha512-FHg60rS6DBePAYZ9X9F67x+JObFdmgn6tupA1C/a3B+CufFmTD4mX+e8M75tCiAO3foR/6xwVBI0KQiI7sn/rw==",
"cpu": [
"x64"
],
@@ -2466,9 +2466,9 @@
}
},
"node_modules/@rolldown/binding-linux-x64-musl": {
- "version": "1.2.11",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.11.tgz",
- "integrity": "sha512-Is78i9A8Ui4SqcxUwFJ9uMmjDn58IbVTjFWYdQestFEgeuEmHMLGNriXnVJKkwG2YiZjw8cP0zCTyDMdDGtOOg==",
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.15.tgz",
+ "integrity": "sha512-/cvV/7v5VGz/moiz0XKRj2dE8DzsKyhIu1KpOvJGPjRywg3yscON889UGvAe8zfiJLHup7VLjBduoGWi3HusWQ==",
"cpu": [
"x64"
],
@@ -2483,9 +2483,9 @@
}
},
"node_modules/@rolldown/binding-openharmony-arm64": {
- "version": "1.2.11",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.11.tgz",
- "integrity": "sha512-dUCXneZ87INUMyQ0D+C0HrEBNUPNXHaPmU5GTjyKTJEiussw9Kaj5Ln8UztPe4epV/ffvgNBEadksdYhmW6xJA==",
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.15.tgz",
+ "integrity": "sha512-MyzC5Hrv/sm+Z7TSGKP/j8001RO2xQm1zOpCNVL4j0cY/VhBZviludA2YFQ7i4lH6ZAXxQm0lcMdBzM+99mE7w==",
"cpu": [
"arm64"
],
@@ -2500,9 +2500,9 @@
}
},
"node_modules/@rolldown/binding-win32-arm64-msvc": {
- "version": "1.2.11",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.11.tgz",
- "integrity": "sha512-jByxb6qfd+bH1xUd0qnfFnb17i9sWBPY2tOavJ0l3tdr3OTu+Kvtm8cd/JV5nFt657b1VqGltxg9olOEfofXWw==",
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.15.tgz",
+ "integrity": "sha512-+PgYiS+AH5omy6L45ZLxybasauJaj3M8buoT83D+nzPmCayXlxUV9hydhciCKVyIg0B/v0BtXPDE1uGqNwCPpg==",
"cpu": [
"arm64"
],
@@ -2517,9 +2517,9 @@
}
},
"node_modules/@rolldown/binding-win32-x64-msvc": {
- "version": "1.2.11",
- "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.11.tgz",
- "integrity": "sha512-/PzKqzAJ03i19oy2ItPvyvaVjOjBCNnfaJs8yvUdGBKmiESgnrJSQ2awd81QzFbbnAmu7YO9ZnJrDCb9VSJPRA==",
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.15.tgz",
+ "integrity": "sha512-HFZd2QNQYn1JbIi+Hpd7H+r/lkWxcfIu28nirZ6eCn2LafuvmExMlb/P96Sfx5tf7pPArw39IdhmCF8vmV+NhQ==",
"cpu": [
"x64"
],
@@ -3246,22 +3246,22 @@
}
},
"node_modules/@vitest/mocker": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-5.0.2.tgz",
- "integrity": "sha512-Z5FS00Q1SJHkB35xATsmWGdQ5WA1/0MV3CDjqyv7GavHv1OfOj145MNfHOlHk7QLes21dKFDHr8EO2zvL+9WGA==",
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-5.0.5.tgz",
+ "integrity": "sha512-xLL3lkDegJZw+MGoGaCCsFayDZthGgpAtr3Vziyfc4p7xH89K7KRPcRBBh/kEYm0Aqkt5DtTmkYpBtRV/FrHZg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@jridgewell/trace-mapping": "0.3.31",
- "@vitest/spy": "5.0.2",
+ "@vitest/spy": "5.0.5",
"estree-walker": "^3.0.3",
- "magic-string": "^1.2.3"
+ "magic-string": "^1.4.3"
},
"funding": {
"url": "https://opencollective.com/vitest"
},
"peerDependencies": {
- "msw": "^2.4.9",
+ "msw": "^2.4.9 || ^3.0.0",
"vite": "^6.0.0 || ^7.0.0 || ^8.0.0"
},
"peerDependenciesMeta": {
@@ -3274,9 +3274,9 @@
}
},
"node_modules/@vitest/spy": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-5.0.2.tgz",
- "integrity": "sha512-Ijc7T1nT9efNb5LxvjaBrEqw3f/QwUv5EE0nKqZxgqsaV/FxAAZ8baGylA8X/Z2oS4Lp+K74Jr6dTJsDKxJDeg==",
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-5.0.5.tgz",
+ "integrity": "sha512-lwJRExuH417257Q5wv9QYugN9IMJkoxcrKrYxGPQkBzl7wlNpTUxD/5yNX4ESKVUIShKPgkGchYPFMWOOk0wzw==",
"dev": true,
"license": "MIT",
"funding": {
@@ -3672,9 +3672,9 @@
"license": "CC-BY-4.0"
},
"node_modules/chai": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz",
- "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==",
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/chai/-/chai-6.3.0.tgz",
+ "integrity": "sha512-XWAtwJ6OHO+tj0EKCs0Y2UamnyOxseZWltU4x2U2wh8g4AigdjwvtUjvLP2tqkA/avxHEtzxNaqGq/YGNwckKg==",
"dev": true,
"license": "MIT",
"engines": {
@@ -5670,9 +5670,9 @@
}
},
"node_modules/magic-string": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.2.tgz",
- "integrity": "sha512-vG+rjFRj1PqdIBozIxAGMjPlOhaVe+GXpbttY/iSK7rGcJRMlwNJO7dcUwmUqkymsFLJiNGI06t4D7Fr7yRC9g==",
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.4.3.tgz",
+ "integrity": "sha512-z12OxmaPGE0F4xlpGdjuAUckipLpQlTAuAmyGhNoD7ODpYUzvDfvtxUbjM/jwznyP178oju/KDdyi220wNJ0RQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5737,9 +5737,9 @@
"license": "MIT"
},
"node_modules/nanoid": {
- "version": "3.3.19",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.19.tgz",
- "integrity": "sha512-Y2tUNy4ouw6tq5oDSKeQYGOyhkUBhNOcGV/02KC+6kd9eDGqdZd++mjMiIDilrBYvjEnCYvVtsuHCuP+okSfug==",
+ "version": "3.3.20",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.20.tgz",
+ "integrity": "sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==",
"dev": true,
"funding": [
{
@@ -5810,9 +5810,9 @@
}
},
"node_modules/obug": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/obug/-/obug-2.2.1.tgz",
- "integrity": "sha512-XrsrhT5sybtKI6wakr2SPOlGZWWYbUXZ7a0jT8/QOeAPau+1X/bSegNe5YR75oJmEZQbKningirmGOEJCIk61Q==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/obug/-/obug-3.0.0.tgz",
+ "integrity": "sha512-5vvB5+W7ePv+p3uqxi+RcW1XAzLW0/hxt3/4X4Lc4qHudzOhmBiBwOY6DRob4WnanAEGvNcLjF+KNOufrUoEQw==",
"dev": true,
"funding": [
"https://github.com/sponsors/sxzz",
@@ -6025,9 +6025,9 @@
}
},
"node_modules/postcss": {
- "version": "8.5.28",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.28.tgz",
- "integrity": "sha512-RRuzqDtt5Y9h3quz5hWhK+TPnsmVs6WwSU6LkJMeY4HstUEDuYTG8UJSdawMRzmzAtV+KEoG8N3Qg2qLy5vM/A==",
+ "version": "8.5.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.31.tgz",
+ "integrity": "sha512-YUbWYCgErwnMAVkjUnYa+KlMBzGpHwiIt/DE7f0G33AuX2LH9UcTk6KgWxd3zRU+pN3u/C+Xl3EnMLM4Hea7Sg==",
"dev": true,
"funding": [
{
@@ -6045,9 +6045,9 @@
],
"license": "MIT",
"dependencies": {
- "nanoid": "^3.3.18",
+ "nanoid": "^3.3.20",
"picocolors": "^1.1.1",
- "source-map-js": "^1.2.1"
+ "source-map-js": "^1.2.2"
},
"engines": {
"node": "^10 || ^12 || >=14"
@@ -6270,13 +6270,13 @@
}
},
"node_modules/rolldown": {
- "version": "1.2.11",
- "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.11.tgz",
- "integrity": "sha512-qpSwIyz0jHQq5qXBTNxFmE6664rJ7O+4TvPFOiOaBSrz8IOHc1koKKSqTM2H6u1UG1+TveuC6vaDHKXFOvb1Kw==",
+ "version": "1.2.15",
+ "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.15.tgz",
+ "integrity": "sha512-6odND+fel5zVw3I4Yc2e69gvguDnX0CAAGiNDZSq4ik5WUcaLrkD2GLuog0XcODbor31hZ5ayEMgVDno+KPV5g==",
"dev": true,
"license": "MIT",
"dependencies": {
- "@oxc-project/types": "=0.151.0",
+ "@oxc-project/types": "=0.155.0",
"@rolldown/pluginutils": "^1.0.0"
},
"bin": {
@@ -6286,21 +6286,21 @@
"node": "^20.19.0 || >=22.12.0"
},
"optionalDependencies": {
- "@rolldown/binding-android-arm-eabi": "1.2.11",
- "@rolldown/binding-android-arm64": "1.2.11",
- "@rolldown/binding-darwin-arm64": "1.2.11",
- "@rolldown/binding-darwin-x64": "1.2.11",
- "@rolldown/binding-freebsd-x64": "1.2.11",
- "@rolldown/binding-linux-arm-gnueabihf": "1.2.11",
- "@rolldown/binding-linux-arm64-gnu": "1.2.11",
- "@rolldown/binding-linux-arm64-musl": "1.2.11",
- "@rolldown/binding-linux-ppc64-gnu": "1.2.11",
- "@rolldown/binding-linux-s390x-gnu": "1.2.11",
- "@rolldown/binding-linux-x64-gnu": "1.2.11",
- "@rolldown/binding-linux-x64-musl": "1.2.11",
- "@rolldown/binding-openharmony-arm64": "1.2.11",
- "@rolldown/binding-win32-arm64-msvc": "1.2.11",
- "@rolldown/binding-win32-x64-msvc": "1.2.11"
+ "@rolldown/binding-android-arm-eabi": "1.2.15",
+ "@rolldown/binding-android-arm64": "1.2.15",
+ "@rolldown/binding-darwin-arm64": "1.2.15",
+ "@rolldown/binding-darwin-x64": "1.2.15",
+ "@rolldown/binding-freebsd-x64": "1.2.15",
+ "@rolldown/binding-linux-arm-gnueabihf": "1.2.15",
+ "@rolldown/binding-linux-arm64-gnu": "1.2.15",
+ "@rolldown/binding-linux-arm64-musl": "1.2.15",
+ "@rolldown/binding-linux-ppc64-gnu": "1.2.15",
+ "@rolldown/binding-linux-s390x-gnu": "1.2.15",
+ "@rolldown/binding-linux-x64-gnu": "1.2.15",
+ "@rolldown/binding-linux-x64-musl": "1.2.15",
+ "@rolldown/binding-openharmony-arm64": "1.2.15",
+ "@rolldown/binding-win32-arm64-msvc": "1.2.15",
+ "@rolldown/binding-win32-x64-msvc": "1.2.15"
}
},
"node_modules/rollup": {
@@ -6656,9 +6656,9 @@
}
},
"node_modules/std-env": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz",
- "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.3.0.tgz",
+ "integrity": "sha512-OtU/EgQ1kIm5KwqQpBC6ZEMXrZRui11w8zgfTWp8cdO9B8OaPsbA8bTHO2P+HNo1VlUTGMVBwPhydu6poeXiag==",
"dev": true,
"license": "MIT"
},
@@ -6890,9 +6890,9 @@
}
},
"node_modules/tinybench": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-6.2.0.tgz",
- "integrity": "sha512-78U2TlB2CnVenajOFzf3BKSm0J6oz5L0NV7g32LCPccvYc0lbWvys4d3uUUCS2B1N8PAf2+aekR8i1KbC3HO7Q==",
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-6.2.2.tgz",
+ "integrity": "sha512-nIZ2N2dFpjBsg2hgitKu7mA+FvsIJuGJOwysRngmVRRmWgR/UyPjwJj8c/fT/dhm8EkHnF5EOogRf+0Z2qrimA==",
"dev": true,
"license": "MIT",
"engines": {
@@ -7229,16 +7229,16 @@
"license": "MIT"
},
"node_modules/vite": {
- "version": "8.3.1",
- "resolved": "https://registry.npmjs.org/vite/-/vite-8.3.1.tgz",
- "integrity": "sha512-/bvH9E9tmCXRGp2uXY3WbOldqpTwFkbha/8ANaEQ6VkxhH60KyqLwgZq6lG2y+4uT55x9+9eUHMpQ7uGnOCKjA==",
+ "version": "8.3.5",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-8.3.5.tgz",
+ "integrity": "sha512-z1YpjieJ9g0ebTmQpLBv/oq9E3F9EIlOe+7LahW8SrE3LTiG3udBRUXQOlYXP9b+IC2q2phHeVxj9xGlw34OEQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"lightningcss": "^1.33.0",
"picomatch": "^4.0.7",
- "postcss": "^8.5.28",
- "rolldown": "~1.2.9",
+ "postcss": "^8.5.30",
+ "rolldown": "~1.2.14",
"tinyglobby": "^0.2.17"
},
"bin": {
@@ -7255,7 +7255,7 @@
},
"peerDependencies": {
"@types/node": "^20.19.0 || >=22.12.0",
- "@vitejs/devtools": "^0.7.1",
+ "@vitejs/devtools": "^0.7.1 || ^0.8.0",
"esbuild": "^0.27.0 || ^0.28.0",
"jiti": ">=1.21.0",
"less": "^4.0.0",
@@ -7338,25 +7338,25 @@
}
},
"node_modules/vitest": {
- "version": "5.0.2",
- "resolved": "https://registry.npmjs.org/vitest/-/vitest-5.0.2.tgz",
- "integrity": "sha512-7MQrx9pDv5aHiUcovIb/70Ys3tgtkUVgCtledvKdCmEO+/1Dicq5ZqoSxOW034m03oqC+oHOKui2dM6qtMLoJg==",
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/vitest/-/vitest-5.0.5.tgz",
+ "integrity": "sha512-cPODOMF8YnkiiYtDdHo6n4wWmBrOBBbOIYH2d33M4l3CdNn72h+qMmO6uXffUN6A5AZFXNND/d+krS9mgkXRfg==",
"dev": true,
"license": "MIT",
"dependencies": {
"@types/chai": "^5.2.2",
- "@vitest/mocker": "5.0.2",
- "chai": "^6.2.2",
+ "@vitest/mocker": "5.0.5",
+ "chai": "^6.3.0",
"es-module-lexer": "^2.3.2",
"expect-type": "^1.4.0",
- "magic-string": "^1.2.3",
- "obug": "^2.1.4",
+ "magic-string": "^1.4.3",
+ "obug": "^3.0.0",
"picomatch": "^4.0.7",
- "std-env": "^4.2.0",
- "tinybench": "^6.1.4",
- "tinyexec": "^1.3.0",
+ "std-env": "^4.3.0",
+ "tinybench": "^6.2.2",
+ "tinyexec": "^1.3.1",
"tinyglobby": "^0.2.17",
- "why-is-node-running": "^3.2.1"
+ "why-is-node-running": "3.2.1"
},
"bin": {
"vitest": "vitest.mjs"
@@ -7371,12 +7371,12 @@
"@edge-runtime/vm": "*",
"@opentelemetry/api": "^1.9.0",
"@types/node": "^22.0.0 || >=24.0.0",
- "@vitest/browser-playwright": "5.0.2",
- "@vitest/browser-preview": "5.0.2",
+ "@vitest/browser-playwright": "5.0.5",
+ "@vitest/browser-preview": "5.0.5",
"@vitest/browser-webdriverio": "^5.0.0-beta.5 || >=5.0.0",
- "@vitest/coverage-istanbul": "5.0.2",
- "@vitest/coverage-v8": "5.0.2",
- "@vitest/ui": "5.0.2",
+ "@vitest/coverage-istanbul": "5.0.5",
+ "@vitest/coverage-v8": "5.0.5",
+ "@vitest/ui": "5.0.5",
"happy-dom": "*",
"jsdom": "*",
"vite": "^6.4.0 || ^7.0.0 || ^8.0.0"
@@ -7574,9 +7574,9 @@
}
},
"node_modules/why-is-node-running": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-3.2.2.tgz",
- "integrity": "sha512-NKUzAelcoCXhXL4dJzKIwXeR8iEVqsA0Lq6Vnd0UXvgaKbzVo4ZTHROF2Jidrv+SgxOQ03fMinnNhzZATxOD3A==",
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-3.2.1.tgz",
+ "integrity": "sha512-Tb2FUhB4vUsGQlfSquQLYkApkuPAFQXGFzxWKHHumVz2dK+X1RUm/HnID4+TfIGYJ1kTcwOaCk/buYCEJr6YjQ==",
"dev": true,
"license": "MIT",
"bin": {
diff --git a/web/src/codex.css b/web/src/codex.css
index 1adbe33..1f44689 100644
--- a/web/src/codex.css
+++ b/web/src/codex.css
@@ -571,3 +571,74 @@
.cb-fasc-btn.is-locked .jk-mini { opacity: 0.45; }
.cb-fasc-verrou { display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 600; line-height: 1.3; }
.cb-fasc-verrou .ic { flex: none; width: 16px; height: 16px; }
+
+/* ---------- Codex : vue Réseau, la constellation en deux rives (App#91) ---------- */
+.cst { display: grid; gap: 12px; min-width: 0; }
+.cst-choix { display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between; gap: 0 24px; min-width: 0; }
+.cst-choix .cb-views { margin-bottom: 0; }
+.cst-vues { flex: 1 1 260px; min-width: 0; }
+.cst .cb-note { margin: 0; }
+.cst-mot { font-family: var(--serif); }
+/* Cadre à l'échelle 1 : il défile en hauteur avec la page, en largeur dans son propre cadre. */
+.cst-cadre { min-width: 0; overflow-x: auto; overscroll-behavior-x: contain; border: 1.5px solid var(--line); border-radius: 14px; background: var(--paper); }
+.cst-svg { display: block; }
+.cst-filet { fill: none; stroke: var(--line-strong); stroke-opacity: 0.35; stroke-width: 1; }
+.cst-titre { fill: var(--ink-2); font-family: var(--mono); font-size: 12px; font-weight: 700; }
+/* Courbes : neutres ; la dernière découverte en Corail (nouveauté) ; la famille suivie en Encre. */
+.cst-lien { fill: none; stroke: var(--ink-3); stroke-width: 1; }
+.cst-lien.is-dernier { stroke: var(--c-action); stroke-width: 2.5; }
+.cst-antenne { fill: none; stroke: var(--ink-3); stroke-width: 1.5; stroke-linecap: round; }
+.cst-compte { fill: var(--ink-2); font-family: var(--mono); font-size: 12px; font-variant-numeric: tabular-nums; }
+.has-focus :is(.cst-lien, .cst-antenne) { stroke: var(--line); }
+.has-focus .cst-compte { opacity: 0.45; }
+.has-focus .cst-lien.is-famille { stroke: var(--ink); stroke-width: 2.5; }
+/* Briques : toute la rangée est la cible. */
+.cst-n { cursor: pointer; outline: none; }
+.cst-cible { fill: transparent; stroke: none; }
+.cst-n:hover .cst-cible { fill: color-mix(in srgb, var(--ink) 6%, transparent); }
+.cst-n:focus-visible .cst-cible { stroke: var(--ink); stroke-width: 2; }
+.cst-ombre { fill: var(--pop-shadow); }
+.cst-brique { fill: var(--c-prefix); stroke: var(--fixed-ink); stroke-width: 1.5; }
+.cst-brique[data-kind="suffixe"] { fill: var(--c-suffix); }
+/* Cartes de mot neutres : Encre sur Crème, de jour comme de nuit (comme .brick). */
+.cst-brique[data-kind="mot"] { fill: #fffbf3; }
+.cst-etiquette { fill: var(--fixed-ink); font-family: var(--serif); font-weight: 700; pointer-events: none; }
+.cst-rail { fill: var(--paper-2); stroke: var(--ink-3); stroke-width: 0.75; }
+.cst-part { fill: var(--c-family); }
+.cst-cpt { fill: var(--ink-2); font-family: var(--mono); font-size: 12px; font-variant-numeric: tabular-nums; pointer-events: none; }
+.cst-n.is-focus .cst-brique { stroke-width: 3; }
+.cst-n.is-focus .cst-cible { fill: color-mix(in srgb, var(--ink) 8%, transparent); }
+/* Hors famille : la brique pâlit, son étiquette reste lisible (Encre fixe sur couleur vive). */
+.cst-n.is-loin .cst-brique { fill-opacity: 0.45; stroke-opacity: 0.45; }
+.cst-n.is-loin :is(.cst-ombre, .cst-rail, .cst-part) { opacity: 0.45; }
+.cst-n.is-loin .cst-cpt { fill: var(--ink-3); }
+/* Panneau de la famille suivie : collé en bas de l'écran, repliable. */
+.cst-panneau { position: sticky; bottom: 12px; z-index: 2; display: grid; gap: 8px; padding: 6px 10px; border: 1.5px solid var(--line-strong); border-radius: 14px; background: var(--cream); box-shadow: 4px 4px 0 var(--pop-shadow); }
+.cst-tete { display: flex; align-items: center; gap: 8px; min-width: 0; }
+.cst-deplier { display: flex; flex: 1 1 auto; align-items: center; gap: 8px; min-width: 0; min-height: 48px; padding: 4px 6px; border: 0; border-radius: 10px; background: transparent; color: var(--ink); cursor: pointer; font: inherit; font-size: 14px; text-align: left; }
+.cst-deplier:hover { background: color-mix(in srgb, var(--ink) 6%, transparent); }
+.cst-deplier:focus-visible, .cst-partenaire:focus-visible, .cst-lien-mot:focus-visible { outline: 2px solid var(--ink); outline-offset: 1px; }
+.cst-resume-fam { display: flex; flex: 1 1 auto; flex-wrap: wrap; align-items: center; gap: 0 8px; min-width: 0; }
+.cst-glose { font-family: var(--serif); }
+.cst-nb { color: var(--ink-2); font-family: var(--mono); font-size: 12px; }
+.cst-chevron { flex: none; width: 8px; height: 8px; margin: 0 6px; border-right: 2px solid var(--ink-3); border-bottom: 2px solid var(--ink-3); transform: rotate(45deg); transition: transform var(--dur-rapide) var(--ease-out); }
+.cst-deplier[aria-expanded="true"] .cst-chevron { transform: rotate(-135deg); }
+.cst-fermer { flex: none; min-height: 44px; padding: 6px 12px; }
+.cst-mots { display: flex; flex-wrap: wrap; gap: 0 14px; max-height: 38vh; margin: 0; padding: 0 0 4px; overflow-y: auto; list-style: none; }
+.cst-mots li { display: inline-flex; align-items: center; gap: 2px; }
+.cst-lien-mot { min-height: 44px; padding: 0 4px; border: 0; border-radius: 8px; background: transparent; color: var(--ink); cursor: pointer; font-family: var(--serif); font-size: 15px; font-style: italic; text-decoration: underline; text-decoration-color: var(--line-strong); text-underline-offset: 3px; }
+.cst-partenaire { display: inline-grid; place-items: center; min-width: 44px; min-height: 44px; padding: 0 6px; border: 0; border-radius: 8px; background: transparent; cursor: pointer; }
+.cst-partenaire:hover .bchip { box-shadow: 3px 3px 0 var(--pop-shadow); }
+/* Liste en repli, qui sert aussi aux lecteurs d'écran. */
+.cst-liste { display: grid; gap: 18px; }
+.cst-bande h3 { margin-bottom: 10px; padding-bottom: 6px; border-bottom: 1.5px solid var(--line); font-family: var(--mono); font-size: 12px; letter-spacing: 0.08em; text-transform: uppercase; }
+.cst-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 12px 24px; }
+.cst-familles { display: grid; align-content: start; gap: 10px; margin: 0; padding: 0; list-style: none; }
+.cst-fam-tete { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; }
+.cst-barre { display: inline-block; width: 72px; height: 7px; overflow: hidden; border: 1px solid var(--ink-3); border-radius: 999px; background: var(--paper-2); }
+.cst-barre i { display: block; height: 100%; background: var(--c-family); }
+.cst-num { font-family: var(--mono); font-size: 12px; font-variant-numeric: tabular-nums; }
+.cst-mots-liste { margin: 0; color: var(--ink-2); }
+.cst-mots-liste .cst-lien-mot { min-height: 32px; font-size: 14px; }
+:root[data-mouvement="reduit"] .cst-chevron { transition: none; }
+@media (prefers-reduced-motion: reduce) { .cst-chevron { transition: none; } }
diff --git a/web/src/composants/Codex.tsx b/web/src/composants/Codex.tsx
index 40a58c7..e582e02 100644
--- a/web/src/composants/Codex.tsx
+++ b/web/src/composants/Codex.tsx
@@ -1,4 +1,4 @@
-import { Fragment, cloneElement, createContext, useContext, useEffect, useLayoutEffect, useRef, useState } from 'react'
+import { Fragment, cloneElement, createContext, useContext, useEffect, useLayoutEffect, useMemo, useRef, useState } from 'react'
import {
CERTITUDES,
@@ -30,6 +30,8 @@ import { bandeau } from './bandeau'
import { FormeRarete } from './Rarete'
import { Filet, Galet } from './Maitrise'
import { Jaquette, SelecteurFascicules, TitreFascicule } from './Fascicules'
+import { Constellation } from './Constellation'
+import { useDeblocage } from '../services/deblocage'
type Tri = TriCodex
const TRIS: [Tri, string][] = [
@@ -53,6 +55,7 @@ const VUES: [VueCodex, string][] = [
['tout', 'Tout'],
['recentes', 'Récentes'],
['familles', 'Familles'],
+ ['reseau', 'Réseau'],
['cabinet', 'Cabinet'],
]
@@ -947,6 +950,12 @@ export function Codex({ entrees, jeu, joursDeJeu, nouvelles, onVue, vue, onChang
const lesFamilles = familles(entrees, jeu)
const aCompleter = lesFamilles.filter((f) => f.trouves < f.mots.length)
const stats = cabinet(entrees, jeu)
+ // Vue Réseau : seuls les fascicules débloqués y entrent (ADR 0069) ; sans contexte, tous les parus.
+ const deblocage = useDeblocage()
+ const debloques = useMemo(
+ () => new Set(jeu.fascicules.filter((f) => !deblocage || deblocage.debloques.has(f.manifeste.id)).map((f) => f.numero)),
+ [jeu, deblocage],
+ )
// Précédente et suivante : l'ordre de ce qui est affiché.
const sequence = enRecherche
@@ -955,7 +964,7 @@ export function Codex({ entrees, jeu, joursDeJeu, nouvelles, onVue, vue, onChang
? dernieres
: vue.vue === 'familles'
? lesFamilles.flatMap((f) => f.mots)
- : vue.vue === 'cabinet'
+ : vue.vue === 'cabinet' || vue.vue === 'reseau'
? []
: visibles.filter((e) => !replie(e))
@@ -1024,7 +1033,7 @@ export function Codex({ entrees, jeu, joursDeJeu, nouvelles, onVue, vue, onChang
>
) : (
<>
- Vue {{ tout: 'globale', familles: 'des familles', cabinet: 'du cabinet' }[vue.vue]}
+ Vue {{ tout: 'globale', familles: 'des familles', reseau: 'en réseau', cabinet: 'du cabinet' }[vue.vue]}
>
)}
@@ -1141,6 +1150,8 @@ export function Codex({ entrees, jeu, joursDeJeu, nouvelles, onVue, vue, onChang
))}
)
+ ) : vue.vue === 'reseau' ? (
+
+ {vueValide === 'tous' ? `${pluriel(mots.length, 'mot')} trouvé${mots.length > 1 ? 's' : ''}` : `${mots.length} sur ${totalVue} mots ${ou}`} · {pluriel(nbBriques, 'brique')}. + {dernier && ( + <> + {' '} + Dernière découverte : {dernier.libelle}. + > + )} +
+ + {mots.length === 0 ? ( +{vide}
++ {siens.map((m, i) => ( + + {i > 0 && ', '} + + + ))} +
+