etro 0.8.0 → 0.8.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.
Files changed (97) hide show
  1. package/.github/workflows/nodejs.yml +3 -1
  2. package/.github/workflows/shipjs-trigger.yml +29 -0
  3. package/CHANGELOG.md +36 -13
  4. package/CODE_OF_CONDUCT.md +5 -5
  5. package/CONTRIBUTING.md +22 -72
  6. package/README.md +2 -2
  7. package/dist/effect/base.d.ts +14 -1
  8. package/dist/etro-cjs.js +189 -230
  9. package/dist/etro-iife.js +189 -230
  10. package/dist/layer/base.d.ts +13 -0
  11. package/eslint.conf.js +2 -1
  12. package/eslint.test-conf.js +1 -0
  13. package/examples/application/readme-screenshot.html +4 -8
  14. package/examples/application/video-player.html +3 -4
  15. package/examples/introduction/effects.html +23 -4
  16. package/karma.conf.js +4 -2
  17. package/package.json +8 -4
  18. package/scripts/gen-effect-samples.html +0 -3
  19. package/ship.config.js +80 -0
  20. package/src/effect/base.ts +29 -10
  21. package/src/effect/gaussian-blur.ts +10 -10
  22. package/src/effect/pixelate.ts +1 -2
  23. package/src/effect/shader.ts +18 -22
  24. package/src/effect/stack.ts +8 -4
  25. package/src/effect/transform.ts +13 -14
  26. package/src/event.ts +8 -14
  27. package/src/layer/audio-source.ts +16 -14
  28. package/src/layer/audio.ts +1 -2
  29. package/src/layer/base.ts +26 -7
  30. package/src/layer/visual.ts +11 -6
  31. package/src/movie.ts +70 -64
  32. package/src/util.ts +50 -57
  33. package/docs/effect.js.html +0 -1215
  34. package/docs/event.js.html +0 -145
  35. package/docs/index.html +0 -81
  36. package/docs/index.js.html +0 -92
  37. package/docs/layer.js.html +0 -888
  38. package/docs/module-effect-GaussianBlurComponent.html +0 -345
  39. package/docs/module-effect.Brightness.html +0 -339
  40. package/docs/module-effect.Channels.html +0 -319
  41. package/docs/module-effect.ChromaKey.html +0 -611
  42. package/docs/module-effect.Contrast.html +0 -339
  43. package/docs/module-effect.EllipticalMask.html +0 -200
  44. package/docs/module-effect.GaussianBlur.html +0 -202
  45. package/docs/module-effect.GaussianBlurHorizontal.html +0 -242
  46. package/docs/module-effect.GaussianBlurVertical.html +0 -242
  47. package/docs/module-effect.Pixelate.html +0 -330
  48. package/docs/module-effect.Shader.html +0 -1227
  49. package/docs/module-effect.Stack.html +0 -406
  50. package/docs/module-effect.Transform.Matrix.html +0 -193
  51. package/docs/module-effect.Transform.html +0 -1174
  52. package/docs/module-effect.html +0 -148
  53. package/docs/module-event.html +0 -473
  54. package/docs/module-index.html +0 -186
  55. package/docs/module-layer-Media.html +0 -1116
  56. package/docs/module-layer-MediaMixin.html +0 -164
  57. package/docs/module-layer.Audio.html +0 -1188
  58. package/docs/module-layer.Base.html +0 -629
  59. package/docs/module-layer.Image.html +0 -1421
  60. package/docs/module-layer.Text.html +0 -1731
  61. package/docs/module-layer.Video.html +0 -1938
  62. package/docs/module-layer.Visual.html +0 -1698
  63. package/docs/module-layer.html +0 -137
  64. package/docs/module-movie.html +0 -3118
  65. package/docs/module-util.Color.html +0 -702
  66. package/docs/module-util.Font.html +0 -395
  67. package/docs/module-util.html +0 -845
  68. package/docs/movie.js.html +0 -689
  69. package/docs/scripts/collapse.js +0 -20
  70. package/docs/scripts/linenumber.js +0 -25
  71. package/docs/scripts/nav.js +0 -12
  72. package/docs/scripts/polyfill.js +0 -4
  73. package/docs/scripts/prettify/Apache-License-2.0.txt +0 -202
  74. package/docs/scripts/prettify/lang-css.js +0 -2
  75. package/docs/scripts/prettify/prettify.js +0 -28
  76. package/docs/scripts/search.js +0 -83
  77. package/docs/styles/jsdoc.css +0 -671
  78. package/docs/styles/prettify.css +0 -79
  79. package/docs/util.js.html +0 -503
  80. package/spec/assets/effect/gaussian-blur-horizontal.png +0 -0
  81. package/spec/assets/effect/gaussian-blur-vertical.png +0 -0
  82. package/spec/assets/effect/grayscale.png +0 -0
  83. package/spec/assets/effect/original.png +0 -0
  84. package/spec/assets/effect/pixelate.png +0 -0
  85. package/spec/assets/effect/transform/multiply.png +0 -0
  86. package/spec/assets/effect/transform/rotate.png +0 -0
  87. package/spec/assets/effect/transform/scale-fraction.png +0 -0
  88. package/spec/assets/effect/transform/scale.png +0 -0
  89. package/spec/assets/effect/transform/translate-fraction.png +0 -0
  90. package/spec/assets/effect/transform/translate.png +0 -0
  91. package/spec/assets/layer/audio.wav +0 -0
  92. package/spec/assets/layer/image.jpg +0 -0
  93. package/spec/effect.spec.js +0 -421
  94. package/spec/event.spec.js +0 -39
  95. package/spec/layer.spec.js +0 -307
  96. package/spec/movie.spec.js +0 -346
  97. package/spec/util.spec.js +0 -294
