chnobli 0.1.4 → 0.1.6

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 (238) hide show
  1. package/.prettierignore +4 -0
  2. package/.prettierrc +6 -0
  3. package/.vscode/settings.json +4 -0
  4. package/auto-docs/easing.js.html +342 -0
  5. package/auto-docs/fonts/OpenSans-Bold-webfont.eot +0 -0
  6. package/auto-docs/fonts/OpenSans-Bold-webfont.svg +1830 -0
  7. package/auto-docs/fonts/OpenSans-Bold-webfont.woff +0 -0
  8. package/auto-docs/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
  9. package/auto-docs/fonts/OpenSans-BoldItalic-webfont.svg +1830 -0
  10. package/auto-docs/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
  11. package/auto-docs/fonts/OpenSans-Italic-webfont.eot +0 -0
  12. package/auto-docs/fonts/OpenSans-Italic-webfont.svg +1830 -0
  13. package/auto-docs/fonts/OpenSans-Italic-webfont.woff +0 -0
  14. package/auto-docs/fonts/OpenSans-Light-webfont.eot +0 -0
  15. package/auto-docs/fonts/OpenSans-Light-webfont.svg +1831 -0
  16. package/auto-docs/fonts/OpenSans-Light-webfont.woff +0 -0
  17. package/auto-docs/fonts/OpenSans-LightItalic-webfont.eot +0 -0
  18. package/auto-docs/fonts/OpenSans-LightItalic-webfont.svg +1835 -0
  19. package/auto-docs/fonts/OpenSans-LightItalic-webfont.woff +0 -0
  20. package/auto-docs/fonts/OpenSans-Regular-webfont.eot +0 -0
  21. package/auto-docs/fonts/OpenSans-Regular-webfont.svg +1831 -0
  22. package/auto-docs/fonts/OpenSans-Regular-webfont.woff +0 -0
  23. package/auto-docs/global.html +4810 -0
  24. package/auto-docs/index.html +65 -0
  25. package/auto-docs/scripts/linenumber.js +25 -0
  26. package/auto-docs/scripts/prettify/Apache-License-2.0.txt +202 -0
  27. package/auto-docs/scripts/prettify/lang-css.js +2 -0
  28. package/auto-docs/scripts/prettify/prettify.js +28 -0
  29. package/auto-docs/styles/jsdoc-default.css +358 -0
  30. package/auto-docs/styles/prettify-jsdoc.css +111 -0
  31. package/auto-docs/styles/prettify-tomorrow.css +132 -0
  32. package/dist/animation/Animation.d.ts +36 -0
  33. package/dist/animation/Animation.d.ts.map +1 -0
  34. package/dist/animation/Animation.js +230 -0
  35. package/dist/animation/Animation.js.map +1 -0
  36. package/dist/animation/animation.d.ts +36 -0
  37. package/dist/animation/animation.d.ts.map +1 -0
  38. package/dist/animation/animation.js +230 -0
  39. package/dist/animation/animation.js.map +1 -0
  40. package/dist/animation/public.d.ts +55 -0
  41. package/dist/animation/public.d.ts.map +1 -0
  42. package/dist/animation/public.js +104 -0
  43. package/dist/animation/public.js.map +1 -0
  44. package/dist/chnobli.d.ts +15 -0
  45. package/dist/chnobli.d.ts.map +1 -0
  46. package/dist/chnobli.js +63 -0
  47. package/dist/chnobli.js.map +1 -0
  48. package/dist/property/BasicProperty.d.ts +38 -0
  49. package/dist/property/BasicProperty.d.ts.map +1 -0
  50. package/dist/property/BasicProperty.js +72 -0
  51. package/dist/property/BasicProperty.js.map +1 -0
  52. package/dist/property/ClassProperty.d.ts +32 -0
  53. package/dist/property/ClassProperty.d.ts.map +1 -0
  54. package/dist/property/ClassProperty.js +108 -0
  55. package/dist/property/ClassProperty.js.map +1 -0
  56. package/dist/property/Property.d.ts +13 -0
  57. package/dist/property/Property.d.ts.map +1 -0
  58. package/dist/property/Property.js +20 -0
  59. package/dist/property/Property.js.map +1 -0
  60. package/dist/property/StyleProperty.d.ts +25 -0
  61. package/dist/property/StyleProperty.d.ts.map +1 -0
  62. package/dist/property/StyleProperty.js +221 -0
  63. package/dist/property/StyleProperty.js.map +1 -0
  64. package/dist/property/TransformProperty.d.ts +15 -0
  65. package/dist/property/TransformProperty.d.ts.map +1 -0
  66. package/dist/property/TransformProperty.js +43 -0
  67. package/dist/property/TransformProperty.js.map +1 -0
  68. package/dist/property/TransformXYProperty.d.ts +28 -0
  69. package/dist/property/TransformXYProperty.d.ts.map +1 -0
  70. package/dist/property/TransformXYProperty.js +65 -0
  71. package/dist/property/TransformXYProperty.js.map +1 -0
  72. package/dist/responsive/ResponsiveEvent.d.ts +17 -0
  73. package/dist/responsive/ResponsiveEvent.d.ts.map +1 -0
  74. package/dist/responsive/ResponsiveEvent.js +45 -0
  75. package/dist/responsive/ResponsiveEvent.js.map +1 -0
  76. package/dist/responsive/TestEvent.d.ts +11 -0
  77. package/dist/responsive/TestEvent.d.ts.map +1 -0
  78. package/dist/responsive/TestEvent.js +26 -0
  79. package/dist/responsive/TestEvent.js.map +1 -0
  80. package/dist/responsive/event.d.ts +10 -0
  81. package/dist/responsive/event.d.ts.map +1 -0
  82. package/dist/responsive/event.js +39 -0
  83. package/dist/responsive/event.js.map +1 -0
  84. package/dist/scroll/Scroll.d.ts +27 -0
  85. package/dist/scroll/Scroll.d.ts.map +1 -0
  86. package/dist/scroll/Scroll.js +132 -0
  87. package/dist/scroll/Scroll.js.map +1 -0
  88. package/dist/scroll/ScrollEvent.d.ts +17 -0
  89. package/dist/scroll/ScrollEvent.d.ts.map +1 -0
  90. package/dist/scroll/ScrollEvent.js +39 -0
  91. package/dist/scroll/ScrollEvent.js.map +1 -0
  92. package/dist/scroll/public.d.ts +7 -0
  93. package/dist/scroll/public.d.ts.map +1 -0
  94. package/dist/scroll/public.js +17 -0
  95. package/dist/scroll/public.js.map +1 -0
  96. package/dist/stagger/stagger.d.ts +13 -0
  97. package/dist/stagger/stagger.d.ts.map +1 -0
  98. package/dist/stagger/stagger.js +35 -0
  99. package/dist/stagger/stagger.js.map +1 -0
  100. package/dist/target/BaseTarget.old.d.ts +33 -0
  101. package/dist/target/BaseTarget.old.d.ts.map +1 -0
  102. package/dist/target/BaseTarget.old.js +73 -0
  103. package/dist/target/BaseTarget.old.js.map +1 -0
  104. package/dist/target/DomTarget.d.ts +41 -0
  105. package/dist/target/DomTarget.d.ts.map +1 -0
  106. package/dist/target/DomTarget.js +230 -0
  107. package/dist/target/DomTarget.js.map +1 -0
  108. package/dist/target/Target.d.ts +22 -0
  109. package/dist/target/Target.d.ts.map +1 -0
  110. package/dist/target/Target.js +21 -0
  111. package/dist/target/Target.js.map +1 -0
  112. package/dist/target/TestDomNode.d.ts +14 -0
  113. package/dist/target/TestDomNode.d.ts.map +1 -0
  114. package/dist/target/TestDomNode.js +55 -0
  115. package/dist/target/TestDomNode.js.map +1 -0
  116. package/dist/timeline/Nested.d.ts +30 -0
  117. package/dist/timeline/Nested.d.ts.map +1 -0
  118. package/dist/timeline/Nested.js +51 -0
  119. package/dist/timeline/Nested.js.map +1 -0
  120. package/dist/timeline/TimeLine.d.ts +32 -0
  121. package/dist/timeline/TimeLine.d.ts.map +1 -0
  122. package/dist/timeline/TimeLine.js +288 -0
  123. package/dist/timeline/TimeLine.js.map +1 -0
  124. package/dist/timeline/public.d.ts +120 -0
  125. package/dist/timeline/public.d.ts.map +1 -0
  126. package/dist/timeline/public.js +301 -0
  127. package/dist/timeline/public.js.map +1 -0
  128. package/dist/timing/AnimationFrameTicker.d.ts +32 -0
  129. package/dist/timing/AnimationFrameTicker.d.ts.map +1 -0
  130. package/dist/timing/AnimationFrameTicker.js +134 -0
  131. package/dist/timing/AnimationFrameTicker.js.map +1 -0
  132. package/dist/timing/Ease.d.ts +6 -0
  133. package/dist/timing/Ease.d.ts.map +1 -0
  134. package/dist/timing/Ease.js +15 -0
  135. package/dist/timing/Ease.js.map +1 -0
  136. package/dist/timing/TestTicker.d.ts +19 -0
  137. package/dist/timing/TestTicker.d.ts.map +1 -0
  138. package/dist/timing/TestTicker.js +81 -0
  139. package/dist/timing/TestTicker.js.map +1 -0
  140. package/dist/timing/Ticker.d.ts +14 -0
  141. package/dist/timing/Ticker.d.ts.map +1 -0
  142. package/dist/timing/Ticker.js +2 -0
  143. package/dist/timing/Ticker.js.map +1 -0
  144. package/dist/timing/Timing.d.ts +62 -0
  145. package/dist/timing/Timing.d.ts.map +1 -0
  146. package/dist/timing/Timing.js +257 -0
  147. package/dist/timing/Timing.js.map +1 -0
  148. package/dist/timing/easing.d.ts +158 -0
  149. package/dist/timing/easing.d.ts.map +1 -0
  150. package/dist/timing/easing.js +273 -0
  151. package/dist/timing/easing.js.map +1 -0
  152. package/dist/utils/Events.d.ts +9 -0
  153. package/dist/utils/Events.d.ts.map +1 -0
  154. package/dist/utils/Events.js +35 -0
  155. package/dist/utils/Events.js.map +1 -0
  156. package/dist/utils/internal.d.ts +2 -0
  157. package/dist/utils/internal.d.ts.map +1 -0
  158. package/dist/utils/internal.js +6 -0
  159. package/dist/utils/internal.js.map +1 -0
  160. package/dist/utils/motionpath.d.ts +16 -0
  161. package/dist/utils/motionpath.d.ts.map +1 -0
  162. package/dist/utils/motionpath.js +41 -0
  163. package/dist/utils/motionpath.js.map +1 -0
  164. package/dist/utils/utils.d.ts +43 -0
  165. package/dist/utils/utils.d.ts.map +1 -0
  166. package/dist/utils/utils.js +93 -0
  167. package/dist/utils/utils.js.map +1 -0
  168. package/dist/values/ColorValue.d.ts +12 -0
  169. package/dist/values/ColorValue.d.ts.map +1 -0
  170. package/dist/values/ColorValue.js +133 -0
  171. package/dist/values/ColorValue.js.map +1 -0
  172. package/dist/values/StyleValue.d.ts +40 -0
  173. package/dist/values/StyleValue.d.ts.map +1 -0
  174. package/dist/values/StyleValue.js +149 -0
  175. package/dist/values/StyleValue.js.map +1 -0
  176. package/dist/values/Value.d.ts +13 -0
  177. package/dist/values/Value.d.ts.map +1 -0
  178. package/dist/values/Value.js +38 -0
  179. package/dist/values/Value.js.map +1 -0
  180. package/dist/values/defaultcolors.d.ts +2 -0
  181. package/dist/values/defaultcolors.d.ts.map +1 -0
  182. package/dist/values/defaultcolors.js +149 -0
  183. package/dist/values/defaultcolors.js.map +1 -0
  184. package/package.json +11 -7
  185. package/src/animation/{animation.js → Animation.ts} +56 -54
  186. package/src/animation/{public.js → public.ts} +23 -18
  187. package/src/{chnobli.js → chnobli.ts} +11 -12
  188. package/src/property/BasicProperty.ts +91 -0
  189. package/src/property/ClassProperty.ts +132 -0
  190. package/src/property/Property.ts +33 -0
  191. package/src/property/StyleProperty.ts +273 -0
  192. package/src/property/TransformProperty.ts +56 -0
  193. package/src/property/TransformXYProperty.ts +88 -0
  194. package/src/responsive/ResponsiveEvent.ts +60 -0
  195. package/src/responsive/{testevent.js → TestEvent.ts} +12 -10
  196. package/src/scroll/{scroll.js → Scroll.ts} +53 -35
  197. package/src/scroll/ScrollEvent.ts +53 -0
  198. package/src/scroll/public.ts +20 -0
  199. package/src/stagger/stagger.ts +45 -0
  200. package/src/target/{basetarget.js → BaseTarget.old.ts} +25 -26
  201. package/src/target/DomTarget.ts +281 -0
  202. package/src/target/Target.ts +48 -0
  203. package/src/target/{testdomnode.js → TestDomNode.ts} +18 -15
  204. package/src/tests/{properties.test.js → properties.test.ts} +54 -49
  205. package/src/tests/timeline.test.ts +290 -0
  206. package/src/tests/{timing.test.js → timing.test.ts} +25 -22
  207. package/src/tests/{usecases.test.js → usecases.test.ts} +13 -10
  208. package/src/tests/{values.test.js → values.test.ts} +21 -21
  209. package/src/timeline/Nested.ts +67 -0
  210. package/src/timeline/{timeline.js → TimeLine.ts} +126 -56
  211. package/src/timeline/{public.js → public.ts} +112 -73
  212. package/src/timing/{ticker.js → AnimationFrameTicker.ts} +36 -21
  213. package/src/timing/{ease.js → Ease.ts} +6 -5
  214. package/src/timing/{testticker.js → TestTicker.ts} +27 -24
  215. package/src/timing/Ticker.ts +11 -0
  216. package/src/timing/{timing.js → Timing.ts} +72 -63
  217. package/src/timing/{easing.js → easing.ts} +52 -43
  218. package/src/utils/{events.js → Events.ts} +12 -11
  219. package/src/utils/internal.ts +10 -0
  220. package/src/utils/{motionpath.js → motionpath.ts} +36 -13
  221. package/src/utils/utils.ts +110 -0
  222. package/src/values/{colorvalue.js → ColorValue.ts} +46 -47
  223. package/src/values/StyleValue.ts +186 -0
  224. package/src/values/{value.js → Value.ts} +14 -12
  225. package/src/values/{defaultcolors.js → defaultcolors.ts} +2 -2
  226. package/tsconfig.build.json +19 -0
  227. package/tsconfig.json +17 -108
  228. package/src/animation/property.js +0 -556
  229. package/src/responsive/event.js +0 -46
  230. package/src/scroll/event.js +0 -41
  231. package/src/scroll/public.js +0 -17
  232. package/src/stagger/stagger.js +0 -42
  233. package/src/target/domtarget.js +0 -266
  234. package/src/target/target.js +0 -22
  235. package/src/tests/timeline.test.js +0 -234
  236. package/src/utils/internal.js +0 -7
  237. package/src/utils/utils.js +0 -75
  238. package/src/values/stylevalue.js +0 -148
