reflex 0.7.2a2__py3-none-any.whl → 0.7.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of reflex might be problematic. Click here for more details.
- reflex/.templates/jinja/web/pages/custom_component.js.jinja2 +6 -3
- reflex/.templates/web/components/reflex/radix_themes_color_mode_provider.js +1 -1
- reflex/.templates/web/components/shiki/code.js +26 -21
- reflex/.templates/web/postcss.config.js +1 -1
- reflex/.templates/web/utils/client_side_routing.js +18 -16
- reflex/.templates/web/utils/helpers/dataeditor.js +1 -1
- reflex/.templates/web/utils/helpers/range.js +30 -30
- reflex/.templates/web/utils/state.js +44 -22
- reflex/app_mixins/middleware.py +9 -10
- reflex/compiler/compiler.py +7 -0
- reflex/components/core/banner.py +1 -1
- reflex/components/core/foreach.py +3 -2
- reflex/components/datadisplay/logo.py +1 -1
- reflex/components/el/__init__.pyi +22 -0
- reflex/components/el/elements/__init__.py +20 -1
- reflex/components/el/elements/__init__.pyi +42 -1
- reflex/components/el/elements/media.py +11 -0
- reflex/components/el/elements/media.pyi +11 -0
- reflex/components/lucide/icon.py +8 -6
- reflex/components/lucide/icon.pyi +0 -1
- reflex/components/radix/themes/components/slider.py +2 -1
- reflex/config.py +13 -7
- reflex/custom_components/custom_components.py +23 -25
- reflex/event.py +7 -2
- reflex/istate/data.py +59 -7
- reflex/reflex.py +75 -32
- reflex/state.py +3 -3
- reflex/style.py +3 -3
- reflex/testing.py +4 -10
- reflex/utils/exceptions.py +31 -1
- reflex/utils/exec.py +4 -8
- reflex/utils/export.py +2 -2
- reflex/utils/prerequisites.py +3 -45
- reflex/utils/pyi_generator.py +2 -2
- reflex/utils/redir.py +3 -12
- reflex/vars/base.py +26 -3
- reflex/vars/number.py +22 -21
- reflex/vars/object.py +29 -0
- reflex/vars/sequence.py +37 -0
- {reflex-0.7.2a2.dist-info → reflex-0.7.3.dist-info}/METADATA +52 -59
- {reflex-0.7.2a2.dist-info → reflex-0.7.3.dist-info}/RECORD +64 -64
- {reflex-0.7.2a2.dist-info → reflex-0.7.3.dist-info}/WHEEL +1 -1
- reflex-0.7.3.dist-info/entry_points.txt +2 -0
- reflex-0.7.2a2.dist-info/entry_points.txt +0 -3
- {reflex-0.7.2a2.dist-info → reflex-0.7.3.dist-info/licenses}/LICENSE +0 -0
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
{% extends "web/pages/base_page.js.jinja2" %}
|
|
2
2
|
{% from "web/pages/macros.js.jinja2" import renderHooks %}
|
|
3
|
-
{% block export %}
|
|
4
|
-
{% for component in components %}
|
|
5
3
|
|
|
6
|
-
{%
|
|
4
|
+
{% block declaration %}
|
|
5
|
+
{% for custom_code in custom_codes %}
|
|
7
6
|
{{custom_code}}
|
|
8
7
|
{% endfor %}
|
|
8
|
+
{% endblock %}
|
|
9
|
+
|
|
10
|
+
{% block export %}
|
|
11
|
+
{% for component in components %}
|
|
9
12
|
|
|
10
13
|
export const {{component.name}} = memo(({ {{-component.props|join(", ")-}} }) => {
|
|
11
14
|
{{ renderHooks(component.hooks) }}
|
|
@@ -11,7 +11,7 @@ export default function RadixThemesColorModeProvider({ children }) {
|
|
|
11
11
|
const { theme, resolvedTheme, setTheme } = useTheme();
|
|
12
12
|
const [rawColorMode, setRawColorMode] = useState(defaultColorMode);
|
|
13
13
|
const [resolvedColorMode, setResolvedColorMode] = useState(
|
|
14
|
-
defaultColorMode === "dark" ? "dark" : "light"
|
|
14
|
+
defaultColorMode === "dark" ? "dark" : "light",
|
|
15
15
|
);
|
|
16
16
|
|
|
17
17
|
useEffect(() => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { useEffect, useState } from "react"
|
|
2
|
-
import { codeToHtml} from "shiki"
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
import { codeToHtml } from "shiki";
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Code component that uses Shiki to convert code to HTML and render it.
|
|
@@ -12,23 +12,28 @@ import { codeToHtml} from "shiki"
|
|
|
12
12
|
* @param divProps - Additional properties to be passed to the div element.
|
|
13
13
|
* @returns The rendered code block.
|
|
14
14
|
*/
|
|
15
|
-
export function Code
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
15
|
+
export function Code({
|
|
16
|
+
code,
|
|
17
|
+
theme,
|
|
18
|
+
language,
|
|
19
|
+
transformers,
|
|
20
|
+
decorations,
|
|
21
|
+
...divProps
|
|
22
|
+
}) {
|
|
23
|
+
const [codeResult, setCodeResult] = useState("");
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
async function fetchCode() {
|
|
26
|
+
const result = await codeToHtml(code, {
|
|
27
|
+
lang: language,
|
|
28
|
+
theme,
|
|
29
|
+
transformers,
|
|
30
|
+
decorations,
|
|
31
|
+
});
|
|
32
|
+
setCodeResult(result);
|
|
33
|
+
}
|
|
34
|
+
fetchCode();
|
|
35
|
+
}, [code, language, theme, transformers, decorations]);
|
|
36
|
+
return (
|
|
37
|
+
<div dangerouslySetInnerHTML={{ __html: codeResult }} {...divProps}></div>
|
|
38
|
+
);
|
|
34
39
|
}
|
|
@@ -10,32 +10,34 @@ import { useRouter } from "next/router";
|
|
|
10
10
|
* @returns {boolean} routeNotFound - true if the current route is an actual 404
|
|
11
11
|
*/
|
|
12
12
|
export const useClientSideRouting = () => {
|
|
13
|
-
const [routeNotFound, setRouteNotFound] = useState(false)
|
|
14
|
-
const didRedirect = useRef(false)
|
|
15
|
-
const router = useRouter()
|
|
13
|
+
const [routeNotFound, setRouteNotFound] = useState(false);
|
|
14
|
+
const didRedirect = useRef(false);
|
|
15
|
+
const router = useRouter();
|
|
16
16
|
useEffect(() => {
|
|
17
17
|
if (
|
|
18
18
|
router.isReady &&
|
|
19
|
-
!didRedirect.current
|
|
19
|
+
!didRedirect.current // have not tried redirecting yet
|
|
20
20
|
) {
|
|
21
|
-
didRedirect.current = true
|
|
21
|
+
didRedirect.current = true; // never redirect twice to avoid "Hard Navigate" error
|
|
22
22
|
// attempt to redirect to the route in the browser address bar once
|
|
23
|
-
router
|
|
23
|
+
router
|
|
24
|
+
.replace({
|
|
24
25
|
pathname: window.location.pathname,
|
|
25
26
|
query: window.location.search.slice(1),
|
|
26
|
-
|
|
27
|
+
})
|
|
28
|
+
.then(() => {
|
|
27
29
|
// Check if the current route is /404
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
if (router.pathname === "/404") {
|
|
31
|
+
setRouteNotFound(true); // Mark as an actual 404
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
.catch((e) => {
|
|
35
|
+
setRouteNotFound(true); // navigation failed, so this is a real 404
|
|
36
|
+
});
|
|
35
37
|
}
|
|
36
38
|
}, [router.isReady]);
|
|
37
39
|
|
|
38
40
|
// Return the reactive bool, to avoid flashing 404 page until we know for sure
|
|
39
41
|
// the route is not found.
|
|
40
|
-
return routeNotFound
|
|
41
|
-
}
|
|
42
|
+
return routeNotFound;
|
|
43
|
+
};
|
|
@@ -48,7 +48,7 @@ export function formatCell(value, column) {
|
|
|
48
48
|
};
|
|
49
49
|
default:
|
|
50
50
|
console.log(
|
|
51
|
-
"Warning: column.type is undefined for column.title=" + column.title
|
|
51
|
+
"Warning: column.type is undefined for column.title=" + column.title,
|
|
52
52
|
);
|
|
53
53
|
return {
|
|
54
54
|
kind: GridCellKind.Text,
|
|
@@ -1,43 +1,43 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Simulate the python range() builtin function.
|
|
3
3
|
* inspired by https://dev.to/guyariely/using-python-range-in-javascript-337p
|
|
4
|
-
*
|
|
4
|
+
*
|
|
5
5
|
* If needed outside of an iterator context, use `Array.from(range(10))` or
|
|
6
6
|
* spread syntax `[...range(10)]` to get an array.
|
|
7
|
-
*
|
|
7
|
+
*
|
|
8
8
|
* @param {number} start: the start or end of the range.
|
|
9
9
|
* @param {number} stop: the end of the range.
|
|
10
10
|
* @param {number} step: the step of the range.
|
|
11
11
|
* @returns {object} an object with a Symbol.iterator method over the range
|
|
12
12
|
*/
|
|
13
13
|
export default function range(start, stop, step) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
return {
|
|
31
|
-
value: i,
|
|
32
|
-
done: false,
|
|
33
|
-
};
|
|
34
|
-
}
|
|
14
|
+
return {
|
|
15
|
+
[Symbol.iterator]() {
|
|
16
|
+
if (stop === undefined) {
|
|
17
|
+
stop = start;
|
|
18
|
+
start = 0;
|
|
19
|
+
}
|
|
20
|
+
if (step === undefined) {
|
|
21
|
+
step = 1;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
let i = start - step;
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
next() {
|
|
28
|
+
i += step;
|
|
29
|
+
if ((step > 0 && i < stop) || (step < 0 && i > stop)) {
|
|
35
30
|
return {
|
|
36
|
-
value:
|
|
37
|
-
done:
|
|
31
|
+
value: i,
|
|
32
|
+
done: false,
|
|
38
33
|
};
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
value: undefined,
|
|
37
|
+
done: true,
|
|
38
|
+
};
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -227,8 +227,8 @@ export const applyEvent = async (event, socket) => {
|
|
|
227
227
|
a.href = eval?.(
|
|
228
228
|
event.payload.url.replace(
|
|
229
229
|
"getBackendURL(env.UPLOAD)",
|
|
230
|
-
`"${getBackendURL(env.UPLOAD)}"
|
|
231
|
-
)
|
|
230
|
+
`"${getBackendURL(env.UPLOAD)}"`,
|
|
231
|
+
),
|
|
232
232
|
);
|
|
233
233
|
}
|
|
234
234
|
a.download = event.payload.filename;
|
|
@@ -341,7 +341,7 @@ export const applyRestEvent = async (event, socket) => {
|
|
|
341
341
|
event.payload.files,
|
|
342
342
|
event.payload.upload_id,
|
|
343
343
|
event.payload.on_upload_progress,
|
|
344
|
-
socket
|
|
344
|
+
socket,
|
|
345
345
|
);
|
|
346
346
|
return false;
|
|
347
347
|
}
|
|
@@ -352,8 +352,18 @@ export const applyRestEvent = async (event, socket) => {
|
|
|
352
352
|
* Queue events to be processed and trigger processing of queue.
|
|
353
353
|
* @param events Array of events to queue.
|
|
354
354
|
* @param socket The socket object to send the event on.
|
|
355
|
+
* @param prepend Whether to place the events at the beginning of the queue.
|
|
355
356
|
*/
|
|
356
|
-
export const queueEvents = async (events, socket) => {
|
|
357
|
+
export const queueEvents = async (events, socket, prepend) => {
|
|
358
|
+
if (prepend) {
|
|
359
|
+
// Drain the existing queue and place it after the given events.
|
|
360
|
+
events = [
|
|
361
|
+
...events,
|
|
362
|
+
...Array.from({ length: event_queue.length }).map(() =>
|
|
363
|
+
event_queue.shift(),
|
|
364
|
+
),
|
|
365
|
+
];
|
|
366
|
+
}
|
|
357
367
|
event_queue.push(...events);
|
|
358
368
|
await processEvent(socket.current);
|
|
359
369
|
};
|
|
@@ -408,7 +418,7 @@ export const connect = async (
|
|
|
408
418
|
dispatch,
|
|
409
419
|
transports,
|
|
410
420
|
setConnectErrors,
|
|
411
|
-
client_storage = {}
|
|
421
|
+
client_storage = {},
|
|
412
422
|
) => {
|
|
413
423
|
// Get backend URL object from the endpoint.
|
|
414
424
|
const endpoint = getBackendURL(EVENTURL);
|
|
@@ -441,6 +451,13 @@ export const connect = async (
|
|
|
441
451
|
}
|
|
442
452
|
}
|
|
443
453
|
|
|
454
|
+
const disconnectTrigger = (event) => {
|
|
455
|
+
if (socket.current?.connected) {
|
|
456
|
+
console.log("Disconnect websocket on unload");
|
|
457
|
+
socket.current.disconnect();
|
|
458
|
+
}
|
|
459
|
+
};
|
|
460
|
+
|
|
444
461
|
const pagehideHandler = (event) => {
|
|
445
462
|
if (event.persisted && socket.current?.connected) {
|
|
446
463
|
console.log("Disconnect backend before bfcache on navigation");
|
|
@@ -452,6 +469,8 @@ export const connect = async (
|
|
|
452
469
|
socket.current.on("connect", () => {
|
|
453
470
|
setConnectErrors([]);
|
|
454
471
|
window.addEventListener("pagehide", pagehideHandler);
|
|
472
|
+
window.addEventListener("beforeunload", disconnectTrigger);
|
|
473
|
+
window.addEventListener("unload", disconnectTrigger);
|
|
455
474
|
});
|
|
456
475
|
|
|
457
476
|
socket.current.on("connect_error", (error) => {
|
|
@@ -461,6 +480,8 @@ export const connect = async (
|
|
|
461
480
|
// When the socket disconnects reset the event_processing flag
|
|
462
481
|
socket.current.on("disconnect", () => {
|
|
463
482
|
event_processing = false;
|
|
483
|
+
window.removeEventListener("unload", disconnectTrigger);
|
|
484
|
+
window.removeEventListener("beforeunload", disconnectTrigger);
|
|
464
485
|
window.removeEventListener("pagehide", pagehideHandler);
|
|
465
486
|
});
|
|
466
487
|
|
|
@@ -477,7 +498,7 @@ export const connect = async (
|
|
|
477
498
|
});
|
|
478
499
|
socket.current.on("reload", async (event) => {
|
|
479
500
|
event_processing = false;
|
|
480
|
-
queueEvents([...initialEvents(), event], socket);
|
|
501
|
+
queueEvents([...initialEvents(), event], socket, true);
|
|
481
502
|
});
|
|
482
503
|
|
|
483
504
|
document.addEventListener("visibilitychange", checkVisibility);
|
|
@@ -499,7 +520,7 @@ export const uploadFiles = async (
|
|
|
499
520
|
files,
|
|
500
521
|
upload_id,
|
|
501
522
|
on_upload_progress,
|
|
502
|
-
socket
|
|
523
|
+
socket,
|
|
503
524
|
) => {
|
|
504
525
|
// return if there's no file to upload
|
|
505
526
|
if (files === undefined || files.length === 0) {
|
|
@@ -604,7 +625,7 @@ export const Event = (
|
|
|
604
625
|
name,
|
|
605
626
|
payload = {},
|
|
606
627
|
event_actions = {},
|
|
607
|
-
handler = null
|
|
628
|
+
handler = null,
|
|
608
629
|
) => {
|
|
609
630
|
return { name, payload, handler, event_actions };
|
|
610
631
|
};
|
|
@@ -631,7 +652,7 @@ export const hydrateClientStorage = (client_storage) => {
|
|
|
631
652
|
for (const state_key in client_storage.local_storage) {
|
|
632
653
|
const options = client_storage.local_storage[state_key];
|
|
633
654
|
const local_storage_value = localStorage.getItem(
|
|
634
|
-
options.name || state_key
|
|
655
|
+
options.name || state_key,
|
|
635
656
|
);
|
|
636
657
|
if (local_storage_value !== null) {
|
|
637
658
|
client_storage_values[state_key] = local_storage_value;
|
|
@@ -642,7 +663,7 @@ export const hydrateClientStorage = (client_storage) => {
|
|
|
642
663
|
for (const state_key in client_storage.session_storage) {
|
|
643
664
|
const session_options = client_storage.session_storage[state_key];
|
|
644
665
|
const session_storage_value = sessionStorage.getItem(
|
|
645
|
-
session_options.name || state_key
|
|
666
|
+
session_options.name || state_key,
|
|
646
667
|
);
|
|
647
668
|
if (session_storage_value != null) {
|
|
648
669
|
client_storage_values[state_key] = session_storage_value;
|
|
@@ -667,7 +688,7 @@ export const hydrateClientStorage = (client_storage) => {
|
|
|
667
688
|
const applyClientStorageDelta = (client_storage, delta) => {
|
|
668
689
|
// find the main state and check for is_hydrated
|
|
669
690
|
const unqualified_states = Object.keys(delta).filter(
|
|
670
|
-
(key) => key.split(".").length === 1
|
|
691
|
+
(key) => key.split(".").length === 1,
|
|
671
692
|
);
|
|
672
693
|
if (unqualified_states.length === 1) {
|
|
673
694
|
const main_state = delta[unqualified_states[0]];
|
|
@@ -701,7 +722,7 @@ const applyClientStorageDelta = (client_storage, delta) => {
|
|
|
701
722
|
const session_options = client_storage.session_storage[state_key];
|
|
702
723
|
sessionStorage.setItem(
|
|
703
724
|
session_options.name || state_key,
|
|
704
|
-
delta[substate][key]
|
|
725
|
+
delta[substate][key],
|
|
705
726
|
);
|
|
706
727
|
}
|
|
707
728
|
}
|
|
@@ -721,7 +742,7 @@ const applyClientStorageDelta = (client_storage, delta) => {
|
|
|
721
742
|
export const useEventLoop = (
|
|
722
743
|
dispatch,
|
|
723
744
|
initial_events = () => [],
|
|
724
|
-
client_storage = {}
|
|
745
|
+
client_storage = {},
|
|
725
746
|
) => {
|
|
726
747
|
const socket = useRef(null);
|
|
727
748
|
const router = useRouter();
|
|
@@ -735,7 +756,7 @@ export const useEventLoop = (
|
|
|
735
756
|
|
|
736
757
|
event_actions = events.reduce(
|
|
737
758
|
(acc, e) => ({ ...acc, ...e.event_actions }),
|
|
738
|
-
event_actions ?? {}
|
|
759
|
+
event_actions ?? {},
|
|
739
760
|
);
|
|
740
761
|
|
|
741
762
|
const _e = args.filter((o) => o?.preventDefault !== undefined)[0];
|
|
@@ -763,7 +784,7 @@ export const useEventLoop = (
|
|
|
763
784
|
debounce(
|
|
764
785
|
combined_name,
|
|
765
786
|
() => queueEvents(events, socket),
|
|
766
|
-
event_actions.debounce
|
|
787
|
+
event_actions.debounce,
|
|
767
788
|
);
|
|
768
789
|
} else {
|
|
769
790
|
queueEvents(events, socket);
|
|
@@ -773,16 +794,17 @@ export const useEventLoop = (
|
|
|
773
794
|
const sentHydrate = useRef(false); // Avoid double-hydrate due to React strict-mode
|
|
774
795
|
useEffect(() => {
|
|
775
796
|
if (router.isReady && !sentHydrate.current) {
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
events.map((e) => ({
|
|
797
|
+
queueEvents(
|
|
798
|
+
initial_events().map((e) => ({
|
|
779
799
|
...e,
|
|
780
800
|
router_data: (({ pathname, query, asPath }) => ({
|
|
781
801
|
pathname,
|
|
782
802
|
query,
|
|
783
803
|
asPath,
|
|
784
804
|
}))(router),
|
|
785
|
-
}))
|
|
805
|
+
})),
|
|
806
|
+
socket,
|
|
807
|
+
true,
|
|
786
808
|
);
|
|
787
809
|
sentHydrate.current = true;
|
|
788
810
|
}
|
|
@@ -828,7 +850,7 @@ export const useEventLoop = (
|
|
|
828
850
|
dispatch,
|
|
829
851
|
["websocket"],
|
|
830
852
|
setConnectErrors,
|
|
831
|
-
client_storage
|
|
853
|
+
client_storage,
|
|
832
854
|
);
|
|
833
855
|
}
|
|
834
856
|
}
|
|
@@ -876,7 +898,7 @@ export const useEventLoop = (
|
|
|
876
898
|
vars[storage_to_state_map[e.key]] = e.newValue;
|
|
877
899
|
const event = Event(
|
|
878
900
|
`${state_name}.reflex___state____update_vars_internal_state.update_vars_internal`,
|
|
879
|
-
{ vars: vars }
|
|
901
|
+
{ vars: vars },
|
|
880
902
|
);
|
|
881
903
|
addEvents([event], e);
|
|
882
904
|
}
|
|
@@ -969,7 +991,7 @@ export const getRefValues = (refs) => {
|
|
|
969
991
|
return refs.map((ref) =>
|
|
970
992
|
ref.current
|
|
971
993
|
? ref.current.value || ref.current.getAttribute("aria-valuenow")
|
|
972
|
-
: null
|
|
994
|
+
: null,
|
|
973
995
|
);
|
|
974
996
|
};
|
|
975
997
|
|
reflex/app_mixins/middleware.py
CHANGED
|
@@ -16,11 +16,11 @@ from .mixin import AppMixin
|
|
|
16
16
|
class MiddlewareMixin(AppMixin):
|
|
17
17
|
"""Middleware Mixin that allow to add middleware to the app."""
|
|
18
18
|
|
|
19
|
-
# Middleware to add to the app. Users should use `add_middleware`.
|
|
20
|
-
|
|
19
|
+
# Middleware to add to the app. Users should use `add_middleware`.
|
|
20
|
+
_middlewares: list[Middleware] = dataclasses.field(default_factory=list)
|
|
21
21
|
|
|
22
22
|
def _init_mixin(self):
|
|
23
|
-
self.
|
|
23
|
+
self._middlewares.append(HydrateMiddleware())
|
|
24
24
|
|
|
25
25
|
def add_middleware(self, middleware: Middleware, index: int | None = None):
|
|
26
26
|
"""Add middleware to the app.
|
|
@@ -30,9 +30,9 @@ class MiddlewareMixin(AppMixin):
|
|
|
30
30
|
index: The index to add the middleware at.
|
|
31
31
|
"""
|
|
32
32
|
if index is None:
|
|
33
|
-
self.
|
|
33
|
+
self._middlewares.append(middleware)
|
|
34
34
|
else:
|
|
35
|
-
self.
|
|
35
|
+
self._middlewares.insert(index, middleware)
|
|
36
36
|
|
|
37
37
|
async def _preprocess(self, state: BaseState, event: Event) -> StateUpdate | None:
|
|
38
38
|
"""Preprocess the event.
|
|
@@ -50,7 +50,7 @@ class MiddlewareMixin(AppMixin):
|
|
|
50
50
|
Returns:
|
|
51
51
|
An optional state to return.
|
|
52
52
|
"""
|
|
53
|
-
for middleware in self.
|
|
53
|
+
for middleware in self._middlewares:
|
|
54
54
|
if asyncio.iscoroutinefunction(middleware.preprocess):
|
|
55
55
|
out = await middleware.preprocess(app=self, state=state, event=event) # pyright: ignore [reportArgumentType]
|
|
56
56
|
else:
|
|
@@ -74,7 +74,8 @@ class MiddlewareMixin(AppMixin):
|
|
|
74
74
|
Returns:
|
|
75
75
|
The state update to return.
|
|
76
76
|
"""
|
|
77
|
-
|
|
77
|
+
out = update
|
|
78
|
+
for middleware in self._middlewares:
|
|
78
79
|
if asyncio.iscoroutinefunction(middleware.postprocess):
|
|
79
80
|
out = await middleware.postprocess(
|
|
80
81
|
app=self, # pyright: ignore [reportArgumentType]
|
|
@@ -89,6 +90,4 @@ class MiddlewareMixin(AppMixin):
|
|
|
89
90
|
event=event,
|
|
90
91
|
update=update,
|
|
91
92
|
)
|
|
92
|
-
|
|
93
|
-
return out # pyright: ignore [reportReturnType]
|
|
94
|
-
return update
|
|
93
|
+
return out # pyright: ignore[reportReturnType]
|
reflex/compiler/compiler.py
CHANGED
|
@@ -247,12 +247,19 @@ def _compile_components(
|
|
|
247
247
|
for comp_import in comp_render["dynamic_imports"]
|
|
248
248
|
}
|
|
249
249
|
|
|
250
|
+
custom_codes = {
|
|
251
|
+
comp_custom_code: None
|
|
252
|
+
for comp_render in component_renders
|
|
253
|
+
for comp_custom_code in comp_render.get("custom_code", [])
|
|
254
|
+
}
|
|
255
|
+
|
|
250
256
|
# Compile the components page.
|
|
251
257
|
return (
|
|
252
258
|
templates.COMPONENTS.render(
|
|
253
259
|
imports=utils.compile_imports(imports),
|
|
254
260
|
components=component_renders,
|
|
255
261
|
dynamic_imports=dynamic_imports,
|
|
262
|
+
custom_codes=custom_codes,
|
|
256
263
|
),
|
|
257
264
|
imports,
|
|
258
265
|
)
|
reflex/components/core/banner.py
CHANGED
|
@@ -382,7 +382,7 @@ class BackendDisabled(Div):
|
|
|
382
382
|
),
|
|
383
383
|
rx.hstack(
|
|
384
384
|
rx.el.svg(
|
|
385
|
-
rx.el.
|
|
385
|
+
rx.el.path(
|
|
386
386
|
d="M6.90816 1.34341C7.61776 1.10786 8.38256 1.10786 9.09216 1.34341C9.7989 1.57799 10.3538 2.13435 10.9112 2.91605C11.4668 3.69515 12.0807 4.78145 12.872 6.18175L12.9031 6.23672C13.6946 7.63721 14.3085 8.72348 14.6911 9.60441C15.0755 10.4896 15.267 11.2539 15.1142 11.9881C14.9604 12.7275 14.5811 13.3997 14.0287 13.9079C13.4776 14.4147 12.7273 14.6286 11.7826 14.7313C10.8432 14.8334 9.6143 14.8334 8.0327 14.8334H7.9677C6.38604 14.8334 5.15719 14.8334 4.21778 14.7313C3.27301 14.6286 2.52269 14.4147 1.97164 13.9079C1.41924 13.3997 1.03995 12.7275 0.88613 11.9881C0.733363 11.2539 0.92483 10.4896 1.30926 9.60441C1.69184 8.72348 2.30573 7.63721 3.09722 6.23671L3.12828 6.18175C3.91964 4.78146 4.53355 3.69515 5.08914 2.91605C5.64658 2.13435 6.20146 1.57799 6.90816 1.34341ZM7.3335 11.3334C7.3335 10.9652 7.63063 10.6667 7.99716 10.6667H8.00316C8.3697 10.6667 8.66683 10.9652 8.66683 11.3334C8.66683 11.7016 8.3697 12.0001 8.00316 12.0001H7.99716C7.63063 12.0001 7.3335 11.7016 7.3335 11.3334ZM7.3335 8.66675C7.3335 9.03495 7.63196 9.33341 8.00016 9.33341C8.36836 9.33341 8.66683 9.03495 8.66683 8.66675V6.00008C8.66683 5.63189 8.36836 5.33341 8.00016 5.33341C7.63196 5.33341 7.3335 5.63189 7.3335 6.00008V8.66675Z",
|
|
387
387
|
fill_rule="evenodd",
|
|
388
388
|
clip_rule="evenodd",
|
|
@@ -100,8 +100,9 @@ class Foreach(Component):
|
|
|
100
100
|
component.children = [component._render().render_component()]
|
|
101
101
|
except UntypedVarError as e:
|
|
102
102
|
raise UntypedVarError(
|
|
103
|
-
|
|
104
|
-
"
|
|
103
|
+
iterable,
|
|
104
|
+
"foreach",
|
|
105
|
+
"https://reflex.dev/docs/library/dynamic-rendering/foreach/",
|
|
105
106
|
) from e
|
|
106
107
|
return component
|
|
107
108
|
|
|
@@ -90,29 +90,51 @@ from .elements.inline import u as u
|
|
|
90
90
|
from .elements.inline import wbr as wbr
|
|
91
91
|
from .elements.media import Area as Area
|
|
92
92
|
from .elements.media import Audio as Audio
|
|
93
|
+
from .elements.media import Circle as Circle
|
|
94
|
+
from .elements.media import Defs as Defs
|
|
95
|
+
from .elements.media import Ellipse as Ellipse
|
|
93
96
|
from .elements.media import Embed as Embed
|
|
94
97
|
from .elements.media import Iframe as Iframe
|
|
95
98
|
from .elements.media import Img as Img
|
|
99
|
+
from .elements.media import Line as Line
|
|
100
|
+
from .elements.media import LinearGradient as LinearGradient
|
|
96
101
|
from .elements.media import Map as Map
|
|
97
102
|
from .elements.media import Object as Object
|
|
103
|
+
from .elements.media import Path as Path
|
|
98
104
|
from .elements.media import Picture as Picture
|
|
105
|
+
from .elements.media import Polygon as Polygon
|
|
99
106
|
from .elements.media import Portal as Portal
|
|
107
|
+
from .elements.media import RadialGradient as RadialGradient
|
|
108
|
+
from .elements.media import Rect as Rect
|
|
100
109
|
from .elements.media import Source as Source
|
|
110
|
+
from .elements.media import Stop as Stop
|
|
101
111
|
from .elements.media import Svg as Svg
|
|
112
|
+
from .elements.media import Text as Text
|
|
102
113
|
from .elements.media import Track as Track
|
|
103
114
|
from .elements.media import Video as Video
|
|
104
115
|
from .elements.media import area as area
|
|
105
116
|
from .elements.media import audio as audio
|
|
117
|
+
from .elements.media import circle as circle
|
|
118
|
+
from .elements.media import defs as defs
|
|
119
|
+
from .elements.media import ellipse as ellipse
|
|
106
120
|
from .elements.media import embed as embed
|
|
107
121
|
from .elements.media import iframe as iframe
|
|
108
122
|
from .elements.media import image as image
|
|
109
123
|
from .elements.media import img as img
|
|
124
|
+
from .elements.media import line as line
|
|
125
|
+
from .elements.media import linear_gradient as linear_gradient
|
|
110
126
|
from .elements.media import map as map
|
|
111
127
|
from .elements.media import object as object
|
|
128
|
+
from .elements.media import path as path
|
|
112
129
|
from .elements.media import picture as picture
|
|
130
|
+
from .elements.media import polygon as polygon
|
|
113
131
|
from .elements.media import portal as portal
|
|
132
|
+
from .elements.media import radial_gradient as radial_gradient
|
|
133
|
+
from .elements.media import rect as rect
|
|
114
134
|
from .elements.media import source as source
|
|
135
|
+
from .elements.media import stop as stop
|
|
115
136
|
from .elements.media import svg as svg
|
|
137
|
+
from .elements.media import text as text
|
|
116
138
|
from .elements.media import track as track
|
|
117
139
|
from .elements.media import video as video
|
|
118
140
|
from .elements.metadata import Base as Base
|
|
@@ -66,6 +66,17 @@ _MAPPING = {
|
|
|
66
66
|
"portal",
|
|
67
67
|
"source",
|
|
68
68
|
"svg",
|
|
69
|
+
"text",
|
|
70
|
+
"line",
|
|
71
|
+
"circle",
|
|
72
|
+
"ellipse",
|
|
73
|
+
"rect",
|
|
74
|
+
"polygon",
|
|
75
|
+
"path",
|
|
76
|
+
"stop",
|
|
77
|
+
"linear_gradient",
|
|
78
|
+
"radial_gradient",
|
|
79
|
+
"defs",
|
|
69
80
|
],
|
|
70
81
|
"metadata": [
|
|
71
82
|
"base",
|
|
@@ -128,7 +139,15 @@ _MAPPING = {
|
|
|
128
139
|
|
|
129
140
|
EXCLUDE = ["del_", "Del", "image"]
|
|
130
141
|
for v in _MAPPING.values():
|
|
131
|
-
|
|
142
|
+
from reflex.utils.format import to_camel_case
|
|
143
|
+
|
|
144
|
+
v.extend(
|
|
145
|
+
[
|
|
146
|
+
to_camel_case(mod)[0].upper() + to_camel_case(mod)[1:]
|
|
147
|
+
for mod in v
|
|
148
|
+
if mod not in EXCLUDE
|
|
149
|
+
]
|
|
150
|
+
)
|
|
132
151
|
|
|
133
152
|
_SUBMOD_ATTRS: dict[str, list[str]] = _MAPPING
|
|
134
153
|
|