@agence-zef/astro 0.10.1 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +11 -0
- package/dist/index.js +15 -1
- package/dist/reveal.d.ts +2 -0
- package/dist/reveal.js +76 -0
- package/package.json +7 -3
- package/styles.css +127 -0
package/dist/index.d.ts
CHANGED
|
@@ -32,6 +32,17 @@ export type ZefOptions = {
|
|
|
32
32
|
checkout?: string;
|
|
33
33
|
confirmation?: string;
|
|
34
34
|
};
|
|
35
|
+
/**
|
|
36
|
+
* Apparitions au défilement (`data-reveal` dans les sections, styles dans `styles.css`) :
|
|
37
|
+
* actives par défaut. `false` les coupe sur tout le site ; `once: false` les rejoue à chaque
|
|
38
|
+
* entrée dans l'écran ; `threshold` (part visible, 0 à 1) et `rootMargin` règlent le moment
|
|
39
|
+
* où elles partent.
|
|
40
|
+
*/
|
|
41
|
+
animations?: false | {
|
|
42
|
+
once?: boolean;
|
|
43
|
+
threshold?: number;
|
|
44
|
+
rootMargin?: string;
|
|
45
|
+
};
|
|
35
46
|
};
|
|
36
47
|
/**
|
|
37
48
|
* Intégration Astro du CMS ZEF (cahier des charges § 10) : route attrape-tout des pages
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,15 @@ export * from "./accounts.js";
|
|
|
7
7
|
export * from "./helpers.js";
|
|
8
8
|
export * from "./seo.js";
|
|
9
9
|
export * from "./shop.js";
|
|
10
|
+
/**
|
|
11
|
+
* Script en tête de page : active les apparitions (`data-zef-reveal` sur `<html>`, avec leurs
|
|
12
|
+
* réglages) avant le premier affichage, sauf dans les routes de l'éditeur (`/__zef/…`). Filet de
|
|
13
|
+
* sécurité : si le script des apparitions n'a pas démarré après 2,5 s, tout redevient visible.
|
|
14
|
+
*/
|
|
15
|
+
function revealHead(animations) {
|
|
16
|
+
const settings = JSON.stringify(animations || {});
|
|
17
|
+
return `(function(){var d=document.documentElement;if(location.pathname.indexOf("/__zef/")===0)return;d.setAttribute("data-zef-reveal",${JSON.stringify(settings)});setTimeout(function(){if(!window.__zefReveal)d.removeAttribute("data-zef-reveal")},2500)})();`;
|
|
18
|
+
}
|
|
10
19
|
const MEDIA_URL = "https://medias.agence-zef.fr";
|
|
11
20
|
/** `rendering` de `zef.config.ts` (lu comme la CLI, avec jiti) ; `static` en cas de doute. */
|
|
12
21
|
async function readRendering(file) {
|
|
@@ -72,7 +81,7 @@ export default function zef(options = {}) {
|
|
|
72
81
|
return {
|
|
73
82
|
name: "@agence-zef/astro",
|
|
74
83
|
hooks: {
|
|
75
|
-
"astro:config:setup": async ({ config, command, injectRoute, updateConfig, addWatchFile, addMiddleware, logger, }) => {
|
|
84
|
+
"astro:config:setup": async ({ config, command, injectRoute, injectScript, updateConfig, addWatchFile, addMiddleware, logger, }) => {
|
|
76
85
|
const root = fileURLToPath(config.root);
|
|
77
86
|
loadZefEnv(root);
|
|
78
87
|
// Redirections du CMS (C-17 : slugs modifiés, pages déplacées, redirections manuelles).
|
|
@@ -104,6 +113,11 @@ export default function zef(options = {}) {
|
|
|
104
113
|
if (config.build.inlineStylesheets === "auto") {
|
|
105
114
|
updateConfig({ build: { inlineStylesheets: "always" } });
|
|
106
115
|
}
|
|
116
|
+
// Apparitions au défilement (`data-reveal`) : actives sauf `animations: false`.
|
|
117
|
+
if (options.animations !== false) {
|
|
118
|
+
injectScript("head-inline", revealHead(options.animations));
|
|
119
|
+
injectScript("page", 'import "@agence-zef/astro/reveal";');
|
|
120
|
+
}
|
|
107
121
|
addWatchFile(join(root, ".env"));
|
|
108
122
|
const layout = join(root, options.layout ?? "src/layouts/Page.astro");
|
|
109
123
|
const configFile = join(root, "zef.config.ts");
|
package/dist/reveal.d.ts
ADDED
package/dist/reveal.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Apparitions au défilement (`data-reveal`), chargé sur chaque page par l'intégration (option
|
|
3
|
+
* `animations`). Le visuel est dans `styles.css` ; ce script pose seulement `data-zef-visible`
|
|
4
|
+
* quand un élément entre dans l'écran, puis `data-zef-done` une fois l'effet joué (l'élément
|
|
5
|
+
* retrouve alors ses propres transitions). Ne fait rien sans `data-zef-reveal` sur `<html>`
|
|
6
|
+
* (aperçu de l'éditeur, animations coupées).
|
|
7
|
+
*
|
|
8
|
+
* Attributs : `data-reveal` (effet), `data-reveal-delay` (ms), `data-reveal-stagger` sur un
|
|
9
|
+
* parent (ses `data-reveal` arrivent en cascade), `data-reveal-scroll` (100 % CSS, ignoré ici).
|
|
10
|
+
*/
|
|
11
|
+
const root = document.documentElement;
|
|
12
|
+
const observed = new WeakSet();
|
|
13
|
+
let observer = null;
|
|
14
|
+
let options = { once: true, threshold: 0.15, rootMargin: "0px 0px -5% 0px" };
|
|
15
|
+
/** Fin de l'effet : l'élément ne porte plus la transition d'apparition. */
|
|
16
|
+
function done(el) {
|
|
17
|
+
const style = getComputedStyle(el);
|
|
18
|
+
const seconds = (v) => Math.max(...v.split(",").map((s) => Number.parseFloat(s) || 0));
|
|
19
|
+
const ms = (seconds(style.transitionDuration) + seconds(style.transitionDelay)) * 1000;
|
|
20
|
+
window.setTimeout(() => el.setAttribute("data-zef-done", ""), ms + 50);
|
|
21
|
+
}
|
|
22
|
+
function onIntersect(entries) {
|
|
23
|
+
// Cascade : rang parmi les éléments d'une même liste qui apparaissent ensemble (un élément
|
|
24
|
+
// qui arrive seul à l'écran, sur mobile, part tout de suite).
|
|
25
|
+
const ranks = new Map();
|
|
26
|
+
for (const { target, isIntersecting } of entries) {
|
|
27
|
+
const el = target;
|
|
28
|
+
if (isIntersecting) {
|
|
29
|
+
const parent = el.closest("[data-reveal-stagger]");
|
|
30
|
+
if (parent) {
|
|
31
|
+
const rank = ranks.get(parent) ?? 0;
|
|
32
|
+
ranks.set(parent, rank + 1);
|
|
33
|
+
el.style.setProperty("--zef-reveal-index", String(rank));
|
|
34
|
+
}
|
|
35
|
+
el.setAttribute("data-zef-visible", "");
|
|
36
|
+
if (options.once) {
|
|
37
|
+
observer?.unobserve(el);
|
|
38
|
+
done(el);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
else if (!options.once) {
|
|
42
|
+
el.removeAttribute("data-zef-visible");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** Observe les nouveaux `data-reveal` de la page (contenu ajouté après le chargement compris). */
|
|
47
|
+
export function scanReveals(scope = document) {
|
|
48
|
+
if (!observer)
|
|
49
|
+
return;
|
|
50
|
+
for (const el of scope.querySelectorAll("[data-reveal]:not([data-reveal-scroll])")) {
|
|
51
|
+
if (observed.has(el))
|
|
52
|
+
continue;
|
|
53
|
+
observed.add(el);
|
|
54
|
+
const delay = Number(el.dataset.revealDelay);
|
|
55
|
+
if (delay > 0)
|
|
56
|
+
el.style.setProperty("--zef-reveal-delay", `${delay}ms`);
|
|
57
|
+
observer.observe(el);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
function start() {
|
|
61
|
+
const raw = root.getAttribute("data-zef-reveal");
|
|
62
|
+
if (raw === null || observer)
|
|
63
|
+
return;
|
|
64
|
+
window.__zefReveal = true;
|
|
65
|
+
try {
|
|
66
|
+
options = { ...options, ...JSON.parse(raw || "{}") };
|
|
67
|
+
}
|
|
68
|
+
catch { }
|
|
69
|
+
observer = new IntersectionObserver(onIntersect, {
|
|
70
|
+
threshold: options.threshold,
|
|
71
|
+
rootMargin: options.rootMargin,
|
|
72
|
+
});
|
|
73
|
+
scanReveals();
|
|
74
|
+
}
|
|
75
|
+
start();
|
|
76
|
+
document.addEventListener("astro:page-load", () => scanReveals());
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agence-zef/astro",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"description": "Intégration Astro du CMS ZEF : routes, rendu des sections, aperçu, composants réutilisables sans style.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -65,6 +65,10 @@
|
|
|
65
65
|
"types": "./dist/ui.d.ts",
|
|
66
66
|
"import": "./dist/ui.js"
|
|
67
67
|
},
|
|
68
|
+
"./reveal": {
|
|
69
|
+
"types": "./dist/reveal.d.ts",
|
|
70
|
+
"import": "./dist/reveal.js"
|
|
71
|
+
},
|
|
68
72
|
"./routes/page-cached.astro": "./components/routes/page-cached.astro",
|
|
69
73
|
"./routes/revalidate.ts": "./components/routes/revalidate.ts"
|
|
70
74
|
},
|
|
@@ -86,8 +90,8 @@
|
|
|
86
90
|
"dependencies": {
|
|
87
91
|
"jiti": "^2.6.1",
|
|
88
92
|
"vanilla-cookieconsent": "3.1.0",
|
|
89
|
-
"@agence-zef/schema": "0.
|
|
90
|
-
"@agence-zef/sdk": "0.
|
|
93
|
+
"@agence-zef/schema": "0.11.0",
|
|
94
|
+
"@agence-zef/sdk": "0.11.0"
|
|
91
95
|
},
|
|
92
96
|
"homepage": "https://agence-zef.fr",
|
|
93
97
|
"scripts": {
|
package/styles.css
CHANGED
|
@@ -686,3 +686,130 @@
|
|
|
686
686
|
flex-basis: 100%;
|
|
687
687
|
}
|
|
688
688
|
}
|
|
689
|
+
|
|
690
|
+
/*
|
|
691
|
+
* Apparitions au défilement (`data-reveal`) : le visuel est ici, en CSS ; le script de
|
|
692
|
+
* l'intégration (`src/reveal.ts`) pose seulement `data-zef-visible` quand l'élément entre dans
|
|
693
|
+
* l'écran. L'état masqué ne s'applique que sous `:root[data-zef-reveal]`, posé en tête de page
|
|
694
|
+
* par l'intégration (option `animations`) : sans JavaScript, dans l'aperçu de l'éditeur ou si le
|
|
695
|
+
* script ne se charge pas, tout reste visible.
|
|
696
|
+
*
|
|
697
|
+
* Réglages par site : les variables `--zef-reveal-*` dans le `:root` du site ; un effet maison
|
|
698
|
+
* se déclare avec les variables `--zef-reveal-from-*` (voir `CLAUDE.md` du kit).
|
|
699
|
+
*/
|
|
700
|
+
:where(:root) {
|
|
701
|
+
--zef-reveal-duration: 0.7s;
|
|
702
|
+
--zef-reveal-easing: cubic-bezier(0.22, 1, 0.36, 1);
|
|
703
|
+
--zef-reveal-distance: 1.5rem;
|
|
704
|
+
--zef-reveal-scale: 0.94;
|
|
705
|
+
--zef-reveal-blur: 8px;
|
|
706
|
+
--zef-reveal-stagger: 80ms;
|
|
707
|
+
--zef-reveal-scroll-range: entry 0% cover 35%;
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
/* Point de départ de chaque effet (fade-up par défaut) */
|
|
711
|
+
:where([data-reveal]) {
|
|
712
|
+
--zef-reveal-from-opacity: 0;
|
|
713
|
+
--zef-reveal-from-translate: 0 var(--zef-reveal-distance);
|
|
714
|
+
--zef-reveal-from-scale: none;
|
|
715
|
+
--zef-reveal-from-filter: none;
|
|
716
|
+
}
|
|
717
|
+
:where([data-reveal="fade"]) {
|
|
718
|
+
--zef-reveal-from-translate: none;
|
|
719
|
+
}
|
|
720
|
+
:where([data-reveal="fade-down"]) {
|
|
721
|
+
--zef-reveal-from-translate: 0 calc(var(--zef-reveal-distance) * -1);
|
|
722
|
+
}
|
|
723
|
+
:where([data-reveal="slide-left"]) {
|
|
724
|
+
--zef-reveal-from-translate: var(--zef-reveal-distance) 0;
|
|
725
|
+
}
|
|
726
|
+
:where([data-reveal="slide-right"]) {
|
|
727
|
+
--zef-reveal-from-translate: calc(var(--zef-reveal-distance) * -1) 0;
|
|
728
|
+
}
|
|
729
|
+
:where([data-reveal="zoom"]) {
|
|
730
|
+
--zef-reveal-from-translate: none;
|
|
731
|
+
--zef-reveal-from-scale: var(--zef-reveal-scale);
|
|
732
|
+
}
|
|
733
|
+
:where([data-reveal="blur"]) {
|
|
734
|
+
--zef-reveal-from-translate: none;
|
|
735
|
+
--zef-reveal-from-filter: blur(var(--zef-reveal-blur));
|
|
736
|
+
}
|
|
737
|
+
:where([data-reveal="clip"]) {
|
|
738
|
+
--zef-reveal-from-opacity: 1;
|
|
739
|
+
--zef-reveal-from-translate: none;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/* Déclenché à l'entrée dans l'écran : transition de l'état de départ à l'état normal */
|
|
743
|
+
:root[data-zef-reveal] [data-reveal]:not([data-reveal-scroll], [data-zef-done]) {
|
|
744
|
+
transition-property: opacity, translate, scale, filter, clip-path;
|
|
745
|
+
transition-duration: var(--zef-reveal-duration);
|
|
746
|
+
transition-timing-function: var(--zef-reveal-easing);
|
|
747
|
+
transition-delay: calc(
|
|
748
|
+
var(--zef-reveal-delay, 0ms) +
|
|
749
|
+
var(--zef-reveal-index, 0) *
|
|
750
|
+
var(--zef-reveal-stagger)
|
|
751
|
+
);
|
|
752
|
+
}
|
|
753
|
+
:root[data-zef-reveal] [data-reveal]:not([data-reveal-scroll], [data-zef-visible]) {
|
|
754
|
+
opacity: var(--zef-reveal-from-opacity);
|
|
755
|
+
translate: var(--zef-reveal-from-translate);
|
|
756
|
+
scale: var(--zef-reveal-from-scale);
|
|
757
|
+
filter: var(--zef-reveal-from-filter);
|
|
758
|
+
}
|
|
759
|
+
/* Dévoilement par masque : seul effet qui touche à clip-path (les autres gardent celui du site) */
|
|
760
|
+
:root[data-zef-reveal] [data-reveal="clip"]:not([data-reveal-scroll], [data-zef-visible]) {
|
|
761
|
+
clip-path: inset(0 100% 0 0);
|
|
762
|
+
}
|
|
763
|
+
:root[data-zef-reveal] [data-reveal="clip"][data-zef-visible]:not([data-zef-done]) {
|
|
764
|
+
clip-path: inset(0 0 0 0);
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
/*
|
|
768
|
+
* Variante 100 % CSS liée au défilement (`data-reveal-scroll`) : l'effet avance et recule avec
|
|
769
|
+
* le défilement. Navigateurs sans `animation-timeline` : rien n'est animé, tout est visible.
|
|
770
|
+
*/
|
|
771
|
+
@keyframes zef-reveal {
|
|
772
|
+
from {
|
|
773
|
+
opacity: var(--zef-reveal-from-opacity);
|
|
774
|
+
translate: var(--zef-reveal-from-translate);
|
|
775
|
+
scale: var(--zef-reveal-from-scale);
|
|
776
|
+
filter: var(--zef-reveal-from-filter);
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
@keyframes zef-reveal-clip {
|
|
780
|
+
from {
|
|
781
|
+
clip-path: inset(0 100% 0 0);
|
|
782
|
+
}
|
|
783
|
+
to {
|
|
784
|
+
clip-path: inset(0 0 0 0);
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
@supports (animation-timeline: view()) {
|
|
788
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
789
|
+
:root[data-zef-reveal] [data-reveal][data-reveal-scroll] {
|
|
790
|
+
animation: zef-reveal linear both;
|
|
791
|
+
animation-timeline: view();
|
|
792
|
+
animation-range: var(--zef-reveal-scroll-range);
|
|
793
|
+
}
|
|
794
|
+
:root[data-zef-reveal] [data-reveal="clip"][data-reveal-scroll] {
|
|
795
|
+
animation-name: zef-reveal-clip;
|
|
796
|
+
}
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
/* Mouvement réduit : un fondu court, sans déplacement ni flou */
|
|
801
|
+
@media (prefers-reduced-motion: reduce) {
|
|
802
|
+
:where([data-reveal]) {
|
|
803
|
+
--zef-reveal-from-translate: none;
|
|
804
|
+
--zef-reveal-from-scale: none;
|
|
805
|
+
--zef-reveal-from-filter: none;
|
|
806
|
+
--zef-reveal-stagger: 0ms;
|
|
807
|
+
--zef-reveal-duration: 0.3s;
|
|
808
|
+
}
|
|
809
|
+
:where([data-reveal="clip"]) {
|
|
810
|
+
--zef-reveal-from-opacity: 0;
|
|
811
|
+
}
|
|
812
|
+
:root[data-zef-reveal] [data-reveal="clip"]:not([data-reveal-scroll], [data-zef-visible]) {
|
|
813
|
+
clip-path: none;
|
|
814
|
+
}
|
|
815
|
+
}
|