Add text import export for toolbox modules

This commit is contained in:
Shinuwa 2026-08-09 15:26:10 +02:00
parent a9b5ca423a
commit 117b7b79e1
27 changed files with 1430 additions and 181 deletions

View file

@ -1,5 +1,5 @@
// Rôle : affiche la librairie des outils avec des exemples locaux non persistés.
import React, { useEffect, useMemo, useState } from "react";
import React, { useEffect, useMemo, useRef, useState } from "react";
import { Icon } from "../components/Icon.jsx";
import { CalculatorModule } from "../features/toolboxes/modules/CalculatorModule.jsx";
import { ChecklistModule } from "../features/toolboxes/modules/ChecklistModule.jsx";
@ -266,6 +266,9 @@ export function LibraryPage({ siteContent, actions }) {
categoryTitle={activeCategory.title}
docs={content.toolDocs?.[module.type]}
featureHeading={content.featureHeading}
advancedHeading={content.advancedHeading}
advancedCopyLabel={content.copyExampleLabel}
advancedCopySuccess={content.copyExampleSuccess}
controlLegendHeading={content.controlLegendHeading}
context={moduleContext}
/>
@ -324,7 +327,7 @@ function LibraryDocNav({ content, categories, activeCategoryKey, onSelectCategor
);
}
function LibraryToolExample({ module, sourceData, description, categoryTitle, docs, featureHeading, controlLegendHeading, context }) {
function LibraryToolExample({ module, sourceData, description, categoryTitle, docs, featureHeading, advancedHeading, advancedCopyLabel, advancedCopySuccess, controlLegendHeading, context }) {
const definition = MODULE_COMPONENTS[module.type] || MODULE_COMPONENTS.notepad;
const Component = definition.Component;
const [scrollable, setScrollable] = useState(false);
@ -390,6 +393,7 @@ function LibraryToolExample({ module, sourceData, description, categoryTitle, do
</article>
</div>
<ToolFeatureList docs={docs} heading={featureHeading || "Fonctionnalités"} />
<ToolAdvancedFeatureList docs={docs} heading={advancedHeading || "Import par texte"} copyLabel={advancedCopyLabel} copySuccess={advancedCopySuccess} context={context} />
</section>
);
}
@ -515,7 +519,7 @@ function ControlPreview({ item }) {
function ToolFeatureList({ docs, heading }) {
const features = Array.isArray(docs?.features) ? docs.features : [];
if (!features.length && !docs?.importFormat) return null;
if (!features.length) return null;
return (
<section className="library-tool-docs">
@ -540,13 +544,44 @@ function ToolFeatureList({ docs, heading }) {
</div>
))}
</dl>
{docs?.importFormat && (
<div className="library-tool-import-format">
<h3>{docs.importFormat.title}</h3>
<p>{docs.importFormat.text}</p>
<pre><code>{docs.importFormat.example}</code></pre>
</div>
)}
</div>
</details>
</section>
);
}
function ToolAdvancedFeatureList({ docs, heading, copyLabel, copySuccess, context }) {
const [copied, setCopied] = useState(false);
const copiedTimeoutRef = useRef(0);
useEffect(() => () => window.clearTimeout(copiedTimeoutRef.current), []);
if (!docs?.importFormat) return null;
async function copyExample() {
if (!await context.copyText(docs.importFormat.example)) return;
setCopied(true);
context.notify?.(copySuccess || "Exemple copié.");
window.clearTimeout(copiedTimeoutRef.current);
copiedTimeoutRef.current = window.setTimeout(() => setCopied(false), 1400);
}
return (
<section className="library-tool-docs">
<details className="library-tool-feature-list library-tool-advanced-list">
<summary>
<h3>{heading}</h3>
<Icon name="chevron-down" />
</summary>
<div className="library-tool-feature-content">
<div className="library-tool-import-format">
<p>{docs.importFormat.text}</p>
<div className="library-tool-import-example">
<pre><code>{docs.importFormat.example}</code></pre>
<button type="button" onClick={copyExample} title={copyLabel || "Copier l'exemple"}>
<Icon name="copy" />
<span>{copied ? copySuccess || "Exemple copié." : copyLabel || "Copier l'exemple"}</span>
</button>
</div>
</div>
</div>
</details>
</section>