reflex 0.8.12a1__py3-none-any.whl → 0.8.13__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 +48 -17
- reflex/app.py +17 -12
- reflex/app_mixins/lifespan.py +11 -0
- reflex/compiler/compiler.py +4 -1
- reflex/components/core/upload.py +53 -14
- reflex/components/core/upload.pyi +8 -0
- reflex/components/react_player/audio.pyi +23 -46
- reflex/components/react_player/react_player.py +159 -19
- reflex/components/react_player/react_player.pyi +40 -45
- reflex/components/react_player/video.pyi +23 -46
- reflex/components/recharts/recharts.py +2 -2
- reflex/constants/colors.py +3 -1
- reflex/constants/installer.py +2 -2
- reflex/environment.py +3 -0
- reflex/istate/proxy.py +36 -36
- reflex/plugins/shared_tailwind.py +1 -1
- reflex/reflex.py +54 -3
- reflex/state.py +15 -5
- reflex/testing.py +14 -0
- reflex/utils/build.py +77 -57
- reflex/utils/exec.py +12 -0
- reflex/utils/export.py +7 -2
- reflex/utils/prerequisites.py +82 -7
- reflex/utils/serializers.py +8 -4
- reflex/utils/token_manager.py +10 -0
- reflex/utils/types.py +2 -0
- reflex/vars/__init__.py +56 -26
- reflex/vars/base.py +20 -113
- reflex/vars/color.py +214 -0
- reflex/vars/number.py +2 -2
- reflex/vars/sequence.py +0 -136
- {reflex-0.8.12a1.dist-info → reflex-0.8.13.dist-info}/METADATA +1 -1
- {reflex-0.8.12a1.dist-info → reflex-0.8.13.dist-info}/RECORD +36 -35
- {reflex-0.8.12a1.dist-info → reflex-0.8.13.dist-info}/WHEEL +0 -0
- {reflex-0.8.12a1.dist-info → reflex-0.8.13.dist-info}/entry_points.txt +0 -0
- {reflex-0.8.12a1.dist-info → reflex-0.8.13.dist-info}/licenses/LICENSE +0 -0
|
@@ -531,6 +531,7 @@ export const connect = async (
|
|
|
531
531
|
) => {
|
|
532
532
|
// Get backend URL object from the endpoint.
|
|
533
533
|
const endpoint = getBackendURL(EVENTURL);
|
|
534
|
+
const on_hydrated_queue = [];
|
|
534
535
|
|
|
535
536
|
// Create the socket.
|
|
536
537
|
socket.current = io(endpoint.href, {
|
|
@@ -552,7 +553,17 @@ export const connect = async (
|
|
|
552
553
|
|
|
553
554
|
function checkVisibility() {
|
|
554
555
|
if (document.visibilityState === "visible") {
|
|
555
|
-
if (!socket.current
|
|
556
|
+
if (!socket.current) {
|
|
557
|
+
connect(
|
|
558
|
+
socket,
|
|
559
|
+
dispatch,
|
|
560
|
+
transports,
|
|
561
|
+
setConnectErrors,
|
|
562
|
+
client_storage,
|
|
563
|
+
navigate,
|
|
564
|
+
params,
|
|
565
|
+
);
|
|
566
|
+
} else if (!socket.current.connected) {
|
|
556
567
|
console.log("Socket is disconnected, attempting to reconnect ");
|
|
557
568
|
socket.current.connect();
|
|
558
569
|
} else {
|
|
@@ -593,6 +604,7 @@ export const connect = async (
|
|
|
593
604
|
|
|
594
605
|
// When the socket disconnects reset the event_processing flag
|
|
595
606
|
socket.current.on("disconnect", () => {
|
|
607
|
+
socket.current = null; // allow reconnect to occur automatically
|
|
596
608
|
event_processing = false;
|
|
597
609
|
window.removeEventListener("unload", disconnectTrigger);
|
|
598
610
|
window.removeEventListener("beforeunload", disconnectTrigger);
|
|
@@ -603,6 +615,14 @@ export const connect = async (
|
|
|
603
615
|
socket.current.on("event", async (update) => {
|
|
604
616
|
for (const substate in update.delta) {
|
|
605
617
|
dispatch[substate](update.delta[substate]);
|
|
618
|
+
// handle events waiting for `is_hydrated`
|
|
619
|
+
if (
|
|
620
|
+
substate === state_name &&
|
|
621
|
+
update.delta[substate]?.is_hydrated_rx_state_
|
|
622
|
+
) {
|
|
623
|
+
queueEvents(on_hydrated_queue, socket, false, navigate, params);
|
|
624
|
+
on_hydrated_queue.length = 0;
|
|
625
|
+
}
|
|
606
626
|
}
|
|
607
627
|
applyClientStorageDelta(client_storage, update.delta);
|
|
608
628
|
event_processing = !update.final;
|
|
@@ -612,7 +632,8 @@ export const connect = async (
|
|
|
612
632
|
});
|
|
613
633
|
socket.current.on("reload", async (event) => {
|
|
614
634
|
event_processing = false;
|
|
615
|
-
|
|
635
|
+
on_hydrated_queue.push(event);
|
|
636
|
+
queueEvents(initialEvents(), socket, true, navigate, params);
|
|
616
637
|
});
|
|
617
638
|
socket.current.on("new_token", async (new_token) => {
|
|
618
639
|
token = new_token;
|
|
@@ -774,10 +795,32 @@ export const useEventLoop = (
|
|
|
774
795
|
}
|
|
775
796
|
}, [paramsR]);
|
|
776
797
|
|
|
798
|
+
const ensureSocketConnected = useCallback(async () => {
|
|
799
|
+
// only use websockets if state is present and backend is not disabled (reflex cloud).
|
|
800
|
+
if (
|
|
801
|
+
Object.keys(initialState).length > 1 &&
|
|
802
|
+
!isBackendDisabled() &&
|
|
803
|
+
!socket.current
|
|
804
|
+
) {
|
|
805
|
+
// Initialize the websocket connection.
|
|
806
|
+
await connect(
|
|
807
|
+
socket,
|
|
808
|
+
dispatch,
|
|
809
|
+
["websocket"],
|
|
810
|
+
setConnectErrors,
|
|
811
|
+
client_storage,
|
|
812
|
+
navigate,
|
|
813
|
+
() => params.current,
|
|
814
|
+
);
|
|
815
|
+
}
|
|
816
|
+
}, [socket, dispatch, setConnectErrors, client_storage, navigate, params]);
|
|
817
|
+
|
|
777
818
|
// Function to add new events to the event queue.
|
|
778
819
|
const addEvents = useCallback((events, args, event_actions) => {
|
|
779
820
|
const _events = events.filter((e) => e !== undefined && e !== null);
|
|
780
821
|
|
|
822
|
+
ensureSocketConnected();
|
|
823
|
+
|
|
781
824
|
if (!(args instanceof Array)) {
|
|
782
825
|
args = [args];
|
|
783
826
|
}
|
|
@@ -870,21 +913,8 @@ export const useEventLoop = (
|
|
|
870
913
|
|
|
871
914
|
// Handle socket connect/disconnect.
|
|
872
915
|
useEffect(() => {
|
|
873
|
-
//
|
|
874
|
-
|
|
875
|
-
// Initialize the websocket connection.
|
|
876
|
-
if (!socket.current) {
|
|
877
|
-
connect(
|
|
878
|
-
socket,
|
|
879
|
-
dispatch,
|
|
880
|
-
["websocket"],
|
|
881
|
-
setConnectErrors,
|
|
882
|
-
client_storage,
|
|
883
|
-
navigate,
|
|
884
|
-
() => params.current,
|
|
885
|
-
);
|
|
886
|
-
}
|
|
887
|
-
}
|
|
916
|
+
// Initialize the websocket connection.
|
|
917
|
+
ensureSocketConnected();
|
|
888
918
|
|
|
889
919
|
// Cleanup function.
|
|
890
920
|
return () => {
|
|
@@ -903,6 +933,7 @@ export const useEventLoop = (
|
|
|
903
933
|
(async () => {
|
|
904
934
|
// Process all outstanding events.
|
|
905
935
|
while (event_queue.length > 0 && !event_processing) {
|
|
936
|
+
await ensureSocketConnected();
|
|
906
937
|
await processEvent(socket.current, navigate, () => params.current);
|
|
907
938
|
}
|
|
908
939
|
})();
|
reflex/app.py
CHANGED
|
@@ -97,6 +97,7 @@ from reflex.state import (
|
|
|
97
97
|
State,
|
|
98
98
|
StateManager,
|
|
99
99
|
StateUpdate,
|
|
100
|
+
_split_substate_key,
|
|
100
101
|
_substate_key,
|
|
101
102
|
all_base_state_classes,
|
|
102
103
|
code_uses_state_contexts,
|
|
@@ -112,7 +113,12 @@ from reflex.utils import (
|
|
|
112
113
|
prerequisites,
|
|
113
114
|
types,
|
|
114
115
|
)
|
|
115
|
-
from reflex.utils.exec import
|
|
116
|
+
from reflex.utils.exec import (
|
|
117
|
+
get_compile_context,
|
|
118
|
+
is_prod_mode,
|
|
119
|
+
is_testing_env,
|
|
120
|
+
should_prerender_routes,
|
|
121
|
+
)
|
|
116
122
|
from reflex.utils.imports import ImportVar
|
|
117
123
|
from reflex.utils.token_manager import TokenManager
|
|
118
124
|
from reflex.utils.types import ASGIApp, Message, Receive, Scope, Send
|
|
@@ -606,7 +612,7 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
606
612
|
"""
|
|
607
613
|
from reflex.vars.base import GLOBAL_CACHE
|
|
608
614
|
|
|
609
|
-
self._compile(prerender_routes=
|
|
615
|
+
self._compile(prerender_routes=should_prerender_routes())
|
|
610
616
|
|
|
611
617
|
config = get_config()
|
|
612
618
|
|
|
@@ -1559,7 +1565,7 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
1559
1565
|
state._clean()
|
|
1560
1566
|
await self.event_namespace.emit_update(
|
|
1561
1567
|
update=StateUpdate(delta=delta),
|
|
1562
|
-
|
|
1568
|
+
token=token,
|
|
1563
1569
|
)
|
|
1564
1570
|
|
|
1565
1571
|
def _process_background(
|
|
@@ -1599,7 +1605,7 @@ class App(MiddlewareMixin, LifespanMixin):
|
|
|
1599
1605
|
# Send the update to the client.
|
|
1600
1606
|
await self.event_namespace.emit_update(
|
|
1601
1607
|
update=update,
|
|
1602
|
-
|
|
1608
|
+
token=event.token,
|
|
1603
1609
|
)
|
|
1604
1610
|
|
|
1605
1611
|
task = asyncio.create_task(
|
|
@@ -2061,20 +2067,19 @@ class EventNamespace(AsyncNamespace):
|
|
|
2061
2067
|
and console.error(f"Token cleanup error: {t.exception()}")
|
|
2062
2068
|
)
|
|
2063
2069
|
|
|
2064
|
-
async def emit_update(self, update: StateUpdate,
|
|
2070
|
+
async def emit_update(self, update: StateUpdate, token: str) -> None:
|
|
2065
2071
|
"""Emit an update to the client.
|
|
2066
2072
|
|
|
2067
2073
|
Args:
|
|
2068
2074
|
update: The state update to send.
|
|
2069
|
-
|
|
2075
|
+
token: The client token (tab) associated with the event.
|
|
2070
2076
|
"""
|
|
2071
|
-
|
|
2077
|
+
client_token, _ = _split_substate_key(token)
|
|
2078
|
+
sid = self.token_to_sid.get(client_token)
|
|
2079
|
+
if sid is None:
|
|
2072
2080
|
# If the sid is None, we are not connected to a client. Prevent sending
|
|
2073
2081
|
# updates to all clients.
|
|
2074
|
-
|
|
2075
|
-
token = self.sid_to_token.get(sid)
|
|
2076
|
-
if token is None:
|
|
2077
|
-
console.warn(f"Attempting to send delta to disconnected websocket {sid}")
|
|
2082
|
+
console.warn(f"Attempting to send delta to disconnected client {token!r}")
|
|
2078
2083
|
return
|
|
2079
2084
|
# Creating a task prevents the update from being blocked behind other coroutines.
|
|
2080
2085
|
await asyncio.create_task(
|
|
@@ -2165,7 +2170,7 @@ class EventNamespace(AsyncNamespace):
|
|
|
2165
2170
|
# Process the events.
|
|
2166
2171
|
async for update in updates_gen:
|
|
2167
2172
|
# Emit the update from processing the event.
|
|
2168
|
-
await self.emit_update(update=update,
|
|
2173
|
+
await self.emit_update(update=update, token=event.token)
|
|
2169
2174
|
|
|
2170
2175
|
async def on_ping(self, sid: str):
|
|
2171
2176
|
"""Event for testing the API endpoint.
|
reflex/app_mixins/lifespan.py
CHANGED
|
@@ -60,6 +60,17 @@ class LifespanMixin(AppMixin):
|
|
|
60
60
|
for task in running_tasks:
|
|
61
61
|
console.debug(f"Canceling lifespan task: {task}")
|
|
62
62
|
task.cancel(msg="lifespan_cleanup")
|
|
63
|
+
# Disassociate sid / token pairings so they can be reconnected properly.
|
|
64
|
+
try:
|
|
65
|
+
event_namespace = self.event_namespace # pyright: ignore[reportAttributeAccessIssue]
|
|
66
|
+
except AttributeError:
|
|
67
|
+
pass
|
|
68
|
+
else:
|
|
69
|
+
try:
|
|
70
|
+
if event_namespace:
|
|
71
|
+
await event_namespace._token_manager.disconnect_all()
|
|
72
|
+
except Exception as e:
|
|
73
|
+
console.error(f"Error during lifespan cleanup: {e}")
|
|
63
74
|
|
|
64
75
|
def register_lifespan_task(self, task: Callable | asyncio.Task, **task_kwargs):
|
|
65
76
|
"""Register a task to run during the lifespan of the app.
|
reflex/compiler/compiler.py
CHANGED
|
@@ -621,7 +621,10 @@ def purge_web_pages_dir():
|
|
|
621
621
|
return
|
|
622
622
|
|
|
623
623
|
# Empty out the web pages directory.
|
|
624
|
-
utils.empty_dir(
|
|
624
|
+
utils.empty_dir(
|
|
625
|
+
get_web_dir() / constants.Dirs.PAGES,
|
|
626
|
+
keep_files=["routes.js", "entry.client.js"],
|
|
627
|
+
)
|
|
625
628
|
|
|
626
629
|
|
|
627
630
|
if TYPE_CHECKING:
|
reflex/components/core/upload.py
CHANGED
|
@@ -17,6 +17,7 @@ from reflex.components.component import (
|
|
|
17
17
|
from reflex.components.core.cond import cond
|
|
18
18
|
from reflex.components.el.elements.forms import Input
|
|
19
19
|
from reflex.components.radix.themes.layout.box import Box
|
|
20
|
+
from reflex.components.sonner.toast import toast
|
|
20
21
|
from reflex.constants import Dirs
|
|
21
22
|
from reflex.constants.compiler import Hooks, Imports
|
|
22
23
|
from reflex.environment import environment
|
|
@@ -36,7 +37,8 @@ from reflex.utils.imports import ImportVar
|
|
|
36
37
|
from reflex.vars import VarData
|
|
37
38
|
from reflex.vars.base import Var, get_unique_variable_name
|
|
38
39
|
from reflex.vars.function import FunctionVar
|
|
39
|
-
from reflex.vars.
|
|
40
|
+
from reflex.vars.object import ObjectVar
|
|
41
|
+
from reflex.vars.sequence import ArrayVar, LiteralStringVar
|
|
40
42
|
|
|
41
43
|
DEFAULT_UPLOAD_ID: str = "default"
|
|
42
44
|
|
|
@@ -178,6 +180,34 @@ def _on_drop_spec(files: Var) -> tuple[Var[Any]]:
|
|
|
178
180
|
return (files,)
|
|
179
181
|
|
|
180
182
|
|
|
183
|
+
def _default_drop_rejected(rejected_files: ArrayVar[list[dict[str, Any]]]) -> EventSpec:
|
|
184
|
+
"""Event handler for showing a toast with rejected file info.
|
|
185
|
+
|
|
186
|
+
Args:
|
|
187
|
+
rejected_files: The files that were rejected.
|
|
188
|
+
|
|
189
|
+
Returns:
|
|
190
|
+
An event spec that shows a toast with the rejected file info when triggered.
|
|
191
|
+
"""
|
|
192
|
+
|
|
193
|
+
def _format_rejected_file_record(rf: ObjectVar[dict[str, Any]]) -> str:
|
|
194
|
+
rf = rf.to(ObjectVar, dict[str, dict[str, Any]])
|
|
195
|
+
file = rf["file"].to(ObjectVar, dict[str, Any])
|
|
196
|
+
errors = rf["errors"].to(ArrayVar, list[dict[str, Any]])
|
|
197
|
+
return (
|
|
198
|
+
f"{file['path']}: {errors.foreach(lambda err: err['message']).join(', ')}"
|
|
199
|
+
)
|
|
200
|
+
|
|
201
|
+
return toast.error(
|
|
202
|
+
title="Files not Accepted",
|
|
203
|
+
description=rejected_files.to(ArrayVar)
|
|
204
|
+
.foreach(_format_rejected_file_record)
|
|
205
|
+
.join("\n\n"),
|
|
206
|
+
close_button=True,
|
|
207
|
+
style={"white_space": "pre-line"},
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
|
|
181
211
|
class UploadFilesProvider(Component):
|
|
182
212
|
"""AppWrap component that provides a dict of selected files by ID via useContext."""
|
|
183
213
|
|
|
@@ -191,6 +221,9 @@ class GhostUpload(Fragment):
|
|
|
191
221
|
# Fired when files are dropped.
|
|
192
222
|
on_drop: EventHandler[_on_drop_spec]
|
|
193
223
|
|
|
224
|
+
# Fired when dropped files do not meet the specified criteria.
|
|
225
|
+
on_drop_rejected: EventHandler[_on_drop_spec]
|
|
226
|
+
|
|
194
227
|
|
|
195
228
|
class Upload(MemoizationLeaf):
|
|
196
229
|
"""A file upload component."""
|
|
@@ -234,6 +267,9 @@ class Upload(MemoizationLeaf):
|
|
|
234
267
|
# Fired when files are dropped.
|
|
235
268
|
on_drop: EventHandler[_on_drop_spec]
|
|
236
269
|
|
|
270
|
+
# Fired when dropped files do not meet the specified criteria.
|
|
271
|
+
on_drop_rejected: EventHandler[_on_drop_spec]
|
|
272
|
+
|
|
237
273
|
# Style rules to apply when actively dragging.
|
|
238
274
|
drag_active_style: Style | None = field(default=None, is_javascript_property=False)
|
|
239
275
|
|
|
@@ -295,6 +331,10 @@ class Upload(MemoizationLeaf):
|
|
|
295
331
|
on_drop[ix] = event
|
|
296
332
|
upload_props["on_drop"] = on_drop
|
|
297
333
|
|
|
334
|
+
if upload_props.get("on_drop_rejected") is None:
|
|
335
|
+
# If on_drop_rejected is not provided, show an error toast.
|
|
336
|
+
upload_props["on_drop_rejected"] = _default_drop_rejected
|
|
337
|
+
|
|
298
338
|
input_props_unique_name = get_unique_variable_name()
|
|
299
339
|
root_props_unique_name = get_unique_variable_name()
|
|
300
340
|
is_drag_active_unique_name = get_unique_variable_name()
|
|
@@ -313,22 +353,22 @@ class Upload(MemoizationLeaf):
|
|
|
313
353
|
),
|
|
314
354
|
)
|
|
315
355
|
|
|
316
|
-
|
|
317
|
-
GhostUpload.create(
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
356
|
+
event_triggers = StatefulComponent._get_memoized_event_triggers(
|
|
357
|
+
GhostUpload.create(
|
|
358
|
+
on_drop=upload_props["on_drop"],
|
|
359
|
+
on_drop_rejected=upload_props["on_drop_rejected"],
|
|
360
|
+
)
|
|
361
|
+
)
|
|
362
|
+
callback_hooks = []
|
|
363
|
+
for trigger_name, (event_var, callback_str) in event_triggers.items():
|
|
364
|
+
upload_props[trigger_name] = event_var
|
|
365
|
+
callback_hooks.append(callback_str)
|
|
321
366
|
|
|
322
367
|
upload_props = {
|
|
323
368
|
format.to_camel_case(key): value for key, value in upload_props.items()
|
|
324
369
|
}
|
|
325
370
|
|
|
326
|
-
use_dropzone_arguments = Var.create(
|
|
327
|
-
{
|
|
328
|
-
"onDrop": event_var,
|
|
329
|
-
**upload_props,
|
|
330
|
-
}
|
|
331
|
-
)
|
|
371
|
+
use_dropzone_arguments = Var.create(upload_props)
|
|
332
372
|
|
|
333
373
|
left_side = (
|
|
334
374
|
"const { "
|
|
@@ -344,11 +384,10 @@ class Upload(MemoizationLeaf):
|
|
|
344
384
|
imports=Imports.EVENTS,
|
|
345
385
|
hooks={Hooks.EVENTS: None},
|
|
346
386
|
),
|
|
347
|
-
event_var._get_all_var_data(),
|
|
348
387
|
use_dropzone_arguments._get_all_var_data(),
|
|
349
388
|
VarData(
|
|
350
389
|
hooks={
|
|
351
|
-
|
|
390
|
+
**dict.fromkeys(callback_hooks, None),
|
|
352
391
|
f"{left_side} = {right_side};": None,
|
|
353
392
|
},
|
|
354
393
|
imports={
|
|
@@ -108,6 +108,7 @@ class GhostUpload(Fragment):
|
|
|
108
108
|
on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
|
|
109
109
|
on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
|
|
110
110
|
on_drop: EventType[()] | EventType[Any] | None = None,
|
|
111
|
+
on_drop_rejected: EventType[()] | EventType[Any] | None = None,
|
|
111
112
|
on_focus: EventType[()] | None = None,
|
|
112
113
|
on_mount: EventType[()] | None = None,
|
|
113
114
|
on_mouse_down: EventType[()] | None = None,
|
|
@@ -127,6 +128,7 @@ class GhostUpload(Fragment):
|
|
|
127
128
|
Args:
|
|
128
129
|
*children: The children of the component.
|
|
129
130
|
on_drop: Fired when files are dropped.
|
|
131
|
+
on_drop_rejected: Fired when dropped files do not meet the specified criteria.
|
|
130
132
|
style: The style of the component.
|
|
131
133
|
key: A unique key for the component.
|
|
132
134
|
id: The id for the component.
|
|
@@ -171,6 +173,7 @@ class Upload(MemoizationLeaf):
|
|
|
171
173
|
on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
|
|
172
174
|
on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
|
|
173
175
|
on_drop: EventType[()] | EventType[Any] | None = None,
|
|
176
|
+
on_drop_rejected: EventType[()] | EventType[Any] | None = None,
|
|
174
177
|
on_focus: EventType[()] | None = None,
|
|
175
178
|
on_mount: EventType[()] | None = None,
|
|
176
179
|
on_mouse_down: EventType[()] | None = None,
|
|
@@ -199,6 +202,7 @@ class Upload(MemoizationLeaf):
|
|
|
199
202
|
no_drag: Whether to disable drag and drop.
|
|
200
203
|
no_keyboard: Whether to disable using the space/enter keys to upload.
|
|
201
204
|
on_drop: Fired when files are dropped.
|
|
205
|
+
on_drop_rejected: Fired when dropped files do not meet the specified criteria.
|
|
202
206
|
drag_active_style: Style rules to apply when actively dragging.
|
|
203
207
|
style: The style of the component.
|
|
204
208
|
key: A unique key for the component.
|
|
@@ -242,6 +246,7 @@ class StyledUpload(Upload):
|
|
|
242
246
|
on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
|
|
243
247
|
on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
|
|
244
248
|
on_drop: EventType[()] | EventType[Any] | None = None,
|
|
249
|
+
on_drop_rejected: EventType[()] | EventType[Any] | None = None,
|
|
245
250
|
on_focus: EventType[()] | None = None,
|
|
246
251
|
on_mount: EventType[()] | None = None,
|
|
247
252
|
on_mouse_down: EventType[()] | None = None,
|
|
@@ -270,6 +275,7 @@ class StyledUpload(Upload):
|
|
|
270
275
|
no_drag: Whether to disable drag and drop.
|
|
271
276
|
no_keyboard: Whether to disable using the space/enter keys to upload.
|
|
272
277
|
on_drop: Fired when files are dropped.
|
|
278
|
+
on_drop_rejected: Fired when dropped files do not meet the specified criteria.
|
|
273
279
|
drag_active_style: Style rules to apply when actively dragging.
|
|
274
280
|
style: The style of the component.
|
|
275
281
|
key: A unique key for the component.
|
|
@@ -314,6 +320,7 @@ class UploadNamespace(ComponentNamespace):
|
|
|
314
320
|
on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
|
|
315
321
|
on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
|
|
316
322
|
on_drop: EventType[()] | EventType[Any] | None = None,
|
|
323
|
+
on_drop_rejected: EventType[()] | EventType[Any] | None = None,
|
|
317
324
|
on_focus: EventType[()] | None = None,
|
|
318
325
|
on_mount: EventType[()] | None = None,
|
|
319
326
|
on_mouse_down: EventType[()] | None = None,
|
|
@@ -342,6 +349,7 @@ class UploadNamespace(ComponentNamespace):
|
|
|
342
349
|
no_drag: Whether to disable drag and drop.
|
|
343
350
|
no_keyboard: Whether to disable using the space/enter keys to upload.
|
|
344
351
|
on_drop: Fired when files are dropped.
|
|
352
|
+
on_drop_rejected: Fired when dropped files do not meet the specified criteria.
|
|
345
353
|
drag_active_style: Style rules to apply when actively dragging.
|
|
346
354
|
style: The style of the component.
|
|
347
355
|
key: A unique key for the component.
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
from collections.abc import Mapping, Sequence
|
|
7
7
|
from typing import Any
|
|
8
8
|
|
|
9
|
-
import reflex
|
|
10
9
|
from reflex.components.core.breakpoints import Breakpoints
|
|
11
10
|
from reflex.components.react_player.react_player import ReactPlayer
|
|
12
11
|
from reflex.event import EventType, PointerEventInfo
|
|
@@ -17,13 +16,18 @@ class Audio(ReactPlayer):
|
|
|
17
16
|
def create(
|
|
18
17
|
cls,
|
|
19
18
|
*children,
|
|
20
|
-
|
|
19
|
+
src: Var[list[dict[str, str]] | list[str] | str]
|
|
20
|
+
| list[dict[str, str]]
|
|
21
|
+
| list[str]
|
|
22
|
+
| str
|
|
23
|
+
| None = None,
|
|
21
24
|
playing: Var[bool] | bool | None = None,
|
|
22
25
|
loop: Var[bool] | bool | None = None,
|
|
23
26
|
controls: Var[bool] | bool | None = None,
|
|
24
27
|
light: Var[bool] | bool | None = None,
|
|
25
28
|
volume: Var[float] | float | None = None,
|
|
26
29
|
muted: Var[bool] | bool | None = None,
|
|
30
|
+
config: Var[dict[str, Any]] | dict[str, Any] | None = None,
|
|
27
31
|
style: Sequence[Mapping[str, Any]]
|
|
28
32
|
| Mapping[str, Any]
|
|
29
33
|
| Var[Mapping[str, Any]]
|
|
@@ -35,18 +39,16 @@ class Audio(ReactPlayer):
|
|
|
35
39
|
class_name: Any | None = None,
|
|
36
40
|
custom_attrs: dict[str, Var | Any] | None = None,
|
|
37
41
|
on_blur: EventType[()] | None = None,
|
|
38
|
-
on_buffer: EventType[()] | None = None,
|
|
39
|
-
on_buffer_end: EventType[()] | None = None,
|
|
40
42
|
on_click: EventType[()] | EventType[PointerEventInfo] | None = None,
|
|
41
43
|
on_click_preview: EventType[()] | None = None,
|
|
42
44
|
on_context_menu: EventType[()] | EventType[PointerEventInfo] | None = None,
|
|
43
|
-
on_disable_pip: EventType[()] | None = None,
|
|
44
45
|
on_double_click: EventType[()] | EventType[PointerEventInfo] | None = None,
|
|
45
|
-
|
|
46
|
-
on_enable_pip: EventType[()] | None = None,
|
|
46
|
+
on_duration_change: EventType[Any] | None = None,
|
|
47
47
|
on_ended: EventType[()] | None = None,
|
|
48
|
+
on_enter_picture_in_picture: EventType[()] | None = None,
|
|
48
49
|
on_error: EventType[()] | None = None,
|
|
49
50
|
on_focus: EventType[()] | None = None,
|
|
51
|
+
on_leave_picture_in_picture: EventType[()] | None = None,
|
|
50
52
|
on_mount: EventType[()] | None = None,
|
|
51
53
|
on_mouse_down: EventType[()] | None = None,
|
|
52
54
|
on_mouse_enter: EventType[()] | None = None,
|
|
@@ -57,54 +59,29 @@ class Audio(ReactPlayer):
|
|
|
57
59
|
on_mouse_up: EventType[()] | None = None,
|
|
58
60
|
on_pause: EventType[()] | None = None,
|
|
59
61
|
on_play: EventType[()] | None = None,
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
| EventType[reflex.components.react_player.react_player.Progress]
|
|
64
|
-
| None = None,
|
|
62
|
+
on_playing: EventType[()] | None = None,
|
|
63
|
+
on_progress: EventType[Any] | None = None,
|
|
64
|
+
on_rate_change: EventType[Any] | None = None,
|
|
65
65
|
on_ready: EventType[()] | None = None,
|
|
66
66
|
on_scroll: EventType[()] | None = None,
|
|
67
67
|
on_scroll_end: EventType[()] | None = None,
|
|
68
|
-
|
|
68
|
+
on_seeked: EventType[Any] | None = None,
|
|
69
|
+
on_seeking: EventType[()] | None = None,
|
|
69
70
|
on_start: EventType[()] | None = None,
|
|
71
|
+
on_time_update: EventType[Any] | None = None,
|
|
70
72
|
on_unmount: EventType[()] | None = None,
|
|
73
|
+
on_waiting: EventType[()] | None = None,
|
|
71
74
|
**props,
|
|
72
75
|
) -> Audio:
|
|
73
|
-
"""Create
|
|
76
|
+
"""Create a component.
|
|
74
77
|
|
|
75
78
|
Args:
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
playing: Set to true or false to pause or play the media
|
|
79
|
-
loop: Set to true or false to loop the media
|
|
80
|
-
controls: Set to true or false to display native player controls.
|
|
81
|
-
light: Set to true to show just the video thumbnail, which loads the full player on click
|
|
82
|
-
volume: Set the volume of the player, between 0 and 1
|
|
83
|
-
muted: Mutes the player
|
|
84
|
-
on_ready: Called when media is loaded and ready to play. If playing is set to true, media will play immediately.
|
|
85
|
-
on_start: Called when media starts playing.
|
|
86
|
-
on_play: Called when media starts or resumes playing after pausing or buffering.
|
|
87
|
-
on_progress: Callback containing played and loaded progress as a fraction, and playedSeconds and loadedSeconds in seconds. eg { played: 0.12, playedSeconds: 11.3, loaded: 0.34, loadedSeconds: 16.7 }
|
|
88
|
-
on_duration: Callback containing duration of the media, in seconds.
|
|
89
|
-
on_pause: Called when media is paused.
|
|
90
|
-
on_buffer: Called when media starts buffering.
|
|
91
|
-
on_buffer_end: Called when media has finished buffering. Works for files, YouTube and Facebook.
|
|
92
|
-
on_seek: Called when media seeks with seconds parameter.
|
|
93
|
-
on_playback_rate_change: Called when playback rate of the player changed. Only supported by YouTube, Vimeo (if enabled), Wistia, and file paths.
|
|
94
|
-
on_playback_quality_change: Called when playback quality of the player changed. Only supported by YouTube (if enabled).
|
|
95
|
-
on_ended: Called when media finishes playing. Does not fire when loop is set to true.
|
|
96
|
-
on_error: Called when an error occurs whilst attempting to play media.
|
|
97
|
-
on_click_preview: Called when user clicks the light mode preview.
|
|
98
|
-
on_enable_pip: Called when picture-in-picture mode is enabled.
|
|
99
|
-
on_disable_pip: Called when picture-in-picture mode is disabled.
|
|
100
|
-
style: The style of the component.
|
|
101
|
-
key: A unique key for the component.
|
|
102
|
-
id: The id for the component.
|
|
103
|
-
ref: The Var to pass as the ref to the component.
|
|
104
|
-
class_name: The class name for the component.
|
|
105
|
-
custom_attrs: custom attribute
|
|
106
|
-
**props: The props of the component.
|
|
79
|
+
children: The children of the component.
|
|
80
|
+
props: The props of the component.
|
|
107
81
|
|
|
108
82
|
Returns:
|
|
109
|
-
The component.
|
|
83
|
+
The created component.
|
|
84
|
+
|
|
85
|
+
Raises:
|
|
86
|
+
ValueError: If both a deprecated prop and its replacement are both passed.
|
|
110
87
|
"""
|