reflex-reactbits 0.1.1__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.
- reflex_reactbits/__init__.py +12 -0
- reflex_reactbits/animations.py +2128 -0
- reflex_reactbits/animations.pyi +2043 -0
- reflex_reactbits/backgrounds.py +3503 -0
- reflex_reactbits/backgrounds.pyi +3149 -0
- reflex_reactbits/base.py +97 -0
- reflex_reactbits/base.pyi +58 -0
- reflex_reactbits/catalog.json +26580 -0
- reflex_reactbits/catalog.py +23 -0
- reflex_reactbits/cli.py +125 -0
- reflex_reactbits/components.py +2383 -0
- reflex_reactbits/components.pyi +2430 -0
- reflex_reactbits/micro.py +2336 -0
- reflex_reactbits/micro.pyi +1858 -0
- reflex_reactbits/py.typed +0 -0
- reflex_reactbits/source.py +236 -0
- reflex_reactbits/text_animations.py +1629 -0
- reflex_reactbits/text_animations.pyi +1671 -0
- reflex_reactbits-0.1.1.dist-info/METADATA +223 -0
- reflex_reactbits-0.1.1.dist-info/RECORD +24 -0
- reflex_reactbits-0.1.1.dist-info/WHEEL +5 -0
- reflex_reactbits-0.1.1.dist-info/entry_points.txt +2 -0
- reflex_reactbits-0.1.1.dist-info/licenses/LICENSE +21 -0
- reflex_reactbits-0.1.1.dist-info/top_level.txt +1 -0
reflex_reactbits/base.py
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""Base class shared by every React Bits wrapper."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import Any, ClassVar
|
|
6
|
+
|
|
7
|
+
import reflex as rx
|
|
8
|
+
from reflex.components.component import NoSSRComponent
|
|
9
|
+
from reflex.vars.function import FunctionStringVar
|
|
10
|
+
|
|
11
|
+
from .source import ASSETS_SUBDIR, backend_only, ensure_component_source
|
|
12
|
+
|
|
13
|
+
SAFE_FN_NAME = "reactbitsSafe"
|
|
14
|
+
|
|
15
|
+
# Event payloads are sent to the backend as JSON. React Bits callbacks sometimes
|
|
16
|
+
# pass rich objects (items holding React elements, Errors, Files, DOM events),
|
|
17
|
+
# so every event argument goes through this sanitizer first.
|
|
18
|
+
SAFE_FN_CODE = """
|
|
19
|
+
const reactbitsSafe = (value, depth = 0, seen = new WeakSet()) => {
|
|
20
|
+
if (value === undefined || value === null) return null;
|
|
21
|
+
const kind = typeof value;
|
|
22
|
+
if (kind === "function" || kind === "symbol") return undefined;
|
|
23
|
+
if (kind === "bigint") return Number(value);
|
|
24
|
+
if (kind === "number") return Number.isFinite(value) ? value : null;
|
|
25
|
+
if (kind !== "object") return value;
|
|
26
|
+
if (value.$$typeof) return undefined;
|
|
27
|
+
if (value.nativeEvent) return { type: value.type };
|
|
28
|
+
if (typeof Event !== "undefined" && value instanceof Event) return { type: value.type };
|
|
29
|
+
if (typeof Node !== "undefined" && value instanceof Node) return undefined;
|
|
30
|
+
if (typeof File !== "undefined" && value instanceof File)
|
|
31
|
+
return { name: value.name, size: value.size, type: value.type, lastModified: value.lastModified };
|
|
32
|
+
if (value instanceof Error) return { name: value.name, message: value.message };
|
|
33
|
+
if (value instanceof Date) return value.toISOString();
|
|
34
|
+
if (depth > 8 || seen.has(value)) return undefined;
|
|
35
|
+
// seen tracks the current path, not every value already visited: an object
|
|
36
|
+
// reachable twice (the same option listed twice, two keys sharing a config)
|
|
37
|
+
// is not a cycle and must survive both times, so it is removed again below.
|
|
38
|
+
seen.add(value);
|
|
39
|
+
let out;
|
|
40
|
+
if (Array.isArray(value) || (typeof FileList !== "undefined" && value instanceof FileList)) {
|
|
41
|
+
out = Array.from(value, (item) => reactbitsSafe(item, depth + 1, seen) ?? null);
|
|
42
|
+
} else {
|
|
43
|
+
out = {};
|
|
44
|
+
for (const [key, item] of Object.entries(value)) {
|
|
45
|
+
const safe = reactbitsSafe(item, depth + 1, seen);
|
|
46
|
+
if (safe !== undefined) out[key] = safe;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
seen.delete(value);
|
|
50
|
+
return out;
|
|
51
|
+
};
|
|
52
|
+
"""
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def safe(value: rx.Var) -> rx.Var:
|
|
56
|
+
"""Wrap a JS event argument so it is always JSON serializable."""
|
|
57
|
+
return FunctionStringVar.create(SAFE_FN_NAME).call(value)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class ReactBitsComponent(NoSSRComponent):
|
|
61
|
+
"""A React Bits component whose source lives in the app's ``assets/reactbits``.
|
|
62
|
+
|
|
63
|
+
Subclasses declare the React Bits category/name and the files making up the
|
|
64
|
+
component. The source is copied into the app on first use (see
|
|
65
|
+
:mod:`reflex_reactbits.source`), and the component is imported client-side
|
|
66
|
+
only, since most React Bits components rely on ``window``, WebGL or canvas.
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
# React Bits category folder, e.g. "TextAnimations".
|
|
70
|
+
_rb_category: ClassVar[str] = ""
|
|
71
|
+
# React Bits component folder, e.g. "BlurText".
|
|
72
|
+
_rb_name: ClassVar[str] = ""
|
|
73
|
+
# Source files of the component (relative to its folder).
|
|
74
|
+
_rb_files: ClassVar[tuple[str, ...]] = ()
|
|
75
|
+
# Entry module (defaults to "<name>.jsx").
|
|
76
|
+
_rb_entry: ClassVar[str] = ""
|
|
77
|
+
|
|
78
|
+
def __init_subclass__(cls, **kwargs: Any):
|
|
79
|
+
"""Derive the local import path for the component module."""
|
|
80
|
+
if cls.__dict__.get("_rb_name"):
|
|
81
|
+
entry = cls.__dict__.get("_rb_entry") or f"{cls._rb_name}.jsx"
|
|
82
|
+
cls.library = f"$/public/{ASSETS_SUBDIR}/{cls._rb_category}/{cls._rb_name}/{entry}"
|
|
83
|
+
super().__init_subclass__(**kwargs)
|
|
84
|
+
|
|
85
|
+
@classmethod
|
|
86
|
+
def create(cls, *children: Any, **props: Any) -> rx.Component:
|
|
87
|
+
"""Copy the component source into the app (once) and create the component."""
|
|
88
|
+
# A backend-only process has no frontend to compile, so there is nothing
|
|
89
|
+
# to vendor. The guard lives here and not in ensure_component_source so
|
|
90
|
+
# that the ``reactbits add`` CLI still works in such an environment.
|
|
91
|
+
if cls._rb_name and not backend_only():
|
|
92
|
+
ensure_component_source(cls._rb_category, cls._rb_name, cls._rb_files)
|
|
93
|
+
return super().create(*children, **props)
|
|
94
|
+
|
|
95
|
+
def add_custom_code(self) -> list[str]:
|
|
96
|
+
"""Add the event payload sanitizer used by the event specs."""
|
|
97
|
+
return [SAFE_FN_CODE]
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""Stub file for reflex_reactbits/base.py"""
|
|
2
|
+
|
|
3
|
+
# ------------------- DO NOT EDIT ----------------------
|
|
4
|
+
# This file was generated by `reflex/utils/pyi_generator.py`!
|
|
5
|
+
# ------------------------------------------------------
|
|
6
|
+
from collections.abc import Mapping, Sequence
|
|
7
|
+
from typing import Any, Optional
|
|
8
|
+
from reflex_components_core.core.breakpoints import Breakpoints
|
|
9
|
+
from reflex_base.event import (
|
|
10
|
+
EventType,
|
|
11
|
+
PointerEventInfo,
|
|
12
|
+
)
|
|
13
|
+
from reflex_base.vars.base import Var
|
|
14
|
+
import reflex as rx
|
|
15
|
+
from reflex.components.component import NoSSRComponent
|
|
16
|
+
|
|
17
|
+
SAFE_FN_NAME = "reactbitsSafe"
|
|
18
|
+
SAFE_FN_CODE = '\nconst reactbitsSafe = (value, depth = 0, seen = new WeakSet()) => {\n if (value === undefined || value === null) return null;\n const kind = typeof value;\n if (kind === "function" || kind === "symbol") return undefined;\n if (kind === "bigint") return Number(value);\n if (kind === "number") return Number.isFinite(value) ? value : null;\n if (kind !== "object") return value;\n if (value.$$typeof) return undefined;\n if (value.nativeEvent) return { type: value.type };\n if (typeof Event !== "undefined" && value instanceof Event) return { type: value.type };\n if (typeof Node !== "undefined" && value instanceof Node) return undefined;\n if (typeof File !== "undefined" && value instanceof File)\n return { name: value.name, size: value.size, type: value.type, lastModified: value.lastModified };\n if (value instanceof Error) return { name: value.name, message: value.message };\n if (value instanceof Date) return value.toISOString();\n if (depth > 8 || seen.has(value)) return undefined;\n seen.add(value);\n if (Array.isArray(value) || (typeof FileList !== "undefined" && value instanceof FileList))\n return Array.from(value, (item) => reactbitsSafe(item, depth + 1, seen) ?? null);\n const out = {};\n for (const [key, item] of Object.entries(value)) {\n const safe = reactbitsSafe(item, depth + 1, seen);\n if (safe !== undefined) out[key] = safe;\n }\n return out;\n};\n'
|
|
19
|
+
|
|
20
|
+
def safe(value: rx.Var) -> rx.Var: ...
|
|
21
|
+
|
|
22
|
+
class ReactBitsComponent(NoSSRComponent):
|
|
23
|
+
@classmethod
|
|
24
|
+
def create(
|
|
25
|
+
cls,
|
|
26
|
+
*children,
|
|
27
|
+
style: Sequence[Mapping[str, Any]]
|
|
28
|
+
| Mapping[str, Any]
|
|
29
|
+
| Var[Mapping[str, Any]]
|
|
30
|
+
| Breakpoints
|
|
31
|
+
| None = None,
|
|
32
|
+
key: Any | None = None,
|
|
33
|
+
id: Any | None = None,
|
|
34
|
+
ref: Var | None = None,
|
|
35
|
+
class_name: Any | None = None,
|
|
36
|
+
custom_attrs: dict[str, Any | Var] | None = None,
|
|
37
|
+
on_blur: Optional[EventType[()]] = None,
|
|
38
|
+
on_click: Optional[EventType[()] | EventType[PointerEventInfo]] = None,
|
|
39
|
+
on_context_menu: Optional[EventType[()] | EventType[PointerEventInfo]] = None,
|
|
40
|
+
on_double_click: Optional[EventType[()] | EventType[PointerEventInfo]] = None,
|
|
41
|
+
on_focus: Optional[EventType[()]] = None,
|
|
42
|
+
on_mount: Optional[EventType[()]] = None,
|
|
43
|
+
on_mouse_down: Optional[EventType[()]] = None,
|
|
44
|
+
on_mouse_enter: Optional[EventType[()]] = None,
|
|
45
|
+
on_mouse_leave: Optional[EventType[()]] = None,
|
|
46
|
+
on_mouse_move: Optional[EventType[()]] = None,
|
|
47
|
+
on_mouse_out: Optional[EventType[()]] = None,
|
|
48
|
+
on_mouse_over: Optional[EventType[()]] = None,
|
|
49
|
+
on_mouse_up: Optional[EventType[()]] = None,
|
|
50
|
+
on_scroll: Optional[EventType[()]] = None,
|
|
51
|
+
on_scroll_end: Optional[EventType[()]] = None,
|
|
52
|
+
on_unmount: Optional[EventType[()]] = None,
|
|
53
|
+
**props,
|
|
54
|
+
) -> "ReactBitsComponent":
|
|
55
|
+
"""Copy the component source into the app (once) and create the component."""
|
|
56
|
+
...
|
|
57
|
+
|
|
58
|
+
def add_custom_code(self) -> list[str]: ...
|