Skip to content

Commit e40d05a

Browse files
added dash_excalidraw 🎨updated dash_swiper, small fixes on dash_pannellum and insta stories
1 parent b401348 commit e40d05a

13 files changed

+518
-12
lines changed
1.65 MB
Loading
349 KB
Loading
440 KB
Loading
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
---
2+
name: Dash Excalidraw
3+
description: Notebook, Freeform, Drawing type of component.
4+
endpoint: /pip/dash_excalidraw
5+
package: dash_excalidraw
6+
icon: simple-icons:libreofficedraw
7+
---
8+
9+
.. toc::
10+
11+
[Visit GitHub Repo](https://github.com/pip-install-python/dash_emoji_mart)
12+
13+
Features
14+
The Excalidraw editor (pip dash package) supports:
15+
16+
- 💯 Free & open-source.
17+
- 🎨 Infinite, canvas-based whiteboard.
18+
- ✍️ Hand-drawn like style.
19+
- 🌓 Dark mode.
20+
- 🏗️ Customizable.
21+
- 📷 Image support.
22+
- 😀 Shape libraries support.
23+
- 👅 Localization (i18n) support.
24+
- 🖼️ Export to PNG, SVG & clipboard.
25+
- 💾 Open format - export drawings as an .excalidraw json file.
26+
- ⚒️ Wide range of tools - rectangle, circle, diamond, arrow, line, free-draw, eraser...
27+
- ➡️ Arrow-binding & labeled arrows.
28+
- 🔙 Undo / Redo.
29+
- 🔍 Zoom and panning support.
30+
- 🚀 +Many more...
31+
32+
### Installation
33+
34+
```bash
35+
pip install dash-excalidraw
36+
```
37+
38+
### Introduction
39+
40+
.. exec::docs.dash_excalidraw.introduction
41+
42+
### Simple Example
43+
44+
.. exec::docs.dash_excalidraw.simple_example
45+
46+
### Options / Props
47+
48+
| Option | Default | Choices | Description |
49+
|------------------------|----------------------------------|-----------------------------------------------|-----------------------------------------------------------|
50+
| id | `none` | | The ID used to identify this component in Dash callbacks |
51+
| width | `'100%'` | | The width of the Excalidraw component |
52+
| height | `'400px'` | | The height of the Excalidraw component |
53+
| initialData | `{ elements: [], appState: {} }` | | Initial data to load into the Excalidraw component |
54+
| elements | `[]` | | The current elements in the Excalidraw scene |
55+
| appState | `{}` | | The current application state of Excalidraw |
56+
| files | `{}` | | Files associated with the Excalidraw scene |
57+
| serializedData | `''` | | Serialized data of the entire Excalidraw scene |
58+
| excalidrawAPI | `null` | | Callback to access the Excalidraw API |
59+
| isCollaborating | `true` | | Indicates if the component is in collaboration mode |
60+
| onPointerUpdate | `null` | | Callback triggered on pointer update |
61+
| onPointerDown | `null` | | Callback triggered on pointer down event |
62+
| onScrollChange | `null` | | Callback triggered on scroll change |
63+
| onPaste | `null` | | Callback triggered on paste event |
64+
| onLibraryChange | `null` | | Callback triggered when the library changes |
65+
| onLinkOpen | `null` | | Callback triggered when a link is opened |
66+
| langCode | `'en'` | | The language code for localization |
67+
| renderTopRightUI | `null` | | Function to render custom UI in the top right corner |
68+
| renderCustomStats | `null` | | Function to render custom stats |
69+
| viewModeEnabled | `false` | | Enables view-only mode |
70+
| zenModeEnabled | `false` | | Enables zen mode |
71+
| gridModeEnabled | `true` | | Enables grid mode |
72+
| libraryReturnUrl | `''` | | URL to return to after using the library |
73+
| theme | `'light'` | light, dark | The theme of the Excalidraw component |
74+
| name | `''` | | Name of the drawing |
75+
| UIOptions | `{}` | | UI options for customizing the Excalidraw interface |
76+
| detectScroll | `true` | | Determines whether to detect scroll events |
77+
| handleKeyboardGlobally | `false` | | Determines whether to handle keyboard events globally |
78+
| autoFocus | `true` | | Determines whether to auto-focus the Excalidraw component |
79+
| generateIdForFile | `null` | | Function to generate ID for files |
80+
| validateEmbeddable | `true` | boolean, string[], RegExp, RegExp[], function | Function or value to validate embeddable content |
81+
| renderEmbeddable | `null` | | Function to render embeddable content |

docs/dash_excalidraw/introduction.py

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import dash_excalidraw
2+
from dash import Dash, html, dcc, callback, Input, Output, State
3+
import json
4+
import dash_mantine_components as dmc
5+
from dash_ace import DashAceEditor
6+
7+
# _dash_renderer._set_react_version("18.2.0")
8+
9+
class CustomJSONDecoder(json.JSONDecoder):
10+
def decode(self, s):
11+
result = super().decode(s)
12+
return self._decode(result)
13+
14+
def _decode(self, o):
15+
if isinstance(o, bool):
16+
return o
17+
if isinstance(o, dict):
18+
return {k: self._decode(v) for k, v in o.items()}
19+
if isinstance(o, list):
20+
return [self._decode(v) for v in o]
21+
if o == "true":
22+
return True
23+
if o == "false":
24+
return False
25+
if o == "null":
26+
return None
27+
return o
28+
29+
30+
def custom_pprint(obj, indent=2):
31+
def format_value(v):
32+
if isinstance(v, (dict, list)):
33+
return custom_pprint(v, indent)
34+
elif v is True:
35+
return 'True'
36+
elif v is False:
37+
return 'False'
38+
elif v is None:
39+
return 'None'
40+
else:
41+
return repr(v)
42+
43+
if isinstance(obj, dict):
44+
items = [f"{' ' * indent}{repr(k)}: {format_value(v)}" for k, v in obj.items()]
45+
return "{\n" + ",\n".join(items) + "\n}"
46+
elif isinstance(obj, list):
47+
items = [f"{' ' * indent}{format_value(v)}" for v in obj]
48+
return "[\n" + ",\n".join(items) + "\n]"
49+
else:
50+
return repr(obj)
51+
52+
53+
initialCanvasData = {}
54+
55+
component = html.Div([
56+
dmc.Tabs(
57+
[
58+
dmc.TabsList(
59+
[
60+
dmc.TabsTab(
61+
"Dash Excalidraw",
62+
# leftSection=DashIconify(icon="tabler:message"),
63+
value="dashecalidraw-component",
64+
style={'font-size': '1.5rem', 'color': '#15b886'}
65+
),
66+
dmc.TabsTab(
67+
"DashExcalidraw .json Output",
68+
# leftSection=DashIconify(icon="tabler:settings"),
69+
value="canvas-output",
70+
style={'font-size': '1.5rem', 'color': '#15b886'}
71+
),
72+
]
73+
),
74+
dmc.TabsPanel(dash_excalidraw.DashExcalidraw(
75+
id='excalidraw',
76+
width='100%',
77+
height='80vh',
78+
initialData=initialCanvasData,
79+
# validateEmbeddable=False,
80+
# isCollaborating=False,
81+
), value="dashecalidraw-component"),
82+
dmc.TabsPanel(html.Div([
83+
html.Div(id='number-of-elements'),
84+
html.Div(id='output')
85+
]), value="canvas-output"),
86+
],
87+
value="dashecalidraw-component",
88+
),
89+
# dcc.Interval(id='interval', interval=1000)
90+
]
91+
)
92+
93+
94+
@callback(
95+
Output('output', 'children'),
96+
Output('number-of-elements', 'children'),
97+
Input('excalidraw', 'serializedData'),
98+
)
99+
def display_output(serializedData):
100+
if not serializedData:
101+
return 'No elements drawn yet'
102+
103+
# Parse the serialized data with custom decoder
104+
data = json.loads(serializedData, cls=CustomJSONDecoder)
105+
106+
# Count the number of elements
107+
num_elements = len(data.get('elements', []))
108+
109+
# Use custom pretty-print function
110+
output = custom_pprint(data, indent=2)
111+
112+
# Add a key to force re-rendering
113+
return DashAceEditor(
114+
id='dash-ace-editor',
115+
value=f'{output}',
116+
theme='monokai',
117+
mode='python',
118+
tabSize=2,
119+
enableBasicAutocompletion=True,
120+
enableLiveAutocompletion=True,
121+
autocompleter='/autocompleter?prefix=',
122+
placeholder='Python code ...',
123+
style={'height': '500px', 'width': '80vw'}
124+
), html.Label(f"Number of elements: {num_elements}")
125+
126+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from dash_excalidraw import DashExcalidraw
2+
from dash import Dash, html, dcc, callback, Input, Output, State
3+
4+
initialCanvasData = {}
5+
6+
component = html.Div([
7+
DashExcalidraw(
8+
id='excalidraw-simple',
9+
width='100%',
10+
height='80vh',
11+
initialData=initialCanvasData,
12+
)
13+
])

docs/dash_insta_stories/introduction.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,32 @@
44
# Define your stories
55
stories = [
66
{
7-
"url": "https://letsenhance.io/static/8f5e523ee6b2479e26ecc91b9c25261e/1015f/MainAfter.jpg",
7+
"url": "/assets/images/dash_insta_stories_0.png",
88
"type": "image",
99
"duration": 5000,
1010
"header": {
11-
"heading": "Colorize lizard",
11+
"heading": "",
1212
"subheading": "Cute isn't he?",
13-
"profileImage": "https://sea2.discourse-cdn.com/business7/user_avatar/community.plotly.com/pipinstallpython/288/27532_2.png"
13+
"profileImage": "https://avatars.githubusercontent.com/u/120129682?v=4"
1414
},
1515
# "seeMore": lambda: {"url": "https://example.com"},
1616
"styles": {"background": "#f5f5f5"},
1717
"preloadResource": True
1818
},
1919
{
20-
"url": "https://www.simplilearn.com/ice9/free_resources_article_thumb/what_is_image_Processing.jpg",
20+
"url": "/assets/images/dash_insta_stories_1.png",
2121
"header": {
22-
"heading": "Eyeseast",
22+
"heading": "Mobile view of a Django app I've built check out the blog posts",
2323
"subheading": "👀",
24-
"profileImage": "https://sea2.discourse-cdn.com/business7/user_avatar/community.plotly.com/pipinstallpython/288/27532_2.png"
24+
"profileImage": "https://avatars.githubusercontent.com/u/120129682?v=4"
2525
}
2626
},
2727
{
28-
"url": "https://www.adobe.com/products/media_14562ad96c12a2f3030725ae81bd3ede1c68cb783.jpeg?width=750&format=jpeg&optimize=medium",
28+
"url": "/assets/images/dash_insta_stories_2.png",
2929
"header": {
30-
"heading": "backster",
31-
"subheading": "puppies with sweaters",
32-
"profileImage": "https://sea2.discourse-cdn.com/business7/user_avatar/community.plotly.com/pipinstallpython/288/27532_2.png"
30+
"heading": "Buy something from me? 🤑",
31+
"subheading": "Mobile view of an e-commerce site I've built.",
32+
"profileImage": "https://avatars.githubusercontent.com/u/120129682?v=4"
3333
}
3434
}
3535
# Add more stories as needed

docs/dash_pannellum/dash_pannellum.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ Features
3131
- full screen mode
3232

3333
### Installation
34-
`pip install dash-pannellum`
34+
```bash
35+
pip install dash-pannellum
36+
```
3537

3638
### Usage Example
3739
Here's a simple example of how to use the DashPannellum component:

docs/dash_swiper/basic_carousel.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import dash_swiper
2+
from dash import *
3+
import dash_mantine_components as dmc
4+
5+
component = dmc.SimpleGrid(
6+
[
7+
dmc.Paper(
8+
html.Div(id="view-carousel-basic-output"),
9+
id="intro-wrapper-carousel-basic",
10+
style={"gridColumn": "1 / 4"},
11+
),
12+
dmc.Stack(
13+
[
14+
dmc.NumberInput(
15+
id="slides-per-view",
16+
label="Slides Per View",
17+
value=2,
18+
min=1,
19+
max=5,
20+
step=1,
21+
),
22+
dmc.NumberInput(
23+
id="side-slides",
24+
label="Side Slides",
25+
value=2,
26+
min=1,
27+
max=4,
28+
step=1,
29+
),
30+
dmc.Checkbox(
31+
id="carousel-navigation",
32+
label="Show Navigation",
33+
checked=True,
34+
),
35+
dmc.Checkbox(
36+
id="carousel-pagination",
37+
label="Show Pagination",
38+
checked=True,
39+
),
40+
dmc.Checkbox(
41+
id="carousel-autoplay",
42+
label="Enable Autoplay",
43+
checked=False,
44+
),
45+
],
46+
),
47+
],
48+
cols={"base": 1, "sm": 1, "lg": 4},
49+
spacing="2rem",
50+
)
51+
52+
53+
@callback(
54+
Output("view-carousel-basic-output", "children"),
55+
Input("slides-per-view", "value"),
56+
Input("side-slides", "value"),
57+
Input("carousel-navigation", "checked"),
58+
Input("carousel-pagination", "checked"),
59+
Input("carousel-autoplay", "checked"),
60+
)
61+
def update_carousel_basic(slides_per_view, side_slides, show_nav, show_pagination, enable_autoplay):
62+
carousel = dash_swiper.DashCarousel(
63+
id="basic-carousel-demo",
64+
className="custom-carousel",
65+
slides=[
66+
{
67+
"src": get_asset_url("images/01.jpg"),
68+
"alt": "Nature 1",
69+
"title": "Mountain Lake",
70+
"description": "Serene mountain lake at sunset.",
71+
},
72+
{
73+
"src": get_asset_url("images/02.jpg"),
74+
"alt": "Nature 2",
75+
"title": "Forest Path",
76+
"description": "A winding path through ancient trees.",
77+
},
78+
{
79+
"src": get_asset_url("images/03.jpg"),
80+
"alt": "Nature 3",
81+
"title": "Desert Dunes",
82+
"description": "Rolling sand dunes at dawn.",
83+
},
84+
{
85+
"src": get_asset_url("images/04.jpg"),
86+
"alt": "Nature 4",
87+
"title": "Ocean Waves",
88+
"description": "Powerful waves crash on rocky shores.",
89+
},
90+
{
91+
"src": get_asset_url("images/05.jpg"),
92+
"alt": "Nature 5",
93+
"title": "Alpine Meadow",
94+
"description": "Wildflowers bloom in mountain meadows.",
95+
},
96+
],
97+
carouselEffect={
98+
"opacityStep": 0.33,
99+
"scaleStep": 0.2,
100+
"sideSlides": side_slides,
101+
},
102+
autoplayEnabled=enable_autoplay,
103+
autoplay={
104+
"delay": 3000,
105+
"disableOnInteraction": True,
106+
},
107+
loop=True,
108+
grabCursor=True,
109+
navigation=show_nav,
110+
pagination=show_pagination,
111+
slidesPerView=slides_per_view,
112+
style={"width": "100%", "height": "300px"},
113+
)
114+
115+
return carousel

0 commit comments

Comments
 (0)