Skip to content

Commit 2fa2c0f

Browse files
authored
Merge pull request #4 from Lemoncode/feature/#3-react-image-focal-point-package
Feature/#3 react image focal point package
2 parents a484fd4 + 9ab7cd5 commit 2fa2c0f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

69 files changed

+17158
-3504
lines changed

.github/workflows/ci.yml

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
6+
jobs:
7+
ci:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- name: Checkout Repository
11+
uses: actions/checkout@v3
12+
13+
- name: Add NPM registry
14+
uses: actions/setup-node@v3
15+
with:
16+
node-version: 18.x
17+
18+
- name: Install
19+
run: npm ci
20+
21+
- name: Tests
22+
run: npm test

examples/basic-with-apply/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Basic example, apply button
2+
3+
This example is quite similar to the [basic example](https://github.com/Lemoncode/react-image-focal-point/tree/main/examples/basic), but instead of applying the changes real time, the user has to click on an 'apply' button to see the updates reflected.
4+
5+
<a target="_blank" href="https://stackblitz.com/github/Lemoncode/react-image-focal-point/tree/main/examples/basic-with-apply">
6+
<img
7+
src="https://developer.stackblitz.com/img/open_in_stackblitz.svg"
8+
alt="Edit on StackBlitz"
9+
title="Edit on StackBlitz"
10+
height="36"
11+
/>
12+
</a> <a target="_blank" href="https://codesandbox.io/s/github/Lemoncode/react-image-focal-point/tree/main/examples/basic-with-apply">
13+
<img
14+
src="https://codesandbox.io/static/img/play-codesandbox.svg"
15+
alt="Edit on StackBlitz"
16+
title="Edit on StackBlitz"
17+
height="36"
18+
/>
19+
</a>

examples/basic-with-apply/index.html

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<link rel="icon" href="/favicon.ico" />
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
7+
<title>Basic example, apply button</title>
8+
</head>
9+
<body>
10+
<div id="root"></div>
11+
<script type="module" src="/src/index.tsx"></script>
12+
</body>
13+
</html>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
"name": "basic-with-apply-example",
3+
"scripts": {
4+
"start": "vite --open"
5+
},
6+
"repository": {
7+
"type": "git",
8+
"url": "git+https://github.com/Lemoncode/react-image-focal-point.git"
9+
},
10+
"author": "Lemoncode",
11+
"homepage": "https://github.com/Lemoncode/react-image-focal-point/tree/main/#readme",
12+
"devDependencies": {
13+
"@types/react": "^18.0.27",
14+
"@types/react-dom": "^18.0.10",
15+
"@vitejs/plugin-react": "^3.1.0",
16+
"typescript": "^4.9.5",
17+
"vite": "^4.1.1"
18+
},
19+
"dependencies": {
20+
"@lemoncode/react-image-focal-point": "*",
21+
"react": "^18.2.0",
22+
"react-dom": "^18.2.0"
23+
}
24+
}
2.21 MB
Loading

