diff --git a/plugins/carhop-blocks/src/story-timeline-step/block.json b/plugins/carhop-blocks/src/story-timeline-step/block.json
new file mode 100644
index 0000000..d85f646
--- /dev/null
+++ b/plugins/carhop-blocks/src/story-timeline-step/block.json
@@ -0,0 +1,28 @@
+{
+ "$schema": "https://schemas.wp.org/trunk/block.json",
+ "apiVersion": 3,
+ "name": "carhop-blocks/story-timeline-step",
+ "version": "0.1.0",
+ "title": "Étape de timeline",
+ "category": "carhop-blocks",
+ "icon": "calendar",
+ "description": "Étape de timeline pour la mise en forme d'une étape de timeline",
+ "example": {},
+ "parent": [
+ "carhop-blocks/story-timeline"
+ ],
+ "supports": {
+ "html": false
+ },
+ "textdomain": "carhop-blocks",
+ "editorScript": "file:./index.js",
+ "editorStyle": "file:./index.css",
+ "style": "file:./style-index.css",
+ "viewScript": "file:./view.js",
+ "attributes": {
+ "year": {
+ "type": "number",
+ "default": 2025
+ }
+ }
+}
\ No newline at end of file
diff --git a/plugins/carhop-blocks/src/story-timeline-step/edit.js b/plugins/carhop-blocks/src/story-timeline-step/edit.js
new file mode 100644
index 0000000..9fb957c
--- /dev/null
+++ b/plugins/carhop-blocks/src/story-timeline-step/edit.js
@@ -0,0 +1,77 @@
+import { __ } from "@wordpress/i18n";
+import { useBlockProps, InnerBlocks } from "@wordpress/block-editor";
+import "./editor.scss";
+import {
+ PanelBody,
+ Card,
+ CardBody,
+ CardHeader,
+ TextControl,
+ Button,
+ __experimentalNumberControl as NumberControl,
+} from "@wordpress/components";
+import { InspectorControls } from "@wordpress/block-editor";
+
+import { RichText } from "@wordpress/block-editor";
+
+export default function Edit({ attributes, setAttributes, ...props }) {
+ const { year } = attributes;
+ return (
+ <>
+
+
+ {
+ const n = parseInt(value, 10);
+ setAttributes({ year: Number.isFinite(n) ? n : undefined });
+ }}
+ />
+
+
+
+ >
+ );
+}
diff --git a/plugins/carhop-blocks/src/story-timeline-step/editor.scss b/plugins/carhop-blocks/src/story-timeline-step/editor.scss
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/plugins/carhop-blocks/src/story-timeline-step/editor.scss
@@ -0,0 +1 @@
+
diff --git a/plugins/carhop-blocks/src/story-timeline-step/index.js b/plugins/carhop-blocks/src/story-timeline-step/index.js
new file mode 100644
index 0000000..1807b0f
--- /dev/null
+++ b/plugins/carhop-blocks/src/story-timeline-step/index.js
@@ -0,0 +1,24 @@
+import { registerBlockType } from "@wordpress/blocks";
+import "./style.scss";
+
+import Edit from "./edit";
+import save from "./save";
+import metadata from "./block.json";
+
+registerBlockType(metadata.name, {
+ icon: {
+ foreground: "#136f63",
+ src: (
+
+ ),
+ },
+ edit: Edit,
+ save,
+});
diff --git a/plugins/carhop-blocks/src/story-timeline-step/save.js b/plugins/carhop-blocks/src/story-timeline-step/save.js
new file mode 100644
index 0000000..85a2c1e
--- /dev/null
+++ b/plugins/carhop-blocks/src/story-timeline-step/save.js
@@ -0,0 +1,18 @@
+import { useBlockProps, InnerBlocks } from "@wordpress/block-editor";
+
+export default function save({ attributes }) {
+ const { year } = attributes;
+ return (
+
+ );
+}
diff --git a/plugins/carhop-blocks/src/story-timeline-step/style.scss b/plugins/carhop-blocks/src/story-timeline-step/style.scss
new file mode 100644
index 0000000..e69de29
diff --git a/plugins/carhop-blocks/src/story-timeline-step/view.js b/plugins/carhop-blocks/src/story-timeline-step/view.js
new file mode 100644
index 0000000..e69de29
diff --git a/plugins/carhop-blocks/src/story-timeline/block.json b/plugins/carhop-blocks/src/story-timeline/block.json
new file mode 100644
index 0000000..62812ee
--- /dev/null
+++ b/plugins/carhop-blocks/src/story-timeline/block.json
@@ -0,0 +1,20 @@
+{
+ "$schema": "https://schemas.wp.org/trunk/block.json",
+ "apiVersion": 3,
+ "name": "carhop-blocks/story-timeline",
+ "version": "0.1.0",
+ "title": "Timeline",
+ "category": "carhop-blocks",
+ "icon": "calendar-alt",
+ "description": "Boite de timeline pour la mise en forme d'une timeline",
+ "example": {},
+ "supports": {
+ "html": false
+ },
+ "textdomain": "carhop-blocks",
+ "editorScript": "file:./index.js",
+ "editorStyle": "file:./index.css",
+ "style": "file:./style-index.css",
+ "viewScript": "file:./view.js",
+ "render": "file:./render.php"
+}
\ No newline at end of file
diff --git a/plugins/carhop-blocks/src/story-timeline/edit.js b/plugins/carhop-blocks/src/story-timeline/edit.js
new file mode 100644
index 0000000..bc438e3
--- /dev/null
+++ b/plugins/carhop-blocks/src/story-timeline/edit.js
@@ -0,0 +1,40 @@
+import { __ } from "@wordpress/i18n";
+import { useBlockProps, InnerBlocks } from "@wordpress/block-editor";
+import { useSelect } from "@wordpress/data";
+import "./editor.scss";
+
+export default function Edit({ attributes, setAttributes, ...props }) {
+ const years = useSelect(
+ (select) => {
+ const { getBlocks } = select("core/block-editor");
+ const childBlocks = getBlocks(props.clientId) || [];
+ return childBlocks
+ .filter((b) => b.name === "carhop-blocks/story-timeline-step")
+ .map((b) => b.attributes?.year)
+ .filter((y) => y !== undefined && y !== null && y !== "");
+ },
+ [props.clientId]
+ );
+ return (
+ <>
+
+
+
+
+
+
+ >
+ );
+}
diff --git a/plugins/carhop-blocks/src/story-timeline/editor.scss b/plugins/carhop-blocks/src/story-timeline/editor.scss
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/plugins/carhop-blocks/src/story-timeline/editor.scss
@@ -0,0 +1 @@
+
diff --git a/plugins/carhop-blocks/src/story-timeline/index.js b/plugins/carhop-blocks/src/story-timeline/index.js
new file mode 100644
index 0000000..1807b0f
--- /dev/null
+++ b/plugins/carhop-blocks/src/story-timeline/index.js
@@ -0,0 +1,24 @@
+import { registerBlockType } from "@wordpress/blocks";
+import "./style.scss";
+
+import Edit from "./edit";
+import save from "./save";
+import metadata from "./block.json";
+
+registerBlockType(metadata.name, {
+ icon: {
+ foreground: "#136f63",
+ src: (
+
+ ),
+ },
+ edit: Edit,
+ save,
+});
diff --git a/plugins/carhop-blocks/src/story-timeline/render.php b/plugins/carhop-blocks/src/story-timeline/render.php
new file mode 100644
index 0000000..73edd32
--- /dev/null
+++ b/plugins/carhop-blocks/src/story-timeline/render.php
@@ -0,0 +1,28 @@
+ 'story-timeline'));
+
+$years = array();
+if (isset($block) && is_object($block) && ! empty($block->inner_blocks)) {
+ foreach ($block->inner_blocks as $inner_block) {
+ if (isset($inner_block->name) && $inner_block->name === 'carhop-blocks/story-timeline-step') {
+ $y = isset($inner_block->attributes['year']) ? $inner_block->attributes['year'] : null;
+ if ($y !== null && $y !== '') {
+ $years[] = $y;
+ }
+ }
+ }
+}
+?>
+
+
\ No newline at end of file
diff --git a/plugins/carhop-blocks/src/story-timeline/save.js b/plugins/carhop-blocks/src/story-timeline/save.js
new file mode 100644
index 0000000..bfa118f
--- /dev/null
+++ b/plugins/carhop-blocks/src/story-timeline/save.js
@@ -0,0 +1,5 @@
+import { useBlockProps, InnerBlocks } from "@wordpress/block-editor";
+
+export default function save({ attributes }) {
+ return ;
+}
diff --git a/plugins/carhop-blocks/src/story-timeline/style.scss b/plugins/carhop-blocks/src/story-timeline/style.scss
new file mode 100644
index 0000000..e69de29
diff --git a/plugins/carhop-blocks/src/story-timeline/view.js b/plugins/carhop-blocks/src/story-timeline/view.js
new file mode 100644
index 0000000..84ad319
--- /dev/null
+++ b/plugins/carhop-blocks/src/story-timeline/view.js
@@ -0,0 +1,67 @@
+document.addEventListener("DOMContentLoaded", function () {
+ const timeline = document.querySelector(
+ ".wp-block-carhop-blocks-story-timeline"
+ );
+ if (!timeline) return;
+
+ function initBlock() {
+ const years = timeline.querySelectorAll(".story-timeline__year");
+ years.forEach((year, index) => {
+ year.setAttribute("data-active", index === 0 ? "true" : "false");
+ });
+ }
+
+ function removePreviousActiveLinkInSidebar() {
+ const activeSidebarLinks = document.querySelectorAll(
+ `.story-timeline__years .story-timeline__year[data-active="true"]`
+ );
+
+ activeSidebarLinks.forEach((sidebarLink) => {
+ sidebarLink.setAttribute("data-active", "false");
+ });
+ }
+
+ const timelineStepsProgressionObserver = new IntersectionObserver(
+ (entries) => {
+ // Ne pas traiter les entrées si l'observer est en pause (pendant un clic)
+ // const isIntersetionObserverPaused = getChapterObserverPausedState();
+ // if (isIntersetionObserverPaused) return;
+
+ entries.forEach((entry) => {
+ const blockId = entry.target.getAttribute("id");
+ const relatedStepLink = document.querySelector(`a[href="#${blockId}"]`);
+ console.log(relatedStepLink);
+
+ if (entry.isIntersecting) {
+ removePreviousActiveLinkInSidebar();
+ // setActiveLinkInSidebar();
+
+ entry.target.setAttribute("active", "true");
+ relatedStepLink?.parentElement?.setAttribute("data-active", "true");
+ }
+ });
+ },
+ {
+ rootMargin: "-10% 0px -50% 0px",
+ }
+ );
+
+ const timelineSteps = document.querySelectorAll(
+ ".story-timeline__innerblocks .wp-block-carhop-blocks-story-timeline-step"
+ );
+ console.log(timelineSteps);
+ timelineSteps.forEach((step) => {
+ timelineStepsProgressionObserver.observe(step);
+ });
+
+ initBlock();
+});
+
+// Initialiser les écouteurs de liens
+// observeChapterLinks();
+
+// // Observer tous les titres h2 de l'article
+// const titlesBlocks = document.querySelectorAll('.article-content h2');
+// titlesBlocks.forEach((block) => {
+// chapterProgressionObserver.observe(block);
+// });