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.
Files changed (68) hide show
  1. dars/__init__.py +0 -0
  2. dars/all.py +52 -0
  3. dars/cli/__init__.py +0 -0
  4. dars/cli/hot_reload.py +33 -0
  5. dars/cli/main.py +637 -0
  6. dars/cli/preview.py +419 -0
  7. dars/cli/translations.py +389 -0
  8. dars/components/__init__.py +0 -0
  9. dars/components/advanced/__init__.py +8 -0
  10. dars/components/advanced/accordion.py +21 -0
  11. dars/components/advanced/card.py +28 -0
  12. dars/components/advanced/modal.py +40 -0
  13. dars/components/advanced/navbar.py +31 -0
  14. dars/components/advanced/table.py +24 -0
  15. dars/components/advanced/tabs.py +26 -0
  16. dars/components/basic/__init__.py +34 -0
  17. dars/components/basic/button.py +29 -0
  18. dars/components/basic/checkbox.py +34 -0
  19. dars/components/basic/container.py +23 -0
  20. dars/components/basic/datepicker.py +139 -0
  21. dars/components/basic/image.py +36 -0
  22. dars/components/basic/input.py +50 -0
  23. dars/components/basic/link.py +31 -0
  24. dars/components/basic/page.py +20 -0
  25. dars/components/basic/progressbar.py +17 -0
  26. dars/components/basic/radiobutton.py +34 -0
  27. dars/components/basic/select.py +81 -0
  28. dars/components/basic/slider.py +63 -0
  29. dars/components/basic/spinner.py +11 -0
  30. dars/components/basic/text.py +22 -0
  31. dars/components/basic/textarea.py +46 -0
  32. dars/components/basic/tooltip.py +18 -0
  33. dars/components/layout/__init__.py +0 -0
  34. dars/components/layout/anchor.py +13 -0
  35. dars/components/layout/flex.py +26 -0
  36. dars/components/layout/grid.py +45 -0
  37. dars/core/__init__.py +0 -0
  38. dars/core/app.py +630 -0
  39. dars/core/component.py +25 -0
  40. dars/core/events.py +101 -0
  41. dars/core/properties.py +127 -0
  42. dars/docs/__init__.py +0 -0
  43. dars/exporters/__init__.py +0 -0
  44. dars/exporters/base.py +69 -0
  45. dars/exporters/web/__init__.py +0 -0
  46. dars/exporters/web/html_css_js.py +1406 -0
  47. dars/scripts/__init__.py +0 -0
  48. dars/scripts/script.py +38 -0
  49. dars/templates/__init__.py +0 -0
  50. dars/templates/examples/advanced/all_components_demo.py +87 -0
  51. dars/templates/examples/advanced/dashboard.py +440 -0
  52. dars/templates/examples/advanced/modern_web_app.py +452 -0
  53. dars/templates/examples/basic/flex_layout_responsive.py +13 -0
  54. dars/templates/examples/basic/form_components.py +516 -0
  55. dars/templates/examples/basic/grid_layout_responsive.py +13 -0
  56. dars/templates/examples/basic/hello_world.py +104 -0
  57. dars/templates/examples/basic/layout_multipage_demo.py +23 -0
  58. dars/templates/examples/basic/multipage_example.py +70 -0
  59. dars/templates/examples/basic/pwa_custom_icons.py +31 -0
  60. dars/templates/examples/basic/simple_form.py +377 -0
  61. dars/templates/examples/demo/complete_app.py +720 -0
  62. dars/templates/html/__init__.py +0 -0
  63. dars_framework-1.0.0.dist-info/METADATA +146 -0
  64. dars_framework-1.0.0.dist-info/RECORD +68 -0
  65. dars_framework-1.0.0.dist-info/WHEEL +5 -0
  66. dars_framework-1.0.0.dist-info/entry_points.txt +2 -0
  67. dars_framework-1.0.0.dist-info/licenses/LICENSE +21 -0
  68. dars_framework-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,389 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Dars Translations - Translation system for Dars CLI
