chnobli 0.1.1 → 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.
package/.eslintignore ADDED
@@ -0,0 +1 @@
1
+ *.test.js
@@ -17,5 +17,18 @@ jobs:
17
17
  - name: Install dependencies
18
18
  run: npm ci
19
19
 
20
- - name: Check types
20
+ - name: Lint
21
21
  run: npm run lint
22
+
23
+ test:
24
+ runs-on: ubuntu-latest
25
+
26
+ steps:
27
+ - name: Checkout code
28
+ uses: actions/checkout@v3
29
+
30
+ - name: Install dependencies
31
+ run: npm ci
32
+
33
+ - name: Run tests
34
+ run: npm run test:once
package/LICENSE.md CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 Sören Meier
3
+ Copyright (c) 2024 Sören Meier
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/docs/INDEX.md ADDED
@@ -0,0 +1,15 @@
1
+ # Docs
2
+
3
+
4
+ ## Property
5
+
6
+ ### Value
7
+ A property can be one of the following values:
8
+
9
+ **string** which contains a unit for example `10px`
10
+ **number** a number which presents the default unit of that field
11
+ **from** a return value from the `utils::from` function
12
+ **to** a return value from the `utils::to` function
13
+ **fromTo** a return value from the `utils::fromTo` function
14
+ **reactive** a return value from the `utils::reactive` function
15
+ **function** a function `(t: 0-1) -> value` which returns a value (string or number)
package/jsdoc.conf.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "excludePattern": "(^|\\/|\\\\)_"
6
6
  },
7
7
  "opts": {
8
- "destination": "./docs/",
8
+ "destination": "./auto-docs/",
9
9
  "recurse": true,
10
10
  "verbose": true
11
11
  }
package/package.json CHANGED
@@ -1,12 +1,14 @@
1
1
  {
2
2
  "name": "chnobli",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "author": "Sören Meier <info@soerenmeier.ch>",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "docs": "jsdoc -c jsdoc.conf.json",
8
8
  "check": "tsc",
9
- "lint": "eslint ./src"
9
+ "lint": "eslint ./src",
10
+ "test": "node --expose-gc ./node_modules/.bin/vitest",
11
+ "test:once": "node --expose-gc ./node_modules/.bin/vitest run"
10
12
  },
