diff --git a/src/app/layout.tsx b/src/app/layout.tsx index abb50de..3ad8d45 100644 --- a/src/app/layout.tsx +++ b/src/app/layout.tsx @@ -6,26 +6,43 @@ import { ServiceWrapper } from "@/components/ServiceWrapper"; import Tag from "@/tag/Tag"; const publicSans = Public_Sans({ - variable: "--font-public-sans", subsets: ["latin"], + variable: "--font-public-sans", + subsets: ["latin"], }); const inter = Inter({ - variable: "--font-inter", subsets: ["latin"], + variable: "--font-inter", + subsets: ["latin"], }); export const metadata: Metadata = { - title: "SE7EN7 Production | Faster Video & Motion Design", description: "Combine AI technology with creative expertise to produce stunning videos, commercials, and motion graphics in days, not weeks. Faster timelines. Lower costs. Higher quality.", keywords: "AI video production, motion graphics, commercial production, AI creative, faster content creation", metadataBase: new URL("https://aicreativity.studio"), + title: "SE7EN7 Production | Faster Video & Motion Design", + description: "Combine AI technology with creative expertise to produce stunning videos, commercials, and motion graphics in days, not weeks. Faster timelines. Lower costs. Higher quality.", + keywords: "AI video production, motion graphics, commercial production, AI creative, faster content creation", + metadataBase: new URL("https://aicreativity.studio"), alternates: { - canonical: "https://aicreativity.studio"}, + canonical: "https://aicreativity.studio", + }, openGraph: { - title: "SE7EN7 Production | High-Impact Creative at Speed", description: "AI-accelerated creative production combines artificial intelligence with human creative direction.", url: "https://aicreativity.studio", siteName: "SE7EN7", type: "website", images: [ + title: "SE7EN7 Production | High-Impact Creative at Speed", + description: "AI-accelerated creative production combines artificial intelligence with human creative direction.", + url: "https://aicreativity.studio", + siteName: "SE7EN7", + type: "website", + images: [ { - url: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AUMcZjgypY9viEkugChOKNPLY6/a-fast-moving-montage-of-ai-generated-vi-1772642860605-c126ad0d.png", alt: "SE7EN7 Production Hero"}, + url: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AUMcZjgypY9viEkugChOKNPLY6/a-fast-moving-montage-of-ai-generated-vi-1772642860605-c126ad0d.png", + alt: "SE7EN7 Production Hero", + }, ], }, twitter: { - card: "summary_large_image", title: "SE7EN7 Production | Faster Videos & Motion Design", description: "AI-powered creative that's faster, smarter, and more cost-effective than traditional production.", images: [ - "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AUMcZjgypY9viEkugChOKNPLY6/a-fast-moving-montage-of-ai-generated-vi-1772642860605-c126ad0d.png"], + card: "summary_large_image", + title: "SE7EN7 Production | Faster Videos & Motion Design", + description: "AI-powered creative that's faster, smarter, and more cost-effective than traditional production.", + images: [ + "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AUMcZjgypY9viEkugChOKNPLY6/a-fast-moving-montage-of-ai-generated-vi-1772642860605-c126ad0d.png", + ], }, robots: { index: true, @@ -173,7 +190,7 @@ export default function RootLayout({ const backgroundImage = computedStyle.backgroundImage; if (backgroundImage && backgroundImage !== 'none') { - const urlMatch = backgroundImage.match(/url(['"']?([^'")]+)['"']?)/i); + const urlMatch = backgroundImage.match(/url(['"]?([^'")]+)['"]?)/); if (urlMatch && urlMatch[1] && !urlMatch[1].includes('gradient')) { const area = element.offsetWidth * element.offsetHeight; const hasReasonableSize = area > 1000; @@ -191,7 +208,7 @@ export default function RootLayout({ const buttonClasses = ['btn', 'button', 'cta', 'action-button']; const hasButtonClass = buttonClasses.some(cls => - element.classList.contains(cls) || element.classList.contains('btn-' + cls) + element.classList.contains(cls) || element.classList.contains(\`btn-\${cls}\`) ); if (hasButtonClass && element.textContent && element.textContent.trim().length > 0) { @@ -342,7 +359,7 @@ export default function RootLayout({ const computedStyle = window.getComputedStyle(element); const backgroundImage = computedStyle.backgroundImage; if (backgroundImage && backgroundImage !== 'none') { - const urlMatch = backgroundImage.match(/url(['"']?([^'")]+)['"']?)/i); + const urlMatch = backgroundImage.match(/url(['"]?([^'")]+)['"]?)/); if (urlMatch) { const originalBgSrc = extractOriginalUrl(urlMatch[1]); if (tagName !== 'img') { @@ -513,12 +530,15 @@ export default function RootLayout({ }, '*'); const handleBeforeInput = (e) => { + // Prevent deletion if it would leave the element empty const currentText = element.textContent || ''; const inputType = e.inputType; + // Check if this is a delete operation that would leave the element empty if ((inputType === 'deleteContentBackward' || inputType === 'deleteContentForward' || inputType === 'deleteByCut') && currentText.length <= 1) { e.preventDefault(); element.textContent = ' '; + // Move cursor to the beginning const range = document.createRange(); const sel = window.getSelection(); range.setStart(element.firstChild || element, 0); @@ -532,9 +552,11 @@ export default function RootLayout({ const elementInfo = getElementInfo(element); let currentText = element.textContent; + // Ensure there's always at least a space to keep the element editable if (currentText === '' || currentText === null || currentText.length === 0) { element.textContent = ' '; currentText = ' '; + // Move cursor to the beginning try { const range = document.createRange(); const sel = window.getSelection(); @@ -543,6 +565,7 @@ export default function RootLayout({ sel.removeAllRanges(); sel.addRange(range); } catch (e) { + // Ignore cursor positioning errors } } @@ -643,8 +666,10 @@ export default function RootLayout({ const elementInfo = getElementInfo(element); let finalText = element.textContent; + // Trim the final text and convert space-only to empty string for saving if (finalText === ' ' || finalText.trim() === '') { finalText = ''; + // Update the actual element text to empty for display element.textContent = ''; } @@ -675,7 +700,17 @@ export default function RootLayout({ const rect = element.getBoundingClientRect(); const overlay = document.createElement('div'); overlay.className = 'webild-hover-overlay'; - overlay.style.cssText = 'position: fixed !important;top: ' + (rect.top - 2) + 'px !important;left: ' + (rect.left - 2) + 'px !important;width: ' + (rect.width + 4) + 'px !important;height: ' + (rect.height + 4) + 'px !important;background-color: rgba(90, 113, 230, 0.15) !important;pointer-events: none !important;z-index: 999998 !important;transition: all 0.15s ease !important;'; + overlay.style.cssText = \` + position: fixed !important; + top: \${rect.top - 2}px !important; + left: \${rect.left - 2}px !important; + width: \${rect.width + 4}px !important; + height: \${rect.height + 4}px !important; + background-color: rgba(90, 113, 230, 0.15) !important; + pointer-events: none !important; + z-index: 999998 !important; + transition: all 0.15s ease !important; + \`; document.body.appendChild(overlay); return overlay; }; @@ -738,7 +773,11 @@ export default function RootLayout({ elementTypeLabel.classList.add('label-bottom'); } - elementTypeLabel.style.cssText = 'left: ' + labelLeft + 'px !important;top: ' + labelTop + 'px !important;transform: none !important;'; + elementTypeLabel.style.cssText = \` + left: \${labelLeft}px !important; + top: \${labelTop}px !important; + transform: none !important; + \`; }; const removeElementTypeLabel = () => { @@ -992,7 +1031,7 @@ export default function RootLayout({ const getStorageKey = () => { const url = new URL(window.location.href); const pathParts = url.pathname.split('/').filter(Boolean); - return 'webild-changes-' + pathParts.join('-'); + return \`webild-changes-\${pathParts.join('-')}\`; }; const saveChangeToStorage = (change) => { @@ -1206,10 +1245,10 @@ export default function RootLayout({ try { element = document.querySelector(selector); - } catch (err) { + } catch { window.parent.postMessage({ type: 'webild-image-replacement-error', - data: { selector, message: 'Invalid selector: ' + err.message, success: false } + data: { selector, message: 'Invalid selector: ' + error.message, success: false } }, '*'); return; } @@ -1228,7 +1267,7 @@ export default function RootLayout({ if (isBackground) { oldValue = window.getComputedStyle(element).backgroundImage; - element.style.backgroundImage = 'url(\'\'' + newSrc + '\'\'')'; + element.style.backgroundImage = \`url('\${newSrc}')\`; replaced = true; } else if (element.tagName.toLowerCase() === 'img') { oldValue = element.src; @@ -1263,7 +1302,7 @@ export default function RootLayout({ const hasBackgroundImage = window.getComputedStyle(element).backgroundImage !== 'none'; if (hasBackgroundImage) { oldValue = window.getComputedStyle(element).backgroundImage; - element.style.backgroundImage = 'url(\'\'' + newSrc + '\'\'')'; + element.style.backgroundImage = \`url('\${newSrc}')\`; replaced = true; } } @@ -1273,7 +1312,7 @@ export default function RootLayout({ let cleanOldValue = oldValue; if (oldValue.includes('url(')) { - const urlMatch = oldValue.match(/url(['"']?([^'")]+)['"']?)/i); + const urlMatch = oldValue.match(/url(['"]?([^'")]+)['"]?)/); if (urlMatch) { cleanOldValue = urlMatch[1]; } @@ -2762,4 +2801,4 @@ export default function RootLayout({ ); -} +} \ No newline at end of file