4
+ """
5
+
6
+ # Diccionario de traducciones
7
+ translations = {
8
+ 'en': {
9
+ # CLI descriptions
10
+ 'cli_description': "Dars Exporter - Export Dars applications to Web",
11
+ 'cli_subtitle': "Multiplatform UI Framework in Python",
12
+ 'main_description': "Export Dars applications to Web",
13
+
14
+ # Commands
15
+ 'available_commands': "Available commands",
16
+ 'export_help': "Export application",
17
+ 'info_help': "Show application information",
18
+ 'formats_help': "Show supported formats",
19
+ 'preview_help': "Preview information",
20
+ 'preview_cmd_help': "Preview exported application",
21
+ 'init_help': "Create a Dars project",
22
+
23
+ # Export command
24
+ 'file_help': "Python file with Dars application",
25
+ 'format_help': "Export format",
26
+ 'output_help': "Output directory",
27
+ 'preview_arg_help': "Show preview information (HTML only)",
28
+
29
+ # Init command
30
+ 'name_help': "Project name",
31
+ 'template_help': "Initial template: category/name (e.g. basic/hello_world)",
32
+
33
+ # Preview command
34
+ 'path_help': "Directory with exported application",
35
+ 'preview_description': "Dars Preview - Preview system",
36
+ 'directory_help': "Directory with the exported application",
37
+ 'no_open_help': "Do not automatically open the browser",
38
+ 'port_help': "Port for the server (HTML only)",
39
+ 'lang_help': "Language for the preview (en or es)",
40
+
41
+ # Preview server messages
42
+ 'server_start_error': "Error starting server: {error}",
43
+ 'preview_server_started': "Preview server started",
44
+ 'directory': "Directory",
45
+ 'port': "Port",
46
+ 'press_ctrl_c': "Press Ctrl+C to stop the server",
47
+ 'opening_in_browser': "Opening in browser: {url}",
48
+ 'browser_open_error': "Could not open browser automatically: {error}",
49
+ 'open_manually': "Open manually: {url}",
50
+ 'stopping_server': "Stopping server...",
51
+ 'server_stopped': "Server stopped",
52
+
53
+ # Preview HTML app
54
+ 'html_preview': "HTML Preview",
55
+ 'index_html_missing': "Error: index.html not found in {directory}",
56
+
57
+ # Preview React app
58
+ 'react_preview': "React App Preview",
59
+ 'react_package_json_missing': "Error: package.json not found in {directory}",
60
+ 'react_navigate': "1. Navigate to the directory: cd {directory}",
61
+ 'react_install': "2. Install dependencies: npm install",
62
+ 'react_start': "3. Start the development server: npm start",
63
+ 'react_auto_open': "The app will open automatically in your browser",
64
+
65
+ # Preview React Native app
66
+ 'react_native_preview': "React Native App Preview",
67
+ 'react_native_package_json_missing': "Error: package.json not found in {directory}",
68
+ 'react_native_navigate': "1. Navigate to the directory: cd {directory}",
69
+ 'react_native_install': "2. Install dependencies: npm install",
70
+ 'react_native_android': "3. For Android: npm run android",
71
+ 'react_native_ios': "4. For iOS: npm run ios",
72
+ 'react_native_start': "5. Start Metro bundler: npm start",
73
+ 'react_native_note': "Note: Make sure you have the React Native development environment set up",
74
+
75
+ # Preview PySide6 app
76
+ 'pyside6_preview': "PySide6 App Preview",
77
+ 'pyside6_main_missing': "Error: main.py not found in {directory}",
78
+ 'pyside6_navigate': "1. Navigate to the directory: cd {directory}",
79
+ 'pyside6_install': "2. Install dependencies: pip install -r requirements.txt (if available)",
80
+ 'pyside6_run': "3. Run the application: python main.py",
81
+ 'pyside6_note': "Note: Make sure you have PySide6 installed (pip install pyside6)",
82
+
83
+ # Preview C# app
84
+ 'csharp_preview': "C# App Preview",
85
+ 'csharp_project_missing': "Error: No .csproj file found in {directory}",
86
+ 'csharp_navigate': "1. Navigate to the directory: cd {directory}",
87
+ 'csharp_restore': "2. Restore dependencies: dotnet restore",
88
+ 'csharp_build': "3. Build the application: dotnet build",
89
+ 'csharp_run': "4. Run the application: dotnet run",
90
+ 'csharp_note': "Note: Make sure you have .NET SDK installed",
91
+
92
+ # Preview Kotlin app
93
+ 'kotlin_preview': "Kotlin Multiplatform App Preview",
94
+ 'kotlin_gradle_missing': "Error: build.gradle.kts not found in {directory}",
95
+ 'kotlin_navigate': "1. Navigate to the directory: cd {directory}",
96
+ 'kotlin_desktop': "2. Run for desktop: ./gradlew run",
97
+ 'kotlin_android': "3. Install for Android: ./gradlew installDebug",
98
+ 'kotlin_build_all': "4. Build for all platforms: ./gradlew build",
99
+ 'kotlin_note': "Note: Make sure you have JDK and Android SDK installed",
100
+
101
+ # Preview app
102
+ 'directory_not_exists': "Error: The directory {directory} does not exist",
103
+ 'format_not_detected': "Error: Could not detect the application format in {directory}",
104
+ 'detected_format': "Detected format",
105
+ 'format_not_supported': "Error: Format '{format}' not supported for preview",
106
+
107
+ # Help sections
108
+ 'usage': "USAGE",
109
+ 'positional_arguments': "POSITIONAL ARGUMENTS",
110
+ 'options': "OPTIONS",
111
+ 'commands': "AVAILABLE COMMANDS",
112
+ 'examples': "EXAMPLES",
113
+ 'help_arg_message': "show this help message and exit",
114
+
115
+ # Examples
116
+ 'usage_examples': "Usage examples",
117
+ 'examples_text': """
118
+ dars export app.py --format html --output ./dist
119
+ dars info app.py
120
+ dars preview ./dist
121
+ dars init my_new_project
122
+ dars init my_new_project -t demo/complete_app
123
+ """,
124
+
125
+ # Messages
126
+ 'app_found': "Application found at: {}",
127
+ 'open_in_browser': "Open in browser: file://{}",
128
+ 'preview_question': "Do you want to see the preview? [green]y[/green] / [red]n[/red] [y/n] ",
129
+ 'index_not_found': "index.html not found in {}",
130
+ 'dir_created': "Directory '{}' created",
131
+ 'template_copied': "Template '{template}' copied as main.py",
132
+ 'main_created': "main.py file created (default Hello World)",
133
+ 'project_initialized': "🎉 Dars project successfully initialized",
134
+ 'export_command': "To export the template use",
135
+ 'preview_command': "To view the project in a browser use",
136
+
137
+ # Formats
138
+ 'supported_formats': "Supported export formats",
139
+ 'format_name': "Format",
140
+ 'format_description': "Description",
141
+ 'html_description': "Standard HTML/CSS/JavaScript",
142
+
143
+ # App info
144
+ 'app_info': "Application Information: {}",
145
+ 'property': "Property",
146
+ 'value': "Value",
147
+ 'title': "Title",
148
+ 'total_components': "Total components",
149
+ 'max_depth': "Maximum depth",
150
+ 'scripts': "Scripts",
151
+ 'global_styles': "Global styles",
152
+ 'theme': "Theme",
153
+ 'responsive': "Responsive",
154
+ 'component_structure': "Component Structure"
155
+ },
156
+ 'es': {
157
+ # CLI descriptions
158
+ 'cli_description': "Dars Exporter - Exporta aplicaciones Dars a Web",
159
+ 'cli_subtitle': "Framework de UI multiplataforma en Python",
160
+ 'main_description': "Dars Exporter - Exporta aplicaciones Dars a Web",
161
+
162
+ # Commands
163
+ 'available_commands': "Comandos disponibles",
164
+ 'export_help': "Exportar aplicación",
165
+ 'info_help': "Mostrar información de la aplicación",
166
+ 'formats_help': "Mostrar formatos soportados",
167
+ 'preview_help': "Información de preview",
168
+ 'preview_cmd_help': "Previsualizar aplicación exportada",
169
+ 'init_help': "Crea un proyecto Dars",
170
+
171
+ # Export command
172
+ 'file_help': "Archivo Python con la aplicación Dars",
173
+ 'format_help': "Formato de exportación",
174
+ 'output_help': "Directorio de salida",
175
+ 'preview_arg_help': "Mostrar información de preview (solo para HTML)",
176
+
177
+ # Init command
178
+ 'name_help': "Nombre del proyecto",
179
+ 'template_help': "Plantilla inicial: categoría/nombre (por ejemplo basic/hello_world)",
180
+
181
+ # Preview command
182
+ 'path_help': "Directorio con la aplicación exportada",
183
+ 'preview_description': "Dars Preview - Sistema de preview",
184
+ 'directory_help': "Directorio con la aplicación exportada",
185
+ 'no_open_help': "No abrir automáticamente el navegador",
186
+ 'port_help': "Puerto para el servidor (solo HTML)",
187
+ 'lang_help': "Idioma para la preview (en o es)",
188
+
189
+ # Preview server messages
190
+ 'server_start_error': "Error al iniciar el servidor: {error}",
191
+ 'preview_server_started': "Servidor de preview iniciado",
192
+ 'directory': "Directorio",
193
+ 'port': "Puerto",
194
+ 'press_ctrl_c': "Presiona Ctrl+C para detener el servidor",
195
+ 'opening_in_browser': "Abriendo en navegador: {url}",
196
+ 'browser_open_error': "No se pudo abrir el navegador automáticamente: {error}",
197
+ 'open_manually': "Abrir manualmente: {url}",
198
+ 'stopping_server': "Deteniendo servidor...",
199
+ 'server_stopped': "Servidor detenido",
200
+
201
+ # Preview HTML app
202
+ 'html_preview': "Preview HTML",
203
+ 'index_html_missing': "Error: No se encontró index.html en {directory}",
204
+
205
+ # Preview React app
206
+ 'react_preview': "Preview de App React",
207
+ 'react_package_json_missing': "Error: No se encontró package.json en {directory}",
208
+ 'react_navigate': "1. Navega al directorio: cd {directory}",
209
+ 'react_install': "2. Instala dependencias: npm install",
210
+ 'react_start': "3. Inicia el servidor de desarrollo: npm start",
211
+ 'react_auto_open': "La aplicación se abrirá automáticamente en tu navegador",
212
+
213
+ # Preview React Native app
214
+ 'react_native_preview': "Preview de App React Native",
215
+ 'react_native_package_json_missing': "Error: No se encontró package.json en {directory}",
216
+ 'react_native_navigate': "1. Navega al directorio: cd {directory}",
217
+ 'react_native_install': "2. Instala dependencias: npm install",
218
+ 'react_native_android': "3. Para Android: npm run android",
219
+ 'react_native_ios': "4. Para iOS: npm run ios",
220
+ 'react_native_start': "5. Inicia Metro bundler: npm start",
221
+ 'react_native_note': "Nota: Asegúrate de tener configurado el entorno de desarrollo de React Native",
222
+
223
+ # Preview PySide6 app
224
+ 'pyside6_preview': "Preview de App PySide6",
225
+ 'pyside6_main_missing': "Error: No se encontró main.py en {directory}",
226
+ 'pyside6_navigate': "1. Navega al directorio: cd {directory}",
227
+ 'pyside6_install': "2. Instala dependencias: pip install -r requirements.txt (si está disponible)",
228
+ 'pyside6_run': "3. Ejecuta la aplicación: python main.py",
229
+ 'pyside6_note': "Nota: Asegúrate de tener PySide6 instalado (pip install pyside6)",
230
+
231
+ # Preview C# app
232
+ 'csharp_preview': "Preview de App C#",
233
+ 'csharp_project_missing': "Error: No se encontró archivo .csproj en {directory}",
234
+ 'csharp_navigate': "1. Navega al directorio: cd {directory}",
235
+ 'csharp_restore': "2. Restaura dependencias: dotnet restore",
236
+ 'csharp_build': "3. Compila la aplicación: dotnet build",
237
+ 'csharp_run': "4. Ejecuta la aplicación: dotnet run",
238
+ 'csharp_note': "Nota: Asegúrate de tener instalado .NET SDK",
239
+
240
+ # Preview Kotlin app
241
+ 'kotlin_preview': "Preview de App Kotlin Multiplatform",
242
+ 'kotlin_gradle_missing': "Error: No se encontró build.gradle.kts en {directory}",
243
+ 'kotlin_navigate': "1. Navega al directorio: cd {directory}",
244
+ 'kotlin_desktop': "2. Ejecutar para desktop: ./gradlew run",
245
+ 'kotlin_android': "3. Instalar para Android: ./gradlew installDebug",
246
+ 'kotlin_build_all': "4. Compilar para todas las plataformas: ./gradlew build",
247
+ 'kotlin_note': "Nota: Asegúrate de tener instalado JDK y Android SDK",
248
+
249
+ # Preview app
250
+ 'directory_not_exists': "Error: El directorio {directory} no existe",
251
+ 'format_not_detected': "Error: No se pudo detectar el formato de la aplicación en {directory}",
252
+ 'detected_format': "Formato detectado",
253
+ 'format_not_supported': "Error: Formato '{format}' no soportado para preview",
254
+
255
+ # Help sections
256
+ 'usage': "USO",
257
+ 'positional_arguments': "ARGUMENTOS POSICIONALES",
258
+ 'options': "OPCIONES",
259
+ 'commands': "COMANDOS DISPONIBLES",
260
+ 'examples': "EJEMPLOS",
261
+ 'help_arg_message': "muestra este mensaje de ayuda y sal",
262
+
263
+ # Examples
264
+ 'usage_examples': "Ejemplos de uso",
265
+ 'examples_text': """
266
+ dars export app.py --format html --output ./dist
267
+ dars info app.py
268
+ dars preview ./dist
269
+ dars init mi_nuevo_proyecto
270
+ dars init mi_nuevo_proyecto -t demo/complete_app
271
+ """,
272
+
273
+ # Messages
274
+ 'app_found': "Aplicación encontrada en: {}",
275
+ 'open_in_browser': "Abrir en navegador: file://{}",
276
+ 'preview_question': "¿Quieres ver la preview? [green]y[/green] / [red]n[/red] [y/n] ",
277
+ 'index_not_found': "No se encontró index.html en {}",
278
+ 'dir_created': "Directorio '{}' creado",
279
+ 'template_copied': "Template '{template}' copiado como main.py",
280
+ 'main_created': "Archivo main.py creado (Hello World por defecto)",
281
+ 'project_initialized': "🎉 Proyecto Dars inicializado exitosamente",
282
+ 'export_command': "Para exportar el template usa",
283
+ 'preview_command': "Para ver el proyecto en un navegador usa",
284
+
285
+ # Formats
286
+ 'supported_formats': "Formatos de exportación soportados",
287
+ 'format_name': "Formato",
288
+ 'format_description': "Descripción",
289
+ 'html_description': "HTML/CSS/JavaScript estándar",
290
+
291
+ # App info
292
+ 'app_info': "Información de la Aplicación: {}",
293
+ 'property': "Propiedad",
294
+ 'value': "Valor",
295
+ 'title': "Título",
296
+ 'total_components': "Componentes totales",
297
+ 'max_depth': "Profundidad máxima",
298
+ 'scripts': "Scripts",
299
+ 'global_styles': "Estilos globales",
300
+ 'theme': "Tema",
301
+ 'responsive': "Responsive",
302
+ 'component_structure': "Estructura de Componentes"
303
+ }
304
+ }
305
+
306
+ import os
307
+ import configparser
308
+
309
+ class Translator:
310
+ """Class for handling translations"""
311
+
312
+ def __init__(self, language='en'):
313
+ self.config_file = self._get_config_path()
314
+ self.language = self._load_language_preference() or language
315
+
316
+ def _get_config_path(self):
317
+ """Returns the path to the configuration file"""
318
+ # Use user's home directory for configuration
319
+ home_dir = os.path.expanduser("~")
320
+ dars_config_dir = os.path.join(home_dir, ".dars")
321
+
322
+ # Create the directory if it doesn't exist
323
+ if not os.path.exists(dars_config_dir):
324
+ os.makedirs(dars_config_dir)
325
+
326
+ return os.path.join(dars_config_dir, "config.ini")
327
+
328
+ def _load_language_preference(self):
329
+ """Loads the language preference from the configuration file"""
330
+ config = configparser.ConfigParser()
331
+
332
+ if os.path.exists(self.config_file):
333
+ config.read(self.config_file)
334
+ if 'preferences' in config and 'language' in config['preferences']:
335
+ lang = config['preferences']['language']
336
+ if lang in translations:
337
+ return lang
338
+ return None
339
+
340
+ def _save_language_preference(self):
341
+ """Saves the current language preference to the configuration file"""
342
+ config = configparser.ConfigParser()
343
+
344
+ # Load existing config if it exists
345
+ if os.path.exists(self.config_file):
346
+ config.read(self.config_file)
347
+
348
+ # Ensure the preferences section exists
349
+ if 'preferences' not in config:
350
+ config['preferences'] = {}
351
+
352
+ # Update the language preference
353
+ config['preferences']['language'] = self.language
354
+
355
+ # Save the configuration
356
+ with open(self.config_file, 'w') as configfile:
357
+ config.write(configfile)
358
+
359
+ def set_language(self, language, save=True):
360
+ """Sets the current language and optionally saves the preference"""
361
+ if language in translations:
362
+ self.language = language
363
+ if save:
364
+ self._save_language_preference()
365
+ else:
366
+ print(f"Language {language} not supported, using default (en)")
367
+ self.language = 'en'
368
+ if save:
369
+ self._save_language_preference()
370
+
371
+ def get(self, key, **kwargs):
372
+ """Gets a translation by its key"""
373
+ if self.language in translations and key in translations[self.language]:
374
+ text = translations[self.language][key]
375
+ # Apply formatting if there are arguments
376
+ if kwargs:
377
+ return text.format(**kwargs)
378
+ return text
379
+ # Fallback to English if the key is not found in current language
380
+ if 'en' in translations and key in translations['en']:
381
+ text = translations['en'][key]
382
+ if kwargs:
383
+ return text.format(**kwargs)
384
+ return text
385
+ # If not found in any language, return the key
386
+ return key
387
+
388
+ # Instancia global del traductor
389
+ translator = Translator()
File without changes
@@ -0,0 +1,8 @@
1
+ from .card import Card
2
+ from .modal import Modal
3
+ from .navbar import Navbar
4
+ from .table import Table
5
+ from .tabs import Tabs
6
+ from .accordion import Accordion
7
+
8
+ __all__ = ['Card', 'Modal', 'Navbar', 'Table', 'Tabs', 'Accordion']
@@ -0,0 +1,21 @@
1
+ from dars.core.component import Component
2
+ from typing import List, Optional
3
+
4
+ class Accordion(Component):
5
+ """
6
+ Componente Accordion para mostrar secciones colapsables.
7
+ sections: Lista de tuplas (título, contenido)
8
+ open_indices: Lista de índices abiertos (opcional)
9
+ """
10
+ def __init__(self, sections: List[tuple], open_indices: Optional[List[int]]=None, **props):
11
+ super().__init__(**props)
12
+ self.sections = sections
13
+ self.open_indices = open_indices or []
14
+
15
+ def render(self) -> str:
16
+ html = '<div class="dars-accordion">'
17
+ for i, (title, content) in enumerate(self.sections):
18
+ opened = ' dars-accordion-open' if i in self.open_indices else ''
19
+ html += f'<div class="dars-accordion-section{opened}"><div class="dars-accordion-title">{title}</div><div class="dars-accordion-content">{content.render() if hasattr(content, "render") else content}</div></div>'
20
+ html += '</div>'
21
+ return html
@@ -0,0 +1,28 @@
1
+ from dars.core.component import Component
2
+ from typing import Optional, Dict, Any, List
3
+
4
+ class Card(Component):
5
+ """Componente para mostrar contenido en una tarjeta."""
6
+ def __init__(
7
+ self,
8
+ children: Optional[List[Component]] = None,
9
+ title: Optional[str] = None,
10
+ class_name: Optional[str] = None,
11
+ style: Optional[Dict[str, Any]] = None,
12
+ **kwargs
13
+ ):
14
+ super().__init__(children=children, class_name=class_name, style=style, **kwargs)
15
+ self.title = title
16
+
17
+ def render(self) -> str:
18
+ title_html = f'<h2>{self.title}</h2>' if self.title else ''
19
+ children_html = ''.join([child.render() for child in self.children])
20
+
21
+ attrs = []
22
+ if self.class_name: attrs.append(f'class="dars-card {self.class_name}"')
23
+ else: attrs.append('class="dars-card"')
24
+ if self.style: attrs.append(f'style="{self.render_styles(self.style)}"')
25
+
26
+ return f'<div {" ".join(attrs)}>{title_html}{children_html}</div>'
27
+
28
+
@@ -0,0 +1,40 @@
1
+ from dars.core.component import Component
2
+ from typing import Optional, Dict, Any, List
3
+
4
+ class Modal(Component):
5
+ """Componente para mostrar contenido en un modal."""
6
+ def __init__(
7
+ self,
8
+ children: Optional[List[Component]] = None,
9
+ title: Optional[str] = None,
10
+ is_open: bool = False,
11
+ class_name: Optional[str] = None,
12
+ style: Optional[Dict[str, Any]] = None,
13
+ **kwargs
14
+ ):
15
+ super().__init__(children=children, class_name=class_name, style=style, **kwargs)
16
+ self.title = title
17
+ self.is_open = is_open
18
+
19
+ def render(self) -> str:
20
+ title_html = f'<h2>{self.title}</h2>' if self.title else ''
21
+ children_html = ''.join([child.render() for child in self.children])
22
+
23
+ display_style = 'display: flex' if self.is_open else 'display: none'
24
+
25
+ attrs = []
26
+ if self.class_name: attrs.append(f'class="dars-modal {self.class_name}"')
27
+ else: attrs.append('class="dars-modal"')
28
+
29
+ modal_style = f'{display_style}; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0,0,0,0.5); justify-content: center; align-items: center; z-index: 1000'
30
+ if self.style:
31
+ modal_style += f'; {self.render_styles(self.style)}'
32
+ attrs.append(f'style="{modal_style}"')
33
+
34
+ return f'''<div {" ".join(attrs)}>
35
+ <div class="dars-modal-content" style="background: white; padding: 20px; border-radius: 8px; max-width: 500px; width: 90%;">
36
+ {title_html}
37
+ {children_html}
38
+ </div>
39
+ </div>'''
40
+
@@ -0,0 +1,31 @@
1
+ from dars.core.component import Component
2
+ from typing import Optional, Dict, Any, List
3
+
4
+ class Navbar(Component):
5
+ """Componente para crear barras de navegación."""
6
+ def __init__(
7
+ self,
8
+ children: Optional[List[Component]] = None,
9
+ brand: Optional[str] = None,
10
+ class_name: Optional[str] = None,
11
+ style: Optional[Dict[str, Any]] = None,
12
+ **kwargs
13
+ ):
14
+ super().__init__(children=children, class_name=class_name, style=style, **kwargs)
15
+ self.brand = brand
16
+
17
+ def render(self) -> str:
18
+ brand_html = f'<div class="dars-navbar-brand">{self.brand}</div>' if self.brand else ''
19
+ children_html = ''.join([child.render() for child in self.children])
20
+
21
+ attrs = []
22
+ if self.class_name: attrs.append(f'class="dars-navbar {self.class_name}"')
23
+ else: attrs.append('class="dars-navbar"')
24
+
25
+ navbar_style = 'display: flex; justify-content: space-between; align-items: center; padding: 1rem; background-color: #f8f9fa; border-bottom: 1px solid #dee2e6'
26
+ if self.style:
27
+ navbar_style += f'; {self.render_styles(self.style)}'
28
+ attrs.append(f'style="{navbar_style}"')
29
+
30
+ return f'<nav {" ".join(attrs)}>{brand_html}<div class="dars-navbar-nav">{children_html}</div></nav>'
31
+
@@ -0,0 +1,24 @@
1
+ from dars.core.component import Component
2
+ from typing import List, Dict, Any, Optional
3
+
4
+ class Table(Component):
5
+ """
6
+ Componente para mostrar datos tabulares con columnas, datos, paginación, orden y filtrado.
7
+ columns: Lista de diccionarios con claves 'title', 'field', 'sortable', 'width', etc.
8
+ data: Lista de diccionarios (cada uno es una fila).
9
+ page_size: Número de filas por página (opcional).
10
+ """
11
+ def __init__(self, columns: List[Dict[str, Any]], data: List[Dict[str, Any]], page_size: Optional[int]=None, **props):
12
+ super().__init__(**props)
13
+ self.columns = columns
14
+ self.data = data
15
+ self.page_size = page_size
16
+
17
+ def render(self) -> str:
18
+ # Renderiza la tabla en HTML (solo vista simple, sin JS avanzado todavía)
19
+ thead = '<thead><tr>' + ''.join(f'<th>{col["title"]}</th>' for col in self.columns) + '</tr></thead>'
20
+ rows = self.data[:self.page_size] if self.page_size else self.data
21
+ tbody = '<tbody>' + ''.join(
22
+ '<tr>' + ''.join(f'<td>{row.get(col["field"], "")}</td>' for col in self.columns) + '</tr>'
23
+ for row in rows) + '</tbody>'
24
+ return f'<table class="dars-table">{thead}{tbody}</table>'
@@ -0,0 +1,26 @@
1
+ from dars.core.component import Component
2
+ from typing import List, Optional
3
+
4
+ class Tabs(Component):
5
+ """
6
+ Componente de navegación por pestañas.
7
+ tabs: Lista de títulos de pestañas
8
+ panels: Lista de componentes o strings (contenido de cada pestaña)
9
+ selected: Índice de la pestaña activa (opcional)
10
+ """
11
+ def __init__(self, tabs: List[str], panels: List[Component], selected: Optional[int]=0, **props):
12
+ super().__init__(**props)
13
+ self.tabs = tabs
14
+ self.panels = panels
15
+ self.selected = selected or 0
16
+
17
+ def render(self) -> str:
18
+ tab_headers = ''.join(
19
+ f'<button class="dars-tab{ " dars-tab-active" if i == self.selected else "" }" data-tab="{i}">{title}</button>'
20
+ for i, title in enumerate(self.tabs)
21
+ )
22
+ panels_html = ''.join(
23
+ f'<div class="dars-tab-panel{ " dars-tab-panel-active" if i == self.selected else "" }">{panel.render() if hasattr(panel, "render") else panel}</div>'
24
+ for i, panel in enumerate(self.panels)
25
+ )
26
+ return f'<div class="dars-tabs"><div class="dars-tabs-header">{tab_headers}</div><div class="dars-tabs-panels">{panels_html}</div></div>'
@@ -0,0 +1,34 @@
1
+ from .text import Text
2
+ from .button import Button
3
+ from .input import Input
4
+ from .container import Container
5
+ from .page import Page
6
+ from .image import Image
7
+ from .link import Link
8
+ from .textarea import Textarea
9
+ from .checkbox import Checkbox
10
+ from .radiobutton import RadioButton
11
+ from .select import Select, SelectOption
12
+ from .slider import Slider
13
+ from .datepicker import DatePicker
14
+
15
+ from .progressbar import ProgressBar
16
+ from .spinner import Spinner
17
+ from .tooltip import Tooltip
18
+
19
+ __all__ = [
20
+ 'Text',
21
+ 'Button',
22
+ 'Input',
23
+ 'Container',
24
+ 'Page',
25
+ 'Image',
26
+ 'Link',
27
+ 'Textarea',
28
+ 'Checkbox',
29
+ 'RadioButton',
30
+ 'Select',
31
+ 'SelectOption',
32
+ 'Slider',
33
+ 'DatePicker'
34
+ ]
@@ -0,0 +1,29 @@
1
+ from dars.core.component import Component
2
+ from dars.core.properties import StyleProps
3
+ from dars.core.events import EventTypes
4
+ from typing import Optional, Union, Dict, Any, Callable
5
+
6
+ class Button(Component):
7
+ def __init__(
8
+ self,
9
+ text: str = "Button",
10
+ id: Optional[str] = None,
11
+ class_name: Optional[str] = None,
12
+ style: Optional[Dict[str, Any]] = None,
13
+ disabled: bool = False,
14
+ button_type: str = "button", # "button", "submit", "reset"
15
+ on_click: Optional[Callable] = None
16
+ ):
17
+ super().__init__(id=id, class_name=class_name, style=style)
18
+ self.text = text
19
+ self.disabled = disabled
20
+ self.button_type = button_type
21
+
22
+ # Registrar evento de click si se proporciona
23
+ if on_click:
24
+ self.set_event(EventTypes.CLICK, on_click)
25
+
26
+ def render(self, exporter: Any) -> str:
27
+ # El método render será implementado por cada exportador
28
+ raise NotImplementedError("El método render debe ser implementado por el exportador")
29
+