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.
- dars/__init__.py +0 -0
- dars/all.py +69 -0
- dars/cli/__init__.py +0 -0
- dars/cli/doctor/__init__.py +1 -0
- dars/cli/doctor/detect.py +154 -0
- dars/cli/doctor/doctor.py +176 -0
- dars/cli/doctor/installers.py +100 -0
- dars/cli/doctor/persist.py +62 -0
- dars/cli/doctor/preflight.py +33 -0
- dars/cli/doctor/ui.py +54 -0
- dars/cli/hot_reload.py +33 -0
- dars/cli/main.py +1107 -0
- dars/cli/preview.py +448 -0
- dars/cli/translations.py +531 -0
- dars/components/__init__.py +0 -0
- dars/components/advanced/__init__.py +8 -0
- dars/components/advanced/accordion.py +26 -0
- dars/components/advanced/card.py +33 -0
- dars/components/advanced/modal.py +45 -0
- dars/components/advanced/navbar.py +44 -0
- dars/components/advanced/table.py +25 -0
- dars/components/advanced/tabs.py +31 -0
- dars/components/basic/__init__.py +34 -0
- dars/components/basic/button.py +55 -0
- dars/components/basic/checkbox.py +35 -0
- dars/components/basic/container.py +29 -0
- dars/components/basic/datepicker.py +139 -0
- dars/components/basic/image.py +36 -0
- dars/components/basic/input.py +57 -0
- dars/components/basic/link.py +31 -0
- dars/components/basic/markdown.py +86 -0
- dars/components/basic/page.py +20 -0
- dars/components/basic/progressbar.py +18 -0
- dars/components/basic/radiobutton.py +35 -0
- dars/components/basic/select.py +82 -0
- dars/components/basic/slider.py +63 -0
- dars/components/basic/spinner.py +12 -0
- dars/components/basic/text.py +23 -0
- dars/components/basic/textarea.py +46 -0
- dars/components/basic/tooltip.py +19 -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/config.py +134 -0
- dars/core/__init__.py +0 -0
- dars/core/app.py +957 -0
- dars/core/component.py +284 -0
- dars/core/events.py +102 -0
- dars/core/js_bridge.py +99 -0
- dars/core/properties.py +127 -0
- dars/core/state.py +309 -0
- dars/dars_tests/apps_test/health_check.py +56 -0
- dars/dars_tests/run_tests.py +275 -0
- dars/dars_tests/tests/test_advanced_components.py +69 -0
- dars/dars_tests/tests/test_basic_components.py +88 -0
- dars/dars_tests/tests/test_core_and_cli.py +17 -0
- dars/dars_tests/tests/test_layout_components.py +58 -0
- dars/dars_tests/tests/test_version_check.py +21 -0
- dars/docs/__init__.py +0 -0
- dars/docs/app.md +290 -0
- dars/docs/cli.md +80 -0
- dars/docs/components.md +1679 -0
- dars/docs/custom_components.md +30 -0
- dars/docs/events.md +45 -0
- dars/docs/exporters.md +162 -0
- dars/docs/getting_started.md +79 -0
- dars/docs/index.md +18 -0
- dars/docs/scripts.md +593 -0
- dars/docs/state_management.md +57 -0
- dars/exporters/__init__.py +0 -0
- dars/exporters/base.py +96 -0
- dars/exporters/web/OLD/html_css_js_OLD4.py +1538 -0
- dars/exporters/web/OLD/html_css_js_old.py +1406 -0
- dars/exporters/web/OLD/html_css_js_old2.py +1406 -0
- dars/exporters/web/__init__.py +0 -0
- dars/exporters/web/html_css_js.py +2675 -0
- dars/exporters/web/vdom.py +251 -0
- dars/js_lib.py +206 -0
- dars/scripts/__init__.py +0 -0
- dars/scripts/dscript.py +26 -0
- dars/scripts/script.py +39 -0
- dars/security.py +195 -0
- dars/templates/__init__.py +0 -0
- dars/templates/__pycache__/__init__.cpython-311.pyc +0 -0
- dars/templates/examples/README.md +4 -0
- dars/templates/examples/__pycache__/dynamic_event_demo.cpython-311.pyc +0 -0
- dars/templates/examples/advanced/Modal_Demo/advanced_modal_demo.py +275 -0
- dars/templates/examples/advanced/SimpleDashboard/dashboard.py +437 -0
- dars/templates/examples/advanced/SimpleModermWeb/modern_web_app.py +452 -0
- dars/templates/examples/advanced/VariousComponents/all_components_demo.py +87 -0
- dars/templates/examples/advanced/__init__.py +0 -0
- dars/templates/examples/advanced/dState/state_mods_demo.py +68 -0
- dars/templates/examples/basic/Forms/form_components.py +516 -0
- dars/templates/examples/basic/Forms/simple_form.py +379 -0
- dars/templates/examples/basic/HelloWorld/hello_world.py +56 -0
- dars/templates/examples/basic/Layouts/flex_layout_responsive.py +13 -0
- dars/templates/examples/basic/Layouts/grid_layout_responsive.py +12 -0
- dars/templates/examples/basic/Layouts/layout_multipage_demo.py +23 -0
- dars/templates/examples/basic/Multipage/multipage_example.py +67 -0
- dars/templates/examples/basic/PWA/icon-192x192.png +0 -0
- dars/templates/examples/basic/PWA/icon-512x512.png +0 -0
- dars/templates/examples/basic/PWA/pwa_custom_icons.py +33 -0
- dars/templates/examples/basic/__init__.py +0 -0
- dars/templates/examples/demo/__pycache__/complete_app.cpython-311.pyc +0 -0
- dars/templates/examples/demo/complete_app.py +21 -0
- dars/templates/examples/markdown/MarkdownTemplate/README.md +159 -0
- dars/templates/examples/markdown/MarkdownTemplate/markdown_template.py +21 -0
- dars/templates/examples/markdown/MarkdownTemplate/other_docs.md +1 -0
- dars/templates/examples/markdown/__init__.py +0 -0
- dars/templates/html/__init__.py +0 -0
- dars/version.py +2 -0
- dars_framework-1.2.3.dist-info/METADATA +15 -0
- dars_framework-1.2.3.dist-info/RECORD +118 -0
- dars_framework-1.2.3.dist-info/WHEEL +5 -0
- dars_framework-1.2.3.dist-info/entry_points.txt +2 -0
- dars_framework-1.2.3.dist-info/licenses/LICENSE +21 -0
- dars_framework-1.2.3.dist-info/top_level.txt +1 -0
dars/docs/components.md
ADDED
|
@@ -0,0 +1,1679 @@
|
|
|
1
|
+
The documentstion of dars is moving to the documentation official website please visit https://ztamdev.github.io/Dars-Framework/documentation.html because this documents will be deprecated in some time...
|
|
2
|
+
|
|
3
|
+
# Dars - Components Documentation
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Barrel Import
|
|
8
|
+
|
|
9
|
+
You can now import all main components and modules with a single line:
|
|
10
|
+
|
|
11
|
+
```python
|
|
12
|
+
from dars.all import *
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
This simplifies integration and improves the developer experience.
|
|
16
|
+
> But if you crate your own components it can cause conflicts with names of your components and built in components if they have the same name.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
## Introduction to Components
|
|
21
|
+
|
|
22
|
+
Components are the fundamental elements of Dars that represent UI elements. Each component encapsulates its appearance, behavior, and state, allowing you to create complex interfaces by composing simple elements.
|
|
23
|
+
|
|
24
|
+
To learn how to create your own custom components, refer to the documentation in [Custom Components](#custom-components-in-dars-framework).
|
|
25
|
+
|
|
26
|
+
## Event Handling with dScript
|
|
27
|
+
|
|
28
|
+
Dars provides a powerful way to handle user interactions through the `dScript` class. You can attach event handlers to interactive components like `Button` and `Input` to create dynamic and responsive user interfaces.
|
|
29
|
+
|
|
30
|
+
For a complete list of available event types and how to use them, refer to the documentation in [Events](#events-in-dars).
|
|
31
|
+
|
|
32
|
+
### Basic Usage
|
|
33
|
+
|
|
34
|
+
```python
|
|
35
|
+
from dars.scripts.dscript import dScript
|
|
36
|
+
|
|
37
|
+
# Button with click handler
|
|
38
|
+
button = Button(
|
|
39
|
+
text="Click me",
|
|
40
|
+
on_click=dScript("""
|
|
41
|
+
function handleClick(event) {
|
|
42
|
+
alert('Button was clicked!');
|
|
43
|
+
// Access the button element
|
|
44
|
+
const button = event.target;
|
|
45
|
+
// Toggle a class on click
|
|
46
|
+
button.classList.toggle('clicked');
|
|
47
|
+
}
|
|
48
|
+
""")
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# Input with change handler
|
|
52
|
+
input_field = Input(
|
|
53
|
+
placeholder="Type something...",
|
|
54
|
+
on_change=dScript("""
|
|
55
|
+
function handleChange(event) {
|
|
56
|
+
console.log('Input value changed to:', event.target.value);
|
|
57
|
+
// Add validation or other logic here
|
|
58
|
+
if (event.target.value.length < 3) {
|
|
59
|
+
event.target.style.borderColor = 'red';
|
|
60
|
+
} else {
|
|
61
|
+
event.target.style.borderColor = 'green';
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
"""
|
|
65
|
+
)
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Available Events
|
|
69
|
+
|
|
70
|
+
| Component | Event | Description |
|
|
71
|
+
|-----------|-------|-------------|
|
|
72
|
+
| `Button` | `on_click` | Triggered when the button is clicked |
|
|
73
|
+
| `Button` | `on_double_click` | Triggered on double click |
|
|
74
|
+
| `Button` | `on_mouse_enter` | Triggered when mouse enters the button |
|
|
75
|
+
| `Button` | `on_mouse_leave` | Triggered when mouse leaves the button |
|
|
76
|
+
| `Input` | `on_change` | Triggered when input value changes |
|
|
77
|
+
| `Input` | `on_key_up` | Triggered when a key is released |
|
|
78
|
+
| `Input` | `on_key_down` | Triggered when a key is pressed |
|
|
79
|
+
|
|
80
|
+
### Best Practices
|
|
81
|
+
|
|
82
|
+
1. **Use Named Functions**: Makes debugging easier and allows reusing the same function for multiple events.
|
|
83
|
+
2. **Keep Handlers Small**: Move complex logic to separate functions in your JavaScript code.
|
|
84
|
+
3. **Access Event Object**: The event object provides useful properties like `target`, `keyCode`, etc.
|
|
85
|
+
4. **Return `false`** to prevent default behavior when needed.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
### Quick Access
|
|
90
|
+
|
|
91
|
+
- [Base Component Class](#base-component-class)
|
|
92
|
+
- [Component Search](#component-search-and-modification)
|
|
93
|
+
- [Page](#page)
|
|
94
|
+
- [Text](#text)
|
|
95
|
+
- [Button](#button)
|
|
96
|
+
- [Input](#input)
|
|
97
|
+
- [Container](#container)
|
|
98
|
+
- [Markdown](#markdown)
|
|
99
|
+
- [Image](#image)
|
|
100
|
+
- [Link](#link)
|
|
101
|
+
- [Textarea](#textarea)
|
|
102
|
+
- [Checkbox](#checkbox)
|
|
103
|
+
- [RadioButton](#radiobutton)
|
|
104
|
+
- [Select](#select)
|
|
105
|
+
- [Slider](#slider)
|
|
106
|
+
- [ProgressBar](#progressBar)
|
|
107
|
+
- [Tooltip](#tooltip)
|
|
108
|
+
- [DatePicker](#datepicker)
|
|
109
|
+
- [Card](#card)
|
|
110
|
+
- [Modal](#modal)
|
|
111
|
+
- [Navbar](#navbar)
|
|
112
|
+
- [Accordion](#accordion)
|
|
113
|
+
- [Tabs](#tabs)
|
|
114
|
+
- [Table](#table)
|
|
115
|
+
- [Layout Components](#layout-components)
|
|
116
|
+
- [GridLayout](#gridlayout)
|
|
117
|
+
- [FlexLayout](#flexlayout)
|
|
118
|
+
- [LayoutBase](#layoutbase)
|
|
119
|
+
- [AnchorPoint](#anchorpoint)
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Base Component Class
|
|
124
|
+
|
|
125
|
+
All components in Dars inherit from the base `Component` class, which provides common functionality:
|
|
126
|
+
|
|
127
|
+
```python
|
|
128
|
+
from dars.core.component import Component
|
|
129
|
+
|
|
130
|
+
class Component(ABC):
|
|
131
|
+
def __init__(self, **props):
|
|
132
|
+
self.props = props
|
|
133
|
+
self.children = []
|
|
134
|
+
self.parent = None
|
|
135
|
+
self.id = props.get("id")
|
|
136
|
+
self.class_name = props.get("class_name")
|
|
137
|
+
self.style = props.get("style", {})
|
|
138
|
+
self.events = {}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Common Properties
|
|
142
|
+
|
|
143
|
+
All components support these basic properties:
|
|
144
|
+
|
|
145
|
+
- **id**: Unique component identifier
|
|
146
|
+
- **class_name**: CSS class for additional styles
|
|
147
|
+
- **style**: Dictionary of CSS styles
|
|
148
|
+
- **children**: List of child components (for containers)
|
|
149
|
+
|
|
150
|
+
### Component-Search-and-Modification
|
|
151
|
+
|
|
152
|
+
All components include a powerful search and modification system through the `find()` method. This allows you to search for components in the component tree and modify their attributes using a fluent interface.
|
|
153
|
+
|
|
154
|
+
#### Basic Search
|
|
155
|
+
|
|
156
|
+
```python
|
|
157
|
+
# Find by ID
|
|
158
|
+
component.find(id="search-button")
|
|
159
|
+
|
|
160
|
+
# Find by CSS class
|
|
161
|
+
component.find(class_name="primary-button")
|
|
162
|
+
|
|
163
|
+
# Find by component type
|
|
164
|
+
component.find(type="Button") # or type=Button
|
|
165
|
+
|
|
166
|
+
# Find using a custom predicate
|
|
167
|
+
component.find(predicate=lambda c: "welcome" in c.text.lower())
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
#### Chained Searches
|
|
171
|
+
|
|
172
|
+
You can chain multiple `find()` calls to search within the results of previous searches:
|
|
173
|
+
|
|
174
|
+
```python
|
|
175
|
+
# Find a container and then search within it
|
|
176
|
+
component.find(id="main-container")\
|
|
177
|
+
.find(type="Text")\
|
|
178
|
+
.attr(text="New text")
|
|
179
|
+
|
|
180
|
+
# Multiple levels of search
|
|
181
|
+
component.find(class_name="section")\
|
|
182
|
+
.find(type="Container")\
|
|
183
|
+
.find(id="special-text")\
|
|
184
|
+
.attr(text="Modified text")
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
#### Modifying Components
|
|
188
|
+
|
|
189
|
+
Use the `attr()` method to modify the found components:
|
|
190
|
+
|
|
191
|
+
```python
|
|
192
|
+
# Modify styles
|
|
193
|
+
component.find(type="Button").attr(
|
|
194
|
+
style={"background-color": "red", "color": "white"}
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
# Modify class names
|
|
198
|
+
component.find(class_name="btn").attr(
|
|
199
|
+
class_name="btn primary"
|
|
200
|
+
)
|
|
201
|
+
|
|
202
|
+
# Modify component-specific attributes
|
|
203
|
+
component.find(type="Text").attr(
|
|
204
|
+
text="New content"
|
|
205
|
+
)
|
|
206
|
+
|
|
207
|
+
# Multiple modifications at once
|
|
208
|
+
component.find(type="Input").attr(
|
|
209
|
+
placeholder="Type here...",
|
|
210
|
+
style={"padding": "10px"},
|
|
211
|
+
class_name="modern-input"
|
|
212
|
+
)
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
#### Getting Results
|
|
216
|
+
|
|
217
|
+
```python
|
|
218
|
+
# Get all matched components
|
|
219
|
+
components = component.find(type="Button").get()
|
|
220
|
+
|
|
221
|
+
# Get only the first match
|
|
222
|
+
first_button = component.find(type="Button").first()
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
#### Search Parameters
|
|
226
|
+
|
|
227
|
+
| Parameter | Type | Description | Example |
|
|
228
|
+
|-----------|------|-------------|---------|
|
|
229
|
+
| `id` | str | Search by component ID | `find(id="search-btn")` |
|
|
230
|
+
| `class_name` | str | Search by CSS class | `find(class_name="primary")` |
|
|
231
|
+
| `type` | str/Type | Search by component type | `find(type="Button")` or `find(type=Button)` |
|
|
232
|
+
| `predicate` | Callable | Custom search function | `find(predicate=lambda c: len(c.children) > 0)` |
|
|
233
|
+
|
|
234
|
+
### Page
|
|
235
|
+
|
|
236
|
+
The `Page` component represents the root of a multipage app. It can contain other components and scripts specific to that page.
|
|
237
|
+
|
|
238
|
+
#### Syntax
|
|
239
|
+
|
|
240
|
+
```python
|
|
241
|
+
from dars.components.basic import Page, Text, Button
|
|
242
|
+
from dars.scripts.script import InlineScript
|
|
243
|
+
page = Page(
|
|
244
|
+
Text("Bienvenido!"),
|
|
245
|
+
Button("Click aquí", id="btn-demo")
|
|
246
|
+
)
|
|
247
|
+
# Añadir script JS solo a esta página
|
|
248
|
+
page.add_script(InlineScript("""
|
|
249
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
250
|
+
var btn = document.getElementById('btn-demo');
|
|
251
|
+
if (btn) btn.onclick = () => alert('¡Botón de esta página!');
|
|
252
|
+
});
|
|
253
|
+
"""))
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Use `Page` as the root of each page in the multipage system. Allows passing children directly as arguments and JS scripts per page.
|
|
257
|
+
|
|
258
|
+
#### Properties
|
|
259
|
+
|
|
260
|
+
| Property | Type | Description |
|
|
261
|
+
|-------------|--------|-----------------------------------------------------|
|
|
262
|
+
| `children` | list | List of child components |
|
|
263
|
+
| `anchors` | dict | Optional anchor points for child placement |
|
|
264
|
+
|
|
265
|
+
#### Page Scripts System
|
|
266
|
+
|
|
267
|
+
The new page scripts system allows assigning scripts to specific pages instead of globally:
|
|
268
|
+
|
|
269
|
+
* **Adding Scripts**:
|
|
270
|
+
Use the `add_script()` method on a page instance.
|
|
271
|
+
|
|
272
|
+
```python
|
|
273
|
+
from dars.scripts.dscript import dScript
|
|
274
|
+
|
|
275
|
+
index.add_script(
|
|
276
|
+
dScript(code="console.log('Hello world')")
|
|
277
|
+
)
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Text
|
|
281
|
+
|
|
282
|
+
The `Text` component displays static or dynamic text.
|
|
283
|
+
|
|
284
|
+
#### Syntax
|
|
285
|
+
|
|
286
|
+
```python
|
|
287
|
+
from dars.components.basic.text import Text
|
|
288
|
+
|
|
289
|
+
text = Text(
|
|
290
|
+
text="Contenido del text",
|
|
291
|
+
id="mi-text",
|
|
292
|
+
class_name="text-principal",
|
|
293
|
+
style={
|
|
294
|
+
"font-size": "16px",
|
|
295
|
+
"color": "#333",
|
|
296
|
+
"font-weight": "bold"
|
|
297
|
+
}
|
|
298
|
+
)
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
#### Properties
|
|
302
|
+
|
|
303
|
+
| Property | Type | Description | Example |
|
|
304
|
+
|-----------|------|-------------|---------|
|
|
305
|
+
| `text` | str | Text content | `"Hello world"` |
|
|
306
|
+
| `id` | str | Unique identifier | `"title-primary"` |
|
|
307
|
+
| `class_name` | str | CSS class | `"text-highlight"` |
|
|
308
|
+
| `style` | dict | CSS styles | `{"color": "red"}` |
|
|
309
|
+
|
|
310
|
+
#### Common Styles
|
|
311
|
+
|
|
312
|
+
```python
|
|
313
|
+
# Título principal
|
|
314
|
+
title = Text(
|
|
315
|
+
text="Título Principal",
|
|
316
|
+
style={
|
|
317
|
+
"font-size": "32px",
|
|
318
|
+
"font-weight": "bold",
|
|
319
|
+
"color": "#2c3e50",
|
|
320
|
+
"margin-bottom": "20px",
|
|
321
|
+
"text-align": "center"
|
|
322
|
+
}
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
# Párrafo de contenido
|
|
326
|
+
paragraph = Text(
|
|
327
|
+
text="Este es un párrafo de ejemplo con contenido descriptivo.",
|
|
328
|
+
style={
|
|
329
|
+
"font-size": "16px",
|
|
330
|
+
"line-height": "1.6",
|
|
331
|
+
"color": "#34495e",
|
|
332
|
+
"margin-bottom": "15px"
|
|
333
|
+
}
|
|
334
|
+
)
|
|
335
|
+
|
|
336
|
+
# Texto pequeño
|
|
337
|
+
note = Text(
|
|
338
|
+
text="Nota: Esta información es importante.",
|
|
339
|
+
style={
|
|
340
|
+
"font-size": "12px",
|
|
341
|
+
"color": "#7f8c8d",
|
|
342
|
+
"font-style": "italic"
|
|
343
|
+
}
|
|
344
|
+
)
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Button
|
|
348
|
+
|
|
349
|
+
The `Button` component creates interactive buttons that can execute actions.
|
|
350
|
+
|
|
351
|
+
#### Syntax
|
|
352
|
+
|
|
353
|
+
```python
|
|
354
|
+
from dars.components.basic.button import Button
|
|
355
|
+
|
|
356
|
+
boton = Button(
|
|
357
|
+
text="Hacer clic",
|
|
358
|
+
button_type="button", # "button", "submit", "reset"
|
|
359
|
+
disabled=False,
|
|
360
|
+
on_click=dScript("""
|
|
361
|
+
function handleClick() {
|
|
362
|
+
alert('Button clicked!');
|
|
363
|
+
}
|
|
364
|
+
""")
|
|
365
|
+
style={
|
|
366
|
+
"background-color": "#3498db",
|
|
367
|
+
"color": "white",
|
|
368
|
+
"padding": "10px 20px",
|
|
369
|
+
"border": "none",
|
|
370
|
+
"border-radius": "4px"
|
|
371
|
+
}
|
|
372
|
+
)
|
|
373
|
+
```
|
|
374
|
+
|
|
375
|
+
#### Properties
|
|
376
|
+
|
|
377
|
+
| Property | Type | Description | Values |
|
|
378
|
+
|-----------|------|-------------|---------|
|
|
379
|
+
| `text` | str | Button text | `"Enviar"` |
|
|
380
|
+
| `button_type` | str | Button type | `"button"`, `"submit"`, `"reset"` |
|
|
381
|
+
| `disabled` | bool | Si está deshabilitado | `True`, `False` |
|
|
382
|
+
| `on_click` | dScript | Click handler | `dScript("function() { ... }")` |
|
|
383
|
+
| `on_double_click` | dScript | Double click handler | `dScript("function() { ... }")` |
|
|
384
|
+
| `on_mouse_enter` | dScript | Mouse enter handler | `dScript("function() { ... }")` |
|
|
385
|
+
| `on_mouse_leave` | dScript | Mouse leave handler | `dScript("function() { ... }")` |
|
|
386
|
+
| `on_key_up` | dScript | Key up handler | `dScript("function(e) { ... }")` |
|
|
387
|
+
| `on_key_down` | dScript | Key down handler | `dScript("function(e) { ... }")` |
|
|
388
|
+
|
|
389
|
+
#### Button Examples
|
|
390
|
+
|
|
391
|
+
```python
|
|
392
|
+
# Primary Button
|
|
393
|
+
primary_button = Button(
|
|
394
|
+
text="Acción Principal",
|
|
395
|
+
style={
|
|
396
|
+
"background-color": "#007bff",
|
|
397
|
+
"color": "white",
|
|
398
|
+
"padding": "12px 24px",
|
|
399
|
+
"border": "none",
|
|
400
|
+
"border-radius": "6px",
|
|
401
|
+
"font-size": "16px",
|
|
402
|
+
"font-weight": "500",
|
|
403
|
+
"cursor": "pointer",
|
|
404
|
+
"transition": "background-color 0.3s"
|
|
405
|
+
}
|
|
406
|
+
)
|
|
407
|
+
|
|
408
|
+
# Secondary Button
|
|
409
|
+
secondary_button = Button(
|
|
410
|
+
text="Cancelar",
|
|
411
|
+
style={
|
|
412
|
+
"background-color": "transparent",
|
|
413
|
+
"color": "#6c757d",
|
|
414
|
+
"padding": "12px 24px",
|
|
415
|
+
"border": "1px solid #6c757d",
|
|
416
|
+
"border-radius": "6px",
|
|
417
|
+
"font-size": "16px",
|
|
418
|
+
"cursor": "pointer"
|
|
419
|
+
}
|
|
420
|
+
)
|
|
421
|
+
|
|
422
|
+
# Danger Button
|
|
423
|
+
delete_button = Button(
|
|
424
|
+
text="Eliminar",
|
|
425
|
+
style={
|
|
426
|
+
"background-color": "#dc3545",
|
|
427
|
+
"color": "white",
|
|
428
|
+
"padding": "8px 16px",
|
|
429
|
+
"border": "none",
|
|
430
|
+
"border-radius": "4px",
|
|
431
|
+
"font-size": "14px"
|
|
432
|
+
}
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
# Disabled Button
|
|
436
|
+
disabled_button = Button(
|
|
437
|
+
text="No disponible",
|
|
438
|
+
disabled=True,
|
|
439
|
+
style={
|
|
440
|
+
"background-color": "#e9ecef",
|
|
441
|
+
"color": "#6c757d",
|
|
442
|
+
"padding": "10px 20px",
|
|
443
|
+
"border": "none",
|
|
444
|
+
"border-radius": "4px",
|
|
445
|
+
"cursor": "not-allowed"
|
|
446
|
+
}
|
|
447
|
+
)
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
### Input
|
|
451
|
+
|
|
452
|
+
The `Input` component allows user data entry.
|
|
453
|
+
|
|
454
|
+
#### Syntax
|
|
455
|
+
|
|
456
|
+
```python
|
|
457
|
+
from dars.components.basic.input import Input
|
|
458
|
+
|
|
459
|
+
entrada = Input(
|
|
460
|
+
value="Valor inicial",
|
|
461
|
+
placeholder="Escribe aquí...",
|
|
462
|
+
input_type="text", # "text", "password", "email", "number", etc.
|
|
463
|
+
disabled=False,
|
|
464
|
+
readonly=False,
|
|
465
|
+
required=False,
|
|
466
|
+
max_length=100,
|
|
467
|
+
on_change=dScript("""
|
|
468
|
+
function handleChange(event) {
|
|
469
|
+
console.log('Input changed:', event.target.value);
|
|
470
|
+
}
|
|
471
|
+
""")
|
|
472
|
+
style={
|
|
473
|
+
"width": "300px",
|
|
474
|
+
"padding": "10px",
|
|
475
|
+
"border": "1px solid #ddd",
|
|
476
|
+
"border-radius": "4px"
|
|
477
|
+
}
|
|
478
|
+
)
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
#### Properties
|
|
482
|
+
|
|
483
|
+
| Property | Type | Description | Values |
|
|
484
|
+
|-----------|------|-------------|---------|
|
|
485
|
+
| `value` | str | Initial value | `"text"` |
|
|
486
|
+
| `placeholder` | str | Help text | `"Ingresa tu name"` |
|
|
487
|
+
| `input_type` | str | Tipo de entrada | `"text"`, `"password"`, `"email"`, `"number"` |
|
|
488
|
+
| `disabled` | bool | Si está deshabilitado | `True`, `False` |
|
|
489
|
+
| `readonly` | bool | Solo lectura | `True`, `False` |
|
|
490
|
+
| `required` | bool | Campo obligatorio | `True`, `False` |
|
|
491
|
+
| `on_change` | dScript | Change handler | `dScript("function(e) { ... }")` |
|
|
492
|
+
| `on_key_up` | dScript | Key up handler | `dScript("function(e) { ... }")` |
|
|
493
|
+
| `on_key_down` | dScript | Key down handler | `dScript("function(e) { ... }")` |
|
|
494
|
+
| `max_length` | int | Longitud máxima | `50` |
|
|
495
|
+
| `min_length` | int | Longitud mínima | `3` |
|
|
496
|
+
| `pattern` | str | Validation pattern | `"[0-9]+"` |
|
|
497
|
+
|
|
498
|
+
#### Input Types
|
|
499
|
+
|
|
500
|
+
```python
|
|
501
|
+
# Basic text input
|
|
502
|
+
name = Input(
|
|
503
|
+
placeholder="Ingresa tu name",
|
|
504
|
+
input_type="text",
|
|
505
|
+
required=True,
|
|
506
|
+
style={
|
|
507
|
+
"width": "100%",
|
|
508
|
+
"padding": "12px",
|
|
509
|
+
"border": "2px solid #e1e5e9",
|
|
510
|
+
"border-radius": "8px",
|
|
511
|
+
"font-size": "16px"
|
|
512
|
+
}
|
|
513
|
+
)
|
|
514
|
+
|
|
515
|
+
# Email input
|
|
516
|
+
email = Input(
|
|
517
|
+
placeholder="tu@email.com",
|
|
518
|
+
input_type="email",
|
|
519
|
+
required=True,
|
|
520
|
+
style={
|
|
521
|
+
"width": "100%",
|
|
522
|
+
"padding": "12px",
|
|
523
|
+
"border": "2px solid #e1e5e9",
|
|
524
|
+
"border-radius": "8px"
|
|
525
|
+
}
|
|
526
|
+
)
|
|
527
|
+
|
|
528
|
+
# Password input
|
|
529
|
+
password = Input(
|
|
530
|
+
placeholder="Contraseña",
|
|
531
|
+
input_type="password",
|
|
532
|
+
required=True,
|
|
533
|
+
min_length=8,
|
|
534
|
+
style={
|
|
535
|
+
"width": "100%",
|
|
536
|
+
"padding": "12px",
|
|
537
|
+
"border": "2px solid #e1e5e9",
|
|
538
|
+
"border-radius": "8px"
|
|
539
|
+
}
|
|
540
|
+
)
|
|
541
|
+
|
|
542
|
+
# Numeric input
|
|
543
|
+
edad = Input(
|
|
544
|
+
placeholder="Edad",
|
|
545
|
+
input_type="number",
|
|
546
|
+
style={
|
|
547
|
+
"width": "100px",
|
|
548
|
+
"padding": "8px",
|
|
549
|
+
"border": "1px solid #ccc",
|
|
550
|
+
"border-radius": "4px",
|
|
551
|
+
"text-align": "center"
|
|
552
|
+
}
|
|
553
|
+
)
|
|
554
|
+
|
|
555
|
+
# Search input
|
|
556
|
+
busqueda = Input(
|
|
557
|
+
placeholder="Buscar...",
|
|
558
|
+
input_type="search",
|
|
559
|
+
style={
|
|
560
|
+
"width": "300px",
|
|
561
|
+
"padding": "10px 15px",
|
|
562
|
+
"border": "1px solid #ddd",
|
|
563
|
+
"border-radius": "20px",
|
|
564
|
+
"background-color": "#f8f9fa"
|
|
565
|
+
}
|
|
566
|
+
)
|
|
567
|
+
```
|
|
568
|
+
|
|
569
|
+
### Container
|
|
570
|
+
|
|
571
|
+
The `Container` component is a container that can hold other components. It supports multiple ways to add child components.
|
|
572
|
+
|
|
573
|
+
#### Syntax
|
|
574
|
+
|
|
575
|
+
```python
|
|
576
|
+
from dars.components.basic.container import Container
|
|
577
|
+
|
|
578
|
+
# Method 1: Pass components as arguments
|
|
579
|
+
container = Container(
|
|
580
|
+
Text("Hello"),
|
|
581
|
+
Button("Click me"),
|
|
582
|
+
style={
|
|
583
|
+
"display": "flex",
|
|
584
|
+
"flex-direction": "column",
|
|
585
|
+
"padding": "20px",
|
|
586
|
+
"background-color": "#f8f9fa"
|
|
587
|
+
}
|
|
588
|
+
)
|
|
589
|
+
|
|
590
|
+
# Method 2: Use additional_children parameter
|
|
591
|
+
components = [Text("Hello"), Button("Click me")]
|
|
592
|
+
container = Container(
|
|
593
|
+
additional_children=components,
|
|
594
|
+
style={
|
|
595
|
+
"display": "flex",
|
|
596
|
+
"flex-direction": "column",
|
|
597
|
+
"padding": "20px",
|
|
598
|
+
"background-color": "#f8f9fa"
|
|
599
|
+
}
|
|
600
|
+
)
|
|
601
|
+
|
|
602
|
+
# Method 3: Add children after creation
|
|
603
|
+
container = Container(style={
|
|
604
|
+
"display": "flex",
|
|
605
|
+
"flex-direction": "column",
|
|
606
|
+
"padding": "20px",
|
|
607
|
+
"background-color": "#f8f9fa"
|
|
608
|
+
})
|
|
609
|
+
container.add_child(Text("Hello"))
|
|
610
|
+
container.add_child(Button("Click me"))
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
#### Properties
|
|
614
|
+
|
|
615
|
+
| Property | Type | Description |
|
|
616
|
+
|-----------|------|-------------|
|
|
617
|
+
| `children` | tuple | Components passed as positional arguments |
|
|
618
|
+
| `additional_children` | list | Optional list of additional components |
|
|
619
|
+
|
|
620
|
+
#### Container Layouts
|
|
621
|
+
|
|
622
|
+
```python
|
|
623
|
+
# Vertical layout (column)
|
|
624
|
+
columna = Container(
|
|
625
|
+
style={
|
|
626
|
+
"display": "flex",
|
|
627
|
+
"flex-direction": "column",
|
|
628
|
+
"gap": "15px",
|
|
629
|
+
"padding": "20px"
|
|
630
|
+
}
|
|
631
|
+
)
|
|
632
|
+
|
|
633
|
+
# Horizontal layout (row)
|
|
634
|
+
fila = Container(
|
|
635
|
+
style={
|
|
636
|
+
"display": "flex",
|
|
637
|
+
"flex-direction": "row",
|
|
638
|
+
"gap": "20px",
|
|
639
|
+
"align-items": "center"
|
|
640
|
+
}
|
|
641
|
+
)
|
|
642
|
+
|
|
643
|
+
# Layout centrado
|
|
644
|
+
centrado = Container(
|
|
645
|
+
style={
|
|
646
|
+
"display": "flex",
|
|
647
|
+
"justify-content": "center",
|
|
648
|
+
"align-items": "center",
|
|
649
|
+
"min-height": "100vh",
|
|
650
|
+
"background-color": "#f0f2f5"
|
|
651
|
+
}
|
|
652
|
+
)
|
|
653
|
+
|
|
654
|
+
# Card/Tarjeta
|
|
655
|
+
tarjeta = Container(
|
|
656
|
+
style={
|
|
657
|
+
"background-color": "white",
|
|
658
|
+
"border-radius": "12px",
|
|
659
|
+
"padding": "24px",
|
|
660
|
+
"box-shadow": "0 2px 10px rgba(0,0,0,0.1)",
|
|
661
|
+
"max-width": "400px",
|
|
662
|
+
"margin": "20px auto"
|
|
663
|
+
}
|
|
664
|
+
)
|
|
665
|
+
|
|
666
|
+
# Sidebar
|
|
667
|
+
sidebar = Container(
|
|
668
|
+
style={
|
|
669
|
+
"width": "250px",
|
|
670
|
+
"height": "100vh",
|
|
671
|
+
"background-color": "#2c3e50",
|
|
672
|
+
"padding": "20px",
|
|
673
|
+
"position": "fixed",
|
|
674
|
+
"left": "0",
|
|
675
|
+
"top": "0"
|
|
676
|
+
}
|
|
677
|
+
)
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
# Markdown
|
|
681
|
+
|
|
682
|
+
The `Markdown` component allows you to render markdown content directly in your Dars applications, converting markdown syntax to beautiful HTML with proper styling.
|
|
683
|
+
|
|
684
|
+
## Syntax
|
|
685
|
+
|
|
686
|
+
```python
|
|
687
|
+
from dars.components.basic.markdown import Markdown
|
|
688
|
+
|
|
689
|
+
# From string content
|
|
690
|
+
markdown_component = Markdown(
|
|
691
|
+
content="# Welcome\nThis is **markdown** content",
|
|
692
|
+
id="my-markdown",
|
|
693
|
+
class_name="custom-markdown",
|
|
694
|
+
style={"padding": "20px"}
|
|
695
|
+
)
|
|
696
|
+
|
|
697
|
+
# From file
|
|
698
|
+
markdown_from_file = Markdown(
|
|
699
|
+
file_path="README.md",
|
|
700
|
+
id="documentation",
|
|
701
|
+
dark_theme=True
|
|
702
|
+
)
|
|
703
|
+
```
|
|
704
|
+
|
|
705
|
+
## Properties
|
|
706
|
+
|
|
707
|
+
| Property | Type | Description | Example |
|
|
708
|
+
|-----------|------|-------------|---------|
|
|
709
|
+
| `content` | str | Markdown content as string | `"# Heading"` |
|
|
710
|
+
| `file_path` | str | Path to a markdown file | `"docs/intro.md"` |
|
|
711
|
+
| `dark_theme` | bool | Enable dark theme styling | `True` |
|
|
712
|
+
| `id` | str | Component ID | `"markdown-content"` |
|
|
713
|
+
| `class_name` | str | CSS class | `"markdown-body"` |
|
|
714
|
+
| `style` | dict | CSS styles | `{"fontSize": "16px"}` |
|
|
715
|
+
|
|
716
|
+
## Methods
|
|
717
|
+
|
|
718
|
+
| Method | Description | Example |
|
|
719
|
+
|--------|-------------|---------|
|
|
720
|
+
| `update_content(new_content=None, new_file_path=None)` | Update markdown content | `markdown_component.update_content(new_content="# New")` |
|
|
721
|
+
| `set_dark_theme(enabled=True)` | Enable/disable dark theme | `markdown_component.set_dark_theme(True)` |
|
|
722
|
+
|
|
723
|
+
## Examples
|
|
724
|
+
|
|
725
|
+
```python
|
|
726
|
+
# Simple markdown from string
|
|
727
|
+
simple_md = Markdown(
|
|
728
|
+
content="# Hello\nThis is a **markdown** example",
|
|
729
|
+
style={"maxWidth": "800px", "margin": "0 auto"}
|
|
730
|
+
)
|
|
731
|
+
|
|
732
|
+
# Load from file with dark theme
|
|
733
|
+
docs_md = Markdown(
|
|
734
|
+
file_path="documentation.md",
|
|
735
|
+
dark_theme=True,
|
|
736
|
+
class_name="docs-content"
|
|
737
|
+
)
|
|
738
|
+
|
|
739
|
+
# Update content dynamically
|
|
740
|
+
simple_md.update_content(new_content="# Updated\nNew content here")
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
## Dependencies
|
|
744
|
+
|
|
745
|
+
The Markdown component requires the `markdown2` library. Included with the framework.
|
|
746
|
+
|
|
747
|
+
## Supported Markdown Features
|
|
748
|
+
|
|
749
|
+
- Headers (`#`, `##`, `###`)
|
|
750
|
+
- **Bold** and *italic* text
|
|
751
|
+
- Lists (ordered and unordered)
|
|
752
|
+
- [Links](https://github.com/ZtaMDev/Dars-Framework)
|
|
753
|
+
- `Inline code` and code blocks
|
|
754
|
+
- Tables
|
|
755
|
+
- Blockquotes
|
|
756
|
+
- Images
|
|
757
|
+
- Horizontal rules
|
|
758
|
+
|
|
759
|
+
## Styling
|
|
760
|
+
|
|
761
|
+
The Markdown component includes comprehensive default styling for both light and dark themes:
|
|
762
|
+
|
|
763
|
+
```python
|
|
764
|
+
# Light theme (default)
|
|
765
|
+
markdown_light = Markdown(content="# Light theme")
|
|
766
|
+
|
|
767
|
+
# Dark theme
|
|
768
|
+
markdown_dark = Markdown(
|
|
769
|
+
content="# Dark theme",
|
|
770
|
+
dark_theme=True,
|
|
771
|
+
style={"padding": "20px", "borderRadius": "8px"}
|
|
772
|
+
)
|
|
773
|
+
```
|
|
774
|
+
|
|
775
|
+
## Best Practices
|
|
776
|
+
|
|
777
|
+
1. Use file paths for large documentation content
|
|
778
|
+
2. Enable dark theme for better readability in low-light environments
|
|
779
|
+
3. Combine with layout components for responsive designs
|
|
780
|
+
4. Use the update methods for dynamic content changes
|
|
781
|
+
|
|
782
|
+
## Integration Example
|
|
783
|
+
|
|
784
|
+
```python
|
|
785
|
+
from dars.core.app import App
|
|
786
|
+
from dars.components.basic.markdown import Markdown
|
|
787
|
+
from dars.components.basic.container import Container
|
|
788
|
+
|
|
789
|
+
app = App(title="Documentation Viewer")
|
|
790
|
+
|
|
791
|
+
# Load documentation from file
|
|
792
|
+
docs = Markdown(
|
|
793
|
+
file_path="README.md",
|
|
794
|
+
dark_theme=True,
|
|
795
|
+
class_name="documentation",
|
|
796
|
+
style={
|
|
797
|
+
"maxWidth": "800px",
|
|
798
|
+
"margin": "0 auto",
|
|
799
|
+
"padding": "40px",
|
|
800
|
+
"lineHeight": "1.6"
|
|
801
|
+
}
|
|
802
|
+
)
|
|
803
|
+
|
|
804
|
+
app.set_root(Container(children=[docs]))
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
This component is perfect for creating documentation pages, blog posts, content management systems, and any application that needs to display formatted text content.
|
|
808
|
+
|
|
809
|
+
### Image
|
|
810
|
+
|
|
811
|
+
The `Image` component displays images.
|
|
812
|
+
|
|
813
|
+
#### Syntax
|
|
814
|
+
|
|
815
|
+
```python
|
|
816
|
+
from dars.components.basic.image import Image
|
|
817
|
+
|
|
818
|
+
image = Image(
|
|
819
|
+
src="path/to/your/image.jpg",
|
|
820
|
+
alt="Descripción de la image",
|
|
821
|
+
width="300px",
|
|
822
|
+
height="200px",
|
|
823
|
+
class_name="responsive-img",
|
|
824
|
+
style={
|
|
825
|
+
"border-radius": "8px",
|
|
826
|
+
"box-shadow": "0 4px 8px rgba(0,0,0,0.1)"
|
|
827
|
+
}
|
|
828
|
+
)
|
|
829
|
+
```
|
|
830
|
+
|
|
831
|
+
#### Properties
|
|
832
|
+
|
|
833
|
+
| Property | Type | Description | Example |
|
|
834
|
+
|-----------|------|-------------|---------|
|
|
835
|
+
| `src` | str | Image path | `"images/logo.png"` |
|
|
836
|
+
| `alt` | str | Alternative text | `"Logo of the company"` |
|
|
837
|
+
| `width` | str | Ancho de la image (CSS) | `"100%"`, `"200px"` |
|
|
838
|
+
| `height` | str | Alto de la image (CSS) | `"auto"`, `"150px"` |
|
|
839
|
+
|
|
840
|
+
### Link
|
|
841
|
+
|
|
842
|
+
The `Link` component creates navigation links.
|
|
843
|
+
|
|
844
|
+
#### Syntax
|
|
845
|
+
|
|
846
|
+
```python
|
|
847
|
+
from dars.components.basic.link import Link
|
|
848
|
+
|
|
849
|
+
link = Link(
|
|
850
|
+
text="Visitar Google",
|
|
851
|
+
href="https://www.google.com",
|
|
852
|
+
target="_blank", # Abre en una nueva pestaña
|
|
853
|
+
class_name="external-link",
|
|
854
|
+
style={
|
|
855
|
+
"color": "#007bff",
|
|
856
|
+
"text-decoration": "none",
|
|
857
|
+
"font-weight": "bold"
|
|
858
|
+
}
|
|
859
|
+
)
|
|
860
|
+
```
|
|
861
|
+
|
|
862
|
+
#### Properties
|
|
863
|
+
|
|
864
|
+
| Property | Type | Description | Values |
|
|
865
|
+
|-----------|------|-------------|---------|
|
|
866
|
+
| `text` | str | Link text | `"Ir a la página"` |
|
|
867
|
+
| `href` | str | URL of destination | `"/about"`, `"https://example.com"` |
|
|
868
|
+
| `target` | str | Dónde abrir el link | `"_self"` (misma pestaña), `"_blank"` (nueva pestaña) |
|
|
869
|
+
|
|
870
|
+
### Textarea
|
|
871
|
+
|
|
872
|
+
The `Textarea` component allows for multi-line text input.
|
|
873
|
+
|
|
874
|
+
#### Syntax
|
|
875
|
+
|
|
876
|
+
```python
|
|
877
|
+
from dars.components.basic.textarea import Textarea
|
|
878
|
+
|
|
879
|
+
area_text = Textarea(
|
|
880
|
+
value="Texto inicial",
|
|
881
|
+
placeholder="Escribe tu mensaje aquí...",
|
|
882
|
+
rows=5,
|
|
883
|
+
cols=40,
|
|
884
|
+
disabled=False,
|
|
885
|
+
readonly=False,
|
|
886
|
+
required=True,
|
|
887
|
+
max_length=500,
|
|
888
|
+
class_name="comment-box",
|
|
889
|
+
style={
|
|
890
|
+
"width": "100%",
|
|
891
|
+
"padding": "10px",
|
|
892
|
+
"border": "1px solid #ccc",
|
|
893
|
+
"border-radius": "5px"
|
|
894
|
+
}
|
|
895
|
+
)
|
|
896
|
+
```
|
|
897
|
+
|
|
898
|
+
#### Properties
|
|
899
|
+
|
|
900
|
+
| Property | Type | Description | Values |
|
|
901
|
+
|-----------|------|-------------|---------|
|
|
902
|
+
| `value` | str | Initial value | `""` |
|
|
903
|
+
| `placeholder` | str | Help text | `"Escribe aquí..."` |
|
|
904
|
+
| `rows` | int | Número de filas visibles | `4` |
|
|
905
|
+
| `cols` | int | Número de columnas visibles | `50` |
|
|
906
|
+
| `disabled` | bool | Si está deshabilitado | `True`, `False` |
|
|
907
|
+
| `readonly` | bool | Solo lectura | `True`, `False` |
|
|
908
|
+
| `required` | bool | Campo obligatorio | `True`, `False` |
|
|
909
|
+
| `max_length` | int | Longitud máxima | `500` |
|
|
910
|
+
|
|
911
|
+
---
|
|
912
|
+
|
|
913
|
+
---
|
|
914
|
+
|
|
915
|
+
### ProgressBar
|
|
916
|
+
|
|
917
|
+
The `ProgressBar` component visually displays progress for a task, such as loading or completion percentage.
|
|
918
|
+
|
|
919
|
+
#### Syntax
|
|
920
|
+
|
|
921
|
+
```python
|
|
922
|
+
from dars.components.basic.progressbar import ProgressBar
|
|
923
|
+
|
|
924
|
+
progress = ProgressBar(value=40, max_value=100)
|
|
925
|
+
```
|
|
926
|
+
|
|
927
|
+
#### Properties
|
|
928
|
+
|
|
929
|
+
| Property | Type | Description |
|
|
930
|
+
|-------------|------|-----------------------------------|
|
|
931
|
+
| `value` | int | Current progress value |
|
|
932
|
+
| `max_value` | int | Maximum value (default: 100) |
|
|
933
|
+
|
|
934
|
+
#### Example
|
|
935
|
+
|
|
936
|
+
```python
|
|
937
|
+
progress = ProgressBar(value=75, max_value=100)
|
|
938
|
+
```
|
|
939
|
+
|
|
940
|
+
---
|
|
941
|
+
|
|
942
|
+
### Tooltip
|
|
943
|
+
|
|
944
|
+
The `Tooltip` component displays a tooltip when hovering over a child component.
|
|
945
|
+
|
|
946
|
+
#### Syntax
|
|
947
|
+
|
|
948
|
+
```python
|
|
949
|
+
from dars.components.basic.tooltip import Tooltip
|
|
950
|
+
from dars.components.basic.button import Button
|
|
951
|
+
|
|
952
|
+
tooltip = Tooltip(
|
|
953
|
+
text="More info",
|
|
954
|
+
child=Button(text="Hover me")
|
|
955
|
+
)
|
|
956
|
+
```
|
|
957
|
+
|
|
958
|
+
#### Properties
|
|
959
|
+
|
|
960
|
+
| Property | Type | Description |
|
|
961
|
+
|------------|-----------|-----------------------------------------|
|
|
962
|
+
| `text` | str | Tooltip text |
|
|
963
|
+
| `child` | Component | Component to wrap |
|
|
964
|
+
| `position` | str | Tooltip position (e.g., "top") |
|
|
965
|
+
|
|
966
|
+
#### Example
|
|
967
|
+
|
|
968
|
+
```python
|
|
969
|
+
tooltip = Tooltip(text="Help", child=Button(text="?"))
|
|
970
|
+
```
|
|
971
|
+
|
|
972
|
+
---
|
|
973
|
+
|
|
974
|
+
### Accordion
|
|
975
|
+
|
|
976
|
+
The `Accordion` component creates a vertically stacked set of expandable/collapsible panels for organizing content.
|
|
977
|
+
|
|
978
|
+
#### Syntax
|
|
979
|
+
|
|
980
|
+
```python
|
|
981
|
+
from dars.components.advanced.accordion import Accordion
|
|
982
|
+
|
|
983
|
+
accordion = Accordion(
|
|
984
|
+
items=[
|
|
985
|
+
{"title": "Section 1", "content": "Content for section 1"},
|
|
986
|
+
{"title": "Section 2", "content": "Content for section 2"}
|
|
987
|
+
],
|
|
988
|
+
allow_multiple=False
|
|
989
|
+
)
|
|
990
|
+
```
|
|
991
|
+
|
|
992
|
+
#### Properties
|
|
993
|
+
|
|
994
|
+
| Property | Type | Description |
|
|
995
|
+
|------------------|---------|-----------------------------------------------------|
|
|
996
|
+
| `items` | list | List of dicts with `title` and `content` |
|
|
997
|
+
| `allow_multiple` | bool | Allow multiple sections open at once |
|
|
998
|
+
|
|
999
|
+
#### Example
|
|
1000
|
+
|
|
1001
|
+
```python
|
|
1002
|
+
accordion = Accordion(
|
|
1003
|
+
items=[
|
|
1004
|
+
{"title": "FAQ 1", "content": "Answer 1"},
|
|
1005
|
+
{"title": "FAQ 2", "content": "Answer 2"}
|
|
1006
|
+
]
|
|
1007
|
+
)
|
|
1008
|
+
```
|
|
1009
|
+
|
|
1010
|
+
---
|
|
1011
|
+
|
|
1012
|
+
### Tabs
|
|
1013
|
+
|
|
1014
|
+
The `Tabs` component allows navigation between different views or content panels.
|
|
1015
|
+
|
|
1016
|
+
> **New in 1.0.5:** The exporter now recursively detects Tabs at any nesting level (including inside containers, panels, or multipage apps) for `minimum_logic` and JS injection. You can safely nest Tabs in any structure and the export will work as expected.
|
|
1017
|
+
|
|
1018
|
+
|
|
1019
|
+
#### Syntax
|
|
1020
|
+
|
|
1021
|
+
```python
|
|
1022
|
+
from dars.components.advanced.tabs import Tabs
|
|
1023
|
+
|
|
1024
|
+
tabs = Tabs(
|
|
1025
|
+
tabs=[
|
|
1026
|
+
{"label": "Tab 1", "content": "Content 1"},
|
|
1027
|
+
{"label": "Tab 2", "content": "Content 2"}
|
|
1028
|
+
],
|
|
1029
|
+
default_index=0
|
|
1030
|
+
)
|
|
1031
|
+
```
|
|
1032
|
+
|
|
1033
|
+
#### Properties
|
|
1034
|
+
|
|
1035
|
+
| Property | Type | Description |
|
|
1036
|
+
|-----------------|------|------------------------------------------|
|
|
1037
|
+
| `tabs` | list | List of dicts with `label` and `content` |
|
|
1038
|
+
| `default_index` | int | Index of the initially selected tab |
|
|
1039
|
+
|
|
1040
|
+
#### Example
|
|
1041
|
+
|
|
1042
|
+
```python
|
|
1043
|
+
tabs = Tabs(
|
|
1044
|
+
tabs=[
|
|
1045
|
+
{"label": "Overview", "content": "Main content"},
|
|
1046
|
+
{"label": "Details", "content": "Detailed info"}
|
|
1047
|
+
],
|
|
1048
|
+
default_index=0
|
|
1049
|
+
)
|
|
1050
|
+
```
|
|
1051
|
+
|
|
1052
|
+
---
|
|
1053
|
+
|
|
1054
|
+
### Table
|
|
1055
|
+
|
|
1056
|
+
The `Table` component displays tabular data with rows and columns.
|
|
1057
|
+
|
|
1058
|
+
#### Syntax
|
|
1059
|
+
|
|
1060
|
+
```python
|
|
1061
|
+
from dars.components.advanced.table import Table
|
|
1062
|
+
|
|
1063
|
+
table = Table(
|
|
1064
|
+
columns=["Name", "Age", "Country"],
|
|
1065
|
+
data=[
|
|
1066
|
+
["Alice", 30, "USA"],
|
|
1067
|
+
["Bob", 25, "UK"]
|
|
1068
|
+
]
|
|
1069
|
+
)
|
|
1070
|
+
```
|
|
1071
|
+
|
|
1072
|
+
#### Properties
|
|
1073
|
+
|
|
1074
|
+
| Property | Type | Description |
|
|
1075
|
+
|------------|--------|-----------------------------------|
|
|
1076
|
+
| `columns` | list | List of column headers |
|
|
1077
|
+
| `data` | list | List of rows (each a list/tuple) |
|
|
1078
|
+
|
|
1079
|
+
#### Example
|
|
1080
|
+
|
|
1081
|
+
```python
|
|
1082
|
+
table = Table(
|
|
1083
|
+
columns=["Product", "Price"],
|
|
1084
|
+
data=[
|
|
1085
|
+
["Book", "$10"],
|
|
1086
|
+
["Pen", "$2"]
|
|
1087
|
+
]
|
|
1088
|
+
)
|
|
1089
|
+
```
|
|
1090
|
+
|
|
1091
|
+
---
|
|
1092
|
+
|
|
1093
|
+
## Layout Components
|
|
1094
|
+
|
|
1095
|
+
### GridLayout
|
|
1096
|
+
|
|
1097
|
+
The `GridLayout` component provides a responsive grid-based layout with customizable rows, columns, gaps, and anchor points for precise positioning of children.
|
|
1098
|
+
|
|
1099
|
+
#### Syntax
|
|
1100
|
+
|
|
1101
|
+
```python
|
|
1102
|
+
from dars.components.layout.grid import GridLayout
|
|
1103
|
+
from dars.components.basic.text import Text
|
|
1104
|
+
|
|
1105
|
+
grid = GridLayout(
|
|
1106
|
+
rows=2,
|
|
1107
|
+
cols=2,
|
|
1108
|
+
gap="24px",
|
|
1109
|
+
children=[
|
|
1110
|
+
Text("Top Left"),
|
|
1111
|
+
Text("Top Right"),
|
|
1112
|
+
Text("Bottom Left"),
|
|
1113
|
+
Text("Bottom Right")
|
|
1114
|
+
]
|
|
1115
|
+
)
|
|
1116
|
+
```
|
|
1117
|
+
|
|
1118
|
+
#### Properties
|
|
1119
|
+
|
|
1120
|
+
| Property | Type | Description |
|
|
1121
|
+
|------------|--------|---------------------------------------------|
|
|
1122
|
+
| `rows` | int | Number of grid rows |
|
|
1123
|
+
| `cols` | int | Number of grid columns |
|
|
1124
|
+
| `gap` | str | Gap between grid cells (e.g., "16px") |
|
|
1125
|
+
| `children` | list | List of child components |
|
|
1126
|
+
| `anchors` | dict | Optional anchor points for child placement |
|
|
1127
|
+
|
|
1128
|
+
#### Example
|
|
1129
|
+
|
|
1130
|
+
```python
|
|
1131
|
+
grid = GridLayout(
|
|
1132
|
+
rows=3,
|
|
1133
|
+
cols=2,
|
|
1134
|
+
gap="16px",
|
|
1135
|
+
children=[Text(f"Cell {i}") for i in range(6)]
|
|
1136
|
+
)
|
|
1137
|
+
```
|
|
1138
|
+
|
|
1139
|
+
---
|
|
1140
|
+
|
|
1141
|
+
### FlexLayout
|
|
1142
|
+
|
|
1143
|
+
The `FlexLayout` component provides a responsive flexbox layout, supporting direction, wrap, alignment, and gap between children. Useful for row/column layouts.
|
|
1144
|
+
|
|
1145
|
+
#### Syntax
|
|
1146
|
+
|
|
1147
|
+
```python
|
|
1148
|
+
from dars.components.layout.flex import FlexLayout
|
|
1149
|
+
from dars.components.basic.button import Button
|
|
1150
|
+
|
|
1151
|
+
flex = FlexLayout(
|
|
1152
|
+
direction="row",
|
|
1153
|
+
justify="space-between",
|
|
1154
|
+
align="center",
|
|
1155
|
+
gap="12px",
|
|
1156
|
+
children=[Button("A"), Button("B"), Button("C")]
|
|
1157
|
+
)
|
|
1158
|
+
```
|
|
1159
|
+
|
|
1160
|
+
#### Properties
|
|
1161
|
+
|
|
1162
|
+
| Property | Type | Description |
|
|
1163
|
+
|-------------|--------|-----------------------------------------------------|
|
|
1164
|
+
| `direction` | str | Flex direction: "row" or "column" |
|
|
1165
|
+
| `wrap` | str | Flex wrap: "wrap" or "nowrap" |
|
|
1166
|
+
| `justify` | str | Justify content: e.g., "flex-start", "center" |
|
|
1167
|
+
| `align` | str | Align items: e.g., "stretch", "center" |
|
|
1168
|
+
| `gap` | str | Gap between children (e.g., "16px") |
|
|
1169
|
+
| `children` | list | List of child components |
|
|
1170
|
+
| `anchors` | dict | Optional anchor points for child placement |
|
|
1171
|
+
|
|
1172
|
+
#### Example
|
|
1173
|
+
|
|
1174
|
+
```python
|
|
1175
|
+
flex = FlexLayout(
|
|
1176
|
+
direction="column",
|
|
1177
|
+
gap="24px",
|
|
1178
|
+
children=[Button("Save"), Button("Cancel")]
|
|
1179
|
+
)
|
|
1180
|
+
```
|
|
1181
|
+
|
|
1182
|
+
---
|
|
1183
|
+
|
|
1184
|
+
### LayoutBase
|
|
1185
|
+
|
|
1186
|
+
The `LayoutBase` component is the base class for all layout components. It allows adding children and anchor/positioning info. You typically use `FlexLayout` or `GridLayout` directly.
|
|
1187
|
+
|
|
1188
|
+
#### Syntax
|
|
1189
|
+
|
|
1190
|
+
```python
|
|
1191
|
+
from dars.components.layout.grid import LayoutBase
|
|
1192
|
+
from dars.components.basic.text import Text
|
|
1193
|
+
|
|
1194
|
+
layout = LayoutBase(
|
|
1195
|
+
children=[Text("Item 1"), Text("Item 2")],
|
|
1196
|
+
anchors={}
|
|
1197
|
+
)
|
|
1198
|
+
```
|
|
1199
|
+
|
|
1200
|
+
#### Properties
|
|
1201
|
+
|
|
1202
|
+
| Property | Type | Description |
|
|
1203
|
+
|-------------|--------|--------------------------------|
|
|
1204
|
+
| `children` | list | List of child components |
|
|
1205
|
+
| `anchors` | dict | Anchor/positioning information |
|
|
1206
|
+
|
|
1207
|
+
---
|
|
1208
|
+
|
|
1209
|
+
### AnchorPoint
|
|
1210
|
+
|
|
1211
|
+
The `AnchorPoint` class represents an anchor or alignment point for a child in a layout (e.g., top, left, right, bottom, center, percent, or px).
|
|
1212
|
+
|
|
1213
|
+
#### Syntax
|
|
1214
|
+
|
|
1215
|
+
```python
|
|
1216
|
+
from dars.components.layout.anchor import AnchorPoint
|
|
1217
|
+
|
|
1218
|
+
anchor = AnchorPoint(x="left", y="top", name="top-left")
|
|
1219
|
+
```
|
|
1220
|
+
|
|
1221
|
+
#### Properties
|
|
1222
|
+
|
|
1223
|
+
| Property | Type | Description |
|
|
1224
|
+
|----------|------|--------------------------------------------------|
|
|
1225
|
+
| `x` | str | Horizontal alignment (e.g., "left", "center") |
|
|
1226
|
+
| `y` | str | Vertical alignment (e.g., "top", "center") |
|
|
1227
|
+
| `name` | str | Optional semantic name for the anchor |
|
|
1228
|
+
|
|
1229
|
+
#### Example
|
|
1230
|
+
|
|
1231
|
+
```python
|
|
1232
|
+
anchor = AnchorPoint(x="50%", y="50%", name="center")
|
|
1233
|
+
```
|
|
1234
|
+
|
|
1235
|
+
---
|
|
1236
|
+
|
|
1237
|
+
### Card
|
|
1238
|
+
|
|
1239
|
+
The `Card` component is a styled container to group related content, such as a title and other components.
|
|
1240
|
+
|
|
1241
|
+
#### Syntax
|
|
1242
|
+
|
|
1243
|
+
```python
|
|
1244
|
+
from dars.components.basic.card import Card
|
|
1245
|
+
from dars.components.basic.text import Text
|
|
1246
|
+
from dars.components.basic.button import Button
|
|
1247
|
+
|
|
1248
|
+
my_card = Card(
|
|
1249
|
+
title="Título de la Tarjeta",
|
|
1250
|
+
children=[
|
|
1251
|
+
Text("Este es el contenido de la tarjeta."),
|
|
1252
|
+
Button("Ver más")
|
|
1253
|
+
],
|
|
1254
|
+
class_name="product-card",
|
|
1255
|
+
style={
|
|
1256
|
+
"background-color": "#ffffff",
|
|
1257
|
+
"border": "1px solid #e0e0e0",
|
|
1258
|
+
"border-radius": "10px",
|
|
1259
|
+
"padding": "20px",
|
|
1260
|
+
"box-shadow": "0 4px 8px rgba(0,0,0,0.05)"
|
|
1261
|
+
}
|
|
1262
|
+
)
|
|
1263
|
+
```
|
|
1264
|
+
|
|
1265
|
+
#### Properties
|
|
1266
|
+
|
|
1267
|
+
| Property | Type | Description |
|
|
1268
|
+
|-----------|------|-------------|
|
|
1269
|
+
| `title` | str | Card title |
|
|
1270
|
+
| `children` | list | List of child components |
|
|
1271
|
+
|
|
1272
|
+
#### Example
|
|
1273
|
+
|
|
1274
|
+
```python
|
|
1275
|
+
my_card = Card(
|
|
1276
|
+
title="Título de la Tarjeta",
|
|
1277
|
+
children=[
|
|
1278
|
+
Text("Este es el contenido de la tarjeta."),
|
|
1279
|
+
Button("Ver más")
|
|
1280
|
+
],
|
|
1281
|
+
class_name="product-card",
|
|
1282
|
+
style={
|
|
1283
|
+
"background-color": "#ffffff",
|
|
1284
|
+
"border": "1px solid #e0e0e0",
|
|
1285
|
+
"border-radius": "10px",
|
|
1286
|
+
"padding": "20px",
|
|
1287
|
+
"box-shadow": "0 4px 8px rgba(0,0,0,0.05)"
|
|
1288
|
+
}
|
|
1289
|
+
)
|
|
1290
|
+
```
|
|
1291
|
+
|
|
1292
|
+
---
|
|
1293
|
+
|
|
1294
|
+
### Modal
|
|
1295
|
+
|
|
1296
|
+
The `Modal` component creates an overlay window that appears on top of the main page content.
|
|
1297
|
+
|
|
1298
|
+
> **New in 1.0.5:** Modal is now exported as hidden by default (`hidden` attribute and `dars-modal-hidden` class) if `is_open=False`, preventing any visual flicker on page load, even if CSS/JS loads slowly.
|
|
1299
|
+
|
|
1300
|
+
#### Syntax
|
|
1301
|
+
|
|
1302
|
+
```python
|
|
1303
|
+
from dars.components.advanced.modal import Modal
|
|
1304
|
+
from dars.components.basic.text import Text
|
|
1305
|
+
from dars.components.basic.button import Button
|
|
1306
|
+
|
|
1307
|
+
my_modal = Modal(
|
|
1308
|
+
title="Welcome to the Modal",
|
|
1309
|
+
is_open=False, # Now hidden from the very first render
|
|
1310
|
+
children=[
|
|
1311
|
+
Text("This is your modal content."),
|
|
1312
|
+
Button("Close")
|
|
1313
|
+
],
|
|
1314
|
+
class_name="welcome-modal",
|
|
1315
|
+
style={
|
|
1316
|
+
"background-color": "rgba(0, 0, 0, 0.7)" # Overlay style
|
|
1317
|
+
}
|
|
1318
|
+
)
|
|
1319
|
+
```
|
|
1320
|
+
|
|
1321
|
+
#### Properties
|
|
1322
|
+
|
|
1323
|
+
| Property | Type | Description |
|
|
1324
|
+
|------------|------|------------------------------------------------------------|
|
|
1325
|
+
| `title` | str | Modal title |
|
|
1326
|
+
| `is_open` | bool | Controls modal visibility (`True` to show, `False` to hide). If `False`, modal is hidden from exported HTML. |
|
|
1327
|
+
| `children` | list | List of child components |
|
|
1328
|
+
|
|
1329
|
+
#### Updated Example
|
|
1330
|
+
|
|
1331
|
+
```python
|
|
1332
|
+
my_modal = Modal(
|
|
1333
|
+
title="Welcome to the Modal",
|
|
1334
|
+
is_open=False, # Hidden from the very first render
|
|
1335
|
+
children=[
|
|
1336
|
+
Text("This is your modal content."),
|
|
1337
|
+
Button("Close")
|
|
1338
|
+
],
|
|
1339
|
+
class_name="welcome-modal",
|
|
1340
|
+
style={
|
|
1341
|
+
"background-color": "rgba(0, 0, 0, 0.7)"
|
|
1342
|
+
}
|
|
1343
|
+
)
|
|
1344
|
+
```
|
|
1345
|
+
|
|
1346
|
+
> **Note:** The exporter now recursively detects advanced components (Tabs, Accordion, Modal, Card) at any nesting level, including inside multipage apps, and applies `minimum_logic` robustly.
|
|
1347
|
+
|
|
1348
|
+
---
|
|
1349
|
+
|
|
1350
|
+
### Navbar
|
|
1351
|
+
|
|
1352
|
+
The `Navbar` component creates a navigation bar, commonly used at the top of pages.
|
|
1353
|
+
|
|
1354
|
+
#### Syntax
|
|
1355
|
+
|
|
1356
|
+
```python
|
|
1357
|
+
from dars.components.advanced.navbar import Navbar
|
|
1358
|
+
from dars.components.basic.link import Link
|
|
1359
|
+
|
|
1360
|
+
my_navbar = Navbar(
|
|
1361
|
+
brand="Mi App",
|
|
1362
|
+
children=[
|
|
1363
|
+
Link("Inicio", "/"),
|
|
1364
|
+
Link("Acerca de", "/about"),
|
|
1365
|
+
Link("Contacto", "/contact")
|
|
1366
|
+
],
|
|
1367
|
+
class_name="main-nav",
|
|
1368
|
+
style={
|
|
1369
|
+
"background-color": "#333",
|
|
1370
|
+
"color": "white",
|
|
1371
|
+
"padding": "15px 20px"
|
|
1372
|
+
}
|
|
1373
|
+
)
|
|
1374
|
+
```
|
|
1375
|
+
|
|
1376
|
+
#### Properties
|
|
1377
|
+
|
|
1378
|
+
| Property | Type | Description |
|
|
1379
|
+
|-----------|------|-------------|
|
|
1380
|
+
| `brand` | str | Texto o componente para la marca/logo de la navegación |
|
|
1381
|
+
| `children` | list | List of child components (navigation items, usually `Link`s) |
|
|
1382
|
+
|
|
1383
|
+
## Additional Components
|
|
1384
|
+
|
|
1385
|
+
### Checkbox
|
|
1386
|
+
|
|
1387
|
+
The `Checkbox` component allows users to select options.
|
|
1388
|
+
|
|
1389
|
+
#### Syntax
|
|
1390
|
+
|
|
1391
|
+
```python
|
|
1392
|
+
from dars.components.basic.checkbox import Checkbox
|
|
1393
|
+
|
|
1394
|
+
mi_checkbox = Checkbox(
|
|
1395
|
+
label="Acepto términos",
|
|
1396
|
+
checked=True,
|
|
1397
|
+
style={
|
|
1398
|
+
"margin": "10px"
|
|
1399
|
+
}
|
|
1400
|
+
)
|
|
1401
|
+
```
|
|
1402
|
+
|
|
1403
|
+
#### Properties
|
|
1404
|
+
|
|
1405
|
+
| Property | Type | Description | Values |
|
|
1406
|
+
|-----------|------|-------------|---------|
|
|
1407
|
+
| `label` | str | Texto de la etiqueta | `"Acepto términos"` |
|
|
1408
|
+
| `checked` | bool | Estado de selección | `True`, `False` |
|
|
1409
|
+
|
|
1410
|
+
### RadioButton
|
|
1411
|
+
|
|
1412
|
+
The `RadioButton` component allows users to select one option from a group of options.
|
|
1413
|
+
|
|
1414
|
+
#### Syntax
|
|
1415
|
+
|
|
1416
|
+
```python
|
|
1417
|
+
from dars.components.basic.radio_button import RadioButton
|
|
1418
|
+
|
|
1419
|
+
mi_radio_button = RadioButton(
|
|
1420
|
+
label="Opción A",
|
|
1421
|
+
name="grupo1",
|
|
1422
|
+
checked=False,
|
|
1423
|
+
style={
|
|
1424
|
+
"margin": "10px"
|
|
1425
|
+
}
|
|
1426
|
+
)
|
|
1427
|
+
```
|
|
1428
|
+
|
|
1429
|
+
#### Properties
|
|
1430
|
+
|
|
1431
|
+
| Property | Type | Description | Values |
|
|
1432
|
+
|-----------|------|-------------|---------|
|
|
1433
|
+
| `label` | str | Texto de la etiqueta | `"Opción A"` |
|
|
1434
|
+
| `name` | str | Nombre del grupo de radio buttons | `"grupo1"` |
|
|
1435
|
+
| `checked` | bool | Estado de selección | `True`, `False` |
|
|
1436
|
+
|
|
1437
|
+
### Select
|
|
1438
|
+
|
|
1439
|
+
The `Select` component allows users to select one option from a group of options.
|
|
1440
|
+
|
|
1441
|
+
#### Syntax
|
|
1442
|
+
|
|
1443
|
+
```python
|
|
1444
|
+
from dars.components.basic.select import Select
|
|
1445
|
+
|
|
1446
|
+
mi_select = Select(
|
|
1447
|
+
options=["Uno", "Dos", "Tres"],
|
|
1448
|
+
value="Dos",
|
|
1449
|
+
style={
|
|
1450
|
+
"width": "200px",
|
|
1451
|
+
"padding": "10px",
|
|
1452
|
+
"border": "1px solid #ccc"
|
|
1453
|
+
}
|
|
1454
|
+
)
|
|
1455
|
+
```
|
|
1456
|
+
|
|
1457
|
+
#### Properties
|
|
1458
|
+
|
|
1459
|
+
| Property | Type | Description | Values |
|
|
1460
|
+
|-----------|------|-------------|---------|
|
|
1461
|
+
| `options` | list | List of options | `["Uno", "Dos", "Tres"]` |
|
|
1462
|
+
| `value` | str | Selected value | `"Dos"` |
|
|
1463
|
+
|
|
1464
|
+
### Slider
|
|
1465
|
+
|
|
1466
|
+
The `Slider` component allows users to select a value within a range.
|
|
1467
|
+
|
|
1468
|
+
#### Syntax
|
|
1469
|
+
|
|
1470
|
+
```python
|
|
1471
|
+
from dars.components.basic.slider import Slider
|
|
1472
|
+
|
|
1473
|
+
mi_slider = Slider(
|
|
1474
|
+
min_value=0,
|
|
1475
|
+
max_value=100,
|
|
1476
|
+
value=50,
|
|
1477
|
+
show_value=True,
|
|
1478
|
+
style={
|
|
1479
|
+
"width": "200px",
|
|
1480
|
+
"padding": "10px"
|
|
1481
|
+
}
|
|
1482
|
+
)
|
|
1483
|
+
```
|
|
1484
|
+
|
|
1485
|
+
#### Properties
|
|
1486
|
+
|
|
1487
|
+
| Property | Type | Description | Values |
|
|
1488
|
+
|-----------|------|-------------|---------|
|
|
1489
|
+
| `min_value` | int | Minimum value | `0` |
|
|
1490
|
+
| `max_value` | int | Maximum value | `100` |
|
|
1491
|
+
| `value` | int | Valor selectado | `50` |
|
|
1492
|
+
| `show_value` | bool | Mostrar el valor selectado | `True`, `False` |
|
|
1493
|
+
|
|
1494
|
+
|
|
1495
|
+
### DatePicker
|
|
1496
|
+
|
|
1497
|
+
The `DatePicker` component allows users to select a date.
|
|
1498
|
+
|
|
1499
|
+
#### Syntax
|
|
1500
|
+
|
|
1501
|
+
```python
|
|
1502
|
+
from dars.components.basic.date_picker import DatePicker
|
|
1503
|
+
|
|
1504
|
+
mi_date_picker = DatePicker(
|
|
1505
|
+
value="2025-08-06",
|
|
1506
|
+
style={
|
|
1507
|
+
"width": "200px",
|
|
1508
|
+
"padding": "10px",
|
|
1509
|
+
"border": "1px solid #ccc"
|
|
1510
|
+
}
|
|
1511
|
+
)
|
|
1512
|
+
```
|
|
1513
|
+
|
|
1514
|
+
#### Properties
|
|
1515
|
+
|
|
1516
|
+
| Property | Type | Description | Values |
|
|
1517
|
+
|-----------|------|-------------|---------|
|
|
1518
|
+
| `value` | str | Selected date | `"2025-08-06"` |
|
|
1519
|
+
|
|
1520
|
+
## Styling System
|
|
1521
|
+
|
|
1522
|
+
### Supported Style Properties
|
|
1523
|
+
|
|
1524
|
+
Dars supports most standard CSS properties:
|
|
1525
|
+
|
|
1526
|
+
#### Dimensions
|
|
1527
|
+
- `width`, `height`
|
|
1528
|
+
- `min-width`, `min-height`
|
|
1529
|
+
- `max-width`, `max-height`
|
|
1530
|
+
|
|
1531
|
+
#### Spacing
|
|
1532
|
+
- `margin`, `margin-top`, `margin-right`, `margin-bottom`, `margin-left`
|
|
1533
|
+
- `padding`, `padding-top`, `padding-right`, `padding-bottom`, `padding-left`
|
|
1534
|
+
|
|
1535
|
+
#### Colors
|
|
1536
|
+
- `background-color`
|
|
1537
|
+
- `color`
|
|
1538
|
+
- `border-color`
|
|
1539
|
+
|
|
1540
|
+
#### Typography
|
|
1541
|
+
- `font-size`, `font-family`, `font-weight`, `font-style`
|
|
1542
|
+
- `text-align`, `text-decoration`, `line-height`
|
|
1543
|
+
|
|
1544
|
+
#### Borders
|
|
1545
|
+
- `border`, `border-width`, `border-style`, `border-radius`
|
|
1546
|
+
|
|
1547
|
+
#### Layout
|
|
1548
|
+
- `display`, `position`
|
|
1549
|
+
- `top`, `right`, `bottom`, `left`, `z-index`
|
|
1550
|
+
|
|
1551
|
+
#### Flexbox
|
|
1552
|
+
- `flex-direction`, `flex-wrap`
|
|
1553
|
+
- `justify-content`, `align-items`, `align-content`
|
|
1554
|
+
- `flex`, `flex-grow`, `flex-shrink`, `flex-basis`
|
|
1555
|
+
|
|
1556
|
+
#### Grid
|
|
1557
|
+
- `grid-template-columns`, `grid-template-rows`
|
|
1558
|
+
- `grid-gap`, `grid-column`, `grid-row`
|
|
1559
|
+
|
|
1560
|
+
#### Effects
|
|
1561
|
+
- `opacity`, `box-shadow`, `transform`, `transition`
|
|
1562
|
+
|
|
1563
|
+
### Advanced Style Examples
|
|
1564
|
+
|
|
1565
|
+
```python
|
|
1566
|
+
# Gradiente de fondo
|
|
1567
|
+
gradiente = Container(
|
|
1568
|
+
style={
|
|
1569
|
+
"background": "linear-gradient(135deg, #667eea 0%, #764ba2 100%)",
|
|
1570
|
+
"min-height": "100vh",
|
|
1571
|
+
"display": "flex",
|
|
1572
|
+
"align-items": "center",
|
|
1573
|
+
"justify-content": "center"
|
|
1574
|
+
}
|
|
1575
|
+
)
|
|
1576
|
+
|
|
1577
|
+
# Animación de hover (para web)
|
|
1578
|
+
boton_animado = Button(
|
|
1579
|
+
text="Hover me",
|
|
1580
|
+
style={
|
|
1581
|
+
"background-color": "#3498db",
|
|
1582
|
+
"color": "white",
|
|
1583
|
+
"padding": "15px 30px",
|
|
1584
|
+
"border": "none",
|
|
1585
|
+
"border-radius": "8px",
|
|
1586
|
+
"transition": "all 0.3s ease",
|
|
1587
|
+
"transform": "translateY(0)",
|
|
1588
|
+
"box-shadow": "0 4px 15px rgba(52, 152, 219, 0.3)"
|
|
1589
|
+
}
|
|
1590
|
+
)
|
|
1591
|
+
|
|
1592
|
+
# Layout de grid
|
|
1593
|
+
grid_container = Container(
|
|
1594
|
+
style={
|
|
1595
|
+
"display": "grid",
|
|
1596
|
+
"grid-template-columns": "repeat(auto-fit, minmax(250px, 1fr))",
|
|
1597
|
+
"grid-gap": "20px",
|
|
1598
|
+
"padding": "20px"
|
|
1599
|
+
}
|
|
1600
|
+
)
|
|
1601
|
+
|
|
1602
|
+
# Responsive design
|
|
1603
|
+
responsive_container = Container(
|
|
1604
|
+
style={
|
|
1605
|
+
"width": "100%",
|
|
1606
|
+
"max-width": "1200px",
|
|
1607
|
+
"margin": "0 auto",
|
|
1608
|
+
"padding": "0 20px"
|
|
1609
|
+
}
|
|
1610
|
+
)
|
|
1611
|
+
```
|
|
1612
|
+
|
|
1613
|
+
|
|
1614
|
+
|
|
1615
|
+
## Best Practices
|
|
1616
|
+
|
|
1617
|
+
### Component Organization
|
|
1618
|
+
|
|
1619
|
+
```python
|
|
1620
|
+
def create_header():
|
|
1621
|
+
return Container(
|
|
1622
|
+
children=[
|
|
1623
|
+
Text("My Application", style={"font-size": "24px", "font-weight": "bold"}),
|
|
1624
|
+
Text("Descriptive subtitle", style={"color": "#666"})
|
|
1625
|
+
],
|
|
1626
|
+
style={
|
|
1627
|
+
"padding": "20px",
|
|
1628
|
+
"background-color": "#f8f9fa",
|
|
1629
|
+
"border-bottom": "1px solid #dee2e6"
|
|
1630
|
+
}
|
|
1631
|
+
)
|
|
1632
|
+
|
|
1633
|
+
def create_form():
|
|
1634
|
+
return Container(
|
|
1635
|
+
children=[
|
|
1636
|
+
Text("Contact Form", style={"font-size": "20px", "margin-bottom": "20px"}),
|
|
1637
|
+
Input(placeholder="Name", style={"margin-bottom": "10px"}),
|
|
1638
|
+
Input(placeholder="Email", input_type="email", style={"margin-bottom": "10px"}),
|
|
1639
|
+
Button("Send", style={"background-color": "#007bff", "color": "white"})
|
|
1640
|
+
],
|
|
1641
|
+
style={
|
|
1642
|
+
"max-width": "400px",
|
|
1643
|
+
"margin": "20px auto",
|
|
1644
|
+
"padding": "20px"
|
|
1645
|
+
}
|
|
1646
|
+
)
|
|
1647
|
+
```
|
|
1648
|
+
|
|
1649
|
+
### Style Reuse
|
|
1650
|
+
|
|
1651
|
+
```python
|
|
1652
|
+
# Define common styles
|
|
1653
|
+
BASE_BUTTON_STYLES = {
|
|
1654
|
+
"padding": "10px 20px",
|
|
1655
|
+
"border": "none",
|
|
1656
|
+
"border-radius": "4px",
|
|
1657
|
+
"font-size": "14px",
|
|
1658
|
+
"cursor": "pointer"
|
|
1659
|
+
}
|
|
1660
|
+
|
|
1661
|
+
PRIMARY_BUTTON_STYLES = {
|
|
1662
|
+
**BASE_BUTTON_STYLES,
|
|
1663
|
+
"background-color": "#007bff",
|
|
1664
|
+
"color": "white"
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
SECONDARY_BUTTON_STYLES = {
|
|
1668
|
+
**BASE_BUTTON_STYLES,
|
|
1669
|
+
"background-color": "#6c757d",
|
|
1670
|
+
"color": "white"
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
# Use in components
|
|
1674
|
+
cancel_button = Button("Cancelar", style=SECONDARY_BUTTON_STYLES)
|
|
1675
|
+
save_button = Button("Guardar", style=PRIMARY_BUTTON_STYLES)
|
|
1676
|
+
```
|
|
1677
|
+
|
|
1678
|
+
Components provide a solid foundation for creating modern and responsive user interfaces that can be exported to multiple platforms while maintaining consistency and functionality.
|
|
1679
|
+
|