dars-framework 1.2.3__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.
Files changed (118) hide show
  1. dars/__init__.py +0 -0
  2. dars/all.py +69 -0
  3. dars/cli/__init__.py +0 -0
  4. dars/cli/doctor/__init__.py +1 -0
  5. dars/cli/doctor/detect.py +154 -0
  6. dars/cli/doctor/doctor.py +176 -0
  7. dars/cli/doctor/installers.py +100 -0
  8. dars/cli/doctor/persist.py +62 -0
  9. dars/cli/doctor/preflight.py +33 -0
  10. dars/cli/doctor/ui.py +54 -0
  11. dars/cli/hot_reload.py +33 -0
  12. dars/cli/main.py +1107 -0
  13. dars/cli/preview.py +448 -0
  14. dars/cli/translations.py +531 -0
  15. dars/components/__init__.py +0 -0
  16. dars/components/advanced/__init__.py +8 -0
  17. dars/components/advanced/accordion.py +26 -0
  18. dars/components/advanced/card.py +33 -0
  19. dars/components/advanced/modal.py +45 -0
  20. dars/components/advanced/navbar.py +44 -0
  21. dars/components/advanced/table.py +25 -0
  22. dars/components/advanced/tabs.py +31 -0
  23. dars/components/basic/__init__.py +34 -0
  24. dars/components/basic/button.py +55 -0
  25. dars/components/basic/checkbox.py +35 -0
  26. dars/components/basic/container.py +29 -0
  27. dars/components/basic/datepicker.py +139 -0
  28. dars/components/basic/image.py +36 -0
  29. dars/components/basic/input.py +57 -0
  30. dars/components/basic/link.py +31 -0
  31. dars/components/basic/markdown.py +86 -0
  32. dars/components/basic/page.py +20 -0
  33. dars/components/basic/progressbar.py +18 -0
  34. dars/components/basic/radiobutton.py +35 -0
  35. dars/components/basic/select.py +82 -0
  36. dars/components/basic/slider.py +63 -0
  37. dars/components/basic/spinner.py +12 -0
  38. dars/components/basic/text.py +23 -0
  39. dars/components/basic/textarea.py +46 -0
  40. dars/components/basic/tooltip.py +19 -0
  41. dars/components/layout/__init__.py +0 -0
  42. dars/components/layout/anchor.py +13 -0
  43. dars/components/layout/flex.py +26 -0
  44. dars/components/layout/grid.py +45 -0
  45. dars/config.py +134 -0
  46. dars/core/__init__.py +0 -0
  47. dars/core/app.py +957 -0
  48. dars/core/component.py +284 -0
  49. dars/core/events.py +102 -0
  50. dars/core/js_bridge.py +99 -0
  51. dars/core/properties.py +127 -0
  52. dars/core/state.py +309 -0
  53. dars/dars_tests/apps_test/health_check.py +56 -0
  54. dars/dars_tests/run_tests.py +275 -0
  55. dars/dars_tests/tests/test_advanced_components.py +69 -0
  56. dars/dars_tests/tests/test_basic_components.py +88 -0
  57. dars/dars_tests/tests/test_core_and_cli.py +17 -0
  58. dars/dars_tests/tests/test_layout_components.py +58 -0
  59. dars/dars_tests/tests/test_version_check.py +21 -0
  60. dars/docs/__init__.py +0 -0
  61. dars/docs/app.md +290 -0
  62. dars/docs/cli.md +80 -0
  63. dars/docs/components.md +1679 -0
  64. dars/docs/custom_components.md +30 -0
  65. dars/docs/events.md +45 -0
  66. dars/docs/exporters.md +162 -0
  67. dars/docs/getting_started.md +79 -0
  68. dars/docs/index.md +18 -0
  69. dars/docs/scripts.md +593 -0
  70. dars/docs/state_management.md +57 -0
  71. dars/exporters/__init__.py +0 -0
  72. dars/exporters/base.py +96 -0
  73. dars/exporters/web/OLD/html_css_js_OLD4.py +1538 -0
  74. dars/exporters/web/OLD/html_css_js_old.py +1406 -0
  75. dars/exporters/web/OLD/html_css_js_old2.py +1406 -0
  76. dars/exporters/web/__init__.py +0 -0
  77. dars/exporters/web/html_css_js.py +2675 -0
  78. dars/exporters/web/vdom.py +251 -0
  79. dars/js_lib.py +206 -0
  80. dars/scripts/__init__.py +0 -0
  81. dars/scripts/dscript.py +26 -0
  82. dars/scripts/script.py +39 -0
  83. dars/security.py +195 -0
  84. dars/templates/__init__.py +0 -0
  85. dars/templates/__pycache__/__init__.cpython-311.pyc +0 -0
  86. dars/templates/examples/README.md +4 -0
  87. dars/templates/examples/__pycache__/dynamic_event_demo.cpython-311.pyc +0 -0
  88. dars/templates/examples/advanced/Modal_Demo/advanced_modal_demo.py +275 -0
  89. dars/templates/examples/advanced/SimpleDashboard/dashboard.py +437 -0
  90. dars/templates/examples/advanced/SimpleModermWeb/modern_web_app.py +452 -0
  91. dars/templates/examples/advanced/VariousComponents/all_components_demo.py +87 -0
  92. dars/templates/examples/advanced/__init__.py +0 -0
  93. dars/templates/examples/advanced/dState/state_mods_demo.py +68 -0
  94. dars/templates/examples/basic/Forms/form_components.py +516 -0
  95. dars/templates/examples/basic/Forms/simple_form.py +379 -0
  96. dars/templates/examples/basic/HelloWorld/hello_world.py +56 -0
  97. dars/templates/examples/basic/Layouts/flex_layout_responsive.py +13 -0
  98. dars/templates/examples/basic/Layouts/grid_layout_responsive.py +12 -0
  99. dars/templates/examples/basic/Layouts/layout_multipage_demo.py +23 -0
  100. dars/templates/examples/basic/Multipage/multipage_example.py +67 -0
  101. dars/templates/examples/basic/PWA/icon-192x192.png +0 -0
  102. dars/templates/examples/basic/PWA/icon-512x512.png +0 -0
  103. dars/templates/examples/basic/PWA/pwa_custom_icons.py +33 -0
  104. dars/templates/examples/basic/__init__.py +0 -0
  105. dars/templates/examples/demo/__pycache__/complete_app.cpython-311.pyc +0 -0
  106. dars/templates/examples/demo/complete_app.py +21 -0
  107. dars/templates/examples/markdown/MarkdownTemplate/README.md +159 -0
  108. dars/templates/examples/markdown/MarkdownTemplate/markdown_template.py +21 -0
  109. dars/templates/examples/markdown/MarkdownTemplate/other_docs.md +1 -0
  110. dars/templates/examples/markdown/__init__.py +0 -0
  111. dars/templates/html/__init__.py +0 -0
  112. dars/version.py +2 -0
  113. dars_framework-1.2.3.dist-info/METADATA +15 -0
  114. dars_framework-1.2.3.dist-info/RECORD +118 -0
  115. dars_framework-1.2.3.dist-info/WHEEL +5 -0
  116. dars_framework-1.2.3.dist-info/entry_points.txt +2 -0
  117. dars_framework-1.2.3.dist-info/licenses/LICENSE +21 -0
  118. dars_framework-1.2.3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,516 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Plantilla: Componentes de Formulario - Dars Framework
