Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
import { config, animated, useSpring } from 'react-spring';
import { useDrag } from 'react-use-gesture';
import clsx from 'clsx';
import { disableBodyScroll, enableBodyScroll } from 'body-scroll-lock';
import _ from 'lodash';
interface Props {
header?: React.ReactNode | ((args: { onClose(): void }) => React.ReactNode);
footer?: React.ReactNode | ((args: { onClose(): void }) => React.ReactNode);
children?: React.ReactNode | ((args: { onClose(): void }) => React.ReactNode);
sheetClassName?: string;
onClose(): void;
}
const spring = {
...config.stiff,
clamp: true
};
// The sheet is dismissed if it's flicked at a velocity above dismissVelocity or dragged down more than dismissAmount times the height of the sheet.
const dismissVelocity = 0.8;
const dismissAmount = 0.5;
// Disable body scroll on mobile
const mobile = /iPad|iPhone|iPod|Android/.test(navigator.userAgent);
const stopPropagation = (e) => e.stopPropagation();
/**
* A Sheet is a UI element that comes up from the bottom of the scren, and can be dragged to dismiss.
*/
export default function Sheet({
export default function DraggableList({
items = 'Lorem ipsum dolor sit'.split(' '),
}) {
const order = useRef(items.map((_, index) => index)) // Store indicies as a local ref, this represents the item order
const [springs, setSprings] = useSprings(items.length, fn(order.current)) // Create springs, each corresponds to an item, controlling its transform, scale, etc.
const bind = useDrag(({ args: [originalIndex], down, movement: [, y] }) => {
const curIndex = order.current.indexOf(originalIndex)
const curRow = clamp(
Math.round((curIndex * 100 + y) / 100),
0,
items.length - 1
)
const newOrder = swap(order.current, curIndex, curRow)
setSprings(fn(newOrder, down, originalIndex, curIndex, y)) // Feed springs new style data, they'll animate the view without causing a single render
if (!down) order.current = newOrder
})
return (
<div style="{{">
{springs.map(({ zIndex, shadow, y, scale }, i) => (</div>
export default function App() {
const [open, set] = useState(false)
// 1. create spring-refs, which will refer to the springs Controller
const springRef = useRef()
const { size, opacity, ...rest } = useSpring({
from: { size: '20%', background: 'hotpink' },
size: open ? '80%' : '20%',
background: open ? 'white' : 'hotpink',
config: { ...config.stiff, precision: 0.01 },
ref: springRef,
})
// 2. create transition-refs
const transRef = useRef()
const transitions = useTransition(open ? data : [], item => item.name, {
from: { opacity: 0, transform: 'scale(0)' },
enter: { opacity: 1, transform: 'scale(1)' },
leave: { opacity: 0, transform: 'scale(0)' },
trail: 400 / data.length,
config: { ...config.stiff, precision: 0.01, cancelDelay: true },
unique: true,
const HeaderLoadingIndicator: React.FC = ({ loading, label, ratio, ...props }) => {
const [prevLabel, setPrevLabel] = useState(undefined);
if (label !== prevLabel) {
setPrevLabel(label);
}
const spring = useSpring({
backgroundColor: loading ? properties.colorsValue.grayDark : properties.colorsBlanding.accent,
});
const trans = useTransition([label, prevLabel], t => t || '', {
from: { opacity: 0, transform: `translate3d(0, -100%, 0)` },
enter: { opacity: 1, transform: `translate3d(0, 0, 0)` },
// tslint:disable-next-line:jsx-alignment
leave: { opacity: 0, transform: `translate3d(0, 100%, 0)` },
});
return (
<content>
{loading ? : undefined}
{trans.map(({ item, props, key }) => (
<label style="{props}"></label></content>
import { animated } from 'react-spring'
import styled from 'styled-components'
import { Moon } from 'styled-icons/fa-solid/Moon'
import { Sun } from 'styled-icons/fa-solid/Sun'
export const Box = styled.div`
display: grid;
> * {
/* for vertical centering */
display: flex;
grid-area: 1/1;
}
`
// Needed as a selector in Notification below.
export const Div = styled(animated.div)``
export const Notification = styled.div`
color: white;
a {
color: ${props => props.theme.lighterBlue};
}
position: absolute;
top: calc(100% + 1em);
width: max-content;
max-width: 5em;
text-align: center;
background: rgba(0, 0, 0, 0.9);
padding: 0.1em 0.3em;
border-radius: 0.2em;
left: 50%;
transform: translateX(-50%);
const selected = useSelector(
(state) => state.street.environment || DEFAULT_ENVIRONS
)
const show = useSelector((state) => state.ui.toolboxVisible || false)
const dispatch = useDispatch()
const handleClick = (event, env) => {
dispatch(setEnvironment(env.id))
}
const handleClose = (event) => {
dispatch(toggleToolbox())
}
const envs = getAllEnvirons()
const transitions = useTransition(show, null, {
from: { opacity: 0, transform: 'scale(0.75)', pointerEvents: 'none' },
enter: { opacity: 1, transform: 'scale(1)', pointerEvents: 'auto' },
leave: { opacity: 0, transform: 'scale(0.85)', pointerEvents: 'none' },
config: { tension: 600, velocity: 20, clamp: true }
})
return transitions.map(
({ item, key, props }) =>
item && (
{/* Two containers are necessary because different libraries are applying CSS transforms */}
{/* Outer container is transformed by Draggable's position */}
<div>
{/* Inner container contains transition styles from Transition */}
</div>
}, [props.alerts])
const transitionConfigs: any = {
from: { height: 0, opacity: 0, life: "100%" },
enter: (item: AlertProps) => async (next: any) =>
await next({ height: refMap.get(item).offsetHeight, opacity: 1 }),
leave: (item: AlertProps) => async (next: any, cancel: any) => {
cancelMap.set(item, cancel)
await next({ life: "0%" })
await next({ opacity: 0 })
await next({ height: 0 })
},
config: config,
}
const transitionProps = useTransition(
alerts,
item => item.key as string,
transitionConfigs
)
// Return container based on placement prop
const getWrapper = () => {
switch (props.placement) {
case "topLeft":
return TopLeftBox
case "topRight":
return TopRightBox
case "bottomLeft":
return BottomLeftBox
case "bottomRight":
return BottomRightBox
// interpolate(
// [bgRad, bgPos],
// (bgRad, bgPos) =>
// `linear-gradient(${90+bgRad}deg, rgb(0, 0, 0, 0.3) 0%,rgba(184, 184, 184, 0) ${300-bgPos}px)`
// )
WebkitClipPath: interpolate(
[x1, y1, x2, y2, x3, y3, x4, y4, x5, y5],
(x1, y1, x2, y2, x3, y3, x4, y4, x5, y5) => {
if (x5 === undefined) x5 = x4;
if (y5 === undefined) y5 = y4;
return `polygon(${x1}px ${y1}px, ${x2}px ${y2}px, ${x3}px ${y3}px, ${x4}px ${y4}px, ${x5}px ${y5}px )`;
}
),
transformOrigin: i % 2 === 0 ? pageWidth + "px 0px" : "0px 0px",
transform: interpolate(
[x, y, r, scaleX],
(x, y, r, scaleX) =>
`translateX(${x}px) translateY(${y}px) rotate(${r}rad) scaleX(${scaleX})`
)
}}
className={`page page--${i} `}
{...bind(i)}
>
<div></div>
{false && i === index.value + 2 && (
if (Array.isArray(prop)) {
let transformProps: string[] = [];
let transformUnits: string[] = [];
const result = prop.map(styles => {
const [transformProp] = Object.keys(styles);
transformProps.push(transformProp);
const { unit = '', ...rest } = styles[transformProp];
transformUnits.push(unit);
return offset.interpolate(rest);
});
const transformStyle = interpolate(result, (...values) =>
values
.map((value, index) => {
return `${transformProps[index]}(${value}${transformUnits[index]})`;
})
.join(' ')
);
style[key] = transformStyle;
}
// e.g opacity: { range, output => -1 -> 0.1}
else if (typeof prop === 'object') {
style[key] = offset
.interpolate(prop)
// @ts-ignore
.interpolate(val => `${val}`);
}
return props.map(({x, y, rot, scale}, i) => (
`translate3d(${x}px,${y}px,0)`)}}>
{/* This is the card itself, we're binding our gesture to it (and inject its index so we know which is which) */}
))
}