@rafaelaugusto/jolt 0.1.0-beta.12 → 0.1.0-beta.14

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 (151) hide show
  1. package/README.md +9 -6
  2. package/dist/animate.d.ts +6 -4
  3. package/dist/animate.d.ts.map +1 -1
  4. package/dist/animate.js +3 -1
  5. package/dist/animate.js.map +1 -1
  6. package/dist/drag.js +3 -3
  7. package/dist/drag.js.map +1 -1
  8. package/dist/driver/android-gradient.d.ts.map +1 -1
  9. package/dist/driver/android-gradient.js +11 -1
  10. package/dist/driver/android-gradient.js.map +1 -1
  11. package/dist/driver/android-particles.d.ts +6 -0
  12. package/dist/driver/android-particles.d.ts.map +1 -0
  13. package/dist/driver/android-particles.js +93 -0
  14. package/dist/driver/android-particles.js.map +1 -0
  15. package/dist/driver/android.d.ts.map +1 -1
  16. package/dist/driver/android.js +2 -0
  17. package/dist/driver/android.js.map +1 -1
  18. package/dist/driver/frame.d.ts +3 -0
  19. package/dist/driver/frame.d.ts.map +1 -0
  20. package/dist/driver/frame.js +7 -0
  21. package/dist/driver/frame.js.map +1 -0
  22. package/dist/driver/index.d.ts +2 -0
  23. package/dist/driver/index.d.ts.map +1 -1
  24. package/dist/driver/index.js.map +1 -1
  25. package/dist/driver/ios-gradient.d.ts.map +1 -1
  26. package/dist/driver/ios-gradient.js +24 -2
  27. package/dist/driver/ios-gradient.js.map +1 -1
  28. package/dist/driver/ios.d.ts.map +1 -1
  29. package/dist/driver/ios.js +2 -0
  30. package/dist/driver/ios.js.map +1 -1
  31. package/dist/engine.d.ts +2 -1
  32. package/dist/engine.d.ts.map +1 -1
  33. package/dist/engine.js +32 -5
  34. package/dist/engine.js.map +1 -1
  35. package/dist/gradient-binding.d.ts +38 -0
  36. package/dist/gradient-binding.d.ts.map +1 -0
  37. package/dist/gradient-binding.js +128 -0
  38. package/dist/gradient-binding.js.map +1 -0
  39. package/dist/gradient.d.ts +19 -4
  40. package/dist/gradient.d.ts.map +1 -1
  41. package/dist/gradient.js +331 -70
  42. package/dist/gradient.js.map +1 -1
  43. package/dist/haptics.d.ts.map +1 -1
  44. package/dist/haptics.js +101 -28
  45. package/dist/haptics.js.map +1 -1
  46. package/dist/image-effect.d.ts +1 -0
  47. package/dist/image-effect.d.ts.map +1 -1
  48. package/dist/image-effect.js +10 -2
  49. package/dist/image-effect.js.map +1 -1
  50. package/dist/index.d.ts +6 -2
  51. package/dist/index.d.ts.map +1 -1
  52. package/dist/index.js +2 -0
  53. package/dist/index.js.map +1 -1
  54. package/dist/motion-scope.d.ts +3 -2
  55. package/dist/motion-scope.d.ts.map +1 -1
  56. package/dist/motion-scope.js +12 -2
  57. package/dist/motion-scope.js.map +1 -1
  58. package/dist/motion-value.d.ts +62 -8
  59. package/dist/motion-value.d.ts.map +1 -1
  60. package/dist/motion-value.js +327 -91
  61. package/dist/motion-value.js.map +1 -1
  62. package/dist/native/index.d.ts +7 -0
  63. package/dist/native/index.d.ts.map +1 -0
  64. package/dist/native/index.js +4 -0
  65. package/dist/native/index.js.map +1 -0
  66. package/dist/native-properties.d.ts +28 -0
  67. package/dist/native-properties.d.ts.map +1 -0
  68. package/dist/native-properties.js +154 -0
  69. package/dist/native-properties.js.map +1 -0
  70. package/dist/native-property-driver.d.ts +19 -0
  71. package/dist/native-property-driver.d.ts.map +1 -0
  72. package/dist/native-property-driver.js +69 -0
  73. package/dist/native-property-driver.js.map +1 -0
  74. package/dist/native-property.d.ts +35 -0
  75. package/dist/native-property.d.ts.map +1 -0
  76. package/dist/native-property.js +277 -0
  77. package/dist/native-property.js.map +1 -0
  78. package/dist/particles.d.ts +5 -2
  79. package/dist/particles.d.ts.map +1 -1
  80. package/dist/particles.js +16 -10
  81. package/dist/particles.js.map +1 -1
  82. package/dist/playback-group.d.ts.map +1 -1
  83. package/dist/playback-group.js +17 -1
  84. package/dist/playback-group.js.map +1 -1
  85. package/dist/playback.d.ts +15 -0
  86. package/dist/playback.d.ts.map +1 -1
  87. package/dist/playback.js +23 -0
  88. package/dist/playback.js.map +1 -1
  89. package/dist/scene-appearance.d.ts +14 -0
  90. package/dist/scene-appearance.d.ts.map +1 -0
  91. package/dist/scene-appearance.js +68 -0
  92. package/dist/scene-appearance.js.map +1 -0
  93. package/dist/sequence.d.ts +24 -0
  94. package/dist/sequence.d.ts.map +1 -1
  95. package/dist/sequence.js +181 -19
  96. package/dist/sequence.js.map +1 -1
  97. package/dist/timed-animation.d.ts +38 -0
  98. package/dist/timed-animation.d.ts.map +1 -0
  99. package/dist/timed-animation.js +177 -0
  100. package/dist/timed-animation.js.map +1 -0
  101. package/dist/types.d.ts +1 -1
  102. package/dist/types.d.ts.map +1 -1
  103. package/dist/value-observers.d.ts +19 -0
  104. package/dist/value-observers.d.ts.map +1 -0
  105. package/dist/value-observers.js +111 -0
  106. package/dist/value-observers.js.map +1 -0
  107. package/dist/value-track.d.ts +13 -0
  108. package/dist/value-track.d.ts.map +1 -0
  109. package/dist/value-track.js +59 -0
  110. package/dist/value-track.js.map +1 -0
  111. package/dist/vue/index.d.ts.map +1 -1
  112. package/dist/vue/index.js +28 -5
  113. package/dist/vue/index.js.map +1 -1
  114. package/package.json +6 -2
  115. package/platforms/android/java/org/rafaelaugusto/jolt/GradientLayer.java +30 -1
  116. package/platforms/android/java/org/rafaelaugusto/jolt/ParticleEmitter.java +192 -0
  117. package/platforms/android/java/org/rafaelaugusto/jolt/ParticleSimulation.java +114 -0
  118. package/platforms/android/proguard-rules.pro +2 -0
  119. package/src/android-plugin.d.ts +93 -0
  120. package/src/animate.ts +13 -7
  121. package/src/drag.ts +3 -3
  122. package/src/driver/android-gradient.ts +8 -1
  123. package/src/driver/android-particles.ts +118 -0
  124. package/src/driver/android.ts +2 -0
  125. package/src/driver/frame.ts +10 -0
  126. package/src/driver/index.ts +2 -0
  127. package/src/driver/ios-gradient.ts +24 -2
  128. package/src/driver/ios.ts +2 -0
  129. package/src/engine.ts +33 -6
  130. package/src/gradient-binding.ts +158 -0
  131. package/src/gradient.ts +376 -91
  132. package/src/haptics.ts +106 -28
  133. package/src/image-effect.ts +10 -2
  134. package/src/index.ts +6 -0
  135. package/src/ios-plugin.d.ts +40 -0
  136. package/src/motion-scope.ts +14 -3
  137. package/src/motion-value.ts +374 -99
  138. package/src/native/index.ts +23 -0
  139. package/src/native-properties.ts +188 -0
  140. package/src/native-property-driver.ts +123 -0
  141. package/src/native-property.ts +353 -0
  142. package/src/particles.ts +18 -17
  143. package/src/playback-group.ts +17 -1
  144. package/src/playback.ts +41 -0
  145. package/src/scene-appearance.ts +92 -0
  146. package/src/sequence.ts +209 -20
  147. package/src/timed-animation.ts +192 -0
  148. package/src/types.ts +1 -1
  149. package/src/value-observers.ts +133 -0
  150. package/src/value-track.ts +71 -0
  151. package/src/vue/index.ts +29 -5
