reflex 0.8.14a2__py3-none-any.whl → 0.8.15__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.
Potentially problematic release.
This version of reflex might be problematic. Click here for more details.
- reflex/.templates/web/utils/state.js +68 -8
- reflex/__init__.py +12 -7
- reflex/__init__.pyi +11 -3
- reflex/app.py +10 -7
- reflex/base.py +58 -33
- reflex/components/datadisplay/dataeditor.py +17 -2
- reflex/components/datadisplay/dataeditor.pyi +6 -2
- reflex/components/field.py +3 -1
- reflex/components/lucide/icon.py +2 -1
- reflex/components/lucide/icon.pyi +2 -1
- reflex/components/markdown/markdown.py +101 -27
- reflex/components/sonner/toast.py +3 -2
- reflex/components/sonner/toast.pyi +3 -2
- reflex/constants/base.py +5 -0
- reflex/constants/installer.py +3 -3
- reflex/environment.py +9 -1
- reflex/event.py +3 -0
- reflex/experimental/client_state.py +1 -1
- reflex/istate/manager/__init__.py +120 -0
- reflex/istate/manager/disk.py +210 -0
- reflex/istate/manager/memory.py +76 -0
- reflex/istate/{manager.py → manager/redis.py} +5 -372
- reflex/istate/proxy.py +35 -24
- reflex/model.py +534 -511
- reflex/plugins/tailwind_v4.py +2 -2
- reflex/reflex.py +16 -10
- reflex/state.py +35 -34
- reflex/testing.py +12 -14
- reflex/utils/build.py +11 -1
- reflex/utils/codespaces.py +30 -1
- reflex/utils/compat.py +51 -48
- reflex/utils/misc.py +2 -1
- reflex/utils/monitoring.py +1 -2
- reflex/utils/prerequisites.py +19 -4
- reflex/utils/processes.py +3 -1
- reflex/utils/redir.py +21 -37
- reflex/utils/serializers.py +21 -20
- reflex/utils/telemetry.py +0 -2
- reflex/utils/templates.py +4 -4
- reflex/utils/types.py +89 -90
- reflex/vars/base.py +108 -41
- reflex/vars/color.py +28 -8
- reflex/vars/datetime.py +6 -2
- reflex/vars/dep_tracking.py +2 -2
- reflex/vars/number.py +26 -0
- reflex/vars/object.py +51 -7
- reflex/vars/sequence.py +32 -1
- {reflex-0.8.14a2.dist-info → reflex-0.8.15.dist-info}/METADATA +8 -3
- {reflex-0.8.14a2.dist-info → reflex-0.8.15.dist-info}/RECORD +52 -49
- {reflex-0.8.14a2.dist-info → reflex-0.8.15.dist-info}/WHEEL +0 -0
- {reflex-0.8.14a2.dist-info → reflex-0.8.15.dist-info}/entry_points.txt +0 -0
- {reflex-0.8.14a2.dist-info → reflex-0.8.15.dist-info}/licenses/LICENSE +0 -0
|
@@ -529,6 +529,14 @@ export const connect = async (
|
|
|
529
529
|
navigate,
|
|
530
530
|
params,
|
|
531
531
|
) => {
|
|
532
|
+
// Socket already allocated, just reconnect it if needed.
|
|
533
|
+
if (socket.current) {
|
|
534
|
+
if (!socket.current.connected) {
|
|
535
|
+
socket.current.reconnect();
|
|
536
|
+
}
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
|
|
532
540
|
// Get backend URL object from the endpoint.
|
|
533
541
|
const endpoint = getBackendURL(EVENTURL);
|
|
534
542
|
const on_hydrated_queue = [];
|
|
@@ -540,7 +548,9 @@ export const connect = async (
|
|
|
540
548
|
protocols: [reflexEnvironment.version],
|
|
541
549
|
autoUnref: false,
|
|
542
550
|
query: { token: getToken() },
|
|
551
|
+
reconnection: false, // Reconnection will be handled manually.
|
|
543
552
|
});
|
|
553
|
+
socket.current.wait_connect = !socket.current.connected;
|
|
544
554
|
// Ensure undefined fields in events are sent as null instead of removed
|
|
545
555
|
socket.current.io.encoder.replacer = (k, v) => (v === undefined ? null : v);
|
|
546
556
|
socket.current.io.decoder.tryParse = (str) => {
|
|
@@ -550,6 +560,18 @@ export const connect = async (
|
|
|
550
560
|
return false;
|
|
551
561
|
}
|
|
552
562
|
};
|
|
563
|
+
// Set up a reconnect helper function
|
|
564
|
+
socket.current.reconnect = () => {
|
|
565
|
+
if (
|
|
566
|
+
socket.current &&
|
|
567
|
+
!socket.current.connected &&
|
|
568
|
+
!socket.current.wait_connect
|
|
569
|
+
) {
|
|
570
|
+
socket.current.wait_connect = true;
|
|
571
|
+
socket.current.io.opts.query = { token: getToken() }; // Update token for reconnect.
|
|
572
|
+
socket.current.connect();
|
|
573
|
+
}
|
|
574
|
+
};
|
|
553
575
|
|
|
554
576
|
function checkVisibility() {
|
|
555
577
|
if (document.visibilityState === "visible") {
|
|
@@ -565,7 +587,7 @@ export const connect = async (
|
|
|
565
587
|
);
|
|
566
588
|
} else if (!socket.current.connected) {
|
|
567
589
|
console.log("Socket is disconnected, attempting to reconnect ");
|
|
568
|
-
socket.current.
|
|
590
|
+
socket.current.reconnect();
|
|
569
591
|
} else {
|
|
570
592
|
console.log("Socket is reconnected ");
|
|
571
593
|
}
|
|
@@ -588,6 +610,7 @@ export const connect = async (
|
|
|
588
610
|
|
|
589
611
|
// Once the socket is open, hydrate the page.
|
|
590
612
|
socket.current.on("connect", async () => {
|
|
613
|
+
socket.current.wait_connect = false;
|
|
591
614
|
setConnectErrors([]);
|
|
592
615
|
window.addEventListener("pagehide", pagehideHandler);
|
|
593
616
|
window.addEventListener("beforeunload", disconnectTrigger);
|
|
@@ -599,16 +622,33 @@ export const connect = async (
|
|
|
599
622
|
});
|
|
600
623
|
|
|
601
624
|
socket.current.on("connect_error", (error) => {
|
|
602
|
-
|
|
625
|
+
socket.current.wait_connect = false;
|
|
626
|
+
let n_connect_errors = 0;
|
|
627
|
+
setConnectErrors((connectErrors) => {
|
|
628
|
+
const new_errors = [...connectErrors.slice(-9), error];
|
|
629
|
+
n_connect_errors = new_errors.length;
|
|
630
|
+
return new_errors;
|
|
631
|
+
});
|
|
632
|
+
window.setTimeout(() => {
|
|
633
|
+
if (socket.current && !socket.current.connected) {
|
|
634
|
+
socket.current.reconnect();
|
|
635
|
+
}
|
|
636
|
+
}, 200 * n_connect_errors); // Incremental backoff
|
|
603
637
|
});
|
|
604
638
|
|
|
605
639
|
// When the socket disconnects reset the event_processing flag
|
|
606
|
-
socket.current.on("disconnect", () => {
|
|
607
|
-
socket.current =
|
|
640
|
+
socket.current.on("disconnect", (reason, details) => {
|
|
641
|
+
socket.current.wait_connect = false;
|
|
642
|
+
const try_reconnect =
|
|
643
|
+
reason !== "io server disconnect" && reason !== "io client disconnect";
|
|
608
644
|
event_processing = false;
|
|
609
645
|
window.removeEventListener("unload", disconnectTrigger);
|
|
610
646
|
window.removeEventListener("beforeunload", disconnectTrigger);
|
|
611
647
|
window.removeEventListener("pagehide", pagehideHandler);
|
|
648
|
+
if (try_reconnect) {
|
|
649
|
+
// Attempt to reconnect transient non-intentional disconnects.
|
|
650
|
+
socket.current.reconnect();
|
|
651
|
+
}
|
|
612
652
|
});
|
|
613
653
|
|
|
614
654
|
// On each received message, queue the updates and events.
|
|
@@ -785,6 +825,7 @@ export const useEventLoop = (
|
|
|
785
825
|
const [searchParams] = useSearchParams();
|
|
786
826
|
const [connectErrors, setConnectErrors] = useState([]);
|
|
787
827
|
const params = useRef(paramsR);
|
|
828
|
+
const mounted = useRef(false);
|
|
788
829
|
|
|
789
830
|
useEffect(() => {
|
|
790
831
|
const { "*": splat, ...remainingParams } = paramsR;
|
|
@@ -796,11 +837,16 @@ export const useEventLoop = (
|
|
|
796
837
|
}, [paramsR]);
|
|
797
838
|
|
|
798
839
|
const ensureSocketConnected = useCallback(async () => {
|
|
840
|
+
if (!mounted.current) {
|
|
841
|
+
// During hot reload, some components may still have a reference to
|
|
842
|
+
// addEvents, so avoid reconnecting the socket of an unmounted event loop.
|
|
843
|
+
return;
|
|
844
|
+
}
|
|
799
845
|
// only use websockets if state is present and backend is not disabled (reflex cloud).
|
|
800
846
|
if (
|
|
801
847
|
Object.keys(initialState).length > 1 &&
|
|
802
848
|
!isBackendDisabled() &&
|
|
803
|
-
!socket.current
|
|
849
|
+
!socket.current?.connected
|
|
804
850
|
) {
|
|
805
851
|
// Initialize the websocket connection.
|
|
806
852
|
await connect(
|
|
@@ -813,13 +859,23 @@ export const useEventLoop = (
|
|
|
813
859
|
() => params.current,
|
|
814
860
|
);
|
|
815
861
|
}
|
|
816
|
-
}, [
|
|
862
|
+
}, [
|
|
863
|
+
socket,
|
|
864
|
+
dispatch,
|
|
865
|
+
setConnectErrors,
|
|
866
|
+
client_storage,
|
|
867
|
+
navigate,
|
|
868
|
+
params,
|
|
869
|
+
mounted,
|
|
870
|
+
]);
|
|
817
871
|
|
|
818
872
|
// Function to add new events to the event queue.
|
|
819
873
|
const addEvents = useCallback((events, args, event_actions) => {
|
|
820
874
|
const _events = events.filter((e) => e !== undefined && e !== null);
|
|
821
|
-
|
|
822
|
-
|
|
875
|
+
if (!event_actions?.temporal) {
|
|
876
|
+
// Reconnect socket if needed for non-temporal events.
|
|
877
|
+
ensureSocketConnected();
|
|
878
|
+
}
|
|
823
879
|
|
|
824
880
|
if (!(args instanceof Array)) {
|
|
825
881
|
args = [args];
|
|
@@ -914,12 +970,16 @@ export const useEventLoop = (
|
|
|
914
970
|
// Handle socket connect/disconnect.
|
|
915
971
|
useEffect(() => {
|
|
916
972
|
// Initialize the websocket connection.
|
|
973
|
+
mounted.current = true;
|
|
917
974
|
ensureSocketConnected();
|
|
918
975
|
|
|
919
976
|
// Cleanup function.
|
|
920
977
|
return () => {
|
|
978
|
+
mounted.current = false;
|
|
921
979
|
if (socket.current) {
|
|
922
980
|
socket.current.disconnect();
|
|
981
|
+
socket.current.off();
|
|
982
|
+
socket.current = null;
|
|
923
983
|
}
|
|
924
984
|
};
|
|
925
985
|
}, []);
|
reflex/__init__.py
CHANGED
|
@@ -84,13 +84,18 @@ In the example above, you will be able to do `rx.list`
|
|
|
84
84
|
|
|
85
85
|
from __future__ import annotations
|
|
86
86
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
import sys
|
|
88
|
+
|
|
89
|
+
from reflex.utils import lazy_loader
|
|
90
|
+
|
|
91
|
+
if sys.version_info < (3, 11):
|
|
92
|
+
from reflex.utils import console
|
|
91
93
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
+
console.warn(
|
|
95
|
+
"Reflex support for Python 3.10 is deprecated and will be removed in a future release. Please upgrade to Python 3.11 or higher for continued support."
|
|
96
|
+
)
|
|
97
|
+
del console
|
|
98
|
+
del sys
|
|
94
99
|
|
|
95
100
|
RADIX_THEMES_MAPPING: dict = {
|
|
96
101
|
"components.radix.themes.base": ["color_mode", "theme", "theme_panel"],
|
|
@@ -323,7 +328,7 @@ _MAPPING: dict = {
|
|
|
323
328
|
"SessionStorage",
|
|
324
329
|
],
|
|
325
330
|
"middleware": ["middleware", "Middleware"],
|
|
326
|
-
"model": ["asession", "session", "Model"],
|
|
331
|
+
"model": ["asession", "session", "Model", "ModelRegistry"],
|
|
327
332
|
"page": ["page"],
|
|
328
333
|
"state": [
|
|
329
334
|
"var",
|
reflex/__init__.pyi
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
# This file was generated by `reflex/utils/pyi_generator.py`!
|
|
4
4
|
# ------------------------------------------------------
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
import sys
|
|
7
7
|
|
|
8
8
|
from . import (
|
|
9
9
|
admin,
|
|
@@ -151,7 +151,7 @@ from .experimental import _x
|
|
|
151
151
|
from .istate.storage import Cookie, LocalStorage, SessionStorage
|
|
152
152
|
from .istate.wrappers import get_state
|
|
153
153
|
from .middleware import Middleware, middleware
|
|
154
|
-
from .model import Model, asession, session
|
|
154
|
+
from .model import Model, ModelRegistry, asession, session
|
|
155
155
|
from .page import page
|
|
156
156
|
from .state import ComponentState, State, dynamic, var
|
|
157
157
|
from .style import Style, toggle_color_mode
|
|
@@ -160,7 +160,14 @@ from .utils.misc import run_in_thread
|
|
|
160
160
|
from .utils.serializers import serializer
|
|
161
161
|
from .vars import Field, Var, field
|
|
162
162
|
|
|
163
|
-
|
|
163
|
+
if sys.version_info < (3, 11):
|
|
164
|
+
from reflex.utils import console
|
|
165
|
+
|
|
166
|
+
console.warn(
|
|
167
|
+
"Reflex support for Python 3.10 is deprecated and will be removed in a future release. Please upgrade to Python 3.11 or higher for continued support."
|
|
168
|
+
)
|
|
169
|
+
del console
|
|
170
|
+
del sys
|
|
164
171
|
RADIX_THEMES_MAPPING: dict
|
|
165
172
|
RADIX_THEMES_COMPONENTS_MAPPING: dict
|
|
166
173
|
RADIX_THEMES_LAYOUT_MAPPING: dict
|
|
@@ -192,6 +199,7 @@ __all__ = [
|
|
|
192
199
|
"LocalStorage",
|
|
193
200
|
"Middleware",
|
|
194
201
|
"Model",
|
|
202
|
+
"ModelRegistry",
|
|
195
203
|
"MomentDelta",
|
|
196
204
|
"NoSSRComponent",
|
|
197
205
|
"PropsBase",
|
reflex/app.py
CHANGED
|
@@ -83,7 +83,6 @@ from reflex.event import (
|
|
|
83
83
|
get_hydrate_event,
|
|
84
84
|
noop,
|
|
85
85
|
)
|
|
86
|
-
from reflex.model import Model, get_db_status
|
|
87
86
|
from reflex.page import DECORATED_PAGES
|
|
88
87
|
from reflex.route import (
|
|
89
88
|
get_route_args,
|
|
@@ -648,7 +647,7 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
648
647
|
|
|
649
648
|
for api_transformer in api_transformers:
|
|
650
649
|
if isinstance(api_transformer, Starlette):
|
|
651
|
-
# Mount the api to the
|
|
650
|
+
# Mount the api to the starlette app.
|
|
652
651
|
App._add_cors(api_transformer)
|
|
653
652
|
api_transformer.mount("", asgi_app)
|
|
654
653
|
asgi_app = api_transformer
|
|
@@ -957,6 +956,8 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
957
956
|
try:
|
|
958
957
|
from starlette_admin.contrib.sqla.admin import Admin
|
|
959
958
|
from starlette_admin.contrib.sqla.view import ModelView
|
|
959
|
+
|
|
960
|
+
from reflex.model import Model
|
|
960
961
|
except ImportError:
|
|
961
962
|
return
|
|
962
963
|
|
|
@@ -1780,16 +1781,16 @@ async def process(
|
|
|
1780
1781
|
name=f"reflex_emit_reload|{event.name}|{time.time()}|{event.token}",
|
|
1781
1782
|
)
|
|
1782
1783
|
return
|
|
1784
|
+
router_data[constants.RouteVar.PATH] = "/" + (
|
|
1785
|
+
app.router(path) or "404"
|
|
1786
|
+
if (path := router_data.get(constants.RouteVar.PATH))
|
|
1787
|
+
else "404"
|
|
1788
|
+
).removeprefix("/")
|
|
1783
1789
|
# re-assign only when the value is different
|
|
1784
1790
|
if state.router_data != router_data:
|
|
1785
1791
|
# assignment will recurse into substates and force recalculation of
|
|
1786
1792
|
# dependent ComputedVar (dynamic route variables)
|
|
1787
1793
|
state.router_data = router_data
|
|
1788
|
-
router_data[constants.RouteVar.PATH] = "/" + (
|
|
1789
|
-
app.router(path) or "404"
|
|
1790
|
-
if (path := router_data.get(constants.RouteVar.PATH))
|
|
1791
|
-
else "404"
|
|
1792
|
-
).removeprefix("/")
|
|
1793
1794
|
state.router = RouterData.from_router_data(router_data)
|
|
1794
1795
|
|
|
1795
1796
|
# Preprocess the event.
|
|
@@ -1849,6 +1850,8 @@ async def health(_request: Request) -> JSONResponse:
|
|
|
1849
1850
|
tasks = []
|
|
1850
1851
|
|
|
1851
1852
|
if prerequisites.check_db_used():
|
|
1853
|
+
from reflex.model import get_db_status
|
|
1854
|
+
|
|
1852
1855
|
tasks.append(get_db_status())
|
|
1853
1856
|
if prerequisites.check_redis_used():
|
|
1854
1857
|
tasks.append(prerequisites.get_redis_status())
|
reflex/base.py
CHANGED
|
@@ -1,47 +1,72 @@
|
|
|
1
1
|
"""Define the base Reflex class."""
|
|
2
2
|
|
|
3
|
-
from
|
|
3
|
+
from importlib.util import find_spec
|
|
4
4
|
|
|
5
|
+
if find_spec("pydantic") and find_spec("pydantic.v1"):
|
|
6
|
+
from pydantic.v1 import BaseModel
|
|
5
7
|
|
|
6
|
-
|
|
7
|
-
"""The base class subclassed by all Reflex classes.
|
|
8
|
+
from reflex.utils.compat import ModelMetaclassLazyAnnotations
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
10
|
+
class Base(BaseModel, metaclass=ModelMetaclassLazyAnnotations):
|
|
11
|
+
"""The base class subclassed by all Reflex classes.
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"""
|
|
13
|
+
This class wraps Pydantic and provides common methods such as
|
|
14
|
+
serialization and setting fields.
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
Any data structure that needs to be transferred between the
|
|
17
|
+
frontend and backend should subclass this class.
|
|
18
|
+
"""
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
extra = "allow"
|
|
20
|
+
class Config:
|
|
21
|
+
"""Pydantic config."""
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
arbitrary_types_allowed = True
|
|
24
|
+
use_enum_values = True
|
|
25
|
+
extra = "allow"
|
|
25
26
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
from reflex.utils.serializers import serialize
|
|
27
|
+
def __init_subclass__(cls):
|
|
28
|
+
"""Warn that rx.Base is deprecated."""
|
|
29
|
+
from reflex.utils import console
|
|
30
30
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
console.deprecate(
|
|
32
|
+
feature_name="rx.Base",
|
|
33
|
+
reason=f"{cls!r} is subclassing rx.Base. You can subclass from `pydantic.BaseModel` directly instead or use dataclasses if possible.",
|
|
34
|
+
deprecation_version="0.8.15",
|
|
35
|
+
removal_version="0.9.0",
|
|
36
|
+
)
|
|
37
|
+
super().__init_subclass__()
|
|
35
38
|
|
|
36
|
-
|
|
37
|
-
|
|
39
|
+
def json(self) -> str:
|
|
40
|
+
"""Convert the object to a json string.
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
|
|
42
|
+
Returns:
|
|
43
|
+
The object as a json string.
|
|
44
|
+
"""
|
|
45
|
+
from reflex.utils.serializers import serialize
|
|
41
46
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
return self.__config__.json_dumps(
|
|
48
|
+
self.dict(),
|
|
49
|
+
default=serialize,
|
|
50
|
+
)
|
|
51
|
+
else:
|
|
52
|
+
|
|
53
|
+
class PydanticNotFoundFallback:
|
|
54
|
+
"""Fallback base class for environments without Pydantic."""
|
|
55
|
+
|
|
56
|
+
def __init__(self, *args, **kwargs):
|
|
57
|
+
"""Initialize the base class.
|
|
58
|
+
|
|
59
|
+
Args:
|
|
60
|
+
*args: Positional arguments.
|
|
61
|
+
**kwargs: Keyword arguments.
|
|
62
|
+
|
|
63
|
+
Raises:
|
|
64
|
+
ImportError: As Pydantic is not installed.
|
|
65
|
+
"""
|
|
66
|
+
msg = (
|
|
67
|
+
"Pydantic is not installed. Please install it to use rx.Base."
|
|
68
|
+
"You can install it with `pip install pydantic`."
|
|
69
|
+
)
|
|
70
|
+
raise ImportError(msg)
|
|
71
|
+
|
|
72
|
+
Base = PydanticNotFoundFallback # pyright: ignore[reportAssignmentType]
|
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import dataclasses
|
|
5
6
|
from collections.abc import Mapping, Sequence
|
|
6
7
|
from enum import Enum
|
|
7
8
|
from typing import Any, Literal, TypedDict
|
|
8
9
|
|
|
9
|
-
from reflex.base import Base
|
|
10
10
|
from reflex.components.component import Component, NoSSRComponent
|
|
11
11
|
from reflex.components.literals import LiteralRowMarker
|
|
12
12
|
from reflex.event import EventHandler, no_args_event_spec, passthrough_event_spec
|
|
@@ -50,7 +50,8 @@ class GridColumnIcons(Enum):
|
|
|
50
50
|
VideoUri = "video_uri"
|
|
51
51
|
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
@dataclasses.dataclass
|
|
54
|
+
class DataEditorThemeBase:
|
|
54
55
|
"""The theme for the DataEditor component."""
|
|
55
56
|
|
|
56
57
|
accent_color: str | None = None
|
|
@@ -87,6 +88,20 @@ class DataEditorTheme(Base):
|
|
|
87
88
|
text_medium: str | None = None
|
|
88
89
|
|
|
89
90
|
|
|
91
|
+
@dataclasses.dataclass(init=False)
|
|
92
|
+
class DataEditorTheme(DataEditorThemeBase):
|
|
93
|
+
"""The theme for the DataEditor component."""
|
|
94
|
+
|
|
95
|
+
def __init__(self, **kwargs: Any):
|
|
96
|
+
"""Initialize the DataEditorTheme.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
**kwargs: The keyword arguments to initialize the theme.
|
|
100
|
+
"""
|
|
101
|
+
kwargs = {format.to_snake_case(k): v for k, v in kwargs.items()}
|
|
102
|
+
super().__init__(**kwargs)
|
|
103
|
+
|
|
104
|
+
|
|
90
105
|
class Bounds(TypedDict):
|
|
91
106
|
"""The bounds of the group header."""
|
|
92
107
|
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
# ------------------- DO NOT EDIT ----------------------
|
|
4
4
|
# This file was generated by `reflex/utils/pyi_generator.py`!
|
|
5
5
|
# ------------------------------------------------------
|
|
6
|
+
import dataclasses
|
|
6
7
|
from collections.abc import Mapping, Sequence
|
|
7
8
|
from enum import Enum
|
|
8
9
|
from typing import Any, Literal, TypedDict
|
|
9
10
|
|
|
10
|
-
from reflex.base import Base
|
|
11
11
|
from reflex.components.component import NoSSRComponent
|
|
12
12
|
from reflex.components.core.breakpoints import Breakpoints
|
|
13
13
|
from reflex.event import EventType, PointerEventInfo
|
|
@@ -43,7 +43,8 @@ class GridColumnIcons(Enum):
|
|
|
43
43
|
Uri = "uri"
|
|
44
44
|
VideoUri = "video_uri"
|
|
45
45
|
|
|
46
|
-
|
|
46
|
+
@dataclasses.dataclass
|
|
47
|
+
class DataEditorThemeBase:
|
|
47
48
|
accent_color: str | None
|
|
48
49
|
accent_fg: str | None
|
|
49
50
|
accent_light: str | None
|
|
@@ -77,6 +78,9 @@ class DataEditorTheme(Base):
|
|
|
77
78
|
text_light: str | None
|
|
78
79
|
text_medium: str | None
|
|
79
80
|
|
|
81
|
+
@dataclasses.dataclass(init=False)
|
|
82
|
+
class DataEditorTheme(DataEditorThemeBase): ...
|
|
83
|
+
|
|
80
84
|
class Bounds(TypedDict):
|
|
81
85
|
x: int
|
|
82
86
|
y: int
|
reflex/components/field.py
CHANGED
|
@@ -7,6 +7,7 @@ from dataclasses import _MISSING_TYPE, MISSING
|
|
|
7
7
|
from typing import Annotated, Any, Generic, TypeVar, get_origin
|
|
8
8
|
|
|
9
9
|
from reflex.utils import types
|
|
10
|
+
from reflex.utils.compat import annotations_from_namespace
|
|
10
11
|
|
|
11
12
|
FIELD_TYPE = TypeVar("FIELD_TYPE")
|
|
12
13
|
|
|
@@ -117,7 +118,8 @@ class FieldBasedMeta(type):
|
|
|
117
118
|
cls, namespace: dict[str, Any], name: str
|
|
118
119
|
) -> dict[str, Any]:
|
|
119
120
|
return types.resolve_annotations(
|
|
120
|
-
namespace
|
|
121
|
+
annotations_from_namespace(namespace),
|
|
122
|
+
namespace["__module__"],
|
|
121
123
|
)
|
|
122
124
|
|
|
123
125
|
@classmethod
|
reflex/components/lucide/icon.py
CHANGED
|
@@ -6,7 +6,7 @@ from reflex.utils.imports import ImportVar
|
|
|
6
6
|
from reflex.vars.base import LiteralVar, Var
|
|
7
7
|
from reflex.vars.sequence import LiteralStringVar, StringVar
|
|
8
8
|
|
|
9
|
-
LUCIDE_LIBRARY = "lucide-react@0.
|
|
9
|
+
LUCIDE_LIBRARY = "lucide-react@0.545.0"
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class LucideIconComponent(Component):
|
|
@@ -1129,6 +1129,7 @@ LUCIDE_ICON_LIST = [
|
|
|
1129
1129
|
"monitor",
|
|
1130
1130
|
"moon_star",
|
|
1131
1131
|
"moon",
|
|
1132
|
+
"motorbike",
|
|
1132
1133
|
"mountain_snow",
|
|
1133
1134
|
"mountain",
|
|
1134
1135
|
"mouse_off",
|
|
@@ -11,7 +11,7 @@ from reflex.components.core.breakpoints import Breakpoints
|
|
|
11
11
|
from reflex.event import EventType, PointerEventInfo
|
|
12
12
|
from reflex.vars.base import Var
|
|
13
13
|
|
|
14
|
-
LUCIDE_LIBRARY = "lucide-react@0.
|
|
14
|
+
LUCIDE_LIBRARY = "lucide-react@0.545.0"
|
|
15
15
|
|
|
16
16
|
class LucideIconComponent(Component):
|
|
17
17
|
@classmethod
|
|
@@ -1194,6 +1194,7 @@ LUCIDE_ICON_LIST = [
|
|
|
1194
1194
|
"monitor",
|
|
1195
1195
|
"moon_star",
|
|
1196
1196
|
"moon",
|
|
1197
|
+
"motorbike",
|
|
1197
1198
|
"mountain_snow",
|
|
1198
1199
|
"mountain",
|
|
1199
1200
|
"mouse_off",
|
|
@@ -38,6 +38,84 @@ _REHYPE_PLUGINS = LiteralVar.create([_REHYPE_KATEX, _REHYPE_RAW])
|
|
|
38
38
|
NO_PROPS_TAGS = ("ul", "ol", "li")
|
|
39
39
|
|
|
40
40
|
|
|
41
|
+
def _h1(value: object):
|
|
42
|
+
from reflex.components.radix.themes.typography.heading import Heading
|
|
43
|
+
|
|
44
|
+
return Heading.create(value, as_="h1", size="6", margin_y="0.5em")
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _h2(value: object):
|
|
48
|
+
from reflex.components.radix.themes.typography.heading import Heading
|
|
49
|
+
|
|
50
|
+
return Heading.create(value, as_="h2", size="5", margin_y="0.5em")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _h3(value: object):
|
|
54
|
+
from reflex.components.radix.themes.typography.heading import Heading
|
|
55
|
+
|
|
56
|
+
return Heading.create(value, as_="h3", size="4", margin_y="0.5em")
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _h4(value: object):
|
|
60
|
+
from reflex.components.radix.themes.typography.heading import Heading
|
|
61
|
+
|
|
62
|
+
return Heading.create(value, as_="h4", size="3", margin_y="0.5em")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def _h5(value: object):
|
|
66
|
+
from reflex.components.radix.themes.typography.heading import Heading
|
|
67
|
+
|
|
68
|
+
return Heading.create(value, as_="h5", size="2", margin_y="0.5em")
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _h6(value: object):
|
|
72
|
+
from reflex.components.radix.themes.typography.heading import Heading
|
|
73
|
+
|
|
74
|
+
return Heading.create(value, as_="h6", size="1", margin_y="0.5em")
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _p(value: object):
|
|
78
|
+
from reflex.components.radix.themes.typography.text import Text
|
|
79
|
+
|
|
80
|
+
return Text.create(value, margin_y="1em")
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _ul(value: object):
|
|
84
|
+
from reflex.components.radix.themes.layout.list import UnorderedList
|
|
85
|
+
|
|
86
|
+
return UnorderedList.create(value, margin_y="1em")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def _ol(value: object):
|
|
90
|
+
from reflex.components.radix.themes.layout.list import OrderedList
|
|
91
|
+
|
|
92
|
+
return OrderedList.create(value, margin_y="1em")
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def _li(value: object):
|
|
96
|
+
from reflex.components.radix.themes.layout.list import ListItem
|
|
97
|
+
|
|
98
|
+
return ListItem.create(value, margin_y="0.5em")
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _a(value: object):
|
|
102
|
+
from reflex.components.radix.themes.typography.link import Link
|
|
103
|
+
|
|
104
|
+
return Link.create(value)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _code(value: object):
|
|
108
|
+
from reflex.components.radix.themes.typography.code import Code
|
|
109
|
+
|
|
110
|
+
return Code.create(value)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def _codeblock(value: object, **props):
|
|
114
|
+
from reflex.components.datadisplay.code import CodeBlock
|
|
115
|
+
|
|
116
|
+
return CodeBlock.create(value, margin_y="1em", wrap_long_lines=True, **props)
|
|
117
|
+
|
|
118
|
+
|
|
41
119
|
# Component Mapping
|
|
42
120
|
@lru_cache
|
|
43
121
|
def get_base_component_map() -> dict[str, Callable]:
|
|
@@ -46,33 +124,20 @@ def get_base_component_map() -> dict[str, Callable]:
|
|
|
46
124
|
Returns:
|
|
47
125
|
The base component map.
|
|
48
126
|
"""
|
|
49
|
-
from reflex.components.datadisplay.code import CodeBlock
|
|
50
|
-
from reflex.components.radix.themes.layout.list import (
|
|
51
|
-
ListItem,
|
|
52
|
-
OrderedList,
|
|
53
|
-
UnorderedList,
|
|
54
|
-
)
|
|
55
|
-
from reflex.components.radix.themes.typography.code import Code
|
|
56
|
-
from reflex.components.radix.themes.typography.heading import Heading
|
|
57
|
-
from reflex.components.radix.themes.typography.link import Link
|
|
58
|
-
from reflex.components.radix.themes.typography.text import Text
|
|
59
|
-
|
|
60
127
|
return {
|
|
61
|
-
"h1":
|
|
62
|
-
"h2":
|
|
63
|
-
"h3":
|
|
64
|
-
"h4":
|
|
65
|
-
"h5":
|
|
66
|
-
"h6":
|
|
67
|
-
"p":
|
|
68
|
-
"ul":
|
|
69
|
-
"ol":
|
|
70
|
-
"li":
|
|
71
|
-
"a":
|
|
72
|
-
"code":
|
|
73
|
-
"codeblock":
|
|
74
|
-
value, margin_y="1em", wrap_long_lines=True, **props
|
|
75
|
-
),
|
|
128
|
+
"h1": _h1,
|
|
129
|
+
"h2": _h2,
|
|
130
|
+
"h3": _h3,
|
|
131
|
+
"h4": _h4,
|
|
132
|
+
"h5": _h5,
|
|
133
|
+
"h6": _h6,
|
|
134
|
+
"p": _p,
|
|
135
|
+
"ul": _ul,
|
|
136
|
+
"ol": _ol,
|
|
137
|
+
"li": _li,
|
|
138
|
+
"a": _a,
|
|
139
|
+
"code": _code,
|
|
140
|
+
"codeblock": _codeblock,
|
|
76
141
|
}
|
|
77
142
|
|
|
78
143
|
|
|
@@ -413,7 +478,16 @@ let {_LANGUAGE!s} = match ? match[1] : '';
|
|
|
413
478
|
@staticmethod
|
|
414
479
|
def _component_map_hash(component_map: dict) -> str:
|
|
415
480
|
inp = str(
|
|
416
|
-
{
|
|
481
|
+
{
|
|
482
|
+
tag: (
|
|
483
|
+
f"{component.__module__}.{component.__qualname__}"
|
|
484
|
+
if (
|
|
485
|
+
"<" not in component.__name__
|
|
486
|
+
) # simple way to check against lambdas
|
|
487
|
+
else component(_MOCK_ARG)
|
|
488
|
+
)
|
|
489
|
+
for tag, component in component_map.items()
|
|
490
|
+
}
|
|
417
491
|
).encode()
|
|
418
492
|
return md5(inp).hexdigest()
|
|
419
493
|
|