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
dars/core/events.py ADDED
@@ -0,0 +1,101 @@
1
+ from typing import Callable, Dict, Any, Optional
2
+ from abc import ABC, abstractmethod
3
+
4
+ class EventHandler:
5
+ """Manejador de eventos para componentes"""
6
+
7
+ def __init__(self, handler: Callable, event_type: str):
8
+ self.handler = handler
9
+ self.event_type = event_type
10
+ self.id = f"event_{id(self)}"
11
+
12
+ def __call__(self, *args, **kwargs):
13
+ return self.handler(*args, **kwargs)
14
+
15
+ class EventManager:
16
+ """Gestor de eventos para la aplicación"""
17
+
18
+ def __init__(self):
19
+ self.handlers: Dict[str, EventHandler] = {}
20
+ self.component_events: Dict[str, Dict[str, EventHandler]] = {}
21
+
22
+ def register_event(self, component_id: str, event_type: str, handler: Callable) -> str:
23
+ """Registra un evento para un componente"""
24
+ event_handler = EventHandler(handler, event_type)
25
+
26
+ if component_id not in self.component_events:
27
+ self.component_events[component_id] = {}
28
+
29
+ self.component_events[component_id][event_type] = event_handler
30
+ self.handlers[event_handler.id] = event_handler
31
+
32
+ return event_handler.id
33
+
34
+ def get_event_handler(self, handler_id: str) -> Optional[EventHandler]:
35
+ """Obtiene un manejador de eventos por su ID"""
36
+ return self.handlers.get(handler_id)
37
+
38
+ def get_component_events(self, component_id: str) -> Dict[str, EventHandler]:
39
+ """Obtiene todos los eventos de un componente"""
40
+ return self.component_events.get(component_id, {})
41
+
42
+ def remove_event(self, component_id: str, event_type: str):
43
+ """Elimina un evento de un componente"""
44
+ if component_id in self.component_events:
45
+ if event_type in self.component_events[component_id]:
46
+ handler = self.component_events[component_id][event_type]
47
+ del self.handlers[handler.id]
48
+ del self.component_events[component_id][event_type]
49
+
50
+ class EventEmitter(ABC):
51
+ """Clase base para componentes que pueden emitir eventos"""
52
+
53
+ def __init__(self):
54
+ self.event_manager = EventManager()
55
+
56
+ def on(self, event_type: str, handler: Callable) -> str:
57
+ """Registra un manejador de eventos"""
58
+ component_id = getattr(self, 'id', str(id(self)))
59
+ return self.event_manager.register_event(component_id, event_type, handler)
60
+
61
+ def off(self, event_type: str):
62
+ """Elimina un manejador de eventos"""
63
+ component_id = getattr(self, 'id', str(id(self)))
64
+ self.event_manager.remove_event(component_id, event_type)
65
+
66
+ @abstractmethod
67
+ def emit(self, event_type: str, *args, **kwargs):
68
+ """Emite un evento"""
69
+ pass
70
+
71
+ # Tipos de eventos estándar
72
+ class EventTypes:
73
+ # Eventos de mouse
74
+ CLICK = "click"
75
+ DOUBLE_CLICK = "dblclick"
76
+ MOUSE_DOWN = "mousedown"
77
+ MOUSE_UP = "mouseup"
78
+ MOUSE_ENTER = "mouseenter"
79
+ MOUSE_LEAVE = "mouseleave"
80
+ MOUSE_MOVE = "mousemove"
81
+
82
+ # Eventos de teclado
83
+ KEY_DOWN = "keydown"
84
+ KEY_UP = "keyup"
85
+ KEY_PRESS = "keypress"
86
+
87
+ # Eventos de formulario
88
+ CHANGE = "change"
89
+ INPUT = "input"
90
+ SUBMIT = "submit"
91
+ FOCUS = "focus"
92
+ BLUR = "blur"
93
+
94
+ # Eventos de carga
95
+ LOAD = "load"
96
+ ERROR = "error"
97
+ RESIZE = "resize"
98
+
99
+ # Eventos personalizados
100
+ CUSTOM = "custom"
101
+
@@ -0,0 +1,127 @@
1
+ from typing import Union, Optional, Dict, Any, Callable
2
+ from dataclasses import dataclass
3
+
4
+ @dataclass
5
+ class StyleProps:
6
+ """Propiedades de estilo para componentes UI"""
7
+ # Dimensiones
8
+ width: Optional[Union[str, int]] = None
9
+ height: Optional[Union[str, int]] = None
10
+ min_width: Optional[Union[str, int]] = None
11
+ min_height: Optional[Union[str, int]] = None
12
+ max_width: Optional[Union[str, int]] = None
13
+ max_height: Optional[Union[str, int]] = None
14
+
15
+ # Espaciado
16
+ margin: Optional[Union[str, int]] = None
17
+ margin_top: Optional[Union[str, int]] = None
18
+ margin_right: Optional[Union[str, int]] = None
19
+ margin_bottom: Optional[Union[str, int]] = None
20
+ margin_left: Optional[Union[str, int]] = None
21
+ padding: Optional[Union[str, int]] = None
22
+ padding_top: Optional[Union[str, int]] = None
23
+ padding_right: Optional[Union[str, int]] = None
24
+ padding_bottom: Optional[Union[str, int]] = None
25
+ padding_left: Optional[Union[str, int]] = None
26
+
27
+ # Colores
28
+ background_color: Optional[str] = None
29
+ color: Optional[str] = None
30
+ border_color: Optional[str] = None
31
+
32
+ # Tipografía
33
+ font_size: Optional[Union[str, int]] = None
34
+ font_family: Optional[str] = None
35
+ font_weight: Optional[Union[str, int]] = None
36
+ font_style: Optional[str] = None
37
+ text_align: Optional[str] = None
38
+ text_decoration: Optional[str] = None
39
+ line_height: Optional[Union[str, int]] = None
40
+
41
+ # Bordes
42
+ border: Optional[str] = None
43
+ border_width: Optional[Union[str, int]] = None
44
+ border_style: Optional[str] = None
45
+ border_radius: Optional[Union[str, int]] = None
46
+
47
+ # Layout
48
+ display: Optional[str] = None
49
+ position: Optional[str] = None
50
+ top: Optional[Union[str, int]] = None
51
+ right: Optional[Union[str, int]] = None
52
+ bottom: Optional[Union[str, int]] = None
53
+ left: Optional[Union[str, int]] = None
54
+ z_index: Optional[int] = None
55
+
56
+ # Flexbox
57
+ flex_direction: Optional[str] = None
58
+ flex_wrap: Optional[str] = None
59
+ justify_content: Optional[str] = None
60
+ align_items: Optional[str] = None
61
+ align_content: Optional[str] = None
62
+ flex: Optional[Union[str, int]] = None
63
+ flex_grow: Optional[int] = None
64
+ flex_shrink: Optional[int] = None
65
+ flex_basis: Optional[Union[str, int]] = None
66
+
67
+ # Grid
68
+ grid_template_columns: Optional[str] = None
69
+ grid_template_rows: Optional[str] = None
70
+ grid_gap: Optional[Union[str, int]] = None
71
+ grid_column: Optional[str] = None
72
+ grid_row: Optional[str] = None
73
+
74
+ # Efectos
75
+ opacity: Optional[float] = None
76
+ box_shadow: Optional[str] = None
77
+ transform: Optional[str] = None
78
+ transition: Optional[str] = None
79
+
80
+ # Overflow
81
+ overflow: Optional[str] = None
82
+ overflow_x: Optional[str] = None
83
+ overflow_y: Optional[str] = None
84
+
85
+ def to_dict(self) -> Dict[str, Any]:
86
+ """Convierte las propiedades a un diccionario, excluyendo valores None"""
87
+ result = {}
88
+ for key, value in self.__dict__.items():
89
+ if value is not None:
90
+ # Convertir snake_case a kebab-case para CSS
91
+ css_key = key.replace('_', '-')
92
+ result[css_key] = value
93
+ return result
94
+
95
+ @dataclass
96
+ class EventProps:
97
+ """Propiedades de eventos para componentes UI"""
98
+ on_click: Optional[Callable] = None
99
+ on_double_click: Optional[Callable] = None
100
+ on_mouse_enter: Optional[Callable] = None
101
+ on_mouse_leave: Optional[Callable] = None
102
+ on_mouse_down: Optional[Callable] = None
103
+ on_mouse_up: Optional[Callable] = None
104
+ on_key_down: Optional[Callable] = None
105
+ on_key_up: Optional[Callable] = None
106
+ on_focus: Optional[Callable] = None
107
+ on_blur: Optional[Callable] = None
108
+ on_change: Optional[Callable] = None
109
+ on_input: Optional[Callable] = None
110
+ on_submit: Optional[Callable] = None
111
+ on_load: Optional[Callable] = None
112
+ on_error: Optional[Callable] = None
113
+
114
+ def normalize_style_value(value: Union[str, int]) -> str:
115
+ """Normaliza un valor de estilo a string CSS"""
116
+ if isinstance(value, int):
117
+ return f"{value}px"
118
+ return str(value)
119
+
120
+ def merge_styles(*styles: Dict[str, Any]) -> Dict[str, Any]:
121
+ """Combina múltiples diccionarios de estilos"""
122
+ result = {}
123
+ for style in styles:
124
+ if style:
125
+ result.update(style)
126
+ return result
127
+
dars/docs/__init__.py ADDED
File without changes
File without changes
dars/exporters/base.py ADDED
@@ -0,0 +1,69 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Dict, Any
3
+ import os
4
+
5
+ class Exporter(ABC):
6
+ """Clase base para todos los exportadores"""
7
+
8
+ def __init__(self):
9
+ self.templates_path = os.path.join(os.path.dirname(__file__), "..", "templates")
10
+
11
+ @abstractmethod
12
+ def export(self, app: 'App', output_path: str) -> bool:
13
+ """Exporta la aplicación al formato específico"""
14
+ pass
15
+
16
+ @abstractmethod
17
+ def render_component(self, component: 'Component') -> str:
18
+ """Renderiza un componente individual"""
19
+ pass
20
+
21
+ def load_template(self, template_name: str) -> str:
22
+ """Carga una plantilla desde el directorio de templates"""
23
+ template_path = os.path.join(self.templates_path, self.get_platform(), template_name)
24
+ try:
25
+ with open(template_path, 'r', encoding='utf-8') as f:
26
+ return f.read()
27
+ except FileNotFoundError:
28
+ raise FileNotFoundError(f"Plantilla no encontrada: {template_path}")
29
+
30
+ @abstractmethod
31
+ def get_platform(self) -> str:
32
+ """Retorna el nombre de la plataforma (html, react, etc.)"""
33
+ pass
34
+
35
+ def create_output_directory(self, output_path: str):
36
+ """Crea el directorio de salida si no existe"""
37
+ os.makedirs(output_path, exist_ok=True)
38
+
39
+ def write_file(self, file_path: str, content: str):
40
+ """Escribe contenido a un archivo"""
41
+ os.makedirs(os.path.dirname(file_path), exist_ok=True)
42
+ with open(file_path, 'w', encoding='utf-8') as f:
43
+ f.write(content)
44
+
45
+ def copy_file(self, source_path: str, dest_path: str):
46
+ """Copia un archivo de origen a destino"""
47
+ import shutil
48
+ os.makedirs(os.path.dirname(dest_path), exist_ok=True)
49
+ shutil.copy2(source_path, dest_path)
50
+
51
+ def render_styles(self, styles: Dict[str, Any]) -> str:
52
+ """Convierte un diccionario de estilos a CSS"""
53
+ if not styles:
54
+ return ""
55
+
56
+ css_rules = []
57
+ for property_name, value in styles.items():
58
+ # Convertir snake_case a kebab-case
59
+ css_property = property_name.replace('_', '-')
60
+ css_rules.append(f"{css_property}: {value}")
61
+
62
+ return "; ".join(css_rules)
63
+
64
+ def generate_unique_id(self, component: 'Component') -> str:
65
+ """Genera un ID único para un componente si no tiene uno"""
66
+ if component.id:
67
+ return component.id
68
+ return f"component_{id(component)}"
69
+
File without changes