chnobli 0.1.2 → 0.1.3

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.
@@ -0,0 +1,234 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import TestTicker from '../timing/testticker.js';
3
+ import { animate, timeline } from '../chnobli.js';
4
+ import { el } from '../target/testdomnode.js';
5
+
6
+ describe('timeline', () => {
7
+ it('empty timeline', () => {
8
+ const ticker = new TestTicker;
9
+
10
+ const tl = timeline();
11
+ tl.play();
12
+ const finished = ticker.run();
13
+ expect(finished).toBe(true);
14
+ });
15
+
16
+ it('single timeline', () => {
17
+ const ticker = new TestTicker;
18
+
19
+ const tl = timeline();
20
+ const target = el();
21
+ tl.add(target, {
22
+ x: 10,
23
+ duration: 10
24
+ });
25
+ tl.play();
26
+
27
+ ticker.run(0);
28
+ expect(target.style.transform)
29
+ .toBe('translate3d(0.000px,0.000px,0.000px)');
30
+
31
+ ticker.run();
32
+ expect(target.style.transform)
33
+ .toBe('translate3d(10.000px,0.000px,0.000px)');
34
+
35
+ tl.reverse();
36
+ tl.play();
37
+ ticker.run();
38
+ expect(target.style.transform).toBe('');
39
+ });
40
+
41
+ it('timeline set', () => {
42
+ const ticker = new TestTicker;
43
+
44
+ const target = el();
45
+ const tl = timeline()
46
+ .set(target, {
47
+ x: 10
48
+ });
49
+ tl.play();
50
+
51
+ ticker.run(0);
52
+ expect(target.style.transform)
53
+ .toBe('translate3d(10.000px,0.000px,0.000px)');
54
+
55
+ ticker.run();
56
+ expect(target.style.transform)
57
+ .toBe('translate3d(10.000px,0.000px,0.000px)');
58
+
59
+ tl.reverse();
60
+ tl.play();
61
+ ticker.run();
62
+ expect(target.style.transform)
63
+ .toBe('translate3d(10.000px,0.000px,0.000px)');
64
+ });
65
+
66
+ it('offsetTimeline timeline', () => {
67
+ const ticker = new TestTicker;
68
+
69
+ const tl = timeline();
70
+ const target = el();
71
+ tl.add(target, {
72
+ x: 10,
73
+ duration: 10
74
+ });
75
+ tl.add(target, {
76
+ x: 20,
77
+ duration: 10
78
+ })
79
+ tl.play();
80
+
81
+ ticker.run(10);
82
+ expect(target.style.transform)
83
+ .toBe('translate3d(10.000px,0.000px,0.000px)');
84
+ ticker.run(1);
85
+ expect(target.style.transform)
86
+ .toBe('translate3d(11.000px,0.000px,0.000px)');
87
+
88
+ ticker.run();
89
+ expect(target.style.transform)
90
+ .toBe('translate3d(20.000px,0.000px,0.000px)');
91
+ });
92
+
93
+ it('timeline seeking', () => {
94
+ const ticker = new TestTicker;
95
+
96
+ const tl = timeline();
97
+ const target = el();
98
+ tl.add(target, {
99
+ x: 10,
100
+ duration: 10
101
+ });
102
+ tl.add(target, {
103
+ x: 20,
104
+ duration: 10
105
+ })
106
+
107
+ tl.seekMs(10);
108
+ ticker.run();
109
+ expect(target.style.transform)
110
+ .toBe('translate3d(10.000px,0.000px,0.000px)');
111
+
112
+ tl.seekMs(11);
113
+ ticker.run();
114
+ expect(target.style.transform)
115
+ .toBe('translate3d(11.000px,0.000px,0.000px)');
116
+
117
+ tl.seekMs(20);
118
+ ticker.run();
119
+ expect(target.style.transform)
120
+ .toBe('translate3d(20.000px,0.000px,0.000px)');
121
+
122
+ tl.seekMs(8);
123
+ ticker.run();
124
+ expect(target.style.transform)
125
+ .toBe('translate3d(8.000px,0.000px,0.000px)');
126
+ });
127
+
128
+ it('seeking after', () => {
129
+ const ticker = new TestTicker;
130
+
131
+ const target = el();
132
+ const ani = animate(target, {
133
+ autoplay: false,
134
+ duration: 10,
135
+ x: 10
136
+ });
137
+ ani.seek(2);
138
+
139
+ ticker.run();
140
+ expect(target.style.transform)
141
+ .toBe('translate3d(10.000px,0.000px,0.000px)');
142
+ });
143
+
144
+ it('timeline controls', () => {
145
+ const ticker = new TestTicker;
146
+
147
+ const tl = timeline();
148
+ const target = el();
149
+ tl.add(target, {
150
+ x: 10,
151
+ duration: 10
152
+ });
153
+ tl.add(target, {
154
+ x: 20,
155
+ duration: 10
156
+ })
157
+
158
+ tl.seekMs(10);
159
+ ticker.run();
160
+ expect(target.style.transform)
161
+ .toBe('translate3d(10.000px,0.000px,0.000px)');
162
+
163
+ tl.play();
164
+ ticker.run();
165
+ expect(target.style.transform)
166
+ .toBe('translate3d(20.000px,0.000px,0.000px)');
167
+
168
+ tl.reset();
169
+ tl.play();
170
+ ticker.run(10);
171
+ expect(target.style.transform)
172
+ .toBe('translate3d(10.000px,0.000px,0.000px)');
173
+
174
+ tl.reverse();
175
+ ticker.run(5);
176
+ expect(target.style.transform)
177
+ .toBe('translate3d(5.000px,0.000px,0.000px)');
178
+
179
+ tl.reverse();
180
+ ticker.run();
181
+ expect(target.style.transform)
182
+ .toBe('translate3d(20.000px,0.000px,0.000px)');
183
+
184
+ tl.reverse();
185
+ tl.play();
186
+ ticker.run();
187
+ expect(target.style.transform).toBe('');
188
+ });
189
+
190
+ it('timeline events', () => {
191
+ const ticker = new TestTicker;
192
+
193
+ const target = el();
194
+ const tl = timeline()
195
+ .add(target, {
196
+ x: 50,
197
+ duration: 10
198
+ })
199
+ .add(target, {
200
+ y: 50,
201
+ duration: 10
202
+ });
203
+
204
+ let endCounter = 0;
205
+ tl.on('end', () => endCounter += 1);
206
+
207
+ tl.play();
208
+ ticker.run(5);
209
+ expect(endCounter).toBe(0);
210
+
211
+ ticker.run();
212
+ expect(endCounter).toBe(1);
213
+
214
+ tl.play();
215
+ ticker.run();
216
+ // not sure this is the behaviour we wan't
217
+ expect(endCounter).toBe(2);
218
+
219
+ tl.reverse();
220
+ ticker.run();
221
+ expect(endCounter).toBe(2);
222
+ expect(target.style.transform)
223
+ .toBe('translate3d(50.000px,50.000px,0.000px)');
224
+
225
+ tl.play();
226
+ ticker.run();
227
+ expect(endCounter).toBe(3);
228
+ expect(target.style.transform).toBe('');
229
+
230
+ tl.play();
231
+ ticker.run();
232
+ expect(endCounter).toBe(4);
233
+ });
234
+ });
@@ -0,0 +1,270 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import Timing, {
3
+ STATE_BEFORE, STATE_START, STATE_RUNNING, STATE_ENDED, STATE_AFTER
4
+ } from '../timing/timing.js';
5
+
6
+ describe('timing', () => {
7
+ it('zero duration', () => {
8
+ // if duration is zero the position is always 1
9
+ // and the state is either BEFORE or AFTER
10
+ const timing = new Timing({
11
+ duration: 0
12
+ });
13
+ expect(timing.duration).toBe(0);
14
+ expect(timing.state).toBe(STATE_BEFORE);
15
+
16
+ timing.seek(-1);
17
+ expect(timing.position).toBe(1);
18
+ expect(timing.state).toBe(STATE_BEFORE);
19
+
20
+ timing.seek(0);
21
+ expect(timing.position).toBe(1);
22
+ expect(timing.state).toBe(STATE_AFTER);
23
+
24
+ timing.seek(.5);
25
+ expect(timing.position).toBe(1);
26
+ expect(timing.state).toBe(STATE_AFTER);
27
+
28
+ timing.seek(1);
29
+ expect(timing.position).toBe(1);
30
+ expect(timing.state).toBe(STATE_AFTER);
31
+
32
+ timing.seek(2);
33
+ expect(timing.position).toBe(1);
34
+ expect(timing.state).toBe(STATE_AFTER);
35
+
36
+ timing.seekMs(-1);
37
+ expect(timing.position).toBe(1);
38
+ expect(timing.state).toBe(STATE_BEFORE);
39
+
40
+ timing.seekMs(0);
41
+ expect(timing.position).toBe(1);
42
+ expect(timing.state).toBe(STATE_AFTER);
43
+
44
+ timing.seekMs(.5);
45
+ expect(timing.position).toBe(1);
46
+ expect(timing.state).toBe(STATE_AFTER);
47
+
48
+ timing.seekMs(1);
49
+ expect(timing.position).toBe(1);
50
+ expect(timing.state).toBe(STATE_AFTER);
51
+ });
52
+
53
+ it('short timing', () => {
54
+ const timing = new Timing({
55
+ duration: 1
56
+ });
57
+ expect(timing.duration).toBe(1);
58
+ expect(timing.state).toBe(STATE_BEFORE);
59
+
60
+ timing.seek(-1);
61
+ expect(timing.position).toBe(0);
62
+ expect(timing.state).toBe(STATE_BEFORE);
63
+
64
+ timing.seek(0);
65
+ expect(timing.position).toBe(0);
66
+ expect(timing.state).toBe(STATE_START);
67
+
68
+ timing.seek(.5);
69
+ expect(timing.position).toBe(.5);
70
+ expect(timing.state).toBe(STATE_RUNNING);
71
+
72
+ timing.seek(1);
73
+ expect(timing.position).toBe(1);
74
+ expect(timing.state).toBe(STATE_ENDED);
75
+
76
+ timing.seek(2);
77
+ expect(timing.position).toBe(1);
78
+ expect(timing.state).toBe(STATE_AFTER);
79
+
80
+ timing.seekMs(-1);
81
+ expect(timing.position).toBe(0);
82
+ expect(timing.state).toBe(STATE_BEFORE);
83
+
84
+ timing.seekMs(0);
85
+ expect(timing.position).toBe(0);
86
+ expect(timing.state).toBe(STATE_START);
87
+
88
+ timing.seekMs(.5);
89
+ expect(timing.position).toBe(.5);
90
+ expect(timing.state).toBe(STATE_RUNNING);
91
+
92
+ timing.seekMs(1);
93
+ expect(timing.position).toBe(1);
94
+ expect(timing.state).toBe(STATE_ENDED);
95
+
96
+ timing.seekMs(2);
97
+ expect(timing.position).toBe(1);
98
+ expect(timing.state).toBe(STATE_AFTER);
99
+ });
100
+
101
+ it('state management', () => {
102
+ const timing = new Timing({
103
+ duration: 100
104
+ });
105
+
106
+ timing.advance(20);
107
+ expect(timing.state).toBe(STATE_RUNNING);
108
+ expect(timing.position).toBe(.2);
109
+
110
+ timing.advance(20);
111
+ expect(timing.positionMs()).toBe(40);
112
+ expect(timing.state).toBe(STATE_RUNNING);
113
+ expect(timing.position).toBe(.4);
114
+
115
+ timing.advance(20);
116
+ expect(timing.state).toBe(STATE_RUNNING);
117
+ expect(Math.floor(timing.position * 10) / 10).toBe(.6);
118
+
119
+ timing.advance(20);
120
+ expect(timing.state).toBe(STATE_RUNNING);
121
+ expect(timing.position).toBe(.8);
122
+
123
+ timing.advance(20);
124
+ expect(timing.state).toBe(STATE_ENDED);
125
+ expect(timing.position).toBe(1);
126
+
127
+ timing.advance(20);
128
+ expect(timing.state).toBe(STATE_AFTER);
129
+ expect(timing.position).toBe(1);
130
+ });
131
+
132
+ it('reverse', () => {
133
+ const timing = new Timing({
134
+ duration: 100
135
+ });
136
+
137
+ expect(timing.state).toBe(STATE_BEFORE);
138
+ expect(timing.position).toBe(0);
139
+
140
+ // <
141
+ timing.reverse();
142
+ expect(timing.state).toBe(STATE_AFTER);
143
+ expect(timing.position).toBe(0);
144
+
145
+ // >
146
+ timing.reverse();
147
+ expect(timing.state).toBe(STATE_BEFORE);
148
+ expect(timing.position).toBe(0);
149
+
150
+ // >
151
+ timing.advance(25);
152
+ expect(timing.state).toBe(STATE_RUNNING);
153
+ expect(timing.position).toBe(0.25);
154
+
155
+ // <
156
+ timing.reverse();
157
+ expect(timing.state).toBe(STATE_RUNNING);
158
+ expect(timing.position).toBe(0.25);
159
+
160
+ // <
161
+ timing.advance(24);
162
+ expect(timing.state).toBe(STATE_RUNNING);
163
+ expect(timing.position.toFixed(3)).toBe('0.010');
164
+
165
+ // <
166
+ timing.advance(1);
167
+ expect(timing.state).toBe(STATE_ENDED);
168
+ expect(timing.position).toBe(0);
169
+
170
+ // >
171
+ timing.reverse();
172
+ expect(timing.state).toBe(STATE_START);
173
+ expect(timing.position).toBe(0);
174
+
175
+ // ><
176
+ timing.seek(0.75);
177
+ timing.reverse();
178
+ expect(timing.position).toBe(0.75);
179
+
180
+ // <
181
+ timing.advance(10);
182
+ expect(timing.position).toBe(0.65);
183
+
184
+
185
+ const timing2 = new Timing({
186
+ duration: 100
187
+ });
188
+
189
+ timing2.advance(100);
190
+ expect(timing2.state).toBe(STATE_ENDED);
191
+ expect(timing2.position).toBe(1);
192
+
193
+ timing2.reverse();
194
+ expect(timing2.state).toBe(STATE_START);
195
+ expect(timing2.position).toBe(1);
196
+
197
+ timing2.seek(-1);
198
+ expect(timing2.state).toBe(STATE_BEFORE);
199
+ expect(timing2.position).toBe(1);
200
+
201
+ timing2.seek(.25);
202
+ expect(timing2.state).toBe(STATE_RUNNING);
203
+ expect(timing2.position).toBe(.75);
204
+ });
205
+
206
+ it('repeat', () => {
207
+ const timing = new Timing({
208
+ duration: 100,
209
+ repeat: -1
210
+ });
211
+
212
+ // >
213
+ timing.advance(25);
214
+ expect(timing.state).toBe(STATE_RUNNING);
215
+ expect(timing.position).toBe(0.25);
216
+
217
+ // ><
218
+ timing.advance(100);
219
+ expect(timing.position).toBe(0.75);
220
+
221
+ // <
222
+ timing.advance(50);
223
+ expect(timing.position).toBe(0.25);
224
+
225
+ // <>
226
+ timing.advance(50);
227
+ expect(timing.position).toBe(0.25);
228
+
229
+ // >
230
+ timing.advance(50);
231
+ expect(timing.position).toBe(0.75);
232
+
233
+ // <
234
+ timing.reverse();
235
+ expect(timing.position).toBe(0.75);
236
+
237
+ timing.advance(50);
238
+ expect(timing.position).toBe(0.25);
239
+
240
+ // <>
241
+ timing.advance(50);
242
+ expect(timing.position).toBe(0.25);
243
+
244
+ // >
245
+ timing.setAlternate(false);
246
+ timing.advance(50);
247
+ expect(timing.position).toBe(0.75);
248
+
249
+ // >
250
+ timing.advance(50);
251
+ expect(timing.position).toBe(0.25);
252
+
253
+ // <
254
+ timing.reverse();
255
+ expect(timing.position).toBe(0.25);
256
+
257
+ // <
258
+ timing.advance(50);
259
+ expect(timing.position).toBe(0.75);
260
+
261
+ // <
262
+ timing.setAlternate(true);
263
+ timing.advance(50);
264
+ expect(timing.position).toBe(0.25);
265
+
266
+ // <>
267
+ timing.advance(50);
268
+ expect(timing.position).toBe(0.25);
269
+ });
270
+ });
@@ -0,0 +1,64 @@
1
+ import { describe, expect, it } from 'vitest';
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
+
8
+ describe('usecases', () => {
9
+ it('accordion', () => {
10
+ const ticker = new TestTicker;
11
+ const respEv = new TestResponsiveEvent;
12
+
13
+ const itm = el();
14
+ const ctn = el();
15
+ ctn.computedStyle.maxHeight = 'none';
16
+ ctn.scrollHeight = '100px';
17
+
18
+ const tl = timeline()
19
+ .set(itm, {
20
+ cls: 'open'
21
+ })
22
+ .add(ctn, {
23
+ maxHeight: responsive(el => el.scrollHeight),
24
+ duration: 100
25
+ });
26
+
27
+ tl.play();
28
+ ticker.run(1);
29
+ expect(ctn.style.maxHeight).toBe('1.000px');
30
+ expect(itm.classList.contains('open')).toBe(true);
31
+
32
+ // // on click
33
+ tl.play();
34
+ ticker.run(4);
35
+ expect(ctn.style.maxHeight).toBe('5.000px');
36
+ expect(itm.classList.contains('open')).toBe(true);
37
+
38
+ ticker.run();
39
+ expect(ctn.style.maxHeight).toBe('100.000px');
40
+ expect(itm.classList.contains('open')).toBe(true);
41
+
42
+ // now a resize comes
43
+ ctn.scrollHeight = '200px';
44
+ tl.update();
45
+ expect(ctn.style.maxHeight).toBe('200.000px');
46
+ expect(itm.classList.contains('open')).toBe(true);
47
+
48
+ // on click
49
+ tl.reverse();
50
+ tl.play();
51
+ ticker.run(12);
52
+ expect(ctn.style.maxHeight).toBe('176.000px');
53
+ expect(itm.classList.contains('open')).toBe(true);
54
+
55
+ ctn.scrollHeight = '150px';
56
+ respEv.resize(1000, 1000);
57
+ expect(ctn.style.maxHeight).toBe('132.000px');
58
+ expect(itm.classList.contains('open')).toBe(true);
59
+
60
+ ticker.run();
61
+ expect(ctn.style.maxHeight).toBe(undefined);
62
+ expect(itm.classList.contains('open')).toBe(false);
63
+ });
64
+ });
@@ -0,0 +1,162 @@
1
+ import { describe, expect, it } from 'vitest';
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, fromTo } from '../utils/utils.js';
6
+ import { el, getRootElement } from '../target/testdomnode.js';
7
+ import { timeout } from 'fire/util.js';
8
+
9
+ describe('values', () => {
10
+ it('rem unit', () => {
11
+ const ticker = new TestTicker;
12
+
13
+ const root = getRootElement();
14
+ root.computedStyle.fontSize = '13px';
15
+
16
+ const div = el();
17
+ const tl = timeline()
18
+ .add(div, {
19
+ width: '10rem',
20
+ duration: 5
21
+ })
22
+ .add(div, {
23
+ width: 20,
24
+ duration: 5
25
+ })
26
+ .play();
27
+
28
+ ticker.run(0);
29
+ expect(div.style.width).toBe('0.000rem');
30
+
31
+ ticker.run();
32
+ expect(div.style.width).toBe('20.000rem');
33
+ });
34
+
35
+ it('percent unit', () => {
36
+ const ticker = new TestTicker;
37
+
38
+ const div = el();
39
+ div.computedStyle.width = '10px';
40
+ const tl = timeline()
41
+ .add(div, {
42
+ x: '10%',
43
+ width: '50%',
44
+ duration: 10
45
+ })
46
+ .play();
47
+
48
+ ticker.run(0);
49
+ expect(div.style.transform).toBe('translate3d(0.000%,0.000px,0.000px)');
50
+ expect(div.style.width).toBe('100.000%');
51
+
52
+ ticker.run();
53
+ expect(div.style.transform).toBe('translate3d(10.000%,0.000px,0.000px)');
54
+ expect(div.style.width).toBe('50.000%');
55
+ });
56
+
57
+ it('multiple values', () => {
58
+ const ticker = new TestTicker;
59
+
60
+ const root = getRootElement();
61
+ root.computedStyle.fontSize = '10px';
62
+
63
+ const div = el();
64
+ div.computedStyle.padding = '5px';
65
+ const tl = timeline()
66
+ .add(div, {
67
+ padding: '10px 20rem',
68
+ duration: 10
69
+ })
70
+ .play();
71
+
72
+ ticker.run(0);
73
+ expect(div.style.padding).toBe('5.000px 0.500rem');
74
+
75
+ ticker.run();
76
+ expect(div.style.padding).toBe('10.000px 20.000rem');
77
+ });
78
+
79
+ it('display', () => {
80
+ const ticker = new TestTicker;
81
+
82
+ const div = el();
83
+ div.computedStyle.display = 'block';
84
+ const tl = timeline()
85
+ .add(div, {
86
+ display: 'none',
87
+ position: from('absolute'),
88
+ visibility: fromTo('hidden', 'visible'),
89
+ duration: 10
90
+ })
91
+ .play();
92
+
93
+ ticker.run(0);
94
+ expect(div.style.display).toBe(undefined);
95
+ expect(div.style.position).toBe('absolute');
96
+ expect(div.style.visibility).toBe('hidden');
97
+
98
+ ticker.run();
99
+ expect(div.style.display).toBe('none');
100
+ expect(div.style.position).toBe(undefined);
101
+ expect(div.style.visibility).toBe('visible');
102
+
103
+ tl.seek(-1);
104
+ ticker.run();
105
+ expect(div.style.display).toBe(undefined);
106
+ expect(div.style.position).toBe(undefined);
107
+ expect(div.style.visibility).toBe(undefined);
108
+ });
109
+
110
+ it('colors', () => {
111
+ const ticker = new TestTicker;
112
+ const div = el();
113
+ div.computedStyle.color = 'rgb(120, 130, 20)';
114
+
115
+ const tl = timeline()
116
+ .add(div, {
117
+ color: 'black',
118
+ backgroundColor: 'hsl(10, 80%, 40%)',
119
+ duration: 10
120
+ })
121
+ .play();
122
+
123
+ ticker.run(0);
124
+ expect(div.style.color).toBe('rgba(120, 130, 20, 1.000)');
125
+ expect(div.style.backgroundColor).toBe('rgba(255, 255, 255, 1.000)');
126
+
127
+ ticker.run(5);
128
+ expect(div.style.color).toBe('rgba(60, 65, 10, 1.000)');
129
+ expect(div.style.backgroundColor).toBe('rgba(220, 152, 138, 1.000)');
130
+
131
+ ticker.run();
132
+ expect(div.style.color).toBe('rgba(0, 0, 0, 1.000)');
133
+ expect(div.style.backgroundColor).toBe('rgba(184, 48, 20, 1.000)');
134
+ });
135
+
136
+ it('css-vars', () => {
137
+ const ticker = new TestTicker;
138
+ const div = el();
139
+ div.computedStyle['--color'] = 'rgb(120, 130, 20)';
140
+ div.computedStyle['--border'] = '20px';
141
+
142
+ const tl = timeline()
143
+ .add(div, {
144
+ '--color': 'black',
145
+ '--border': '1px 20px',
146
+ duration: 10
147
+ })
148
+ .play();
149
+
150
+ ticker.run(0);
151
+ expect(div.style['--color']).toBe('rgba(120, 130, 20, 1.000)');
152
+ expect(div.style['--border']).toBe('20.000px 20.000px');
153
+
154
+ ticker.run(5);
155
+ expect(div.style['--color']).toBe('rgba(60, 65, 10, 1.000)');
156
+ expect(div.style['--border']).toBe('10.500px 20.000px');
157
+
158
+ ticker.run();
159
+ expect(div.style['--color']).toBe('rgba(0, 0, 0, 1.000)');
160
+ expect(div.style['--border']).toBe('1.000px 20.000px');
161
+ });
162
+ });