diff --git a/docs/src/about/code.md b/docs/src/about/code.md index b4790d5b..93121a75 100644 --- a/docs/src/about/code.md +++ b/docs/src/about/code.md @@ -6,7 +6,7 @@

-!!! note +!!! abstract "Note" Looking to contribute features that are not Django specific? @@ -59,7 +59,7 @@ Navigate to [`http://127.0.0.1:8000`](http://127.0.0.1:8000) to see if the tests ## Running the full test suite -!!! note +!!! abstract "Note" This repository uses [Nox](https://nox.thea.codes/en/stable/) to run tests. For a full test of available scripts run `nox -l`. diff --git a/docs/src/assets/css/admonition.css b/docs/src/assets/css/admonition.css index 7813830c..8b3f06ef 100644 --- a/docs/src/assets/css/admonition.css +++ b/docs/src/assets/css/admonition.css @@ -68,33 +68,27 @@ React Name: "You will learn" } /* -Admonition: "note" +Admonition: "abstract" React Name: "Note" */ -.md-typeset .admonition.note { +.md-typeset .admonition.abstract { background: var(--note-bg-color); padding: 0.8rem 1.4rem; border-radius: 0.8rem; } -.md-typeset .note .admonition-title { +.md-typeset .abstract .admonition-title { font-size: 1rem; background: transparent; padding-bottom: 0; color: rgb(68, 172, 153); } -.md-typeset .note .admonition-title:before { +.md-typeset .abstract .admonition-title:before { font-size: 1.1rem; background: rgb(68, 172, 153); } -.md-typeset .note > .admonition-title:before, -.md-typeset .note > summary:before { - -webkit-mask-image: var(--md-admonition-icon--abstract); - mask-image: var(--md-admonition-icon--abstract); -} - /* Admonition: "warning" React Name: "Pitfall" diff --git a/docs/src/assets/css/sidebar.css b/docs/src/assets/css/sidebar.css index bf197138..b6507d96 100644 --- a/docs/src/assets/css/sidebar.css +++ b/docs/src/assets/css/sidebar.css @@ -2,6 +2,10 @@ --sizebar-font-size: 0.62rem; } +.md-nav__link { + word-break: break-word; +} + /* Desktop Styling */ @media screen and (min-width: 76.1875em) { /* Move the sidebar and TOC to the edge of the page */ diff --git a/docs/src/assets/css/table-of-contents.css b/docs/src/assets/css/table-of-contents.css index aa9a61ae..6c94f06e 100644 --- a/docs/src/assets/css/table-of-contents.css +++ b/docs/src/assets/css/table-of-contents.css @@ -29,6 +29,15 @@ border-radius: 10px 0 0 10px; font-weight: 400; } + + [data-md-component="toc"] + .md-nav__item + .md-nav__list + .md-nav__item + .md-nav__link { + padding-left: 1.25rem; + } + [dir="ltr"] .md-sidebar__inner { padding: 0; } diff --git a/docs/src/learn/add-reactpy-to-a-django-project.md b/docs/src/learn/add-reactpy-to-a-django-project.md index 311bc3c3..5a22b8f6 100644 --- a/docs/src/learn/add-reactpy-to-a-django-project.md +++ b/docs/src/learn/add-reactpy-to-a-django-project.md @@ -6,7 +6,7 @@ If you want to add some interactivity to your existing **Django project**, you d

-!!! note +!!! abstract "Note" These docs assumes you have already created [a **Django project**](https://docs.djangoproject.com/en/dev/intro/tutorial01/), which involves creating and installing at least one **Django app**. @@ -51,11 +51,11 @@ Add `#!python "reactpy_django"` to [`INSTALLED_APPS`](https://docs.djangoproject {% include "../../python/configure-channels-asgi-app.py" %} ``` -??? note "Configure ReactPy settings (Optional)" +??? info "Configure ReactPy settings (Optional)" - {% include "../reference/settings.md" start="" end="" %} + ReactPy's has additional configuration available to fit a variety of use cases. - {% include "../reference/settings.md" start="" end="" %} + See the [ReactPy settings](../reference/settings.md) documentation to learn more. ## Step 3: Configure `urls.py` @@ -77,7 +77,7 @@ Register ReactPy's WebSocket using `#!python REACTPY_WEBSOCKET_ROUTE` in your [` {% include "../../python/configure-asgi.py" %} ``` -??? note "Add `#!python AuthMiddlewareStack` and `#!python SessionMiddlewareStack` (Optional)" +??? info "Add `#!python AuthMiddlewareStack` and `#!python SessionMiddlewareStack` (Optional)" There are many situations where you need to access the Django `#!python User` or `#!python Session` objects within ReactPy components. For example, if you want to: diff --git a/docs/src/learn/your-first-component.md b/docs/src/learn/your-first-component.md index e7ddcd65..87530f77 100644 --- a/docs/src/learn/your-first-component.md +++ b/docs/src/learn/your-first-component.md @@ -6,7 +6,7 @@ Components are one of the core concepts of ReactPy. They are the foundation upon

-!!! note +!!! abstract "Note" If you have reached this point, you should have already [installed ReactPy-Django](../learn/add-reactpy-to-a-django-project.md) through the previous steps. diff --git a/docs/src/reference/hooks.md b/docs/src/reference/hooks.md index 62986930..3233a5bb 100644 --- a/docs/src/reference/hooks.md +++ b/docs/src/reference/hooks.md @@ -6,7 +6,7 @@ Prefabricated hooks can be used within your `components.py` to help simplify dev

-!!! note +!!! abstract "Note" Looking for standard React hooks? diff --git a/docs/src/reference/settings.md b/docs/src/reference/settings.md index 3a013ed7..35f65b6e 100644 --- a/docs/src/reference/settings.md +++ b/docs/src/reference/settings.md @@ -2,15 +2,11 @@

- - These are ReactPy-Django's default settings values. You can modify these values in your **Django project's** `settings.py` to change the behavior of ReactPy. - -

-!!! note +!!! abstract "Note" The default configuration of ReactPy is suitable for the vast majority of use cases. @@ -18,34 +14,187 @@ These are ReactPy-Django's default settings values. You can modify these values --- - - ## General Settings -| Setting | Default Value | Example Value(s) | Description | -| --- | --- | --- | --- | -| `#!python REACTPY_URL_PREFIX` | `#!python "reactpy/"` | `#!python "rp/"`, `#!python "render/reactpy/"` | The prefix used for all ReactPy WebSocket and HTTP URLs. | -| `#!python REACTPY_DEFAULT_QUERY_POSTPROCESSOR` | `#!python "reactpy_django.utils.django_query_postprocessor"` | `#!python "example_project.postprocessor"`, `#!python None` | Dotted path to the default `#!python reactpy_django.hooks.use_query` postprocessor function. Postprocessor functions can be async or sync, and the function must contain a `#!python data` parameter. Set `#!python REACTPY_DEFAULT_QUERY_POSTPROCESSOR` to `#!python None` to globally disable the default postprocessor. | -| `#!python REACTPY_AUTH_BACKEND` | `#!python "django.contrib.auth.backends.ModelBackend"` | `#!python "example_project.auth.MyModelBackend"` | Dotted path to the Django authentication backend to use for ReactPy components. This is only needed if:
1. You are using `#!python AuthMiddlewareStack` and...
2. You are using Django's `#!python AUTHENTICATION_BACKENDS` setting and...
3. Your Django user model does not define a `#!python backend` attribute. | +--- + +### `#!python REACTPY_URL_PREFIX` + +**Default:** `#!python "reactpy/"` + +**Example Value(s):** `#!python "rp/"`, `#!python "render/reactpy/"` + +The prefix used for all ReactPy WebSocket and HTTP URLs. + +--- + +### `#!python REACTPY_DEFAULT_QUERY_POSTPROCESSOR` + +**Default:** `#!python "reactpy_django.utils.django_query_postprocessor"` + +**Example Value(s):** `#!python "example_project.postprocessor"`, `#!python None` + +Dotted path to the default `#!python reactpy_django.hooks.use_query` postprocessor function. + +Postprocessor functions can be async or sync. Here is an example of a sync postprocessor function: + +```python linenums="0" +def postprocessor(data): + del data["foo"] + return data +``` + +Set `#!python REACTPY_DEFAULT_QUERY_POSTPROCESSOR` to `#!python None` to disable the default postprocessor. + +--- + +### `#!python REACTPY_AUTH_BACKEND` + +**Default:** `#!python "django.contrib.auth.backends.ModelBackend"` + +**Example Value(s):** `#!python "example_project.auth.MyModelBackend"` + +Dotted path to the Django authentication backend to use for ReactPy components. This is only needed if: + +1. You are using `#!python AuthMiddlewareStack` and... +2. You are using Django's `#!python AUTHENTICATION_BACKENDS` setting and... +3. Your Django user model does not define a `#!python backend` attribute. + +--- ## Performance Settings -| Setting | Default Value | Example Value(s) | Description | -| --- | --- | --- | --- | -| `#!python REACTPY_DATABASE` | `#!python "default"` | `#!python "my-reactpy-database"` | Multiprocessing-safe database used to store ReactPy session data. If configuring `#!python REACTPY_DATABASE`, it is mandatory to enable our database router like such:
`#!python DATABASE_ROUTERS = ["reactpy_django.database.Router", ...]` | -| `#!python REACTPY_CACHE` | `#!python "default"` | `#!python "my-reactpy-cache"` | Cache used for ReactPy JavaScript modules. We recommend installing [`redis`](https://redis.io/) or [`python-diskcache`](https://grantjenks.com/docs/diskcache/tutorial.html#djangocache). | -| `#!python REACTPY_BACKHAUL_THREAD` | `#!python False` | `#!python True` | Configures whether ReactPy components are rendered in a dedicated thread. This allows the web server to process traffic during ReactPy rendering. Vastly improves throughput with web servers such as [`hypercorn`](https://pgjones.gitlab.io/hypercorn/) and [`uvicorn`](https://www.uvicorn.org/). | -| `#!python REACTPY_DEFAULT_HOSTS` | `#!python None` | `#!python ["localhost:8000", "localhost:8001", "localhost:8002/subdir"]` | The default host(s) that can render your ReactPy components. ReactPy will use these hosts in a round-robin fashion, allowing for easy distributed computing. You can use the `#!python host` argument in your [template tag](../reference/template-tag.md#component) as a manual override. | -| `#!python REACTPY_PRERENDER` | `#!python False` | `#!python True` | Configures whether to pre-render your components, which enables SEO compatibility and increases perceived responsiveness. You can use the `#!python prerender` argument in your [template tag](../reference/template-tag.md#component) as a manual override. During pre-rendering, there are some key differences in behavior:
1. Only the component's first render is pre-rendered.
2. All `#!python connection` related hooks use HTTP.
3. `#!python html.script` is executed during both pre-render and render.
4. Component is non-interactive until a WebSocket connection is formed. | +--- + +### `#!python REACTPY_DATABASE` + +**Default:** `#!python "default"` + +**Example Value(s):** `#!python "my-reactpy-database"` + +Multiprocessing-safe database used by ReactPy, typically for session data. + +If configuring this value, it is mandatory to enable our database router like such: + +```python linenums="0" +DATABASE_ROUTERS = ["reactpy_django.database.Router", ...] +``` + +--- + +### `#!python REACTPY_CACHE` + +**Default:** `#!python "default"` + +**Example Value(s):** `#!python "my-reactpy-cache"` + +Cache used by ReactPy, typically for file operations. + +We recommend configuring [`redis`](https://docs.djangoproject.com/en/dev/topics/cache/#redis), [`python-diskcache`](https://grantjenks.com/docs/diskcache/tutorial.html#djangocache), or [`LocMemCache`](https://docs.djangoproject.com/en/dev/topics/cache/#local-memory-caching). + +--- + +### `#!python REACTPY_BACKHAUL_THREAD` + +**Default:** `#!python False` + +**Example Value(s):** `#!python True` + +Configures whether ReactPy components are rendered in a dedicated thread. + +This setting allows the web server to process other traffic during ReactPy rendering. Vastly improves throughput with web servers such as [`hypercorn`](https://pgjones.gitlab.io/hypercorn/) and [`uvicorn`](https://www.uvicorn.org/). + +--- + +### `#!python REACTPY_DEFAULT_HOSTS` + +**Default:** `#!python None` + +**Example Value(s):** `#!python ["localhost:8000", "localhost:8001", "localhost:8002/subdir"]` + +The default host(s) that can render your ReactPy components. + +ReactPy will use these hosts in a round-robin fashion, allowing for easy distributed computing. + +You can use the `#!python host` argument in your [template tag](../reference/template-tag.md#component) to manually override this default. + +--- + +### `#!python REACTPY_PRERENDER` + +**Default:** `#!python False` + +**Example Value(s):** `#!python True` + +Configures whether to pre-render your components, which enables SEO compatibility and reduces perceived latency. + +During pre-rendering, there are some key differences in behavior: + +1. Only the component's first render is pre-rendered. +2. All `#!python connection` related hooks use HTTP. +3. `#!python html.script` elements are executed twice (pre-render and post-render). +4. The component will be non-interactive until a WebSocket connection is formed. + +You can use the `#!python prerender` argument in your [template tag](../reference/template-tag.md#component) to manually override this default. + +--- ## Stability Settings -| Setting | Default Value | Example Value(s) | Description | -| --- | --- | --- | --- | -| `#!python REACTPY_RECONNECT_INTERVAL` | `#!python 750` | `#!python 100`, `#!python 2500`, `#!python 6000` | Milliseconds between client reconnection attempts. | -| `#!python REACTPY_RECONNECT_BACKOFF_MULTIPLIER` | `#!python 1.25` | `#!python 1`, `#!python 1.5`, `#!python 3` | On each reconnection attempt, the `#!python REACTPY_RECONNECT_INTERVAL` will be multiplied by this value to increase the time between attempts. You can keep time between each reconnection the same by setting this to `#!python 1`. | -| `#!python REACTPY_RECONNECT_MAX_INTERVAL` | `#!python 60000` | `#!python 10000`, `#!python 25000`, `#!python 900000` | Maximum milliseconds between client reconnection attempts. This allows setting an upper bound on how high `#!python REACTPY_RECONNECT_BACKOFF_MULTIPLIER` can increase the time between reconnection attempts. | -| `#!python REACTPY_RECONNECT_MAX_RETRIES` | `#!python 150` | `#!python 0`, `#!python 5`, `#!python 300` | Maximum number of reconnection attempts before the client gives up. | -| `#!python REACTPY_SESSION_MAX_AGE` | `#!python 259200` | `#!python 0`, `#!python 60`, `#!python 96000` | Maximum seconds to store ReactPy component sessions. This includes data such as `#!python *args` and `#!python **kwargs` passed into your component template tag. Use `#!python 0` to not store any session data. | +--- + +### `#!python REACTPY_RECONNECT_INTERVAL` + +**Default:** `#!python 750` + +**Example Value(s):** `#!python 100`, `#!python 2500`, `#!python 6000` + +Milliseconds between client reconnection attempts. + +--- + +### `#!python REACTPY_RECONNECT_BACKOFF_MULTIPLIER` + +**Default:** `#!python 1.25` + +**Example Value(s):** `#!python 1`, `#!python 1.5`, `#!python 3` + +On each reconnection attempt, the `#!python REACTPY_RECONNECT_INTERVAL` will be multiplied by this value to increase the time between attempts. + +You can keep time between each reconnection the same by setting this to `#!python 1`. + +--- + +### `#!python REACTPY_RECONNECT_MAX_INTERVAL` + +**Default:** `#!python 60000` + +**Example Value(s):** `#!python 10000`, `#!python 25000`, `#!python 900000` + +Maximum milliseconds between client reconnection attempts. + +This allows setting an upper bound on how high `#!python REACTPY_RECONNECT_BACKOFF_MULTIPLIER` can increase the time between reconnection attempts. + +--- + +### `#!python REACTPY_RECONNECT_MAX_RETRIES` + +**Default:** `#!python 150` + +**Example Value(s):** `#!python 0`, `#!python 5`, `#!python 300` + +Maximum number of reconnection attempts before the client gives up. + +--- + +### `#!python REACTPY_SESSION_MAX_AGE` + +**Default:** `#!python 259200` + +**Example Value(s):** `#!python 0`, `#!python 60`, `#!python 96000` + +Maximum seconds to store ReactPy component sessions. + +ReactPy sessions include data such as `#!python *args` and `#!python **kwargs` passed into your `#!jinja {% component %}` template tag. - +Use `#!python 0` to not store any session data. diff --git a/docs/src/reference/template-tag.md b/docs/src/reference/template-tag.md index b9b9017f..39974eb7 100644 --- a/docs/src/reference/template-tag.md +++ b/docs/src/reference/template-tag.md @@ -27,7 +27,7 @@ This template tag can be used to insert any number of ReactPy components onto yo | `#!python class` | `#!python str | None` | The HTML class to apply to the top-level component div. | `#!python None` | | `#!python key` | `#!python Any` | Force the component's root node to use a [specific key value](https://reactpy.dev/docs/guides/creating-interfaces/rendering-data/index.html#organizing-items-with-keys). Using `#!python key` within a template tag is effectively useless. | `#!python None` | | `#!python host` | `#!python str | None` | The host to use for the ReactPy connections. If unset, the host will be automatically configured.
Example values include: `localhost:8000`, `example.com`, `example.com/subdir` | `#!python None` | - | `#!python prerender` | `#!python str` | If `#!python "True"`, the component will pre-rendered, which enables SEO compatibility and increases perceived responsiveness. | `#!python "False"` | + | `#!python prerender` | `#!python str` | If `#!python "True"`, the component will pre-rendered, which enables SEO compatibility and reduces perceived latency. | `#!python "False"` | | `#!python **kwargs` | `#!python Any` | The keyword arguments to provide to the component. | N/A | **Returns** diff --git a/mkdocs.yml b/mkdocs.yml index 9269b109..af88f66b 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -46,6 +46,8 @@ theme: - search.highlight icon: repo: fontawesome/brands/github + admonition: + note: fontawesome/solid/note-sticky logo: https://raw.githubusercontent.com/reactive-python/reactpy/main/branding/svg/reactpy-logo-square.svg favicon: https://raw.githubusercontent.com/reactive-python/reactpy/main/branding/svg/reactpy-logo-square.svg diff --git a/src/reactpy_django/templatetags/reactpy.py b/src/reactpy_django/templatetags/reactpy.py index d9e0bf5e..209c0ec8 100644 --- a/src/reactpy_django/templatetags/reactpy.py +++ b/src/reactpy_django/templatetags/reactpy.py @@ -54,7 +54,7 @@ def component( the host will be automatically configured. \ Example values include: `localhost:8000`, `example.com`, `example.com/subdir` prerender: Configures whether to pre-render this component, which \ - enables SEO compatibility and increases perceived responsiveness. + enables SEO compatibility and reduces perceived latency. **kwargs: The keyword arguments to provide to the component. Example ::