steer-core 0.1.7__py3-none-any.whl → 0.1.9__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.
- steer_core/Apps/Components/CompoundComponents.py +0 -0
- steer_core/Apps/Components/RangeSliderComponents.py +500 -0
- steer_core/Apps/Components/SliderComponents.py +657 -0
- steer_core/Apps/Components/__init__.py +0 -0
- steer_core/Apps/Utils/SliderControls.py +677 -0
- steer_core/Apps/Utils/__init__.py +0 -0
- steer_core/Data/database.db +0 -0
- steer_core/DataManager.py +5 -3
- steer_core/__init__.py +1 -1
- {steer_core-0.1.7.dist-info → steer_core-0.1.9.dist-info}/METADATA +1 -1
- {steer_core-0.1.7.dist-info → steer_core-0.1.9.dist-info}/RECORD +13 -6
- {steer_core-0.1.7.dist-info → steer_core-0.1.9.dist-info}/WHEEL +0 -0
- {steer_core-0.1.7.dist-info → steer_core-0.1.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,657 @@
|
|
1
|
+
import dash as ds
|
2
|
+
import numpy as np
|
3
|
+
from typing import Union
|
4
|
+
from dash import Input, Output
|
5
|
+
|
6
|
+
|
7
|
+
class SliderWithTextInput:
|
8
|
+
"""
|
9
|
+
A custom Dash component that combines a slider and text input for synchronized value control.
|
10
|
+
|
11
|
+
This component creates a user interface element consisting of a slider and a numeric input field
|
12
|
+
that can be used together to set numeric values. The slider provides visual feedback and easy
|
13
|
+
adjustment, while the text input allows for precise value entry. Both components are synchronized
|
14
|
+
and share the same value constraints.
|
15
|
+
|
16
|
+
The component is designed for use in Dash applications where users need to input numeric values
|
17
|
+
within a specified range, with the flexibility of both visual (slider) and precise (text input)
|
18
|
+
control methods.
|
19
|
+
|
20
|
+
Attributes:
|
21
|
+
id_base (dict): Base identifier dictionary used to construct unique IDs for child components
|
22
|
+
min_val (float): Minimum allowed value for both slider and input
|
23
|
+
max_val (float): Maximum allowed value for both slider and input
|
24
|
+
default_val (Union[float, list[float], None]): Default value to display on initialization
|
25
|
+
step (float): Step size for value increments/decrements
|
26
|
+
mark_interval (float): Interval between tick marks on the slider
|
27
|
+
property_name (str): Property identifier used in component ID construction
|
28
|
+
title (str): Display title for the component
|
29
|
+
with_slider_titles (bool): Whether to show the title above the slider
|
30
|
+
div_width (str): CSS width specification for the container div
|
31
|
+
slider_disable (bool): Whether the components should be disabled
|
32
|
+
message (str): Optional message displayed between title and slider
|
33
|
+
slider_id (dict): Computed ID for the slider component
|
34
|
+
input_id (dict): Computed ID for the input component
|
35
|
+
|
36
|
+
Example:
|
37
|
+
>>> slider_component = SliderWithTextInput(
|
38
|
+
... id_base={'type': 'parameter', 'index': 0},
|
39
|
+
... min_val=0.0,
|
40
|
+
... max_val=100.0,
|
41
|
+
... step=1.0,
|
42
|
+
... mark_interval=10.0,
|
43
|
+
... property_name='temperature',
|
44
|
+
... title='Temperature (°C)',
|
45
|
+
... default_val=25.0,
|
46
|
+
... message='Optimal range is 20-30°C' # Optional message
|
47
|
+
... )
|
48
|
+
>>> layout_element = slider_component() # Returns Dash HTML Div component
|
49
|
+
"""
|
50
|
+
|
51
|
+
def __init__(
|
52
|
+
self,
|
53
|
+
id_base: dict,
|
54
|
+
min_val: float,
|
55
|
+
max_val: float,
|
56
|
+
step: float,
|
57
|
+
mark_interval: float,
|
58
|
+
property_name: str,
|
59
|
+
title: str,
|
60
|
+
default_val: Union[float, list[float]] = None,
|
61
|
+
with_slider_titles: bool = True,
|
62
|
+
slider_disable: bool = False,
|
63
|
+
div_width: str = 'calc(90%)',
|
64
|
+
message: str = None,
|
65
|
+
):
|
66
|
+
"""
|
67
|
+
Initialize the SliderWithTextInput component.
|
68
|
+
|
69
|
+
Args:
|
70
|
+
id_base (dict): Base dictionary for generating component IDs. Should contain
|
71
|
+
identifying information that will be extended with component-specific
|
72
|
+
subtypes and properties.
|
73
|
+
min_val (float): Minimum value that can be selected on the slider or entered
|
74
|
+
in the text input.
|
75
|
+
max_val (float): Maximum value that can be selected on the slider or entered
|
76
|
+
in the text input.
|
77
|
+
step (float): The granularity of value changes. Determines the smallest
|
78
|
+
increment/decrement possible.
|
79
|
+
mark_interval (float): The spacing between tick marks displayed on the slider.
|
80
|
+
Should be a multiple of step for best visual alignment.
|
81
|
+
property_name (str): A string identifier for this specific property, used
|
82
|
+
in ID generation and callbacks.
|
83
|
+
title (str): Human-readable title displayed above the component.
|
84
|
+
default_val (Union[float, list[float]], optional): Initial value to display.
|
85
|
+
If None, defaults to min_val. Can be a single float or list
|
86
|
+
for compatibility with range sliders.
|
87
|
+
with_slider_titles (bool, optional): If True, displays the title above
|
88
|
+
the slider. If False, shows a non-breaking
|
89
|
+
space to maintain layout. Defaults to True.
|
90
|
+
slider_disable (bool, optional): If True, disables both slider and input
|
91
|
+
interactions. Defaults to False.
|
92
|
+
div_width (str, optional): CSS width specification for the container div.
|
93
|
+
Defaults to 'calc(90%)'.
|
94
|
+
message (str, optional): Optional message to display between the title
|
95
|
+
and slider. If None, no message is displayed.
|
96
|
+
Defaults to None.
|
97
|
+
|
98
|
+
Raises:
|
99
|
+
ValueError: If min_val >= max_val, or if step <= 0, or if mark_interval <= 0.
|
100
|
+
TypeError: If default_val is provided but not numeric.
|
101
|
+
"""
|
102
|
+
|
103
|
+
self.id_base = id_base
|
104
|
+
self.min_val = min_val
|
105
|
+
self.max_val = max_val
|
106
|
+
self.default_val = default_val
|
107
|
+
self.step = step
|
108
|
+
self.mark_interval = mark_interval
|
109
|
+
self.property_name = property_name
|
110
|
+
self.title = title
|
111
|
+
self.with_slider_titles = with_slider_titles
|
112
|
+
self.div_width = div_width
|
113
|
+
self.slider_disable = slider_disable
|
114
|
+
self.message = message
|
115
|
+
|
116
|
+
self.slider_id = self._make_id('slider')
|
117
|
+
self.input_id = self._make_id('input')
|
118
|
+
|
119
|
+
def _make_id(self, subtype: str):
|
120
|
+
"""
|
121
|
+
Generate a unique ID dictionary for component sub-elements.
|
122
|
+
|
123
|
+
Combines the base ID with component-specific subtype and property information
|
124
|
+
to create unique identifiers for Dash callbacks and component references.
|
125
|
+
|
126
|
+
Args:
|
127
|
+
subtype (str): The specific component subtype (e.g., 'slider', 'input').
|
128
|
+
|
129
|
+
Returns:
|
130
|
+
dict: Complete ID dictionary containing base ID information plus subtype
|
131
|
+
and property specifications.
|
132
|
+
|
133
|
+
Example:
|
134
|
+
>>> component._make_id('slider')
|
135
|
+
{'type': 'parameter', 'index': 0, 'subtype': 'slider', 'property': 'temperature'}
|
136
|
+
"""
|
137
|
+
return {**self.id_base, 'subtype': subtype, 'property': self.property_name}
|
138
|
+
|
139
|
+
def _make_slider(self):
|
140
|
+
"""
|
141
|
+
Create and configure the Dash slider component.
|
142
|
+
|
143
|
+
Generates a dcc.Slider with the specified range, step size, default value,
|
144
|
+
and tick marks. The slider provides visual feedback for value selection
|
145
|
+
and is synchronized with the text input component.
|
146
|
+
|
147
|
+
Returns:
|
148
|
+
dash.dcc.Slider: Configured slider component with ID, value constraints,
|
149
|
+
tick marks, and styling options.
|
150
|
+
|
151
|
+
Note:
|
152
|
+
- Tick marks are generated at intervals specified by mark_interval
|
153
|
+
- updatemode is set to 'mouseup' to reduce callback frequency
|
154
|
+
- The slider can be disabled via the slider_disable attribute
|
155
|
+
"""
|
156
|
+
return ds.dcc.Slider(
|
157
|
+
id=self.slider_id,
|
158
|
+
min=self.min_val,
|
159
|
+
max=self.max_val,
|
160
|
+
value=self.default_val,
|
161
|
+
step=self.step,
|
162
|
+
disabled=self.slider_disable,
|
163
|
+
marks={int(i): "" for i in np.arange(self.min_val, self.max_val + self.mark_interval, self.mark_interval)},
|
164
|
+
updatemode='mouseup'
|
165
|
+
)
|
166
|
+
|
167
|
+
def _make_input(self):
|
168
|
+
"""
|
169
|
+
Create and configure the Dash numeric input component.
|
170
|
+
|
171
|
+
Generates a dcc.Input with number type for precise value entry.
|
172
|
+
The input is synchronized with the slider and provides an alternative
|
173
|
+
method for users to specify exact values.
|
174
|
+
|
175
|
+
Returns:
|
176
|
+
dash.dcc.Input: Configured numeric input component with ID, type,
|
177
|
+
value constraints, styling, and step specification.
|
178
|
+
|
179
|
+
Note:
|
180
|
+
- Input type is set to 'number' for numeric validation
|
181
|
+
- Left margin styling provides visual alignment with slider
|
182
|
+
- Step size matches the slider for consistent granularity
|
183
|
+
"""
|
184
|
+
return ds.dcc.Input(
|
185
|
+
id=self.input_id,
|
186
|
+
type='number',
|
187
|
+
value=self.default_val,
|
188
|
+
style={'margin-left': '20px'},
|
189
|
+
step=self.step,
|
190
|
+
disabled=self.slider_disable
|
191
|
+
)
|
192
|
+
|
193
|
+
def __call__(self):
|
194
|
+
"""
|
195
|
+
Generate the complete component layout as a callable object.
|
196
|
+
|
197
|
+
Creates and returns a Dash HTML Div containing the title, optional message,
|
198
|
+
slider, and input components arranged in a cohesive layout. This method allows
|
199
|
+
the class instance to be used as a callable that returns the complete
|
200
|
+
component structure.
|
201
|
+
|
202
|
+
Returns:
|
203
|
+
dash.html.Div: Complete component layout containing:
|
204
|
+
- Title paragraph (conditional based on with_slider_titles)
|
205
|
+
- Optional message paragraph (if message is provided)
|
206
|
+
- Slider component in a styled container
|
207
|
+
- Numeric input component
|
208
|
+
- Spacing elements (line breaks)
|
209
|
+
|
210
|
+
Note:
|
211
|
+
- Title display is controlled by with_slider_titles attribute
|
212
|
+
- When title is hidden, a non-breaking space maintains layout
|
213
|
+
- Message is displayed only if provided during initialization
|
214
|
+
- Negative bottom margin on slider container reduces spacing
|
215
|
+
- Container width is controlled by div_width attribute
|
216
|
+
"""
|
217
|
+
slider_title = self.title if self.with_slider_titles else "\u00A0"
|
218
|
+
|
219
|
+
# Build the component list
|
220
|
+
components = [
|
221
|
+
ds.html.P(slider_title, style={'margin-left': '20px', 'margin-bottom': '0px'})
|
222
|
+
]
|
223
|
+
|
224
|
+
# Add optional message if provided
|
225
|
+
if self.message:
|
226
|
+
components.append(
|
227
|
+
ds.html.P(self.message, style={
|
228
|
+
'margin-left': '20px',
|
229
|
+
'margin-bottom': '5px',
|
230
|
+
'margin-top': '2px',
|
231
|
+
'font-size': '0.9em',
|
232
|
+
'color': '#666666',
|
233
|
+
'font-style': 'italic'
|
234
|
+
})
|
235
|
+
)
|
236
|
+
|
237
|
+
# Add slider, input, and breaks
|
238
|
+
components.extend([
|
239
|
+
ds.html.Div([self._make_slider()], style={'margin-bottom': '-18px'}),
|
240
|
+
self._make_input(),
|
241
|
+
ds.html.Br(), ds.html.Br()
|
242
|
+
])
|
243
|
+
|
244
|
+
return ds.html.Div(components, style={'width': self.div_width, 'margin-left': '-20px'})
|
245
|
+
|
246
|
+
@property
|
247
|
+
def components(self):
|
248
|
+
"""
|
249
|
+
Get a dictionary mapping component types to their IDs.
|
250
|
+
|
251
|
+
Provides easy access to the IDs of the slider and input components
|
252
|
+
for use in Dash callbacks and component interactions.
|
253
|
+
|
254
|
+
Returns:
|
255
|
+
dict: Dictionary with component type keys mapping to their ID dictionaries.
|
256
|
+
|
257
|
+
Example:
|
258
|
+
>>> component.components
|
259
|
+
{
|
260
|
+
'slider': {'type': 'parameter', 'subtype': 'slider', 'property': 'temperature'},
|
261
|
+
'input': {'type': 'parameter', 'subtype': 'input', 'property': 'temperature'}
|
262
|
+
}
|
263
|
+
|
264
|
+
Note:
|
265
|
+
This property is particularly useful for setting up Dash callbacks
|
266
|
+
that need to reference the specific component IDs.
|
267
|
+
"""
|
268
|
+
return {
|
269
|
+
'slider': self.slider_id,
|
270
|
+
'input': self.input_id
|
271
|
+
}
|
272
|
+
|
273
|
+
def get_value_inputs(self):
|
274
|
+
"""
|
275
|
+
Get Input objects for listening to component value changes.
|
276
|
+
|
277
|
+
Returns a list of Dash Input objects that can be used in callbacks to
|
278
|
+
listen for value changes from either the slider or input components.
|
279
|
+
|
280
|
+
Returns:
|
281
|
+
list: List containing [Input(slider_id, 'value'), Input(input_id, 'value')]
|
282
|
+
|
283
|
+
Example:
|
284
|
+
>>> @app.callback(
|
285
|
+
... Output('some-output', 'children'),
|
286
|
+
... component.get_value_inputs()
|
287
|
+
... )
|
288
|
+
... def update_display(slider_val, input_val):
|
289
|
+
... return f"Value: {slider_val or input_val}"
|
290
|
+
"""
|
291
|
+
return [
|
292
|
+
Input(self.slider_id, 'value'),
|
293
|
+
Input(self.input_id, 'value')
|
294
|
+
]
|
295
|
+
|
296
|
+
def get_value_outputs(self):
|
297
|
+
"""
|
298
|
+
Get Output objects for updating component values.
|
299
|
+
|
300
|
+
Returns a list of Dash Output objects that can be used in callbacks to
|
301
|
+
update the values of both the slider and input components.
|
302
|
+
|
303
|
+
Returns:
|
304
|
+
list: List containing [Output(slider_id, 'value'), Output(input_id, 'value')]
|
305
|
+
|
306
|
+
Example:
|
307
|
+
>>> @app.callback(
|
308
|
+
... component.get_value_outputs(),
|
309
|
+
... [Input('some-input', 'value')]
|
310
|
+
... )
|
311
|
+
... def update_components(new_value):
|
312
|
+
... return [new_value, new_value]
|
313
|
+
"""
|
314
|
+
return [
|
315
|
+
Output(self.slider_id, 'value'),
|
316
|
+
Output(self.input_id, 'value')
|
317
|
+
]
|
318
|
+
|
319
|
+
def get_pattern_matching_value_inputs(self, property_name='ALL'):
|
320
|
+
"""
|
321
|
+
Get pattern-matching Input objects for listening to multiple component instances.
|
322
|
+
|
323
|
+
Returns Input objects using pattern-matching to listen to all components
|
324
|
+
with the specified property name, useful for multi-component callbacks.
|
325
|
+
|
326
|
+
Args:
|
327
|
+
property_name: The property to match. Use 'ALL' for all properties,
|
328
|
+
or specify a specific property name.
|
329
|
+
|
330
|
+
Returns:
|
331
|
+
list: List containing pattern-matching Input objects
|
332
|
+
|
333
|
+
Example:
|
334
|
+
>>> @app.callback(
|
335
|
+
... Output('summary', 'children'),
|
336
|
+
... component.get_pattern_matching_value_inputs('ALL')
|
337
|
+
... )
|
338
|
+
... def update_summary(slider_values, input_values):
|
339
|
+
... return f"Total sliders: {len(slider_values)}"
|
340
|
+
"""
|
341
|
+
pattern = {'type': 'parameter', 'subtype': 'slider', 'property': property_name}
|
342
|
+
input_pattern = {'type': 'parameter', 'subtype': 'input', 'property': property_name}
|
343
|
+
|
344
|
+
return [
|
345
|
+
Input(pattern, 'value'),
|
346
|
+
Input(input_pattern, 'value')
|
347
|
+
]
|
348
|
+
|
349
|
+
def get_pattern_matching_value_outputs(self, property_name='ALL'):
|
350
|
+
"""
|
351
|
+
Get pattern-matching Output objects for updating multiple component instances.
|
352
|
+
|
353
|
+
Returns Output objects using pattern-matching to update all components
|
354
|
+
with the specified property name.
|
355
|
+
|
356
|
+
Args:
|
357
|
+
property_name: The property to match. Use 'ALL' for all properties,
|
358
|
+
or specify a specific property name.
|
359
|
+
|
360
|
+
Returns:
|
361
|
+
list: List containing pattern-matching Output objects
|
362
|
+
|
363
|
+
Example:
|
364
|
+
>>> @app.callback(
|
365
|
+
... component.get_pattern_matching_value_outputs('ALL'),
|
366
|
+
... [Input('reset-button', 'n_clicks')]
|
367
|
+
... )
|
368
|
+
... def reset_all_components(n_clicks):
|
369
|
+
... if n_clicks:
|
370
|
+
... return [[0] * len(slider_values), [0] * len(input_values)]
|
371
|
+
... return [dash.no_update, dash.no_update]
|
372
|
+
"""
|
373
|
+
pattern = {'type': 'parameter', 'subtype': 'slider', 'property': property_name}
|
374
|
+
input_pattern = {'type': 'parameter', 'subtype': 'input', 'property': property_name}
|
375
|
+
|
376
|
+
return [
|
377
|
+
Output(pattern, 'value'),
|
378
|
+
Output(input_pattern, 'value')
|
379
|
+
]
|
380
|
+
|
381
|
+
def _validate_and_clamp_value(self, value):
|
382
|
+
"""
|
383
|
+
Validate and clamp a value to the component's valid range.
|
384
|
+
|
385
|
+
Ensures that any input value is within the min_val to max_val range
|
386
|
+
and handles None values appropriately.
|
387
|
+
|
388
|
+
Args:
|
389
|
+
value: The value to validate and clamp.
|
390
|
+
|
391
|
+
Returns:
|
392
|
+
float: The clamped value within the valid range, or the current
|
393
|
+
default_val if the input value is invalid.
|
394
|
+
"""
|
395
|
+
if value is None:
|
396
|
+
return self.default_val if self.default_val is not None else self.min_val
|
397
|
+
|
398
|
+
try:
|
399
|
+
numeric_value = float(value)
|
400
|
+
return max(self.min_val, min(self.max_val, numeric_value))
|
401
|
+
except (ValueError, TypeError):
|
402
|
+
return self.default_val if self.default_val is not None else self.min_val
|
403
|
+
|
404
|
+
|
405
|
+
class SliderWithTextInputAndCheckbox(SliderWithTextInput):
|
406
|
+
"""
|
407
|
+
A custom Dash component that extends SliderWithTextInput by adding a checkbox with a message.
|
408
|
+
|
409
|
+
This component inherits all functionality from SliderWithTextInput and adds a checkbox
|
410
|
+
positioned beneath the input field. The checkbox can be used to enable/disable features,
|
411
|
+
toggle options, or provide additional control over the parameter being adjusted.
|
412
|
+
|
413
|
+
The checkbox includes an associated message that describes its purpose or provides
|
414
|
+
additional context for the user. The checkbox is larger than standard size and has
|
415
|
+
proper spacing between the checkbox and its label text.
|
416
|
+
|
417
|
+
Attributes:
|
418
|
+
checkbox_message (str): The message displayed next to the checkbox
|
419
|
+
checkbox_default (bool): Default checked state of the checkbox
|
420
|
+
checkbox_id (dict): Computed ID for the checkbox component
|
421
|
+
|
422
|
+
Note:
|
423
|
+
The checkbox value is [True] when checked, [] when unchecked.
|
424
|
+
|
425
|
+
Example:
|
426
|
+
>>> slider_component = SliderWithTextInputAndCheckbox(
|
427
|
+
... id_base={'type': 'parameter', 'index': 0},
|
428
|
+
... min_val=0.0,
|
429
|
+
... max_val=100.0,
|
430
|
+
... step=1.0,
|
431
|
+
... mark_interval=10.0,
|
432
|
+
... property_name='temperature',
|
433
|
+
... title='Temperature (°C)',
|
434
|
+
... default_val=25.0,
|
435
|
+
... checkbox_message='Use automatic temperature control',
|
436
|
+
... checkbox_default=True
|
437
|
+
... )
|
438
|
+
>>> layout_element = slider_component() # Returns Dash HTML Div component
|
439
|
+
"""
|
440
|
+
|
441
|
+
def __init__(
|
442
|
+
self,
|
443
|
+
id_base: dict,
|
444
|
+
min_val: float,
|
445
|
+
max_val: float,
|
446
|
+
step: float,
|
447
|
+
mark_interval: float,
|
448
|
+
property_name: str,
|
449
|
+
title: str,
|
450
|
+
checkbox_message: str,
|
451
|
+
default_val: Union[float, list[float]] = None,
|
452
|
+
checkbox_default: bool = False,
|
453
|
+
with_slider_titles: bool = True,
|
454
|
+
slider_disable: bool = False,
|
455
|
+
div_width: str = 'calc(90%)',
|
456
|
+
message: str = None,
|
457
|
+
):
|
458
|
+
"""
|
459
|
+
Initialize the SliderWithTextInputAndCheckbox component.
|
460
|
+
|
461
|
+
Args:
|
462
|
+
id_base (dict): Base dictionary for generating component IDs.
|
463
|
+
min_val (float): Minimum value for the slider and input.
|
464
|
+
max_val (float): Maximum value for the slider and input.
|
465
|
+
step (float): Step size for value increments/decrements.
|
466
|
+
mark_interval (float): Interval between tick marks on the slider.
|
467
|
+
property_name (str): String identifier for this property.
|
468
|
+
title (str): Title displayed above the component.
|
469
|
+
checkbox_message (str): Message displayed next to the checkbox.
|
470
|
+
default_val (Union[float, list[float]], optional): Initial value for slider/input.
|
471
|
+
checkbox_default (bool, optional): Initial checked state of checkbox. Defaults to False.
|
472
|
+
with_slider_titles (bool, optional): Whether to show title. Defaults to True.
|
473
|
+
slider_disable (bool, optional): Whether to disable interactions. Defaults to False.
|
474
|
+
div_width (str, optional): CSS width for container. Defaults to 'calc(90%)'.
|
475
|
+
message (str, optional): Optional message between title and slider.
|
476
|
+
"""
|
477
|
+
# Initialize parent class
|
478
|
+
super().__init__(
|
479
|
+
id_base=id_base,
|
480
|
+
min_val=min_val,
|
481
|
+
max_val=max_val,
|
482
|
+
step=step,
|
483
|
+
mark_interval=mark_interval,
|
484
|
+
property_name=property_name,
|
485
|
+
title=title,
|
486
|
+
default_val=default_val,
|
487
|
+
with_slider_titles=with_slider_titles,
|
488
|
+
slider_disable=slider_disable,
|
489
|
+
div_width=div_width,
|
490
|
+
message=message,
|
491
|
+
)
|
492
|
+
|
493
|
+
# Add checkbox-specific attributes
|
494
|
+
self.checkbox_message = checkbox_message
|
495
|
+
self.checkbox_default = checkbox_default
|
496
|
+
self.checkbox_id = self._make_id('checkbox')
|
497
|
+
|
498
|
+
def _make_checkbox(self):
|
499
|
+
"""
|
500
|
+
Create and configure the Dash checkbox component.
|
501
|
+
|
502
|
+
Returns:
|
503
|
+
dash.html.Div: Container with a larger checkbox and separated label text.
|
504
|
+
"""
|
505
|
+
return ds.html.Div([
|
506
|
+
ds.dcc.Checklist(
|
507
|
+
id=self.checkbox_id,
|
508
|
+
options=[{'label': '', 'value': True}],
|
509
|
+
value=[True] if self.checkbox_default else [],
|
510
|
+
style={
|
511
|
+
'display': 'inline-block',
|
512
|
+
'margin-right': '10px',
|
513
|
+
'transform': 'scale(1.3)', # Make checkbox larger
|
514
|
+
'transform-origin': 'left top', # Changed to 'top' for better alignment
|
515
|
+
'vertical-align': 'baseline' # Use baseline alignment
|
516
|
+
},
|
517
|
+
labelStyle={'margin': '0px'}
|
518
|
+
),
|
519
|
+
ds.html.Span(
|
520
|
+
self.checkbox_message,
|
521
|
+
style={
|
522
|
+
'display': 'inline-block',
|
523
|
+
'vertical-align': 'baseline', # Match checkbox baseline
|
524
|
+
'margin-left': '5px',
|
525
|
+
'line-height': '1.3', # Slightly higher line height
|
526
|
+
'margin-top': '-4px' # Pull text up more aggressively
|
527
|
+
}
|
528
|
+
)
|
529
|
+
], style={'margin-left': '20px', 'margin-top': '10px', 'line-height': '1'})
|
530
|
+
|
531
|
+
def __call__(self):
|
532
|
+
"""
|
533
|
+
Generate the complete component layout including the checkbox.
|
534
|
+
|
535
|
+
Creates and returns a Dash HTML Div containing the title, optional message,
|
536
|
+
slider, input, and checkbox components arranged in a cohesive layout.
|
537
|
+
|
538
|
+
Returns:
|
539
|
+
dash.html.Div: Complete component layout containing all elements plus checkbox.
|
540
|
+
"""
|
541
|
+
slider_title = self.title if self.with_slider_titles else "\u00A0"
|
542
|
+
|
543
|
+
# Build the component list
|
544
|
+
components = [
|
545
|
+
ds.html.P(slider_title, style={'margin-left': '20px', 'margin-bottom': '0px'})
|
546
|
+
]
|
547
|
+
|
548
|
+
# Add optional message if provided
|
549
|
+
if self.message:
|
550
|
+
components.append(
|
551
|
+
ds.html.P(self.message, style={
|
552
|
+
'margin-left': '20px',
|
553
|
+
'margin-bottom': '5px',
|
554
|
+
'margin-top': '2px',
|
555
|
+
'font-size': '0.9em',
|
556
|
+
'color': '#666666',
|
557
|
+
'font-style': 'italic'
|
558
|
+
})
|
559
|
+
)
|
560
|
+
|
561
|
+
# Add slider and input
|
562
|
+
components.extend([
|
563
|
+
ds.html.Div([self._make_slider()], style={'margin-bottom': '-18px'}),
|
564
|
+
self._make_input(),
|
565
|
+
])
|
566
|
+
|
567
|
+
# Add checkbox beneath the input
|
568
|
+
components.extend([
|
569
|
+
self._make_checkbox(),
|
570
|
+
ds.html.Br(), ds.html.Br()
|
571
|
+
])
|
572
|
+
|
573
|
+
return ds.html.Div(components, style={'width': self.div_width, 'margin-left': '-20px'})
|
574
|
+
|
575
|
+
@property
|
576
|
+
def components(self):
|
577
|
+
"""
|
578
|
+
Get a dictionary mapping component types to their IDs, including the checkbox.
|
579
|
+
|
580
|
+
Returns:
|
581
|
+
dict: Dictionary with component type keys mapping to their ID dictionaries.
|
582
|
+
"""
|
583
|
+
return {
|
584
|
+
'slider': self.slider_id,
|
585
|
+
'input': self.input_id,
|
586
|
+
'checkbox': self.checkbox_id
|
587
|
+
}
|
588
|
+
|
589
|
+
def get_checkbox_input(self):
|
590
|
+
"""
|
591
|
+
Get Input object for listening to checkbox value changes.
|
592
|
+
|
593
|
+
Returns:
|
594
|
+
Input: Dash Input object for the checkbox component.
|
595
|
+
|
596
|
+
Note:
|
597
|
+
The checkbox value will be [True] when checked, [] when unchecked.
|
598
|
+
|
599
|
+
Example:
|
600
|
+
>>> @app.callback(
|
601
|
+
... Output('some-output', 'children'),
|
602
|
+
... component.get_checkbox_input()
|
603
|
+
... )
|
604
|
+
... def update_display(checkbox_value):
|
605
|
+
... is_checked = True in (checkbox_value or [])
|
606
|
+
... return f"Checkbox is {'checked' if is_checked else 'unchecked'}"
|
607
|
+
"""
|
608
|
+
return Input(self.checkbox_id, 'value')
|
609
|
+
|
610
|
+
def get_checkbox_output(self):
|
611
|
+
"""
|
612
|
+
Get Output object for updating checkbox value.
|
613
|
+
|
614
|
+
Returns:
|
615
|
+
Output: Dash Output object for the checkbox component.
|
616
|
+
|
617
|
+
Note:
|
618
|
+
To check the checkbox, return [True]. To uncheck, return [].
|
619
|
+
|
620
|
+
Example:
|
621
|
+
>>> @app.callback(
|
622
|
+
... component.get_checkbox_output(),
|
623
|
+
... [Input('some-button', 'n_clicks')]
|
624
|
+
... )
|
625
|
+
... def toggle_checkbox(n_clicks):
|
626
|
+
... if n_clicks and n_clicks % 2 == 1:
|
627
|
+
... return [True]
|
628
|
+
... return []
|
629
|
+
"""
|
630
|
+
return Output(self.checkbox_id, 'value')
|
631
|
+
|
632
|
+
def get_all_inputs(self):
|
633
|
+
"""
|
634
|
+
Get Input objects for all component values (slider, input, and checkbox).
|
635
|
+
|
636
|
+
Returns:
|
637
|
+
list: List containing Input objects for slider, input, and checkbox.
|
638
|
+
|
639
|
+
Note:
|
640
|
+
The checkbox value will be [True] when checked, [] when unchecked.
|
641
|
+
|
642
|
+
Example:
|
643
|
+
>>> @app.callback(
|
644
|
+
... Output('summary', 'children'),
|
645
|
+
... component.get_all_inputs()
|
646
|
+
... )
|
647
|
+
... def update_summary(slider_val, input_val, checkbox_val):
|
648
|
+
... is_checked = True in (checkbox_val or [])
|
649
|
+
... value = slider_val or input_val
|
650
|
+
... return f"Value: {value}, Option enabled: {is_checked}"
|
651
|
+
"""
|
652
|
+
return [
|
653
|
+
Input(self.slider_id, 'value'),
|
654
|
+
Input(self.input_id, 'value'),
|
655
|
+
Input(self.checkbox_id, 'value')
|
656
|
+
]
|
657
|
+
|
File without changes
|