diff --git a/src/app/about/page.tsx b/src/app/about/page.tsx new file mode 100644 index 0000000..f2f40cd --- /dev/null +++ b/src/app/about/page.tsx @@ -0,0 +1,164 @@ +"use client"; + +import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider"; +import NavbarLayoutFloatingOverlay from '@/components/navbar/NavbarLayoutFloatingOverlay/NavbarLayoutFloatingOverlay'; +import MetricSplitMediaAbout from '@/components/sections/about/MetricSplitMediaAbout'; +import FeatureHoverPattern from '@/components/sections/feature/featureHoverPattern/FeatureHoverPattern'; +import TeamCardFive from '@/components/sections/team/TeamCardFive'; +import ContactCTA from '@/components/sections/contact/ContactCTA'; +import FooterBaseReveal from '@/components/sections/footer/FooterBaseReveal'; +import { Sparkles, Users, Heart, Award } from "lucide-react"; + +export default function AboutPage() { + return ( + + + +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ + +
+ ); +} diff --git a/src/app/blog/page.tsx b/src/app/blog/page.tsx index 75a964c..f0737ab 100644 --- a/src/app/blog/page.tsx +++ b/src/app/blog/page.tsx @@ -28,11 +28,12 @@ export default function BlogPage() { ); -} \ No newline at end of file +} diff --git a/src/app/layout.tsx b/src/app/layout.tsx index 730aa76..70e14b5 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -77,7 +77,9 @@ export default function RootLayout({ ' background-color: #4d96ff05 !important;' + '}' + 'img.webild-hover,' + - 'img.webild-selected {' + + 'img.webild-selected,' + + 'video.webild-hover,' + + 'video.webild-selected {' + ' outline-offset: 2px !important;' + '}' + '.webild-element-type-label {' + @@ -149,6 +151,10 @@ export default function RootLayout({ return 'Image'; } + if (tagName === 'video') { + return 'Video'; + } + const backgroundImage = computedStyle.backgroundImage; if (backgroundImage && backgroundImage !== 'none') { const urlMatch = backgroundImage.match(/url(['"]?([^'")]+)['"]?)/); @@ -231,6 +237,38 @@ export default function RootLayout({ return url; }; + const getMediaTypeFromUrl = (url) => { + const videoExts = ['.mp4', '.webm', '.ogg', '.mov', '.avi', '.mkv', '.m4v', '.wmv']; + const imageExts = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg', '.bmp', '.ico', '.tiff', '.avif']; + try { + const pathname = new URL(url).pathname.toLowerCase(); + if (videoExts.some(function(ext) { return pathname.endsWith(ext); })) return 'video'; + if (imageExts.some(function(ext) { return pathname.endsWith(ext); })) return 'image'; + } catch(e) {} + return 'unknown'; + }; + + const swapMediaElement = (oldEl, newTag, newSrc) => { + const newEl = document.createElement(newTag); + Array.from(oldEl.attributes).forEach(function(attr) { + if (attr.name !== 'src' && attr.name !== 'alt' && attr.name !== 'srcset' && attr.name !== 'autoplay' && attr.name !== 'loop' && attr.name !== 'muted' && attr.name !== 'playsinline') { + try { newEl.setAttribute(attr.name, attr.value); } catch(e) {} + } + }); + newEl.style.cssText = oldEl.style.cssText; + if (newTag === 'video') { + newEl.setAttribute('autoplay', ''); + newEl.setAttribute('loop', ''); + newEl.setAttribute('muted', ''); + newEl.setAttribute('playsinline', ''); + } + newEl.src = newSrc; + if (oldEl.parentNode) { + oldEl.parentNode.replaceChild(newEl, oldEl); + } + return newEl; + }; + const getElementInfo = (element, assignId = false) => { const rect = element.getBoundingClientRect(); const tagName = element.tagName.toLowerCase(); @@ -273,7 +311,18 @@ export default function RootLayout({ isBackground: false }; } - + + if (tagName === 'video') { + const rawSrc = element.src || element.currentSrc || (element.querySelector('source') && element.querySelector('source').src) || ''; + const resolvedSrc = extractOriginalUrl(rawSrc); + info.imageData = { + src: resolvedSrc, + alt: element.getAttribute('aria-label') || undefined, + isBackground: false, + isVideo: true + }; + } + const computedStyle = window.getComputedStyle(element); const backgroundImage = computedStyle.backgroundImage; if (backgroundImage && backgroundImage !== 'none') { @@ -321,7 +370,8 @@ export default function RootLayout({ const tagName = element.tagName?.toLowerCase(); if (invalidElements.includes(tagName)) return false; const isImage = tagName === 'img'; - if (isImage) return true; + const isVideo = tagName === 'video'; + if (isImage || isVideo) return true; const hasInnerHTML = element.innerHTML && element.innerHTML.trim().length > 0; const hasTextContent = element.textContent && element.textContent.trim().length > 0; const hasChildren = element.children && element.children.length > 0; @@ -361,7 +411,7 @@ export default function RootLayout({ node.nodeType === Node.TEXT_NODE && node.textContent && node.textContent.trim().length > 0 ); - const hasImages = element.tagName === 'IMG' || computedStyle.backgroundImage !== 'none' || element.querySelector('img'); + const hasImages = element.tagName === 'IMG' || element.tagName === 'VIDEO' || computedStyle.backgroundImage !== 'none' || element.querySelector('img') || element.querySelector('video'); const isInteractive = ['BUTTON', 'A', 'INPUT', 'SELECT', 'TEXTAREA'].includes(element.tagName); const hasFewChildren = element.children.length <= 3; const area = rect.width * rect.height; @@ -1042,11 +1092,22 @@ export default function RootLayout({ updateButtonText(element, change.oldValue); } } else if (change.type === 'replaceImage') { - const isBackground = element.tagName.toLowerCase() !== 'img'; + const revertTag = element.tagName.toLowerCase(); + const isBackground = revertTag !== 'img' && revertTag !== 'video'; if (isBackground) { element.style.backgroundImage = change.oldValue ? 'url(' + change.oldValue + ')' : ''; } else { - element.src = change.oldValue; + const oldMediaType = getMediaTypeFromUrl(change.oldValue); + if (revertTag === 'video' && oldMediaType === 'image') { + swapMediaElement(element, 'img', change.oldValue); + } else if (revertTag === 'img' && oldMediaType === 'video') { + swapMediaElement(element, 'video', change.oldValue); + } else if (revertTag === 'video') { + element.src = change.oldValue; + element.load(); + } else { + element.src = change.oldValue; + } } } } catch (err) { @@ -1146,7 +1207,7 @@ export default function RootLayout({ if (!isActive) return; if (e.data.type === 'webild-replace-image') { - const { selector, newSrc, isBackground } = e.data.data; + const { selector, newSrc, isBackground, allowMediaTypeSwap } = e.data.data; let element = null; try { @@ -1177,7 +1238,32 @@ export default function RootLayout({ replaced = true; } else if (element.tagName.toLowerCase() === 'img') { oldValue = element.src; - element.src = newSrc; + const newMediaType = getMediaTypeFromUrl(newSrc); + if (newMediaType === 'video' && allowMediaTypeSwap) { + const swapped = swapMediaElement(element, 'video', newSrc); + if (selectedElement === element) selectedElement = swapped; + element = swapped; + } else { + element.src = newSrc; + } + replaced = true; + } else if (element.tagName.toLowerCase() === 'video') { + oldValue = element.src || element.currentSrc || ''; + const newMediaType = getMediaTypeFromUrl(newSrc); + const sources = element.querySelectorAll('source'); + if (newMediaType === 'image' && allowMediaTypeSwap) { + const swapped = swapMediaElement(element, 'img', newSrc); + if (selectedElement === element) selectedElement = swapped; + element = swapped; + } else { + if (sources.length > 0) { + sources.forEach(function(source) { source.src = newSrc; }); + element.load(); + } else { + element.src = newSrc; + element.load(); + } + } replaced = true; } else { const hasBackgroundImage = window.getComputedStyle(element).backgroundImage !== 'none'; @@ -1315,4 +1401,4 @@ export default function RootLayout({ ); -} \ No newline at end of file +} diff --git a/src/app/page.tsx b/src/app/page.tsx index 25cfed1..78ada65 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -1,4 +1,4 @@ -"use client" +"use client"; import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider"; import NavbarLayoutFloatingOverlay from '@/components/navbar/NavbarLayoutFloatingOverlay/NavbarLayoutFloatingOverlay'; @@ -32,6 +32,7 @@ export default function LandingPage() { { name: "Menu", id: "menu" }, { name: "Banquets", id: "banquets" }, { name: "Delivery", id: "delivery" }, + { name: "About Us", id: "/about" }, { name: "Contacts", id: "contact" } ]} button={{ text: "Reserve Table", href: "#contact" }} @@ -225,7 +226,8 @@ export default function LandingPage() { { label: "Philosophy", href: "#about" }, { label: "Menu", href: "#menu" }, { label: "Banquets", href: "#banquets" }, - { label: "Delivery", href: "#delivery" } + { label: "Delivery", href: "#delivery" }, + { label: "About Us", href: "/about" } ] }, { @@ -250,4 +252,4 @@ export default function LandingPage() { ); -} \ No newline at end of file +} diff --git a/src/app/shop/[id]/page.tsx b/src/app/shop/[id]/page.tsx index 30dd619..ae42cee 100644 --- a/src/app/shop/[id]/page.tsx +++ b/src/app/shop/[id]/page.tsx @@ -85,11 +85,12 @@ export default function ProductPage({ params }: ProductPageProps) { setCartOpen(true) }} buttonClassName="rounded-full px-6 py-2" @@ -102,7 +103,7 @@ export default function ProductPage({ params }: ProductPageProps) {