11
13
  "repository": {
12
14
  "type": "git",
@@ -21,7 +23,8 @@
21
23
  "devDependencies": {
22
24
  "eslint": "^8.45.0",
23
25
  "jsdoc": "^4.0.2",
24
- "typescript": "^5.1.6"
26
+ "typescript": "^5.1.6",
27
+ "vitest": "^1.1.3"
25
28
  },
26
29
  "dependencies": {
27
30
  "bezier-easing": "^2.1.0",
@@ -1,7 +1,4 @@
1
- import { takeProp } from '../utils/internal.js';
2
- import Value from '../utils/value.js';
3
- // import Ease from '../easing/ease.js';
4
- import Timing, {
1
+ import {
5
2
  newTiming, STATE_BEFORE, STATE_AFTER
6
3
  } from '../timing/timing.js';
7
4
 
@@ -18,7 +15,7 @@ export default class Animation {
18
15
  constructor(target, ticker, props = {}) {
19
16
  this.timing = newTiming(props);
20
17
  this._ticker = ticker;
21
- this.target = ticker._targets.register(target);
18
+ this.target = ticker.registerTarget(target);
22
19
 
23
20
  this._prevTimingState = this.timing.state;
24
21
  this._props = [];
@@ -42,6 +39,11 @@ export default class Animation {
42
39
  this.timing.advance(change);
43
40
  }
44
41
 
42
+ seekMs(ms) {
43
+ this._prevTimingState = this.timing.state;
44
+ this.timing.seekMs(ms);
45
+ }
46
+
45
47
  seek(pos) {
46
48
  this._prevTimingState = this.timing.state;
47
49
  this.timing.seek(pos);
@@ -55,8 +57,8 @@ export default class Animation {
55
57
  return this.timing.duration;
56
58
  }
57
59
 
58
- init() {
59
- if (this._initialized)
60
+ init(reset = false) {
61
+ if (this._initialized && !reset)
60
62
  return;
61
63
  this._initialized = true;
62
64
 
@@ -88,6 +90,20 @@ export default class Animation {
88
90
  prop.render(pos, this.target);
89
91
  }
90
92
  }
93
+
94
+ destroy() {
95
+ for (const prop of this._props) {
96
+ prop.restoreBefore(this.target);
97
+ }
98
+
99
+ this._ticker.unregisterTarget(this.target.target);
100
+ }
101
+ }
102
+
103
+ function maybeResponsiveValue(prop, val) {
104
+ if (typeof val === 'object' && 'responsive' in val)
105
+ return val.responsive;
106
+ return prop.parseValue(val);
91
107
  }
92
108
 
93
109
  class PropertyAnimation {
@@ -95,23 +111,32 @@ class PropertyAnimation {
95
111
  this.prop = newProperty(prop, animation.target.type());
96
112
  // we will get the from the targets
97
113
 
114
+ this.staticValueFn = false;
98
115
  this.valueFn = null;
99
116
 
117
+ this.iniResponsive = null;
100
118
  this.iniFrom = null;
101
119
  this.iniTo = null;
102
120
 
103
- this.from = null;
104
- this.to = null;
105
-
106
121
  if (typeof value === 'object') {
107
122
  if ('from' in value)
108
- this.iniFrom = this.prop.parseValue(value.from);
123
+ this.iniFrom = maybeResponsiveValue(this.prop, value.from);
109
124
  if ('to' in value)
110
- this.iniTo = this.prop.parseValue(value.to);
125
+ this.iniTo = maybeResponsiveValue(this.prop, value.to);
111
126
 
112
- if (!this.iniFrom && !this.iniTo)
127
+ if ('responsive' in value)
128
+ this.iniResponsive = value.responsive;
129
+
130
+ if (!this.iniFrom && !this.iniTo && !this.iniResponsive)
113
131
  throw new Error('from or to expected');
114
132
  } else if (typeof value === 'function') {
133
+ if (!this.prop.allowsValueFn()) {
134
+ throw new Error(
135
+ 'prop ' + prop + ' does not allow value functions'
136
+ );
137
+ }
138
+
139
+ this.staticValueFn = true;
115
140
  this.valueFn = value;
116
141
  } else {
117
142
  this.iniTo = this.prop.parseValue(value);
@@ -120,22 +145,62 @@ class PropertyAnimation {
120
145
 
121
146
  // calculate from and to position
122
147
  init(target) {
123
- if (this.valueFn)
148
+ // there is nothing to initialize since on every render we call the
149
+ // value Fn
150
+ if (this.staticValueFn)
124
151
  return;
125
152
 
126
- this.from = this.iniFrom;
127
- if (!this.from)
128
- this.from = this.prop.getValue(target);
153
+ this.valueFn = null;
154
+ let from = null;
155
+ let to = null;
156
+
157
+ // init via responsive fn
158
+ if (this.iniResponsive) {
159
+ const value = this.iniResponsive(target.target);
160
+
161
+ if (typeof value === 'object') {
162
+ if ('from' in value)
163
+ from = this.prop.parseValue(value.from);
164
+ if ('to' in value)
165
+ to = this.prop.parseValue(value.to);
166
+
167
+ if (!from && !to)
168
+ throw new Error('from or to expected');
169
+ } else if (typeof value === 'function') {
170
+ if (!this.prop.allowsValueFn()) {
171
+ throw new Error(
172
+ `prop ${this.prop.name} does not allow value functions`
173
+ );
174
+ }
175
+
176
+ this.valueFn = value;
177
+ return;
178
+ } else {
179
+ to = this.prop.parseValue(value);
180
+ }
181
+ }
182
+
183
+ // init from
184
+ if (!from) {
185
+ if (typeof this.iniFrom === 'function')
186
+ from = this.prop.parseValue(this.iniFrom(target.target));
187
+ else
188
+ from = this.iniFrom;
189
+ }
129
190
 
130
- this.to = this.iniTo;
131
- if (!this.to)
132
- this.to = this.prop.getValue(target);
191
+ // init to
192
+ if (!to) {
193
+ if (typeof this.iniTo === 'function')
194
+ to = this.prop.parseValue(this.iniTo(target.target));
195
+ else
196
+ to = this.iniTo;
197
+ }
133
198
 
134
- if (this.to.unit !== this.from.unit)
135
- throw new Error(this.from.unit + ' != ' + this.to.unit);
199
+ this.prop.init(target, from, to);
136
200
  }
137
201
 
138
202
  restoreBefore(target) {
203
+ // todo this might not be enough
139
204
  this.prop.removeValue(target);
140
205
  }
141
206
 
@@ -145,9 +210,7 @@ class PropertyAnimation {
145
210
  return;
146
211
  }
147
212
 
148
- const dif = this.to.num - this.from.num;
149
-
150
- this.prop.setValue(target, this.from.cloneAdd(pos * dif));
213
+ this.prop.setValue(target, this.prop.interpolate(pos));
151
214
  }
152
215
  }
153
216