diff --git a/components/home/Hero.tsx b/components/home/Hero.tsx index c566f75b..cd13c31f 100644 --- a/components/home/Hero.tsx +++ b/components/home/Hero.tsx @@ -167,7 +167,7 @@ const scribbleVariants = { } as const; const subtitleVariants = { - hidden: { opacity: 0, y: 20, scale: 0.98 }, + hidden: { opacity: 1, y: 20, scale: 0.98 }, visible: { opacity: 1, y: 0, @@ -177,7 +177,7 @@ const subtitleVariants = { } as const; const buttonContainerVariants = { - hidden: { opacity: 0 }, + hidden: { opacity: 1 }, visible: { opacity: 1, transition: { @@ -188,7 +188,7 @@ const buttonContainerVariants = { } as const; const buttonVariants = { - hidden: { opacity: 0, y: 30, scale: 0.9 }, + hidden: { opacity: 1, y: 30, scale: 0.9 }, visible: { opacity: 1, y: 0, diff --git a/components/home/VideoSection.tsx b/components/home/VideoSection.tsx index 8ebd2d64..c1503329 100644 --- a/components/home/VideoSection.tsx +++ b/components/home/VideoSection.tsx @@ -1,26 +1,44 @@ +'use client'; + +import React, { useState, useEffect, useRef } from 'react'; import Scribble from '@/components/Scribble'; import { useTranslations } from 'next-intl'; export default function VideoSection() { const t = useTranslations('Home.video'); + const [isVisible, setIsVisible] = useState(false); + const sectionRef = useRef(null); + + useEffect(() => { + const observer = new IntersectionObserver( + ([entry]) => { + if (entry.isIntersecting) { + setIsVisible(true); + observer.disconnect(); + } + }, + { rootMargin: '200px' }, + ); + + if (sectionRef.current) { + observer.observe(sectionRef.current); + } + + return () => observer.disconnect(); + }, []); return ( -
- -
-
+
+ {isVisible && ( + + )} +
+

{t.rich('title', { future: (chunks) => ( diff --git a/components/record-mode/ToolCoordinator.tsx b/components/record-mode/ToolCoordinator.tsx index 14528428..7ebb9104 100644 --- a/components/record-mode/ToolCoordinator.tsx +++ b/components/record-mode/ToolCoordinator.tsx @@ -2,8 +2,17 @@ import React, { useState, useEffect } from 'react'; import { useRecordMode } from './RecordModeContext'; -import { FeedbackOverlay } from '@mintel/next-feedback/FeedbackOverlay'; -import { RecordModeOverlay } from './RecordModeOverlay'; +import dynamic from 'next/dynamic'; + +const FeedbackOverlay = dynamic( + () => import('@mintel/next-feedback/FeedbackOverlay').then((mod) => mod.FeedbackOverlay), + { ssr: false }, +); + +const RecordModeOverlay = dynamic( + () => import('./RecordModeOverlay').then((mod) => mod.RecordModeOverlay), + { ssr: false }, +); import { PickingHelper } from './PickingHelper'; interface ToolCoordinatorProps { diff --git a/next.config.mjs b/next.config.mjs index 071f2027..38c47b71 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,4 +1,6 @@ import withMintelConfig from '@mintel/next-config'; +import withBundleAnalyzer from '@next/bundle-analyzer'; +import { withSentryConfig } from '@sentry/nextjs'; console.log('🚀 NEXT CONFIG LOADED FROM:', process.cwd()); @@ -354,6 +356,10 @@ const nextConfig = { }, }; -export default withMintelConfig(nextConfig, { - hideSourceMaps: true, +const withAnalyzer = withBundleAnalyzer({ + enabled: process.env.ANALYZE === 'true', }); + +export default withAnalyzer(withMintelConfig(nextConfig, { + hideSourceMaps: true, +})); diff --git a/package.json b/package.json index 29347467..c6b62712 100644 --- a/package.json +++ b/package.json @@ -49,6 +49,7 @@ "@lhci/cli": "^0.15.1", "@mintel/eslint-config": "1.8.3", "@mintel/tsconfig": "1.8.3", + "@next/bundle-analyzer": "^16.1.6", "@remotion/cli": "^4.0.421", "@remotion/google-fonts": "^4.0.421", "@remotion/player": "^4.0.421", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e507146a..8e11dd27 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -144,6 +144,9 @@ importers: '@mintel/tsconfig': specifier: 1.8.3 version: 1.8.3 + '@next/bundle-analyzer': + specifier: ^16.1.6 + version: 16.1.6 '@remotion/cli': specifier: ^4.0.421 version: 4.0.421(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -464,6 +467,10 @@ packages: resolution: {integrity: sha512-Ig8zZAQDbc7QMIM54N+x71C04lni9MN9yalNAezjDjFdNknTJzupDY7V5cb+kOJL8GsqDE9Bg8xq8xCmkDVs5A==} engines: {node: '>=22'} + '@discoveryjs/json-ext@0.5.7': + resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} + engines: {node: '>=10.0.0'} + '@emnapi/core@1.8.1': resolution: {integrity: sha512-AvT9QFpxK0Zd8J0jopedNm+w/2fIzvtPKPjqyw9jwvBaReTTqPBk9Hixaz7KbjimP+QNz605/XnjFcDAL2pqBg==} @@ -1269,6 +1276,9 @@ packages: '@napi-rs/wasm-runtime@0.2.12': resolution: {integrity: sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ==} + '@next/bundle-analyzer@16.1.6': + resolution: {integrity: sha512-ee2kagdTaeEWPlotgdTOqFHYcD3e2m2bbE3I9Rq2i6ABYi5OgopmtEUe8NM23viaYxLV2tDH/2nd5+qKoEr6cw==} + '@next/env@16.1.6': resolution: {integrity: sha512-N1ySLuZjnAtN3kFnwhAwPvZah8RJxKasD7x1f8shFqhncnWZn4JMfg37diLNuoHsLAlrDfM3g4mawVdtAG8XLQ==} @@ -3038,6 +3048,10 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + acorn-walk@8.3.5: + resolution: {integrity: sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==} + engines: {node: '>=0.4.0'} + acorn@8.15.0: resolution: {integrity: sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==} engines: {node: '>=0.4.0'} @@ -3581,6 +3595,10 @@ packages: commander@2.20.3: resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + commander@7.2.0: + resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} + engines: {node: '>= 10'} + commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} @@ -3800,6 +3818,9 @@ packages: resolution: {integrity: sha512-rBMW+F2TXryBwB54Q0d8drNEI+TfoS9JpNTAoVpukbWEhjXQq4rySFYLaqXMFXwdv61Zb2OHtj5bviSoimqxRQ==} engines: {node: '>=18'} + debounce@1.2.1: + resolution: {integrity: sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==} + debounce@2.2.0: resolution: {integrity: sha512-Xks6RUDLZFdz8LIdR6q0MTH44k7FikOmnh5xkSjMig6ch45afc8sjTjRQf3P6ax8dMgcQrYO/AR2RGWURrruqw==} engines: {node: '>=18'} @@ -4588,6 +4609,10 @@ packages: resolution: {integrity: sha512-5v6yZd4JK3eMI3FqqCouswVqwugaA9r4dNZB1wwcmrD02QkV5H0y7XBQW8QwQqEaZY1pM9aqORSORhJRdNK44Q==} engines: {node: '>=6.0'} + gzip-size@6.0.0: + resolution: {integrity: sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==} + engines: {node: '>=10'} + happy-dom@20.6.1: resolution: {integrity: sha512-+0vhESXXhFwkdjZnJ5DlmJIfUYGgIEEjzIjB+aKJbFuqlvvKyOi+XkI1fYbgYR9QCxG5T08koxsQ6HrQfa5gCQ==} engines: {node: '>=20.0.0'} @@ -4658,6 +4683,9 @@ packages: resolution: {integrity: sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==} engines: {node: ^20.19.0 || ^22.12.0 || >=24.0.0} + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + html-parse-stringify@3.0.1: resolution: {integrity: sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==} @@ -4943,6 +4971,10 @@ packages: resolution: {integrity: sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==} engines: {node: '>=12'} + is-plain-object@5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} + is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} @@ -5870,6 +5902,10 @@ packages: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} + opener@1.5.2: + resolution: {integrity: sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==} + hasBin: true + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -6618,6 +6654,10 @@ packages: simple-swizzle@0.2.4: resolution: {integrity: sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==} + sirv@2.0.4: + resolution: {integrity: sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==} + engines: {node: '>= 10'} + sirv@3.0.2: resolution: {integrity: sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==} engines: {node: '>=18'} @@ -7332,6 +7372,11 @@ packages: resolution: {integrity: sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==} engines: {node: '>=20'} + webpack-bundle-analyzer@4.10.1: + resolution: {integrity: sha512-s3P7pgexgT/HTUSYgxJyn28A+99mmLq4HsJepMPzu0R8ImJc52QNqaFYW1Z2z2uIb1/J3eYgaAWVpaC+v/1aAQ==} + engines: {node: '>= 10.13.0'} + hasBin: true + webpack-sources@3.3.3: resolution: {integrity: sha512-yd1RBzSGanHkitROoPFd6qsrxt+oFhg/129YzheDGqeustzX0vTZJZsSsQjVQC4yzBQ56K55XU8gaNCtIzOnTg==} engines: {node: '>=10.13.0'} @@ -7867,6 +7912,8 @@ snapshots: '@directus/sdk@21.1.0': {} + '@discoveryjs/json-ext@0.5.7': {} + '@emnapi/core@1.8.1': dependencies: '@emnapi/wasi-threads': 1.1.0 @@ -8557,6 +8604,13 @@ snapshots: '@tybys/wasm-util': 0.10.1 optional: true + '@next/bundle-analyzer@16.1.6': + dependencies: + webpack-bundle-analyzer: 4.10.1 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + '@next/env@16.1.6': {} '@next/eslint-plugin-next@16.1.6': @@ -10508,6 +10562,10 @@ snapshots: dependencies: acorn: 8.15.0 + acorn-walk@8.3.5: + dependencies: + acorn: 8.15.0 + acorn@8.15.0: {} adler-32@1.3.1: {} @@ -11072,6 +11130,8 @@ snapshots: commander@2.20.3: {} + commander@7.2.0: {} + commondir@1.0.1: {} compare-func@2.0.0: @@ -11305,6 +11365,8 @@ snapshots: dependencies: mimic-function: 5.0.1 + debounce@1.2.1: {} + debounce@2.2.0: {} debug@2.6.9: @@ -12350,6 +12412,10 @@ snapshots: section-matter: 1.0.0 strip-bom-string: 1.0.0 + gzip-size@6.0.0: + dependencies: + duplexer: 0.1.2 + happy-dom@20.6.1: dependencies: '@types/node': 22.19.10 @@ -12457,6 +12523,8 @@ snapshots: transitivePeerDependencies: - '@noble/hashes' + html-escaper@2.0.2: {} + html-parse-stringify@3.0.1: dependencies: void-elements: 3.1.0 @@ -12758,6 +12826,8 @@ snapshots: is-plain-obj@4.1.0: {} + is-plain-object@5.0.0: {} + is-potential-custom-element-name@1.0.1: {} is-reference@1.2.1: @@ -13859,6 +13929,8 @@ snapshots: is-docker: 2.2.1 is-wsl: 2.2.0 + opener@1.5.2: {} + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -14853,6 +14925,12 @@ snapshots: dependencies: is-arrayish: 0.3.4 + sirv@2.0.4: + dependencies: + '@polka/url': 1.0.0-next.29 + mrmime: 2.0.1 + totalist: 3.0.1 + sirv@3.0.2: dependencies: '@polka/url': 1.0.0-next.29 @@ -15666,6 +15744,25 @@ snapshots: webidl-conversions@8.0.1: {} + webpack-bundle-analyzer@4.10.1: + dependencies: + '@discoveryjs/json-ext': 0.5.7 + acorn: 8.15.0 + acorn-walk: 8.3.5 + commander: 7.2.0 + debounce: 1.2.1 + escape-string-regexp: 4.0.0 + gzip-size: 6.0.0 + html-escaper: 2.0.2 + is-plain-object: 5.0.0 + opener: 1.5.2 + picocolors: 1.1.1 + sirv: 2.0.4 + ws: 7.5.10 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + webpack-sources@3.3.3: {} webpack-virtual-modules@0.5.0: {}