From 1ee7a41d0147a654fdc9656516ef9f656a63f725 Mon Sep 17 00:00:00 2001 From: Ana Neri <42419543+ananeridev@users.noreply.github.com> Date: Sat, 9 May 2026 23:02:25 -0300 Subject: [PATCH 1/6] fix: minor site (#43) fix: minor photo Signed-off-by: ananeridev --- i18n/en-US/code.json | 6 ------ i18n/es-419/code.json | 6 ------ i18n/pt-BR/code.json | 6 ------ src/website/assets/img/team/wells.webp | Bin 12492 -> 0 bytes src/website/components/home/Team.tsx | 14 -------------- src/website/hooks/useScroll.tsx | 5 ----- 6 files changed, 37 deletions(-) delete mode 100644 src/website/assets/img/team/wells.webp diff --git a/i18n/en-US/code.json b/i18n/en-US/code.json index 2a2b546..3b53049 100644 --- a/i18n/en-US/code.json +++ b/i18n/en-US/code.json @@ -167,12 +167,6 @@ "team.ana.position": { "message": "Senior Software Engineer" }, - "team.weslley.bio": { - "message": "Weslley Araújo is a developer with over 11 years of experience, MySQL2 maintainer and creator of Poku, a high-performance test runner that challenges the programming language itself." - }, - "team.weslley.position": { - "message": "Principal Developer" - }, "team.lojhan.bio": { "message": "Tech Lead & Full Stack Developer. Helping teams build scalable applications with modern technologies. Specialized in frontend, backend and architecture design." }, diff --git a/i18n/es-419/code.json b/i18n/es-419/code.json index af19f06..7ec79d6 100644 --- a/i18n/es-419/code.json +++ b/i18n/es-419/code.json @@ -167,12 +167,6 @@ "team.ana.position": { "message": "Senior Software Engineer" }, - "team.weslley.bio": { - "message": "Weslley Araújo es un desarrollador con más de 11 años de experiencia, mantenedor de MySQL2 y creador de Poku, un test runner de alto rendimiento que desafía al propio lenguaje de programación." - }, - "team.weslley.position": { - "message": "Principal Developer" - }, "team.lojhan.bio": { "message": "Tech Lead & Full Stack Developer. Ayudando a equipos a construir aplicaciones escalables con tecnologías modernas. Especializado en frontend, backend y diseño de arquitectura." }, diff --git a/i18n/pt-BR/code.json b/i18n/pt-BR/code.json index fb181e4..bd77e87 100644 --- a/i18n/pt-BR/code.json +++ b/i18n/pt-BR/code.json @@ -167,12 +167,6 @@ "team.ana.position": { "message": "Senior Software Engineer" }, - "team.weslley.bio": { - "message": "Weslley Araújo é um desenvolvedor com mais de 11 anos de experiência, mantenedor do MySQL2 e criador do Poku, um test runner de alta performance que desafia a própria linguagem de programação." - }, - "team.weslley.position": { - "message": "Principal Developer" - }, "team.lojhan.bio": { "message": "Tech Lead & Full Stack Developer. Ajudando equipes a construir aplicações escaláveis com tecnologias modernas. Especializado em frontend, backend e design de arquitetura." }, diff --git a/src/website/assets/img/team/wells.webp b/src/website/assets/img/team/wells.webp deleted file mode 100644 index 64bc10ec46c1f295ef8ddfb79084328ca2e37290..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12492 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 z000005CBL3000310RTt<000310XRZQO#~ {
- Date: Sun, 10 May 2026 17:11:12 -0300 Subject: [PATCH 2/6] Readme (#44) * fix: minor photo Signed-off-by: ananeridev * fix: readme Signed-off-by: ananeridev --------- Signed-off-by: ananeridev --- DEVELOPMENT.md | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 81 ++++++----------------------------------------- 2 files changed, 96 insertions(+), 71 deletions(-) create mode 100644 DEVELOPMENT.md diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 0000000..f7c34e1 --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,86 @@ +# Desenvolvimento do site + +Este repositório contém o **código-fonte** do site oficial da **JSConf Brasil** ([jsconf.com.br](https://jsconf.com.br)): páginas em **Docusaurus**, conteúdo multilíngue e um **Worker** (Cloudflare) para formulários e API. Aqui você encontra como rodar o projeto localmente, traduzir textos e validar o build antes de abrir um PR. + +--- + +## Primeiros passos + +```sh +npm ci +npm start # Inicia o website e o servidor localmente (pt-BR) +``` + +--- + +### Idiomas + +```sh +npm run start:en # Inglês +npm run start:es # Espanhol +``` + +> [!TIP] +> +> Use o componente `` ao invés de `` para visualizar as imagens corretamente em todos os idiomas durante o desenvolvimento. +> +> - O componente `` utiliza `loading="lazy"` e `decoding="async"` por padrão. + +--- + +### Traduções (i18n) + +Use `` para conteúdo JSX e `text()` para atributos HTML (`aria-label`, `alt`, `placeholder`, etc.): + +```tsx +

+ +

+``` + +```tsx +{text({ +``` + +`` e `text()` são abstrações do [``](https://docusaurus.io/docs/docusaurus-core#translate) do **Docusaurus**: + +- IDs tipados com autocomplete a partir de `i18n/pt-BR/code.json` +- Fallback automático do idioma principal (`pt-BR`) — não é necessário passar `children` + +Para adicionar um novo texto: + +1. Crie a chave em `i18n/pt-BR/code.json` +2. Use `` ou `text({ id: '...' })` no componente +3. Os tipos são inferidos automaticamente usando `i18n/pt-BR/code.json` como fonte de verdade + +--- + +### Formatação / Linting + +```sh +npm run lint:fix +``` + +--- + +## Compilação + +```sh +npm run build # Compila o website e o worker +``` + +--- + +## Testes + +```sh +npm test # Testes unitários +``` + +```sh +npm run typecheck # Verificação de tipos TypeScript +``` + +```sh +npm run lint # Verificação de linting +``` diff --git a/README.md b/README.md index 0235c6c..8f30b63 100644 --- a/README.md +++ b/README.md @@ -1,82 +1,21 @@ -# JSConf Brasil 2026 🐢✨ +# JSConf Brasil 2026 -## Desenvolvimento +A **JSConf Brasil** é a conferência brasileira dentro da família **JSConf**, dedicada à comunidade **JavaScript** e ao ecossistema em torno da linguagem — do front ao back, ferramentas, performance e as pessoas que constroem produtos com tecnologia web. -```sh -npm ci -npm start # Inicia o website e o servidor localmente (pt-BR) -``` +## Propósito ---- - -### Idiomas - -```sh -npm run start:en # Inglês -npm run start:es # Espanhol -``` - -> [!TIP] -> -> Use o componente `` ao invés de `` para visualizar as imagens corretamente em todos os idiomas durante o desenvolvimento. -> -> - O componente `` utiliza `loading="lazy"` e `decoding="async"` por padrão. - ---- - -### Traduções (i18n) - -Use `` para conteúdo JSX e `text()` para atributos HTML ( `aria-label` , `alt` , `placeholder` , etc.): - -```tsx -

- -

-``` - -```tsx -{text({ -``` +O evento existe para **reunir quem desenvolve com JS**, **dividir conhecimento de alto nível** e **fortalecer redes** entre profissionais, estudantes e comunidades de todo o país. Queremos um espaço acolhedor, com palestras que inspiram e práticas que refletem o estado da arte, sempre com olhar para o contexto brasileiro. -`` e `text()` são abstrações do [ `` ](https://docusaurus.io/docs/docusaurus-core#translate) do **Docusaurus**: +## JSConf BR e a NodeBR -- IDs tipados com autocomplete a partir de `i18n/pt-BR/code.json` -- Fallback automático do idioma principal (`pt-BR`) — não é necessário passar `children` +A **JSConf Brasil** é um **braço da [NodeBR](https://nodebr.org)** — a associação que apoia e articula a comunidade **Node.js** e JavaScript no Brasil. Essa ligação traduz o compromisso com **código aberto**, **educação** e **representação** da comunidade técnica nacional em eventos de referência internacional, alinhados aos valores que a NodeBR defende no país. -Para adicionar um novo texto: +## Site e repositório -1. Crie a chave em `i18n/pt-BR/code.json` -2. Use `` ou `text({ id: '...' })` no componente -3. Os tipos são inferidos automaticamente usando `i18n/pt-BR/code.json` como fonte de verdade +O site público está em **[jsconf.com.br](https://jsconf.com.br)**. Este repositório é o código do site e dos serviços que o sustentam (por exemplo, formulários e integrações). ---- - -### Formatação / Linting - -```sh -npm run lint:fix -``` - ---- - -## Compilação - -```sh -npm run build # Compila o website -``` +Quer contribuir com código, traduções ou correções? Veja **[DEVELOPMENT.md](./DEVELOPMENT.md)**. --- -## Testes - -```sh -npm test # Testes unitários -``` - -```sh -npm run typecheck # Verificação de tipos TypeScript -``` - -```sh -npm run lint # Verificação de linting -``` +Licença: **AGPL-3.0-only** — ver [LICENSE](./LICENSE). From d443c2df4c6b18ea59f8a1964e0ef4a1b12e5c92 Mon Sep 17 00:00:00 2001 From: Lucas Santos Date: Sun, 10 May 2026 20:07:27 -0300 Subject: [PATCH 3/6] Revert "wip: apply animation fix" This reverts commit ee396326a507763427726b28f98df2428fde6fce. --- src/website/components/shared/BR.tsx | 163 ++--------------- src/website/components/shared/Page.tsx | 12 +- src/website/hooks/BR/animation.ts | 116 ++++++++++++ src/website/hooks/BR/canvas.ts | 78 ++++++++ src/website/hooks/BR/definitions.ts | 2 +- src/website/hooks/BR/helpers.ts | 168 ++++++++++++++++++ src/website/hooks/BR/types.ts | 39 ++++ src/website/hooks/BR/useBR.tsx | 54 ++++++ src/website/hooks/Background/animation.ts | 113 ++++++++++++ src/website/hooks/Background/definitions.ts | 16 ++ src/website/hooks/Background/stars.ts | 91 ++++++++++ src/website/hooks/Background/types.ts | 54 ++++++ .../hooks/Background/useBackground.tsx | 123 +++++++++++++ src/website/hooks/shared/animation.ts | 7 +- src/website/hooks/useScrollSpy.tsx | 5 +- src/website/scss/global/_animations.scss | 33 ++-- src/website/scss/global/_root.scss | 8 + src/website/scss/pages/_gallery.scss | 4 +- src/website/scss/pages/_waitlist.scss | 9 +- 19 files changed, 923 insertions(+), 172 deletions(-) create mode 100644 src/website/hooks/BR/animation.ts create mode 100644 src/website/hooks/BR/canvas.ts create mode 100644 src/website/hooks/BR/helpers.ts create mode 100644 src/website/hooks/BR/types.ts create mode 100644 src/website/hooks/BR/useBR.tsx create mode 100644 src/website/hooks/Background/animation.ts create mode 100644 src/website/hooks/Background/definitions.ts create mode 100644 src/website/hooks/Background/stars.ts create mode 100644 src/website/hooks/Background/types.ts create mode 100644 src/website/hooks/Background/useBackground.tsx diff --git a/src/website/components/shared/BR.tsx b/src/website/components/shared/BR.tsx index a70df29..d2d0865 100644 --- a/src/website/components/shared/BR.tsx +++ b/src/website/components/shared/BR.tsx @@ -1,154 +1,25 @@ -import { memo, useEffect, useRef } from 'react'; -import { - FINAL_COLOR, - INITIAL_COLOR, - VIEWBOX_WIDTH, -} from '@site/src/website/hooks/BR/definitions'; -import rawDots from '@site/src/website/hooks/BR/dots.json'; +import { memo } from 'react'; +import { useBR } from '../../hooks/BR/useBR'; -const OVERLAY_COUNT = 4; -const OVERLAY_MAX_DOTS = 400; -const CYCLE_S = 16; -// Render at low resolution — dots are hard-edged squares so pixelated scaling is lossless. -// This keeps GPU textures tiny (~1.6 MB total) vs rendering at display size (~200+ MB with scale+DPR). -const RENDER_WIDTH = 320; - -type Dot = { cx: number; cy: number; r: number }; - -const allDots: Dot[] = ( - rawDots as Array<{ cx: number; cy: number; r: number }> -).map((d) => ({ cx: d.cx, cy: d.cy, r: d.r })); - -const BASE_COLOR = `rgba(${INITIAL_COLOR.red},${INITIAL_COLOR.green},${INITIAL_COLOR.blue},${INITIAL_COLOR.alpha})`; -const HIGH_COLOR = `rgba(${FINAL_COLOR.red},${FINAL_COLOR.green},${FINAL_COLOR.blue},${FINAL_COLOR.alpha})`; - -// 100, 200, 300, 400 dots per overlay -const overlaySubsets: Dot[][] = Array.from( - { length: OVERLAY_COUNT }, - (_, i) => { - const count = Math.round(((i + 1) / OVERLAY_COUNT) * OVERLAY_MAX_DOTS); - return [...allDots].sort(() => Math.random() - 0.5).slice(0, count); - } -); - -const offscreen = - typeof document !== 'undefined' ? document.createElement('canvas') : null; - -function toDataURL( - dots: Dot[], - color: string, - renderWidth: number, - renderHeight: number -): string { - if (!offscreen) return ''; - offscreen.width = renderWidth; - offscreen.height = renderHeight; - const ctx = offscreen.getContext('2d'); - if (!ctx) return ''; - ctx.clearRect(0, 0, renderWidth, renderHeight); - const scale = renderWidth / VIEWBOX_WIDTH; - ctx.fillStyle = color; - for (const d of dots) { - const size = Math.max(1, Math.round(d.r * 2 * scale)); - ctx.fillRect( - Math.round(d.cx * scale - size / 2), - Math.round(d.cy * scale - size / 2), - size, - size - ); - } - return offscreen.toDataURL(); -} - -type BRProps = { className?: string; style?: React.CSSProperties }; - -const BRCanvas = ({ className, style }: BRProps) => { - const containerRef = useRef(null); - const baseRef = useRef(null); - const overlayRefs = useRef<(HTMLImageElement | null)[]>( - Array(OVERLAY_COUNT).fill(null) - ); - - useEffect(() => { - const container = containerRef.current; - if (!container) return; - - let rendered = false; - - const repaint = () => { - const containerWidth = container.offsetWidth; - const containerHeight = container.offsetHeight; - if (!containerWidth || !containerHeight) return; - - const renderHeight = Math.round( - containerHeight * (RENDER_WIDTH / containerWidth) - ); - - if (baseRef.current) - baseRef.current.src = toDataURL( - allDots, - BASE_COLOR, - RENDER_WIDTH, - renderHeight - ); - - overlayRefs.current.forEach((el, i) => { - if (el) - el.src = toDataURL( - overlaySubsets[i]!, - HIGH_COLOR, - RENDER_WIDTH, - renderHeight - ); - }); - - rendered = true; - }; - - repaint(); - - const ro = new ResizeObserver(() => { - // Skip re-render on tiny fluctuations after first paint - if (rendered) repaint(); - }); - ro.observe(container); - return () => ro.disconnect(); - }, []); +type CanvasProps = { + className?: string; + style?: React.CSSProperties; +}; - const layerStyle: React.CSSProperties = { - position: 'absolute', - inset: 0, - width: '100%', - height: '100%', - imageRendering: 'pixelated', - }; +const Canvas = ({ className, style }: CanvasProps) => { + const { canvasRef } = useBR(); return ( -
- - {Array.from({ length: OVERLAY_COUNT }, (_, i) => ( - { - overlayRefs.current[i] = el; - }} - style={{ - ...layerStyle, - // translateZ forces independent compositor layer so opacity animation - // doesn't trigger Layerize on the parent subtree every frame - transform: 'translateZ(0)', - animation: `br-cycle ${CYCLE_S}s steps(${CYCLE_S * 30}) ${-(CYCLE_S / OVERLAY_COUNT) * i}s infinite`, - willChange: 'opacity', - }} - /> - ))} -
+ style={{ + width: '100%', + height: '100%', + ...style, + }} + /> ); }; -export const BR = memo(BRCanvas); +export const BR = memo(Canvas); diff --git a/src/website/components/shared/Page.tsx b/src/website/components/shared/Page.tsx index f733651..133d927 100644 --- a/src/website/components/shared/Page.tsx +++ b/src/website/components/shared/Page.tsx @@ -1,6 +1,7 @@ import '@site/src/website/scss/pages/root.scss'; import Head from '@docusaurus/Head'; import Layout from '@theme/Layout'; +import { useBackground } from '../../hooks/Background/useBackground'; type PageProps = { children: React.ReactNode; @@ -9,12 +10,21 @@ type PageProps = { }; export const Page = ({ title, description, children }: PageProps) => { + const { canvasRef } = useBackground({ + intensity: 0.0025, + zoomSpeed: 0.0005, + starColor: '#073f2950', + }); + return ( -
{children}
+
+ + {children} +
); }; diff --git a/src/website/hooks/BR/animation.ts b/src/website/hooks/BR/animation.ts new file mode 100644 index 0000000..62152ea --- /dev/null +++ b/src/website/hooks/BR/animation.ts @@ -0,0 +1,116 @@ +import type { + AnimationRefs, + AnimationState, +} from '@site/src/website/hooks/BR/types'; +import { draw } from '@site/src/website/hooks/BR/canvas'; +import { + FINAL_COLOR, + INITIAL_COLOR, +} from '@site/src/website/hooks/BR/definitions'; +import { + initializeResizeObserver, + stopAnimationFrame, +} from '@site/src/website/hooks/shared/animation'; + +const easeIn = (progress: number): number => progress * progress; + +const lerp = (start: number, end: number, progress: number): number => + start + (end - start) * progress; + +export const getColor = (progress: number): string => { + const easedProgress = easeIn(Math.min(1, Math.max(0, progress))); + const red = Math.round( + lerp(INITIAL_COLOR.red, FINAL_COLOR.red, easedProgress) + ); + const green = Math.round( + lerp(INITIAL_COLOR.green, FINAL_COLOR.green, easedProgress) + ); + const blue = Math.round( + lerp(INITIAL_COLOR.blue, FINAL_COLOR.blue, easedProgress) + ); + const alpha = lerp(INITIAL_COLOR.alpha, FINAL_COLOR.alpha, easedProgress); + + return `rgba(${red},${green},${blue},${alpha})`; +}; + +const createAnimationLoop = ( + canvas: HTMLCanvasElement, + animation: AnimationRefs, + state: AnimationState +) => { + const animate = (timestamp: number) => { + const context = canvas.getContext('2d'); + if (!context) return; + + animation.startTime ??= timestamp; + + const shouldRenderFrame = timestamp - animation.lastFrameTime >= 16; + if (shouldRenderFrame) { + const elapsed = + timestamp - animation.startTime + animation.elapsedBeforePause; + draw(context, canvas, state, elapsed); + animation.lastFrameTime = timestamp; + } + + animation.animationFrameId = requestAnimationFrame(animate); + }; + + return animate; +}; + +const resetPauseState = (animation: AnimationRefs): void => { + if (animation.pauseTime === null) return; + + animation.startTime = null; + animation.pauseTime = null; +}; + +const savePauseState = (animation: AnimationRefs): void => { + const canSavePauseState = + animation.startTime !== null && animation.pauseTime === null; + if (!canSavePauseState) return; + + animation.elapsedBeforePause += performance.now() - animation.startTime!; + animation.pauseTime = performance.now(); + animation.startTime = null; +}; + +const startAnimationLoop = ( + canvas: HTMLCanvasElement, + animation: AnimationRefs, + state: AnimationState, + handleResize: () => void +): void => { + const animate = createAnimationLoop(canvas, animation, state); + + stopAnimationFrame(animation); + requestAnimationFrame(() => { + handleResize(); + animation.animationFrameId = requestAnimationFrame(animate); + }); +}; + +export const handleVisibilityOn = ( + canvas: HTMLCanvasElement, + animation: AnimationRefs, + state: AnimationState, + handleResize: () => void +): void => { + resetPauseState(animation); + initializeResizeObserver(canvas, animation, handleResize); + startAnimationLoop(canvas, animation, state, handleResize); +}; + +export const handleVisibilityOff = (animation: AnimationRefs): void => { + savePauseState(animation); + stopAnimationFrame(animation); +}; + +export const createElapsedTimeGetter = + (animation: AnimationRefs) => (): number => { + if (animation.startTime === null) return 0; + + return ( + performance.now() - animation.startTime + animation.elapsedBeforePause + ); + }; diff --git a/src/website/hooks/BR/canvas.ts b/src/website/hooks/BR/canvas.ts new file mode 100644 index 0000000..e4d7ff0 --- /dev/null +++ b/src/website/hooks/BR/canvas.ts @@ -0,0 +1,78 @@ +import type { AnimationState, Dot } from '@site/src/website/hooks/BR/types'; +import { getColor } from '@site/src/website/hooks/BR/animation'; +import { VIEWBOX_WIDTH } from '@site/src/website/hooks/BR/definitions'; +import { + calculateDotProgress, + processRemovals, +} from '@site/src/website/hooks/BR/helpers'; + +const drawSquare = ( + context: CanvasRenderingContext2D, + dot: Dot, + progress: number, + scale: number +): void => { + const color = getColor(progress); + const size = dot.radius * 2 * scale; + const x = dot.centerX * scale - size / 2; + const y = dot.centerY * scale - size / 2; + + context.fillStyle = color; + context.fillRect(x, y, size, size); +}; + +export const draw = ( + context: CanvasRenderingContext2D, + canvas: HTMLCanvasElement, + state: AnimationState, + elapsed: number +): void => { + if (canvas.width === 0 || canvas.height === 0) return; + + const visibleIndices: number[] = []; + const scale = canvas.width / VIEWBOX_WIDTH; + + let visibleCount = 0; + + context.clearRect(0, 0, canvas.width, canvas.height); + + for (let dotIndex = 0; dotIndex < state.dots.length; dotIndex++) { + const dotState = state.dots[dotIndex]; + if (!dotState) continue; + + const result = calculateDotProgress(dotState, elapsed); + + dotState.visible = result.visible; + dotState.disappearAt = result.disappearAt; + + if (result.progress > 0) { + visibleCount++; + + drawSquare(context, dotState.dot, result.progress, scale); + + const isStableVisible = result.visible && result.disappearAt === null; + if (isStableVisible) { + visibleIndices.push(dotIndex); + } + } + } + + processRemovals(state, visibleIndices, visibleCount, elapsed); +}; + +export const updateCanvasSize = ( + canvas: HTMLCanvasElement, + state: AnimationState, + getElapsed: () => number +): void => { + const rect = canvas.getBoundingClientRect(); + if (rect.width === 0 || rect.height === 0) return; + + canvas.width = rect.width; + canvas.height = rect.height; + + const context = canvas.getContext('2d'); + if (context) { + draw(context, canvas, state, getElapsed()); + } +}; diff --git a/src/website/hooks/BR/definitions.ts b/src/website/hooks/BR/definitions.ts index 5407c8f..b4a1b9b 100644 --- a/src/website/hooks/BR/definitions.ts +++ b/src/website/hooks/BR/definitions.ts @@ -1,6 +1,6 @@ export const ANIMATION_DURATION = 250; export const DELAY_PER_DOT = 25; -export const VISIBLE_THRESHOLD = 200; +export const VISIBLE_THRESHOLD = 1000; export const VIEWBOX_WIDTH = 1086; export const INITIAL_COLOR = { red: 255, green: 255, blue: 255, alpha: 0.025 }; export const FINAL_COLOR = { red: 102, green: 255, blue: 0, alpha: 0.25 }; diff --git a/src/website/hooks/BR/helpers.ts b/src/website/hooks/BR/helpers.ts new file mode 100644 index 0000000..69e29e9 --- /dev/null +++ b/src/website/hooks/BR/helpers.ts @@ -0,0 +1,168 @@ +import type { + AnimationState, + Dot, + DotProgressResult, + DotState, + RawDotData, +} from '@site/src/website/hooks/BR/types'; +import { + ANIMATION_DURATION, + DELAY_PER_DOT, + VISIBLE_THRESHOLD, +} from '@site/src/website/hooks/BR/definitions'; +import dots from '@site/src/website/hooks/BR/dots.json'; + +const shuffleArray = (array: T[]): T[] => { + const result = [...array]; + + for (let currentIndex = result.length - 1; currentIndex > 0; currentIndex--) { + const randomIndex = Math.floor(Math.random() * (currentIndex + 1)); + + const currentValue = result[currentIndex]; + const randomValue = result[randomIndex]; + + if (currentValue !== undefined && randomValue !== undefined) { + result[currentIndex] = randomValue; + result[randomIndex] = currentValue; + } + } + + return result; +}; + +const mapRawDotToDot = (rawDot: RawDotData): Dot => ({ + centerX: rawDot.cx, + centerY: rawDot.cy, + radius: rawDot.r, +}); + +const createHiddenProgress = (): DotProgressResult => ({ + progress: 0, + visible: false, + disappearAt: null, +}); + +const createVisibleProgress = (): DotProgressResult => ({ + progress: 1, + visible: true, + disappearAt: null, +}); + +const calculateDisappearingProgress = ( + elapsed: number, + disappearAt: number, + visible: boolean +): DotProgressResult | null => { + if (disappearAt === null) return null; + + const timeSinceDisappear = elapsed - disappearAt; + const hasFinishedDisappearing = timeSinceDisappear >= ANIMATION_DURATION; + + if (hasFinishedDisappearing) return createHiddenProgress(); + + return { + progress: 1 - timeSinceDisappear / ANIMATION_DURATION, + visible, + disappearAt, + }; +}; + +const calculateAppearingProgress = ( + elapsed: number, + appearAt: number +): DotProgressResult => { + const timeSinceAppear = elapsed - appearAt; + + const hasNotStartedAppearing = timeSinceAppear <= 0; + if (hasNotStartedAppearing) return createHiddenProgress(); + + const hasFinishedAppearing = timeSinceAppear >= ANIMATION_DURATION; + if (hasFinishedAppearing) return createVisibleProgress(); + + return { + progress: timeSinceAppear / ANIMATION_DURATION, + visible: false, + disappearAt: null, + }; +}; + +export const calculateDotProgress = ( + dotState: DotState, + elapsed: number +): DotProgressResult => { + const { visible, appearAt, disappearAt } = dotState; + + const disappearingProgress = calculateDisappearingProgress( + elapsed, + disappearAt!, + visible + ); + if (disappearingProgress) return disappearingProgress; + + if (visible) return createVisibleProgress(); + + return calculateAppearingProgress(elapsed, appearAt); +}; + +const scheduleDotsForRemoval = ( + state: AnimationState, + visibleIndices: number[], + elapsed: number +): void => { + state.nextRemovalAt ??= elapsed; + + while (state.nextRemovalAt <= elapsed && visibleIndices.length > 0) { + const randomIndex = Math.floor(Math.random() * visibleIndices.length); + const dotIndex = visibleIndices.splice(randomIndex, 1)[0]; + const dot = dotIndex !== undefined ? state.dots[dotIndex] : undefined; + + if (dot) { + dot.disappearAt = state.nextRemovalAt; + dot.appearAt = state.nextDelay; + } + + state.nextDelay += DELAY_PER_DOT; + state.nextRemovalAt += DELAY_PER_DOT; + } +}; + +const resetRemovalSchedule = (state: AnimationState): void => { + state.nextRemovalAt = null; +}; + +export const processRemovals = ( + state: AnimationState, + visibleIndices: number[], + visibleCount: number, + elapsed: number +): void => { + const shouldScheduleRemovals = + visibleCount >= VISIBLE_THRESHOLD && visibleIndices.length > 0; + const shouldResetSchedule = visibleCount < VISIBLE_THRESHOLD; + + if (shouldScheduleRemovals) { + scheduleDotsForRemoval(state, visibleIndices, elapsed); + return; + } + + if (shouldResetSchedule) { + resetRemovalSchedule(state); + } +}; + +export const createInitialState = (): AnimationState => { + const indices = shuffleArray( + Array.from({ length: dots.length }, (_, index) => index) + ); + + return { + dots: (dots as RawDotData[]).map((rawDot, index) => ({ + dot: mapRawDotToDot(rawDot), + visible: false, + appearAt: (indices[index] ?? index) * DELAY_PER_DOT, + disappearAt: null, + })), + nextDelay: dots.length * DELAY_PER_DOT, + nextRemovalAt: null, + }; +}; diff --git a/src/website/hooks/BR/types.ts b/src/website/hooks/BR/types.ts new file mode 100644 index 0000000..686e93b --- /dev/null +++ b/src/website/hooks/BR/types.ts @@ -0,0 +1,39 @@ +export type Dot = { + centerX: number; + centerY: number; + radius: number; +}; + +export type DotState = { + dot: Dot; + visible: boolean; + appearAt: number; + disappearAt: number | null; +}; + +export type AnimationState = { + dots: DotState[]; + nextDelay: number; + nextRemovalAt: number | null; +}; + +export type AnimationRefs = { + animationFrameId: number; + lastFrameTime: number; + elapsedBeforePause: number; + pauseTime: number | null; + startTime: number | null; + resizeObserver: ResizeObserver | null; +}; + +export type RawDotData = { + cx: number; + cy: number; + r: number; +}; + +export type DotProgressResult = { + progress: number; + visible: boolean; + disappearAt: number | null; +}; diff --git a/src/website/hooks/BR/useBR.tsx b/src/website/hooks/BR/useBR.tsx new file mode 100644 index 0000000..a3f79e6 --- /dev/null +++ b/src/website/hooks/BR/useBR.tsx @@ -0,0 +1,54 @@ +import { useRef } from 'react'; +import { + createElapsedTimeGetter, + handleVisibilityOff, + handleVisibilityOn, +} from '@site/src/website/hooks/BR/animation'; +import { updateCanvasSize } from '@site/src/website/hooks/BR/canvas'; +import { createInitialState } from '@site/src/website/hooks/BR/helpers'; +import { + AnimationRefs, + AnimationState, +} from '@site/src/website/hooks/BR/types'; +import { cleanupAnimation } from '@site/src/website/hooks/shared/animation'; +import { useVisibility } from '@site/src/website/hooks/useVisibility'; + +export const useBR = () => { + const canvasRef = useRef(null); + const stateRef = useRef(null); + const animationRef = useRef({ + animationFrameId: 0, + lastFrameTime: 0, + elapsedBeforePause: 0, + pauseTime: null, + startTime: null, + resizeObserver: null, + }); + + useVisibility( + canvasRef, + ({ isFullyVisible }, canvas) => { + const animation = animationRef.current; + + stateRef.current ??= createInitialState(); + const state = stateRef.current; + + const getElapsed = createElapsedTimeGetter(animation); + const handleResize = () => updateCanvasSize(canvas, state, getElapsed); + + const visibilityHandlers: Record void> = { + visible: () => + handleVisibilityOn(canvas, animation, state, handleResize), + hidden: () => handleVisibilityOff(animation), + }; + + const visibilityState = isFullyVisible ? 'visible' : 'hidden'; + visibilityHandlers[visibilityState]?.(); + }, + { + onReset: () => cleanupAnimation(animationRef.current), + } + ); + + return { canvasRef }; +}; diff --git a/src/website/hooks/Background/animation.ts b/src/website/hooks/Background/animation.ts new file mode 100644 index 0000000..7be71ae --- /dev/null +++ b/src/website/hooks/Background/animation.ts @@ -0,0 +1,113 @@ +import type { + AnimationRefs, + AnimationState, +} from '@site/src/website/hooks/Background/types'; +import { + isStarOutOfBounds, + recycleStar, +} from '@site/src/website/hooks/Background/stars'; +import { stopAnimationFrame } from '@site/src/website/hooks/shared/animation'; + +const updateVelocity = (state: AnimationState): void => { + const { velocity, config } = state; + const { friction, responsiveness } = config; + + velocity.targetX *= friction; + velocity.targetY *= friction; + + velocity.x += (velocity.targetX - velocity.x) * responsiveness; + velocity.y += (velocity.targetY - velocity.y) * responsiveness; +}; + +const updateStars = (state: AnimationState): void => { + const { stars, velocity, dimensions, config } = state; + const { width, height } = dimensions; + const { overflowThreshold } = config; + + const centerX = width / 2; + const centerY = height / 2; + + for (const star of stars) { + star.x += velocity.x * star.z; + star.y += velocity.y * star.z; + + star.x += (star.x - centerX) * velocity.zoom * star.z; + star.y += (star.y - centerY) * velocity.zoom * star.z; + star.z += velocity.zoom; + + if (isStarOutOfBounds(star, width, height, overflowThreshold)) + recycleStar(star, state); + } +}; + +const renderStars = ( + context: CanvasRenderingContext2D, + state: AnimationState +): void => { + const { stars, velocity, dimensions, config } = state; + const { scale } = dimensions; + const { starSize, starColor } = config; + + context.lineCap = 'round'; + context.strokeStyle = starColor; + + for (const star of stars) { + context.beginPath(); + + context.lineWidth = starSize * star.z * scale; + context.globalAlpha = 0.5 + 0.5 * Math.random(); + + context.moveTo(star.x, star.y); + + let tailX = velocity.x * 2; + let tailY = velocity.y * 2; + + if (Math.abs(tailX) < 0.1) tailX = 0.5; + if (Math.abs(tailY) < 0.1) tailY = 0.5; + + context.lineTo(star.x + tailX, star.y + tailY); + context.stroke(); + } +}; + +const clearCanvas = ( + context: CanvasRenderingContext2D, + width: number, + height: number +): void => { + context.clearRect(0, 0, width, height); +}; + +const createAnimationLoop = ( + canvas: HTMLCanvasElement, + state: AnimationState, + refs: AnimationRefs +) => { + const animate = (): void => { + const context = canvas.getContext('2d'); + if (!context) return; + + const { width, height } = state.dimensions; + + clearCanvas(context, width, height); + updateVelocity(state); + updateStars(state); + renderStars(context, state); + + refs.animationFrameId = requestAnimationFrame(animate); + }; + + return animate; +}; + +export const startAnimation = ( + canvas: HTMLCanvasElement, + state: AnimationState, + refs: AnimationRefs +): void => { + stopAnimationFrame(refs); + + const animate = createAnimationLoop(canvas, state, refs); + + refs.animationFrameId = requestAnimationFrame(animate); +}; diff --git a/src/website/hooks/Background/definitions.ts b/src/website/hooks/Background/definitions.ts new file mode 100644 index 0000000..f3e8197 --- /dev/null +++ b/src/website/hooks/Background/definitions.ts @@ -0,0 +1,16 @@ +import type { BackgroundConfig } from '@site/src/website/hooks/Background/types'; + +export const DEFAULT_CONFIG: BackgroundConfig = { + starColor: '#ffffff', + starSize: 3, + starMinScale: 0.2, + starCount: 0, + overflowThreshold: 50, + intensity: 0.15, + zoomSpeed: 0.0005, + friction: 0.96, + responsiveness: 0.8, +}; + +export const calculateStarCount = (width: number, height: number): number => + Math.floor((width + height) / 8); diff --git a/src/website/hooks/Background/stars.ts b/src/website/hooks/Background/stars.ts new file mode 100644 index 0000000..81bcb67 --- /dev/null +++ b/src/website/hooks/Background/stars.ts @@ -0,0 +1,91 @@ +import type { + AnimationState, + RecycleDirection, + Star, +} from '@site/src/website/hooks/Background/types'; + +export const createStar = (minScale: number): Star => ({ + x: 0, + y: 0, + z: minScale + Math.random() * (1 - minScale), +}); + +export const createStars = (count: number, minScale: number): Star[] => + Array.from({ length: count }, () => createStar(minScale)); + +export const placeStar = (star: Star, width: number, height: number): void => { + star.x = Math.random() * width; + star.y = Math.random() * height; +}; + +export const placeAllStars = ( + stars: Star[], + width: number, + height: number +): void => { + for (const star of stars) placeStar(star, width, height); +}; + +const determineRecycleDirection = ( + velocityX: number, + velocityY: number +): RecycleDirection => { + const absVelocityX = Math.abs(velocityX); + const absVelocityY = Math.abs(velocityY); + + const hasSignificantVelocity = absVelocityX > 1 || absVelocityY > 1; + if (!hasSignificantVelocity) return 'center'; + + const isHorizontalDominant = + absVelocityX > absVelocityY + ? Math.random() < absVelocityX / (absVelocityX + absVelocityY) + : Math.random() >= absVelocityY / (absVelocityX + absVelocityY); + + if (isHorizontalDominant) return velocityX > 0 ? 'left' : 'right'; + return velocityY > 0 ? 'top' : 'bottom'; +}; + +export const recycleStar = (star: Star, state: AnimationState): void => { + const { velocity, dimensions, config } = state; + const { width, height } = dimensions; + const { overflowThreshold, starMinScale } = config; + + const direction = determineRecycleDirection(velocity.x, velocity.y); + + star.z = starMinScale + Math.random() * (1 - starMinScale); + + switch (direction) { + case 'center': + star.z = 0.1; + star.x = Math.random() * width; + star.y = Math.random() * height; + break; + case 'left': + star.x = -overflowThreshold; + star.y = Math.random() * height; + break; + case 'right': + star.x = width + overflowThreshold; + star.y = Math.random() * height; + break; + case 'top': + star.x = Math.random() * width; + star.y = -overflowThreshold; + break; + case 'bottom': + star.x = Math.random() * width; + star.y = height + overflowThreshold; + break; + } +}; + +export const isStarOutOfBounds = ( + star: Star, + width: number, + height: number, + threshold: number +): boolean => + star.x < -threshold || + star.x > width + threshold || + star.y < -threshold || + star.y > height + threshold; diff --git a/src/website/hooks/Background/types.ts b/src/website/hooks/Background/types.ts new file mode 100644 index 0000000..f0620e6 --- /dev/null +++ b/src/website/hooks/Background/types.ts @@ -0,0 +1,54 @@ +export type Star = { + x: number; + y: number; + z: number; +}; + +export type RecycleDirection = 'center' | 'left' | 'right' | 'top' | 'bottom'; + +export type Velocity = { + x: number; + y: number; + targetX: number; + targetY: number; + zoom: number; +}; + +export type Pointer = { + x: number | null; + y: number | null; + isTouch: boolean; +}; + +export type CanvasDimensions = { + width: number; + height: number; + scale: number; +}; + +export type BackgroundConfig = { + starColor: string; + starSize: number; + starMinScale: number; + starCount: number; + overflowThreshold: number; + intensity: number; + zoomSpeed: number; + friction: number; + responsiveness: number; +}; + +export type AnimationState = { + stars: Star[]; + velocity: Velocity; + pointer: Pointer; + dimensions: CanvasDimensions; + config: BackgroundConfig; +}; + +export type AnimationRefs = { + animationFrameId: number; + resizeObserver: ResizeObserver | null; +}; + +export type UseBackgroundOptions = Partial; diff --git a/src/website/hooks/Background/useBackground.tsx b/src/website/hooks/Background/useBackground.tsx new file mode 100644 index 0000000..4d74c34 --- /dev/null +++ b/src/website/hooks/Background/useBackground.tsx @@ -0,0 +1,123 @@ +import type { + AnimationRefs, + AnimationState, + Pointer, + UseBackgroundOptions, +} from '@site/src/website/hooks/Background/types'; +import { useCallback, useEffect, useRef } from 'react'; +import { startAnimation } from '@site/src/website/hooks/Background/animation'; +import { + calculateStarCount, + DEFAULT_CONFIG, +} from '@site/src/website/hooks/Background/definitions'; +import { + createStars, + placeAllStars, +} from '@site/src/website/hooks/Background/stars'; +import { cleanupAnimation } from '@site/src/website/hooks/shared/animation'; + +const createInitialState = (options: UseBackgroundOptions): AnimationState => { + const config = { ...DEFAULT_CONFIG, ...options }; + + return { + stars: [], + velocity: { x: 0, y: 0, targetX: 0, targetY: 0, zoom: config.zoomSpeed }, + pointer: { x: null, y: null, isTouch: false }, + dimensions: { width: 0, height: 0, scale: 1 }, + config, + }; +}; + +const updatePointerVelocity = ( + state: AnimationState, + clientX: number, + clientY: number +): void => { + const { pointer, velocity, dimensions, config } = state; + const { intensity } = config; + + if (pointer.x !== null && pointer.y !== null) { + const deltaX = clientX - pointer.x; + const deltaY = clientY - pointer.y; + + velocity.targetX += deltaX * intensity * dimensions.scale; + velocity.targetY += deltaY * intensity * dimensions.scale; + } + + pointer.x = clientX; + pointer.y = clientY; +}; + +const resetPointer = (pointer: Pointer): void => { + pointer.x = null; + pointer.y = null; +}; + +export const useBackground = ( + options: UseBackgroundOptions = Object.create(null) +) => { + const canvasRef = useRef(null); + const stateRef = useRef(createInitialState(options)); + const refsRef = useRef({ + animationFrameId: 0, + resizeObserver: null, + }); + + const handleResize = useCallback(() => { + const canvas = canvasRef.current; + if (!canvas) return; + + const state = stateRef.current; + const scale = window.devicePixelRatio || 1; + const width = canvas.offsetWidth * scale; + const height = canvas.offsetHeight * scale; + + canvas.width = width; + canvas.height = height; + + state.dimensions = { width, height, scale }; + + if (state.stars.length === 0) { + const count = state.config.starCount || calculateStarCount(width, height); + state.stars = createStars(count, state.config.starMinScale); + } + + placeAllStars(state.stars, width, height); + }, []); + + const handleMouseMove = useCallback((event: MouseEvent) => { + const state = stateRef.current; + state.pointer.isTouch = false; + updatePointerVelocity(state, event.clientX, event.clientY); + }, []); + + const handlePointerLeave = useCallback(() => { + resetPointer(stateRef.current.pointer); + }, []); + + useEffect(() => { + const canvas = canvasRef.current; + if (!canvas) return; + + const state = stateRef.current; + const refs = refsRef.current; + + handleResize(); + + refs.resizeObserver = new ResizeObserver(handleResize); + refs.resizeObserver.observe(canvas); + + document.addEventListener('mousemove', handleMouseMove); + document.addEventListener('mouseleave', handlePointerLeave); + + startAnimation(canvas, state, refs); + + return () => { + cleanupAnimation(refs); + document.removeEventListener('mousemove', handleMouseMove); + document.removeEventListener('mouseleave', handlePointerLeave); + }; + }, [handleResize, handleMouseMove, handlePointerLeave]); + + return { canvasRef }; +}; diff --git a/src/website/hooks/shared/animation.ts b/src/website/hooks/shared/animation.ts index cd3ae1d..92f826a 100644 --- a/src/website/hooks/shared/animation.ts +++ b/src/website/hooks/shared/animation.ts @@ -1,13 +1,12 @@ +import type { AnimationRefs } from '../Background/types'; + export const stopAnimationFrame = (refs: { animationFrameId: number; }): void => { cancelAnimationFrame(refs.animationFrameId); }; -export const cleanupAnimation = (refs: { - animationFrameId: number; - resizeObserver: ResizeObserver | null; -}): void => { +export const cleanupAnimation = (refs: AnimationRefs): void => { stopAnimationFrame(refs); refs.resizeObserver?.disconnect(); refs.resizeObserver = null; diff --git a/src/website/hooks/useScrollSpy.tsx b/src/website/hooks/useScrollSpy.tsx index 8d93852..b9b516f 100644 --- a/src/website/hooks/useScrollSpy.tsx +++ b/src/website/hooks/useScrollSpy.tsx @@ -9,14 +9,11 @@ type Options = { rootMargin?: string; }; -const DEFAULT_THRESHOLD: number | number[] = [0.1, 0.5]; -const DEFAULT_ROOT_MARGIN = '-120px 0px 0px 0px'; - export const useScrollSpy = ( sections: T, options?: Options ): string | null => { - const { threshold = DEFAULT_THRESHOLD, rootMargin = DEFAULT_ROOT_MARGIN } = + const { threshold = [0.1, 0.5], rootMargin = '-120px 0px 0px 0px' } = options ?? Object.create(null); const [activeId, setActiveId] = useState(null); diff --git a/src/website/scss/global/_animations.scss b/src/website/scss/global/_animations.scss index 59f9411..20843c0 100644 --- a/src/website/scss/global/_animations.scss +++ b/src/website/scss/global/_animations.scss @@ -10,12 +10,14 @@ @keyframes fadeUp { 0% { - transform: translateY(4rem); + position: relative; + top: 4rem; opacity: 0; } 100% { - transform: translateY(0); + position: relative; + top: 0; opacity: 1; } } @@ -61,24 +63,31 @@ } } -@keyframes breathe { +@keyframes morph { 0%, 100% { - rotate: 0deg; + border-radius: 50% 53% 52% 51% / 51% 53% 50% 52%; } - 50% { - rotate: 10deg; + 20% { + border-radius: 52% 50% 51% 53% / 53% 50% 52% 51%; + } + 40% { + border-radius: 51% 52% 53% 50% / 50% 52% 51% 53%; + } + 60% { + border-radius: 53% 51% 50% 52% / 52% 51% 53% 50%; + } + 80% { + border-radius: 50% 53% 52% 51% / 53% 50% 51% 52%; } } -@keyframes br-cycle { +@keyframes breathe { 0%, 100% { - opacity: 0; + rotate: 0deg; } - - 15%, - 25% { - opacity: 1; + 50% { + rotate: 10deg; } } diff --git a/src/website/scss/global/_root.scss b/src/website/scss/global/_root.scss index f133d3d..2a35fb3 100644 --- a/src/website/scss/global/_root.scss +++ b/src/website/scss/global/_root.scss @@ -33,6 +33,14 @@ body { @include load-css('../pages/partial/footer'); } + canvas.bg { + position: fixed; + inset: 0; + width: 100%; + height: 100%; + z-index: -5; + } + .page-content { margin-top: 12.5rem; margin-bottom: 5rem; diff --git a/src/website/scss/pages/_gallery.scss b/src/website/scss/pages/_gallery.scss index 3a63b59..bd6420a 100644 --- a/src/website/scss/pages/_gallery.scss +++ b/src/website/scss/pages/_gallery.scss @@ -71,7 +71,9 @@ width: 3rem; height: 3rem; stroke: var(--ifm-color-primary-darker); - transition: transform 0.4s var(--ease-bounce-strong); + transition: + transform 0.4s var(--ease-bounce-strong), + stroke 0.3s ease; } } diff --git a/src/website/scss/pages/_waitlist.scss b/src/website/scss/pages/_waitlist.scss index 2911c07..51d7ac2 100644 --- a/src/website/scss/pages/_waitlist.scss +++ b/src/website/scss/pages/_waitlist.scss @@ -17,9 +17,12 @@ width: 8rem; height: 8rem; overflow: hidden; - will-change: transform; - animation: breathe 25s var(--ease-back-out-soft) alternate infinite; - transition: transform 0.4s ease; + animation: + morph 12.5s var(--ease-bounce-strong) alternate infinite, + breathe 25s var(--ease-back-out-soft) alternate infinite; + transition: + border-radius 0.4s ease, + rotate 0.4s ease; svg { display: block; From 7e0977ef737741cb43ac0448eac81986e78d1329 Mon Sep 17 00:00:00 2001 From: Lucas Santos Date: Sun, 10 May 2026 20:08:09 -0300 Subject: [PATCH 4/6] Revert "fix: fix CPU issue in dot animations (#42)" This reverts commit ac6ba1db37ffd671a9199c0a9c143a4f3105e3e7. --- src/website/hooks/BR/canvas.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/website/hooks/BR/canvas.ts b/src/website/hooks/BR/canvas.ts index e4d7ff0..fec8c66 100644 --- a/src/website/hooks/BR/canvas.ts +++ b/src/website/hooks/BR/canvas.ts @@ -16,9 +16,12 @@ const drawSquare = ( const size = dot.radius * 2 * scale; const x = dot.centerX * scale - size / 2; const y = dot.centerY * scale - size / 2; + const borderRadius = size * 0.2; context.fillStyle = color; - context.fillRect(x, y, size, size); + context.beginPath(); + context.roundRect(x, y, size, size, borderRadius); + context.fill(); }; export const draw = ( @@ -48,13 +51,13 @@ export const draw = ( if (result.progress > 0) { visibleCount++; - drawSquare(context, dotState.dot, result.progress, scale); - const isStableVisible = result.visible && result.disappearAt === null; if (isStableVisible) { visibleIndices.push(dotIndex); } } + + drawSquare(context, dotState.dot, result.progress, scale); } processRemovals(state, visibleIndices, visibleCount, elapsed); @@ -68,8 +71,9 @@ export const updateCanvasSize = ( const rect = canvas.getBoundingClientRect(); if (rect.width === 0 || rect.height === 0) return; - canvas.width = rect.width; - canvas.height = rect.height; + const devicePixelRatio = window.devicePixelRatio || 1; + canvas.width = rect.width * devicePixelRatio; + canvas.height = rect.height * devicePixelRatio; const context = canvas.getContext('2d'); if (context) { From 0ad0508c14f637d0a38e33d849f2b9640f103b8a Mon Sep 17 00:00:00 2001 From: Lucas Santos Date: Sun, 10 May 2026 20:39:34 -0300 Subject: [PATCH 5/6] ci: don't deploy worker for now --- .github/workflows/cd_deploy.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/cd_deploy.yml b/.github/workflows/cd_deploy.yml index 1a2824b..1d2cea1 100644 --- a/.github/workflows/cd_deploy.yml +++ b/.github/workflows/cd_deploy.yml @@ -56,14 +56,14 @@ jobs: WORKER_D1: ${{ secrets.WORKER_D1 }} CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} - - name: Deploy — Worker - uses: peaceiris/actions-gh-pages@v4 - with: - github_token: ${{ secrets.PAT }} - publish_dir: ./server - publish_branch: 'server' - allow_empty_commit: false - enable_jekyll: true + # - name: Deploy — Worker + # uses: peaceiris/actions-gh-pages@v4 + # with: + # github_token: ${{ secrets.PAT }} + # publish_dir: ./server + # publish_branch: 'server' + # allow_empty_commit: false + # enable_jekyll: true - name: Deploy — Website uses: peaceiris/actions-gh-pages@v4 From 83de55543b6355a794c78b35cffc27ee3cd22075 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 10 May 2026 23:41:01 +0000 Subject: [PATCH 6/6] chore(deps-dev): bump @babel/plugin-transform-modules-systemjs Bumps [@babel/plugin-transform-modules-systemjs](https://github.com/babel/babel/tree/HEAD/packages/babel-plugin-transform-modules-systemjs) from 7.29.0 to 7.29.4. - [Release notes](https://github.com/babel/babel/releases) - [Changelog](https://github.com/babel/babel/blob/main/CHANGELOG.md) - [Commits](https://github.com/babel/babel/commits/v7.29.4/packages/babel-plugin-transform-modules-systemjs) --- updated-dependencies: - dependency-name: "@babel/plugin-transform-modules-systemjs" dependency-version: 7.29.4 dependency-type: indirect ... Signed-off-by: dependabot[bot] --- package-lock.json | 199 ++++++++++++++++------------------------------ 1 file changed, 67 insertions(+), 132 deletions(-) diff --git a/package-lock.json b/package-lock.json index 5dbf850..62cac20 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1339,9 +1339,9 @@ } }, "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.0.tgz", - "integrity": "sha512-PrujnVFbOdUpw4UHiVwKvKRLMMic8+eC0CuNlxjsyZUiBjhFdPsewdXCkveh2KqBA9/waD0W1b4hXSOBQJezpQ==", + "version": "7.29.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.4.tgz", + "integrity": "sha512-N7QmZ0xRZfjHOfZeQLJjwgX2zS9pdGHSVl/cjSGlo4dXMqvurfxXDMKY4RqEKzPozV78VMcd0lxyG13mlbKc4w==", "dev": true, "license": "MIT", "dependencies": { @@ -5096,9 +5096,6 @@ "arm" ], "dev": true, - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -5116,9 +5113,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -5136,9 +5130,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -5156,9 +5147,6 @@ "riscv64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -5176,9 +5164,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -5196,9 +5181,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -5216,9 +5198,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -5236,9 +5215,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "LGPL-3.0-or-later", "optional": true, "os": [ @@ -5256,9 +5232,6 @@ "arm" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -5282,9 +5255,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -5308,9 +5278,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -5334,9 +5301,6 @@ "riscv64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -5360,9 +5324,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -5386,9 +5347,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -5412,9 +5370,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -5438,9 +5393,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "Apache-2.0", "optional": true, "os": [ @@ -6301,9 +6253,6 @@ "arm" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -6325,9 +6274,6 @@ "arm" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -6349,9 +6295,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -6373,9 +6316,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -6397,9 +6337,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -6421,9 +6358,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -7028,9 +6962,6 @@ "arm" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -7045,9 +6976,6 @@ "arm" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -7062,9 +6990,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -7079,9 +7004,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -7096,9 +7018,6 @@ "loong64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -7113,9 +7032,6 @@ "loong64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -7130,9 +7046,6 @@ "ppc64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -7147,9 +7060,6 @@ "ppc64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -7164,9 +7074,6 @@ "riscv64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -7181,9 +7088,6 @@ "riscv64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -7198,9 +7102,6 @@ "s390x" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -7215,9 +7116,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -7232,9 +7130,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -7815,9 +7710,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -7835,9 +7727,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -7855,9 +7744,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MIT", "optional": true, "os": [ @@ -7875,9 +7761,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MIT", "optional": true, "os": [ @@ -7917,6 +7800,70 @@ "node": ">=14.0.0" } }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.8.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.8.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { + "version": "2.8.1", + "dev": true, + "inBundle": true, + "license": "0BSD", + "optional": true + }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.2.tgz", @@ -14107,9 +14054,6 @@ "arm64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -14131,9 +14075,6 @@ "arm64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -14155,9 +14096,6 @@ "x64" ], "dev": true, - "libc": [ - "glibc" - ], "license": "MPL-2.0", "optional": true, "os": [ @@ -14179,9 +14117,6 @@ "x64" ], "dev": true, - "libc": [ - "musl" - ], "license": "MPL-2.0", "optional": true, "os": [