diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..ce62956 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,7 @@ +FROM nginx:alpine +COPY index.html /usr/share/nginx/html/index.html +RUN apk add --no-cache curl && \ + ln -sf /dev/stdout /usr/share/nginx/html/health +EXPOSE 80 +HEALTHCHECK --interval=10s --timeout=3s --retries=3 CMD curl -sf /health || exit 1 +CMD ["nginx", "-g", "daemon off;"] diff --git a/MEMORY.md b/MEMORY.md index 58ea22b..42a8a05 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -109,3 +109,15 @@ Stack Swarm `dev` com ambiente completo de desenvolvimento: - Stack: Vite + React 18 + TS + @react-three/fiber + drei + framer-motion - npm install + build OK - Dev: `cd pulse-3d-landing && npm run dev` + +## πŸ“¦ @pulse-libs/ui β€” Design System Compartilhado (2026-05-20) +- **Repo**: https://git.octal.tec.br/Roberto/pulse-libs +- **30 arquivos TS** β€” Atoms(10) Β· Molecules(3) Β· Organisms(4) Β· Templates(3) Β· Lib(1) + indices +- Atoms 2D: Button, Badge, Card, GradientText, Divider, ThemeToggle +- Atoms 3D stubs: FloatingMesh3d, ParticleField3d, LightGlow3d, FloatingText3d (deprecated) +- Molecules: FeatureCard, Navbar, Footer +- Organisms: HeroSection, FeaturesGrid, CtaBlock, StatsGrid +- Templates: MainLayout, MinimalLayout, PageWithSidebar +- TOKENS export: color / space / radius constants em TypeScript +- Uso: projetos importam do path `../libs/pulse-libs/src/` ou como submodule +- Ligado aos projetos: pulse-3d-landing, test-octal (landing page) diff --git a/pulse-docs b/pulse-docs index 8208a67..e1924ad 160000 --- a/pulse-docs +++ b/pulse-docs @@ -1 +1 @@ -Subproject commit 8208a6783d6e2ffb57c1b3f85af7930971ab87f6 +Subproject commit e1924ad4f208a47055b98d564e848f9d790a0d68 diff --git a/pulse-libs b/pulse-libs new file mode 160000 index 0000000..29a7a5a --- /dev/null +++ b/pulse-libs @@ -0,0 +1 @@ +Subproject commit 29a7a5adb9f3939371b8d7f8e3dee1d2edd92fd1 diff --git a/pulse-memory b/pulse-memory index de88a83..73c50dc 160000 --- a/pulse-memory +++ b/pulse-memory @@ -1 +1 @@ -Subproject commit de88a83ca379d1b13cb645d7df09de3337966429 +Subproject commit 73c50dccd55518c7f7814faa6b9b8a438085eeb7 diff --git a/scripts/build-lib.py b/scripts/build-lib.py new file mode 100644 index 0000000..3ef94e9 --- /dev/null +++ b/scripts/build-lib.py @@ -0,0 +1,182 @@ +import pathlib +lib = pathlib.Path("/root/.openclaw/workspace/pulse-libs/src") + +mol = { + "FeatureCard.ts": """\ +import { Card } from '../atoms' +interface FeatureCardProps { title:string, description:string, icon?:string, delay?:number, variant?:'default'|'accent', style?:React.CSSProperties } +export function FeatureCard({title,description,icon,delay=0,variant='default',style}:FeatureCardProps){ + const bg = variant==='accent'?'linear-gradient(135deg,rgba(37,99,235,.06),rgba(124,58,237,.04))':'transparent' + return ( + + {variant==='accent' &&
} + {icon &&
{icon}
} +

{title}

+

{description}

