import param import panel as pn js_files = { 'mdc': 'https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js' } css_files = [ 'https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css' ] pn.extension(js_files=js_files, css_files=css_files) from panel.viewable import Viewer class EditableRange(Viewer): value = param.Range(doc="A numeric range.") width = param.Integer(default=300) def __init__(self, **params): self._start_input = pn.widgets.FloatInput() self._end_input = pn.widgets.FloatInput(align='end') super().__init__(**params) self._layout = pn.Row(self._start_input, self._end_input) self._sync_widgets() def __panel__(self): return self._layout @param.depends('value', 'width', watch=True) def _sync_widgets(self): self._start_input.name = self.name self._start_input.value = self.value[0] self._end_input.value = self.value[1] self._start_input.width = self.width//2 self._end_input.width = self.width//2 @param.depends('_start_input.value', '_end_input.value', watch=True) def _sync_params(self): self.value = (self._start_input.value, self._end_input.value) range_widget = EditableRange(name='Range', value=(0, 10)) pn.Column( '## This is a custom widget', range_widget ) from panel.reactive import ReactiveHTML class Slideshow(ReactiveHTML): index = param.Integer(default=0) _template = '' def _img_click(self, event): self.index += 1 Slideshow(width=800, height=300) class JSSlideshow(ReactiveHTML): index = param.Integer(default=0) _template = """""" _scripts = {'click': 'data.index += 1'} JSSlideshow(width=800, height=300) class Select(ReactiveHTML): options = param.List(doc="Options to choose from.") value = param.String(doc="Current selected option") _template = """ """ _dom_events = {'select': ['change']} select = Select(options=['A', 'B', 'C']) select class Canvas(ReactiveHTML): color = param.Color(default='#000000') line_width = param.Number(default=1, bounds=(0.1, 10)) uri = param.String() _template = """ """ _scripts = { 'render': """ state.ctx = canvas.getContext("2d") """, 'start': """ state.start = event state.ctx.beginPath() state.ctx.moveTo(state.start.offsetX, state.start.offsetY) """, 'draw': """ if (state.start == null) return state.ctx.lineTo(event.offsetX, event.offsetY) state.ctx.stroke() """, 'end': """ delete state.start """, 'clear': """ state.ctx.clearRect(0, 0, canvas.width, canvas.height); """, 'save': """ data.uri = canvas.toDataURL(); """, 'line_width': """ state.ctx.lineWidth = data.line_width; """, 'color': """ state.ctx.strokeStyle = data.color; """ } canvas = Canvas(width=400, height=400) # We create a separate HTML element which syncs with the uri parameter of the Canvas png_view = pn.pane.HTML() canvas.jslink(png_view, code={'uri': "target.text = ``"}) pn.Column( '# Drag on canvas to draw\n To export the drawing to a png click save.', pn.Row( canvas.controls(['color', 'line_width']), canvas, png_view ) ) class MaterialTextField(ReactiveHTML): value = param.String(default='') _template = """ """ _dom_events = {'text-input': ['change']} _scripts = { 'render': "mdc.textField.MDCTextField.attachTo(text_field);" } __javascript__ = [ 'https://unpkg.com/material-components-web@latest/dist/material-components-web.min.js' ] __css__ = [ 'https://unpkg.com/material-components-web@latest/dist/material-components-web.min.css' ] text_field = MaterialTextField() text_field