dara-core 1.21.22__py3-none-any.whl → 1.21.24__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.
- dara/core/base_definitions.py +23 -0
- dara/core/defaults.py +6 -0
- dara/core/interactivity/__init__.py +4 -0
- dara/core/interactivity/actions.py +81 -0
- dara/core/interactivity/loop_variable.py +25 -0
- dara/core/router/router.py +44 -0
- dara/core/umd/dara.core.umd.cjs +1864 -1620
- dara/core/visual/components/__init__.py +3 -0
- dara/core/visual/components/match_cmp.py +46 -0
- dara/core/visual/themes/dark.py +3 -0
- dara/core/visual/themes/definitions.py +3 -0
- dara/core/visual/themes/light.py +3 -0
- {dara_core-1.21.22.dist-info → dara_core-1.21.24.dist-info}/METADATA +10 -10
- {dara_core-1.21.22.dist-info → dara_core-1.21.24.dist-info}/RECORD +17 -16
- {dara_core-1.21.22.dist-info → dara_core-1.21.24.dist-info}/LICENSE +0 -0
- {dara_core-1.21.22.dist-info → dara_core-1.21.24.dist-info}/WHEEL +0 -0
- {dara_core-1.21.22.dist-info → dara_core-1.21.24.dist-info}/entry_points.txt +0 -0
dara/core/base_definitions.py
CHANGED
|
@@ -454,6 +454,29 @@ class RouterPath(BaseModel):
|
|
|
454
454
|
A URL hash string, beginning with '#'.
|
|
455
455
|
"""
|
|
456
456
|
|
|
457
|
+
params: dict[str, ClientVariable | Any] | None = None # type: ignore # noqa: F821
|
|
458
|
+
"""
|
|
459
|
+
Optional mapping of dynamic path params to their values.
|
|
460
|
+
|
|
461
|
+
```python
|
|
462
|
+
from dara.core import RouterPath, Variable
|
|
463
|
+
|
|
464
|
+
foo_var = Variable('foo_value')
|
|
465
|
+
|
|
466
|
+
# Will resolve to '/foo_value/bar'
|
|
467
|
+
path = RouterPath(pathname='/:foo/:bar', params={'foo': foo_var, 'bar': 'bar'})
|
|
468
|
+
|
|
469
|
+
Link('Link to path', to=path)
|
|
470
|
+
```
|
|
471
|
+
"""
|
|
472
|
+
|
|
473
|
+
def __init__(self, **data):
|
|
474
|
+
# Resolve the circular dependency to use ClientVariable as the type of the params
|
|
475
|
+
from dara.core.interactivity.client_variable import ClientVariable # noqa: F401
|
|
476
|
+
|
|
477
|
+
self.model_rebuild()
|
|
478
|
+
super().__init__(**data)
|
|
479
|
+
|
|
457
480
|
|
|
458
481
|
class NavigateOptions(BaseModel):
|
|
459
482
|
"""
|
dara/core/defaults.py
CHANGED
|
@@ -21,6 +21,8 @@ from typing import TYPE_CHECKING, cast
|
|
|
21
21
|
|
|
22
22
|
from dara.core.base_definitions import ActionDef
|
|
23
23
|
from dara.core.interactivity.actions import (
|
|
24
|
+
CopyToClipboard,
|
|
25
|
+
CopyToClipboardDef,
|
|
24
26
|
DownloadContentDef,
|
|
25
27
|
DownloadVariable,
|
|
26
28
|
DownloadVariableDef,
|
|
@@ -42,6 +44,8 @@ from dara.core.visual.components import (
|
|
|
42
44
|
Fallback,
|
|
43
45
|
For,
|
|
44
46
|
ForDef,
|
|
47
|
+
Match,
|
|
48
|
+
MatchDef,
|
|
45
49
|
Menu,
|
|
46
50
|
MenuDef,
|
|
47
51
|
PoweredByCausalens,
|
|
@@ -87,6 +91,7 @@ CORE_COMPONENTS: dict[str, ComponentTypeAnnotation] = {
|
|
|
87
91
|
cast(str, Fallback.Default.py_component): DefaultFallbackDef,
|
|
88
92
|
cast(str, Fallback.Row.py_component): RowFallbackDef,
|
|
89
93
|
cast(str, Fallback.Custom.py_component): CustomFallbackDef,
|
|
94
|
+
Match.__name__: MatchDef,
|
|
90
95
|
For.__name__: ForDef,
|
|
91
96
|
Link.__name__: LinkDef,
|
|
92
97
|
Outlet.__name__: OutletDef,
|
|
@@ -102,6 +107,7 @@ CORE_ACTIONS: dict[str, ActionDef] = {
|
|
|
102
107
|
TriggerVariable.__name__: TriggerVariableDef,
|
|
103
108
|
ResetVariables.__name__: ResetVariablesDef,
|
|
104
109
|
DownloadVariable.__name__: DownloadVariableDef,
|
|
110
|
+
CopyToClipboard.__name__: CopyToClipboardDef,
|
|
105
111
|
'DownloadContent': DownloadContentDef,
|
|
106
112
|
Notify.__name__: NotifyDef,
|
|
107
113
|
}
|
|
@@ -23,6 +23,7 @@ from pydantic import BaseModel
|
|
|
23
23
|
|
|
24
24
|
from dara.core.interactivity.actions import (
|
|
25
25
|
ActionCtx,
|
|
26
|
+
CopyToClipboard,
|
|
26
27
|
DownloadContent,
|
|
27
28
|
DownloadContentImpl,
|
|
28
29
|
DownloadVariable,
|
|
@@ -43,6 +44,7 @@ from dara.core.interactivity.condition import Condition, Operator
|
|
|
43
44
|
from dara.core.interactivity.data_variable import DataVariable
|
|
44
45
|
from dara.core.interactivity.derived_data_variable import DerivedDataVariable
|
|
45
46
|
from dara.core.interactivity.derived_variable import DerivedVariable
|
|
47
|
+
from dara.core.interactivity.loop_variable import LoopVariable
|
|
46
48
|
from dara.core.interactivity.non_data_variable import NonDataVariable
|
|
47
49
|
from dara.core.interactivity.plain_variable import Variable
|
|
48
50
|
from dara.core.interactivity.server_variable import ServerVariable
|
|
@@ -64,9 +66,11 @@ __all__ = [
|
|
|
64
66
|
'DerivedVariable',
|
|
65
67
|
'DerivedDataVariable',
|
|
66
68
|
'UrlVariable',
|
|
69
|
+
'CopyToClipboard',
|
|
67
70
|
'DownloadVariable',
|
|
68
71
|
'DownloadContent',
|
|
69
72
|
'DownloadContentImpl',
|
|
73
|
+
'LoopVariable',
|
|
70
74
|
'NavigateTo',
|
|
71
75
|
'NavigateToImpl',
|
|
72
76
|
'Notify',
|
|
@@ -62,6 +62,7 @@ from dara.core.internal.utils import run_user_handler
|
|
|
62
62
|
if TYPE_CHECKING:
|
|
63
63
|
from dara.core.interactivity import (
|
|
64
64
|
AnyVariable,
|
|
65
|
+
ClientVariable,
|
|
65
66
|
DerivedVariable,
|
|
66
67
|
Variable,
|
|
67
68
|
)
|
|
@@ -727,6 +728,41 @@ class DownloadVariable(ActionImpl):
|
|
|
727
728
|
type: Literal['csv', 'xlsx', 'json'] = 'csv'
|
|
728
729
|
|
|
729
730
|
|
|
731
|
+
CopyToClipboardDef = ActionDef(name='CopyToClipboard', js_module='@darajs/core', py_module='dara.core')
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
class CopyToClipboard(ActionImpl):
|
|
735
|
+
"""
|
|
736
|
+
CopyToClipboard action copies the provided value to the user's clipboard.
|
|
737
|
+
|
|
738
|
+
```python
|
|
739
|
+
|
|
740
|
+
from dara.core import action, ConfigurationBuilder, CopyToClipboard
|
|
741
|
+
from dara.components import Stack, Button
|
|
742
|
+
|
|
743
|
+
config = ConfigurationBuilder()
|
|
744
|
+
|
|
745
|
+
def test_page():
|
|
746
|
+
return Stack(
|
|
747
|
+
Button(
|
|
748
|
+
'Copy to clipboard',
|
|
749
|
+
onclick=CopyToClipboard(value='Hello, World!')
|
|
750
|
+
)
|
|
751
|
+
)
|
|
752
|
+
|
|
753
|
+
|
|
754
|
+
config.router.add_page(path='copy-to-clipboard', content=test_page)
|
|
755
|
+
"""
|
|
756
|
+
|
|
757
|
+
value: str | ClientVariable
|
|
758
|
+
|
|
759
|
+
success_message: str | None = None
|
|
760
|
+
"""Message to display when the value is copied to the clipboard"""
|
|
761
|
+
|
|
762
|
+
error_message: str | None = None
|
|
763
|
+
"""Message to display when the value could not be copied to the clipboard"""
|
|
764
|
+
|
|
765
|
+
|
|
730
766
|
@deprecated('Use @action instead')
|
|
731
767
|
def SideEffect(
|
|
732
768
|
function: Callable[[ComponentActionContext], Any],
|
|
@@ -826,6 +862,51 @@ class ActionCtx:
|
|
|
826
862
|
)
|
|
827
863
|
self._on_action = _on_action
|
|
828
864
|
|
|
865
|
+
async def copy_to_clipboard(
|
|
866
|
+
self,
|
|
867
|
+
value: str,
|
|
868
|
+
success_message: str | None = None,
|
|
869
|
+
error_message: str | None = None,
|
|
870
|
+
):
|
|
871
|
+
"""
|
|
872
|
+
Copy a given value to the user's clipboard.
|
|
873
|
+
|
|
874
|
+
Note that this could fail in some browsers if e.g. user has disabled clipboard access.
|
|
875
|
+
Dara will display an error notification in this case, the message can be customized with the `error_message` parameter.
|
|
876
|
+
|
|
877
|
+
```python
|
|
878
|
+
|
|
879
|
+
from dara.core import action, ConfigurationBuilder, CopyToClipboard
|
|
880
|
+
from dara.components import Stack, Button
|
|
881
|
+
|
|
882
|
+
config = ConfigurationBuilder()
|
|
883
|
+
|
|
884
|
+
@action
|
|
885
|
+
async def copy_demo(ctx: action.Ctx, value: str):
|
|
886
|
+
await ctx.copy_to_clipboard(value)
|
|
887
|
+
|
|
888
|
+
def test_page():
|
|
889
|
+
return Stack(
|
|
890
|
+
Button(
|
|
891
|
+
'Copy to clipboard',
|
|
892
|
+
onclick=copy_demo(value='Hello, World!')
|
|
893
|
+
)
|
|
894
|
+
)
|
|
895
|
+
|
|
896
|
+
|
|
897
|
+
config.router.add_page(path='copy-to-clipboard', content=test_page)
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
:param value: the value to copy to the clipboard
|
|
901
|
+
:param success_message: the message to display when the value is copied to the clipboard
|
|
902
|
+
:param error_message: the message to display when the value could not be copied to the clipboard
|
|
903
|
+
"""
|
|
904
|
+
return await CopyToClipboard(
|
|
905
|
+
value=value,
|
|
906
|
+
success_message=success_message,
|
|
907
|
+
error_message=error_message,
|
|
908
|
+
).execute(self)
|
|
909
|
+
|
|
829
910
|
@overload
|
|
830
911
|
async def update(self, variable: ServerVariable, value: DataFrame | None): ...
|
|
831
912
|
|
|
@@ -2,6 +2,10 @@ from pydantic import Field, SerializerFunctionWrapHandler, model_serializer
|
|
|
2
2
|
|
|
3
3
|
from .client_variable import ClientVariable
|
|
4
4
|
|
|
5
|
+
_INDEX = '__index'
|
|
6
|
+
_IS_LAST = '__is_last'
|
|
7
|
+
_IS_FIRST = '__is_first'
|
|
8
|
+
|
|
5
9
|
|
|
6
10
|
class LoopVariable(ClientVariable):
|
|
7
11
|
"""
|
|
@@ -76,6 +80,27 @@ class LoopVariable(ClientVariable):
|
|
|
76
80
|
def __getitem__(self, key: str):
|
|
77
81
|
return self.get(key)
|
|
78
82
|
|
|
83
|
+
@property
|
|
84
|
+
def index(self):
|
|
85
|
+
"""
|
|
86
|
+
Value of the index of the current item in the list.
|
|
87
|
+
"""
|
|
88
|
+
return self.model_copy(update={'nested': [_INDEX]}, deep=True)
|
|
89
|
+
|
|
90
|
+
@property
|
|
91
|
+
def is_last(self):
|
|
92
|
+
"""
|
|
93
|
+
Whether the current item is the last item in the list.
|
|
94
|
+
"""
|
|
95
|
+
return self.model_copy(update={'nested': [_IS_LAST]}, deep=True)
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def is_first(self):
|
|
99
|
+
"""
|
|
100
|
+
Whether the current item is the first item in the list.
|
|
101
|
+
"""
|
|
102
|
+
return self.model_copy(update={'nested': [_IS_FIRST]}, deep=True)
|
|
103
|
+
|
|
79
104
|
@property
|
|
80
105
|
def list_item(self):
|
|
81
106
|
raise RuntimeError('LoopVariable does not support list_item')
|
dara/core/router/router.py
CHANGED
|
@@ -81,6 +81,44 @@ class _PathParamStore(PersistenceStore):
|
|
|
81
81
|
pass
|
|
82
82
|
|
|
83
83
|
|
|
84
|
+
class _RouteMatchStore(PersistenceStore):
|
|
85
|
+
"""
|
|
86
|
+
Internal store for route matches.
|
|
87
|
+
Should not be used directly, Dara will use this internally to keep a variable
|
|
88
|
+
in sync with the current route matches.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
async def init(self, variable: 'Variable'):
|
|
92
|
+
# noop
|
|
93
|
+
pass
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class RouteMatch(BaseModel):
|
|
97
|
+
"""
|
|
98
|
+
Data structure representing a route match in the router
|
|
99
|
+
"""
|
|
100
|
+
|
|
101
|
+
id: str
|
|
102
|
+
"""
|
|
103
|
+
Route ID, as set when defining the route
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
pathname: str
|
|
107
|
+
"""
|
|
108
|
+
Full pathname of the route
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
params: dict[str, Any]
|
|
112
|
+
"""
|
|
113
|
+
Mapping of dynamic path params to their values
|
|
114
|
+
"""
|
|
115
|
+
|
|
116
|
+
definition: 'BaseRoute'
|
|
117
|
+
"""
|
|
118
|
+
Definition of the route
|
|
119
|
+
"""
|
|
120
|
+
|
|
121
|
+
|
|
84
122
|
class RouteData(BaseModel):
|
|
85
123
|
"""
|
|
86
124
|
Data structure representing a route in the router
|
|
@@ -709,6 +747,12 @@ class Router(HasChildRoutes):
|
|
|
709
747
|
building routes step by step, while the object API is more declarative and compact.
|
|
710
748
|
"""
|
|
711
749
|
|
|
750
|
+
route_matches: Variable[list[RouteMatch]] = Field(default_factory=lambda: Variable([], store=_RouteMatchStore()))
|
|
751
|
+
"""
|
|
752
|
+
Variable containing current list of route matches.
|
|
753
|
+
Note that this will be updated by Dara automatically, so you should not modify it directly.
|
|
754
|
+
"""
|
|
755
|
+
|
|
712
756
|
def __init__(self, *children: BaseRoute, **kwargs):
|
|
713
757
|
routes = list(children)
|
|
714
758
|
if 'children' not in kwargs:
|