+
+ {variant==='accent' && core} +
+ + ) +} +""", + "Navbar.ts": """\ +import { GradientText, Button } from '../atoms' +interface NavProps { logo:string, links:{label:string,href:string}[], ctaLabel?:string, ctaHref?:string } +export function Navbar({logo,links,ctaLabel,ctaHref='#'}:NavProps){ + return ( + + ) +} +""", + "Footer.ts": """\ +interface FooterProps { brand?:string, year?:number, links:{label:string,href:string}[] } +export function Footer({brand='Pulse 3D',year=__DATE__,links=[]}:FooterProps){ + return ( + + ) +} +""", + "index.ts": """\ +export { FeatureCard } from './FeatureCard' +export { Navbar } from './Navbar' +export { Footer } from './Footer' +""", +} + +for name, code in mol.items(): + (lib / "molecules" / name).write_text(code) + +print("βœ… Molecules: FeatureCard, Navbar, Footer + index") + +# ── ORGANISMS ────────────────────────────────────────────────────── +org = { + "HeroSection.ts": """\ +import { Card, Badge, GradientText, Button } from '../atoms' +import type { JSX } from 'react' +interface HeroProps { badge?:string, title:string, description:string, cta:{label:string,onClick():void}[], showScrollHint?:boolean, style?:React.CSSProperties } +export function HeroSection({badge,title,description,cta=[],showScrollHint=true,style}:HeroProps){ + return ( +
+ {badge && {badge}} +

+ {title} +

+

{description}

+
+ {cta.map((b,i)=>)} +
+ {showScrollHint &&
scroll para explorar
↓
} +
+ ) +} +""", + "FeaturesGrid.ts": """\ +import { Card } from '../atoms' +interface Feature { icon:string, title:string, description:string } +interface FeaturesProps { title?:string, features:Feature[], style?:React.CSSProperties } +export function FeaturesGrid({title,features,style}:FeaturesProps){ + return ( +
+ {title &&

{title}

} +

Componentes que compΓ΅em o sistema β€” do Γ‘tomo ao organismo.

+
+ {features.map((f,i)=>
{f.icon}

{f.title}

{f.description}

) } +
+
+ ) +} +""", + "CtaBlock.ts": """\ +import { Button, GradientText } from '../atoms' +interface CtaProps { title:string, description:string, primary:{label:string,onClick():void}, secondary?:{label:string,onClick():void}, dark?:boolean } +export function CtaBlock({title,description,primary,secondary,dark=false}:CtaProps){ + const bg = dark ? 'rgba(5,5,16,.96)' : 'rgba(15,17,23,.5)' + return ( +
+

{title}

+

{description}

+
+ + {secondary && } +
+

{'\\u2699'} @pulse-libs/ui β€” MIT β€” {new Date().getFullYear()}

+
+ ) +} +""", + "StatsGrid.ts": """\ +interface Stat { label:string, value:string|number, color?:string } +export function StatsGrid({stats}:{stats:Stat[]}){ + return ( +
+ {stats.map((s,i)=>
+
{s.value}
+
{s.label}
+
)} +
+ ) +} +""", + "index.ts": """\ +export { HeroSection } from './HeroSection' +export { FeaturesGrid } from './FeaturesGrid' +export { CtaBlock } from './CtaBlock' +export { StatsGrid } from './StatsGrid' +""", +} + +for name, code in org.items(): + if name != "index.ts": + (lib / "organisms" / name).write_text(code) + else: + (lib / "organisms" / name).write_text(code) + +print("βœ… Organisms: HeroSection, FeaturesGrid, CtaBlock, StatsGrid + index") + +# ── TEMPLATES ────────────────────────────────────────────────────── +templates = { + "MainLayout.ts": """\ +import { ReactNode } from 'react' +import { Navbar, Footer, Divider } from './..' +interface LayoutProps { children:ReactNode, nav:{logo:string,links:{label:string,href:string}[],cta?:{label:string,href:string}}, footer?:{brand:string,links:{label:string,href:string}[]} } +export function MainLayout({children,nav,footer}:LayoutProps){ + return ( +
+ +
{children}
+ {footer &&
} +
+ ) +} +""", + "MinimalLayout.ts": """\ +interface MinimalProps { children:React.ReactNode, centered?:boolean } +export function MinimalLayout({children,centered=true}:MinimalProps){ + return
{children}
+} +""", + "index.ts": """\ +export { MainLayout } from './MainLayout' +export { MinimalLayout } from './MinimalLayout' +""", +} + +for name, code in templates.items(): + (lib / "templates" / name).write_text(code) + +print("βœ… Templates: MainLayout, MinimalLayout + index") +PYEOF \ No newline at end of file