Skip to content

Commit

Permalink
provide plotly subpackages
Browse files Browse the repository at this point in the history
  • Loading branch information
adhami3310 committed Feb 7, 2025
1 parent 70920a6 commit 0d5555c
Show file tree
Hide file tree
Showing 5 changed files with 1,054 additions and 14 deletions.
34 changes: 22 additions & 12 deletions reflex/compiler/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,24 +119,34 @@ def compile_imports(import_dict: ParsedImportDict) -> list[dict]:
validate_imports(collapsed_import_dict)
import_dicts = []
for lib, fields in collapsed_import_dict.items():
default, rest = compile_import_statement(fields)

# prevent lib from being rendered on the page if all imports are non rendered kind
if not any(f.render for f in fields):
continue

if not lib:
if default:
raise ValueError("No default field allowed for empty library.")
if rest is None or len(rest) == 0:
raise ValueError("No fields to import.")
import_dicts.extend(get_import_dict(module) for module in sorted(rest))
continue
lib_paths: dict[str, list[ImportVar]] = {}

for field in fields:
lib_paths.setdefault(field.package_path, []).append(field)

# remove the version before rendering the package imports
lib = format.format_library_name(lib)
compiled = {
path: compile_import_statement(fields) for path, fields in lib_paths.items()
}

for path, (default, rest) in compiled.items():
if not lib:
if default:
raise ValueError("No default field allowed for empty library.")
if rest is None or len(rest) == 0:
raise ValueError("No fields to import.")
import_dicts.extend(get_import_dict(module) for module in sorted(rest))
continue

# remove the version before rendering the package imports
formatted_lib = format.format_library_name(lib) + (
path if path != "/" else ""
)

import_dicts.append(get_import_dict(lib, default, rest))
import_dicts.append(get_import_dict(formatted_lib, default, rest))
return import_dicts


Expand Down
31 changes: 29 additions & 2 deletions reflex/components/plotly/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,32 @@
"""Plotly components."""

from .plotly import Plotly
from reflex.components.component import ComponentNamespace

plotly = Plotly.create
from .plotly import (
Plotly,
PlotlyBasic,
PlotlyCartesian,
PlotlyFinance,
PlotlyGeo,
PlotlyGl2d,
PlotlyGl3d,
PlotlyMapbox,
PlotlyStrict,
)


class PlotlyNamespace(ComponentNamespace):
"""Plotly namespace."""

__call__ = Plotly.create
basic = PlotlyBasic.create
cartesian = PlotlyCartesian.create
geo = PlotlyGeo.create
gl2d = PlotlyGl2d.create
gl3d = PlotlyGl3d.create
finance = PlotlyFinance.create
mapbox = PlotlyMapbox.create
strict = PlotlyStrict.create


plotly = PlotlyNamespace()
235 changes: 235 additions & 0 deletions reflex/components/plotly/plotly.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
from reflex.components.core.cond import color_mode_cond
from reflex.event import EventHandler, no_args_event_spec
from reflex.utils import console
from reflex.utils.imports import ImportDict, ImportVar
from reflex.vars.base import LiteralVar, Var

try:
Expand Down Expand Up @@ -278,3 +279,237 @@ def _render(self):
# Spread the figure dict over props, nothing to merge.
tag.special_props.append(Var(_js_expr=f"{{...{figure!s}}}"))
return tag


CREATE_PLOTLY_COMPONENT: ImportDict = {
"react-plotly.js": [
ImportVar(
tag="createPlotlyComponent",
is_default=True,
package_path="/factory",
),
]
}


def dynamic_plotly_import(name: str, package: str) -> str:
"""Create a dynamic import for a plotly component.
Args:
name: The name of the component.
package: The package path of the component.
Returns:
The dynamic import for the plotly component.
"""
return f"""
const {name} = dynamic(() => import('{package}').then(mod => createPlotlyComponent(mod)), {{ssr: false}})
"""


class PlotlyBasic(Plotly):
"""Display a basic plotly graph."""

tag: str = "BasicPlotlyPlot"

library = "[email protected]"

lib_dependencies: list[str] = ["[email protected]"]

def add_imports(self) -> ImportDict | list[ImportDict]:
"""Add imports for the plotly basic component.
Returns:
The imports for the plotly basic component.
"""
return CREATE_PLOTLY_COMPONENT

def _get_dynamic_imports(self) -> str:
"""Get the dynamic imports for the plotly basic component.
Returns:
The dynamic imports for the plotly basic component.
"""
return dynamic_plotly_import(self.tag, "plotly.js-basic-dist-min")


class PlotlyCartesian(Plotly):
"""Display a plotly cartesian graph."""

tag: str = "CartesianPlotlyPlot"

