diff --git a/docs/manuals/gui/extension.md b/docs/manuals/gui/extension.md
index 55e6576f0..39eb070eb 100644
--- a/docs/manuals/gui/extension.md
+++ b/docs/manuals/gui/extension.md
@@ -9,30 +9,30 @@ cases or integrate third-party Web components. One can expand the functionality
offered by the base Taipy GUI package to create custom components that can be
effortlessly used in pages and shared with the community.
-Custom visual elements are grouped into *Element Libraries*, where each element is identified
+Custom visual elements are grouped into _Element Libraries_, where each element is identified
by its name. An element name must be unique in the context of its library.
Each library also as a name. To insert a custom visual element in a page, you will use
the full name of the element:
-- `.` in a Markdown page
-- `:` in an HTML page
+- `.` in a Markdown page
+- `:` in an HTML page
## Element Libraries and Custom Elements
-An Element Library holds the information necessary to refer to and instantiate custom visual elements. Element libraries can hold several visual element descriptors, and can be packaged
+An Element Library holds the information necessary to refer to and instantiate custom visual elements. Element libraries can hold several visual element descriptors, and can be packaged
into a standalone Python package that a Taipy GUI application can import or that can be
deployed.
Here are important things you need to know about element libraries:
-- An element library is a Python object that derives from the `ElementLibrary^` class.
-- Element libraries have a name (returned by `ElementLibrary.get_name()^`) that is
- used to refer to visual elements in page definitions.
-- Element libraries hold the set of the elements it holds, as returned by
- `ElementLibrary.get_elements()^`.
+- An element library is a Python object that derives from the `ElementLibrary^` class.
+- Element libraries have a name (returned by `ElementLibrary.get_name()^`) that is
+ used to refer to visual elements in page definitions.
+- Element libraries hold the set of the elements it holds, as returned by
+ `ElementLibrary.get_elements()^`.
You can create an element library by simply instantiating the `ElementLibrary^`, and override the methods that are required. The two mandatory methods to override are
-`(ElementLibrary.)get_name()^` and `(ElementLibrary.)get_elements()^`:
+`(ElementLibrary.)get_name()^` and `(ElementLibrary.)get_elements()^`:
```py
from taipy.gui.extension import ElementLibrary
@@ -55,7 +55,7 @@ Other methods can be overridden if necessary, which will be discussed later in t
As we have seen, custom visual element descriptors are associated with the name of
the element as it appears in pages, in the `(ElementLibrary.)get_elements()^` method.
-The [`Element` constructor](Element.__init__()^) needs a description of all the properties
+The [`Element` constructor]() needs a description of all the properties
that this element holds, as well as how this element is rendered.
```py
@@ -76,8 +76,8 @@ All elements must indicate what is its default property name. That is used in Ma
page as the first fragment of the `<|...|>` construct, or the value located in the
text part of an element tag in HTML pages.
-Of course *default_property_name* must be one of the keys of the properties dictionary
-provided to the [`Element` constructor](Element.__init__()^).
+Of course _default_property_name_ must be one of the keys of the properties dictionary
+provided to the [`Element` constructor]().
## Rendering Elements
@@ -85,33 +85,33 @@ The Taipy GUI Extension package provides two different ways to implement the ren
of the element and its interactions. Both approaches deliver HTML fragments that are
inserted in the page when it is requested.
-- Static elements.
- A static visual element is one that cannot interact with the underlying application.
- It can be used just like any other element in a page, but its properties are not
- bound to the application variable: if the variable value is modified, it does not
- modify the representation of the element on the page.
- Static elements are implemented by creating a string that holds the XHTML text (that is,
- HTML that respects the XML syntax, where all tags must be closed) that is inserted in
- the page displayed by the browser.
- Please go to the [Static Elements Example](extension_static_element.md) page for
- a complete description of how to implement your own static custom elements.
-
-- Dynamic elements.
- Dynamic elements provide the binding functionality of Taipy GUI: if a property value
- depends on an application variable (and if the property type is *dynamic*) then the
- page automatically updates when the variable value changes.
- In Taipy GUI, dynamic visual element are implemented using the
- [React](https://reactjs.org/) JavaScript library, and the
- [TypeScript](https://www.typescriptlang.org/) programming language (that builds on
- JavaScript).
+- Static elements.
+ A static visual element is one that cannot interact with the underlying application.
+ It can be used just like any other element in a page, but its properties are not
+ bound to the application variable: if the variable value is modified, it does not
+ modify the representation of the element on the page.
+ Static elements are implemented by creating a string that holds the XHTML text (that is,
+ HTML that respects the XML syntax, where all tags must be closed) that is inserted in
+ the page displayed by the browser.
+ Please go to the [Static Elements Example](extension_static_element.md) page for
+ a complete description of how to implement your own static custom elements.
+
+- Dynamic elements.
+ Dynamic elements provide the binding functionality of Taipy GUI: if a property value
+ depends on an application variable (and if the property type is _dynamic_) then the
+ page automatically updates when the variable value changes.
+ In Taipy GUI, dynamic visual element are implemented using the
+ [React](https://reactjs.org/) JavaScript library, and the
+ [TypeScript](https://www.typescriptlang.org/) programming language (that builds on
+ JavaScript).
## Prerequisites
In order to create and use custom visual elements, you need to install:
-- Taipy GUI 2.0 or higher (included in Taipy and Taipy Enterprise).
-- Python 3.8 or higher.
-- NodeJS (and NPM) if you plan to create dynamic custom visual elements.
+- Taipy GUI 2.0 or higher (included in Taipy and Taipy Enterprise).
+- Python 3.8 or higher.
+- NodeJS (and NPM) if you plan to create dynamic custom visual elements.
A basic knowledge of React (that we use with TypeScript) is welcome.
@@ -129,9 +129,10 @@ complete explanation of what part of the Extension API is used.
Each example addresses specific areas of the extension API. You should be able to
make you way from one example to the next.
-- [Custom static element](extension_static_element.md)
-- [Accessing assets](extension_assets.md)
-- [Custom dynamic element](extension_dynamic_element.md)
-- [Using List of Values](extension_list_of_values.md)
-- [Using tabular data](extension_data.md)
-- [Packaging an element library](extension_packaging.md)
+- [Custom static element](extension_static_element.md)
+- [Accessing assets](extension_assets.md)
+- [Custom dynamic element](extension_dynamic_element.md)
+- [Using List of Values](extension_list_of_values.md)
+- [Using tabular data](extension_data.md)
+- [Using Charts](extension_charts.md)
+- [Packaging an element library](extension_packaging.md)
diff --git a/docs/manuals/gui/extension_charts.md b/docs/manuals/gui/extension_charts.md
new file mode 100644
index 000000000..efd6cc205
--- /dev/null
+++ b/docs/manuals/gui/extension_charts.md
@@ -0,0 +1,342 @@
+# Creating Charts
+
+In this section, we will create a custom visual element that displays a chart. Charts will be implemented using the [Plotly](https://plotly.com) library.
+
+## Installing Plotly packages
+
+Go to the `[your_extension_directory]/demo_lib/frontend` directory and install the following Plotly packages:
+
+```bash
+npm install --save-dev plotly.js
+npm install --save-dev react-plotly.js
+npm install --save-dev @types/react-plotly.js
+```
+
+Also don't forget to increase size limit and add the following in `webpack.config.js`:
+
+```javascript
+module.exports = {
+ ...
+ performance: {
+ hints: false,
+ maxAssetSize: 50000,
+ maxEntrypointSize: 50000,
+ },
+ plugins: [
+ ...
+ new webpack.optimize.LimitChunkCountPlugin({
+ maxChunks: 1,
+ }),
+ ],
+ ...
+}
+```
+
+## Defining the chart element properties
+
+```python
+class DemoLibrary(ElementLibrary):
+ elts = {
+ "chart": Element(
+ "data",
+ {
+ "data": ElementProperty(PropertyType.dict),
+ "layout": ElementProperty(PropertyType.dict),
+ "config": ElementProperty(PropertyType.dict),
+ },
+ react_component="DemoChart", # <--- This is the component's name that we will create.
+ ),
+ }
+
+ def get_name(self) -> str:
+ return "demo_library"
+
+ def get_elements(self) -> dict:
+ return DemoLibrary.elts
+
+ def get_scripts(self) -> list[str]:
+ # Only one JavaScript bundle for this library.
+ return ["demo_lib/frontend/dist/demo.js"]
+```
+
+- `data`: The data to display in the chart. This is a dictionary type that is passed to the `data` prop of the `Plot` component.
+
+- `layout`: The layout of the chart. This is a dictionary type that is passed to the `layout` prop of the `Plot` component.
+
+- `config`: The configuration of the chart. This is a dictionary type that is passed to the `config` prop of the `Plot` component.
+
+- `type`: defines overall default type of the chart
+
+## Creating the React component
+
+```tsx
+const Plot = lazy(() => import("react-plotly.js"));
+
+interface DemoChartProps {
+ data?: string;
+ defaultData: string;
+ layout?: string;
+ type?: PlotType;
+ config?: string;
+}
+
+export default function DemoChart(props: DemoChartProps) {
+ const plotlyMain = useMemo(() => {
+ const data: Data[] = JSON.parse(props?.data || props.defaultData).map((d: Data) => {
+ return {
+ ...d,
+ // if overall chart type is not specified, use the type of the data in the data series
+ type: props?.type || d.type,
+ };
+ });
+ const layout: Partial = JSON.parse(props?.layout || "{}");
+ const config: Partial = JSON.parse(props?.config || "{}");
+
+ return { data, layout, config };
+ }, [props.data, props.layout, props.config]);
+
+ const { data, layout, config } = plotlyMain;
+
+ return (
+ Loading...
}>
+
+
+ );
+}
+```
+
+As you can see we are parsing incoming props before passing them to our `Plot` component. This is because `dict` types come as strings. We are also using `Suspense` in order to show a loading message while the component is being loaded. This is a good practice when using `lazy` components.
+
+## Chart Usage
+
+Now we can use our chart element in our application. Let's create different types of charts.
+
+### Line Chart
+
+```python
+trace1 = {"x": [1, 2, 3, 4], "y": [10, 15, 13, 17], "mode": "markers"}
+
+trace2 = {"x": [2, 3, 4, 5], "y": [16, 5, 11, 9], "mode": "lines"}
+
+trace3 = {"x": [1, 2, 3, 4], "y": [12, 9, 15, 12], "mode": "lines+markers"}
+
+layout = {"title": "Line and Scatter Plot"}
+
+data = [trace1, trace2, trace3]
+
+md = """
+# Line chart
+<|{data}|demo_library.chart|layout={layout}|>
+"""
+```
+
+- since we provided `data` as the default property we don't need specify the name of the property when using the element.
+
+![Line Chart Light](./images/line-chart-l.png)
+![Line Chart Dark](./images/line-chart-d.png)
+
+### Bar Chart
+
+```python
+trace1 = {
+ "x": ["giraffes", "orangutans", "monkeys"],
+ "y": [20, 14, 23],
+ "name": "SF Zoo",
+ "type": "bar",
+}
+
+
+trace2 = {
+ "x": ["giraffes", "orangutans", "monkeys"],
+ "y": [12, 18, 29],
+ "name": "LA Zoo",
+ "type": "bar",
+}
+
+
+data = [
+ trace1,
+ trace2,
+]
+
+layout = {
+ "barmode": "group",
+}
+
+md = """
+# Bar chart
+
+<|{data}|demo_library.chart|layout={layout}|>
+"""
+```
+
+![Bar Chart Light](./images/bar-chart-l.png)
+![Bar Chart Dark](./images/bar-chart-d.png)
+
+### Pie Chart
+
+```python
+data = [
+ {
+ "type": "pie",
+ "values": [2, 3, 4, 4],
+ "labels": ["Wages", "Operating expenses", "Cost of sales", "Insurance"],
+ "textinfo": "label+percent",
+ "textposition": "outside",
+ "automargin": True,
+ }
+]
+
+
+layout = {
+ "width": 500,
+ "height": 500,
+ "margin": {"t": 0, "b": 0, "l": 0, "r": 0},
+ "showlegend": False
+}
+
+md = """
+# Pie Chart
+
+<|{data}|demo_library.chart|layout={layout}|>
+"""
+```
+
+![Pie Chart Light](./images/pie-chart-l.png)
+![Pie Chart Dark](./images/pie-chart-d.png)
+
+### Bubble Chart
+
+```python
+trace1 = {
+ "x": [1, 2, 3, 4],
+ "y": [10, 11, 12, 13],
+ "mode": "markers",
+ "marker": {
+ "color": [
+ "rgb(93, 164, 214)",
+ "rgb(255, 144, 14)",
+ "rgb(44, 160, 101)",
+ "rgb(255, 65, 54)",
+ ],
+ "opacity": [1, 0.8, 0.6, 0.4],
+ "size": [40, 60, 80, 100],
+ },
+}
+
+
+data = [
+ trace1,
+]
+
+layout = {
+ "title": "Marker Size and Color",
+}
+
+md = """
+# Bubble chart
+
+<|{data}|demo_library.chart|layout={layout}|>
+"""
+```
+
+![Bubble Chart Light](./images/bubble-chart-l.png)
+![Bubble Chart Dark](./images/bubble-chart-d.png)
+
+## Histogram Chart
+
+```python
+trace1 = {
+ "x": [random.random() for i in range(500)],
+ "type": "histogram",
+}
+
+trace2 = {
+ "x": [random.random() for i in range(500)],
+ "type": "histogram",
+}
+
+
+data = [
+ trace1,
+ trace2,
+]
+
+layout = {
+ "barmode": "stack",
+}
+
+md = """
+# Histogram chart
+
+<|{data}|demo_library.chart|layout={layout}|>
+"""
+```
+
+![Histogram Chart Light](./images/histogram-chart-l.png)
+![Histogram Chart Dark](./images/histogram-chart-d.png)
+
+## Box Plots
+
+```python
+trace1 = {
+ "x": [random.random() for i in range(50)],
+ "type": "box",
+}
+
+trace2 = {
+ "x": [random.random() + 1 for i in range(50)],
+ "type": "box",
+}
+
+
+data = [
+ trace1,
+ trace2,
+]
+
+md = """
+# Box plot
+
+<|{data}|demo_library.chart|>
+"""
+```
+
+![Box Plot Light](./images/box-plot-l.png)
+![Box Plot Dark](./images/box-plot-d.png)
+
+## Gantt Chart
+
+```python
+ganttdata = [
+ {
+ "x": ["Task 1", "Task 2", "Task 3"],
+ "y": [1, 2, 3],
+ "type": "bar",
+ "name": "Tasks",
+ "marker": {"color": "rgb(55, 83, 109)"},
+ "orientation": "h",
+ }
+]
+
+ganttlayout = {
+ "xaxis": {
+ "ticktext": ["Task 1", "Task 2", "Task 3"],
+ "tickvals": [1, 2, 3],
+ "showgrid": True,
+ "zeroline": True,
+ },
+ "yaxis": {"title": "Duration (days)", "showgrid": True, "zeroline": True},
+}
+
+md = """
+# Gantt chart
+
+<|{ganttdata}|demo_library.chart|layout={ganttlayout}|>
+"""
+```
+
+![Gantt Chart Light](./images/gantt-chart-l.png)
+![Gantt Chart Dark](./images/gantt-chart-d.png)
+
+You can find more of these examples in the in [Plotly's Website](https://plotly.com/javascript/)
diff --git a/docs/manuals/gui/images/bar-chart-d.png b/docs/manuals/gui/images/bar-chart-d.png
new file mode 100644
index 000000000..fd5b788e7
Binary files /dev/null and b/docs/manuals/gui/images/bar-chart-d.png differ
diff --git a/docs/manuals/gui/images/bar-chart-l.png b/docs/manuals/gui/images/bar-chart-l.png
new file mode 100644
index 000000000..f8eb07b29
Binary files /dev/null and b/docs/manuals/gui/images/bar-chart-l.png differ
diff --git a/docs/manuals/gui/images/box-plot-d.png b/docs/manuals/gui/images/box-plot-d.png
new file mode 100644
index 000000000..ad40c1925
Binary files /dev/null and b/docs/manuals/gui/images/box-plot-d.png differ
diff --git a/docs/manuals/gui/images/box-plot-l.png b/docs/manuals/gui/images/box-plot-l.png
new file mode 100644
index 000000000..e02cec6ad
Binary files /dev/null and b/docs/manuals/gui/images/box-plot-l.png differ
diff --git a/docs/manuals/gui/images/bubble-chart-d.png b/docs/manuals/gui/images/bubble-chart-d.png
new file mode 100644
index 000000000..7f88e2ac7
Binary files /dev/null and b/docs/manuals/gui/images/bubble-chart-d.png differ
diff --git a/docs/manuals/gui/images/bubble-chart-l.png b/docs/manuals/gui/images/bubble-chart-l.png
new file mode 100644
index 000000000..d82b98abb
Binary files /dev/null and b/docs/manuals/gui/images/bubble-chart-l.png differ
diff --git a/docs/manuals/gui/images/gantt-chart-d.png b/docs/manuals/gui/images/gantt-chart-d.png
new file mode 100644
index 000000000..8befe1b2b
Binary files /dev/null and b/docs/manuals/gui/images/gantt-chart-d.png differ
diff --git a/docs/manuals/gui/images/gantt-chart-l.png b/docs/manuals/gui/images/gantt-chart-l.png
new file mode 100644
index 000000000..0b70d4a9b
Binary files /dev/null and b/docs/manuals/gui/images/gantt-chart-l.png differ
diff --git a/docs/manuals/gui/images/histogram-chart-d.png b/docs/manuals/gui/images/histogram-chart-d.png
new file mode 100644
index 000000000..71b6ff4ce
Binary files /dev/null and b/docs/manuals/gui/images/histogram-chart-d.png differ
diff --git a/docs/manuals/gui/images/histogram-chart-l.png b/docs/manuals/gui/images/histogram-chart-l.png
new file mode 100644
index 000000000..b3384ef51
Binary files /dev/null and b/docs/manuals/gui/images/histogram-chart-l.png differ
diff --git a/docs/manuals/gui/images/line-chart-d.png b/docs/manuals/gui/images/line-chart-d.png
new file mode 100644
index 000000000..b41aba6bf
Binary files /dev/null and b/docs/manuals/gui/images/line-chart-d.png differ
diff --git a/docs/manuals/gui/images/line-chart-l.png b/docs/manuals/gui/images/line-chart-l.png
new file mode 100644
index 000000000..c73bca993
Binary files /dev/null and b/docs/manuals/gui/images/line-chart-l.png differ
diff --git a/docs/manuals/gui/images/pie-chart-d.png b/docs/manuals/gui/images/pie-chart-d.png
new file mode 100644
index 000000000..1fac29594
Binary files /dev/null and b/docs/manuals/gui/images/pie-chart-d.png differ
diff --git a/docs/manuals/gui/images/pie-chart-l.png b/docs/manuals/gui/images/pie-chart-l.png
new file mode 100644
index 000000000..7f2f7eb1b
Binary files /dev/null and b/docs/manuals/gui/images/pie-chart-l.png differ