@vanillaskyai/video 0.8.8 → 0.9.0
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/CHANGELOG.md +30 -0
- package/PUBLIC-API.md +5 -8
- package/dist/{builtin-server-CUYPIDE7.js → builtin-server-HW6HGXCZ.js} +2 -2
- package/dist/{catalog-types-BIhSpOWK.d.ts → catalog-types-WTbLP6Jh.d.ts} +5 -1
- package/dist/chapter-title-YRLIQY3V.js +7 -0
- package/dist/check-runtime.js +6 -15
- package/dist/{chunk-2USVB3CY.js → chunk-3ZTEFJIR.js} +285 -178
- package/dist/chunk-4YM2M62S.js +13 -0
- package/dist/chunk-77VY4O7A.js +390 -0
- package/dist/{chunk-MMUXVA47.js → chunk-7M56IUUX.js} +9 -8
- package/dist/chunk-7NZOMTAL.js +63 -0
- package/dist/{chunk-2DOLF4QN.js → chunk-AUPC6MDK.js} +12 -14
- package/dist/{chunk-352ZZCET.js → chunk-EGVQODKU.js} +2 -2
- package/dist/chunk-EWWCQFTI.js +18 -0
- package/dist/{chunk-MXZSDGZQ.js → chunk-G7IZBBWF.js} +14 -9
- package/dist/{chunk-KT3M7KDL.js → chunk-HKUI5BTB.js} +3 -3
- package/dist/{chunk-LMG3GHLL.js → chunk-IQMYK5DX.js} +29 -3
- package/dist/chunk-LH4BPALA.js +564 -0
- package/dist/{chunk-OWBT45EN.js → chunk-MQILEEXC.js} +1 -1
- package/dist/chunk-MXEYPK7M.js +552 -0
- package/dist/{chunk-AITKH6QT.js → chunk-OR52UMSF.js} +13 -39
- package/dist/{chunk-5SLENAJW.js → chunk-PAJ44TFW.js} +1 -2
- package/dist/{chunk-L7QGGKJ2.js → chunk-PDQFQIQW.js} +1 -1
- package/dist/{chunk-WJ6FLKNC.js → chunk-R3XAOMKP.js} +14 -0
- package/dist/{chunk-2OKB27TG.js → chunk-RXTN2CW6.js} +2 -2
- package/dist/{chunk-XWWLKRNU.js → chunk-TVIU23OM.js} +38 -49
- package/dist/{chunk-224QNWRA.js → chunk-UDIODEDK.js} +1 -5
- package/dist/{chunk-3VRMKFM7.js → chunk-ZDJNFA52.js} +11 -24
- package/dist/cinema-media-YQHSIFDA.js +11 -0
- package/dist/cli.js +18 -9
- package/dist/comparison-RZMMHZR2.js +27 -0
- package/dist/compose-video-TBFTONUC.js +12 -0
- package/dist/editorial-timeline-OZX7OS6G.js +36 -0
- package/dist/{events-BQ6z264n.d.ts → events-B4YCc4vc.d.ts} +1 -1
- package/dist/focus-cards-TJ72BT7U.js +20 -0
- package/dist/index.d.ts +4 -6
- package/dist/index.js +3 -7
- package/dist/key-figure-GYENXKH3.js +20 -0
- package/dist/{kit-tQnCPMOM.d.ts → kit-DrRpdn0p.d.ts} +2 -2
- package/dist/mobile-message-UZUPIKHD.js +49 -0
- package/dist/{preload-media-LJXWKTWG.js → preload-media-CFTZIMZL.js} +1 -1
- package/dist/quote-EW5HQA6H.js +23 -0
- package/dist/react.d.ts +21 -11
- package/dist/react.js +590 -833
- package/dist/scene-video-backdrop-PCTARAAJ.js +7 -0
- package/dist/server.d.ts +7 -8
- package/dist/server.js +91 -74
- package/dist/{system-prompt-RRXIWDDD.js → system-prompt-SYRT5DWM.js} +1 -1
- package/dist/template-catalog.d.ts +257 -16
- package/dist/template-catalog.js +1 -1
- package/dist/templates.d.ts +5 -5
- package/dist/test.d.ts +3 -3
- package/dist/test.js +18 -18
- package/dist/text-stream-LD364KBI.js +9 -0
- package/dist/{types-DWFO6qca.d.ts → types-CdBmNTGD.d.ts} +1 -1
- package/dist/{types-CEh9eUFu.d.ts → types-DdZw4GRQ.d.ts} +17 -48
- package/dist/validate-4OUD2CLX.js +10 -0
- package/docs/architecture.md +1 -1
- package/docs/concepts.md +1 -1
- package/docs/custom-templates.md +13 -28
- package/docs/customization.md +11 -59
- package/docs/getting-started.md +2 -2
- package/docs/immersive-interface.md +3 -4
- package/docs/maintainers/cinematic-migration.md +34 -0
- package/docs/media-and-audio.md +14 -14
- package/docs/motion-and-effects.md +6 -14
- package/docs/persistence.md +3 -3
- package/docs/production.md +11 -9
- package/docs/provider-integration.md +9 -16
- package/docs/reference/design-system.html +1 -1
- package/docs/reference/protocol.md +14 -4
- package/docs/testing.md +1 -1
- package/package.json +6 -3
- package/registry/items/backgrounds.json +1 -1
- package/registry/items/chapterTitle.json +80 -0
- package/registry/items/cinemaMedia.json +136 -0
- package/registry/items/comparison.json +101 -0
- package/registry/items/editorialTimeline.json +105 -0
- package/registry/items/focusCards.json +90 -0
- package/registry/items/keyFigure.json +97 -0
- package/registry/items/mobileMessage.json +153 -0
- package/registry/items/quote.json +94 -0
- package/registry/items/template-context.json +1 -1
- package/registry/items/theme.json +1 -1
- package/starters/video-chat/README.md +24 -26
- package/starters/video-chat/package.json +1 -1
- package/starters/video-chat/providers/video.ts +6 -5
- package/starters/video-chat/stock.ts +35 -151
- package/styles/fonts/OFL.txt +93 -0
- package/styles/fonts/manifest.json +66 -0
- package/styles/fonts/roboto-v51-cyrillic-ext.woff2 +0 -0
- package/styles/fonts/roboto-v51-cyrillic.woff2 +0 -0
- package/styles/fonts/roboto-v51-greek-ext.woff2 +0 -0
- package/styles/fonts/roboto-v51-greek.woff2 +0 -0
- package/styles/fonts/roboto-v51-latin-ext.woff2 +0 -0
- package/styles/fonts/roboto-v51-latin.woff2 +0 -0
- package/styles/fonts/roboto-v51-math.woff2 +0 -0
- package/styles/fonts/roboto-v51-symbols.woff2 +0 -0
- package/styles/fonts/roboto-v51-vietnamese.woff2 +0 -0
- package/styles/fonts/roboto.css +91 -0
- package/styles/video-chat.css +30 -22
- package/dist/bg-confetti-HITCGLGD.js +0 -89
- package/dist/bg-emoji-VU4UZYZN.js +0 -150
- package/dist/bg-media-L34PDQXJ.js +0 -106
- package/dist/brand-message-FUJ4STFO.js +0 -256
- package/dist/chart-bar-EGPHJATL.js +0 -310
- package/dist/chart-counter-5FFWQNZO.js +0 -306
- package/dist/chart-progress-ring-JMXQLMLC.js +0 -302
- package/dist/chunk-4UNKZEAT.js +0 -3575
- package/dist/chunk-5CDAM24P.js +0 -31
- package/dist/chunk-AOWSXU2K.js +0 -18
- package/dist/chunk-CJ7F2CE6.js +0 -104
- package/dist/chunk-FRN6WKHA.js +0 -185
- package/dist/chunk-G5JPHBX7.js +0 -336
- package/dist/chunk-L5BTTCZV.js +0 -97
- package/dist/chunk-P22HHFDK.js +0 -43
- package/dist/chunk-PP3MCPN4.js +0 -1998
- package/dist/chunk-QAAO7OAY.js +0 -19
- package/dist/chunk-S7HFLYNN.js +0 -35
- package/dist/chunk-W3VDIBGR.js +0 -217
- package/dist/chunk-XGRA2MUV.js +0 -242
- package/dist/chunk-XTOXFMLM.js +0 -105
- package/dist/chunk-YJJC4N4D.js +0 -761
- package/dist/compose-video-2NFH4DZY.js +0 -13
- package/dist/cta-logo-YR7LYUR5.js +0 -212
- package/dist/cta-media-DQJBKUO2.js +0 -221
- package/dist/incoming-call-54KQ7O5A.js +0 -323
- package/dist/infographic-before-after-ROS52GOW.js +0 -460
- package/dist/infographic-feature-list-E7MGUDAN.js +0 -272
- package/dist/infographic-problem-solution-3S6NGO5N.js +0 -343
- package/dist/infographic-stat-row-SYB7AB7H.js +0 -247
- package/dist/infographic-steps-KCE6JWE2.js +0 -406
- package/dist/prompt-input-MHX4O42G.js +0 -239
- package/dist/reaction-SLEGR3BE.js +0 -122
- package/dist/scene-video-backdrop-XFPX4O3I.js +0 -10
- package/dist/showcase-code-2HLAVKBM.js +0 -357
- package/dist/showcase-phone-Q4HEO4LH.js +0 -278
- package/dist/showcase-terminal-DL45LUFG.js +0 -312
- package/dist/showcase-web-2QZO73FZ.js +0 -396
- package/dist/social-conversation-75SD2637.js +0 -695
- package/dist/social-milestone-GEFUQSBF.js +0 -296
- package/dist/social-notification-FJ5VHVLK.js +0 -247
- package/dist/social-review-stack-KXQCKFRP.js +0 -242
- package/dist/social-testimonial-JZ7CHC7S.js +0 -287
- package/dist/social-tweet-UCDXM25F.js +0 -298
- package/dist/text-stream-54LXABJW.js +0 -10
- package/dist/validate-T7GBU2YF.js +0 -8
- package/registry/items/barChart.json +0 -245
- package/registry/items/beforeAfter.json +0 -180
- package/registry/items/bigNumber.json +0 -232
- package/registry/items/brandMessage.json +0 -164
- package/registry/items/cardList.json +0 -214
- package/registry/items/chatMessenger.json +0 -151
- package/registry/items/chatWhatsapp.json +0 -151
- package/registry/items/codeEditor.json +0 -191
- package/registry/items/confetti.json +0 -107
- package/registry/items/ctaLogo.json +0 -167
- package/registry/items/ctaMedia.json +0 -200
- package/registry/items/emojiBurst.json +0 -101
- package/registry/items/incomingCall.json +0 -177
- package/registry/items/media.json +0 -187
- package/registry/items/milestone.json +0 -212
- package/registry/items/notification.json +0 -189
- package/registry/items/phoneMockup.json +0 -261
- package/registry/items/problemSolution.json +0 -193
- package/registry/items/progressRing.json +0 -206
- package/registry/items/promptInput.json +0 -155
- package/registry/items/reaction.json +0 -176
- package/registry/items/reviewStack.json +0 -231
- package/registry/items/steps.json +0 -215
- package/registry/items/terminal.json +0 -219
- package/registry/items/testimonial.json +0 -171
- package/registry/items/tripleStats.json +0 -235
- package/registry/items/tweet.json +0 -210
- package/registry/items/webMockup.json +0 -280
package/dist/chunk-QAAO7OAY.js
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
// src/visual-system/scene-templates/celebration-particle-timing.ts
|
|
2
|
-
var SECOND_WAVE_INTERVAL = 4;
|
|
3
|
-
var SECOND_WAVE_START = 0.33;
|
|
4
|
-
var SECOND_WAVE_DURATION = 1;
|
|
5
|
-
var EXIT_FADE_START = 0.76;
|
|
6
|
-
var EXIT_FADE_END = 0.85;
|
|
7
|
-
function getCelebrationParticleTiming(sceneProgress, particleIndex, durationFactor) {
|
|
8
|
-
if (sceneProgress >= EXIT_FADE_END) return null;
|
|
9
|
-
const isSecondWave = particleIndex % SECOND_WAVE_INTERVAL === 0;
|
|
10
|
-
if (isSecondWave && sceneProgress <= SECOND_WAVE_START) return null;
|
|
11
|
-
const waveProgress = isSecondWave ? (sceneProgress - SECOND_WAVE_START) / SECOND_WAVE_DURATION : sceneProgress;
|
|
12
|
-
const progress = Math.min(1, Math.max(0, waveProgress / durationFactor));
|
|
13
|
-
const opacity = sceneProgress <= EXIT_FADE_START ? 1 : (EXIT_FADE_END - sceneProgress) / (EXIT_FADE_END - EXIT_FADE_START);
|
|
14
|
-
return { progress, opacity };
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export {
|
|
18
|
-
getCelebrationParticleTiming
|
|
19
|
-
};
|
package/dist/chunk-S7HFLYNN.js
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
// src/visual-system/scene-templates/text-utils.ts
|
|
2
|
-
function stripPipe(text) {
|
|
3
|
-
const idx = text.indexOf("|");
|
|
4
|
-
return idx === -1 ? text : text.slice(0, idx);
|
|
5
|
-
}
|
|
6
|
-
function getResponsiveFontSize(text, width, role = "headline", height) {
|
|
7
|
-
const s = height ? Math.min(width, height) / 1080 : width / 1080;
|
|
8
|
-
const words = text.split(/\s+/).filter(Boolean).length;
|
|
9
|
-
const chars = text.length;
|
|
10
|
-
if (role === "subtitle") {
|
|
11
|
-
if (chars > 60) return 24 * s;
|
|
12
|
-
if (chars > 30) return 28 * s;
|
|
13
|
-
return 32 * s;
|
|
14
|
-
}
|
|
15
|
-
if (words <= 2 && chars <= 12) return Math.max(36 * s, 96 * s);
|
|
16
|
-
if (words <= 3 && chars <= 20) return Math.max(36 * s, 80 * s);
|
|
17
|
-
if (words <= 5 && chars <= 35) return Math.max(36 * s, 64 * s);
|
|
18
|
-
if (words <= 8 && chars <= 60) return Math.max(36 * s, 48 * s);
|
|
19
|
-
return 36 * s;
|
|
20
|
-
}
|
|
21
|
-
function fitTextSize(text, baseFontSize, maxWidth, opts) {
|
|
22
|
-
if (!text) return baseFontSize;
|
|
23
|
-
const minScale = opts?.minScale ?? 0.5;
|
|
24
|
-
const charWidthRatio = opts?.charWidthRatio ?? 0.55;
|
|
25
|
-
const estWidth = text.length * baseFontSize * charWidthRatio;
|
|
26
|
-
if (estWidth <= maxWidth) return baseFontSize;
|
|
27
|
-
const scaled = maxWidth / estWidth * baseFontSize;
|
|
28
|
-
return Math.max(scaled, baseFontSize * minScale);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export {
|
|
32
|
-
stripPipe,
|
|
33
|
-
getResponsiveFontSize,
|
|
34
|
-
fitTextSize
|
|
35
|
-
};
|
package/dist/chunk-W3VDIBGR.js
DELETED
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
interpolate
|
|
3
|
-
} from "./chunk-XTOXFMLM.js";
|
|
4
|
-
import {
|
|
5
|
-
darken,
|
|
6
|
-
resolveTokens
|
|
7
|
-
} from "./chunk-XWWLKRNU.js";
|
|
8
|
-
|
|
9
|
-
// src/visual-system/theme/colors.ts
|
|
10
|
-
function withOpacity(hex, opacity) {
|
|
11
|
-
const match = hex.match(/^#([0-9a-f]{3,8})$/i);
|
|
12
|
-
if (!match) return hex;
|
|
13
|
-
const h = match[1];
|
|
14
|
-
let r;
|
|
15
|
-
let g;
|
|
16
|
-
let b;
|
|
17
|
-
if (h.length === 3) {
|
|
18
|
-
r = parseInt(h[0] + h[0], 16);
|
|
19
|
-
g = parseInt(h[1] + h[1], 16);
|
|
20
|
-
b = parseInt(h[2] + h[2], 16);
|
|
21
|
-
} else if (h.length >= 6) {
|
|
22
|
-
r = parseInt(h.slice(0, 2), 16);
|
|
23
|
-
g = parseInt(h.slice(2, 4), 16);
|
|
24
|
-
b = parseInt(h.slice(4, 6), 16);
|
|
25
|
-
} else {
|
|
26
|
-
return hex;
|
|
27
|
-
}
|
|
28
|
-
return `rgba(${r},${g},${b},${opacity})`;
|
|
29
|
-
}
|
|
30
|
-
function orderDarkToLight(a, b) {
|
|
31
|
-
const luminance = (hex) => {
|
|
32
|
-
const match = hex.match(/^#([0-9a-f]{6})$/i);
|
|
33
|
-
if (!match) return 0;
|
|
34
|
-
const h = match[1];
|
|
35
|
-
return 0.299 * parseInt(h.slice(0, 2), 16) + 0.587 * parseInt(h.slice(2, 4), 16) + 0.114 * parseInt(h.slice(4, 6), 16);
|
|
36
|
-
};
|
|
37
|
-
return luminance(a) <= luminance(b) ? [a, b] : [b, a];
|
|
38
|
-
}
|
|
39
|
-
function relativeLuminance(hex) {
|
|
40
|
-
const match = hex.match(/^#([0-9a-f]{3}|[0-9a-f]{6}|[0-9a-f]{8})$/i);
|
|
41
|
-
if (!match) return void 0;
|
|
42
|
-
const value = match[1].length === 3 ? match[1].split("").map((character) => character + character).join("") : match[1].slice(0, 6);
|
|
43
|
-
const channel = (offset) => {
|
|
44
|
-
const encoded = Number.parseInt(value.slice(offset, offset + 2), 16) / 255;
|
|
45
|
-
return encoded <= 0.04045 ? encoded / 12.92 : ((encoded + 0.055) / 1.055) ** 2.4;
|
|
46
|
-
};
|
|
47
|
-
return 0.2126 * channel(0) + 0.7152 * channel(2) + 0.0722 * channel(4);
|
|
48
|
-
}
|
|
49
|
-
function contrastRatio(first, second) {
|
|
50
|
-
const firstLuminance = relativeLuminance(first);
|
|
51
|
-
const secondLuminance = relativeLuminance(second);
|
|
52
|
-
if (firstLuminance == null || secondLuminance == null) return 0;
|
|
53
|
-
return (Math.max(firstLuminance, secondLuminance) + 0.05) / (Math.min(firstLuminance, secondLuminance) + 0.05);
|
|
54
|
-
}
|
|
55
|
-
function accessibleTextColor(background, preferred) {
|
|
56
|
-
if (preferred && contrastRatio(background, preferred) >= 4.5) return preferred;
|
|
57
|
-
return contrastRatio(background, "#FFFFFF") >= contrastRatio(background, "#000000") ? "#FFFFFF" : "#000000";
|
|
58
|
-
}
|
|
59
|
-
function autoTextColor(background) {
|
|
60
|
-
return accessibleTextColor(background);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
// src/visual-system/scene-templates/color-utils.ts
|
|
64
|
-
import React from "react";
|
|
65
|
-
var TOP_TEXT_AREA_RATIO = 0.32;
|
|
66
|
-
function gradientBackground({
|
|
67
|
-
colorA,
|
|
68
|
-
colorB,
|
|
69
|
-
solidBg,
|
|
70
|
-
progress,
|
|
71
|
-
sceneDuration,
|
|
72
|
-
seed,
|
|
73
|
-
family
|
|
74
|
-
}) {
|
|
75
|
-
if (solidBg) return solidBg;
|
|
76
|
-
const normalizedProgress = Math.max(0, Math.min(1, progress));
|
|
77
|
-
const atBoundary = normalizedProgress === 0 || normalizedProgress === 1;
|
|
78
|
-
const easedLoop = normalizedProgress * normalizedProgress * (3 - 2 * normalizedProgress);
|
|
79
|
-
const seedEnvelope = atBoundary ? 0 : Math.sin(normalizedProgress * Math.PI) ** 2;
|
|
80
|
-
void sceneDuration;
|
|
81
|
-
const seededRandom = (s) => {
|
|
82
|
-
const x = Math.sin(s * 12.9898 + s * 78.233) * 43758.5453;
|
|
83
|
-
return x - Math.floor(x);
|
|
84
|
-
};
|
|
85
|
-
const phase = seededRandom(seed) * Math.PI * 2 * seedEnvelope;
|
|
86
|
-
const t = (atBoundary ? 0 : easedLoop * Math.PI * 2) + phase;
|
|
87
|
-
const [topColor, bottomColor] = orderDarkToLight(colorA, colorB);
|
|
88
|
-
if (family === "wash") {
|
|
89
|
-
const shift = Math.sin(t) * 6;
|
|
90
|
-
return `linear-gradient(${175 + shift}deg, ${topColor} 0%, ${bottomColor} 100%)`;
|
|
91
|
-
}
|
|
92
|
-
if (family === "spotlight") {
|
|
93
|
-
const x = 50 + Math.sin(t) * 8;
|
|
94
|
-
const y = 28 + Math.cos(t + 1) * 5;
|
|
95
|
-
return `
|
|
96
|
-
radial-gradient(ellipse 70% 55% at ${x}% ${y}%, ${colorA}66 0%, ${colorA}1a 45%, transparent 72%),
|
|
97
|
-
linear-gradient(180deg, ${darken(topColor, 0.55)} 0%, ${darken(bottomColor, 0.7)} 100%)
|
|
98
|
-
`;
|
|
99
|
-
}
|
|
100
|
-
const x1 = 25 + Math.sin(t) * 25;
|
|
101
|
-
const y1 = 30 + Math.cos(t + 1) * 25;
|
|
102
|
-
const x2 = 75 + Math.sin(t + 2) * 25;
|
|
103
|
-
const y2 = 70 + Math.cos(t + 3.5) * 25;
|
|
104
|
-
return `
|
|
105
|
-
radial-gradient(ellipse 60% 60% at ${x1}% ${y1}%, ${colorA}4d 0%, transparent 65%),
|
|
106
|
-
radial-gradient(ellipse 60% 60% at ${x2}% ${y2}%, ${colorB}4d 0%, transparent 65%),
|
|
107
|
-
linear-gradient(180deg, ${topColor} 0%, ${bottomColor} 100%)
|
|
108
|
-
`;
|
|
109
|
-
}
|
|
110
|
-
var BrandGradientOverlay = ({ style: globalStyle, progress, sceneDuration, seed }) => {
|
|
111
|
-
const tokens = resolveTokens(globalStyle);
|
|
112
|
-
const [first, second] = tokens.background.type === "gradient" ? tokens.background.colors : [tokens.background.color, tokens.background.color];
|
|
113
|
-
const solidBg = tokens.background.type === "solid" ? tokens.background.color : void 0;
|
|
114
|
-
return React.createElement("div", {
|
|
115
|
-
"data-brand-gradient": "true",
|
|
116
|
-
style: {
|
|
117
|
-
position: "absolute",
|
|
118
|
-
inset: 0,
|
|
119
|
-
background: gradientBackground({ colorA: first, colorB: second, solidBg, progress, sceneDuration, seed, family: tokens.preset.background }),
|
|
120
|
-
pointerEvents: "none"
|
|
121
|
-
}
|
|
122
|
-
});
|
|
123
|
-
};
|
|
124
|
-
|
|
125
|
-
// src/visual-system/scene-templates/background-effect.ts
|
|
126
|
-
var DIRECTIONS = ["right", "left", "up", "down"];
|
|
127
|
-
function getKenBurnsTransform(progress, direction) {
|
|
128
|
-
const scale = interpolate(progress, [0, 1], [1.05, 1.15]);
|
|
129
|
-
const mainAxis = direction === "right" || direction === "left";
|
|
130
|
-
const sign = direction === "right" || direction === "down" ? 1 : -1;
|
|
131
|
-
const primary = interpolate(progress, [0, 1], [-2 * sign, 2 * sign]);
|
|
132
|
-
const secondary = interpolate(progress, [0, 1], [-0.5, 0.5]);
|
|
133
|
-
const x = mainAxis ? primary : secondary;
|
|
134
|
-
const y = mainAxis ? secondary : primary;
|
|
135
|
-
return {
|
|
136
|
-
transform: `scale(${scale}) translate(${x}%, ${y}%)`,
|
|
137
|
-
transformOrigin: "center"
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
function getDriftTransform(progress, direction) {
|
|
141
|
-
const horizontal = direction === "right" || direction === "left";
|
|
142
|
-
const sign = direction === "right" || direction === "down" ? 1 : -1;
|
|
143
|
-
const offset = interpolate(progress, [0, 1], [-2 * sign, 2 * sign]);
|
|
144
|
-
return {
|
|
145
|
-
transform: horizontal ? `scale(1.1) translateX(${offset}%)` : `scale(1.1) translateY(${offset}%)`,
|
|
146
|
-
transformOrigin: "center"
|
|
147
|
-
};
|
|
148
|
-
}
|
|
149
|
-
function getBackgroundTransform(effect, progress, beatIntensity = 0, sceneIndex = 0) {
|
|
150
|
-
const dir = DIRECTIONS[sceneIndex % DIRECTIONS.length];
|
|
151
|
-
const resolved = effect ?? "static";
|
|
152
|
-
switch (resolved) {
|
|
153
|
-
case "slow-zoom-in":
|
|
154
|
-
return {
|
|
155
|
-
transform: `scale(${interpolate(progress, [0, 1], [1, 1.12])})`,
|
|
156
|
-
transformOrigin: "center"
|
|
157
|
-
};
|
|
158
|
-
case "slow-zoom-out":
|
|
159
|
-
return {
|
|
160
|
-
transform: `scale(${interpolate(progress, [0, 1], [1.12, 1])})`,
|
|
161
|
-
transformOrigin: "center"
|
|
162
|
-
};
|
|
163
|
-
case "ken-burns":
|
|
164
|
-
return getKenBurnsTransform(progress, dir);
|
|
165
|
-
case "drift":
|
|
166
|
-
return getDriftTransform(progress, dir);
|
|
167
|
-
case "pulse": {
|
|
168
|
-
const base = 1 + beatIntensity * 0.04;
|
|
169
|
-
const breathe = 1 + Math.sin(progress * Math.PI * 2) * 0.02;
|
|
170
|
-
return {
|
|
171
|
-
transform: `scale(${base * breathe})`,
|
|
172
|
-
transformOrigin: "center"
|
|
173
|
-
};
|
|
174
|
-
}
|
|
175
|
-
case "breathe": {
|
|
176
|
-
const s = 1 + Math.sin(progress * Math.PI) * 0.03;
|
|
177
|
-
const y = Math.sin(progress * Math.PI) * 0.5;
|
|
178
|
-
return {
|
|
179
|
-
transform: `scale(${s}) translateY(${y}%)`,
|
|
180
|
-
transformOrigin: "center"
|
|
181
|
-
};
|
|
182
|
-
}
|
|
183
|
-
case "slow-tilt": {
|
|
184
|
-
const angle = interpolate(progress, [0, 1], [0, 2.5]);
|
|
185
|
-
return {
|
|
186
|
-
transform: `scale(1.08) rotate(${angle}deg)`,
|
|
187
|
-
transformOrigin: "center"
|
|
188
|
-
};
|
|
189
|
-
}
|
|
190
|
-
case "camera-shake": {
|
|
191
|
-
const t = progress * 40;
|
|
192
|
-
const sx = Math.sin(t * 2.3) * 0.4 + Math.sin(t * 5.7) * 0.2;
|
|
193
|
-
const sy = Math.cos(t * 3.1) * 0.3 + Math.cos(t * 4.9) * 0.15;
|
|
194
|
-
const sr = Math.sin(t * 1.7) * 0.3;
|
|
195
|
-
return {
|
|
196
|
-
transform: `scale(1.05) translate(${sx}%, ${sy}%) rotate(${sr}deg)`,
|
|
197
|
-
transformOrigin: "center"
|
|
198
|
-
};
|
|
199
|
-
}
|
|
200
|
-
case "static":
|
|
201
|
-
default:
|
|
202
|
-
return {
|
|
203
|
-
transform: "none",
|
|
204
|
-
transformOrigin: "center"
|
|
205
|
-
};
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
export {
|
|
210
|
-
withOpacity,
|
|
211
|
-
accessibleTextColor,
|
|
212
|
-
autoTextColor,
|
|
213
|
-
TOP_TEXT_AREA_RATIO,
|
|
214
|
-
gradientBackground,
|
|
215
|
-
BrandGradientOverlay,
|
|
216
|
-
getBackgroundTransform
|
|
217
|
-
};
|
package/dist/chunk-XGRA2MUV.js
DELETED
|
@@ -1,242 +0,0 @@
|
|
|
1
|
-
// src/protocol/background.ts
|
|
2
|
-
var BACKGROUND_PRESETS = {
|
|
3
|
-
cosmic: { type: "gradient", colors: ["#8711C1", "#2167E3"] },
|
|
4
|
-
horizon: { type: "gradient", colors: ["#5967C4", "#133A94"] },
|
|
5
|
-
twilight: { type: "gradient", colors: ["#0C1740", "#3D1B66"] },
|
|
6
|
-
meadow: { type: "gradient", colors: ["#348756", "#54B6CA"] },
|
|
7
|
-
velvet: { type: "gradient", colors: ["#76030F", "#121B67"] },
|
|
8
|
-
flamingo: { type: "gradient", colors: ["#C72D50", "#3E3B92"] },
|
|
9
|
-
peach: { type: "gradient", colors: ["#B45A4A", "#AD336D"] },
|
|
10
|
-
saffron: { type: "gradient", colors: ["#F3696E", "#F8A902"] },
|
|
11
|
-
black: { type: "solid", color: "#000000" },
|
|
12
|
-
midnight: { type: "solid", color: "#070B20" },
|
|
13
|
-
aubergine: { type: "solid", color: "#170A2E" },
|
|
14
|
-
coal: { type: "solid", color: "#0A0A0A" },
|
|
15
|
-
navy: { type: "solid", color: "#0A2240" }
|
|
16
|
-
};
|
|
17
|
-
var DEFAULT_BACKGROUND_PRESET = "cosmic";
|
|
18
|
-
var DEFAULT_COLORS = {
|
|
19
|
-
primary: "#00E5A0",
|
|
20
|
-
secondary: "#006BE5",
|
|
21
|
-
foreground: "#FFFFFF",
|
|
22
|
-
surface: "#0A0A14",
|
|
23
|
-
surfaceElevated: "#14152A",
|
|
24
|
-
muted: "#A7A6B0"
|
|
25
|
-
};
|
|
26
|
-
var HEX_COLOR = /^#[0-9a-f]{6}$/i;
|
|
27
|
-
var MINIMUM_TEXT_CONTRAST = 4.5;
|
|
28
|
-
function normalizeColor(value, path) {
|
|
29
|
-
if (!HEX_COLOR.test(value)) throw new Error(`${path} must be a hex color`);
|
|
30
|
-
return value.toUpperCase();
|
|
31
|
-
}
|
|
32
|
-
function resolveBackground(input) {
|
|
33
|
-
if (input == null || typeof input === "string") {
|
|
34
|
-
const preset = BACKGROUND_PRESETS[input ?? DEFAULT_BACKGROUND_PRESET];
|
|
35
|
-
return preset.type === "solid" ? { type: "solid", color: preset.color } : { type: "gradient", colors: [...preset.colors] };
|
|
36
|
-
}
|
|
37
|
-
if ("color" in input) {
|
|
38
|
-
return { type: "solid", color: normalizeColor(input.color, "brand.background.color") };
|
|
39
|
-
}
|
|
40
|
-
return {
|
|
41
|
-
type: "gradient",
|
|
42
|
-
colors: [
|
|
43
|
-
normalizeColor(input.colors[0], "brand.background.colors[0]"),
|
|
44
|
-
normalizeColor(input.colors[1], "brand.background.colors[1]")
|
|
45
|
-
]
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
function channel(value) {
|
|
49
|
-
const normalized = value / 255;
|
|
50
|
-
return normalized <= 0.04045 ? normalized / 12.92 : ((normalized + 0.055) / 1.055) ** 2.4;
|
|
51
|
-
}
|
|
52
|
-
function luminance(color) {
|
|
53
|
-
return 0.2126 * channel(Number.parseInt(color.slice(1, 3), 16)) + 0.7152 * channel(Number.parseInt(color.slice(3, 5), 16)) + 0.0722 * channel(Number.parseInt(color.slice(5, 7), 16));
|
|
54
|
-
}
|
|
55
|
-
function gradientLuminanceAt(colors, progress) {
|
|
56
|
-
const channels = colors.map((color) => [1, 3, 5].map((offset) => Number.parseInt(color.slice(offset, offset + 2), 16)));
|
|
57
|
-
return 0.2126 * channel(channels[0][0] + (channels[1][0] - channels[0][0]) * progress) + 0.7152 * channel(channels[0][1] + (channels[1][1] - channels[0][1]) * progress) + 0.0722 * channel(channels[0][2] + (channels[1][2] - channels[0][2]) * progress);
|
|
58
|
-
}
|
|
59
|
-
function backgroundLuminanceRange(background) {
|
|
60
|
-
if (background.type === "solid") {
|
|
61
|
-
const value = luminance(background.color);
|
|
62
|
-
return [value, value];
|
|
63
|
-
}
|
|
64
|
-
const start = luminance(background.colors[0]);
|
|
65
|
-
const end = luminance(background.colors[1]);
|
|
66
|
-
let left = 0;
|
|
67
|
-
let right = 1;
|
|
68
|
-
for (let iteration = 0; iteration < 64; iteration += 1) {
|
|
69
|
-
const first = left + (right - left) / 3;
|
|
70
|
-
const second = right - (right - left) / 3;
|
|
71
|
-
if (gradientLuminanceAt(background.colors, first) <= gradientLuminanceAt(background.colors, second)) {
|
|
72
|
-
right = second;
|
|
73
|
-
} else {
|
|
74
|
-
left = first;
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
const minimum = Math.min(start, end, gradientLuminanceAt(background.colors, (left + right) / 2));
|
|
78
|
-
return [minimum, Math.max(start, end)];
|
|
79
|
-
}
|
|
80
|
-
function minimumBackgroundContrast(background, foreground) {
|
|
81
|
-
const foregroundLuminance = luminance(foreground);
|
|
82
|
-
const [minimum, maximum] = backgroundLuminanceRange(background);
|
|
83
|
-
if (foregroundLuminance < minimum) {
|
|
84
|
-
return (minimum + 0.05) / (foregroundLuminance + 0.05);
|
|
85
|
-
}
|
|
86
|
-
if (foregroundLuminance > maximum) {
|
|
87
|
-
return (foregroundLuminance + 0.05) / (maximum + 0.05);
|
|
88
|
-
}
|
|
89
|
-
return 1;
|
|
90
|
-
}
|
|
91
|
-
function resolveForeground(input, background) {
|
|
92
|
-
const supplied = input?.colors?.foreground;
|
|
93
|
-
if (supplied != null) return normalizeColor(supplied, "brand.colors.foreground");
|
|
94
|
-
const candidates = ["#FFFFFF", "#000000"];
|
|
95
|
-
const foreground = candidates.map((color) => ({ color, contrast: minimumBackgroundContrast(background, color) })).sort((left, right) => right.contrast - left.contrast)[0];
|
|
96
|
-
if (foreground.contrast < MINIMUM_TEXT_CONTRAST) {
|
|
97
|
-
throw new Error(
|
|
98
|
-
"brand.colors.foreground is required because neither black nor white contrasts with the entire background; choose a background with one consistently readable foreground"
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
return foreground.color;
|
|
102
|
-
}
|
|
103
|
-
function validateResolvedBrandContrast(brand, path) {
|
|
104
|
-
const contrast = minimumBackgroundContrast(brand.background, brand.colors.foreground);
|
|
105
|
-
if (contrast < MINIMUM_TEXT_CONTRAST) {
|
|
106
|
-
throw new Error(
|
|
107
|
-
`${path}.colors.foreground must have at least 4.5:1 contrast across ${path}.background (minimum ${contrast.toFixed(2)}:1); choose a different foreground or background)`
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
function resolveVideoBrand(input) {
|
|
112
|
-
validateBrandInput(input, "brand");
|
|
113
|
-
const background = resolveBackground(input?.background);
|
|
114
|
-
const colors = Object.fromEntries(Object.entries({
|
|
115
|
-
...DEFAULT_COLORS,
|
|
116
|
-
...input?.colors,
|
|
117
|
-
foreground: resolveForeground(input, background)
|
|
118
|
-
}).map(([name, value]) => [name, normalizeColor(value, `brand.colors.${name}`)]));
|
|
119
|
-
const brand = {
|
|
120
|
-
...input?.name?.trim() ? { name: input.name.trim() } : {},
|
|
121
|
-
...input?.logoUrl?.trim() ? { logoUrl: input.logoUrl.trim() } : {},
|
|
122
|
-
font: input?.font?.trim() || "Inter",
|
|
123
|
-
scriptFont: input?.scriptFont?.trim() || "Caveat",
|
|
124
|
-
background,
|
|
125
|
-
colors
|
|
126
|
-
};
|
|
127
|
-
validateResolvedBrandContrast(brand, "brand");
|
|
128
|
-
return brand;
|
|
129
|
-
}
|
|
130
|
-
function isBackgroundPreset(value) {
|
|
131
|
-
return Object.prototype.hasOwnProperty.call(BACKGROUND_PRESETS, value);
|
|
132
|
-
}
|
|
133
|
-
function validateBrandBackgroundInput(value, path) {
|
|
134
|
-
if (typeof value === "string") {
|
|
135
|
-
if (!isBackgroundPreset(value)) throw new Error(`${path} preset is unsupported`);
|
|
136
|
-
return;
|
|
137
|
-
}
|
|
138
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
139
|
-
throw new Error(`${path} must be a preset or custom color object`);
|
|
140
|
-
}
|
|
141
|
-
const background = value;
|
|
142
|
-
const keys = Object.keys(background);
|
|
143
|
-
if (keys.length !== 1 || keys[0] !== "color" && keys[0] !== "colors") {
|
|
144
|
-
throw new Error(`${path} must contain either color or colors`);
|
|
145
|
-
}
|
|
146
|
-
if ("color" in background) {
|
|
147
|
-
if (typeof background.color !== "string") throw new Error(`${path}.color must be a hex color`);
|
|
148
|
-
normalizeColor(background.color, `${path}.color`);
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
if (!Array.isArray(background.colors) || background.colors.length !== 2 || background.colors.some((color) => typeof color !== "string")) {
|
|
152
|
-
throw new Error(`${path}.colors must contain two colors`);
|
|
153
|
-
}
|
|
154
|
-
background.colors.forEach((color, index) => normalizeColor(color, `${path}.colors[${index}]`));
|
|
155
|
-
}
|
|
156
|
-
function validateBrandInput(value, path) {
|
|
157
|
-
if (value == null) return;
|
|
158
|
-
if (typeof value !== "object" || Array.isArray(value)) throw new Error(`${path} must be an object`);
|
|
159
|
-
const input = value;
|
|
160
|
-
const allowed = /* @__PURE__ */ new Set(["name", "logoUrl", "font", "scriptFont", "background", "colors"]);
|
|
161
|
-
for (const key of Object.keys(input)) {
|
|
162
|
-
if (!allowed.has(key)) throw new Error(`${path} contains unsupported field ${key}`);
|
|
163
|
-
}
|
|
164
|
-
for (const key of ["name", "logoUrl", "font", "scriptFont"]) {
|
|
165
|
-
if (input[key] != null && (typeof input[key] !== "string" || !input[key].trim())) {
|
|
166
|
-
throw new Error(`${path}.${key} must be a non-empty string`);
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
if (input.background != null) validateBrandBackgroundInput(input.background, `${path}.background`);
|
|
170
|
-
if (input.colors != null) {
|
|
171
|
-
if (typeof input.colors !== "object" || Array.isArray(input.colors)) {
|
|
172
|
-
throw new Error(`${path}.colors must be an object`);
|
|
173
|
-
}
|
|
174
|
-
const colors = input.colors;
|
|
175
|
-
const colorNames = new Set(Object.keys(DEFAULT_COLORS));
|
|
176
|
-
for (const [name, color] of Object.entries(colors)) {
|
|
177
|
-
if (!colorNames.has(name)) throw new Error(`${path}.colors contains unsupported field ${name}`);
|
|
178
|
-
if (typeof color !== "string") throw new Error(`${path}.colors.${name} must be a hex color`);
|
|
179
|
-
normalizeColor(color, `${path}.colors.${name}`);
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
function validateVideoBrand(value, path) {
|
|
184
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
185
|
-
throw new Error(`${path} must be an object`);
|
|
186
|
-
}
|
|
187
|
-
const brand = value;
|
|
188
|
-
const allowed = /* @__PURE__ */ new Set(["name", "logoUrl", "font", "scriptFont", "background", "colors"]);
|
|
189
|
-
for (const key of Object.keys(brand)) {
|
|
190
|
-
if (!allowed.has(key)) throw new Error(`${path} contains unsupported field ${key}`);
|
|
191
|
-
}
|
|
192
|
-
for (const key of ["font", "scriptFont"]) {
|
|
193
|
-
if (typeof brand[key] !== "string" || !brand[key].trim()) {
|
|
194
|
-
throw new Error(`${path}.${key} must be a non-empty string`);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
for (const key of ["name", "logoUrl"]) {
|
|
198
|
-
if (brand[key] != null && (typeof brand[key] !== "string" || !brand[key].trim())) {
|
|
199
|
-
throw new Error(`${path}.${key} must be a non-empty string`);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
if (!brand.background || typeof brand.background !== "object" || Array.isArray(brand.background)) {
|
|
203
|
-
throw new Error(`${path}.background must be an object`);
|
|
204
|
-
}
|
|
205
|
-
const background = brand.background;
|
|
206
|
-
if (background.type === "solid") {
|
|
207
|
-
if (Object.keys(background).some((key) => key !== "type" && key !== "color")) {
|
|
208
|
-
throw new Error(`${path}.background contains unsupported fields`);
|
|
209
|
-
}
|
|
210
|
-
if (typeof background.color !== "string") throw new Error(`${path}.background.color must be a hex color`);
|
|
211
|
-
normalizeColor(background.color, `${path}.background.color`);
|
|
212
|
-
} else if (background.type === "gradient") {
|
|
213
|
-
if (Object.keys(background).some((key) => key !== "type" && key !== "colors")) {
|
|
214
|
-
throw new Error(`${path}.background contains unsupported fields`);
|
|
215
|
-
}
|
|
216
|
-
if (!Array.isArray(background.colors) || background.colors.length !== 2 || background.colors.some((color) => typeof color !== "string")) {
|
|
217
|
-
throw new Error(`${path}.background.colors must contain two colors`);
|
|
218
|
-
}
|
|
219
|
-
background.colors.forEach((color, index) => normalizeColor(color, `${path}.background.colors[${index}]`));
|
|
220
|
-
} else {
|
|
221
|
-
throw new Error(`${path}.background.type is unsupported`);
|
|
222
|
-
}
|
|
223
|
-
if (!brand.colors || typeof brand.colors !== "object" || Array.isArray(brand.colors)) {
|
|
224
|
-
throw new Error(`${path}.colors must be an object`);
|
|
225
|
-
}
|
|
226
|
-
const colors = brand.colors;
|
|
227
|
-
const requiredColors = Object.keys(DEFAULT_COLORS);
|
|
228
|
-
for (const name of requiredColors) {
|
|
229
|
-
if (typeof colors[name] !== "string") throw new Error(`${path}.colors.${name} must be a hex color`);
|
|
230
|
-
normalizeColor(colors[name], `${path}.colors.${name}`);
|
|
231
|
-
}
|
|
232
|
-
for (const name of Object.keys(colors)) {
|
|
233
|
-
if (!requiredColors.includes(name)) throw new Error(`${path}.colors contains unsupported field ${name}`);
|
|
234
|
-
}
|
|
235
|
-
validateResolvedBrandContrast(brand, path);
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
export {
|
|
239
|
-
resolveVideoBrand,
|
|
240
|
-
validateBrandInput,
|
|
241
|
-
validateVideoBrand
|
|
242
|
-
};
|
package/dist/chunk-XTOXFMLM.js
DELETED
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
// src/visual-system/motion/curves.ts
|
|
2
|
-
function cubicBezier(x1, y1, x2, y2) {
|
|
3
|
-
const cx = 3 * x1;
|
|
4
|
-
const bx = 3 * (x2 - x1) - cx;
|
|
5
|
-
const ax = 1 - cx - bx;
|
|
6
|
-
const cy = 3 * y1;
|
|
7
|
-
const by = 3 * (y2 - y1) - cy;
|
|
8
|
-
const ay = 1 - cy - by;
|
|
9
|
-
const sampleX = (t) => ((ax * t + bx) * t + cx) * t;
|
|
10
|
-
const sampleY = (t) => ((ay * t + by) * t + cy) * t;
|
|
11
|
-
const sampleDX = (t) => (3 * ax * t + 2 * bx) * t + cx;
|
|
12
|
-
return (x) => {
|
|
13
|
-
if (x <= 0) return 0;
|
|
14
|
-
if (x >= 1) return 1;
|
|
15
|
-
let t = x;
|
|
16
|
-
for (let i = 0; i < 8; i++) {
|
|
17
|
-
const err = sampleX(t) - x;
|
|
18
|
-
if (Math.abs(err) < 1e-6) return sampleY(t);
|
|
19
|
-
const d = sampleDX(t);
|
|
20
|
-
if (Math.abs(d) < 1e-6) break;
|
|
21
|
-
t -= err / d;
|
|
22
|
-
}
|
|
23
|
-
let lo = 0;
|
|
24
|
-
let hi = 1;
|
|
25
|
-
t = x;
|
|
26
|
-
for (let i = 0; i < 24; i++) {
|
|
27
|
-
const v = sampleX(t);
|
|
28
|
-
if (Math.abs(v - x) < 1e-6) break;
|
|
29
|
-
if (v < x) lo = t;
|
|
30
|
-
else hi = t;
|
|
31
|
-
t = (lo + hi) / 2;
|
|
32
|
-
}
|
|
33
|
-
return sampleY(t);
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
var Easing = {
|
|
37
|
-
/** Easing.bezier(0.16, 1, 0.3, 1) — the canonical curve syntax from docs/motion-library.md. */
|
|
38
|
-
bezier: cubicBezier,
|
|
39
|
-
// Curves
|
|
40
|
-
linear: (t) => t,
|
|
41
|
-
quad: (t) => t * t,
|
|
42
|
-
cubic: (t) => t * t * t,
|
|
43
|
-
sin: (t) => 1 - Math.cos(t * Math.PI / 2),
|
|
44
|
-
exp: (t) => t === 0 ? 0 : Math.pow(2, 10 * (t - 1)),
|
|
45
|
-
circle: (t) => 1 - Math.sqrt(1 - t * t),
|
|
46
|
-
// Directional modifiers
|
|
47
|
-
in: (fn) => fn,
|
|
48
|
-
out: (fn) => (t) => 1 - fn(1 - t),
|
|
49
|
-
inOut: (fn) => (t) => t < 0.5 ? fn(t * 2) / 2 : 1 - fn((1 - t) * 2) / 2
|
|
50
|
-
};
|
|
51
|
-
function interpolate(value, inputRange, outputRange, options) {
|
|
52
|
-
const { easing, extrapolateLeft = "extend", extrapolateRight = "extend" } = options ?? {};
|
|
53
|
-
let i = 0;
|
|
54
|
-
for (; i < inputRange.length - 2; i++) {
|
|
55
|
-
if (value < inputRange[i + 1]) break;
|
|
56
|
-
}
|
|
57
|
-
const inputMin = inputRange[i];
|
|
58
|
-
const inputMax = inputRange[i + 1];
|
|
59
|
-
const outputMin = outputRange[i];
|
|
60
|
-
const outputMax = outputRange[i + 1];
|
|
61
|
-
let t = inputMax === inputMin ? 0 : (value - inputMin) / (inputMax - inputMin);
|
|
62
|
-
if (t < 0 && extrapolateLeft === "clamp") t = 0;
|
|
63
|
-
if (t > 1 && extrapolateRight === "clamp") t = 1;
|
|
64
|
-
if (easing && t >= 0 && t <= 1) {
|
|
65
|
-
t = easing(t);
|
|
66
|
-
}
|
|
67
|
-
return outputMin + t * (outputMax - outputMin);
|
|
68
|
-
}
|
|
69
|
-
var SPRING_SMOOTH = { damping: 26, stiffness: 170 };
|
|
70
|
-
var SPRING_SNAPPY = { damping: 20, stiffness: 300 };
|
|
71
|
-
var SPRING_BOUNCY = { damping: 10, stiffness: 180 };
|
|
72
|
-
var SPRING_CRISP = { damping: 14, stiffness: 320 };
|
|
73
|
-
function spring(progress, config) {
|
|
74
|
-
if (progress <= 0) return 0;
|
|
75
|
-
if (progress >= 1) {
|
|
76
|
-
const { damping: damping2 = 26 } = config ?? {};
|
|
77
|
-
if (damping2 >= 20) return 1;
|
|
78
|
-
}
|
|
79
|
-
const { damping = 26, stiffness = 170, mass = 1 } = config ?? {};
|
|
80
|
-
const omega = Math.sqrt(stiffness / mass);
|
|
81
|
-
const zeta = damping / (2 * Math.sqrt(stiffness * mass));
|
|
82
|
-
const t = progress * 3.5;
|
|
83
|
-
let value;
|
|
84
|
-
if (zeta < 1) {
|
|
85
|
-
const omegaD = omega * Math.sqrt(1 - zeta * zeta);
|
|
86
|
-
value = 1 - Math.exp(-zeta * omega * t) * (Math.cos(omegaD * t) + zeta * omega / omegaD * Math.sin(omegaD * t));
|
|
87
|
-
} else if (zeta === 1) {
|
|
88
|
-
value = 1 - Math.exp(-omega * t) * (1 + omega * t);
|
|
89
|
-
} else {
|
|
90
|
-
const s1 = -omega * (zeta + Math.sqrt(zeta * zeta - 1));
|
|
91
|
-
const s2 = -omega * (zeta - Math.sqrt(zeta * zeta - 1));
|
|
92
|
-
value = 1 + (s1 * Math.exp(s2 * t) - s2 * Math.exp(s1 * t)) / (s2 - s1);
|
|
93
|
-
}
|
|
94
|
-
return value;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export {
|
|
98
|
-
Easing,
|
|
99
|
-
interpolate,
|
|
100
|
-
SPRING_SMOOTH,
|
|
101
|
-
SPRING_SNAPPY,
|
|
102
|
-
SPRING_BOUNCY,
|
|
103
|
-
SPRING_CRISP,
|
|
104
|
-
spring
|
|
105
|
-
};
|