Skip to content

Commit

Permalink
fix: make SpringRef instances callable to avoid breaking change #1359 (
Browse files Browse the repository at this point in the history
…#1387)

* chore: inline alloc/fluids and upgrade rafz

* chore: inline alloc/types

* chore: normalize demo styles

* chore: add flipCard sandbox

* chore: add Slide sandbox

* chore: add sandboxes

* chore: add TS to dev dependencies to sandboxes demo

* chore: add alloc/types missing types

* chore: inline react-layout-effect and remove it from deps

* fix: make SpringRef instances callable to avoid breaking change #1359

* chore: optimize sandbox

* chore: refactor based on react-use-gesture sandbox

* fix: make SpringRef instances callable to avoid breaking change #1359

* fix: `alias ref()` to `ref.start()` instead of `ref.set()`

* chore: add comment about deprecating calling ref as a fn

* fix: replace ref with api and set with start

* fix: make SpringRef instances callable to avoid breaking change #1359

* chore: update comment to reflect

* feat: add directCall of set deprecation log

* fix: infer SpringValue types only from the `from` prop when it exists

* fix: remove global styles

* fix: remove logs

* fix: remove duplicates

* fix: use proper api for useTrail

Co-authored-by: Josh Ellis <[email protected]>
  • Loading branch information
dbismut and joshuaellis authored Apr 8, 2021
1 parent c6f2872 commit f3c4c0b
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 36 deletions.
4 changes: 2 additions & 2 deletions demo/src/sandboxes/goo-blobs/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ const trans = (x: number, y: number) =>
`translate3d(${x}px,${y}px,0) translate3d(-50%,-50%,0)`

export default function App() {
const [trail, api] = useTrail(3, () => ({
const [trail, api] = useTrail(3, i => ({
xy: [0, 0],
config: i => (i === 0 ? fast : slow), // TODO fix lint error
config: i === 0 ? fast : slow,
}))
return (
<>
Expand Down
14 changes: 1 addition & 13 deletions demo/src/sandboxes/notification-hub/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,26 +40,14 @@ function MessageHub({
await next({ opacity: 1, height: refMap.get(item).offsetHeight })
await next({ life: '0%' })
},
leave: [
{
opacity: 0,
onResolve: (v, c, i) => console.log('onResolve', v, c, i),
onRest: (v, c, i) => console.log('onRest', v, c, i),
},
{ height: 0 },
],
onStart: (result, ctrl, item) => console.log(result, ctrl, item),
// onChange: {
// opacity: (result, ctrl, item) => console.log(result, ctrl, item),
// },
leave: [{ opacity: 0 }, { height: 0 }],
onRest: (result, ctrl, item) => {
setItems(state =>
state.filter(i => {
return i.key !== item.key
})
)
},
// onResolve: (result, ctrl, item) => console.log('resolve', result, ctrl, item),
config: (item, index, phase) => key => (phase === 'enter' && key === 'life' ? { duration: timeout } : config),
})

Expand Down
27 changes: 25 additions & 2 deletions packages/core/src/SpringRef.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { each, is } from '@react-spring/shared'
import { each, is, deprecateDirectCall } from '@react-spring/shared'
import { Lookup, Falsy, OneOrMore } from '@react-spring/types'
import { AsyncResult, ControllerUpdate } from './types'
import { Controller } from './Controller'
Expand All @@ -7,9 +7,29 @@ interface ControllerUpdateFn<State extends Lookup = Lookup> {
(i: number, ctrl: Controller<State>): ControllerUpdate<State> | Falsy
}

export class SpringRef<State extends Lookup = Lookup> {
/**
* Extending from function allows SpringRef instances to be callable.
* https://hackernoon.com/creating-callable-objects-in-javascript-d21l3te1
*
* ```js
* const [springs, api] = useSpring(() => ({x: 0}))
* api.start({x: 3}) // this works
* api({x: 3}) // this also works (non breaking from 9rc3)
* ```
*/
export class SpringRef<State extends Lookup = Lookup> extends Function {
readonly current: Controller<State>[] = []

constructor() {
super('return arguments.callee._call.apply(arguments.callee, arguments)')
}

/** @deprecated use the property 'start' instead */
_call(props?: ControllerUpdate<State> | ControllerUpdateFn<State>) {
deprecateDirectCall()
this.start(props)
}

/** Update the state of each controller without animating. */
set(values: Partial<State>) {
each(this.current, ctrl => ctrl.set(values))
Expand Down Expand Up @@ -79,6 +99,9 @@ export class SpringRef<State extends Lookup = Lookup> {
}

export interface SpringRef<State extends Lookup> {
(props?: ControllerUpdate<State> | ControllerUpdateFn<State>): AsyncResult<
Controller<State>
>[]
/** Stop all animations. */
stop(): this
/** Stop animations for the given keys. */
Expand Down
16 changes: 5 additions & 11 deletions packages/core/src/types/props.ts
Original file line number Diff line number Diff line change
Expand Up @@ -352,10 +352,11 @@ export type PickAnimated<Props extends object, Fwd = true> = unknown &
: [object] extends [Props]
? Lookup
: ObjectFromUnion<
| FromValues<Props>
| (TransitionKey & keyof Props extends never
? ToValues<Props, Fwd>
: TransitionValues<Props>)
Props extends { from: infer From } // extract prop from the `from` prop if it exists
? ObjectType<From>
: TransitionKey & keyof Props extends never
? ToValues<Props, Fwd>
: TransitionValues<Props>
>)

/**
Expand All @@ -368,10 +369,3 @@ type ToValues<Props extends object, AndForward = true> = unknown &
? ForwardProps<[To] extends [object] ? To : Partial<Extract<To, object>>>
: never
: unknown)

/**
* Pick the values of the `from` prop.
*/
type FromValues<Props extends object> = ForwardProps<
Props extends { from?: infer From } ? ObjectType<From> : object
>
35 changes: 27 additions & 8 deletions packages/shared/src/deprecations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,32 @@ declare const console: any

const prefix = 'react-spring: '

let flagInterpolate = false
export function deprecateInterpolate() {
if (!flagInterpolate) {
flagInterpolate = true
console.warn(
prefix +
'The "interpolate" function is deprecated in v9 (use "to" instead)'
)
const once = <TFunc extends (...args: any) => any>(fn: TFunc) => {
const func = fn
let called = false

if (typeof func != 'function') {
throw new TypeError(`${prefix}once requires a function parameter`)
}

return (...args: any) => {
if (!called) {
func(...args)
called = true
}
}
}

const warnInterpolate = once(console.warn)
export function deprecateInterpolate() {
warnInterpolate(
`${prefix}The "interpolate" function is deprecated in v9 (use "to" instead)`
)
}

const warnDirectCall = once(console.warn)
export function deprecateDirectCall() {
warnDirectCall(
`${prefix}Directly calling start instead of using the api object is deprecated in v9 (use ".start" instead)`
)
}

0 comments on commit f3c4c0b

Please sign in to comment.