Merge pull request #135 from Utkarsh-Singhal-26/fixes/minor-fixes

[ FIX ] : Minor Fixes
This commit is contained in:
David
2026-01-17 23:10:50 +02:00
committed by GitHub
10 changed files with 126 additions and 63 deletions

View File

@@ -41,7 +41,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref, onMounted, onUnmounted, defineComponent, h, useTemplateRef } from 'vue'; import { ref, onMounted, onUnmounted, defineComponent, h, useTemplateRef } from 'vue';
import { gsap } from 'gsap'; import { gsap } from 'gsap';
import CountUp from '../../../content/Animations/CountUp/CountUp.vue'; import CountUp from '../../../content/TextAnimations/CountUp/CountUp.vue';
import './FeatureCards.css'; import './FeatureCards.css';
const isMobile = ref(false); const isMobile = ref(false);

View File

@@ -1,12 +1,24 @@
// Highlighted sidebar items // Highlighted sidebar items
export const NEW = ['Antigravity', 'Color Bends', 'Ghost Cursor', 'Laser Flow', 'Liquid Ether', 'Pixel Blast', 'Floating Lines', 'Light Pillar', 'Pixel Snow', 'Grid Scan']; export const NEW = [
'Antigravity',
'Color Bends',
'Floating Lines',
'Ghost Cursor',
'Grid Scan',
'Laser Flow',
'Light Pillar',
'Liquid Ether',
'Pixel Blast',
'Pixel Snow',
];
export const UPDATED = []; export const UPDATED = [];
// Used for main sidebar navigation // Used for main sidebar navigation
export const CATEGORIES = [ export const CATEGORIES = [
{ {
name: 'Get Started', name: 'Get Started',
subcategories: ['Index'] subcategories: [ 'Index' ],
}, },
{ {
name: 'Text Animations', name: 'Text Animations',
@@ -14,6 +26,7 @@ export const CATEGORIES = [
'Ascii Text', 'Ascii Text',
'Blur Text', 'Blur Text',
'Circular Text', 'Circular Text',
'Count Up',
'Curved Loop', 'Curved Loop',
'Decrypted Text', 'Decrypted Text',
'Falling Text', 'Falling Text',
@@ -43,7 +56,6 @@ export const CATEGORIES = [
'Antigravity', 'Antigravity',
'Blob Cursor', 'Blob Cursor',
'Click Spark', 'Click Spark',
'Count Up',
'Crosshair', 'Crosshair',
'Cubes', 'Cubes',
'Electric Border', 'Electric Border',
@@ -56,8 +68,8 @@ export const CATEGORIES = [
'Logo Loop', 'Logo Loop',
'Magnet', 'Magnet',
'Magnet Lines', 'Magnet Lines',
'Meta Balls',
'Metallic Paint', 'Metallic Paint',
'Meta Balls',
'Noise', 'Noise',
'Pixel Trail', 'Pixel Trail',
'Pixel Transition', 'Pixel Transition',
@@ -95,8 +107,8 @@ export const CATEGORIES = [
'Infinite Scroll', 'Infinite Scroll',
'Magic Bento', 'Magic Bento',
'Masonry', 'Masonry',
'Pixel Card',
'Pill Nav', 'Pill Nav',
'Pixel Card',
'Profile Card', 'Profile Card',
'Rolling Gallery', 'Rolling Gallery',
'Scroll Stack', 'Scroll Stack',
@@ -128,9 +140,9 @@ export const CATEGORIES = [
'Hyperspeed', 'Hyperspeed',
'Iridescence', 'Iridescence',
'Letter Glitch', 'Letter Glitch',
'Lightning',
'Light Pillar', 'Light Pillar',
'Light Rays', 'Light Rays',
'Lightning',
'Liquid Chrome', 'Liquid Chrome',
'Liquid Ether', 'Liquid Ether',
'Orb', 'Orb',

View File

@@ -10,7 +10,6 @@ const animations = {
'metallic-paint': () => import('../demo/Animations/MetallicPaintDemo.vue'), 'metallic-paint': () => import('../demo/Animations/MetallicPaintDemo.vue'),
'magnet': () => import('../demo/Animations/MagnetDemo.vue'), 'magnet': () => import('../demo/Animations/MagnetDemo.vue'),
'cubes': () => import('../demo/Animations/CubesDemo.vue'), 'cubes': () => import('../demo/Animations/CubesDemo.vue'),
'count-up': () => import('../demo/Animations/CountUpDemo.vue'),
'splash-cursor': () => import('../demo/Animations/SplashCursorDemo.vue'), 'splash-cursor': () => import('../demo/Animations/SplashCursorDemo.vue'),
'noise': () => import('../demo/Animations/NoiseDemo.vue'), 'noise': () => import('../demo/Animations/NoiseDemo.vue'),
'star-border': () => import('../demo/Animations/StarBorderDemo.vue'), 'star-border': () => import('../demo/Animations/StarBorderDemo.vue'),
@@ -35,6 +34,7 @@ const textAnimations = {
'circular-text': () => import("../demo/TextAnimations/CircularTextDemo.vue"), 'circular-text': () => import("../demo/TextAnimations/CircularTextDemo.vue"),
'shiny-text': () => import("../demo/TextAnimations/ShinyTextDemo.vue"), 'shiny-text': () => import("../demo/TextAnimations/ShinyTextDemo.vue"),
'text-pressure': () => import("../demo/TextAnimations/TextPressureDemo.vue"), 'text-pressure': () => import("../demo/TextAnimations/TextPressureDemo.vue"),
'count-up': () => import('../demo/TextAnimations/CountUpDemo.vue'),
'curved-loop': () => import("../demo/TextAnimations/CurvedLoopDemo.vue"), 'curved-loop': () => import("../demo/TextAnimations/CurvedLoopDemo.vue"),
'fuzzy-text': () => import("../demo/TextAnimations/FuzzyTextDemo.vue"), 'fuzzy-text': () => import("../demo/TextAnimations/FuzzyTextDemo.vue"),
'gradient-text': () => import("../demo/TextAnimations/GradientTextDemo.vue"), 'gradient-text': () => import("../demo/TextAnimations/GradientTextDemo.vue"),

View File

@@ -214,14 +214,6 @@ export const componentMetadata: ComponentMetadata = {
docsUrl: 'https://vue-bits.dev/animations/laser-flow', docsUrl: 'https://vue-bits.dev/animations/laser-flow',
tags: [] tags: []
}, },
'Animations/CountUp': {
videoUrl: '/assets/videos/countup.webm',
description: 'Animated number counter supporting formatting and decimals.',
category: 'Animations',
name: 'CountUp',
docsUrl: 'https://vue-bits.dev/text-animations/count-up',
tags: []
},
'Animations/PixelTrail': { 'Animations/PixelTrail': {
videoUrl: '/assets/videos/pixeltrail.webm', videoUrl: '/assets/videos/pixeltrail.webm',
description: 'Pixel grid trail effect that follows cursor movement with customizable gooey filter.', description: 'Pixel grid trail effect that follows cursor movement with customizable gooey filter.',
@@ -241,6 +233,14 @@ export const componentMetadata: ComponentMetadata = {
docsUrl: 'https://vue-bits.dev/text-animations/ascii-text', docsUrl: 'https://vue-bits.dev/text-animations/ascii-text',
tags: [] tags: []
}, },
'TextAnimations/CountUp': {
videoUrl: '/assets/videos/countup.webm',
description: 'Animated number counter supporting formatting and decimals.',
category: 'TextAnimations',
name: 'CountUp',
docsUrl: 'https://vue-bits.dev/text-animations/count-up',
tags: []
},
'TextAnimations/BlurText': { 'TextAnimations/BlurText': {
videoUrl: '/assets/videos/blurtext.webm', videoUrl: '/assets/videos/blurtext.webm',
description: 'Text starts blurred then crisply resolves for a soft-focus reveal effect.', description: 'Text starts blurred then crisply resolves for a soft-focus reveal effect.',

View File

@@ -1,7 +1,7 @@
import code from '@/content/Animations/CountUp/CountUp.vue?raw'; import code from '@/content/TextAnimations/CountUp/CountUp.vue?raw';
import { createCodeObject } from '@/types/code'; import { createCodeObject } from '@/types/code';
export const countup = createCodeObject(code, 'Animations/CountUp', { export const countup = createCodeObject(code, 'TextAnimations/CountUp', {
usage: `<template> usage: `<template>
<CountUp <CountUp
:from="0" :from="0"

View File

@@ -16,7 +16,7 @@ export interface ShuffleProps {
text: string; text: string;
className?: string; className?: string;
style?: Record<string, any>; style?: Record<string, any>;
shuffleDirection?: 'left' | 'right'; shuffleDirection?: 'left' | 'right' | 'up' | 'down';
duration?: number; duration?: number;
maxDelay?: number; maxDelay?: number;
ease?: string | ((t: number) => number); ease?: string | ((t: number) => number);
@@ -152,54 +152,87 @@ const build = () => {
if (!parent) return; if (!parent) return;
const w = ch.getBoundingClientRect().width; const w = ch.getBoundingClientRect().width;
const h = ch.getBoundingClientRect().height;
if (!w) return; if (!w) return;
const wrap = document.createElement('span'); const wrap = document.createElement('span');
wrap.className = 'inline-block overflow-hidden align-baseline text-left'; wrap.className = 'inline-block overflow-hidden text-left';
Object.assign(wrap.style, { width: w + 'px' }); Object.assign(wrap.style, {
width: w + 'px',
height: props.shuffleDirection === 'up' || props.shuffleDirection === 'down' ? h + 'px' : 'auto',
verticalAlign: 'bottom'
});
const inner = document.createElement('span'); const inner = document.createElement('span');
inner.className = 'inline-block whitespace-nowrap will-change-transform origin-left transform-gpu'; inner.className =
'inline-block will-change-transform origin-left transform-gpu ' +
(props.shuffleDirection === 'up' || props.shuffleDirection === 'down'
? 'whitespace-normal'
: 'whitespace-nowrap');
parent.insertBefore(wrap, ch); parent.insertBefore(wrap, ch);
wrap.appendChild(inner); wrap.appendChild(inner);
const firstOrig = ch.cloneNode(true) as HTMLElement; const firstOrig = ch.cloneNode(true) as HTMLElement;
firstOrig.className = 'inline-block text-left'; firstOrig.className =
'text-left ' + (props.shuffleDirection === 'up' || props.shuffleDirection === 'down' ? 'block' : 'inline-block');
Object.assign(firstOrig.style, { width: w + 'px', fontFamily: computedFont }); Object.assign(firstOrig.style, { width: w + 'px', fontFamily: computedFont });
ch.setAttribute('data-orig', '1'); ch.setAttribute('data-orig', '1');
ch.className = 'inline-block text-left'; ch.className =
'text-left ' + (props.shuffleDirection === 'up' || props.shuffleDirection === 'down' ? 'block' : 'inline-block');
Object.assign(ch.style, { width: w + 'px', fontFamily: computedFont }); Object.assign(ch.style, { width: w + 'px', fontFamily: computedFont });
inner.appendChild(firstOrig); inner.appendChild(firstOrig);
for (let k = 0; k < rolls; k++) { for (let k = 0; k < rolls; k++) {
const c = ch.cloneNode(true) as HTMLElement; const c = ch.cloneNode(true) as HTMLElement;
if (props.scrambleCharset) c.textContent = rand(props.scrambleCharset); if (props.scrambleCharset) c.textContent = rand(props.scrambleCharset);
c.className = 'inline-block text-left'; c.className =
'text-left ' +
(props.shuffleDirection === 'up' || props.shuffleDirection === 'down' ? 'block' : 'inline-block');
Object.assign(c.style, { width: w + 'px', fontFamily: computedFont }); Object.assign(c.style, { width: w + 'px', fontFamily: computedFont });
inner.appendChild(c); inner.appendChild(c);
} }
inner.appendChild(ch); inner.appendChild(ch);
const steps = rolls + 1; const steps = rolls + 1;
let startX = 0; if (props.shuffleDirection === 'right' || props.shuffleDirection === 'down') {
let finalX = -steps * w;
if (props.shuffleDirection === 'right') {
const firstCopy = inner.firstElementChild as HTMLElement | null; const firstCopy = inner.firstElementChild as HTMLElement | null;
const real = inner.lastElementChild as HTMLElement | null; const real = inner.lastElementChild as HTMLElement | null;
if (real) inner.insertBefore(real, inner.firstChild); if (real) inner.insertBefore(real, inner.firstChild);
if (firstCopy) inner.appendChild(firstCopy); if (firstCopy) inner.appendChild(firstCopy);
startX = -steps * w;
finalX = 0;
} }
gsap.set(inner, { x: startX, force3D: true }); let startX = 0;
let finalX = 0;
let startY = 0;
let finalY = 0;
if (props.shuffleDirection === 'right') {
startX = -steps * w;
finalX = 0;
} else if (props.shuffleDirection === 'left') {
startX = 0;
finalX = -steps * w;
} else if (props.shuffleDirection === 'down') {
startY = -steps * h;
finalY = 0;
} else if (props.shuffleDirection === 'up') {
startY = 0;
finalY = -steps * h;
}
if (props.shuffleDirection === 'left' || props.shuffleDirection === 'right') {
gsap.set(inner, { x: startX, y: 0, force3D: true });
inner.setAttribute('data-start-x', String(startX));
inner.setAttribute('data-final-x', String(finalX));
} else {
gsap.set(inner, { x: 0, y: startY, force3D: true });
inner.setAttribute('data-start-y', String(startY));
inner.setAttribute('data-final-y', String(finalY));
}
if (props.colorFrom) (inner.style as any).color = props.colorFrom; if (props.colorFrom) (inner.style as any).color = props.colorFrom;
inner.setAttribute('data-final-x', String(finalX));
inner.setAttribute('data-start-x', String(startX));
wrappersRef.value.push(wrap); wrappersRef.value.push(wrap);
}); });
}; };
@@ -248,6 +281,7 @@ const play = () => {
if (!strips.length) return; if (!strips.length) return;
playingRef.value = true; playingRef.value = true;
const isVertical = props.shuffleDirection === 'up' || props.shuffleDirection === 'down';
const tl = gsap.timeline({ const tl = gsap.timeline({
smoothChildTiming: true, smoothChildTiming: true,
@@ -255,7 +289,11 @@ const play = () => {
repeatDelay: props.loop ? props.loopDelay : 0, repeatDelay: props.loop ? props.loopDelay : 0,
onRepeat: () => { onRepeat: () => {
if (props.scrambleCharset) randomizeScrambles(); if (props.scrambleCharset) randomizeScrambles();
gsap.set(strips, { x: (i, t: HTMLElement) => parseFloat(t.getAttribute('data-start-x') || '0') }); if (isVertical) {
gsap.set(strips, { y: (i, t: HTMLElement) => parseFloat(t.getAttribute('data-start-y') || '0') });
} else {
gsap.set(strips, { x: (i, t: HTMLElement) => parseFloat(t.getAttribute('data-start-x') || '0') });
}
emit('shuffle-complete'); emit('shuffle-complete');
props.onShuffleComplete?.(); props.onShuffleComplete?.();
}, },
@@ -272,17 +310,19 @@ const play = () => {
}); });
const addTween = (targets: HTMLElement[], at: number) => { const addTween = (targets: HTMLElement[], at: number) => {
tl.to( const vars: any = {
targets, duration: props.duration,
{ ease: props.ease,
x: (i, t: HTMLElement) => parseFloat(t.getAttribute('data-final-x') || '0'), force3D: true,
duration: props.duration, stagger: props.animationMode === 'evenodd' ? props.stagger : 0
ease: props.ease, };
force3D: true, if (isVertical) {
stagger: props.animationMode === 'evenodd' ? props.stagger : 0 vars.y = (i: number, t: HTMLElement) => parseFloat(t.getAttribute('data-final-y') || '0');
}, } else {
at vars.x = (i: number, t: HTMLElement) => parseFloat(t.getAttribute('data-final-x') || '0');
); }
tl.to(targets, vars, at);
if (props.colorFrom && props.colorTo) if (props.colorFrom && props.colorTo)
tl.to(targets, { color: props.colorTo, duration: props.duration, ease: props.ease }, at); tl.to(targets, { color: props.colorTo, duration: props.duration, ease: props.ease }, at);
}; };
@@ -297,16 +337,17 @@ const play = () => {
} else { } else {
strips.forEach(strip => { strips.forEach(strip => {
const d = Math.random() * props.maxDelay; const d = Math.random() * props.maxDelay;
tl.to( const vars: any = {
strip, duration: props.duration,
{ ease: props.ease,
x: parseFloat(strip.getAttribute('data-final-x') || '0'), force3D: true
duration: props.duration, };
ease: props.ease, if (isVertical) {
force3D: true vars.y = parseFloat(strip.getAttribute('data-final-y') || '0');
}, } else {
d vars.x = parseFloat(strip.getAttribute('data-final-x') || '0');
); }
tl.to(strip, vars, d);
if (props.colorFrom && props.colorTo) if (props.colorFrom && props.colorTo)
tl.fromTo( tl.fromTo(
strip, strip,

View File

@@ -71,8 +71,8 @@ import PropTable from '../../components/common/PropTable.vue';
import CliInstallation from '../../components/code/CliInstallation.vue'; import CliInstallation from '../../components/code/CliInstallation.vue';
import CodeExample from '../../components/code/CodeExample.vue'; import CodeExample from '../../components/code/CodeExample.vue';
import RefreshButton from '../../components/common/RefreshButton.vue'; import RefreshButton from '../../components/common/RefreshButton.vue';
import CountUp from '../../content/Animations/CountUp/CountUp.vue'; import CountUp from '../../content/TextAnimations/CountUp/CountUp.vue';
import { countup } from '@/constants/code/Animations/countUpCode'; import { countup } from '@/constants/code/TextAnimations/countUpCode';
import { useForceRerender } from '@/composables/useForceRerender'; import { useForceRerender } from '@/composables/useForceRerender';
import Customize from '../../components/common/Customize.vue'; import Customize from '../../components/common/Customize.vue';
import PreviewSlider from '../../components/common/PreviewSlider.vue'; import PreviewSlider from '../../components/common/PreviewSlider.vue';

View File

@@ -80,7 +80,7 @@ const { rerenderKey: key, forceRerender } = useForceRerender();
const duration = ref(0.35); const duration = ref(0.35);
const shuffleTimes = ref(1); const shuffleTimes = ref(1);
const stagger = ref(0.03); const stagger = ref(0.03);
const shuffleDirection = ref<'left' | 'right'>('right'); const shuffleDirection = ref<'left' | 'right' | 'up' | 'down'>('right');
const ease = ref('power3.out'); const ease = ref('power3.out');
const loop = ref(false); const loop = ref(false);
const loopDelay = ref(0); const loopDelay = ref(0);
@@ -88,7 +88,9 @@ const triggerOnHover = ref(true);
const directionOptions = [ const directionOptions = [
{ label: 'Right', value: 'right' }, { label: 'Right', value: 'right' },
{ label: 'Left', value: 'left' } { label: 'Left', value: 'left' },
{ label: 'Up', value: 'up' },
{ label: 'Down', value: 'down' }
]; ];
const easeOptions = [ const easeOptions = [
@@ -104,7 +106,7 @@ const propData = [
{ name: 'style', type: 'object', default: '{}', description: 'Inline styles applied to the wrapper element.' }, { name: 'style', type: 'object', default: '{}', description: 'Inline styles applied to the wrapper element.' },
{ {
name: 'shuffleDirection', name: 'shuffleDirection',
type: '"left" | "right"', type: '"left" | "right" | "up" | "down"',
default: '"right"', default: '"right"',
description: 'Direction the per-letter strip slides to reveal the final character.' description: 'Direction the per-letter strip slides to reveal the final character.'
}, },

View File

@@ -17,7 +17,7 @@
</div> </div>
<Customize> <Customize>
<PreviewSelect v-model="cursorCharacter" :options="['|', '_', '█', '▌', '▐']" title="Cursor Character" /> <PreviewSelect v-model="cursorCharacter" :options="cursorOptions" title="Cursor Character" />
<PreviewSlider v-model="typingSpeed" title="Typing Speed" :min="10" :max="200" :step="5" value-unit="ms" /> <PreviewSlider v-model="typingSpeed" title="Typing Speed" :min="10" :max="200" :step="5" value-unit="ms" />
<PreviewSlider <PreviewSlider
v-model="pauseDuration" v-model="pauseDuration"
@@ -99,6 +99,14 @@ const cursorBlinkDuration = ref(0.5);
const { rerenderKey: key } = useForceRerender(); const { rerenderKey: key } = useForceRerender();
const cursorOptions = [
{ value: '_', label: 'Underscore (_)' },
{ value: '|', label: 'Pipe (|)' },
{ value: '▎', label: 'Block (▎)' },
{ value: '●', label: 'Dot (●)' },
{ value: '█', label: 'Full Block (█)' }
];
const propData = [ const propData = [
{ {
name: 'text', name: 'text',