@tamagui/animation-helpers 2.7.7 → 3.0.0-beta.1097.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/dist/cjs/index.cjs +32 -21
  2. package/dist/cjs/index.native.cjs +46 -0
  3. package/dist/cjs/index.native.js +33 -21
  4. package/dist/cjs/index.native.js.map +1 -1
  5. package/dist/cjs/presets.cjs +77 -0
  6. package/dist/cjs/presets.native.cjs +79 -0
  7. package/dist/cjs/presets.native.js +81 -0
  8. package/dist/cjs/presets.native.js.map +1 -0
  9. package/dist/cjs/propertyNames.cjs +91 -0
  10. package/dist/cjs/propertyNames.native.cjs +95 -0
  11. package/dist/cjs/propertyNames.native.js +97 -0
  12. package/dist/cjs/propertyNames.native.js.map +1 -0
  13. package/dist/cjs/resolveTransition.cjs +345 -0
  14. package/dist/cjs/resolveTransition.native.cjs +424 -0
  15. package/dist/cjs/resolveTransition.native.js +426 -0
  16. package/dist/cjs/resolveTransition.native.js.map +1 -0
  17. package/dist/cjs/transitionResolver.cjs +34 -0
  18. package/dist/cjs/transitionResolver.native.cjs +37 -0
  19. package/dist/cjs/transitionResolver.native.js +39 -0
  20. package/dist/cjs/transitionResolver.native.js.map +1 -0
  21. package/dist/cjs/types.cjs +9 -11
  22. package/dist/cjs/types.native.cjs +18 -0
  23. package/dist/cjs/types.native.js +9 -10
  24. package/dist/cjs/types.native.js.map +1 -1
  25. package/dist/esm/index.js +6 -3
  26. package/dist/esm/index.mjs +6 -3
  27. package/dist/esm/index.native.js +6 -3
  28. package/dist/esm/presets.mjs +57 -0
  29. package/dist/esm/presets.mjs.map +1 -0
  30. package/dist/esm/presets.native.js +57 -0
  31. package/dist/esm/presets.native.js.map +1 -0
  32. package/dist/esm/propertyNames.mjs +67 -0
  33. package/dist/esm/propertyNames.mjs.map +1 -0
  34. package/dist/esm/propertyNames.native.js +69 -0
  35. package/dist/esm/propertyNames.native.js.map +1 -0
  36. package/dist/esm/resolveTransition.mjs +315 -0
  37. package/dist/esm/resolveTransition.mjs.map +1 -0
  38. package/dist/esm/resolveTransition.native.js +392 -0
  39. package/dist/esm/resolveTransition.native.js.map +1 -0
  40. package/dist/esm/transitionResolver.mjs +11 -0
  41. package/dist/esm/transitionResolver.mjs.map +1 -0
  42. package/dist/esm/transitionResolver.native.js +12 -0
  43. package/dist/esm/transitionResolver.native.js.map +1 -0
  44. package/dist/esm/types.mjs +0 -2
  45. package/dist/esm/types.native.js +0 -2
  46. package/package.json +23 -2
  47. package/src/index.ts +39 -9
  48. package/src/presets.ts +40 -0
  49. package/src/propertyNames.ts +78 -0
  50. package/src/resolveTransition.ts +503 -0
  51. package/src/transitionResolver.ts +35 -0
  52. package/src/types.ts +42 -46
  53. package/types/index.d.ts +6 -2
  54. package/types/index.d.ts.map +2 -2
  55. package/types/presets.d.ts +79 -0
  56. package/types/presets.d.ts.map +11 -0
  57. package/types/propertyNames.d.ts +13 -0
  58. package/types/propertyNames.d.ts.map +11 -0
  59. package/types/resolveTransition.d.ts +108 -0
  60. package/types/resolveTransition.d.ts.map +11 -0
  61. package/types/transitionResolver.d.ts +30 -0
  62. package/types/transitionResolver.d.ts.map +11 -0
  63. package/types/types.d.ts +35 -42
  64. package/types/types.d.ts.map +2 -2
  65. package/dist/cjs/normalizeTransition.cjs +0 -164
  66. package/dist/cjs/normalizeTransition.native.js +0 -231
  67. package/dist/cjs/normalizeTransition.native.js.map +0 -1
  68. package/dist/esm/index.js.map +0 -1
  69. package/dist/esm/index.mjs.map +0 -1
  70. package/dist/esm/index.native.js.map +0 -1
  71. package/dist/esm/normalizeTransition.mjs +0 -134
  72. package/dist/esm/normalizeTransition.mjs.map +0 -1
  73. package/dist/esm/normalizeTransition.native.js +0 -198
  74. package/dist/esm/normalizeTransition.native.js.map +0 -1
  75. package/dist/esm/types.mjs.map +0 -1
  76. package/dist/esm/types.native.js.map +0 -1
  77. package/src/normalizeTransition.ts +0 -255
  78. package/types/normalizeTransition.d.ts +0 -54
  79. package/types/normalizeTransition.d.ts.map +0 -11
package/src/types.ts CHANGED
@@ -1,6 +1,42 @@
1
1
  /**
2
- * Animation configuration that can include additional properties
3
- * like delay, duration, stiffness, damping, etc.
2
+ * One entry in a driver's `animations` config, and the same type for all four
3
+ * drivers: a config written once resolves to the same motion on css,
4
+ * reanimated, motion, and react-native.
5
+ *
6
+ * The canonical spelling is `{ duration, bounce }`. `duration` is the spring's
7
+ * undamped period, the "how fast does this feel" number, and `bounce` is 0 for
8
+ * critically damped, up toward 1 for loose and oscillating, negative for
9
+ * sluggish. A css string is a timing; `{ type: 'timing' }` is the object
10
+ * spelling of one. `stiffness`/`damping`/`mass` stay available for a config
11
+ * that was already tuned against them.
12
+ */
13
+ export type PresetConfig =
14
+ | string
15
+ | {
16
+ type?: 'spring'
17
+ duration?: number
18
+ bounce?: number
19
+ stiffness?: number
20
+ damping?: number
21
+ mass?: number
22
+ velocity?: number
23
+ overshootClamping?: boolean
24
+ restDisplacementThreshold?: number
25
+ restSpeedThreshold?: number
26
+ }
27
+ | {
28
+ type: 'timing'
29
+ duration: number
30
+ /** any css timing function */
31
+ easing?: string
32
+ }
33
+
34
+ /** the `animations` object a driver is created with */
35
+ export type AnimationsConfig = Record<string, PresetConfig>
36
+
37
+ /**
38
+ * A resolved animation config in a driver's own terms. Drivers build these
39
+ * from a `ResolvedEntry`; nothing parses one.
4
40
  */