@@ -0,0 +1,158 @@
1
+ import { parseColor, type ColorValue } from './color.js'
2
+ import { reducedMotion } from './config.js'
3
+ import {
4
+ isDerived,
5
+ valueSource,
6
+ type DerivedValue,
7
+ type DerivedColor,
8
+ } from './motion-value.js'
9
+ import type { GradientFrame } from './gradient.js'
10
+
11
+ export interface GradientBindings {
12
+ colors?: readonly (ColorValue | DerivedColor)[]
13
+ stops?: readonly (number | DerivedValue)[]
14
+ angle?: number | DerivedValue
15
+ center?: { readonly x?: number | DerivedValue; readonly y?: number | DerivedValue }
16
+ radius?: number | DerivedValue
17
+ }
18
+
19
+ export type GradientComponent =
20
+ 'angle' | 'x' | 'y' | 'radius' | `color:${number}` | `stop:${number}`
21
+ export type GradientSource = ReturnType<typeof valueSource>
22
+ export type GradientComponentValue = number | GradientSource
23
+ export type GradientPatch = Map<GradientComponent, GradientComponentValue>
24
+
25
+ export function cloneFrame(frame: GradientFrame): GradientFrame {
26
+ return { ...frame, colors: [...frame.colors], stops: [...frame.stops] }
27
+ }
28
+
29
+ export function put(frame: GradientFrame, key: GradientComponent, value: number) {
30
+ if (key.startsWith('color:')) frame.colors[Number(key.slice(6))] = value
31
+ else if (key.startsWith('stop:')) frame.stops[Number(key.slice(5))] = value
32
+ else frame[key as 'angle' | 'x' | 'y' | 'radius'] = value
33
+ }
34
+
35
+ export function take(frame: GradientFrame, key: GradientComponent) {
36
+ if (key.startsWith('color:')) return frame.colors[Number(key.slice(6))]!
37
+ if (key.startsWith('stop:')) return frame.stops[Number(key.slice(5))]!
38
+ return frame[key as 'angle' | 'x' | 'y' | 'radius']
39
+ }
40
+
41
+ /** Validate structural/static inputs before touching any existing owner. */
42
+ export function gradientPatch(values: GradientBindings, count: number): GradientPatch {
43
+ if (!values || typeof values !== 'object' || Array.isArray(values))
44
+ throw new TypeError('Gradient values must be an object.')
45
+ const patch: GradientPatch = new Map()
46
+ const add = (key: GradientComponent, value: unknown, color = false) => {
47
+ if (value === undefined) return
48
+ if (isDerived(value)) patch.set(key, valueSource(value, color))
49
+ else if (color) patch.set(key, parseColor(value as ColorValue))
50
+ else {
51
+ if (typeof value !== 'number' || !Number.isFinite(value))
52
+ throw new RangeError(`Invalid gradient ${key}: ${String(value)}.`)
53
+ if (key === 'radius' && value < 0)
54
+ throw new RangeError('Gradient radius must not be negative.')
55
+ if (key.startsWith('stop:') && (value < 0 || value > 1))
56
+ throw new RangeError('Gradient stops must be from 0 to 1.')
57
+ patch.set(key, value)
58
+ }
59
+ }
60
+ if (values.colors !== undefined) {
61
+ if (
62
+ !Array.isArray(values.colors) ||
63
+ values.colors.length < 2 ||
64
+ values.colors.length > 8
65
+ )
66
+ throw new RangeError('A gradient needs between two and eight colors.')
67
+ count = values.colors.length
68
+ Array.from(values.colors).forEach((value, i) => {
69
+ if (value === undefined) throw new TypeError('Gradient colors cannot be empty.')
70
+ add(`color:${i}`, value, true)
71
+ })
72
+ }
73
+ if (values.stops !== undefined) {
74
+ if (!Array.isArray(values.stops) || values.stops.length !== count)
75
+ throw new RangeError('Gradient stops need one value per color.')
76
+ Array.from(values.stops).forEach((value, i) => {
77
+ if (value === undefined) throw new TypeError('Gradient stops cannot be empty.')
78
+ add(`stop:${i}`, value)
79
+ })
80
+ if (
81
+ values.stops.every((value) => typeof value === 'number') &&
82
+ values.stops.some((value, i) => i > 0 && value < (values.stops![i - 1] as number))
83
+ )
84
+ throw new RangeError('Gradient stops must be ordered without going back.')
85
+ } else if (values.colors !== undefined) {
86
+ // Preserve the concrete API's rule: replacing colors resets unspecified stops.
87
+ values.colors.forEach((_, i) => patch.set(`stop:${i}`, i / (count - 1)))
88
+ }
89
+ add('angle', values.angle)
90
+ if (
91
+ values.center !== undefined &&
92
+ (!values.center || typeof values.center !== 'object')
93
+ )
94
+ throw new TypeError('Gradient center needs x/y components.')
95
+ add('x', values.center?.x)
96
+ add('y', values.center?.y)
97
+ add('radius', values.radius)
98
+ return patch
99
+ }
100
+
101
+ export interface GradientBase {
102
+ at(delta: number): GradientFrame
103
+ remaining: number
104
+ elapsed(): number
105
+ }
106
+
107
+ /** Native windows share a source clock. Only setup/commands/window boundaries enter JS. */
108
+ export function gradientProgram(base: GradientBase, bindings: GradientPatch) {
109
+ const roots = new Map<object, ReturnType<GradientSource['snapshot']>>()
110
+ for (const value of bindings.values())
111
+ if (typeof value !== 'number' && !roots.has(value.identity))
112
+ roots.set(value.identity, value.snapshot())
113
+ const moving = [...roots.values()].filter((state) => state.running)
114
+ const remaining = Math.max(
115
+ base.remaining,
116
+ ...moving.map((state) => state.track.end - state.elapsed),
117
+ 0,
118
+ )
119
+ const duration = Math.min(4000, remaining)
120
+ const anchor = moving[0]
121
+ const elapsed = anchor
122
+ ? () => Math.max(0, anchor.time() - anchor.elapsed)
123
+ : base.elapsed
124
+ const reduced = reducedMotion()
125
+ const at = (delta: number) => {
126
+ const frame = cloneFrame(base.at(delta))
127
+ for (const [key, source] of bindings) {
128
+ if (typeof source === 'number') {
129
+ put(frame, key, source)
130
+ continue
131
+ }
132
+ const state = roots.get(source.identity)!
133
+ const geometry = key === 'angle' || key === 'x' || key === 'y' || key === 'radius'
134
+ const input =
135
+ reduced && geometry && state.running
136
+ ? state.track.to
137
+ : state.running
138
+ ? state.track.valueAt(state.elapsed + delta)
139
+ : state.value
140
+ const value = source.read(input)
141
+ if (!Number.isFinite(value))
142
+ throw new RangeError(`Nonfinite gradient binding: ${key}.`)
143
+ put(frame, key, value)
144
+ }
145
+ // Project the complete vector without sorting colors. Spring overshoot may
146
+ // merge adjacent stops; their identity and order are retained.
147
+ frame.radius = Math.max(0, frame.radius)
148
+ frame.stops = frame.stops.map((stop) => Math.min(1, Math.max(0, stop)))
149
+ for (let i = 1; i < frame.stops.length; i++)
150
+ frame.stops[i] = Math.max(frame.stops[i - 1]!, frame.stops[i]!)
151
+ return frame
152
+ }
153
+ const current = at(0)
154
+ const steps = Math.max(1, Math.ceil((duration * 60) / 1000))
155
+ const times = Array.from({ length: steps + 1 }, (_, i) => i / steps)
156
+ const frames = times.map((time) => at(time * duration))
157
+ return { current, frames, times, duration, remaining, elapsed, at }
158
+ }