create-fluxstack 1.13.0 → 1.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/LLMD/patterns/anti-patterns.md +100 -0
  2. package/LLMD/reference/routing.md +39 -39
  3. package/LLMD/resources/live-auth.md +20 -2
  4. package/LLMD/resources/live-components.md +94 -10
  5. package/LLMD/resources/live-logging.md +95 -33
  6. package/LLMD/resources/live-upload.md +59 -8
  7. package/app/client/index.html +2 -2
  8. package/app/client/public/favicon.svg +46 -0
  9. package/app/client/src/App.tsx +2 -1
  10. package/app/client/src/assets/fluxstack-static.svg +46 -0
  11. package/app/client/src/assets/fluxstack.svg +183 -0
  12. package/app/client/src/components/AppLayout.tsx +138 -9
  13. package/app/client/src/components/BackButton.tsx +13 -13
  14. package/app/client/src/components/DemoPage.tsx +4 -4
  15. package/app/client/src/live/AuthDemo.tsx +23 -21
  16. package/app/client/src/live/ChatDemo.tsx +2 -2
  17. package/app/client/src/live/CounterDemo.tsx +12 -12
  18. package/app/client/src/live/FormDemo.tsx +2 -2
  19. package/app/client/src/live/LiveDebuggerPanel.tsx +779 -0
  20. package/app/client/src/live/RoomChatDemo.tsx +24 -16
  21. package/app/client/src/main.tsx +13 -13
  22. package/app/client/src/pages/ApiTestPage.tsx +6 -6
  23. package/app/client/src/pages/HomePage.tsx +80 -52
  24. package/app/server/live/LiveAdminPanel.ts +1 -0
  25. package/app/server/live/LiveChat.ts +78 -77
  26. package/app/server/live/LiveCounter.ts +1 -1
  27. package/app/server/live/LiveForm.ts +1 -0
  28. package/app/server/live/LiveLocalCounter.ts +38 -37
  29. package/app/server/live/LiveProtectedChat.ts +1 -0
  30. package/app/server/live/LiveRoomChat.ts +1 -0
  31. package/app/server/live/LiveUpload.ts +1 -0
  32. package/app/server/live/register-components.ts +19 -19
  33. package/config/system/runtime.config.ts +4 -0
  34. package/core/build/optimizer.ts +235 -235
  35. package/core/client/components/Live.tsx +17 -11
  36. package/core/client/components/LiveDebugger.tsx +1324 -0
  37. package/core/client/hooks/AdaptiveChunkSizer.ts +215 -215
  38. package/core/client/hooks/useLiveComponent.ts +11 -1
  39. package/core/client/hooks/useLiveDebugger.ts +392 -0
  40. package/core/client/index.ts +14 -0
  41. package/core/plugins/built-in/index.ts +134 -134
  42. package/core/plugins/built-in/live-components/commands/create-live-component.ts +4 -0
  43. package/core/plugins/built-in/vite/index.ts +75 -21
  44. package/core/server/index.ts +15 -15
  45. package/core/server/live/ComponentRegistry.ts +55 -26
  46. package/core/server/live/FileUploadManager.ts +188 -24
  47. package/core/server/live/LiveDebugger.ts +462 -0
  48. package/core/server/live/LiveLogger.ts +38 -5
  49. package/core/server/live/LiveRoomManager.ts +17 -1
  50. package/core/server/live/StateSignature.ts +87 -27
  51. package/core/server/live/WebSocketConnectionManager.ts +11 -10
  52. package/core/server/live/auto-generated-components.ts +1 -1
  53. package/core/server/live/websocket-plugin.ts +233 -8
  54. package/core/server/plugins/static-files-plugin.ts +179 -69
  55. package/core/types/build.ts +219 -219
  56. package/core/types/plugin.ts +107 -107
  57. package/core/types/types.ts +145 -9
  58. package/core/utils/logger/startup-banner.ts +82 -82
  59. package/core/utils/version.ts +6 -6
  60. package/package.json +1 -1
  61. package/app/client/src/assets/react.svg +0 -1