examples/basic-with-apply/src/app.tsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from 'react';
2+
import '@lemoncode/react-image-focal-point/style.css';
3+
import { ImageFocalPoint, FocalPoint } from '@lemoncode/react-image-focal-point';
4+
import { Playground } from './playground';
5+
6+
const IMAGE_URL = 'landscape.jpg';
7+
8+
export const App = () => {
9+
const [focalPoint, setFocalPoint] = React.useState<FocalPoint>();
10+
11+
return (
12+
<Playground src={IMAGE_URL} focalPoint={focalPoint}>
13+
<ImageFocalPoint src={IMAGE_URL} onChange={setFocalPoint} />
14+
</Playground>
15+
);
16+
};
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { createRoot } from 'react-dom/client';
2+
import { App } from './app';
3+
4+
const root = createRoot(document.getElementById('root')!);
5+
6+
root.render(<App />);
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
body {
2+
font-family: Roboto, Oxygen-Sans, Ubuntu, Cantarell, 'Helvetica Neue', sans-serif;
3+
}
4+
5+
h1,
6+
h2,
7+
p {
8+
margin: 0;
9+
}
10+
11+
.root {
12+
display: grid;
13+
grid-template-areas:
14+
'title title'
15+
'description description'
16+
'focal-point-subtitle result-subtitle'
17+
'focal-point result';
18+
row-gap: 1rem;
19+
column-gap: 10rem;
20+
grid-template-columns: auto 1fr;
21+
}
22+
23+
.title {
24+
grid-area: title;
25+
font-size: 2rem;
26+
font-weight: bold;
27+
text-align: center;
28+
}
29+
30+
.description {
31+
grid-area: description;
32+
text-align: center;
33+
}
34+
35+
.focal-point-subtitle {
36+
grid-area: focal-point-subtitle;
37+
font-size: 1.5rem;
38+
font-weight: bold;
39+
text-align: center;
40+
}
41+
42+
.focal-point {
43+
grid-area: focal-point;
44+
display: flex;
45+
flex-direction: column;
46+
gap: 1rem;
47+
align-items: flex-end;
48+
}
49+
50+
.submit-button {
51+
cursor: pointer;
52+
padding: 0.5rem 1rem;
53+
border-radius: 4px;
54+
border-style: none;
55+
box-sizing: border-box;
56+
min-width: 100px;
57+
background-color: #a3c769;
58+
font-size: 14px;
59+
}
60+
61+
.submit-button:hover {
62+
background-color: #8ebc5a;
63+
}
64+
65+
.submit-button:active {
66+
transform: scale(0.95);
67+
}
68+
69+
.result-subtitle {
70+
grid-area: result-subtitle;
71+
font-size: 1.5rem;
72+
font-weight: bold;
73+
text-align: center;
74+
}
75+
76+
.result {
77+
grid-area: result;
78+
display: flex;
79+
flex-direction: column;
80+
flex-wrap: wrap;
81+
gap: 1rem;
82+
width: 100%;
83+
height: 100%;
84+
}
85+
86+
.portrait-image {
87+
width: 100%;
88+
height: 100%;
89+
object-fit: cover;
90+
max-width: 300px;
91+
}
92+
93+
.landscape-image {
94+
width: 100%;
95+
height: 100%;
96+
object-fit: cover;
97+
max-height: 300px;
98+
}
99+
100+
.square-image {
101+
grid-area: square;
102+
object-fit: cover;
103+
width: 300px;
104+
height: 300px;
105+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import React from 'react';
2+
import { FocalPoint } from '@lemoncode/react-image-focal-point';
3+
import classes from './playground.module.css';
4+
5+
interface Props {
6+
src: string;
7+
focalPoint?: FocalPoint;
8+
children: React.ReactNode;
9+
}
10+
11+
export const Playground: React.FC<Props> = props => {
12+
const { src, children } = props;
13+
const [focalPoint, setFocalPoint] = React.useState<FocalPoint>();
14+
15+
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
16+
event.preventDefault();
17+
if (props.focalPoint) {
18+
setFocalPoint(props.focalPoint);
19+
}
20+
};
21+
22+
return (
23+
<div className={classes.root}>
24+
<h1 className={classes.title}>Basic example, apply button</h1>
25+
<p className={classes.description}>
26+
In this example you can play changing the focal point by dragging it, and once you are done you can click on the
27+
apply button and it will reflected on the example pictures
28+
</p>
29+
<h2 className={classes.focalPointSubtitle}>Image focal point</h2>
30+
<form className={classes.focalPoint} onSubmit={handleSubmit}>
31+
{children}
32+
<button className={classes.submitButton} type="submit">
33+
Apply
34+
</button>
35+
</form>
36+
37+
<h2 className={classes.resultSubtitle}>Example results</h2>
38+
<div className={classes.result}>
39+
<img
40+
src={src}
41+
className={classes.portraitImage}
42+
style={{ objectPosition: `${focalPoint?.x}% ${focalPoint?.y}%` }}
43+
/>
44+
<img
45+
src={src}
46+
className={classes.landscapeImage}
47+
style={{ objectPosition: `${focalPoint?.x}% ${focalPoint?.y}%` }}
48+
/>
49+
<img
50+
src={src}
51+
className={classes.squareImage}
52+
style={{ objectPosition: `${focalPoint?.x}% ${focalPoint?.y}%` }}
53+
/>
54+
</div>
55+
</div>
56+
);
57+
};
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
"compilerOptions": {
3+
"composite": false,
4+
"declaration": true,
5+
"declarationMap": true,
6+
"esModuleInterop": true,
7+
"forceConsistentCasingInFileNames": true,
8+
"inlineSources": false,
9+
"isolatedModules": true,
10+
"moduleResolution": "node",
11+
"noUnusedLocals": false,
12+
"noUnusedParameters": false,
13+
"preserveWatchOutput": true,
14+
"skipLibCheck": true,
15+
"strict": true,
16+
"allowSyntheticDefaultImports": true,
17+
"noImplicitAny": false,
18+
"jsx": "react-jsx",
19+
"lib": ["ESNext", "DOM"],
20+
"module": "ESNext",
21+
"target": "ESNext",
22+
"baseUrl": "./src"
23+
},
24+
"include": ["src", "./vite-env.d.ts"],
25+
"exclude": ["node_modules"]
26+
}

0 commit comments

Comments
 (0)