chnobli 0.1.5 → 0.1.7
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/.editorconfig +11 -0
- package/.prettierignore +4 -0
- package/.prettierrc +6 -0
- package/.vscode/settings.json +4 -0
- package/auto-docs/easing.js.html +342 -0
- package/auto-docs/fonts/OpenSans-Bold-webfont.eot +0 -0
- package/auto-docs/fonts/OpenSans-Bold-webfont.svg +1830 -0
- package/auto-docs/fonts/OpenSans-Bold-webfont.woff +0 -0
- package/auto-docs/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
- package/auto-docs/fonts/OpenSans-BoldItalic-webfont.svg +1830 -0
- package/auto-docs/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
- package/auto-docs/fonts/OpenSans-Italic-webfont.eot +0 -0
- package/auto-docs/fonts/OpenSans-Italic-webfont.svg +1830 -0
- package/auto-docs/fonts/OpenSans-Italic-webfont.woff +0 -0
- package/auto-docs/fonts/OpenSans-Light-webfont.eot +0 -0
- package/auto-docs/fonts/OpenSans-Light-webfont.svg +1831 -0
- package/auto-docs/fonts/OpenSans-Light-webfont.woff +0 -0
- package/auto-docs/fonts/OpenSans-LightItalic-webfont.eot +0 -0
- package/auto-docs/fonts/OpenSans-LightItalic-webfont.svg +1835 -0
- package/auto-docs/fonts/OpenSans-LightItalic-webfont.woff +0 -0
- package/auto-docs/fonts/OpenSans-Regular-webfont.eot +0 -0
- package/auto-docs/fonts/OpenSans-Regular-webfont.svg +1831 -0
- package/auto-docs/fonts/OpenSans-Regular-webfont.woff +0 -0
- package/auto-docs/global.html +4810 -0
- package/auto-docs/index.html +65 -0
- package/auto-docs/scripts/linenumber.js +25 -0
- package/auto-docs/scripts/prettify/Apache-License-2.0.txt +202 -0
- package/auto-docs/scripts/prettify/lang-css.js +2 -0
- package/auto-docs/scripts/prettify/prettify.js +28 -0
- package/auto-docs/styles/jsdoc-default.css +358 -0
- package/auto-docs/styles/prettify-jsdoc.css +111 -0
- package/auto-docs/styles/prettify-tomorrow.css +132 -0
- package/dist/animation/Animation.d.ts +36 -0
- package/dist/animation/Animation.d.ts.map +1 -0
- package/dist/animation/Animation.js +230 -0
- package/dist/animation/Animation.js.map +1 -0
- package/dist/animation/animation.d.ts +36 -0
- package/dist/animation/animation.d.ts.map +1 -0
- package/dist/animation/animation.js +230 -0
- package/dist/animation/animation.js.map +1 -0
- package/dist/animation/public.d.ts +55 -0
- package/dist/animation/public.d.ts.map +1 -0
- package/dist/animation/public.js +104 -0
- package/dist/animation/public.js.map +1 -0
- package/dist/chnobli.d.ts +15 -0
- package/dist/chnobli.d.ts.map +1 -0
- package/dist/chnobli.js +63 -0
- package/dist/chnobli.js.map +1 -0
- package/dist/property/BasicProperty.d.ts +38 -0
- package/dist/property/BasicProperty.d.ts.map +1 -0
- package/dist/property/BasicProperty.js +72 -0
- package/dist/property/BasicProperty.js.map +1 -0
- package/dist/property/ClassProperty.d.ts +32 -0
- package/dist/property/ClassProperty.d.ts.map +1 -0
- package/dist/property/ClassProperty.js +108 -0
- package/dist/property/ClassProperty.js.map +1 -0
- package/dist/property/Property.d.ts +13 -0
- package/dist/property/Property.d.ts.map +1 -0
- package/dist/property/Property.js +20 -0
- package/dist/property/Property.js.map +1 -0
- package/dist/property/StyleProperty.d.ts +25 -0
- package/dist/property/StyleProperty.d.ts.map +1 -0
- package/dist/property/StyleProperty.js +221 -0
- package/dist/property/StyleProperty.js.map +1 -0
- package/dist/property/TransformProperty.d.ts +15 -0
- package/dist/property/TransformProperty.d.ts.map +1 -0
- package/dist/property/TransformProperty.js +43 -0
- package/dist/property/TransformProperty.js.map +1 -0
- package/dist/property/TransformXYProperty.d.ts +28 -0
- package/dist/property/TransformXYProperty.d.ts.map +1 -0
- package/dist/property/TransformXYProperty.js +65 -0
- package/dist/property/TransformXYProperty.js.map +1 -0
- package/dist/responsive/ResponsiveEvent.d.ts +17 -0
- package/dist/responsive/ResponsiveEvent.d.ts.map +1 -0
- package/dist/responsive/ResponsiveEvent.js +45 -0
- package/dist/responsive/ResponsiveEvent.js.map +1 -0
- package/dist/responsive/TestEvent.d.ts +11 -0
- package/dist/responsive/TestEvent.d.ts.map +1 -0
- package/dist/responsive/TestEvent.js +26 -0
- package/dist/responsive/TestEvent.js.map +1 -0
- package/dist/responsive/event.d.ts +10 -0
- package/dist/responsive/event.d.ts.map +1 -0
- package/dist/responsive/event.js +39 -0
- package/dist/responsive/event.js.map +1 -0
- package/dist/scroll/Scroll.d.ts +27 -0
- package/dist/scroll/Scroll.d.ts.map +1 -0
- package/dist/scroll/Scroll.js +132 -0
- package/dist/scroll/Scroll.js.map +1 -0
- package/dist/scroll/ScrollEvent.d.ts +17 -0
- package/dist/scroll/ScrollEvent.d.ts.map +1 -0
- package/dist/scroll/ScrollEvent.js +39 -0
- package/dist/scroll/ScrollEvent.js.map +1 -0
- package/dist/scroll/public.d.ts +7 -0
- package/dist/scroll/public.d.ts.map +1 -0
- package/dist/scroll/public.js +17 -0
- package/dist/scroll/public.js.map +1 -0
- package/dist/stagger/stagger.d.ts +13 -0
- package/dist/stagger/stagger.d.ts.map +1 -0
- package/dist/stagger/stagger.js +35 -0
- package/dist/stagger/stagger.js.map +1 -0
- package/dist/target/BaseTarget.old.d.ts +33 -0
- package/dist/target/BaseTarget.old.d.ts.map +1 -0
- package/dist/target/BaseTarget.old.js +73 -0
- package/dist/target/BaseTarget.old.js.map +1 -0
- package/dist/target/DomTarget.d.ts +41 -0
- package/dist/target/DomTarget.d.ts.map +1 -0
- package/dist/target/DomTarget.js +230 -0
- package/dist/target/DomTarget.js.map +1 -0
- package/dist/target/Target.d.ts +22 -0
- package/dist/target/Target.d.ts.map +1 -0
- package/dist/target/Target.js +21 -0
- package/dist/target/Target.js.map +1 -0
- package/dist/target/TestDomNode.d.ts +14 -0
- package/dist/target/TestDomNode.d.ts.map +1 -0
- package/dist/target/TestDomNode.js +55 -0
- package/dist/target/TestDomNode.js.map +1 -0
- package/dist/timeline/Nested.d.ts +30 -0
- package/dist/timeline/Nested.d.ts.map +1 -0
- package/dist/timeline/Nested.js +51 -0
- package/dist/timeline/Nested.js.map +1 -0
- package/dist/timeline/TimeLine.d.ts +32 -0
- package/dist/timeline/TimeLine.d.ts.map +1 -0
- package/dist/timeline/TimeLine.js +288 -0
- package/dist/timeline/TimeLine.js.map +1 -0
- package/dist/timeline/public.d.ts +120 -0
- package/dist/timeline/public.d.ts.map +1 -0
- package/dist/timeline/public.js +301 -0
- package/dist/timeline/public.js.map +1 -0
- package/dist/timing/AnimationFrameTicker.d.ts +32 -0
- package/dist/timing/AnimationFrameTicker.d.ts.map +1 -0
- package/dist/timing/AnimationFrameTicker.js +134 -0
- package/dist/timing/AnimationFrameTicker.js.map +1 -0
- package/dist/timing/Ease.d.ts +6 -0
- package/dist/timing/Ease.d.ts.map +1 -0
- package/dist/timing/Ease.js +15 -0
- package/dist/timing/Ease.js.map +1 -0
- package/dist/timing/TestTicker.d.ts +19 -0
- package/dist/timing/TestTicker.d.ts.map +1 -0
- package/dist/timing/TestTicker.js +81 -0
- package/dist/timing/TestTicker.js.map +1 -0
- package/dist/timing/Ticker.d.ts +14 -0
- package/dist/timing/Ticker.d.ts.map +1 -0
- package/dist/timing/Ticker.js +2 -0
- package/dist/timing/Ticker.js.map +1 -0
- package/dist/timing/Timing.d.ts +62 -0
- package/dist/timing/Timing.d.ts.map +1 -0
- package/dist/timing/Timing.js +257 -0
- package/dist/timing/Timing.js.map +1 -0
- package/dist/timing/easing.d.ts +158 -0
- package/dist/timing/easing.d.ts.map +1 -0
- package/dist/timing/easing.js +273 -0
- package/dist/timing/easing.js.map +1 -0
- package/dist/utils/Events.d.ts +9 -0
- package/dist/utils/Events.d.ts.map +1 -0
- package/dist/utils/Events.js +35 -0
- package/dist/utils/Events.js.map +1 -0
- package/dist/utils/internal.d.ts +2 -0
- package/dist/utils/internal.d.ts.map +1 -0
- package/dist/utils/internal.js +6 -0
- package/dist/utils/internal.js.map +1 -0
- package/dist/utils/motionpath.d.ts +16 -0
- package/dist/utils/motionpath.d.ts.map +1 -0
- package/dist/utils/motionpath.js +41 -0
- package/dist/utils/motionpath.js.map +1 -0
- package/dist/utils/utils.d.ts +43 -0
- package/dist/utils/utils.d.ts.map +1 -0
- package/dist/utils/utils.js +93 -0
- package/dist/utils/utils.js.map +1 -0
- package/dist/values/ColorValue.d.ts +12 -0
- package/dist/values/ColorValue.d.ts.map +1 -0
- package/dist/values/ColorValue.js +133 -0
- package/dist/values/ColorValue.js.map +1 -0
- package/dist/values/StyleValue.d.ts +40 -0
- package/dist/values/StyleValue.d.ts.map +1 -0
- package/dist/values/StyleValue.js +149 -0
- package/dist/values/StyleValue.js.map +1 -0
- package/dist/values/Value.d.ts +13 -0
- package/dist/values/Value.d.ts.map +1 -0
- package/dist/values/Value.js +38 -0
- package/dist/values/Value.js.map +1 -0
- package/dist/values/defaultcolors.d.ts +2 -0
- package/dist/values/defaultcolors.d.ts.map +1 -0
- package/dist/values/defaultcolors.js +149 -0
- package/dist/values/defaultcolors.js.map +1 -0
- package/package.json +11 -7
- package/src/animation/{animation.js → Animation.ts} +56 -54
- package/src/animation/{public.js → public.ts} +23 -18
- package/src/{chnobli.js → chnobli.ts} +11 -12
- package/src/property/BasicProperty.ts +91 -0
- package/src/property/ClassProperty.ts +132 -0
- package/src/property/Property.ts +33 -0
- package/src/property/StyleProperty.ts +273 -0
- package/src/property/TransformProperty.ts +56 -0
- package/src/property/TransformXYProperty.ts +88 -0
- package/src/responsive/ResponsiveEvent.ts +60 -0
- package/src/responsive/{testevent.js → TestEvent.ts} +12 -10
- package/src/scroll/{scroll.js → Scroll.ts} +53 -35
- package/src/scroll/ScrollEvent.ts +53 -0
- package/src/scroll/public.ts +20 -0
- package/src/stagger/stagger.ts +45 -0
- package/src/target/{basetarget.js → BaseTarget.old.ts} +25 -26
- package/src/target/DomTarget.ts +281 -0
- package/src/target/Target.ts +48 -0
- package/src/target/{testdomnode.js → TestDomNode.ts} +18 -15
- package/src/tests/{properties.test.js → properties.test.ts} +54 -49
- package/src/tests/{timeline.test.js → timeline.test.ts} +92 -75
- package/src/tests/{timing.test.js → timing.test.ts} +25 -22
- package/src/tests/{usecases.test.js → usecases.test.ts} +13 -10
- package/src/tests/{values.test.js → values.test.ts} +21 -21
- package/src/timeline/{nested.js → Nested.ts} +18 -12
- package/src/timeline/{timeline.js → TimeLine.ts} +100 -60
- package/src/timeline/{public.js → public.ts} +75 -60
- package/src/timing/{ticker.js → AnimationFrameTicker.ts} +36 -21
- package/src/timing/{ease.js → Ease.ts} +6 -5
- package/src/timing/{testticker.js → TestTicker.ts} +27 -24
- package/src/timing/Ticker.ts +11 -0
- package/src/timing/{timing.js → Timing.ts} +72 -63
- package/src/timing/{easing.js → easing.ts} +52 -43
- package/src/utils/{events.js → Events.ts} +12 -11
- package/src/utils/internal.ts +10 -0
- package/src/utils/{motionpath.js → motionpath.ts} +36 -13
- package/src/utils/utils.ts +110 -0
- package/src/values/{colorvalue.js → ColorValue.ts} +46 -47
- package/src/values/StyleValue.ts +186 -0
- package/src/values/{value.js → Value.ts} +14 -12
- package/src/values/{defaultcolors.js → defaultcolors.ts} +2 -2
- package/tsconfig.build.json +19 -0
- package/tsconfig.json +17 -108
- package/src/animation/property.js +0 -556
- package/src/responsive/event.js +0 -46
- package/src/scroll/event.js +0 -41
- package/src/scroll/public.js +0 -17
- package/src/stagger/stagger.js +0 -42
- package/src/target/domtarget.js +0 -266
- package/src/target/target.js +0 -22
- package/src/utils/internal.js +0 -7
- package/src/utils/utils.js +0 -107
- package/src/values/stylevalue.js +0 -148
|
@@ -1,19 +1,44 @@
|
|
|
1
|
-
function catmullRom(
|
|
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 (
|
|
8
|
-
|
|
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(
|
|
15
|
-
|
|
16
|
-
|
|
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 =
|
|
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
|
|
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
|
-
|
|
28
|
-
if (v.startsWith('
|
|
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
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
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
|
|
147
|
-
g = Math.round(hueToRgb(p, q, h) * 255
|
|
148
|
-
b = Math.round(hueToRgb(p, q, h - 1 / 3) * 255
|
|
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
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if (t <
|
|
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
|
-
|
|
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
|
-
|
|
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
|
+
}
|