chnobli 0.1.7 → 0.1.9

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 (225) hide show
  1. package/package.json +24 -11
  2. package/src/animation/Animation.ts +10 -6
  3. package/src/animation/public.ts +47 -10
  4. package/src/chnobli.ts +20 -11
  5. package/src/property/BasicProperty.ts +3 -3
  6. package/src/property/ClassProperty.ts +2 -2
  7. package/src/property/Property.ts +7 -5
  8. package/src/property/StyleProperty.ts +7 -7
  9. package/src/property/TransformProperty.ts +4 -4
  10. package/src/property/TransformXYProperty.ts +3 -3
  11. package/src/responsive/TestEvent.ts +1 -1
  12. package/src/scroll/Scroll.ts +174 -90
  13. package/src/scroll/index.ts +8 -0
  14. package/src/scroll/public.ts +23 -12
  15. package/src/stagger/stagger.ts +34 -14
  16. package/src/target/BaseTarget.old.ts +2 -2
  17. package/src/target/DomTarget.ts +3 -3
  18. package/src/target/ObjectTarget.ts +124 -0
  19. package/src/target/Target.ts +16 -3
  20. package/src/tests/properties.test.ts +54 -4
  21. package/src/tests/timeline.test.ts +3 -3
  22. package/src/tests/timing.test.ts +1 -1
  23. package/src/tests/usecases.test.ts +5 -5
  24. package/src/tests/values.test.ts +4 -4
  25. package/src/timeline/Nested.ts +7 -7
  26. package/src/timeline/{TimeLine.ts → Timeline.ts} +29 -9
  27. package/src/timeline/public.ts +198 -58
  28. package/src/timing/AnimationFrameTicker.ts +2 -2
  29. package/src/timing/TestTicker.ts +2 -2
  30. package/src/timing/Ticker.ts +1 -1
  31. package/src/timing/Timing.ts +38 -4
  32. package/src/utils/internal.ts +6 -3
  33. package/src/utils/utils.ts +18 -9
  34. package/src/values/ColorValue.ts +1 -1
  35. package/src/values/StyleValue.ts +15 -3
  36. package/tsconfig.build.json +2 -2
  37. package/tsconfig.json +2 -3
  38. package/.editorconfig +0 -11
  39. package/.github/workflows/ci.yaml +0 -34
  40. package/.prettierignore +0 -4
  41. package/.prettierrc +0 -6
  42. package/.vscode/settings.json +0 -4
  43. package/LICENSE.md +0 -21
  44. package/README.md +0 -5
  45. package/auto-docs/easing.js.html +0 -342
  46. package/auto-docs/fonts/OpenSans-Bold-webfont.eot +0 -0
  47. package/auto-docs/fonts/OpenSans-Bold-webfont.svg +0 -1830
  48. package/auto-docs/fonts/OpenSans-Bold-webfont.woff +0 -0
  49. package/auto-docs/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
  50. package/auto-docs/fonts/OpenSans-BoldItalic-webfont.svg +0 -1830
  51. package/auto-docs/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
  52. package/auto-docs/fonts/OpenSans-Italic-webfont.eot +0 -0
  53. package/auto-docs/fonts/OpenSans-Italic-webfont.svg +0 -1830
  54. package/auto-docs/fonts/OpenSans-Italic-webfont.woff +0 -0
  55. package/auto-docs/fonts/OpenSans-Light-webfont.eot +0 -0
  56. package/auto-docs/fonts/OpenSans-Light-webfont.svg +0 -1831
  57. package/auto-docs/fonts/OpenSans-Light-webfont.woff +0 -0
  58. package/auto-docs/fonts/OpenSans-LightItalic-webfont.eot +0 -0
  59. package/auto-docs/fonts/OpenSans-LightItalic-webfont.svg +0 -1835
  60. package/auto-docs/fonts/OpenSans-LightItalic-webfont.woff +0 -0
  61. package/auto-docs/fonts/OpenSans-Regular-webfont.eot +0 -0
  62. package/auto-docs/fonts/OpenSans-Regular-webfont.svg +0 -1831
  63. package/auto-docs/fonts/OpenSans-Regular-webfont.woff +0 -0
  64. package/auto-docs/global.html +0 -4810
  65. package/auto-docs/index.html +0 -65
  66. package/auto-docs/scripts/linenumber.js +0 -25
  67. package/auto-docs/scripts/prettify/Apache-License-2.0.txt +0 -202
  68. package/auto-docs/scripts/prettify/lang-css.js +0 -2
  69. package/auto-docs/scripts/prettify/prettify.js +0 -28
  70. package/auto-docs/styles/jsdoc-default.css +0 -358
  71. package/auto-docs/styles/prettify-jsdoc.css +0 -111
  72. package/auto-docs/styles/prettify-tomorrow.css +0 -132
  73. package/dist/animation/Animation.d.ts +0 -36
  74. package/dist/animation/Animation.d.ts.map +0 -1
  75. package/dist/animation/Animation.js +0 -230
  76. package/dist/animation/Animation.js.map +0 -1
  77. package/dist/animation/animation.d.ts +0 -36
  78. package/dist/animation/animation.d.ts.map +0 -1
  79. package/dist/animation/animation.js +0 -230
  80. package/dist/animation/animation.js.map +0 -1
  81. package/dist/animation/public.d.ts +0 -55
  82. package/dist/animation/public.d.ts.map +0 -1
  83. package/dist/animation/public.js +0 -104
  84. package/dist/animation/public.js.map +0 -1
  85. package/dist/chnobli.d.ts +0 -15
  86. package/dist/chnobli.d.ts.map +0 -1
  87. package/dist/chnobli.js +0 -63
  88. package/dist/chnobli.js.map +0 -1
  89. package/dist/property/BasicProperty.d.ts +0 -38
  90. package/dist/property/BasicProperty.d.ts.map +0 -1
  91. package/dist/property/BasicProperty.js +0 -72
  92. package/dist/property/BasicProperty.js.map +0 -1
  93. package/dist/property/ClassProperty.d.ts +0 -32
  94. package/dist/property/ClassProperty.d.ts.map +0 -1
  95. package/dist/property/ClassProperty.js +0 -108
  96. package/dist/property/ClassProperty.js.map +0 -1
  97. package/dist/property/Property.d.ts +0 -13
  98. package/dist/property/Property.d.ts.map +0 -1
  99. package/dist/property/Property.js +0 -20
  100. package/dist/property/Property.js.map +0 -1
  101. package/dist/property/StyleProperty.d.ts +0 -25
  102. package/dist/property/StyleProperty.d.ts.map +0 -1
  103. package/dist/property/StyleProperty.js +0 -221
  104. package/dist/property/StyleProperty.js.map +0 -1
  105. package/dist/property/TransformProperty.d.ts +0 -15
  106. package/dist/property/TransformProperty.d.ts.map +0 -1
  107. package/dist/property/TransformProperty.js +0 -43
  108. package/dist/property/TransformProperty.js.map +0 -1
  109. package/dist/property/TransformXYProperty.d.ts +0 -28
  110. package/dist/property/TransformXYProperty.d.ts.map +0 -1
  111. package/dist/property/TransformXYProperty.js +0 -65
  112. package/dist/property/TransformXYProperty.js.map +0 -1
  113. package/dist/responsive/ResponsiveEvent.d.ts +0 -17
  114. package/dist/responsive/ResponsiveEvent.d.ts.map +0 -1
  115. package/dist/responsive/ResponsiveEvent.js +0 -45
  116. package/dist/responsive/ResponsiveEvent.js.map +0 -1
  117. package/dist/responsive/TestEvent.d.ts +0 -11
  118. package/dist/responsive/TestEvent.d.ts.map +0 -1
  119. package/dist/responsive/TestEvent.js +0 -26
  120. package/dist/responsive/TestEvent.js.map +0 -1
  121. package/dist/responsive/event.d.ts +0 -10
  122. package/dist/responsive/event.d.ts.map +0 -1
  123. package/dist/responsive/event.js +0 -39
  124. package/dist/responsive/event.js.map +0 -1
  125. package/dist/scroll/Scroll.d.ts +0 -27
  126. package/dist/scroll/Scroll.d.ts.map +0 -1
  127. package/dist/scroll/Scroll.js +0 -132
  128. package/dist/scroll/Scroll.js.map +0 -1
  129. package/dist/scroll/ScrollEvent.d.ts +0 -17
  130. package/dist/scroll/ScrollEvent.d.ts.map +0 -1
  131. package/dist/scroll/ScrollEvent.js +0 -39
  132. package/dist/scroll/ScrollEvent.js.map +0 -1
  133. package/dist/scroll/public.d.ts +0 -7
  134. package/dist/scroll/public.d.ts.map +0 -1
  135. package/dist/scroll/public.js +0 -17
  136. package/dist/scroll/public.js.map +0 -1
  137. package/dist/stagger/stagger.d.ts +0 -13
  138. package/dist/stagger/stagger.d.ts.map +0 -1
  139. package/dist/stagger/stagger.js +0 -35
  140. package/dist/stagger/stagger.js.map +0 -1
  141. package/dist/target/BaseTarget.old.d.ts +0 -33
  142. package/dist/target/BaseTarget.old.d.ts.map +0 -1
  143. package/dist/target/BaseTarget.old.js +0 -73
  144. package/dist/target/BaseTarget.old.js.map +0 -1
  145. package/dist/target/DomTarget.d.ts +0 -41
  146. package/dist/target/DomTarget.d.ts.map +0 -1
  147. package/dist/target/DomTarget.js +0 -230
  148. package/dist/target/DomTarget.js.map +0 -1
  149. package/dist/target/Target.d.ts +0 -22
  150. package/dist/target/Target.d.ts.map +0 -1
  151. package/dist/target/Target.js +0 -21
  152. package/dist/target/Target.js.map +0 -1
  153. package/dist/target/TestDomNode.d.ts +0 -14
  154. package/dist/target/TestDomNode.d.ts.map +0 -1
  155. package/dist/target/TestDomNode.js +0 -55
  156. package/dist/target/TestDomNode.js.map +0 -1
  157. package/dist/timeline/Nested.d.ts +0 -30
  158. package/dist/timeline/Nested.d.ts.map +0 -1
  159. package/dist/timeline/Nested.js +0 -51
  160. package/dist/timeline/Nested.js.map +0 -1
  161. package/dist/timeline/TimeLine.d.ts +0 -32
  162. package/dist/timeline/TimeLine.d.ts.map +0 -1
  163. package/dist/timeline/TimeLine.js +0 -288
  164. package/dist/timeline/TimeLine.js.map +0 -1
  165. package/dist/timeline/public.d.ts +0 -120
  166. package/dist/timeline/public.d.ts.map +0 -1
  167. package/dist/timeline/public.js +0 -301
  168. package/dist/timeline/public.js.map +0 -1
  169. package/dist/timing/AnimationFrameTicker.d.ts +0 -32
  170. package/dist/timing/AnimationFrameTicker.d.ts.map +0 -1
  171. package/dist/timing/AnimationFrameTicker.js +0 -134
  172. package/dist/timing/AnimationFrameTicker.js.map +0 -1
  173. package/dist/timing/Ease.d.ts +0 -6
  174. package/dist/timing/Ease.d.ts.map +0 -1
  175. package/dist/timing/Ease.js +0 -15
  176. package/dist/timing/Ease.js.map +0 -1
  177. package/dist/timing/TestTicker.d.ts +0 -19
  178. package/dist/timing/TestTicker.d.ts.map +0 -1
  179. package/dist/timing/TestTicker.js +0 -81
  180. package/dist/timing/TestTicker.js.map +0 -1
  181. package/dist/timing/Ticker.d.ts +0 -14
  182. package/dist/timing/Ticker.d.ts.map +0 -1
  183. package/dist/timing/Ticker.js +0 -2
  184. package/dist/timing/Ticker.js.map +0 -1
  185. package/dist/timing/Timing.d.ts +0 -62
  186. package/dist/timing/Timing.d.ts.map +0 -1
  187. package/dist/timing/Timing.js +0 -257
  188. package/dist/timing/Timing.js.map +0 -1
  189. package/dist/timing/easing.d.ts +0 -158
  190. package/dist/timing/easing.d.ts.map +0 -1
  191. package/dist/timing/easing.js +0 -273
  192. package/dist/timing/easing.js.map +0 -1
  193. package/dist/utils/Events.d.ts +0 -9
  194. package/dist/utils/Events.d.ts.map +0 -1
  195. package/dist/utils/Events.js +0 -35
  196. package/dist/utils/Events.js.map +0 -1
  197. package/dist/utils/internal.d.ts +0 -2
  198. package/dist/utils/internal.d.ts.map +0 -1
  199. package/dist/utils/internal.js +0 -6
  200. package/dist/utils/internal.js.map +0 -1
  201. package/dist/utils/motionpath.d.ts +0 -16
  202. package/dist/utils/motionpath.d.ts.map +0 -1
  203. package/dist/utils/motionpath.js +0 -41
  204. package/dist/utils/motionpath.js.map +0 -1
  205. package/dist/utils/utils.d.ts +0 -43
  206. package/dist/utils/utils.d.ts.map +0 -1
  207. package/dist/utils/utils.js +0 -93
  208. package/dist/utils/utils.js.map +0 -1
  209. package/dist/values/ColorValue.d.ts +0 -12
  210. package/dist/values/ColorValue.d.ts.map +0 -1
  211. package/dist/values/ColorValue.js +0 -133
  212. package/dist/values/ColorValue.js.map +0 -1
  213. package/dist/values/StyleValue.d.ts +0 -40
  214. package/dist/values/StyleValue.d.ts.map +0 -1
  215. package/dist/values/StyleValue.js +0 -149
  216. package/dist/values/StyleValue.js.map +0 -1
  217. package/dist/values/Value.d.ts +0 -13
  218. package/dist/values/Value.d.ts.map +0 -1
  219. package/dist/values/Value.js +0 -38
  220. package/dist/values/Value.js.map +0 -1
  221. package/dist/values/defaultcolors.d.ts +0 -2
  222. package/dist/values/defaultcolors.d.ts.map +0 -1
  223. package/dist/values/defaultcolors.js +0 -149
  224. package/dist/values/defaultcolors.js.map +0 -1
  225. package/docs/INDEX.md +0 -15