library = "[email protected]"

lib_dependencies: list[str] = ["[email protected]"]

def add_imports(self) -> ImportDict | list[ImportDict]:
"""Add imports for the plotly cartesian component.
Returns:
The imports for the plotly cartesian component.
"""
return CREATE_PLOTLY_COMPONENT

def _get_dynamic_imports(self) -> str:
"""Get the dynamic imports for the plotly cartesian component.
Returns:
The dynamic imports for the plotly cartesian component.
"""
return dynamic_plotly_import(self.tag, "plotly.js-cartesian-dist-min")


class PlotlyGeo(Plotly):
"""Display a plotly geo graph."""

tag: str = "GeoPlotlyPlot"

library = "[email protected]"

lib_dependencies: list[str] = ["[email protected]"]

def add_imports(self) -> ImportDict | list[ImportDict]:
"""Add imports for the plotly geo component.
Returns:
The imports for the plotly geo component.
"""
return CREATE_PLOTLY_COMPONENT

def _get_dynamic_imports(self) -> str:
"""Get the dynamic imports for the plotly geo component.
Returns:
The dynamic imports for the plotly geo component.
"""
return dynamic_plotly_import(self.tag, "plotly.js-geo-dist-min")


class PlotlyGl3d(Plotly):
"""Display a plotly 3d graph."""

tag: str = "Gl3dPlotlyPlot"

library = "[email protected]"

lib_dependencies: list[str] = ["[email protected]"]

def add_imports(self) -> ImportDict | list[ImportDict]:
"""Add imports for the plotly 3d component.
Returns:
The imports for the plotly 3d component.
"""
return CREATE_PLOTLY_COMPONENT

def _get_dynamic_imports(self) -> str:
"""Get the dynamic imports for the plotly 3d component.
Returns:
The dynamic imports for the plotly 3d component.
"""
return dynamic_plotly_import(self.tag, "plotly.js-gl3d-dist-min")


class PlotlyGl2d(Plotly):
"""Display a plotly 2d graph."""

tag: str = "Gl2dPlotlyPlot"

library = "[email protected]"

lib_dependencies: list[str] = ["[email protected]"]

def add_imports(self) -> ImportDict | list[ImportDict]:
"""Add imports for the plotly 2d component.
Returns:
The imports for the plotly 2d component.
"""
return CREATE_PLOTLY_COMPONENT

def _get_dynamic_imports(self) -> str:
"""Get the dynamic imports for the plotly 2d component.
Returns:
The dynamic imports for the plotly 2d component.
"""
return dynamic_plotly_import(self.tag, "plotly.js-gl2d-dist-min")


class PlotlyMapbox(Plotly):
"""Display a plotly mapbox graph."""

tag: str = "MapboxPlotlyPlot"

library = "[email protected]"

lib_dependencies: list[str] = ["[email protected]"]

def add_imports(self) -> ImportDict | list[ImportDict]:
"""Add imports for the plotly mapbox component.
Returns:
The imports for the plotly mapbox component.
"""
return CREATE_PLOTLY_COMPONENT

def _get_dynamic_imports(self) -> str:
"""Get the dynamic imports for the plotly mapbox component.
Returns:
The dynamic imports for the plotly mapbox component.
"""
return dynamic_plotly_import(self.tag, "plotly.js-mapbox-dist-min")


class PlotlyFinance(Plotly):
"""Display a plotly finance graph."""

tag: str = "FinancePlotlyPlot"

library = "[email protected]"

lib_dependencies: list[str] = ["[email protected]"]

def add_imports(self) -> ImportDict | list[ImportDict]:
"""Add imports for the plotly finance component.
Returns:
The imports for the plotly finance component.
"""
return CREATE_PLOTLY_COMPONENT

def _get_dynamic_imports(self) -> str:
"""Get the dynamic imports for the plotly finance component.
Returns:
The dynamic imports for the plotly finance component.
"""
return dynamic_plotly_import(self.tag, "plotly.js-finance-dist-min")


class PlotlyStrict(Plotly):
"""Display a plotly strict graph."""

tag: str = "StrictPlotlyPlot"

library = "[email protected]"

lib_dependencies: list[str] = ["[email protected]"]

def add_imports(self) -> ImportDict | list[ImportDict]:
"""Add imports for the plotly strict component.
Returns:
The imports for the plotly strict component.
"""
return CREATE_PLOTLY_COMPONENT

def _get_dynamic_imports(self) -> str:
"""Get the dynamic imports for the plotly strict component.
Returns:
The dynamic imports for the plotly strict component.
"""
return dynamic_plotly_import(self.tag, "plotly.js-strict-dist-min")
Loading

0 comments on commit 0d5555c

Please sign in to comment.