Skip to content

Commit

Permalink
Implement support for Design to wrap root
Browse files Browse the repository at this point in the history
  • Loading branch information
philippjfr committed Feb 15, 2023
1 parent 2e59771 commit d1317f2
Show file tree
Hide file tree
Showing 8 changed files with 104 additions and 54 deletions.
29 changes: 23 additions & 6 deletions panel/pane/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,20 @@ def _update(self, ref: str, model: Model) -> None:
"""
raise NotImplementedError

def _get_root_model(
self, doc: Optional[Document] = None, comm: Comm | None = None,
preprocess: bool = True
) -> Tuple[Viewable, Model]:
if self._updates:
root = self._get_model(doc, comm=comm)
root_view = self
else:
root = self.layout._get_model(doc, comm=comm)
root_view = self.layout
if preprocess:
self._preprocess(root)
return root_view, root

#----------------------------------------------------------------
# Public API
#----------------------------------------------------------------
Expand Down Expand Up @@ -326,14 +340,17 @@ def get_root(
Returns the bokeh model corresponding to this panel object
"""
doc = init_doc(doc)
if self._updates:
root = self._get_model(doc, comm=comm)
if self._design and comm:
wrapper = self._design._wrapper(self)
if wrapper is self:
root_view, root = self._get_root_model(doc, comm, preprocess)
else:
root_view = wrapper
root = wrapper.get_root(doc, comm, preprocess)
else:
root = self.layout._get_model(doc, comm=comm)
if preprocess:
self._preprocess(root)
root_view, root = self._get_root_model(doc, comm, preprocess)
ref = root.ref['id']
state._views[ref] = (self, root, doc, comm)
state._views[ref] = (root_view, root, doc, comm)
return root

@classmethod
Expand Down
29 changes: 1 addition & 28 deletions panel/param.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from param.parameterized import classlist, discard_events

from .config import config
from .io import init_doc, state
from .io import state
from .layout import (
Column, Panel, Row, Spacer, Tabs,
)
Expand Down Expand Up @@ -728,33 +728,6 @@ def select(self, selector=None):
"""
return super().select(selector) + self.layout.select(selector)

def get_root(
self, doc: Optional[Document] = None, comm: Optional[Comm] = None,
preprocess: bool = True
) -> Model:
"""
Returns the root model and applies pre-processing hooks
Arguments
---------
doc: bokeh.Document
Bokeh document the bokeh model will be attached to.
comm: pyviz_comms.Comm
Optional pyviz_comms when working in notebook
preprocess: boolean (default=True)
Whether to run preprocessing hooks
Returns
-------
Returns the bokeh model corresponding to this panel object
"""
doc = init_doc(doc)
root = self.layout.get_root(doc, comm, preprocess)
ref = root.ref['id']
self._models[ref] = (root, None)
state._views[ref] = (self, root, doc, comm)
return root


class ParamMethod(ReplacementPane):
"""
Expand Down
2 changes: 1 addition & 1 deletion panel/template/fast/fast.css
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ div.pn-wrapper {

#menu a[disabled=""] {
pointer-events: none;
color: var(--neutral-outline-rest)
color: var(--neutral-stroke-rest)
}

