dars-framework 1.0.0__py3-none-any.whl
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.
- dars/__init__.py +0 -0
- dars/all.py +52 -0
- dars/cli/__init__.py +0 -0
- dars/cli/hot_reload.py +33 -0
- dars/cli/main.py +637 -0
- dars/cli/preview.py +419 -0
- dars/cli/translations.py +389 -0
- dars/components/__init__.py +0 -0
- dars/components/advanced/__init__.py +8 -0
- dars/components/advanced/accordion.py +21 -0
- dars/components/advanced/card.py +28 -0
- dars/components/advanced/modal.py +40 -0
- dars/components/advanced/navbar.py +31 -0
- dars/components/advanced/table.py +24 -0
- dars/components/advanced/tabs.py +26 -0
- dars/components/basic/__init__.py +34 -0
- dars/components/basic/button.py +29 -0
- dars/components/basic/checkbox.py +34 -0
- dars/components/basic/container.py +23 -0
- dars/components/basic/datepicker.py +139 -0
- dars/components/basic/image.py +36 -0
- dars/components/basic/input.py +50 -0
- dars/components/basic/link.py +31 -0
- dars/components/basic/page.py +20 -0
- dars/components/basic/progressbar.py +17 -0
- dars/components/basic/radiobutton.py +34 -0
- dars/components/basic/select.py +81 -0
- dars/components/basic/slider.py +63 -0
- dars/components/basic/spinner.py +11 -0
- dars/components/basic/text.py +22 -0
- dars/components/basic/textarea.py +46 -0
- dars/components/basic/tooltip.py +18 -0
- dars/components/layout/__init__.py +0 -0
- dars/components/layout/anchor.py +13 -0
- dars/components/layout/flex.py +26 -0
- dars/components/layout/grid.py +45 -0
- dars/core/__init__.py +0 -0
- dars/core/app.py +630 -0
- dars/core/component.py +25 -0
- dars/core/events.py +101 -0
- dars/core/properties.py +127 -0
- dars/docs/__init__.py +0 -0
- dars/exporters/__init__.py +0 -0
- dars/exporters/base.py +69 -0
- dars/exporters/web/__init__.py +0 -0
- dars/exporters/web/html_css_js.py +1406 -0
- dars/scripts/__init__.py +0 -0
- dars/scripts/script.py +38 -0
- dars/templates/__init__.py +0 -0
- dars/templates/examples/advanced/all_components_demo.py +87 -0
- dars/templates/examples/advanced/dashboard.py +440 -0
- dars/templates/examples/advanced/modern_web_app.py +452 -0
- dars/templates/examples/basic/flex_layout_responsive.py +13 -0
- dars/templates/examples/basic/form_components.py +516 -0
- dars/templates/examples/basic/grid_layout_responsive.py +13 -0
- dars/templates/examples/basic/hello_world.py +104 -0
- dars/templates/examples/basic/layout_multipage_demo.py +23 -0
- dars/templates/examples/basic/multipage_example.py +70 -0
- dars/templates/examples/basic/pwa_custom_icons.py +31 -0
- dars/templates/examples/basic/simple_form.py +377 -0
- dars/templates/examples/demo/complete_app.py +720 -0
- dars/templates/html/__init__.py +0 -0
- dars_framework-1.0.0.dist-info/METADATA +146 -0
- dars_framework-1.0.0.dist-info/RECORD +68 -0
- dars_framework-1.0.0.dist-info/WHEEL +5 -0
- dars_framework-1.0.0.dist-info/entry_points.txt +2 -0
- dars_framework-1.0.0.dist-info/licenses/LICENSE +21 -0
- dars_framework-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,720 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Dars - Aplicación de Demostración Completa
|
|
4
|
+
Una aplicación que demuestra todas las características principales de Dars
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
import os
|
|
9
|
+
|
|
10
|
+
from dars.core.app import App
|
|
11
|
+
from dars.components.basic.text import Text
|
|
12
|
+
from dars.components.basic.button import Button
|
|
13
|
+
from dars.components.basic.input import Input
|
|
14
|
+
from dars.components.basic.container import Container
|
|
15
|
+
from dars.scripts.script import InlineScript, FileScript
|
|
16
|
+
|
|
17
|
+
# Crear la aplicación con configuración avanzada
|
|
18
|
+
app = App(
|
|
19
|
+
title="Dars - Demostración Completa",
|
|
20
|
+
theme="light",
|
|
21
|
+
responsive=True
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
# Estilos globales
|
|
25
|
+
app.add_global_style("body", {
|
|
26
|
+
'margin': '0',
|
|
27
|
+
'padding': '0',
|
|
28
|
+
'font-family': '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
|
|
29
|
+
'background-color': '#f8f9fa'
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
app.add_global_style(".fade-in", {
|
|
33
|
+
'opacity': '0',
|
|
34
|
+
'transition': 'opacity 0.5s ease-in-out'
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
# Contenedor principal
|
|
38
|
+
main_container = Container(
|
|
39
|
+
id="main-app",
|
|
40
|
+
style={
|
|
41
|
+
'min-height': '100vh',
|
|
42
|
+
'display': 'flex',
|
|
43
|
+
'flex-direction': 'column'
|
|
44
|
+
}
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# Header/Navegación
|
|
48
|
+
header = Container(
|
|
49
|
+
id="header",
|
|
50
|
+
style={
|
|
51
|
+
'background': 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
52
|
+
'color': 'white',
|
|
53
|
+
'padding': '20px 0',
|
|
54
|
+
'box-shadow': '0 2px 10px rgba(0,0,0,0.1)'
|
|
55
|
+
}
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
nav_container = Container(
|
|
59
|
+
style={
|
|
60
|
+
'max-width': '1200px',
|
|
61
|
+
'margin': '0 auto',
|
|
62
|
+
'padding': '0 20px',
|
|
63
|
+
'display': 'flex',
|
|
64
|
+
'justify-content': 'space-between',
|
|
65
|
+
'align-items': 'center'
|
|
66
|
+
}
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
logo = Text(
|
|
70
|
+
text="🚀 Dars Demo",
|
|
71
|
+
style={
|
|
72
|
+
'font-size': '28px',
|
|
73
|
+
'font-weight': 'bold'
|
|
74
|
+
}
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
nav_menu = Container(
|
|
78
|
+
style={
|
|
79
|
+
'display': 'flex',
|
|
80
|
+
'gap': '30px'
|
|
81
|
+
}
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
nav_items = ["Inicio", "Componentes", "Formularios", "Dashboard", "Acerca"]
|
|
85
|
+
for item in nav_items:
|
|
86
|
+
nav_button = Button(
|
|
87
|
+
id=f"nav-{item.lower()}",
|
|
88
|
+
text=item,
|
|
89
|
+
style={
|
|
90
|
+
'background': 'transparent',
|
|
91
|
+
'color': 'white',
|
|
92
|
+
'border': '2px solid transparent',
|
|
93
|
+
'padding': '8px 16px',
|
|
94
|
+
'border-radius': '20px',
|
|
95
|
+
'cursor': 'pointer',
|
|
96
|
+
'transition': 'all 0.3s ease'
|
|
97
|
+
}
|
|
98
|
+
)
|
|
99
|
+
nav_menu.add_child(nav_button)
|
|
100
|
+
|
|
101
|
+
# Área de contenido principal
|
|
102
|
+
content_area = Container(
|
|
103
|
+
id="content-area",
|
|
104
|
+
style={
|
|
105
|
+
'flex': '1',
|
|
106
|
+
'max-width': '1200px',
|
|
107
|
+
'margin': '0 auto',
|
|
108
|
+
'padding': '40px 20px'
|
|
109
|
+
}
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
# Sección Hero
|
|
113
|
+
hero_section = Container(
|
|
114
|
+
id="hero",
|
|
115
|
+
class_name="fade-in",
|
|
116
|
+
style={
|
|
117
|
+
'text-align': 'center',
|
|
118
|
+
'padding': '60px 0',
|
|
119
|
+
'background': 'linear-gradient(135deg, #f093fb 0%, #f5576c 100%)',
|
|
120
|
+
'border-radius': '20px',
|
|
121
|
+
'margin-bottom': '40px',
|
|
122
|
+
'color': 'white'
|
|
123
|
+
}
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
hero_title = Text(
|
|
127
|
+
text="Bienvenido a Dars",
|
|
128
|
+
style={
|
|
129
|
+
'font-size': '48px',
|
|
130
|
+
'font-weight': 'bold',
|
|
131
|
+
'margin-bottom': '20px'
|
|
132
|
+
}
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
hero_subtitle = Text(
|
|
136
|
+
text="Framework de UI multiplataforma en Python",
|
|
137
|
+
style={
|
|
138
|
+
'font-size': '24px',
|
|
139
|
+
'margin-bottom': '30px',
|
|
140
|
+
'opacity': '0.9'
|
|
141
|
+
}
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
hero_description = Text(
|
|
145
|
+
text="Crea interfaces de usuario modernas con Python y expórtalas a HTML, React, React Native, PySide6, C# y Kotlin",
|
|
146
|
+
style={
|
|
147
|
+
'font-size': '18px',
|
|
148
|
+
'margin-bottom': '40px',
|
|
149
|
+
'max-width': '600px',
|
|
150
|
+
'margin-left': 'auto',
|
|
151
|
+
'margin-right': 'auto',
|
|
152
|
+
'line-height': '1.6'
|
|
153
|
+
}
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
hero_cta = Button(
|
|
157
|
+
id="hero-cta",
|
|
158
|
+
text="🚀 Comenzar Ahora",
|
|
159
|
+
style={
|
|
160
|
+
'background-color': 'white',
|
|
161
|
+
'color': '#f5576c',
|
|
162
|
+
'padding': '15px 30px',
|
|
163
|
+
'border': 'none',
|
|
164
|
+
'border-radius': '30px',
|
|
165
|
+
'font-size': '18px',
|
|
166
|
+
'font-weight': 'bold',
|
|
167
|
+
'cursor': 'pointer',
|
|
168
|
+
'box-shadow': '0 4px 15px rgba(0,0,0,0.2)'
|
|
169
|
+
}
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
# Sección de características
|
|
173
|
+
features_section = Container(
|
|
174
|
+
id="features",
|
|
175
|
+
class_name="fade-in",
|
|
176
|
+
style={
|
|
177
|
+
'margin-bottom': '40px'
|
|
178
|
+
}
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
features_title = Text(
|
|
182
|
+
text="Características Principales",
|
|
183
|
+
style={
|
|
184
|
+
'font-size': '36px',
|
|
185
|
+
'font-weight': 'bold',
|
|
186
|
+
'text-align': 'center',
|
|
187
|
+
'margin-bottom': '40px',
|
|
188
|
+
'color': '#2c3e50'
|
|
189
|
+
}
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
features_grid = Container(
|
|
193
|
+
style={
|
|
194
|
+
'display': 'grid',
|
|
195
|
+
'grid-template-columns': 'repeat(auto-fit, minmax(300px, 1fr))',
|
|
196
|
+
'gap': '30px'
|
|
197
|
+
}
|
|
198
|
+
)
|
|
199
|
+
|
|
200
|
+
# Función para crear tarjetas de características
|
|
201
|
+
def crear_feature_card(icono, titulo, descripcion):
|
|
202
|
+
card = Container(
|
|
203
|
+
style={
|
|
204
|
+
'background': 'white',
|
|
205
|
+
'padding': '30px',
|
|
206
|
+
'border-radius': '15px',
|
|
207
|
+
'box-shadow': '0 5px 20px rgba(0,0,0,0.1)',
|
|
208
|
+
'text-align': 'center',
|
|
209
|
+
'transition': 'transform 0.3s ease'
|
|
210
|
+
}
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
card_icon = Text(
|
|
214
|
+
text=icono,
|
|
215
|
+
style={
|
|
216
|
+
'font-size': '48px',
|
|
217
|
+
'margin-bottom': '20px'
|
|
218
|
+
}
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
card_title = Text(
|
|
222
|
+
text=titulo,
|
|
223
|
+
style={
|
|
224
|
+
'font-size': '24px',
|
|
225
|
+
'font-weight': 'bold',
|
|
226
|
+
'margin-bottom': '15px',
|
|
227
|
+
'color': '#2c3e50'
|
|
228
|
+
}
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
card_description = Text(
|
|
232
|
+
text=descripcion,
|
|
233
|
+
style={
|
|
234
|
+
'font-size': '16px',
|
|
235
|
+
'line-height': '1.6',
|
|
236
|
+
'color': '#6c757d'
|
|
237
|
+
}
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
card.add_child(card_icon)
|
|
241
|
+
card.add_child(card_title)
|
|
242
|
+
card.add_child(card_description)
|
|
243
|
+
|
|
244
|
+
return card
|
|
245
|
+
|
|
246
|
+
# Crear tarjetas de características
|
|
247
|
+
features_data = [
|
|
248
|
+
("🐍", "Python Puro", "Escribe interfaces de usuario usando únicamente Python, sin necesidad de aprender otros lenguajes."),
|
|
249
|
+
("🌐", "Multiplataforma", "Exporta a HTML, React, React Native, PySide6, C# y Kotlin desde un solo código fuente."),
|
|
250
|
+
("⚡", "Fácil de Usar", "Sintaxis simple e intuitiva que permite crear aplicaciones complejas con pocas líneas de código."),
|
|
251
|
+
("🎨", "Personalizable", "Sistema de estilos flexible que soporta CSS moderno y temas personalizados."),
|
|
252
|
+
("🔧", "Extensible", "Arquitectura modular que permite agregar nuevos componentes y exportadores fácilmente."),
|
|
253
|
+
("📱", "Responsive", "Interfaces que se adaptan automáticamente a diferentes tamaños de pantalla y dispositivos.")
|
|
254
|
+
]
|
|
255
|
+
|
|
256
|
+
for icono, titulo, descripcion in features_data:
|
|
257
|
+
features_grid.add_child(crear_feature_card(icono, titulo, descripcion))
|
|
258
|
+
|
|
259
|
+
# Sección de demostración interactiva
|
|
260
|
+
demo_section = Container(
|
|
261
|
+
id="demo",
|
|
262
|
+
class_name="fade-in",
|
|
263
|
+
style={
|
|
264
|
+
'background': 'white',
|
|
265
|
+
'padding': '40px',
|
|
266
|
+
'border-radius': '15px',
|
|
267
|
+
'box-shadow': '0 5px 20px rgba(0,0,0,0.1)',
|
|
268
|
+
'margin-bottom': '40px'
|
|
269
|
+
}
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
demo_title = Text(
|
|
273
|
+
text="Demostración Interactiva",
|
|
274
|
+
style={
|
|
275
|
+
'font-size': '32px',
|
|
276
|
+
'font-weight': 'bold',
|
|
277
|
+
'text-align': 'center',
|
|
278
|
+
'margin-bottom': '30px',
|
|
279
|
+
'color': '#2c3e50'
|
|
280
|
+
}
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
# Formulario de demostración
|
|
284
|
+
demo_form = Container(
|
|
285
|
+
style={
|
|
286
|
+
'max-width': '500px',
|
|
287
|
+
'margin': '0 auto'
|
|
288
|
+
}
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
form_title = Text(
|
|
292
|
+
text="Prueba los Componentes",
|
|
293
|
+
style={
|
|
294
|
+
'font-size': '20px',
|
|
295
|
+
'margin-bottom': '20px',
|
|
296
|
+
'color': '#495057'
|
|
297
|
+
}
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
# Campos del formulario
|
|
301
|
+
name_input = Input(
|
|
302
|
+
id="demo-name",
|
|
303
|
+
placeholder="Tu nombre",
|
|
304
|
+
style={
|
|
305
|
+
'width': '100%',
|
|
306
|
+
'padding': '12px',
|
|
307
|
+
'border': '2px solid #e9ecef',
|
|
308
|
+
'border-radius': '8px',
|
|
309
|
+
'font-size': '16px',
|
|
310
|
+
'margin-bottom': '15px'
|
|
311
|
+
}
|
|
312
|
+
)
|
|
313
|
+
|
|
314
|
+
email_input = Input(
|
|
315
|
+
id="demo-email",
|
|
316
|
+
placeholder="tu@email.com",
|
|
317
|
+
input_type="email",
|
|
318
|
+
style={
|
|
319
|
+
'width': '100%',
|
|
320
|
+
'padding': '12px',
|
|
321
|
+
'border': '2px solid #e9ecef',
|
|
322
|
+
'border-radius': '8px',
|
|
323
|
+
'font-size': '16px',
|
|
324
|
+
'margin-bottom': '15px'
|
|
325
|
+
}
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
message_input = Input(
|
|
329
|
+
id="demo-message",
|
|
330
|
+
placeholder="Tu mensaje...",
|
|
331
|
+
style={
|
|
332
|
+
'width': '100%',
|
|
333
|
+
'padding': '12px',
|
|
334
|
+
'border': '2px solid #e9ecef',
|
|
335
|
+
'border-radius': '8px',
|
|
336
|
+
'font-size': '16px',
|
|
337
|
+
'margin-bottom': '20px',
|
|
338
|
+
'min-height': '100px'
|
|
339
|
+
}
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
demo_button = Button(
|
|
343
|
+
id="demo-submit",
|
|
344
|
+
text="Enviar Demostración",
|
|
345
|
+
style={
|
|
346
|
+
'width': '100%',
|
|
347
|
+
'background': 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
|
348
|
+
'color': 'white',
|
|
349
|
+
'padding': '15px',
|
|
350
|
+
'border': 'none',
|
|
351
|
+
'border-radius': '8px',
|
|
352
|
+
'font-size': '16px',
|
|
353
|
+
'font-weight': 'bold',
|
|
354
|
+
'cursor': 'pointer'
|
|
355
|
+
}
|
|
356
|
+
)
|
|
357
|
+
|
|
358
|
+
# Resultado de la demostración
|
|
359
|
+
demo_result = Container(
|
|
360
|
+
id="demo-result",
|
|
361
|
+
style={
|
|
362
|
+
'margin-top': '20px',
|
|
363
|
+
'padding': '20px',
|
|
364
|
+
'background-color': '#f8f9fa',
|
|
365
|
+
'border-radius': '8px',
|
|
366
|
+
'display': 'none'
|
|
367
|
+
}
|
|
368
|
+
)
|
|
369
|
+
|
|
370
|
+
result_text = Text(
|
|
371
|
+
id="result-text",
|
|
372
|
+
text="",
|
|
373
|
+
style={
|
|
374
|
+
'font-size': '16px',
|
|
375
|
+
'color': '#495057'
|
|
376
|
+
}
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
# Footer
|
|
380
|
+
footer = Container(
|
|
381
|
+
style={
|
|
382
|
+
'background-color': '#2c3e50',
|
|
383
|
+
'color': 'white',
|
|
384
|
+
'text-align': 'center',
|
|
385
|
+
'padding': '40px 20px',
|
|
386
|
+
'margin-top': 'auto'
|
|
387
|
+
}
|
|
388
|
+
)
|
|
389
|
+
|
|
390
|
+
footer_text = Text(
|
|
391
|
+
text="© 2024 PyWebUI Framework - Creado con ❤️ en Python",
|
|
392
|
+
style={
|
|
393
|
+
'font-size': '16px'
|
|
394
|
+
}
|
|
395
|
+
)
|
|
396
|
+
|
|
397
|
+
# Script principal de la aplicación
|
|
398
|
+
main_script = InlineScript(r"""
|
|
399
|
+
// Estado global de la aplicación
|
|
400
|
+
const AppState = {
|
|
401
|
+
currentSection: 'inicio',
|
|
402
|
+
animationDelay: 100,
|
|
403
|
+
isLoaded: false
|
|
404
|
+
};
|
|
405
|
+
|
|
406
|
+
// Utilidades
|
|
407
|
+
const Utils = {
|
|
408
|
+
// Animación de fade in
|
|
409
|
+
fadeIn: function(element, delay = 0) {
|
|
410
|
+
setTimeout(() => {
|
|
411
|
+
element.style.opacity = '1';
|
|
412
|
+
}, delay);
|
|
413
|
+
},
|
|
414
|
+
|
|
415
|
+
// Scroll suave
|
|
416
|
+
smoothScroll: function(target) {
|
|
417
|
+
document.querySelector(target).scrollIntoView({
|
|
418
|
+
behavior: 'smooth'
|
|
419
|
+
});
|
|
420
|
+
},
|
|
421
|
+
|
|
422
|
+
// Validar email
|
|
423
|
+
isValidEmail: function(email) {
|
|
424
|
+
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
425
|
+
return regex.test(email);
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
// Gestión de navegación
|
|
430
|
+
const Navigation = {
|
|
431
|
+
init: function() {
|
|
432
|
+
const navButtons = document.querySelectorAll('[id^="nav-"]');
|
|
433
|
+
navButtons.forEach(button => {
|
|
434
|
+
button.addEventListener('click', this.handleNavClick.bind(this));
|
|
435
|
+
|
|
436
|
+
// Efectos hover
|
|
437
|
+
button.addEventListener('mouseenter', function() {
|
|
438
|
+
this.style.borderColor = 'white';
|
|
439
|
+
this.style.backgroundColor = 'rgba(255,255,255,0.1)';
|
|
440
|
+
});
|
|
441
|
+
|
|
442
|
+
button.addEventListener('mouseleave', function() {
|
|
443
|
+
this.style.borderColor = 'transparent';
|
|
444
|
+
this.style.backgroundColor = 'transparent';
|
|
445
|
+
});
|
|
446
|
+
});
|
|
447
|
+
},
|
|
448
|
+
|
|
449
|
+
handleNavClick: function(event) {
|
|
450
|
+
const section = event.target.textContent.toLowerCase();
|
|
451
|
+
this.navigateToSection(section);
|
|
452
|
+
},
|
|
453
|
+
|
|
454
|
+
navigateToSection: function(section) {
|
|
455
|
+
AppState.currentSection = section;
|
|
456
|
+
|
|
457
|
+
// Aquí podrías implementar navegación real entre secciones
|
|
458
|
+
console.log(`Navegando a: ${section}`);
|
|
459
|
+
|
|
460
|
+
// Ejemplo de scroll a sección
|
|
461
|
+
if (section === 'componentes') {
|
|
462
|
+
Utils.smoothScroll('#demo');
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
// Gestión de animaciones
|
|
468
|
+
const Animations = {
|
|
469
|
+
init: function() {
|
|
470
|
+
this.setupIntersectionObserver();
|
|
471
|
+
this.animateHero();
|
|
472
|
+
this.setupCardHovers();
|
|
473
|
+
},
|
|
474
|
+
|
|
475
|
+
setupIntersectionObserver: function() {
|
|
476
|
+
const observer = new IntersectionObserver((entries) => {
|
|
477
|
+
entries.forEach(entry => {
|
|
478
|
+
if (entry.isIntersecting) {
|
|
479
|
+
Utils.fadeIn(entry.target, 200);
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
}, { threshold: 0.1 });
|
|
483
|
+
|
|
484
|
+
document.querySelectorAll('.fade-in').forEach(el => {
|
|
485
|
+
observer.observe(el);
|
|
486
|
+
});
|
|
487
|
+
},
|
|
488
|
+
|
|
489
|
+
animateHero: function() {
|
|
490
|
+
const hero = document.getElementById('hero');
|
|
491
|
+
if (hero) {
|
|
492
|
+
Utils.fadeIn(hero, 300);
|
|
493
|
+
}
|
|
494
|
+
},
|
|
495
|
+
|
|
496
|
+
setupCardHovers: function() {
|
|
497
|
+
const cards = document.querySelectorAll('#features > div > div');
|
|
498
|
+
cards.forEach(card => {
|
|
499
|
+
card.addEventListener('mouseenter', function() {
|
|
500
|
+
this.style.transform = 'translateY(-10px)';
|
|
501
|
+
this.style.boxShadow = '0 10px 30px rgba(0,0,0,0.15)';
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
card.addEventListener('mouseleave', function() {
|
|
505
|
+
this.style.transform = 'translateY(0)';
|
|
506
|
+
this.style.boxShadow = '0 5px 20px rgba(0,0,0,0.1)';
|
|
507
|
+
});
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
};
|
|
511
|
+
|
|
512
|
+
// Gestión del formulario de demostración
|
|
513
|
+
const DemoForm = {
|
|
514
|
+
init: function() {
|
|
515
|
+
const submitButton = document.getElementById('demo-submit');
|
|
516
|
+
if (submitButton) {
|
|
517
|
+
submitButton.addEventListener('click', this.handleSubmit.bind(this));
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// Validación en tiempo real
|
|
521
|
+
const inputs = ['demo-name', 'demo-email', 'demo-message'];
|
|
522
|
+
inputs.forEach(id => {
|
|
523
|
+
const input = document.getElementById(id);
|
|
524
|
+
if (input) {
|
|
525
|
+
input.addEventListener('input', this.validateField.bind(this));
|
|
526
|
+
input.addEventListener('blur', this.validateField.bind(this));
|
|
527
|
+
}
|
|
528
|
+
});
|
|
529
|
+
},
|
|
530
|
+
|
|
531
|
+
validateField: function(event) {
|
|
532
|
+
const field = event.target;
|
|
533
|
+
const value = field.value.trim();
|
|
534
|
+
|
|
535
|
+
// Limpiar estilos previos
|
|
536
|
+
field.style.borderColor = '#e9ecef';
|
|
537
|
+
|
|
538
|
+
if (field.id === 'demo-email' && value) {
|
|
539
|
+
if (Utils.isValidEmail(value)) {
|
|
540
|
+
field.style.borderColor = '#28a745';
|
|
541
|
+
} else {
|
|
542
|
+
field.style.borderColor = '#dc3545';
|
|
543
|
+
}
|
|
544
|
+
} else if (value) {
|
|
545
|
+
field.style.borderColor = '#28a745';
|
|
546
|
+
}
|
|
547
|
+
},
|
|
548
|
+
|
|
549
|
+
handleSubmit: function(event) {
|
|
550
|
+
event.preventDefault();
|
|
551
|
+
|
|
552
|
+
const name = document.getElementById('demo-name').value.trim();
|
|
553
|
+
const email = document.getElementById('demo-email').value.trim();
|
|
554
|
+
const message = document.getElementById('demo-message').value.trim();
|
|
555
|
+
|
|
556
|
+
// Validación
|
|
557
|
+
if (!name || !email || !message) {
|
|
558
|
+
this.showResult('Por favor, completa todos los campos.', 'error');
|
|
559
|
+
return;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
if (!Utils.isValidEmail(email)) {
|
|
563
|
+
this.showResult('Por favor, ingresa un email válido.', 'error');
|
|
564
|
+
return;
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
// Simular envío
|
|
568
|
+
this.simulateSubmission(name, email, message);
|
|
569
|
+
},
|
|
570
|
+
|
|
571
|
+
simulateSubmission: function(name, email, message) {
|
|
572
|
+
const button = document.getElementById('demo-submit');
|
|
573
|
+
const originalText = button.textContent;
|
|
574
|
+
|
|
575
|
+
button.textContent = 'Enviando...';
|
|
576
|
+
button.disabled = true;
|
|
577
|
+
button.style.opacity = '0.7';
|
|
578
|
+
|
|
579
|
+
setTimeout(() => {
|
|
580
|
+
this.showResult(`¡Gracias ${name}! Tu mensaje ha sido enviado correctamente. Te contactaremos en ${email}.`, 'success');
|
|
581
|
+
|
|
582
|
+
// Limpiar formulario
|
|
583
|
+
document.getElementById('demo-name').value = '';
|
|
584
|
+
document.getElementById('demo-email').value = '';
|
|
585
|
+
document.getElementById('demo-message').value = '';
|
|
586
|
+
|
|
587
|
+
// Restaurar botón
|
|
588
|
+
button.textContent = originalText;
|
|
589
|
+
button.disabled = false;
|
|
590
|
+
button.style.opacity = '1';
|
|
591
|
+
}, 2000);
|
|
592
|
+
},
|
|
593
|
+
|
|
594
|
+
showResult: function(message, type) {
|
|
595
|
+
const resultContainer = document.getElementById('demo-result');
|
|
596
|
+
const resultText = document.getElementById('result-text');
|
|
597
|
+
|
|
598
|
+
if (resultContainer && resultText) {
|
|
599
|
+
resultText.textContent = message;
|
|
600
|
+
resultContainer.style.display = 'block';
|
|
601
|
+
resultContainer.style.backgroundColor = type === 'success' ? '#d4edda' : '#f8d7da';
|
|
602
|
+
resultContainer.style.color = type === 'success' ? '#155724' : '#721c24';
|
|
603
|
+
resultContainer.style.borderLeft = `4px solid ${type === 'success' ? '#28a745' : '#dc3545'}`;
|
|
604
|
+
|
|
605
|
+
// Auto-ocultar después de 5 segundos
|
|
606
|
+
setTimeout(() => {
|
|
607
|
+
resultContainer.style.display = 'none';
|
|
608
|
+
}, 5000);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
};
|
|
612
|
+
|
|
613
|
+
// Efectos especiales
|
|
614
|
+
const SpecialEffects = {
|
|
615
|
+
init: function() {
|
|
616
|
+
this.setupHeroCTA();
|
|
617
|
+
this.setupParallax();
|
|
618
|
+
},
|
|
619
|
+
|
|
620
|
+
setupHeroCTA: function() {
|
|
621
|
+
const ctaButton = document.getElementById('hero-cta');
|
|
622
|
+
if (ctaButton) {
|
|
623
|
+
ctaButton.addEventListener('click', function() {
|
|
624
|
+
Utils.smoothScroll('#demo');
|
|
625
|
+
});
|
|
626
|
+
|
|
627
|
+
ctaButton.addEventListener('mouseenter', function() {
|
|
628
|
+
this.style.transform = 'translateY(-2px)';
|
|
629
|
+
this.style.boxShadow = '0 6px 20px rgba(0,0,0,0.3)';
|
|
630
|
+
});
|
|
631
|
+
|
|
632
|
+
ctaButton.addEventListener('mouseleave', function() {
|
|
633
|
+
this.style.transform = 'translateY(0)';
|
|
634
|
+
this.style.boxShadow = '0 4px 15px rgba(0,0,0,0.2)';
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
},
|
|
638
|
+
|
|
639
|
+
setupParallax: function() {
|
|
640
|
+
window.addEventListener('scroll', function() {
|
|
641
|
+
const scrolled = window.pageYOffset;
|
|
642
|
+
const hero = document.getElementById('hero');
|
|
643
|
+
|
|
644
|
+
if (hero) {
|
|
645
|
+
const speed = scrolled * 0.5;
|
|
646
|
+
hero.style.transform = `translateY(${speed}px)`;
|
|
647
|
+
}
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
};
|
|
651
|
+
|
|
652
|
+
// Inicialización principal
|
|
653
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
654
|
+
console.log('🚀 Dars Demo App iniciada');
|
|
655
|
+
|
|
656
|
+
// Inicializar módulos
|
|
657
|
+
Navigation.init();
|
|
658
|
+
Animations.init();
|
|
659
|
+
DemoForm.init();
|
|
660
|
+
SpecialEffects.init();
|
|
661
|
+
|
|
662
|
+
// Marcar como cargada
|
|
663
|
+
AppState.isLoaded = true;
|
|
664
|
+
|
|
665
|
+
// Mensaje de bienvenida
|
|
666
|
+
setTimeout(() => {
|
|
667
|
+
console.log('✨ Todas las funcionalidades cargadas correctamente');
|
|
668
|
+
}, 1000);
|
|
669
|
+
});
|
|
670
|
+
|
|
671
|
+
// Manejo de errores globales
|
|
672
|
+
window.addEventListener('error', function(e) {
|
|
673
|
+
console.error('Error en la aplicación:', e.error);
|
|
674
|
+
});
|
|
675
|
+
""")
|
|
676
|
+
|
|
677
|
+
# Ensamblar la aplicación
|
|
678
|
+
nav_container.add_child(logo)
|
|
679
|
+
nav_container.add_child(nav_menu)
|
|
680
|
+
header.add_child(nav_container)
|
|
681
|
+
|
|
682
|
+
hero_section.add_child(hero_title)
|
|
683
|
+
hero_section.add_child(hero_subtitle)
|
|
684
|
+
hero_section.add_child(hero_description)
|
|
685
|
+
hero_section.add_child(hero_cta)
|
|
686
|
+
|
|
687
|
+
features_section.add_child(features_title)
|
|
688
|
+
features_section.add_child(features_grid)
|
|
689
|
+
|
|
690
|
+
demo_form.add_child(form_title)
|
|
691
|
+
demo_form.add_child(name_input)
|
|
692
|
+
demo_form.add_child(email_input)
|
|
693
|
+
demo_form.add_child(message_input)
|
|
694
|
+
demo_form.add_child(demo_button)
|
|
695
|
+
|
|
696
|
+
demo_result.add_child(result_text)
|
|
697
|
+
demo_form.add_child(demo_result)
|
|
698
|
+
|
|
699
|
+
demo_section.add_child(demo_title)
|
|
700
|
+
demo_section.add_child(demo_form)
|
|
701
|
+
|
|
702
|
+
content_area.add_child(hero_section)
|
|
703
|
+
content_area.add_child(features_section)
|
|
704
|
+
content_area.add_child(demo_section)
|
|
705
|
+
|
|
706
|
+
footer.add_child(footer_text)
|
|
707
|
+
|
|
708
|
+
main_container.add_child(header)
|
|
709
|
+
main_container.add_child(content_area)
|
|
710
|
+
main_container.add_child(footer)
|
|
711
|
+
|
|
712
|
+
app.set_root(main_container)
|
|
713
|
+
app.add_script(main_script)
|
|
714
|
+
|
|
715
|
+
# Para exportar esta aplicación, ejecuta:
|
|
716
|
+
# dars export examples/demo/complete_app.py --format html --output ./complete_app_output
|
|
717
|
+
|
|
718
|
+
if __name__ == "__main__":
|
|
719
|
+
app.rTimeCompile() # Preview/compilación rápida
|
|
720
|
+
|
|
File without changes
|