4
+ Demuestra el uso completo de todos los componentes básicos de formulario:
5
+ Checkbox, RadioButton, Select, Slider, DatePicker
6
+
7
+ Esta plantilla es ideal para:
8
+ - Aprender a usar los nuevos componentes básicos
9
+ - Crear formularios complejos e interactivos
10
+ - Entender el sistema de eventos de Dars
11
+ - Diseñar interfaces de usuario modernas
12
+
13
+ Uso:
14
+ dars init mi_proyecto -t basic/form_components
15
+ """
16
+
17
+ from dars.core.app import App
18
+ from dars.components.basic.container import Container
19
+ from dars.components.basic.text import Text
20
+ from dars.components.basic.button import Button
21
+ from dars.components.basic.checkbox import Checkbox
22
+ from dars.components.basic.radiobutton import RadioButton
23
+ from dars.components.basic.select import Select, SelectOption
24
+ from dars.components.basic.slider import Slider
25
+ from dars.components.basic.datepicker import DatePicker
26
+ from dars.scripts.script import InlineScript
27
+
28
+ # Crear aplicación
29
+ app = App(title="Dars - Componentes de Formulario")
30
+
31
+ # Contenedor principal
32
+ main_container = Container(style={
33
+ 'max-width': '800px',
34
+ 'margin': '0 auto',
35
+ 'padding': '40px 20px',
36
+ 'font-family': 'Arial, sans-serif'
37
+ })
38
+
39
+ # Título principal
40
+ title = Text(
41
+ text="📋 Formulario Completo con Dars",
42
+ style={
43
+ 'font-size': '32px',
44
+ 'font-weight': 'bold',
45
+ 'color': '#2c3e50',
46
+ 'text-align': 'center',
47
+ 'margin-bottom': '20px',
48
+ 'display': 'block'
49
+ }
50
+ )
51
+
52
+ # Descripción
53
+ description = Text(
54
+ text="Ejemplo completo de todos los componentes básicos de formulario disponibles en Dars Framework",
55
+ style={
56
+ 'font-size': '16px',
57
+ 'color': '#7f8c8d',
58
+ 'text-align': 'center',
59
+ 'margin-bottom': '40px',
60
+ 'display': 'block'
61
+ }
62
+ )
63
+
64
+ # Sección 1: Información Personal
65
+ personal_section = Container(style={
66
+ 'margin-bottom': '30px',
67
+ 'padding': '20px',
68
+ 'border': '1px solid #e0e0e0',
69
+ 'border-radius': '8px',
70
+ 'background-color': '#f9f9f9'
71
+ })
72
+
73
+ personal_title = Text(
74
+ text="👤 Información Personal",
75
+ style={
76
+ 'font-size': '20px',
77
+ 'font-weight': 'bold',
78
+ 'color': '#34495e',
79
+ 'margin-bottom': '15px',
80
+ 'display': 'block'
81
+ }
82
+ )
83
+
84
+ # DatePicker para fecha de nacimiento
85
+ birth_date = DatePicker(
86
+ placeholder="Fecha de nacimiento",
87
+ format="DD/MM/YYYY",
88
+ required=True,
89
+ style={'margin-bottom': '15px', 'width': '200px'}
90
+ )
91
+
92
+ # Select para país
93
+ country_select = Select(
94
+ options=[
95
+ SelectOption("es", "España"),
96
+ SelectOption("mx", "México"),
97
+ SelectOption("ar", "Argentina"),
98
+ SelectOption("co", "Colombia"),
99
+ SelectOption("pe", "Perú"),
100
+ SelectOption("cl", "Chile"),
101
+ SelectOption("ve", "Venezuela"),
102
+ SelectOption("ec", "Ecuador")
103
+ ],
104
+ placeholder="Selecciona tu país",
105
+ required=True,
106
+ style={'margin-bottom': '15px', 'width': '200px'}
107
+ )
108
+
109
+ # Sección 2: Preferencias
110
+ preferences_section = Container(style={
111
+ 'margin-bottom': '30px',
112
+ 'padding': '20px',
113
+ 'border': '1px solid #e0e0e0',
114
+ 'border-radius': '8px',
115
+ 'background-color': '#f9f9f9'
116
+ })
117
+
118
+ preferences_title = Text(
119
+ text="⚙️ Preferencias",
120
+ style={
121
+ 'font-size': '20px',
122
+ 'font-weight': 'bold',
123
+ 'color': '#34495e',
124
+ 'margin-bottom': '15px',
125
+ 'display': 'block'
126
+ }
127
+ )
128
+
129
+ # Checkboxes para notificaciones
130
+ notifications_label = Text(
131
+ text="Notificaciones:",
132
+ style={'display': 'block', 'margin-bottom': '8px', 'font-weight': 'bold'}
133
+ )
134
+
135
+ email_notifications = Checkbox(
136
+ label="Recibir notificaciones por email",
137
+ name="notifications",
138
+ value="email",
139
+ checked=True
140
+ )
141
+
142
+ sms_notifications = Checkbox(
143
+ label="Recibir notificaciones por SMS",
144
+ name="notifications",
145
+ value="sms"
146
+ )
147
+
148
+ push_notifications = Checkbox(
149
+ label="Notificaciones push en el navegador",
150
+ name="notifications",
151
+ value="push",
152
+ checked=True
153
+ )
154
+
155
+ # Radio buttons para tema
156
+ theme_label = Text(
157
+ text="Tema de la aplicación:",
158
+ style={'display': 'block', 'margin-bottom': '8px', 'margin-top': '20px', 'font-weight': 'bold'}
159
+ )
160
+
161
+ theme_light = RadioButton(
162
+ label="Tema claro",
163
+ name="theme",
164
+ value="light",
165
+ checked=True
166
+ )
167
+
168
+ theme_dark = RadioButton(
169
+ label="Tema oscuro",
170
+ name="theme",
171
+ value="dark"
172
+ )
173
+
174
+ theme_auto = RadioButton(
175
+ label="Automático (según sistema)",
176
+ name="theme",
177
+ value="auto"
178
+ )
179
+
180
+ # Sección 3: Configuración Avanzada
181
+ advanced_section = Container(style={
182
+ 'margin-bottom': '30px',
183
+ 'padding': '20px',
184
+ 'border': '1px solid #e0e0e0',
185
+ 'border-radius': '8px',
186
+ 'background-color': '#f9f9f9'
187
+ })
188
+
189
+ advanced_title = Text(
190
+ text="🔧 Configuración Avanzada",
191
+ style={
192
+ 'font-size': '20px',
193
+ 'font-weight': 'bold',
194
+ 'color': '#34495e',
195
+ 'margin-bottom': '15px',
196
+ 'display': 'block'
197
+ }
198
+ )
199
+
200
+ # Slider para volumen
201
+ volume_slider = Slider(
202
+ min_value=0,
203
+ max_value=100,
204
+ value=75,
205
+ step=5,
206
+ label="Volumen de notificaciones:",
207
+ show_value=True,
208
+ style={'margin-bottom': '20px'}
209
+ )
210
+
211
+ # Slider para calidad
212
+ quality_slider = Slider(
213
+ min_value=1,
214
+ max_value=5,
215
+ value=3,
216
+ step=1,
217
+ label="Calidad de imagen (1=baja, 5=alta):",
218
+ show_value=True,
219
+ style={'margin-bottom': '20px'}
220
+ )
221
+
222
+ # Select múltiple para habilidades
223
+ skills_label = Text(
224
+ text="Habilidades técnicas:",
225
+ style={'display': 'block', 'margin-bottom': '8px', 'font-weight': 'bold'}
226
+ )
227
+
228
+ skills_select = Select(
229
+ options=[
230
+ "Python", "JavaScript", "HTML/CSS", "React", "Vue.js",
231
+ "Django", "Flask", "Node.js", "MongoDB", "PostgreSQL",
232
+ "Docker", "Kubernetes", "AWS", "Git", "Linux"
233
+ ],
234
+ placeholder="Selecciona tus habilidades (múltiple)",
235
+ multiple=True,
236
+ size=6,
237
+ style={'width': '100%', 'max-width': '400px'}
238
+ )
239
+
240
+ # Sección 4: Programación
241
+ schedule_section = Container(style={
242
+ 'margin-bottom': '30px',
243
+ 'padding': '20px',
244
+ 'border': '1px solid #e0e0e0',
245
+ 'border-radius': '8px',
246
+ 'background-color': '#f9f9f9'
247
+ })
248
+
249
+ schedule_title = Text(
250
+ text="📅 Programación",
251
+ style={
252
+ 'font-size': '20px',
253
+ 'font-weight': 'bold',
254
+ 'color': '#34495e',
255
+ 'margin-bottom': '15px',
256
+ 'display': 'block'
257
+ }
258
+ )
259
+
260
+ # DatePicker con tiempo para cita
261
+ appointment_label = Text(
262
+ text="Próxima cita:",
263
+ style={'display': 'block', 'margin-bottom': '8px', 'font-weight': 'bold'}
264
+ )
265
+
266
+ appointment_date = DatePicker(
267
+ placeholder="Selecciona fecha y hora",
268
+ format="YYYY-MM-DD",
269
+ show_time=True,
270
+ style={'margin-bottom': '15px', 'width': '250px'}
271
+ )
272
+
273
+ # DatePicker para evento
274
+ event_label = Text(
275
+ text="Fecha del evento (solo 2024):",
276
+ style={'display': 'block', 'margin-bottom': '8px', 'font-weight': 'bold'}
277
+ )
278
+
279
+ event_date = DatePicker(
280
+ placeholder="Fecha del evento",
281
+ format="DD-MM-YYYY",
282
+ min_date="01-01-2024",
283
+ max_date="31-12-2024",
284
+ style={'width': '200px'}
285
+ )
286
+
287
+ # Botones de acción
288
+ actions_container = Container(style={
289
+ 'text-align': 'center',
290
+ 'margin-top': '40px'
291
+ })
292
+
293
+ save_button = Button(
294
+ text="💾 Guardar Configuración",
295
+ style={
296
+ 'background-color': '#27ae60',
297
+ 'color': 'white',
298
+ 'padding': '12px 24px',
299
+ 'font-size': '16px',
300
+ 'font-weight': 'bold',
301
+ 'border': 'none',
302
+ 'border-radius': '6px',
303
+ 'cursor': 'pointer',
304
+ 'margin-right': '15px'
305
+ }
306
+ )
307
+
308
+ reset_button = Button(
309
+ text="🔄 Restablecer",
310
+ style={
311
+ 'background-color': '#e74c3c',
312
+ 'color': 'white',
313
+ 'padding': '12px 24px',
314
+ 'font-size': '16px',
315
+ 'font-weight': 'bold',
316
+ 'border': 'none',
317
+ 'border-radius': '6px',
318
+ 'cursor': 'pointer'
319
+ }
320
+ )
321
+
322
+ # Script para interactividad
323
+ script = InlineScript("""
324
+ document.addEventListener('DOMContentLoaded', function() {
325
+ console.log('🚀 Formulario de componentes Dars cargado');
326
+
327
+ // Actualizar valores de sliders en tiempo real
328
+ const sliders = document.querySelectorAll('input[type="range"]');
329
+ sliders.forEach(slider => {
330
+ const valueDisplay = slider.parentElement.querySelector('.dars-slider-value');
331
+ if (valueDisplay) {
332
+ slider.addEventListener('input', function() {
333
+ valueDisplay.textContent = this.value;
334
+ });
335
+ }
336
+ });
337
+
338
+ // Manejar botón de guardar
339
+ const saveBtn = document.querySelector('button[style*="27ae60"]');
340
+ if (saveBtn) {
341
+ saveBtn.addEventListener('click', function() {
342
+ const formData = collectFormData();
343
+ console.log('📊 Datos del formulario:', formData);
344
+ alert('✅ Configuración guardada exitosamente!\\n\\nRevisa la consola del navegador para ver todos los datos recopilados.');
345
+ });
346
+ }
347
+
348
+ // Manejar botón de reset
349
+ const resetBtn = document.querySelector('button[style*="e74c3c"]');
350
+ if (resetBtn) {
351
+ resetBtn.addEventListener('click', function() {
352
+ if (confirm('¿Estás seguro de que quieres restablecer todos los valores?')) {
353
+ resetForm();
354
+ alert('🔄 Formulario restablecido a valores por defecto.');
355
+ }
356
+ });
357
+ }
358
+
359
+ // Función para recopilar datos del formulario
360
+ function collectFormData() {
361
+ const data = {
362
+ personalInfo: {},
363
+ preferences: {},
364
+ advanced: {},
365
+ schedule: {}
366
+ };
367
+
368
+ // Información personal
369
+ const birthDate = document.querySelector('input[type="date"]');
370
+ if (birthDate && birthDate.value) {
371
+ data.personalInfo.birthDate = birthDate.value;
372
+ }
373
+
374
+ const countrySelect = document.querySelector('select:not([multiple])');
375
+ if (countrySelect && countrySelect.value) {
376
+ data.personalInfo.country = countrySelect.value;
377
+ }
378
+
379
+ // Preferencias - Checkboxes
380
+ const notifications = [];
381
+ const checkboxes = document.querySelectorAll('input[type="checkbox"]:checked');
382
+ checkboxes.forEach(cb => {
383
+ if (cb.name === 'notifications') {
384
+ notifications.push(cb.value);
385
+ }
386
+ });
387
+ data.preferences.notifications = notifications;
388
+
389
+ // Preferencias - Tema
390
+ const selectedTheme = document.querySelector('input[type="radio"]:checked');
391
+ if (selectedTheme) {
392
+ data.preferences.theme = selectedTheme.value;
393
+ }
394
+
395
+ // Configuración avanzada - Sliders
396
+ const sliders = document.querySelectorAll('input[type="range"]');
397
+ if (sliders.length >= 2) {
398
+ data.advanced.volume = parseInt(sliders[0].value);
399
+ data.advanced.quality = parseInt(sliders[1].value);
400
+ }
401
+
402
+ // Habilidades
403
+ const skillsSelect = document.querySelector('select[multiple]');
404
+ if (skillsSelect) {
405
+ data.advanced.skills = Array.from(skillsSelect.selectedOptions).map(opt => opt.value);
406
+ }
407
+
408
+ // Programación
409
+ const datetimeInput = document.querySelector('input[type="datetime-local"]');
410
+ if (datetimeInput && datetimeInput.value) {
411
+ data.schedule.appointment = datetimeInput.value;
412
+ }
413
+
414
+ return data;
415
+ }
416
+
417
+ // Función para restablecer formulario
418
+ function resetForm() {
419
+ // Restablecer checkboxes
420
+ document.querySelectorAll('input[type="checkbox"]').forEach(cb => {
421
+ cb.checked = cb.defaultChecked;
422
+ });
423
+
424
+ // Restablecer radio buttons
425
+ document.querySelectorAll('input[type="radio"]').forEach(radio => {
426
+ radio.checked = radio.defaultChecked;
427
+ });
428
+
429
+ // Restablecer selects
430
+ document.querySelectorAll('select').forEach(select => {
431
+ select.selectedIndex = 0;
432
+ });
433
+
434
+ // Restablecer sliders
435
+ document.querySelectorAll('input[type="range"]').forEach(slider => {
436
+ slider.value = slider.defaultValue;
437
+ const valueDisplay = slider.parentElement.querySelector('.dars-slider-value');
438
+ if (valueDisplay) {
439
+ valueDisplay.textContent = slider.value;
440
+ }
441
+ });
442
+
443
+ // Restablecer fechas
444
+ document.querySelectorAll('input[type="date"], input[type="datetime-local"]').forEach(date => {
445
+ date.value = '';
446
+ });
447
+ }
448
+ });
449
+ """)
450
+
451
+ # Ensamblar aplicación
452
+ main_container.add_child(title)
453
+ main_container.add_child(description)
454
+
455
+ # Sección personal
456
+ personal_section.add_child(personal_title)
457
+ personal_section.add_child(Text(text="Fecha de nacimiento:", style={'display': 'block', 'margin-bottom': '5px', 'font-weight': 'bold'}))
458
+ personal_section.add_child(birth_date)
459
+ personal_section.add_child(Text(text="País:", style={'display': 'block', 'margin-bottom': '5px', 'margin-top': '15px', 'font-weight': 'bold'}))
460
+ personal_section.add_child(country_select)
461
+ main_container.add_child(personal_section)
462
+
463
+ # Sección preferencias
464
+ preferences_section.add_child(preferences_title)
465
+ preferences_section.add_child(notifications_label)
466
+ preferences_section.add_child(email_notifications)
467
+ preferences_section.add_child(sms_notifications)
468
+ preferences_section.add_child(push_notifications)
469
+ preferences_section.add_child(theme_label)
470
+ preferences_section.add_child(theme_light)
471
+ preferences_section.add_child(theme_dark)
472
+ preferences_section.add_child(theme_auto)
473
+ main_container.add_child(preferences_section)
474
+
475
+ # Sección avanzada
476
+ advanced_section.add_child(advanced_title)
477
+ advanced_section.add_child(volume_slider)
478
+ advanced_section.add_child(quality_slider)
479
+ advanced_section.add_child(skills_label)
480
+ advanced_section.add_child(skills_select)
481
+ main_container.add_child(advanced_section)
482
+
483
+ # Sección programación
484
+ schedule_section.add_child(schedule_title)
485
+ schedule_section.add_child(appointment_label)
486
+ schedule_section.add_child(appointment_date)
487
+ schedule_section.add_child(event_label)
488
+ schedule_section.add_child(event_date)
489
+ main_container.add_child(schedule_section)
490
+
491
+ # Botones de acción
492
+ actions_container.add_child(save_button)
493
+ actions_container.add_child(reset_button)
494
+ main_container.add_child(actions_container)
495
+
496
+ # Configurar aplicación
497
+ app.set_root(main_container)
498
+ app.add_script(script)
499
+
500
+ # Añadir estilos globales
501
+ app.add_global_style('body', {
502
+ 'background-color': '#ecf0f1',
503
+ 'line-height': '1.6'
504
+ })
505
+
506
+ app.add_global_style('.dars-checkbox-wrapper, .dars-radio-wrapper', {
507
+ 'margin': '8px 0'
508
+ })
509
+
510
+ app.add_global_style('button:hover', {
511
+ 'transform': 'translateY(-1px)',
512
+ 'box-shadow': '0 4px 8px rgba(0,0,0,0.2)'
513
+ })
514
+
515
+ if __name__ == '__main__':
516
+ app.rTimeCompile()