@@ -1,9 +1,9 @@
1
1
  import { describe, expect, it } from 'vitest';
2
- import TestTicker from '../timing/TestTicker';
3
- import TestResponsiveEvent from '../responsive/TestEvent';
2
+ import TestTicker from '../timing/TestTicker.js';
3
+ import TestResponsiveEvent from '../responsive/TestEvent.js';
4
4
  import { animate, timeline } from '../chnobli.js';
5
- import { responsive, curve } from '../utils/utils';
6
- import { el } from '../target/TestDomNode';
5
+ import { responsive, curve, fromTo } from '../utils/utils.js';
6
+ import { el } from '../target/TestDomNode.js';
7
7
  import { timeout } from 'fire/utils';
8
8
 
9
9
  describe('properties', () => {
@@ -180,4 +180,54 @@ describe('properties', () => {
180
180
  'translate3d(50.000px,20.000px,0.000px)',
181
181
  );
182
182
  });
183
+
184
+ it('object-target', () => {
185
+ const ticker = new TestTicker();
186
+
187
+ const obj: { x: number; width?: number } = {
188
+ x: 0,
189
+ };
190
+ const tl = timeline()
191
+ .add(obj, {
192
+ x: 100,
193
+ width: fromTo(0, 100),
194
+ duration: 10,
195
+ })
196
+ .play();
197
+
198
+ ticker.run(5);
199
+ expect(obj.x).toBe(50);
200
+ expect(obj.width).toBe(50);
201
+
202
+ ticker.run();
203
+ expect(obj.x).toBe(100);
204
+ expect(obj.width).toBe(100);
205
+
206
+ tl.reverse();
207
+ tl.play();
208
+ ticker.run();
209
+ expect(obj.x).toBe(undefined);
210
+ expect(obj.width).toBe(undefined);
211
+ });
212
+
213
+ it('reset values', () => {
214
+ const ticker = new TestTicker();
215
+
216
+ const div = el();
217
+ div.computedStyle.width = '0px';
218
+ const tl = timeline()
219
+ .add(div, {
220
+ width: 100,
221
+ duration: 10,
222
+ })
223
+ .play();
224
+
225
+ ticker.run();
226
+ expect(div.style.width).toBe('100.000px');
227
+
228
+ tl.reverse();
229
+ tl.play();
230
+ ticker.run();
231
+ expect(div.style.width).toBe(undefined);
232
+ });
183
233
  });