@@ -1,5 +1,8 @@
1
+ import { useState, useEffect } from 'react'
1
2
  import { Link, Outlet, useLocation } from 'react-router'
2
- import { FaBook, FaGithub } from 'react-icons/fa'
3
+ import { FaBook, FaGithub, FaBars, FaTimes } from 'react-icons/fa'
4
+ import FluxStackLogo from '@client/src/assets/fluxstack.svg'
5
+ import faviconSvg from '@client/src/assets/fluxstack-static.svg?raw'
3
6
 
4
7
  const navItems = [
5
8
  { to: '/', label: 'Home' },
@@ -12,17 +15,60 @@ const navItems = [
12
15
  { to: '/api-test', label: 'API Test' }
13
16
  ]
14
17
 
18
+ const routeFlameHue: Record<string, string> = {
19
+ '/': '0deg', // roxo original
20
+ '/counter': '180deg', // ciano
21
+ '/form': '300deg', // rosa
22
+ '/upload': '60deg', // amarelo
23
+ '/chat': '120deg', // verde
24
+ '/room-chat': '240deg', // azul
25
+ '/auth': '330deg', // vermelho
26
+ '/api-test': '90deg', // lima
27
+ }
28
+
15
29
  export function AppLayout() {
16
30
  const location = useLocation()
31
+ const [menuOpen, setMenuOpen] = useState(false)
32
+
33
+ useEffect(() => {
34
+ const current = navItems.find(item => item.to === location.pathname)
35
+ document.title = current ? `${current.label} - FluxStack` : 'FluxStack'
36
+
37
+ // Dynamic favicon with hue-rotate
38
+ const hue = routeFlameHue[location.pathname] || '0deg'
39
+ const colored = faviconSvg.replace(
40
+ '<svg ',
41
+ `<svg style="filter: hue-rotate(${hue})" `
42
+ )
43
+ const blob = new Blob([colored], { type: 'image/svg+xml' })
44
+ const url = URL.createObjectURL(blob)
45
+ let link = document.querySelector<HTMLLinkElement>('link[rel="icon"]')
46
+ if (!link) {
47
+ link = document.createElement('link')
48
+ link.rel = 'icon'
49
+ document.head.appendChild(link)
50
+ }
51
+ link.type = 'image/svg+xml'
52
+ link.href = url
53
+ return () => URL.revokeObjectURL(url)
54
+ }, [location.pathname])
17
55
 
18
56
  return (
19
57
  <div className="min-h-screen bg-gradient-to-br from-slate-900 via-purple-900 to-slate-900">
20
- <header className="sticky top-0 z-10 backdrop-blur-md bg-slate-900/60 border-b border-white/10">
21
- <div className="container mx-auto px-6 py-4 flex flex-wrap items-center justify-between gap-4">
22
- <div className="text-white font-semibold tracking-wide">
58
+ <header className="sticky top-0 z-50 backdrop-blur-md bg-slate-900/60 border-b border-white/10">
59
+ <div className="container mx-auto px-4 sm:px-6 py-3 sm:py-4 flex items-center justify-between gap-4">
60
+ <Link to="/" className="flex items-center gap-2 text-white font-semibold tracking-wide">
61
+ <img
62
+ src={FluxStackLogo}
63
+ alt="FluxStack"
64
+ className="w-9 h-9 transition-[filter] duration-500 drop-shadow-[0_0_8px_rgba(168,85,247,0.5)]"
65
+ style={{ filter: `hue-rotate(${routeFlameHue[location.pathname] || '0deg'})` }}
66
+ />
23
67
  FluxStack
24
- </div>
25
- <nav className="flex flex-wrap items-center gap-2">
68
+ </Link>
69
+
70
+ {/* Desktop nav */}
71
+ <nav className="hidden md:flex items-center gap-2">
26
72
  {navItems.map((item) => {
27
73
  const active = location.pathname === item.to
28
74
  return (
@@ -40,27 +86,110 @@ export function AppLayout() {
40
86
  )
41
87
  })}
42
88
  </nav>
89
+
43
90
  <div className="flex items-center gap-2">
91
+ <a
92
+ href="https://live-docs.marcosbrendon.com/"
93
+ target="_blank"
94
+ rel="noopener noreferrer"
95
+ className="hidden sm:inline-flex items-center gap-2 px-3 py-1.5 bg-purple-500/20 border border-purple-500/30 text-purple-200 rounded-lg text-sm hover:bg-purple-500/30 transition-all"
96
+ >
97
+ <FaBook />
98
+ Live Docs
99
+ </a>
44
100
  <a
45
101
  href="/swagger"
46
102
  target="_blank"
47
103
  rel="noopener noreferrer"
48
- className="inline-flex items-center gap-2 px-3 py-1.5 bg-white/10 border border-white/20 text-white rounded-lg text-sm hover:bg-white/20 transition-all"
104
+ className="hidden sm:inline-flex items-center gap-2 px-3 py-1.5 bg-white/10 border border-white/20 text-white rounded-lg text-sm hover:bg-white/20 transition-all"
49
105
  >
50
106
  <FaBook />
51
- Docs
107
+ API Docs
52
108
  </a>
53
109
  <a
54
110
  href="https://github.com/MarcosBrendonDePaula/FluxStack"
55
111
  target="_blank"
56
112
  rel="noopener noreferrer"
57
- className="inline-flex items-center gap-2 px-3 py-1.5 bg-white/10 border border-white/20 text-white rounded-lg text-sm hover:bg-white/20 transition-all"
113
+ className="hidden sm:inline-flex items-center gap-2 px-3 py-1.5 bg-white/10 border border-white/20 text-white rounded-lg text-sm hover:bg-white/20 transition-all"
58
114
  >
59
115
  <FaGithub />
60
116
  GitHub
61
117
  </a>
118
+
119
+ {/* Mobile menu toggle */}
120
+ <button
121
+ onClick={() => setMenuOpen(!menuOpen)}
122
+ className="md:hidden p-2 text-gray-300 hover:text-white transition-colors"
123
+ aria-label="Toggle menu"
124
+ >
125
+ {menuOpen ? <FaTimes size={20} /> : <FaBars size={20} />}
126
+ </button>
62
127
  </div>
63
128
  </div>
129
+
130
+ {/* Mobile nav */}
131
+ {menuOpen && (
132
+ <div className="md:hidden border-t border-white/10 bg-slate-900/90 backdrop-blur-md">
133
+ <nav className="container mx-auto px-4 py-3 flex gap-4 relative">
134
+ <div className="flex flex-col gap-1 flex-1">
135
+ {navItems.map((item) => {
136
+ const active = location.pathname === item.to
137
+ return (
138
+ <Link
139
+ key={item.to}
140
+ to={item.to}
141
+ onClick={() => setMenuOpen(false)}
142
+ className={`px-3 py-2 rounded-lg text-sm transition-all ${
143
+ active
144
+ ? 'bg-white/15 text-white'
145
+ : 'text-gray-300 hover:bg-white/10'
146
+ }`}
147
+ >
148
+ {item.label}
149
+ </Link>
150
+ )
151
+ })}
152
+ <div className="flex flex-wrap gap-2 mt-2 pt-2 border-t border-white/10">
153
+ <a
154
+ href="https://live-docs.marcosbrendon.com/"
155
+ target="_blank"
156
+ rel="noopener noreferrer"
157
+ className="inline-flex items-center gap-2 px-3 py-2 bg-purple-500/20 border border-purple-500/30 text-purple-200 rounded-lg text-sm hover:bg-purple-500/30 transition-all"
158
+ >
159
+ <FaBook />
160
+ Live Docs
161
+ </a>
162
+ <a
163
+ href="/swagger"
164
+ target="_blank"
165
+ rel="noopener noreferrer"
166
+ className="inline-flex items-center gap-2 px-3 py-2 bg-white/10 border border-white/20 text-white rounded-lg text-sm hover:bg-white/20 transition-all"
167
+ >
168
+ <FaBook />
169
+ API Docs
170
+ </a>
171
+ <a
172
+ href="https://github.com/MarcosBrendonDePaula/FluxStack"
173
+ target="_blank"
174
+ rel="noopener noreferrer"
175
+ className="inline-flex items-center gap-2 px-3 py-2 bg-white/10 border border-white/20 text-white rounded-lg text-sm hover:bg-white/20 transition-all"
176
+ >
177
+ <FaGithub />
178
+ GitHub
179
+ </a>
180
+ </div>
181
+ </div>
182
+
183
+ {/* Logo floating right */}
184
+ <img
185
+ src={FluxStackLogo}
186
+ alt=""
187
+ className="absolute right-4 top-1/2 -translate-y-1/2 w-40 h-40 opacity-15 pointer-events-none transition-[filter] duration-500"
188
+ style={{ filter: `hue-rotate(${routeFlameHue[location.pathname] || '0deg'})` }}
189
+ />
190
+ </nav>
191
+ </div>
192
+ )}
64
193
  </header>
65
194
 
66
195
  <Outlet />
@@ -1,13 +1,13 @@
1
- import { useNavigate } from 'react-router'
2
-
3
- export function BackButton() {
4
- const navigate = useNavigate()
5
- return (
6
- <button
7
- onClick={() => navigate(-1)}
8
- className="px-4 py-2 bg-white/10 backdrop-blur-sm border border-white/20 text-white rounded-lg font-medium hover:bg-white/20 transition-all"
9
- >
10
- ← Voltar
11
- </button>
12
- )
13
- }
1
+ import { useNavigate } from 'react-router'
2
+
3
+ export function BackButton() {
4
+ const navigate = useNavigate()
5
+ return (
6
+ <button
7
+ onClick={() => navigate(-1)}
8
+ className="px-4 py-2 bg-white/10 backdrop-blur-sm border border-white/20 text-white rounded-lg font-medium hover:bg-white/20 transition-all"
9
+ >
10
+ ← Voltar
11
+ </button>
12
+ )
13
+ }
@@ -3,15 +3,15 @@ import { BackButton } from './BackButton'
3
3
 
4
4
  export function DemoPage({ children, note }: { children: ReactNode; note?: ReactNode }) {
5
5
  return (
6
- <div className="min-h-screen bg-gradient-to-br from-slate-900 via-purple-900 to-slate-900 flex flex-col items-center justify-center px-4">
7
- <div className="mb-8">
6
+ <div className="min-h-[calc(100vh-56px)] sm:min-h-[calc(100vh-64px)] flex flex-col items-center justify-center px-3 sm:px-4 py-6 sm:py-8">
7
+ <div className="mb-4 sm:mb-8">
8
8
  <BackButton />
9
9
  </div>
10
- <div className="w-full max-w-6xl">
10
+ <div className="w-full max-w-6xl mx-auto flex flex-col items-center">
11
11
  {children}
12
12
  </div>
13
13
  {note && (
14
- <p className="mt-6 text-gray-400 text-sm max-w-md text-center">
14
+ <p className="mt-4 sm:mt-6 text-gray-400 text-xs sm:text-sm max-w-md text-center px-2">
15
15
  {note}
16
16
  </p>
17
17
  )}
@@ -27,7 +27,7 @@ function PublicSection() {
27
27
  })
28
28
 
29
29
  return (
30
- <div className="bg-white/5 border border-white/10 rounded-xl p-6">
30
+ <div className="bg-white/5 border border-white/10 rounded-xl p-4 sm:p-6">
31
31
  <h3 className="text-lg font-semibold text-white mb-1">Contador Público</h3>
32
32
  <p className="text-gray-400 text-xs mb-4">Sem autenticação necessária</p>
33
33
 
@@ -113,8 +113,8 @@ function AdminSection() {
113
113
  }
114
114
 
115
115
  return (
116
- <div className="bg-white/5 border border-white/10 rounded-xl p-6">
117
- <div className="flex items-center justify-between mb-4">
116
+ <div className="bg-white/5 border border-white/10 rounded-xl p-4 sm:p-6">
117
+ <div className="flex flex-col sm:flex-row sm:items-center justify-between gap-2 mb-4">
118
118
  <div>
119
119
  <h3 className="text-lg font-semibold text-white">Painel Admin</h3>
120
120
  <p className="text-gray-400 text-xs">
@@ -227,7 +227,7 @@ function AuthControls() {
227
227
  }
228
228
 
229
229
  return (
230
- <div className="bg-white/5 border border-white/10 rounded-xl p-6 mb-6">
230
+ <div className="bg-white/5 border border-white/10 rounded-xl p-4 sm:p-6 mb-6">
231
231
  <h3 className="text-lg font-semibold text-white mb-2">Autenticação</h3>
232
232
 
233
233
  <div className="flex items-center gap-3 mb-4">
@@ -237,7 +237,7 @@ function AuthControls() {
237
237
  </span>
238
238
  </div>
239
239
 
240
- <div className="flex gap-2">
240
+ <div className="flex flex-col sm:flex-row gap-2">
241
241
  <input
242
242
  value={token}
243
243
  onChange={e => setToken(e.target.value)}
@@ -245,26 +245,28 @@ function AuthControls() {
245
245
  placeholder="Token (JWT, API key, etc.)"
246
246
  className="flex-1 px-3 py-2 rounded-lg bg-white/10 border border-white/20 text-white text-sm placeholder-gray-500 focus:outline-none focus:ring-2 focus:ring-purple-500/50"
247
247
  />
248
- <button
249
- onClick={handleLogin}
250
- disabled={isLoggingIn}
251
- className="px-4 py-2 rounded-lg bg-emerald-500/20 border border-emerald-500/30 text-emerald-200 text-sm hover:bg-emerald-500/30 disabled:opacity-50"
252
- >
253
- {isLoggingIn ? 'Autenticando...' : 'Login'}
254
- </button>
255
- {authenticated && (
248
+ <div className="flex gap-2">
256
249
  <button
257
- onClick={handleLogout}
258
- className="px-4 py-2 rounded-lg bg-red-500/20 border border-red-500/30 text-red-200 text-sm hover:bg-red-500/30"
250
+ onClick={handleLogin}
251
+ disabled={isLoggingIn}
252
+ className="flex-1 sm:flex-initial px-4 py-2 rounded-lg bg-emerald-500/20 border border-emerald-500/30 text-emerald-200 text-sm hover:bg-emerald-500/30 disabled:opacity-50"
259
253
  >
260
- Logout
254
+ {isLoggingIn ? 'Autenticando...' : 'Login'}
261
255
  </button>
262
- )}
256
+ {authenticated && (
257
+ <button
258
+ onClick={handleLogout}
259
+ className="flex-1 sm:flex-initial px-4 py-2 rounded-lg bg-red-500/20 border border-red-500/30 text-red-200 text-sm hover:bg-red-500/30"
260
+ >
261
+ Logout
262
+ </button>
263
+ )}
264
+ </div>
263
265
  </div>
264
266
 
265
267
  <div className="mt-4 p-3 bg-emerald-500/10 border border-emerald-500/20 rounded-lg">
266
268
  <p className="text-emerald-300 text-xs font-semibold mb-2">Tokens de teste (dev only):</p>
267
- <div className="grid grid-cols-3 gap-2 text-xs">
269
+ <div className="grid grid-cols-1 sm:grid-cols-3 gap-2 text-xs">
268
270
  <button
269
271
  onClick={() => { setToken('admin-token'); }}
270
272
  className="px-2 py-1 rounded bg-purple-500/20 text-purple-300 hover:bg-purple-500/30"
@@ -304,8 +306,8 @@ function AuthControls() {
304
306
  export function AuthDemo() {
305
307
  return (
306
308
  <div className="space-y-6 w-full max-w-2xl mx-auto">
307
- <div className="text-center mb-8">
308
- <h2 className="text-3xl font-bold text-white mb-2">Live Components Auth</h2>
309
+ <div className="text-center mb-6 sm:mb-8">
310
+ <h2 className="text-2xl sm:text-3xl font-bold text-white mb-2">Live Components Auth</h2>
309
311
  <p className="text-gray-400">
310
312
  Sistema de autenticação declarativo para componentes real-time
311
313
  </p>
@@ -318,7 +320,7 @@ export function AuthDemo() {
318
320
  <AdminSection />
319
321
  </div>
320
322
 
321
- <div className="bg-white/5 border border-white/10 rounded-xl p-6 text-xs text-gray-500 space-y-2">
323
+ <div className="bg-white/5 border border-white/10 rounded-xl p-4 sm:p-6 text-xs text-gray-500 space-y-2 overflow-x-auto">
322
324
  <h4 className="text-sm font-semibold text-gray-300 mb-3">Como funciona</h4>
323
325
  <p><strong className="text-purple-300">Server:</strong> <code>static auth = &#123; required: true, roles: [&apos;admin&apos;] &#125;</code></p>
324
326
  <p><strong className="text-purple-300">Server:</strong> <code>static actionAuth = &#123; deleteUser: &#123; permissions: [&apos;users.delete&apos;] &#125; &#125;</code></p>
@@ -44,7 +44,7 @@ export function ChatDemo() {
44
44
  }
45
45
 
46
46
  return (
47
- <div className="bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-8 w-full mx-auto">
47
+ <div className="bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-4 sm:p-6 md:p-8 w-full max-w-2xl mx-auto">
48
48
  <h2 className="text-2xl font-bold text-white mb-2 text-center">Chat Compartilhado</h2>
49
49
  <p className="text-gray-400 text-sm text-center mb-4">
50
50
  Sala global em tempo real. Abra em várias abas para testar.
@@ -70,7 +70,7 @@ export function ChatDemo() {
70
70
  <div
71
71
  ref={containerRef}
72
72
  onScroll={handleScroll}
73
- className="bg-black/40 border border-white/10 rounded-xl p-5 h-[28rem] overflow-auto space-y-3"
73
+ className="bg-black/40 border border-white/10 rounded-xl p-3 sm:p-5 h-72 sm:h-96 md:h-[28rem] overflow-auto space-y-3"
74
74
  >
75
75
  {chat.$state.messages.length === 0 && (
76
76
  <div className="text-gray-500 text-sm text-center">Nenhuma mensagem ainda</div>
@@ -47,16 +47,16 @@ export function CounterDemo() {
47
47
  }
48
48
 
49
49
  return (
50
- <div className="bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-8 max-w-md w-full">
51
- <h2 className="text-2xl font-bold text-white mb-2 text-center">
50
+ <div className="bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-5 sm:p-8 max-w-md w-full flex flex-col">
51
+ <h2 className="text-xl sm:text-2xl font-bold text-white mb-2 text-center">
52
52
  {title}
53
53
  </h2>
54
54
 
55
- <p className="text-gray-400 text-sm text-center mb-6">
55
+ <p className="text-gray-400 text-xs sm:text-sm text-center mb-4 sm:mb-6">
56
56
  {description}
57
57
  </p>
58
58
 
59
- <div className="flex justify-center gap-4 mb-6">
59
+ <div className="flex flex-wrap justify-center gap-2 sm:gap-4 mb-4 sm:mb-6">
60
60
  <div className={`flex items-center gap-2 px-3 py-1 rounded-full text-xs ${
61
61
  counter.$connected
62
62
  ? 'bg-emerald-500/20 text-emerald-300'
@@ -74,8 +74,8 @@ export function CounterDemo() {
74
74
  </div>
75
75
  </div>
76
76
 
77
- <div className="text-center mb-8">
78
- <div className="text-8xl font-bold bg-gradient-to-r from-blue-400 via-purple-400 to-pink-400 bg-clip-text text-transparent">
77
+ <div className="text-center mb-6 sm:mb-8 flex-1 flex flex-col justify-center">
78
+ <div className="text-6xl sm:text-8xl font-bold bg-gradient-to-r from-blue-400 via-purple-400 to-pink-400 bg-clip-text text-transparent">
79
79
  {counter.$state.count}
80
80
  </div>
81
81
 
@@ -139,16 +139,16 @@ export function CounterDemo() {
139
139
  }
140
140
 
141
141
  return (
142
- <div className="bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-8 max-w-md w-full">
143
- <h2 className="text-2xl font-bold text-white mb-2 text-center">
142
+ <div className="bg-white/5 backdrop-blur-sm border border-white/10 rounded-2xl p-5 sm:p-8 max-w-md w-full flex flex-col">
143
+ <h2 className="text-xl sm:text-2xl font-bold text-white mb-2 text-center">
144
144
  Contador Local (sem Room)
145
145
  </h2>
146
- <p className="text-gray-400 text-sm text-center mb-6">
146
+ <p className="text-gray-400 text-xs sm:text-sm text-center mb-4 sm:mb-6">
147
147
  Estado local do componente, sem eventos de sala.
148
148
  </p>
149
149
 
150
- <div className="text-center mb-8">
151
- <div className="text-8xl font-bold bg-gradient-to-r from-amber-400 via-orange-400 to-rose-400 bg-clip-text text-transparent">
150
+ <div className="text-center mb-6 sm:mb-8 flex-1 flex flex-col justify-center">
151
+ <div className="text-6xl sm:text-8xl font-bold bg-gradient-to-r from-amber-400 via-orange-400 to-rose-400 bg-clip-text text-transparent">
152
152
  {localCounter.$state.count}
153
153
  </div>
154
154
  </div>
@@ -189,7 +189,7 @@ export function CounterDemo() {
189
189
  }
190
190
 
191
191
  return (
192
- <div className="flex flex-col lg:flex-row gap-6 items-start justify-center">
192
+ <div className="flex flex-col lg:flex-row gap-4 sm:gap-6 items-stretch justify-center">
193
193
  {renderLocalCounter()}
194
194
  {renderCounter(
195
195
  'Contador Isolado',
@@ -9,7 +9,7 @@ export function FormDemo() {
9
9
  // Sucesso
10
10
  if (form.submitted) {
11
11
  return (
12
- <div className="p-6 bg-green-500/20 border border-green-500/30 rounded-xl text-center">
12
+ <div className="p-4 sm:p-6 bg-green-500/20 border border-green-500/30 rounded-xl text-center w-full max-w-xl mx-auto">
13
13
  <div className="text-4xl mb-3">✅</div>
14
14
  <h2 className="text-xl font-bold text-white mb-2">Enviado!</h2>
15
15
  <p className="text-gray-300">Obrigado, <span className="text-green-400">{form.name}</span>!</p>
@@ -27,7 +27,7 @@ export function FormDemo() {
27
27
  }
28
28
 
29
29
  return (
30
- <div className="p-6 bg-white/10 backdrop-blur-sm border border-white/20 rounded-xl">
30
+ <div className="p-4 sm:p-6 bg-white/10 backdrop-blur-sm border border-white/20 rounded-xl w-full max-w-xl mx-auto">
31
31
  <div className="flex items-center justify-between mb-6">
32
32
  <h2 className="text-xl font-bold text-white">Live Form</h2>
33
33
  <span className={`px-3 py-1 rounded-full text-xs ${