hightjs 0.3.5 → 0.5.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 (123) hide show
  1. package/README.md +48 -116
  2. package/dist/bin/hightjs.js +51 -23
  3. package/dist/builder.js +198 -8
  4. package/dist/client/DefaultNotFound.d.ts +1 -1
  5. package/dist/client/DefaultNotFound.js +72 -46
  6. package/dist/client/client.d.ts +3 -0
  7. package/dist/{client.js → client/client.js} +4 -4
  8. package/dist/client/entry.client.js +77 -9
  9. package/dist/global/global.d.ts +117 -0
  10. package/dist/{auth/types.js → global/global.js} +0 -1
  11. package/dist/helpers.js +80 -2
  12. package/dist/hotReload.js +84 -4
  13. package/dist/index.js +72 -61
  14. package/dist/loaders.d.ts +1 -0
  15. package/dist/loaders.js +46 -0
  16. package/dist/renderer.js +158 -4
  17. package/dist/types.d.ts +44 -0
  18. package/package.json +37 -30
  19. package/.idea/HightJS.iml +0 -9
  20. package/.idea/copilot.data.migration.agent.xml +0 -6
  21. package/.idea/copilot.data.migration.ask.xml +0 -6
  22. package/.idea/copilot.data.migration.ask2agent.xml +0 -6
  23. package/.idea/copilot.data.migration.edit.xml +0 -6
  24. package/.idea/copilotDiffState.xml +0 -67
  25. package/.idea/inspectionProfiles/Project_Default.xml +0 -13
  26. package/.idea/libraries/test_package.xml +0 -9
  27. package/.idea/libraries/ts_commonjs_default_export.xml +0 -9
  28. package/.idea/misc.xml +0 -7
  29. package/.idea/modules.xml +0 -8
  30. package/.idea/vcs.xml +0 -6
  31. package/dist/auth/client.d.ts +0 -24
  32. package/dist/auth/client.js +0 -146
  33. package/dist/auth/components.d.ts +0 -29
  34. package/dist/auth/components.js +0 -100
  35. package/dist/auth/core.d.ts +0 -55
  36. package/dist/auth/core.js +0 -189
  37. package/dist/auth/index.d.ts +0 -7
  38. package/dist/auth/index.js +0 -45
  39. package/dist/auth/jwt.d.ts +0 -41
  40. package/dist/auth/jwt.js +0 -185
  41. package/dist/auth/providers/credentials.d.ts +0 -60
  42. package/dist/auth/providers/credentials.js +0 -97
  43. package/dist/auth/providers/discord.d.ts +0 -63
  44. package/dist/auth/providers/discord.js +0 -190
  45. package/dist/auth/providers/google.d.ts +0 -63
  46. package/dist/auth/providers/google.js +0 -186
  47. package/dist/auth/providers/index.d.ts +0 -2
  48. package/dist/auth/providers/index.js +0 -35
  49. package/dist/auth/providers.d.ts +0 -3
  50. package/dist/auth/providers.js +0 -26
  51. package/dist/auth/react/index.d.ts +0 -6
  52. package/dist/auth/react/index.js +0 -48
  53. package/dist/auth/react.d.ts +0 -22
  54. package/dist/auth/react.js +0 -199
  55. package/dist/auth/routes.d.ts +0 -16
  56. package/dist/auth/routes.js +0 -152
  57. package/dist/auth/types.d.ts +0 -76
  58. package/dist/client.d.ts +0 -3
  59. package/docs/README.md +0 -58
  60. package/docs/arquivos-especiais.md +0 -10
  61. package/docs/autenticacao.md +0 -212
  62. package/docs/checklist.md +0 -9
  63. package/docs/cli.md +0 -72
  64. package/docs/config.md +0 -216
  65. package/docs/estrutura.md +0 -20
  66. package/docs/faq.md +0 -10
  67. package/docs/hot-reload.md +0 -5
  68. package/docs/integracoes.md +0 -240
  69. package/docs/middlewares.md +0 -73
  70. package/docs/rotas-backend.md +0 -45
  71. package/docs/rotas-frontend.md +0 -66
  72. package/docs/seguranca.md +0 -8
  73. package/docs/websocket.md +0 -45
  74. package/example/certs/cert.pem +0 -20
  75. package/example/certs/key.pem +0 -27
  76. package/example/hightjs.config.ts +0 -87
  77. package/example/package-lock.json +0 -1174
  78. package/example/package.json +0 -26
  79. package/example/postcss.config.js +0 -8
  80. package/example/src/auth.ts +0 -42
  81. package/example/src/web/backend/routes/auth.ts +0 -3
  82. package/example/src/web/backend/routes/version.ts +0 -13
  83. package/example/src/web/globals.css +0 -5
  84. package/example/src/web/layout.tsx +0 -100
  85. package/example/src/web/routes/index.tsx +0 -153
  86. package/example/src/web/routes/login.tsx +0 -175
  87. package/example/tailwind.config.js +0 -12
  88. package/example/tsconfig.json +0 -15
  89. package/src/adapters/express.ts +0 -87
  90. package/src/adapters/factory.ts +0 -112
  91. package/src/adapters/fastify.ts +0 -104
  92. package/src/adapters/native.ts +0 -234
  93. package/src/api/console.ts +0 -305
  94. package/src/api/http.ts +0 -535
  95. package/src/auth/client.ts +0 -171
  96. package/src/auth/components.tsx +0 -125
  97. package/src/auth/core.ts +0 -215
  98. package/src/auth/index.ts +0 -25
  99. package/src/auth/jwt.ts +0 -210
  100. package/src/auth/providers/credentials.ts +0 -139
  101. package/src/auth/providers/discord.ts +0 -239
  102. package/src/auth/providers/google.ts +0 -234
  103. package/src/auth/providers/index.ts +0 -20
  104. package/src/auth/providers.ts +0 -20
  105. package/src/auth/react/index.ts +0 -25
  106. package/src/auth/react.tsx +0 -234
  107. package/src/auth/routes.ts +0 -183
  108. package/src/auth/types.ts +0 -108
  109. package/src/bin/hightjs.js +0 -222
  110. package/src/builder.js +0 -411
  111. package/src/client/DefaultNotFound.tsx +0 -84
  112. package/src/client/clientRouter.ts +0 -153
  113. package/src/client/entry.client.tsx +0 -444
  114. package/src/client.ts +0 -24
  115. package/src/components/Link.tsx +0 -38
  116. package/src/helpers.ts +0 -542
  117. package/src/hotReload.ts +0 -489
  118. package/src/index.ts +0 -546
  119. package/src/renderer.tsx +0 -263
  120. package/src/router.ts +0 -730
  121. package/src/types/framework.ts +0 -58
  122. package/src/types.ts +0 -207
  123. package/tsconfig.json +0 -17
