diff --git a/example/src/SelectablePig.js b/example/src/SelectablePig.js
new file mode 100644
index 0000000..0e000ff
--- /dev/null
+++ b/example/src/SelectablePig.js
@@ -0,0 +1,98 @@
+import React, { Component } from "react";
+import Pig from "pig-react";
+import imageData from "./imageData.json";
+
+export default class SelectablePig extends Component {
+ constructor(props) {
+ super(props)
+ this.imageData = imageData
+ this.state = {
+ selectedItems: []
+ }
+ }
+
+ handleSelection = item => {
+ let newSelectedItems = this.state.selectedItems;
+ if (newSelectedItems.find(selectedItem => selectedItem.id === item.id)) {
+ newSelectedItems = newSelectedItems.filter(value => value.id !== item.id)
+ } else {
+ newSelectedItems = newSelectedItems.concat(item)
+ }
+ this.setState({ selectedItems: newSelectedItems })
+ };
+
+ handleSelections = items => {
+ let newSelectedItems = this.state.selectedItems;
+ items.forEach(item => {
+ if (newSelectedItems.find(selectedItem => selectedItem.id === item.id)) {
+ newSelectedItems = newSelectedItems.filter(value => value.id !== item.id)
+ } else {
+ newSelectedItems = newSelectedItems.concat(item)
+ }
+ });
+ this.setState({ selectedItems: newSelectedItems })
+ };
+
+ handleClick = (event, item) => {
+ //if an image is selectabel, then handle shift click
+ if (event.shiftKey) {
+ let lastSelectedElement = this.state.selectedItems.slice(-1)[0]
+ if (lastSelectedElement === undefined) {
+ this.handleSelection(item)
+ return;
+ }
+ let indexOfCurrentlySelectedItem = this.imageData.findIndex(image => image.id === item.id)
+ let indexOfLastSelectedItem = this.imageData.findIndex(image => image.id === lastSelectedElement.id)
+ if (indexOfCurrentlySelectedItem > indexOfLastSelectedItem) {
+ this.handleSelections(
+ this.imageData.slice(
+ indexOfLastSelectedItem + 1,
+ indexOfCurrentlySelectedItem + 1
+ )
+ );
+ return;
+ } else {
+ this.handleSelections(
+ this.imageData.slice(
+ indexOfCurrentlySelectedItem,
+ indexOfLastSelectedItem
+ )
+ )
+ return
+ }
+ }
+ // if an image is already selected, then we are in selection mode
+ if (this.state.selectedItems.length > 0) {
+ this.handleSelection(item)
+ return
+ }
+
+ // if an image is already the width of the container, don't expand it on click
+ if (item.style.width >= this.containerWidth) {
+ this.setState({ activeTileUrl: null })
+ return
+ }
+
+ this.setState({
+ // if Tile is already active, deactivate it
+ activeTileUrl: item.url !== this.state.activeTileUrl ? item.url : null
+ })
+ }
+
+ render() {
+ return (
+
+ )
+ }
+}
diff --git a/example/src/index.js b/example/src/index.js
index 13df94e..d48a166 100644
--- a/example/src/index.js
+++ b/example/src/index.js
@@ -1,22 +1,26 @@
import React from 'react'
import ReactDOM from 'react-dom'
import Pig from 'pig-react'
+import SelectablePig from './SelectablePig'
import imageData from './imageData.json'
import './base.css'
ReactDOM.render(
+ {
+ //
+ }
, document.getElementById('root'))
diff --git a/src/components/Tile/Tile.js b/src/components/Tile/Tile.js
index 7da6cd8..21a51f3 100644
--- a/src/components/Tile/Tile.js
+++ b/src/components/Tile/Tile.js
@@ -13,11 +13,15 @@ const Tile = React.memo(function Tile({
getUrl,
activeTileUrl,
handleClick,
+ handleSelection,
+ selected,
+ selectable,
windowHeight,
scrollSpeed,
settings,
}) {
-
+ const isSelectable = selectable
+ const isSelected = selected
const isExpanded = activeTileUrl === item.url
const isVideo = item.url.includes('.mp4') || item.url.includes('.mov')
const [isFullSizeLoaded, setFullSizeLoaded] = useState(isVideo ? true : false)
@@ -29,12 +33,16 @@ const Tile = React.memo(function Tile({
// screenCenter is positioning logic for when the item is active and expanded
const screenCenter = `translate3d(${offsetX}px, ${offsetY}px, 0)`
- const { width, height, transform, zIndex } = useSpring({
+ const { width, height, transform, zIndex, marginLeft, marginRight, marginTop, marginBottom } = useSpring({
transform: isExpanded ? screenCenter : gridPosition,
zIndex: isExpanded ? 10 : 0, // 10 so that it takes a little longer before settling at 0
- width: isExpanded ? Math.ceil(calcWidth) + 'px' : item.style.width + 'px',
- height: isExpanded ? Math.ceil(calcHeight) + 'px' : item.style.height + 'px',
- config: { mass: 1.5, tension: 400, friction: 40 }
+ width: isExpanded ? Math.ceil(calcWidth) + 'px' : isSelected ? item.style.width - item.style.width * 0.1 + 'px' : item.style.width + 'px',
+ height: isExpanded ? Math.ceil(calcHeight) + 'px' : isSelected ? item.style.height - item.style.height * 0.1 + 'px' : item.style.height + 'px',
+ config: { mass: 1.5, tension: 400, friction: 40 },
+ marginLeft: isSelected && !isExpanded ? item.style.width * 0.05 : 0,
+ marginRight: isSelected && !isExpanded ? item.style.width * 0.05 : 0,
+ marginTop: isSelected && !isExpanded ? item.style.height * 0.05 : 0,
+ marginBottom: isSelected && !isExpanded ? item.style.height * 0.05 : 0,
})
return (
@@ -47,7 +55,11 @@ const Tile = React.memo(function Tile({
zIndex: zIndex.interpolate(t => Math.round(t)),
width: width.interpolate(t => t),
height: height.interpolate(t => t),
- transform: transform.interpolate(t => t)
+ transform: transform.interpolate(t => t),
+ marginLeft: marginLeft.interpolate(t => t),
+ marginRight: marginRight.interpolate(t => t),
+ marginTop: marginTop.interpolate(t => t),
+ marginBottom: marginBottom.interpolate(t => t)
}}
>
@@ -62,7 +74,7 @@ const Tile = React.memo(function Tile({
alt=""
/>
}
-
+
{(scrollSpeed === 'slow' ) && !isVideo &&
// grid image
)}
-
+
{isExpanded && isVideo && (
// full size expanded video
)}
+ {isSelectable && (
+ {
+ event.stopPropagation()
+ handleSelection(item)
+ }}
+ >
+ )}
)
})
diff --git a/src/components/Tile/styles.css b/src/components/Tile/styles.css
index 3e99985..ec1285d 100644
--- a/src/components/Tile/styles.css
+++ b/src/components/Tile/styles.css
@@ -68,7 +68,7 @@
width: 100%;
padding: 8px;
} */
-/*
+/*
.caption::after {
content: '';
background-image: linear-gradient(transparent,rgba(0,0,0,.105),rgba(0,0,0,.4));
@@ -79,3 +79,26 @@
position: absolute;
z-index: -1;
} */
+
+.pigBtn:hover .checkbox {
+ opacity: 0.5;
+ transition: all 200ms linear;
+}
+
+.pigBtn:hover .checkbox:checked {
+ opacity: 1;
+}
+
+.checkbox {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ opacity: 0;
+}
+
+.checkbox:checked {
+ position: absolute;
+ top: 0px;
+ left: 0px;
+ opacity: 1;
+}
diff --git a/src/index.js b/src/index.js
index a70205c..caf21ac 100644
--- a/src/index.js
+++ b/src/index.js
@@ -27,6 +27,9 @@ export default class Pig extends Component {
this.imageData = props.imageData
+ this.selectable = props.selectable || false
+ this.handleSelection = props.handleSelection || this.defaultHandleSelection
+
// if sortFunc has been provided as a prop, use it
if (props.sortFunc) this.imageData.sort(props.sortFunc)
else if (props.sortByDate) this.imageData = sortByDate(this.imageData)
@@ -44,6 +47,7 @@ export default class Pig extends Component {
this.state = {
renderedItems: [],
+ selectedItems: [],
scrollSpeed: 'slow',
activeTileUrl: null
}
@@ -95,6 +99,16 @@ export default class Pig extends Component {
this.setState({ renderedItems })
}
+ defaultHandleSelection = (item) => {
+ let newSelectedItems = this.state.selectedItems
+ if (newSelectedItems.includes(item)) {
+ newSelectedItems = newSelectedItems.filter(value => value !== item)
+ } else {
+ newSelectedItems = newSelectedItems.concat(item)
+ }
+ this.setState({selectedItems : newSelectedItems})
+ };
+
onScroll = () => {
this.previousYOffset = this.latestYOffset || window.pageYOffset
this.latestYOffset = window.pageYOffset
@@ -108,7 +122,7 @@ export default class Pig extends Component {
this.setState({ scrollSpeed }) // scroll idle callback
})
this.setState({ scrollSpeed })
-
+
// dismiss any active Tile
if (this.state.activeTileUrl) this.setState({ activeTileUrl: null })
})
@@ -197,6 +211,9 @@ export default class Pig extends Component {
activeTileUrl: item.url !== this.state.activeTileUrl ? item.url : null
})
}}
+ handleSelection={this.handleSelection}
+ selectable={this.selectable}
+ selected={this.props.selectedItems ? this.props.selectedItems.find(selectedItem => selectedItem.id === item.id) : this.state.selectedItems.includes(item)}
activeTileUrl={this.state.activeTileUrl}
settings={this.settings}
thumbnailSize={this.props.thumbnailSize}