From b4e4be8138aadfd8339c7e6ab1bd2ca45179dc2a Mon Sep 17 00:00:00 2001 From: Philipp Rudiger Date: Fri, 3 Jan 2025 16:19:30 +0100 Subject: [PATCH] Implement theming --- src/panel_material_ui/base.py | 57 +++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/src/panel_material_ui/base.py b/src/panel_material_ui/base.py index 31b57e4..8ca7204 100644 --- a/src/panel_material_ui/base.py +++ b/src/panel_material_ui/base.py @@ -1,22 +1,75 @@ from __future__ import annotations +import inspect +import pathlib + import param from panel.config import config from panel.custom import ReactComponent +from panel.util import classproperty COLORS = ["primary", "secondary", "error", "info", "success", "warning"] +THEME_WRAPPER = """ +import {{ ThemeProvider, createTheme }} from '@mui/material/styles'; +import CssBaseline from '@mui/material/CssBaseline'; + +{esm} + +function themed_render(props) {{ + const [defaultTheme] = props.model.useState('theme') + + const theme = createTheme({{ + colorSchemes: {{ + dark: defaultTheme === "dark", + }}, + }}); + + return ( + + + + + ) +}} + +export default {{ render: themed_render }} +""" + + class MaterialComponent(ReactComponent): - theme = param.Selector(default=config.theme, objects=["default", "dark"]) + + theme = param.Selector(default="default", objects=["default", "dark"]) _importmap = { "imports": { "@mui/material/": "https://esm.sh/@mui/material@6.1.7/", - "@mui/icons-material/": "https://esm.sh/@mui/icons-material@6.1.6/", + "@mui/icons-material/": "https://esm.sh/@mui/icons-material@6.1.7/", } } + _esm_base = None + # _bundle = "panel-material-ui.bundle.js" + def __init__(self, **params): + if 'theme' not in params: + params['theme'] = config.theme + super().__init__(**params) + + @classproperty + def _esm(cls): + if cls._esm_base is None: + return None + esm_base = pathlib.Path(inspect.getfile(cls)).parent / cls._esm_base + component = cls.__name__ + esm = ( + esm_base + .read_text() + .replace('export function render(', f'export function Panel{component}(') + .replace('const render =', f'const Panel{component} =') + ) + return THEME_WRAPPER.format(esm=esm, component=component) + __abstract = True