@@ -1,7 +1,7 @@
1
1
  import { describe, expect, it } from 'vitest';
2
- import TestTicker from '../timing/TestTicker';
3
- import { animate, timeline } from '../chnobli';
4
- import { el } from '../target/TestDomNode';
2
+ import TestTicker from '../timing/TestTicker.js';
3
+ import { animate, timeline } from '../chnobli.js';
4
+ import { el } from '../target/TestDomNode.js';
5
5
 
6
6
  describe('timeline', () => {
7
7
  it('empty timeline', () => {
@@ -5,7 +5,7 @@ import Timing, {
5
5
  STATE_RUNNING,
6
6
  STATE_ENDED,
7
7
  STATE_AFTER,
8
- } from '../timing/Timing';
8
+ } from '../timing/Timing.js';
9
9
 
10
10
  describe('timing', () => {
11
11
  it('zero duration', () => {
@@ -1,9 +1,9 @@
1
1
  import { describe, expect, it } from 'vitest';
2
- import TestTicker from '../timing/TestTicker';
3
- import TestResponsiveEvent from '../responsive/TestEvent';
4
- import { animate, timeline } from '../chnobli';
5
- import { responsive } from '../utils/utils';
6
- import { el } from '../target/TestDomNode';
2
+ import TestTicker from '../timing/TestTicker.js';
3
+ import TestResponsiveEvent from '../responsive/TestEvent.js';
4
+ import { animate, timeline } from '../chnobli.js';
5
+ import { responsive } from '../utils/utils.js';
6
+ import { el } from '../target/TestDomNode.js';
7
7
 
8
8
  describe('usecases', () => {
9
9
  it('accordion', () => {
@@ -1,8 +1,8 @@
1
1
  import { describe, expect, it } from 'vitest';
2
- import TestTicker from '../timing/TestTicker';
3
- import { animate, timeline } from '../chnobli';
4
- import { responsive, from, fromTo } from '../utils/utils';
5
- import { el, getRootElement } from '../target/TestDomNode';
2
+ import TestTicker from '../timing/TestTicker.js';
3
+ import { animate, timeline } from '../chnobli.js';
4
+ import { responsive, from, fromTo } from '../utils/utils.js';
5
+ import { el, getRootElement } from '../target/TestDomNode.js';
6
6
 
7
7
  describe('values', () => {
8
8
  it('rem unit', () => {
@@ -1,6 +1,6 @@
1
- import { takeProp } from '../utils/internal';
2
- import Timeline from './TimeLine';
3
- import { timelineAdd } from './public';
1
+ import { takeProp } from '../utils/internal.js';
2
+ import Timeline from './Timeline.js';
3
+ import { timelineAdd } from './public.js';
4
4
 
5
5
  export default class NestedTimeline {
6
6
  _defaults: Record<string, any>;
@@ -19,7 +19,7 @@ export default class NestedTimeline {
19
19
  * Set's properties
20
20
  * offset can be staggered, a number, a label or a string `+=10`
21
21
  */
22
- set(targets: any, props: Record<string, any>, offset: any = null) {
22
+ set(targets: any, props: Record<string, any>, offset: any = null): this {
23
23
  // for the moment let's just add as usual but set the duration to 0
24
24
  return this.add(targets, { ...props, duration: 0 }, offset);
25
25
  }
@@ -29,7 +29,7 @@ export default class NestedTimeline {
29
29
  *
30
30
  * offset can be staggered, a number, a label or a string `+=10`
31
31
  */
32
- add(targets: any, props: Record<string, any>, offset: any = null) {
32
+ add(targets: any, props: Record<string, any>, offset: any = null): this {
33
33
  timelineAdd(this, targets, props, offset);
34
34
 
35
35
  return this;
@@ -40,7 +40,7 @@ export default class NestedTimeline {
40
40
  *
41
41
  * This label can then be used in offsets
42
42
  */
43
- label(label: string, offset: any = null) {
43
+ label(label: string, offset: any = null): this {
44
44
  this._inner.label(label, offset);
45
45
 
46
46
  return this;
@@ -55,7 +55,7 @@ export default class NestedTimeline {
55
55
  fn: (tl: NestedTimeline) => void,
56
56
  opts: Record<string, any> = {},
57
57
  offset: any = null,
58
- ) {
58
+ ): this {
59
59
  const tl = new NestedTimeline(opts);
60
60
 
61
61
  fn(tl);
@@ -1,4 +1,4 @@
1
- import { takeProp } from '../utils/internal';
1
+ import { takeProp } from '../utils/internal.js';
2
2
  import Timing, {
3
3
  parseEase,
4
4
  parseRepeat,
@@ -6,10 +6,10 @@ import Timing, {
6
6
  parseReversed,
7
7
  STATE_BEFORE,
8
8
  STATE_ENDED,
9
- } from '../timing/Timing';
10
- import Ticker from '../timing/Ticker';
11
- import Animation from '../animation/Animation';
12
- import AnimationFrameTicker from '../timing/AnimationFrameTicker';
9
+ } from '../timing/Timing.js';
10
+ import Ticker from '../timing/Ticker.js';
11
+ import Animation from '../animation/Animation.js';
12
+ import AnimationFrameTicker from '../timing/AnimationFrameTicker.js';
13
13
 
14
14
  type Entry = {
15
15
  type: 'label' | 'animation' | 'timeline';
@@ -24,7 +24,7 @@ type Entry = {
24
24
  * Timeline is the most versatile class
25
25
  *
26
26
  * A timeline can contain multiple animation, ordered one after the other or
27
- * offset.
27
+ * by an offset.
28
28
  */
29
29
  export default class Timeline {
30
30
  timing: Timing;
@@ -49,6 +49,8 @@ export default class Timeline {
49
49
  */
50
50
  constructor(props: Record<string, any> = {}) {
51
51
  const nProps = {
52
+ // duration here is not important since it will be calculated
53
+ // based on the animations that get added
52
54
  duration: 1000,
53
55
  ease: parseEase(takeProp(props, 'ease', null)),
54
56
  repeat: parseRepeat(takeProp(props, 'repeat', false)),
@@ -71,7 +73,7 @@ export default class Timeline {
71
73
  };
72
74
  }
73
75
 
74
- isFinite() {
76
+ isFinite(): boolean {
75
77
  return !this.entries.some(e => {
76
78
  return e.type === 'animation' && !e.value.isFinite();
77
79
  });
@@ -84,7 +86,7 @@ export default class Timeline {
84
86
  props: Record<string, any>,
85
87
  offset: any = null,
86
88
  relative = 0,
87
- ) {
89
+ ): this {
88
90
  const animation = new Animation(target, this.ticker, props);
89
91
 
90
92
  if (!animation.isFinite())
@@ -111,7 +113,7 @@ export default class Timeline {
111
113
  });
112
114
  }
113
115
 
114
- label(label: string, offset: any = null) {
116
+ label(label: string, offset: any = null): this {
115
117
  this.entries.push({
116
118
  type: 'label',
117
119
  value: label,
@@ -145,6 +147,21 @@ export default class Timeline {
145
147
  this._updateTimings();
146
148
  }
147
149
 
150
+ /**
151
+ * Returns the position of a label
152
+ *
153
+ * needs to be initialized
154
+ */
155
+ labelPosition(label: string): number {
156
+ const entry = this.entries.find(e => {
157
+ return e.type === 'label' && e.value === label;
158
+ });
159
+
160
+ if (!entry) throw new Error('could not find label ' + label);
161
+
162
+ return entry.start! / this.timing.duration;
163
+ }
164
+
148
165
  init() {
149
166
  if (this._initialized) return;
150
167
  this._initialized = true;
@@ -254,6 +271,9 @@ export default class Timeline {
254
271
  }
255
272
  }
256
273
 
274
+ /**
275
+ * Updates the timings of all animations
276
+ */
257
277
  _updateTimings() {
258
278
  this._renderQueue = {
259
279
  upcoming: [],
@@ -1,34 +1,73 @@
1
- import { takeProp } from '../utils/internal';
2
- import Timeline from './TimeLine';
3
- import { STATE_ENDED } from '../timing/Timing';
4
- import { callStagger } from '../stagger/stagger';
5
- import Events from '../utils/Events';
6
- import ResponsiveEvent from '../responsive/ResponsiveEvent';
7
- import NestedTimeline from './Nested';
1
+ import { takeProp } from '../utils/internal.js';
2
+ import Timeline from './Timeline.js';
3
+ import Timing, {
4
+ STATE_BEFORE,
5
+ STATE_ENDED,
6
+ TimingProps,
7
+ } from '../timing/Timing.js';
8
+ import Stagger, { callStagger } from '../stagger/stagger.js';
9
+ import Events from '../utils/Events.js';
10
+ import ResponsiveEvent from '../responsive/ResponsiveEvent.js';
11
+ import NestedTimeline from './Nested.js';
12
+ import { Targets } from '../chnobli.js';
8
13
 
9
14
  const STATE_PAUSED = 0;
10
15
  const STATE_RENDER_ONCE = 1;
11
- const STATE_PLAYING = 2;
16
+ const STATE_SEEK = 2;
17
+ const STATE_PLAYING = 3;
12
18
 
13
19
  export type Responsive = {
14
20
  responsive: () => void;
15
21
  };
16
22
 
23
+ export type TimelineProps = {
24
+ // default properties for all animations
25
+ defaults?: Record<string, any>;
26
+
27
+ // make the timeline responsive default is true
28
+ // this means the timeline will update on resize
29
+ responsive?: boolean;
30
+
31
+ // ease
32
+ ease?: (t: number) => number;
33
+
34
+ // smoothSeek
35
+ smoothSeek?: SmoothSeekValue;
36
+
37
+ // repeat
38
+ // alternate
39
+ // reversed
40
+
41
+ // other properties
42
+ [key: string]: any;
43
+ };
44
+
45
+ export type Offset = number | string | Stagger<number | string>;
46
+
17
47
  export default class PublicTimeline {
48
+ /**
49
+ * @ignore
50
+ */
18
51
  _defaults: Record<string, any>;
19
52
  private _responsive: boolean;
20
53
 
54
+ /**
55
+ * @ignore
56
+ */
21
57
  _inner: Timeline;
22
58
 
23
59
  private _events: Events;
60
+ private _triggeredStart: boolean;
24
61
 
25
62
  private _state: number;
26
63
  private _renderedOnce: boolean;
27
64
  private _runningTicker: any;
28
65
  private _responsiveBlocks: { responsive: () => void }[];
29
66
  private _responsiveEvent: any;
67
+ private _smoothSeek: SmoothSeek | null;
68
+ private _seekTo: number;
30
69
 
31
- constructor(props: Record<string, any> = {}) {
70
+ constructor(props: TimelineProps = {}) {
32
71
  this._defaults = takeProp(props, 'defaults', {});
33
72
  this._responsive = takeProp(props, 'responsive', true);
34
73
 
@@ -37,10 +76,16 @@ export default class PublicTimeline {
37
76
  if ('duration' in props)
38
77
  throw new Error('a timeline does not accept a duration');
39
78
 
79
+ this._smoothSeek = parseSmoothSeek(
80
+ takeProp<SmoothSeekValue>(props, 'smoothSeek', undefined),
81
+ );
82
+ this._seekTo = 0;
83
+
40
84
  this._inner = new Timeline(props);
41
85
 
42
86
  // 'start', 'end'
43
87
  this._events = new Events();
88
+ this._triggeredStart = false;
44
89
 
45
90
  this._state = STATE_PAUSED;
46
91
  this._renderedOnce = false;
@@ -64,9 +109,10 @@ export default class PublicTimeline {
64
109
 
65
110
  /**
66
111
  * Set's properties
112
+ *
67
113
  * offset can be staggered, a number, a label or a string `+=10`
68
114
  */
69
- set(targets: any, props: Record<string, any>, offset = null) {
115
+ set(targets: Targets, props: Record<string, any>, offset?: Offset): this {
70
116
  // for the moment let's just add as usual but set the duration to 0
71
117
  return this.add(targets, { ...props, duration: 0 }, offset);
72
118
  }
@@ -76,18 +122,18 @@ export default class PublicTimeline {
76
122
  *
77
123
  * offset can be staggered, a number, a label or a string `+=10`
78
124
  */
79
- add(targets: any, props: Record<string, any>, offset = null) {
125
+ add(targets: Targets, props: Record<string, any>, offset?: Offset): this {
80
126
  timelineAdd(this, targets, props, offset);
81
127
 
82
128
  return this;
83
129
  }
84
130
 
85
131
  /**
86
- * Adds a label at to the current nOffse
132
+ * Adds a label at to the current nOffset
87
133
  *
88
134
  * This label can then be used in offsets
89
135
  */
90
- label(label: string, offset: any = null) {
136
+ label(label: string, offset: any = null): this {
91
137
  this._inner.label(label, offset);
92
138
 
93
139
  return this;
@@ -99,7 +145,11 @@ export default class PublicTimeline {
99
145
  * fn: (timeline)
100
146
  */
101
147
  // todo probably tl should be an interface
102
- nest(fn: (tl: NestedTimeline) => void, opts = {}, offset: any = null) {
148
+ nest(
149
+ fn: (tl: NestedTimeline) => void,
150
+ opts = {},
151
+ offset: any = null,
152
+ ): this {
103
153
  const tl = new NestedTimeline(opts);
104
154
 
105
155
  fn(tl);
@@ -113,7 +163,7 @@ export default class PublicTimeline {
113
163
  * Adds a responsive function call which get's called before the responsive
114
164
  * functions in properties
115
165
  */
116
- addResponsive(responsive: Responsive | Responsive[]) {
166
+ addResponsive(responsive: Responsive | Responsive[]): this {
117
167
  if (!this._responsiveEvent)
118
168
  throw new Error('this timeline is not responsive');
119
169
 
@@ -133,7 +183,7 @@ export default class PublicTimeline {
133
183
  /**
134
184
  * Starts to play the timeline if it hasn't started
135
185
  */
136
- play() {
186
+ play(): this {
137
187
  if (this._state === STATE_PLAYING) return this;
138
188
 
139
189
  this._state = STATE_PLAYING;
@@ -160,13 +210,14 @@ export default class PublicTimeline {
160
210
  seekMs(ms: number) {
161
211
  this._inner.init();
162
212
 
163
- this._inner.seekMs(ms);
164
-
165
- if (this._state !== STATE_PLAYING) this._state = STATE_RENDER_ONCE;
166
-
167
- this._startTicker();
213
+ this.seek(this._inner.timing.normalizeMs(ms));
168
214
  }
169
215
 
216
+ // todo maybe we should have two functions
217
+ // seek
218
+ // and setPosition
219
+ // seek would include reverse but setPosition would not
220
+
170
221
  /**
171
222
  * Seeks to a normalized position in the timeline
172
223
  *
@@ -175,19 +226,37 @@ export default class PublicTimeline {
175
226
  seek(pos: number) {
176
227
  this._inner.init();
177
228
 
178
- this._inner.seek(pos);
229
+ if (this._smoothSeek) {
230
+ this._smoothSeek.update(this._inner.timing.positionLinear(), pos);
231
+
232
+ if (this._state !== STATE_PLAYING) this._state = STATE_SEEK;
233
+ } else {
234
+ // this._inner.seek(pos);
235
+ this._seekTo = pos;
179
236
 
180
- if (this._state !== STATE_PLAYING) this._state = STATE_RENDER_ONCE;
237
+ if (this._state !== STATE_PLAYING) this._state = STATE_RENDER_ONCE;
238
+ }
181
239
 
182
240
  this._startTicker();
183
241
  }
184
242
 
243
+ /**
244
+ * Returns the position of a label
245
+ */
246
+ labelPosition(label: string): number {
247
+ this._inner.init();
248
+
249
+ return this._inner.labelPosition(label);
250
+ }
251
+
185
252
  // seek in Range (useful for scroll timelines)
186
253
  // seek(startOffset, endOffset, pos)
187
254
 
188
255
  /**
189
256
  * Resets the current timeline to the start
190
257
  * without changing anything
258
+ *
259
+ * this operation is not smooth use seek 0 if you wan't that
191
260
  */
192
261
  reset() {
193
262
  this._inner.seek(0);
@@ -217,7 +286,7 @@ export default class PublicTimeline {
217
286
  /**
218
287
  * Returns wether the timeline is set to reversed
219
288
  */
220
- isReversed() {
289
+ isReversed(): boolean {
221
290
  return this._inner.timing.reversed;
222
291
  }
223
292
 
@@ -234,6 +303,8 @@ export default class PublicTimeline {
234
303
  */
235
304
  reverse() {
236
305
  this._inner.timing.reverse();
306
+
307
+ // todo does this work with smooth seek?
237
308
  }
238
309
 
239
310
  /**
@@ -248,12 +319,12 @@ export default class PublicTimeline {
248
319
  * Does not get executed during seeking
249
320
  *
250
321
  */
251
- on(event: string, fn: (...args: any[]) => void) {
322
+ on(event: string, fn: (...args: any[]) => void): () => void {
252
323
  return this._events.add(event, fn);
253
324
  }
254
325
 
255
326
  // not working
256
- onPromise(event: string) {
327
+ onPromise(event: string): Promise<any> {
257
328
  return this._events.wait(event);
258
329
  }
259
330
 
@@ -270,57 +341,67 @@ export default class PublicTimeline {
270
341
  this._inner = null;
271
342
  }
272
343
 
344
+ _maybeTriggerEndEvent() {
345
+ if (this._state !== STATE_PLAYING) return;
346
+
347
+ this._events.trigger('end');
348
+ this._triggeredStart = false;
349
+ }
350
+
351
+ /**
352
+ * @ignore
353
+ */
273
354
  _startTicker() {
274
355
  if (this._runningTicker) return;
275
356
 
276
357
  this._inner.init();
277
358
 
359
+ const timingEnded = () => this._inner.timing.state >= STATE_ENDED;
360
+ const smoothSeekEnded = () =>
361
+ !this._smoothSeek || this._smoothSeek.state >= STATE_ENDED;
362
+
278
363
  this._runningTicker = this._inner.ticker.add(change => {
279
- if (this._inner.timing.state >= STATE_ENDED) {
280
- if (!this._renderedOnce) {
281
- this._renderedOnce = true;
282
- this._inner.render();
364
+ if (!this._triggeredStart) {
365
+ // todo check that we are at the start
366
+ if (this._inner.timing.state <= STATE_BEFORE) {
367
+ this._events.trigger('start');
368
+ this._triggeredStart = true;
283
369
  }
284
-
285
- if (this._state === STATE_PLAYING) this._events.trigger('end');
286
-
287
- this._state = STATE_PAUSED;
288
- this._stopTicker();
289
- return;
290
370
  }
291
371
 
292
- // if (this._inner.timing.state <= STATE_START) {
293
- // this._events.trigger('start');
294
- // }
295
-
296
- // if (this._inner.timing.state >= STATE_ENDED) {
297
- // this._stopTicker();
298
- // this._events.trigger('end');
299
- // return;
300
- // }
301
-
302
- if (this._state === STATE_PLAYING) this._inner.advance(change);
303
-
304
- // todo when we add smooth seeks we need to update this
372
+ const allowSmoothSeek =
373
+ this._state === STATE_PLAYING || this._state === STATE_SEEK;
374
+ if (
375
+ allowSmoothSeek &&
376
+ this._smoothSeek &&
377
+ this._smoothSeek.state < STATE_ENDED
378
+ ) {
379
+ this._smoothSeek.advance(change);
380
+ this._inner.seek(this._smoothSeek.value);
381
+ } else if (this._state === STATE_RENDER_ONCE) {
382
+ this._inner.seek(this._seekTo);
383
+ } else if (this._state === STATE_PLAYING) {
384
+ this._inner.advance(change);
385
+ }
305
386
 
306
387
  this._inner.render();
307
388
 
308
- if (this._inner.timing.state >= STATE_ENDED) {
309
- if (this._state === STATE_PLAYING) this._events.trigger('end');
389
+ // we rendered once let's stop
390
+ const renderOnce = this._state === STATE_RENDER_ONCE;
310
391
 
311
- this._state = STATE_PAUSED;
312
- this._stopTicker();
313
- return;
314
- }
392
+ if (renderOnce || (timingEnded() && smoothSeekEnded())) {
393
+ this._maybeTriggerEndEvent();
315
394
 
316
- // we rendered once let's stop
317
- if (this._state === STATE_RENDER_ONCE) {
318
395
  this._state = STATE_PAUSED;
319
396
  this._stopTicker();
397
+ return;
320
398
  }
321
399
  });
322
400
  }
323
401
 
402
+ /**
403
+ * @ignore
404
+ */
324
405
  _stopTicker() {
325
406
  if (!this._runningTicker) return;
326
407
 
@@ -328,6 +409,9 @@ export default class PublicTimeline {
328
409
  this._runningTicker = null;
329
410
  }
330
411
 
412
+ /**
413
+ * @ignore
414
+ */
331
415
  _onResponsive(
332
416
  a: { width: number; height: number },
333
417
  b: { remove: () => void },
@@ -365,8 +449,64 @@ export function timelineAdd(
365
449
  nProps[prop] = callStagger(nProps[prop], i, targets.length);
366
450
  }
367
451
 
368
- const nOffset = callStagger(offset, i);
452
+ const nOffset = callStagger(offset, i, targets.length);
369
453
 
370
454
  tl._inner.add(target, nProps, nOffset, i);
371
455
  }
372
456
  }
457
+
458
+ export type SmoothSeekValue =
459
+ | number
460
+ | undefined
461
+ | { duration: number; ease?: (t: number) => number };
462
+
463
+ /**
464
+ * Smooth seek
465
+ *
466
+ * can either just be a number (duration) or an object { duration, ease }
467
+ */
468
+ function parseSmoothSeek(smoothSeek: SmoothSeekValue): SmoothSeek | null {
469
+ if (!smoothSeek) return null;
470
+
471
+ if (typeof smoothSeek === 'number') {
472
+ return new SmoothSeek({
473
+ duration: smoothSeek,
474
+ });
475
+ }
476
+
477
+ return new SmoothSeek({
478
+ duration: smoothSeek.duration,
479
+ ease: smoothSeek?.ease,
480
+ });
481
+ }
482
+
483
+ class SmoothSeek {
484
+ timing: Timing;
485
+ from: number;
486
+ to: number;
487
+
488
+ constructor(timing: TimingProps) {
489
+ this.timing = new Timing(timing);
490
+ this.timing.seek(1);
491
+ this.from = 0;
492
+ this.to = 0;
493
+ }
494
+
495
+ update(from: number, to: number) {
496
+ this.from = from;
497
+ this.to = to;
498
+ this.timing.seek(0);
499
+ }
500
+
501
+ advance(change: number) {
502
+ this.timing.advance(change);
503
+ }
504
+
505
+ get value(): number {
506
+ return this.from + (this.to - this.from) * this.timing.position;
507
+ }
508
+
509
+ get state(): number {
510
+ return this.timing.state;
511
+ }
512
+ }
@@ -1,5 +1,5 @@
1
- import { newTarget } from '../target/Target';
2
- import Ticker, { Callback } from './Ticker';
1
+ import { newTarget } from '../target/Target.js';
2
+ import Ticker, { Callback } from './Ticker.js';
3
3
 
4
4
  /**
5
5
  * The ticker is the main driver for all animations