summaryrefslogtreecommitdiff
path: root/apps/web/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/lib')
-rw-r--r--apps/web/src/lib/animation/color-channel.ts19
-rw-r--r--apps/web/src/lib/animation/index.ts1
-rw-r--r--apps/web/src/lib/animation/interpolation.ts2
-rw-r--r--apps/web/src/lib/animation/property-registry.ts52
-rw-r--r--apps/web/src/lib/animation/resolve.ts23
5 files changed, 85 insertions, 12 deletions
diff --git a/apps/web/src/lib/animation/color-channel.ts b/apps/web/src/lib/animation/color-channel.ts
new file mode 100644
index 00000000..2a340f94
--- /dev/null
+++ b/apps/web/src/lib/animation/color-channel.ts
@@ -0,0 +1,19 @@
+import type {
+ AnimationPropertyPath,
+ ColorAnimationChannel,
+ ElementAnimations,
+} from "@/types/animation";
+
+export function getColorChannelForPath({
+ animations,
+ propertyPath,
+}: {
+ animations: ElementAnimations | undefined;
+ propertyPath: AnimationPropertyPath;
+}): ColorAnimationChannel | undefined {
+ const channel = animations?.channels[propertyPath];
+ if (!channel || channel.valueKind !== "color") {
+ return undefined;
+ }
+ return channel;
+}
diff --git a/apps/web/src/lib/animation/index.ts b/apps/web/src/lib/animation/index.ts
index c41c1a7e..f6a0b974 100644
--- a/apps/web/src/lib/animation/index.ts
+++ b/apps/web/src/lib/animation/index.ts
@@ -17,6 +17,7 @@ export {
export {
getElementLocalTime,
+ resolveColorAtTime,
resolveOpacityAtTime,
resolveTransformAtTime,
resolveVolumeAtTime,
diff --git a/apps/web/src/lib/animation/interpolation.ts b/apps/web/src/lib/animation/interpolation.ts
index d3f68010..7a6fc6cf 100644
--- a/apps/web/src/lib/animation/interpolation.ts
+++ b/apps/web/src/lib/animation/interpolation.ts
@@ -277,7 +277,7 @@ export function getNumberChannelValueAtTime({
});
}
-function getColorValueAtTime({
+export function getColorValueAtTime({
channel,
time,
fallbackValue,
diff --git a/apps/web/src/lib/animation/property-registry.ts b/apps/web/src/lib/animation/property-registry.ts
index 44f5d638..69757d49 100644
--- a/apps/web/src/lib/animation/property-registry.ts
+++ b/apps/web/src/lib/animation/property-registry.ts
@@ -19,13 +19,13 @@ interface AnimationPropertyDefinition {
defaultInterpolation: AnimationInterpolation;
numericRange?: NumericRange;
supportsElement: ({ element }: { element: TimelineElement }) => boolean;
- getValue: ({ element }: { element: TimelineElement }) => number | null;
+ getValue: ({ element }: { element: TimelineElement }) => AnimationValue | null;
setValue: ({
element,
value,
}: {
element: TimelineElement;
- value: number;
+ value: AnimationValue;
}) => TimelineElement;
}
@@ -45,7 +45,7 @@ const ANIMATION_PROPERTY_REGISTRY: Record<
...element,
transform: {
...element.transform,
- position: { ...element.transform.position, x: value },
+ position: { ...element.transform.position, x: value as number },
},
}
: element,
@@ -62,7 +62,7 @@ const ANIMATION_PROPERTY_REGISTRY: Record<
...element,
transform: {
...element.transform,
- position: { ...element.transform.position, y: value },
+ position: { ...element.transform.position, y: value as number },
},
}
: element,
@@ -76,7 +76,10 @@ const ANIMATION_PROPERTY_REGISTRY: Record<
isVisualElement(element) ? element.transform.scale : null,
setValue: ({ element, value }) =>
isVisualElement(element)
- ? { ...element, transform: { ...element.transform, scale: value } }
+ ? {
+ ...element,
+ transform: { ...element.transform, scale: value as number },
+ }
: element,
},
"transform.rotate": {
@@ -87,7 +90,10 @@ const ANIMATION_PROPERTY_REGISTRY: Record<
isVisualElement(element) ? element.transform.rotate : null,
setValue: ({ element, value }) =>
isVisualElement(element)
- ? { ...element, transform: { ...element.transform, rotate: value } }
+ ? {
+ ...element,
+ transform: { ...element.transform, rotate: value as number },
+ }
: element,
},
opacity: {
@@ -98,7 +104,9 @@ const ANIMATION_PROPERTY_REGISTRY: Record<
getValue: ({ element }) =>
isVisualElement(element) ? element.opacity : null,
setValue: ({ element, value }) =>
- isVisualElement(element) ? { ...element, opacity: value } : element,
+ isVisualElement(element)
+ ? { ...element, opacity: value as number }
+ : element,
},
volume: {
valueKind: "number",
@@ -108,7 +116,33 @@ const ANIMATION_PROPERTY_REGISTRY: Record<
getValue: ({ element }) =>
element.type === "audio" ? element.volume : null,
setValue: ({ element, value }) =>
- element.type === "audio" ? { ...element, volume: value } : element,
+ element.type === "audio"
+ ? { ...element, volume: value as number }
+ : element,
+ },
+ color: {
+ valueKind: "color",
+ defaultInterpolation: "linear",
+ supportsElement: ({ element }) => element.type === "text",
+ getValue: ({ element }) => (element.type === "text" ? element.color : null),
+ setValue: ({ element, value }) =>
+ element.type === "text"
+ ? { ...element, color: value as string }
+ : element,
+ },
+ "background.color": {
+ valueKind: "color",
+ defaultInterpolation: "linear",
+ supportsElement: ({ element }) => element.type === "text",
+ getValue: ({ element }) =>
+ element.type === "text" ? element.background.color : null,
+ setValue: ({ element, value }) =>
+ element.type === "text"
+ ? {
+ ...element,
+ background: { ...element.background, color: value as string },
+ }
+ : element,
},
};
@@ -163,7 +197,7 @@ export function withElementBaseValueForProperty({
value: AnimationValue;
}): TimelineElement {
const coercedValue = coerceAnimationValueForProperty({ propertyPath, value });
- if (coercedValue === null || typeof coercedValue !== "number") {
+ if (coercedValue === null) {
return element;
}
const definition = getAnimationPropertyDefinition({ propertyPath });
diff --git a/apps/web/src/lib/animation/resolve.ts b/apps/web/src/lib/animation/resolve.ts
index 58f292b1..450ae983 100644
--- a/apps/web/src/lib/animation/resolve.ts
+++ b/apps/web/src/lib/animation/resolve.ts
@@ -1,6 +1,7 @@
-import type { ElementAnimations } from "@/types/animation";
+import type { AnimationPropertyPath, ElementAnimations } from "@/types/animation";
import type { Transform } from "@/types/timeline";
-import { getNumberChannelValueAtTime } from "./interpolation";
+import { getColorValueAtTime, getNumberChannelValueAtTime } from "./interpolation";
+import { getColorChannelForPath } from "./color-channel";
import { getNumberChannelForPath } from "./number-channel";
export function getElementLocalTime({
@@ -91,6 +92,24 @@ export function resolveOpacityAtTime({
});
}
+export function resolveColorAtTime({
+ baseColor,
+ animations,
+ propertyPath,
+ localTime,
+}: {
+ baseColor: string;
+ animations: ElementAnimations | undefined;
+ propertyPath: AnimationPropertyPath;
+ localTime: number;
+}): string {
+ return getColorValueAtTime({
+ channel: getColorChannelForPath({ animations, propertyPath }),
+ time: Math.max(0, localTime),
+ fallbackValue: baseColor,
+ });
+}
+
export function resolveVolumeAtTime({
baseVolume,
animations,