@sonordev/agency-site-kit 0.1.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/dist/BeforeAfterSection-6QUJOBO2.js +176 -0
- package/dist/BeforeAfterSection-6QUJOBO2.js.map +1 -0
- package/dist/BeforeAfterSection-DVAWWE4K.cjs +181 -0
- package/dist/BeforeAfterSection-DVAWWE4K.cjs.map +1 -0
- package/dist/CTASection-4JKLXEUF.cjs +111 -0
- package/dist/CTASection-4JKLXEUF.cjs.map +1 -0
- package/dist/CTASection-BJA72XIL.js +106 -0
- package/dist/CTASection-BJA72XIL.js.map +1 -0
- package/dist/ChallengesSection-GEQGVSJN.js +180 -0
- package/dist/ChallengesSection-GEQGVSJN.js.map +1 -0
- package/dist/ChallengesSection-IZ3DHECS.cjs +182 -0
- package/dist/ChallengesSection-IZ3DHECS.cjs.map +1 -0
- package/dist/ConversionFunnelSection-AUUSJ5HQ.cjs +209 -0
- package/dist/ConversionFunnelSection-AUUSJ5HQ.cjs.map +1 -0
- package/dist/ConversionFunnelSection-D3GE4NKE.js +203 -0
- package/dist/ConversionFunnelSection-D3GE4NKE.js.map +1 -0
- package/dist/DetailsSection-FB763FS7.js +135 -0
- package/dist/DetailsSection-FB763FS7.js.map +1 -0
- package/dist/DetailsSection-OACJFGH7.cjs +137 -0
- package/dist/DetailsSection-OACJFGH7.cjs.map +1 -0
- package/dist/FeatureSpotlightSection-B7P3JGNL.js +205 -0
- package/dist/FeatureSpotlightSection-B7P3JGNL.js.map +1 -0
- package/dist/FeatureSpotlightSection-WRHXS7TU.cjs +210 -0
- package/dist/FeatureSpotlightSection-WRHXS7TU.cjs.map +1 -0
- package/dist/GallerySection-VMKORC47.js +218 -0
- package/dist/GallerySection-VMKORC47.js.map +1 -0
- package/dist/GallerySection-WJ4PQDBI.cjs +219 -0
- package/dist/GallerySection-WJ4PQDBI.cjs.map +1 -0
- package/dist/MetricsTimelineSection-4L6DUHJ5.cjs +258 -0
- package/dist/MetricsTimelineSection-4L6DUHJ5.cjs.map +1 -0
- package/dist/MetricsTimelineSection-6BT5GNFV.js +253 -0
- package/dist/MetricsTimelineSection-6BT5GNFV.js.map +1 -0
- package/dist/ResultsSection-DFUJ5U6M.js +93 -0
- package/dist/ResultsSection-DFUJ5U6M.js.map +1 -0
- package/dist/ResultsSection-XLGMMQKY.cjs +95 -0
- package/dist/ResultsSection-XLGMMQKY.cjs.map +1 -0
- package/dist/ServicesSection-D5V3Q4GR.js +118 -0
- package/dist/ServicesSection-D5V3Q4GR.js.map +1 -0
- package/dist/ServicesSection-WJMGK2MF.cjs +120 -0
- package/dist/ServicesSection-WJMGK2MF.cjs.map +1 -0
- package/dist/StrategySection-3ED3QW4R.cjs +180 -0
- package/dist/StrategySection-3ED3QW4R.cjs.map +1 -0
- package/dist/StrategySection-VUWMIYYP.js +175 -0
- package/dist/StrategySection-VUWMIYYP.js.map +1 -0
- package/dist/TeamSection-DZVSNZE6.cjs +112 -0
- package/dist/TeamSection-DZVSNZE6.cjs.map +1 -0
- package/dist/TeamSection-HGKFW6PQ.js +107 -0
- package/dist/TeamSection-HGKFW6PQ.js.map +1 -0
- package/dist/TechStackSection-OCUYG4XT.js +90 -0
- package/dist/TechStackSection-OCUYG4XT.js.map +1 -0
- package/dist/TechStackSection-VKJK4KQB.cjs +91 -0
- package/dist/TechStackSection-VKJK4KQB.cjs.map +1 -0
- package/dist/TestimonialSection-6RGSMXQB.js +122 -0
- package/dist/TestimonialSection-6RGSMXQB.js.map +1 -0
- package/dist/TestimonialSection-XPTFUQIN.cjs +124 -0
- package/dist/TestimonialSection-XPTFUQIN.cjs.map +1 -0
- package/dist/VideoSection-4A2HC6K6.js +117 -0
- package/dist/VideoSection-4A2HC6K6.js.map +1 -0
- package/dist/VideoSection-G3DFS7UH.cjs +118 -0
- package/dist/VideoSection-G3DFS7UH.cjs.map +1 -0
- package/dist/chunk-2VNNFAG6.js +415 -0
- package/dist/chunk-2VNNFAG6.js.map +1 -0
- package/dist/chunk-2Y4O3LWM.js +53 -0
- package/dist/chunk-2Y4O3LWM.js.map +1 -0
- package/dist/chunk-5FKOLIV6.cjs +221 -0
- package/dist/chunk-5FKOLIV6.cjs.map +1 -0
- package/dist/chunk-7CFFAKDM.js +74 -0
- package/dist/chunk-7CFFAKDM.js.map +1 -0
- package/dist/chunk-A4I4IK7V.js +69 -0
- package/dist/chunk-A4I4IK7V.js.map +1 -0
- package/dist/chunk-IKBK7HYX.cjs +79 -0
- package/dist/chunk-IKBK7HYX.cjs.map +1 -0
- package/dist/chunk-KEOHORIH.cjs +79 -0
- package/dist/chunk-KEOHORIH.cjs.map +1 -0
- package/dist/chunk-NAS4K5UR.cjs +139 -0
- package/dist/chunk-NAS4K5UR.cjs.map +1 -0
- package/dist/chunk-QBLWP25X.cjs +73 -0
- package/dist/chunk-QBLWP25X.cjs.map +1 -0
- package/dist/chunk-QIC6JFFD.js +210 -0
- package/dist/chunk-QIC6JFFD.js.map +1 -0
- package/dist/chunk-TAPNXT7X.cjs +422 -0
- package/dist/chunk-TAPNXT7X.cjs.map +1 -0
- package/dist/chunk-XCKXHK44.js +15 -0
- package/dist/chunk-XCKXHK44.js.map +1 -0
- package/dist/chunk-XMC4DN6G.js +131 -0
- package/dist/chunk-XMC4DN6G.js.map +1 -0
- package/dist/chunk-XONXEFJY.cjs +58 -0
- package/dist/chunk-XONXEFJY.cjs.map +1 -0
- package/dist/chunk-XQNJED46.cjs +19 -0
- package/dist/chunk-XQNJED46.cjs.map +1 -0
- package/dist/chunk-YB4B3OMC.js +74 -0
- package/dist/chunk-YB4B3OMC.js.map +1 -0
- package/dist/index.cjs +271 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +137 -0
- package/dist/index.d.ts +137 -0
- package/dist/index.js +197 -0
- package/dist/index.js.map +1 -0
- package/dist/layout/index.cjs +13 -0
- package/dist/layout/index.cjs.map +1 -0
- package/dist/layout/index.d.cts +54 -0
- package/dist/layout/index.d.ts +54 -0
- package/dist/layout/index.js +4 -0
- package/dist/layout/index.js.map +1 -0
- package/dist/portfolio/client.cjs +18 -0
- package/dist/portfolio/client.cjs.map +1 -0
- package/dist/portfolio/client.d.cts +97 -0
- package/dist/portfolio/client.d.ts +97 -0
- package/dist/portfolio/client.js +6 -0
- package/dist/portfolio/client.js.map +1 -0
- package/dist/portfolio/index.cjs +41 -0
- package/dist/portfolio/index.cjs.map +1 -0
- package/dist/portfolio/index.d.cts +12 -0
- package/dist/portfolio/index.d.ts +12 -0
- package/dist/portfolio/index.js +8 -0
- package/dist/portfolio/index.js.map +1 -0
- package/dist/portfolio/sections.cjs +20 -0
- package/dist/portfolio/sections.cjs.map +1 -0
- package/dist/portfolio/sections.d.cts +42 -0
- package/dist/portfolio/sections.d.ts +42 -0
- package/dist/portfolio/sections.js +4 -0
- package/dist/portfolio/sections.js.map +1 -0
- package/dist/portfolio/server.cjs +141 -0
- package/dist/portfolio/server.cjs.map +1 -0
- package/dist/portfolio/server.d.cts +68 -0
- package/dist/portfolio/server.d.ts +68 -0
- package/dist/portfolio/server.js +134 -0
- package/dist/portfolio/server.js.map +1 -0
- package/dist/types-BMUhBhWx.d.cts +346 -0
- package/dist/types-BMUhBhWx.d.ts +346 -0
- package/package.json +71 -0
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkXONXEFJY_cjs = require('./chunk-XONXEFJY.cjs');
|
|
4
|
+
var chunkKEOHORIH_cjs = require('./chunk-KEOHORIH.cjs');
|
|
5
|
+
var chunkIKBK7HYX_cjs = require('./chunk-IKBK7HYX.cjs');
|
|
6
|
+
var React = require('react');
|
|
7
|
+
var gsap = require('gsap');
|
|
8
|
+
var ScrollTrigger = require('gsap/ScrollTrigger');
|
|
9
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
10
|
+
|
|
11
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
+
|
|
13
|
+
var React__default = /*#__PURE__*/_interopDefault(React);
|
|
14
|
+
var gsap__default = /*#__PURE__*/_interopDefault(gsap);
|
|
15
|
+
|
|
16
|
+
function ConversionFunnelSection({ data }) {
|
|
17
|
+
const funnelRef = React.useRef(null);
|
|
18
|
+
const flowLinesRef = React.useRef(null);
|
|
19
|
+
React.useEffect(() => {
|
|
20
|
+
gsap__default.default.registerPlugin(ScrollTrigger.ScrollTrigger);
|
|
21
|
+
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
22
|
+
if (prefersReducedMotion) return;
|
|
23
|
+
const ctx = gsap__default.default.context(() => {
|
|
24
|
+
const stages = funnelRef.current?.querySelectorAll(".funnel-stage-fill");
|
|
25
|
+
if (stages && stages.length > 0) {
|
|
26
|
+
gsap__default.default.fromTo(
|
|
27
|
+
stages,
|
|
28
|
+
{ scaleX: 0 },
|
|
29
|
+
{
|
|
30
|
+
scaleX: 1,
|
|
31
|
+
duration: 0.8,
|
|
32
|
+
stagger: 0.2,
|
|
33
|
+
ease: "power2.out",
|
|
34
|
+
transformOrigin: "left center",
|
|
35
|
+
scrollTrigger: {
|
|
36
|
+
trigger: funnelRef.current,
|
|
37
|
+
start: "top 70%",
|
|
38
|
+
toggleActions: "play none none none"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
const flowLines = flowLinesRef.current?.querySelectorAll(".flow-connector");
|
|
44
|
+
if (flowLines && flowLines.length > 0) {
|
|
45
|
+
gsap__default.default.fromTo(
|
|
46
|
+
flowLines,
|
|
47
|
+
{ scaleX: 0, opacity: 0 },
|
|
48
|
+
{
|
|
49
|
+
scaleX: 1,
|
|
50
|
+
opacity: 1,
|
|
51
|
+
duration: 0.5,
|
|
52
|
+
stagger: 0.15,
|
|
53
|
+
delay: 0.3,
|
|
54
|
+
ease: "power2.out",
|
|
55
|
+
transformOrigin: "left center",
|
|
56
|
+
scrollTrigger: {
|
|
57
|
+
trigger: funnelRef.current,
|
|
58
|
+
start: "top 70%",
|
|
59
|
+
toggleActions: "play none none none"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
return () => ctx.revert();
|
|
66
|
+
}, [data.stages.length]);
|
|
67
|
+
const maxValue = Math.max(...data.stages.map((s) => s.value), 1);
|
|
68
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
69
|
+
"section",
|
|
70
|
+
{
|
|
71
|
+
className: "w-full py-20 md:py-28",
|
|
72
|
+
style: { background: "var(--sk-bg, #0a0a0a)" },
|
|
73
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "max-w-6xl mx-auto px-6", children: [
|
|
74
|
+
(data.title || data.description) && /* @__PURE__ */ jsxRuntime.jsxs(chunkIKBK7HYX_cjs.ScrollReveal, { y: 30, children: [
|
|
75
|
+
data.title && /* @__PURE__ */ jsxRuntime.jsx(
|
|
76
|
+
"h2",
|
|
77
|
+
{
|
|
78
|
+
className: "text-3xl md:text-4xl font-bold mb-4",
|
|
79
|
+
style: {
|
|
80
|
+
color: "var(--sk-text-primary, #ffffff)",
|
|
81
|
+
fontFamily: "var(--sk-font-heading, inherit)"
|
|
82
|
+
},
|
|
83
|
+
children: data.title
|
|
84
|
+
}
|
|
85
|
+
),
|
|
86
|
+
data.description && /* @__PURE__ */ jsxRuntime.jsx(
|
|
87
|
+
"p",
|
|
88
|
+
{
|
|
89
|
+
className: "text-lg mb-12 max-w-2xl",
|
|
90
|
+
style: { color: "var(--sk-text-secondary, #a1a1aa)" },
|
|
91
|
+
children: data.description
|
|
92
|
+
}
|
|
93
|
+
)
|
|
94
|
+
] }),
|
|
95
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { ref: funnelRef, className: "hidden md:block", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-end gap-0 relative", ref: flowLinesRef, children: data.stages.map((stage, index) => {
|
|
96
|
+
const widthPercent = 60 + stage.value / maxValue * 40;
|
|
97
|
+
const stageColor = stage.color || "var(--sk-primary, #6366f1)";
|
|
98
|
+
const dropOff = index > 0 ? Math.round(
|
|
99
|
+
(data.stages[index - 1].value - stage.value) / data.stages[index - 1].value * 100
|
|
100
|
+
) : null;
|
|
101
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React__default.default.Fragment, { children: [
|
|
102
|
+
dropOff !== null && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center px-2 shrink-0", style: { minWidth: 48 }, children: [
|
|
103
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
104
|
+
"div",
|
|
105
|
+
{
|
|
106
|
+
className: "flow-connector h-0.5 w-full mb-1",
|
|
107
|
+
style: {
|
|
108
|
+
background: `linear-gradient(to right, ${data.stages[index - 1].color || "var(--sk-primary, #6366f1)"}, ${stageColor})`,
|
|
109
|
+
willChange: "transform"
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
),
|
|
113
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
114
|
+
"span",
|
|
115
|
+
{
|
|
116
|
+
className: "text-xs font-medium whitespace-nowrap",
|
|
117
|
+
style: { color: "var(--sk-text-tertiary, #71717a)" },
|
|
118
|
+
children: [
|
|
119
|
+
"-",
|
|
120
|
+
dropOff,
|
|
121
|
+
"%"
|
|
122
|
+
]
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
] }),
|
|
126
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", style: { maxWidth: `${widthPercent}%` }, children: /* @__PURE__ */ jsxRuntime.jsx(chunkKEOHORIH_cjs.GlassCard, { padding: "md", hover: false, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative overflow-hidden rounded-lg", children: [
|
|
127
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
128
|
+
"div",
|
|
129
|
+
{
|
|
130
|
+
className: "funnel-stage-fill absolute inset-0 rounded-lg opacity-15",
|
|
131
|
+
style: {
|
|
132
|
+
background: stageColor,
|
|
133
|
+
willChange: "transform"
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
),
|
|
137
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative flex flex-col items-center gap-2 py-4", children: [
|
|
138
|
+
stage.icon && /* @__PURE__ */ jsxRuntime.jsx("img", { src: stage.icon, alt: "", width: 24, height: 24, className: "w-6 h-6 object-contain" }),
|
|
139
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
140
|
+
"span",
|
|
141
|
+
{
|
|
142
|
+
className: "text-xs font-semibold uppercase tracking-wider text-center",
|
|
143
|
+
style: { color: "var(--sk-text-tertiary, #71717a)" },
|
|
144
|
+
children: stage.label
|
|
145
|
+
}
|
|
146
|
+
),
|
|
147
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
148
|
+
"div",
|
|
149
|
+
{
|
|
150
|
+
className: "text-2xl font-bold",
|
|
151
|
+
style: { color: stageColor },
|
|
152
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(chunkXONXEFJY_cjs.AnimatedCounter, { value: stage.value, duration: 2 })
|
|
153
|
+
}
|
|
154
|
+
)
|
|
155
|
+
] })
|
|
156
|
+
] }) }) })
|
|
157
|
+
] }, index);
|
|
158
|
+
}) }) }),
|
|
159
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "md:hidden flex flex-col gap-3", children: data.stages.map((stage, index) => {
|
|
160
|
+
const widthPercent = 60 + stage.value / maxValue * 40;
|
|
161
|
+
const stageColor = stage.color || "var(--sk-primary, #6366f1)";
|
|
162
|
+
const dropOff = index > 0 ? Math.round(
|
|
163
|
+
(data.stages[index - 1].value - stage.value) / data.stages[index - 1].value * 100
|
|
164
|
+
) : null;
|
|
165
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React__default.default.Fragment, { children: [
|
|
166
|
+
dropOff !== null && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center py-1", children: [
|
|
167
|
+
/* @__PURE__ */ jsxRuntime.jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M10 4v12M6 12l4 4 4-4", stroke: "var(--sk-text-tertiary, #71717a)", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }),
|
|
168
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
169
|
+
"span",
|
|
170
|
+
{
|
|
171
|
+
className: "text-xs font-medium ml-2",
|
|
172
|
+
style: { color: "var(--sk-text-tertiary, #71717a)" },
|
|
173
|
+
children: [
|
|
174
|
+
"-",
|
|
175
|
+
dropOff,
|
|
176
|
+
"% drop-off"
|
|
177
|
+
]
|
|
178
|
+
}
|
|
179
|
+
)
|
|
180
|
+
] }),
|
|
181
|
+
/* @__PURE__ */ jsxRuntime.jsx(chunkIKBK7HYX_cjs.ScrollReveal, { y: 20, delay: index * 0.1, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: { width: `${widthPercent}%`, marginLeft: "auto", marginRight: "auto" }, children: /* @__PURE__ */ jsxRuntime.jsx(chunkKEOHORIH_cjs.GlassCard, { padding: "md", hover: false, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-4", children: [
|
|
182
|
+
stage.icon && /* @__PURE__ */ jsxRuntime.jsx("img", { src: stage.icon, alt: "", width: 24, height: 24, className: "w-6 h-6 object-contain shrink-0" }),
|
|
183
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
184
|
+
"span",
|
|
185
|
+
{
|
|
186
|
+
className: "text-xs font-semibold uppercase tracking-wider",
|
|
187
|
+
style: { color: "var(--sk-text-tertiary, #71717a)" },
|
|
188
|
+
children: stage.label
|
|
189
|
+
}
|
|
190
|
+
) }),
|
|
191
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
192
|
+
"div",
|
|
193
|
+
{
|
|
194
|
+
className: "text-xl font-bold",
|
|
195
|
+
style: { color: stageColor },
|
|
196
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(chunkXONXEFJY_cjs.AnimatedCounter, { value: stage.value, duration: 2 })
|
|
197
|
+
}
|
|
198
|
+
)
|
|
199
|
+
] }) }) }) })
|
|
200
|
+
] }, index);
|
|
201
|
+
}) })
|
|
202
|
+
] })
|
|
203
|
+
}
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
module.exports = ConversionFunnelSection;
|
|
208
|
+
//# sourceMappingURL=ConversionFunnelSection-AUUSJ5HQ.cjs.map
|
|
209
|
+
//# sourceMappingURL=ConversionFunnelSection-AUUSJ5HQ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/portfolio/components/sections/ConversionFunnelSection.tsx"],"names":["useRef","useEffect","gsap","ScrollTrigger","jsx","jsxs","ScrollReveal","React","GlassCard","AnimatedCounter"],"mappings":"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","file":"ConversionFunnelSection-AUUSJ5HQ.cjs","sourcesContent":["'use client';\n\nimport React, { useRef, useEffect } from 'react';\nimport gsap from 'gsap';\nimport { ScrollTrigger } from 'gsap/ScrollTrigger';\nimport type { PortfolioConversionFunnelData } from '../../../types';\nimport ScrollReveal from '../primitives/ScrollReveal';\nimport AnimatedCounter from '../primitives/AnimatedCounter';\nimport GlassCard from '../primitives/GlassCard';\n\ninterface ConversionFunnelSectionProps {\n data: PortfolioConversionFunnelData;\n}\n\nexport default function ConversionFunnelSection({ data }: ConversionFunnelSectionProps) {\n const funnelRef = useRef<HTMLDivElement>(null);\n const flowLinesRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n gsap.registerPlugin(ScrollTrigger);\n\n const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n if (prefersReducedMotion) return;\n\n const ctx = gsap.context(() => {\n // Fill stages left-to-right with color\n const stages = funnelRef.current?.querySelectorAll('.funnel-stage-fill');\n if (stages && stages.length > 0) {\n gsap.fromTo(\n stages,\n { scaleX: 0 },\n {\n scaleX: 1,\n duration: 0.8,\n stagger: 0.2,\n ease: 'power2.out',\n transformOrigin: 'left center',\n scrollTrigger: {\n trigger: funnelRef.current,\n start: 'top 70%',\n toggleActions: 'play none none none',\n },\n },\n );\n }\n\n // Animate flow line connectors\n const flowLines = flowLinesRef.current?.querySelectorAll('.flow-connector');\n if (flowLines && flowLines.length > 0) {\n gsap.fromTo(\n flowLines,\n { scaleX: 0, opacity: 0 },\n {\n scaleX: 1,\n opacity: 1,\n duration: 0.5,\n stagger: 0.15,\n delay: 0.3,\n ease: 'power2.out',\n transformOrigin: 'left center',\n scrollTrigger: {\n trigger: funnelRef.current,\n start: 'top 70%',\n toggleActions: 'play none none none',\n },\n },\n );\n }\n });\n\n return () => ctx.revert();\n }, [data.stages.length]);\n\n const maxValue = Math.max(...data.stages.map((s) => s.value), 1);\n\n return (\n <section\n className=\"w-full py-20 md:py-28\"\n style={{ background: 'var(--sk-bg, #0a0a0a)' }}\n >\n <div className=\"max-w-6xl mx-auto px-6\">\n {(data.title || data.description) && (\n <ScrollReveal y={30}>\n {data.title && (\n <h2\n className=\"text-3xl md:text-4xl font-bold mb-4\"\n style={{\n color: 'var(--sk-text-primary, #ffffff)',\n fontFamily: 'var(--sk-font-heading, inherit)',\n }}\n >\n {data.title}\n </h2>\n )}\n {data.description && (\n <p\n className=\"text-lg mb-12 max-w-2xl\"\n style={{ color: 'var(--sk-text-secondary, #a1a1aa)' }}\n >\n {data.description}\n </p>\n )}\n </ScrollReveal>\n )}\n\n {/* Desktop: horizontal funnel */}\n <div ref={funnelRef} className=\"hidden md:block\">\n <div className=\"flex items-end gap-0 relative\" ref={flowLinesRef}>\n {data.stages.map((stage, index) => {\n const widthPercent = 60 + (stage.value / maxValue) * 40;\n const stageColor = stage.color || 'var(--sk-primary, #6366f1)';\n const dropOff =\n index > 0\n ? Math.round(\n ((data.stages[index - 1].value - stage.value) /\n data.stages[index - 1].value) *\n 100,\n )\n : null;\n\n return (\n <React.Fragment key={index}>\n {/* Drop-off connector */}\n {dropOff !== null && (\n <div className=\"flex flex-col items-center justify-center px-2 shrink-0\" style={{ minWidth: 48 }}>\n <div\n className=\"flow-connector h-0.5 w-full mb-1\"\n style={{\n background: `linear-gradient(to right, ${data.stages[index - 1].color || 'var(--sk-primary, #6366f1)'}, ${stageColor})`,\n willChange: 'transform',\n }}\n />\n <span\n className=\"text-xs font-medium whitespace-nowrap\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n -{dropOff}%\n </span>\n </div>\n )}\n\n {/* Stage card */}\n <div className=\"flex-1\" style={{ maxWidth: `${widthPercent}%` }}>\n <GlassCard padding=\"md\" hover={false}>\n <div className=\"relative overflow-hidden rounded-lg\">\n {/* Animated fill bar */}\n <div\n className=\"funnel-stage-fill absolute inset-0 rounded-lg opacity-15\"\n style={{\n background: stageColor,\n willChange: 'transform',\n }}\n />\n <div className=\"relative flex flex-col items-center gap-2 py-4\">\n {/* Icon */}\n {stage.icon && (\n <img src={stage.icon} alt=\"\" width={24} height={24} className=\"w-6 h-6 object-contain\" />\n )}\n <span\n className=\"text-xs font-semibold uppercase tracking-wider text-center\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n {stage.label}\n </span>\n <div\n className=\"text-2xl font-bold\"\n style={{ color: stageColor }}\n >\n <AnimatedCounter value={stage.value} duration={2} />\n </div>\n </div>\n </div>\n </GlassCard>\n </div>\n </React.Fragment>\n );\n })}\n </div>\n </div>\n\n {/* Mobile: vertical funnel */}\n <div className=\"md:hidden flex flex-col gap-3\">\n {data.stages.map((stage, index) => {\n const widthPercent = 60 + (stage.value / maxValue) * 40;\n const stageColor = stage.color || 'var(--sk-primary, #6366f1)';\n const dropOff =\n index > 0\n ? Math.round(\n ((data.stages[index - 1].value - stage.value) /\n data.stages[index - 1].value) *\n 100,\n )\n : null;\n\n return (\n <React.Fragment key={index}>\n {dropOff !== null && (\n <div className=\"flex items-center justify-center py-1\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path d=\"M10 4v12M6 12l4 4 4-4\" stroke=\"var(--sk-text-tertiary, #71717a)\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n <span\n className=\"text-xs font-medium ml-2\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n -{dropOff}% drop-off\n </span>\n </div>\n )}\n <ScrollReveal y={20} delay={index * 0.1}>\n <div style={{ width: `${widthPercent}%`, marginLeft: 'auto', marginRight: 'auto' }}>\n <GlassCard padding=\"md\" hover={false}>\n <div className=\"flex items-center gap-4\">\n {stage.icon && (\n <img src={stage.icon} alt=\"\" width={24} height={24} className=\"w-6 h-6 object-contain shrink-0\" />\n )}\n <div className=\"flex-1\">\n <span\n className=\"text-xs font-semibold uppercase tracking-wider\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n {stage.label}\n </span>\n </div>\n <div\n className=\"text-xl font-bold\"\n style={{ color: stageColor }}\n >\n <AnimatedCounter value={stage.value} duration={2} />\n </div>\n </div>\n </GlassCard>\n </div>\n </ScrollReveal>\n </React.Fragment>\n );\n })}\n </div>\n </div>\n </section>\n );\n}\n"]}
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { AnimatedCounter } from './chunk-2Y4O3LWM.js';
|
|
3
|
+
import { GlassCard } from './chunk-YB4B3OMC.js';
|
|
4
|
+
import { ScrollReveal } from './chunk-7CFFAKDM.js';
|
|
5
|
+
import React, { useRef, useEffect } from 'react';
|
|
6
|
+
import gsap from 'gsap';
|
|
7
|
+
import { ScrollTrigger } from 'gsap/ScrollTrigger';
|
|
8
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
9
|
+
|
|
10
|
+
function ConversionFunnelSection({ data }) {
|
|
11
|
+
const funnelRef = useRef(null);
|
|
12
|
+
const flowLinesRef = useRef(null);
|
|
13
|
+
useEffect(() => {
|
|
14
|
+
gsap.registerPlugin(ScrollTrigger);
|
|
15
|
+
const prefersReducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
16
|
+
if (prefersReducedMotion) return;
|
|
17
|
+
const ctx = gsap.context(() => {
|
|
18
|
+
const stages = funnelRef.current?.querySelectorAll(".funnel-stage-fill");
|
|
19
|
+
if (stages && stages.length > 0) {
|
|
20
|
+
gsap.fromTo(
|
|
21
|
+
stages,
|
|
22
|
+
{ scaleX: 0 },
|
|
23
|
+
{
|
|
24
|
+
scaleX: 1,
|
|
25
|
+
duration: 0.8,
|
|
26
|
+
stagger: 0.2,
|
|
27
|
+
ease: "power2.out",
|
|
28
|
+
transformOrigin: "left center",
|
|
29
|
+
scrollTrigger: {
|
|
30
|
+
trigger: funnelRef.current,
|
|
31
|
+
start: "top 70%",
|
|
32
|
+
toggleActions: "play none none none"
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
const flowLines = flowLinesRef.current?.querySelectorAll(".flow-connector");
|
|
38
|
+
if (flowLines && flowLines.length > 0) {
|
|
39
|
+
gsap.fromTo(
|
|
40
|
+
flowLines,
|
|
41
|
+
{ scaleX: 0, opacity: 0 },
|
|
42
|
+
{
|
|
43
|
+
scaleX: 1,
|
|
44
|
+
opacity: 1,
|
|
45
|
+
duration: 0.5,
|
|
46
|
+
stagger: 0.15,
|
|
47
|
+
delay: 0.3,
|
|
48
|
+
ease: "power2.out",
|
|
49
|
+
transformOrigin: "left center",
|
|
50
|
+
scrollTrigger: {
|
|
51
|
+
trigger: funnelRef.current,
|
|
52
|
+
start: "top 70%",
|
|
53
|
+
toggleActions: "play none none none"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
return () => ctx.revert();
|
|
60
|
+
}, [data.stages.length]);
|
|
61
|
+
const maxValue = Math.max(...data.stages.map((s) => s.value), 1);
|
|
62
|
+
return /* @__PURE__ */ jsx(
|
|
63
|
+
"section",
|
|
64
|
+
{
|
|
65
|
+
className: "w-full py-20 md:py-28",
|
|
66
|
+
style: { background: "var(--sk-bg, #0a0a0a)" },
|
|
67
|
+
children: /* @__PURE__ */ jsxs("div", { className: "max-w-6xl mx-auto px-6", children: [
|
|
68
|
+
(data.title || data.description) && /* @__PURE__ */ jsxs(ScrollReveal, { y: 30, children: [
|
|
69
|
+
data.title && /* @__PURE__ */ jsx(
|
|
70
|
+
"h2",
|
|
71
|
+
{
|
|
72
|
+
className: "text-3xl md:text-4xl font-bold mb-4",
|
|
73
|
+
style: {
|
|
74
|
+
color: "var(--sk-text-primary, #ffffff)",
|
|
75
|
+
fontFamily: "var(--sk-font-heading, inherit)"
|
|
76
|
+
},
|
|
77
|
+
children: data.title
|
|
78
|
+
}
|
|
79
|
+
),
|
|
80
|
+
data.description && /* @__PURE__ */ jsx(
|
|
81
|
+
"p",
|
|
82
|
+
{
|
|
83
|
+
className: "text-lg mb-12 max-w-2xl",
|
|
84
|
+
style: { color: "var(--sk-text-secondary, #a1a1aa)" },
|
|
85
|
+
children: data.description
|
|
86
|
+
}
|
|
87
|
+
)
|
|
88
|
+
] }),
|
|
89
|
+
/* @__PURE__ */ jsx("div", { ref: funnelRef, className: "hidden md:block", children: /* @__PURE__ */ jsx("div", { className: "flex items-end gap-0 relative", ref: flowLinesRef, children: data.stages.map((stage, index) => {
|
|
90
|
+
const widthPercent = 60 + stage.value / maxValue * 40;
|
|
91
|
+
const stageColor = stage.color || "var(--sk-primary, #6366f1)";
|
|
92
|
+
const dropOff = index > 0 ? Math.round(
|
|
93
|
+
(data.stages[index - 1].value - stage.value) / data.stages[index - 1].value * 100
|
|
94
|
+
) : null;
|
|
95
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
96
|
+
dropOff !== null && /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center px-2 shrink-0", style: { minWidth: 48 }, children: [
|
|
97
|
+
/* @__PURE__ */ jsx(
|
|
98
|
+
"div",
|
|
99
|
+
{
|
|
100
|
+
className: "flow-connector h-0.5 w-full mb-1",
|
|
101
|
+
style: {
|
|
102
|
+
background: `linear-gradient(to right, ${data.stages[index - 1].color || "var(--sk-primary, #6366f1)"}, ${stageColor})`,
|
|
103
|
+
willChange: "transform"
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
),
|
|
107
|
+
/* @__PURE__ */ jsxs(
|
|
108
|
+
"span",
|
|
109
|
+
{
|
|
110
|
+
className: "text-xs font-medium whitespace-nowrap",
|
|
111
|
+
style: { color: "var(--sk-text-tertiary, #71717a)" },
|
|
112
|
+
children: [
|
|
113
|
+
"-",
|
|
114
|
+
dropOff,
|
|
115
|
+
"%"
|
|
116
|
+
]
|
|
117
|
+
}
|
|
118
|
+
)
|
|
119
|
+
] }),
|
|
120
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1", style: { maxWidth: `${widthPercent}%` }, children: /* @__PURE__ */ jsx(GlassCard, { padding: "md", hover: false, children: /* @__PURE__ */ jsxs("div", { className: "relative overflow-hidden rounded-lg", children: [
|
|
121
|
+
/* @__PURE__ */ jsx(
|
|
122
|
+
"div",
|
|
123
|
+
{
|
|
124
|
+
className: "funnel-stage-fill absolute inset-0 rounded-lg opacity-15",
|
|
125
|
+
style: {
|
|
126
|
+
background: stageColor,
|
|
127
|
+
willChange: "transform"
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
),
|
|
131
|
+
/* @__PURE__ */ jsxs("div", { className: "relative flex flex-col items-center gap-2 py-4", children: [
|
|
132
|
+
stage.icon && /* @__PURE__ */ jsx("img", { src: stage.icon, alt: "", width: 24, height: 24, className: "w-6 h-6 object-contain" }),
|
|
133
|
+
/* @__PURE__ */ jsx(
|
|
134
|
+
"span",
|
|
135
|
+
{
|
|
136
|
+
className: "text-xs font-semibold uppercase tracking-wider text-center",
|
|
137
|
+
style: { color: "var(--sk-text-tertiary, #71717a)" },
|
|
138
|
+
children: stage.label
|
|
139
|
+
}
|
|
140
|
+
),
|
|
141
|
+
/* @__PURE__ */ jsx(
|
|
142
|
+
"div",
|
|
143
|
+
{
|
|
144
|
+
className: "text-2xl font-bold",
|
|
145
|
+
style: { color: stageColor },
|
|
146
|
+
children: /* @__PURE__ */ jsx(AnimatedCounter, { value: stage.value, duration: 2 })
|
|
147
|
+
}
|
|
148
|
+
)
|
|
149
|
+
] })
|
|
150
|
+
] }) }) })
|
|
151
|
+
] }, index);
|
|
152
|
+
}) }) }),
|
|
153
|
+
/* @__PURE__ */ jsx("div", { className: "md:hidden flex flex-col gap-3", children: data.stages.map((stage, index) => {
|
|
154
|
+
const widthPercent = 60 + stage.value / maxValue * 40;
|
|
155
|
+
const stageColor = stage.color || "var(--sk-primary, #6366f1)";
|
|
156
|
+
const dropOff = index > 0 ? Math.round(
|
|
157
|
+
(data.stages[index - 1].value - stage.value) / data.stages[index - 1].value * 100
|
|
158
|
+
) : null;
|
|
159
|
+
return /* @__PURE__ */ jsxs(React.Fragment, { children: [
|
|
160
|
+
dropOff !== null && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center py-1", children: [
|
|
161
|
+
/* @__PURE__ */ jsx("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M10 4v12M6 12l4 4 4-4", stroke: "var(--sk-text-tertiary, #71717a)", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) }),
|
|
162
|
+
/* @__PURE__ */ jsxs(
|
|
163
|
+
"span",
|
|
164
|
+
{
|
|
165
|
+
className: "text-xs font-medium ml-2",
|
|
166
|
+
style: { color: "var(--sk-text-tertiary, #71717a)" },
|
|
167
|
+
children: [
|
|
168
|
+
"-",
|
|
169
|
+
dropOff,
|
|
170
|
+
"% drop-off"
|
|
171
|
+
]
|
|
172
|
+
}
|
|
173
|
+
)
|
|
174
|
+
] }),
|
|
175
|
+
/* @__PURE__ */ jsx(ScrollReveal, { y: 20, delay: index * 0.1, children: /* @__PURE__ */ jsx("div", { style: { width: `${widthPercent}%`, marginLeft: "auto", marginRight: "auto" }, children: /* @__PURE__ */ jsx(GlassCard, { padding: "md", hover: false, children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4", children: [
|
|
176
|
+
stage.icon && /* @__PURE__ */ jsx("img", { src: stage.icon, alt: "", width: 24, height: 24, className: "w-6 h-6 object-contain shrink-0" }),
|
|
177
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1", children: /* @__PURE__ */ jsx(
|
|
178
|
+
"span",
|
|
179
|
+
{
|
|
180
|
+
className: "text-xs font-semibold uppercase tracking-wider",
|
|
181
|
+
style: { color: "var(--sk-text-tertiary, #71717a)" },
|
|
182
|
+
children: stage.label
|
|
183
|
+
}
|
|
184
|
+
) }),
|
|
185
|
+
/* @__PURE__ */ jsx(
|
|
186
|
+
"div",
|
|
187
|
+
{
|
|
188
|
+
className: "text-xl font-bold",
|
|
189
|
+
style: { color: stageColor },
|
|
190
|
+
children: /* @__PURE__ */ jsx(AnimatedCounter, { value: stage.value, duration: 2 })
|
|
191
|
+
}
|
|
192
|
+
)
|
|
193
|
+
] }) }) }) })
|
|
194
|
+
] }, index);
|
|
195
|
+
}) })
|
|
196
|
+
] })
|
|
197
|
+
}
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export { ConversionFunnelSection as default };
|
|
202
|
+
//# sourceMappingURL=ConversionFunnelSection-D3GE4NKE.js.map
|
|
203
|
+
//# sourceMappingURL=ConversionFunnelSection-D3GE4NKE.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/portfolio/components/sections/ConversionFunnelSection.tsx"],"names":[],"mappings":"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","file":"ConversionFunnelSection-D3GE4NKE.js","sourcesContent":["'use client';\n\nimport React, { useRef, useEffect } from 'react';\nimport gsap from 'gsap';\nimport { ScrollTrigger } from 'gsap/ScrollTrigger';\nimport type { PortfolioConversionFunnelData } from '../../../types';\nimport ScrollReveal from '../primitives/ScrollReveal';\nimport AnimatedCounter from '../primitives/AnimatedCounter';\nimport GlassCard from '../primitives/GlassCard';\n\ninterface ConversionFunnelSectionProps {\n data: PortfolioConversionFunnelData;\n}\n\nexport default function ConversionFunnelSection({ data }: ConversionFunnelSectionProps) {\n const funnelRef = useRef<HTMLDivElement>(null);\n const flowLinesRef = useRef<HTMLDivElement>(null);\n\n useEffect(() => {\n gsap.registerPlugin(ScrollTrigger);\n\n const prefersReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;\n if (prefersReducedMotion) return;\n\n const ctx = gsap.context(() => {\n // Fill stages left-to-right with color\n const stages = funnelRef.current?.querySelectorAll('.funnel-stage-fill');\n if (stages && stages.length > 0) {\n gsap.fromTo(\n stages,\n { scaleX: 0 },\n {\n scaleX: 1,\n duration: 0.8,\n stagger: 0.2,\n ease: 'power2.out',\n transformOrigin: 'left center',\n scrollTrigger: {\n trigger: funnelRef.current,\n start: 'top 70%',\n toggleActions: 'play none none none',\n },\n },\n );\n }\n\n // Animate flow line connectors\n const flowLines = flowLinesRef.current?.querySelectorAll('.flow-connector');\n if (flowLines && flowLines.length > 0) {\n gsap.fromTo(\n flowLines,\n { scaleX: 0, opacity: 0 },\n {\n scaleX: 1,\n opacity: 1,\n duration: 0.5,\n stagger: 0.15,\n delay: 0.3,\n ease: 'power2.out',\n transformOrigin: 'left center',\n scrollTrigger: {\n trigger: funnelRef.current,\n start: 'top 70%',\n toggleActions: 'play none none none',\n },\n },\n );\n }\n });\n\n return () => ctx.revert();\n }, [data.stages.length]);\n\n const maxValue = Math.max(...data.stages.map((s) => s.value), 1);\n\n return (\n <section\n className=\"w-full py-20 md:py-28\"\n style={{ background: 'var(--sk-bg, #0a0a0a)' }}\n >\n <div className=\"max-w-6xl mx-auto px-6\">\n {(data.title || data.description) && (\n <ScrollReveal y={30}>\n {data.title && (\n <h2\n className=\"text-3xl md:text-4xl font-bold mb-4\"\n style={{\n color: 'var(--sk-text-primary, #ffffff)',\n fontFamily: 'var(--sk-font-heading, inherit)',\n }}\n >\n {data.title}\n </h2>\n )}\n {data.description && (\n <p\n className=\"text-lg mb-12 max-w-2xl\"\n style={{ color: 'var(--sk-text-secondary, #a1a1aa)' }}\n >\n {data.description}\n </p>\n )}\n </ScrollReveal>\n )}\n\n {/* Desktop: horizontal funnel */}\n <div ref={funnelRef} className=\"hidden md:block\">\n <div className=\"flex items-end gap-0 relative\" ref={flowLinesRef}>\n {data.stages.map((stage, index) => {\n const widthPercent = 60 + (stage.value / maxValue) * 40;\n const stageColor = stage.color || 'var(--sk-primary, #6366f1)';\n const dropOff =\n index > 0\n ? Math.round(\n ((data.stages[index - 1].value - stage.value) /\n data.stages[index - 1].value) *\n 100,\n )\n : null;\n\n return (\n <React.Fragment key={index}>\n {/* Drop-off connector */}\n {dropOff !== null && (\n <div className=\"flex flex-col items-center justify-center px-2 shrink-0\" style={{ minWidth: 48 }}>\n <div\n className=\"flow-connector h-0.5 w-full mb-1\"\n style={{\n background: `linear-gradient(to right, ${data.stages[index - 1].color || 'var(--sk-primary, #6366f1)'}, ${stageColor})`,\n willChange: 'transform',\n }}\n />\n <span\n className=\"text-xs font-medium whitespace-nowrap\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n -{dropOff}%\n </span>\n </div>\n )}\n\n {/* Stage card */}\n <div className=\"flex-1\" style={{ maxWidth: `${widthPercent}%` }}>\n <GlassCard padding=\"md\" hover={false}>\n <div className=\"relative overflow-hidden rounded-lg\">\n {/* Animated fill bar */}\n <div\n className=\"funnel-stage-fill absolute inset-0 rounded-lg opacity-15\"\n style={{\n background: stageColor,\n willChange: 'transform',\n }}\n />\n <div className=\"relative flex flex-col items-center gap-2 py-4\">\n {/* Icon */}\n {stage.icon && (\n <img src={stage.icon} alt=\"\" width={24} height={24} className=\"w-6 h-6 object-contain\" />\n )}\n <span\n className=\"text-xs font-semibold uppercase tracking-wider text-center\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n {stage.label}\n </span>\n <div\n className=\"text-2xl font-bold\"\n style={{ color: stageColor }}\n >\n <AnimatedCounter value={stage.value} duration={2} />\n </div>\n </div>\n </div>\n </GlassCard>\n </div>\n </React.Fragment>\n );\n })}\n </div>\n </div>\n\n {/* Mobile: vertical funnel */}\n <div className=\"md:hidden flex flex-col gap-3\">\n {data.stages.map((stage, index) => {\n const widthPercent = 60 + (stage.value / maxValue) * 40;\n const stageColor = stage.color || 'var(--sk-primary, #6366f1)';\n const dropOff =\n index > 0\n ? Math.round(\n ((data.stages[index - 1].value - stage.value) /\n data.stages[index - 1].value) *\n 100,\n )\n : null;\n\n return (\n <React.Fragment key={index}>\n {dropOff !== null && (\n <div className=\"flex items-center justify-center py-1\">\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\n <path d=\"M10 4v12M6 12l4 4 4-4\" stroke=\"var(--sk-text-tertiary, #71717a)\" strokeWidth=\"1.5\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n <span\n className=\"text-xs font-medium ml-2\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n -{dropOff}% drop-off\n </span>\n </div>\n )}\n <ScrollReveal y={20} delay={index * 0.1}>\n <div style={{ width: `${widthPercent}%`, marginLeft: 'auto', marginRight: 'auto' }}>\n <GlassCard padding=\"md\" hover={false}>\n <div className=\"flex items-center gap-4\">\n {stage.icon && (\n <img src={stage.icon} alt=\"\" width={24} height={24} className=\"w-6 h-6 object-contain shrink-0\" />\n )}\n <div className=\"flex-1\">\n <span\n className=\"text-xs font-semibold uppercase tracking-wider\"\n style={{ color: 'var(--sk-text-tertiary, #71717a)' }}\n >\n {stage.label}\n </span>\n </div>\n <div\n className=\"text-xl font-bold\"\n style={{ color: stageColor }}\n >\n <AnimatedCounter value={stage.value} duration={2} />\n </div>\n </div>\n </GlassCard>\n </div>\n </ScrollReveal>\n </React.Fragment>\n );\n })}\n </div>\n </div>\n </section>\n );\n}\n"]}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import { GlassCard } from './chunk-YB4B3OMC.js';
|
|
2
|
+
import { ScrollReveal } from './chunk-7CFFAKDM.js';
|
|
3
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
function DetailsSection({ data }) {
|
|
6
|
+
const rows = [];
|
|
7
|
+
if (data.industry) {
|
|
8
|
+
rows.push({
|
|
9
|
+
label: "Industry",
|
|
10
|
+
value: data.industry,
|
|
11
|
+
icon: /* @__PURE__ */ jsx("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M3 16.5h12M4.5 1.5h9l1.5 6H3l1.5-6zM6 7.5v9M12 7.5v9M9 7.5v9", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
if (data.location) {
|
|
15
|
+
rows.push({
|
|
16
|
+
label: "Location",
|
|
17
|
+
value: data.location,
|
|
18
|
+
icon: /* @__PURE__ */ jsxs("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", children: [
|
|
19
|
+
/* @__PURE__ */ jsx("path", { d: "M15 7.5c0 4.5-6 9-6 9s-6-4.5-6-9a6 6 0 1112 0z", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
20
|
+
/* @__PURE__ */ jsx("circle", { cx: "9", cy: "7.5", r: "2", stroke: "currentColor", strokeWidth: "1.5" })
|
|
21
|
+
] })
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
if (data.website) {
|
|
25
|
+
rows.push({
|
|
26
|
+
label: "Website",
|
|
27
|
+
value: data.website,
|
|
28
|
+
icon: /* @__PURE__ */ jsxs("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", children: [
|
|
29
|
+
/* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "7.5", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
30
|
+
/* @__PURE__ */ jsx("path", { d: "M1.5 9h15M9 1.5a11.25 11.25 0 013 7.5 11.25 11.25 0 01-3 7.5 11.25 11.25 0 01-3-7.5 11.25 11.25 0 013-7.5z", stroke: "currentColor", strokeWidth: "1.5" })
|
|
31
|
+
] })
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
if (data.timeline) {
|
|
35
|
+
rows.push({
|
|
36
|
+
label: "Timeline",
|
|
37
|
+
value: data.timeline,
|
|
38
|
+
icon: /* @__PURE__ */ jsxs("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", children: [
|
|
39
|
+
/* @__PURE__ */ jsx("circle", { cx: "9", cy: "9", r: "7.5", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
40
|
+
/* @__PURE__ */ jsx("path", { d: "M9 4.5V9l3 1.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
41
|
+
] })
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
if (data.launchDate) {
|
|
45
|
+
rows.push({
|
|
46
|
+
label: "Launch Date",
|
|
47
|
+
value: data.launchDate,
|
|
48
|
+
icon: /* @__PURE__ */ jsxs("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", children: [
|
|
49
|
+
/* @__PURE__ */ jsx("rect", { x: "2.25", y: "3", width: "13.5", height: "12.75", rx: "2", stroke: "currentColor", strokeWidth: "1.5" }),
|
|
50
|
+
/* @__PURE__ */ jsx("path", { d: "M12 1.5v3M6 1.5v3M2.25 7.5h13.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" })
|
|
51
|
+
] })
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
if (data.budgetRange) {
|
|
55
|
+
rows.push({
|
|
56
|
+
label: "Budget Range",
|
|
57
|
+
value: data.budgetRange,
|
|
58
|
+
icon: /* @__PURE__ */ jsx("svg", { width: "18", height: "18", viewBox: "0 0 18 18", fill: "none", children: /* @__PURE__ */ jsx("path", { d: "M9 1.5v15M13.5 4.5H6.75a2.625 2.625 0 000 5.25h4.5a2.625 2.625 0 010 5.25H4.5", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
if (rows.length === 0) return null;
|
|
62
|
+
return /* @__PURE__ */ jsx(
|
|
63
|
+
"section",
|
|
64
|
+
{
|
|
65
|
+
className: "w-full py-20 md:py-28",
|
|
66
|
+
style: { background: "var(--sk-bg, #0a0a0a)" },
|
|
67
|
+
children: /* @__PURE__ */ jsxs("div", { className: "max-w-4xl mx-auto px-6", children: [
|
|
68
|
+
/* @__PURE__ */ jsx(ScrollReveal, { y: 30, children: /* @__PURE__ */ jsx(
|
|
69
|
+
"h2",
|
|
70
|
+
{
|
|
71
|
+
className: "text-3xl md:text-4xl font-bold mb-8",
|
|
72
|
+
style: {
|
|
73
|
+
color: "var(--sk-text-primary, #ffffff)",
|
|
74
|
+
fontFamily: "var(--sk-font-heading, inherit)"
|
|
75
|
+
},
|
|
76
|
+
children: "Project Details"
|
|
77
|
+
}
|
|
78
|
+
) }),
|
|
79
|
+
/* @__PURE__ */ jsx(ScrollReveal, { y: 40, delay: 0.1, children: /* @__PURE__ */ jsx(GlassCard, { padding: "lg", hover: false, children: /* @__PURE__ */ jsx("div", { className: "flex flex-col divide-y", style: { borderColor: "var(--sk-border, rgba(255,255,255,0.1))" }, children: rows.map((row, index) => /* @__PURE__ */ jsxs(
|
|
80
|
+
"div",
|
|
81
|
+
{
|
|
82
|
+
className: "flex items-center gap-4 py-4 first:pt-0 last:pb-0",
|
|
83
|
+
style: {
|
|
84
|
+
borderColor: "var(--sk-border, rgba(255,255,255,0.1))"
|
|
85
|
+
},
|
|
86
|
+
children: [
|
|
87
|
+
/* @__PURE__ */ jsx(
|
|
88
|
+
"span",
|
|
89
|
+
{
|
|
90
|
+
className: "flex items-center justify-center w-9 h-9 rounded-lg shrink-0",
|
|
91
|
+
style: {
|
|
92
|
+
background: "color-mix(in srgb, var(--sk-primary, #6366f1) 12%, transparent)",
|
|
93
|
+
color: "var(--sk-primary, #6366f1)"
|
|
94
|
+
},
|
|
95
|
+
children: row.icon
|
|
96
|
+
}
|
|
97
|
+
),
|
|
98
|
+
/* @__PURE__ */ jsx(
|
|
99
|
+
"span",
|
|
100
|
+
{
|
|
101
|
+
className: "text-sm font-medium w-32 shrink-0",
|
|
102
|
+
style: { color: "var(--sk-text-tertiary, #71717a)" },
|
|
103
|
+
children: row.label
|
|
104
|
+
}
|
|
105
|
+
),
|
|
106
|
+
row.label === "Website" ? /* @__PURE__ */ jsx(
|
|
107
|
+
"a",
|
|
108
|
+
{
|
|
109
|
+
href: row.value.startsWith("http") ? row.value : `https://${row.value}`,
|
|
110
|
+
target: "_blank",
|
|
111
|
+
rel: "noopener noreferrer",
|
|
112
|
+
className: "text-sm font-medium hover:underline",
|
|
113
|
+
style: { color: "var(--sk-primary, #6366f1)" },
|
|
114
|
+
children: row.value
|
|
115
|
+
}
|
|
116
|
+
) : /* @__PURE__ */ jsx(
|
|
117
|
+
"span",
|
|
118
|
+
{
|
|
119
|
+
className: "text-sm font-medium",
|
|
120
|
+
style: { color: "var(--sk-text-primary, #ffffff)" },
|
|
121
|
+
children: row.value
|
|
122
|
+
}
|
|
123
|
+
)
|
|
124
|
+
]
|
|
125
|
+
},
|
|
126
|
+
index
|
|
127
|
+
)) }) }) })
|
|
128
|
+
] })
|
|
129
|
+
}
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export { DetailsSection as default };
|
|
134
|
+
//# sourceMappingURL=DetailsSection-FB763FS7.js.map
|
|
135
|
+
//# sourceMappingURL=DetailsSection-FB763FS7.js.map
|