@@ -1,84 +0,0 @@
1
- /*
2
- * This file is part of the HightJS Project.
3
- * Copyright (c) 2025 itsmuzin
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
16
- */
17
- import React from 'react';
18
-
19
- export default function DefaultNotFound() {
20
- return (
21
- <div style={{
22
- fontFamily: 'system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"',
23
- height: '100vh',
24
- textAlign: 'center',
25
- display: 'flex',
26
- flexDirection: 'column',
27
- alignItems: 'center',
28
- justifyContent: 'center'
29
- }}>
30
- <div>
31
- <style dangerouslySetInnerHTML={{
32
- __html: `
33
- body {
34
- color: #000;
35
- /* Alterado de cor sólida para gradiente */
36
- background: linear-gradient(to bottom, #e9e9e9, #ffffff);
37
- margin: 0;
38
- }
39
-
40
- .next-error-h1 {
41
- border-right: 1px solid rgba(0, 0, 0, .3);
42
- }
43
-
44
- @media (prefers-color-scheme: dark) {
45
- body {
46
- color: #fff;
47
- /* Alterado de cor sólida para gradiente escuro */
48
- background: linear-gradient(to bottom, #222, #000);
49
- }
50
-
51
- .next-error-h1 {
52
- border-right: 1px solid rgba(255, 255, 255, .3);
53
- }
54
- }
55
- `
56
- }} />
57
- <h1
58
- className="next-error-h1"
59
- style={{
60
- display: 'inline-block',
61
- margin: '0px 20px 0px 0px',
62
- padding: '0px 23px 0px 0px',
63
- fontSize: '24px',
64
- fontWeight: '500',
65
- verticalAlign: 'top',
66
- lineHeight: '49px'
67
- }}
68
- >
69
- 404
70
- </h1>
71
- <div style={{ display: 'inline-block' }}>
72
- <h2 style={{
73
- fontSize: '14px',
74
- fontWeight: '400',
75
- lineHeight: '49px',
76
- margin: '0px'
77
- }}>
78
- This page cannot be found.
79
- </h2>
80
- </div>
81
- </div>
82
- </div>
83
- );
84
- }
@@ -1,153 +0,0 @@
1
- /*
2
- * This file is part of the HightJS Project.
3
- * Copyright (c) 2025 itsmuzin
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
16
- */
17
- // Sistema de roteamento do lado do cliente para hweb-sdk
18
-
19
- export interface RouterEvents {
20
- beforeNavigate?: (url: string) => boolean | Promise<boolean>;
21
- afterNavigate?: (url: string) => void;
22
- }
23
-
24
- class Router {
25
- private events: RouterEvents = {};
26
- private listeners: Set<() => void> = new Set();
27
-
28
- /**
29
- * Navega para uma nova rota
30
- */
31
- async push(url: string): Promise<void> {
32
- // Callback antes de navegar
33
- if (this.events.beforeNavigate) {
34
- const shouldProceed = await this.events.beforeNavigate(url);
35
- if (shouldProceed === false) return;
36
- }
37
-
38
- // Atualiza a URL na barra de endereço
39
- window.history.pushState({ path: url }, '', url);
40
-
41
- // Dispara evento para o roteador capturar de forma assíncrona
42
- setTimeout(() => this.triggerNavigation(), 0);
43
-
44
- // Callback após navegar
45
- if (this.events.afterNavigate) {
46
- this.events.afterNavigate(url);
47
- }
48
- }
49
-
50
- /**
51
- * Substitui a entrada atual do histórico
52
- */
53
- async replace(url: string): Promise<void> {
54
- // Callback antes de navegar
55
- if (this.events.beforeNavigate) {
56
- const shouldProceed = await this.events.beforeNavigate(url);
57
- if (shouldProceed === false) return;
58
- }
59
-
60
- // Substitui a URL atual no histórico
61
- window.history.replaceState({ path: url }, '', url);
62
-
63
- // Dispara evento para o roteador capturar de forma assíncrona
64
- setTimeout(() => this.triggerNavigation(), 0);
65
-
66
- // Callback após navegar
67
- if (this.events.afterNavigate) {
68
- this.events.afterNavigate(url);
69
- }
70
- }
71
-
72
- /**
73
- * Volta uma página no histórico
74
- */
75
- back(): void {
76
- window.history.back();
77
- }
78
-
79
- /**
80
- * Avança uma página no histórico
81
- */
82
- forward(): void {
83
- window.history.forward();
84
- }
85
-
86
- /**
87
- * Recarrega a página atual (re-renderiza o componente)
88
- */
89
- refresh(): void {
90
- setTimeout(() => this.triggerNavigation(), 0);
91
- }
92
-
93
- /**
94
- * Obtém a URL atual
95
- */
96
- get pathname(): string {
97
- return window.location.pathname;
98
- }
99
-
100
- /**
101
- * Obtém os query parameters atuais
102
- */
103
- get query(): URLSearchParams {
104
- return new URLSearchParams(window.location.search);
105
- }
106
-
107
- /**
108
- * Obtém a URL completa atual
109
- */
110
- get url(): string {
111
- return window.location.href;
112
- }
113
-
114
- /**
115
- * Adiciona event listeners para eventos de roteamento
116
- */
117
- on(events: RouterEvents): void {
118
- this.events = { ...this.events, ...events };
119
- }
120
-
121
- /**
122
- * Remove event listeners
123
- */
124
- off(): void {
125
- this.events = {};
126
- }
127
-
128
- /**
129
- * Adiciona um listener para mudanças de rota
130
- */
131
- subscribe(listener: () => void): () => void {
132
- this.listeners.add(listener);
133
- return () => this.listeners.delete(listener);
134
- }
135
-
136
- /**
137
- * Dispara evento de navegação para todos os listeners
138
- */
139
- private triggerNavigation(): void {
140
- // Dispara o evento nativo para o roteador do hweb capturar
141
- window.dispatchEvent(new PopStateEvent('popstate'));
142
-
143
- // Notifica todos os listeners customizados
144
- this.listeners.forEach(listener => listener());
145
- }
146
-
147
- }
148
-
149
- // Instância singleton do router
150
- export const router = new Router();
151
-
152
- // Para compatibilidade, também exporta como default
153
- export default router;
@@ -1,444 +0,0 @@
1
- /*
2
- * This file is part of the HightJS Project.
3
- * Copyright (c) 2025 itsmuzin
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
16
- */
17
- import React, {useState, useEffect, useCallback, useRef} from 'react';
18
- import { createRoot } from 'react-dom/client';
19
- import { router } from './clientRouter';
20
-
21
- // --- O Componente Principal do Cliente (Roteador) ---
22
-
23
- interface AppProps {
24
- componentMap: Record<string, any>;
25
- routes: { pattern: string; componentPath: string }[];
26
- initialComponentPath: string;
27
- initialParams: any;
28
- layoutComponent?: any;
29
- }
30
-
31
- function App({ componentMap, routes, initialComponentPath, initialParams, layoutComponent }: AppProps) {
32
- // Estado que guarda o componente a ser renderizado atualmente
33
-
34
- const [CurrentPageComponent, setCurrentPageComponent] = useState(() => {
35
- // Se for a rota especial __404__, não busca no componentMap
36
- if (initialComponentPath === '__404__') {
37
- return null;
38
- }
39
- return componentMap[initialComponentPath];
40
- });
41
- const [params, setParams] = useState(initialParams);
42
-
43
- const findRouteForPath = useCallback((path: string) => {
44
- for (const route of routes) {
45
- const regexPattern = route.pattern
46
- // [[...param]] → opcional catch-all
47
- .replace(/\[\[\.\.\.(\w+)\]\]/g, '(?<$1>.+)?')
48
- // [...param] → obrigatório catch-all
49
- .replace(/\[\.\.\.(\w+)\]/g, '(?<$1>.+)')
50
- // /[[param]] → opcional com barra também opcional
51
- .replace(/\/\[\[(\w+)\]\]/g, '(?:/(?<$1>[^/]+))?')
52
- // [[param]] → segmento opcional (sem barra anterior)
53
- .replace(/\[\[(\w+)\]\]/g, '(?<$1>[^/]+)?')
54
- // [param] → segmento obrigatório
55
- .replace(/\[(\w+)\]/g, '(?<$1>[^/]+)');
56
- const regex = new RegExp(`^${regexPattern}/?$`);
57
- const match = path.match(regex);
58
- if (match) {
59
- return {
60
- componentPath: route.componentPath,
61
- params: match.groups || {}
62
- };
63
- }
64
- }
65
- return null;
66
- }, [routes]);
67
-
68
- const updateRoute = useCallback(() => {
69
- const currentPath = router.pathname;
70
- const match = findRouteForPath(currentPath);
71
- if (match) {
72
- setCurrentPageComponent(() => componentMap[match.componentPath]);
73
- setParams(match.params);
74
- } else {
75
- // Se não encontrou rota, define como null para mostrar 404
76
- setCurrentPageComponent(null);
77
- setParams({});
78
- }
79
- }, [router.pathname, findRouteForPath, componentMap]);
80
-
81
- // Ouve os eventos de "voltar" e "avançar" do navegador
82
- useEffect(() => {
83
- const handlePopState = () => {
84
- updateRoute();
85
- };
86
-
87
- window.addEventListener('popstate', handlePopState);
88
-
89
- // Também se inscreve no router para mudanças de rota
90
- const unsubscribe = router.subscribe(updateRoute);
91
-
92
- return () => {
93
- window.removeEventListener('popstate', handlePopState);
94
- unsubscribe();
95
- };
96
- }, [updateRoute]);
97
-
98
- // Se não há componente ou é a rota __404__, mostra página 404
99
- if (!CurrentPageComponent || initialComponentPath === '__404__') {
100
- // Usa o componente 404 personalizado se existir, senão usa o padrão do hweb
101
- const NotFoundComponent = (window as any).__HWEB_NOT_FOUND__;
102
-
103
- if (NotFoundComponent) {
104
- // Usa o notFound.tsx personalizado do usuário
105
- const NotFoundContent = <NotFoundComponent />;
106
-
107
- // Aplica o layout se existir
108
- if (layoutComponent) {
109
- return React.createElement(layoutComponent, { children: NotFoundContent });
110
- }
111
- return NotFoundContent;
112
- } else {
113
- // Usa o 404 padrão do hweb que foi incluído no build
114
- const DefaultNotFound = (window as any).__HWEB_DEFAULT_NOT_FOUND__;
115
- const NotFoundContent = <DefaultNotFound />;
116
-
117
- // Aplica o layout se existir
118
- if (layoutComponent) {
119
- return React.createElement(layoutComponent, { children: NotFoundContent });
120
- }
121
- return NotFoundContent;
122
- }
123
- }
124
-
125
- // Renderiza o componente atual (sem Context, usa o router diretamente)
126
- const PageContent = <CurrentPageComponent params={params} />;
127
-
128
- // SEMPRE usa o layout - se não existir, cria um wrapper padrão
129
- const content = layoutComponent
130
- ? React.createElement(layoutComponent, { children: PageContent })
131
- : <div>{PageContent}</div>;
132
-
133
- // Adiciona o indicador de dev se não for produção
134
- return (
135
- <>
136
- {content}
137
- {process.env.NODE_ENV !== 'production' && <DevIndicator />}
138
- </>
139
- );
140
- }
141
-
142
-
143
-
144
- // --- Constantes de Configuração ---
145
- const DEV_INDICATOR_SIZE = 48;
146
- const DEV_INDICATOR_CORNERS = [
147
- { top: 16, left: 16 }, // 0: topo-esquerda
148
- { top: 16, right: 16 }, // 1: topo-direita
149
- { bottom: 16, left: 16 }, // 2: baixo-esquerda
150
- { bottom: 16, right: 16 },// 3: baixo-direita
151
- ];
152
-
153
- function DevIndicator() {
154
- const [corner, setCorner] = useState(3); // Canto atual (0-3)
155
- const [isDragging, setIsDragging] = useState(false); // Estado de arrastar
156
- const [isBuilding, setIsBuilding] = useState(false); // Estado de build
157
-
158
- // Posição visual do indicador durante o arraste
159
- const [position, setPosition] = useState<{ top: number; left: number }>({ top: 0, left: 0 });
160
-
161
- const indicatorRef = useRef<HTMLDivElement>(null);
162
- const dragStartRef = useRef<{ x: number; y: number; moved: boolean } | null>(null);
163
-
164
- // Escuta eventos de hot reload para mostrar estado de build
165
- useEffect(() => {
166
- if (typeof window === 'undefined') return;
167
-
168
- const handleHotReloadMessage = (event: MessageEvent) => {
169
- try {
170
- const message = JSON.parse(event.data);
171
-
172
- // Quando detecta mudança em arquivo, ativa loading
173
- if (message.type === 'frontend-reload' ||
174
- message.type === 'backend-api-reload' ||
175
- message.type === 'src-reload') {
176
- setIsBuilding(true);
177
- }
178
-
179
- // Quando o build termina ou servidor fica pronto, desativa loading
180
- if (message.type === 'server-ready' || message.type === 'build-complete') {
181
- setIsBuilding(false);
182
- }
183
- } catch (e) {
184
- // Ignora mensagens que não são JSON
185
- }
186
- };
187
-
188
- // Intercepta mensagens WebSocket
189
- const originalWebSocket = window.WebSocket;
190
- window.WebSocket = class extends originalWebSocket {
191
- constructor(url: string | URL, protocols?: string | string[]) {
192
- super(url, protocols);
193
-
194
- this.addEventListener('message', (event) => {
195
- if (url.toString().includes('hweb-hotreload')) {
196
- handleHotReloadMessage(event);
197
- }
198
- });
199
- }
200
- } as any;
201
-
202
- return () => {
203
- window.WebSocket = originalWebSocket;
204
- };
205
- }, []);
206
-
207
- // --- Estilos Dinâmicos ---
208
- const getIndicatorStyle = (): React.CSSProperties => {
209
- const baseStyle: React.CSSProperties = {
210
- position: 'fixed',
211
- zIndex: 9999,
212
- width: DEV_INDICATOR_SIZE,
213
- height: DEV_INDICATOR_SIZE,
214
- borderRadius: '50%',
215
- background: isBuilding
216
- ? 'linear-gradient(135deg, #f093fb, #f5576c)' // Gradiente Rosa/Vermelho quando building
217
- : 'linear-gradient(135deg, #8e2de2, #4a00e0)', // Gradiente Roxo normal
218
- color: 'white',
219
- fontWeight: 'bold',
220
- fontSize: 28,
221
- boxShadow: isBuilding
222
- ? '0 4px 25px rgba(245, 87, 108, 0.6)' // Shadow mais forte quando building
223
- : '0 4px 15px rgba(0,0,0,0.2)',
224
- display: 'flex',
225
- alignItems: 'center',
226
- justifyContent: 'center',
227
- cursor: isDragging ? 'grabbing' : 'grab',
228
- userSelect: 'none',
229
- transition: isDragging ? 'none' : 'all 0.3s ease-out',
230
- animation: isBuilding ? 'hweb-pulse 1.5s ease-in-out infinite' : 'none',
231
- };
232
-
233
- if (isDragging) {
234
- return {
235
- ...baseStyle,
236
- top: position.top,
237
- left: position.left,
238
- };
239
- }
240
-
241
- return { ...baseStyle, ...DEV_INDICATOR_CORNERS[corner] };
242
- };
243
-
244
- const getMenuPositionStyle = (): React.CSSProperties => {
245
- // Posiciona o menu dependendo do canto
246
- switch (corner) {
247
- case 0: return { top: '110%', left: '0' }; // Top-Left
248
- case 1: return { top: '110%', right: '0' }; // Top-Right
249
- case 2: return { bottom: '110%', left: '0' }; // Bottom-Left
250
- case 3: return { bottom: '110%', right: '0' }; // Bottom-Right
251
- default: return {};
252
- }
253
- };
254
-
255
- // --- Lógica de Eventos ---
256
- const handleMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
257
- e.preventDefault();
258
- dragStartRef.current = { x: e.clientX, y: e.clientY, moved: false };
259
- if (indicatorRef.current) {
260
- const rect = indicatorRef.current.getBoundingClientRect();
261
- setPosition({ top: rect.top, left: rect.left });
262
- }
263
- setIsDragging(true);
264
- };
265
-
266
- const handleMouseMove = useCallback((e: MouseEvent) => {
267
- if (!isDragging || !dragStartRef.current) return;
268
-
269
- const deltaX = e.clientX - dragStartRef.current.x;
270
- const deltaY = e.clientY - dragStartRef.current.y;
271
-
272
- // Diferencia clique de arrastar (threshold de 5px)
273
- if (!dragStartRef.current.moved && Math.hypot(deltaX, deltaY) > 5) {
274
- dragStartRef.current.moved = true;
275
- }
276
-
277
- if (dragStartRef.current.moved) {
278
- setPosition(prevPos => ({
279
- top: prevPos.top + deltaY,
280
- left: prevPos.left + deltaX,
281
- }));
282
- // Atualiza a referência para o próximo movimento
283
- dragStartRef.current.x = e.clientX;
284
- dragStartRef.current.y = e.clientY;
285
- }
286
- }, [isDragging]);
287
-
288
- const handleMouseUp = useCallback((e: MouseEvent) => {
289
- if (!isDragging) return;
290
- setIsDragging(false);
291
-
292
- // Se moveu, calcula o canto mais próximo
293
- if (dragStartRef.current?.moved) {
294
- const { clientX, clientY } = e;
295
- const w = window.innerWidth;
296
- const h = window.innerHeight;
297
-
298
- const dists = [
299
- Math.hypot(clientX, clientY), // TL
300
- Math.hypot(w - clientX, clientY), // TR
301
- Math.hypot(clientX, h - clientY), // BL
302
- Math.hypot(w - clientX, h - clientY), // BR
303
- ];
304
- setCorner(dists.indexOf(Math.min(...dists)));
305
- }
306
-
307
- dragStartRef.current = null;
308
- }, [isDragging]);
309
-
310
- // Adiciona e remove listeners globais
311
- useEffect(() => {
312
- if (isDragging) {
313
- window.addEventListener('mousemove', handleMouseMove);
314
- window.addEventListener('mouseup', handleMouseUp);
315
- }
316
- return () => {
317
- window.removeEventListener('mousemove', handleMouseMove);
318
- window.removeEventListener('mouseup', handleMouseUp);
319
- };
320
- }, [isDragging, handleMouseMove, handleMouseUp]);
321
-
322
-
323
- return (
324
- <>
325
- <style>
326
- {`
327
- @keyframes hweb-pulse {
328
- 0%, 100% {
329
- transform: scale(1);
330
- opacity: 1;
331
- }
332
- 50% {
333
- transform: scale(1.1);
334
- opacity: 0.8;
335
- }
336
- }
337
-
338
- @keyframes hweb-spin {
339
- from {
340
- transform: rotate(0deg);
341
- }
342
- to {
343
- transform: rotate(360deg);
344
- }
345
- }
346
- `}
347
- </style>
348
- <div
349
- ref={indicatorRef}
350
- style={getIndicatorStyle()}
351
- onMouseDown={handleMouseDown}
352
- title={isBuilding ? "Building..." : "Modo Dev HightJS"}
353
- >
354
- {isBuilding ? (
355
- <span style={{ animation: 'hweb-spin 1s linear infinite' }}>⟳</span>
356
- ) : (
357
- 'H'
358
- )}
359
- </div>
360
- </>
361
- );
362
- }
363
-
364
- // --- Inicialização do Cliente (CSR - Client-Side Rendering) ---
365
-
366
- function deobfuscateData(obfuscated: string): any {
367
- try {
368
- // Remove o hash fake
369
- const parts = obfuscated.split('.');
370
- const base64 = parts.length > 1 ? parts[1] : parts[0];
371
-
372
- // Decodifica base64
373
- const jsonStr = atob(base64);
374
-
375
- // Parse JSON
376
- return JSON.parse(jsonStr);
377
- } catch (error) {
378
- console.error('[hweb] Failed to decode data:', error);
379
- return null;
380
- }
381
- }
382
-
383
- function initializeClient() {
384
- // Lê os dados do atributo data-h
385
- const dataElement = document.getElementById('__hight_data__');
386
-
387
- if (!dataElement) {
388
- console.error('[hweb] Initial data script not found.');
389
- return;
390
- }
391
-
392
- const obfuscated = dataElement.getAttribute('data-h');
393
-
394
- if (!obfuscated) {
395
- console.error('[hweb] Data attribute not found.');
396
- return;
397
- }
398
-
399
- const initialData = deobfuscateData(obfuscated);
400
-
401
- if (!initialData) {
402
- console.error('[hweb] Failed to parse initial data.');
403
- return;
404
- }
405
-
406
- // Cria o mapa de componentes dinamicamente a partir dos módulos carregados
407
- const componentMap: Record<string, any> = {};
408
-
409
- // Registra todos os componentes que foram importados
410
- if ((window as any).__HWEB_COMPONENTS__) {
411
- Object.assign(componentMap, (window as any).__HWEB_COMPONENTS__);
412
- }
413
-
414
- const container = document.getElementById('root');
415
- if (!container) {
416
- console.error('[hweb] Container #root not found.');
417
- return;
418
- }
419
-
420
- try {
421
- // Usar createRoot para render inicial (CSR)
422
- const root = createRoot(container);
423
-
424
- root.render(
425
- <App
426
- componentMap={componentMap}
427
- routes={initialData.routes}
428
- initialComponentPath={initialData.initialComponentPath}
429
- initialParams={initialData.initialParams}
430
- layoutComponent={(window as any).__HWEB_LAYOUT__}
431
- />
432
- );
433
- } catch (error) {
434
- console.error('[hweb] Error rendering application:', error);
435
- }
436
- }
437
-
438
- // Executa quando o DOM estiver pronto
439
- if (document.readyState === 'loading') {
440
- document.addEventListener('DOMContentLoaded', initializeClient);
441
- } else {
442
- initializeClient();
443
- }
444
-
package/src/client.ts DELETED
@@ -1,24 +0,0 @@
1
- /*
2
- * This file is part of the HightJS Project.
3
- * Copyright (c) 2025 itsmuzin
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
16
- */
17
- // Este arquivo exporta apenas código seguro para o cliente (navegador)
18
- export { Link } from './components/Link';
19
- export { RouteConfig, Metadata } from "./types";
20
- export { router } from './client/clientRouter';
21
-
22
-
23
-
24
-