-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1967 from roberdm49/TP-2066-grid-image-picker
TP-2066: Grid image picker
- Loading branch information
Showing
32 changed files
with
1,005 additions
and
13 deletions.
There are no files selected for viewing
File renamed without changes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
File renamed without changes.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
2 changes: 1 addition & 1 deletion
2
docs/runtime~main.c541cfd3.iframe.bundle.js → docs/runtime~main.e88fcb0c.iframe.bundle.js
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
File renamed without changes.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
*.spec.js | ||
*.story.js | ||
src |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import { useEffect, useState } from 'react' | ||
|
||
function useAspectRatio (src) { | ||
const [data, setData] = useState({ | ||
aspectRatio: 0, | ||
loading: true, | ||
error: false, | ||
}) | ||
|
||
useEffect(() => { | ||
const fetchAspectRatio = async (src) => { | ||
try { | ||
setData({ aspectRatio: 0, loading: true, error: false }) | ||
|
||
const img = new window.Image() | ||
img.src = src | ||
|
||
img.onload = () => { | ||
const aspectRatio = img.width / img.height | ||
setData({ aspectRatio, loading: false, error: false }) | ||
} | ||
|
||
img.onerror = (error) => { | ||
console.error(error) | ||
setData({ aspectRatio: 0, loading: false, error: true }) | ||
} | ||
} catch (error) { | ||
console.error(error) | ||
setData({ aspectRatio: 0, loading: false, error: true }) | ||
} | ||
} | ||
|
||
if (src) { | ||
fetchAspectRatio(src) | ||
} | ||
}, [src]) | ||
|
||
return [data.aspectRatio, data.loading, data.error] | ||
} | ||
|
||
export default useAspectRatio |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import { useCallback, useEffect, useState } from 'react' | ||
import { arrayMove } from '@dnd-kit/sortable' | ||
import { isItemClickable } from '../utils/manageItem' | ||
import { | ||
getItemsInitialState, | ||
getUpdatedItemsWithDecrement, | ||
getUpdatedItemsWithIncrement, | ||
refreshItemsPosition, | ||
fillCheckedItems, | ||
getSelectAllItems, | ||
getDeselectAllItems, | ||
} from '../utils/manageListOfItems' | ||
import '../styles/GridImagePicker.css' | ||
|
||
function useGridImagePicker ({ | ||
listOfSrc, | ||
maxSelectablePreferenceByUser, | ||
maxSizeInMB, | ||
minAspectRatio, | ||
maxAspectRatio, | ||
onChange, | ||
}) { | ||
const [isDraggingActive, setIsDraggingActive] = useState(false) | ||
const [items, setItems] = useState(() => getItemsInitialState(listOfSrc)) | ||
const maxSelectable = Math.min( | ||
maxSelectablePreferenceByUser, | ||
items.filter(item => !item.sizeError && !item.aspectRatioError && !item.fetchError).length | ||
) | ||
const numberOfCheckedItems = items.filter(item => item.checked).length | ||
const isMaxSelectableReached = numberOfCheckedItems >= maxSelectable | ||
const itemsAreReady = items.every(item => !item.loading) | ||
|
||
const config = { maxSizeInMB, minAspectRatio, maxAspectRatio, maxSelectable } | ||
const status = { isDraggingActive, isMaxSelectableReached, itemsAreReady, numberOfCheckedItems } | ||
|
||
useEffect(() => { | ||
if (!onChange) return | ||
|
||
onChange(items) | ||
}, [items]) | ||
|
||
useEffect(() => { | ||
if (!itemsAreReady) return | ||
|
||
const updatedItems = fillCheckedItems(items, maxSelectable) | ||
setItems(updatedItems) | ||
}, [itemsAreReady]) | ||
|
||
const handleClickItem = useCallback((targetItem) => { | ||
const isUnclickable = !isItemClickable(targetItem, isMaxSelectableReached) | ||
if (isUnclickable) return | ||
|
||
const updatedItems = targetItem.checked | ||
? getUpdatedItemsWithDecrement(items, targetItem) | ||
: getUpdatedItemsWithIncrement(items, targetItem) | ||
|
||
const refreshedItems = refreshItemsPosition(updatedItems) | ||
setItems(refreshedItems) | ||
}, [isMaxSelectableReached, items]) | ||
|
||
const handleSelectAll = useCallback(() => { | ||
const newItems = getSelectAllItems(items, maxSelectable) | ||
const refreshedItems = refreshItemsPosition(newItems) | ||
setItems(refreshedItems) | ||
}, [items, maxSelectable]) | ||
|
||
const handleDeselectAll = useCallback(() => { | ||
const newItems = getDeselectAllItems(items) | ||
setItems(newItems) | ||
}, [items]) | ||
|
||
const handleUpdateItem = useCallback(({ id, ...restOfKeys }) => { | ||
const newItems = items.map(item => item.id === id | ||
? { ...item, ...restOfKeys } | ||
: item | ||
) | ||
setItems(newItems) | ||
}, [items]) | ||
|
||
const handleDragStart = () => { | ||
setIsDraggingActive(true) | ||
} | ||
|
||
const handleDragEnd = ({ active, over }) => { | ||
setIsDraggingActive(false) | ||
if (active.id === over.id) return | ||
|
||
const oldIndex = items.findIndex(item => item.id === active.id) | ||
const newIndex = items.findIndex(item => item.id === over.id) | ||
const reorderedItems = arrayMove(items, oldIndex, newIndex) | ||
const refreshedItems = refreshItemsPosition(reorderedItems) | ||
|
||
setItems(refreshedItems) | ||
} | ||
|
||
return { | ||
attributes: { items, config, status }, | ||
methods: { | ||
handleClickItem, | ||
handleUpdateItem, | ||
handleDeselectAll, | ||
handleSelectAll, | ||
handleDragStart, | ||
handleDragEnd, | ||
}, | ||
} | ||
} | ||
|
||
export default useGridImagePicker |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { useEffect, useState } from 'react' | ||
|
||
function useSize (src) { | ||
const [data, setData] = useState({ | ||
size: 0, | ||
loading: true, | ||
error: false, | ||
}) | ||
|
||
useEffect(() => { | ||
const fetchImageSize = async (src) => { | ||
try { | ||
setData({ size: 0, loading: true, error: false }) | ||
const response = await window.fetch(src) | ||
const blob = await response.blob() | ||
|
||
const sizeInMegaBytes = (blob.size / 1024) / 1024 | ||
|
||
setData({ size: sizeInMegaBytes, loading: false, error: false }) | ||
} catch (error) { | ||
console.error(error) | ||
setData({ size: 0, loading: false, error: true }) | ||
} | ||
} | ||
|
||
if (src) { | ||
fetchImageSize(src) | ||
} | ||
}, [src]) | ||
|
||
return [data.size, data.loading, data.error] | ||
} | ||
|
||
export default useSize |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
{ | ||
"name": "@oneloop/gridimagepicker", | ||
"version": "1.0.0", | ||
"main": "lib/index.js", | ||
"module": "src/index.js", | ||
"files": [ | ||
"lib" | ||
], | ||
"dependencies": { | ||
"@oneloop/box": "^1.2.285", | ||
"@oneloop/icons": "^1.2.309", | ||
"@dnd-kit/core": "^6.0.8", | ||
"@dnd-kit/sortable": "^7.0.2", | ||
"@dnd-kit/modifiers": "^7.0.0", | ||
"@dnd-kit/utilities": "^3.2.2" | ||
}, | ||
"peerDependencies": { | ||
"react": "^16.8.0" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"gitHead": "d65c6a2618eac0470ecc4f462e8905e0aaf1bd9d" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import React from 'react' | ||
import { GridImagePicker } from '.' | ||
|
||
// 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAIAAAD8GO2jAAAAKUlEQVR4nO3NMQEAAAjDMED5pGMCvlRA00nqs3m9AwAAAAAAAAAAgMMWvj0BwDVKG0sAAAAASUVORK5CYII=', | ||
// 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEAAAAAgCAIAAAAt/+nTAAAAQElEQVR4nO3PQQ0AIBDAMED5SUcEj4ZkVbDtmVk/OzrgVQNaA1oDWgNaA1oDWgNaA1oDWgNaA1oDWgNaA1oD2gVLaQHAY0QxtQAAAABJRU5ErkJggg==', | ||
// 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAACACAIAAADlBPxNAAAASUlEQVR4nO3NMQEAAAjDMED5pKMCrlRA00nqsjm9AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB4ABYzLwKAkfv2VAAAAABJRU5ErkJggg==' | ||
|
||
const INSTAGRAM_RECOMMENDED_MIN_ASPECT_RATIO = 4 / 5 | ||
const INSTAGRAM_RECOMMENDED_MAX_ASPECT_RATIO = 1.91 / 1 | ||
|
||
export default { | ||
component: GridImagePicker, | ||
title: 'GridImagePicker', | ||
} | ||
|
||
export const normal = () => ( | ||
<GridImagePicker | ||
minAspectRatio={INSTAGRAM_RECOMMENDED_MIN_ASPECT_RATIO} | ||
maxAspectRatio={INSTAGRAM_RECOMMENDED_MAX_ASPECT_RATIO} | ||
listOfSrc={[ | ||
'https://images.pexels.com/photos/39866/entrepreneur-startup-start-up-man-39866.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500', | ||
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcREoRGyXmHy_6aIgXYqWHdOT3KjfmnuSyxypw&s', | ||
'https://img-cdn.pixlr.com/image-generator/history/65bb506dcb310754719cf81f/ede935de-1138-4f66-8ed7-44bd16efc709/medium.webp', | ||
'https://images.pexels.com/photos/1054666/pexels-photo-1054666.jpeg?cs=srgb&dl=pexels-hsapir-1054666.jpg&fm=jpg', | ||
'https://letsenhance.io/static/8f5e523ee6b2479e26ecc91b9c25261e/1015f/MainAfter.jpg', | ||
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRQYq7qbO4AdXp0gXMxvGmnVSc-8OlsMSGrNw&s', | ||
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQq10gYXsQjI1uLya6MjHpGkLIX5kzVNQYOaQ&s', | ||
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTwB8-oiew0oNWLIPqQGPhcNJOYEzkaPKAbXw&s', | ||
'https://b.thumbs.redditmedia.com/s-QXg7UUFth82jkXneJB5ahQMdyCsIhG0eAL-iFBRlU.jpg', | ||
'https://media.vandal.net/i/640x360/10-2023/17/202310171652270_2.jpg', | ||
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRb3Nakk8OPx919ZVYgOxBq_FFapYcAEVQdBQ&s', | ||
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQHKxBCtsEIetdYRldyKjADBJ88W_gk_Sh3qg&s', | ||
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTGbUyUaLlMBdDIiUzN-v1yaBhAk24zzVaRNg&s', | ||
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRuj-4zb0fZ8bRiVZ3JhkNcm3iU26Oj42HwVg&s', | ||
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRBExwuuCqBEPFxceL1tTggoj8XaYvxr0X2hA&s', | ||
'https://cdn.britannica.com/05/187505-131-7E335F18/Benedict-Cumberbatch-2014.jpg', | ||
]} | ||
/> | ||
) |
Oops, something went wrong.