From 44f98310c0f649ad61a59cd5927cb3fffee7584c Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Tue, 9 Jul 2019 21:44:26 -0400 Subject: [PATCH 01/43] feat: rework useTransition --- packages/core/src/legacy.js | 13 +- packages/core/src/useTransition.d.ts | 124 ------------ packages/core/src/useTransition.js | 272 --------------------------- packages/core/src/useTransition.tsx | 209 ++++++++++++++++++++ 4 files changed, 211 insertions(+), 407 deletions(-) delete mode 100644 packages/core/src/useTransition.d.ts delete mode 100644 packages/core/src/useTransition.js create mode 100644 packages/core/src/useTransition.tsx diff --git a/packages/core/src/legacy.js b/packages/core/src/legacy.js index 2683556cb5..586499569e 100644 --- a/packages/core/src/legacy.js +++ b/packages/core/src/legacy.js @@ -16,15 +16,6 @@ export function Trail({ items, children, ...props }) { }) } -export function Transition({ items, keys = null, children, ...props }) { - const transitions = useTransition(items, keys, props) - return transitions.map(({ item, key, props, phase }, index) => { - const result = children(item, phase, index) - const element = is.fun(result) ? result(props) : result - return element && element.type ? ( - - ) : ( - element - ) - }) +export function Transition({ items, children, ...props }) { + return useTransition(items, props)(children) } diff --git a/packages/core/src/useTransition.d.ts b/packages/core/src/useTransition.d.ts deleted file mode 100644 index 1b53c459ac..0000000000 --- a/packages/core/src/useTransition.d.ts +++ /dev/null @@ -1,124 +0,0 @@ -import { Solve, TransitionPhase, UnknownProps } from './types/common' -import { - SpringAsyncFn, - SpringConfig, - SpringUpdate, - SpringValues, -} from './types/spring' - -export type ItemsProp = ReadonlyArray | T | null | undefined -export type ItemKeys = - | ((item: T) => string | number) - | ReadonlyArray - | string - | number - | null - -/** - * Animate a set of values whenever one changes. - * - * The returned array can be safely mutated. - */ -export declare function useTransition< - Item, - Props extends UnknownProps & UseTransitionProps ->( - items: ItemsProp, - keys: ItemKeys, - props: Props -): ItemTransition[] - -/** The transition state of a single item */ -export type ItemTransition = Solve<{ - key: string | number - item: Item - phase: TransitionPhase - props: SpringValues -}> - -/** For props that provide animated keys */ -type TransitionProp = - | SpringUpdate - | readonly SpringUpdate[] - | ((item: Item) => SpringUpdate | SpringAsyncFn) - -export type UseTransitionProps = { - /** - * Base values (from -> enter), or: item => values - * @default {} - */ - from?: TransitionProp - /** - * Values that apply to new elements, or: item => values - * @default {} - */ - enter?: TransitionProp - /** - * Values that apply to leaving elements, or: item => values - * @default {} - */ - leave?: TransitionProp - /** - * Values that apply to elements that are neither entering nor leaving (you - * can use this to update present elements), or: item => values - */ - update?: TransitionProp - /** - * First-render initial values, if present overrides "from" on the first - * render pass. It can be "null" to skip first mounting transition. Otherwise - * it can take an object or a function (item => object) - */ - initial?: TransitionProp | null - /** - * Configure the spring behavior for each item. - */ - config?: SpringConfig | ((item: Item, phase: TransitionPhase) => SpringConfig) - /** - * The same keys you would normally hand over to React in a list. - */ - keys?: - | ((item: Item) => string | number) - | ReadonlyArray - | string - | number - /** - * When this and `unique` are both true, items in the "enter" phase start from - * their values in the "from" prop instead of their current positions. - */ - reset?: boolean - /** - * Milliseconds of delay before animating the next item. - * - * This applies to all transition phases. - */ - trail?: number - /** - * When true, no two items can have the same key. Reuse any items that - * re-enter before they finish leaving. - */ - unique?: boolean - /** - * Called when an animation is about to start - */ - onStart?: (item: Item, phase: TransitionPhase, animation: any) => void - /** - * Called when all animations come to a stand-still - */ - onRest?: ( - item: Item, - phase: TransitionPhase, - restValues: UnknownProps - ) => void - /** - * Called on every frame when animations are active - */ - onFrame?: ( - item: Item, - phase: TransitionPhase, - currentValues: UnknownProps - ) => void - /** - * Called after an object has finished its "leave" transition - */ - onDestroyed?: (item: Item) => void -} diff --git a/packages/core/src/useTransition.js b/packages/core/src/useTransition.js deleted file mode 100644 index cda8f1c3f1..0000000000 --- a/packages/core/src/useTransition.js +++ /dev/null @@ -1,272 +0,0 @@ -import { useRef, useEffect, useMemo, useImperativeHandle } from 'react' -import { callProp, interpolateTo, reconcileDeleted } from './helpers' -import { is, toArray, useForceUpdate, useOnce } from 'shared' -import { Controller } from './Controller' - -/** API - * const transitions = useTransition(items, itemKeys, { ... }) - * const [transitions, update] = useTransition(items, itemKeys, () => ({ ... })) - */ - -let guid = 0 - -const INITIAL = 'initial' -const ENTER = 'enter' -const UPDATE = 'update' -const LEAVE = 'leave' - -const makeKeys = (items, keys) => - (typeof keys === 'function' ? items.map(keys) : toArray(keys)).map(String) - -const makeConfig = props => { - let { items, keys, ...rest } = props - items = toArray(is.und(items) ? null : items) - return { items, keys: makeKeys(items, keys), ...rest } -} - -export function useTransition(input, keyTransform, props) { - props = makeConfig({ - ...props, - items: input, - keys: keyTransform || (i => i), - }) - const { - lazy = false, - unique = false, - from, - enter, - leave, - update, - onDestroyed, - keys, - items, - onFrame, - onRest, - onStart, - ref, - ...extra - } = props - - const forceUpdate = useForceUpdate() - const mounted = useRef(false) - const state = useRef({ - mounted: false, - first: true, - deleted: [], - current: {}, - transitions: [], - prevProps: {}, - paused: !!ref, - instances: !mounted.current && new Map(), - forceUpdate, - }) - - useImperativeHandle(ref, () => ({ - start: () => - Promise.all( - Array.from(state.current.instances).map( - ([, c]) => new Promise(r => c.start(r)) - ) - ), - stop: finished => - Array.from(state.current.instances).forEach(([, c]) => c.stop(finished)), - get controllers() { - return Array.from(state.current.instances).map(([, c]) => c) - }, - })) - - // Update state - state.current = diffItems(state.current, props) - if (state.current.changed) { - // Update state - state.current.transitions.forEach(transition => { - const { phase, key, item, props } = transition - if (!state.current.instances.has(key)) - state.current.instances.set(key, new Controller()) - - // Avoid calling `onStart` more than once per transition. - let started = false - - // update the map object - const ctrl = state.current.instances.get(key) - const itemProps = { - ...extra, - ...props, - onRest: values => { - if (state.current.mounted) { - if (transition.destroyed) { - // If no ref is given delete destroyed items immediately - if (!ref && !lazy) cleanUp(state, key) - if (onDestroyed) onDestroyed(item) - } - - // A transition comes to rest once all its springs conclude - const curInstances = Array.from(state.current.instances) - const active = curInstances.some(([, c]) => !c.idle) - if (!active && (ref || lazy) && state.current.deleted.length > 0) { - cleanUp(state) - } - if (is.fun(onRest)) { - onRest(item, phase, values) - } - } - }, - onFrame: is.fun(onFrame) && (values => onFrame(item, phase, values)), - onStart: - is.fun(onStart) && - (animation => - started || (started = (onStart(item, phase, animation), true))), - } - - // Update controller - ctrl.update(itemProps) - if (!state.current.paused) ctrl.start() - }) - } - - useOnce(() => { - state.current.mounted = mounted.current = true - return () => { - state.current.mounted = mounted.current = false - Array.from(state.current.instances).map(([, c]) => c.destroy()) - state.current.instances.clear() - } - }) - - return state.current.transitions.map(({ item, phase, key }) => { - return { - item, - key, - phase, - props: { ...state.current.instances.get(key).animated }, - } - }) -} - -function cleanUp({ current: state }, filterKey) { - const { deleted } = state - for (let { key } of deleted) { - const filter = t => t.key !== key - if (is.und(filterKey) || filterKey === key) { - state.instances.delete(key) - state.transitions = state.transitions.filter(filter) - state.deleted = state.deleted.filter(filter) - } - } - state.forceUpdate() -} - -function diffItems({ first, current, deleted, prevProps, ...state }, props) { - let { - items, - keys, - initial, - from, - enter, - leave, - update, - trail = 0, - unique, - config, - order = [ENTER, LEAVE, UPDATE], - } = props - let { keys: _keys, items: _items } = makeConfig(prevProps) - - if (props.reset) { - current = {} - state.transitions = [] - } - - // Compare next keys with current keys - const currentKeys = Object.keys(current) - const currentSet = new Set(currentKeys) - const nextSet = new Set(keys) - - const addedKeys = keys.filter(key => !currentSet.has(key)) - const updatedKeys = update ? keys.filter(key => currentSet.has(key)) : [] - const deletedKeys = state.transitions - .filter(t => !t.destroyed && !nextSet.has(t.originalKey)) - .map(t => t.originalKey) - - let delay = -trail - - while (order.length) { - let phase = order.shift() - if (phase === ENTER) { - if (first && !is.und(initial)) { - phase = INITIAL - from = initial - } - addedKeys.forEach(key => { - // In unique mode, remove fading out transitions if their key comes in again - if (unique && deleted.find(d => d.originalKey === key)) { - deleted = deleted.filter(t => t.originalKey !== key) - } - const i = keys.indexOf(key) - const item = items[i] - const enterProps = callProp(enter, item, i) - current[key] = { - phase, - originalKey: key, - key: unique ? String(key) : guid++, - item, - props: { - delay: (delay += trail), - config: callProp(config, item, phase), - from: callProp(from, item, i), - to: enterProps, - ...(is.obj(enterProps) && interpolateTo(enterProps)), - }, - } - }) - } else if (phase === LEAVE) { - deletedKeys.forEach(key => { - const i = _keys.indexOf(key) - const item = _items[i] - const leaveProps = callProp(leave, item, i) - deleted.push({ - ...current[key], - phase, - destroyed: true, - left: _keys[i - 1], - right: _keys[i + 1], - props: { - delay: (delay += trail), - config: callProp(config, item, phase), - to: leaveProps, - ...(is.obj(leaveProps) && interpolateTo(leaveProps)), - }, - }) - delete current[key] - }) - } else if (phase === UPDATE) { - updatedKeys.forEach(key => { - const i = keys.indexOf(key) - const item = items[i] - const updateProps = callProp(update, item, i) - current[key] = { - ...current[key], - phase, - props: { - delay: (delay += trail), - config: callProp(config, item, phase), - to: updateProps, - ...(is.obj(updateProps) && interpolateTo(updateProps)), - }, - } - }) - } - } - let out = keys.map(key => current[key]) - out = reconcileDeleted(deleted, out) - - return { - ...state, - first: first && !addedKeys.length, - changed: !!(addedKeys.length || deletedKeys.length || updatedKeys.length), - transitions: out, - current, - deleted, - prevProps: props, - } -} diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx new file mode 100644 index 0000000000..f2b39b7a56 --- /dev/null +++ b/packages/core/src/useTransition.tsx @@ -0,0 +1,209 @@ +import React, { useEffect, useRef, useImperativeHandle, ReactNode } from 'react' +import { is, toArray, useForceUpdate, useOnce } from 'shared' +import { callProp, interpolateTo } from './helpers' +import { Controller } from './Controller' +import { now } from 'shared/globals' + +export function useTransition( + data: T | readonly T[], + props: any, + deps?: any +) { + const { ref, reset } = props + const { transitions, changes } = useDiff(data, props) + + useEffect( + () => { + changes.forEach(({ phase, payload }, t) => { + t.phase = phase + if (payload) t.spring.update(payload) + if (!ref) t.spring.start() + }) + }, + reset ? void 0 : deps + ) + + const render = (render: (props: any, item: T) => ReactNode) => + transitions.map(t => { + const elem: any = render({ ...t.spring.animated }, t.item) + return elem && elem.type ? ( + + ) : ( + elem + ) + }) + + return render +} + +interface State { + transitions: Transition[] + changes: Map, Change> +} + +interface Change { + phase: Phase + payload?: any +} + +interface Transition { + id: number + item: T + phase: Phase + spring: Controller + /** Destroy no later than this date */ + expiresBy?: number + expirationId?: number +} + +const enum Phase { + /** This transition is being mounted */ + Mount, + /** This transition is entering or has entered */ + Enter, + /** This transition had its animations updated */ + Update, + /** This transition will expire after animating */ + Leave, +} + +function useDiff(data: T | readonly T[], props: any): State { + const { reset, trail = 0, expires = Infinity } = props + + // Every item has its own transition. + const items = toArray(data) + const transitions: Transition[] = [] + + // The "onRest" callbacks need a ref to the latest transitions. + const usedTransitions = useRef(null) + const prevTransitions = usedTransitions.current + useEffect(() => { + usedTransitions.current = transitions + }) + + // Destroy all transitions on dismount. + useOnce(() => () => { + usedTransitions.current!.forEach(t => t.spring.destroy()) + }) + + // All items are new on first render. + let newItems = items + + // Track the first render for the "initial" prop. + const isFirst = reset || !prevTransitions + if (!isFirst) { + // Reuse old transitions unless expired. + prevTransitions!.forEach(t => { + if (is.und(t.expiresBy)) { + transitions.push(t) + } else { + clearTimeout(t.expirationId) + } + }) + + // Deduce which items are new. + const oldItems = transitions.map(t => t.item) + newItems = newItems.filter(item => oldItems.indexOf(item) < 0) + } + + // Append transitions for new items. + newItems.forEach(item => { + const spring = new Controller() + transitions.push({ id: spring.id, item, phase: Phase.Mount, spring }) + }) + + // Track cumulative delay for the "trail" prop. + let delay = -trail + + // Expired transitions use this to dismount. + const forceUpdate = useForceUpdate() + + // Generate changes to apply in useEffect. + const changes = new Map, Change>() + transitions.forEach((t, i) => { + let to: any + let phase: Phase + if (t.phase == Phase.Mount) { + to = (isFirst && props.initial) || props.enter + phase = Phase.Enter + } else { + const isDeleted = items.indexOf(t.item) < 0 + if (t.phase < Phase.Leave) { + if (isDeleted) { + to = props.leave + phase = Phase.Leave + } else if ((to = props.update)) { + phase = Phase.Update + } else return + } else if (!isDeleted) { + to = props.enter + phase = Phase.Enter + } else return + } + + const payload: any = { + // When "to" is a function, it can return (1) an array of "useSpring" props, + // (2) an async function, or (3) an object with any "useSpring" props. + to: to = callProp(to, t.item, i), + from: phase < Phase.Update ? callProp(props.from, t.item, i) : void 0, + delay: delay += trail, + config: callProp(props.config, t.item, i), + ...(is.obj(to) && interpolateTo(to)), + } + + const { onRest } = payload + payload.onRest = (values: any) => { + if (is.fun(onRest)) { + onRest(values) + } + if (t.phase == Phase.Leave) { + t.expiresBy = now() + expires + if (expires <= 0) { + forceUpdate() + } else { + // Postpone dismounts while other controllers are active. + const transitions = usedTransitions.current! + if (transitions.every(t => t.spring.idle)) { + forceUpdate() + } else if (expires < Infinity) { + t.expirationId = setTimeout(forceUpdate, expires) + } + } + } + } + + const change: Change = { phase } + changes.set(t, change) + + // To ensure all Animated nodes exist during render, + // the payload must be applied immediately for new items. + if (t.phase > Phase.Mount) { + change.payload = payload + } else { + t.spring.update(payload) + } + }) + + useImperativeHandle( + props.ref, + () => ({ + get controllers() { + return usedTransitions.current!.map(t => t.spring) + }, + start: () => + Promise.all( + usedTransitions.current!.map( + t => new Promise(done => t.spring.start(done)) + ) + ), + stop: (finished?: boolean) => + usedTransitions.current!.forEach(t => t.spring.stop(finished)), + }), + [] + ) + + return { + changes, + transitions, + } +} From 2ea13d01814dd95e8d7f755c4ec2fa5c7adb532b Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Wed, 10 Jul 2019 14:20:19 -0400 Subject: [PATCH 02/43] refactor: remove pointless useDiff function --- packages/core/src/useTransition.tsx | 113 ++++++++++++---------------- 1 file changed, 48 insertions(+), 65 deletions(-) diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index f2b39b7a56..889d8dc3fa 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -9,66 +9,7 @@ export function useTransition( props: any, deps?: any ) { - const { ref, reset } = props - const { transitions, changes } = useDiff(data, props) - - useEffect( - () => { - changes.forEach(({ phase, payload }, t) => { - t.phase = phase - if (payload) t.spring.update(payload) - if (!ref) t.spring.start() - }) - }, - reset ? void 0 : deps - ) - - const render = (render: (props: any, item: T) => ReactNode) => - transitions.map(t => { - const elem: any = render({ ...t.spring.animated }, t.item) - return elem && elem.type ? ( - - ) : ( - elem - ) - }) - - return render -} - -interface State { - transitions: Transition[] - changes: Map, Change> -} - -interface Change { - phase: Phase - payload?: any -} - -interface Transition { - id: number - item: T - phase: Phase - spring: Controller - /** Destroy no later than this date */ - expiresBy?: number - expirationId?: number -} - -const enum Phase { - /** This transition is being mounted */ - Mount, - /** This transition is entering or has entered */ - Enter, - /** This transition had its animations updated */ - Update, - /** This transition will expire after animating */ - Leave, -} - -function useDiff(data: T | readonly T[], props: any): State { - const { reset, trail = 0, expires = Infinity } = props + const { ref, reset, trail = 0, expires = Infinity } = props // Every item has its own transition. const items = toArray(data) @@ -185,7 +126,7 @@ function useDiff(data: T | readonly T[], props: any): State { }) useImperativeHandle( - props.ref, + ref, () => ({ get controllers() { return usedTransitions.current!.map(t => t.spring) @@ -202,8 +143,50 @@ function useDiff(data: T | readonly T[], props: any): State { [] ) - return { - changes, - transitions, - } + useEffect( + () => { + changes.forEach(({ phase, payload }, t) => { + t.phase = phase + if (payload) t.spring.update(payload) + if (!ref) t.spring.start() + }) + }, + reset ? void 0 : deps + ) + + return (render: (props: any, item: T) => ReactNode) => + transitions.map(t => { + const elem: any = render({ ...t.spring.animated }, t.item) + return elem && elem.type ? ( + + ) : ( + elem + ) + }) +} + +interface Change { + phase: Phase + payload?: any +} + +interface Transition { + id: number + item: T + phase: Phase + spring: Controller + /** Destroy no later than this date */ + expiresBy?: number + expirationId?: number +} + +const enum Phase { + /** This transition is being mounted */ + Mount, + /** This transition is entering or has entered */ + Enter, + /** This transition had its animations updated */ + Update, + /** This transition will expire after animating */ + Leave, } From 2b5d1c28c4dc58886d9b2874ee5906bca7d3fcc1 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Wed, 10 Jul 2019 19:00:46 -0400 Subject: [PATCH 03/43] fix: "initial" prop --- packages/core/src/useTransition.tsx | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index 889d8dc3fa..25df17ea21 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -27,27 +27,22 @@ export function useTransition( usedTransitions.current!.forEach(t => t.spring.destroy()) }) - // All items are new on first render. + // Determine which items are new. let newItems = items - - // Track the first render for the "initial" prop. - const isFirst = reset || !prevTransitions - if (!isFirst) { + if (prevTransitions && !reset) { // Reuse old transitions unless expired. - prevTransitions!.forEach(t => { + prevTransitions.forEach(t => { if (is.und(t.expiresBy)) { transitions.push(t) } else { clearTimeout(t.expirationId) } }) - - // Deduce which items are new. const oldItems = transitions.map(t => t.item) newItems = newItems.filter(item => oldItems.indexOf(item) < 0) } - // Append transitions for new items. + // Append new transitions for new items. newItems.forEach(item => { const spring = new Controller() transitions.push({ id: spring.id, item, phase: Phase.Mount, spring }) @@ -63,10 +58,17 @@ export function useTransition( const changes = new Map, Change>() transitions.forEach((t, i) => { let to: any + let from: any let phase: Phase if (t.phase == Phase.Mount) { - to = (isFirst && props.initial) || props.enter + to = props.enter phase = Phase.Enter + // The "initial" prop is only used on first render. It always overrides + // the "from" prop when defined, and it makes "enter" instant when null. + from = props.initial + if (is.und(from) || (prevTransitions && !reset)) { + from = props.from + } } else { const isDeleted = items.indexOf(t.item) < 0 if (t.phase < Phase.Leave) { @@ -86,7 +88,7 @@ export function useTransition( // When "to" is a function, it can return (1) an array of "useSpring" props, // (2) an async function, or (3) an object with any "useSpring" props. to: to = callProp(to, t.item, i), - from: phase < Phase.Update ? callProp(props.from, t.item, i) : void 0, + from: callProp(from, t.item, i), delay: delay += trail, config: callProp(props.config, t.item, i), ...(is.obj(to) && interpolateTo(to)), From 84c23ede519e5db424f0705d744e85437f676937 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Wed, 10 Jul 2019 18:34:44 -0400 Subject: [PATCH 04/43] fix: avoid "const enum" for now Babel doesn't support them currently --- packages/core/src/useTransition.tsx | 38 ++++++++++++++--------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index 25df17ea21..a7f5600db7 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -4,6 +4,17 @@ import { callProp, interpolateTo } from './helpers' import { Controller } from './Controller' import { now } from 'shared/globals' +// TODO: convert to "const enum" once Babel supports it +type Phase = number +/** This transition is being mounted */ +const MOUNT = 0 +/** This transition is entering or has entered */ +const ENTER = 1 +/** This transition had its animations updated */ +const UPDATE = 2 +/** This transition will expire after animating */ +const LEAVE = 3 + export function useTransition( data: T | readonly T[], props: any, @@ -60,9 +71,9 @@ export function useTransition( let to: any let from: any let phase: Phase - if (t.phase == Phase.Mount) { + if (t.phase == MOUNT) { to = props.enter - phase = Phase.Enter + phase = ENTER // The "initial" prop is only used on first render. It always overrides // the "from" prop when defined, and it makes "enter" instant when null. from = props.initial @@ -71,16 +82,16 @@ export function useTransition( } } else { const isDeleted = items.indexOf(t.item) < 0 - if (t.phase < Phase.Leave) { + if (t.phase < LEAVE) { if (isDeleted) { to = props.leave - phase = Phase.Leave + phase = LEAVE } else if ((to = props.update)) { - phase = Phase.Update + phase = UPDATE } else return } else if (!isDeleted) { to = props.enter - phase = Phase.Enter + phase = ENTER } else return } @@ -99,7 +110,7 @@ export function useTransition( if (is.fun(onRest)) { onRest(values) } - if (t.phase == Phase.Leave) { + if (t.phase == LEAVE) { t.expiresBy = now() + expires if (expires <= 0) { forceUpdate() @@ -120,7 +131,7 @@ export function useTransition( // To ensure all Animated nodes exist during render, // the payload must be applied immediately for new items. - if (t.phase > Phase.Mount) { + if (t.phase > MOUNT) { change.payload = payload } else { t.spring.update(payload) @@ -181,14 +192,3 @@ interface Transition { expiresBy?: number expirationId?: number } - -const enum Phase { - /** This transition is being mounted */ - Mount, - /** This transition is entering or has entered */ - Enter, - /** This transition had its animations updated */ - Update, - /** This transition will expire after animating */ - Leave, -} From 14e9bf9ab862cbc12509306b5511a001750d3e86 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Wed, 10 Jul 2019 21:33:18 -0400 Subject: [PATCH 05/43] feat: add "key" prop This lets users pass immutable objects as items --- packages/core/src/useTransition.tsx | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index a7f5600db7..389008bb47 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -20,12 +20,15 @@ export function useTransition( props: any, deps?: any ) { - const { ref, reset, trail = 0, expires = Infinity } = props + const { key, ref, reset, trail = 0, expires = Infinity } = props // Every item has its own transition. const items = toArray(data) const transitions: Transition[] = [] + // Explicit keys are used to associate transitions with immutable items. + const keys = is.und(key) ? key : is.fun(key) ? items.map(key) : toArray(key) + // The "onRest" callbacks need a ref to the latest transitions. const usedTransitions = useRef(null) const prevTransitions = usedTransitions.current @@ -38,25 +41,25 @@ export function useTransition( usedTransitions.current!.forEach(t => t.spring.destroy()) }) - // Determine which items are new. - let newItems = items - if (prevTransitions && !reset) { - // Reuse old transitions unless expired. + // Determine which transitions can be reused. + const prevKeys: any[] = [] + if (prevTransitions && !reset) prevTransitions.forEach(t => { if (is.und(t.expiresBy)) { + prevKeys.push(keys ? t.key : t.item) transitions.push(t) } else { clearTimeout(t.expirationId) } }) - const oldItems = transitions.map(t => t.item) - newItems = newItems.filter(item => oldItems.indexOf(item) < 0) - } // Append new transitions for new items. - newItems.forEach(item => { - const spring = new Controller() - transitions.push({ id: spring.id, item, phase: Phase.Mount, spring }) + items.forEach((item, i) => { + const key = keys && keys[i] + if (prevKeys.indexOf(keys ? key : item) < 0) { + const spring = new Controller() + transitions.push({ id: spring.id, key, item, phase: MOUNT, spring }) + } }) // Track cumulative delay for the "trail" prop. @@ -81,7 +84,7 @@ export function useTransition( from = props.from } } else { - const isDeleted = items.indexOf(t.item) < 0 + const isDeleted = (keys || items).indexOf(keys ? t.key : t.item) < 0 if (t.phase < LEAVE) { if (isDeleted) { to = props.leave @@ -185,6 +188,7 @@ interface Change { interface Transition { id: number + key?: keyof any item: T phase: Phase spring: Controller From b6418376f904e972c8a21201527f082d004197a1 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Thu, 11 Jul 2019 11:55:49 -0400 Subject: [PATCH 06/43] feat: add "sort" prop For guaranteed DOM order --- packages/core/src/useTransition.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index 389008bb47..9711a8da75 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -20,7 +20,7 @@ export function useTransition( props: any, deps?: any ) { - const { key, ref, reset, trail = 0, expires = Infinity } = props + const { key, ref, reset, sort, trail = 0, expires = Infinity } = props // Every item has its own transition. const items = toArray(data) @@ -62,6 +62,10 @@ export function useTransition( } }) + if (is.fun(sort)) { + transitions.sort((a, b) => sort(a.item, b.item)) + } + // Track cumulative delay for the "trail" prop. let delay = -trail From 0d6958ac363c607805668a5bcac2725959eba962 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Thu, 11 Jul 2019 18:59:32 -0400 Subject: [PATCH 07/43] refactor: use "each" helper because it minifies better --- packages/core/src/useTransition.tsx | 14 +++++++------- packages/shared/src/helpers.ts | 6 ++++++ 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index 9711a8da75..54d0dce915 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -1,5 +1,5 @@ import React, { useEffect, useRef, useImperativeHandle, ReactNode } from 'react' -import { is, toArray, useForceUpdate, useOnce } from 'shared' +import { is, toArray, useForceUpdate, useOnce, each } from 'shared' import { callProp, interpolateTo } from './helpers' import { Controller } from './Controller' import { now } from 'shared/globals' @@ -38,13 +38,13 @@ export function useTransition( // Destroy all transitions on dismount. useOnce(() => () => { - usedTransitions.current!.forEach(t => t.spring.destroy()) + each(usedTransitions.current!, t => t.spring.destroy()) }) // Determine which transitions can be reused. const prevKeys: any[] = [] if (prevTransitions && !reset) - prevTransitions.forEach(t => { + each(prevTransitions, t => { if (is.und(t.expiresBy)) { prevKeys.push(keys ? t.key : t.item) transitions.push(t) @@ -54,7 +54,7 @@ export function useTransition( }) // Append new transitions for new items. - items.forEach((item, i) => { + each(items, (item, i) => { const key = keys && keys[i] if (prevKeys.indexOf(keys ? key : item) < 0) { const spring = new Controller() @@ -74,7 +74,7 @@ export function useTransition( // Generate changes to apply in useEffect. const changes = new Map, Change>() - transitions.forEach((t, i) => { + each(transitions, (t, i) => { let to: any let from: any let phase: Phase @@ -158,14 +158,14 @@ export function useTransition( ) ), stop: (finished?: boolean) => - usedTransitions.current!.forEach(t => t.spring.stop(finished)), + each(usedTransitions.current!, t => t.spring.stop(finished)), }), [] ) useEffect( () => { - changes.forEach(({ phase, payload }, t) => { + each(changes, ({ phase, payload }, t) => { t.phase = phase if (payload) t.spring.update(payload) if (!ref) t.spring.start() diff --git a/packages/shared/src/helpers.ts b/packages/shared/src/helpers.ts index 4745d1a083..4071aaecbc 100644 --- a/packages/shared/src/helpers.ts +++ b/packages/shared/src/helpers.ts @@ -56,6 +56,12 @@ interface EachFn { ctx?: This ): void +

( + obj: ReadonlyMap, + cb: (this: This, value: T, key: P) => void, + ctx?: This + ): void + ( arr: readonly T[], cb: (this: This, value: T, index: number) => void, From c67157c5c1891f4543571a1d064631703b6f619d Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Thu, 11 Jul 2019 20:25:06 -0400 Subject: [PATCH 08/43] refactor: make "transition.key" always exist This lets us avoid ternary operators more --- packages/core/src/useTransition.tsx | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index 54d0dce915..02683b9fb4 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -26,8 +26,8 @@ export function useTransition( const items = toArray(data) const transitions: Transition[] = [] - // Explicit keys are used to associate transitions with immutable items. - const keys = is.und(key) ? key : is.fun(key) ? items.map(key) : toArray(key) + // Keys help with reusing transitions between renders. + const keys = is.und(key) ? items : is.fun(key) ? items.map(key) : toArray(key) // The "onRest" callbacks need a ref to the latest transitions. const usedTransitions = useRef(null) @@ -46,7 +46,7 @@ export function useTransition( if (prevTransitions && !reset) each(prevTransitions, t => { if (is.und(t.expiresBy)) { - prevKeys.push(keys ? t.key : t.item) + prevKeys.push(t.key) transitions.push(t) } else { clearTimeout(t.expirationId) @@ -55,8 +55,8 @@ export function useTransition( // Append new transitions for new items. each(items, (item, i) => { - const key = keys && keys[i] - if (prevKeys.indexOf(keys ? key : item) < 0) { + const key = keys[i] + if (prevKeys.indexOf(key) < 0) { const spring = new Controller() transitions.push({ id: spring.id, key, item, phase: MOUNT, spring }) } @@ -88,7 +88,7 @@ export function useTransition( from = props.from } } else { - const isDeleted = (keys || items).indexOf(keys ? t.key : t.item) < 0 + const isDeleted = keys.indexOf(t.key) < 0 if (t.phase < LEAVE) { if (isDeleted) { to = props.leave @@ -192,7 +192,7 @@ interface Change { interface Transition { id: number - key?: keyof any + key: any item: T phase: Phase spring: Controller From dddeabca74799425bd2f684cfecfe5abfd8802e6 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Fri, 12 Jul 2019 16:01:08 -0400 Subject: [PATCH 09/43] fix: use "transition.key" when string or number and remove "transition.id" in favor of "transition.spring.id" --- packages/core/src/useTransition.tsx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index 02683b9fb4..6bca0b21a7 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -57,8 +57,7 @@ export function useTransition( each(items, (item, i) => { const key = keys[i] if (prevKeys.indexOf(key) < 0) { - const spring = new Controller() - transitions.push({ id: spring.id, key, item, phase: MOUNT, spring }) + transitions.push({ key, item, phase: MOUNT, spring: new Controller() }) } }) @@ -178,7 +177,11 @@ export function useTransition( transitions.map(t => { const elem: any = render({ ...t.spring.animated }, t.item) return elem && elem.type ? ( - + ) : ( elem ) @@ -191,7 +194,6 @@ interface Change { } interface Transition { - id: number key: any item: T phase: Phase From 814b2435d1f3c9e26b6a8ad4a6141eb86238b5a5 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Fri, 12 Jul 2019 16:56:50 -0400 Subject: [PATCH 10/43] refactor: rename variable --- packages/core/src/useTransition.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index 6bca0b21a7..0bbd05e000 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -87,15 +87,15 @@ export function useTransition( from = props.from } } else { - const isDeleted = keys.indexOf(t.key) < 0 + const isLeave = keys.indexOf(t.key) < 0 if (t.phase < LEAVE) { - if (isDeleted) { + if (isLeave) { to = props.leave phase = LEAVE } else if ((to = props.update)) { phase = UPDATE } else return - } else if (!isDeleted) { + } else if (!isLeave) { to = props.enter phase = ENTER } else return From fb070b471dac38f5e89a26e359f190c6974d071c Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Fri, 12 Jul 2019 16:57:32 -0400 Subject: [PATCH 11/43] fix: always respect item order --- packages/core/src/helpers.ts | 82 ----------------------------- packages/core/src/useTransition.tsx | 39 ++++++++++---- 2 files changed, 29 insertions(+), 92 deletions(-) diff --git a/packages/core/src/helpers.ts b/packages/core/src/helpers.ts index 26658a24f4..733a49d2f4 100644 --- a/packages/core/src/helpers.ts +++ b/packages/core/src/helpers.ts @@ -109,88 +109,6 @@ export function interpolateTo(props: T): InterpolateTo { return out } -type ItemKey = number | string - -interface Item { - key: ItemKey - originalKey: ItemKey - phase: string - item: any - props: object - destroyed?: boolean -} - -interface DeletedItem extends Item { - left?: ItemKey - right?: ItemKey -} - -/** - * This tries to put deleted items back into the given `out` list in correct - * order. Deleted items must have a `left` and `right` property with key of - * their sibling which is used to find the correct placement. - */ -export function reconcileDeleted( - deleted: DeletedItem[], - current: Item[] -): any[] { - // Copy as we will be mutating the arrays - deleted = [...deleted] - current = [...current] - - // Used to detect deadlock (when a pass finds 0 siblings) - let failedTries = 0 - - // Track where the current pass start/ends - let passIndex = 0 - let nextPassIndex = deleted.length - - // Insert all deleted items into `current` - for (let i = 0; i < deleted.length; i++) { - if (i === nextPassIndex) { - // Sanity test: Push to end if somehow no siblings were found - if (passIndex + failedTries === nextPassIndex) { - for (let j = i; j < deleted.length; j++) { - const { left, right, ...deletedItem } = deleted[j] - current.push(deletedItem) - } - break - } - // Update local state at the end of each pass - passIndex = nextPassIndex - nextPassIndex = deleted.length - failedTries = 0 - } - - // The index of the deleted item in `current` - let index = -1 - - // Look for the left or right sibling in `current` - const { left, right, ...deletedItem } = deleted[i] - for (let j = current.length; --j >= 0; ) { - const { originalKey: key } = current[j] - if (key === right) { - index = j - break - } - if (key === left) { - index = j + 1 - break - } - } - - // Items with no index are revisited in the next pass - if (index < 0) { - failedTries++ - deleted.push(deleted[i]) - } else { - current.splice(index, 0, deletedItem) - } - } - - return current -} - export function freeze(obj: T): T { if ( typeof process !== 'undefined' && diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index 0bbd05e000..dc033d52ca 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -41,26 +41,45 @@ export function useTransition( each(usedTransitions.current!, t => t.spring.destroy()) }) - // Determine which transitions can be reused. - const prevKeys: any[] = [] + // Map old indices to new indices. + const reused: number[] = [] if (prevTransitions && !reset) - each(prevTransitions, t => { + each(prevTransitions, (t, i) => { + // Expired transitions are not rendered. if (is.und(t.expiresBy)) { - prevKeys.push(t.key) - transitions.push(t) + i = reused[i] = keys.indexOf(t.key) + if (~i) transitions[i] = t } else { clearTimeout(t.expirationId) } }) - // Append new transitions for new items. + // Mount new items with fresh transitions. each(items, (item, i) => { - const key = keys[i] - if (prevKeys.indexOf(key) < 0) { - transitions.push({ key, item, phase: MOUNT, spring: new Controller() }) - } + transitions[i] || + (transitions[i] = { + key: keys[i], + item, + phase: MOUNT, + spring: new Controller(), + }) }) + // Update the item of any transition whose key still exists, + // and ensure leaving transitions are rendered until they finish. + if (reused.length) { + let i = -1 + each(reused, (keyIndex, prevIndex) => { + const t = prevTransitions![prevIndex] + if (~keyIndex) { + i = transitions.indexOf(t) + transitions[i] = { ...t, item: items[keyIndex] } + } else if (props.leave) { + transitions.splice(++i, 0, t) + } + }) + } + if (is.fun(sort)) { transitions.sort((a, b) => sort(a.item, b.item)) } From f1cf028e2be1a7d47160f315c33993567b0fd278 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Fri, 12 Jul 2019 18:32:13 -0400 Subject: [PATCH 12/43] fix: clear expiration timeouts on dismount --- packages/core/src/useTransition.tsx | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index dc033d52ca..26611282fb 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -37,20 +37,23 @@ export function useTransition( }) // Destroy all transitions on dismount. - useOnce(() => () => { - each(usedTransitions.current!, t => t.spring.destroy()) - }) + useOnce(() => () => + each(usedTransitions.current!, t => { + if (t.expiresBy) clearTimeout(t.expirationId) + t.spring.destroy() + }) + ) // Map old indices to new indices. const reused: number[] = [] if (prevTransitions && !reset) each(prevTransitions, (t, i) => { // Expired transitions are not rendered. - if (is.und(t.expiresBy)) { + if (t.expiresBy) { + clearTimeout(t.expirationId) + } else { i = reused[i] = keys.indexOf(t.key) if (~i) transitions[i] = t - } else { - clearTimeout(t.expirationId) } }) From 8ab10ff56c3309c1e9ec4d5654914f2d50b03c3d Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Fri, 26 Jul 2019 20:06:10 -0400 Subject: [PATCH 13/43] wip: useTransition types --- packages/core/src/useTransition.tsx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index 26611282fb..58a170757c 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -15,6 +15,15 @@ const UPDATE = 2 /** This transition will expire after animating */ const LEAVE = 3 +export type UseTransitionProps = { [key: string]: any | T } // TODO +export type ItemsProp = ReadonlyArray | T | null | undefined +export type ItemKeys = + | ((item: T) => string | number) + | ReadonlyArray + | string + | number + | null + export function useTransition( data: T | readonly T[], props: any, From 0b24f76ae8587112d09b7bb9808d4092caf5b2ac Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Mon, 9 Sep 2019 15:45:40 -0400 Subject: [PATCH 14/43] fix: type errors in useTransition and add an "update" method to the ref api --- packages/core/src/useTransition.tsx | 82 ++++++++++++++++++----------- 1 file changed, 52 insertions(+), 30 deletions(-) diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index 58a170757c..802be46ca5 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -1,8 +1,16 @@ -import React, { useEffect, useRef, useImperativeHandle, ReactNode } from 'react' -import { is, toArray, useForceUpdate, useOnce, each } from 'shared' +import React, { + useEffect, + useRef, + useImperativeHandle, + ReactNode, + useMemo, +} from 'react' +import { is, toArray, useForceUpdate, useOnce, each, OneOrMore } from 'shared' +import { now } from 'shared/globals' + import { callProp, interpolateTo } from './helpers' +import { SpringHandle } from './types/spring' import { Controller } from './Controller' -import { now } from 'shared/globals' // TODO: convert to "const enum" once Babel supports it type Phase = number @@ -24,19 +32,22 @@ export type ItemKeys = | number | null -export function useTransition( - data: T | readonly T[], - props: any, - deps?: any -) { +export function useTransition(data: OneOrMore, props: any, deps?: any) { const { key, ref, reset, sort, trail = 0, expires = Infinity } = props // Every item has its own transition. - const items = toArray(data) + const items = toArray(data) const transitions: Transition[] = [] // Keys help with reusing transitions between renders. - const keys = is.und(key) ? items : is.fun(key) ? items.map(key) : toArray(key) + // The `key` prop can be undefined (which means the items themselves are used + // as keys), or a function (which maps each item to its key), or an array of + // keys (which are assigned to each item by index). + const keys: any[] = is.und(key) + ? items + : is.fun(key) + ? items.map(key) + : toArray(key) // The "onRest" callbacks need a ref to the latest transitions. const usedTransitions = useRef(null) @@ -49,7 +60,7 @@ export function useTransition( useOnce(() => () => each(usedTransitions.current!, t => { if (t.expiresBy) clearTimeout(t.expirationId) - t.spring.destroy() + t.ctrl.dispose() }) ) @@ -73,7 +84,7 @@ export function useTransition( key: keys[i], item, phase: MOUNT, - spring: new Controller(), + ctrl: new Controller(), }) }) @@ -132,6 +143,7 @@ export function useTransition( } else return } + // The payload is used to update the spring props once the current render is committed. const payload: any = { // When "to" is a function, it can return (1) an array of "useSpring" props, // (2) an async function, or (3) an object with any "useSpring" props. @@ -154,7 +166,7 @@ export function useTransition( } else { // Postpone dismounts while other controllers are active. const transitions = usedTransitions.current! - if (transitions.every(t => t.spring.idle)) { + if (transitions.every(t => t.ctrl.idle)) { forceUpdate() } else if (expires < Infinity) { t.expirationId = setTimeout(forceUpdate, expires) @@ -171,34 +183,44 @@ export function useTransition( if (t.phase > MOUNT) { change.payload = payload } else { - t.spring.update(payload) + t.ctrl.update(payload) } }) - useImperativeHandle( - ref, - () => ({ + const api = useMemo( + (): SpringHandle => ({ get controllers() { - return usedTransitions.current!.map(t => t.spring) + return usedTransitions.current!.map(t => t.ctrl) }, - start: () => - Promise.all( - usedTransitions.current!.map( - t => new Promise(done => t.spring.start(done)) + update(props) { + each(usedTransitions.current!, (t, i) => + t.ctrl.update( + is.fun(props) ? props(i, t.ctrl) : is.arr(props) ? props[i] : props ) - ), - stop: (finished?: boolean) => - each(usedTransitions.current!, t => t.spring.stop(finished)), + ) + return api + }, + async start() { + const transitions = usedTransitions.current! + const results = await Promise.all(transitions.map(t => t.ctrl.start())) + return { + value: results.map(result => result.value), + finished: results.every(result => result.finished), + } + }, + stop: keys => each(usedTransitions.current!, t => t.ctrl.stop(keys)), }), [] ) + useImperativeHandle(ref, () => api) + useEffect( () => { each(changes, ({ phase, payload }, t) => { t.phase = phase - if (payload) t.spring.update(payload) - if (!ref) t.spring.start() + if (payload) t.ctrl.update(payload) + if (!ref) t.ctrl.start() }) }, reset ? void 0 : deps @@ -206,11 +228,11 @@ export function useTransition( return (render: (props: any, item: T) => ReactNode) => transitions.map(t => { - const elem: any = render({ ...t.spring.animated }, t.item) + const elem: any = render({ ...t.ctrl.springs }, t.item) return elem && elem.type ? ( ) : ( @@ -227,8 +249,8 @@ interface Change { interface Transition { key: any item: T + ctrl: Controller phase: Phase - spring: Controller /** Destroy no later than this date */ expiresBy?: number expirationId?: number From 7a844180b018d39119a4947f7f3300cd6ab8d699 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Wed, 11 Sep 2019 16:46:37 -0400 Subject: [PATCH 15/43] fix: add default props to useTransition --- packages/core/src/useTransition.tsx | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index 802be46ca5..726815bdca 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -8,8 +8,8 @@ import React, { import { is, toArray, useForceUpdate, useOnce, each, OneOrMore } from 'shared' import { now } from 'shared/globals' -import { callProp, interpolateTo } from './helpers' -import { SpringHandle } from './types/spring' +import { DEFAULT_PROPS, callProp, interpolateTo } from './helpers' +import { SpringHandle, SpringProps } from './types/spring' import { Controller } from './Controller' // TODO: convert to "const enum" once Babel supports it @@ -113,6 +113,13 @@ export function useTransition(data: OneOrMore, props: any, deps?: any) { // Expired transitions use this to dismount. const forceUpdate = useForceUpdate() + const defaultProps: any = {} + each(DEFAULT_PROPS, prop => { + if (/function|object/.test(typeof props[prop])) { + defaultProps[prop] = props[prop] + } + }) + // Generate changes to apply in useEffect. const changes = new Map, Change>() each(transitions, (t, i) => { @@ -144,20 +151,21 @@ export function useTransition(data: OneOrMore, props: any, deps?: any) { } // The payload is used to update the spring props once the current render is committed. - const payload: any = { + const payload = { + ...defaultProps, // When "to" is a function, it can return (1) an array of "useSpring" props, // (2) an async function, or (3) an object with any "useSpring" props. to: to = callProp(to, t.item, i), from: callProp(from, t.item, i), delay: delay += trail, - config: callProp(props.config, t.item, i), + config: callProp(props.config || defaultProps.config, t.item, i), ...(is.obj(to) && interpolateTo(to)), - } + } as SpringProps const { onRest } = payload - payload.onRest = (values: any) => { + payload.onRest = result => { if (is.fun(onRest)) { - onRest(values) + onRest(result) } if (t.phase == LEAVE) { t.expiresBy = now() + expires From ffffbf70e946e878c88113ad2eec6adbb8d99267 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Fri, 13 Sep 2019 20:06:24 -0400 Subject: [PATCH 16/43] fix: call useLayoutEffect in useTransition --- packages/core/src/useTransition.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index 726815bdca..4c808e2f8b 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -1,9 +1,9 @@ import React, { - useEffect, useRef, + useMemo, + useLayoutEffect, useImperativeHandle, ReactNode, - useMemo, } from 'react' import { is, toArray, useForceUpdate, useOnce, each, OneOrMore } from 'shared' import { now } from 'shared/globals' @@ -52,7 +52,7 @@ export function useTransition(data: OneOrMore, props: any, deps?: any) { // The "onRest" callbacks need a ref to the latest transitions. const usedTransitions = useRef(null) const prevTransitions = usedTransitions.current - useEffect(() => { + useLayoutEffect(() => { usedTransitions.current = transitions }) @@ -223,7 +223,7 @@ export function useTransition(data: OneOrMore, props: any, deps?: any) { useImperativeHandle(ref, () => api) - useEffect( + useLayoutEffect( () => { each(changes, ({ phase, payload }, t) => { t.phase = phase From 9d6f6fcfdfe1efd61f04f27a73809a1f00c12104 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Sat, 14 Sep 2019 10:58:09 -0400 Subject: [PATCH 17/43] nit: fix type error --- packages/core/src/useTransition.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index 4c808e2f8b..663d7b8f84 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -43,7 +43,7 @@ export function useTransition(data: OneOrMore, props: any, deps?: any) { // The `key` prop can be undefined (which means the items themselves are used // as keys), or a function (which maps each item to its key), or an array of // keys (which are assigned to each item by index). - const keys: any[] = is.und(key) + const keys: readonly any[] = is.und(key) ? items : is.fun(key) ? items.map(key) From aa374f4615ed1c35af3e9fbe29a69f1b3642eb69 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Tue, 17 Sep 2019 22:19:54 -0400 Subject: [PATCH 18/43] types: update useTransition types --- packages/core/src/useTransition.tsx | 150 ++++++++++++++---- .../web/src/types/__tests__/Transition.tsx | 4 +- .../web/src/types/__tests__/useTransition.tsx | 58 +++---- 3 files changed, 149 insertions(+), 63 deletions(-) diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index 663d7b8f84..1f51c5388c 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -4,40 +4,118 @@ import React, { useLayoutEffect, useImperativeHandle, ReactNode, + RefObject, } from 'react' -import { is, toArray, useForceUpdate, useOnce, each, OneOrMore } from 'shared' +import { + is, + toArray, + useForceUpdate, + useOnce, + each, + OneOrMore, + Falsy, + Indexable, + Merge, +} from 'shared' import { now } from 'shared/globals' import { DEFAULT_PROPS, callProp, interpolateTo } from './helpers' -import { SpringHandle, SpringProps } from './types/spring' -import { Controller } from './Controller' +import { SpringHandle, AsyncTo, FromProp, SpringValues } from './types/spring' +import { Controller, ControllerProps } from './Controller' +import { AnimationProps, AnimationEvents } from './types/animated' +import { UseSpringProps } from './useSpring' +import { PickAnimated } from './types/common' // TODO: convert to "const enum" once Babel supports it -type Phase = number +export type Phase = number & { __type: 'TransitionPhase' } /** This transition is being mounted */ -const MOUNT = 0 +const MOUNT = 0 as Phase /** This transition is entering or has entered */ -const ENTER = 1 +const ENTER = 1 as Phase /** This transition had its animations updated */ -const UPDATE = 2 +const UPDATE = 2 as Phase /** This transition will expire after animating */ -const LEAVE = 3 - -export type UseTransitionProps = { [key: string]: any | T } // TODO -export type ItemsProp = ReadonlyArray | T | null | undefined -export type ItemKeys = - | ((item: T) => string | number) - | ReadonlyArray - | string - | number - | null - -export function useTransition(data: OneOrMore, props: any, deps?: any) { +const LEAVE = 3 as Phase + +type UnknownProps = Indexable + +type PhaseProp = + | Falsy + | OneOrMore + | (( + item: Item, + index: number + ) => UseSpringProps | AsyncTo | Falsy) + +type PhaseProps = { + from?: From & + ( + | FromProp + | ((item: Item, index: number) => FromProp)) + initial?: From & + ( + | FromProp + | ((item: Item, index: number) => FromProp)) + enter?: PhaseProp + update?: PhaseProp + leave?: PhaseProp +} + +type Key = string | number + +export type ItemKeys = Key | ReadonlyArray | ((item: T) => Key) | null + +export type UseTransitionProps = Merge< + AnimationProps & AnimationEvents, + { + /** + * Used to access the imperative API. + * + * Animations never auto-start when `ref` is defined. + */ + ref?: RefObject + key?: ItemKeys + sort?: (a: Item, b: Item) => number + trail?: number + expires?: number + } +> + +/** The imperative `ref` API */ +export type TransitionHandle = Merge< + SpringHandle, + { + update(props: ControllerProps): TransitionHandle + } +> + +/** The function returned by `useTransition` */ +export interface TransitionFn { + ( + render: ( + values: SpringValues, + item: Item, + transition: TransitionState + ) => ReactNode + ): ReactNode[] +} + +export function useTransition( + data: OneOrMore, + props: Props & PhaseProps & UseTransitionProps, + deps?: any[] +): TransitionFn> + +export function useTransition( + data: unknown, + props: PhaseProps & UseTransitionProps, + deps?: any[] +): TransitionFn { const { key, ref, reset, sort, trail = 0, expires = Infinity } = props // Every item has its own transition. - const items = toArray(data) - const transitions: Transition[] = [] + const items = toArray(data) + const transitions: TransitionState[] = [] // Keys help with reusing transitions between renders. // The `key` prop can be undefined (which means the items themselves are used @@ -50,7 +128,7 @@ export function useTransition(data: OneOrMore, props: any, deps?: any) { : toArray(key) // The "onRest" callbacks need a ref to the latest transitions. - const usedTransitions = useRef(null) + const usedTransitions = useRef(null) const prevTransitions = usedTransitions.current useLayoutEffect(() => { usedTransitions.current = transitions @@ -59,7 +137,9 @@ export function useTransition(data: OneOrMore, props: any, deps?: any) { // Destroy all transitions on dismount. useOnce(() => () => each(usedTransitions.current!, t => { - if (t.expiresBy) clearTimeout(t.expirationId) + if (t.expiresBy != null) { + clearTimeout(t.expirationId) + } t.ctrl.dispose() }) ) @@ -69,7 +149,7 @@ export function useTransition(data: OneOrMore, props: any, deps?: any) { if (prevTransitions && !reset) each(prevTransitions, (t, i) => { // Expired transitions are not rendered. - if (t.expiresBy) { + if (t.expiresBy != null) { clearTimeout(t.expirationId) } else { i = reused[i] = keys.indexOf(t.key) @@ -113,7 +193,7 @@ export function useTransition(data: OneOrMore, props: any, deps?: any) { // Expired transitions use this to dismount. const forceUpdate = useForceUpdate() - const defaultProps: any = {} + const defaultProps = {} as UnknownProps each(DEFAULT_PROPS, prop => { if (/function|object/.test(typeof props[prop])) { defaultProps[prop] = props[prop] @@ -121,7 +201,7 @@ export function useTransition(data: OneOrMore, props: any, deps?: any) { }) // Generate changes to apply in useEffect. - const changes = new Map, Change>() + const changes = new Map() each(transitions, (t, i) => { let to: any let from: any @@ -151,7 +231,7 @@ export function useTransition(data: OneOrMore, props: any, deps?: any) { } // The payload is used to update the spring props once the current render is committed. - const payload = { + const payload: ControllerProps = { ...defaultProps, // When "to" is a function, it can return (1) an array of "useSpring" props, // (2) an async function, or (3) an object with any "useSpring" props. @@ -160,7 +240,7 @@ export function useTransition(data: OneOrMore, props: any, deps?: any) { delay: delay += trail, config: callProp(props.config || defaultProps.config, t.item, i), ...(is.obj(to) && interpolateTo(to)), - } as SpringProps + } const { onRest } = payload payload.onRest = result => { @@ -176,7 +256,9 @@ export function useTransition(data: OneOrMore, props: any, deps?: any) { const transitions = usedTransitions.current! if (transitions.every(t => t.ctrl.idle)) { forceUpdate() - } else if (expires < Infinity) { + } + // When `expires` is infinite, postpone dismount until next render. + else if (expires < Infinity) { t.expirationId = setTimeout(forceUpdate, expires) } } @@ -196,7 +278,7 @@ export function useTransition(data: OneOrMore, props: any, deps?: any) { }) const api = useMemo( - (): SpringHandle => ({ + (): TransitionHandle => ({ get controllers() { return usedTransitions.current!.map(t => t.ctrl) }, @@ -234,9 +316,9 @@ export function useTransition(data: OneOrMore, props: any, deps?: any) { reset ? void 0 : deps ) - return (render: (props: any, item: T) => ReactNode) => + return render => transitions.map(t => { - const elem: any = render({ ...t.ctrl.springs }, t.item) + const elem: any = render(t.ctrl.springs, t.item, t) return elem && elem.type ? ( { +export interface TransitionState { key: any - item: T + item: Item ctrl: Controller phase: Phase /** Destroy no later than this date */ diff --git a/targets/web/src/types/__tests__/Transition.tsx b/targets/web/src/types/__tests__/Transition.tsx index 8c8ecfde39..056c3f0a95 100644 --- a/targets/web/src/types/__tests__/Transition.tsx +++ b/targets/web/src/types/__tests__/Transition.tsx @@ -1,7 +1,7 @@ import React from 'react'; import { assert, test, _ } from 'spec.ts'; -import { Transition, animated, SpringValue, TransitionPhase } from '../..'; -import { SpringValues } from '@react-spring/core'; +import { SpringValues, Transition, TransitionPhase } from '@react-spring/core'; +import { animated } from '../..'; const View = animated('div'); diff --git a/targets/web/src/types/__tests__/useTransition.tsx b/targets/web/src/types/__tests__/useTransition.tsx index 30eeb32db3..528841041e 100644 --- a/targets/web/src/types/__tests__/useTransition.tsx +++ b/targets/web/src/types/__tests__/useTransition.tsx @@ -1,52 +1,53 @@ import React from 'react'; import { assert, test, _ } from 'spec.ts'; -import { - animated, - useTransition, - ItemTransition, - SpringValue, - SpringUpdateFn, -} from '../..'; +import { SpringValues } from '@react-spring/core'; +import { animated, useTransition, SpringUpdateFn } from '../..'; const View = animated('div'); const items = [1, 2] as [1, 2]; test('infer animated from these props', () => { - const [transition] = useTransition(items, null, { + const transition = useTransition(items, { from: { a: 1 }, enter: { b: 1 }, leave: { c: 1 }, update: { d: 1 }, initial: { e: 1 }, }); - assert(transition.props, _ as { - [key: string]: SpringValue; - a: SpringValue; - b: SpringValue; - c: SpringValue; - d: SpringValue; - e: SpringValue; + transition((style, item) => { + assert(style, _ as SpringValues<{ + a: number; + b: number; + c: number; + d: number; + e: number; + }>); + assert(item, _ as 1 | 2); + return null; }); }); test('basic usage', () => { - const transitions = useTransition(items, null, { + const transition = useTransition(items, { from: { opacity: 0 }, enter: [{ opacity: 1 }, { color: 'red' }], leave: { opacity: 0 }, }); // You typically map transition objects into JSX elements. - return transitions.map(transition => { - type T = ItemTransition<1 | 2, { opacity: number; color: string }>; - assert(transition, _ as T); - return {transition.item}; + return transition((style, item) => { + assert(style, _ as SpringValues<{ + opacity?: number; // FIXME: "opacity" should never be undefined because it exists in "from" + color?: string; + }>); + assert(item, _ as 1 | 2); + return {item}; }); }); test('with function props', () => { - const transitions = useTransition(items, null, { + const transition = useTransition(items, { from: item => { assert(item, _ as 1 | 2); return { width: 0, height: 0 }; @@ -57,15 +58,18 @@ test('with function props', () => { }, leave: { width: '0%', opacity: 0 }, }); - assert(transitions[0].props, _ as { - [key: string]: SpringValue; - width: SpringValue; - height: SpringValue; - opacity: SpringValue; + transition((style, item) => { + assert(style, _ as SpringValues<{ + width: string | number; + height: string; + opacity: number; + }>); + assert(item, _ as 1 | 2); + return null; }); test('return an async function', () => { - useTransition(items, null, { + useTransition(items, { update: item => async next => { assert(item, _ as 1 | 2); assert(next, _ as SpringUpdateFn); // FIXME: should be "SpringUpdateFn<{ opacity: number, ... }>" From 9cd633f1e6179c839102d2b1e775d12586d8e7e0 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Wed, 18 Sep 2019 12:44:29 -0400 Subject: [PATCH 19/43] feat: add warning to useTransition for "keys" prop The user wants "key" instead --- packages/core/src/useTransition.tsx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index 1f51c5388c..e1292ce747 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -113,6 +113,12 @@ export function useTransition( ): TransitionFn { const { key, ref, reset, sort, trail = 0, expires = Infinity } = props + if ('keys' in props) { + console.warn( + 'Unknown prop "keys" was passed to useTransition. Did you mean "key"?' + ) + } + // Every item has its own transition. const items = toArray(data) const transitions: TransitionState[] = [] From d547c4fecdd4fa76d321729ce7fd8df47e42aa8e Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Sat, 28 Sep 2019 21:25:39 -0400 Subject: [PATCH 20/43] chore: canary release --- lerna.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lerna.json b/lerna.json index 284d9e4511..a70d8dc15c 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-beta.34", + "version": "9.0.0-canary.809.1.aa2db98.0", "npmClient": "yarn", "useWorkspaces": true, "registry": "https://registry.npmjs.org", From 5ceecce8133ce4ea80b7c0154fb219975792a931 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Sat, 28 Sep 2019 22:34:37 -0400 Subject: [PATCH 21/43] chore: tweak scripts/prepare.js --- scripts/prepare.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/prepare.js b/scripts/prepare.js index 7b2b796091..86a6bc830d 100644 --- a/scripts/prepare.js +++ b/scripts/prepare.js @@ -249,14 +249,15 @@ async function prepare() { pkg[key] = fields[key] }) - log(``) + log('') + log(chalk.yellow(lernaJson.version)) + log('') await Promise.all( Object.keys(packages).map(name => { const pkg = packages[name] log(chalk.cyan(name)) - log(` rootDir: %O`, pkg.dir) - log(` version: %O`, pkg.version) - log(``) + log('./' + pkg.dir) + log('') return preparePackage(pkg) }) ) From fe17b80f52c91b5fbeb6d804b984da0bb214c1b0 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Sat, 28 Sep 2019 23:28:58 -0400 Subject: [PATCH 22/43] build: remove "preDistTag" from lerna.json --- lerna.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lerna.json b/lerna.json index a70d8dc15c..2242a1d16c 100644 --- a/lerna.json +++ b/lerna.json @@ -19,8 +19,7 @@ "publish": { "bump": "from-package", "contents": "dist", - "ignoreScripts": true, - "preDistTag": "next" + "ignoreScripts": true } } } From 7c9b218b4b474de0d285fd4fadd2f43d1330b7e4 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Sun, 29 Sep 2019 00:05:21 -0400 Subject: [PATCH 23/43] build: remove "from-package" for lerna publish --- lerna.json | 1 - 1 file changed, 1 deletion(-) diff --git a/lerna.json b/lerna.json index 2242a1d16c..4c25507e06 100644 --- a/lerna.json +++ b/lerna.json @@ -17,7 +17,6 @@ "push": false }, "publish": { - "bump": "from-package", "contents": "dist", "ignoreScripts": true } From 411084c0bd7799db6a7daed9a39bd166735669a1 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Sun, 29 Sep 2019 00:09:17 -0400 Subject: [PATCH 24/43] build: fix lerna version issue --- packages/addons/package.json | 2 +- packages/animated/package.json | 2 +- packages/core/package.json | 2 +- packages/react-spring/package.json | 2 +- packages/shared/package.json | 2 +- targets/konva/package.json | 2 +- targets/native/package.json | 2 +- targets/three/package.json | 2 +- targets/web/package.json | 2 +- targets/zdog/package.json | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/addons/package.json b/packages/addons/package.json index b2ba6ffcf4..1d9c6ce879 100644 --- a/packages/addons/package.json +++ b/packages/addons/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/addons", - "version": "next", + "version": "0.0.0", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../animated", diff --git a/packages/animated/package.json b/packages/animated/package.json index 1b834bddef..232456dbf0 100644 --- a/packages/animated/package.json +++ b/packages/animated/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/animated", - "version": "next", + "version": "0.0.0", "description": "Animated component props for React", "main": "src/index.ts", "scripts": { diff --git a/packages/core/package.json b/packages/core/package.json index b00d20660e..986c632b7d 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/core", - "version": "next", + "version": "0.0.0", "main": "src/index.ts", "scripts": { "build": "rollup -c", diff --git a/packages/react-spring/package.json b/packages/react-spring/package.json index d72c49ec5c..edb3f30fce 100644 --- a/packages/react-spring/package.json +++ b/packages/react-spring/package.json @@ -1,6 +1,6 @@ { "name": "react-spring", - "version": "next", + "version": "0.0.0", "main": "src/web.ts", "dependencies": { "@react-spring/addons": "link:../addons", diff --git a/packages/shared/package.json b/packages/shared/package.json index 29d76fa745..2142711414 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/shared", - "version": "next", + "version": "0.0.0", "description": "Globals and shared modules", "main": "src/index.ts", "scripts": { diff --git a/targets/konva/package.json b/targets/konva/package.json index 1d9e48a09b..d7edf55a89 100644 --- a/targets/konva/package.json +++ b/targets/konva/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/konva", - "version": "next", + "version": "0.0.0", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/targets/native/package.json b/targets/native/package.json index 508918f4dd..f1f4f18ab5 100644 --- a/targets/native/package.json +++ b/targets/native/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/native", - "version": "next", + "version": "0.0.0", "main": "src/index.ts", "scripts": { "build": "rollup -c" diff --git a/targets/three/package.json b/targets/three/package.json index 3bec65df2e..515a35bd78 100644 --- a/targets/three/package.json +++ b/targets/three/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/three", - "version": "next", + "version": "0.0.0", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/targets/web/package.json b/targets/web/package.json index 207212b37f..ff883c211e 100644 --- a/targets/web/package.json +++ b/targets/web/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/web", - "version": "next", + "version": "0.0.0", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/targets/zdog/package.json b/targets/zdog/package.json index fb53f78a48..9a74b7145f 100644 --- a/targets/zdog/package.json +++ b/targets/zdog/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/zdog", - "version": "next", + "version": "0.0.0", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", From c617404110ef9421d115635f082093975fb01f90 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Sun, 29 Sep 2019 00:14:14 -0400 Subject: [PATCH 25/43] =?UTF-8?q?chore:=20ship=20it=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/addons/package.json | 2 +- packages/animated/package.json | 2 +- packages/core/package.json | 2 +- packages/react-spring/package.json | 2 +- packages/shared/package.json | 2 +- targets/konva/package.json | 2 +- targets/native/package.json | 2 +- targets/three/package.json | 2 +- targets/web/package.json | 2 +- targets/zdog/package.json | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/addons/package.json b/packages/addons/package.json index 1d9c6ce879..c5ee1f1079 100644 --- a/packages/addons/package.json +++ b/packages/addons/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/addons", - "version": "0.0.0", + "version": "9.0.0-canary.809.1.aa2db98.0", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../animated", diff --git a/packages/animated/package.json b/packages/animated/package.json index 232456dbf0..4e8181a07d 100644 --- a/packages/animated/package.json +++ b/packages/animated/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/animated", - "version": "0.0.0", + "version": "9.0.0-canary.809.1.aa2db98.0", "description": "Animated component props for React", "main": "src/index.ts", "scripts": { diff --git a/packages/core/package.json b/packages/core/package.json index 986c632b7d..385bc73681 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/core", - "version": "0.0.0", + "version": "9.0.0-canary.809.1.aa2db98.0", "main": "src/index.ts", "scripts": { "build": "rollup -c", diff --git a/packages/react-spring/package.json b/packages/react-spring/package.json index edb3f30fce..7cf7674377 100644 --- a/packages/react-spring/package.json +++ b/packages/react-spring/package.json @@ -1,6 +1,6 @@ { "name": "react-spring", - "version": "0.0.0", + "version": "9.0.0-canary.809.1.aa2db98.0", "main": "src/web.ts", "dependencies": { "@react-spring/addons": "link:../addons", diff --git a/packages/shared/package.json b/packages/shared/package.json index 2142711414..90f5929e1d 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/shared", - "version": "0.0.0", + "version": "9.0.0-canary.809.1.aa2db98.0", "description": "Globals and shared modules", "main": "src/index.ts", "scripts": { diff --git a/targets/konva/package.json b/targets/konva/package.json index d7edf55a89..69cdc18747 100644 --- a/targets/konva/package.json +++ b/targets/konva/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/konva", - "version": "0.0.0", + "version": "9.0.0-canary.809.1.aa2db98.0", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/targets/native/package.json b/targets/native/package.json index f1f4f18ab5..9d509bbbf2 100644 --- a/targets/native/package.json +++ b/targets/native/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/native", - "version": "0.0.0", + "version": "9.0.0-canary.809.1.aa2db98.0", "main": "src/index.ts", "scripts": { "build": "rollup -c" diff --git a/targets/three/package.json b/targets/three/package.json index 515a35bd78..e89de0d34e 100644 --- a/targets/three/package.json +++ b/targets/three/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/three", - "version": "0.0.0", + "version": "9.0.0-canary.809.1.aa2db98.0", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/targets/web/package.json b/targets/web/package.json index ff883c211e..cc5a901881 100644 --- a/targets/web/package.json +++ b/targets/web/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/web", - "version": "0.0.0", + "version": "9.0.0-canary.809.1.aa2db98.0", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/targets/zdog/package.json b/targets/zdog/package.json index 9a74b7145f..e21750dd27 100644 --- a/targets/zdog/package.json +++ b/targets/zdog/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/zdog", - "version": "0.0.0", + "version": "9.0.0-canary.809.1.aa2db98.0", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", From ec151a05d8ab4f9d98225bf684d8abc6fa0f2488 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Sun, 29 Sep 2019 12:21:55 -0400 Subject: [PATCH 26/43] fix: never set "expiresBy" for non-idle transitions --- packages/core/src/useTransition.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index e1292ce747..118996a074 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -253,7 +253,7 @@ export function useTransition( if (is.fun(onRest)) { onRest(result) } - if (t.phase == LEAVE) { + if (t.phase == LEAVE && t.ctrl.idle) { t.expiresBy = now() + expires if (expires <= 0) { forceUpdate() From 010dfdb6acf0106135a87a008ab88ec1eb537d71 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Sun, 29 Sep 2019 13:54:57 -0400 Subject: [PATCH 27/43] fix: avoid calling "useLayoutEffect" when SSR --- packages/core/src/useTransition.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index 118996a074..15c39e0a48 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -1,7 +1,6 @@ import React, { useRef, useMemo, - useLayoutEffect, useImperativeHandle, ReactNode, RefObject, @@ -10,6 +9,7 @@ import { is, toArray, useForceUpdate, + useIsomorphicLayoutEffect, useOnce, each, OneOrMore, @@ -136,7 +136,7 @@ export function useTransition( // The "onRest" callbacks need a ref to the latest transitions. const usedTransitions = useRef(null) const prevTransitions = usedTransitions.current - useLayoutEffect(() => { + useIsomorphicLayoutEffect(() => { usedTransitions.current = transitions }) @@ -311,7 +311,7 @@ export function useTransition( useImperativeHandle(ref, () => api) - useLayoutEffect( + useIsomorphicLayoutEffect( () => { each(changes, ({ phase, payload }, t) => { t.phase = phase From 56174de02675dcdbe5060055a44c4a13cb18adde Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Sun, 29 Sep 2019 17:33:33 -0400 Subject: [PATCH 28/43] build: never use caret ranges with canary and beta versions --- scripts/prepare.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/prepare.js b/scripts/prepare.js index 86a6bc830d..9363e1bad6 100644 --- a/scripts/prepare.js +++ b/scripts/prepare.js @@ -178,7 +178,9 @@ async function prepare() { for (const depName in deps) { const dep = packages[depName] if (dep) { - deps[depName] = '^' + packages[depName].version + const version = packages[depName].version + deps[depName] = + (/-(canary|beta)\./.test(version) ? '' : '^') + version // Link "dist" packages together. const linkDir = join(pkg.dir, DIST, 'node_modules') From 85b515ee9f4793657b9edf8b77359070575c4929 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Sun, 29 Sep 2019 17:34:14 -0400 Subject: [PATCH 29/43] =?UTF-8?q?chore:=20ship=20it=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lerna.json | 2 +- packages/addons/package.json | 2 +- packages/animated/package.json | 2 +- packages/core/package.json | 2 +- packages/react-spring/package.json | 2 +- packages/shared/package.json | 2 +- targets/konva/package.json | 2 +- targets/native/package.json | 2 +- targets/three/package.json | 2 +- targets/web/package.json | 2 +- targets/zdog/package.json | 2 +- yarn.lock | 25 ++++++++++--------------- 12 files changed, 21 insertions(+), 26 deletions(-) diff --git a/lerna.json b/lerna.json index 4c25507e06..9222671589 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-canary.809.1.aa2db98.0", + "version": "9.0.0-canary.809.2.49361198", "npmClient": "yarn", "useWorkspaces": true, "registry": "https://registry.npmjs.org", diff --git a/packages/addons/package.json b/packages/addons/package.json index c5ee1f1079..214ac18c75 100644 --- a/packages/addons/package.json +++ b/packages/addons/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/addons", - "version": "9.0.0-canary.809.1.aa2db98.0", + "version": "9.0.0-canary.809.2.49361198", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../animated", diff --git a/packages/animated/package.json b/packages/animated/package.json index 4e8181a07d..45131b810f 100644 --- a/packages/animated/package.json +++ b/packages/animated/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/animated", - "version": "9.0.0-canary.809.1.aa2db98.0", + "version": "9.0.0-canary.809.2.49361198", "description": "Animated component props for React", "main": "src/index.ts", "scripts": { diff --git a/packages/core/package.json b/packages/core/package.json index 385bc73681..92f48a50af 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/core", - "version": "9.0.0-canary.809.1.aa2db98.0", + "version": "9.0.0-canary.809.2.49361198", "main": "src/index.ts", "scripts": { "build": "rollup -c", diff --git a/packages/react-spring/package.json b/packages/react-spring/package.json index 7cf7674377..89b4b39077 100644 --- a/packages/react-spring/package.json +++ b/packages/react-spring/package.json @@ -1,6 +1,6 @@ { "name": "react-spring", - "version": "9.0.0-canary.809.1.aa2db98.0", + "version": "9.0.0-canary.809.2.49361198", "main": "src/web.ts", "dependencies": { "@react-spring/addons": "link:../addons", diff --git a/packages/shared/package.json b/packages/shared/package.json index 90f5929e1d..a1ae1ca51e 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/shared", - "version": "9.0.0-canary.809.1.aa2db98.0", + "version": "9.0.0-canary.809.2.49361198", "description": "Globals and shared modules", "main": "src/index.ts", "scripts": { diff --git a/targets/konva/package.json b/targets/konva/package.json index 69cdc18747..0add354cb0 100644 --- a/targets/konva/package.json +++ b/targets/konva/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/konva", - "version": "9.0.0-canary.809.1.aa2db98.0", + "version": "9.0.0-canary.809.2.49361198", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/targets/native/package.json b/targets/native/package.json index 9d509bbbf2..a60e32172f 100644 --- a/targets/native/package.json +++ b/targets/native/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/native", - "version": "9.0.0-canary.809.1.aa2db98.0", + "version": "9.0.0-canary.809.2.49361198", "main": "src/index.ts", "scripts": { "build": "rollup -c" diff --git a/targets/three/package.json b/targets/three/package.json index e89de0d34e..091c0bae25 100644 --- a/targets/three/package.json +++ b/targets/three/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/three", - "version": "9.0.0-canary.809.1.aa2db98.0", + "version": "9.0.0-canary.809.2.49361198", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/targets/web/package.json b/targets/web/package.json index cc5a901881..78907ed9a4 100644 --- a/targets/web/package.json +++ b/targets/web/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/web", - "version": "9.0.0-canary.809.1.aa2db98.0", + "version": "9.0.0-canary.809.2.49361198", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/targets/zdog/package.json b/targets/zdog/package.json index e21750dd27..fa89fd33e0 100644 --- a/targets/zdog/package.json +++ b/targets/zdog/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/zdog", - "version": "9.0.0-canary.809.1.aa2db98.0", + "version": "9.0.0-canary.809.2.49361198", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/yarn.lock b/yarn.lock index 8708cd2faa..2c24f6db2f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1869,57 +1869,57 @@ universal-user-agent "^4.0.0" "@react-spring/addons@link:packages/addons": - version "9.0.0-beta.33" + version "9.0.0-canary.809.2.49361198" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" use-memo-one "^1.1.0" "@react-spring/animated@link:packages/animated": - version "9.0.0-beta.33" + version "9.0.0-canary.809.2.49361198" dependencies: "@react-spring/shared" "link:packages/shared" "@react-spring/core@link:packages/core": - version "9.0.0-beta.33" + version "9.0.0-canary.809.2.49361198" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/shared" "link:packages/shared" use-memo-one "^1.1.0" "@react-spring/konva@link:targets/konva": - version "9.0.0-beta.33" + version "9.0.0-canary.809.2.49361198" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" "@react-spring/shared" "link:packages/shared" "@react-spring/native@link:targets/native": - version "9.0.0-beta.33" + version "9.0.0-canary.809.2.49361198" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" "@react-spring/shared" "link:packages/shared" "@react-spring/shared@link:packages/shared": - version "9.0.0-beta.33" + version "9.0.0-canary.809.2.49361198" "@react-spring/three@link:targets/three": - version "9.0.0-beta.33" + version "9.0.0-canary.809.2.49361198" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" "@react-spring/shared" "link:packages/shared" "@react-spring/web@link:targets/web": - version "9.0.0-beta.34" + version "9.0.0-canary.809.2.49361198" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" "@react-spring/shared" "link:packages/shared" "@react-spring/zdog@link:targets/zdog": - version "9.0.0-beta.33" + version "9.0.0-canary.809.2.49361198" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" @@ -3086,7 +3086,7 @@ commander@mateodelnorte/commander.js: version "2.15.1" resolved "https://codeload.github.com/mateodelnorte/commander.js/tar.gz/9060bf880b791cf39245d425f1e8a41a55616781" dependencies: - find-module-bin "0.0.2" + find-module-bin "^1.0.0" commander@~2.13.0: version "2.13.0" @@ -3673,11 +3673,6 @@ envinfo@^5.7.0: resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-5.12.1.tgz#83068c33e0972eb657d6bc69a6df30badefb46ef" integrity sha512-pwdo0/G3CIkQ0y6PCXq4RdkvId2elvtPCJMG0konqlrfkWQbf1DWeH9K2b/cvu2YgGvPPTOnonZxXM1gikFu1w== -envinfo@^7.3.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-7.3.1.tgz#892e42f7bf858b3446d9414ad240dbaf8da52f09" - integrity sha512-GvXiDTqLYrORVSCuJCsWHPXF5BFvoWMQA9xX4YVjPT1jyS3aZEHUBwjzxU/6LTPF9ReHgVEbX7IEN5UvSXHw/A== - err-code@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/err-code/-/err-code-1.1.2.tgz#06e0116d3028f6aef4806849eb0ea6a748ae6960" From d7e5b4e122215f1059bcb95c36b5e28d312c319c Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Mon, 30 Sep 2019 10:14:43 -0400 Subject: [PATCH 30/43] fix: use "frameLoop.onFrame" in Parallax Closes #820 --- packages/addons/src/parallax.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/addons/src/parallax.tsx b/packages/addons/src/parallax.tsx index 0bb3c06f29..57cf16f149 100644 --- a/packages/addons/src/parallax.tsx +++ b/packages/addons/src/parallax.tsx @@ -5,7 +5,7 @@ import React, { useEffect, CSSProperties, } from 'react' -import { requestAnimationFrame, defaultElement as View } from 'shared/globals' +import { frameLoop, defaultElement as View } from 'shared/globals' import { Controller, SpringConfig, config as configs } from '@react-spring/core' import { withAnimated } from '@react-spring/animated' import { useMemoOne } from 'use-memo-one' @@ -239,7 +239,7 @@ export const Parallax = React.memo( if (!state.busy) { state.busy = true state.current = event.target[getScrollType(horizontal)] - requestAnimationFrame(() => { + frameLoop.onFrame(() => { state.layers.forEach(layer => layer.setPosition(state.space, state.current) ) @@ -254,7 +254,7 @@ export const Parallax = React.memo( const onResize = () => { const update = () => state.update() - requestAnimationFrame(update) + frameLoop.onFrame(update) setTimeout(update, 150) // Some browsers don't fire on maximize! } From d423a84956a696142be46000b621ce82b0453d9c Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Mon, 30 Sep 2019 10:31:06 -0400 Subject: [PATCH 31/43] build: use @babel/runtime/regenerator Fixes https://github.com/react-spring/react-spring/issues/642#issuecomment-536562278 --- rollup.config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rollup.config.js b/rollup.config.js index e1efbe6de3..aa24bcda29 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -125,7 +125,7 @@ export const getBabelOptions = ({ useESModules }, targets) => ({ plugins: [ ['@babel/plugin-proposal-class-properties', { loose: true }], ['@babel/plugin-proposal-object-rest-spread', { loose: true }], - ['@babel/plugin-transform-runtime', { regenerator: false, useESModules }], + ['@babel/plugin-transform-runtime', { useESModules }], ], }) From deb1e16020b397af8a5d19fb70560b6fe68bc089 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Mon, 30 Sep 2019 11:24:44 -0400 Subject: [PATCH 32/43] chore: add --canary flag to "yarn release" --- CONTRIBUTING.md | 12 +++++- package.json | 6 ++- scripts/release.js | 90 +++++++++++++++++++++++++++++++++++++++++++++ yarn.lock | 91 ++++++++++++++++++++++++++++++++++++++++++---- 4 files changed, 187 insertions(+), 12 deletions(-) create mode 100644 scripts/release.js diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1569eff81e..3f4ad162c3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -56,6 +56,14 @@ React 16.8+ has global state to support its "hooks" feature, so you need to ensu # Publishing -Run `yarn bump` to analyze commits and increment the version of any updated packages. +To publish a new version: -Run `yarn release` to publish any packages with a new version. +``` +yarn release +``` + +To publish a **canary** version: + +``` +yarn release --canary +``` diff --git a/package.json b/package.json index 470b12c560..ac3647745d 100644 --- a/package.json +++ b/package.json @@ -38,10 +38,9 @@ }, "scripts": { "build": "bic", - "bump": "lerna version && yarn --force", "clean": "lerna exec --parallel --no-bail -- rimraf node_modules dist .rpt2_cache .bic_cache", "prepare": "node ./scripts/prepare.js && bic", - "release": "lerna publish", + "release": "node ./scripts/release.js", "test": "jest", "test:cov": "jest --coverage", "test:ts": "cd packages/react-spring && tsc -p . --noEmit" @@ -66,6 +65,8 @@ "@types/react": "^16.8.19", "build-if-changed": "^1.5.0", "chalk": "^2.4.2", + "enquirer": "^2.3.2", + "execa": "^2.0.4", "fs-extra": "7.0.1", "husky": "1.3.1", "jest": "^24.8.0", @@ -84,6 +85,7 @@ "rollup-plugin-node-resolve": "4.0.0", "rollup-plugin-terser": "5.0.0", "rollup-plugin-typescript2": "0.21.1", + "sade": "^1.6.1", "sort-package-json": "1.22.1", "spec.ts": "1.1.3", "ts-jest": "^24.0.2", diff --git a/scripts/release.js b/scripts/release.js new file mode 100644 index 0000000000..7b888214e9 --- /dev/null +++ b/scripts/release.js @@ -0,0 +1,90 @@ +const { prompt } = require('enquirer') +const chalk = require('chalk') +const execa = require('execa') +const sade = require('sade') +const path = require('path') + +const lernaBin = './node_modules/.bin/lerna' + +sade('release', true) + .version('1.0.0') + .describe('Release a version') + .option('--canary', 'Release the last commit without a tag') + .option('--no-commit', 'Release the current version as-is') + .action(opts => { + process.chdir(path.dirname(__dirname)) + return opts.canary ? publishCanary(opts) : publish() + }) + .parse(process.argv) + .catch(err => { + if (!err.command) { + console.error(err) + } else if (err.stderr) { + console.error(err.stderr) + } + process.exit(1) + }) + +async function publish() { + exec(`${lernaBin} version`) + updateLockfile() + exec(`${lernaBin} publish`) +} + +async function publishCanary(opts) { + if (opts.commit !== false) { + const lastVersion = require('../lerna.json').version + const match = + /([^-]+)(?:-canary\.([^\.]+)\.([^\.]+))?/.exec(lastVersion) || [] + + let version = await ask('Version', match[1]) + + const pr = await ask('PR number', match[2]) + const build = await ask('Build number', Number(match[3] || 0) + 1) + + const head = exec('git rev-parse HEAD', { silent: true }).stdout + const commit = await ask('Commit hash', head.slice(0, 7)) + + // Create the version commit. + version = `${version}-canary.${pr}.${build}.${commit}` + exec(`${lernaBin} version ${version} --yes`) + + updateLockfile() + } + + // Publish the canary with a temporary tag. + const publishCmd = `cd dist && npm publish --tag tmp && npm dist-tag rm \\$LERNA_PACKAGE_NAME tmp` + exec(`${lernaBin} exec -- ${publishCmd}`) +} + +function updateLockfile() { + // Ensure "yarn.lock" is up-to-date. + exec(`yarn clean`) + exec(`yarn --force`) + + // Merge the "yarn.lock" changes into the version commit. + exec(`git add yarn.lock`) + exec(`git commit --amend --no-edit`) + + // Ensure the "dist" directories are in good condition. + exec(`yarn prepare`) +} + +function exec(cmd, { silent } = {}) { + cmd = cmd.trim().replace(/\n /g, '\n') + if (!silent) console.log(`\nExecuting command:\n ${chalk.green(cmd)}\n`) + cmd = cmd.split(/[\s]+/g) + return execa.sync(cmd[0], cmd.slice(1), { + stdio: silent ? 'pipe' : 'inherit', + }) +} + +async function ask(message, initial) { + const { value } = await prompt({ + type: 'input', + name: 'value', + message, + initial, + }) + return value +} diff --git a/yarn.lock b/yarn.lock index 2c24f6db2f..a44ca916f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2210,6 +2210,11 @@ ansi-colors@^1.0.1: dependencies: ansi-wrap "^0.1.0" +ansi-colors@^3.2.1: + version "3.2.4" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" + integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== + ansi-cyan@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/ansi-cyan/-/ansi-cyan-0.1.1.tgz#538ae528af8982f28ae30d86f2f17456d2609873" @@ -3329,7 +3334,7 @@ cross-spawn@^5.0.1, cross-spawn@^5.1.0: shebang-command "^1.2.0" which "^1.2.9" -cross-spawn@^6.0.0: +cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== @@ -3412,7 +3417,7 @@ dateformat@^3.0.0: resolved "https://registry.yarnpkg.com/dateformat/-/dateformat-3.0.3.tgz#a6e37499a4d9a9cf85ef5872044d62901c9889ae" integrity sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q== -debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.4.4: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -3668,6 +3673,13 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" +enquirer@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.2.tgz#1c30284907cadff5ed2404bd8396036dd3da070e" + integrity sha512-PLhTMPUXlnaIv9D3Cq3/Zr1xb7soeDDgunobyCmYLUG19n24dvC8i+ZZgm2DekGpDnx7JvFSHV7lxfM58PMtbA== + dependencies: + ansi-colors "^3.2.1" + envinfo@^5.7.0: version "5.12.1" resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-5.12.1.tgz#83068c33e0972eb657d6bc69a6df30badefb46ef" @@ -3848,6 +3860,21 @@ execa@^1.0.0: signal-exit "^3.0.0" strip-eof "^1.0.0" +execa@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/execa/-/execa-2.0.4.tgz#2f5cc589c81db316628627004ea4e37b93391d8e" + integrity sha512-VcQfhuGD51vQUQtKIq2fjGDLDbL6N1DTQVpYzxZ7LPIXw3HqTuIz6uxRmpV1qf8i31LHf2kjiaGI+GdHwRgbnQ== + dependencies: + cross-spawn "^6.0.5" + get-stream "^5.0.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^3.0.0" + onetime "^5.1.0" + p-finally "^2.0.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + exit@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/exit/-/exit-0.1.2.tgz#0632638f8d877cc82107d30a0fff1a17cba1cd0c" @@ -4134,12 +4161,12 @@ find-cache-dir@^2.0.0: make-dir "^2.0.0" pkg-dir "^3.0.0" -find-module-bin@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/find-module-bin/-/find-module-bin-0.0.2.tgz#99ef84fb548aedae3bfe4da14b61846cd9888666" - integrity sha1-me+E+1SK7a47/k2hS2GEbNmIhmY= +find-module-bin@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/find-module-bin/-/find-module-bin-1.1.0.tgz#5f465cf4b2431deb184b3ebaee8ad6c9c5af8523" + integrity sha512-v53mIFOiuump1BSkwURrLblQm+LpWDVQOkQdph/xLPRrbyCU48RryPUSYxih6+gkAdNw9AkqWL7OXUhmE1ddmg== dependencies: - debug "^2.4.4" + debug "^4.1.1" global-paths "^1.0.0" find-up@^1.0.0: @@ -4371,6 +4398,13 @@ get-stream@^4.0.0, get-stream@^4.1.0: dependencies: pump "^3.0.0" +get-stream@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" + integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== + dependencies: + pump "^3.0.0" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -5170,6 +5204,11 @@ is-stream@^1.0.1, is-stream@^1.1.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + is-symbol@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38" @@ -6606,7 +6645,7 @@ mimic-fn@^1.0.0: resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== -mimic-fn@^2.0.0: +mimic-fn@^2.0.0, mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== @@ -7006,6 +7045,13 @@ npm-run-path@^2.0.0: dependencies: path-key "^2.0.0" +npm-run-path@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-3.1.0.tgz#7f91be317f6a466efed3c9f2980ad8a4ee8b0fa5" + integrity sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg== + dependencies: + path-key "^3.0.0" + "npmlog@0 || 1 || 2 || 3 || 4", npmlog@^4.0.2, npmlog@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" @@ -7140,6 +7186,13 @@ onetime@^2.0.0: dependencies: mimic-fn "^1.0.0" +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + dependencies: + mimic-fn "^2.1.0" + opn@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/opn/-/opn-3.0.3.tgz#b6d99e7399f78d65c3baaffef1fb288e9b85243a" @@ -7233,6 +7286,11 @@ p-finally@^1.0.0: resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= +p-finally@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561" + integrity sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw== + p-is-promise@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" @@ -7421,6 +7479,11 @@ path-key@^2.0.0, path-key@^2.0.1: resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= +path-key@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.0.tgz#99a10d870a803bdd5ee6f0470e58dfcd2f9a54d3" + integrity sha512-8cChqz0RP6SHJkMt48FW0A7+qUOn+OsnOsVtzI59tZ8m+5bCSk7hzwET0pulwOM2YMn9J1efb07KB9l9f30SGg== + path-parse@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" @@ -8483,6 +8546,13 @@ rxjs@^6.4.0: dependencies: tslib "^1.9.0" +sade@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/sade/-/sade-1.6.1.tgz#aba16655e998b2b68beb9f13938af010f42eddd2" + integrity sha512-USHm9quYNmJwFwhOnEuJohdnBhUOKV1mhL0koHSJMLJaesRX0nuDuzbWmtUBbUmXkwTalLtUBzDlEnU940BiQA== + dependencies: + mri "^1.1.0" + safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" @@ -9111,6 +9181,11 @@ strip-eof@^1.0.0: resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + strip-indent@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-1.0.1.tgz#0c7962a6adefa7bbd4ac366460a638552ae1a0a2" From 99c3827210d44b9f8f5e024351123229f5a84f63 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Mon, 30 Sep 2019 12:09:55 -0400 Subject: [PATCH 33/43] =?UTF-8?q?chore:=20ship=20it=20=F0=9F=9A=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lerna.json | 2 +- packages/addons/package.json | 2 +- packages/animated/package.json | 2 +- packages/core/package.json | 2 +- packages/react-spring/package.json | 2 +- packages/shared/package.json | 2 +- targets/konva/package.json | 2 +- targets/native/package.json | 2 +- targets/three/package.json | 2 +- targets/web/package.json | 2 +- targets/zdog/package.json | 2 +- yarn.lock | 18 +++++++++--------- 12 files changed, 20 insertions(+), 20 deletions(-) diff --git a/lerna.json b/lerna.json index 9222671589..ac301b56c9 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-canary.809.2.49361198", + "version": "9.0.0-canary.809.3.a66b280", "npmClient": "yarn", "useWorkspaces": true, "registry": "https://registry.npmjs.org", diff --git a/packages/addons/package.json b/packages/addons/package.json index 214ac18c75..624abefef9 100644 --- a/packages/addons/package.json +++ b/packages/addons/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/addons", - "version": "9.0.0-canary.809.2.49361198", + "version": "9.0.0-canary.809.3.a66b280", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../animated", diff --git a/packages/animated/package.json b/packages/animated/package.json index 45131b810f..01615022f0 100644 --- a/packages/animated/package.json +++ b/packages/animated/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/animated", - "version": "9.0.0-canary.809.2.49361198", + "version": "9.0.0-canary.809.3.a66b280", "description": "Animated component props for React", "main": "src/index.ts", "scripts": { diff --git a/packages/core/package.json b/packages/core/package.json index 92f48a50af..4c21d0ca01 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/core", - "version": "9.0.0-canary.809.2.49361198", + "version": "9.0.0-canary.809.3.a66b280", "main": "src/index.ts", "scripts": { "build": "rollup -c", diff --git a/packages/react-spring/package.json b/packages/react-spring/package.json index 89b4b39077..0d216b030c 100644 --- a/packages/react-spring/package.json +++ b/packages/react-spring/package.json @@ -1,6 +1,6 @@ { "name": "react-spring", - "version": "9.0.0-canary.809.2.49361198", + "version": "9.0.0-canary.809.3.a66b280", "main": "src/web.ts", "dependencies": { "@react-spring/addons": "link:../addons", diff --git a/packages/shared/package.json b/packages/shared/package.json index a1ae1ca51e..727993dc5b 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/shared", - "version": "9.0.0-canary.809.2.49361198", + "version": "9.0.0-canary.809.3.a66b280", "description": "Globals and shared modules", "main": "src/index.ts", "scripts": { diff --git a/targets/konva/package.json b/targets/konva/package.json index 0add354cb0..e5f2e6711e 100644 --- a/targets/konva/package.json +++ b/targets/konva/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/konva", - "version": "9.0.0-canary.809.2.49361198", + "version": "9.0.0-canary.809.3.a66b280", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/targets/native/package.json b/targets/native/package.json index a60e32172f..cdd7f5371b 100644 --- a/targets/native/package.json +++ b/targets/native/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/native", - "version": "9.0.0-canary.809.2.49361198", + "version": "9.0.0-canary.809.3.a66b280", "main": "src/index.ts", "scripts": { "build": "rollup -c" diff --git a/targets/three/package.json b/targets/three/package.json index 091c0bae25..6d0497eb9e 100644 --- a/targets/three/package.json +++ b/targets/three/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/three", - "version": "9.0.0-canary.809.2.49361198", + "version": "9.0.0-canary.809.3.a66b280", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/targets/web/package.json b/targets/web/package.json index 78907ed9a4..2919ffe991 100644 --- a/targets/web/package.json +++ b/targets/web/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/web", - "version": "9.0.0-canary.809.2.49361198", + "version": "9.0.0-canary.809.3.a66b280", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/targets/zdog/package.json b/targets/zdog/package.json index fa89fd33e0..10b06eb02f 100644 --- a/targets/zdog/package.json +++ b/targets/zdog/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/zdog", - "version": "9.0.0-canary.809.2.49361198", + "version": "9.0.0-canary.809.3.a66b280", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/yarn.lock b/yarn.lock index a44ca916f2..f7772512f9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1869,57 +1869,57 @@ universal-user-agent "^4.0.0" "@react-spring/addons@link:packages/addons": - version "9.0.0-canary.809.2.49361198" + version "9.0.0-canary.809.3.a66b280" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" use-memo-one "^1.1.0" "@react-spring/animated@link:packages/animated": - version "9.0.0-canary.809.2.49361198" + version "9.0.0-canary.809.3.a66b280" dependencies: "@react-spring/shared" "link:packages/shared" "@react-spring/core@link:packages/core": - version "9.0.0-canary.809.2.49361198" + version "9.0.0-canary.809.3.a66b280" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/shared" "link:packages/shared" use-memo-one "^1.1.0" "@react-spring/konva@link:targets/konva": - version "9.0.0-canary.809.2.49361198" + version "9.0.0-canary.809.3.a66b280" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" "@react-spring/shared" "link:packages/shared" "@react-spring/native@link:targets/native": - version "9.0.0-canary.809.2.49361198" + version "9.0.0-canary.809.3.a66b280" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" "@react-spring/shared" "link:packages/shared" "@react-spring/shared@link:packages/shared": - version "9.0.0-canary.809.2.49361198" + version "9.0.0-canary.809.3.a66b280" "@react-spring/three@link:targets/three": - version "9.0.0-canary.809.2.49361198" + version "9.0.0-canary.809.3.a66b280" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" "@react-spring/shared" "link:packages/shared" "@react-spring/web@link:targets/web": - version "9.0.0-canary.809.2.49361198" + version "9.0.0-canary.809.3.a66b280" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" "@react-spring/shared" "link:packages/shared" "@react-spring/zdog@link:targets/zdog": - version "9.0.0-canary.809.2.49361198" + version "9.0.0-canary.809.3.a66b280" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" From 0637589f5788fa3a2c0cb3cb56031ea37b35724e Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Wed, 2 Oct 2019 07:57:32 -0400 Subject: [PATCH 34/43] fix: make "keys" a valid useTransition prop You can use either "key" or "keys", whatever works for you. --- packages/core/src/useTransition.tsx | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/packages/core/src/useTransition.tsx b/packages/core/src/useTransition.tsx index 15c39e0a48..58de042878 100644 --- a/packages/core/src/useTransition.tsx +++ b/packages/core/src/useTransition.tsx @@ -63,7 +63,7 @@ type PhaseProps = { type Key = string | number -export type ItemKeys = Key | ReadonlyArray | ((item: T) => Key) | null +export type ItemKeys = OneOrMore | ((item: T) => Key) | null export type UseTransitionProps = Merge< AnimationProps & AnimationEvents, @@ -100,6 +100,13 @@ export interface TransitionFn { ): ReactNode[] } +function getKeys( + items: readonly any[], + { key, keys = key }: { key?: ItemKeys; keys?: ItemKeys } +): readonly any[] { + return is.und(keys) ? items : is.fun(keys) ? items.map(keys) : toArray(keys) +} + export function useTransition( data: OneOrMore, props: Props & PhaseProps & UseTransitionProps, @@ -111,13 +118,7 @@ export function useTransition( props: PhaseProps & UseTransitionProps, deps?: any[] ): TransitionFn { - const { key, ref, reset, sort, trail = 0, expires = Infinity } = props - - if ('keys' in props) { - console.warn( - 'Unknown prop "keys" was passed to useTransition. Did you mean "key"?' - ) - } + const { ref, reset, sort, trail = 0, expires = Infinity } = props // Every item has its own transition. const items = toArray(data) @@ -127,11 +128,7 @@ export function useTransition( // The `key` prop can be undefined (which means the items themselves are used // as keys), or a function (which maps each item to its key), or an array of // keys (which are assigned to each item by index). - const keys: readonly any[] = is.und(key) - ? items - : is.fun(key) - ? items.map(key) - : toArray(key) + const keys = getKeys(items, props) // The "onRest" callbacks need a ref to the latest transitions. const usedTransitions = useRef(null) From 1ab611ca4ee12b1ba575bc1193ce007c0b475c99 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Thu, 3 Oct 2019 10:36:42 -0400 Subject: [PATCH 35/43] 9.0.0-canary.809.4.a637589 --- lerna.json | 2 +- packages/addons/package.json | 2 +- packages/animated/package.json | 2 +- packages/core/package.json | 2 +- packages/react-spring/package.json | 2 +- packages/shared/package.json | 2 +- targets/konva/package.json | 2 +- targets/native/package.json | 2 +- targets/three/package.json | 2 +- targets/web/package.json | 2 +- targets/zdog/package.json | 2 +- yarn.lock | 18 +++++++++--------- 12 files changed, 20 insertions(+), 20 deletions(-) diff --git a/lerna.json b/lerna.json index ac301b56c9..9501a82f55 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-canary.809.3.a66b280", + "version": "9.0.0-canary.809.4.a637589", "npmClient": "yarn", "useWorkspaces": true, "registry": "https://registry.npmjs.org", diff --git a/packages/addons/package.json b/packages/addons/package.json index 624abefef9..325c621540 100644 --- a/packages/addons/package.json +++ b/packages/addons/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/addons", - "version": "9.0.0-canary.809.3.a66b280", + "version": "9.0.0-canary.809.4.a637589", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../animated", diff --git a/packages/animated/package.json b/packages/animated/package.json index 01615022f0..17f529229b 100644 --- a/packages/animated/package.json +++ b/packages/animated/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/animated", - "version": "9.0.0-canary.809.3.a66b280", + "version": "9.0.0-canary.809.4.a637589", "description": "Animated component props for React", "main": "src/index.ts", "scripts": { diff --git a/packages/core/package.json b/packages/core/package.json index 4c21d0ca01..8f7f386343 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/core", - "version": "9.0.0-canary.809.3.a66b280", + "version": "9.0.0-canary.809.4.a637589", "main": "src/index.ts", "scripts": { "build": "rollup -c", diff --git a/packages/react-spring/package.json b/packages/react-spring/package.json index 0d216b030c..4973919c87 100644 --- a/packages/react-spring/package.json +++ b/packages/react-spring/package.json @@ -1,6 +1,6 @@ { "name": "react-spring", - "version": "9.0.0-canary.809.3.a66b280", + "version": "9.0.0-canary.809.4.a637589", "main": "src/web.ts", "dependencies": { "@react-spring/addons": "link:../addons", diff --git a/packages/shared/package.json b/packages/shared/package.json index 727993dc5b..961914a284 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/shared", - "version": "9.0.0-canary.809.3.a66b280", + "version": "9.0.0-canary.809.4.a637589", "description": "Globals and shared modules", "main": "src/index.ts", "scripts": { diff --git a/targets/konva/package.json b/targets/konva/package.json index e5f2e6711e..98d3dbd85e 100644 --- a/targets/konva/package.json +++ b/targets/konva/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/konva", - "version": "9.0.0-canary.809.3.a66b280", + "version": "9.0.0-canary.809.4.a637589", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/targets/native/package.json b/targets/native/package.json index cdd7f5371b..7a092cd2b1 100644 --- a/targets/native/package.json +++ b/targets/native/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/native", - "version": "9.0.0-canary.809.3.a66b280", + "version": "9.0.0-canary.809.4.a637589", "main": "src/index.ts", "scripts": { "build": "rollup -c" diff --git a/targets/three/package.json b/targets/three/package.json index 6d0497eb9e..6fb70de6da 100644 --- a/targets/three/package.json +++ b/targets/three/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/three", - "version": "9.0.0-canary.809.3.a66b280", + "version": "9.0.0-canary.809.4.a637589", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/targets/web/package.json b/targets/web/package.json index 2919ffe991..c2b107e236 100644 --- a/targets/web/package.json +++ b/targets/web/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/web", - "version": "9.0.0-canary.809.3.a66b280", + "version": "9.0.0-canary.809.4.a637589", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/targets/zdog/package.json b/targets/zdog/package.json index 10b06eb02f..ae883ad3cb 100644 --- a/targets/zdog/package.json +++ b/targets/zdog/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/zdog", - "version": "9.0.0-canary.809.3.a66b280", + "version": "9.0.0-canary.809.4.a637589", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/yarn.lock b/yarn.lock index f7772512f9..2d478f60e5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1869,57 +1869,57 @@ universal-user-agent "^4.0.0" "@react-spring/addons@link:packages/addons": - version "9.0.0-canary.809.3.a66b280" + version "9.0.0-canary.809.4.a637589" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" use-memo-one "^1.1.0" "@react-spring/animated@link:packages/animated": - version "9.0.0-canary.809.3.a66b280" + version "9.0.0-canary.809.4.a637589" dependencies: "@react-spring/shared" "link:packages/shared" "@react-spring/core@link:packages/core": - version "9.0.0-canary.809.3.a66b280" + version "9.0.0-canary.809.4.a637589" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/shared" "link:packages/shared" use-memo-one "^1.1.0" "@react-spring/konva@link:targets/konva": - version "9.0.0-canary.809.3.a66b280" + version "9.0.0-canary.809.4.a637589" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" "@react-spring/shared" "link:packages/shared" "@react-spring/native@link:targets/native": - version "9.0.0-canary.809.3.a66b280" + version "9.0.0-canary.809.4.a637589" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" "@react-spring/shared" "link:packages/shared" "@react-spring/shared@link:packages/shared": - version "9.0.0-canary.809.3.a66b280" + version "9.0.0-canary.809.4.a637589" "@react-spring/three@link:targets/three": - version "9.0.0-canary.809.3.a66b280" + version "9.0.0-canary.809.4.a637589" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" "@react-spring/shared" "link:packages/shared" "@react-spring/web@link:targets/web": - version "9.0.0-canary.809.3.a66b280" + version "9.0.0-canary.809.4.a637589" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" "@react-spring/shared" "link:packages/shared" "@react-spring/zdog@link:targets/zdog": - version "9.0.0-canary.809.3.a66b280" + version "9.0.0-canary.809.4.a637589" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" From 52abf0886e8ee5527975f66b858c36246ac7b560 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Thu, 3 Oct 2019 11:05:15 -0400 Subject: [PATCH 36/43] chore: add --no-clean to "yarn release" --- scripts/release.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/release.js b/scripts/release.js index 7b888214e9..e8af51c410 100644 --- a/scripts/release.js +++ b/scripts/release.js @@ -11,6 +11,7 @@ sade('release', true) .describe('Release a version') .option('--canary', 'Release the last commit without a tag') .option('--no-commit', 'Release the current version as-is') + .option('--no-clean', 'Skip "yarn clean" for faster publishing') .action(opts => { process.chdir(path.dirname(__dirname)) return opts.canary ? publishCanary(opts) : publish() @@ -49,7 +50,7 @@ async function publishCanary(opts) { version = `${version}-canary.${pr}.${build}.${commit}` exec(`${lernaBin} version ${version} --yes`) - updateLockfile() + updateLockfile(opts) } // Publish the canary with a temporary tag. @@ -57,9 +58,9 @@ async function publishCanary(opts) { exec(`${lernaBin} exec -- ${publishCmd}`) } -function updateLockfile() { +function updateLockfile(opts = {}) { // Ensure "yarn.lock" is up-to-date. - exec(`yarn clean`) + if (opts.clean !== false) exec(`yarn clean`) exec(`yarn --force`) // Merge the "yarn.lock" changes into the version commit. From 13b904e3252e2e450c005a816899141e267b3787 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Thu, 3 Oct 2019 11:05:29 -0400 Subject: [PATCH 37/43] chore: remove extraneous "yarn prepare" call --- scripts/release.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/scripts/release.js b/scripts/release.js index e8af51c410..1f878753c4 100644 --- a/scripts/release.js +++ b/scripts/release.js @@ -66,9 +66,6 @@ function updateLockfile(opts = {}) { // Merge the "yarn.lock" changes into the version commit. exec(`git add yarn.lock`) exec(`git commit --amend --no-edit`) - - // Ensure the "dist" directories are in good condition. - exec(`yarn prepare`) } function exec(cmd, { silent } = {}) { From 66abac1416f3b4ebe3a01a33e4f1f72ec2abb91a Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Thu, 3 Oct 2019 11:20:33 -0400 Subject: [PATCH 38/43] types: avoid issue with rollup-plugin-dts Using "declare class" in a ".ts" module causes problems. --- targets/native/src/animated.ts | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/targets/native/src/animated.ts b/targets/native/src/animated.ts index ecc8bb55f5..5c689a07ed 100644 --- a/targets/native/src/animated.ts +++ b/targets/native/src/animated.ts @@ -1,4 +1,4 @@ -import { ForwardRefExoticComponent, Component, ReactNode } from 'react' +import { ForwardRefExoticComponent, ComponentClass, ReactNode } from 'react' import { withAnimated, extendAnimated } from '@react-spring/animated' import { Text, @@ -6,8 +6,6 @@ import { Image, ViewProps, ViewStyle, - NativeMethodsMixin, - Constructor, RecursiveArray, } from 'react-native' import { @@ -17,14 +15,12 @@ import { FluidValue, } from 'shared' -declare class ViewComponent extends Component< - // @types/react-native forgot to add "children" to the "View" component?? - ViewProps & { children?: ReactNode } -> {} - // These are converted into `animated` components const elements = { - View: View as Constructor & typeof ViewComponent, + View: View as ComponentClass< + // @types/react-native forgot to add "children" to the "View" component?? + ViewProps & { children?: ReactNode } + >, Text, Image, } From a90f0be590f130fceb2753b5a9d6d1ae85ee0c84 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Thu, 3 Oct 2019 12:19:20 -0400 Subject: [PATCH 39/43] cli: properly handle "sade.parse" return value See here: https://github.com/lukeed/sade/pull/31 --- scripts/release.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/scripts/release.js b/scripts/release.js index 1f878753c4..57eb86f3e9 100644 --- a/scripts/release.js +++ b/scripts/release.js @@ -6,7 +6,7 @@ const path = require('path') const lernaBin = './node_modules/.bin/lerna' -sade('release', true) +const cli = sade('release', true) .version('1.0.0') .describe('Release a version') .option('--canary', 'Release the last commit without a tag') @@ -16,15 +16,15 @@ sade('release', true) process.chdir(path.dirname(__dirname)) return opts.canary ? publishCanary(opts) : publish() }) - .parse(process.argv) - .catch(err => { - if (!err.command) { - console.error(err) - } else if (err.stderr) { - console.error(err.stderr) - } - process.exit(1) - }) + +Promise.resolve(cli.parse(process.argv)).catch(err => { + if (!err.command) { + console.error(err) + } else if (err.stderr) { + console.error(err.stderr) + } + process.exit(1) +}) async function publish() { exec(`${lernaBin} version`) From b0b5c4e61ab3bc3ee5e727d33700d06939f4b123 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Thu, 3 Oct 2019 13:26:19 -0400 Subject: [PATCH 40/43] chore: run "test:ts" script during prepare phase --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index ac3647745d..fa154577ee 100644 --- a/package.json +++ b/package.json @@ -39,7 +39,7 @@ "scripts": { "build": "bic", "clean": "lerna exec --parallel --no-bail -- rimraf node_modules dist .rpt2_cache .bic_cache", - "prepare": "node ./scripts/prepare.js && bic", + "prepare": "node ./scripts/prepare.js && bic && yarn test:ts", "release": "node ./scripts/release.js", "test": "jest", "test:cov": "jest --coverage", From 3cee32883d2977818519ef568fab9a25f9d1731f Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Thu, 3 Oct 2019 13:26:58 -0400 Subject: [PATCH 41/43] cli: add --dry-run to "yarn release" --- scripts/release.js | 84 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 21 deletions(-) diff --git a/scripts/release.js b/scripts/release.js index 57eb86f3e9..07ea2474f0 100644 --- a/scripts/release.js +++ b/scripts/release.js @@ -10,11 +10,13 @@ const cli = sade('release', true) .version('1.0.0') .describe('Release a version') .option('--canary', 'Release the last commit without a tag') + .option('--dry-run, -n', 'Disable side effects for testing') .option('--no-commit', 'Release the current version as-is') .option('--no-clean', 'Skip "yarn clean" for faster publishing') .action(opts => { + opts.dry = !!opts['dry-run'] process.chdir(path.dirname(__dirname)) - return opts.canary ? publishCanary(opts) : publish() + return opts.canary ? publishCanary(opts) : publish(opts) }) Promise.resolve(cli.parse(process.argv)).catch(err => { @@ -26,41 +28,62 @@ Promise.resolve(cli.parse(process.argv)).catch(err => { process.exit(1) }) -async function publish() { +async function publish(opts) { exec(`${lernaBin} version`) + process.on('exit', () => { + if (opts.dry) { + undoCommit() + } + }) updateLockfile() - exec(`${lernaBin} publish`) + execDry(`${lernaBin} publish`, opts) } async function publishCanary(opts) { - if (opts.commit !== false) { - const lastVersion = require('../lerna.json').version - const match = - /([^-]+)(?:-canary\.([^\.]+)\.([^\.]+))?/.exec(lastVersion) || [] + // Publish the canary with a temporary tag. + const publishUntagged = () => + exec(` + ${lernaBin} exec + -- cd dist + && npm publish ${opts.dry ? '--dry-run' : '--tag tmp'} + ${opts.dry ? '' : '&& npm dist-tag rm \\$LERNA_PACKAGE_NAME tmp'} + `) - let version = await ask('Version', match[1]) + if (opts.commit === false) { + return publishUntagged() + } - const pr = await ask('PR number', match[2]) - const build = await ask('Build number', Number(match[3] || 0) + 1) + const lastVersion = require('../lerna.json').version + const match = + /([^-]+)(?:-canary\.([^\.]+)\.([^\.]+))?/.exec(lastVersion) || [] - const head = exec('git rev-parse HEAD', { silent: true }).stdout - const commit = await ask('Commit hash', head.slice(0, 7)) + let version = await ask('Version', match[1]) - // Create the version commit. - version = `${version}-canary.${pr}.${build}.${commit}` - exec(`${lernaBin} version ${version} --yes`) + const pr = await ask('PR number', match[2]) + const build = await ask('Build number', Number(match[3] || 0) + 1) - updateLockfile(opts) - } + const head = exec('git rev-parse HEAD', { silent: true }).stdout + const commit = await ask('Commit hash', head.slice(0, 7)) - // Publish the canary with a temporary tag. - const publishCmd = `cd dist && npm publish --tag tmp && npm dist-tag rm \\$LERNA_PACKAGE_NAME tmp` - exec(`${lernaBin} exec -- ${publishCmd}`) + // Create the version commit. + version = `${version}-canary.${pr}.${build}.${commit}` + exec(`${lernaBin} version ${version} --yes`) + process.on('exit', () => { + if (opts.dry) { + undoCommit(commit => commit == version) + } + }) + + updateLockfile(opts) + publishUntagged() } function updateLockfile(opts = {}) { + if (opts.clean !== false) { + exec(`yarn clean`) + } + // Ensure "yarn.lock" is up-to-date. - if (opts.clean !== false) exec(`yarn clean`) exec(`yarn --force`) // Merge the "yarn.lock" changes into the version commit. @@ -68,6 +91,25 @@ function updateLockfile(opts = {}) { exec(`git commit --amend --no-edit`) } +function undoCommit(shouldUndo) { + if (shouldUndo) { + // Pass the commit title to the `shouldUndo` function. + const { stdout } = exec(`git --no-pager show -s --format=%s HEAD`, { + silent: true, + }) + if (!shouldUndo(stdout)) return + } + exec(`git reset --hard HEAD^`) +} + +function execDry(cmd, opts) { + if (opts.dry) { + console.log(`\nSkipping command:\n ${chalk.yellow(cmd)}\n`) + } else { + exec(cmd, opts) + } +} + function exec(cmd, { silent } = {}) { cmd = cmd.trim().replace(/\n /g, '\n') if (!silent) console.log(`\nExecuting command:\n ${chalk.green(cmd)}\n`) From f01ecc21c18dfbc0d2423fd962f3bda5c00bf235 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Thu, 3 Oct 2019 13:45:18 -0400 Subject: [PATCH 42/43] chore: fix "test:ts" script --- packages/core/tsconfig.json | 2 +- packages/react-spring/tsconfig.json | 4 ++-- packages/shared/src/types/global.ts | 6 ++++++ packages/shared/src/types/index.ts | 1 + 4 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 packages/shared/src/types/global.ts diff --git a/packages/core/tsconfig.json b/packages/core/tsconfig.json index 33ae980dbb..99a9536c9a 100644 --- a/packages/core/tsconfig.json +++ b/packages/core/tsconfig.json @@ -5,7 +5,7 @@ "esModuleInterop": true, "forceConsistentCasingInFileNames": true, "jsx": "react", - "lib": ["dom", "es2017"], + "lib": ["es2017"], "moduleResolution": "node", "noEmitOnError": true, "noFallthroughCasesInSwitch": true, diff --git a/packages/react-spring/tsconfig.json b/packages/react-spring/tsconfig.json index 040013db8b..5a1580bdb6 100644 --- a/packages/react-spring/tsconfig.json +++ b/packages/react-spring/tsconfig.json @@ -12,8 +12,8 @@ "noUnusedLocals": true, "noUnusedParameters": true, "paths": { - "shared": ["../shared/dist"], - "shared/*": ["../shared/dist/*"] + "shared": ["../shared/src"], + "shared/*": ["../shared/src/*"] }, "preserveSymlinks": true, "skipLibCheck": true, diff --git a/packages/shared/src/types/global.ts b/packages/shared/src/types/global.ts new file mode 100644 index 0000000000..de3c214158 --- /dev/null +++ b/packages/shared/src/types/global.ts @@ -0,0 +1,6 @@ +declare function clearTimeout(handle?: number): void +declare function setTimeout( + handler: Function, + timeout?: number, + ...arguments: any[] +): number diff --git a/packages/shared/src/types/index.ts b/packages/shared/src/types/index.ts index ddf02ca371..dae4ec0526 100644 --- a/packages/shared/src/types/index.ts +++ b/packages/shared/src/types/index.ts @@ -1,3 +1,4 @@ +import './global' export * from './animated' export * from './interpolation' export * from './common' From 652955e67f56595176e70c08a2d777eaccd35be6 Mon Sep 17 00:00:00 2001 From: Alec Larson Date: Thu, 3 Oct 2019 13:50:02 -0400 Subject: [PATCH 43/43] 9.0.0-canary.809.5.f01ecc2 --- lerna.json | 2 +- packages/addons/package.json | 2 +- packages/animated/package.json | 2 +- packages/core/package.json | 2 +- packages/react-spring/package.json | 2 +- packages/shared/package.json | 2 +- targets/konva/package.json | 2 +- targets/native/package.json | 2 +- targets/three/package.json | 2 +- targets/web/package.json | 2 +- targets/zdog/package.json | 2 +- yarn.lock | 18 +++++++++--------- 12 files changed, 20 insertions(+), 20 deletions(-) diff --git a/lerna.json b/lerna.json index 9501a82f55..e0d70194f3 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "9.0.0-canary.809.4.a637589", + "version": "9.0.0-canary.809.5.f01ecc2", "npmClient": "yarn", "useWorkspaces": true, "registry": "https://registry.npmjs.org", diff --git a/packages/addons/package.json b/packages/addons/package.json index 325c621540..0e4f3846ef 100644 --- a/packages/addons/package.json +++ b/packages/addons/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/addons", - "version": "9.0.0-canary.809.4.a637589", + "version": "9.0.0-canary.809.5.f01ecc2", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../animated", diff --git a/packages/animated/package.json b/packages/animated/package.json index 17f529229b..ffa9b5c674 100644 --- a/packages/animated/package.json +++ b/packages/animated/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/animated", - "version": "9.0.0-canary.809.4.a637589", + "version": "9.0.0-canary.809.5.f01ecc2", "description": "Animated component props for React", "main": "src/index.ts", "scripts": { diff --git a/packages/core/package.json b/packages/core/package.json index 8f7f386343..be6597cf54 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/core", - "version": "9.0.0-canary.809.4.a637589", + "version": "9.0.0-canary.809.5.f01ecc2", "main": "src/index.ts", "scripts": { "build": "rollup -c", diff --git a/packages/react-spring/package.json b/packages/react-spring/package.json index 4973919c87..4662154910 100644 --- a/packages/react-spring/package.json +++ b/packages/react-spring/package.json @@ -1,6 +1,6 @@ { "name": "react-spring", - "version": "9.0.0-canary.809.4.a637589", + "version": "9.0.0-canary.809.5.f01ecc2", "main": "src/web.ts", "dependencies": { "@react-spring/addons": "link:../addons", diff --git a/packages/shared/package.json b/packages/shared/package.json index 961914a284..9f7264086c 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/shared", - "version": "9.0.0-canary.809.4.a637589", + "version": "9.0.0-canary.809.5.f01ecc2", "description": "Globals and shared modules", "main": "src/index.ts", "scripts": { diff --git a/targets/konva/package.json b/targets/konva/package.json index 98d3dbd85e..35b0a3e1a9 100644 --- a/targets/konva/package.json +++ b/targets/konva/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/konva", - "version": "9.0.0-canary.809.4.a637589", + "version": "9.0.0-canary.809.5.f01ecc2", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/targets/native/package.json b/targets/native/package.json index 7a092cd2b1..2cc2432d41 100644 --- a/targets/native/package.json +++ b/targets/native/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/native", - "version": "9.0.0-canary.809.4.a637589", + "version": "9.0.0-canary.809.5.f01ecc2", "main": "src/index.ts", "scripts": { "build": "rollup -c" diff --git a/targets/three/package.json b/targets/three/package.json index 6fb70de6da..1c06f2077a 100644 --- a/targets/three/package.json +++ b/targets/three/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/three", - "version": "9.0.0-canary.809.4.a637589", + "version": "9.0.0-canary.809.5.f01ecc2", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/targets/web/package.json b/targets/web/package.json index c2b107e236..63ba767dd4 100644 --- a/targets/web/package.json +++ b/targets/web/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/web", - "version": "9.0.0-canary.809.4.a637589", + "version": "9.0.0-canary.809.5.f01ecc2", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/targets/zdog/package.json b/targets/zdog/package.json index ae883ad3cb..bf99ade202 100644 --- a/targets/zdog/package.json +++ b/targets/zdog/package.json @@ -1,6 +1,6 @@ { "name": "@react-spring/zdog", - "version": "9.0.0-canary.809.4.a637589", + "version": "9.0.0-canary.809.5.f01ecc2", "main": "src/index.ts", "dependencies": { "@react-spring/animated": "link:../../packages/animated", diff --git a/yarn.lock b/yarn.lock index 2d478f60e5..d00878a649 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1869,57 +1869,57 @@ universal-user-agent "^4.0.0" "@react-spring/addons@link:packages/addons": - version "9.0.0-canary.809.4.a637589" + version "9.0.0-canary.809.5.f01ecc2" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" use-memo-one "^1.1.0" "@react-spring/animated@link:packages/animated": - version "9.0.0-canary.809.4.a637589" + version "9.0.0-canary.809.5.f01ecc2" dependencies: "@react-spring/shared" "link:packages/shared" "@react-spring/core@link:packages/core": - version "9.0.0-canary.809.4.a637589" + version "9.0.0-canary.809.5.f01ecc2" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/shared" "link:packages/shared" use-memo-one "^1.1.0" "@react-spring/konva@link:targets/konva": - version "9.0.0-canary.809.4.a637589" + version "9.0.0-canary.809.5.f01ecc2" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" "@react-spring/shared" "link:packages/shared" "@react-spring/native@link:targets/native": - version "9.0.0-canary.809.4.a637589" + version "9.0.0-canary.809.5.f01ecc2" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" "@react-spring/shared" "link:packages/shared" "@react-spring/shared@link:packages/shared": - version "9.0.0-canary.809.4.a637589" + version "9.0.0-canary.809.5.f01ecc2" "@react-spring/three@link:targets/three": - version "9.0.0-canary.809.4.a637589" + version "9.0.0-canary.809.5.f01ecc2" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" "@react-spring/shared" "link:packages/shared" "@react-spring/web@link:targets/web": - version "9.0.0-canary.809.4.a637589" + version "9.0.0-canary.809.5.f01ecc2" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core" "@react-spring/shared" "link:packages/shared" "@react-spring/zdog@link:targets/zdog": - version "9.0.0-canary.809.4.a637589" + version "9.0.0-canary.809.5.f01ecc2" dependencies: "@react-spring/animated" "link:packages/animated" "@react-spring/core" "link:packages/core"