# Excalidraw > Notebook, Freeform, Drawing type of component. --- .. toc:: .. llms_copy::Excalidraw Features The Excalidraw editor (pip dash package) supports: - 💯 Free & open-source. - 🎨 Infinite, canvas-based whiteboard. - ✍️ Hand-drawn like style. - 🌓 Dark mode. - 🏗️ Customizable. - 📷 Image support. - 😀 Shape libraries support. - 👅 Localization (i18n) support. - 🖼️ Export to PNG, SVG & clipboard. - 💾 Open format - export drawings as an .excalidraw json file. - ⚒️ Wide range of tools - rectangle, circle, diamond, arrow, line, free-draw, eraser... - ➡️ Arrow-binding & labeled arrows. - 🔙 Undo / Redo. - 🔍 Zoom and panning support. - 🚀 +Many more... ### Installation [Visit GitHub Repo](https://github.com/pip-install-python/dash_excalidraw) ```bash pip install dash-excalidraw ``` ### Introduction .. exec::docs.dash_excalidraw.introduction :code: false ```python # File: docs/dash_excalidraw/introduction.py import dash_excalidraw from dash import Dash, html, dcc, callback, Input, Output, State import json import dash_mantine_components as dmc from dash_ace import DashAceEditor # _dash_renderer._set_react_version("18.2.0") class CustomJSONDecoder(json.JSONDecoder): def decode(self, s): result = super().decode(s) return self._decode(result) def _decode(self, o): if isinstance(o, bool): return o if isinstance(o, dict): return {k: self._decode(v) for k, v in o.items()} if isinstance(o, list): return [self._decode(v) for v in o] if o == "true": return True if o == "false": return False if o == "null": return None return o def custom_pprint(obj, indent=2): def format_value(v): if isinstance(v, (dict, list)): return custom_pprint(v, indent) elif v is True: return 'True' elif v is False: return 'False' elif v is None: return 'None' else: return repr(v) if isinstance(obj, dict): items = [f"{' ' * indent}{repr(k)}: {format_value(v)}" for k, v in obj.items()] return "{\n" + ",\n".join(items) + "\n}" elif isinstance(obj, list): items = [f"{' ' * indent}{format_value(v)}" for v in obj] return "[\n" + ",\n".join(items) + "\n]" else: return repr(obj) initialCanvasData = {} component = html.Div([ dmc.Tabs( [ dmc.TabsList( [ dmc.TabsTab( "Dash Excalidraw", # leftSection=DashIconify(icon="tabler:message"), value="dashecalidraw-component", style={'font-size': '1.5rem', 'color': 'light-dark(rgb(28, 126, 214), rgb(116, 192, 252))'} ), dmc.TabsTab( "DashExcalidraw .json Output", # leftSection=DashIconify(icon="tabler:settings"), value="canvas-output", style={'font-size': '1.5rem', 'color': 'light-dark(rgb(28, 126, 214), rgb(116, 192, 252))'} ), ] ), dmc.TabsPanel(dash_excalidraw.DashExcalidraw( id='excalidraw', width='100%', height='65vh', initialData=initialCanvasData, # validateEmbeddable=False, # isCollaborating=False, ), value="dashecalidraw-component"), dmc.TabsPanel(html.Div([ html.Div(id='number-of-elements'), html.Div(id='output') ]), value="canvas-output"), ], value="dashecalidraw-component", ), # dcc.Interval(id='interval', interval=1000) ] ) @callback( Output('output', 'children'), Output('number-of-elements', 'children'), Input('excalidraw', 'serializedData'), ) def display_output(serializedData): if not serializedData: return 'No elements drawn yet', 'Number of elements: 0' # Parse the serialized data with custom decoder data = json.loads(serializedData, cls=CustomJSONDecoder) # Count the number of elements num_elements = len(data.get('elements', [])) # Use custom pretty-print function output = custom_pprint(data, indent=2) # Add a key to force re-rendering return DashAceEditor( id='dash-ace-editor', value=f'{output}', theme='monokai', mode='python', tabSize=2, enableBasicAutocompletion=True, enableLiveAutocompletion=True, autocompleter='/autocompleter?prefix=', placeholder='Python code ...', style={'height': '500px', 'width': '80vw'} ), html.Label(f"Number of elements: {num_elements}") ``` ### Simple Example #### Excalidraw Props | Option | Default | Choices | Description | |------------------------|----------------------------------|-----------------------------------------------|-----------------------------------------------------------| | id | `none` | | The ID used to identify this component in Dash callbacks | | width | `'100%'` | | The width of the Excalidraw component | | height | `'400px'` | | The height of the Excalidraw component | | initialData | `{ elements: [], appState: {} }` | | Initial data to load into the Excalidraw component | | elements | `[]` | | The current elements in the Excalidraw scene | | appState | `{}` | | The current application state of Excalidraw | | files | `{}` | | Files associated with the Excalidraw scene | | serializedData | `''` | | Serialized data of the entire Excalidraw scene | | excalidrawAPI | `null` | | Callback to access the Excalidraw API | | isCollaborating | `true` | | Indicates if the component is in collaboration mode | | onPointerUpdate | `null` | | Callback triggered on pointer update | | onPointerDown | `null` | | Callback triggered on pointer down event | | onScrollChange | `null` | | Callback triggered on scroll change | | onPaste | `null` | | Callback triggered on paste event | | onLibraryChange | `null` | | Callback triggered when the library changes | | onLinkOpen | `null` | | Callback triggered when a link is opened | | langCode | `'en'` | | The language code for localization | | renderTopRightUI | `null` | | Function to render custom UI in the top right corner | | renderCustomStats | `null` | | Function to render custom stats | | viewModeEnabled | `false` | | Enables view-only mode | | zenModeEnabled | `false` | | Enables zen mode | | gridModeEnabled | `true` | | Enables grid mode | | libraryReturnUrl | `''` | | URL to return to after using the library | | theme | `'light'` | light, dark | The theme of the Excalidraw component | | name | `''` | | Name of the drawing | | UIOptions | `{}` | | UI options for customizing the Excalidraw interface | | detectScroll | `true` | | Determines whether to detect scroll events | | handleKeyboardGlobally | `false` | | Determines whether to handle keyboard events globally | | autoFocus | `true` | | Determines whether to auto-focus the Excalidraw component | | generateIdForFile | `null` | | Function to generate ID for files | | validateEmbeddable | `true` | boolean, string[], RegExp, RegExp[], function | Function or value to validate embeddable content | | renderEmbeddable | `null` | | Function to render embeddable content | --- *Source: /pip/dash_excalidraw* *Generated with dash-improve-my-llms*