@@ -1,19 +1,44 @@
1
- function catmullRom(p0, p1, p2, p3, t, p1Tension, p2Tension) {
1
+ function catmullRom(
2
+ p0: number,
3
+ p1: number,
4
+ p2: number,
5
+ p3: number,
6
+ t: number,
7
+ p1Tension: number,
8
+ p2Tension: number,
9
+ ) {
2
10
  let v0 = (p2 - p0) * p1Tension;
3
11
  let v1 = (p3 - p1) * p2Tension;
4
12
  let t2 = t * t;
5
13
  let t3 = t2 * t;
6
14
 
7
- return (2 * p1 - 2 * p2 + v0 + v1) *
8
- t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;
15
+ return (
16
+ (2 * p1 - 2 * p2 + v0 + v1) * t3 +
17
+ (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 +
18
+ v0 * t +
19
+ p1
20
+ );
9
21
  }
10
22
 
23
+ export type CurveOptions = {
24
+ startEndStraight?: boolean;
25
+ };
26
+
27
+ export type Point = {
28
+ x: number;
29
+ y: number;
30
+ straight?: boolean;
31
+ };
32
+
11
33
  /**
12
34
  * Calculates a curve between different points
13
35
  */
14
- export function curve(points, tension = 1, opts = {}) {
15
- if (points.length <= 1)
16
- throw new Error('curve expects at least 2 points');
36
+ export function curve(
37
+ points: Point[],
38
+ tension = 1,
39
+ opts: CurveOptions = {},
40
+ ): (t: number) => { x: number; y: number } {
41
+ if (points.length <= 1) throw new Error('curve expects at least 2 points');
17
42
 
18
43
  let startEndStraight = opts.startEndStraight ?? true;
19
44
  if (startEndStraight) {
@@ -23,7 +48,7 @@ export function curve(points, tension = 1, opts = {}) {
23
48
 
24
49
  return t => {
25
50
  const segment = Math.floor(t * (points.length - 1));
26
- const localT = (t * (points.length - 1)) - segment;
51
+ const localT = t * (points.length - 1) - segment;
27
52
 
28
53
  const p0 = points[Math.max(0, segment - 1)];
29
54
  const p1 = points[segment];
@@ -33,15 +58,13 @@ export function curve(points, tension = 1, opts = {}) {
33
58
  let p1Tension = tension;
34
59
  let p2Tension = tension;
35
60
 
36
- if (p1.straight)
37
- p1Tension = 0;
61
+ if (p1.straight) p1Tension = 0;
38
62
 
39
- if (p2.straight)
40
- p2Tension = 0;
63
+ if (p2.straight) p2Tension = 0;
41
64
 
42
65
  return {
43
66
  x: catmullRom(p0.x, p1.x, p2.x, p3.x, localT, p1Tension, p2Tension),
44
- y: catmullRom(p0.y, p1.y, p2.y, p3.y, localT, p1Tension, p2Tension)
67
+ y: catmullRom(p0.y, p1.y, p2.y, p3.y, localT, p1Tension, p2Tension),
45
68
  };
46
69
  };
47
- }
70
+ }
@@ -0,0 +1,110 @@
1
+ import { Callback } from '../responsive/ResponsiveEvent';
2
+ import { curve } from './motionpath';
3
+
4
+ export { curve };
5
+
6
+ /**
7
+ * Explicitly tells a property to animate the to value
8
+ */
9
+ export function to(to: any) {
10
+ return { to };
11
+ }
12
+
13
+ /**
14
+ * Explicitly tells a property to animate the from value
15
+ */
16
+ export function from(from: any) {
17
+ return { from };
18
+ }
19
+
20
+ /**
21
+ * Explicitly tells a property to animate with the from and to values
22
+ */
23
+ export function fromTo(from: any, to: any) {
24
+ return { from, to };
25
+ }
26
+
27
+ /**
28
+ * makes a value reactive to `Timeline::update` calls or resizes
29
+ */
30
+ export function responsive(fn: (target: any) => void): any {
31
+ return { responsive: fn };
32
+ }
33
+
34
+ /**
35
+ * Converts an element with text into span with chars
36
+ */
37
+ export function chars(element: HTMLElement) {
38
+ if (element.dataset.processedChars) return Array.from(element.children);
39
+
40
+ const chars = element.textContent!.split('');
41
+
42
+ element.textContent = '';
43
+ element.dataset.processedChars = 'yes';
44
+
45
+ return chars
46
+ .map(c => {
47
+ if (c.trim().length === 0) {
48
+ element.appendChild(document.createTextNode(c));
49
+ return null;
50
+ }
51
+
52
+ const span = document.createElement('span');
53
+ span.textContent = c;
54
+ span.style.display = 'inline-block';
55
+ element.appendChild(span);
56
+
57
+ return span;
58
+ })
59
+ .filter(c => !!c);
60
+ }
61
+
62
+ /**
63
+ * Converts an element with text into span with words
64
+ */
65
+ export function words(element: HTMLElement) {
66
+ if (element.dataset.processedWords) return Array.from(element.children);
67
+
68
+ const words = element.textContent!.split(/(\s+)/);
69
+
70
+ element.textContent = '';
71
+ element.dataset.processedWords = 'yes';
72
+
73
+ return words
74
+ .map(word => {
75
+ if (word.trim().length === 0) {
76
+ element.appendChild(document.createTextNode(word));
77
+ return null;
78
+ }
79
+
80
+ const span = document.createElement('span');
81
+ span.textContent = word;
82
+ span.style.display = 'inline-block';
83
+ element.appendChild(span);
84
+
85
+ return span;
86
+ })
87
+ .filter(w => !!w);
88
+ }
89
+
90
+ /**
91
+ * get the offset to the current page page
92
+ */
93
+ export function pageOffset(el: HTMLElement) {
94
+ if ('offsetTop' in el) {
95
+ return {
96
+ top: el.offsetTop,
97
+ left: el.offsetLeft,
98
+ width: el.offsetWidth,
99
+ height: el.offsetHeight,
100
+ };
101
+ }
102
+
103
+ const rect = (el as HTMLElement).getBoundingClientRect();
104
+ return {
105
+ top: window.scrollY + rect.top,
106
+ left: window.scrollX + rect.left,
107
+ width: rect.width,
108
+ height: rect.height,
109
+ };
110
+ }
@@ -1,21 +1,28 @@
1
- import { COLORS } from './defaultcolors.js';
1
+ import { COLORS } from './defaultcolors';
2
+
3
+ export type RGBA = [number, number, number, number];
4
+ export type HSLA = [number, number, number, number];
5
+ export type RGB = [number, number, number];
2
6
 
3
7
  export default class ColorValue {
8
+ values: RGBA;
9
+
4
10
  // [r, g, b, a?]
5
- constructor(v) {
6
- if (v.length === 3)
11
+ constructor(v: RGBA | RGB) {
12
+ if (v.length === 3) {
7
13
  v = [...v, 1];
14
+ }
8
15
 
9
16
  // always [r, g, b, a]
10
17
  this.values = v;
11
18
  }
12
19
 
13
- static parse(v) {
20
+ static parse(v: string | number[]) {
14
21
  if (Array.isArray(v)) {
15
22
  if (v.length < 3 || v.length > 4)
16
23
  throw new Error('expected array [r, g, b, a]');
17
24
 
18
- return new ColorValue(v);
25
+ return new ColorValue(v as any);
19
26
  }
20
27
 
21
28
  if (typeof v !== 'string')
@@ -23,43 +30,41 @@ export default class ColorValue {
23
30
 
24
31
  v = v.trim();
25
32
 
26
- if (v.startsWith('#'))
27
- return new ColorValue(parseHex(v.substring(1)));
28
- if (v.startsWith('rgb'))
29
- return new ColorValue(parseRgb(v));
30
- if (v.startsWith('hsl'))
31
- return new ColorValue(parseHsl(v));
33
+ if (v.startsWith('#')) return new ColorValue(parseHex(v.substring(1)));
34
+ if (v.startsWith('rgb')) return new ColorValue(parseRgb(v));
35
+ if (v.startsWith('hsl')) return new ColorValue(parseHsl(v));
32
36
 
33
- if (v in COLORS)
34
- return new ColorValue(COLORS[v]);
37
+ if (v in COLORS) return new ColorValue(COLORS[v]);
35
38
 
36
39
  throw new Error('unknown color value ' + v);
37
40
  }
38
41
 
39
42
  // v needs to be a string
40
- static mightBeAColor(v) {
43
+ static mightBeAColor(v: string) {
41
44
  v = v.trim();
42
45
 
43
- return v.startsWith('#')
44
- || v.startsWith('rgb')
45
- || v.startsWith('hsl')
46
- || v in COLORS;
46
+ return (
47
+ v.startsWith('#') ||
48
+ v.startsWith('rgb') ||
49
+ v.startsWith('hsl') ||
50
+ v in COLORS
51
+ );
47
52
  }
48
53
 
49
54
  clone() {
50
- return new ColorValue(this.values.slice());
55
+ return new ColorValue(this.values.slice() as any);
51
56
  }
52
57
 
53
58
  toString() {
54
59
  const [r, g, b, a] = this.values;
55
- return `rgba(${[r, g, b].map(v => Math.round(v)).join(', ')}, ${
56
- a.toFixed(3)
57
- })`;
60
+ return `rgba(${[r, g, b].map(v => Math.round(v)).join(', ')}, ${a.toFixed(
61
+ 3,
62
+ )})`;
58
63
  }
59
64
  }
60
65
 
61
66
  // hex without the hash
62
- function parseHex(hex) {
67
+ function parseHex(hex: string): RGBA {
63
68
  if (hex.length !== 3 && hex.length !== 6 && hex.length !== 8)
64
69
  throw new Error('unknown hex value ' + hex);
65
70
 
@@ -73,17 +78,16 @@ function parseHex(hex) {
73
78
  const b = parseInt(hex.substring(4, 6), 16);
74
79
  let a = 255;
75
80
 
76
- if (hex.length === 8)
77
- a = parseInt(hex.substring(6, 8), 16);
81
+ if (hex.length === 8) a = parseInt(hex.substring(6, 8), 16);
78
82
 
79
83
  return [r, g, b, a / 255];
80
84
  }
81
85
 
82
86
  // rgb needs to start with rgb
83
- function parseRgb(rgb) {
87
+ function parseRgb(rgb: string): RGBA {
84
88
  const rgba = rgb.startsWith('rgba');
85
89
  // remove the function name
86
- rgb = rgb.substring(3 + rgba);
90
+ rgb = rgb.substring(3 + +rgba);
87
91
  if (!rgb.startsWith('(') && !rgb.endsWith(')'))
88
92
  throw new Error('invalid rgb function ' + rgb);
89
93
 
@@ -102,10 +106,10 @@ function parseRgb(rgb) {
102
106
  }
103
107
 
104
108
  // hsl needs to start with hsl
105
- function parseHsl(hsl) {
109
+ function parseHsl(hsl: string): RGBA {
106
110
  const hsla = hsl.startsWith('hsla');
107
111
  // Remove the function name
108
- hsl = hsl.substring(3 + hsla);
112
+ hsl = hsl.substring(3 + +hsla);
109
113
  if (!hsl.startsWith('(') || !hsl.endsWith(')'))
110
114
  throw new Error('invalid hsl function ' + hsl);
111
115
 
@@ -129,7 +133,7 @@ function parseHsl(hsl) {
129
133
  }
130
134
 
131
135
  /// expects [h, s, l, a]
132
- function hslToRgba(hsla) {
136
+ function hslToRgba(hsla: HSLA): RGBA {
133
137
  let [h, s, l, a] = hsla;
134
138
 
135
139
  // normalize
@@ -141,27 +145,22 @@ function hslToRgba(hsla) {
141
145
  if (s === 0) {
142
146
  r = g = b = l;
143
147
  } else {
144
- const q = l < .5 ? l * (1 + s) : l + s - l * s;
148
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
145
149
  const p = 2 * l - q;
146
- r = Math.round(hueToRgb(p, q, h + 1 / 3) * 255, 0);
147
- g = Math.round(hueToRgb(p, q, h) * 255, 0);
148
- b = Math.round(hueToRgb(p, q, h - 1 / 3) * 255, 0);
150
+ r = Math.round(hueToRgb(p, q, h + 1 / 3) * 255);
151
+ g = Math.round(hueToRgb(p, q, h) * 255);
152
+ b = Math.round(hueToRgb(p, q, h - 1 / 3) * 255);
149
153
  }
150
154
 
151
155
  return [r, g, b, a];
152
156
  }
153
157
 
154
- function hueToRgb(p, q, t) {
155
- if (t < 0)
156
- t += 1;
157
- if (t > 1)
158
- t -= 1;
159
-
160
- if (t < 1 / 6)
161
- return p + (q - p) * 6 * t;
162
- if (t < 1 / 2)
163
- return q;
164
- if (t < 2 / 3)
165
- return p + (q - p) * (2 / 3 - t) * 6;
158
+ function hueToRgb(p: number, q: number, t: number): number {
159
+ if (t < 0) t += 1;
160
+ if (t > 1) t -= 1;
161
+
162
+ if (t < 1 / 6) return p + (q - p) * 6 * t;
163
+ if (t < 1 / 2) return q;
164
+ if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
166
165
  return p;
167
- }
166
+ }
@@ -0,0 +1,186 @@
1
+ import Value from './Value';
2
+ import ColorValue from './ColorValue';
3
+
4
+ const AT_THE_END_VALUES = ['none', 'hidden'];
5
+
6
+ type InnerText = {
7
+ kind: 'text';
8
+ values: string;
9
+ };
10
+
11
+ type InnerValues = {
12
+ kind: 'values';
13
+ values: Value[];
14
+ };
15
+
16
+ type InnerColor = {
17
+ kind: 'color';
18
+ values: ColorValue;
19
+ };
20
+
21
+ /**
22
+ * A value from a style property
23
+ *
24
+ * might be a textual representation like none|auto|block|var(--abc)
25
+ * might be a value with unit or not
26
+ * might be multiple values `10 20px 4rem`
27
+ *
28
+ * values like hidden|none|null|undefined are market as at the end
29
+ * which means they should be set at the end
30
+ */
31
+ export default class StyleValue {
32
+ private inner: InnerText | InnerValues | InnerColor;
33
+ private textAtTheEnd: boolean;
34
+
35
+ /**
36
+ * Creates a style value
37
+ *
38
+ * ## value must be one of the following
39
+ * - string (meaning this is of kind text)
40
+ * - number (meaning this is of kind values with one value)
41
+ * - array (meaning this is of kind values and each array element needs to
42
+ * be a Value)
43
+ * - ColorValue
44
+ */
45
+ constructor(value: string | number | Value[] | ColorValue) {
46
+ if (typeof value === 'string') {
47
+ this.inner = {
48
+ kind: 'text',
49
+ values: value.trim(),
50
+ };
51
+ } else if (typeof value === 'number') {
52
+ this.inner = {
53
+ kind: 'values',
54
+ values: [Value.parse(value)],
55
+ };
56
+ } else if (Array.isArray(value)) {
57
+ this.inner = {
58
+ kind: 'values',
59
+ values: value,
60
+ };
61
+ } else if (value instanceof ColorValue) {
62
+ this.inner = {
63
+ kind: 'color',
64
+ values: value,
65
+ };
66
+ } else {
67
+ throw new Error('unknown style value ' + value);
68
+ }
69
+
70
+ /**
71
+ * If this is true the value should be set at the end of a animation
72
+ * this only works with kind === text
73
+ */
74
+ this.textAtTheEnd =
75
+ this.inner.kind === 'text'
76
+ ? AT_THE_END_VALUES.includes(this.inner.values)
77
+ : false;
78
+ }
79
+
80
+ static parse(v: string | number | (string | number)[]) {
81
+ if (typeof v === 'number') return new StyleValue(v);
82
+
83
+ if (Array.isArray(v)) {
84
+ const val = v.map(v => Value.parse(v));
85
+ return new StyleValue(val);
86
+ }
87
+
88
+ if (typeof v !== 'string')
89
+ throw new Error('expected a string as style value ' + v);
90
+
91
+ // let's first try to make it a color
92
+ if (ColorValue.mightBeAColor(v))
93
+ return new StyleValue(ColorValue.parse(v));
94
+
95
+ const split = v
96
+ .split(' ')
97
+ .map(v => v.trim())
98
+ .filter(v => !!v);
99
+ if (split.length === 0) throw new Error('style value cannot be empty');
100
+
101
+ if (split.length === 1) {
102
+ try {
103
+ const val = Value.parse(split[0]);
104
+ return new StyleValue([val]);
105
+ } catch (e) {
106
+ // console.log('failed to parse first style value ', e);
107
+ return new StyleValue(split[0]);
108
+ }
109
+ }
110
+
111
+ return new StyleValue(split.map(v => Value.parse(v)));
112
+ }
113
+
114
+ get kind(): 'text' | 'values' | 'color' {
115
+ return this.inner.kind;
116
+ }
117
+
118
+ get values(): string | Value[] | ColorValue {
119
+ return this.inner.values;
120
+ }
121
+
122
+ /// only works if the kind is values
123
+ get length() {
124
+ if (this.inner.kind !== 'values')
125
+ throw new Error('only works with kind values');
126
+
127
+ return this.inner.values.length;
128
+ }
129
+
130
+ extendToLength(length: number) {
131
+ if (this.length >= length) return;
132
+
133
+ // length already checks that kind is values
134
+ this.inner.values = Array(length).fill(this.values).flat();
135
+ }
136
+
137
+ /**
138
+ * Throws if the this does not contain exactly one value
139
+ */
140
+ intoValue(): Value {
141
+ if (this.length !== 1)
142
+ throw new Error('style value does not contain only one value');
143
+
144
+ // length already checks that kind is values
145
+ return (this.inner.values as Value[])[0];
146
+ }
147
+
148
+ clone() {
149
+ if (this.inner.kind === 'text')
150
+ return new StyleValue(this.inner.values);
151
+
152
+ if (this.inner.kind === 'color')
153
+ return new StyleValue(this.inner.values.clone());
154
+
155
+ return new StyleValue(this.inner.values.map(v => v.clone()));
156
+ }
157
+
158
+ /// if this is called with a text value nothing happens
159
+ withDefaultUnit(unit: string | null) {
160
+ if (this.inner.kind === 'text')
161
+ return new StyleValue(this.inner.values);
162
+
163
+ if (this.inner.kind === 'color')
164
+ return new StyleValue(this.inner.values.clone());
165
+
166
+ return new StyleValue(
167
+ this.inner.values.map(v => v.withDefaultUnit(unit)),
168
+ );
169
+ }
170
+
171
+ toString() {
172
+ switch (this.inner.kind) {
173
+ case 'text':
174
+ return this.inner.values;
175
+
176
+ case 'color':
177
+ return this.inner.values.toString();
178
+
179
+ case 'values':
180
+ return this.inner.values.join(' ');
181
+
182
+ default:
183
+ throw new Error('unknown kind ' + this.kind);
184
+ }
185
+ }
186
+ }
@@ -1,46 +1,48 @@
1
1
  const REGEX = /^(\d+\.?\d*|\.\d+)(\w*|%)$/;
2
2
 
3
-
4
3
  export default class Value {
5
- constructor(num, unit = null) {
4
+ num: number;
5
+ unit: string | null;
6
+
7
+ constructor(num: number, unit: string | null = null) {
6
8
  this.num = num;
7
9
  this.unit = unit;
8
10
  }
9
11
 
10
- static parse(v) {
12
+ static parse(v: string | number) {
11
13
  if (typeof v === 'number') {
12
14
  return new Value(v);
13
15
  }
14
16
 
17
+ // @ts-ignore
15
18
  const [_v, num, unit] = REGEX.exec(v);
16
19
 
17
20
  return new Value(parseFloat(num), unit ? unit : null);
18
21
  }
19
22
 
20
- eq(other) {
23
+ eq(other: Value) {
21
24
  return this.unit === other.unit && this.num === other.num;
22
25
  }
23
26
 
24
- clone(newNum = null) {
25
- if (newNum !== null)
26
- return new Value(newNum, this.unit);
27
-
27
+ clone(newNum: number | null = null) {
28
+ if (newNum !== null) return new Value(newNum, this.unit);
29
+
28
30
  return new Value(this.num, this.unit);
29
31
  }
30
32
 
31
- cloneAdd(add) {
33
+ cloneAdd(add: number) {
32
34
  return new Value(this.num + add, this.unit);
33
35
  }
34
36
 
35
- cloneMul(mul) {
37
+ cloneMul(mul: number) {
36
38
  return new Value(this.num * mul, this.unit);
37
39
  }
38
40
 
39
- withDefaultUnit(unit) {
41
+ withDefaultUnit(unit: string | null) {
40
42
  return new Value(this.num, this.unit ?? unit);
41
43
  }
42
44
 
43
45
  toString() {
44
46
  return this.num.toFixed(3) + (this.unit ?? '');
45
47
  }
46
- }
48
+ }
@@ -1,4 +1,4 @@
1
- export const COLORS = {
1
+ export const COLORS: Record<string, [number, number, number]> = {
2
2
  black: [0, 0, 0],
3
3
  silver: [192, 192, 192],
4
4
  gray: [128, 128, 128],
@@ -144,5 +144,5 @@ export const COLORS = {
144
144
  violet: [238, 130, 238],
145
145
  wheat: [245, 222, 179],
146
146
  whitesmoke: [245, 245, 245],
147
- yellowgreen: [154, 205, 50]
147
+ yellowgreen: [154, 205, 50],
148
148
  };
@@ -0,0 +1,19 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "useDefineForClassFields": true,
5
+ "module": "ESNext",
6
+ "moduleResolution": "Bundler",
7
+ "declaration": true,
8
+ "declarationMap": true,
9
+ "sourceMap": true,
10
+ "baseUrl": ".",
11
+ "allowJs": true,
12
+ "checkJs": false,
13
+ "isolatedModules": true,
14
+ "strict": true,
15
+ "outDir": "./dist"
16
+ },
17
+ "include": ["src/**/*.ts"],
18
+ "exclude": ["src/**/*.test.ts"]
19
+ }