Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions .github/workflows/code-quality.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
name: Code Quality Check

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'

- name: Install dependencies
run: npm ci

- name: Run linting check
run: npm run lint:check
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,13 @@ The `demo/` folder contains the following examples:
- Safari (latest versions)
- Edge (latest versions)

## Linting and Formatting

This project uses [Biome](https://biomejs.dev/) for code formatting and linting.

- Run `npm run lint:check` to check for formatting and linting issues.
- Run `npm run lint:fix` to automatically fix formatting and safe linting issues.

## License

MIT
30 changes: 30 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"$schema": "https://biomejs.dev/schemas/1.9.4/schema.json",
"vcs": {
"enabled": false,
"clientKind": "git",
"useIgnoreFile": false
},
"files": {
"ignoreUnknown": false,
"ignore": ["dist/**"]
},
"formatter": {
"enabled": true,
"indentStyle": "tab"
},
"organizeImports": {
"enabled": true
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"javascript": {
"formatter": {
"quoteStyle": "double"
}
}
}
File renamed without changes.
264 changes: 135 additions & 129 deletions demo/react-integration.jsx
Original file line number Diff line number Diff line change
@@ -1,150 +1,156 @@
import React, { useEffect, useRef, useState } from 'react';
import React, { useEffect, useRef, useState } from "react";
// Dans un projet réel, vous importeriez depuis le package npm
// import ImageTool from 'image-tool';

// Composant d'exemple pour l'intégration avec React
function ImageEditor() {
const imageRef = useRef(null);
const toolRef = useRef(null);
const [focusPoint, setFocusPoint] = useState({ x: 0, y: 0 });
const [cropZone, setCropZone] = useState({ x: 0, y: 0, width: 0, height: 0 });
const [focusActive, setFocusActive] = useState(false);
const [cropActive, setCropActive] = useState(false);
const imageRef = useRef(null);
const toolRef = useRef(null);
const [focusPoint, setFocusPoint] = useState({ x: 0, y: 0 });
const [cropZone, setCropZone] = useState({ x: 0, y: 0, width: 0, height: 0 });
const [focusActive, setFocusActive] = useState(false);
const [cropActive, setCropActive] = useState(false);

// Initialiser l'outil lorsque le composant est monté
useEffect(() => {
if (imageRef.current && !toolRef.current) {
// Attendre que l'image soit chargée
if (!imageRef.current.complete) {
imageRef.current.onload = initializeTool;
} else {
initializeTool();
}
}
// Initialiser l'outil lorsque le composant est monté
useEffect(() => {
if (imageRef.current && !toolRef.current) {
// Attendre que l'image soit chargée
if (!imageRef.current.complete) {
imageRef.current.onload = initializeTool;
} else {
initializeTool();
}
}

// Nettoyer lors du démontage du composant
return () => {
if (toolRef.current) {
toolRef.current.destroy();
toolRef.current = null;
}
};
}, []);
// Nettoyer lors du démontage du composant
return () => {
if (toolRef.current) {
toolRef.current.destroy();
toolRef.current = null;
}
};
}, []);

// Fonction pour initialiser l'outil
const initializeTool = () => {
// Dans un projet réel, vous utiliseriez l'import
// Ici, nous supposons que ImageTool est disponible globalement
toolRef.current = new ImageTool({
imageElement: imageRef.current,
focusPoint: {
enabled: true,
style: {
width: '30px',
height: '30px',
border: '3px solid white',
boxShadow: '0 0 0 2px black, 0 0 5px rgba(0,0,0,0.5)',
backgroundColor: 'rgba(255, 0, 0, 0.5)'
}
},
cropZone: {
enabled: true,
style: {
border: '1px dashed #fff',
backgroundColor: 'rgba(0, 0, 0, 0.4)'
}
},
onChange: handleToolChange
});
};
// Fonction pour initialiser l'outil
const initializeTool = () => {
// Dans un projet réel, vous utiliseriez l'import
// Ici, nous supposons que ImageTool est disponible globalement
toolRef.current = new ImageTool({
imageElement: imageRef.current,
focusPoint: {
enabled: true,
style: {
width: "30px",
height: "30px",
border: "3px solid white",
boxShadow: "0 0 0 2px black, 0 0 5px rgba(0,0,0,0.5)",
backgroundColor: "rgba(255, 0, 0, 0.5)",
},
},
cropZone: {
enabled: true,
style: {
border: "1px dashed #fff",
backgroundColor: "rgba(0, 0, 0, 0.4)",
},
},
onChange: handleToolChange,
});
};

// Gérer les changements de l'outil
const handleToolChange = (data) => {
setFocusPoint(data.focusPoint);
setCropZone(data.cropZone);
setFocusActive(data.focusActive);
setCropActive(data.cropActive);
};
// Gérer les changements de l'outil
const handleToolChange = (data) => {
setFocusPoint(data.focusPoint);
setCropZone(data.cropZone);
setFocusActive(data.focusActive);
setCropActive(data.cropActive);
};

// Activer/désactiver le point focal
const toggleFocusPoint = () => {
if (toolRef.current) {
toolRef.current.toggleFocusPoint();
}
};
// Activer/désactiver le point focal
const toggleFocusPoint = () => {
if (toolRef.current) {
toolRef.current.toggleFocusPoint();
}
};

// Activer/désactiver la zone de recadrage
const toggleCropZone = () => {
if (toolRef.current) {
toolRef.current.toggleCropZone();
}
};
// Activer/désactiver la zone de recadrage
const toggleCropZone = () => {
if (toolRef.current) {
toolRef.current.toggleCropZone();
}
};

// Centrer le point focal
const centerFocusPoint = () => {
if (toolRef.current) {
const dimensions = toolRef.current.getImageDimensions();
toolRef.current.setFocusPoint(
dimensions.width / 2,
dimensions.height / 2
);
}
};
// Centrer le point focal
const centerFocusPoint = () => {
if (toolRef.current) {
const dimensions = toolRef.current.getImageDimensions();
toolRef.current.setFocusPoint(
dimensions.width / 2,
dimensions.height / 2,
);
}
};

// Réinitialiser la zone de recadrage
const resetCropZone = () => {
if (toolRef.current) {
const dimensions = toolRef.current.getImageDimensions();
const width = dimensions.width / 2;
const height = dimensions.height / 2;
toolRef.current.setCropZone(
(dimensions.width - width) / 2,
(dimensions.height - height) / 2,
width,
height
);
}
};
// Réinitialiser la zone de recadrage
const resetCropZone = () => {
if (toolRef.current) {
const dimensions = toolRef.current.getImageDimensions();
const width = dimensions.width / 2;
const height = dimensions.height / 2;
toolRef.current.setCropZone(
(dimensions.width - width) / 2,
(dimensions.height - height) / 2,
width,
height,
);
}
};

return (
<div className="image-editor">
<div className="image-container">
<img
ref={imageRef}
src="https://images.unsplash.com/photo-1506744038136-46273834b3fb?ixlib=rb-1.2.1&auto=format&fit=crop&w=1024&q=80"
alt="Paysage éditable"
/>
</div>
return (
<div className="image-editor">
<div className="image-container">
<img
ref={imageRef}
src="https://images.unsplash.com/photo-1506744038136-46273834b3fb?ixlib=rb-1.2.1&auto=format&fit=crop&w=1024&q=80"
alt="Paysage éditable"
/>
</div>

<div className="controls">
<h2>Contrôles</h2>
<button onClick={toggleFocusPoint}>
{focusActive ? 'Désactiver Point Focal' : 'Activer Point Focal'}
</button>
<button onClick={toggleCropZone}>
{cropActive ? 'Désactiver Zone de Recadrage' : 'Activer Zone de Recadrage'}
</button>
<div className="controls">
<h2>Contrôles</h2>
<button type="button" onClick={toggleFocusPoint}>
{focusActive ? "Désactiver Point Focal" : "Activer Point Focal"}
</button>
<button type="button" onClick={toggleCropZone}>
{cropActive
? "Désactiver Zone de Recadrage"
: "Activer Zone de Recadrage"}
</button>

<h3>Actions</h3>
<button onClick={centerFocusPoint}>Centrer le Point Focal</button>
<button onClick={resetCropZone}>Réinitialiser la Zone de Recadrage</button>
<h3>Actions</h3>
<button type="button" onClick={centerFocusPoint}>
Centrer le Point Focal
</button>
<button type="button" onClick={resetCropZone}>
Réinitialiser la Zone de Recadrage
</button>

<h3>Données actuelles</h3>
<div className="data-display">
<h4>Point Focal</h4>
<p>
X: {Math.round(focusPoint.x)}, Y: {Math.round(focusPoint.y)}
</p>
<h3>Données actuelles</h3>
<div className="data-display">
<h4>Point Focal</h4>
<p>
X: {Math.round(focusPoint.x)}, Y: {Math.round(focusPoint.y)}
</p>

<h4>Zone de Recadrage</h4>
<p>
X: {Math.round(cropZone.x)}, Y: {Math.round(cropZone.y)},
Largeur: {Math.round(cropZone.width)}, Hauteur: {Math.round(cropZone.height)}
</p>
</div>
</div>
</div>
);
<h4>Zone de Recadrage</h4>
<p>
X: {Math.round(cropZone.x)}, Y: {Math.round(cropZone.y)}, Largeur:{" "}
{Math.round(cropZone.width)}, Hauteur: {Math.round(cropZone.height)}
</p>
</div>
</div>
</div>
);
}

export default ImageEditor;
Loading