Skip to content

Commit 1527ee2

Browse files
committed
chore(release): publish packages
- [email protected]
1 parent 254635c commit 1527ee2

File tree

6 files changed

+962
-1
lines changed

6 files changed

+962
-1
lines changed

packages/vyuh_node_flow/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.15.0
2+
3+
- **FEAT**: refactor test factory and add unit tests for constructor initialization.
4+
15
## 0.14.1
26

37
- **FEAT**: simplify drag operations across nodes, connections and resizers.

packages/vyuh_node_flow/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: vyuh_node_flow
22
description: A flexible, high-performance node-based flow editor for Flutter. Build visual programming interfaces, workflow editors, diagrams, and data pipelines.
3-
version: 0.14.1
3+
version: 0.15.0
44

55
homepage: https://vyuh.tech
66
repository: https://github.com/vyuh-tech/vyuh_node_flow
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
'use client';
2+
3+
import {
4+
Zap,
5+
Palette,
6+
Sparkles,
7+
Map,
8+
FileJson,
9+
Plug,
10+
ShieldCheck,
11+
Box,
12+
Activity,
13+
MessageSquare,
14+
Group,
15+
} from 'lucide-react';
16+
import { SectionHeader } from '@/components/section-header';
17+
import { BentoGrid, BentoCard } from '@/components/bento-grid';
18+
19+
const features = [
20+
{
21+
Icon: Zap,
22+
name: 'High Performance',
23+
description:
24+
'Rendering hundreds of nodes at 60fps with optimized virtualization.',
25+
href: '/docs/core-concepts/performance',
26+
cta: 'Learn more',
27+
className: 'lg:row-start-1 lg:row-end-2 lg:col-start-1 lg:col-end-3',
28+
background: (
29+
<div className="absolute inset-0 bg-gradient-to-br from-amber-100 to-transparent dark:from-amber-900/20 opacity-50" />
30+
),
31+
},
32+
{
33+
Icon: Palette,
34+
name: 'Custom Themes',
35+
description: 'Style every aspect of your graph to match your brand identity.',
36+
href: '/docs/theming',
37+
cta: 'Explore theming',
38+
className: 'lg:col-start-3 lg:col-end-4 lg:row-start-1 lg:row-end-2',
39+
background: (
40+
<div className="absolute inset-0 bg-gradient-to-br from-purple-100 to-transparent dark:from-purple-900/20 opacity-50" />
41+
),
42+
},
43+
{
44+
Icon: Plug,
45+
name: 'Smart Connections',
46+
description: 'Auto-routing, validation, and multiple path styles included.',
47+
href: '/docs/core-concepts/connections',
48+
cta: 'See connections',
49+
className: 'lg:col-start-1 lg:col-end-2 lg:row-start-2 lg:row-end-3',
50+
background: (
51+
<div className="absolute inset-0 bg-gradient-to-br from-blue-100 to-transparent dark:from-blue-900/20 opacity-50" />
52+
),
53+
},
54+
{
55+
Icon: Box,
56+
name: 'Custom Nodes',
57+
description:
58+
'Create any node UI you can imagine using standard Flutter widgets.',
59+
href: '/docs/core-concepts/custom-nodes',
60+
cta: 'Build nodes',
61+
className: 'lg:col-start-2 lg:col-end-4 lg:row-start-2 lg:row-end-3',
62+
background: (
63+
<div className="absolute inset-0 bg-gradient-to-br from-green-100 to-transparent dark:from-green-900/20 opacity-50" />
64+
),
65+
},
66+
{
67+
Icon: Map,
68+
name: 'MiniMap',
69+
description: 'Navigate huge graphs effortlessly with real-time overview.',
70+
href: '/docs/components/minimap',
71+
cta: 'Try minimap',
72+
className: 'lg:col-start-1 lg:col-end-2 lg:row-start-3 lg:row-end-4',
73+
background: (
74+
<div className="absolute inset-0 bg-gradient-to-br from-teal-100 to-transparent dark:from-teal-900/20 opacity-50" />
75+
),
76+
},
77+
{
78+
Icon: ShieldCheck,
79+
name: 'Type-Safe Data',
80+
description: 'Generic type support for strongly-typed node data.',
81+
href: '/docs/core-concepts/node-data',
82+
cta: 'See types',
83+
className: 'lg:col-start-2 lg:col-end-3 lg:row-start-3 lg:row-end-4',
84+
background: (
85+
<div className="absolute inset-0 bg-gradient-to-br from-emerald-100 to-transparent dark:from-emerald-900/20 opacity-50" />
86+
),
87+
},
88+
{
89+
Icon: FileJson,
90+
name: 'Serialization',
91+
description:
92+
'Save and load flows from JSON with type-safe deserialization.',
93+
href: '/docs/core-concepts/serialization',
94+
cta: 'Learn JSON',
95+
className: 'lg:col-start-3 lg:col-end-4 lg:row-start-3 lg:row-end-4',
96+
background: (
97+
<div className="absolute inset-0 bg-gradient-to-br from-orange-100 to-transparent dark:from-orange-900/20 opacity-50" />
98+
),
99+
},
100+
{
101+
Icon: Sparkles,
102+
name: 'Connection Effects',
103+
description: 'Animated effects like FlowingDash, Particle, and Pulse.',
104+
href: '/docs/core-concepts/connection-effects',
105+
cta: 'View effects',
106+
className: 'lg:col-start-1 lg:col-end-2 lg:row-start-4 lg:row-end-5',
107+
background: (
108+
<div className="absolute inset-0 bg-gradient-to-br from-pink-100 to-transparent dark:from-pink-900/20 opacity-50" />
109+
),
110+
},
111+
{
112+
Icon: Activity,
113+
name: 'Event System',
114+
description:
115+
'Rich event callbacks for user interactions and state changes.',
116+
href: '/docs/advanced/events',
117+
cta: 'Handle events',
118+
className: 'lg:col-start-2 lg:col-end-4 lg:row-start-4 lg:row-end-5',
119+
background: (
120+
<div className="absolute inset-0 bg-gradient-to-br from-indigo-100 to-transparent dark:from-indigo-900/20 opacity-50" />
121+
),
122+
},
123+
{
124+
Icon: MessageSquare,
125+
name: 'Annotations',
126+
description:
127+
'Add sticky notes, comments, and documentation directly on your canvas.',
128+
href: '/docs/advanced/annotations',
129+
cta: 'Add notes',
130+
className: 'lg:col-start-1 lg:col-end-3 lg:row-start-5 lg:row-end-6',
131+
background: (
132+
<div className="absolute inset-0 bg-gradient-to-br from-yellow-100 to-transparent dark:from-yellow-900/20 opacity-50" />
133+
),
134+
},
135+
{
136+
Icon: Group,
137+
name: 'Group Nodes',
138+
description:
139+
'Organize complex flows with collapsible groups and nested hierarchies.',
140+
href: '/docs/advanced/group-nodes',
141+
cta: 'Learn grouping',
142+
className: 'lg:col-start-3 lg:col-end-4 lg:row-start-5 lg:row-end-6',
143+
background: (
144+
<div className="absolute inset-0 bg-gradient-to-br from-cyan-100 to-transparent dark:from-cyan-900/20 opacity-50" />
145+
),
146+
},
147+
];
148+
149+
export function BentoGridSection() {
150+
return (
151+
<section className="py-32 relative z-20">
152+
<div className="container px-4 md:px-6 mx-auto">
153+
<div className="mb-20">
154+
<SectionHeader
155+
icon={<Sparkles className="w-5 h-5" />}
156+
tag="Packed with Features"
157+
tagColor="purple"
158+
title="Everything You Need"
159+
subtitle="A complete toolkit for building professional node-based interfaces."
160+
/>
161+
</div>
162+
<BentoGrid className="lg:grid-rows-5">
163+
{features.map((feature) => (
164+
<BentoCard key={feature.name} {...feature} />
165+
))}
166+
</BentoGrid>
167+
</div>
168+
</section>
169+
);
170+
}
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
'use client';
2+
3+
import Link from 'next/link';
4+
import React, { useEffect, useState } from 'react';
5+
import { ArrowRight } from 'lucide-react';
6+
import { SiFlutter } from 'react-icons/si';
7+
import { HeroVisual } from '@/components/hero-visual';
8+
import { GridBackground } from '@/components/grid-background';
9+
import { BlinkingGridBackground } from '@/components/blinking-grid';
10+
import { FloatingOrbs } from '@/components/floating-orbs';
11+
import { ScrambleText } from '@/components/scramble-text';
12+
import { SCENARIOS } from '@/components/hero-scenarios';
13+
import { clsx } from 'clsx';
14+
import { twMerge } from 'tailwind-merge';
15+
import { motion, AnimatePresence } from 'motion/react';
16+
import { useIsMobile } from '@/hooks/use-mobile';
17+
18+
function cn(...inputs: (string | undefined | null | false)[]) {
19+
return twMerge(clsx(inputs));
20+
}
21+
22+
const CYCLE_DURATION = 5000;
23+
24+
export function HeroSection() {
25+
const [activeIndex, setActiveIndex] = useState(0);
26+
const [isLocked, setIsLocked] = useState(false);
27+
const [mounted, setMounted] = useState(false);
28+
const isMobile = useIsMobile();
29+
30+
useEffect(() => {
31+
setMounted(true);
32+
}, []);
33+
34+
useEffect(() => {
35+
if (isLocked) return;
36+
37+
const timer = setInterval(() => {
38+
setActiveIndex((prev) => (prev + 1) % SCENARIOS.length);
39+
}, CYCLE_DURATION);
40+
41+
return () => clearInterval(timer);
42+
}, [isLocked]);
43+
44+
const activeScenario = SCENARIOS[activeIndex];
45+
46+
return (
47+
<section
48+
className="relative w-full overflow-hidden min-h-screen flex flex-col justify-center"
49+
onClick={() => setIsLocked(false)}
50+
>
51+
{/* Fixed Background Layer */}
52+
<div className="absolute inset-0 z-0 pointer-events-none">
53+
<GridBackground />
54+
<div className="absolute inset-0 [mask-image:linear-gradient(to_bottom,black_0%,black_60%,transparent_80%)]">
55+
<BlinkingGridBackground />
56+
</div>
57+
</div>
58+
59+
{/* Floating Orbs - only on desktop */}
60+
<FloatingOrbs />
61+
62+
{/* Ambient Lighting */}
63+
<div className="absolute top-[-10%] left-[-10%] w-[70%] h-[90%] bg-blue-300/30 dark:bg-blue-600/20 blur-[150px] dark:blur-[200px] rounded-full pointer-events-none" />
64+
<div className="absolute bottom-[-10%] right-[-10%] w-[70%] h-[90%] bg-purple-300/30 dark:bg-purple-600/30 blur-[150px] dark:blur-[200px] rounded-full pointer-events-none" />
65+
66+
<div className="container relative z-10 px-4 md:px-6 mx-auto pt-32 pb-20">
67+
<div className="text-center mb-16">
68+
{mounted ? (
69+
<motion.div
70+
initial={{ opacity: 0, y: 20 }}
71+
animate={{ opacity: 1, y: 0 }}
72+
className="inline-flex items-center rounded-full border border-blue-500/20 bg-blue-500/10 px-4 py-1.5 text-sm font-medium text-blue-600 dark:text-blue-300 backdrop-blur-xl mb-8 shadow-lg shadow-blue-500/10"
73+
>
74+
<span className="flex h-2.5 w-2.5 rounded-full bg-blue-400 mr-2.5 shadow-[0_0_10px_#3b82f6]"></span>
75+
Beta now available
76+
</motion.div>
77+
) : (
78+
<div className="inline-flex items-center rounded-full border border-blue-500/20 bg-blue-500/10 px-4 py-1.5 text-sm font-medium text-blue-600 dark:text-blue-300 backdrop-blur-xl mb-8 shadow-lg shadow-blue-500/10">
79+
<span className="flex h-2.5 w-2.5 rounded-full bg-blue-400 mr-2.5 shadow-[0_0_10px_#3b82f6]"></span>
80+
Beta now available
81+
</div>
82+
)}
83+
84+
<h1 className="text-6xl md:text-8xl font-black font-heading mb-8 text-slate-900 dark:text-white drop-shadow-sm px-4">
85+
Visualize Your <br className="hidden md:block" />
86+
<span className="inline-block py-2 pr-4 text-transparent bg-clip-text bg-gradient-to-r from-blue-600 via-indigo-500 to-purple-600 dark:from-blue-400 dark:via-white dark:to-purple-400 uppercase tracking-tight">
87+
<ScrambleText /> Flow
88+
</span>
89+
</h1>
90+
91+
<p className="max-w-3xl mx-auto text-xl md:text-2xl text-slate-600 dark:text-slate-300 mb-12 leading-relaxed font-medium">
92+
A high-performance, fully customizable node-based flow editor for{' '}
93+
<span className="inline-flex items-baseline font-bold text-blue-600 dark:text-blue-400 uppercase tracking-tight">
94+
<SiFlutter className="w-5 h-5 md:w-6 md:h-6 mr-1" />
95+
Flutter
96+
</span>
97+
. Build workflow editors and process automation tools with
98+
<span className="font-bold text-blue-600 dark:text-blue-400">
99+
{' '}
100+
fluid precision
101+
</span>
102+
.
103+
</p>
104+
105+
<div className="flex flex-col sm:flex-row gap-6 justify-center items-center">
106+
<div className="relative group">
107+
<div className="absolute -inset-[2px] rounded-full bg-gradient-to-r from-blue-600 via-purple-500 to-blue-600 opacity-75 blur-sm group-hover:opacity-100 group-hover:blur-md transition-all duration-200 animate-gradient-x" />
108+
<div className="absolute -inset-4 rounded-full bg-blue-500/20 blur-xl opacity-0 group-hover:opacity-100 transition-opacity duration-200" />
109+
<Link
110+
href="/docs/getting-started"
111+
className="relative inline-flex items-center justify-center h-14 px-10 rounded-full bg-blue-600 text-white font-black font-heading text-xl transition-all duration-150 hover:bg-blue-500 hover:scale-105 shadow-xl shadow-blue-500/30 active:scale-95"
112+
>
113+
Start Building
114+
<ArrowRight className="ml-2 h-6 w-6" />
115+
</Link>
116+
</div>
117+
<a
118+
href="https://flow.demo.vyuh.tech"
119+
target="_blank"
120+
rel="noreferrer"
121+
className="inline-flex items-center justify-center h-14 px-10 rounded-full border border-slate-300 dark:border-blue-400/40 bg-white/50 dark:bg-white/5 text-slate-900 dark:text-blue-100 font-bold text-xl transition-all duration-150 hover:bg-white/80 dark:hover:bg-white/10 hover:border-blue-400 hover:shadow-lg hover:shadow-blue-500/10 backdrop-blur-xl active:scale-95"
122+
>
123+
Live Demo
124+
</a>
125+
</div>
126+
</div>
127+
128+
{/* Interactive Demo Section */}
129+
<div className="grid grid-cols-1 lg:grid-cols-12 gap-10 lg:gap-16 items-center">
130+
<div className="lg:col-span-4 flex flex-col gap-4">
131+
{SCENARIOS.map((scenario, index) => {
132+
const isActive = activeIndex === index;
133+
return (
134+
<button
135+
key={scenario.id}
136+
onClick={(e) => {
137+
e.stopPropagation();
138+
setActiveIndex(index);
139+
setIsLocked(true);
140+
}}
141+
className={cn(
142+
'relative text-left p-6 rounded-2xl transition-all duration-150 border overflow-hidden backdrop-blur-3xl group',
143+
isActive
144+
? 'border-blue-500/60 shadow-xl shadow-blue-500/10 scale-[1.02] bg-white/[0.08] dark:bg-white/[0.04]'
145+
: 'border-slate-200/50 dark:border-white/5 bg-white/[0.02] dark:bg-white/[0.01] hover:bg-white/[0.06] hover:border-blue-300/30 text-slate-500'
146+
)}
147+
>
148+
{isActive && !isLocked && !isMobile && (
149+
<motion.div
150+
key={`progress-${index}`}
151+
initial={{ x: '-100%' }}
152+
animate={{ x: '0%' }}
153+
transition={{
154+
duration: CYCLE_DURATION / 1000,
155+
ease: 'linear',
156+
}}
157+
className="absolute inset-0 bg-blue-500/20 z-0 origin-left"
158+
/>
159+
)}
160+
{isActive && isLocked && (
161+
<div className="absolute inset-0 bg-blue-500/[0.15] z-0" />
162+
)}
163+
<div className="relative z-10">
164+
<div
165+
className={cn(
166+
'font-black font-heading text-lg mb-1 transition-all duration-300 tracking-widest uppercase',
167+
isActive
168+
? 'text-blue-700 dark:text-blue-300'
169+
: 'text-slate-500 dark:text-slate-400 group-hover:text-slate-700 dark:group-hover:text-white'
170+
)}
171+
>
172+
{scenario.label}
173+
</div>
174+
<div
175+
className={cn(
176+
'text-sm font-bold leading-relaxed transition-all duration-300',
177+
isActive
178+
? 'text-slate-800 dark:text-blue-100/90'
179+
: 'text-slate-400 dark:text-slate-500'
180+
)}
181+
>
182+
{scenario.description}
183+
</div>
184+
</div>
185+
</button>
186+
);
187+
})}
188+
</div>
189+
<div className="lg:col-span-8 relative h-[400px] lg:h-[600px]">
190+
<div className="absolute inset-0 flex items-center justify-center">
191+
<AnimatePresence mode="wait">
192+
<motion.div
193+
key={activeIndex}
194+
initial={{ opacity: 0, scale: 0.95 }}
195+
animate={{ opacity: 1, scale: 1 }}
196+
exit={{ opacity: 0, scale: 1.05 }}
197+
transition={{ duration: 0.5 }}
198+
className="w-full h-full flex items-center justify-center"
199+
>
200+
<HeroVisual
201+
nodes={activeScenario.nodes}
202+
connections={activeScenario.connections}
203+
/>
204+
</motion.div>
205+
</AnimatePresence>
206+
</div>
207+
</div>
208+
</div>
209+
</div>
210+
</section>
211+
);
212+
}

0 commit comments

Comments
 (0)