diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
deleted file mode 100644
index c7c221a..0000000
--- a/.github/workflows/docs.yml
+++ /dev/null
@@ -1,48 +0,0 @@
-name: docs
-
-on:
- push:
- branches:
- - main
- paths:
- - 'LICENSE'
- - 'CHANGELOG.md'
- - 'docs/**'
- - 'mkdocs.yml'
- - 'pyproject.toml'
- - '.github/workflows/docs.yml'
- - 'src/flet_charts/**'
- - 'examples/charts_example/src/**'
-
- workflow_dispatch: # Allow manual trigger from the GitHub Actions UI
-
-concurrency:
- group: "docs" # Prevent multiple overlapping deploys
- cancel-in-progress: false # Allow in-progress deploys to finish
-
-permissions:
- contents: write # Required to push to the gh-pages branch
-
-env:
- GH_TOKEN: ${{ secrets.GH_TOKEN }} # used by mkdocs for publishing
-
-jobs:
- deploy:
- name: Deploy Documentation
- runs-on: ubuntu-latest
- if: github.repository == github.event.repository.full_name # don't run on forks
- steps:
- - name: Checkout repository
- uses: actions/checkout@v4
-
- - name: Setup uv
- uses: astral-sh/setup-uv@v6
-
- - name: Configure Git for mkdocs
- run: |
- git config user.name github-actions[bot]
- git config user.email 41898282+github-actions[bot]@users.noreply.github.com
-
- - name: Deploy to GitHub Pages
- run: |
- uv run --group docs --group lint mkdocs gh-deploy --force -v
diff --git a/README.md b/README.md
index 41b35f4..a97ed6c 100644
--- a/README.md
+++ b/README.md
@@ -10,20 +10,15 @@ It is based on the [fl_chart](https://pub.dev/packages/fl_chart) Flutter package
## Documentation
-Detailed documentation to this package can be found [here](https://flet-dev.github.io/flet-charts/).
+Detailed documentation to this package can be found [here](https://flet-charts.docs.flet.dev/).
## Platform Support
This package supports the following platforms:
-| Platform | Supported |
-|----------|:---------:|
-| Windows | ✅ |
-| macOS | ✅ |
-| Linux | ✅ |
-| iOS | ✅ |
-| Android | ✅ |
-| Web | ✅ |
+| Platform | Windows | macOS | Linux | iOS | Android | Web |
+|----------|---------|-------|-------|-----|---------|-----|
+| Supported| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
## Usage
@@ -42,11 +37,6 @@ To install the `flet-charts` package and add it to your project dependencies:
```
After this, you will have to manually add this package to your `requirements.txt` or `pyproject.toml`.
-- Using `poetry`:
- ```bash
- poetry add flet-charts
- ```
-
### Examples
For examples, see [these](./examples).
diff --git a/docs/bar_chart.md b/docs/bar_chart.md
index 6970e79..e9721b1 100644
--- a/docs/bar_chart.md
+++ b/docs/bar_chart.md
@@ -1,3 +1,10 @@
+---
+class_name: flet_charts.bar_chart.BarChart
+image: assets/bar-chart-diagram.svg
+---
+
+{{ class_summary(class_name, image) }}
+
## Examples
### Example 1
@@ -20,4 +27,4 @@
--8<-- "examples/charts_example/src/bar_chart/example_2.py"
```
-::: flet_charts.bar_chart.BarChart
+{{ class_members(class_name) }}
\ No newline at end of file
diff --git a/docs/bar_chart_group.md b/docs/bar_chart_group.md
index c32d48b..43ee287 100644
--- a/docs/bar_chart_group.md
+++ b/docs/bar_chart_group.md
@@ -1 +1 @@
-::: flet_charts.bar_chart_group.BarChartGroup
\ No newline at end of file
+{{ class_all_options("flet_charts.bar_chart_group.BarChartGroup") }}
\ No newline at end of file
diff --git a/docs/bar_chart_rod.md b/docs/bar_chart_rod.md
index ff4b867..0b21460 100644
--- a/docs/bar_chart_rod.md
+++ b/docs/bar_chart_rod.md
@@ -1 +1 @@
-::: flet_charts.bar_chart_rod.BarChartRod
\ No newline at end of file
+{{ class_all_options("flet_charts.bar_chart_rod.BarChartRod") }}
\ No newline at end of file
diff --git a/docs/bar_chart_rod_stack_item.md b/docs/bar_chart_rod_stack_item.md
index 051dc95..898d520 100644
--- a/docs/bar_chart_rod_stack_item.md
+++ b/docs/bar_chart_rod_stack_item.md
@@ -1 +1 @@
-::: flet_charts.bar_chart_rod_stack_item.BarChartRodStackItem
\ No newline at end of file
+{{ class_all_options("flet_charts.bar_chart_rod_stack_item.BarChartRodStackItem") }}
\ No newline at end of file
diff --git a/docs/chart_axis.md b/docs/chart_axis.md
index ffd9eff..782ee5d 100644
--- a/docs/chart_axis.md
+++ b/docs/chart_axis.md
@@ -1 +1 @@
-::: flet_charts.chart_axis.ChartAxis
\ No newline at end of file
+{{ class_all_options("flet_charts.chart_axis.ChartAxis") }}
\ No newline at end of file
diff --git a/docs/chart_axis_label.md b/docs/chart_axis_label.md
index c826d7b..bdb1159 100644
--- a/docs/chart_axis_label.md
+++ b/docs/chart_axis_label.md
@@ -1 +1 @@
-::: flet_charts.chart_axis.ChartAxisLabel
\ No newline at end of file
+{{ class_all_options("flet_charts.chart_axis.ChartAxisLabel") }}
\ No newline at end of file
diff --git a/docs/extras/css/mkdocstrings.css b/docs/extras/css/mkdocstrings.css
new file mode 100644
index 0000000..6be79fb
--- /dev/null
+++ b/docs/extras/css/mkdocstrings.css
@@ -0,0 +1,88 @@
+/* Material Symbols font with selected icons */
+@import url("https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,200,1,200&icon_names=account_tree,bolt,build,category,deployed_code");
+
+/* Hide the original label text */
+code.doc-symbol { font-size: 0; }
+
+/* Show only the icon */
+code.doc-symbol::before {
+ font-family: "Material Symbols Outlined";
+ font-variation-settings: 'FILL' 1, 'GRAD' 200, 'opsz' 24, 'wght' 200;
+ font-size: .82rem;
+ position: relative;
+ top: .25em;
+}
+
+.doc-heading .doc-symbol::before {
+ font-size: 1.0rem;
+ top: .21em;
+}
+
+code.doc-symbol-class::before {
+ content: "category";
+}
+
+code.doc-symbol-attribute::before {
+ content: "build";
+}
+
+code.doc-symbol-event::before {
+ content: "bolt";
+}
+
+code.doc-symbol-method::before {
+ content: "deployed_code";
+}
+
+/* Overrides */
+[data-md-color-scheme="default"] {
+ --doc-symbol-class-fg-color: #f0a502;
+ --doc-symbol-attribute-fg-color: #0b8dd9; /* ae106f */
+ --doc-symbol-attribute-bg-color: #9500721a;
+
+ --doc-symbol-event-fg-color: #f8aa01;
+ --doc-symbol-event-bg-color: #e5ff001a;
+}
+
+[data-md-color-scheme="slate"] {
+ --doc-symbol-class-fg-color: #f0a502;
+ --doc-symbol-attribute-fg-color: #0b8dd9; /* ae106f */
+ --doc-symbol-attribute-bg-color: #9500721a;
+
+ --doc-symbol-event-fg-color: #f8aa01;
+ --doc-symbol-event-bg-color: #e5ff001a;
+}
+
+code.doc-symbol-event,
+a code.doc-symbol-event {
+ color: var(--doc-symbol-event-fg-color);
+ background-color: var(--doc-symbol-event-bg-color);
+}
+
+/* Overrides */
+
+/* Command symbol */
+:root, :host,
+ /* Light mode */
+[data-md-color-scheme="default"] {
+ --doc-symbol-command-fg-color: #9538001;
+ --doc-symbol-command-bg-color: #9538001a;
+}
+
+/* Dark mode */
+[data-md-color-scheme="slate"] {
+ --doc-symbol-command-fg-color: #ffa6571;
+ --doc-symbol-command-bg-color: #ffa6571a;
+}
+
+code.doc-symbol-command,
+a code.doc-symbol-command {
+ color: var(--doc-symbol-command-fg-color);
+ background-color: var(--doc-symbol-command-bg-color);
+}
+
+code.doc-symbol-command::after {
+ content: "cmd";
+}
+
+/* Command symbol */
\ No newline at end of file
diff --git a/docs/extras/macros/__init__.py b/docs/extras/macros/__init__.py
new file mode 100644
index 0000000..382a5a0
--- /dev/null
+++ b/docs/extras/macros/__init__.py
@@ -0,0 +1,46 @@
+def define_env(env):
+ @env.macro
+ def class_all_options(class_name, separate_signature=True):
+ return f"""
+::: {class_name}
+ options:
+ show_root_toc_entry: true
+ show_bases: true
+ separate_signature: {str(separate_signature).lower()}
+ extra:
+ show_class_docstring: true
+ show_children: true
+ summary:
+ attributes: true
+ functions: true
+"""
+
+ @env.macro
+ def class_summary(class_name, image=None):
+ control_name = class_name.split(".")[-1]
+ image_md = f"\n\n\n\n" if image else ""
+ return f"""
+::: {class_name}
+ options:
+ show_root_toc_entry: true
+ extra:
+ show_class_docstring: true
+
+{image_md}
+
+::: {class_name}
+ options:
+ show_bases: true
+ summary:
+ attributes: true
+ functions: true
+"""
+
+ @env.macro
+ def class_members(class_name):
+ return f"""
+::: {class_name}
+ options:
+ extra:
+ show_children: true
+"""
diff --git a/docs/images/logo.svg b/docs/images/logo.svg
index 5d95ef0..ca983da 100644
--- a/docs/images/logo.svg
+++ b/docs/images/logo.svg
@@ -1,19 +1,29 @@
-
-
-
-
+
+
diff --git a/docs/index.md b/docs/index.md
index 1ab8192..97f1f76 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -1,25 +1,20 @@
-# flet-charts
+# Getting started
[](https://pypi.python.org/pypi/flet-charts)
[](https://pepy.tech/project/flet-charts)
[](https://github.com/flet-dev/flet-charts/blob/main/LICENSE)
-A [Flet](https://flet.dev) extension for creating interactive charts and graphs.
+`flet-charts` is a [Flet](https://flet.dev) extension for creating interactive charts and graphs.
It is based on the [fl_chart](https://pub.dev/packages/fl_chart) Flutter package.
## Platform Support
-This package supports the following platforms:
+This package is supported on the following platforms:
-| Platform | Supported |
-|----------|:---------:|
-| Windows | ✅ |
-| macOS | ✅ |
-| Linux | ✅ |
-| iOS | ✅ |
-| Android | ✅ |
-| Web | ✅ |
+| Windows | macOS | Linux | iOS | Android | Web |
+|---------|-------|-------|-----|---------|-----|
+| ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
## Usage
@@ -39,11 +34,6 @@ To install the `flet-charts` package and add it to your project dependencies:
1. After this, you will have to manually add this package to your `requirements.txt` or `pyproject.toml`.
-=== "poetry"
- ```bash
- poetry add flet-charts
- ```
-
## Examples
You can find examples in the respective documentation pages for each chart type:
diff --git a/docs/line_chart.md b/docs/line_chart.md
index 798d8e5..d20af92 100644
--- a/docs/line_chart.md
+++ b/docs/line_chart.md
@@ -1,3 +1,10 @@
+---
+class_name: flet_charts.line_chart.LineChart
+image: assets/line-chart-diagram.svg
+---
+
+{{ class_summary(class_name, image) }}
+
## Examples
### Example 1
@@ -20,4 +27,4 @@
--8<-- "examples/charts_example/src/line_chart/example_2.py"
```
-::: flet_charts.line_chart.LineChart
+{{ class_members(class_name) }}
\ No newline at end of file
diff --git a/docs/line_chart_data.md b/docs/line_chart_data.md
index 21cb1a6..a81c9b0 100644
--- a/docs/line_chart_data.md
+++ b/docs/line_chart_data.md
@@ -1 +1 @@
-::: flet_charts.line_chart_data.LineChartData
\ No newline at end of file
+{{ class_all_options("flet_charts.line_chart_data.LineChartData") }}
\ No newline at end of file
diff --git a/docs/line_chart_data_point.md b/docs/line_chart_data_point.md
index f78d7f8..b8d4cce 100644
--- a/docs/line_chart_data_point.md
+++ b/docs/line_chart_data_point.md
@@ -1 +1 @@
-::: flet_charts.line_chart_data_point.LineChartDataPoint
\ No newline at end of file
+{{ class_all_options("flet_charts.line_chart_data_point.LineChartDataPoint") }}
\ No newline at end of file
diff --git a/docs/matplotlib_chart.md b/docs/matplotlib_chart.md
index fbd5c2c..f6b8365 100644
--- a/docs/matplotlib_chart.md
+++ b/docs/matplotlib_chart.md
@@ -1,3 +1,9 @@
+---
+class_name: flet_charts.matplotlib_chart.MatplotlibChart
+---
+
+{{ class_summary(class_name) }}
+
## Examples
### Example 1
@@ -26,4 +32,4 @@ official [Matplotlib example](https://matplotlib.org/stable/gallery/lines_bars_a
--8<-- "examples/charts_example/src/matplotlib_chart/example_2.py"
```
-::: flet_charts.matplotlib_chart.MatplotlibChart
+{{ class_members(class_name) }}
\ No newline at end of file
diff --git a/docs/pie_chart.md b/docs/pie_chart.md
index 6a32015..48ba3eb 100644
--- a/docs/pie_chart.md
+++ b/docs/pie_chart.md
@@ -1,3 +1,10 @@
+---
+class_name: flet_charts.pie_chart.PieChart
+image: assets/pie-chart-diagram.svg
+---
+
+{{ class_summary(class_name, image) }}
+
## Examples
### Example 1
@@ -30,4 +37,4 @@
--8<-- "examples/charts_example/src/pie_chart/example_3.py"
```
-::: flet_charts.pie_chart.PieChart
+{{ class_members(class_name) }}
\ No newline at end of file
diff --git a/docs/pie_chart_section.md b/docs/pie_chart_section.md
index 1bf9539..7d70267 100644
--- a/docs/pie_chart_section.md
+++ b/docs/pie_chart_section.md
@@ -1 +1 @@
-::: flet_charts.pie_chart_section.PieChartSection
\ No newline at end of file
+{{ class_all_options("flet_charts.pie_chart_section.PieChartSection") }}
\ No newline at end of file
diff --git a/docs/plotly_chart.md b/docs/plotly_chart.md
index 4517473..da520d8 100644
--- a/docs/plotly_chart.md
+++ b/docs/plotly_chart.md
@@ -1,3 +1,9 @@
+---
+class_name: flet_charts.plotly_chart.PlotlyChart
+---
+
+{{ class_summary(class_name) }}
+
## Examples
### Example 1
@@ -24,7 +30,7 @@ Based on an official [Plotly example](https://plotly.com/python/bar-charts).
--8<-- "examples/charts_example/src/plotly_chart/example_2.py"
```
-## Example 3
+### Example 3
Based on an official [Plotly example](https://plotly.com/python/pie-charts).
@@ -48,4 +54,4 @@ Based on an official [Plotly example](https://plotly.com/python/box-plots).
--8<-- "examples/charts_example/src/plotly_chart/example_4.py"
```
-::: flet_charts.plotly_chart.PlotlyChart
+{{ class_members(class_name) }}
\ No newline at end of file
diff --git a/docs/scatter_chart.md b/docs/scatter_chart.md
index 1f9713e..404a64b 100644
--- a/docs/scatter_chart.md
+++ b/docs/scatter_chart.md
@@ -1,3 +1,9 @@
+---
+class_name: flet_charts.scatter_chart.ScatterChart
+---
+
+{{ class_summary(class_name) }}
+
## Examples
### Example 1: Basic Scatter Chart
@@ -6,4 +12,4 @@
--8<-- "examples/charts_example/src/scatter_chart/example_1.py"
```
-::: flet_charts.scatter_chart.ScatterChart
+{{ class_members(class_name) }}
\ No newline at end of file
diff --git a/docs/scatter_chart_spot.md b/docs/scatter_chart_spot.md
index f0c18f4..1c76429 100644
--- a/docs/scatter_chart_spot.md
+++ b/docs/scatter_chart_spot.md
@@ -1 +1 @@
-::: flet_charts.scatter_chart_spot.ScatterChartSpot
\ No newline at end of file
+{{ class_all_options("flet_charts.scatter_chart_spot.ScatterChartSpot") }}
\ No newline at end of file
diff --git a/docs/templates/python/material/placeholder.txt b/docs/templates/python/material/placeholder.txt
new file mode 100644
index 0000000..b1bea0e
--- /dev/null
+++ b/docs/templates/python/material/placeholder.txt
@@ -0,0 +1 @@
+Required along with `python_ref`.
\ No newline at end of file
diff --git a/docs/templates/python_xref/material/attribute.html.jinja b/docs/templates/python_xref/material/attribute.html.jinja
new file mode 100644
index 0000000..df7fbc2
--- /dev/null
+++ b/docs/templates/python_xref/material/attribute.html.jinja
@@ -0,0 +1,132 @@
+{#- Template for Python attributes.
+
+This template renders a Python attribute (or variable).
+This can be a module attribute or a class attribute.
+
+Context:
+ attribute (griffe.Attribute): The attribute to render.
+ root (bool): Whether this is the root object, injected with `:::` in a Markdown page.
+ heading_level (int): The HTML heading level to use.
+ config (dict): The configuration options.
+-#}
+
+{% block logs scoped %}
+ {#- Logging block.
+
+ This block can be used to log debug messages, deprecation messages, warnings, etc.
+ -#}
+ {{ log.debug("Rendering " + attribute.path) }}
+{% endblock logs %}
+
+{% set attr_class_name = "doc-symbol-event" if attribute.name.startswith('on_') else "doc-symbol-attribute" %}
+
+
+ {% with obj = attribute, html_id = attribute.path %}
+
+ {% if root %}
+ {% set show_full_path = config.show_root_full_path %}
+ {% set root_members = True %}
+ {% elif root_members %}
+ {% set show_full_path = config.show_root_members_full_path or config.show_object_full_path %}
+ {% set root_members = False %}
+ {% else %}
+ {% set show_full_path = config.show_object_full_path %}
+ {% endif %}
+
+ {% set attribute_name = attribute.path if show_full_path else attribute.name %}
+
+ {% if not root or config.show_root_heading %}
+ {% filter heading(
+ heading_level,
+ role="data" if attribute.parent.kind.value == "module" else "attr",
+ id=html_id,
+ class="doc doc-heading",
+ toc_label=((' ')|safe if config.show_symbol_type_toc else '') + (config.toc_label if config.toc_label and root else attribute.name),
+ skip_inventory=config.skip_local_inventory,
+ ) %}
+
+ {% block heading scoped %}
+ {#- Heading block.
+
+ This block renders the heading for the attribute.
+ -#}
+ {% if config.show_symbol_type_heading %}{% endif %}
+ {% if config.heading and root %}
+ {{ config.heading }}
+ {% elif config.separate_signature %}
+ {{ attribute_name }}
+ {% else %}
+ {%+ filter highlight(language="python", inline=True) %}
+ {{ attribute_name }}{% if attribute.annotation and config.show_signature_annotations %}: {{ attribute.annotation }}{% endif %}
+ {% if config.show_attribute_values and attribute.value %} = {{ attribute.value }}{% endif %}
+ {% endfilter %}
+ {% endif %}
+ {% endblock heading %}
+
+ {% block labels scoped %}
+ {#- Labels block.
+
+ This block renders the labels for the attribute.
+ -#}
+ {% with labels = attribute.labels %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% include "labels"|get_template with context %}
+ {% endwith %}
+ {% endblock labels %}
+
+ {% endfilter %}
+
+ {% block signature scoped %}
+ {#- Signature block.
+
+ This block renders the signature for the attribute.
+ -#}
+ {% if config.separate_signature %}
+ {% filter format_attribute(attribute, config.line_length, crossrefs=config.signature_crossrefs, show_value=config.show_attribute_values) %}
+ {{ attribute.name }}
+ {% endfilter %}
+ {% endif %}
+ {% endblock signature %}
+
+ {% else %}
+
+ {% if config.show_root_toc_entry %}
+ {% filter heading(heading_level,
+ role="data" if attribute.parent.kind.value == "module" else "attr",
+ id=html_id,
+ toc_label=(' '|safe if config.show_symbol_type_toc else '') + (config.toc_label if config.toc_label and root else attribute_name),
+ hidden=True,
+ skip_inventory=config.skip_local_inventory,
+ ) %}
+ {% endfilter %}
+ {% endif %}
+ {% set heading_level = heading_level - 1 %}
+ {% endif %}
+
+
+ {% block contents scoped %}
+ {#- Contents block.
+
+ This block renders the contents of the attribute.
+ It contains other blocks that users can override.
+ Overriding the contents block allows to rearrange the order of the blocks.
+ -#}
+ {% block docstring scoped %}
+ {#- Docstring block.
+
+ This block renders the docstring for the attribute.
+ -#}
+ {% with docstring_sections = attribute.docstring.parsed %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% include "docstring"|get_template with context %}
+ {% endwith %}
+ {% endblock docstring %}
+
+ {% if config.backlinks %}
+
+ {% endif %}
+ {% endblock contents %}
+
+
+ {% endwith %}
+
diff --git a/docs/templates/python_xref/material/children.html.jinja b/docs/templates/python_xref/material/children.html.jinja
new file mode 100644
index 0000000..6c39abc
--- /dev/null
+++ b/docs/templates/python_xref/material/children.html.jinja
@@ -0,0 +1,204 @@
+{#- Template for members (children) of an object.
+
+This template iterates on members of a given object and renders them.
+It can group members by category (attributes, classes, functions, modules) or render them in a flat list.
+
+Context:
+ obj (griffe.Object): The object to render.
+ config (dict): The configuration options.
+ root_members (bool): Whether the object is the root object.
+ heading_level (int): The HTML heading level to use.
+-#}
+
+{% if obj.all_members %}
+ {% block logs scoped %}
+ {#- Logging block.
+
+ This block can be used to log debug messages, deprecation messages, warnings, etc.
+ -#}
+ {{ log.debug("Rendering children of " + obj.path) }}
+ {% endblock logs %}
+
+
+
+ {% if root_members %}
+ {% set members_list = config.members %}
+ {% else %}
+ {% set members_list = none %}
+ {% endif %}
+
+ {% if config.group_by_category %}
+
+ {% with %}
+
+ {% if config.show_category_heading %}
+ {% set extra_level = 1 %}
+ {% else %}
+ {% set extra_level = 0 %}
+ {% endif %}
+
+ {# decide headings for properties #}
+ {% set attr_heading_id = "-properties" if obj.is_class else "-attributes" %}
+ {% set attr_heading_name = "Properties" if obj.is_class else "Attributes" %}
+
+ {% with attributes = obj.attributes | filter_objects(
+ filters=config.filters,
+ members_list=members_list,
+ inherited_members=config.inherited_members,
+ keep_no_docstrings=config.show_if_no_docstring,
+ ) %}
+ {% if attributes %}
+ {# order once, then split into two lists #}
+ {% set ordered = attributes | order_members(config.members_order, members_list) %}
+ {% set ns = namespace(props=[], events=[]) %}
+ {% for attribute in ordered %}
+ {% if config.filters == "public" or members_list is not none or (not attribute.is_imported or attribute.is_public) %}
+ {% if attribute.name.startswith("on_") %}
+ {% set _ = ns.events.append(attribute) %}
+ {% else %}
+ {% set _ = ns.props.append(attribute) %}
+ {% endif %}
+ {% endif %}
+ {% endfor %}
+
+ {# --- PROPERTIES --- #}
+ {% if ns.props %}
+ {% if config.show_category_heading %}
+ {% filter heading(heading_level, id=html_id ~ attr_heading_id, skip_inventory=config.skip_local_inventory) %}{{ attr_heading_name }}{% endfilter %}
+ {% endif %}
+ {% with heading_level = heading_level + extra_level %}
+ {% for attribute in ns.props %}
+ {% include attribute|get_template with context %}
+ {% endfor %}
+ {% endwith %}
+ {% endif %}
+
+ {# --- EVENTS (on_*) --- #}
+ {% if ns.events %}
+ {% if config.show_category_heading %}
+ {% filter heading(heading_level, id=html_id ~ "-events", skip_inventory=config.skip_local_inventory) %}Events{% endfilter %}
+ {% endif %}
+ {% with heading_level = heading_level + extra_level %}
+ {% for attribute in ns.events %}
+ {% include attribute|get_template with context %}
+ {% endfor %}
+ {% endwith %}
+ {% endif %}
+ {% endif %}
+ {% endwith %}
+
+ {% with classes = obj.classes|filter_objects(
+ filters=config.filters,
+ members_list=members_list,
+ inherited_members=config.inherited_members,
+ keep_no_docstrings=config.show_if_no_docstring,
+ ) %}
+ {% if classes %}
+ {% if config.show_category_heading %}
+ {% filter heading(heading_level, id=html_id ~ "-classes", skip_inventory=config.skip_local_inventory) %}Classes{% endfilter %}
+ {% endif %}
+ {% with heading_level = heading_level + extra_level %}
+ {% for class in classes|order_members(config.members_order, members_list) %}
+ {% if config.filters == "public" or members_list is not none or (not class.is_imported or class.is_public) %}
+ {% include class|get_template with context %}
+ {% endif %}
+ {% endfor %}
+ {% endwith %}
+ {% endif %}
+ {% endwith %}
+
+ {% set func_heading_id = "-methods" if obj.is_class else "-functions" %}
+ {% set func_heading_name = "Methods" if obj.is_class else "Functions" %}
+ {% with functions = obj.functions|filter_objects(
+ filters=config.filters,
+ members_list=members_list,
+ inherited_members=config.inherited_members,
+ keep_no_docstrings=config.show_if_no_docstring,
+ ) %}
+ {% if functions %}
+ {% if config.show_category_heading %}
+ {% filter heading(heading_level, id=html_id ~ func_heading_id, skip_inventory=config.skip_local_inventory) %}{{ func_heading_name }}{% endfilter %}
+ {% endif %}
+ {% with heading_level = heading_level + extra_level %}
+ {% for function in functions|order_members(config.members_order, members_list) %}
+ {% if not (obj.kind.value == "class" and function.name == "__init__" and config.merge_init_into_class) %}
+ {% if config.filters == "public" or members_list is not none or (not function.is_imported or function.is_public) %}
+ {% include function|get_template with context %}
+ {% endif %}
+ {% endif %}
+ {% endfor %}
+ {% endwith %}
+ {% endif %}
+ {% endwith %}
+
+ {% if config.show_submodules %}
+ {% with modules = obj.modules|filter_objects(
+ filters=config.filters,
+ members_list=members_list,
+ inherited_members=config.inherited_members,
+ keep_no_docstrings=config.show_if_no_docstring,
+ ) %}
+ {% if modules %}
+ {% if config.show_category_heading %}
+ {% filter heading(heading_level, id=html_id ~ "-modules", skip_inventory=config.skip_local_inventory) %}Modules{% endfilter %}
+ {% endif %}
+ {% with heading_level = heading_level + extra_level %}
+ {% for module in modules|order_members("alphabetical", members_list) %}
+ {% if config.filters == "public" or members_list is not none or (not module.is_alias or module.is_public) %}
+ {% include module|get_template with context %}
+ {% endif %}
+ {% endfor %}
+ {% endwith %}
+ {% endif %}
+ {% endwith %}
+ {% endif %}
+
+ {% endwith %}
+
+ {% else %}
+
+ {% for child in obj.all_members
+ |filter_objects(
+ filters=config.filters,
+ members_list=members_list,
+ inherited_members=config.inherited_members,
+ keep_no_docstrings=config.show_if_no_docstring,
+ )
+ |order_members(config.members_order, members_list)
+ %}
+
+ {% if not (obj.is_class and child.name == "__init__" and config.merge_init_into_class) %}
+
+ {% if config.filters == "public" or members_list is not none or child.is_public %}
+ {% if child.is_attribute %}
+ {% with attribute = child %}
+ {% include attribute|get_template with context %}
+ {% endwith %}
+
+ {% elif child.is_class %}
+ {% with class = child %}
+ {% include class|get_template with context %}
+ {% endwith %}
+
+ {% elif child.is_function %}
+ {% with function = child %}
+ {% include function|get_template with context %}
+ {% endwith %}
+
+ {% elif child.is_module and config.show_submodules %}
+ {% with module = child %}
+ {% include module|get_template with context %}
+ {% endwith %}
+
+ {% endif %}
+ {% endif %}
+
+ {% endif %}
+
+ {% endfor %}
+
+ {% endif %}
+
+
+
+{% endif %}
diff --git a/docs/templates/python_xref/material/class.html.jinja b/docs/templates/python_xref/material/class.html.jinja
new file mode 100644
index 0000000..2d26e7c
--- /dev/null
+++ b/docs/templates/python_xref/material/class.html.jinja
@@ -0,0 +1,60 @@
+{% extends "_base/class.html.jinja" %}
+
+{% block bases %}
+ {#- Class bases block.
+
+ This block renders the bases for the class.
+ -#}
+ {% if config.show_bases and class.bases %}
+
+ Inherits: {% for expression in class.bases -%}
+
+ {%- with backlink_type = "subclassed-by" -%}
+ {#- YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. -#}
+ {%- include "expression"|get_template with context -%}
+ {%- endwith -%}
+ {% if not loop.last %}, {% endif %}
+ {% endfor -%}
+
+ {% endif %}
+{% endblock bases %}
+
+{% block docstring %}
+ {#- Docstring block.
+
+ This block renders the docstring for the class.
+ -#}
+ {% if config.extra.show_class_docstring %}
+ {% with docstring_sections = class.docstring.parsed %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% include "docstring"|get_template with context %}
+ {% endwith %}
+ {% if config.merge_init_into_class %}
+ {# We don't want to merge the inherited `__init__` method docstring into the class docstring #}
+ {# if such inherited method was not selected through `inherited_members`. #}
+ {% with check_members = all_members if (config.inherited_members is true or (config.inherited_members is iterable and "__init__" in config.inherited_members)) else class.members %}
+ {% if "__init__" in check_members and check_members["__init__"].has_docstring %}
+ {% with function = check_members["__init__"] %}
+ {% with obj = function, docstring_sections = function.docstring.parsed %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% include "docstring"|get_template with context %}
+ {% endwith %}
+ {% endwith %}
+ {% endif %}
+ {% endwith %}
+ {% endif %}
+ {% endif %}
+{% endblock docstring %}
+
+{% block children scoped %}
+ {#- Children block.
+
+ This block renders the children (members) of the class.
+ -#}
+ {% if config.extra.show_children %}
+ {% set root = False %}
+ {% set heading_level = heading_level + 1 %}
+ {# YORE: Bump 2: Replace `"|get_template` with `.html.jinja"` within line. #}
+ {% include "children"|get_template with context %}
+ {% endif %}
+{% endblock children %}
\ No newline at end of file
diff --git a/docs/templates/python_xref/material/docstring/attributes.html.jinja b/docs/templates/python_xref/material/docstring/attributes.html.jinja
new file mode 100644
index 0000000..f6687c2
--- /dev/null
+++ b/docs/templates/python_xref/material/docstring/attributes.html.jinja
@@ -0,0 +1,43 @@
+{% extends "_base/docstring/attributes.html.jinja" %}
+
+{% block list_style %}
+ {# Split attributes into events and properties #}
+ {% set ns = namespace(events=[], props=[]) %}
+ {% for attribute in section.value %}
+ {% if attribute.name.startswith('on_') %}
+ {% set _ = ns.events.append(attribute) %}
+ {% else %}
+ {% set _ = ns.props.append(attribute) %}
+ {% endif %}
+ {% endfor %}
+
+ {# Small helper to render a titled list #}
+ {% macro render_group(title, items) -%}
+
{{ title }}
+
+ {%- for attribute in items %}
+
+ {{ attribute.name }}
+ {%- if attribute.annotation %}
+ {%- with expression = attribute.annotation -%}
+ ({% include "expression"|get_template with context %})
+ {%- endwith %}
+ {%- endif %}
+ –
+