improve notepad features and add drawing canvas
All checks were successful
Deploy Sokko G / deploy (push) Successful in 7s

This commit is contained in:
Shinuwa 2026-07-29 13:51:42 +02:00
parent e73d754082
commit de1b8a5638
20 changed files with 1732 additions and 141 deletions

View file

@ -0,0 +1,180 @@
// Rôle : rend les contrôles compacts des calques de dessin réutilisables.
import { CompactDropdown } from "../../../components/CompactDropdown.jsx";
import { Icon } from "../../../components/Icon.jsx";
const DEFAULT_WIDTHS = [2, 4, 8, 12];
export function DrawingControls({ textContent = {}, active, onToggleActive, eraseActive, onToggleErase, color, colors, onColorChange, width, widths = DEFAULT_WIDTHS, onWidthChange, onUndo, onClear, storageMode, onToggleStorageMode }) {
return (
<div className={`drawing-controls-panel ${active ? "is-open" : ""}`} aria-label={textContent.drawingLabel || "Dessin"}>
<button className={`drawing-control-button ${active ? "active" : ""}`} type="button" aria-pressed={active} title={textContent.drawTitle || "Dessiner"} onClick={onToggleActive}>
<Icon name="edit" />
</button>
{active && (
<>
<button
className={`drawing-control-button ${eraseActive ? "active" : ""}`}
type="button"
aria-pressed={eraseActive}
title={textContent.eraseTitle || "Gommer"}
onClick={onToggleErase}
>
<Icon name="rubber" />
</button>
<DrawingColorDropdown
label={textContent.drawingColorLabel || "Couleur du dessin"}
colors={colors}
value={color}
onSelect={onColorChange}
/>
<DrawingWidthDropdown
label={textContent.drawingWidthLabel || "Épaisseur du trait"}
widths={widths}
value={width}
onSelect={onWidthChange}
/>
<button className="drawing-control-button" type="button" title={textContent.undoDrawingTitle || "Annuler le dernier trait"} onClick={onUndo}>
<Icon name="back" />
</button>
<button className="drawing-control-button danger" type="button" title={textContent.clearDrawingTitle || "Effacer les dessins"} onClick={onClear}>
<Icon name="trash" />
</button>
{onToggleStorageMode && (
<button
className={`module-scroll-button drawing-storage-switch ${storageMode === "permanent" ? "active" : ""}`}
type="button"
aria-pressed={storageMode === "permanent"}
aria-label={storageMode === "permanent" ? textContent.permanentTitle || "Annotations permanentes" : textContent.temporaryTitle || "Annotations temporaires"}
title={storageMode === "permanent" ? textContent.permanentTitle || "Annotations permanentes" : textContent.temporaryTitle || "Annotations temporaires"}
onClick={onToggleStorageMode}
>
<Icon name="save" />
<i aria-hidden="true" />
</button>
)}
</>
)}
</div>
);
}
export function FormattingColorDropdown({ label, sections }) {
return (
<CompactDropdown
className="notepad-color-dropdown"
menuClassName="notepad-color-menu is-sectioned"
label={label}
closeOnMouseLeave
preventMouseDown
renderTrigger={({ toggle }) => (
<button className="notepad-color-toggle is-rainbow" type="button" title={label} aria-label={label} onClick={toggle} />
)}
>
{({ close }) => (
<>
{sections.map((section) => (
<div className="notepad-color-section" key={section.label}>
<span className="notepad-color-section-label">{section.label}</span>
<div className="notepad-color-section-swatches">
{section.colors.map((color) => (
<button
key={`${section.label}-${color}`}
className={`notepad-swatch ${section.value === color ? "active" : ""}`}
type="button"
title={`${section.label} ${color}`}
aria-label={`${section.label} ${color}`}
aria-pressed={section.value === color}
style={{ "--swatch-color": color }}
onClick={() => {
section.onSelect(color);
close();
}}
/>
))}
</div>
</div>
))}
</>
)}
</CompactDropdown>
);
}
export function DrawingColorDropdown({ label, colors, value, onSelect }) {
return (
<CompactDropdown
className="notepad-color-dropdown"
menuClassName="notepad-color-menu"
label={label}
closeOnMouseLeave
preventMouseDown
renderTrigger={({ toggle }) => (
<button
className="notepad-color-toggle is-rainbow"
type="button"
title={label}
aria-label={label}
style={{ "--swatch-color": value }}
onClick={toggle}
/>
)}
>
{({ close }) => (
<>
{colors.map((color) => (
<button
key={color}
className={`notepad-swatch ${value === color ? "active" : ""}`}
type="button"
title={`${label} ${color}`}
aria-label={`${label} ${color}`}
aria-pressed={value === color}
style={{ "--swatch-color": color }}
onClick={() => {
onSelect(color);
close();
}}
/>
))}
</>
)}
</CompactDropdown>
);
}
export function DrawingWidthDropdown({ label, widths, value, onSelect }) {
return (
<CompactDropdown
className="drawing-width-dropdown"
menuClassName="drawing-width-menu"
label={label}
closeOnMouseLeave
preventMouseDown
renderTrigger={({ toggle }) => (
<button className="drawing-width-toggle" type="button" title={label} aria-label={label} onClick={toggle}>
<span style={{ "--line-width": `${value}px` }} />
</button>
)}
>
{({ close }) => (
<>
{widths.map((lineWidth) => (
<button
key={lineWidth}
className={`drawing-width-button ${value === lineWidth ? "active" : ""}`}
type="button"
aria-pressed={value === lineWidth}
title={`${label} ${lineWidth}`}
onClick={() => {
onSelect(lineWidth);
close();
}}
>
<span style={{ "--line-width": `${lineWidth}px` }} />
</button>
))}
</>
)}
</CompactDropdown>
);
}