5
41
  export type AnimationConfig = {
6
42
  type?: string
@@ -8,50 +44,10 @@ export type AnimationConfig = {
8
44
  }
9
45
 
10
46
  /**
11
- * Input format for the transition prop - supports multiple syntaxes:
12
- *
13
- * 1. String: "bouncy"
14
- * 2. Object with property mappings: { x: 'quick', y: 'bouncy', default: 'slow' }
15
- * 3. Array with config: ['bouncy', { delay: 100, x: 'quick' }]
16
- * 4. Object with enter/exit: { enter: 'bouncy', exit: 'quick', default: 'slow' }
47
+ * Input format for the `transition` prop: a CSS transition string, a preset
48
+ * name, or a config object. See `@tamagui/style-grammar/transitions`.
17
49
  *
18
- * Note: Uses `any` to be compatible with the TransitionProp type from @tamagui/web
19
- * which has more complex union types.
50
+ * Note: uses `any` to stay compatible with the `TransitionProp` type from
51
+ * `@tamagui/web`, which carries the full style-key union.
20
52
  */
21
53
  export type TransitionPropInput = any
22
-
23
- /**
24
- * Spring configuration parameters that can override preset defaults.
25
- * These are the common parameters across animation drivers.
26
- */
27
- export type SpringConfig = {
28
- stiffness?: number
29
- damping?: number
30
- mass?: number
31
- tension?: number
32
- friction?: number
33
- velocity?: number
34
- overshootClamping?: boolean
35
- duration?: number
36
- bounciness?: number
37
- speed?: number
38
- }
39
-
40
- /**
41
- * Normalized output format that all animation drivers consume.
42
- * Provides a consistent structure regardless of input format.
43
- */
44
- export type NormalizedTransition = {
45
- /** Default animation key for properties not explicitly listed */
46
- default: string | null
47
- /** Animation key to use during enter transitions (mount) */
48
- enter: string | null
49
- /** Animation key to use during exit transitions (unmount) */
50
- exit: string | null
51
- /** Global delay in ms */
52
- delay: number | undefined
53
- /** Per-property animation configs: propertyName -> animationKey or config */
54
- properties: Record<string, string | AnimationConfig>
55
- /** Global spring config overrides that merge with the preset defaults */
56
- config?: SpringConfig
57
- }
package/types/index.d.ts CHANGED
@@ -1,4 +1,8 @@
1
- export { normalizeTransition, getAnimationForProperty, hasAnimation, getAnimatedProperties, getEffectiveAnimation, getAnimationConfigsForKeys } from "./normalizeTransition";
2
- export type { AnimationConfig, NormalizedTransition, TransitionPropInput } from "./types";
1
+ export { animationPresets } from "./presets";
2
+ export { canonicalTransitionProperty, isTransformProperty, styleKeysForProperty } from "./propertyNames";
3
+ export { getTransitionResolver, setTransitionResolver, type TransitionResolver } from "./transitionResolver";
4
+ export { easingToBezier, entryToCSS, forAnimationState, getMaxDurationMs, getSettleMs, getTransitionForKey, hasTransition, presetToTiming, resolveTransition, toCSSTransition } from "./resolveTransition";
5
+ export type { DriverTiming, ResolvedEntry, ResolvedTransition, ResolveTransitionOptions } from "./resolveTransition";
6
+ export type { AnimationConfig, AnimationsConfig, PresetConfig, TransitionPropInput } from "./types";
3
7
 
4
8
  //# sourceMappingURL=index.d.ts.map
@@ -1,11 +1,11 @@
1
1
  {
2
- "mappings": "AAAA,SACE,qBACA,yBACA,cACA,uBACA,uBACA,kCACK;AAEP,cAAc,iBAAiB,sBAAsB,2BAA2B",
2
+ "mappings": "AAAA,SAAS,wBAAwB;AAEjC,SACE,6BACA,qBACA,4BACK;AAEP,SACE,uBACA,4BACK,0BACA;AAEP,SACE,gBACA,YACA,mBACA,kBACA,aACA,qBACA,eACA,gBACA,mBACA,uBACK;AAEP,cACE,cACA,eACA,oBACA,gCACK;AAEP,cACE,iBACA,kBACA,cACA,2BACK",
3
3
  "names": [],
4
4
  "sources": [
5
5
  "src/index.ts"
6
6
  ],
7
7
  "version": 3,
8
8
  "sourcesContent": [
9
- "export {\n normalizeTransition,\n getAnimationForProperty,\n hasAnimation,\n getAnimatedProperties,\n getEffectiveAnimation,\n getAnimationConfigsForKeys,\n} from './normalizeTransition'\n\nexport type { AnimationConfig, NormalizedTransition, TransitionPropInput } from './types'\n"
9
+ "export { animationPresets } from './presets'\n\nexport {\n canonicalTransitionProperty,\n isTransformProperty,\n styleKeysForProperty,\n} from './propertyNames'\n\nexport {\n getTransitionResolver,\n setTransitionResolver,\n type TransitionResolver,\n} from './transitionResolver'\n\nexport {\n easingToBezier,\n entryToCSS,\n forAnimationState,\n getMaxDurationMs,\n getSettleMs,\n getTransitionForKey,\n hasTransition,\n presetToTiming,\n resolveTransition,\n toCSSTransition,\n} from './resolveTransition'\n\nexport type {\n DriverTiming,\n ResolvedEntry,\n ResolvedTransition,\n ResolveTransitionOptions,\n} from './resolveTransition'\n\nexport type {\n AnimationConfig,\n AnimationsConfig,\n PresetConfig,\n TransitionPropInput,\n} from './types'\n"
10
10
  ]
11
11
  }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * The shipped animation presets, defined once for every driver.
3
+ *
4
+ * Before v3 each driver carried its own hand-tuned table, so `bouncy` was a
5
+ * 350ms cubic-bezier on the web, a stiffness-120 spring on react-native, and a
6
+ * stiffness-90 spring on motion. Three different motions under one name.
7
+ *
8
+ * They are springs in the canonical pair instead:
9
+ *
10
+ * - `duration` is the spring's undamped period, which is what "how fast does
11
+ * this feel" actually means. It is not a stopwatch: a bouncy spring keeps
12
+ * ringing past it, which is the point of a bouncy spring.
13
+ * - `bounce` is 0 for critically damped (fast, no overshoot), up toward 1 for
14
+ * loose and oscillating, and negative for sluggish.
15
+ *
16
+ * On the web these compile to a `linear()` easing that traces the real spring
17
+ * curve, overshoot included, with no javascript running.
18
+ *
19
+ * There are no `'200ms'`-style presets any more. A duration is CSS now, so
20
+ * `transition="200ms"` and `transition="200ms ease-out"` work directly and
21
+ * need nothing configured. Keep your own table small for the same reason:
22
+ * a name is worth having only when it means something a duration cannot say.
23
+ */
24
+ export declare const animationPresets: {
25
+ readonly quickest: {
26
+ readonly duration: 120;
27
+ readonly bounce: 0.2;
28
+ };
29
+ readonly quickestLessBouncy: {
30
+ readonly duration: 120;
31
+ readonly bounce: 0;
32
+ };
33
+ readonly quicker: {
34
+ readonly duration: 160;
35
+ readonly bounce: 0.25;
36
+ };
37
+ readonly quickerLessBouncy: {
38
+ readonly duration: 160;
39
+ readonly bounce: 0;
40
+ };
41
+ readonly quick: {
42
+ readonly duration: 220;
43
+ readonly bounce: 0.3;
44
+ };
45
+ readonly quickLessBouncy: {
46
+ readonly duration: 220;
47
+ readonly bounce: 0;
48
+ };
49
+ readonly medium: {
50
+ readonly duration: 300;
51
+ readonly bounce: 0.15;
52
+ };
53
+ readonly slow: {
54
+ readonly duration: 450;
55
+ readonly bounce: 0.1;
56
+ };
57
+ readonly slowest: {
58
+ readonly duration: 700;
59
+ readonly bounce: 0.1;
60
+ };
61
+ readonly lazy: {
62
+ readonly duration: 500;
63
+ readonly bounce: -0.2;
64
+ };
65
+ readonly superLazy: {
66
+ readonly duration: 800;
67
+ readonly bounce: -0.3;
68
+ };
69
+ readonly bouncy: {
70
+ readonly duration: 400;
71
+ readonly bounce: 0.5;
72
+ };
73
+ readonly superBouncy: {
74
+ readonly duration: 400;
75
+ readonly bounce: 0.75;
76
+ };
77
+ };
78
+
79
+ //# sourceMappingURL=presets.d.ts.map
@@ -0,0 +1,11 @@
1
+ {
2
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;AAyBA,OAAO,cAAM;UACX;WAAY,UAAU;WAAK,QAAQ;;UACnC;WAAsB,UAAU;WAAK,QAAQ;;UAC7C;WAAW,UAAU;WAAK,QAAQ;;UAClC;WAAqB,UAAU;WAAK,QAAQ;;UAC5C;WAAS,UAAU;WAAK,QAAQ;;UAChC;WAAmB,UAAU;WAAK,QAAQ;;UAC1C;WAAU,UAAU;WAAK,QAAQ;;UACjC;WAAQ,UAAU;WAAK,QAAQ;;UAC/B;WAAW,UAAU;WAAK,QAAQ;;UAClC;WAAQ,UAAU;WAAK,QAAQ,CAAC;;UAChC;WAAa,UAAU;WAAK,QAAQ,CAAC;;UACrC;WAAU,UAAU;WAAK,QAAQ;;UACjC;WAAe,UAAU;WAAK,QAAQ",
3
+ "names": [],
4
+ "sources": [
5
+ "src/presets.ts"
6
+ ],
7
+ "version": 3,
8
+ "sourcesContent": [
9
+ "import type { AnimationsConfig } from './types'\n\n/**\n * The shipped animation presets, defined once for every driver.\n *\n * Before v3 each driver carried its own hand-tuned table, so `bouncy` was a\n * 350ms cubic-bezier on the web, a stiffness-120 spring on react-native, and a\n * stiffness-90 spring on motion. Three different motions under one name.\n *\n * They are springs in the canonical pair instead:\n *\n * - `duration` is the spring's undamped period, which is what \"how fast does\n * this feel\" actually means. It is not a stopwatch: a bouncy spring keeps\n * ringing past it, which is the point of a bouncy spring.\n * - `bounce` is 0 for critically damped (fast, no overshoot), up toward 1 for\n * loose and oscillating, and negative for sluggish.\n *\n * On the web these compile to a `linear()` easing that traces the real spring\n * curve, overshoot included, with no javascript running.\n *\n * There are no `'200ms'`-style presets any more. A duration is CSS now, so\n * `transition=\"200ms\"` and `transition=\"200ms ease-out\"` work directly and\n * need nothing configured. Keep your own table small for the same reason:\n * a name is worth having only when it means something a duration cannot say.\n */\nexport const animationPresets = {\n quickest: { duration: 120, bounce: 0.2 },\n quickestLessBouncy: { duration: 120, bounce: 0 },\n quicker: { duration: 160, bounce: 0.25 },\n quickerLessBouncy: { duration: 160, bounce: 0 },\n quick: { duration: 220, bounce: 0.3 },\n quickLessBouncy: { duration: 220, bounce: 0 },\n medium: { duration: 300, bounce: 0.15 },\n slow: { duration: 450, bounce: 0.1 },\n slowest: { duration: 700, bounce: 0.1 },\n lazy: { duration: 500, bounce: -0.2 },\n superLazy: { duration: 800, bounce: -0.3 },\n bouncy: { duration: 400, bounce: 0.5 },\n superBouncy: { duration: 400, bounce: 0.75 },\n} as const satisfies AnimationsConfig\n"
10
+ ]
11
+ }
@@ -0,0 +1,13 @@
1
+ /**
2
+ * the css property name an entry is filed under, so `backgroundColor` and
3
+ * `background-color` are one key and cannot both silently apply.
4
+ */
5
+ export declare function canonicalTransitionProperty(key: string): string;
6
+ export declare function isTransformProperty(key: string): boolean;
7
+ /**
8
+ * the style keys a css property covers, for drivers that key their per-property
9
+ * options by style key rather than css property (motion, react-native).
10
+ */
11
+ export declare function styleKeysForProperty(property: string): readonly string[];
12
+
13
+ //# sourceMappingURL=propertyNames.d.ts.map
@@ -0,0 +1,11 @@
1
+ {
2
+ "mappings": ";;;;AA0CA,OAAO,iBAAS,4BAA4B;AAO5C,OAAO,iBAAS,oBAAoB;;;;;AAwBpC,OAAO,iBAAS,qBAAqB",
3
+ "names": [],
4
+ "sources": [
5
+ "src/propertyNames.ts"
6
+ ],
7
+ "version": 3,
8
+ "sourcesContent": [
9
+ "// which css property a tamagui style key animates under.\n//\n// this is a module of its own, with no imports, because `@tamagui/web` needs\n// it on every styled component while the parser and the spring solver in\n// `resolveTransition` are only needed when a driver is in the bundle.\n\n/**\n * transform parts map onto the css property that actually animates them.\n * `translate`, `scale`, and `rotate` are real individual transform properties;\n * everything else can only be reached through `transform` as a whole.\n *\n * collapsing here is deliberate. css cannot animate `rotateX` separately from\n * `skewY` (both live in `transform`), so letting a js driver do it would be a\n * capability that silently disappears the moment you build for the web.\n */\nconst transformProperties: Record<string, string> = {\n x: 'translate',\n y: 'translate',\n z: 'translate',\n translate: 'translate',\n translateX: 'translate',\n translateY: 'translate',\n translateZ: 'translate',\n scale: 'scale',\n scaleX: 'scale',\n scaleY: 'scale',\n scaleZ: 'scale',\n rotate: 'rotate',\n rotateX: 'transform',\n rotateY: 'transform',\n rotateZ: 'transform',\n skewX: 'transform',\n skewY: 'transform',\n perspective: 'transform',\n matrix: 'transform',\n transform: 'transform',\n}\n\n/**\n * the css property name an entry is filed under, so `backgroundColor` and\n * `background-color` are one key and cannot both silently apply.\n */\nexport function canonicalTransitionProperty(key: string): string {\n if (key === 'all' || key === 'none') return key\n const transform = transformProperties[key]\n if (transform) return transform\n return key.includes('-') ? key : key.replace(/[A-Z]/g, '-$&').toLowerCase()\n}\n\nexport function isTransformProperty(key: string): boolean {\n return key in transformProperties\n}\n\nconst styleKeysByProperty: Record<string, readonly string[]> = {\n translate: ['translate', 'translateX', 'translateY', 'translateZ', 'x', 'y', 'z'],\n scale: ['scale', 'scaleX', 'scaleY', 'scaleZ'],\n rotate: ['rotate'],\n transform: [\n 'transform',\n 'rotateX',\n 'rotateY',\n 'rotateZ',\n 'skewX',\n 'skewY',\n 'perspective',\n 'matrix',\n ],\n}\n\n/**\n * the style keys a css property covers, for drivers that key their per-property\n * options by style key rather than css property (motion, react-native).\n */\nexport function styleKeysForProperty(property: string): readonly string[] {\n const transform = styleKeysByProperty[property]\n if (transform) return transform\n return [property.replace(/-([a-z])/g, (_, letter: string) => letter.toUpperCase())]\n}\n"
10
+ ]
11
+ }
@@ -0,0 +1,108 @@
1
+ import { type TransitionBehavior, type TransitionDiagnostic, type TransitionObjectValue } from "@tamagui/style-grammar/transitions";
2
+ export type DriverTiming = {
3
+ kind: "timing";
4
+ durationMs: number;
5
+ easing: string;
6
+ } | {
7
+ kind: "spring";
8
+ /** the undamped period, the portable "how fast does this feel" number */
9
+ durationMs: number;
10
+ bounce: number;
11
+ stiffness: number;
12
+ damping: number;
13
+ mass: number;
14
+ /** authored low-level overrides, for drivers that take them raw */
15
+ extra?: Record<string, unknown>;
16
+ };
17
+ export interface ResolvedEntry {
18
+ /** canonical property name, kebab-case, or `all` / `none` */
19
+ property: string;
20
+ timing: DriverTiming;
21
+ delayMs: number;
22
+ behavior: TransitionBehavior;
23
+ }
24
+ export interface ResolvedTransition {
25
+ /** in authored order; later entries win under the css last-wins rule */
26
+ entries: readonly ResolvedEntry[];
27
+ /** the winning `all` entry, or null when only specific properties were named */
28
+ all: ResolvedEntry | null;
29
+ /** winning entry per canonical property name, excluding `all` */
30
+ byProperty: Readonly<Record<string, ResolvedEntry>>;
31
+ /** true when the author disabled transitions entirely (`transition="none"`) */
32
+ none: boolean;
33
+ /**
34
+ * true when any entry was authored as a preset name or a `spring()`, the two
35
+ * things that have no css spelling of their own. a resolution without one is
36
+ * already plain css and needs no driver at all.
37
+ */
38
+ fused: boolean;
39
+ /** replaces this whole resolution while mounting, when the author set one */
40
+ enter: ResolvedTransition | null;
41
+ /** replaces this whole resolution while unmounting */
42
+ exit: ResolvedTransition | null;
43
+ diagnostics: readonly TransitionDiagnostic[];
44
+ }
45
+ /** the resolution that applies in a given animation state */
46
+ export declare function forAnimationState(resolved: ResolvedTransition, state: "enter" | "exit" | "default"): ResolvedTransition;
47
+ /**
48
+ * turns one entry in a driver's `animations` config into a timing.
49
+ *
50
+ * accepts every shape `PresetConfig` allows: a css string (`'350ms ease-out'`),
51
+ * spring physics (`{ type: 'spring', damping, stiffness, mass }`), a timing
52
+ * (`{ type: 'timing', duration, easing }`), and the canonical pair
53
+ * (`{ duration, bounce }`). configs written for any driver therefore resolve
54
+ * to the same motion on all four.
55
+ */
56
+ export declare function presetToTiming(preset: unknown): DriverTiming | null;
57
+ /**
58
+ * a css easing as cubic-bezier control points, which is the only easing shape
59
+ * reanimated, motion, and react-native all accept.
60
+ *
61
+ * returns null for `steps()` and `linear()`, which have no bezier equivalent.
62
+ * a driver that gets null should fall back to its own default rather than
63
+ * pretending it applied something.
64
+ */
65
+ export declare function easingToBezier(easing: string): readonly [number, number, number, number] | null;
66
+ export interface ResolveTransitionOptions {
67
+ /** the driver's animations config; its keys are the valid preset names */
68
+ animations?: Record<string, unknown> | null;
69
+ /** config shorthands, so `transition="bg 200ms"` names backgroundColor */
70
+ shorthands?: Record<string, string> | null;
71
+ }
72
+ /**
73
+ * parses and resolves a `transition` prop into driver-ready entries.
74
+ *
75
+ * memoized per (animations config, authored value), because this runs on every
76
+ * render of every component carrying a transition.
77
+ */
78
+ export declare function resolveTransition(transition: TransitionObjectValue | null | undefined, options?: ResolveTransitionOptions): ResolvedTransition;
79
+ /**
80
+ * the transition that applies to one style key, under css last-wins.
81
+ *
82
+ * an authored `transform` already expanded into the whole family in
83
+ * `fromEntries`, so `x`, `scale` and `rotate` find a direct entry here.
84
+ */
85
+ export declare function getTransitionForKey(resolved: ResolvedTransition, key: string): ResolvedEntry | null;
86
+ /** true when anything at all will animate */
87
+ export declare function hasTransition(resolved: ResolvedTransition): boolean;
88
+ /**
89
+ * how long a timing actually runs, which for a spring is its settle time and
90
+ * not its nominal duration. this is the number a completion deadline needs.
91
+ */
92
+ export declare function getSettleMs(timing: DriverTiming): number;
93
+ /** the longest anything will take, for the driver's completion bookkeeping */
94
+ export declare function getMaxDurationMs(resolved: ResolvedTransition): number;
95
+ /**
96
+ * one entry as css. a spring becomes a `linear()` easing sampled across its
97
+ * settle time, which is how a real spring curve, overshoot included, survives
98
+ * with no javascript running.
99
+ */
100
+ export declare function entryToCSS(entry: ResolvedEntry): string;
101
+ /**
102
+ * the whole resolution as a css `transition` value, or `undefined` when
103
+ * nothing animates. entry order is preserved, so css last-wins does the
104
+ * per-property resolution for us in the browser.
105
+ */
106
+ export declare function toCSSTransition(resolved: ResolvedTransition): string | undefined;
107
+
108
+ //# sourceMappingURL=resolveTransition.d.ts.map
@@ -0,0 +1,11 @@
1
+ {
2
+ "mappings": "AAaA,cAOO,yBACA,2BAEA,6BAEA;AAKP,YAAY,eACR;CACE,MAAM;CACN;CACA;IAEF;CACE,MAAM;;CAEN;CACA;CACA;CACA;CACA;;CAEA,QAAQ;;AAGd,iBAAiB,cAAc;;CAE7B;CACA,QAAQ;CACR;CACA,UAAU;;AAGZ,iBAAiB,mBAAmB;;CAElC,kBAAkB;;CAElB,KAAK;;CAEL,YAAY,SAAS,eAAe;;CAEpC;;;;;;CAMA;;CAEA,OAAO;;CAEP,MAAM;CACN,sBAAsB;;;AAexB,OAAO,iBAAS,kBACd,UAAU,oBACV,OAAO,UAAU,SAAS,YACzB;;;;;;;;;;AAuCH,OAAO,iBAAS,eAAe,kBAAkB;;;;;;;;;AAwIjD,OAAO,iBAAS,eACd;AAYF,iBAAiB,yBAAyB;;CAExC,aAAa;;CAEb,aAAa;;;;;;;;AAaf,OAAO,iBAAS,kBACd,YAAY,0CACZ,UAAS,2BACR;;;;;;;AAyHH,OAAO,iBAAS,oBACd,UAAU,oBACV,cACC;;AAQH,OAAO,iBAAS,cAAc,UAAU;;;;;AAQxC,OAAO,iBAAS,YAAY,QAAQ;;AAMpC,OAAO,iBAAS,iBAAiB,UAAU;;;;;;AAgB3C,OAAO,iBAAS,WAAW,OAAO;;;;;;AA0BlC,OAAO,iBAAS,gBAAgB,UAAU",
3
+ "names": [],
4
+ "sources": [
5
+ "src/resolveTransition.ts"
6
+ ],
7
+ "version": 3,
8
+ "sourcesContent": [
9
+ "// the one place a `transition` prop becomes driver-ready values.\n//\n// every driver and `getSplitStyles` call `resolveTransition`, so there is a\n// single grammar, a single preset lookup, and a single spring solver behind\n// css, reanimated, motion, and react-native. a transition that means one thing\n// on one driver cannot mean something else on another, because none of them\n// decide anything on their own any more.\n//\n// the shape is CSS's: an ordered entry list where the LAST entry naming a\n// property wins for that property, and entries do not inherit from each other.\n// `transition=\"all 200ms, opacity 150ms ease-out\"` reads exactly as it does in\n// a stylesheet.\n\nimport {\n parseTransition,\n parseTransitionObject,\n springFromDurationBounce,\n springSettleTime,\n springToDurationBounce,\n springToLinearEasing,\n type TransitionBehavior,\n type TransitionDiagnostic,\n type TransitionEntry,\n type TransitionObjectValue,\n type TransitionTiming,\n} from '@tamagui/style-grammar/transitions'\n\nimport { canonicalTransitionProperty } from './propertyNames'\nimport { setTransitionResolver } from './transitionResolver'\n\nexport type DriverTiming =\n | {\n kind: 'timing'\n durationMs: number\n easing: string\n }\n | {\n kind: 'spring'\n /** the undamped period, the portable \"how fast does this feel\" number */\n durationMs: number\n bounce: number\n stiffness: number\n damping: number\n mass: number\n /** authored low-level overrides, for drivers that take them raw */\n extra?: Record<string, unknown>\n }\n\nexport interface ResolvedEntry {\n /** canonical property name, kebab-case, or `all` / `none` */\n property: string\n timing: DriverTiming\n delayMs: number\n behavior: TransitionBehavior\n}\n\nexport interface ResolvedTransition {\n /** in authored order; later entries win under the css last-wins rule */\n entries: readonly ResolvedEntry[]\n /** the winning `all` entry, or null when only specific properties were named */\n all: ResolvedEntry | null\n /** winning entry per canonical property name, excluding `all` */\n byProperty: Readonly<Record<string, ResolvedEntry>>\n /** true when the author disabled transitions entirely (`transition=\"none\"`) */\n none: boolean\n /**\n * true when any entry was authored as a preset name or a `spring()`, the two\n * things that have no css spelling of their own. a resolution without one is\n * already plain css and needs no driver at all.\n */\n fused: boolean\n /** replaces this whole resolution while mounting, when the author set one */\n enter: ResolvedTransition | null\n /** replaces this whole resolution while unmounting */\n exit: ResolvedTransition | null\n diagnostics: readonly TransitionDiagnostic[]\n}\n\nconst emptyResolved: ResolvedTransition = {\n entries: [],\n all: null,\n byProperty: {},\n none: false,\n fused: false,\n enter: null,\n exit: null,\n diagnostics: [],\n}\n\n/** the resolution that applies in a given animation state */\nexport function forAnimationState(\n resolved: ResolvedTransition,\n state: 'enter' | 'exit' | 'default'\n): ResolvedTransition {\n if (state === 'enter' && resolved.enter) return resolved.enter\n if (state === 'exit' && resolved.exit) return resolved.exit\n return resolved\n}\n\nfunction timeToMs(value: string): number {\n // the grammar guarantees a `<number>ms` or `<number>s` token here\n return value.endsWith('ms') ? Number.parseFloat(value) : Number.parseFloat(value) * 1000\n}\n\nfunction springTiming(\n durationMs: number,\n bounce: number,\n extra?: Record<string, unknown>\n): DriverTiming {\n const mass = typeof extra?.mass === 'number' ? extra.mass : 1\n const physics = springFromDurationBounce({ duration: durationMs, bounce }, mass)\n return {\n kind: 'spring',\n durationMs,\n bounce,\n // authored physics win over the derived pair, so the escape hatch is exact\n stiffness: typeof extra?.stiffness === 'number' ? extra.stiffness : physics.stiffness,\n damping: typeof extra?.damping === 'number' ? extra.damping : physics.damping,\n mass,\n extra,\n }\n}\n\n/**\n * turns one entry in a driver's `animations` config into a timing.\n *\n * accepts every shape `PresetConfig` allows: a css string (`'350ms ease-out'`),\n * spring physics (`{ type: 'spring', damping, stiffness, mass }`), a timing\n * (`{ type: 'timing', duration, easing }`), and the canonical pair\n * (`{ duration, bounce }`). configs written for any driver therefore resolve\n * to the same motion on all four.\n */\nexport function presetToTiming(preset: unknown): DriverTiming | null {\n if (typeof preset === 'string') {\n const parsed = parseTransition(preset)\n if (!parsed.ok || parsed.value.kind !== 'transition') return null\n const entry = parsed.value.entries[0]\n if (!entry) return null\n return timingToDriver(entry.timing, null)\n }\n\n if (!preset || typeof preset !== 'object') return null\n const config = preset as Record<string, unknown>\n const duration = typeof config.duration === 'number' ? config.duration : undefined\n const hasPhysics =\n typeof config.stiffness === 'number' || typeof config.damping === 'number'\n\n const stiffness = typeof config.stiffness === 'number' ? config.stiffness : undefined\n const damping = typeof config.damping === 'number' ? config.damping : undefined\n\n const isSpring =\n config.type === 'spring' || typeof config.bounce === 'number' || hasPhysics\n\n if (isSpring) {\n const mass = typeof config.mass === 'number' ? config.mass : 1\n if (stiffness !== undefined) {\n const canonical = springToDurationBounce({\n stiffness,\n damping: damping ?? 2 * Math.sqrt(stiffness * mass),\n mass,\n })\n return {\n kind: 'spring',\n durationMs: duration ?? canonical.duration,\n bounce: typeof config.bounce === 'number' ? config.bounce : canonical.bounce,\n stiffness,\n damping: damping ?? 2 * Math.sqrt(stiffness * mass),\n mass,\n extra: config,\n }\n }\n if (duration !== undefined) {\n return springTiming(\n duration,\n typeof config.bounce === 'number' ? config.bounce : 0,\n config\n )\n }\n return null\n }\n\n if (duration === undefined) return null\n const easing = typeof config.easing === 'string' ? config.easing : 'ease'\n return { kind: 'timing', durationMs: duration, easing }\n}\n\n/**\n * lowers a grammar timing atom into driver values, resolving a preset name\n * against the driver's configured animations.\n */\nfunction timingToDriver(\n timing: TransitionTiming,\n animations: Record<string, unknown> | null\n): DriverTiming | null {\n if (timing.type === 'css') {\n return {\n kind: 'timing',\n durationMs: timeToMs(timing.duration),\n easing: timing.timingFunction,\n }\n }\n\n if (timing.type === 'spring') {\n return springTiming(\n timeToMs(timing.duration),\n timing.bounce,\n timing.config as Record<string, unknown> | undefined\n )\n }\n\n const preset = animations?.[timing.name]\n if (preset === undefined) return null\n const base = presetToTiming(preset)\n if (!base || !timing.config) return base\n\n // authored overrides land on top of the preset, in the preset's own terms\n const overrides = timing.config as Record<string, unknown>\n if (base.kind === 'spring' || typeof overrides.bounce === 'number') {\n const overrideDuration =\n typeof overrides.duration === 'number'\n ? overrides.duration\n : typeof overrides.duration === 'string'\n ? timeToMs(overrides.duration)\n : undefined\n const overrideBounce =\n typeof overrides.bounce === 'number' ? overrides.bounce : undefined\n const durationMs = overrideDuration ?? base.durationMs\n const bounce = overrideBounce ?? (base.kind === 'spring' ? base.bounce : 0)\n let carried = base.kind === 'spring' ? base.extra : undefined\n // a duration or bounce override re-solves the spring, so a preset written as\n // stiffness/damping cannot pass those two through: they ARE what the\n // override replaces. mass belongs to the object rather than the curve, so it\n // carries. physics written in the override still win, exactly as elsewhere.\n if (carried && (overrideDuration !== undefined || overrideBounce !== undefined)) {\n const { stiffness, damping, ...rest } = carried\n carried = rest\n }\n return springTiming(durationMs, bounce, { ...carried, ...overrides })\n }\n\n return {\n kind: 'timing',\n durationMs:\n typeof overrides.duration === 'number'\n ? overrides.duration\n : typeof overrides.duration === 'string'\n ? timeToMs(overrides.duration)\n : base.durationMs,\n easing: typeof overrides.easing === 'string' ? overrides.easing : base.easing,\n }\n}\n\nconst namedEasings: Record<string, readonly [number, number, number, number]> = {\n linear: [0, 0, 1, 1],\n ease: [0.25, 0.1, 0.25, 1],\n 'ease-in': [0.42, 0, 1, 1],\n 'ease-out': [0, 0, 0.58, 1],\n 'ease-in-out': [0.42, 0, 0.58, 1],\n}\n\n/**\n * a css easing as cubic-bezier control points, which is the only easing shape\n * reanimated, motion, and react-native all accept.\n *\n * returns null for `steps()` and `linear()`, which have no bezier equivalent.\n * a driver that gets null should fall back to its own default rather than\n * pretending it applied something.\n */\nexport function easingToBezier(\n easing: string\n): readonly [number, number, number, number] | null {\n const named = namedEasings[easing]\n if (named) return named\n if (!easing.startsWith('cubic-bezier(')) return null\n const parts = easing.slice('cubic-bezier('.length, -1).split(',')\n if (parts.length !== 4) return null\n const points = parts.map((part) => Number.parseFloat(part))\n if (points.some((point) => !Number.isFinite(point))) return null\n return points as unknown as [number, number, number, number]\n}\n\nexport interface ResolveTransitionOptions {\n /** the driver's animations config; its keys are the valid preset names */\n animations?: Record<string, unknown> | null\n /** config shorthands, so `transition=\"bg 200ms\"` names backgroundColor */\n shorthands?: Record<string, string> | null\n}\n\nconst cacheByAnimations = new WeakMap<object, Map<string, ResolvedTransition>>()\nconst objectCache = new WeakMap<object, ResolvedTransition>()\nconst noAnimations: Record<string, unknown> = {}\n\n/**\n * parses and resolves a `transition` prop into driver-ready entries.\n *\n * memoized per (animations config, authored value), because this runs on every\n * render of every component carrying a transition.\n */\nexport function resolveTransition(\n transition: TransitionObjectValue | null | undefined,\n options: ResolveTransitionOptions = {}\n): ResolvedTransition {\n if (transition == null || transition === '') return emptyResolved\n\n const animations = options.animations ?? null\n const cacheKey = (animations ?? noAnimations) as object\n\n if (typeof transition === 'string') {\n let byValue = cacheByAnimations.get(cacheKey)\n if (!byValue) {\n byValue = new Map()\n cacheByAnimations.set(cacheKey, byValue)\n }\n const hit = byValue.get(transition)\n if (hit) return hit\n const built = buildResolved(transition, animations, options.shorthands ?? null)\n // an authored value set is bounded in practice, but a codegen loop is not\n if (byValue.size > 2048) byValue.clear()\n byValue.set(transition, built)\n return built\n }\n\n if (typeof transition !== 'object') return emptyResolved\n const hit = objectCache.get(transition)\n if (hit) return hit\n const built = buildResolved(transition, animations, options.shorthands ?? null)\n objectCache.set(transition, built)\n return built\n}\n\nfunction buildResolved(\n transition: TransitionObjectValue,\n animations: Record<string, unknown> | null,\n shorthands: Record<string, string> | null\n): ResolvedTransition {\n const presetNames = animations ? new Set(Object.keys(animations)) : undefined\n const parsed = parseTransitionObject(transition, presetNames)\n\n if (!parsed.ok) {\n return { ...emptyResolved, diagnostics: parsed.diagnostics }\n }\n if (parsed.value.kind !== 'transition') return emptyResolved\n\n return fromEntries(\n parsed.value.entries,\n animations,\n shorthands,\n parsed.value.enter\n ? fromEntries(parsed.value.enter, animations, shorthands, null, null)\n : null,\n parsed.value.exit\n ? fromEntries(parsed.value.exit, animations, shorthands, null, null)\n : null\n )\n}\n\nconst transformFamily = ['transform', 'translate', 'scale', 'rotate'] as const\n\nfunction fromEntries(\n source: readonly TransitionEntry[],\n animations: Record<string, unknown> | null,\n shorthands: Record<string, string> | null,\n enter: ResolvedTransition | null,\n exit: ResolvedTransition | null\n): ResolvedTransition {\n const entries: ResolvedEntry[] = []\n const byProperty: Record<string, ResolvedEntry> = {}\n const diagnostics: TransitionDiagnostic[] = []\n let all: ResolvedEntry | null = null\n let none = false\n let fused = false\n\n for (const entry of source) {\n if (entry.property === 'none') {\n none = true\n continue\n }\n\n if (entry.timing.type !== 'css') fused = true\n\n const timing = timingToDriver(entry.timing, animations)\n if (!timing) {\n diagnostics.push({\n code: 'transition-invalid-token',\n token: entry.timing.type === 'preset' ? entry.timing.name : undefined,\n message:\n entry.timing.type === 'preset'\n ? `\"${entry.timing.name}\" is not a configured animation`\n : 'transition timing could not be resolved',\n })\n continue\n }\n\n const expanded = shorthands?.[entry.property] ?? entry.property\n const property = canonicalTransitionProperty(expanded)\n const delayMs = timeToMs(entry.delay)\n // tamagui writes x/y into the css `translate` longhand, scale into\n // `scale` and rotate into `rotate`, so an authored `transform` covers the\n // whole family or it transitions nothing the author can see.\n for (const name of expanded === 'transform' ? transformFamily : [property]) {\n const resolved: ResolvedEntry = {\n property: name,\n timing,\n delayMs,\n behavior: entry.behavior,\n }\n entries.push(resolved)\n // last wins, exactly as a stylesheet resolves a repeated property\n if (name === 'all') all = resolved\n else byProperty[name] = resolved\n }\n }\n\n return { entries, all, byProperty, none, fused, enter, exit, diagnostics }\n}\n\n/**\n * the transition that applies to one style key, under css last-wins.\n *\n * an authored `transform` already expanded into the whole family in\n * `fromEntries`, so `x`, `scale` and `rotate` find a direct entry here.\n */\nexport function getTransitionForKey(\n resolved: ResolvedTransition,\n key: string\n): ResolvedEntry | null {\n if (resolved.none) return null\n const direct = resolved.byProperty[canonicalTransitionProperty(key)]\n if (direct) return direct\n return resolved.all\n}\n\n/** true when anything at all will animate */\nexport function hasTransition(resolved: ResolvedTransition): boolean {\n return !resolved.none && resolved.entries.length > 0\n}\n\n/**\n * how long a timing actually runs, which for a spring is its settle time and\n * not its nominal duration. this is the number a completion deadline needs.\n */\nexport function getSettleMs(timing: DriverTiming): number {\n if (timing.kind === 'timing') return timing.durationMs\n return springSettleTime({ duration: timing.durationMs, bounce: timing.bounce })\n}\n\n/** the longest anything will take, for the driver's completion bookkeeping */\nexport function getMaxDurationMs(resolved: ResolvedTransition): number {\n let max = 0\n for (const entry of resolved.entries) {\n const total = getSettleMs(entry.timing) + entry.delayMs\n if (total > max) max = total\n }\n return max\n}\n\nconst linearEasingCache = new Map<string, { easing: string; durationMs: number }>()\n\n/**\n * one entry as css. a spring becomes a `linear()` easing sampled across its\n * settle time, which is how a real spring curve, overshoot included, survives\n * with no javascript running.\n */\nexport function entryToCSS(entry: ResolvedEntry): string {\n const delay = entry.delayMs ? ` ${entry.delayMs}ms` : ''\n const behavior = entry.behavior === 'allow-discrete' ? ' allow-discrete' : ''\n\n if (entry.timing.kind === 'timing') {\n return `${entry.property} ${entry.timing.durationMs}ms ${entry.timing.easing}${delay}${behavior}`\n }\n\n const key = `${entry.timing.durationMs}/${entry.timing.bounce}`\n let spring = linearEasingCache.get(key)\n if (!spring) {\n spring = springToLinearEasing({\n duration: entry.timing.durationMs,\n bounce: entry.timing.bounce,\n })\n if (linearEasingCache.size > 256) linearEasingCache.clear()\n linearEasingCache.set(key, spring)\n }\n return `${entry.property} ${Math.round(spring.durationMs)}ms ${spring.easing}${delay}${behavior}`\n}\n\n/**\n * the whole resolution as a css `transition` value, or `undefined` when\n * nothing animates. entry order is preserved, so css last-wins does the\n * per-property resolution for us in the browser.\n */\nexport function toCSSTransition(resolved: ResolvedTransition): string | undefined {\n if (resolved.none) return 'none'\n if (!resolved.entries.length) return undefined\n\n let out = ''\n for (const entry of resolved.entries) {\n out += `${out ? ', ' : ''}${entryToCSS(entry)}`\n }\n return out || undefined\n}\n\n// see `transitionResolver.ts`: this is what keeps the grammar out of a bundle\n// that has no animation driver in it.\nsetTransitionResolver({ resolve: resolveTransition, toCSS: toCSSTransition })\n"
10
+ ]
11
+ }
@@ -0,0 +1,30 @@
1
+ import type { ResolvedTransition } from "./resolveTransition";
2
+ /**
3
+ * `getSplitStyles` needs to know whether a `transition` string is plain css or
4
+ * needs a driver, and that answer has to come from the same grammar the
5
+ * compiler uses. Importing the grammar into `@tamagui/web` would put the
6
+ * parser and the spring solver in every bundle, including one with no
7
+ * animations in it at all, which is about 3.6kb gzip of runtime nobody asked
8
+ * for.
9
+ *
10
+ * So `resolveTransition` registers itself here on import. Loading any driver
11
+ * loads it, and a bundle with no driver in it has no presets to resolve, so
12
+ * the absent resolver is the correct answer rather than a missing one.
13
+ *
14
+ * The slot lives on `globalThis` because a bundler routinely gives one process
15
+ * two copies of this module: Vite's SSR graph and its optimized-deps graph each
16
+ * carry their own, and a module-local `let` then leaves the reader looking at
17
+ * the copy nobody registered into. The server rendered a transition as a static
18
+ * class while the client resolved it to a driver animation, which React reports
19
+ * as a hydration mismatch.
20
+ */
21
+ export type TransitionResolver = {
22
+ resolve: (value: any, options: {
23
+ animations?: any;
24
+ }) => ResolvedTransition;
25
+ toCSS: (resolved: ResolvedTransition) => string | undefined;
26
+ };
27
+ export declare function setTransitionResolver(next: TransitionResolver): void;
28
+ export declare function getTransitionResolver(): TransitionResolver | null;
29
+
30
+ //# sourceMappingURL=transitionResolver.d.ts.map
@@ -0,0 +1,11 @@
1
+ {
2
+ "mappings": "AAAA,cAAc,0BAA0B;;;;;;;;;;;;;;;;;;;;AAqBxC,YAAY,qBAAqB;CAC/B,UAAU,YAAY,SAAS;EAAE;OAAuB;CACxD,QAAQ,UAAU;;AAKpB,OAAO,iBAAS,sBAAsB,MAAM;AAI5C,OAAO,iBAAS,yBAAyB",
3
+ "names": [],
4
+ "sources": [
5
+ "src/transitionResolver.ts"
6
+ ],
7
+ "version": 3,
8
+ "sourcesContent": [
9
+ "import type { ResolvedTransition } from './resolveTransition'\n\n/**\n * `getSplitStyles` needs to know whether a `transition` string is plain css or\n * needs a driver, and that answer has to come from the same grammar the\n * compiler uses. Importing the grammar into `@tamagui/web` would put the\n * parser and the spring solver in every bundle, including one with no\n * animations in it at all, which is about 3.6kb gzip of runtime nobody asked\n * for.\n *\n * So `resolveTransition` registers itself here on import. Loading any driver\n * loads it, and a bundle with no driver in it has no presets to resolve, so\n * the absent resolver is the correct answer rather than a missing one.\n *\n * The slot lives on `globalThis` because a bundler routinely gives one process\n * two copies of this module: Vite's SSR graph and its optimized-deps graph each\n * carry their own, and a module-local `let` then leaves the reader looking at\n * the copy nobody registered into. The server rendered a transition as a static\n * class while the client resolved it to a driver animation, which React reports\n * as a hydration mismatch.\n */\nexport type TransitionResolver = {\n resolve: (value: any, options: { animations?: any }) => ResolvedTransition\n toCSS: (resolved: ResolvedTransition) => string | undefined\n}\n\nconst slot = Symbol.for('tamagui.transitionResolver')\n\nexport function setTransitionResolver(next: TransitionResolver): void {\n ;(globalThis as any)[slot] = next\n}\n\nexport function getTransitionResolver(): TransitionResolver | null {\n return (globalThis as any)[slot] ?? null\n}\n"
10
+ ]
11
+ }
package/types/types.d.ts CHANGED
@@ -1,56 +1,49 @@
1
1
  /**
2
- * Animation configuration that can include additional properties
3
- * like delay, duration, stiffness, damping, etc.
4
- */
5
- export type AnimationConfig = {
6
- type?: string;
7
- [key: string]: any;
8
- };
9
- /**
10
- * Input format for the transition prop - supports multiple syntaxes:
11
- *
12
- * 1. String: "bouncy"
13
- * 2. Object with property mappings: { x: 'quick', y: 'bouncy', default: 'slow' }
14
- * 3. Array with config: ['bouncy', { delay: 100, x: 'quick' }]
15
- * 4. Object with enter/exit: { enter: 'bouncy', exit: 'quick', default: 'slow' }
2
+ * One entry in a driver's `animations` config, and the same type for all four
3
+ * drivers: a config written once resolves to the same motion on css,
4
+ * reanimated, motion, and react-native.
16
5
  *
17
- * Note: Uses `any` to be compatible with the TransitionProp type from @tamagui/web
18
- * which has more complex union types.
19
- */
20
- export type TransitionPropInput = any;
21
- /**
22
- * Spring configuration parameters that can override preset defaults.
23
- * These are the common parameters across animation drivers.
6
+ * The canonical spelling is `{ duration, bounce }`. `duration` is the spring's
7
+ * undamped period, the "how fast does this feel" number, and `bounce` is 0 for
8
+ * critically damped, up toward 1 for loose and oscillating, negative for
9
+ * sluggish. A css string is a timing; `{ type: 'timing' }` is the object
10
+ * spelling of one. `stiffness`/`damping`/`mass` stay available for a config
11
+ * that was already tuned against them.
24
12
  */
25
- export type SpringConfig = {
13
+ export type PresetConfig = string | {
14
+ type?: "spring";
15
+ duration?: number;
16
+ bounce?: number;
26
17
  stiffness?: number;
27
18
  damping?: number;
28
19
  mass?: number;
29
- tension?: number;
30
- friction?: number;
31
20
  velocity?: number;
32
21
  overshootClamping?: boolean;
33
- duration?: number;
34
- bounciness?: number;
35
- speed?: number;
22
+ restDisplacementThreshold?: number;
23
+ restSpeedThreshold?: number;
24
+ } | {
25
+ type: "timing";
26
+ duration: number;
27
+ /** any css timing function */
28
+ easing?: string;
36
29
  };
30
+ /** the `animations` object a driver is created with */
31
+ export type AnimationsConfig = Record<string, PresetConfig>;
37
32
  /**
38
- * Normalized output format that all animation drivers consume.
39
- * Provides a consistent structure regardless of input format.
33
+ * A resolved animation config in a driver's own terms. Drivers build these
34
+ * from a `ResolvedEntry`; nothing parses one.
40
35
  */
41
- export type NormalizedTransition = {
42
- /** Default animation key for properties not explicitly listed */
43
- default: string | null;
44
- /** Animation key to use during enter transitions (mount) */
45
- enter: string | null;
46
- /** Animation key to use during exit transitions (unmount) */
47
- exit: string | null;
48
- /** Global delay in ms */
49
- delay: number | undefined;
50
- /** Per-property animation configs: propertyName -> animationKey or config */
51
- properties: Record<string, string | AnimationConfig>;
52
- /** Global spring config overrides that merge with the preset defaults */
53
- config?: SpringConfig;
36
+ export type AnimationConfig = {
37
+ type?: string;
38
+ [key: string]: any;
54
39
  };
40
+ /**
41
+ * Input format for the `transition` prop: a CSS transition string, a preset
42
+ * name, or a config object. See `@tamagui/style-grammar/transitions`.
43
+ *
44
+ * Note: uses `any` to stay compatible with the `TransitionProp` type from
45
+ * `@tamagui/web`, which carries the full style-key union.
46
+ */
47
+ export type TransitionPropInput = any;
55
48
 
56
49
  //# sourceMappingURL=types.d.ts.map
@@ -1,11 +1,11 @@
1
1
  {
2
- "mappings": ";;;;AAIA,YAAY,kBAAkB;CAC5B;;;;;;;;;;;;;;AAeF,YAAY;;;;;AAMZ,YAAY,eAAe;CACzB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;;;;;;AAOF,YAAY,uBAAuB;;CAEjC;;CAEA;;CAEA;;CAEA;;CAEA,YAAY,wBAAwB;;CAEpC,SAAS",
2
+ "mappings": ";;;;;;;;;;;;AAYA,YAAY,wBAER;CACE,OAAO;CACP;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;IAEF;CACE,MAAM;CACN;;CAEA;;;AAIN,YAAY,mBAAmB,eAAe;;;;;AAM9C,YAAY,kBAAkB;CAC5B;;;;;;;;;;AAWF,YAAY",
3
3
  "names": [],
4
4
  "sources": [
5
5
  "src/types.ts"
6
6
  ],
7
7
  "version": 3,
8
8
  "sourcesContent": [
9
- "/**\n * Animation configuration that can include additional properties\n * like delay, duration, stiffness, damping, etc.\n */\nexport type AnimationConfig = {\n type?: string\n [key: string]: any\n}\n\n/**\n * Input format for the transition prop - supports multiple syntaxes:\n *\n * 1. String: \"bouncy\"\n * 2. Object with property mappings: { x: 'quick', y: 'bouncy', default: 'slow' }\n * 3. Array with config: ['bouncy', { delay: 100, x: 'quick' }]\n * 4. Object with enter/exit: { enter: 'bouncy', exit: 'quick', default: 'slow' }\n *\n * Note: Uses `any` to be compatible with the TransitionProp type from @tamagui/web\n * which has more complex union types.\n */\nexport type TransitionPropInput = any\n\n/**\n * Spring configuration parameters that can override preset defaults.\n * These are the common parameters across animation drivers.\n */\nexport type SpringConfig = {\n stiffness?: number\n damping?: number\n mass?: number\n tension?: number\n friction?: number\n velocity?: number\n overshootClamping?: boolean\n duration?: number\n bounciness?: number\n speed?: number\n}\n\n/**\n * Normalized output format that all animation drivers consume.\n * Provides a consistent structure regardless of input format.\n */\nexport type NormalizedTransition = {\n /** Default animation key for properties not explicitly listed */\n default: string | null\n /** Animation key to use during enter transitions (mount) */\n enter: string | null\n /** Animation key to use during exit transitions (unmount) */\n exit: string | null\n /** Global delay in ms */\n delay: number | undefined\n /** Per-property animation configs: propertyName -> animationKey or config */\n properties: Record<string, string | AnimationConfig>\n /** Global spring config overrides that merge with the preset defaults */\n config?: SpringConfig\n}\n"
9
+ "/**\n * One entry in a driver's `animations` config, and the same type for all four\n * drivers: a config written once resolves to the same motion on css,\n * reanimated, motion, and react-native.\n *\n * The canonical spelling is `{ duration, bounce }`. `duration` is the spring's\n * undamped period, the \"how fast does this feel\" number, and `bounce` is 0 for\n * critically damped, up toward 1 for loose and oscillating, negative for\n * sluggish. A css string is a timing; `{ type: 'timing' }` is the object\n * spelling of one. `stiffness`/`damping`/`mass` stay available for a config\n * that was already tuned against them.\n */\nexport type PresetConfig =\n | string\n | {\n type?: 'spring'\n duration?: number\n bounce?: number\n stiffness?: number\n damping?: number\n mass?: number\n velocity?: number\n overshootClamping?: boolean\n restDisplacementThreshold?: number\n restSpeedThreshold?: number\n }\n | {\n type: 'timing'\n duration: number\n /** any css timing function */\n easing?: string\n }\n\n/** the `animations` object a driver is created with */\nexport type AnimationsConfig = Record<string, PresetConfig>\n\n/**\n * A resolved animation config in a driver's own terms. Drivers build these\n * from a `ResolvedEntry`; nothing parses one.\n */\nexport type AnimationConfig = {\n type?: string\n [key: string]: any\n}\n\n/**\n * Input format for the `transition` prop: a CSS transition string, a preset\n * name, or a config object. See `@tamagui/style-grammar/transitions`.\n *\n * Note: uses `any` to stay compatible with the `TransitionProp` type from\n * `@tamagui/web`, which carries the full style-key union.\n */\nexport type TransitionPropInput = any\n"
10
10
  ]
11
11
  }