h1, h2, h3, h4, h5, h6 {
Expand Down
3 changes: 3 additions & 0 deletions panel/theme/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ def _apply_hooks(self, viewable: Viewable, root: Model) -> None:
with root.document.models.freeze():
self._reapply(viewable, root, isolated=False, cache=cache)

def _wrapper(self, viewable):
return viewable

@classmethod
def _resolve_stylesheets(cls, value, defining_cls, inherited):
new_value = []
Expand Down
26 changes: 13 additions & 13 deletions panel/theme/css/fast.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
/* Variables */

:host {
--track-width: 4;
--thumb-size: calc((var(--base-height-multiplier) + var(--density)) * var(--design-unit) * 0.5 - var(--design-unit));
Expand All @@ -13,6 +12,7 @@
--font-size: var(--type-ramp-base-font-size);
--switch-size: 12px;
--container-background: var(--panel-surface-color);
color: var(--neutral-foreground-rest);
}

/* Track */
Expand Down Expand Up @@ -262,8 +262,8 @@ table.panel-df {
/* Slider Widgets */

.noUi-target {
background: var(--neutral-outline-rest);
border-color: var(--neutral-outline-rest);
background: var(--neutral-stroke-rest);
border-color: var(--neutral-stroke-rest);
box-shadow: unset;
}

Expand Down Expand Up @@ -291,8 +291,8 @@ table.panel-df {
}

.bk-input:focus {
border: 2px solid var(--neutral-outline-active);
box-shadow: 0 0 0 2px var(--neutral-outline-active) inset;
border: 1px solid var(--neutral-stroke-active);
box-shadow: 0 0 0 1px var(--neutral-stroke-active) inset;
}

.bk-input[disabled], .bk-input[disabled]:hover {
Expand Down Expand Up @@ -396,23 +396,23 @@ input[type=file] {
background: transparent;
width: 100%;
height: 100px;
border: 3px dashed var(--neutral-outline-rest);
border: 3px dashed var(--neutral-stroke-rest);
border-radius: calc(var(--corner-radius) * 1px);
text-align: center;
margin: auto;
}

input[type=file][disabled]:hover {
cursor: not-allowed;
border-color: var(--neutral-outline-rest);
border-color: var(--neutral-stroke-rest);
}

input[type=file]:hover {
border-color: var(--neutral-outline-hover);
border-color: var(--neutral-stroke-hover);
}

input[type=file]:active {
border: 3px dashed var(--neutral-outline-active);
border: 3px dashed var(--neutral-stroke-active);
}

/* Buttons */
Expand Down Expand Up @@ -476,7 +476,7 @@ input[type=file]:active {
-moz-appearance: none;
-o-appearance: none;
appearance: none;
border: calc(var(--outline-width) * 1px) solid var(--neutral-outline-rest);
border: calc(var(--stroke-width) * 1px) solid var(--neutral-stroke-rest);
outline: none;
background-color: var(--neutral-fill-input-rest);
cursor: pointer;
Expand All @@ -489,7 +489,7 @@ input[type=file]:active {

.bk-input-group input[type="checkbox"]:hover, .bk-input-group input[type="radio"]:hover {
background: var(--neutral-fill-input-hover);
border-color: var(--neutral-outline-hover);
border-color: var(--neutral-stroke-hover);
}

.bk-input-group input[type="checkbox"]:active, .bk-input-group input[type="radio"]:active {
Expand Down Expand Up @@ -566,15 +566,15 @@ input[type=file]:active {

.body > .bar {
background: var(--neutral-fill-input-rest);
border: 1px solid var(--neutral-outline-rest);
border: 1px solid var(--neutral-stroke-rest);
border-radius: calc(var(--control-corner-radius) * 1px);
height: calc(((var(--base-height-multiplier) + var(--density)) * var(--design-unit) / 2 + var(--design-unit)) * 1px);
top: 0;
width: calc((var(--base-height-multiplier) + var(--density)) * var(--design-unit) * 1px);
}

.body > .bar:hover {
border-color: var(--neutral-outline-hover);
border-color: var(--neutral-stroke-hover);
}

:host(.active) .bar {
Expand Down
37 changes: 37 additions & 0 deletions panel/theme/fast.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from bokeh.themes import Theme as _BkTheme

from ..config import config
from ..reactive import ReactiveHTML
from ..viewable import Viewable
from ..widgets import Number, Tabulator
from .base import (
Expand Down Expand Up @@ -120,6 +121,39 @@ def create_bokeh_theme(self):
}


class FastWrapper(ReactiveHTML):

object = param.ClassSelector(class_=Viewable)

style = param.ClassSelector(class_=FastStyle)

_template = '<div id="fast-wrapper" class="fast-wrapper">${object}</div>'

_scripts = {
'render': """
let accent, bg, luminance
if (window._JUPYTERLAB) {
accent = getComputedStyle(view.el).getPropertyValue('--jp-brand-color0').trim();
bg = getComputedStyle(view.el).getPropertyValue('--jp-layout-color0').trim();
let color = getComputedStyle(view.el).getPropertyValue('--jp-ui-font-color0').trim();
luminance = color == 'rgba(255, 255, 255, 1)' ? 0.23 : 1.0;
} else {
accent = data.style.accent_base_color;
bg = data.style.background_color;
luminance = data.style.luminance;
}
bg = bg === 'white' ? '#ffffff' : bg;
bg = bg === 'black' ? '#000000' : bg;
state.design = design = new window.fastDesignProvider(view.el)
design.setLuminance(luminance);
design.setNeutralColor(data.style.neutral_color);
design.setAccentColor(accent);
design.setBackgroundColor(bg);
design.setCornerRadius(data.style.corner_radius);
"""
}


DEFAULT_STYLE = FastStyle()

DARK_STYLE = FastStyle(
Expand Down Expand Up @@ -193,3 +227,6 @@ class Fast(Design):
'default': FastDefaultTheme,
'dark': FastDarkTheme
}

def _wrapper(self, model):
return FastWrapper(design=None, object=model, style=self.theme.style)
10 changes: 9 additions & 1 deletion panel/theme/js/fast_design.js
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,11 @@ function parseColorHexRGB(raw) {

class FastDesignProvider {
constructor(selector) {
this.provider = document.querySelector(selector);
if (typeof selector === 'string') {
this.provider = document.querySelector(selector);
} else {
this.provider = selector;
}
provideFASTDesignSystem(this.provider)
}

Expand All @@ -74,6 +78,10 @@ class FastDesignProvider {
setLuminance(value) {
baseLayerLuminance.withDefault(value);
}

setCornerRadius(value) {
this.provider.style.setProperty("--corner-radius", value);
}
}

window.fastDesignProvider = FastDesignProvider
22 changes: 17 additions & 5 deletions panel/viewable.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,9 @@ def __init__(self, **params):

@param.depends('design', watch=True, on_init=True)
def _update_design(self):
from .theme import Design
if self.design:
self._design = self.design(theme=config.theme)
self._design = self.design if isinstance(self.design, Design) else self.design(theme=config.theme)
else:
self._design = None

Expand Down Expand Up @@ -577,11 +578,22 @@ def get_root(
Returns the bokeh model corresponding to this panel object
"""
doc = init_doc(doc)
root = self._get_model(doc, comm=comm)
if preprocess:
self._preprocess(root)
if self._design and comm:
wrapper = self._design._wrapper(self)
if wrapper is self:
root = self._get_model(doc, comm=comm)
if preprocess:
self._preprocess(root)
else:
root = wrapper.get_root(doc, comm, preprocess)
root_view = wrapper
else:
root = self._get_model(doc, comm=comm)
root_view = self
if preprocess:
self._preprocess(root)
ref = root.ref['id']
state._views[ref] = (self, root, doc, comm)
state._views[ref] = (root_view, root, doc, comm)
return root


Expand Down

0 comments on commit d1317f2

Please sign in to comment.