diff --git a/package-lock.json b/package-lock.json index e01389f5..a3ddc583 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2863,16 +2863,6 @@ } } }, - "node_modules/@thednp/bezier-easing": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@thednp/bezier-easing/-/bezier-easing-1.0.7.tgz", - "integrity": "sha512-A/M4ijFjRu8bTSbCqhQs7xsFA20hbtlEenER7rK3j8OgS7jk9MdN51P4uhCHXUDoTTWjCH49/6wvP4CaRKyKHQ==" - }, - "node_modules/@thednp/shorty": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@thednp/shorty/-/shorty-1.0.3.tgz", - "integrity": "sha512-PPaERUGmRpi2eWxYUV5yv/pvalPgPOjwKRmRqGMWGuV8xgkvxgtjKIiFJA2D2ei4l4Ih9mEBktDg6Z9+y+To9Q==" - }, "node_modules/@theguild/remark-mermaid": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/@theguild/remark-mermaid/-/remark-mermaid-0.0.5.tgz", @@ -5577,12 +5567,6 @@ "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==", "dev": true }, - "node_modules/dommatrix": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dommatrix/-/dommatrix-1.0.3.tgz", - "integrity": "sha512-l32Xp/TLgWb8ReqbVJAFIvXmY7go4nTxxlWiAFyhoQw9RKEOHBZNnyGvJWqDVSPmq3Y9HlM4npqF/T6VMOXhww==", - "deprecated": "dommatrix is no longer maintained. Please use @thednp/dommatrix." - }, "node_modules/dompurify": { "version": "3.1.6", "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.6.tgz", @@ -8856,17 +8840,6 @@ "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", "dev": true }, - "node_modules/kute.js": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/kute.js/-/kute.js-2.2.4.tgz", - "integrity": "sha512-M63qfJplLT/1+qeRdFtHimC0D4fqUyRqHJcsnWWTY9s+isB6TsNNx/oSR2XzMm4CsY9Rvqurd+xUYSyJggmhbQ==", - "dependencies": { - "@thednp/bezier-easing": "^1.0.1", - "@thednp/shorty": "^1.0.3", - "minifill": "^0.0.17", - "svg-path-commander": "1.0.5" - } - }, "node_modules/language-subtag-registry": { "version": "0.3.23", "resolved": "https://registry.npmjs.org/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz", @@ -10161,11 +10134,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/minifill": { - "version": "0.0.17", - "resolved": "https://registry.npmjs.org/minifill/-/minifill-0.0.17.tgz", - "integrity": "sha512-tV56LFXsi8vjH4tUExtlu8aPKKQw/U/mn4OIrDU9x30H+9sP8/dWFbXzkAPmcH6o+9fho98kyafnk4VgQViYQQ==" - }, "node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -13012,14 +12980,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/svg-path-commander": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/svg-path-commander/-/svg-path-commander-1.0.5.tgz", - "integrity": "sha512-hhQfARVXoPrwwe4DNPWM4hjQLK7rTxwQ+TUc5mxoe5g0k5eStc4SPnKqmivlm/dzZ98bI+yDyKye92n2t+oOiQ==", - "dependencies": { - "dommatrix": "^1.0.3" - } - }, "node_modules/tailwind-merge": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-2.5.2.tgz", @@ -15691,7 +15651,6 @@ "clsx": "^2.1.1", "framer-motion": "^11.11.1", "hamburger-react": "^2.5.0", - "kute.js": "^2.2.4", "lucide-react": "^0.446.0", "moment": "^2.30.1", "next": "14.2.5", diff --git a/website/app/globals.css b/website/app/globals.css index bf6a977e..781bbe96 100644 --- a/website/app/globals.css +++ b/website/app/globals.css @@ -31,7 +31,7 @@ body { } .react-grid-sample2 { - background: linear-gradient(to bottom, #ffffff 80%, transparent 80%), url(../public/static/bg-texture-2.png); + background: linear-gradient(to bottom, #ffffff 80%, transparent 80%), url(../public/static/noise-texture-2.webp); } /* override daisyui theme */ @@ -67,11 +67,11 @@ body { } .texture-bg { - background-image: url(../public/static/bg-texture.png); + background-image: url(../public/static/noise-texture-1.webp); } .texture-bg-2 { - background-image: url(../public/static/bg-texture-2.png); + background-image: url(../public/static/noise-texture-2.webp); } .LiveCode input[type="date"]::-webkit-calendar-picker-indicator { diff --git a/website/app/support/page.tsx b/website/app/support/page.tsx index caa7ffe8..458a1102 100644 --- a/website/app/support/page.tsx +++ b/website/app/support/page.tsx @@ -9,12 +9,12 @@ export default function FeaturesPage() {
<> @@ -32,7 +32,7 @@ export default function FeaturesPage() {
-
+

Got questions?

@@ -47,7 +47,7 @@ export default function FeaturesPage() { page

-
+

Need talented developers? @@ -57,7 +57,7 @@ export default function FeaturesPage() { your product.

-
+

Technical issues?

diff --git a/website/components/bg-shapes.tsx b/website/components/bg-shapes.tsx index 23a51d50..587ad009 100644 --- a/website/components/bg-shapes.tsx +++ b/website/components/bg-shapes.tsx @@ -1,18 +1,36 @@ "use client"; +import { easeInOut, interpolatePaths } from "@/lib/path-interpolation"; import { useEffect } from "react"; -import KUTE from "kute.js"; const Shape1 = () => { useEffect(() => { - const tween1 = KUTE.fromTo( - "#s1-blob1", - { path: "#s1-blob1" }, - { path: "#s1-blob2" }, - { duration: 3500, yoyo: true, repeat: 100 } - ); - - tween1.start(); + const blob1 = document.getElementById("s1-blob1"); + const path1 = blob1?.getAttribute("d"); + const path2 = document.getElementById("s1-blob2")?.getAttribute("d"); + + let startTime: number; + const duration = 11000; + + const animateBlob = (timestamp: number) => { + if (!startTime) startTime = timestamp; + const elapsed = timestamp - startTime; + const progress = (elapsed % duration) / duration; // Normalized progress (0 to 1) + const easedProgress = easeInOut(progress); + + if (!blob1 || !path1 || !path2) return; + + const currentPath = interpolatePaths( + path1, + path2, + Math.abs(Math.sin(easedProgress * Math.PI)) + ); + blob1?.setAttribute("d", currentPath); + + requestAnimationFrame(animateBlob); + }; + + requestAnimationFrame(animateBlob); }, []); return ( @@ -45,14 +63,32 @@ const Shape1 = () => { const Shape2 = () => { useEffect(() => { - const tween1 = KUTE.fromTo( - "#s2-blob1", - { path: "#s2-blob1" }, - { path: "#s2-blob2" }, - { duration: 3500, yoyo: true, repeat: 100 } - ); - - tween1.start(); + const blob1 = document.getElementById("s2-blob1"); + const path1 = blob1?.getAttribute("d"); + const path2 = document.getElementById("s2-blob2")?.getAttribute("d"); + + let startTime: number; + const duration = 11000; + + const animateBlob = (timestamp: number) => { + if (!startTime) startTime = timestamp; + const elapsed = timestamp - startTime; + const progress = (elapsed % duration) / duration; // Normalized progress (0 to 1) + const easedProgress = easeInOut(progress); + + if (!blob1 || !path1 || !path2) return; + + const currentPath = interpolatePaths( + path1, + path2, + Math.abs(Math.sin(easedProgress * Math.PI)) + ); + blob1?.setAttribute("d", currentPath); + + requestAnimationFrame(animateBlob); + }; + + requestAnimationFrame(animateBlob); }, []); return ( diff --git a/website/components/footer.tsx b/website/components/footer.tsx index 12a4b1e9..f177e945 100644 --- a/website/components/footer.tsx +++ b/website/components/footer.tsx @@ -67,7 +67,7 @@ export const Footer = () => {

-
+
© Silevis Software Sp. z o.o. 2019-{new Date().getFullYear()}
diff --git a/website/components/google-analytics.tsx b/website/components/google-analytics.tsx index 4116e7c2..7556b32e 100644 --- a/website/components/google-analytics.tsx +++ b/website/components/google-analytics.tsx @@ -5,7 +5,7 @@ import Script from "next/script"; export default function GoogleAnalytics() { return ( <> - {/* ); } diff --git a/website/lib/path-interpolation.ts b/website/lib/path-interpolation.ts new file mode 100644 index 00000000..d7904204 --- /dev/null +++ b/website/lib/path-interpolation.ts @@ -0,0 +1,29 @@ +// Ease-in-out function +const easeInOut = (t: number) => { + return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t; +}; + +// Utility function to interpolate between two paths +const interpolatePaths = (path1: string, path2: string, t: number): string => { + const interpolateNumbers = (n1: number, n2: number, t: number) => + n1 + (n2 - n1) * t; + + const path1Data = path1.match(/[-+]?[0-9]*\.?[0-9]+/g)?.map(Number) || []; + const path2Data = path2.match(/[-+]?[0-9]*\.?[0-9]+/g)?.map(Number) || []; + + if (path1Data.length !== path2Data.length) { + console.warn( + "Paths must have the same number of points for smooth interpolation." + ); + return path1; // fallback to avoid error + } + + const interpolatedData = path1Data.map((point, index) => + interpolateNumbers(point, path2Data[index], t) + ); + return path1.replace(/[-+]?[0-9]*\.?[0-9]+/g, () => + interpolatedData.shift()!.toString() + ); +}; + +export { easeInOut, interpolatePaths }; diff --git a/website/package.json b/website/package.json index fb7b9b17..789a2359 100644 --- a/website/package.json +++ b/website/package.json @@ -18,7 +18,6 @@ "clsx": "^2.1.1", "framer-motion": "^11.11.1", "hamburger-react": "^2.5.0", - "kute.js": "^2.2.4", "lucide-react": "^0.446.0", "moment": "^2.30.1", "next": "14.2.5", diff --git a/website/public/static/bg-texture-2.png b/website/public/static/bg-texture-2.png deleted file mode 100644 index 49a1800c..00000000 Binary files a/website/public/static/bg-texture-2.png and /dev/null differ diff --git a/website/public/static/bg-texture.png b/website/public/static/bg-texture.png deleted file mode 100644 index 9a1d03f4..00000000 Binary files a/website/public/static/bg-texture.png and /dev/null differ diff --git a/website/public/static/noise-texture-1.webp b/website/public/static/noise-texture-1.webp new file mode 100644 index 00000000..c7fa9807 Binary files /dev/null and b/website/public/static/noise-texture-1.webp differ diff --git a/website/public/static/noise-texture-2.webp b/website/public/static/noise-texture-2.webp new file mode 100644 index 00000000..4de3fc63 Binary files /dev/null and b/website/public/static/noise-texture-2.webp differ