@birdapi/velinstyle 1.2.2 → 1.3.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/README.de.md +18 -4
- package/README.md +42 -7
- package/cli/cli-manifest.json +441 -174
- package/cli/docgen/extract-cli.js +2 -1
- package/cli/docs-generate.js +9 -0
- package/cli/experience.js +173 -0
- package/cli/index.js +1294 -417
- package/cli/motion.js +738 -0
- package/cli/production/extract.js +46 -6
- package/cli/production/report.js +104 -14
- package/cli/production/run.js +44 -1
- package/cli/security.js +190 -0
- package/cli/skills.js +53 -10
- package/cli/transparency.js +140 -41
- package/cli/workflow.js +32 -17
- package/components/velin-theme-toggle.js +15 -1
- package/core/a11y/component-contracts.json +391 -274
- package/core/attributes/registry.js +1 -1
- package/core/motion/analyze.js +38 -0
- package/core/motion/blueprint.js +51 -0
- package/core/motion/composer.js +114 -0
- package/core/motion/data/registry.json +352 -0
- package/core/motion/effects.js +17 -1
- package/core/motion/index.js +112 -9
- package/core/motion/optimize.js +44 -0
- package/core/motion/policy.js +77 -0
- package/core/motion/registry.js +131 -0
- package/core/motion/review.js +59 -0
- package/core/motion/scan.js +150 -0
- package/core/motion/timeline.js +68 -0
- package/core/motion/transitions.js +49 -0
- package/core/motion/triggers.js +168 -0
- package/core/security/checks/fs.js +92 -0
- package/core/security/detect.js +35 -0
- package/core/security/engine.js +116 -0
- package/core/security/index.js +18 -0
- package/core/security/registry.js +85 -0
- package/core/security/report/report.js +113 -0
- package/core/security/rules/ci/index.js +146 -0
- package/core/security/rules/consumer/index.js +174 -0
- package/core/security/rules/deps/index.js +182 -0
- package/core/security/rules/index.js +24 -0
- package/core/security/rules/publish/index.js +230 -0
- package/core/security/rules/repo/index.js +143 -0
- package/core/security/rules/secrets/index.js +133 -0
- package/core/security/score/dependency-health.js +53 -0
- package/core/security/score/release-health.js +66 -0
- package/core/security/score/score.js +102 -0
- package/core/security/timeline/timeline.js +76 -0
- package/dist/chunks/attributes-HK7VIOLA.js +1080 -0
- package/dist/chunks/attributes-VRHHVNDO.js +1080 -0
- package/dist/chunks/chunk-MYKUI364.js +116 -0
- package/dist/chunks/chunk-NEVBPD5T.js +116 -0
- package/dist/chunks/runtime-entry.js +1 -1
- package/dist/chunks/velin-theme-toggle-J2NHC7IM.js +304 -0
- package/dist/llms.txt +2 -2
- package/dist/search-index.json +166 -2
- package/dist/velin-agent.json +156 -32
- package/dist/velinstyle-components.iife.js +862 -17
- package/dist/velinstyle-components.js +862 -17
- package/dist/velinstyle-components.min.js +126 -126
- package/dist/velinstyle.css +42 -7
- package/dist/velinstyle.min.css +1 -1
- package/package.json +158 -143
- package/packages/velinstyle-cli-core/package.json +11 -0
- package/packages/velinstyle-cli-core/src/config.js +84 -0
- package/packages/velinstyle-cli-core/src/contract.js +56 -0
- package/packages/velinstyle-cli-core/src/event-bus.js +50 -0
- package/packages/velinstyle-cli-core/src/index.js +18 -0
- package/packages/velinstyle-cli-core/src/lifecycle.js +33 -0
- package/packages/velinstyle-cli-core/src/runner.js +129 -0
- package/packages/velinstyle-cli-registry/data/commands.json +1216 -0
- package/packages/velinstyle-cli-registry/data/layouts.json +33 -0
- package/packages/velinstyle-cli-registry/data/widgets.json +35 -0
- package/packages/velinstyle-cli-registry/package.json +13 -0
- package/packages/velinstyle-cli-registry/src/index.js +88 -0
- package/packages/velinstyle-cli-renderer/package.json +8 -0
- package/packages/velinstyle-cli-renderer/src/index.js +286 -0
- package/packages/velinstyle-cli-theme/package.json +8 -0
- package/packages/velinstyle-cli-theme/src/index.js +84 -0
- package/packages/velinstyle-cli-ui/package.json +8 -0
- package/packages/velinstyle-cli-ui/src/index.js +34 -0
- package/packages/velinstyle-motion/README.md +81 -0
- package/packages/velinstyle-motion/package.json +37 -0
- package/packages/velinstyle-motion/src/ai/mini-prompt.js +119 -0
- package/packages/velinstyle-motion/src/ai/provider.js +59 -0
- package/packages/velinstyle-motion/src/ai/providers/pixverse-setup.js +402 -0
- package/packages/velinstyle-motion/src/ai/providers/pixverse.js +245 -0
- package/packages/velinstyle-motion/src/config.js +257 -0
- package/packages/velinstyle-motion/src/export/html-clip.js +141 -0
- package/packages/velinstyle-motion/src/index.js +304 -0
- package/packages/velinstyle-motion/src/jobs/cache.js +30 -0
- package/packages/velinstyle-motion/src/jobs/queue.js +69 -0
- package/packages/velinstyle-motion/src/jobs/usage.js +53 -0
- package/packages/velinstyle-motion/src/local/effects.js +139 -0
- package/packages/velinstyle-motion/src/local/engine.js +96 -0
- package/packages/velinstyle-motion/src/providers-catalog.js +44 -0
- package/packages/velinstyle-motion/src/registry/presets.js +25 -0
- package/packages/velinstyle-motion/src/registry/presets.json +85 -0
- package/packages/velinstyle-motion/src/ux/cost-gate.js +37 -0
- package/packages/velinstyle-motion/src/ux/pixverse-gate.js +153 -0
- package/packages/velinstyle-motion/src/ux/wizard.js +171 -0
- package/packages/velinstyle-motion/src/validate-image.js +91 -0
- package/packages/velinstyle-skills/catalog.json +1 -1
- package/packages/velinstyle-skills/registry.json +1 -142
- package/packages/velinstyle-skills/skills/velin-motion-reduced-safe/SKILL.md +1 -1
- package/packages/velinstyle-skills/skills/velin-motion-reveal-feedback/SKILL.md +1 -1
- package/src/tokens/motion.css +7 -0
- package/src/utilities/scroll-animation.css +66 -0
|
@@ -2996,6 +2996,13 @@
|
|
|
2996
2996
|
__export(velin_theme_toggle_exports, {
|
|
2997
2997
|
default: () => velin_theme_toggle_default
|
|
2998
2998
|
});
|
|
2999
|
+
function applyColorScheme(target, slug) {
|
|
3000
|
+
const dark = DARK_THEME_SLUGS.has(slug);
|
|
3001
|
+
if (target === document.documentElement || target === document.body) {
|
|
3002
|
+
target.style.colorScheme = dark ? "dark" : "light";
|
|
3003
|
+
}
|
|
3004
|
+
target.setAttribute("data-velin-color-scheme", dark ? "dark" : "light");
|
|
3005
|
+
}
|
|
2999
3006
|
function ensureThemeStylesheet(slug, base) {
|
|
3000
3007
|
if (!slug || BUILTIN_THEMES.has(slug)) return;
|
|
3001
3008
|
if (loadedThemeStylesheets.has(slug)) return;
|
|
@@ -3011,7 +3018,7 @@
|
|
|
3011
3018
|
document.head.appendChild(link);
|
|
3012
3019
|
loadedThemeStylesheets.add(slug);
|
|
3013
3020
|
}
|
|
3014
|
-
var THEMES, BUILTIN_THEMES, loadedThemeStylesheets, styles6, VelinThemeToggle, velin_theme_toggle_default;
|
|
3021
|
+
var THEMES, BUILTIN_THEMES, DARK_THEME_SLUGS, loadedThemeStylesheets, styles6, VelinThemeToggle, velin_theme_toggle_default;
|
|
3015
3022
|
var init_velin_theme_toggle = __esm({
|
|
3016
3023
|
"components/velin-theme-toggle.js"() {
|
|
3017
3024
|
THEMES = [
|
|
@@ -3032,6 +3039,7 @@
|
|
|
3032
3039
|
{ slug: "sunset", label: "Sunset" }
|
|
3033
3040
|
];
|
|
3034
3041
|
BUILTIN_THEMES = /* @__PURE__ */ new Set(["", "dark"]);
|
|
3042
|
+
DARK_THEME_SLUGS = /* @__PURE__ */ new Set(["dark", "midnight", "neon"]);
|
|
3035
3043
|
loadedThemeStylesheets = /* @__PURE__ */ new Set();
|
|
3036
3044
|
styles6 = `
|
|
3037
3045
|
:host { display: inline-flex; position: relative; }
|
|
@@ -3263,6 +3271,7 @@
|
|
|
3263
3271
|
this.setAttribute("theme", normalized === "dark" ? "dark" : normalized);
|
|
3264
3272
|
ensureThemeStylesheet(normalized, this._themesBase);
|
|
3265
3273
|
}
|
|
3274
|
+
applyColorScheme(this._target, normalized);
|
|
3266
3275
|
if (persist) {
|
|
3267
3276
|
if (!normalized) localStorage.removeItem("velin-theme");
|
|
3268
3277
|
else localStorage.setItem("velin-theme", normalized);
|
|
@@ -3270,7 +3279,11 @@
|
|
|
3270
3279
|
this._highlightActive();
|
|
3271
3280
|
this.dispatchEvent(new CustomEvent("velin-theme-change", {
|
|
3272
3281
|
bubbles: true,
|
|
3273
|
-
detail: {
|
|
3282
|
+
detail: {
|
|
3283
|
+
theme: normalized || "light",
|
|
3284
|
+
dark: DARK_THEME_SLUGS.has(normalized),
|
|
3285
|
+
slug: normalized
|
|
3286
|
+
}
|
|
3274
3287
|
}));
|
|
3275
3288
|
}
|
|
3276
3289
|
_syncTogglePressed() {
|
|
@@ -9677,6 +9690,12 @@
|
|
|
9677
9690
|
const classes = /* @__PURE__ */ new Set();
|
|
9678
9691
|
for (const [name, value] of Object.entries(attrs)) {
|
|
9679
9692
|
if (value === "false" || value === "off") continue;
|
|
9693
|
+
if (name === "motion" && value && value !== "true") {
|
|
9694
|
+
const presetKey = value;
|
|
9695
|
+
const mapped2 = EFFECT_MAP[presetKey];
|
|
9696
|
+
if (mapped2) mapped2.forEach((c) => classes.add(c));
|
|
9697
|
+
continue;
|
|
9698
|
+
}
|
|
9680
9699
|
const mapped = EFFECT_MAP[name];
|
|
9681
9700
|
if (mapped) mapped.forEach((c) => classes.add(c));
|
|
9682
9701
|
if (name === "slide" && value && value !== "true" && value !== "") {
|
|
@@ -9710,12 +9729,20 @@
|
|
|
9710
9729
|
"slide-left": ["velin-animate-on-scroll", "velin-animate-on-scroll--slide-left"],
|
|
9711
9730
|
"slide-right": ["velin-animate-on-scroll", "velin-animate-on-scroll--slide-right"],
|
|
9712
9731
|
scale: ["velin-animate-on-scroll", "velin-animate-on-scroll--scale"],
|
|
9732
|
+
zoom: ["velin-animate-on-scroll", "velin-animate-on-scroll--scale"],
|
|
9713
9733
|
parallax: ["velin-parallax"],
|
|
9714
9734
|
"parallax-slow": ["velin-parallax", "velin-parallax--slow"],
|
|
9715
9735
|
hover: ["velin-animate-hover"],
|
|
9716
9736
|
"hover-lift": ["velin-animate-hover"],
|
|
9737
|
+
lift: ["velin-animate-hover"],
|
|
9717
9738
|
flip: ["velin-animate-scale-in"],
|
|
9718
|
-
blur: ["velin-animate-fade-in"]
|
|
9739
|
+
blur: ["velin-animate-fade-in"],
|
|
9740
|
+
pulse: ["velin-animate-pulse"],
|
|
9741
|
+
shake: ["velin-animate-shake"],
|
|
9742
|
+
bounce: ["velin-animate-bounce"],
|
|
9743
|
+
shimmer: ["velin-skeleton"],
|
|
9744
|
+
heroReveal: ["velin-animate-on-scroll", "velin-animate-on-scroll--fade"],
|
|
9745
|
+
fadeOut: ["velin-animate-fade-out"]
|
|
9719
9746
|
};
|
|
9720
9747
|
}
|
|
9721
9748
|
});
|
|
@@ -9778,12 +9805,804 @@
|
|
|
9778
9805
|
}
|
|
9779
9806
|
});
|
|
9780
9807
|
|
|
9808
|
+
// core/motion/data/registry.json
|
|
9809
|
+
var registry_default;
|
|
9810
|
+
var init_registry2 = __esm({
|
|
9811
|
+
"core/motion/data/registry.json"() {
|
|
9812
|
+
registry_default = {
|
|
9813
|
+
schema: "velinstyle.motion.registry",
|
|
9814
|
+
version: 1,
|
|
9815
|
+
presets: [
|
|
9816
|
+
{
|
|
9817
|
+
id: "fade",
|
|
9818
|
+
title: "Fade",
|
|
9819
|
+
description: "Opacity entrance; layout-safe default reveal.",
|
|
9820
|
+
kind: "preset",
|
|
9821
|
+
category: "hero",
|
|
9822
|
+
tags: ["entrance"],
|
|
9823
|
+
duration: 400,
|
|
9824
|
+
fps: "60",
|
|
9825
|
+
reducedMotion: true,
|
|
9826
|
+
layoutSafe: true,
|
|
9827
|
+
status: "stable",
|
|
9828
|
+
cssClass: "velin-animate-on-scroll--fade",
|
|
9829
|
+
compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
9830
|
+
},
|
|
9831
|
+
{
|
|
9832
|
+
id: "slide",
|
|
9833
|
+
title: "Slide Up",
|
|
9834
|
+
description: "Slide from below into view.",
|
|
9835
|
+
kind: "preset",
|
|
9836
|
+
category: "cards",
|
|
9837
|
+
tags: ["entrance", "slide"],
|
|
9838
|
+
duration: 500,
|
|
9839
|
+
fps: "60",
|
|
9840
|
+
reducedMotion: true,
|
|
9841
|
+
layoutSafe: true,
|
|
9842
|
+
status: "stable",
|
|
9843
|
+
cssClass: "velin-animate-on-scroll--slide-up",
|
|
9844
|
+
compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
9845
|
+
},
|
|
9846
|
+
{
|
|
9847
|
+
id: "slide-down",
|
|
9848
|
+
title: "Slide Down",
|
|
9849
|
+
description: "Slide from above into view.",
|
|
9850
|
+
kind: "preset",
|
|
9851
|
+
category: "navigation",
|
|
9852
|
+
tags: ["entrance", "slide"],
|
|
9853
|
+
duration: 500,
|
|
9854
|
+
reducedMotion: true,
|
|
9855
|
+
layoutSafe: true,
|
|
9856
|
+
status: "stable",
|
|
9857
|
+
cssClass: "velin-animate-on-scroll--slide-down",
|
|
9858
|
+
compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
9859
|
+
},
|
|
9860
|
+
{
|
|
9861
|
+
id: "slide-left",
|
|
9862
|
+
title: "Slide Left",
|
|
9863
|
+
description: "Slide from the inline-end.",
|
|
9864
|
+
kind: "preset",
|
|
9865
|
+
category: "lists",
|
|
9866
|
+
tags: ["entrance", "slide"],
|
|
9867
|
+
duration: 500,
|
|
9868
|
+
reducedMotion: true,
|
|
9869
|
+
layoutSafe: true,
|
|
9870
|
+
status: "stable",
|
|
9871
|
+
cssClass: "velin-animate-on-scroll--slide-left",
|
|
9872
|
+
compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
9873
|
+
},
|
|
9874
|
+
{
|
|
9875
|
+
id: "slide-right",
|
|
9876
|
+
title: "Slide Right",
|
|
9877
|
+
description: "Slide from the inline-start.",
|
|
9878
|
+
kind: "preset",
|
|
9879
|
+
category: "lists",
|
|
9880
|
+
tags: ["entrance", "slide"],
|
|
9881
|
+
duration: 500,
|
|
9882
|
+
reducedMotion: true,
|
|
9883
|
+
layoutSafe: true,
|
|
9884
|
+
status: "stable",
|
|
9885
|
+
cssClass: "velin-animate-on-scroll--slide-right",
|
|
9886
|
+
compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
9887
|
+
},
|
|
9888
|
+
{
|
|
9889
|
+
id: "zoom",
|
|
9890
|
+
title: "Zoom / Scale",
|
|
9891
|
+
description: "Scale-in entrance for cards and media.",
|
|
9892
|
+
kind: "preset",
|
|
9893
|
+
category: "media",
|
|
9894
|
+
tags: ["entrance", "scale"],
|
|
9895
|
+
duration: 450,
|
|
9896
|
+
reducedMotion: true,
|
|
9897
|
+
layoutSafe: true,
|
|
9898
|
+
status: "stable",
|
|
9899
|
+
cssClass: "velin-animate-on-scroll--scale",
|
|
9900
|
+
compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
9901
|
+
},
|
|
9902
|
+
{
|
|
9903
|
+
id: "blur",
|
|
9904
|
+
title: "Blur In",
|
|
9905
|
+
description: "Soft fade/blur entrance (maps to fade-in utility).",
|
|
9906
|
+
kind: "preset",
|
|
9907
|
+
category: "overlay",
|
|
9908
|
+
tags: ["entrance"],
|
|
9909
|
+
duration: 500,
|
|
9910
|
+
reducedMotion: true,
|
|
9911
|
+
layoutSafe: true,
|
|
9912
|
+
status: "beta",
|
|
9913
|
+
cssClass: "velin-animate-fade-in",
|
|
9914
|
+
compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
9915
|
+
},
|
|
9916
|
+
{
|
|
9917
|
+
id: "flip",
|
|
9918
|
+
title: "Flip / Scale In",
|
|
9919
|
+
description: "Attention scale-in for emphasis.",
|
|
9920
|
+
kind: "preset",
|
|
9921
|
+
category: "feedback",
|
|
9922
|
+
tags: ["attention"],
|
|
9923
|
+
duration: 400,
|
|
9924
|
+
reducedMotion: true,
|
|
9925
|
+
layoutSafe: true,
|
|
9926
|
+
status: "beta",
|
|
9927
|
+
cssClass: "velin-animate-scale-in",
|
|
9928
|
+
compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
9929
|
+
},
|
|
9930
|
+
{
|
|
9931
|
+
id: "lift",
|
|
9932
|
+
title: "Hover Lift",
|
|
9933
|
+
description: "Subtle lift on hover for interactive cards and buttons.",
|
|
9934
|
+
kind: "preset",
|
|
9935
|
+
category: "buttons",
|
|
9936
|
+
tags: ["hover"],
|
|
9937
|
+
duration: 200,
|
|
9938
|
+
reducedMotion: true,
|
|
9939
|
+
layoutSafe: true,
|
|
9940
|
+
status: "stable",
|
|
9941
|
+
cssClass: "velin-animate-hover",
|
|
9942
|
+
compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
9943
|
+
},
|
|
9944
|
+
{
|
|
9945
|
+
id: "pulse",
|
|
9946
|
+
title: "Pulse",
|
|
9947
|
+
description: "Attention pulse; prefer finite loops under performance policy.",
|
|
9948
|
+
kind: "preset",
|
|
9949
|
+
category: "feedback",
|
|
9950
|
+
tags: ["attention"],
|
|
9951
|
+
duration: 1e3,
|
|
9952
|
+
reducedMotion: true,
|
|
9953
|
+
layoutSafe: true,
|
|
9954
|
+
status: "stable",
|
|
9955
|
+
cssClass: "velin-animate-pulse",
|
|
9956
|
+
compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
9957
|
+
},
|
|
9958
|
+
{
|
|
9959
|
+
id: "shake",
|
|
9960
|
+
title: "Shake",
|
|
9961
|
+
description: "Error/attention shake feedback.",
|
|
9962
|
+
kind: "preset",
|
|
9963
|
+
category: "forms",
|
|
9964
|
+
tags: ["attention", "feedback"],
|
|
9965
|
+
duration: 400,
|
|
9966
|
+
reducedMotion: true,
|
|
9967
|
+
layoutSafe: true,
|
|
9968
|
+
status: "stable",
|
|
9969
|
+
cssClass: "velin-animate-shake",
|
|
9970
|
+
compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
9971
|
+
},
|
|
9972
|
+
{
|
|
9973
|
+
id: "bounce",
|
|
9974
|
+
title: "Bounce",
|
|
9975
|
+
description: "Playful bounce entrance or attention.",
|
|
9976
|
+
kind: "preset",
|
|
9977
|
+
category: "feedback",
|
|
9978
|
+
tags: ["attention"],
|
|
9979
|
+
duration: 600,
|
|
9980
|
+
reducedMotion: true,
|
|
9981
|
+
layoutSafe: true,
|
|
9982
|
+
status: "stable",
|
|
9983
|
+
cssClass: "velin-animate-bounce",
|
|
9984
|
+
compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
9985
|
+
},
|
|
9986
|
+
{
|
|
9987
|
+
id: "shimmer",
|
|
9988
|
+
title: "Shimmer",
|
|
9989
|
+
description: "Loading shimmer surface (skeleton companion).",
|
|
9990
|
+
kind: "preset",
|
|
9991
|
+
category: "loading",
|
|
9992
|
+
tags: ["loading"],
|
|
9993
|
+
duration: 1200,
|
|
9994
|
+
reducedMotion: true,
|
|
9995
|
+
layoutSafe: true,
|
|
9996
|
+
status: "stable",
|
|
9997
|
+
cssClass: "velin-skeleton",
|
|
9998
|
+
compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
9999
|
+
},
|
|
10000
|
+
{
|
|
10001
|
+
id: "heroReveal",
|
|
10002
|
+
title: "Hero Reveal",
|
|
10003
|
+
description: "Staggered entrance for hero content; layout-safe; reduced-motion fallback.",
|
|
10004
|
+
kind: "preset",
|
|
10005
|
+
category: "hero",
|
|
10006
|
+
tags: ["entrance", "stagger"],
|
|
10007
|
+
duration: 600,
|
|
10008
|
+
fps: "60",
|
|
10009
|
+
reducedMotion: true,
|
|
10010
|
+
layoutSafe: true,
|
|
10011
|
+
status: "stable",
|
|
10012
|
+
cssClass: "velin-animate-on-scroll--fade",
|
|
10013
|
+
compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
10014
|
+
},
|
|
10015
|
+
{
|
|
10016
|
+
id: "parallax",
|
|
10017
|
+
title: "Parallax",
|
|
10018
|
+
description: "Scroll-driven parallax shift.",
|
|
10019
|
+
kind: "preset",
|
|
10020
|
+
category: "media",
|
|
10021
|
+
tags: ["scroll"],
|
|
10022
|
+
duration: 0,
|
|
10023
|
+
reducedMotion: true,
|
|
10024
|
+
layoutSafe: false,
|
|
10025
|
+
status: "stable",
|
|
10026
|
+
cssClass: "velin-parallax",
|
|
10027
|
+
compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
10028
|
+
},
|
|
10029
|
+
{
|
|
10030
|
+
id: "fadeOut",
|
|
10031
|
+
title: "Fade Out",
|
|
10032
|
+
description: "Exit fade (planned composition with timelines).",
|
|
10033
|
+
kind: "preset",
|
|
10034
|
+
category: "overlay",
|
|
10035
|
+
tags: ["exit"],
|
|
10036
|
+
duration: 300,
|
|
10037
|
+
reducedMotion: true,
|
|
10038
|
+
layoutSafe: true,
|
|
10039
|
+
status: "beta",
|
|
10040
|
+
cssClass: "velin-animate-fade-out",
|
|
10041
|
+
compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
10042
|
+
}
|
|
10043
|
+
],
|
|
10044
|
+
timelines: [
|
|
10045
|
+
{
|
|
10046
|
+
id: "hero-intro",
|
|
10047
|
+
title: "Hero Intro",
|
|
10048
|
+
description: "Title \u2192 subtitle \u2192 buttons \u2192 image",
|
|
10049
|
+
kind: "timeline",
|
|
10050
|
+
category: "hero",
|
|
10051
|
+
steps: ["title", "subtitle", "buttons", "image"],
|
|
10052
|
+
status: "beta",
|
|
10053
|
+
compatibility: { cssOnly: false, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
10054
|
+
},
|
|
10055
|
+
{
|
|
10056
|
+
id: "card-stagger",
|
|
10057
|
+
title: "Card Stagger",
|
|
10058
|
+
description: "Sequential card entrance labels.",
|
|
10059
|
+
kind: "timeline",
|
|
10060
|
+
category: "cards",
|
|
10061
|
+
steps: ["card-1", "card-2", "card-3"],
|
|
10062
|
+
status: "beta",
|
|
10063
|
+
compatibility: { cssOnly: false, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
10064
|
+
}
|
|
10065
|
+
],
|
|
10066
|
+
transitions: [
|
|
10067
|
+
{
|
|
10068
|
+
id: "cross-fade",
|
|
10069
|
+
title: "Cross Fade",
|
|
10070
|
+
description: "Page/view cross-fade (View Transition friendly).",
|
|
10071
|
+
kind: "transition",
|
|
10072
|
+
category: "page",
|
|
10073
|
+
status: "planned",
|
|
10074
|
+
compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
10075
|
+
},
|
|
10076
|
+
{
|
|
10077
|
+
id: "modal-enter",
|
|
10078
|
+
title: "Modal Enter",
|
|
10079
|
+
description: "Overlay modal entrance transition.",
|
|
10080
|
+
kind: "transition",
|
|
10081
|
+
category: "modal",
|
|
10082
|
+
status: "planned",
|
|
10083
|
+
compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
10084
|
+
},
|
|
10085
|
+
{
|
|
10086
|
+
id: "drawer-enter",
|
|
10087
|
+
title: "Drawer Enter",
|
|
10088
|
+
description: "Drawer slide transition.",
|
|
10089
|
+
kind: "transition",
|
|
10090
|
+
category: "drawer",
|
|
10091
|
+
status: "planned",
|
|
10092
|
+
compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
10093
|
+
}
|
|
10094
|
+
],
|
|
10095
|
+
physics: [
|
|
10096
|
+
{
|
|
10097
|
+
id: "spring",
|
|
10098
|
+
title: "Spring",
|
|
10099
|
+
description: "Spring easing token mapping (runtime simulation later).",
|
|
10100
|
+
kind: "physics",
|
|
10101
|
+
category: "feedback",
|
|
10102
|
+
status: "planned",
|
|
10103
|
+
token: "--velin-ease-spring",
|
|
10104
|
+
compatibility: { cssOnly: true, runtime: false, webComponents: false, studio: true, production: true, review: true, cli: true }
|
|
10105
|
+
},
|
|
10106
|
+
{
|
|
10107
|
+
id: "elastic",
|
|
10108
|
+
title: "Elastic",
|
|
10109
|
+
description: "Elastic easing token mapping.",
|
|
10110
|
+
kind: "physics",
|
|
10111
|
+
category: "feedback",
|
|
10112
|
+
status: "planned",
|
|
10113
|
+
token: "--velin-ease-elastic",
|
|
10114
|
+
compatibility: { cssOnly: true, runtime: false, webComponents: false, studio: true, production: true, review: true, cli: true }
|
|
10115
|
+
}
|
|
10116
|
+
],
|
|
10117
|
+
composers: [
|
|
10118
|
+
{
|
|
10119
|
+
id: "sequence",
|
|
10120
|
+
title: "Sequence Composer",
|
|
10121
|
+
description: "Ordered fade/wait/slide composition API.",
|
|
10122
|
+
kind: "composer",
|
|
10123
|
+
category: "page",
|
|
10124
|
+
status: "planned",
|
|
10125
|
+
compatibility: { cssOnly: false, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true }
|
|
10126
|
+
}
|
|
10127
|
+
],
|
|
10128
|
+
triggers: [
|
|
10129
|
+
{ id: "load", title: "Load", description: "Start when document/module initializes.", kind: "trigger", category: "page", status: "stable", compatibility: { cssOnly: false, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10130
|
+
{ id: "visible", title: "Visible", description: "Start when element enters the viewport (IntersectionObserver).", kind: "trigger", category: "page", status: "stable", compatibility: { cssOnly: false, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10131
|
+
{ id: "hidden", title: "Hidden", description: "Fire when element leaves the viewport. (Planned \u2014 runtime falls back to visible.)", kind: "trigger", category: "page", status: "planned", compatibility: { cssOnly: false, runtime: false, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10132
|
+
{ id: "hover", title: "Hover", description: "Pointer enter / hover.", kind: "trigger", category: "buttons", status: "stable", compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10133
|
+
{ id: "focus", title: "Focus", description: "Keyboard/pointer focus.", kind: "trigger", category: "forms", status: "stable", compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10134
|
+
{ id: "click", title: "Click", description: "Pointer activation.", kind: "trigger", category: "buttons", status: "stable", compatibility: { cssOnly: false, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10135
|
+
{ id: "scroll", title: "Scroll", description: "Scroll-linked or scroll-progress trigger.", kind: "trigger", category: "page", status: "stable", compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10136
|
+
{ id: "idle", title: "Idle", description: "After user idle timeout. (Planned \u2014 runtime falls back to visible.)", kind: "trigger", category: "feedback", status: "planned", compatibility: { cssOnly: false, runtime: false, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10137
|
+
{ id: "media", title: "Media", description: "Match media query condition. (Planned \u2014 runtime falls back to visible.)", kind: "trigger", category: "page", status: "planned", compatibility: { cssOnly: false, runtime: false, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10138
|
+
{ id: "container", title: "Container", description: "Container query / size trigger. (Planned \u2014 runtime falls back to visible.)", kind: "trigger", category: "cards", status: "planned", compatibility: { cssOnly: false, runtime: false, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10139
|
+
{ id: "theme", title: "Theme", description: "Theme change trigger. (Planned \u2014 runtime falls back to visible.)", kind: "trigger", category: "page", status: "planned", compatibility: { cssOnly: false, runtime: false, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10140
|
+
{ id: "custom", title: "Custom", description: "Custom event name via velin-trigger-event. (Planned \u2014 runtime falls back to visible.)", kind: "trigger", category: "page", status: "planned", compatibility: { cssOnly: false, runtime: false, webComponents: true, studio: true, production: true, review: true, cli: true } }
|
|
10141
|
+
],
|
|
10142
|
+
policies: [
|
|
10143
|
+
{ id: "safe", title: "Safe", description: "Default layout-safe motion with capped durations.", kind: "policy", category: "page", status: "stable", maxDurationMs: 800, allowInfinite: false, compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10144
|
+
{ id: "reduced", title: "Reduced", description: "Honors prefers-reduced-motion first; shorten or skip decorative motion.", kind: "policy", category: "page", status: "stable", maxDurationMs: 200, forceReduced: true, compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10145
|
+
{ id: "marketing", title: "Marketing", description: "Expressive hero motion allowed within caps.", kind: "policy", category: "hero", status: "stable", maxDurationMs: 1200, allowInfinite: false, compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10146
|
+
{ id: "minimal", title: "Minimal", description: "Very little motion; feedback only.", kind: "policy", category: "page", status: "stable", maxDurationMs: 300, allowInfinite: false, compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10147
|
+
{ id: "accessibility", title: "Accessibility", description: "Strict reduced-motion + focus-safe interactions.", kind: "policy", category: "page", status: "stable", maxDurationMs: 200, forceReduced: true, compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10148
|
+
{ id: "performance", title: "Performance", description: "FPS-friendly; ban infinite decorative loops.", kind: "policy", category: "page", status: "stable", maxDurationMs: 600, allowInfinite: false, compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10149
|
+
{ id: "disabled", title: "Disabled", description: "All motion off.", kind: "policy", category: "page", status: "stable", disabled: true, compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } }
|
|
10150
|
+
],
|
|
10151
|
+
blueprints: [
|
|
10152
|
+
{ id: "landing", title: "Landing", description: "Hero reveal + staggered sections + CTA hover.", kind: "blueprint", category: "hero", status: "beta", presets: ["heroReveal", "fade", "lift"], timeline: "hero-intro", policy: "marketing", compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10153
|
+
{ id: "dashboard", title: "Dashboard", description: "Minimal card stagger for admin shells.", kind: "blueprint", category: "cards", status: "beta", presets: ["fade", "slide"], timeline: "card-stagger", policy: "minimal", compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10154
|
+
{ id: "pricing", title: "Pricing", description: "Pricing cards with stagger and lift.", kind: "blueprint", category: "cards", status: "beta", presets: ["slide", "lift"], policy: "marketing", compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10155
|
+
{ id: "portfolio", title: "Portfolio", description: "Media zoom + parallax-safe reveals.", kind: "blueprint", category: "media", status: "beta", presets: ["zoom", "fade"], policy: "marketing", compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10156
|
+
{ id: "shop", title: "Shop", description: "Product cards and feedback pulses.", kind: "blueprint", category: "cards", status: "planned", presets: ["fade", "lift"], policy: "safe", compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10157
|
+
{ id: "forum", title: "Forum", description: "List slides and form feedback.", kind: "blueprint", category: "lists", status: "planned", presets: ["slide", "shake"], policy: "safe", compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10158
|
+
{ id: "docs", title: "Docs", description: "Minimal fade for documentation pages.", kind: "blueprint", category: "page", status: "beta", presets: ["fade"], policy: "minimal", compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10159
|
+
{ id: "blog", title: "Blog", description: "Article hero fade and card slides.", kind: "blueprint", category: "hero", status: "planned", presets: ["fade", "slide"], policy: "safe", compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10160
|
+
{ id: "crm", title: "CRM", description: "Table-safe minimal motion.", kind: "blueprint", category: "tables", status: "planned", presets: ["fade"], policy: "performance", compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } },
|
|
10161
|
+
{ id: "login", title: "Login", description: "Form feedback and focus-safe motion.", kind: "blueprint", category: "forms", status: "beta", presets: ["fade", "shake"], policy: "accessibility", compatibility: { cssOnly: true, runtime: true, webComponents: true, studio: true, production: true, review: true, cli: true } }
|
|
10162
|
+
]
|
|
10163
|
+
};
|
|
10164
|
+
}
|
|
10165
|
+
});
|
|
10166
|
+
|
|
10167
|
+
// core/motion/registry.js
|
|
10168
|
+
function loadMotionRegistry(override = null) {
|
|
10169
|
+
if (override) {
|
|
10170
|
+
cached = override;
|
|
10171
|
+
return cached;
|
|
10172
|
+
}
|
|
10173
|
+
return cached || registry_default;
|
|
10174
|
+
}
|
|
10175
|
+
function listMotion(namespace, filter = {}) {
|
|
10176
|
+
const reg = loadMotionRegistry();
|
|
10177
|
+
const key = namespace.endsWith("s") ? namespace : `${namespace}s`;
|
|
10178
|
+
const items = reg[key] || reg[namespace] || [];
|
|
10179
|
+
return items.filter((item) => {
|
|
10180
|
+
if (filter.status && item.status !== filter.status) return false;
|
|
10181
|
+
if (filter.category && item.category !== filter.category) return false;
|
|
10182
|
+
if (filter.tag && !(item.tags || []).includes(filter.tag)) return false;
|
|
10183
|
+
return true;
|
|
10184
|
+
});
|
|
10185
|
+
}
|
|
10186
|
+
function getMotion(namespace, id) {
|
|
10187
|
+
return listMotion(namespace).find((item) => item.id === id) || null;
|
|
10188
|
+
}
|
|
10189
|
+
function getPreset(id) {
|
|
10190
|
+
return getMotion("presets", id);
|
|
10191
|
+
}
|
|
10192
|
+
function getPolicy(id) {
|
|
10193
|
+
return getMotion("policies", id);
|
|
10194
|
+
}
|
|
10195
|
+
function getTrigger(id) {
|
|
10196
|
+
return getMotion("triggers", id);
|
|
10197
|
+
}
|
|
10198
|
+
function getTimeline(id) {
|
|
10199
|
+
return getMotion("timelines", id);
|
|
10200
|
+
}
|
|
10201
|
+
function listPresets(filter) {
|
|
10202
|
+
return listMotion("presets", filter);
|
|
10203
|
+
}
|
|
10204
|
+
function listPolicies(filter) {
|
|
10205
|
+
return listMotion("policies", filter);
|
|
10206
|
+
}
|
|
10207
|
+
function catalogSummary() {
|
|
10208
|
+
const reg = loadMotionRegistry();
|
|
10209
|
+
const counts = {};
|
|
10210
|
+
for (const ns of NAMESPACES) {
|
|
10211
|
+
counts[ns] = (reg[ns] || []).length;
|
|
10212
|
+
}
|
|
10213
|
+
return {
|
|
10214
|
+
schema: reg.schema,
|
|
10215
|
+
version: reg.version,
|
|
10216
|
+
counts,
|
|
10217
|
+
namespaces: NAMESPACES
|
|
10218
|
+
};
|
|
10219
|
+
}
|
|
10220
|
+
function resolvePresetId(id) {
|
|
10221
|
+
if (!id) return null;
|
|
10222
|
+
const direct = getPreset(id);
|
|
10223
|
+
if (direct) return direct;
|
|
10224
|
+
const aliases = {
|
|
10225
|
+
scale: "zoom",
|
|
10226
|
+
"hover-lift": "lift",
|
|
10227
|
+
reveal: "fade"
|
|
10228
|
+
};
|
|
10229
|
+
const mapped = aliases[id];
|
|
10230
|
+
return mapped ? getPreset(mapped) : null;
|
|
10231
|
+
}
|
|
10232
|
+
var cached, NAMESPACES;
|
|
10233
|
+
var init_registry3 = __esm({
|
|
10234
|
+
"core/motion/registry.js"() {
|
|
10235
|
+
init_registry2();
|
|
10236
|
+
cached = registry_default;
|
|
10237
|
+
NAMESPACES = [
|
|
10238
|
+
"presets",
|
|
10239
|
+
"timelines",
|
|
10240
|
+
"transitions",
|
|
10241
|
+
"physics",
|
|
10242
|
+
"composers",
|
|
10243
|
+
"triggers",
|
|
10244
|
+
"policies",
|
|
10245
|
+
"blueprints"
|
|
10246
|
+
];
|
|
10247
|
+
}
|
|
10248
|
+
});
|
|
10249
|
+
|
|
10250
|
+
// core/motion/triggers.js
|
|
10251
|
+
function readTrigger(el, fallback = "visible") {
|
|
10252
|
+
const raw = (el.getAttribute("velin-trigger") || fallback || "visible").trim().toLowerCase();
|
|
10253
|
+
return raw || fallback;
|
|
10254
|
+
}
|
|
10255
|
+
function bindTrigger(el, triggerId, onFire, opts = {}) {
|
|
10256
|
+
const once = opts.once !== false;
|
|
10257
|
+
const reduced = opts.reduced ?? prefersReducedMotion();
|
|
10258
|
+
const id = (triggerId || "visible").toLowerCase();
|
|
10259
|
+
const meta = getTrigger(id);
|
|
10260
|
+
if (reduced || el.dataset.velinMotion === "off") {
|
|
10261
|
+
onFire();
|
|
10262
|
+
return () => {
|
|
10263
|
+
};
|
|
10264
|
+
}
|
|
10265
|
+
if (meta?.status === "planned" && !TRIGGER_V1.includes(id)) {
|
|
10266
|
+
return bindTrigger(el, "visible", onFire, opts);
|
|
10267
|
+
}
|
|
10268
|
+
let fired = false;
|
|
10269
|
+
const fire = () => {
|
|
10270
|
+
if (once && fired) return;
|
|
10271
|
+
fired = true;
|
|
10272
|
+
onFire();
|
|
10273
|
+
};
|
|
10274
|
+
if (id === "load") {
|
|
10275
|
+
fire();
|
|
10276
|
+
return () => {
|
|
10277
|
+
};
|
|
10278
|
+
}
|
|
10279
|
+
if (id === "visible" || id === "scroll") {
|
|
10280
|
+
return observeInView(el, () => fire());
|
|
10281
|
+
}
|
|
10282
|
+
if (id === "hover") {
|
|
10283
|
+
const enter = () => fire();
|
|
10284
|
+
el.addEventListener("pointerenter", enter);
|
|
10285
|
+
return () => el.removeEventListener("pointerenter", enter);
|
|
10286
|
+
}
|
|
10287
|
+
if (id === "focus") {
|
|
10288
|
+
const onFocus = () => fire();
|
|
10289
|
+
el.addEventListener("focusin", onFocus);
|
|
10290
|
+
return () => el.removeEventListener("focusin", onFocus);
|
|
10291
|
+
}
|
|
10292
|
+
if (id === "click") {
|
|
10293
|
+
const onClick = () => fire();
|
|
10294
|
+
el.addEventListener("click", onClick);
|
|
10295
|
+
return () => el.removeEventListener("click", onClick);
|
|
10296
|
+
}
|
|
10297
|
+
if (id === "hidden") {
|
|
10298
|
+
const stop = observeInView(el, () => {
|
|
10299
|
+
});
|
|
10300
|
+
if (typeof IntersectionObserver === "undefined") return () => {
|
|
10301
|
+
};
|
|
10302
|
+
const io = new IntersectionObserver((entries2) => {
|
|
10303
|
+
for (const entry of entries2) {
|
|
10304
|
+
if (!entry.isIntersecting) fire();
|
|
10305
|
+
}
|
|
10306
|
+
}, { threshold: 0 });
|
|
10307
|
+
io.observe(el);
|
|
10308
|
+
return () => {
|
|
10309
|
+
stop();
|
|
10310
|
+
io.disconnect();
|
|
10311
|
+
};
|
|
10312
|
+
}
|
|
10313
|
+
if (id === "idle") {
|
|
10314
|
+
const ms = Number(el.getAttribute("velin-trigger-delay") || 3e3);
|
|
10315
|
+
const t = setTimeout(fire, ms);
|
|
10316
|
+
return () => clearTimeout(t);
|
|
10317
|
+
}
|
|
10318
|
+
if (id === "media") {
|
|
10319
|
+
const q = el.getAttribute("velin-trigger-media") || "(min-width: 768px)";
|
|
10320
|
+
if (typeof window === "undefined" || !window.matchMedia) {
|
|
10321
|
+
fire();
|
|
10322
|
+
return () => {
|
|
10323
|
+
};
|
|
10324
|
+
}
|
|
10325
|
+
const mql = window.matchMedia(q);
|
|
10326
|
+
const handler = () => {
|
|
10327
|
+
if (mql.matches) fire();
|
|
10328
|
+
};
|
|
10329
|
+
handler();
|
|
10330
|
+
mql.addEventListener?.("change", handler);
|
|
10331
|
+
return () => mql.removeEventListener?.("change", handler);
|
|
10332
|
+
}
|
|
10333
|
+
if (id === "theme") {
|
|
10334
|
+
const root = el.ownerDocument?.documentElement;
|
|
10335
|
+
if (!root || typeof MutationObserver === "undefined") {
|
|
10336
|
+
fire();
|
|
10337
|
+
return () => {
|
|
10338
|
+
};
|
|
10339
|
+
}
|
|
10340
|
+
const mo = new MutationObserver(() => fire());
|
|
10341
|
+
mo.observe(root, { attributes: true, attributeFilter: ["data-velin-theme", "class"] });
|
|
10342
|
+
return () => mo.disconnect();
|
|
10343
|
+
}
|
|
10344
|
+
if (id === "custom") {
|
|
10345
|
+
const evt = el.getAttribute("velin-trigger-event") || "velin:motion";
|
|
10346
|
+
const handler = () => fire();
|
|
10347
|
+
el.addEventListener(evt, handler);
|
|
10348
|
+
return () => el.removeEventListener(evt, handler);
|
|
10349
|
+
}
|
|
10350
|
+
if (id === "container") {
|
|
10351
|
+
return observeInView(el, () => fire());
|
|
10352
|
+
}
|
|
10353
|
+
return observeInView(el, () => fire());
|
|
10354
|
+
}
|
|
10355
|
+
function armMotionElement(el, applyPreset) {
|
|
10356
|
+
applyPreset();
|
|
10357
|
+
const trigger = readTrigger(el, el.hasAttribute("velin-hover") ? "hover" : "visible");
|
|
10358
|
+
if (prefersReducedMotion() || el.dataset.velinMotion === "off") {
|
|
10359
|
+
markVisible(el);
|
|
10360
|
+
return () => {
|
|
10361
|
+
};
|
|
10362
|
+
}
|
|
10363
|
+
if (trigger === "hover" || trigger === "focus") {
|
|
10364
|
+
markVisible(el);
|
|
10365
|
+
return () => {
|
|
10366
|
+
};
|
|
10367
|
+
}
|
|
10368
|
+
if (trigger === "load") {
|
|
10369
|
+
markVisible(el);
|
|
10370
|
+
return () => {
|
|
10371
|
+
};
|
|
10372
|
+
}
|
|
10373
|
+
return bindTrigger(el, trigger, () => markVisible(el));
|
|
10374
|
+
}
|
|
10375
|
+
var TRIGGER_V1, TRIGGER_V2, ALL_TRIGGERS;
|
|
10376
|
+
var init_triggers = __esm({
|
|
10377
|
+
"core/motion/triggers.js"() {
|
|
10378
|
+
init_scheduler();
|
|
10379
|
+
init_effects();
|
|
10380
|
+
init_registry3();
|
|
10381
|
+
TRIGGER_V1 = ["load", "visible", "hover", "focus", "click", "scroll"];
|
|
10382
|
+
TRIGGER_V2 = ["hidden", "idle", "media", "container", "theme", "custom"];
|
|
10383
|
+
ALL_TRIGGERS = [...TRIGGER_V1, ...TRIGGER_V2];
|
|
10384
|
+
}
|
|
10385
|
+
});
|
|
10386
|
+
|
|
10387
|
+
// core/motion/policy.js
|
|
10388
|
+
function resolvePolicy(id = "safe") {
|
|
10389
|
+
return getPolicy(id) || getPolicy("safe");
|
|
10390
|
+
}
|
|
10391
|
+
function shouldDisableMotion(policy) {
|
|
10392
|
+
if (!policy) return prefersReducedMotion();
|
|
10393
|
+
if (policy.disabled) return true;
|
|
10394
|
+
if (policy.forceReduced && prefersReducedMotion()) return true;
|
|
10395
|
+
if (prefersReducedMotion() && policy.id !== "marketing") return true;
|
|
10396
|
+
return false;
|
|
10397
|
+
}
|
|
10398
|
+
function capDuration(ms, policy) {
|
|
10399
|
+
const max = policy?.maxDurationMs ?? 800;
|
|
10400
|
+
if (policy?.disabled) return 0;
|
|
10401
|
+
return Math.min(Number(ms) || 0, max);
|
|
10402
|
+
}
|
|
10403
|
+
function applyMotionVars(el, policy) {
|
|
10404
|
+
const duration = el.getAttribute("velin-duration");
|
|
10405
|
+
const delay2 = el.getAttribute("velin-delay");
|
|
10406
|
+
const ease = el.getAttribute("velin-ease");
|
|
10407
|
+
if (duration) {
|
|
10408
|
+
const capped = capDuration(Number(duration), policy);
|
|
10409
|
+
el.style.setProperty("--velin-motion-duration", `${capped}ms`);
|
|
10410
|
+
el.style.animationDuration = `${capped}ms`;
|
|
10411
|
+
}
|
|
10412
|
+
if (delay2) el.style.animationDelay = `${Number(delay2)}ms`;
|
|
10413
|
+
if (ease) {
|
|
10414
|
+
const map = {
|
|
10415
|
+
spring: "var(--velin-ease-spring)",
|
|
10416
|
+
bounce: "var(--velin-ease-bounce)",
|
|
10417
|
+
elastic: "var(--velin-ease-elastic)",
|
|
10418
|
+
default: "var(--velin-ease-default)"
|
|
10419
|
+
};
|
|
10420
|
+
el.style.animationTimingFunction = map[ease] || ease;
|
|
10421
|
+
}
|
|
10422
|
+
if (policy?.disabled || shouldDisableMotion(policy)) {
|
|
10423
|
+
el.dataset.velinMotion = "off";
|
|
10424
|
+
}
|
|
10425
|
+
}
|
|
10426
|
+
var init_policy = __esm({
|
|
10427
|
+
"core/motion/policy.js"() {
|
|
10428
|
+
init_registry3();
|
|
10429
|
+
init_effects();
|
|
10430
|
+
}
|
|
10431
|
+
});
|
|
10432
|
+
|
|
10433
|
+
// core/motion/timeline.js
|
|
10434
|
+
function runTimeline(timelineId, root, opts = {}) {
|
|
10435
|
+
const tl = getTimeline(timelineId);
|
|
10436
|
+
if (!tl) return { ok: false, error: `Unknown timeline "${timelineId}"`, ran: [] };
|
|
10437
|
+
const stepMs = opts.stepMs ?? 120;
|
|
10438
|
+
const ran = [];
|
|
10439
|
+
if (opts.policyDisabled || prefersReducedMotion()) {
|
|
10440
|
+
for (const step of tl.steps || []) {
|
|
10441
|
+
const el = resolveStep(root, step);
|
|
10442
|
+
if (el) markVisible(el);
|
|
10443
|
+
ran.push(step);
|
|
10444
|
+
}
|
|
10445
|
+
return { ok: true, ran };
|
|
10446
|
+
}
|
|
10447
|
+
let delay2 = 0;
|
|
10448
|
+
for (const step of tl.steps || []) {
|
|
10449
|
+
const el = resolveStep(root, step);
|
|
10450
|
+
if (!el) continue;
|
|
10451
|
+
const d = delay2;
|
|
10452
|
+
delay2 += stepMs;
|
|
10453
|
+
if (typeof window !== "undefined" && window.setTimeout) {
|
|
10454
|
+
window.setTimeout(() => markVisible(el), d);
|
|
10455
|
+
} else {
|
|
10456
|
+
markVisible(el);
|
|
10457
|
+
}
|
|
10458
|
+
ran.push(step);
|
|
10459
|
+
}
|
|
10460
|
+
return { ok: true, ran, timeline: tl };
|
|
10461
|
+
}
|
|
10462
|
+
function resolveStep(root, step) {
|
|
10463
|
+
if (!root?.querySelector) return null;
|
|
10464
|
+
return root.querySelector(`[data-velin-step="${step}"]`) || root.querySelector(`[velin-step="${step}"]`) || root.querySelector(`#${CSS.escape?.(step) || step}`);
|
|
10465
|
+
}
|
|
10466
|
+
function enhanceTimelines(root) {
|
|
10467
|
+
if (!root?.querySelectorAll) return () => {
|
|
10468
|
+
};
|
|
10469
|
+
const nodes = root.querySelectorAll("[velin-timeline]");
|
|
10470
|
+
const teardowns = [];
|
|
10471
|
+
for (const el of nodes) {
|
|
10472
|
+
const id = el.getAttribute("velin-timeline");
|
|
10473
|
+
const result = runTimeline(id, el);
|
|
10474
|
+
teardowns.push(() => result);
|
|
10475
|
+
}
|
|
10476
|
+
return () => {
|
|
10477
|
+
};
|
|
10478
|
+
}
|
|
10479
|
+
var init_timeline = __esm({
|
|
10480
|
+
"core/motion/timeline.js"() {
|
|
10481
|
+
init_registry3();
|
|
10482
|
+
init_effects();
|
|
10483
|
+
}
|
|
10484
|
+
});
|
|
10485
|
+
|
|
10486
|
+
// core/motion/composer.js
|
|
10487
|
+
function fade(ms = 400) {
|
|
10488
|
+
return { type: "fade", ms };
|
|
10489
|
+
}
|
|
10490
|
+
function slide(ms = 500, value = "up") {
|
|
10491
|
+
return { type: "slide", ms, value };
|
|
10492
|
+
}
|
|
10493
|
+
function wait(ms = 200) {
|
|
10494
|
+
return { type: "wait", ms };
|
|
10495
|
+
}
|
|
10496
|
+
function rotate(ms = 400) {
|
|
10497
|
+
return { type: "rotate", ms };
|
|
10498
|
+
}
|
|
10499
|
+
function blur(ms = 400) {
|
|
10500
|
+
return { type: "blur", ms };
|
|
10501
|
+
}
|
|
10502
|
+
function preset(id, ms) {
|
|
10503
|
+
return { type: "preset", preset: id, ms };
|
|
10504
|
+
}
|
|
10505
|
+
async function sequence(steps = [], ctx = {}) {
|
|
10506
|
+
const target = ctx.target || ctx.root;
|
|
10507
|
+
const reduced = prefersReducedMotion();
|
|
10508
|
+
const ran = [];
|
|
10509
|
+
for (const step of steps) {
|
|
10510
|
+
if (step.type === "wait") {
|
|
10511
|
+
if (!reduced && step.ms) await delay(step.ms);
|
|
10512
|
+
ran.push(step);
|
|
10513
|
+
continue;
|
|
10514
|
+
}
|
|
10515
|
+
if (target && typeof target.classList?.add === "function") {
|
|
10516
|
+
if (step.type === "preset" && step.preset) {
|
|
10517
|
+
const p = resolvePresetId(step.preset);
|
|
10518
|
+
if (p?.cssClass) target.classList.add(...String(p.cssClass).split(/\s+/));
|
|
10519
|
+
applyEffects(target, { [step.preset]: "true" });
|
|
10520
|
+
} else if (step.type === "fade") {
|
|
10521
|
+
applyEffects(target, { fade: "true" });
|
|
10522
|
+
} else if (step.type === "slide") {
|
|
10523
|
+
applyEffects(target, { slide: step.value || "up" });
|
|
10524
|
+
} else if (step.type === "blur") {
|
|
10525
|
+
applyEffects(target, { blur: "true" });
|
|
10526
|
+
} else if (step.type === "rotate") {
|
|
10527
|
+
applyEffects(target, { flip: "true" });
|
|
10528
|
+
}
|
|
10529
|
+
markVisible(target);
|
|
10530
|
+
}
|
|
10531
|
+
if (!reduced && step.ms) await delay(step.ms);
|
|
10532
|
+
ran.push(step);
|
|
10533
|
+
}
|
|
10534
|
+
return { ok: true, ran };
|
|
10535
|
+
}
|
|
10536
|
+
function delay(ms) {
|
|
10537
|
+
return new Promise((resolve) => {
|
|
10538
|
+
if (typeof setTimeout === "undefined") return resolve();
|
|
10539
|
+
setTimeout(resolve, ms);
|
|
10540
|
+
});
|
|
10541
|
+
}
|
|
10542
|
+
function enhanceSequences(root) {
|
|
10543
|
+
if (!root?.querySelectorAll) return () => {
|
|
10544
|
+
};
|
|
10545
|
+
const nodes = [...root.querySelectorAll("[velin-motion-sequence]")];
|
|
10546
|
+
for (const section of nodes) {
|
|
10547
|
+
const children = [...section.children];
|
|
10548
|
+
let i = 0;
|
|
10549
|
+
const stepMs = Number(section.getAttribute("velin-sequence-gap") || 120);
|
|
10550
|
+
for (const child of children) {
|
|
10551
|
+
child.classList.add("velin-animate-on-scroll", "velin-animate-on-scroll--fade");
|
|
10552
|
+
if (prefersReducedMotion()) {
|
|
10553
|
+
markVisible(child);
|
|
10554
|
+
} else if (typeof setTimeout !== "undefined") {
|
|
10555
|
+
const delayMs = i * stepMs;
|
|
10556
|
+
setTimeout(() => markVisible(child), delayMs);
|
|
10557
|
+
} else {
|
|
10558
|
+
markVisible(child);
|
|
10559
|
+
}
|
|
10560
|
+
i += 1;
|
|
10561
|
+
}
|
|
10562
|
+
}
|
|
10563
|
+
return () => {
|
|
10564
|
+
};
|
|
10565
|
+
}
|
|
10566
|
+
var Motion;
|
|
10567
|
+
var init_composer = __esm({
|
|
10568
|
+
"core/motion/composer.js"() {
|
|
10569
|
+
init_effects();
|
|
10570
|
+
init_registry3();
|
|
10571
|
+
init_effects();
|
|
10572
|
+
Motion = {
|
|
10573
|
+
sequence,
|
|
10574
|
+
fade,
|
|
10575
|
+
slide,
|
|
10576
|
+
wait,
|
|
10577
|
+
rotate,
|
|
10578
|
+
blur,
|
|
10579
|
+
preset
|
|
10580
|
+
};
|
|
10581
|
+
}
|
|
10582
|
+
});
|
|
10583
|
+
|
|
9781
10584
|
// core/motion/index.js
|
|
10585
|
+
function createMotionEngine(options = {}) {
|
|
10586
|
+
const policy = resolvePolicy(options.policy || "safe");
|
|
10587
|
+
return {
|
|
10588
|
+
policy,
|
|
10589
|
+
registry: () => loadMotionRegistry(),
|
|
10590
|
+
catalog: catalogSummary,
|
|
10591
|
+
listPresets,
|
|
10592
|
+
listPolicies,
|
|
10593
|
+
init: (opts = {}) => initMotion({ ...opts, policy: policy.id }),
|
|
10594
|
+
Motion
|
|
10595
|
+
};
|
|
10596
|
+
}
|
|
9782
10597
|
function initMotion(options = {}) {
|
|
9783
10598
|
const root = options.root || (typeof document !== "undefined" ? document : null);
|
|
9784
10599
|
if (!root) return () => {
|
|
9785
10600
|
};
|
|
10601
|
+
const policy = resolvePolicy(
|
|
10602
|
+
options.policy || root.documentElement?.getAttribute?.("data-velin-motion-policy") || root.querySelector?.("[data-velin-motion-policy]")?.getAttribute("data-velin-motion-policy") || "safe"
|
|
10603
|
+
);
|
|
9786
10604
|
const selector = options.selector || [
|
|
10605
|
+
"[velin-motion]",
|
|
9787
10606
|
"[velin-reveal]",
|
|
9788
10607
|
"[velin-fade]",
|
|
9789
10608
|
"[velin-slide]",
|
|
@@ -9793,26 +10612,40 @@
|
|
|
9793
10612
|
".velin-animate-on-scroll"
|
|
9794
10613
|
].join(",");
|
|
9795
10614
|
const elements = root.querySelectorAll(selector);
|
|
9796
|
-
const reduced = prefersReducedMotion();
|
|
10615
|
+
const reduced = shouldDisableMotion(policy) || prefersReducedMotion();
|
|
9797
10616
|
for (const el of elements) {
|
|
9798
10617
|
if (el.dataset.velinMotionInit) continue;
|
|
9799
10618
|
el.dataset.velinMotionInit = "1";
|
|
10619
|
+
applyMotionVars(el, policy);
|
|
9800
10620
|
const attrs = {};
|
|
9801
|
-
|
|
10621
|
+
const motionPreset = el.getAttribute("velin-motion");
|
|
10622
|
+
if (motionPreset) {
|
|
10623
|
+
attrs.motion = motionPreset;
|
|
10624
|
+
const resolved = resolvePresetId(motionPreset);
|
|
10625
|
+
if (resolved?.id) attrs[resolved.id] = "true";
|
|
10626
|
+
}
|
|
10627
|
+
for (const name of LEGACY_ATTRS) {
|
|
9802
10628
|
if (el.hasAttribute(name)) attrs[name.replace("velin-", "")] = el.getAttribute(name) || "true";
|
|
9803
10629
|
}
|
|
9804
10630
|
applyEffects(el, attrs);
|
|
9805
|
-
if (reduced) {
|
|
10631
|
+
if (reduced || el.dataset.velinMotion === "off") {
|
|
9806
10632
|
markVisible(el);
|
|
9807
10633
|
continue;
|
|
9808
10634
|
}
|
|
9809
|
-
const stop =
|
|
10635
|
+
const stop = armMotionElement(el, () => applyEffects(el, attrs));
|
|
9810
10636
|
teardownFns.push(stop);
|
|
9811
10637
|
}
|
|
9812
10638
|
enhanceStagger(root);
|
|
9813
10639
|
bindSmoothScroll(root);
|
|
10640
|
+
enhanceTimelines(root);
|
|
10641
|
+
enhanceSequences(root);
|
|
9814
10642
|
return () => {
|
|
9815
|
-
teardownFns.forEach((fn) =>
|
|
10643
|
+
teardownFns.forEach((fn) => {
|
|
10644
|
+
try {
|
|
10645
|
+
fn();
|
|
10646
|
+
} catch {
|
|
10647
|
+
}
|
|
10648
|
+
});
|
|
9816
10649
|
teardownFns = [];
|
|
9817
10650
|
disconnectInViewObserver();
|
|
9818
10651
|
};
|
|
@@ -9823,16 +10656,28 @@
|
|
|
9823
10656
|
selector: options.selector || ".velin-animate-on-scroll"
|
|
9824
10657
|
});
|
|
9825
10658
|
}
|
|
9826
|
-
var
|
|
10659
|
+
var LEGACY_ATTRS, teardownFns, velinMotion;
|
|
9827
10660
|
var init_motion = __esm({
|
|
9828
10661
|
"core/motion/index.js"() {
|
|
9829
10662
|
init_scheduler();
|
|
9830
10663
|
init_effects();
|
|
9831
10664
|
init_stagger();
|
|
9832
10665
|
init_scroll();
|
|
9833
|
-
|
|
10666
|
+
init_triggers();
|
|
10667
|
+
init_policy();
|
|
10668
|
+
init_timeline();
|
|
10669
|
+
init_composer();
|
|
10670
|
+
init_registry3();
|
|
10671
|
+
LEGACY_ATTRS = ["velin-reveal", "velin-fade", "velin-slide", "velin-scale", "velin-parallax", "velin-hover"];
|
|
9834
10672
|
teardownFns = [];
|
|
9835
|
-
velinMotion = {
|
|
10673
|
+
velinMotion = {
|
|
10674
|
+
init: initMotion,
|
|
10675
|
+
observe: observeInView,
|
|
10676
|
+
markVisible,
|
|
10677
|
+
VISIBLE_CLASS,
|
|
10678
|
+
createEngine: createMotionEngine,
|
|
10679
|
+
readTrigger
|
|
10680
|
+
};
|
|
9836
10681
|
}
|
|
9837
10682
|
});
|
|
9838
10683
|
|
|
@@ -9976,7 +10821,7 @@
|
|
|
9976
10821
|
}
|
|
9977
10822
|
return `tx-${(h >>> 0).toString(16)}`;
|
|
9978
10823
|
}
|
|
9979
|
-
var
|
|
10824
|
+
var init_registry4 = __esm({
|
|
9980
10825
|
"core/transparency/registry.js"() {
|
|
9981
10826
|
}
|
|
9982
10827
|
});
|
|
@@ -10058,7 +10903,7 @@
|
|
|
10058
10903
|
var init_normalize = __esm({
|
|
10059
10904
|
"core/transparency/normalize.js"() {
|
|
10060
10905
|
init_claims();
|
|
10061
|
-
|
|
10906
|
+
init_registry4();
|
|
10062
10907
|
PROVENANCE_KEYS = [
|
|
10063
10908
|
"createdBy",
|
|
10064
10909
|
"createdAt",
|
|
@@ -10222,7 +11067,7 @@
|
|
|
10222
11067
|
"core/transparency/attach.js"() {
|
|
10223
11068
|
init_normalize();
|
|
10224
11069
|
init_renderer();
|
|
10225
|
-
|
|
11070
|
+
init_registry4();
|
|
10226
11071
|
defaultRegistry = createRegistry();
|
|
10227
11072
|
VelinTransparency = {
|
|
10228
11073
|
attach,
|
|
@@ -10455,7 +11300,7 @@
|
|
|
10455
11300
|
attach2(el);
|
|
10456
11301
|
}
|
|
10457
11302
|
});
|
|
10458
|
-
for (const motion of ["velin-reveal", "velin-fade", "velin-slide", "velin-scale", "velin-parallax", "velin-hover", "velin-stagger", "velin-scroll"]) {
|
|
11303
|
+
for (const motion of ["velin-motion", "velin-trigger", "velin-duration", "velin-delay", "velin-ease", "velin-timeline", "velin-motion-sequence", "velin-reveal", "velin-fade", "velin-slide", "velin-scale", "velin-parallax", "velin-hover", "velin-stagger", "velin-scroll"]) {
|
|
10459
11304
|
registerAttribute(motion, { enhance() {
|
|
10460
11305
|
} });
|
|
10461
11306
|
}
|
|
@@ -10486,7 +11331,7 @@
|
|
|
10486
11331
|
return [...registry.keys()];
|
|
10487
11332
|
}
|
|
10488
11333
|
var registry, enhanced;
|
|
10489
|
-
var
|
|
11334
|
+
var init_registry5 = __esm({
|
|
10490
11335
|
"core/attributes/registry.js"() {
|
|
10491
11336
|
init_runtime();
|
|
10492
11337
|
init_motion();
|
|
@@ -10506,7 +11351,7 @@
|
|
|
10506
11351
|
});
|
|
10507
11352
|
var init_attributes = __esm({
|
|
10508
11353
|
"core/attributes/index.js"() {
|
|
10509
|
-
|
|
11354
|
+
init_registry5();
|
|
10510
11355
|
}
|
|
10511
11356
|
});
|
|
10512
11357
|
|