package/src/util.ts CHANGED
@@ -15,9 +15,9 @@ import { Movie } from './movie'
15
15
  function getPropertyDescriptor (obj: unknown, name: string | number | symbol): PropertyDescriptor {
16
16
  do {
17
17
  const propDesc = Object.getOwnPropertyDescriptor(obj, name)
18
- if (propDesc) {
18
+ if (propDesc)
19
19
  return propDesc
20
- }
20
+
21
21
  obj = Object.getPrototypeOf(obj)
22
22
  } while (obj)
23
23
  return undefined
@@ -34,12 +34,10 @@ export function applyOptions (options: object, destObj: EtroObject): void { // e
34
34
  const defaultOptions = destObj.getDefaultOptions()
35
35
 
36
36
  // Validate; make sure `keys` doesn't have any extraneous items
37
- for (const option in options) {
37
+ for (const option in options)
38
38
  // eslint-disable-next-line no-prototype-builtins
39
- if (!defaultOptions.hasOwnProperty(option)) {
39
+ if (!defaultOptions.hasOwnProperty(option))
40
40
  throw new Error("Invalid option: '" + option + "'")
41
- }
42
- }
43
41
 
44
42
  // Merge options and defaultOptions
45
43
  options = { ...defaultOptions, ...options }
@@ -48,9 +46,8 @@ export function applyOptions (options: object, destObj: EtroObject): void { // e
48
46
  for (const option in options) {
49
47
  const propDesc = getPropertyDescriptor(destObj, option)
50
48
  // Update the property as long as the property has not been set (unless if it has a setter)
51
- if (!propDesc || propDesc.set) {
49
+ if (!propDesc || propDesc.set)
52
50
  destObj[option] = options[option]
53
- }
54
51
  }
55
52
  }
56
53
 
@@ -58,15 +55,15 @@ export function applyOptions (options: object, destObj: EtroObject): void { // e
58
55
  const valCache = new WeakMap()
59
56
  function cacheValue (element: EtroObject, path: string, value: unknown) {
60
57
  // Initiate movie cache
61
- if (!valCache.has(element.movie)) {
58
+ if (!valCache.has(element.movie))
62
59
  valCache.set(element.movie, new WeakMap())
63
- }
60
+
64
61
  const movieCache = valCache.get(element.movie)
65
62
 
66
63
  // Iniitate element cache
67
- if (!movieCache.has(element)) {
64
+ if (!movieCache.has(element))
68
65
  movieCache.set(element, {})
69
- }
66
+
70
67
  const elementCache = movieCache.get(element)
71
68
 
72
69
  // Cache the value
@@ -110,16 +107,16 @@ export class KeyFrame<T> {
110
107
  }
111
108
 
112
109
  evaluate (time: number): T {
113
- if (this.value.length === 0) {
110
+ if (this.value.length === 0)
114
111
  throw new Error('Empty keyframe')
115
- }
116
- if (time === undefined) {
112
+
113
+ if (time === undefined)
117
114
  throw new Error('|time| is undefined or null')
118
- }
115
+
119
116
  const firstTime: number = this.value[0][0] as number
120
- if (time < firstTime) {
117
+ if (time < firstTime)
121
118
  throw new Error('No keyframe point before |time|')
122
- }
119
+
123
120
  // I think reduce are slow to do per-frame (or more)?
124
121
  for (let i = 0; i < this.value.length; i++) {
125
122
  const startTime = this.value[i][0] as number
@@ -129,7 +126,7 @@ export class KeyFrame<T> {
129
126
  if (i + 1 < this.value.length) {
130
127
  const endTime = this.value[i + 1][0] as number
131
128
  const endValue = this.value[i + 1][1] as T
132
- if (startTime <= time && time < endTime) {
129
+ if (startTime <= time && time < endTime)
133
130
  // No need for endValue if it is flat interpolation
134
131
  // TODO: support custom interpolation for 'other' types?
135
132
  if (!(typeof startValue === 'number' || typeof endValue === 'object')) {
@@ -145,7 +142,6 @@ export class KeyFrame<T> {
145
142
  percentProgress, this.interpolationKeys
146
143
  ) as unknown as T
147
144
  }
148
- }
149
145
  } else {
150
146
  // Repeat last value forever
151
147
  return startValue
@@ -173,28 +169,27 @@ export type Dynamic<T> = T | KeyFrame<T> | ((element: EtroObject, time: number)
173
169
  // TODO: Is this function efficient?
174
170
  // TODO: Update doc @params to allow for keyframes
175
171
  export function val (element: EtroObject, path: string, time: number): any { // eslint-disable-line @typescript-eslint/no-explicit-any
176
- if (hasCachedValue(element, path)) {
172
+ if (hasCachedValue(element, path))
177
173
  return getCachedValue(element, path)
178
- }
179
174
 
180
175
  // Get property of element at path
181
176
  const pathParts = path.split('.')
182
177
  let property = element[pathParts.shift()]
183
- while (pathParts.length > 0) {
178
+ while (pathParts.length > 0)
184
179
  property = property[pathParts.shift()]
185
- }
180
+
186
181
  // Property filter function
187
182
  const process = element.propertyFilters[path]
188
183
 
189
184
  let value
190
- if (property instanceof KeyFrame) {
185
+ if (property instanceof KeyFrame)
191
186
  value = property.evaluate(time)
192
- } else if (typeof property === 'function') {
187
+ else if (typeof property === 'function')
193
188
  value = property(element, time) // TODO? add more args
194
- } else {
189
+ else
195
190
  // Simple value
196
191
  value = property
197
- }
192
+
198
193
  return cacheValue(element, path, process ? process.call(element, value) : value)
199
194
  }
200
195
 
@@ -207,18 +202,18 @@ export function val (element: EtroObject, path: string, time: number): any { //
207
202
  } */
208
203
 
209
204
  export function linearInterp (x1: number | object, x2: number | object, t: number, objectKeys?: string[]): number | object { // eslint-disable-line @typescript-eslint/ban-types
210
- if (typeof x1 !== typeof x2) {
205
+ if (typeof x1 !== typeof x2)
211
206
  throw new Error('Type mismatch')
212
- }
213
- if (typeof x1 !== 'number' && typeof x1 !== 'object') {
207
+
208
+ if (typeof x1 !== 'number' && typeof x1 !== 'object')
214
209
  // Flat interpolation (floor)
215
210
  return x1
216
- }
211
+
217
212
  if (typeof x1 === 'object') { // to work with objects (including arrays)
218
213
  // TODO: make this code DRY
219
- if (Object.getPrototypeOf(x1) !== Object.getPrototypeOf(x2)) {
214
+ if (Object.getPrototypeOf(x1) !== Object.getPrototypeOf(x2))
220
215
  throw new Error('Prototype mismatch')
221
- }
216
+
222
217
  // Preserve prototype of objects
223
218
  const int = Object.create(Object.getPrototypeOf(x1))
224
219
  // Take the intersection of properties
@@ -226,9 +221,9 @@ export function linearInterp (x1: number | object, x2: number | object, t: numbe
226
221
  for (let i = 0; i < keys.length; i++) {
227
222
  const key = keys[i]
228
223
  // eslint-disable-next-line no-prototype-builtins
229
- if (!x1.hasOwnProperty(key) || !x2.hasOwnProperty(key)) {
224
+ if (!x1.hasOwnProperty(key) || !x2.hasOwnProperty(key))
230
225
  continue
231
- }
226
+
232
227
  int[key] = linearInterp(x1[key], x2[key], t)
233
228
  }
234
229
  return int
@@ -237,17 +232,17 @@ export function linearInterp (x1: number | object, x2: number | object, t: numbe
237
232
  }
238
233
 
239
234
  export function cosineInterp (x1: number | object, x2: number | object, t: number, objectKeys?: string[]): number | object { // eslint-disable-line @typescript-eslint/ban-types
240
- if (typeof x1 !== typeof x2) {
235
+ if (typeof x1 !== typeof x2)
241
236
  throw new Error('Type mismatch')
242
- }
243
- if (typeof x1 !== 'number' && typeof x1 !== 'object') {
237
+
238
+ if (typeof x1 !== 'number' && typeof x1 !== 'object')
244
239
  // Flat interpolation (floor)
245
240
  return x1
246
- }
241
+
247
242
  if (typeof x1 === 'object' && typeof x2 === 'object') { // to work with objects (including arrays)
248
- if (Object.getPrototypeOf(x1) !== Object.getPrototypeOf(x2)) {
243
+ if (Object.getPrototypeOf(x1) !== Object.getPrototypeOf(x2))
249
244
  throw new Error('Prototype mismatch')
250
- }
245
+
251
246
  // Preserve prototype of objects
252
247
  const int = Object.create(Object.getPrototypeOf(x1))
253
248
  // Take the intersection of properties
@@ -255,9 +250,9 @@ export function cosineInterp (x1: number | object, x2: number | object, t: numbe
255
250
  for (let i = 0; i < keys.length; i++) {
256
251
  const key = keys[i]
257
252
  // eslint-disable-next-line no-prototype-builtins
258
- if (!x1.hasOwnProperty(key) || !x2.hasOwnProperty(key)) {
253
+ if (!x1.hasOwnProperty(key) || !x2.hasOwnProperty(key))
259
254
  continue
260
- }
255
+
261
256
  int[key] = cosineInterp(x1[key], x2[key], t)
262
257
  }
263
258
  return int
@@ -408,12 +403,11 @@ export function mapPixels (
408
403
  width = width || canvas.width
409
404
  height = height || canvas.height
410
405
  const frame = ctx.getImageData(x, y, width, height)
411
- for (let i = 0, l = frame.data.length; i < l; i += 4) {
406
+ for (let i = 0, l = frame.data.length; i < l; i += 4)
412
407
  mapper(frame.data, i)
413
- }
414
- if (flush) {
408
+
409
+ if (flush)
415
410
  ctx.putImageData(frame, x, y)
416
- }
417
411
  }
418
412
 
419
413
  /**
@@ -430,7 +424,8 @@ export function watchPublic (target: EtroObject): EtroObject {
430
424
  // Public API property updated, emit 'modify' event.
431
425
  publish(proxy, `${target.type}.change.modify`, { property: getPath(receiver, prop), newValue: val })
432
426
  }
433
- const check = prop => !(prop.startsWith('_') || target.publicExcludes.includes(prop))
427
+ const canWatch = (receiver, prop) => !prop.startsWith('_') &&
428
+ (receiver.publicExcludes === undefined || !receiver.publicExcludes.includes(prop))
434
429
 
435
430
  // The path to each child property (each is a unique proxy)
436
431
  const paths = new WeakMap()
@@ -438,12 +433,11 @@ export function watchPublic (target: EtroObject): EtroObject {
438
433
  const handler = {
439
434
  set (obj, prop, val, receiver) {
440
435
  // Recurse
441
- if (typeof val === 'object' && val !== null && !paths.has(val) && check(prop)) {
436
+ if (typeof val === 'object' && val !== null && !paths.has(val) && canWatch(receiver, prop)) {
442
437
  val = new Proxy(val, handler)
443
438
  paths.set(val, getPath(receiver, prop))
444
439
  }
445
440
 
446
- const was = prop in obj
447
441
  // Set property or attribute
448
442
  // Search prototype chain for the closest setter
449
443
  let objProto = obj
@@ -455,15 +449,14 @@ export function watchPublic (target: EtroObject): EtroObject {
455
449
  break
456
450
  }
457
451
  }
458
- if (!objProto) {
452
+ if (!objProto)
459
453
  // Couldn't find setter; set value on instance
460
454
  obj[prop] = val
461
- }
462
- // Check if it already existed and if it's a valid property to watch, if
463
- // on root object.
464
- if (obj !== target || (was && check(prop))) {
455
+
456
+ // Check if the property isn't blacklisted in publicExcludes.
457
+ if (canWatch(receiver, prop))
465
458
  callback(prop, val, receiver)
466
- }
459
+
467
460
  return true
468
461
  }
469
462
  }