diff --git a/develop/404.html b/develop/404.html index e65c03ea..d5c51c0e 100644 --- a/develop/404.html +++ b/develop/404.html @@ -1 +1 @@ - ReactPy-Django
\ No newline at end of file + ReactPy-Django
\ No newline at end of file diff --git a/develop/about/changelog/index.html b/develop/about/changelog/index.html index 793e310a..926dd440 100644 --- a/develop/about/changelog/index.html +++ b/develop/about/changelog/index.html @@ -1 +1 @@ - Changelog - ReactPy-Django
Skip to content

Changelog

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.


Unreleased

Added

  • ReactPy components can now use SEO compatible rendering!
    • settings.py:REACTPY_PRERENDER can be set to True to enable this behavior by default
    • Or, you can enable it on individual components via the template tag: {% component "..." prerender="True" %}

Changed

  • Renamed undocumented utility function reactpy_django.utils.ComponentPreloader to reactpy_django.utils.RootComponentFinder.

3.5.1 - 2023-09-07

Added

  • Warning W018 (Suspicious position of 'reactpy_django' in INSTALLED_APPS) has been added.

Changed

  • The default postprocessor can now disabled by setting REACTPY_DEFAULT_QUERY_POSTPROCESSOR to None.
  • Massive overhaul of docs styling.

3.5.0 - 2023-08-26

Added

  • More customization for reconnection behavior through new settings!
    • REACTPY_RECONNECT_INTERVAL
    • REACTPY_RECONNECT_MAX_INTERVAL
    • REACTPY_RECONNECT_MAX_RETRIES
    • REACTPY_RECONNECT_BACKOFF_MULTIPLIER
  • ReactPy-Django docs are now version controlled via mike!

Changed

  • Bumped the minimum ReactPy version to 1.0.2.
  • Prettier WebSocket URLs for components that do not have sessions.
  • Template tag will now only validate args/kwargs if settings.py:DEBUG is enabled.
  • Bumped the minimum @reactpy/client version to 0.3.1
  • Bumped the minimum Django version to 4.2.
  • Use TypeScript instead of JavaScript for this repository.
    • Note: ReactPy-Django will continue bumping minimum Django requirements to versions that increase async support. This "latest-only" trend will continue until Django has all async features that ReactPy benefits from. After this point, ReactPy-Django will begin supporting all maintained Django versions.

Removed

  • settings.py:REACTPY_RECONNECT_MAX is removed. See the docs for the new REACTPY_RECONNECT_* settings.

3.4.0 - 2023-08-18

Added

  • Distributed Computing: ReactPy components can now optionally be rendered by a completely separate server!
    • REACTPY_DEFAULT_HOSTS setting can round-robin a list of ReactPy rendering hosts.
    • host argument has been added to the component template tag to force components to render on a specific host.
  • reactpy_django.utils.register_component function can manually register root components.
    • Useful if you have dedicated ReactPy rendering application(s) that do not use HTML templates.

Changed

  • ReactPy will now provide a warning if your HTTP URLs are not on the same prefix as your WebSockets.
  • Cleaner logging output for auto-detected ReactPy root components.

Deprecated

  • reactpy_django.REACTPY_WEBSOCKET_PATH is deprecated. The identical replacement is REACTPY_WEBSOCKET_ROUTE.
  • settings.py:REACTPY_WEBSOCKET_URL is deprecated. The similar replacement is REACTPY_URL_PREFIX.

Removed

  • Warning W007 (REACTPY_WEBSOCKET_URL doesn't end with a slash) has been removed. ReactPy now automatically handles slashes.
  • Warning W008 (REACTPY_WEBSOCKET_URL doesn't start with an alphanumeric character) has been removed. ReactPy now automatically handles this scenario.
  • Error E009 (channels is not in settings.py:INSTALLED_APPS) has been removed. Newer versions of channels do not require installation via INSTALLED_APPS to receive an ASGI web server.

3.3.2 - 2023-08-13

Added

  • ReactPy WebSocket will now decode messages via orjson resulting in an ~6% overall performance improvement.
  • Built-in asyncio event loops are now patched via nest_asyncio, resulting in an ~10% overall performance improvement. This has no performance impact if you are running your web server with uvloop.

Fixed

  • Fix bug where REACTPY_WEBSOCKET_URL always generates a warning if unset.
  • Fixed bug on Windows where assert f is self._write_fut would be raised by uvicorn when REACTPY_BACKHAUL_THREAD = True.
  • Fixed bug on Windows where rendering behavior would be jittery with daphne when REACTPY_BACKHAUL_THREAD = True.

3.3.1 - 2023-08-08

Added

  • Additional system checks for ReactPy misconfigurations.

Changed

  • REACTPY_BACKHAUL_THREAD now defaults to False.

3.3.0 - 2023-08-05

Added

  • Added system checks for a variety of common ReactPy misconfigurations.
  • REACTPY_BACKHAUL_THREAD setting to enable/disable threading behavior.

Changed

  • If using settings.py:REACTPY_DATABASE, reactpy_django.database.Router must now be registered in settings.py:DATABASE_ROUTERS.
  • By default, ReactPy will now use a backhaul thread to increase performance.
  • Minimum Python version required is now 3.9
  • A thread-safe cache is no longer required.

3.2.1 - 2023-06-29

Added

  • Template tag exception details are now rendered on the webpage when settings.py:DEBUG is enabled.

Fixed

  • Prevent exceptions within the component template tag from causing the whole template to fail to render.

3.2.0 - 2023-06-08

Added

  • Added warning if poor system/cache/database performance is detected while in DEBUG mode.
  • Added REACTPY_AUTH_BACKEND setting to allow for custom authentication backends.

Changed

  • Using SessionMiddlewareStack is now optional.
  • Using AuthMiddlewareStack is now optional.

3.1.0 - 2023-05-06

Added

  • use_query now supports async functions.
  • use_mutation now supports async functions.
  • reactpy_django.types.QueryOptions.thread_sensitive option to customize how sync queries are executed.
  • reactpy_django.hooks.use_mutation now accepts reactpy_django.types.MutationOptions option to customize how mutations are executed.

Changed

  • The mutate argument on reactpy_django.hooks.use_mutation has been renamed to mutation.

Fixed

  • Fix bug where ReactPy utilizes Django's default cache timeout, which can prematurely expire the component cache.

3.0.1 - 2023-04-06

Changed

  • django-reactpy database entries are no longer cleaned during Django application startup. Instead, it will occur on webpage loads if REACTPY_RECONNECT_MAX seconds has elapsed since the last cleaning.

3.0.0-reactpy - 2023-03-30

Changed

  • django-idom has been renamed to reactpy-django! Please note that all references to the word idom in your code should be changed to reactpy. See the docs for more details.

3.0.0 - 2023-03-08

Note

This is Django-IDOM's biggest update yet!

To upgrade from previous version you will need to...

  1. Install django-idom >= 3.0.0
  2. Run idom rewrite-keys <DIR> and idom rewrite-camel-case-props <DIR> to update your idom.html.* calls to the new syntax
  3. Run python manage.py migrate to create the new Django-IDOM database entries

Added

  • The idom client will automatically configure itself to debug mode depending on settings.py:DEBUG.
  • use_connection hook for returning the browser's active Connection.
  • IDOM_CACHE is now configurable within settings.py to whatever cache name you wish.

Changed

  • It is now mandatory to run manage.py migrate after installing IDOM.
  • Bumped the minimum IDOM version to 1.0.0. Due to IDOM 1.0.0, idom.html.*...
    • HTML properties can now be snake_case. For example className now becomes class_name.
    • key=... is now declared within the props dict (rather than as a kwarg).
  • The component template tag now supports both positional and keyword arguments.
  • The component template tag now supports non-serializable arguments.
  • IDOM_WS_MAX_RECONNECT_TIMEOUT setting has been renamed to IDOM_RECONNECT_MAX.

Removed

  • django_idom.hooks.use_websocket has been removed. The similar replacement is django_idom.hooks.use_connection.
  • django_idom.types.IdomWebsocket has been removed. The similar replacement is django_idom.types.Connection.
  • settings.py:CACHE['idom'] is no longer used by default. The name of the cache back-end must now be specified with the IDOM_CACHE setting.

Fixed

  • view_to_component will now retain the contents of a <head> tag when rendering.
  • React client is now set to production rather than development.
  • use_query will now utilize field.related_name when postprocessing many-to-one relationships.

Security

  • Fixed a potential method of component template tag argument spoofing.
  • Exception information will no longer be displayed on the page, based on the value of settings.py:DEBUG.

2.2.1 - 2023-01-09

Fixed

  • Fixed bug where use_query would not recursively fetch many-to-one relationships.
  • IDOM preloader will now print out the exception stack when failing to import a module.

2.2.0 - 2022-12-28

Added

  • Add options: QueryOptions parameter to use_query to allow for configuration of this hook.

Changed

  • By default, use_query will recursively prefetch all many-to-many or many-to-one relationships to prevent SynchronousOnlyOperation exceptions.

Removed

  • django_idom.hooks._fetch_lazy_fields has been deleted. The equivalent replacement is django_idom.utils.django_query_postprocessor.

2.1.0 - 2022-11-01

Changed

  • Minimum channels version is now 4.0.0.

Fixed

  • Change type hint on view_to_component callable to have request argument be optional.
  • Change type hint on view_to_component to represent it as a decorator with parenthesis (such as @view_to_component(compatibility=True))

Security

  • Add note to docs about potential information exposure via view_to_component when using compatibility=True.

2.0.1 - 2022-10-18

Fixed

  • Ability to use key=... parameter on all prefabricated components.

2.0.0 - 2022-10-17

Added

  • use_origin hook for returning the browser's location.origin.

Changed

  • view_to_component now returns a Callable, instead of directly returning a Component. Check the docs for new usage info.
  • use_mutation and use_query will now log any query failures.

Fixed

  • Allow use_mutation to have refetch=None, as the docs suggest is possible.
  • use_query will now prefetch all fields to prevent SynchronousOnlyOperation exceptions.
  • view_to_component, django_css, and django_js type hints will now display like normal functions.
  • IDOM preloader no longer attempts to parse commented out IDOM components.
  • Tests are now fully functional on Windows

1.2.0 - 2022-09-19

Added

  • auth_required decorator to prevent your components from rendering to unauthenticated users.
  • use_query hook for fetching database values.
  • use_mutation hook for modifying database values.
  • view_to_component utility to convert legacy Django views to IDOM components.

Changed

  • Bumped the minimum IDOM version to 0.40.2
  • Testing suite now uses playwright instead of selenium

Fixed

  • IDOM preloader is no longer sensitive to whitespace within template tags.

1.1.0 - 2022-07-01

Added

  • django_css and django_js components to defer loading CSS & JS files until needed.

Changed

  • Bumped the minimum IDOM version to 0.39.0

1.0.0 - 2022-05-22

Added

  • Django specific hooks! use_websocket, use_scope, and use_location are now available within the django_idom.hooks module.
  • Documentation has been placed into a formal docs webpage.
  • Logging for when a component fails to import, or if no components were found within Django.

Changed

  • idom_component template tag has been renamed to component
  • Bumped the minimum IDOM version to 0.38.0

Removed

  • websocket parameter for components has been removed. Functionally, it is replaced with django_idom.hooks.use_websocket.

0.0.5 - 2022-04-04

Changed

  • Bumped the minimum IDOM version to 0.37.2

Fixed

  • ModuleNotFoundError: No module named idom.core.proto caused by IDOM 0.37.2

0.0.4 - 2022-03-05

Changed

  • Bumped the minimum IDOM version to 0.37.1

0.0.3 - 2022-02-19

Changed

  • Bumped the minimum IDOM version to 0.36.3

0.0.2 - 2022-01-30

Added

  • Ability to declare the HTML class of the top-level component div
  • name = ... parameter to IDOM HTTP paths for use with django.urls.reverse()
  • Cache versioning to automatically invalidate old web module files from the cache back-end
  • Automatic pre-population of the IDOM component registry
  • Type hinting for IdomWebsocket

Changed

  • Fetching web modules from disk and/or cache is now fully async
  • Static files are now contained within a django_idom/ parent folder
  • Upgraded IDOM to version 0.36.0
  • Minimum Django version required is now 4.0
  • Minimum Python version required is now 3.8

Removed

  • IDOM_WEB_MODULES_PATH has been replaced with Django include(...)
  • IDOM_WS_MAX_RECONNECT_DELAY has been renamed to IDOM_WS_MAX_RECONNECT_TIMEOUT
  • idom_web_modules cache back-end has been renamed to idom

Fixed

  • Increase test timeout values to prevent false positives
  • Windows compatibility for building Django-IDOM

Security

  • Fixed potential directory traversal attack on the IDOM web modules URL

0.0.1 - 2021-08-18

Added

  • Support for IDOM within the Django

Last update: September 7, 2023
Authors: Mark Bakhit
\ No newline at end of file + Changelog - ReactPy-Django
Skip to content

Changelog

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.


Unreleased

Added

  • ReactPy components can now use SEO compatible rendering!
    • settings.py:REACTPY_PRERENDER can be set to True to enable this behavior by default
    • Or, you can enable it on individual components via the template tag: {% component "..." prerender="True" %}

Changed

  • Renamed undocumented utility function reactpy_django.utils.ComponentPreloader to reactpy_django.utils.RootComponentFinder.

3.5.1 - 2023-09-07

Added

  • Warning W018 (Suspicious position of 'reactpy_django' in INSTALLED_APPS) has been added.

Changed

  • The default postprocessor can now disabled by setting REACTPY_DEFAULT_QUERY_POSTPROCESSOR to None.
  • Massive overhaul of docs styling.

3.5.0 - 2023-08-26

Added

  • More customization for reconnection behavior through new settings!
    • REACTPY_RECONNECT_INTERVAL
    • REACTPY_RECONNECT_MAX_INTERVAL
    • REACTPY_RECONNECT_MAX_RETRIES
    • REACTPY_RECONNECT_BACKOFF_MULTIPLIER
  • ReactPy-Django docs are now version controlled via mike!

Changed

  • Bumped the minimum ReactPy version to 1.0.2.
  • Prettier WebSocket URLs for components that do not have sessions.
  • Template tag will now only validate args/kwargs if settings.py:DEBUG is enabled.
  • Bumped the minimum @reactpy/client version to 0.3.1
  • Bumped the minimum Django version to 4.2.
  • Use TypeScript instead of JavaScript for this repository.
    • Note: ReactPy-Django will continue bumping minimum Django requirements to versions that increase async support. This "latest-only" trend will continue until Django has all async features that ReactPy benefits from. After this point, ReactPy-Django will begin supporting all maintained Django versions.

Removed

  • settings.py:REACTPY_RECONNECT_MAX is removed. See the docs for the new REACTPY_RECONNECT_* settings.

3.4.0 - 2023-08-18

Added

  • Distributed Computing: ReactPy components can now optionally be rendered by a completely separate server!
    • REACTPY_DEFAULT_HOSTS setting can round-robin a list of ReactPy rendering hosts.
    • host argument has been added to the component template tag to force components to render on a specific host.
  • reactpy_django.utils.register_component function can manually register root components.
    • Useful if you have dedicated ReactPy rendering application(s) that do not use HTML templates.

Changed

  • ReactPy will now provide a warning if your HTTP URLs are not on the same prefix as your WebSockets.
  • Cleaner logging output for auto-detected ReactPy root components.

Deprecated

  • reactpy_django.REACTPY_WEBSOCKET_PATH is deprecated. The identical replacement is REACTPY_WEBSOCKET_ROUTE.
  • settings.py:REACTPY_WEBSOCKET_URL is deprecated. The similar replacement is REACTPY_URL_PREFIX.

Removed

  • Warning W007 (REACTPY_WEBSOCKET_URL doesn't end with a slash) has been removed. ReactPy now automatically handles slashes.
  • Warning W008 (REACTPY_WEBSOCKET_URL doesn't start with an alphanumeric character) has been removed. ReactPy now automatically handles this scenario.
  • Error E009 (channels is not in settings.py:INSTALLED_APPS) has been removed. Newer versions of channels do not require installation via INSTALLED_APPS to receive an ASGI web server.

3.3.2 - 2023-08-13

Added

  • ReactPy WebSocket will now decode messages via orjson resulting in an ~6% overall performance improvement.
  • Built-in asyncio event loops are now patched via nest_asyncio, resulting in an ~10% overall performance improvement. This has no performance impact if you are running your web server with uvloop.

Fixed

  • Fix bug where REACTPY_WEBSOCKET_URL always generates a warning if unset.
  • Fixed bug on Windows where assert f is self._write_fut would be raised by uvicorn when REACTPY_BACKHAUL_THREAD = True.
  • Fixed bug on Windows where rendering behavior would be jittery with daphne when REACTPY_BACKHAUL_THREAD = True.

3.3.1 - 2023-08-08

Added

  • Additional system checks for ReactPy misconfigurations.

Changed

  • REACTPY_BACKHAUL_THREAD now defaults to False.

3.3.0 - 2023-08-05

Added

  • Added system checks for a variety of common ReactPy misconfigurations.
  • REACTPY_BACKHAUL_THREAD setting to enable/disable threading behavior.

Changed

  • If using settings.py:REACTPY_DATABASE, reactpy_django.database.Router must now be registered in settings.py:DATABASE_ROUTERS.
  • By default, ReactPy will now use a backhaul thread to increase performance.
  • Minimum Python version required is now 3.9
  • A thread-safe cache is no longer required.

3.2.1 - 2023-06-29

Added

  • Template tag exception details are now rendered on the webpage when settings.py:DEBUG is enabled.

Fixed

  • Prevent exceptions within the component template tag from causing the whole template to fail to render.

3.2.0 - 2023-06-08

Added

  • Added warning if poor system/cache/database performance is detected while in DEBUG mode.
  • Added REACTPY_AUTH_BACKEND setting to allow for custom authentication backends.

Changed

  • Using SessionMiddlewareStack is now optional.
  • Using AuthMiddlewareStack is now optional.

3.1.0 - 2023-05-06

Added

  • use_query now supports async functions.
  • use_mutation now supports async functions.
  • reactpy_django.types.QueryOptions.thread_sensitive option to customize how sync queries are executed.
  • reactpy_django.hooks.use_mutation now accepts reactpy_django.types.MutationOptions option to customize how mutations are executed.

Changed

  • The mutate argument on reactpy_django.hooks.use_mutation has been renamed to mutation.

Fixed

  • Fix bug where ReactPy utilizes Django's default cache timeout, which can prematurely expire the component cache.

3.0.1 - 2023-04-06

Changed

  • django-reactpy database entries are no longer cleaned during Django application startup. Instead, it will occur on webpage loads if REACTPY_RECONNECT_MAX seconds has elapsed since the last cleaning.

3.0.0-reactpy - 2023-03-30

Changed

  • django-idom has been renamed to reactpy-django! Please note that all references to the word idom in your code should be changed to reactpy. See the docs for more details.

3.0.0 - 2023-03-08

Note

This is Django-IDOM's biggest update yet!

To upgrade from previous version you will need to...

  1. Install django-idom >= 3.0.0
  2. Run idom rewrite-keys <DIR> and idom rewrite-camel-case-props <DIR> to update your idom.html.* calls to the new syntax
  3. Run python manage.py migrate to create the new Django-IDOM database entries

Added

  • The idom client will automatically configure itself to debug mode depending on settings.py:DEBUG.
  • use_connection hook for returning the browser's active Connection.
  • IDOM_CACHE is now configurable within settings.py to whatever cache name you wish.

Changed

  • It is now mandatory to run manage.py migrate after installing IDOM.
  • Bumped the minimum IDOM version to 1.0.0. Due to IDOM 1.0.0, idom.html.*...
    • HTML properties can now be snake_case. For example className now becomes class_name.
    • key=... is now declared within the props dict (rather than as a kwarg).
  • The component template tag now supports both positional and keyword arguments.
  • The component template tag now supports non-serializable arguments.
  • IDOM_WS_MAX_RECONNECT_TIMEOUT setting has been renamed to IDOM_RECONNECT_MAX.

Removed

  • django_idom.hooks.use_websocket has been removed. The similar replacement is django_idom.hooks.use_connection.
  • django_idom.types.IdomWebsocket has been removed. The similar replacement is django_idom.types.Connection.
  • settings.py:CACHE['idom'] is no longer used by default. The name of the cache back-end must now be specified with the IDOM_CACHE setting.

Fixed

  • view_to_component will now retain the contents of a <head> tag when rendering.
  • React client is now set to production rather than development.
  • use_query will now utilize field.related_name when postprocessing many-to-one relationships.

Security

  • Fixed a potential method of component template tag argument spoofing.
  • Exception information will no longer be displayed on the page, based on the value of settings.py:DEBUG.

2.2.1 - 2023-01-09

Fixed

  • Fixed bug where use_query would not recursively fetch many-to-one relationships.
  • IDOM preloader will now print out the exception stack when failing to import a module.

2.2.0 - 2022-12-28

Added

  • Add options: QueryOptions parameter to use_query to allow for configuration of this hook.

Changed

  • By default, use_query will recursively prefetch all many-to-many or many-to-one relationships to prevent SynchronousOnlyOperation exceptions.

Removed

  • django_idom.hooks._fetch_lazy_fields has been deleted. The equivalent replacement is django_idom.utils.django_query_postprocessor.

2.1.0 - 2022-11-01

Changed

  • Minimum channels version is now 4.0.0.

Fixed

  • Change type hint on view_to_component callable to have request argument be optional.
  • Change type hint on view_to_component to represent it as a decorator with parenthesis (such as @view_to_component(compatibility=True))

Security

  • Add note to docs about potential information exposure via view_to_component when using compatibility=True.

2.0.1 - 2022-10-18

Fixed

  • Ability to use key=... parameter on all prefabricated components.

2.0.0 - 2022-10-17

Added

  • use_origin hook for returning the browser's location.origin.

Changed

  • view_to_component now returns a Callable, instead of directly returning a Component. Check the docs for new usage info.
  • use_mutation and use_query will now log any query failures.

Fixed

  • Allow use_mutation to have refetch=None, as the docs suggest is possible.
  • use_query will now prefetch all fields to prevent SynchronousOnlyOperation exceptions.
  • view_to_component, django_css, and django_js type hints will now display like normal functions.
  • IDOM preloader no longer attempts to parse commented out IDOM components.
  • Tests are now fully functional on Windows

1.2.0 - 2022-09-19

Added

  • auth_required decorator to prevent your components from rendering to unauthenticated users.
  • use_query hook for fetching database values.
  • use_mutation hook for modifying database values.
  • view_to_component utility to convert legacy Django views to IDOM components.

Changed

  • Bumped the minimum IDOM version to 0.40.2
  • Testing suite now uses playwright instead of selenium

Fixed

  • IDOM preloader is no longer sensitive to whitespace within template tags.

1.1.0 - 2022-07-01

Added

  • django_css and django_js components to defer loading CSS & JS files until needed.

Changed

  • Bumped the minimum IDOM version to 0.39.0

1.0.0 - 2022-05-22

Added

  • Django specific hooks! use_websocket, use_scope, and use_location are now available within the django_idom.hooks module.
  • Documentation has been placed into a formal docs webpage.
  • Logging for when a component fails to import, or if no components were found within Django.

Changed

  • idom_component template tag has been renamed to component
  • Bumped the minimum IDOM version to 0.38.0

Removed

  • websocket parameter for components has been removed. Functionally, it is replaced with django_idom.hooks.use_websocket.

0.0.5 - 2022-04-04

Changed

  • Bumped the minimum IDOM version to 0.37.2

Fixed

  • ModuleNotFoundError: No module named idom.core.proto caused by IDOM 0.37.2

0.0.4 - 2022-03-05

Changed

  • Bumped the minimum IDOM version to 0.37.1

0.0.3 - 2022-02-19

Changed

  • Bumped the minimum IDOM version to 0.36.3

0.0.2 - 2022-01-30

Added

  • Ability to declare the HTML class of the top-level component div
  • name = ... parameter to IDOM HTTP paths for use with django.urls.reverse()
  • Cache versioning to automatically invalidate old web module files from the cache back-end
  • Automatic pre-population of the IDOM component registry
  • Type hinting for IdomWebsocket

Changed

  • Fetching web modules from disk and/or cache is now fully async
  • Static files are now contained within a django_idom/ parent folder
  • Upgraded IDOM to version 0.36.0
  • Minimum Django version required is now 4.0
  • Minimum Python version required is now 3.8

Removed

  • IDOM_WEB_MODULES_PATH has been replaced with Django include(...)
  • IDOM_WS_MAX_RECONNECT_DELAY has been renamed to IDOM_WS_MAX_RECONNECT_TIMEOUT
  • idom_web_modules cache back-end has been renamed to idom

Fixed

  • Increase test timeout values to prevent false positives
  • Windows compatibility for building Django-IDOM

Security

  • Fixed potential directory traversal attack on the IDOM web modules URL

0.0.1 - 2021-08-18

Added

  • Support for IDOM within the Django

Last update: September 7, 2023
Authors: Mark Bakhit
\ No newline at end of file diff --git a/develop/about/code/index.html b/develop/about/code/index.html index ba62c0d6..664836c9 100644 --- a/develop/about/code/index.html +++ b/develop/about/code/index.html @@ -1,4 +1,4 @@ - Code - ReactPy-Django
Skip to content

Code

Overview

You will need to set up a Python environment to develop ReactPy-Django.

Note

Looking to contribute features that are not Django specific?

Everything within the reactpy-django repository must be specific to Django integration. Check out the ReactPy Core documentation to contribute general features such as components, hooks, and events.


Creating an environment

If you plan to make code changes to this repository, you will need to install the following dependencies first:

Once done, you should clone this repository:

git clone https://github.com/reactive-python/reactpy-django.git
+ Code - ReactPy-Django       

Code

Overview

You will need to set up a Python environment to develop ReactPy-Django.

Note

Looking to contribute features that are not Django specific?

Everything within the reactpy-django repository must be specific to Django integration. Check out the ReactPy Core documentation to contribute general features such as components, hooks, and events.


Creating an environment

If you plan to make code changes to this repository, you will need to install the following dependencies first:

Once done, you should clone this repository:

git clone https://github.com/reactive-python/reactpy-django.git
 cd reactpy-django
 

Then, by running the command below you can:

  • Install an editable version of the Python code
  • Download, build, and install Javascript dependencies
pip install -e . -r requirements.txt --verbose --upgrade
 

Pitfall

Some of our development dependencies require a C++ compiler, which is not installed by default on Windows.

If you receive errors related to this during installation, follow the instructions in your console errors.

Finally, to verify that everything is working properly, you can manually run the test web server.

cd tests
@@ -9,4 +9,4 @@
 python manage.py test
 

Running Django test web server

If you want to manually run the Django test application, you can use the following command:

cd tests
 python manage.py runserver
-

Last update: September 16, 2023
Authors: Mark Bakhit
\ No newline at end of file +

Last update: September 16, 2023
Authors: Mark Bakhit
\ No newline at end of file diff --git a/develop/about/docs/index.html b/develop/about/docs/index.html index e6640c42..edd0cf8e 100644 --- a/develop/about/docs/index.html +++ b/develop/about/docs/index.html @@ -1,5 +1,5 @@ - Docs - ReactPy-Django
Skip to content

Docs

Overview

You will need to set up a Python environment to create, test, and preview docs changes.


Modifying Docs

If you plan to make changes to this documentation, you will need to install the following dependencies first:

Once done, you should clone this repository:

git clone https://github.com/reactive-python/reactpy-django.git
+ Docs - ReactPy-Django       

Docs

Overview

You will need to set up a Python environment to create, test, and preview docs changes.


Modifying Docs

If you plan to make changes to this documentation, you will need to install the following dependencies first:

Once done, you should clone this repository:

git clone https://github.com/reactive-python/reactpy-django.git
 cd reactpy-django
 

Then, by running the command below you can:

  • Install an editable version of the documentation
  • Self-host a test server for the documentation
pip install -r requirements.txt --upgrade
 

Finally, to verify that everything is working properly, you can manually run the docs preview web server.

mkdocs serve
-

Navigate to http://127.0.0.1:8000 to view a preview of the documentation.

GitHub Pull Request

Now, you can create/modify the ReactPy-Django source code, and Pull Request (PR) your changes to our GitHub repository.

To learn how to create GitHub PRs, click here.


Last update: September 16, 2023
Authors: Mark Bakhit
\ No newline at end of file +

Navigate to http://127.0.0.1:8000 to view a preview of the documentation.

GitHub Pull Request

Now, you can create/modify the ReactPy-Django source code, and Pull Request (PR) your changes to our GitHub repository.

To learn how to create GitHub PRs, click here.


Last update: September 16, 2023
Authors: Mark Bakhit
\ No newline at end of file diff --git a/develop/about/license/index.html b/develop/about/license/index.html new file mode 100644 index 00000000..ee9a1782 --- /dev/null +++ b/develop/about/license/index.html @@ -0,0 +1 @@ + License - ReactPy-Django
Skip to content

License


The MIT License (MIT)

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Last update: September 21, 2023
Authors: Mark Bakhit
\ No newline at end of file diff --git a/develop/assets/css/banner.css b/develop/assets/css/banner.css new file mode 100644 index 00000000..b3cb5ef4 --- /dev/null +++ b/develop/assets/css/banner.css @@ -0,0 +1,15 @@ +body[data-md-color-scheme="slate"] { + --md-banner-bg-color: #4d4121; + --md-banner-font-color: #fff; +} + +body[data-md-color-scheme="default"] { + --md-banner-bg-color: #ff9; + --md-banner-font-color: #000; +} + +.md-banner--warning { + background-color: var(--md-banner-bg-color); + color: var(--md-banner-font-color); + text-align: center; +} diff --git a/develop/assets/css/footer.css b/develop/assets/css/footer.css index 9dcaca2d..b3408286 100644 --- a/develop/assets/css/footer.css +++ b/develop/assets/css/footer.css @@ -27,3 +27,7 @@ .legal-footer-right { float: right; } + +.md-copyright__highlight div { + display: inline; +} diff --git a/develop/assets/stylesheets/main.046329b4.min.css b/develop/assets/stylesheets/main.046329b4.min.css deleted file mode 100644 index 77ac5aae..00000000 --- a/develop/assets/stylesheets/main.046329b4.min.css +++ /dev/null @@ -1 +0,0 @@ -@charset "UTF-8";html{-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none;box-sizing:border-box}*,:after,:before{box-sizing:inherit}@media (prefers-reduced-motion){*,:after,:before{transition:none!important}}body{margin:0}a,button,input,label{-webkit-tap-highlight-color:transparent}a{color:inherit;text-decoration:none}hr{border:0;box-sizing:initial;display:block;height:.05rem;overflow:visible;padding:0}small{font-size:80%}sub,sup{line-height:1em}img{border-style:none}table{border-collapse:initial;border-spacing:0}td,th{font-weight:400;vertical-align:top}button{background:#0000;border:0;font-family:inherit;font-size:inherit;margin:0;padding:0}input{border:0;outline:none}:root{--md-primary-fg-color:#4051b5;--md-primary-fg-color--light:#5d6cc0;--md-primary-fg-color--dark:#303fa1;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3;--md-accent-fg-color:#526cfe;--md-accent-fg-color--transparent:#526cfe1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-scheme=default]{color-scheme:light}[data-md-color-scheme=default] img[src$="#gh-dark-mode-only"],[data-md-color-scheme=default] img[src$="#only-dark"]{display:none}:root,[data-md-color-scheme=default]{--md-default-fg-color:#000000de;--md-default-fg-color--light:#0000008a;--md-default-fg-color--lighter:#00000052;--md-default-fg-color--lightest:#00000012;--md-default-bg-color:#fff;--md-default-bg-color--light:#ffffffb3;--md-default-bg-color--lighter:#ffffff4d;--md-default-bg-color--lightest:#ffffff1f;--md-code-fg-color:#36464e;--md-code-bg-color:#f5f5f5;--md-code-hl-color:#ffff0080;--md-code-hl-number-color:#d52a2a;--md-code-hl-special-color:#db1457;--md-code-hl-function-color:#a846b9;--md-code-hl-constant-color:#6e59d9;--md-code-hl-keyword-color:#3f6ec6;--md-code-hl-string-color:#1c7d4d;--md-code-hl-name-color:var(--md-code-fg-color);--md-code-hl-operator-color:var(--md-default-fg-color--light);--md-code-hl-punctuation-color:var(--md-default-fg-color--light);--md-code-hl-comment-color:var(--md-default-fg-color--light);--md-code-hl-generic-color:var(--md-default-fg-color--light);--md-code-hl-variable-color:var(--md-default-fg-color--light);--md-typeset-color:var(--md-default-fg-color);--md-typeset-a-color:var(--md-primary-fg-color);--md-typeset-mark-color:#ffff0080;--md-typeset-del-color:#f5503d26;--md-typeset-ins-color:#0bd57026;--md-typeset-kbd-color:#fafafa;--md-typeset-kbd-accent-color:#fff;--md-typeset-kbd-border-color:#b8b8b8;--md-typeset-table-color:#0000001f;--md-typeset-table-color--light:rgba(0,0,0,.035);--md-admonition-fg-color:var(--md-default-fg-color);--md-admonition-bg-color:var(--md-default-bg-color);--md-warning-fg-color:#000000de;--md-warning-bg-color:#ff9;--md-footer-fg-color:#fff;--md-footer-fg-color--light:#ffffffb3;--md-footer-fg-color--lighter:#ffffff73;--md-footer-bg-color:#000000de;--md-footer-bg-color--dark:#00000052;--md-shadow-z1:0 0.2rem 0.5rem #0000000d,0 0 0.05rem #0000001a;--md-shadow-z2:0 0.2rem 0.5rem #0000001a,0 0 0.05rem #00000040;--md-shadow-z3:0 0.2rem 0.5rem #0003,0 0 0.05rem #00000059}.md-icon svg{fill:currentcolor;display:block;height:1.2rem;width:1.2rem}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;--md-text-font-family:var(--md-text-font,_),-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif;--md-code-font-family:var(--md-code-font,_),SFMono-Regular,Consolas,Menlo,monospace}aside,body,input{font-feature-settings:"kern","liga";color:var(--md-typeset-color);font-family:var(--md-text-font-family)}code,kbd,pre{font-feature-settings:"kern";font-family:var(--md-code-font-family)}:root{--md-typeset-table-sort-icon:url('data:image/svg+xml;charset=utf-8,');--md-typeset-table-sort-icon--asc:url('data:image/svg+xml;charset=utf-8,');--md-typeset-table-sort-icon--desc:url('data:image/svg+xml;charset=utf-8,')}.md-typeset{-webkit-print-color-adjust:exact;color-adjust:exact;font-size:.8rem;line-height:1.6}@media print{.md-typeset{font-size:.68rem}}.md-typeset blockquote,.md-typeset dl,.md-typeset figure,.md-typeset ol,.md-typeset pre,.md-typeset ul{margin-bottom:1em;margin-top:1em}.md-typeset h1{color:var(--md-default-fg-color--light);font-size:2em;line-height:1.3;margin:0 0 1.25em}.md-typeset h1,.md-typeset h2{font-weight:300;letter-spacing:-.01em}.md-typeset h2{font-size:1.5625em;line-height:1.4;margin:1.6em 0 .64em}.md-typeset h3{font-size:1.25em;font-weight:400;letter-spacing:-.01em;line-height:1.5;margin:1.6em 0 .8em}.md-typeset h2+h3{margin-top:.8em}.md-typeset h4{font-weight:700;letter-spacing:-.01em;margin:1em 0}.md-typeset h5,.md-typeset h6{color:var(--md-default-fg-color--light);font-size:.8em;font-weight:700;letter-spacing:-.01em;margin:1.25em 0}.md-typeset h5{text-transform:uppercase}.md-typeset hr{border-bottom:.05rem solid var(--md-default-fg-color--lightest);display:flow-root;margin:1.5em 0}.md-typeset a{color:var(--md-typeset-a-color);word-break:break-word}.md-typeset a,.md-typeset a:before{transition:color 125ms}.md-typeset a:focus,.md-typeset a:hover{color:var(--md-accent-fg-color)}.md-typeset a:focus code,.md-typeset a:hover code{background-color:var(--md-accent-fg-color--transparent)}.md-typeset a code{color:currentcolor;transition:background-color 125ms}.md-typeset a.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-typeset code,.md-typeset kbd,.md-typeset pre{color:var(--md-code-fg-color);direction:ltr;font-variant-ligatures:none}@media print{.md-typeset code,.md-typeset kbd,.md-typeset pre{white-space:pre-wrap}}.md-typeset code{background-color:var(--md-code-bg-color);border-radius:.1rem;-webkit-box-decoration-break:clone;box-decoration-break:clone;font-size:.85em;padding:0 .2941176471em;word-break:break-word}.md-typeset code:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}.md-typeset pre{display:flow-root;line-height:1.4;position:relative}.md-typeset pre>code{-webkit-box-decoration-break:slice;box-decoration-break:slice;box-shadow:none;display:block;margin:0;outline-color:var(--md-accent-fg-color);overflow:auto;padding:.7720588235em 1.1764705882em;scrollbar-color:var(--md-default-fg-color--lighter) #0000;scrollbar-width:thin;touch-action:auto;word-break:normal}.md-typeset pre>code:hover{scrollbar-color:var(--md-accent-fg-color) #0000}.md-typeset pre>code::-webkit-scrollbar{height:.2rem;width:.2rem}.md-typeset pre>code::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-typeset pre>code::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}.md-typeset kbd{background-color:var(--md-typeset-kbd-color);border-radius:.1rem;box-shadow:0 .1rem 0 .05rem var(--md-typeset-kbd-border-color),0 .1rem 0 var(--md-typeset-kbd-border-color),0 -.1rem .2rem var(--md-typeset-kbd-accent-color) inset;color:var(--md-default-fg-color);display:inline-block;font-size:.75em;padding:0 .6666666667em;vertical-align:text-top;word-break:break-word}.md-typeset mark{background-color:var(--md-typeset-mark-color);-webkit-box-decoration-break:clone;box-decoration-break:clone;color:inherit;word-break:break-word}.md-typeset abbr{border-bottom:.05rem dotted var(--md-default-fg-color--light);cursor:help;text-decoration:none}@media (hover:none){.md-typeset abbr[title]:focus:after,.md-typeset abbr[title]:hover:after{background-color:var(--md-default-fg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z3);color:var(--md-default-bg-color);content:attr(title);font-size:.7rem;left:.8rem;margin-top:2em;padding:.2rem .3rem;position:absolute;right:.8rem}}.md-typeset small{opacity:.75}[dir=ltr] .md-typeset sub,[dir=ltr] .md-typeset sup{margin-left:.078125em}[dir=rtl] .md-typeset sub,[dir=rtl] .md-typeset sup{margin-right:.078125em}[dir=ltr] .md-typeset blockquote{padding-left:.6rem}[dir=rtl] .md-typeset blockquote{padding-right:.6rem}[dir=ltr] .md-typeset blockquote{border-left:.2rem solid var(--md-default-fg-color--lighter)}[dir=rtl] .md-typeset blockquote{border-right:.2rem solid var(--md-default-fg-color--lighter)}.md-typeset blockquote{color:var(--md-default-fg-color--light);margin-left:0;margin-right:0}.md-typeset ul{list-style-type:disc}[dir=ltr] .md-typeset ol,[dir=ltr] .md-typeset ul{margin-left:.625em}[dir=rtl] .md-typeset ol,[dir=rtl] .md-typeset ul{margin-right:.625em}.md-typeset ol,.md-typeset ul{padding:0}.md-typeset ol:not([hidden]),.md-typeset ul:not([hidden]){display:flow-root}.md-typeset ol ol,.md-typeset ul ol{list-style-type:lower-alpha}.md-typeset ol ol ol,.md-typeset ul ol ol{list-style-type:lower-roman}[dir=ltr] .md-typeset ol li,[dir=ltr] .md-typeset ul li{margin-left:1.25em}[dir=rtl] .md-typeset ol li,[dir=rtl] .md-typeset ul li{margin-right:1.25em}.md-typeset ol li,.md-typeset ul li{margin-bottom:.5em}.md-typeset ol li blockquote,.md-typeset ol li p,.md-typeset ul li blockquote,.md-typeset ul li p{margin:.5em 0}.md-typeset ol li:last-child,.md-typeset ul li:last-child{margin-bottom:0}[dir=ltr] .md-typeset ol li ol,[dir=ltr] .md-typeset ol li ul,[dir=ltr] .md-typeset ul li ol,[dir=ltr] .md-typeset ul li ul{margin-left:.625em}[dir=rtl] .md-typeset ol li ol,[dir=rtl] .md-typeset ol li ul,[dir=rtl] .md-typeset ul li ol,[dir=rtl] .md-typeset ul li ul{margin-right:.625em}.md-typeset ol li ol,.md-typeset ol li ul,.md-typeset ul li ol,.md-typeset ul li ul{margin-bottom:.5em;margin-top:.5em}[dir=ltr] .md-typeset dd{margin-left:1.875em}[dir=rtl] .md-typeset dd{margin-right:1.875em}.md-typeset dd{margin-bottom:1.5em;margin-top:1em}.md-typeset img,.md-typeset svg,.md-typeset video{height:auto;max-width:100%}.md-typeset img[align=left]{margin:1em 1em 1em 0}.md-typeset img[align=right]{margin:1em 0 1em 1em}.md-typeset img[align]:only-child{margin-top:0}.md-typeset figure{display:flow-root;margin:1em auto;max-width:100%;text-align:center;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.md-typeset figure img{display:block}.md-typeset figcaption{font-style:italic;margin:1em auto;max-width:24rem}.md-typeset iframe{max-width:100%}.md-typeset table:not([class]){background-color:var(--md-default-bg-color);border:.05rem solid var(--md-typeset-table-color);border-radius:.1rem;display:inline-block;font-size:.64rem;max-width:100%;overflow:auto;touch-action:auto}@media print{.md-typeset table:not([class]){display:table}}.md-typeset table:not([class])+*{margin-top:1.5em}.md-typeset table:not([class]) td>:first-child,.md-typeset table:not([class]) th>:first-child{margin-top:0}.md-typeset table:not([class]) td>:last-child,.md-typeset table:not([class]) th>:last-child{margin-bottom:0}.md-typeset table:not([class]) td:not([align]),.md-typeset table:not([class]) th:not([align]){text-align:left}[dir=rtl] .md-typeset table:not([class]) td:not([align]),[dir=rtl] .md-typeset table:not([class]) th:not([align]){text-align:right}.md-typeset table:not([class]) th{font-weight:700;min-width:5rem;padding:.9375em 1.25em;vertical-align:top}.md-typeset table:not([class]) td{border-top:.05rem solid var(--md-typeset-table-color);padding:.9375em 1.25em;vertical-align:top}.md-typeset table:not([class]) tbody tr{transition:background-color 125ms}.md-typeset table:not([class]) tbody tr:hover{background-color:var(--md-typeset-table-color--light);box-shadow:0 .05rem 0 var(--md-default-bg-color) inset}.md-typeset table:not([class]) a{word-break:normal}.md-typeset table th[role=columnheader]{cursor:pointer}[dir=ltr] .md-typeset table th[role=columnheader]:after{margin-left:.5em}[dir=rtl] .md-typeset table th[role=columnheader]:after{margin-right:.5em}.md-typeset table th[role=columnheader]:after{content:"";display:inline-block;height:1.2em;-webkit-mask-image:var(--md-typeset-table-sort-icon);mask-image:var(--md-typeset-table-sort-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:background-color 125ms;vertical-align:text-bottom;width:1.2em}.md-typeset table th[role=columnheader]:hover:after{background-color:var(--md-default-fg-color--lighter)}.md-typeset table th[role=columnheader][aria-sort=ascending]:after{background-color:var(--md-default-fg-color--light);-webkit-mask-image:var(--md-typeset-table-sort-icon--asc);mask-image:var(--md-typeset-table-sort-icon--asc)}.md-typeset table th[role=columnheader][aria-sort=descending]:after{background-color:var(--md-default-fg-color--light);-webkit-mask-image:var(--md-typeset-table-sort-icon--desc);mask-image:var(--md-typeset-table-sort-icon--desc)}.md-typeset__scrollwrap{margin:1em -.8rem;overflow-x:auto;touch-action:auto}.md-typeset__table{display:inline-block;margin-bottom:.5em;padding:0 .8rem}@media print{.md-typeset__table{display:block}}html .md-typeset__table table{display:table;margin:0;overflow:hidden;width:100%}@media screen and (max-width:44.9375em){.md-content__inner>pre{margin:1em -.8rem}.md-content__inner>pre code{border-radius:0}}.md-typeset .md-author{display:block;flex-shrink:0;height:1.6rem;overflow:hidden;position:relative;transition:color 125ms,transform 125ms;width:1.6rem}.md-typeset .md-author img{border-radius:100%;display:block}.md-typeset .md-author--more{background:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--lighter);font-size:.6rem;font-weight:700;line-height:1.6rem;text-align:center}.md-typeset .md-author--long{height:2.4rem;width:2.4rem}.md-typeset a.md-author{transform:scale(1)}.md-typeset a.md-author img{filter:grayscale(100%) opacity(75%);transition:filter 125ms}.md-typeset a.md-author:focus,.md-typeset a.md-author:hover{transform:scale(1.1);z-index:1}.md-typeset a.md-author:focus img,.md-typeset a.md-author:hover img{filter:grayscale(0)}.md-banner{background-color:var(--md-footer-bg-color);color:var(--md-footer-fg-color);overflow:auto}@media print{.md-banner{display:none}}.md-banner--warning{background-color:var(--md-warning-bg-color);color:var(--md-warning-fg-color)}.md-banner__inner{font-size:.7rem;margin:.6rem auto;padding:0 .8rem}[dir=ltr] .md-banner__button{float:right}[dir=rtl] .md-banner__button{float:left}.md-banner__button{color:inherit;cursor:pointer;transition:opacity .25s}.no-js .md-banner__button{display:none}.md-banner__button:hover{opacity:.7}html{font-size:125%;height:100%;overflow-x:hidden}@media screen and (min-width:100em){html{font-size:137.5%}}@media screen and (min-width:125em){html{font-size:150%}}body{background-color:var(--md-default-bg-color);display:flex;flex-direction:column;font-size:.5rem;min-height:100%;position:relative;width:100%}@media print{body{display:block}}@media screen and (max-width:59.9375em){body[data-md-scrolllock]{position:fixed}}.md-grid{margin-left:auto;margin-right:auto;max-width:61rem}.md-container{display:flex;flex-direction:column;flex-grow:1}@media print{.md-container{display:block}}.md-main{flex-grow:1}.md-main__inner{display:flex;height:100%;margin-top:1.5rem}.md-ellipsis{overflow:hidden;text-overflow:ellipsis}.md-toggle{display:none}.md-option{height:0;opacity:0;position:absolute;width:0}.md-option:checked+label:not([hidden]){display:block}.md-option.focus-visible+label{outline-color:var(--md-accent-fg-color);outline-style:auto}.md-skip{background-color:var(--md-default-fg-color);border-radius:.1rem;color:var(--md-default-bg-color);font-size:.64rem;margin:.5rem;opacity:0;outline-color:var(--md-accent-fg-color);padding:.3rem .5rem;position:fixed;transform:translateY(.4rem);z-index:-1}.md-skip:focus{opacity:1;transform:translateY(0);transition:transform .25s cubic-bezier(.4,0,.2,1),opacity 175ms 75ms;z-index:10}@page{margin:25mm}:root{--md-clipboard-icon:url('data:image/svg+xml;charset=utf-8,')}.md-clipboard{border-radius:.1rem;color:var(--md-default-fg-color--lightest);cursor:pointer;height:1.5em;outline-color:var(--md-accent-fg-color);outline-offset:.1rem;position:absolute;right:.5em;top:.5em;transition:color .25s;width:1.5em;z-index:1}@media print{.md-clipboard{display:none}}.md-clipboard:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}:hover>.md-clipboard{color:var(--md-default-fg-color--light)}.md-clipboard:focus,.md-clipboard:hover{color:var(--md-accent-fg-color)}.md-clipboard:after{background-color:currentcolor;content:"";display:block;height:1.125em;margin:0 auto;-webkit-mask-image:var(--md-clipboard-icon);mask-image:var(--md-clipboard-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:1.125em}.md-clipboard--inline{cursor:pointer}.md-clipboard--inline code{transition:color .25s,background-color .25s}.md-clipboard--inline:focus code,.md-clipboard--inline:hover code{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}@keyframes consent{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}@keyframes overlay{0%{opacity:0}to{opacity:1}}.md-consent__overlay{animation:overlay .25s both;-webkit-backdrop-filter:blur(.1rem);backdrop-filter:blur(.1rem);background-color:#0000008a;height:100%;opacity:1;position:fixed;top:0;width:100%;z-index:5}.md-consent__inner{animation:consent .5s cubic-bezier(.1,.7,.1,1) both;background-color:var(--md-default-bg-color);border:0;border-radius:.1rem;bottom:0;box-shadow:0 0 .2rem #0000001a,0 .2rem .4rem #0003;max-height:100%;overflow:auto;padding:0;position:fixed;width:100%;z-index:5}.md-consent__form{padding:.8rem}.md-consent__settings{display:none;margin:1em 0}input:checked+.md-consent__settings{display:block}.md-consent__controls{margin-bottom:.8rem}.md-typeset .md-consent__controls .md-button{display:inline}@media screen and (max-width:44.9375em){.md-typeset .md-consent__controls .md-button{display:block;margin-top:.4rem;text-align:center;width:100%}}.md-consent label{cursor:pointer}.md-content{flex-grow:1;min-width:0}.md-content__inner{margin:0 .8rem 1.2rem;padding-top:.6rem}@media screen and (min-width:76.25em){[dir=ltr] .md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-left:1.2rem}[dir=ltr] .md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner,[dir=rtl] .md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-right:1.2rem}[dir=rtl] .md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner{margin-left:1.2rem}}.md-content__inner:before{content:"";display:block;height:.4rem}.md-content__inner>:last-child{margin-bottom:0}[dir=ltr] .md-content__button{float:right}[dir=rtl] .md-content__button{float:left}[dir=ltr] .md-content__button{margin-left:.4rem}[dir=rtl] .md-content__button{margin-right:.4rem}.md-content__button{margin:.4rem 0;padding:0}@media print{.md-content__button{display:none}}.md-typeset .md-content__button{color:var(--md-default-fg-color--lighter)}.md-content__button svg{display:inline;vertical-align:top}[dir=rtl] .md-content__button svg{transform:scaleX(-1)}[dir=ltr] .md-dialog{right:.8rem}[dir=rtl] .md-dialog{left:.8rem}.md-dialog{background-color:var(--md-default-fg-color);border-radius:.1rem;bottom:.8rem;box-shadow:var(--md-shadow-z3);min-width:11.1rem;opacity:0;padding:.4rem .6rem;pointer-events:none;position:fixed;transform:translateY(100%);transition:transform 0ms .4s,opacity .4s;z-index:4}@media print{.md-dialog{display:none}}.md-dialog--active{opacity:1;pointer-events:auto;transform:translateY(0);transition:transform .4s cubic-bezier(.075,.85,.175,1),opacity .4s}.md-dialog__inner{color:var(--md-default-bg-color);font-size:.7rem}.md-feedback{margin:2em 0 1em;text-align:center}.md-feedback fieldset{border:none;margin:0;padding:0}.md-feedback__title{font-weight:700;margin:1em auto}.md-feedback__inner{position:relative}.md-feedback__list{align-content:baseline;display:flex;flex-wrap:wrap;justify-content:center;position:relative}.md-feedback__list:hover .md-icon:not(:disabled){color:var(--md-default-fg-color--lighter)}:disabled .md-feedback__list{min-height:1.8rem}.md-feedback__icon{color:var(--md-default-fg-color--light);cursor:pointer;flex-shrink:0;margin:0 .1rem;transition:color 125ms}.md-feedback__icon:not(:disabled).md-icon:hover{color:var(--md-accent-fg-color)}.md-feedback__icon:disabled{color:var(--md-default-fg-color--lightest);pointer-events:none}.md-feedback__note{opacity:0;position:relative;transform:translateY(.4rem);transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s}.md-feedback__note>*{margin:0 auto;max-width:16rem}:disabled .md-feedback__note{opacity:1;transform:translateY(0)}.md-footer{background-color:var(--md-footer-bg-color);color:var(--md-footer-fg-color)}@media print{.md-footer{display:none}}.md-footer__inner{justify-content:space-between;overflow:auto;padding:.2rem}.md-footer__inner:not([hidden]){display:flex}.md-footer__link{align-items:end;display:flex;flex-grow:0.01;margin-bottom:.4rem;margin-top:1rem;max-width:100%;outline-color:var(--md-accent-fg-color);overflow:hidden;transition:opacity .25s}.md-footer__link:focus,.md-footer__link:hover{opacity:.7}[dir=rtl] .md-footer__link svg{transform:scaleX(-1)}@media screen and (max-width:44.9375em){.md-footer__link--prev{flex-shrink:0}.md-footer__link--prev .md-footer__title{display:none}}[dir=ltr] .md-footer__link--next{margin-left:auto}[dir=rtl] .md-footer__link--next{margin-right:auto}.md-footer__link--next{text-align:right}[dir=rtl] .md-footer__link--next{text-align:left}.md-footer__title{flex-grow:1;font-size:.9rem;margin-bottom:.7rem;max-width:calc(100% - 2.4rem);padding:0 1rem;white-space:nowrap}.md-footer__button{margin:.2rem;padding:.4rem}.md-footer__direction{font-size:.64rem;opacity:.7}.md-footer-meta{background-color:var(--md-footer-bg-color--dark)}.md-footer-meta__inner{display:flex;flex-wrap:wrap;justify-content:space-between;padding:.2rem}html .md-footer-meta.md-typeset a{color:var(--md-footer-fg-color--light)}html .md-footer-meta.md-typeset a:focus,html .md-footer-meta.md-typeset a:hover{color:var(--md-footer-fg-color)}.md-copyright{color:var(--md-footer-fg-color--lighter);font-size:.64rem;margin:auto .6rem;padding:.4rem 0;width:100%}@media screen and (min-width:45em){.md-copyright{width:auto}}.md-copyright__highlight{color:var(--md-footer-fg-color--light)}.md-social{display:inline-flex;gap:.2rem;margin:0 .4rem;padding:.2rem 0 .6rem}@media screen and (min-width:45em){.md-social{padding:.6rem 0}}.md-social__link{display:inline-block;height:1.6rem;text-align:center;width:1.6rem}.md-social__link:before{line-height:1.9}.md-social__link svg{fill:currentcolor;max-height:.8rem;vertical-align:-25%}.md-typeset .md-button{border:.1rem solid;border-radius:.1rem;color:var(--md-primary-fg-color);cursor:pointer;display:inline-block;font-weight:700;padding:.625em 2em;transition:color 125ms,background-color 125ms,border-color 125ms}.md-typeset .md-button--primary{background-color:var(--md-primary-fg-color);border-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color)}.md-typeset .md-button:focus,.md-typeset .md-button:hover{background-color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}[dir=ltr] .md-typeset .md-input{border-top-left-radius:.1rem}[dir=ltr] .md-typeset .md-input,[dir=rtl] .md-typeset .md-input{border-top-right-radius:.1rem}[dir=rtl] .md-typeset .md-input{border-top-left-radius:.1rem}.md-typeset .md-input{border-bottom:.1rem solid var(--md-default-fg-color--lighter);box-shadow:var(--md-shadow-z1);font-size:.8rem;height:1.8rem;padding:0 .6rem;transition:border .25s,box-shadow .25s}.md-typeset .md-input:focus,.md-typeset .md-input:hover{border-bottom-color:var(--md-accent-fg-color);box-shadow:var(--md-shadow-z2)}.md-typeset .md-input--stretch{width:100%}.md-header{background-color:var(--md-primary-fg-color);box-shadow:0 0 .2rem #0000,0 .2rem .4rem #0000;color:var(--md-primary-bg-color);display:block;left:0;position:sticky;right:0;top:0;z-index:4}@media print{.md-header{display:none}}.md-header[hidden]{transform:translateY(-100%);transition:transform .25s cubic-bezier(.8,0,.6,1),box-shadow .25s}.md-header--shadow{box-shadow:0 0 .2rem #0000001a,0 .2rem .4rem #0003;transition:transform .25s cubic-bezier(.1,.7,.1,1),box-shadow .25s}.md-header__inner{align-items:center;display:flex;padding:0 .2rem}.md-header__button{color:currentcolor;cursor:pointer;margin:.2rem;outline-color:var(--md-accent-fg-color);padding:.4rem;position:relative;transition:opacity .25s;vertical-align:middle;z-index:1}.md-header__button:hover{opacity:.7}.md-header__button:not([hidden]){display:inline-block}.md-header__button:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}.md-header__button.md-logo{margin:.2rem;padding:.4rem}@media screen and (max-width:76.1875em){.md-header__button.md-logo{display:none}}.md-header__button.md-logo img,.md-header__button.md-logo svg{fill:currentcolor;display:block;height:1.2rem;width:auto}@media screen and (min-width:60em){.md-header__button[for=__search]{display:none}}.no-js .md-header__button[for=__search]{display:none}[dir=rtl] .md-header__button[for=__search] svg{transform:scaleX(-1)}@media screen and (min-width:76.25em){.md-header__button[for=__drawer]{display:none}}.md-header__topic{display:flex;max-width:100%;position:absolute;transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s;white-space:nowrap}.md-header__topic+.md-header__topic{opacity:0;pointer-events:none;transform:translateX(1.25rem);transition:transform .4s cubic-bezier(1,.7,.1,.1),opacity .15s;z-index:-1}[dir=rtl] .md-header__topic+.md-header__topic{transform:translateX(-1.25rem)}.md-header__topic:first-child{font-weight:700}[dir=ltr] .md-header__title{margin-left:1rem}[dir=rtl] .md-header__title{margin-right:1rem}[dir=ltr] .md-header__title{margin-right:.4rem}[dir=rtl] .md-header__title{margin-left:.4rem}.md-header__title{flex-grow:1;font-size:.9rem;height:2.4rem;line-height:2.4rem}.md-header__title--active .md-header__topic{opacity:0;pointer-events:none;transform:translateX(-1.25rem);transition:transform .4s cubic-bezier(1,.7,.1,.1),opacity .15s;z-index:-1}[dir=rtl] .md-header__title--active .md-header__topic{transform:translateX(1.25rem)}.md-header__title--active .md-header__topic+.md-header__topic{opacity:1;pointer-events:auto;transform:translateX(0);transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s;z-index:0}.md-header__title>.md-header__ellipsis{height:100%;position:relative;width:100%}.md-header__option{display:flex;flex-shrink:0;max-width:100%;transition:max-width 0ms .25s,opacity .25s .25s;white-space:nowrap}[data-md-toggle=search]:checked~.md-header .md-header__option{max-width:0;opacity:0;transition:max-width 0ms,opacity 0ms}.md-header__option>input{bottom:0}.md-header__source{display:none}@media screen and (min-width:60em){[dir=ltr] .md-header__source{margin-left:1rem}[dir=rtl] .md-header__source{margin-right:1rem}.md-header__source{display:block;max-width:11.7rem;width:11.7rem}}@media screen and (min-width:76.25em){[dir=ltr] .md-header__source{margin-left:1.4rem}[dir=rtl] .md-header__source{margin-right:1.4rem}}.md-meta{color:var(--md-default-fg-color--light);font-size:.7rem;line-height:1.3}.md-meta__list{display:inline-flex;flex-wrap:wrap;list-style:none;margin:0;padding:0}.md-meta__item:not(:last-child):after{content:"·";margin-left:.2rem;margin-right:.2rem}.md-meta__link{color:var(--md-typeset-a-color)}.md-meta__link:focus,.md-meta__link:hover{color:var(--md-accent-fg-color)}.md-draft{background-color:#ff1744;border-radius:.125em;color:#fff;display:inline-block;font-weight:700;padding-left:.5714285714em;padding-right:.5714285714em}:root{--md-nav-icon--prev:url('data:image/svg+xml;charset=utf-8,');--md-nav-icon--next:url('data:image/svg+xml;charset=utf-8,');--md-toc-icon:url('data:image/svg+xml;charset=utf-8,')}.md-nav{font-size:.7rem;line-height:1.3}.md-nav__title{color:var(--md-default-fg-color--light);display:block;font-weight:700;overflow:hidden;padding:0 .6rem;text-overflow:ellipsis}.md-nav__title .md-nav__button{display:none}.md-nav__title .md-nav__button img{height:100%;width:auto}.md-nav__title .md-nav__button.md-logo img,.md-nav__title .md-nav__button.md-logo svg{fill:currentcolor;display:block;height:2.4rem;max-width:100%;object-fit:contain;width:auto}.md-nav__list{list-style:none;margin:0;padding:0}.md-nav__item{padding:0 .6rem}[dir=ltr] .md-nav__item .md-nav__item{padding-right:0}[dir=rtl] .md-nav__item .md-nav__item{padding-left:0}.md-nav__link{align-items:flex-start;display:flex;margin-top:.625em;scroll-snap-align:start;transition:color 125ms}.md-nav__link--passed{color:var(--md-default-fg-color--light)}.md-nav__item .md-nav__link--active,.md-nav__item .md-nav__link--active code{color:var(--md-typeset-a-color)}.md-nav__link .md-ellipsis{position:relative}.md-nav__link .md-icon:last-child{margin-left:auto}.md-nav__link svg{fill:currentcolor;flex-shrink:0;height:1.3em}[dir=ltr] .md-nav__link svg+*{margin-left:.4rem}[dir=rtl] .md-nav__link svg+*{margin-right:.4rem}.md-nav__link:not(.md-nav__container):focus,.md-nav__link:not(.md-nav__container):hover{color:var(--md-accent-fg-color);cursor:pointer}.md-nav__link.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-nav--primary .md-nav__link[for=__toc]{display:none}.md-nav--primary .md-nav__link[for=__toc] .md-icon:after{background-color:currentcolor;display:block;height:100%;-webkit-mask-image:var(--md-toc-icon);mask-image:var(--md-toc-icon);width:100%}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:none}.md-nav__container>.md-nav__link{margin-top:0}.md-nav__container>.md-nav__link:first-child{flex-grow:1}.md-nav__icon{flex-shrink:0}.md-nav__source{display:none}@media screen and (max-width:76.1875em){.md-nav--primary,.md-nav--primary .md-nav{background-color:var(--md-default-bg-color);display:flex;flex-direction:column;height:100%;left:0;position:absolute;right:0;top:0;z-index:1}.md-nav--primary .md-nav__item,.md-nav--primary .md-nav__title{font-size:.8rem;line-height:1.5}.md-nav--primary .md-nav__title{background-color:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--light);cursor:pointer;height:5.6rem;line-height:2.4rem;padding:3rem .8rem .2rem;position:relative;white-space:nowrap}[dir=ltr] .md-nav--primary .md-nav__title .md-nav__icon{left:.4rem}[dir=rtl] .md-nav--primary .md-nav__title .md-nav__icon{right:.4rem}.md-nav--primary .md-nav__title .md-nav__icon{display:block;height:1.2rem;margin:.2rem;position:absolute;top:.4rem;width:1.2rem}.md-nav--primary .md-nav__title .md-nav__icon:after{background-color:currentcolor;content:"";display:block;height:100%;-webkit-mask-image:var(--md-nav-icon--prev);mask-image:var(--md-nav-icon--prev);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}.md-nav--primary .md-nav__title~.md-nav__list{background-color:var(--md-default-bg-color);box-shadow:0 .05rem 0 var(--md-default-fg-color--lightest) inset;overflow-y:auto;scroll-snap-type:y mandatory;touch-action:pan-y}.md-nav--primary .md-nav__title~.md-nav__list>:first-child{border-top:0}.md-nav--primary .md-nav__title[for=__drawer]{background-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color);font-weight:700}.md-nav--primary .md-nav__title .md-logo{display:block;left:.2rem;margin:.2rem;padding:.4rem;position:absolute;right:.2rem;top:.2rem}.md-nav--primary .md-nav__list{flex:1}.md-nav--primary .md-nav__item{border-top:.05rem solid var(--md-default-fg-color--lightest);padding:0}.md-nav--primary .md-nav__item--active>.md-nav__link{color:var(--md-typeset-a-color)}.md-nav--primary .md-nav__item--active>.md-nav__link:focus,.md-nav--primary .md-nav__item--active>.md-nav__link:hover{color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__link{margin-top:0;padding:.6rem .8rem}.md-nav--primary .md-nav__link svg{margin-top:.1em}.md-nav--primary .md-nav__link>.md-nav__link{padding:0}[dir=ltr] .md-nav--primary .md-nav__link .md-nav__icon{margin-right:-.2rem}[dir=rtl] .md-nav--primary .md-nav__link .md-nav__icon{margin-left:-.2rem}.md-nav--primary .md-nav__link .md-nav__icon{font-size:1.2rem;height:1.2rem;width:1.2rem}.md-nav--primary .md-nav__link .md-nav__icon:after{background-color:currentcolor;content:"";display:block;height:100%;-webkit-mask-image:var(--md-nav-icon--next);mask-image:var(--md-nav-icon--next);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}[dir=rtl] .md-nav--primary .md-nav__icon:after{transform:scale(-1)}.md-nav--primary .md-nav--secondary .md-nav{background-color:initial;position:static}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-left:1.4rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-right:1.4rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-left:2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-right:2rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-left:2.6rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-right:2.6rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-left:3.2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-right:3.2rem}.md-nav--secondary{background-color:initial}.md-nav__toggle~.md-nav{display:flex;opacity:0;transform:translateX(100%);transition:transform .25s cubic-bezier(.8,0,.6,1),opacity 125ms 50ms}[dir=rtl] .md-nav__toggle~.md-nav{transform:translateX(-100%)}.md-nav__toggle:checked~.md-nav{opacity:1;transform:translateX(0);transition:transform .25s cubic-bezier(.4,0,.2,1),opacity 125ms 125ms}.md-nav__toggle:checked~.md-nav>.md-nav__list{-webkit-backface-visibility:hidden;backface-visibility:hidden}}@media screen and (max-width:59.9375em){.md-nav--primary .md-nav__link[for=__toc]{display:flex}.md-nav--primary .md-nav__link[for=__toc] .md-icon:after{content:""}.md-nav--primary .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:flex}.md-nav__source{background-color:var(--md-primary-fg-color--dark);color:var(--md-primary-bg-color);display:block;padding:0 .2rem}}@media screen and (min-width:60em) and (max-width:76.1875em){.md-nav--integrated .md-nav__link[for=__toc]{display:flex}.md-nav--integrated .md-nav__link[for=__toc] .md-icon:after{content:""}.md-nav--integrated .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--integrated .md-nav__link[for=__toc]~.md-nav{display:flex}}@media screen and (min-width:60em){.md-nav--secondary .md-nav__title{background:var(--md-default-bg-color);box-shadow:0 0 .4rem .4rem var(--md-default-bg-color);position:sticky;top:0;z-index:1}.md-nav--secondary .md-nav__title[for=__toc]{scroll-snap-align:start}.md-nav--secondary .md-nav__title .md-nav__icon{display:none}}@media screen and (min-width:76.25em){.md-nav{transition:max-height .25s cubic-bezier(.86,0,.07,1)}.md-nav--primary .md-nav__title{background:var(--md-default-bg-color);box-shadow:0 0 .4rem .4rem var(--md-default-bg-color);position:sticky;top:0;z-index:1}.md-nav--primary .md-nav__title[for=__drawer]{scroll-snap-align:start}.md-nav--primary .md-nav__title .md-nav__icon,.md-nav__toggle~.md-nav{display:none}.md-nav__toggle:checked~.md-nav,.md-nav__toggle:indeterminate~.md-nav{display:block}.md-nav__item--nested>.md-nav>.md-nav__title{display:none}.md-nav__item--section{display:block;margin:1.25em 0}.md-nav__item--section:last-child{margin-bottom:0}.md-nav__item--section>.md-nav__link{font-weight:700}.md-nav__item--section>.md-nav__link[for]{color:var(--md-default-fg-color--light)}.md-nav__item--section>.md-nav__link:not(.md-nav__container){pointer-events:none}.md-nav__item--section>.md-nav__link .md-nav__icon{display:none}.md-nav__item--section>.md-nav{display:block}.md-nav__item--section>.md-nav>.md-nav__list>.md-nav__item{padding:0}.md-nav__icon{border-radius:100%;height:.9rem;transition:background-color .25s;width:.9rem}.md-nav__icon:hover{background-color:var(--md-accent-fg-color--transparent)}.md-nav__icon:after{background-color:currentcolor;border-radius:100%;content:"";display:inline-block;height:100%;-webkit-mask-image:var(--md-nav-icon--next);mask-image:var(--md-nav-icon--next);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:transform .25s;vertical-align:-.1rem;width:100%}[dir=rtl] .md-nav__icon:after{transform:rotate(180deg)}.md-nav__item--nested .md-nav__toggle:checked~.md-nav__link .md-nav__icon:after,.md-nav__item--nested .md-nav__toggle:indeterminate~.md-nav__link .md-nav__icon:after{transform:rotate(90deg)}.md-nav--lifted>.md-nav__list>.md-nav__item,.md-nav--lifted>.md-nav__list>.md-nav__item--nested,.md-nav--lifted>.md-nav__title{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active{display:block;padding:0}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link{background:var(--md-default-bg-color);box-shadow:0 0 .4rem .4rem var(--md-default-bg-color);font-weight:700;margin-top:0;padding:0 .6rem;position:sticky;top:0;z-index:1}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link:not(.md-nav__container){pointer-events:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link .md-nav__icon{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item>[for]{color:var(--md-default-fg-color--light)}.md-nav--lifted .md-nav[data-md-level="1"]{display:block}[dir=ltr] .md-nav--lifted .md-nav[data-md-level="1"]>.md-nav__list>.md-nav__item{padding-right:.6rem}[dir=rtl] .md-nav--lifted .md-nav[data-md-level="1"]>.md-nav__list>.md-nav__item{padding-left:.6rem}.md-nav--integrated>.md-nav__list>.md-nav__item--active:not(.md-nav__item--nested){padding:0 .6rem}.md-nav--integrated>.md-nav__list>.md-nav__item--active:not(.md-nav__item--nested)>.md-nav__link{padding:0}[dir=ltr] .md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{border-left:.05rem solid var(--md-primary-fg-color)}[dir=rtl] .md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{border-right:.05rem solid var(--md-primary-fg-color)}.md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{display:block;margin-bottom:1.25em}.md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary>.md-nav__title{display:none}}.md-pagination{font-size:.8rem;font-weight:700;gap:.4rem}.md-pagination,.md-pagination>*{align-items:center;display:flex;justify-content:center}.md-pagination>*{border-radius:.2rem;height:1.8rem;min-width:1.8rem;text-align:center}.md-pagination__current{background-color:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--light)}.md-pagination__link{transition:color 125ms,background-color 125ms}.md-pagination__link:focus,.md-pagination__link:hover{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-pagination__link:focus svg,.md-pagination__link:hover svg{color:var(--md-accent-fg-color)}.md-pagination__link.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-pagination__link svg{fill:currentcolor;color:var(--md-default-fg-color--lighter);display:block;max-height:100%;width:1.2rem}.md-post__back{border-bottom:.05rem solid var(--md-default-fg-color--lightest);margin-bottom:1.2rem;padding-bottom:1.2rem}@media screen and (max-width:76.1875em){.md-post__back{display:none}}[dir=rtl] .md-post__back svg{transform:scaleX(-1)}.md-post__authors{display:flex;flex-direction:column;gap:.6rem;margin:0 .6rem}.md-post .md-post__meta a{transition:color 125ms}.md-post .md-post__meta a:focus,.md-post .md-post__meta a:hover{color:var(--md-accent-fg-color)}.md-post--excerpt{margin-bottom:3.2rem}.md-post--excerpt .md-post__header{align-items:center;display:flex;gap:.6rem;min-height:1.6rem}.md-post--excerpt .md-post__authors{align-items:center;display:inline-flex;flex-direction:row;gap:.2rem;margin:0;min-height:2.4rem}[dir=ltr] .md-post--excerpt .md-post__meta .md-meta__list{margin-right:.4rem}[dir=rtl] .md-post--excerpt .md-post__meta .md-meta__list{margin-left:.4rem}.md-post--excerpt .md-post__content>:first-child{--md-scroll-margin:6rem;margin-top:0}.md-post>.md-nav--secondary,.md-post>.md-nav:first-child>.md-nav__list{margin:1em 0}.md-profile{align-items:center;display:flex;font-size:.7rem;gap:.6rem;line-height:1.4;width:100%}.md-profile__description{flex-grow:1}.md-content--post{display:flex}@media screen and (max-width:76.1875em){.md-content--post{flex-flow:column-reverse}}.md-content--post>.md-content__inner{min-width:0}@media screen and (min-width:76.25em){[dir=ltr] .md-content--post>.md-content__inner{margin-left:1.2rem}[dir=rtl] .md-content--post>.md-content__inner{margin-right:1.2rem}}@media screen and (max-width:76.1875em){.md-sidebar.md-sidebar--post{padding:0}}:root{--md-search-result-icon:url('data:image/svg+xml;charset=utf-8,')}.md-search{position:relative}@media screen and (min-width:60em){.md-search{padding:.2rem 0}}.no-js .md-search{display:none}.md-search__overlay{opacity:0;z-index:1}@media screen and (max-width:59.9375em){[dir=ltr] .md-search__overlay{left:-2.2rem}[dir=rtl] .md-search__overlay{right:-2.2rem}.md-search__overlay{background-color:var(--md-default-bg-color);border-radius:1rem;height:2rem;overflow:hidden;pointer-events:none;position:absolute;top:-1rem;transform-origin:center;transition:transform .3s .1s,opacity .2s .2s;width:2rem}[data-md-toggle=search]:checked~.md-header .md-search__overlay{opacity:1;transition:transform .4s,opacity .1s}}@media screen and (min-width:60em){[dir=ltr] .md-search__overlay{left:0}[dir=rtl] .md-search__overlay{right:0}.md-search__overlay{background-color:#0000008a;cursor:pointer;height:0;position:fixed;top:0;transition:width 0ms .25s,height 0ms .25s,opacity .25s;width:0}[data-md-toggle=search]:checked~.md-header .md-search__overlay{height:200vh;opacity:1;transition:width 0ms,height 0ms,opacity .25s;width:100%}}@media screen and (max-width:29.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(45)}}@media screen and (min-width:30em) and (max-width:44.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(60)}}@media screen and (min-width:45em) and (max-width:59.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(75)}}.md-search__inner{-webkit-backface-visibility:hidden;backface-visibility:hidden}@media screen and (max-width:59.9375em){[dir=ltr] .md-search__inner{left:0}[dir=rtl] .md-search__inner{right:0}.md-search__inner{height:0;opacity:0;overflow:hidden;position:fixed;top:0;transform:translateX(5%);transition:width 0ms .3s,height 0ms .3s,transform .15s cubic-bezier(.4,0,.2,1) .15s,opacity .15s .15s;width:0;z-index:2}[dir=rtl] .md-search__inner{transform:translateX(-5%)}[data-md-toggle=search]:checked~.md-header .md-search__inner{height:100%;opacity:1;transform:translateX(0);transition:width 0ms 0ms,height 0ms 0ms,transform .15s cubic-bezier(.1,.7,.1,1) .15s,opacity .15s .15s;width:100%}}@media screen and (min-width:60em){[dir=ltr] .md-search__inner{float:right}[dir=rtl] .md-search__inner{float:left}.md-search__inner{padding:.1rem 0;position:relative;transition:width .25s cubic-bezier(.1,.7,.1,1);width:11.7rem}}@media screen and (min-width:60em) and (max-width:76.1875em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:23.4rem}}@media screen and (min-width:76.25em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:34.4rem}}.md-search__form{background-color:var(--md-default-bg-color);box-shadow:0 0 .6rem #0000;height:2.4rem;position:relative;transition:color .25s,background-color .25s;z-index:2}@media screen and (min-width:60em){.md-search__form{background-color:#00000042;border-radius:.1rem;height:1.8rem}.md-search__form:hover{background-color:#ffffff1f}}[data-md-toggle=search]:checked~.md-header .md-search__form{background-color:var(--md-default-bg-color);border-radius:.1rem .1rem 0 0;box-shadow:0 0 .6rem #00000012;color:var(--md-default-fg-color)}[dir=ltr] .md-search__input{padding-left:3.6rem;padding-right:2.2rem}[dir=rtl] .md-search__input{padding-left:2.2rem;padding-right:3.6rem}.md-search__input{background:#0000;font-size:.9rem;height:100%;position:relative;text-overflow:ellipsis;width:100%;z-index:2}.md-search__input::placeholder{transition:color .25s}.md-search__input::placeholder,.md-search__input~.md-search__icon{color:var(--md-default-fg-color--light)}.md-search__input::-ms-clear{display:none}@media screen and (max-width:59.9375em){.md-search__input{font-size:.9rem;height:2.4rem;width:100%}}@media screen and (min-width:60em){[dir=ltr] .md-search__input{padding-left:2.2rem}[dir=rtl] .md-search__input{padding-right:2.2rem}.md-search__input{color:inherit;font-size:.8rem}.md-search__input::placeholder{color:var(--md-primary-bg-color--light)}.md-search__input+.md-search__icon{color:var(--md-primary-bg-color)}[data-md-toggle=search]:checked~.md-header .md-search__input{text-overflow:clip}[data-md-toggle=search]:checked~.md-header .md-search__input+.md-search__icon{color:var(--md-default-fg-color--light)}[data-md-toggle=search]:checked~.md-header .md-search__input::placeholder{color:#0000}}.md-search__icon{cursor:pointer;display:inline-block;height:1.2rem;transition:color .25s,opacity .25s;width:1.2rem}.md-search__icon:hover{opacity:.7}[dir=ltr] .md-search__icon[for=__search]{left:.5rem}[dir=rtl] .md-search__icon[for=__search]{right:.5rem}.md-search__icon[for=__search]{position:absolute;top:.3rem;z-index:2}[dir=rtl] .md-search__icon[for=__search] svg{transform:scaleX(-1)}@media screen and (max-width:59.9375em){[dir=ltr] .md-search__icon[for=__search]{left:.8rem}[dir=rtl] .md-search__icon[for=__search]{right:.8rem}.md-search__icon[for=__search]{top:.6rem}.md-search__icon[for=__search] svg:first-child{display:none}}@media screen and (min-width:60em){.md-search__icon[for=__search]{pointer-events:none}.md-search__icon[for=__search] svg:last-child{display:none}}[dir=ltr] .md-search__options{right:.5rem}[dir=rtl] .md-search__options{left:.5rem}.md-search__options{pointer-events:none;position:absolute;top:.3rem;z-index:2}@media screen and (max-width:59.9375em){[dir=ltr] .md-search__options{right:.8rem}[dir=rtl] .md-search__options{left:.8rem}.md-search__options{top:.6rem}}[dir=ltr] .md-search__options>.md-icon{margin-left:.2rem}[dir=rtl] .md-search__options>.md-icon{margin-right:.2rem}.md-search__options>.md-icon{color:var(--md-default-fg-color--light);opacity:0;transform:scale(.75);transition:transform .15s cubic-bezier(.1,.7,.1,1),opacity .15s}.md-search__options>.md-icon:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__options>.md-icon{opacity:1;pointer-events:auto;transform:scale(1)}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__options>.md-icon:hover{opacity:.7}[dir=ltr] .md-search__suggest{padding-left:3.6rem;padding-right:2.2rem}[dir=rtl] .md-search__suggest{padding-left:2.2rem;padding-right:3.6rem}.md-search__suggest{align-items:center;color:var(--md-default-fg-color--lighter);display:flex;font-size:.9rem;height:100%;opacity:0;position:absolute;top:0;transition:opacity 50ms;white-space:nowrap;width:100%}@media screen and (min-width:60em){[dir=ltr] .md-search__suggest{padding-left:2.2rem}[dir=rtl] .md-search__suggest{padding-right:2.2rem}.md-search__suggest{font-size:.8rem}}[data-md-toggle=search]:checked~.md-header .md-search__suggest{opacity:1;transition:opacity .3s .1s}[dir=ltr] .md-search__output{border-bottom-left-radius:.1rem}[dir=ltr] .md-search__output,[dir=rtl] .md-search__output{border-bottom-right-radius:.1rem}[dir=rtl] .md-search__output{border-bottom-left-radius:.1rem}.md-search__output{overflow:hidden;position:absolute;width:100%;z-index:1}@media screen and (max-width:59.9375em){.md-search__output{bottom:0;top:2.4rem}}@media screen and (min-width:60em){.md-search__output{opacity:0;top:1.9rem;transition:opacity .4s}[data-md-toggle=search]:checked~.md-header .md-search__output{box-shadow:var(--md-shadow-z3);opacity:1}}.md-search__scrollwrap{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:var(--md-default-bg-color);height:100%;overflow-y:auto;touch-action:pan-y}@media (-webkit-max-device-pixel-ratio:1),(max-resolution:1dppx){.md-search__scrollwrap{transform:translateZ(0)}}@media screen and (min-width:60em) and (max-width:76.1875em){.md-search__scrollwrap{width:23.4rem}}@media screen and (min-width:76.25em){.md-search__scrollwrap{width:34.4rem}}@media screen and (min-width:60em){.md-search__scrollwrap{max-height:0;scrollbar-color:var(--md-default-fg-color--lighter) #0000;scrollbar-width:thin}[data-md-toggle=search]:checked~.md-header .md-search__scrollwrap{max-height:75vh}.md-search__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) #0000}.md-search__scrollwrap::-webkit-scrollbar{height:.2rem;width:.2rem}.md-search__scrollwrap::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}}.md-search-result{color:var(--md-default-fg-color);word-break:break-word}.md-search-result__meta{background-color:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--light);font-size:.64rem;line-height:1.8rem;padding:0 .8rem;scroll-snap-align:start}@media screen and (min-width:60em){[dir=ltr] .md-search-result__meta{padding-left:2.2rem}[dir=rtl] .md-search-result__meta{padding-right:2.2rem}}.md-search-result__list{list-style:none;margin:0;padding:0;-webkit-user-select:none;user-select:none}.md-search-result__item{box-shadow:0 -.05rem var(--md-default-fg-color--lightest)}.md-search-result__item:first-child{box-shadow:none}.md-search-result__link{display:block;outline:none;scroll-snap-align:start;transition:background-color .25s}.md-search-result__link:focus,.md-search-result__link:hover{background-color:var(--md-accent-fg-color--transparent)}.md-search-result__link:last-child p:last-child{margin-bottom:.6rem}.md-search-result__more>summary{cursor:pointer;display:block;outline:none;position:sticky;scroll-snap-align:start;top:0;z-index:1}.md-search-result__more>summary::marker{display:none}.md-search-result__more>summary::-webkit-details-marker{display:none}.md-search-result__more>summary>div{color:var(--md-typeset-a-color);font-size:.64rem;padding:.75em .8rem;transition:color .25s,background-color .25s}@media screen and (min-width:60em){[dir=ltr] .md-search-result__more>summary>div{padding-left:2.2rem}[dir=rtl] .md-search-result__more>summary>div{padding-right:2.2rem}}.md-search-result__more>summary:focus>div,.md-search-result__more>summary:hover>div{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-search-result__more[open]>summary{background-color:var(--md-default-bg-color)}.md-search-result__article{overflow:hidden;padding:0 .8rem;position:relative}@media screen and (min-width:60em){[dir=ltr] .md-search-result__article{padding-left:2.2rem}[dir=rtl] .md-search-result__article{padding-right:2.2rem}}[dir=ltr] .md-search-result__icon{left:0}[dir=rtl] .md-search-result__icon{right:0}.md-search-result__icon{color:var(--md-default-fg-color--light);height:1.2rem;margin:.5rem;position:absolute;width:1.2rem}@media screen and (max-width:59.9375em){.md-search-result__icon{display:none}}.md-search-result__icon:after{background-color:currentcolor;content:"";display:inline-block;height:100%;-webkit-mask-image:var(--md-search-result-icon);mask-image:var(--md-search-result-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}[dir=rtl] .md-search-result__icon:after{transform:scaleX(-1)}.md-search-result .md-typeset{color:var(--md-default-fg-color--light);font-size:.64rem;line-height:1.6}.md-search-result .md-typeset h1{color:var(--md-default-fg-color);font-size:.8rem;font-weight:400;line-height:1.4;margin:.55rem 0}.md-search-result .md-typeset h1 mark{text-decoration:none}.md-search-result .md-typeset h2{color:var(--md-default-fg-color);font-size:.64rem;font-weight:700;line-height:1.6;margin:.5em 0}.md-search-result .md-typeset h2 mark{text-decoration:none}.md-search-result__terms{color:var(--md-default-fg-color);display:block;font-size:.64rem;font-style:italic;margin:.5em 0}.md-search-result mark{background-color:initial;color:var(--md-accent-fg-color);text-decoration:underline}.md-select{position:relative;z-index:1}.md-select__inner{background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);left:50%;margin-top:.2rem;max-height:0;opacity:0;position:absolute;top:calc(100% - .2rem);transform:translate3d(-50%,.3rem,0);transition:transform .25s 375ms,opacity .25s .25s,max-height 0ms .5s}.md-select:focus-within .md-select__inner,.md-select:hover .md-select__inner{max-height:10rem;opacity:1;transform:translate3d(-50%,0,0);transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height 0ms}.md-select__inner:after{border-bottom:.2rem solid #0000;border-bottom-color:var(--md-default-bg-color);border-left:.2rem solid #0000;border-right:.2rem solid #0000;border-top:0;content:"";height:0;left:50%;margin-left:-.2rem;margin-top:-.2rem;position:absolute;top:0;width:0}.md-select__list{border-radius:.1rem;font-size:.8rem;list-style-type:none;margin:0;max-height:inherit;overflow:auto;padding:0}.md-select__item{line-height:1.8rem}[dir=ltr] .md-select__link{padding-left:.6rem;padding-right:1.2rem}[dir=rtl] .md-select__link{padding-left:1.2rem;padding-right:.6rem}.md-select__link{cursor:pointer;display:block;outline:none;scroll-snap-align:start;transition:background-color .25s,color .25s;width:100%}.md-select__link:focus,.md-select__link:hover{color:var(--md-accent-fg-color)}.md-select__link:focus{background-color:var(--md-default-fg-color--lightest)}.md-sidebar{align-self:flex-start;flex-shrink:0;padding:1.2rem 0;position:sticky;top:2.4rem;width:12.1rem}@media print{.md-sidebar{display:none}}@media screen and (max-width:76.1875em){[dir=ltr] .md-sidebar--primary{left:-12.1rem}[dir=rtl] .md-sidebar--primary{right:-12.1rem}.md-sidebar--primary{background-color:var(--md-default-bg-color);display:block;height:100%;position:fixed;top:0;transform:translateX(0);transition:transform .25s cubic-bezier(.4,0,.2,1),box-shadow .25s;width:12.1rem;z-index:5}[data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{box-shadow:var(--md-shadow-z3);transform:translateX(12.1rem)}[dir=rtl] [data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{transform:translateX(-12.1rem)}.md-sidebar--primary .md-sidebar__scrollwrap{bottom:0;left:0;margin:0;overflow:hidden;position:absolute;right:0;scroll-snap-type:none;top:0}}@media screen and (min-width:76.25em){.md-sidebar{height:0}.no-js .md-sidebar{height:auto}.md-header--lifted~.md-container .md-sidebar{top:4.8rem}}.md-sidebar--secondary{display:none;order:2}@media screen and (min-width:60em){.md-sidebar--secondary{height:0}.no-js .md-sidebar--secondary{height:auto}.md-sidebar--secondary:not([hidden]){display:block}.md-sidebar--secondary .md-sidebar__scrollwrap{touch-action:pan-y}}.md-sidebar__scrollwrap{scrollbar-gutter:stable;-webkit-backface-visibility:hidden;backface-visibility:hidden;margin:0 .2rem;overflow-y:auto;scrollbar-color:var(--md-default-fg-color--lighter) #0000;scrollbar-width:thin}.md-sidebar__scrollwrap::-webkit-scrollbar{height:.2rem;width:.2rem}.md-sidebar__scrollwrap:focus-within,.md-sidebar__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) #0000}.md-sidebar__scrollwrap:focus-within::-webkit-scrollbar-thumb,.md-sidebar__scrollwrap:hover::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-sidebar__scrollwrap:focus-within::-webkit-scrollbar-thumb:hover,.md-sidebar__scrollwrap:hover::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}@supports selector(::-webkit-scrollbar){.md-sidebar__scrollwrap{scrollbar-gutter:auto}[dir=ltr] .md-sidebar__inner{padding-right:calc(100% - 11.5rem)}[dir=rtl] .md-sidebar__inner{padding-left:calc(100% - 11.5rem)}}@media screen and (max-width:76.1875em){.md-overlay{background-color:#0000008a;height:0;opacity:0;position:fixed;top:0;transition:width 0ms .25s,height 0ms .25s,opacity .25s;width:0;z-index:5}[data-md-toggle=drawer]:checked~.md-overlay{height:100%;opacity:1;transition:width 0ms,height 0ms,opacity .25s;width:100%}}@keyframes facts{0%{height:0}to{height:.65rem}}@keyframes fact{0%{opacity:0;transform:translateY(100%)}50%{opacity:0}to{opacity:1;transform:translateY(0)}}:root{--md-source-forks-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-repositories-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-stars-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-version-icon:url('data:image/svg+xml;charset=utf-8,')}.md-source{-webkit-backface-visibility:hidden;backface-visibility:hidden;display:block;font-size:.65rem;line-height:1.2;outline-color:var(--md-accent-fg-color);transition:opacity .25s;white-space:nowrap}.md-source:hover{opacity:.7}.md-source__icon{display:inline-block;height:2.4rem;vertical-align:middle;width:2rem}[dir=ltr] .md-source__icon svg{margin-left:.6rem}[dir=rtl] .md-source__icon svg{margin-right:.6rem}.md-source__icon svg{margin-top:.6rem}[dir=ltr] .md-source__icon+.md-source__repository{padding-left:2rem}[dir=rtl] .md-source__icon+.md-source__repository{padding-right:2rem}[dir=ltr] .md-source__icon+.md-source__repository{margin-left:-2rem}[dir=rtl] .md-source__icon+.md-source__repository{margin-right:-2rem}[dir=ltr] .md-source__repository{margin-left:.6rem}[dir=rtl] .md-source__repository{margin-right:.6rem}.md-source__repository{display:inline-block;max-width:calc(100% - 1.2rem);overflow:hidden;text-overflow:ellipsis;vertical-align:middle}.md-source__facts{display:flex;font-size:.55rem;gap:.4rem;list-style-type:none;margin:.1rem 0 0;opacity:.75;overflow:hidden;padding:0;width:100%}.md-source__repository--active .md-source__facts{animation:facts .25s ease-in}.md-source__fact{overflow:hidden;text-overflow:ellipsis}.md-source__repository--active .md-source__fact{animation:fact .4s ease-out}[dir=ltr] .md-source__fact:before{margin-right:.1rem}[dir=rtl] .md-source__fact:before{margin-left:.1rem}.md-source__fact:before{background-color:currentcolor;content:"";display:inline-block;height:.6rem;-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;vertical-align:text-top;width:.6rem}.md-source__fact:nth-child(1n+2){flex-shrink:0}.md-source__fact--version:before{-webkit-mask-image:var(--md-source-version-icon);mask-image:var(--md-source-version-icon)}.md-source__fact--stars:before{-webkit-mask-image:var(--md-source-stars-icon);mask-image:var(--md-source-stars-icon)}.md-source__fact--forks:before{-webkit-mask-image:var(--md-source-forks-icon);mask-image:var(--md-source-forks-icon)}.md-source__fact--repositories:before{-webkit-mask-image:var(--md-source-repositories-icon);mask-image:var(--md-source-repositories-icon)}:root{--md-status:url('data:image/svg+xml;charset=utf-8,');--md-status--new:url('data:image/svg+xml;charset=utf-8,');--md-status--deprecated:url('data:image/svg+xml;charset=utf-8,');--md-status--encrypted:url('data:image/svg+xml;charset=utf-8,')}.md-status{margin-left:.2rem}.md-status:after{background-color:var(--md-default-fg-color--light);content:"";display:inline-block;height:1.125em;-webkit-mask-image:var(--md-status);mask-image:var(--md-status);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;vertical-align:text-bottom;width:1.125em}.md-status:hover:after{background-color:currentcolor}.md-status--new:after{-webkit-mask-image:var(--md-status--new);mask-image:var(--md-status--new)}.md-status--deprecated:after{-webkit-mask-image:var(--md-status--deprecated);mask-image:var(--md-status--deprecated)}.md-status--encrypted:after{-webkit-mask-image:var(--md-status--encrypted);mask-image:var(--md-status--encrypted)}.md-tabs{background-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color);display:block;line-height:1.3;overflow:auto;width:100%;z-index:3}@media print{.md-tabs{display:none}}@media screen and (max-width:76.1875em){.md-tabs{display:none}}.md-tabs[hidden]{pointer-events:none}[dir=ltr] .md-tabs__list{margin-left:.2rem}[dir=rtl] .md-tabs__list{margin-right:.2rem}.md-tabs__list{contain:content;display:flex;list-style:none;margin:0;overflow:auto;padding:0;scrollbar-width:none;white-space:nowrap}.md-tabs__list::-webkit-scrollbar{display:none}.md-tabs__item{height:2.4rem;padding-left:.6rem;padding-right:.6rem}.md-tabs__item--active .md-tabs__link{color:inherit;opacity:1}.md-tabs__link{-webkit-backface-visibility:hidden;backface-visibility:hidden;display:flex;font-size:.7rem;margin-top:.8rem;opacity:.7;outline-color:var(--md-accent-fg-color);outline-offset:.2rem;transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .25s}.md-tabs__link:focus,.md-tabs__link:hover{color:inherit;opacity:1}[dir=ltr] .md-tabs__link svg{margin-right:.4rem}[dir=rtl] .md-tabs__link svg{margin-left:.4rem}.md-tabs__link svg{fill:currentcolor;height:1.3em}.md-tabs__item:nth-child(2) .md-tabs__link{transition-delay:20ms}.md-tabs__item:nth-child(3) .md-tabs__link{transition-delay:40ms}.md-tabs__item:nth-child(4) .md-tabs__link{transition-delay:60ms}.md-tabs__item:nth-child(5) .md-tabs__link{transition-delay:80ms}.md-tabs__item:nth-child(6) .md-tabs__link{transition-delay:.1s}.md-tabs__item:nth-child(7) .md-tabs__link{transition-delay:.12s}.md-tabs__item:nth-child(8) .md-tabs__link{transition-delay:.14s}.md-tabs__item:nth-child(9) .md-tabs__link{transition-delay:.16s}.md-tabs__item:nth-child(10) .md-tabs__link{transition-delay:.18s}.md-tabs__item:nth-child(11) .md-tabs__link{transition-delay:.2s}.md-tabs__item:nth-child(12) .md-tabs__link{transition-delay:.22s}.md-tabs__item:nth-child(13) .md-tabs__link{transition-delay:.24s}.md-tabs__item:nth-child(14) .md-tabs__link{transition-delay:.26s}.md-tabs__item:nth-child(15) .md-tabs__link{transition-delay:.28s}.md-tabs__item:nth-child(16) .md-tabs__link{transition-delay:.3s}.md-tabs[hidden] .md-tabs__link{opacity:0;transform:translateY(50%);transition:transform 0ms .1s,opacity .1s}:root{--md-tag-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .md-tags{margin-bottom:.75em;margin-top:-.125em}[dir=ltr] .md-typeset .md-tag{margin-right:.5em}[dir=rtl] .md-typeset .md-tag{margin-left:.5em}.md-typeset .md-tag{background:var(--md-default-fg-color--lightest);border-radius:2.4rem;display:inline-block;font-size:.64rem;font-weight:700;letter-spacing:normal;line-height:1.6;margin-bottom:.5em;padding:.3125em .9375em;vertical-align:middle}.md-typeset .md-tag[href]{-webkit-tap-highlight-color:transparent;color:inherit;outline:none;transition:color 125ms,background-color 125ms}.md-typeset .md-tag[href]:focus,.md-typeset .md-tag[href]:hover{background-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}[id]>.md-typeset .md-tag{vertical-align:text-top}.md-typeset .md-tag-icon:before{background-color:var(--md-default-fg-color--lighter);content:"";display:inline-block;height:1.2em;margin-right:.4em;-webkit-mask-image:var(--md-tag-icon);mask-image:var(--md-tag-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:background-color 125ms;vertical-align:text-bottom;width:1.2em}.md-typeset .md-tag-icon[href]:focus:before,.md-typeset .md-tag-icon[href]:hover:before{background-color:var(--md-accent-bg-color)}@keyframes pulse{0%{transform:scale(.95)}75%{transform:scale(1)}to{transform:scale(.95)}}:root{--md-annotation-bg-icon:url('data:image/svg+xml;charset=utf-8,');--md-annotation-icon:url('data:image/svg+xml;charset=utf-8,');--md-tooltip-width:20rem}.md-tooltip{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);font-family:var(--md-text-font-family);left:clamp(var(--md-tooltip-0,0rem) + .8rem,var(--md-tooltip-x),100vw + var(--md-tooltip-0,0rem) + .8rem - var(--md-tooltip-width) - 2 * .8rem);max-width:calc(100vw - 1.6rem);opacity:0;position:absolute;top:var(--md-tooltip-y);transform:translateY(-.4rem);transition:transform 0ms .25s,opacity .25s,z-index .25s;width:var(--md-tooltip-width);z-index:0}.md-tooltip--active{opacity:1;transform:translateY(0);transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,z-index 0ms;z-index:2}.focus-visible>.md-tooltip,.md-tooltip:target{outline:var(--md-accent-fg-color) auto}.md-tooltip__inner{font-size:.64rem;padding:.8rem}.md-tooltip__inner.md-typeset>:first-child{margin-top:0}.md-tooltip__inner.md-typeset>:last-child{margin-bottom:0}.md-annotation{font-weight:400;outline:none;vertical-align:text-bottom;white-space:normal}[dir=rtl] .md-annotation{direction:rtl}code .md-annotation{font-family:var(--md-code-font-family);font-size:inherit}.md-annotation:not([hidden]){display:inline-block;line-height:1.25}.md-annotation__index{border-radius:.01px;cursor:pointer;display:inline-block;margin-left:.4ch;margin-right:.4ch;outline:none;overflow:hidden;position:relative;-webkit-user-select:none;user-select:none;vertical-align:text-top;z-index:0}.md-annotation .md-annotation__index{transition:z-index .25s}@media screen{.md-annotation__index{width:2.2ch}[data-md-visible]>.md-annotation__index{animation:pulse 2s infinite}.md-annotation__index:before{background:var(--md-default-bg-color);-webkit-mask-image:var(--md-annotation-bg-icon);mask-image:var(--md-annotation-bg-icon)}.md-annotation__index:after,.md-annotation__index:before{content:"";height:2.2ch;-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:-.1ch;width:2.2ch;z-index:-1}.md-annotation__index:after{background-color:var(--md-default-fg-color--lighter);-webkit-mask-image:var(--md-annotation-icon);mask-image:var(--md-annotation-icon);transform:scale(1.0001);transition:background-color .25s,transform .25s}.md-tooltip--active+.md-annotation__index:after{transform:rotate(45deg)}.md-tooltip--active+.md-annotation__index:after,:hover>.md-annotation__index:after{background-color:var(--md-accent-fg-color)}}.md-tooltip--active+.md-annotation__index{animation-play-state:paused;transition-duration:0ms;z-index:2}.md-annotation__index [data-md-annotation-id]{display:inline-block}@media print{.md-annotation__index [data-md-annotation-id]{background:var(--md-default-fg-color--lighter);border-radius:2ch;color:var(--md-default-bg-color);font-weight:700;padding:0 .6ch;white-space:nowrap}.md-annotation__index [data-md-annotation-id]:after{content:attr(data-md-annotation-id)}}.md-typeset .md-annotation-list{counter-reset:xxx;list-style:none}.md-typeset .md-annotation-list li{position:relative}[dir=ltr] .md-typeset .md-annotation-list li:before{left:-2.125em}[dir=rtl] .md-typeset .md-annotation-list li:before{right:-2.125em}.md-typeset .md-annotation-list li:before{background:var(--md-default-fg-color--lighter);border-radius:2ch;color:var(--md-default-bg-color);content:counter(xxx);counter-increment:xxx;font-size:.8875em;font-weight:700;height:2ch;line-height:1.25;min-width:2ch;padding:0 .6ch;position:absolute;text-align:center;top:.25em}[dir=ltr] .md-top{margin-left:50%}[dir=rtl] .md-top{margin-right:50%}.md-top{background-color:var(--md-default-bg-color);border-radius:1.6rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color--light);cursor:pointer;display:block;font-size:.7rem;outline:none;padding:.4rem .8rem;position:fixed;top:3.2rem;transform:translate(-50%);transition:color 125ms,background-color 125ms,transform 125ms cubic-bezier(.4,0,.2,1),opacity 125ms;z-index:2}@media print{.md-top{display:none}}[dir=rtl] .md-top{transform:translate(50%)}.md-top[hidden]{opacity:0;pointer-events:none;transform:translate(-50%,.2rem);transition-duration:0ms}[dir=rtl] .md-top[hidden]{transform:translate(50%,.2rem)}.md-top:focus,.md-top:hover{background-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}.md-top svg{display:inline-block;vertical-align:-.5em}@keyframes hoverfix{0%{pointer-events:none}}:root{--md-version-icon:url('data:image/svg+xml;charset=utf-8,')}.md-version{flex-shrink:0;font-size:.8rem;height:2.4rem}[dir=ltr] .md-version__current{margin-left:1.4rem;margin-right:.4rem}[dir=rtl] .md-version__current{margin-left:.4rem;margin-right:1.4rem}.md-version__current{color:inherit;cursor:pointer;outline:none;position:relative;top:.05rem}[dir=ltr] .md-version__current:after{margin-left:.4rem}[dir=rtl] .md-version__current:after{margin-right:.4rem}.md-version__current:after{background-color:currentcolor;content:"";display:inline-block;height:.6rem;-webkit-mask-image:var(--md-version-icon);mask-image:var(--md-version-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:.4rem}.md-version__list{background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);list-style-type:none;margin:.2rem .8rem;max-height:0;opacity:0;overflow:auto;padding:0;position:absolute;scroll-snap-type:y mandatory;top:.15rem;transition:max-height 0ms .5s,opacity .25s .25s;z-index:3}.md-version:focus-within .md-version__list,.md-version:hover .md-version__list{max-height:10rem;opacity:1;transition:max-height 0ms,opacity .25s}@media (hover:none),(pointer:coarse){.md-version:hover .md-version__list{animation:hoverfix .25s forwards}.md-version:focus-within .md-version__list{animation:none}}.md-version__item{line-height:1.8rem}[dir=ltr] .md-version__link{padding-left:.6rem;padding-right:1.2rem}[dir=rtl] .md-version__link{padding-left:1.2rem;padding-right:.6rem}.md-version__link{cursor:pointer;display:block;outline:none;scroll-snap-align:start;transition:color .25s,background-color .25s;white-space:nowrap;width:100%}.md-version__link:focus,.md-version__link:hover{color:var(--md-accent-fg-color)}.md-version__link:focus{background-color:var(--md-default-fg-color--lightest)}:root{--md-admonition-icon--note:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--abstract:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--info:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--tip:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--success:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--question:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--warning:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--failure:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--danger:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--bug:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--example:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--quote:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .admonition,.md-typeset details{background-color:var(--md-admonition-bg-color);border:.05rem solid #448aff;border-radius:.2rem;box-shadow:var(--md-shadow-z1);color:var(--md-admonition-fg-color);display:flow-root;font-size:.64rem;margin:1.5625em 0;padding:0 .6rem;page-break-inside:avoid;transition:box-shadow 125ms}@media print{.md-typeset .admonition,.md-typeset details{box-shadow:none}}.md-typeset .admonition:focus-within,.md-typeset details:focus-within{box-shadow:0 0 0 .2rem #448aff1a}.md-typeset .admonition>*,.md-typeset details>*{box-sizing:border-box}.md-typeset .admonition .admonition,.md-typeset .admonition details,.md-typeset details .admonition,.md-typeset details details{margin-bottom:1em;margin-top:1em}.md-typeset .admonition .md-typeset__scrollwrap,.md-typeset details .md-typeset__scrollwrap{margin:1em -.6rem}.md-typeset .admonition .md-typeset__table,.md-typeset details .md-typeset__table{padding:0 .6rem}.md-typeset .admonition>.tabbed-set:only-child,.md-typeset details>.tabbed-set:only-child{margin-top:0}html .md-typeset .admonition>:last-child,html .md-typeset details>:last-child{margin-bottom:.6rem}[dir=ltr] .md-typeset .admonition-title,[dir=ltr] .md-typeset summary{padding-left:2rem;padding-right:.6rem}[dir=rtl] .md-typeset .admonition-title,[dir=rtl] .md-typeset summary{padding-left:.6rem;padding-right:2rem}[dir=ltr] .md-typeset .admonition-title,[dir=ltr] .md-typeset summary{border-left-width:.2rem}[dir=rtl] .md-typeset .admonition-title,[dir=rtl] .md-typeset summary{border-right-width:.2rem}[dir=ltr] .md-typeset .admonition-title,[dir=ltr] .md-typeset summary{border-top-left-radius:.1rem}[dir=ltr] .md-typeset .admonition-title,[dir=ltr] .md-typeset summary,[dir=rtl] .md-typeset .admonition-title,[dir=rtl] .md-typeset summary{border-top-right-radius:.1rem}[dir=rtl] .md-typeset .admonition-title,[dir=rtl] .md-typeset summary{border-top-left-radius:.1rem}.md-typeset .admonition-title,.md-typeset summary{background-color:#448aff1a;border:none;font-weight:700;margin:0 -.6rem;padding-bottom:.4rem;padding-top:.4rem;position:relative}html .md-typeset .admonition-title:last-child,html .md-typeset summary:last-child{margin-bottom:0}[dir=ltr] .md-typeset .admonition-title:before,[dir=ltr] .md-typeset summary:before{left:.6rem}[dir=rtl] .md-typeset .admonition-title:before,[dir=rtl] .md-typeset summary:before{right:.6rem}.md-typeset .admonition-title:before,.md-typeset summary:before{background-color:#448aff;content:"";height:1rem;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.625em;width:1rem}.md-typeset .admonition-title code,.md-typeset summary code{box-shadow:0 0 0 .05rem var(--md-default-fg-color--lightest)}.md-typeset .admonition.note,.md-typeset details.note{border-color:#448aff}.md-typeset .admonition.note:focus-within,.md-typeset details.note:focus-within{box-shadow:0 0 0 .2rem #448aff1a}.md-typeset .note>.admonition-title,.md-typeset .note>summary{background-color:#448aff1a}.md-typeset .note>.admonition-title:before,.md-typeset .note>summary:before{background-color:#448aff;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note)}.md-typeset .note>.admonition-title:after,.md-typeset .note>summary:after{color:#448aff}.md-typeset .admonition.abstract,.md-typeset details.abstract{border-color:#00b0ff}.md-typeset .admonition.abstract:focus-within,.md-typeset details.abstract:focus-within{box-shadow:0 0 0 .2rem #00b0ff1a}.md-typeset .abstract>.admonition-title,.md-typeset .abstract>summary{background-color:#00b0ff1a}.md-typeset .abstract>.admonition-title:before,.md-typeset .abstract>summary:before{background-color:#00b0ff;-webkit-mask-image:var(--md-admonition-icon--abstract);mask-image:var(--md-admonition-icon--abstract)}.md-typeset .abstract>.admonition-title:after,.md-typeset .abstract>summary:after{color:#00b0ff}.md-typeset .admonition.info,.md-typeset details.info{border-color:#00b8d4}.md-typeset .admonition.info:focus-within,.md-typeset details.info:focus-within{box-shadow:0 0 0 .2rem #00b8d41a}.md-typeset .info>.admonition-title,.md-typeset .info>summary{background-color:#00b8d41a}.md-typeset .info>.admonition-title:before,.md-typeset .info>summary:before{background-color:#00b8d4;-webkit-mask-image:var(--md-admonition-icon--info);mask-image:var(--md-admonition-icon--info)}.md-typeset .info>.admonition-title:after,.md-typeset .info>summary:after{color:#00b8d4}.md-typeset .admonition.tip,.md-typeset details.tip{border-color:#00bfa5}.md-typeset .admonition.tip:focus-within,.md-typeset details.tip:focus-within{box-shadow:0 0 0 .2rem #00bfa51a}.md-typeset .tip>.admonition-title,.md-typeset .tip>summary{background-color:#00bfa51a}.md-typeset .tip>.admonition-title:before,.md-typeset .tip>summary:before{background-color:#00bfa5;-webkit-mask-image:var(--md-admonition-icon--tip);mask-image:var(--md-admonition-icon--tip)}.md-typeset .tip>.admonition-title:after,.md-typeset .tip>summary:after{color:#00bfa5}.md-typeset .admonition.success,.md-typeset details.success{border-color:#00c853}.md-typeset .admonition.success:focus-within,.md-typeset details.success:focus-within{box-shadow:0 0 0 .2rem #00c8531a}.md-typeset .success>.admonition-title,.md-typeset .success>summary{background-color:#00c8531a}.md-typeset .success>.admonition-title:before,.md-typeset .success>summary:before{background-color:#00c853;-webkit-mask-image:var(--md-admonition-icon--success);mask-image:var(--md-admonition-icon--success)}.md-typeset .success>.admonition-title:after,.md-typeset .success>summary:after{color:#00c853}.md-typeset .admonition.question,.md-typeset details.question{border-color:#64dd17}.md-typeset .admonition.question:focus-within,.md-typeset details.question:focus-within{box-shadow:0 0 0 .2rem #64dd171a}.md-typeset .question>.admonition-title,.md-typeset .question>summary{background-color:#64dd171a}.md-typeset .question>.admonition-title:before,.md-typeset .question>summary:before{background-color:#64dd17;-webkit-mask-image:var(--md-admonition-icon--question);mask-image:var(--md-admonition-icon--question)}.md-typeset .question>.admonition-title:after,.md-typeset .question>summary:after{color:#64dd17}.md-typeset .admonition.warning,.md-typeset details.warning{border-color:#ff9100}.md-typeset .admonition.warning:focus-within,.md-typeset details.warning:focus-within{box-shadow:0 0 0 .2rem #ff91001a}.md-typeset .warning>.admonition-title,.md-typeset .warning>summary{background-color:#ff91001a}.md-typeset .warning>.admonition-title:before,.md-typeset .warning>summary:before{background-color:#ff9100;-webkit-mask-image:var(--md-admonition-icon--warning);mask-image:var(--md-admonition-icon--warning)}.md-typeset .warning>.admonition-title:after,.md-typeset .warning>summary:after{color:#ff9100}.md-typeset .admonition.failure,.md-typeset details.failure{border-color:#ff5252}.md-typeset .admonition.failure:focus-within,.md-typeset details.failure:focus-within{box-shadow:0 0 0 .2rem #ff52521a}.md-typeset .failure>.admonition-title,.md-typeset .failure>summary{background-color:#ff52521a}.md-typeset .failure>.admonition-title:before,.md-typeset .failure>summary:before{background-color:#ff5252;-webkit-mask-image:var(--md-admonition-icon--failure);mask-image:var(--md-admonition-icon--failure)}.md-typeset .failure>.admonition-title:after,.md-typeset .failure>summary:after{color:#ff5252}.md-typeset .admonition.danger,.md-typeset details.danger{border-color:#ff1744}.md-typeset .admonition.danger:focus-within,.md-typeset details.danger:focus-within{box-shadow:0 0 0 .2rem #ff17441a}.md-typeset .danger>.admonition-title,.md-typeset .danger>summary{background-color:#ff17441a}.md-typeset .danger>.admonition-title:before,.md-typeset .danger>summary:before{background-color:#ff1744;-webkit-mask-image:var(--md-admonition-icon--danger);mask-image:var(--md-admonition-icon--danger)}.md-typeset .danger>.admonition-title:after,.md-typeset .danger>summary:after{color:#ff1744}.md-typeset .admonition.bug,.md-typeset details.bug{border-color:#f50057}.md-typeset .admonition.bug:focus-within,.md-typeset details.bug:focus-within{box-shadow:0 0 0 .2rem #f500571a}.md-typeset .bug>.admonition-title,.md-typeset .bug>summary{background-color:#f500571a}.md-typeset .bug>.admonition-title:before,.md-typeset .bug>summary:before{background-color:#f50057;-webkit-mask-image:var(--md-admonition-icon--bug);mask-image:var(--md-admonition-icon--bug)}.md-typeset .bug>.admonition-title:after,.md-typeset .bug>summary:after{color:#f50057}.md-typeset .admonition.example,.md-typeset details.example{border-color:#7c4dff}.md-typeset .admonition.example:focus-within,.md-typeset details.example:focus-within{box-shadow:0 0 0 .2rem #7c4dff1a}.md-typeset .example>.admonition-title,.md-typeset .example>summary{background-color:#7c4dff1a}.md-typeset .example>.admonition-title:before,.md-typeset .example>summary:before{background-color:#7c4dff;-webkit-mask-image:var(--md-admonition-icon--example);mask-image:var(--md-admonition-icon--example)}.md-typeset .example>.admonition-title:after,.md-typeset .example>summary:after{color:#7c4dff}.md-typeset .admonition.quote,.md-typeset details.quote{border-color:#9e9e9e}.md-typeset .admonition.quote:focus-within,.md-typeset details.quote:focus-within{box-shadow:0 0 0 .2rem #9e9e9e1a}.md-typeset .quote>.admonition-title,.md-typeset .quote>summary{background-color:#9e9e9e1a}.md-typeset .quote>.admonition-title:before,.md-typeset .quote>summary:before{background-color:#9e9e9e;-webkit-mask-image:var(--md-admonition-icon--quote);mask-image:var(--md-admonition-icon--quote)}.md-typeset .quote>.admonition-title:after,.md-typeset .quote>summary:after{color:#9e9e9e}:root{--md-footnotes-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .footnote{color:var(--md-default-fg-color--light);font-size:.64rem}[dir=ltr] .md-typeset .footnote>ol{margin-left:0}[dir=rtl] .md-typeset .footnote>ol{margin-right:0}.md-typeset .footnote>ol>li{transition:color 125ms}.md-typeset .footnote>ol>li:target{color:var(--md-default-fg-color)}.md-typeset .footnote>ol>li:focus-within .footnote-backref{opacity:1;transform:translateX(0);transition:none}.md-typeset .footnote>ol>li:hover .footnote-backref,.md-typeset .footnote>ol>li:target .footnote-backref{opacity:1;transform:translateX(0)}.md-typeset .footnote>ol>li>:first-child{margin-top:0}.md-typeset .footnote-ref{font-size:.75em;font-weight:700}html .md-typeset .footnote-ref{outline-offset:.1rem}.md-typeset [id^="fnref:"]:target>.footnote-ref{outline:auto}.md-typeset .footnote-backref{color:var(--md-typeset-a-color);display:inline-block;font-size:0;opacity:0;transform:translateX(.25rem);transition:color .25s,transform .25s .25s,opacity 125ms .25s;vertical-align:text-bottom}@media print{.md-typeset .footnote-backref{color:var(--md-typeset-a-color);opacity:1;transform:translateX(0)}}[dir=rtl] .md-typeset .footnote-backref{transform:translateX(-.25rem)}.md-typeset .footnote-backref:hover{color:var(--md-accent-fg-color)}.md-typeset .footnote-backref:before{background-color:currentcolor;content:"";display:inline-block;height:.8rem;-webkit-mask-image:var(--md-footnotes-icon);mask-image:var(--md-footnotes-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:.8rem}[dir=rtl] .md-typeset .footnote-backref:before svg{transform:scaleX(-1)}[dir=ltr] .md-typeset .headerlink{margin-left:.5rem}[dir=rtl] .md-typeset .headerlink{margin-right:.5rem}.md-typeset .headerlink{color:var(--md-default-fg-color--lighter);display:inline-block;opacity:0;transition:color .25s,opacity 125ms}@media print{.md-typeset .headerlink{display:none}}.md-typeset .headerlink:focus,.md-typeset :hover>.headerlink,.md-typeset :target>.headerlink{opacity:1;transition:color .25s,opacity 125ms}.md-typeset .headerlink:focus,.md-typeset .headerlink:hover,.md-typeset :target>.headerlink{color:var(--md-accent-fg-color)}.md-typeset :target{--md-scroll-margin:3.6rem;--md-scroll-offset:0rem;scroll-margin-top:calc(var(--md-scroll-margin) - var(--md-scroll-offset))}@media screen and (min-width:76.25em){.md-header--lifted~.md-container .md-typeset :target{--md-scroll-margin:6rem}}.md-typeset h1:target,.md-typeset h2:target,.md-typeset h3:target{--md-scroll-offset:0.2rem}.md-typeset h4:target{--md-scroll-offset:0.15rem}.md-typeset div.arithmatex{overflow:auto}@media screen and (max-width:44.9375em){.md-typeset div.arithmatex{margin:0 -.8rem}}.md-typeset div.arithmatex>*{margin-left:auto!important;margin-right:auto!important;padding:0 .8rem;touch-action:auto;width:-webkit-min-content;width:min-content}.md-typeset div.arithmatex>* mjx-container{margin:0!important}.md-typeset del.critic{background-color:var(--md-typeset-del-color)}.md-typeset del.critic,.md-typeset ins.critic{-webkit-box-decoration-break:clone;box-decoration-break:clone}.md-typeset ins.critic{background-color:var(--md-typeset-ins-color)}.md-typeset .critic.comment{-webkit-box-decoration-break:clone;box-decoration-break:clone;color:var(--md-code-hl-comment-color)}.md-typeset .critic.comment:before{content:"/* "}.md-typeset .critic.comment:after{content:" */"}.md-typeset .critic.block{box-shadow:none;display:block;margin:1em 0;overflow:auto;padding-left:.8rem;padding-right:.8rem}.md-typeset .critic.block>:first-child{margin-top:.5em}.md-typeset .critic.block>:last-child{margin-bottom:.5em}:root{--md-details-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset details{display:flow-root;overflow:visible;padding-top:0}.md-typeset details[open]>summary:after{transform:rotate(90deg)}.md-typeset details:not([open]){box-shadow:none;padding-bottom:0}.md-typeset details:not([open])>summary{border-radius:.1rem}[dir=ltr] .md-typeset summary{padding-right:1.8rem}[dir=rtl] .md-typeset summary{padding-left:1.8rem}[dir=ltr] .md-typeset summary{border-top-left-radius:.1rem}[dir=ltr] .md-typeset summary,[dir=rtl] .md-typeset summary{border-top-right-radius:.1rem}[dir=rtl] .md-typeset summary{border-top-left-radius:.1rem}.md-typeset summary{cursor:pointer;display:block;min-height:1rem}.md-typeset summary.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-typeset summary:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}[dir=ltr] .md-typeset summary:after{right:.4rem}[dir=rtl] .md-typeset summary:after{left:.4rem}.md-typeset summary:after{background-color:currentcolor;content:"";height:1rem;-webkit-mask-image:var(--md-details-icon);mask-image:var(--md-details-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.625em;transform:rotate(0deg);transition:transform .25s;width:1rem}[dir=rtl] .md-typeset summary:after{transform:rotate(180deg)}.md-typeset summary::marker{display:none}.md-typeset summary::-webkit-details-marker{display:none}.md-typeset .emojione,.md-typeset .gemoji,.md-typeset .twemoji{display:inline-flex;height:1.125em;vertical-align:text-top}.md-typeset .emojione svg,.md-typeset .gemoji svg,.md-typeset .twemoji svg{fill:currentcolor;max-height:100%;width:1.125em}.highlight .o,.highlight .ow{color:var(--md-code-hl-operator-color)}.highlight .p{color:var(--md-code-hl-punctuation-color)}.highlight .cpf,.highlight .l,.highlight .s,.highlight .s1,.highlight .s2,.highlight .sb,.highlight .sc,.highlight .si,.highlight .ss{color:var(--md-code-hl-string-color)}.highlight .cp,.highlight .se,.highlight .sh,.highlight .sr,.highlight .sx{color:var(--md-code-hl-special-color)}.highlight .il,.highlight .m,.highlight .mb,.highlight .mf,.highlight .mh,.highlight .mi,.highlight .mo{color:var(--md-code-hl-number-color)}.highlight .k,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr,.highlight .kt{color:var(--md-code-hl-keyword-color)}.highlight .kc,.highlight .n{color:var(--md-code-hl-name-color)}.highlight .bp,.highlight .nb,.highlight .no{color:var(--md-code-hl-constant-color)}.highlight .nc,.highlight .ne,.highlight .nf,.highlight .nn{color:var(--md-code-hl-function-color)}.highlight .nd,.highlight .ni,.highlight .nl,.highlight .nt{color:var(--md-code-hl-keyword-color)}.highlight .c,.highlight .c1,.highlight .ch,.highlight .cm,.highlight .cs,.highlight .sd{color:var(--md-code-hl-comment-color)}.highlight .na,.highlight .nv,.highlight .vc,.highlight .vg,.highlight .vi{color:var(--md-code-hl-variable-color)}.highlight .ge,.highlight .gh,.highlight .go,.highlight .gp,.highlight .gr,.highlight .gs,.highlight .gt,.highlight .gu{color:var(--md-code-hl-generic-color)}.highlight .gd,.highlight .gi{border-radius:.1rem;margin:0 -.125em;padding:0 .125em}.highlight .gd{background-color:var(--md-typeset-del-color)}.highlight .gi{background-color:var(--md-typeset-ins-color)}.highlight .hll{background-color:var(--md-code-hl-color);display:block;margin:0 -1.1764705882em;padding:0 1.1764705882em}.highlight span.filename{background-color:var(--md-code-bg-color);border-bottom:.05rem solid var(--md-default-fg-color--lightest);border-top-left-radius:.1rem;border-top-right-radius:.1rem;display:flow-root;font-size:.85em;font-weight:700;margin-top:1em;padding:.6617647059em 1.1764705882em;position:relative}.highlight span.filename+pre{margin-top:0}.highlight span.filename+pre>code{border-top-left-radius:0;border-top-right-radius:0}.highlight [data-linenos]:before{background-color:var(--md-code-bg-color);box-shadow:-.05rem 0 var(--md-default-fg-color--lightest) inset;color:var(--md-default-fg-color--light);content:attr(data-linenos);float:left;left:-1.1764705882em;margin-left:-1.1764705882em;margin-right:1.1764705882em;padding-left:1.1764705882em;position:sticky;-webkit-user-select:none;user-select:none;z-index:3}.highlight code a[id]{position:absolute;visibility:hidden}.highlight code[data-md-copying] .hll{display:contents}.highlight code[data-md-copying] .md-annotation{display:none}.highlighttable{display:flow-root}.highlighttable tbody,.highlighttable td{display:block;padding:0}.highlighttable tr{display:flex}.highlighttable pre{margin:0}.highlighttable th.filename{flex-grow:1;padding:0;text-align:left}.highlighttable th.filename span.filename{margin-top:0}.highlighttable .linenos{background-color:var(--md-code-bg-color);border-bottom-left-radius:.1rem;border-top-left-radius:.1rem;font-size:.85em;padding:.7720588235em 0 .7720588235em 1.1764705882em;-webkit-user-select:none;user-select:none}.highlighttable .linenodiv{box-shadow:-.05rem 0 var(--md-default-fg-color--lightest) inset;padding-right:.5882352941em}.highlighttable .linenodiv pre{color:var(--md-default-fg-color--light);text-align:right}.highlighttable .code{flex:1;min-width:0}.linenodiv a{color:inherit}.md-typeset .highlighttable{direction:ltr;margin:1em 0}.md-typeset .highlighttable>tbody>tr>.code>div>pre>code{border-bottom-left-radius:0;border-top-left-radius:0}.md-typeset .highlight+.result{border:.05rem solid var(--md-code-bg-color);border-bottom-left-radius:.1rem;border-bottom-right-radius:.1rem;border-top-width:.1rem;margin-top:-1.125em;overflow:visible;padding:0 1em}.md-typeset .highlight+.result:after{clear:both;content:"";display:block}@media screen and (max-width:44.9375em){.md-content__inner>.highlight{margin:1em -.8rem}.md-content__inner>.highlight>.filename,.md-content__inner>.highlight>.highlighttable>tbody>tr>.code>div>pre>code,.md-content__inner>.highlight>.highlighttable>tbody>tr>.filename span.filename,.md-content__inner>.highlight>.highlighttable>tbody>tr>.linenos,.md-content__inner>.highlight>pre>code{border-radius:0}.md-content__inner>.highlight+.result{border-left-width:0;border-radius:0;border-right-width:0;margin-left:-.8rem;margin-right:-.8rem}}.md-typeset .keys kbd:after,.md-typeset .keys kbd:before{-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;color:inherit;margin:0;position:relative}.md-typeset .keys span{color:var(--md-default-fg-color--light);padding:0 .2em}.md-typeset .keys .key-alt:before,.md-typeset .keys .key-left-alt:before,.md-typeset .keys .key-right-alt:before{content:"⎇";padding-right:.4em}.md-typeset .keys .key-command:before,.md-typeset .keys .key-left-command:before,.md-typeset .keys .key-right-command:before{content:"⌘";padding-right:.4em}.md-typeset .keys .key-control:before,.md-typeset .keys .key-left-control:before,.md-typeset .keys .key-right-control:before{content:"⌃";padding-right:.4em}.md-typeset .keys .key-left-meta:before,.md-typeset .keys .key-meta:before,.md-typeset .keys .key-right-meta:before{content:"◆";padding-right:.4em}.md-typeset .keys .key-left-option:before,.md-typeset .keys .key-option:before,.md-typeset .keys .key-right-option:before{content:"⌥";padding-right:.4em}.md-typeset .keys .key-left-shift:before,.md-typeset .keys .key-right-shift:before,.md-typeset .keys .key-shift:before{content:"⇧";padding-right:.4em}.md-typeset .keys .key-left-super:before,.md-typeset .keys .key-right-super:before,.md-typeset .keys .key-super:before{content:"❖";padding-right:.4em}.md-typeset .keys .key-left-windows:before,.md-typeset .keys .key-right-windows:before,.md-typeset .keys .key-windows:before{content:"⊞";padding-right:.4em}.md-typeset .keys .key-arrow-down:before{content:"↓";padding-right:.4em}.md-typeset .keys .key-arrow-left:before{content:"←";padding-right:.4em}.md-typeset .keys .key-arrow-right:before{content:"→";padding-right:.4em}.md-typeset .keys .key-arrow-up:before{content:"↑";padding-right:.4em}.md-typeset .keys .key-backspace:before{content:"⌫";padding-right:.4em}.md-typeset .keys .key-backtab:before{content:"⇤";padding-right:.4em}.md-typeset .keys .key-caps-lock:before{content:"⇪";padding-right:.4em}.md-typeset .keys .key-clear:before{content:"⌧";padding-right:.4em}.md-typeset .keys .key-context-menu:before{content:"☰";padding-right:.4em}.md-typeset .keys .key-delete:before{content:"⌦";padding-right:.4em}.md-typeset .keys .key-eject:before{content:"⏏";padding-right:.4em}.md-typeset .keys .key-end:before{content:"⤓";padding-right:.4em}.md-typeset .keys .key-escape:before{content:"⎋";padding-right:.4em}.md-typeset .keys .key-home:before{content:"⤒";padding-right:.4em}.md-typeset .keys .key-insert:before{content:"⎀";padding-right:.4em}.md-typeset .keys .key-page-down:before{content:"⇟";padding-right:.4em}.md-typeset .keys .key-page-up:before{content:"⇞";padding-right:.4em}.md-typeset .keys .key-print-screen:before{content:"⎙";padding-right:.4em}.md-typeset .keys .key-tab:after{content:"⇥";padding-left:.4em}.md-typeset .keys .key-num-enter:after{content:"⌤";padding-left:.4em}.md-typeset .keys .key-enter:after{content:"⏎";padding-left:.4em}:root{--md-tabbed-icon--prev:url('data:image/svg+xml;charset=utf-8,');--md-tabbed-icon--next:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .tabbed-set{border-radius:.1rem;display:flex;flex-flow:column wrap;margin:1em 0;position:relative}.md-typeset .tabbed-set>input{height:0;opacity:0;position:absolute;width:0}.md-typeset .tabbed-set>input:target{--md-scroll-offset:0.625em}.md-typeset .tabbed-labels{-ms-overflow-style:none;box-shadow:0 -.05rem var(--md-default-fg-color--lightest) inset;display:flex;max-width:100%;overflow:auto;scrollbar-width:none}@media print{.md-typeset .tabbed-labels{display:contents}}@media screen{.js .md-typeset .tabbed-labels{position:relative}.js .md-typeset .tabbed-labels:before{background:var(--md-accent-fg-color);bottom:0;content:"";display:block;height:2px;left:0;position:absolute;transform:translateX(var(--md-indicator-x));transition:width 225ms,transform .25s;transition-timing-function:cubic-bezier(.4,0,.2,1);width:var(--md-indicator-width)}}.md-typeset .tabbed-labels::-webkit-scrollbar{display:none}.md-typeset .tabbed-labels>label{border-bottom:.1rem solid #0000;border-radius:.1rem .1rem 0 0;color:var(--md-default-fg-color--light);cursor:pointer;flex-shrink:0;font-size:.64rem;font-weight:700;padding:.78125em 1.25em .625em;scroll-margin-inline-start:1rem;transition:background-color .25s,color .25s;white-space:nowrap;width:auto}@media print{.md-typeset .tabbed-labels>label:first-child{order:1}.md-typeset .tabbed-labels>label:nth-child(2){order:2}.md-typeset .tabbed-labels>label:nth-child(3){order:3}.md-typeset .tabbed-labels>label:nth-child(4){order:4}.md-typeset .tabbed-labels>label:nth-child(5){order:5}.md-typeset .tabbed-labels>label:nth-child(6){order:6}.md-typeset .tabbed-labels>label:nth-child(7){order:7}.md-typeset .tabbed-labels>label:nth-child(8){order:8}.md-typeset .tabbed-labels>label:nth-child(9){order:9}.md-typeset .tabbed-labels>label:nth-child(10){order:10}.md-typeset .tabbed-labels>label:nth-child(11){order:11}.md-typeset .tabbed-labels>label:nth-child(12){order:12}.md-typeset .tabbed-labels>label:nth-child(13){order:13}.md-typeset .tabbed-labels>label:nth-child(14){order:14}.md-typeset .tabbed-labels>label:nth-child(15){order:15}.md-typeset .tabbed-labels>label:nth-child(16){order:16}.md-typeset .tabbed-labels>label:nth-child(17){order:17}.md-typeset .tabbed-labels>label:nth-child(18){order:18}.md-typeset .tabbed-labels>label:nth-child(19){order:19}.md-typeset .tabbed-labels>label:nth-child(20){order:20}}.md-typeset .tabbed-labels>label:hover{color:var(--md-accent-fg-color)}.md-typeset .tabbed-content{width:100%}@media print{.md-typeset .tabbed-content{display:contents}}.md-typeset .tabbed-block{display:none}@media print{.md-typeset .tabbed-block{display:block}.md-typeset .tabbed-block:first-child{order:1}.md-typeset .tabbed-block:nth-child(2){order:2}.md-typeset .tabbed-block:nth-child(3){order:3}.md-typeset .tabbed-block:nth-child(4){order:4}.md-typeset .tabbed-block:nth-child(5){order:5}.md-typeset .tabbed-block:nth-child(6){order:6}.md-typeset .tabbed-block:nth-child(7){order:7}.md-typeset .tabbed-block:nth-child(8){order:8}.md-typeset .tabbed-block:nth-child(9){order:9}.md-typeset .tabbed-block:nth-child(10){order:10}.md-typeset .tabbed-block:nth-child(11){order:11}.md-typeset .tabbed-block:nth-child(12){order:12}.md-typeset .tabbed-block:nth-child(13){order:13}.md-typeset .tabbed-block:nth-child(14){order:14}.md-typeset .tabbed-block:nth-child(15){order:15}.md-typeset .tabbed-block:nth-child(16){order:16}.md-typeset .tabbed-block:nth-child(17){order:17}.md-typeset .tabbed-block:nth-child(18){order:18}.md-typeset .tabbed-block:nth-child(19){order:19}.md-typeset .tabbed-block:nth-child(20){order:20}}.md-typeset .tabbed-block>.highlight:first-child>pre,.md-typeset .tabbed-block>pre:first-child{margin:0}.md-typeset .tabbed-block>.highlight:first-child>pre>code,.md-typeset .tabbed-block>pre:first-child>code{border-top-left-radius:0;border-top-right-radius:0}.md-typeset .tabbed-block>.highlight:first-child>.filename{border-top-left-radius:0;border-top-right-radius:0;margin:0}.md-typeset .tabbed-block>.highlight:first-child>.highlighttable{margin:0}.md-typeset .tabbed-block>.highlight:first-child>.highlighttable>tbody>tr>.filename span.filename,.md-typeset .tabbed-block>.highlight:first-child>.highlighttable>tbody>tr>.linenos{border-top-left-radius:0;border-top-right-radius:0;margin:0}.md-typeset .tabbed-block>.highlight:first-child>.highlighttable>tbody>tr>.code>div>pre>code{border-top-left-radius:0;border-top-right-radius:0}.md-typeset .tabbed-block>.highlight:first-child+.result{margin-top:-.125em}.md-typeset .tabbed-block>.tabbed-set{margin:0}.md-typeset .tabbed-button{align-self:center;border-radius:100%;color:var(--md-default-fg-color--light);cursor:pointer;display:block;height:.9rem;margin-top:.1rem;pointer-events:auto;transition:background-color .25s;width:.9rem}.md-typeset .tabbed-button:hover{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-typeset .tabbed-button:after{background-color:currentcolor;content:"";display:block;height:100%;-webkit-mask-image:var(--md-tabbed-icon--prev);mask-image:var(--md-tabbed-icon--prev);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:background-color .25s,transform .25s;width:100%}.md-typeset .tabbed-control{background:linear-gradient(to right,var(--md-default-bg-color) 60%,#0000);display:flex;height:1.9rem;justify-content:start;pointer-events:none;position:absolute;transition:opacity 125ms;width:1.2rem}[dir=rtl] .md-typeset .tabbed-control{transform:rotate(180deg)}.md-typeset .tabbed-control[hidden]{opacity:0}.md-typeset .tabbed-control--next{background:linear-gradient(to left,var(--md-default-bg-color) 60%,#0000);justify-content:end;right:0}.md-typeset .tabbed-control--next .tabbed-button:after{-webkit-mask-image:var(--md-tabbed-icon--next);mask-image:var(--md-tabbed-icon--next)}@media screen and (max-width:44.9375em){[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels{padding-left:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels{padding-right:.8rem}.md-content__inner>.tabbed-set .tabbed-labels{margin:0 -.8rem;max-width:100vw;scroll-padding-inline-start:.8rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels:after{padding-right:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels:after{padding-left:.8rem}.md-content__inner>.tabbed-set .tabbed-labels:after{content:""}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{padding-left:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{padding-right:.8rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{margin-left:-.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{margin-right:-.8rem}.md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{width:2rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{padding-right:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{padding-left:.8rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{margin-right:-.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{margin-left:-.8rem}.md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{width:2rem}}@media screen{.md-typeset .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9){color:var(--md-accent-fg-color)}.md-typeset .no-js .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.md-typeset .no-js .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.md-typeset .no-js .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.md-typeset .no-js .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.md-typeset .no-js .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.md-typeset .no-js .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.md-typeset .no-js .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.md-typeset .no-js .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.md-typeset .no-js .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.md-typeset .no-js .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.md-typeset .no-js .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.md-typeset .no-js .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.md-typeset .no-js .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.md-typeset .no-js .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.md-typeset .no-js .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.md-typeset .no-js .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.md-typeset .no-js .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.md-typeset .no-js .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.md-typeset .no-js .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.md-typeset .no-js .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9),.no-js .md-typeset .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.no-js .md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.no-js .md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.no-js .md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.no-js .md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.no-js .md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.no-js .md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.no-js .md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.no-js .md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.no-js .md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.no-js .md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.no-js .md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.no-js .md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.no-js .md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.no-js .md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.no-js .md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.no-js .md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.no-js .md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.no-js .md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.no-js .md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9){border-color:var(--md-accent-fg-color)}}.md-typeset .tabbed-set>input:first-child.focus-visible~.tabbed-labels>:first-child,.md-typeset .tabbed-set>input:nth-child(10).focus-visible~.tabbed-labels>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11).focus-visible~.tabbed-labels>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12).focus-visible~.tabbed-labels>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13).focus-visible~.tabbed-labels>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14).focus-visible~.tabbed-labels>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15).focus-visible~.tabbed-labels>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16).focus-visible~.tabbed-labels>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17).focus-visible~.tabbed-labels>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18).focus-visible~.tabbed-labels>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19).focus-visible~.tabbed-labels>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2).focus-visible~.tabbed-labels>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20).focus-visible~.tabbed-labels>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3).focus-visible~.tabbed-labels>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4).focus-visible~.tabbed-labels>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5).focus-visible~.tabbed-labels>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6).focus-visible~.tabbed-labels>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7).focus-visible~.tabbed-labels>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8).focus-visible~.tabbed-labels>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9).focus-visible~.tabbed-labels>:nth-child(9){background-color:var(--md-accent-fg-color--transparent)}.md-typeset .tabbed-set>input:first-child:checked~.tabbed-content>:first-child,.md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-content>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-content>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-content>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-content>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-content>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-content>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-content>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-content>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-content>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-content>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-content>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-content>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-content>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-content>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-content>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-content>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-content>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-content>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-content>:nth-child(9){display:block}:root{--md-tasklist-icon:url('data:image/svg+xml;charset=utf-8,');--md-tasklist-icon--checked:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .task-list-item{list-style-type:none;position:relative}[dir=ltr] .md-typeset .task-list-item [type=checkbox]{left:-2em}[dir=rtl] .md-typeset .task-list-item [type=checkbox]{right:-2em}.md-typeset .task-list-item [type=checkbox]{position:absolute;top:.45em}.md-typeset .task-list-control [type=checkbox]{opacity:0;z-index:-1}[dir=ltr] .md-typeset .task-list-indicator:before{left:-1.5em}[dir=rtl] .md-typeset .task-list-indicator:before{right:-1.5em}.md-typeset .task-list-indicator:before{background-color:var(--md-default-fg-color--lightest);content:"";height:1.25em;-webkit-mask-image:var(--md-tasklist-icon);mask-image:var(--md-tasklist-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.15em;width:1.25em}.md-typeset [type=checkbox]:checked+.task-list-indicator:before{background-color:#00e676;-webkit-mask-image:var(--md-tasklist-icon--checked);mask-image:var(--md-tasklist-icon--checked)}:root>*{--md-mermaid-font-family:var(--md-text-font-family),sans-serif;--md-mermaid-edge-color:var(--md-code-fg-color);--md-mermaid-node-bg-color:var(--md-accent-fg-color--transparent);--md-mermaid-node-fg-color:var(--md-accent-fg-color);--md-mermaid-label-bg-color:var(--md-default-bg-color);--md-mermaid-label-fg-color:var(--md-code-fg-color);--md-mermaid-sequence-actor-bg-color:var(--md-mermaid-label-bg-color);--md-mermaid-sequence-actor-fg-color:var(--md-mermaid-label-fg-color);--md-mermaid-sequence-actor-border-color:var(--md-mermaid-node-fg-color);--md-mermaid-sequence-actor-line-color:var(--md-default-fg-color--lighter);--md-mermaid-sequence-actorman-bg-color:var(--md-mermaid-label-bg-color);--md-mermaid-sequence-actorman-line-color:var(--md-mermaid-node-fg-color);--md-mermaid-sequence-box-bg-color:var(--md-mermaid-node-bg-color);--md-mermaid-sequence-box-fg-color:var(--md-mermaid-edge-color);--md-mermaid-sequence-label-bg-color:var(--md-mermaid-node-bg-color);--md-mermaid-sequence-label-fg-color:var(--md-mermaid-node-fg-color);--md-mermaid-sequence-loop-bg-color:var(--md-mermaid-node-bg-color);--md-mermaid-sequence-loop-fg-color:var(--md-mermaid-edge-color);--md-mermaid-sequence-loop-border-color:var(--md-mermaid-node-fg-color);--md-mermaid-sequence-message-fg-color:var(--md-mermaid-edge-color);--md-mermaid-sequence-message-line-color:var(--md-mermaid-edge-color);--md-mermaid-sequence-note-bg-color:var(--md-mermaid-label-bg-color);--md-mermaid-sequence-note-fg-color:var(--md-mermaid-edge-color);--md-mermaid-sequence-note-border-color:var(--md-mermaid-label-fg-color);--md-mermaid-sequence-number-bg-color:var(--md-mermaid-node-fg-color);--md-mermaid-sequence-number-fg-color:var(--md-accent-bg-color)}.mermaid{line-height:normal;margin:1em 0}@media screen and (min-width:45em){[dir=ltr] .md-typeset .inline{float:left}[dir=rtl] .md-typeset .inline{float:right}[dir=ltr] .md-typeset .inline{margin-right:.8rem}[dir=rtl] .md-typeset .inline{margin-left:.8rem}.md-typeset .inline{margin-bottom:.8rem;margin-top:0;width:11.7rem}[dir=ltr] .md-typeset .inline.end{float:right}[dir=rtl] .md-typeset .inline.end{float:left}[dir=ltr] .md-typeset .inline.end{margin-left:.8rem;margin-right:0}[dir=rtl] .md-typeset .inline.end{margin-left:0;margin-right:.8rem}} \ No newline at end of file diff --git a/develop/assets/stylesheets/main.046329b4.min.css.map b/develop/assets/stylesheets/main.046329b4.min.css.map deleted file mode 100644 index d84ca009..00000000 --- a/develop/assets/stylesheets/main.046329b4.min.css.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["src/assets/stylesheets/main/components/_meta.scss","../../../src/assets/stylesheets/main.scss","src/assets/stylesheets/main/_resets.scss","src/assets/stylesheets/main/_colors.scss","src/assets/stylesheets/main/_icons.scss","src/assets/stylesheets/main/_typeset.scss","src/assets/stylesheets/utilities/_break.scss","src/assets/stylesheets/main/components/_author.scss","src/assets/stylesheets/main/components/_banner.scss","src/assets/stylesheets/main/components/_base.scss","src/assets/stylesheets/main/components/_clipboard.scss","src/assets/stylesheets/main/components/_consent.scss","src/assets/stylesheets/main/components/_content.scss","src/assets/stylesheets/main/components/_dialog.scss","src/assets/stylesheets/main/components/_feedback.scss","src/assets/stylesheets/main/components/_footer.scss","src/assets/stylesheets/main/components/_form.scss","src/assets/stylesheets/main/components/_header.scss","node_modules/material-design-color/material-color.scss","src/assets/stylesheets/main/components/_nav.scss","src/assets/stylesheets/main/components/_pagination.scss","src/assets/stylesheets/main/components/_post.scss","src/assets/stylesheets/main/components/_search.scss","src/assets/stylesheets/main/components/_select.scss","src/assets/stylesheets/main/components/_sidebar.scss","src/assets/stylesheets/main/components/_source.scss","src/assets/stylesheets/main/components/_status.scss","src/assets/stylesheets/main/components/_tabs.scss","src/assets/stylesheets/main/components/_tag.scss","src/assets/stylesheets/main/components/_tooltip.scss","src/assets/stylesheets/main/components/_top.scss","src/assets/stylesheets/main/components/_version.scss","src/assets/stylesheets/main/extensions/markdown/_admonition.scss","src/assets/stylesheets/main/extensions/markdown/_footnotes.scss","src/assets/stylesheets/main/extensions/markdown/_toc.scss","src/assets/stylesheets/main/extensions/pymdownx/_arithmatex.scss","src/assets/stylesheets/main/extensions/pymdownx/_critic.scss","src/assets/stylesheets/main/extensions/pymdownx/_details.scss","src/assets/stylesheets/main/extensions/pymdownx/_emoji.scss","src/assets/stylesheets/main/extensions/pymdownx/_highlight.scss","src/assets/stylesheets/main/extensions/pymdownx/_keys.scss","src/assets/stylesheets/main/extensions/pymdownx/_tabbed.scss","src/assets/stylesheets/main/extensions/pymdownx/_tasklist.scss","src/assets/stylesheets/main/integrations/_mermaid.scss","src/assets/stylesheets/main/_modifiers.scss"],"names":[],"mappings":"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gC/BupGN,C+BlpGE,4DACE,0B/BqpGJ,C+BlpGI,0EACE,wBAlBG,CAmBH,iDAAA,CAAA,yC/BopGN,C+BhpGI,wEACE,a/BkpGN,C+BvqGE,4DACE,oB/B0qGJ,C+BvqGI,sFACE,gC/ByqGN,C+BpqGE,oEACE,0B/BuqGJ,C+BpqGI,kFACE,wBAlBG,CAmBH,qDAAA,CAAA,6C/BsqGN,C+BlqGI,gFACE,a/BoqGN,C+BzrGE,8DACE,oB/B4rGJ,C+BzrGI,wFACE,gC/B2rGN,C+BtrGE,sEACE,0B/ByrGJ,C+BtrGI,oFACE,wBAlBG,CAmBH,sDAAA,CAAA,8C/BwrGN,C+BprGI,kFACE,a/BsrGN,C+B3sGE,4DACE,oB/B8sGJ,C+B3sGI,sFACE,gC/B6sGN,C+BxsGE,oEACE,0B/B2sGJ,C+BxsGI,kFACE,wBAlBG,CAmBH,qDAAA,CAAA,6C/B0sGN,C+BtsGI,gFACE,a/BwsGN,C+B7tGE,4DACE,oB/BguGJ,C+B7tGI,sFACE,gC/B+tGN,C+B1tGE,oEACE,0B/B6tGJ,C+B1tGI,kFACE,wBAlBG,CAmBH,qDAAA,CAAA,6C/B4tGN,C+BxtGI,gFACE,a/B0tGN,C+B/uGE,0DACE,oB/BkvGJ,C+B/uGI,oFACE,gC/BivGN,C+B5uGE,kEACE,0B/B+uGJ,C+B5uGI,gFACE,wBAlBG,CAmBH,oDAAA,CAAA,4C/B8uGN,C+B1uGI,8EACE,a/B4uGN,C+BjwGE,oDACE,oB/BowGJ,C+BjwGI,8EACE,gC/BmwGN,C+B9vGE,4DACE,0B/BiwGJ,C+B9vGI,0EACE,wBAlBG,CAmBH,iDAAA,CAAA,yC/BgwGN,C+B5vGI,wEACE,a/B8vGN,C+BnxGE,4DACE,oB/BsxGJ,C+BnxGI,sFACE,gC/BqxGN,C+BhxGE,oEACE,0B/BmxGJ,C+BhxGI,kFACE,wBAlBG,CAmBH,qDAAA,CAAA,6C/BkxGN,C+B9wGI,gFACE,a/BgxGN,C+BryGE,wDACE,oB/BwyGJ,C+BryGI,kFACE,gC/BuyGN,C+BlyGE,gEACE,0B/BqyGJ,C+BlyGI,8EACE,wBAlBG,CAmBH,mDAAA,CAAA,2C/BoyGN,C+BhyGI,4EACE,a/B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","file":"main.css"} \ No newline at end of file diff --git a/develop/assets/stylesheets/main.30068a00.min.css b/develop/assets/stylesheets/main.30068a00.min.css new file mode 100644 index 00000000..f813e9a8 --- /dev/null +++ b/develop/assets/stylesheets/main.30068a00.min.css @@ -0,0 +1 @@ +@charset "UTF-8";html{-webkit-text-size-adjust:none;-moz-text-size-adjust:none;text-size-adjust:none;box-sizing:border-box}*,:after,:before{box-sizing:inherit}@media (prefers-reduced-motion){*,:after,:before{transition:none!important}}body{margin:0}a,button,input,label{-webkit-tap-highlight-color:transparent}a{color:inherit;text-decoration:none}hr{border:0;box-sizing:initial;display:block;height:.05rem;overflow:visible;padding:0}small{font-size:80%}sub,sup{line-height:1em}img{border-style:none}table{border-collapse:initial;border-spacing:0}td,th{font-weight:400;vertical-align:top}button{background:#0000;border:0;font-family:inherit;font-size:inherit;margin:0;padding:0}input{border:0;outline:none}:root{--md-primary-fg-color:#4051b5;--md-primary-fg-color--light:#5d6cc0;--md-primary-fg-color--dark:#303fa1;--md-primary-bg-color:#fff;--md-primary-bg-color--light:#ffffffb3;--md-accent-fg-color:#526cfe;--md-accent-fg-color--transparent:#526cfe1a;--md-accent-bg-color:#fff;--md-accent-bg-color--light:#ffffffb3}[data-md-color-scheme=default]{color-scheme:light}[data-md-color-scheme=default] img[src$="#gh-dark-mode-only"],[data-md-color-scheme=default] img[src$="#only-dark"]{display:none}:root,[data-md-color-scheme=default]{--md-default-fg-color:#000000de;--md-default-fg-color--light:#0000008a;--md-default-fg-color--lighter:#00000052;--md-default-fg-color--lightest:#00000012;--md-default-bg-color:#fff;--md-default-bg-color--light:#ffffffb3;--md-default-bg-color--lighter:#ffffff4d;--md-default-bg-color--lightest:#ffffff1f;--md-code-fg-color:#36464e;--md-code-bg-color:#f5f5f5;--md-code-hl-color:#4287ff;--md-code-hl-color--light:#4287ff1a;--md-code-hl-number-color:#d52a2a;--md-code-hl-special-color:#db1457;--md-code-hl-function-color:#a846b9;--md-code-hl-constant-color:#6e59d9;--md-code-hl-keyword-color:#3f6ec6;--md-code-hl-string-color:#1c7d4d;--md-code-hl-name-color:var(--md-code-fg-color);--md-code-hl-operator-color:var(--md-default-fg-color--light);--md-code-hl-punctuation-color:var(--md-default-fg-color--light);--md-code-hl-comment-color:var(--md-default-fg-color--light);--md-code-hl-generic-color:var(--md-default-fg-color--light);--md-code-hl-variable-color:var(--md-default-fg-color--light);--md-typeset-color:var(--md-default-fg-color);--md-typeset-a-color:var(--md-primary-fg-color);--md-typeset-mark-color:#ffff0080;--md-typeset-del-color:#f5503d26;--md-typeset-ins-color:#0bd57026;--md-typeset-kbd-color:#fafafa;--md-typeset-kbd-accent-color:#fff;--md-typeset-kbd-border-color:#b8b8b8;--md-typeset-table-color:#0000001f;--md-typeset-table-color--light:rgba(0,0,0,.035);--md-admonition-fg-color:var(--md-default-fg-color);--md-admonition-bg-color:var(--md-default-bg-color);--md-warning-fg-color:#000000de;--md-warning-bg-color:#ff9;--md-footer-fg-color:#fff;--md-footer-fg-color--light:#ffffffb3;--md-footer-fg-color--lighter:#ffffff73;--md-footer-bg-color:#000000de;--md-footer-bg-color--dark:#00000052;--md-shadow-z1:0 0.2rem 0.5rem #0000000d,0 0 0.05rem #0000001a;--md-shadow-z2:0 0.2rem 0.5rem #0000001a,0 0 0.05rem #00000040;--md-shadow-z3:0 0.2rem 0.5rem #0003,0 0 0.05rem #00000059}.md-icon svg{fill:currentcolor;display:block;height:1.2rem;width:1.2rem}body{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;--md-text-font-family:var(--md-text-font,_),-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif;--md-code-font-family:var(--md-code-font,_),SFMono-Regular,Consolas,Menlo,monospace}aside,body,input{font-feature-settings:"kern","liga";color:var(--md-typeset-color);font-family:var(--md-text-font-family)}code,kbd,pre{font-feature-settings:"kern";font-family:var(--md-code-font-family)}:root{--md-typeset-table-sort-icon:url('data:image/svg+xml;charset=utf-8,');--md-typeset-table-sort-icon--asc:url('data:image/svg+xml;charset=utf-8,');--md-typeset-table-sort-icon--desc:url('data:image/svg+xml;charset=utf-8,')}.md-typeset{-webkit-print-color-adjust:exact;color-adjust:exact;font-size:.8rem;line-height:1.6}@media print{.md-typeset{font-size:.68rem}}.md-typeset blockquote,.md-typeset dl,.md-typeset figure,.md-typeset ol,.md-typeset pre,.md-typeset ul{margin-bottom:1em;margin-top:1em}.md-typeset h1{color:var(--md-default-fg-color--light);font-size:2em;line-height:1.3;margin:0 0 1.25em}.md-typeset h1,.md-typeset h2{font-weight:300;letter-spacing:-.01em}.md-typeset h2{font-size:1.5625em;line-height:1.4;margin:1.6em 0 .64em}.md-typeset h3{font-size:1.25em;font-weight:400;letter-spacing:-.01em;line-height:1.5;margin:1.6em 0 .8em}.md-typeset h2+h3{margin-top:.8em}.md-typeset h4{font-weight:700;letter-spacing:-.01em;margin:1em 0}.md-typeset h5,.md-typeset h6{color:var(--md-default-fg-color--light);font-size:.8em;font-weight:700;letter-spacing:-.01em;margin:1.25em 0}.md-typeset h5{text-transform:uppercase}.md-typeset hr{border-bottom:.05rem solid var(--md-default-fg-color--lightest);display:flow-root;margin:1.5em 0}.md-typeset a{color:var(--md-typeset-a-color);word-break:break-word}.md-typeset a,.md-typeset a:before{transition:color 125ms}.md-typeset a:focus,.md-typeset a:hover{color:var(--md-accent-fg-color)}.md-typeset a:focus code,.md-typeset a:hover code{background-color:var(--md-accent-fg-color--transparent)}.md-typeset a code{color:currentcolor;transition:background-color 125ms}.md-typeset a.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-typeset code,.md-typeset kbd,.md-typeset pre{color:var(--md-code-fg-color);direction:ltr;font-variant-ligatures:none}@media print{.md-typeset code,.md-typeset kbd,.md-typeset pre{white-space:pre-wrap}}.md-typeset code{background-color:var(--md-code-bg-color);border-radius:.1rem;-webkit-box-decoration-break:clone;box-decoration-break:clone;font-size:.85em;padding:0 .2941176471em;word-break:break-word}.md-typeset code:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}.md-typeset pre{display:flow-root;line-height:1.4;position:relative}.md-typeset pre>code{-webkit-box-decoration-break:slice;box-decoration-break:slice;box-shadow:none;display:block;margin:0;outline-color:var(--md-accent-fg-color);overflow:auto;padding:.7720588235em 1.1764705882em;scrollbar-color:var(--md-default-fg-color--lighter) #0000;scrollbar-width:thin;touch-action:auto;word-break:normal}.md-typeset pre>code:hover{scrollbar-color:var(--md-accent-fg-color) #0000}.md-typeset pre>code::-webkit-scrollbar{height:.2rem;width:.2rem}.md-typeset pre>code::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-typeset pre>code::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}.md-typeset kbd{background-color:var(--md-typeset-kbd-color);border-radius:.1rem;box-shadow:0 .1rem 0 .05rem var(--md-typeset-kbd-border-color),0 .1rem 0 var(--md-typeset-kbd-border-color),0 -.1rem .2rem var(--md-typeset-kbd-accent-color) inset;color:var(--md-default-fg-color);display:inline-block;font-size:.75em;padding:0 .6666666667em;vertical-align:text-top;word-break:break-word}.md-typeset mark{background-color:var(--md-typeset-mark-color);-webkit-box-decoration-break:clone;box-decoration-break:clone;color:inherit;word-break:break-word}.md-typeset abbr{border-bottom:.05rem dotted var(--md-default-fg-color--light);cursor:help;text-decoration:none}@media (hover:none){.md-typeset abbr[title]:focus:after,.md-typeset abbr[title]:hover:after{background-color:var(--md-default-fg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z3);color:var(--md-default-bg-color);content:attr(title);font-size:.7rem;left:.8rem;margin-top:2em;padding:.2rem .3rem;position:absolute;right:.8rem}}.md-typeset small{opacity:.75}[dir=ltr] .md-typeset sub,[dir=ltr] .md-typeset sup{margin-left:.078125em}[dir=rtl] .md-typeset sub,[dir=rtl] .md-typeset sup{margin-right:.078125em}[dir=ltr] .md-typeset blockquote{padding-left:.6rem}[dir=rtl] .md-typeset blockquote{padding-right:.6rem}[dir=ltr] .md-typeset blockquote{border-left:.2rem solid var(--md-default-fg-color--lighter)}[dir=rtl] .md-typeset blockquote{border-right:.2rem solid var(--md-default-fg-color--lighter)}.md-typeset blockquote{color:var(--md-default-fg-color--light);margin-left:0;margin-right:0}.md-typeset ul{list-style-type:disc}[dir=ltr] .md-typeset ol,[dir=ltr] .md-typeset ul{margin-left:.625em}[dir=rtl] .md-typeset ol,[dir=rtl] .md-typeset ul{margin-right:.625em}.md-typeset ol,.md-typeset ul{padding:0}.md-typeset ol:not([hidden]),.md-typeset ul:not([hidden]){display:flow-root}.md-typeset ol ol,.md-typeset ul ol{list-style-type:lower-alpha}.md-typeset ol ol ol,.md-typeset ul ol ol{list-style-type:lower-roman}[dir=ltr] .md-typeset ol li,[dir=ltr] .md-typeset ul li{margin-left:1.25em}[dir=rtl] .md-typeset ol li,[dir=rtl] .md-typeset ul li{margin-right:1.25em}.md-typeset ol li,.md-typeset ul li{margin-bottom:.5em}.md-typeset ol li blockquote,.md-typeset ol li p,.md-typeset ul li blockquote,.md-typeset ul li p{margin:.5em 0}.md-typeset ol li:last-child,.md-typeset ul li:last-child{margin-bottom:0}[dir=ltr] .md-typeset ol li ol,[dir=ltr] .md-typeset ol li ul,[dir=ltr] .md-typeset ul li ol,[dir=ltr] .md-typeset ul li ul{margin-left:.625em}[dir=rtl] .md-typeset ol li ol,[dir=rtl] .md-typeset ol li ul,[dir=rtl] .md-typeset ul li ol,[dir=rtl] .md-typeset ul li ul{margin-right:.625em}.md-typeset ol li ol,.md-typeset ol li ul,.md-typeset ul li ol,.md-typeset ul li ul{margin-bottom:.5em;margin-top:.5em}[dir=ltr] .md-typeset dd{margin-left:1.875em}[dir=rtl] .md-typeset dd{margin-right:1.875em}.md-typeset dd{margin-bottom:1.5em;margin-top:1em}.md-typeset img,.md-typeset svg,.md-typeset video{height:auto;max-width:100%}.md-typeset img[align=left]{margin:1em 1em 1em 0}.md-typeset img[align=right]{margin:1em 0 1em 1em}.md-typeset img[align]:only-child{margin-top:0}.md-typeset figure{display:flow-root;margin:1em auto;max-width:100%;text-align:center;width:-webkit-fit-content;width:-moz-fit-content;width:fit-content}.md-typeset figure img{display:block}.md-typeset figcaption{font-style:italic;margin:1em auto;max-width:24rem}.md-typeset iframe{max-width:100%}.md-typeset table:not([class]){background-color:var(--md-default-bg-color);border:.05rem solid var(--md-typeset-table-color);border-radius:.1rem;display:inline-block;font-size:.64rem;max-width:100%;overflow:auto;touch-action:auto}@media print{.md-typeset table:not([class]){display:table}}.md-typeset table:not([class])+*{margin-top:1.5em}.md-typeset table:not([class]) td>:first-child,.md-typeset table:not([class]) th>:first-child{margin-top:0}.md-typeset table:not([class]) td>:last-child,.md-typeset table:not([class]) th>:last-child{margin-bottom:0}.md-typeset table:not([class]) td:not([align]),.md-typeset table:not([class]) th:not([align]){text-align:left}[dir=rtl] .md-typeset table:not([class]) td:not([align]),[dir=rtl] .md-typeset table:not([class]) th:not([align]){text-align:right}.md-typeset table:not([class]) th{font-weight:700;min-width:5rem;padding:.9375em 1.25em;vertical-align:top}.md-typeset table:not([class]) td{border-top:.05rem solid var(--md-typeset-table-color);padding:.9375em 1.25em;vertical-align:top}.md-typeset table:not([class]) tbody tr{transition:background-color 125ms}.md-typeset table:not([class]) tbody tr:hover{background-color:var(--md-typeset-table-color--light);box-shadow:0 .05rem 0 var(--md-default-bg-color) inset}.md-typeset table:not([class]) a{word-break:normal}.md-typeset table th[role=columnheader]{cursor:pointer}[dir=ltr] .md-typeset table th[role=columnheader]:after{margin-left:.5em}[dir=rtl] .md-typeset table th[role=columnheader]:after{margin-right:.5em}.md-typeset table th[role=columnheader]:after{content:"";display:inline-block;height:1.2em;-webkit-mask-image:var(--md-typeset-table-sort-icon);mask-image:var(--md-typeset-table-sort-icon);-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:background-color 125ms;vertical-align:text-bottom;width:1.2em}.md-typeset table th[role=columnheader]:hover:after{background-color:var(--md-default-fg-color--lighter)}.md-typeset table th[role=columnheader][aria-sort=ascending]:after{background-color:var(--md-default-fg-color--light);-webkit-mask-image:var(--md-typeset-table-sort-icon--asc);mask-image:var(--md-typeset-table-sort-icon--asc)}.md-typeset table th[role=columnheader][aria-sort=descending]:after{background-color:var(--md-default-fg-color--light);-webkit-mask-image:var(--md-typeset-table-sort-icon--desc);mask-image:var(--md-typeset-table-sort-icon--desc)}.md-typeset__scrollwrap{margin:1em -.8rem;overflow-x:auto;touch-action:auto}.md-typeset__table{display:inline-block;margin-bottom:.5em;padding:0 .8rem}@media print{.md-typeset__table{display:block}}html .md-typeset__table table{display:table;margin:0;overflow:hidden;width:100%}@media screen and (max-width:44.9375em){.md-content__inner>pre{margin:1em -.8rem}.md-content__inner>pre code{border-radius:0}}.md-typeset .md-author{display:block;flex-shrink:0;height:1.6rem;overflow:hidden;position:relative;transition:color 125ms,transform 125ms;width:1.6rem}.md-typeset .md-author img{border-radius:100%;display:block}.md-typeset .md-author--more{background:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--lighter);font-size:.6rem;font-weight:700;line-height:1.6rem;text-align:center}.md-typeset .md-author--long{height:2.4rem;width:2.4rem}.md-typeset a.md-author{transform:scale(1)}.md-typeset a.md-author img{filter:grayscale(100%) opacity(75%);transition:filter 125ms}.md-typeset a.md-author:focus,.md-typeset a.md-author:hover{transform:scale(1.1);z-index:1}.md-typeset a.md-author:focus img,.md-typeset a.md-author:hover img{filter:grayscale(0)}.md-banner{background-color:var(--md-footer-bg-color);color:var(--md-footer-fg-color);overflow:auto}@media print{.md-banner{display:none}}.md-banner--warning{background-color:var(--md-warning-bg-color);color:var(--md-warning-fg-color)}.md-banner__inner{font-size:.7rem;margin:.6rem auto;padding:0 .8rem}[dir=ltr] .md-banner__button{float:right}[dir=rtl] .md-banner__button{float:left}.md-banner__button{color:inherit;cursor:pointer;transition:opacity .25s}.no-js .md-banner__button{display:none}.md-banner__button:hover{opacity:.7}html{font-size:125%;height:100%;overflow-x:hidden}@media screen and (min-width:100em){html{font-size:137.5%}}@media screen and (min-width:125em){html{font-size:150%}}body{background-color:var(--md-default-bg-color);display:flex;flex-direction:column;font-size:.5rem;min-height:100%;position:relative;width:100%}@media print{body{display:block}}@media screen and (max-width:59.9375em){body[data-md-scrolllock]{position:fixed}}.md-grid{margin-left:auto;margin-right:auto;max-width:61rem}.md-container{display:flex;flex-direction:column;flex-grow:1}@media print{.md-container{display:block}}.md-main{flex-grow:1}.md-main__inner{display:flex;height:100%;margin-top:1.5rem}.md-ellipsis{overflow:hidden;text-overflow:ellipsis}.md-toggle{display:none}.md-option{height:0;opacity:0;position:absolute;width:0}.md-option:checked+label:not([hidden]){display:block}.md-option.focus-visible+label{outline-color:var(--md-accent-fg-color);outline-style:auto}.md-skip{background-color:var(--md-default-fg-color);border-radius:.1rem;color:var(--md-default-bg-color);font-size:.64rem;margin:.5rem;opacity:0;outline-color:var(--md-accent-fg-color);padding:.3rem .5rem;position:fixed;transform:translateY(.4rem);z-index:-1}.md-skip:focus{opacity:1;transform:translateY(0);transition:transform .25s cubic-bezier(.4,0,.2,1),opacity 175ms 75ms;z-index:10}@page{margin:25mm}:root{--md-clipboard-icon:url('data:image/svg+xml;charset=utf-8,')}.md-clipboard{border-radius:.1rem;color:var(--md-default-fg-color--lightest);cursor:pointer;height:1.5em;outline-color:var(--md-accent-fg-color);outline-offset:.1rem;position:absolute;right:.5em;top:.5em;transition:color .25s;width:1.5em;z-index:1}@media print{.md-clipboard{display:none}}.md-clipboard:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}:hover>.md-clipboard{color:var(--md-default-fg-color--light)}.md-clipboard:focus,.md-clipboard:hover{color:var(--md-accent-fg-color)}.md-clipboard:after{background-color:currentcolor;content:"";display:block;height:1.125em;margin:0 auto;-webkit-mask-image:var(--md-clipboard-icon);mask-image:var(--md-clipboard-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:1.125em}.md-clipboard--inline{cursor:pointer}.md-clipboard--inline code{transition:color .25s,background-color .25s}.md-clipboard--inline:focus code,.md-clipboard--inline:hover code{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}@keyframes consent{0%{opacity:0;transform:translateY(100%)}to{opacity:1;transform:translateY(0)}}@keyframes overlay{0%{opacity:0}to{opacity:1}}.md-consent__overlay{animation:overlay .25s both;-webkit-backdrop-filter:blur(.1rem);backdrop-filter:blur(.1rem);background-color:#0000008a;height:100%;opacity:1;position:fixed;top:0;width:100%;z-index:5}.md-consent__inner{animation:consent .5s cubic-bezier(.1,.7,.1,1) both;background-color:var(--md-default-bg-color);border:0;border-radius:.1rem;bottom:0;box-shadow:0 0 .2rem #0000001a,0 .2rem .4rem #0003;max-height:100%;overflow:auto;padding:0;position:fixed;width:100%;z-index:5}.md-consent__form{padding:.8rem}.md-consent__settings{display:none;margin:1em 0}input:checked+.md-consent__settings{display:block}.md-consent__controls{margin-bottom:.8rem}.md-typeset .md-consent__controls .md-button{display:inline}@media screen and (max-width:44.9375em){.md-typeset .md-consent__controls .md-button{display:block;margin-top:.4rem;text-align:center;width:100%}}.md-consent label{cursor:pointer}.md-content{flex-grow:1;min-width:0}.md-content__inner{margin:0 .8rem 1.2rem;padding-top:.6rem}@media screen and (min-width:76.25em){[dir=ltr] .md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-left:1.2rem}[dir=ltr] .md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner,[dir=rtl] .md-sidebar--primary:not([hidden])~.md-content>.md-content__inner{margin-right:1.2rem}[dir=rtl] .md-sidebar--secondary:not([hidden])~.md-content>.md-content__inner{margin-left:1.2rem}}.md-content__inner:before{content:"";display:block;height:.4rem}.md-content__inner>:last-child{margin-bottom:0}[dir=ltr] .md-content__button{float:right}[dir=rtl] .md-content__button{float:left}[dir=ltr] .md-content__button{margin-left:.4rem}[dir=rtl] .md-content__button{margin-right:.4rem}.md-content__button{margin:.4rem 0;padding:0}@media print{.md-content__button{display:none}}.md-typeset .md-content__button{color:var(--md-default-fg-color--lighter)}.md-content__button svg{display:inline;vertical-align:top}[dir=rtl] .md-content__button svg{transform:scaleX(-1)}[dir=ltr] .md-dialog{right:.8rem}[dir=rtl] .md-dialog{left:.8rem}.md-dialog{background-color:var(--md-default-fg-color);border-radius:.1rem;bottom:.8rem;box-shadow:var(--md-shadow-z3);min-width:11.1rem;opacity:0;padding:.4rem .6rem;pointer-events:none;position:fixed;transform:translateY(100%);transition:transform 0ms .4s,opacity .4s;z-index:4}@media print{.md-dialog{display:none}}.md-dialog--active{opacity:1;pointer-events:auto;transform:translateY(0);transition:transform .4s cubic-bezier(.075,.85,.175,1),opacity .4s}.md-dialog__inner{color:var(--md-default-bg-color);font-size:.7rem}.md-feedback{margin:2em 0 1em;text-align:center}.md-feedback fieldset{border:none;margin:0;padding:0}.md-feedback__title{font-weight:700;margin:1em auto}.md-feedback__inner{position:relative}.md-feedback__list{align-content:baseline;display:flex;flex-wrap:wrap;justify-content:center;position:relative}.md-feedback__list:hover .md-icon:not(:disabled){color:var(--md-default-fg-color--lighter)}:disabled .md-feedback__list{min-height:1.8rem}.md-feedback__icon{color:var(--md-default-fg-color--light);cursor:pointer;flex-shrink:0;margin:0 .1rem;transition:color 125ms}.md-feedback__icon:not(:disabled).md-icon:hover{color:var(--md-accent-fg-color)}.md-feedback__icon:disabled{color:var(--md-default-fg-color--lightest);pointer-events:none}.md-feedback__note{opacity:0;position:relative;transform:translateY(.4rem);transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s}.md-feedback__note>*{margin:0 auto;max-width:16rem}:disabled .md-feedback__note{opacity:1;transform:translateY(0)}.md-footer{background-color:var(--md-footer-bg-color);color:var(--md-footer-fg-color)}@media print{.md-footer{display:none}}.md-footer__inner{justify-content:space-between;overflow:auto;padding:.2rem}.md-footer__inner:not([hidden]){display:flex}.md-footer__link{align-items:end;display:flex;flex-grow:0.01;margin-bottom:.4rem;margin-top:1rem;max-width:100%;outline-color:var(--md-accent-fg-color);overflow:hidden;transition:opacity .25s}.md-footer__link:focus,.md-footer__link:hover{opacity:.7}[dir=rtl] .md-footer__link svg{transform:scaleX(-1)}@media screen and (max-width:44.9375em){.md-footer__link--prev{flex-shrink:0}.md-footer__link--prev .md-footer__title{display:none}}[dir=ltr] .md-footer__link--next{margin-left:auto}[dir=rtl] .md-footer__link--next{margin-right:auto}.md-footer__link--next{text-align:right}[dir=rtl] .md-footer__link--next{text-align:left}.md-footer__title{flex-grow:1;font-size:.9rem;margin-bottom:.7rem;max-width:calc(100% - 2.4rem);padding:0 1rem;white-space:nowrap}.md-footer__button{margin:.2rem;padding:.4rem}.md-footer__direction{font-size:.64rem;opacity:.7}.md-footer-meta{background-color:var(--md-footer-bg-color--dark)}.md-footer-meta__inner{display:flex;flex-wrap:wrap;justify-content:space-between;padding:.2rem}html .md-footer-meta.md-typeset a{color:var(--md-footer-fg-color--light)}html .md-footer-meta.md-typeset a:focus,html .md-footer-meta.md-typeset a:hover{color:var(--md-footer-fg-color)}.md-copyright{color:var(--md-footer-fg-color--lighter);font-size:.64rem;margin:auto .6rem;padding:.4rem 0;width:100%}@media screen and (min-width:45em){.md-copyright{width:auto}}.md-copyright__highlight{color:var(--md-footer-fg-color--light)}.md-social{display:inline-flex;gap:.2rem;margin:0 .4rem;padding:.2rem 0 .6rem}@media screen and (min-width:45em){.md-social{padding:.6rem 0}}.md-social__link{display:inline-block;height:1.6rem;text-align:center;width:1.6rem}.md-social__link:before{line-height:1.9}.md-social__link svg{fill:currentcolor;max-height:.8rem;vertical-align:-25%}.md-typeset .md-button{border:.1rem solid;border-radius:.1rem;color:var(--md-primary-fg-color);cursor:pointer;display:inline-block;font-weight:700;padding:.625em 2em;transition:color 125ms,background-color 125ms,border-color 125ms}.md-typeset .md-button--primary{background-color:var(--md-primary-fg-color);border-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color)}.md-typeset .md-button:focus,.md-typeset .md-button:hover{background-color:var(--md-accent-fg-color);border-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}[dir=ltr] .md-typeset .md-input{border-top-left-radius:.1rem}[dir=ltr] .md-typeset .md-input,[dir=rtl] .md-typeset .md-input{border-top-right-radius:.1rem}[dir=rtl] .md-typeset .md-input{border-top-left-radius:.1rem}.md-typeset .md-input{border-bottom:.1rem solid var(--md-default-fg-color--lighter);box-shadow:var(--md-shadow-z1);font-size:.8rem;height:1.8rem;padding:0 .6rem;transition:border .25s,box-shadow .25s}.md-typeset .md-input:focus,.md-typeset .md-input:hover{border-bottom-color:var(--md-accent-fg-color);box-shadow:var(--md-shadow-z2)}.md-typeset .md-input--stretch{width:100%}.md-header{background-color:var(--md-primary-fg-color);box-shadow:0 0 .2rem #0000,0 .2rem .4rem #0000;color:var(--md-primary-bg-color);display:block;left:0;position:sticky;right:0;top:0;z-index:4}@media print{.md-header{display:none}}.md-header[hidden]{transform:translateY(-100%);transition:transform .25s cubic-bezier(.8,0,.6,1),box-shadow .25s}.md-header--shadow{box-shadow:0 0 .2rem #0000001a,0 .2rem .4rem #0003;transition:transform .25s cubic-bezier(.1,.7,.1,1),box-shadow .25s}.md-header__inner{align-items:center;display:flex;padding:0 .2rem}.md-header__button{color:currentcolor;cursor:pointer;margin:.2rem;outline-color:var(--md-accent-fg-color);padding:.4rem;position:relative;transition:opacity .25s;vertical-align:middle;z-index:1}.md-header__button:hover{opacity:.7}.md-header__button:not([hidden]){display:inline-block}.md-header__button:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}.md-header__button.md-logo{margin:.2rem;padding:.4rem}@media screen and (max-width:76.1875em){.md-header__button.md-logo{display:none}}.md-header__button.md-logo img,.md-header__button.md-logo svg{fill:currentcolor;display:block;height:1.2rem;width:auto}@media screen and (min-width:60em){.md-header__button[for=__search]{display:none}}.no-js .md-header__button[for=__search]{display:none}[dir=rtl] .md-header__button[for=__search] svg{transform:scaleX(-1)}@media screen and (min-width:76.25em){.md-header__button[for=__drawer]{display:none}}.md-header__topic{display:flex;max-width:100%;position:absolute;transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s;white-space:nowrap}.md-header__topic+.md-header__topic{opacity:0;pointer-events:none;transform:translateX(1.25rem);transition:transform .4s cubic-bezier(1,.7,.1,.1),opacity .15s;z-index:-1}[dir=rtl] .md-header__topic+.md-header__topic{transform:translateX(-1.25rem)}.md-header__topic:first-child{font-weight:700}[dir=ltr] .md-header__title{margin-left:1rem}[dir=rtl] .md-header__title{margin-right:1rem}[dir=ltr] .md-header__title{margin-right:.4rem}[dir=rtl] .md-header__title{margin-left:.4rem}.md-header__title{flex-grow:1;font-size:.9rem;height:2.4rem;line-height:2.4rem}.md-header__title--active .md-header__topic{opacity:0;pointer-events:none;transform:translateX(-1.25rem);transition:transform .4s cubic-bezier(1,.7,.1,.1),opacity .15s;z-index:-1}[dir=rtl] .md-header__title--active .md-header__topic{transform:translateX(1.25rem)}.md-header__title--active .md-header__topic+.md-header__topic{opacity:1;pointer-events:auto;transform:translateX(0);transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .15s;z-index:0}.md-header__title>.md-header__ellipsis{height:100%;position:relative;width:100%}.md-header__option{display:flex;flex-shrink:0;max-width:100%;transition:max-width 0ms .25s,opacity .25s .25s;white-space:nowrap}[data-md-toggle=search]:checked~.md-header .md-header__option{max-width:0;opacity:0;transition:max-width 0ms,opacity 0ms}.md-header__option>input{bottom:0}.md-header__source{display:none}@media screen and (min-width:60em){[dir=ltr] .md-header__source{margin-left:1rem}[dir=rtl] .md-header__source{margin-right:1rem}.md-header__source{display:block;max-width:11.7rem;width:11.7rem}}@media screen and (min-width:76.25em){[dir=ltr] .md-header__source{margin-left:1.4rem}[dir=rtl] .md-header__source{margin-right:1.4rem}}.md-meta{color:var(--md-default-fg-color--light);font-size:.7rem;line-height:1.3}.md-meta__list{display:inline-flex;flex-wrap:wrap;list-style:none;margin:0;padding:0}.md-meta__item:not(:last-child):after{content:"·";margin-left:.2rem;margin-right:.2rem}.md-meta__link{color:var(--md-typeset-a-color)}.md-meta__link:focus,.md-meta__link:hover{color:var(--md-accent-fg-color)}.md-draft{background-color:#ff1744;border-radius:.125em;color:#fff;display:inline-block;font-weight:700;padding-left:.5714285714em;padding-right:.5714285714em}:root{--md-nav-icon--prev:url('data:image/svg+xml;charset=utf-8,');--md-nav-icon--next:url('data:image/svg+xml;charset=utf-8,');--md-toc-icon:url('data:image/svg+xml;charset=utf-8,')}.md-nav{font-size:.7rem;line-height:1.3}.md-nav__title{color:var(--md-default-fg-color--light);display:block;font-weight:700;overflow:hidden;padding:0 .6rem;text-overflow:ellipsis}.md-nav__title .md-nav__button{display:none}.md-nav__title .md-nav__button img{height:100%;width:auto}.md-nav__title .md-nav__button.md-logo img,.md-nav__title .md-nav__button.md-logo svg{fill:currentcolor;display:block;height:2.4rem;max-width:100%;object-fit:contain;width:auto}.md-nav__list{list-style:none;margin:0;padding:0}.md-nav__item{padding:0 .6rem}[dir=ltr] .md-nav__item .md-nav__item{padding-right:0}[dir=rtl] .md-nav__item .md-nav__item{padding-left:0}.md-nav__link{align-items:flex-start;display:flex;margin-top:.625em;scroll-snap-align:start;transition:color 125ms}.md-nav__link--passed{color:var(--md-default-fg-color--light)}.md-nav__item .md-nav__link--active,.md-nav__item .md-nav__link--active code{color:var(--md-typeset-a-color)}.md-nav__link .md-ellipsis{position:relative}.md-nav__link .md-icon:last-child{margin-left:auto}.md-nav__link svg{fill:currentcolor;flex-shrink:0;height:1.3em}[dir=ltr] .md-nav__link svg+*{margin-left:.4rem}[dir=rtl] .md-nav__link svg+*{margin-right:.4rem}.md-nav__link:not(.md-nav__container):focus,.md-nav__link:not(.md-nav__container):hover{color:var(--md-accent-fg-color);cursor:pointer}.md-nav__link.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-nav--primary .md-nav__link[for=__toc]{display:none}.md-nav--primary .md-nav__link[for=__toc] .md-icon:after{background-color:currentcolor;display:block;height:100%;-webkit-mask-image:var(--md-toc-icon);mask-image:var(--md-toc-icon);width:100%}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:none}.md-nav__container>.md-nav__link{margin-top:0}.md-nav__container>.md-nav__link:first-child{flex-grow:1}.md-nav__icon{flex-shrink:0}.md-nav__source{display:none}@media screen and (max-width:76.1875em){.md-nav--primary,.md-nav--primary .md-nav{background-color:var(--md-default-bg-color);display:flex;flex-direction:column;height:100%;left:0;position:absolute;right:0;top:0;z-index:1}.md-nav--primary .md-nav__item,.md-nav--primary .md-nav__title{font-size:.8rem;line-height:1.5}.md-nav--primary .md-nav__title{background-color:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--light);cursor:pointer;height:5.6rem;line-height:2.4rem;padding:3rem .8rem .2rem;position:relative;white-space:nowrap}[dir=ltr] .md-nav--primary .md-nav__title .md-nav__icon{left:.4rem}[dir=rtl] .md-nav--primary .md-nav__title .md-nav__icon{right:.4rem}.md-nav--primary .md-nav__title .md-nav__icon{display:block;height:1.2rem;margin:.2rem;position:absolute;top:.4rem;width:1.2rem}.md-nav--primary .md-nav__title .md-nav__icon:after{background-color:currentcolor;content:"";display:block;height:100%;-webkit-mask-image:var(--md-nav-icon--prev);mask-image:var(--md-nav-icon--prev);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}.md-nav--primary .md-nav__title~.md-nav__list{background-color:var(--md-default-bg-color);box-shadow:0 .05rem 0 var(--md-default-fg-color--lightest) inset;overflow-y:auto;scroll-snap-type:y mandatory;touch-action:pan-y}.md-nav--primary .md-nav__title~.md-nav__list>:first-child{border-top:0}.md-nav--primary .md-nav__title[for=__drawer]{background-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color);font-weight:700}.md-nav--primary .md-nav__title .md-logo{display:block;left:.2rem;margin:.2rem;padding:.4rem;position:absolute;right:.2rem;top:.2rem}.md-nav--primary .md-nav__list{flex:1}.md-nav--primary .md-nav__item{border-top:.05rem solid var(--md-default-fg-color--lightest);padding:0}.md-nav--primary .md-nav__item--active>.md-nav__link{color:var(--md-typeset-a-color)}.md-nav--primary .md-nav__item--active>.md-nav__link:focus,.md-nav--primary .md-nav__item--active>.md-nav__link:hover{color:var(--md-accent-fg-color)}.md-nav--primary .md-nav__link{margin-top:0;padding:.6rem .8rem}.md-nav--primary .md-nav__link svg{margin-top:.1em}.md-nav--primary .md-nav__link>.md-nav__link{padding:0}[dir=ltr] .md-nav--primary .md-nav__link .md-nav__icon{margin-right:-.2rem}[dir=rtl] .md-nav--primary .md-nav__link .md-nav__icon{margin-left:-.2rem}.md-nav--primary .md-nav__link .md-nav__icon{font-size:1.2rem;height:1.2rem;width:1.2rem}.md-nav--primary .md-nav__link .md-nav__icon:after{background-color:currentcolor;content:"";display:block;height:100%;-webkit-mask-image:var(--md-nav-icon--next);mask-image:var(--md-nav-icon--next);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}[dir=rtl] .md-nav--primary .md-nav__icon:after{transform:scale(-1)}.md-nav--primary .md-nav--secondary .md-nav{background-color:initial;position:static}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-left:1.4rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav__link{padding-right:1.4rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-left:2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav__link{padding-right:2rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-left:2.6rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav__link{padding-right:2.6rem}[dir=ltr] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-left:3.2rem}[dir=rtl] .md-nav--primary .md-nav--secondary .md-nav .md-nav .md-nav .md-nav .md-nav__link{padding-right:3.2rem}.md-nav--secondary{background-color:initial}.md-nav__toggle~.md-nav{display:flex;opacity:0;transform:translateX(100%);transition:transform .25s cubic-bezier(.8,0,.6,1),opacity 125ms 50ms}[dir=rtl] .md-nav__toggle~.md-nav{transform:translateX(-100%)}.md-nav__toggle:checked~.md-nav{opacity:1;transform:translateX(0);transition:transform .25s cubic-bezier(.4,0,.2,1),opacity 125ms 125ms}.md-nav__toggle:checked~.md-nav>.md-nav__list{-webkit-backface-visibility:hidden;backface-visibility:hidden}}@media screen and (max-width:59.9375em){.md-nav--primary .md-nav__link[for=__toc]{display:flex}.md-nav--primary .md-nav__link[for=__toc] .md-icon:after{content:""}.md-nav--primary .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--primary .md-nav__link[for=__toc]~.md-nav{display:flex}.md-nav__source{background-color:var(--md-primary-fg-color--dark);color:var(--md-primary-bg-color);display:block;padding:0 .2rem}}@media screen and (min-width:60em) and (max-width:76.1875em){.md-nav--integrated .md-nav__link[for=__toc]{display:flex}.md-nav--integrated .md-nav__link[for=__toc] .md-icon:after{content:""}.md-nav--integrated .md-nav__link[for=__toc]+.md-nav__link{display:none}.md-nav--integrated .md-nav__link[for=__toc]~.md-nav{display:flex}}@media screen and (min-width:60em){.md-nav--secondary .md-nav__title{background:var(--md-default-bg-color);box-shadow:0 0 .4rem .4rem var(--md-default-bg-color);position:sticky;top:0;z-index:1}.md-nav--secondary .md-nav__title[for=__toc]{scroll-snap-align:start}.md-nav--secondary .md-nav__title .md-nav__icon{display:none}}@media screen and (min-width:76.25em){.md-nav{transition:max-height .25s cubic-bezier(.86,0,.07,1)}.md-nav--primary .md-nav__title{background:var(--md-default-bg-color);box-shadow:0 0 .4rem .4rem var(--md-default-bg-color);position:sticky;top:0;z-index:1}.md-nav--primary .md-nav__title[for=__drawer]{scroll-snap-align:start}.md-nav--primary .md-nav__title .md-nav__icon,.md-nav__toggle~.md-nav{display:none}.md-nav__toggle:checked~.md-nav,.md-nav__toggle:indeterminate~.md-nav{display:block}.md-nav__item--nested>.md-nav>.md-nav__title{display:none}.md-nav__item--section{display:block;margin:1.25em 0}.md-nav__item--section:last-child{margin-bottom:0}.md-nav__item--section>.md-nav__link{font-weight:700}.md-nav__item--section>.md-nav__link[for]{color:var(--md-default-fg-color--light)}.md-nav__item--section>.md-nav__link:not(.md-nav__container){pointer-events:none}.md-nav__item--section>.md-nav__link .md-nav__icon{display:none}.md-nav__item--section>.md-nav{display:block}.md-nav__item--section>.md-nav>.md-nav__list>.md-nav__item{padding:0}.md-nav__icon{border-radius:100%;height:.9rem;transition:background-color .25s;width:.9rem}.md-nav__icon:hover{background-color:var(--md-accent-fg-color--transparent)}.md-nav__icon:after{background-color:currentcolor;border-radius:100%;content:"";display:inline-block;height:100%;-webkit-mask-image:var(--md-nav-icon--next);mask-image:var(--md-nav-icon--next);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:transform .25s;vertical-align:-.1rem;width:100%}[dir=rtl] .md-nav__icon:after{transform:rotate(180deg)}.md-nav__item--nested .md-nav__toggle:checked~.md-nav__link .md-nav__icon:after,.md-nav__item--nested .md-nav__toggle:indeterminate~.md-nav__link .md-nav__icon:after{transform:rotate(90deg)}.md-nav--lifted>.md-nav__list>.md-nav__item,.md-nav--lifted>.md-nav__list>.md-nav__item--nested,.md-nav--lifted>.md-nav__title{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active{display:block;padding:0}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link{background:var(--md-default-bg-color);box-shadow:0 0 .4rem .4rem var(--md-default-bg-color);font-weight:700;margin-top:0;padding:0 .6rem;position:sticky;top:0;z-index:1}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link:not(.md-nav__container){pointer-events:none}.md-nav--lifted>.md-nav__list>.md-nav__item--active>.md-nav__link .md-nav__icon{display:none}.md-nav--lifted>.md-nav__list>.md-nav__item>[for]{color:var(--md-default-fg-color--light)}.md-nav--lifted .md-nav[data-md-level="1"]{display:block}[dir=ltr] .md-nav--lifted .md-nav[data-md-level="1"]>.md-nav__list>.md-nav__item{padding-right:.6rem}[dir=rtl] .md-nav--lifted .md-nav[data-md-level="1"]>.md-nav__list>.md-nav__item{padding-left:.6rem}.md-nav--integrated>.md-nav__list>.md-nav__item--active:not(.md-nav__item--nested){padding:0 .6rem}.md-nav--integrated>.md-nav__list>.md-nav__item--active:not(.md-nav__item--nested)>.md-nav__link{padding:0}[dir=ltr] .md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{border-left:.05rem solid var(--md-primary-fg-color)}[dir=rtl] .md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{border-right:.05rem solid var(--md-primary-fg-color)}.md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary{display:block;margin-bottom:1.25em}.md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary>.md-nav__title{display:none}}.md-pagination{font-size:.8rem;font-weight:700;gap:.4rem}.md-pagination,.md-pagination>*{align-items:center;display:flex;justify-content:center}.md-pagination>*{border-radius:.2rem;height:1.8rem;min-width:1.8rem;text-align:center}.md-pagination__current{background-color:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--light)}.md-pagination__link{transition:color 125ms,background-color 125ms}.md-pagination__link:focus,.md-pagination__link:hover{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-pagination__link:focus svg,.md-pagination__link:hover svg{color:var(--md-accent-fg-color)}.md-pagination__link.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-pagination__link svg{fill:currentcolor;color:var(--md-default-fg-color--lighter);display:block;max-height:100%;width:1.2rem}.md-post__back{border-bottom:.05rem solid var(--md-default-fg-color--lightest);margin-bottom:1.2rem;padding-bottom:1.2rem}@media screen and (max-width:76.1875em){.md-post__back{display:none}}[dir=rtl] .md-post__back svg{transform:scaleX(-1)}.md-post__authors{display:flex;flex-direction:column;gap:.6rem;margin:0 .6rem}.md-post .md-post__meta a{transition:color 125ms}.md-post .md-post__meta a:focus,.md-post .md-post__meta a:hover{color:var(--md-accent-fg-color)}.md-post--excerpt{margin-bottom:3.2rem}.md-post--excerpt .md-post__header{align-items:center;display:flex;gap:.6rem;min-height:1.6rem}.md-post--excerpt .md-post__authors{align-items:center;display:inline-flex;flex-direction:row;gap:.2rem;margin:0;min-height:2.4rem}[dir=ltr] .md-post--excerpt .md-post__meta .md-meta__list{margin-right:.4rem}[dir=rtl] .md-post--excerpt .md-post__meta .md-meta__list{margin-left:.4rem}.md-post--excerpt .md-post__content>:first-child{--md-scroll-margin:6rem;margin-top:0}.md-post>.md-nav--secondary,.md-post>.md-nav:first-child>.md-nav__list{margin:1em 0}.md-profile{align-items:center;display:flex;font-size:.7rem;gap:.6rem;line-height:1.4;width:100%}.md-profile__description{flex-grow:1}.md-content--post{display:flex}@media screen and (max-width:76.1875em){.md-content--post{flex-flow:column-reverse}}.md-content--post>.md-content__inner{min-width:0}@media screen and (min-width:76.25em){[dir=ltr] .md-content--post>.md-content__inner{margin-left:1.2rem}[dir=rtl] .md-content--post>.md-content__inner{margin-right:1.2rem}}@media screen and (max-width:76.1875em){.md-sidebar.md-sidebar--post{padding:0}}:root{--md-search-result-icon:url('data:image/svg+xml;charset=utf-8,')}.md-search{position:relative}@media screen and (min-width:60em){.md-search{padding:.2rem 0}}.no-js .md-search{display:none}.md-search__overlay{opacity:0;z-index:1}@media screen and (max-width:59.9375em){[dir=ltr] .md-search__overlay{left:-2.2rem}[dir=rtl] .md-search__overlay{right:-2.2rem}.md-search__overlay{background-color:var(--md-default-bg-color);border-radius:1rem;height:2rem;overflow:hidden;pointer-events:none;position:absolute;top:-1rem;transform-origin:center;transition:transform .3s .1s,opacity .2s .2s;width:2rem}[data-md-toggle=search]:checked~.md-header .md-search__overlay{opacity:1;transition:transform .4s,opacity .1s}}@media screen and (min-width:60em){[dir=ltr] .md-search__overlay{left:0}[dir=rtl] .md-search__overlay{right:0}.md-search__overlay{background-color:#0000008a;cursor:pointer;height:0;position:fixed;top:0;transition:width 0ms .25s,height 0ms .25s,opacity .25s;width:0}[data-md-toggle=search]:checked~.md-header .md-search__overlay{height:200vh;opacity:1;transition:width 0ms,height 0ms,opacity .25s;width:100%}}@media screen and (max-width:29.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(45)}}@media screen and (min-width:30em) and (max-width:44.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(60)}}@media screen and (min-width:45em) and (max-width:59.9375em){[data-md-toggle=search]:checked~.md-header .md-search__overlay{transform:scale(75)}}.md-search__inner{-webkit-backface-visibility:hidden;backface-visibility:hidden}@media screen and (max-width:59.9375em){[dir=ltr] .md-search__inner{left:0}[dir=rtl] .md-search__inner{right:0}.md-search__inner{height:0;opacity:0;overflow:hidden;position:fixed;top:0;transform:translateX(5%);transition:width 0ms .3s,height 0ms .3s,transform .15s cubic-bezier(.4,0,.2,1) .15s,opacity .15s .15s;width:0;z-index:2}[dir=rtl] .md-search__inner{transform:translateX(-5%)}[data-md-toggle=search]:checked~.md-header .md-search__inner{height:100%;opacity:1;transform:translateX(0);transition:width 0ms 0ms,height 0ms 0ms,transform .15s cubic-bezier(.1,.7,.1,1) .15s,opacity .15s .15s;width:100%}}@media screen and (min-width:60em){[dir=ltr] .md-search__inner{float:right}[dir=rtl] .md-search__inner{float:left}.md-search__inner{padding:.1rem 0;position:relative;transition:width .25s cubic-bezier(.1,.7,.1,1);width:11.7rem}}@media screen and (min-width:60em) and (max-width:76.1875em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:23.4rem}}@media screen and (min-width:76.25em){[data-md-toggle=search]:checked~.md-header .md-search__inner{width:34.4rem}}.md-search__form{background-color:var(--md-default-bg-color);box-shadow:0 0 .6rem #0000;height:2.4rem;position:relative;transition:color .25s,background-color .25s;z-index:2}@media screen and (min-width:60em){.md-search__form{background-color:#00000042;border-radius:.1rem;height:1.8rem}.md-search__form:hover{background-color:#ffffff1f}}[data-md-toggle=search]:checked~.md-header .md-search__form{background-color:var(--md-default-bg-color);border-radius:.1rem .1rem 0 0;box-shadow:0 0 .6rem #00000012;color:var(--md-default-fg-color)}[dir=ltr] .md-search__input{padding-left:3.6rem;padding-right:2.2rem}[dir=rtl] .md-search__input{padding-left:2.2rem;padding-right:3.6rem}.md-search__input{background:#0000;font-size:.9rem;height:100%;position:relative;text-overflow:ellipsis;width:100%;z-index:2}.md-search__input::placeholder{transition:color .25s}.md-search__input::placeholder,.md-search__input~.md-search__icon{color:var(--md-default-fg-color--light)}.md-search__input::-ms-clear{display:none}@media screen and (max-width:59.9375em){.md-search__input{font-size:.9rem;height:2.4rem;width:100%}}@media screen and (min-width:60em){[dir=ltr] .md-search__input{padding-left:2.2rem}[dir=rtl] .md-search__input{padding-right:2.2rem}.md-search__input{color:inherit;font-size:.8rem}.md-search__input::placeholder{color:var(--md-primary-bg-color--light)}.md-search__input+.md-search__icon{color:var(--md-primary-bg-color)}[data-md-toggle=search]:checked~.md-header .md-search__input{text-overflow:clip}[data-md-toggle=search]:checked~.md-header .md-search__input+.md-search__icon{color:var(--md-default-fg-color--light)}[data-md-toggle=search]:checked~.md-header .md-search__input::placeholder{color:#0000}}.md-search__icon{cursor:pointer;display:inline-block;height:1.2rem;transition:color .25s,opacity .25s;width:1.2rem}.md-search__icon:hover{opacity:.7}[dir=ltr] .md-search__icon[for=__search]{left:.5rem}[dir=rtl] .md-search__icon[for=__search]{right:.5rem}.md-search__icon[for=__search]{position:absolute;top:.3rem;z-index:2}[dir=rtl] .md-search__icon[for=__search] svg{transform:scaleX(-1)}@media screen and (max-width:59.9375em){[dir=ltr] .md-search__icon[for=__search]{left:.8rem}[dir=rtl] .md-search__icon[for=__search]{right:.8rem}.md-search__icon[for=__search]{top:.6rem}.md-search__icon[for=__search] svg:first-child{display:none}}@media screen and (min-width:60em){.md-search__icon[for=__search]{pointer-events:none}.md-search__icon[for=__search] svg:last-child{display:none}}[dir=ltr] .md-search__options{right:.5rem}[dir=rtl] .md-search__options{left:.5rem}.md-search__options{pointer-events:none;position:absolute;top:.3rem;z-index:2}@media screen and (max-width:59.9375em){[dir=ltr] .md-search__options{right:.8rem}[dir=rtl] .md-search__options{left:.8rem}.md-search__options{top:.6rem}}[dir=ltr] .md-search__options>.md-icon{margin-left:.2rem}[dir=rtl] .md-search__options>.md-icon{margin-right:.2rem}.md-search__options>.md-icon{color:var(--md-default-fg-color--light);opacity:0;transform:scale(.75);transition:transform .15s cubic-bezier(.1,.7,.1,1),opacity .15s}.md-search__options>.md-icon:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__options>.md-icon{opacity:1;pointer-events:auto;transform:scale(1)}[data-md-toggle=search]:checked~.md-header .md-search__input:valid~.md-search__options>.md-icon:hover{opacity:.7}[dir=ltr] .md-search__suggest{padding-left:3.6rem;padding-right:2.2rem}[dir=rtl] .md-search__suggest{padding-left:2.2rem;padding-right:3.6rem}.md-search__suggest{align-items:center;color:var(--md-default-fg-color--lighter);display:flex;font-size:.9rem;height:100%;opacity:0;position:absolute;top:0;transition:opacity 50ms;white-space:nowrap;width:100%}@media screen and (min-width:60em){[dir=ltr] .md-search__suggest{padding-left:2.2rem}[dir=rtl] .md-search__suggest{padding-right:2.2rem}.md-search__suggest{font-size:.8rem}}[data-md-toggle=search]:checked~.md-header .md-search__suggest{opacity:1;transition:opacity .3s .1s}[dir=ltr] .md-search__output{border-bottom-left-radius:.1rem}[dir=ltr] .md-search__output,[dir=rtl] .md-search__output{border-bottom-right-radius:.1rem}[dir=rtl] .md-search__output{border-bottom-left-radius:.1rem}.md-search__output{overflow:hidden;position:absolute;width:100%;z-index:1}@media screen and (max-width:59.9375em){.md-search__output{bottom:0;top:2.4rem}}@media screen and (min-width:60em){.md-search__output{opacity:0;top:1.9rem;transition:opacity .4s}[data-md-toggle=search]:checked~.md-header .md-search__output{box-shadow:var(--md-shadow-z3);opacity:1}}.md-search__scrollwrap{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:var(--md-default-bg-color);height:100%;overflow-y:auto;touch-action:pan-y}@media (-webkit-max-device-pixel-ratio:1),(max-resolution:1dppx){.md-search__scrollwrap{transform:translateZ(0)}}@media screen and (min-width:60em) and (max-width:76.1875em){.md-search__scrollwrap{width:23.4rem}}@media screen and (min-width:76.25em){.md-search__scrollwrap{width:34.4rem}}@media screen and (min-width:60em){.md-search__scrollwrap{max-height:0;scrollbar-color:var(--md-default-fg-color--lighter) #0000;scrollbar-width:thin}[data-md-toggle=search]:checked~.md-header .md-search__scrollwrap{max-height:75vh}.md-search__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) #0000}.md-search__scrollwrap::-webkit-scrollbar{height:.2rem;width:.2rem}.md-search__scrollwrap::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-search__scrollwrap::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}}.md-search-result{color:var(--md-default-fg-color);word-break:break-word}.md-search-result__meta{background-color:var(--md-default-fg-color--lightest);color:var(--md-default-fg-color--light);font-size:.64rem;line-height:1.8rem;padding:0 .8rem;scroll-snap-align:start}@media screen and (min-width:60em){[dir=ltr] .md-search-result__meta{padding-left:2.2rem}[dir=rtl] .md-search-result__meta{padding-right:2.2rem}}.md-search-result__list{list-style:none;margin:0;padding:0;-webkit-user-select:none;user-select:none}.md-search-result__item{box-shadow:0 -.05rem var(--md-default-fg-color--lightest)}.md-search-result__item:first-child{box-shadow:none}.md-search-result__link{display:block;outline:none;scroll-snap-align:start;transition:background-color .25s}.md-search-result__link:focus,.md-search-result__link:hover{background-color:var(--md-accent-fg-color--transparent)}.md-search-result__link:last-child p:last-child{margin-bottom:.6rem}.md-search-result__more>summary{cursor:pointer;display:block;outline:none;position:sticky;scroll-snap-align:start;top:0;z-index:1}.md-search-result__more>summary::marker{display:none}.md-search-result__more>summary::-webkit-details-marker{display:none}.md-search-result__more>summary>div{color:var(--md-typeset-a-color);font-size:.64rem;padding:.75em .8rem;transition:color .25s,background-color .25s}@media screen and (min-width:60em){[dir=ltr] .md-search-result__more>summary>div{padding-left:2.2rem}[dir=rtl] .md-search-result__more>summary>div{padding-right:2.2rem}}.md-search-result__more>summary:focus>div,.md-search-result__more>summary:hover>div{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-search-result__more[open]>summary{background-color:var(--md-default-bg-color)}.md-search-result__article{overflow:hidden;padding:0 .8rem;position:relative}@media screen and (min-width:60em){[dir=ltr] .md-search-result__article{padding-left:2.2rem}[dir=rtl] .md-search-result__article{padding-right:2.2rem}}[dir=ltr] .md-search-result__icon{left:0}[dir=rtl] .md-search-result__icon{right:0}.md-search-result__icon{color:var(--md-default-fg-color--light);height:1.2rem;margin:.5rem;position:absolute;width:1.2rem}@media screen and (max-width:59.9375em){.md-search-result__icon{display:none}}.md-search-result__icon:after{background-color:currentcolor;content:"";display:inline-block;height:100%;-webkit-mask-image:var(--md-search-result-icon);mask-image:var(--md-search-result-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:100%}[dir=rtl] .md-search-result__icon:after{transform:scaleX(-1)}.md-search-result .md-typeset{color:var(--md-default-fg-color--light);font-size:.64rem;line-height:1.6}.md-search-result .md-typeset h1{color:var(--md-default-fg-color);font-size:.8rem;font-weight:400;line-height:1.4;margin:.55rem 0}.md-search-result .md-typeset h1 mark{text-decoration:none}.md-search-result .md-typeset h2{color:var(--md-default-fg-color);font-size:.64rem;font-weight:700;line-height:1.6;margin:.5em 0}.md-search-result .md-typeset h2 mark{text-decoration:none}.md-search-result__terms{color:var(--md-default-fg-color);display:block;font-size:.64rem;font-style:italic;margin:.5em 0}.md-search-result mark{background-color:initial;color:var(--md-accent-fg-color);text-decoration:underline}.md-select{position:relative;z-index:1}.md-select__inner{background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);left:50%;margin-top:.2rem;max-height:0;opacity:0;position:absolute;top:calc(100% - .2rem);transform:translate3d(-50%,.3rem,0);transition:transform .25s 375ms,opacity .25s .25s,max-height 0ms .5s}.md-select:focus-within .md-select__inner,.md-select:hover .md-select__inner{max-height:10rem;opacity:1;transform:translate3d(-50%,0,0);transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,max-height 0ms}.md-select__inner:after{border-bottom:.2rem solid #0000;border-bottom-color:var(--md-default-bg-color);border-left:.2rem solid #0000;border-right:.2rem solid #0000;border-top:0;content:"";height:0;left:50%;margin-left:-.2rem;margin-top:-.2rem;position:absolute;top:0;width:0}.md-select__list{border-radius:.1rem;font-size:.8rem;list-style-type:none;margin:0;max-height:inherit;overflow:auto;padding:0}.md-select__item{line-height:1.8rem}[dir=ltr] .md-select__link{padding-left:.6rem;padding-right:1.2rem}[dir=rtl] .md-select__link{padding-left:1.2rem;padding-right:.6rem}.md-select__link{cursor:pointer;display:block;outline:none;scroll-snap-align:start;transition:background-color .25s,color .25s;width:100%}.md-select__link:focus,.md-select__link:hover{color:var(--md-accent-fg-color)}.md-select__link:focus{background-color:var(--md-default-fg-color--lightest)}.md-sidebar{align-self:flex-start;flex-shrink:0;padding:1.2rem 0;position:sticky;top:2.4rem;width:12.1rem}@media print{.md-sidebar{display:none}}@media screen and (max-width:76.1875em){[dir=ltr] .md-sidebar--primary{left:-12.1rem}[dir=rtl] .md-sidebar--primary{right:-12.1rem}.md-sidebar--primary{background-color:var(--md-default-bg-color);display:block;height:100%;position:fixed;top:0;transform:translateX(0);transition:transform .25s cubic-bezier(.4,0,.2,1),box-shadow .25s;width:12.1rem;z-index:5}[data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{box-shadow:var(--md-shadow-z3);transform:translateX(12.1rem)}[dir=rtl] [data-md-toggle=drawer]:checked~.md-container .md-sidebar--primary{transform:translateX(-12.1rem)}.md-sidebar--primary .md-sidebar__scrollwrap{bottom:0;left:0;margin:0;overflow:hidden;position:absolute;right:0;scroll-snap-type:none;top:0}}@media screen and (min-width:76.25em){.md-sidebar{height:0}.no-js .md-sidebar{height:auto}.md-header--lifted~.md-container .md-sidebar{top:4.8rem}}.md-sidebar--secondary{display:none;order:2}@media screen and (min-width:60em){.md-sidebar--secondary{height:0}.no-js .md-sidebar--secondary{height:auto}.md-sidebar--secondary:not([hidden]){display:block}.md-sidebar--secondary .md-sidebar__scrollwrap{touch-action:pan-y}}.md-sidebar__scrollwrap{scrollbar-gutter:stable;-webkit-backface-visibility:hidden;backface-visibility:hidden;margin:0 .2rem;overflow-y:auto;scrollbar-color:var(--md-default-fg-color--lighter) #0000;scrollbar-width:thin}.md-sidebar__scrollwrap::-webkit-scrollbar{height:.2rem;width:.2rem}.md-sidebar__scrollwrap:focus-within,.md-sidebar__scrollwrap:hover{scrollbar-color:var(--md-accent-fg-color) #0000}.md-sidebar__scrollwrap:focus-within::-webkit-scrollbar-thumb,.md-sidebar__scrollwrap:hover::-webkit-scrollbar-thumb{background-color:var(--md-default-fg-color--lighter)}.md-sidebar__scrollwrap:focus-within::-webkit-scrollbar-thumb:hover,.md-sidebar__scrollwrap:hover::-webkit-scrollbar-thumb:hover{background-color:var(--md-accent-fg-color)}@supports selector(::-webkit-scrollbar){.md-sidebar__scrollwrap{scrollbar-gutter:auto}[dir=ltr] .md-sidebar__inner{padding-right:calc(100% - 11.5rem)}[dir=rtl] .md-sidebar__inner{padding-left:calc(100% - 11.5rem)}}@media screen and (max-width:76.1875em){.md-overlay{background-color:#0000008a;height:0;opacity:0;position:fixed;top:0;transition:width 0ms .25s,height 0ms .25s,opacity .25s;width:0;z-index:5}[data-md-toggle=drawer]:checked~.md-overlay{height:100%;opacity:1;transition:width 0ms,height 0ms,opacity .25s;width:100%}}@keyframes facts{0%{height:0}to{height:.65rem}}@keyframes fact{0%{opacity:0;transform:translateY(100%)}50%{opacity:0}to{opacity:1;transform:translateY(0)}}:root{--md-source-forks-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-repositories-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-stars-icon:url('data:image/svg+xml;charset=utf-8,');--md-source-version-icon:url('data:image/svg+xml;charset=utf-8,')}.md-source{-webkit-backface-visibility:hidden;backface-visibility:hidden;display:block;font-size:.65rem;line-height:1.2;outline-color:var(--md-accent-fg-color);transition:opacity .25s;white-space:nowrap}.md-source:hover{opacity:.7}.md-source__icon{display:inline-block;height:2.4rem;vertical-align:middle;width:2rem}[dir=ltr] .md-source__icon svg{margin-left:.6rem}[dir=rtl] .md-source__icon svg{margin-right:.6rem}.md-source__icon svg{margin-top:.6rem}[dir=ltr] .md-source__icon+.md-source__repository{padding-left:2rem}[dir=rtl] .md-source__icon+.md-source__repository{padding-right:2rem}[dir=ltr] .md-source__icon+.md-source__repository{margin-left:-2rem}[dir=rtl] .md-source__icon+.md-source__repository{margin-right:-2rem}[dir=ltr] .md-source__repository{margin-left:.6rem}[dir=rtl] .md-source__repository{margin-right:.6rem}.md-source__repository{display:inline-block;max-width:calc(100% - 1.2rem);overflow:hidden;text-overflow:ellipsis;vertical-align:middle}.md-source__facts{display:flex;font-size:.55rem;gap:.4rem;list-style-type:none;margin:.1rem 0 0;opacity:.75;overflow:hidden;padding:0;width:100%}.md-source__repository--active .md-source__facts{animation:facts .25s ease-in}.md-source__fact{overflow:hidden;text-overflow:ellipsis}.md-source__repository--active .md-source__fact{animation:fact .4s ease-out}[dir=ltr] .md-source__fact:before{margin-right:.1rem}[dir=rtl] .md-source__fact:before{margin-left:.1rem}.md-source__fact:before{background-color:currentcolor;content:"";display:inline-block;height:.6rem;-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;vertical-align:text-top;width:.6rem}.md-source__fact:nth-child(1n+2){flex-shrink:0}.md-source__fact--version:before{-webkit-mask-image:var(--md-source-version-icon);mask-image:var(--md-source-version-icon)}.md-source__fact--stars:before{-webkit-mask-image:var(--md-source-stars-icon);mask-image:var(--md-source-stars-icon)}.md-source__fact--forks:before{-webkit-mask-image:var(--md-source-forks-icon);mask-image:var(--md-source-forks-icon)}.md-source__fact--repositories:before{-webkit-mask-image:var(--md-source-repositories-icon);mask-image:var(--md-source-repositories-icon)}:root{--md-status:url('data:image/svg+xml;charset=utf-8,');--md-status--new:url('data:image/svg+xml;charset=utf-8,');--md-status--deprecated:url('data:image/svg+xml;charset=utf-8,');--md-status--encrypted:url('data:image/svg+xml;charset=utf-8,')}.md-status{margin-left:.2rem}.md-status:after{background-color:var(--md-default-fg-color--light);content:"";display:inline-block;height:1.125em;-webkit-mask-image:var(--md-status);mask-image:var(--md-status);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;vertical-align:text-bottom;width:1.125em}.md-status:hover:after{background-color:currentcolor}.md-status--new:after{-webkit-mask-image:var(--md-status--new);mask-image:var(--md-status--new)}.md-status--deprecated:after{-webkit-mask-image:var(--md-status--deprecated);mask-image:var(--md-status--deprecated)}.md-status--encrypted:after{-webkit-mask-image:var(--md-status--encrypted);mask-image:var(--md-status--encrypted)}.md-tabs{background-color:var(--md-primary-fg-color);color:var(--md-primary-bg-color);display:block;line-height:1.3;overflow:auto;width:100%;z-index:3}@media print{.md-tabs{display:none}}@media screen and (max-width:76.1875em){.md-tabs{display:none}}.md-tabs[hidden]{pointer-events:none}[dir=ltr] .md-tabs__list{margin-left:.2rem}[dir=rtl] .md-tabs__list{margin-right:.2rem}.md-tabs__list{contain:content;display:flex;list-style:none;margin:0;overflow:auto;padding:0;scrollbar-width:none;white-space:nowrap}.md-tabs__list::-webkit-scrollbar{display:none}.md-tabs__item{height:2.4rem;padding-left:.6rem;padding-right:.6rem}.md-tabs__item--active .md-tabs__link{color:inherit;opacity:1}.md-tabs__link{-webkit-backface-visibility:hidden;backface-visibility:hidden;display:flex;font-size:.7rem;margin-top:.8rem;opacity:.7;outline-color:var(--md-accent-fg-color);outline-offset:.2rem;transition:transform .4s cubic-bezier(.1,.7,.1,1),opacity .25s}.md-tabs__link:focus,.md-tabs__link:hover{color:inherit;opacity:1}[dir=ltr] .md-tabs__link svg{margin-right:.4rem}[dir=rtl] .md-tabs__link svg{margin-left:.4rem}.md-tabs__link svg{fill:currentcolor;height:1.3em}.md-tabs__item:nth-child(2) .md-tabs__link{transition-delay:20ms}.md-tabs__item:nth-child(3) .md-tabs__link{transition-delay:40ms}.md-tabs__item:nth-child(4) .md-tabs__link{transition-delay:60ms}.md-tabs__item:nth-child(5) .md-tabs__link{transition-delay:80ms}.md-tabs__item:nth-child(6) .md-tabs__link{transition-delay:.1s}.md-tabs__item:nth-child(7) .md-tabs__link{transition-delay:.12s}.md-tabs__item:nth-child(8) .md-tabs__link{transition-delay:.14s}.md-tabs__item:nth-child(9) .md-tabs__link{transition-delay:.16s}.md-tabs__item:nth-child(10) .md-tabs__link{transition-delay:.18s}.md-tabs__item:nth-child(11) .md-tabs__link{transition-delay:.2s}.md-tabs__item:nth-child(12) .md-tabs__link{transition-delay:.22s}.md-tabs__item:nth-child(13) .md-tabs__link{transition-delay:.24s}.md-tabs__item:nth-child(14) .md-tabs__link{transition-delay:.26s}.md-tabs__item:nth-child(15) .md-tabs__link{transition-delay:.28s}.md-tabs__item:nth-child(16) .md-tabs__link{transition-delay:.3s}.md-tabs[hidden] .md-tabs__link{opacity:0;transform:translateY(50%);transition:transform 0ms .1s,opacity .1s}:root{--md-tag-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .md-tags{margin-bottom:.75em;margin-top:-.125em}[dir=ltr] .md-typeset .md-tag{margin-right:.5em}[dir=rtl] .md-typeset .md-tag{margin-left:.5em}.md-typeset .md-tag{background:var(--md-default-fg-color--lightest);border-radius:2.4rem;display:inline-block;font-size:.64rem;font-weight:700;letter-spacing:normal;line-height:1.6;margin-bottom:.5em;padding:.3125em .9375em}.md-typeset .md-tag[href]{-webkit-tap-highlight-color:transparent;color:inherit;outline:none;transition:color 125ms,background-color 125ms}.md-typeset .md-tag[href]:focus,.md-typeset .md-tag[href]:hover{background-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}[id]>.md-typeset .md-tag{vertical-align:text-top}.md-typeset .md-tag-icon:before{background-color:var(--md-default-fg-color--lighter);content:"";display:inline-block;height:1.2em;margin-right:.4em;-webkit-mask-image:var(--md-tag-icon);mask-image:var(--md-tag-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:background-color 125ms;vertical-align:text-bottom;width:1.2em}.md-typeset .md-tag-icon[href]:focus:before,.md-typeset .md-tag-icon[href]:hover:before{background-color:var(--md-accent-bg-color)}@keyframes pulse{0%{transform:scale(.95)}75%{transform:scale(1)}to{transform:scale(.95)}}:root{--md-annotation-bg-icon:url('data:image/svg+xml;charset=utf-8,');--md-annotation-icon:url('data:image/svg+xml;charset=utf-8,');--md-tooltip-width:20rem}.md-tooltip{-webkit-backface-visibility:hidden;backface-visibility:hidden;background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);font-family:var(--md-text-font-family);left:clamp(var(--md-tooltip-0,0rem) + .8rem,var(--md-tooltip-x),100vw + var(--md-tooltip-0,0rem) + .8rem - var(--md-tooltip-width) - 2 * .8rem);max-width:calc(100vw - 1.6rem);opacity:0;position:absolute;top:var(--md-tooltip-y);transform:translateY(-.4rem);transition:transform 0ms .25s,opacity .25s,z-index .25s;width:var(--md-tooltip-width);z-index:0}.md-tooltip--active{opacity:1;transform:translateY(0);transition:transform .25s cubic-bezier(.1,.7,.1,1),opacity .25s,z-index 0ms;z-index:2}.focus-visible>.md-tooltip,.md-tooltip:target{outline:var(--md-accent-fg-color) auto}.md-tooltip__inner{font-size:.64rem;padding:.8rem}.md-tooltip__inner.md-typeset>:first-child{margin-top:0}.md-tooltip__inner.md-typeset>:last-child{margin-bottom:0}.md-annotation{font-weight:400;outline:none;vertical-align:text-bottom;white-space:normal}[dir=rtl] .md-annotation{direction:rtl}code .md-annotation{font-family:var(--md-code-font-family);font-size:inherit}.md-annotation:not([hidden]){display:inline-block;line-height:1.25}.md-annotation__index{border-radius:.01px;cursor:pointer;display:inline-block;margin-left:.4ch;margin-right:.4ch;outline:none;overflow:hidden;position:relative;-webkit-user-select:none;user-select:none;vertical-align:text-top;z-index:0}.md-annotation .md-annotation__index{transition:z-index .25s}@media screen{.md-annotation__index{width:2.2ch}[data-md-visible]>.md-annotation__index{animation:pulse 2s infinite}.md-annotation__index:before{background:var(--md-default-bg-color);-webkit-mask-image:var(--md-annotation-bg-icon);mask-image:var(--md-annotation-bg-icon)}.md-annotation__index:after,.md-annotation__index:before{content:"";height:2.2ch;-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:-.1ch;width:2.2ch;z-index:-1}.md-annotation__index:after{background-color:var(--md-default-fg-color--lighter);-webkit-mask-image:var(--md-annotation-icon);mask-image:var(--md-annotation-icon);transform:scale(1.0001);transition:background-color .25s,transform .25s}.md-tooltip--active+.md-annotation__index:after{transform:rotate(45deg)}.md-tooltip--active+.md-annotation__index:after,:hover>.md-annotation__index:after{background-color:var(--md-accent-fg-color)}}.md-tooltip--active+.md-annotation__index{animation-play-state:paused;transition-duration:0ms;z-index:2}.md-annotation__index [data-md-annotation-id]{display:inline-block}@media print{.md-annotation__index [data-md-annotation-id]{background:var(--md-default-fg-color--lighter);border-radius:2ch;color:var(--md-default-bg-color);font-weight:700;padding:0 .6ch;white-space:nowrap}.md-annotation__index [data-md-annotation-id]:after{content:attr(data-md-annotation-id)}}.md-typeset .md-annotation-list{counter-reset:xxx;list-style:none}.md-typeset .md-annotation-list li{position:relative}[dir=ltr] .md-typeset .md-annotation-list li:before{left:-2.125em}[dir=rtl] .md-typeset .md-annotation-list li:before{right:-2.125em}.md-typeset .md-annotation-list li:before{background:var(--md-default-fg-color--lighter);border-radius:2ch;color:var(--md-default-bg-color);content:counter(xxx);counter-increment:xxx;font-size:.8875em;font-weight:700;height:2ch;line-height:1.25;min-width:2ch;padding:0 .6ch;position:absolute;text-align:center;top:.25em}[dir=ltr] .md-top{margin-left:50%}[dir=rtl] .md-top{margin-right:50%}.md-top{background-color:var(--md-default-bg-color);border-radius:1.6rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color--light);cursor:pointer;display:block;font-size:.7rem;outline:none;padding:.4rem .8rem;position:fixed;top:3.2rem;transform:translate(-50%);transition:color 125ms,background-color 125ms,transform 125ms cubic-bezier(.4,0,.2,1),opacity 125ms;z-index:2}@media print{.md-top{display:none}}[dir=rtl] .md-top{transform:translate(50%)}.md-top[hidden]{opacity:0;pointer-events:none;transform:translate(-50%,.2rem);transition-duration:0ms}[dir=rtl] .md-top[hidden]{transform:translate(50%,.2rem)}.md-top:focus,.md-top:hover{background-color:var(--md-accent-fg-color);color:var(--md-accent-bg-color)}.md-top svg{display:inline-block;vertical-align:-.5em}@keyframes hoverfix{0%{pointer-events:none}}:root{--md-version-icon:url('data:image/svg+xml;charset=utf-8,')}.md-version{flex-shrink:0;font-size:.8rem;height:2.4rem}[dir=ltr] .md-version__current{margin-left:1.4rem;margin-right:.4rem}[dir=rtl] .md-version__current{margin-left:.4rem;margin-right:1.4rem}.md-version__current{color:inherit;cursor:pointer;outline:none;position:relative;top:.05rem}[dir=ltr] .md-version__current:after{margin-left:.4rem}[dir=rtl] .md-version__current:after{margin-right:.4rem}.md-version__current:after{background-color:currentcolor;content:"";display:inline-block;height:.6rem;-webkit-mask-image:var(--md-version-icon);mask-image:var(--md-version-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:.4rem}.md-version__list{background-color:var(--md-default-bg-color);border-radius:.1rem;box-shadow:var(--md-shadow-z2);color:var(--md-default-fg-color);list-style-type:none;margin:.2rem .8rem;max-height:0;opacity:0;overflow:auto;padding:0;position:absolute;scroll-snap-type:y mandatory;top:.15rem;transition:max-height 0ms .5s,opacity .25s .25s;z-index:3}.md-version:focus-within .md-version__list,.md-version:hover .md-version__list{max-height:10rem;opacity:1;transition:max-height 0ms,opacity .25s}@media (hover:none),(pointer:coarse){.md-version:hover .md-version__list{animation:hoverfix .25s forwards}.md-version:focus-within .md-version__list{animation:none}}.md-version__item{line-height:1.8rem}[dir=ltr] .md-version__link{padding-left:.6rem;padding-right:1.2rem}[dir=rtl] .md-version__link{padding-left:1.2rem;padding-right:.6rem}.md-version__link{cursor:pointer;display:block;outline:none;scroll-snap-align:start;transition:color .25s,background-color .25s;white-space:nowrap;width:100%}.md-version__link:focus,.md-version__link:hover{color:var(--md-accent-fg-color)}.md-version__link:focus{background-color:var(--md-default-fg-color--lightest)}:root{--md-admonition-icon--note:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--abstract:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--info:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--tip:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--success:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--question:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--warning:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--failure:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--danger:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--bug:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--example:url('data:image/svg+xml;charset=utf-8,');--md-admonition-icon--quote:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .admonition,.md-typeset details{background-color:var(--md-admonition-bg-color);border:.05rem solid #448aff;border-radius:.2rem;box-shadow:var(--md-shadow-z1);color:var(--md-admonition-fg-color);display:flow-root;font-size:.64rem;margin:1.5625em 0;padding:0 .6rem;page-break-inside:avoid;transition:box-shadow 125ms}@media print{.md-typeset .admonition,.md-typeset details{box-shadow:none}}.md-typeset .admonition:focus-within,.md-typeset details:focus-within{box-shadow:0 0 0 .2rem #448aff1a}.md-typeset .admonition>*,.md-typeset details>*{box-sizing:border-box}.md-typeset .admonition .admonition,.md-typeset .admonition details,.md-typeset details .admonition,.md-typeset details details{margin-bottom:1em;margin-top:1em}.md-typeset .admonition .md-typeset__scrollwrap,.md-typeset details .md-typeset__scrollwrap{margin:1em -.6rem}.md-typeset .admonition .md-typeset__table,.md-typeset details .md-typeset__table{padding:0 .6rem}.md-typeset .admonition>.tabbed-set:only-child,.md-typeset details>.tabbed-set:only-child{margin-top:0}html .md-typeset .admonition>:last-child,html .md-typeset details>:last-child{margin-bottom:.6rem}[dir=ltr] .md-typeset .admonition-title,[dir=ltr] .md-typeset summary{padding-left:2rem;padding-right:.6rem}[dir=rtl] .md-typeset .admonition-title,[dir=rtl] .md-typeset summary{padding-left:.6rem;padding-right:2rem}[dir=ltr] .md-typeset .admonition-title,[dir=ltr] .md-typeset summary{border-left-width:.2rem}[dir=rtl] .md-typeset .admonition-title,[dir=rtl] .md-typeset summary{border-right-width:.2rem}[dir=ltr] .md-typeset .admonition-title,[dir=ltr] .md-typeset summary{border-top-left-radius:.1rem}[dir=ltr] .md-typeset .admonition-title,[dir=ltr] .md-typeset summary,[dir=rtl] .md-typeset .admonition-title,[dir=rtl] .md-typeset summary{border-top-right-radius:.1rem}[dir=rtl] .md-typeset .admonition-title,[dir=rtl] .md-typeset summary{border-top-left-radius:.1rem}.md-typeset .admonition-title,.md-typeset summary{background-color:#448aff1a;border:none;font-weight:700;margin:0 -.6rem;padding-bottom:.4rem;padding-top:.4rem;position:relative}html .md-typeset .admonition-title:last-child,html .md-typeset summary:last-child{margin-bottom:0}[dir=ltr] .md-typeset .admonition-title:before,[dir=ltr] .md-typeset summary:before{left:.6rem}[dir=rtl] .md-typeset .admonition-title:before,[dir=rtl] .md-typeset summary:before{right:.6rem}.md-typeset .admonition-title:before,.md-typeset summary:before{background-color:#448aff;content:"";height:1rem;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.625em;width:1rem}.md-typeset .admonition-title code,.md-typeset summary code{box-shadow:0 0 0 .05rem var(--md-default-fg-color--lightest)}.md-typeset .admonition.note,.md-typeset details.note{border-color:#448aff}.md-typeset .admonition.note:focus-within,.md-typeset details.note:focus-within{box-shadow:0 0 0 .2rem #448aff1a}.md-typeset .note>.admonition-title,.md-typeset .note>summary{background-color:#448aff1a}.md-typeset .note>.admonition-title:before,.md-typeset .note>summary:before{background-color:#448aff;-webkit-mask-image:var(--md-admonition-icon--note);mask-image:var(--md-admonition-icon--note)}.md-typeset .note>.admonition-title:after,.md-typeset .note>summary:after{color:#448aff}.md-typeset .admonition.abstract,.md-typeset details.abstract{border-color:#00b0ff}.md-typeset .admonition.abstract:focus-within,.md-typeset details.abstract:focus-within{box-shadow:0 0 0 .2rem #00b0ff1a}.md-typeset .abstract>.admonition-title,.md-typeset .abstract>summary{background-color:#00b0ff1a}.md-typeset .abstract>.admonition-title:before,.md-typeset .abstract>summary:before{background-color:#00b0ff;-webkit-mask-image:var(--md-admonition-icon--abstract);mask-image:var(--md-admonition-icon--abstract)}.md-typeset .abstract>.admonition-title:after,.md-typeset .abstract>summary:after{color:#00b0ff}.md-typeset .admonition.info,.md-typeset details.info{border-color:#00b8d4}.md-typeset .admonition.info:focus-within,.md-typeset details.info:focus-within{box-shadow:0 0 0 .2rem #00b8d41a}.md-typeset .info>.admonition-title,.md-typeset .info>summary{background-color:#00b8d41a}.md-typeset .info>.admonition-title:before,.md-typeset .info>summary:before{background-color:#00b8d4;-webkit-mask-image:var(--md-admonition-icon--info);mask-image:var(--md-admonition-icon--info)}.md-typeset .info>.admonition-title:after,.md-typeset .info>summary:after{color:#00b8d4}.md-typeset .admonition.tip,.md-typeset details.tip{border-color:#00bfa5}.md-typeset .admonition.tip:focus-within,.md-typeset details.tip:focus-within{box-shadow:0 0 0 .2rem #00bfa51a}.md-typeset .tip>.admonition-title,.md-typeset .tip>summary{background-color:#00bfa51a}.md-typeset .tip>.admonition-title:before,.md-typeset .tip>summary:before{background-color:#00bfa5;-webkit-mask-image:var(--md-admonition-icon--tip);mask-image:var(--md-admonition-icon--tip)}.md-typeset .tip>.admonition-title:after,.md-typeset .tip>summary:after{color:#00bfa5}.md-typeset .admonition.success,.md-typeset details.success{border-color:#00c853}.md-typeset .admonition.success:focus-within,.md-typeset details.success:focus-within{box-shadow:0 0 0 .2rem #00c8531a}.md-typeset .success>.admonition-title,.md-typeset .success>summary{background-color:#00c8531a}.md-typeset .success>.admonition-title:before,.md-typeset .success>summary:before{background-color:#00c853;-webkit-mask-image:var(--md-admonition-icon--success);mask-image:var(--md-admonition-icon--success)}.md-typeset .success>.admonition-title:after,.md-typeset .success>summary:after{color:#00c853}.md-typeset .admonition.question,.md-typeset details.question{border-color:#64dd17}.md-typeset .admonition.question:focus-within,.md-typeset details.question:focus-within{box-shadow:0 0 0 .2rem #64dd171a}.md-typeset .question>.admonition-title,.md-typeset .question>summary{background-color:#64dd171a}.md-typeset .question>.admonition-title:before,.md-typeset .question>summary:before{background-color:#64dd17;-webkit-mask-image:var(--md-admonition-icon--question);mask-image:var(--md-admonition-icon--question)}.md-typeset .question>.admonition-title:after,.md-typeset .question>summary:after{color:#64dd17}.md-typeset .admonition.warning,.md-typeset details.warning{border-color:#ff9100}.md-typeset .admonition.warning:focus-within,.md-typeset details.warning:focus-within{box-shadow:0 0 0 .2rem #ff91001a}.md-typeset .warning>.admonition-title,.md-typeset .warning>summary{background-color:#ff91001a}.md-typeset .warning>.admonition-title:before,.md-typeset .warning>summary:before{background-color:#ff9100;-webkit-mask-image:var(--md-admonition-icon--warning);mask-image:var(--md-admonition-icon--warning)}.md-typeset .warning>.admonition-title:after,.md-typeset .warning>summary:after{color:#ff9100}.md-typeset .admonition.failure,.md-typeset details.failure{border-color:#ff5252}.md-typeset .admonition.failure:focus-within,.md-typeset details.failure:focus-within{box-shadow:0 0 0 .2rem #ff52521a}.md-typeset .failure>.admonition-title,.md-typeset .failure>summary{background-color:#ff52521a}.md-typeset .failure>.admonition-title:before,.md-typeset .failure>summary:before{background-color:#ff5252;-webkit-mask-image:var(--md-admonition-icon--failure);mask-image:var(--md-admonition-icon--failure)}.md-typeset .failure>.admonition-title:after,.md-typeset .failure>summary:after{color:#ff5252}.md-typeset .admonition.danger,.md-typeset details.danger{border-color:#ff1744}.md-typeset .admonition.danger:focus-within,.md-typeset details.danger:focus-within{box-shadow:0 0 0 .2rem #ff17441a}.md-typeset .danger>.admonition-title,.md-typeset .danger>summary{background-color:#ff17441a}.md-typeset .danger>.admonition-title:before,.md-typeset .danger>summary:before{background-color:#ff1744;-webkit-mask-image:var(--md-admonition-icon--danger);mask-image:var(--md-admonition-icon--danger)}.md-typeset .danger>.admonition-title:after,.md-typeset .danger>summary:after{color:#ff1744}.md-typeset .admonition.bug,.md-typeset details.bug{border-color:#f50057}.md-typeset .admonition.bug:focus-within,.md-typeset details.bug:focus-within{box-shadow:0 0 0 .2rem #f500571a}.md-typeset .bug>.admonition-title,.md-typeset .bug>summary{background-color:#f500571a}.md-typeset .bug>.admonition-title:before,.md-typeset .bug>summary:before{background-color:#f50057;-webkit-mask-image:var(--md-admonition-icon--bug);mask-image:var(--md-admonition-icon--bug)}.md-typeset .bug>.admonition-title:after,.md-typeset .bug>summary:after{color:#f50057}.md-typeset .admonition.example,.md-typeset details.example{border-color:#7c4dff}.md-typeset .admonition.example:focus-within,.md-typeset details.example:focus-within{box-shadow:0 0 0 .2rem #7c4dff1a}.md-typeset .example>.admonition-title,.md-typeset .example>summary{background-color:#7c4dff1a}.md-typeset .example>.admonition-title:before,.md-typeset .example>summary:before{background-color:#7c4dff;-webkit-mask-image:var(--md-admonition-icon--example);mask-image:var(--md-admonition-icon--example)}.md-typeset .example>.admonition-title:after,.md-typeset .example>summary:after{color:#7c4dff}.md-typeset .admonition.quote,.md-typeset details.quote{border-color:#9e9e9e}.md-typeset .admonition.quote:focus-within,.md-typeset details.quote:focus-within{box-shadow:0 0 0 .2rem #9e9e9e1a}.md-typeset .quote>.admonition-title,.md-typeset .quote>summary{background-color:#9e9e9e1a}.md-typeset .quote>.admonition-title:before,.md-typeset .quote>summary:before{background-color:#9e9e9e;-webkit-mask-image:var(--md-admonition-icon--quote);mask-image:var(--md-admonition-icon--quote)}.md-typeset .quote>.admonition-title:after,.md-typeset .quote>summary:after{color:#9e9e9e}:root{--md-footnotes-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .footnote{color:var(--md-default-fg-color--light);font-size:.64rem}[dir=ltr] .md-typeset .footnote>ol{margin-left:0}[dir=rtl] .md-typeset .footnote>ol{margin-right:0}.md-typeset .footnote>ol>li{transition:color 125ms}.md-typeset .footnote>ol>li:target{color:var(--md-default-fg-color)}.md-typeset .footnote>ol>li:focus-within .footnote-backref{opacity:1;transform:translateX(0);transition:none}.md-typeset .footnote>ol>li:hover .footnote-backref,.md-typeset .footnote>ol>li:target .footnote-backref{opacity:1;transform:translateX(0)}.md-typeset .footnote>ol>li>:first-child{margin-top:0}.md-typeset .footnote-ref{font-size:.75em;font-weight:700}html .md-typeset .footnote-ref{outline-offset:.1rem}.md-typeset [id^="fnref:"]:target>.footnote-ref{outline:auto}.md-typeset .footnote-backref{color:var(--md-typeset-a-color);display:inline-block;font-size:0;opacity:0;transform:translateX(.25rem);transition:color .25s,transform .25s .25s,opacity 125ms .25s;vertical-align:text-bottom}@media print{.md-typeset .footnote-backref{color:var(--md-typeset-a-color);opacity:1;transform:translateX(0)}}[dir=rtl] .md-typeset .footnote-backref{transform:translateX(-.25rem)}.md-typeset .footnote-backref:hover{color:var(--md-accent-fg-color)}.md-typeset .footnote-backref:before{background-color:currentcolor;content:"";display:inline-block;height:.8rem;-webkit-mask-image:var(--md-footnotes-icon);mask-image:var(--md-footnotes-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;width:.8rem}[dir=rtl] .md-typeset .footnote-backref:before svg{transform:scaleX(-1)}[dir=ltr] .md-typeset .headerlink{margin-left:.5rem}[dir=rtl] .md-typeset .headerlink{margin-right:.5rem}.md-typeset .headerlink{color:var(--md-default-fg-color--lighter);display:inline-block;opacity:0;transition:color .25s,opacity 125ms}@media print{.md-typeset .headerlink{display:none}}.md-typeset .headerlink:focus,.md-typeset :hover>.headerlink,.md-typeset :target>.headerlink{opacity:1;transition:color .25s,opacity 125ms}.md-typeset .headerlink:focus,.md-typeset .headerlink:hover,.md-typeset :target>.headerlink{color:var(--md-accent-fg-color)}.md-typeset :target{--md-scroll-margin:3.6rem;--md-scroll-offset:0rem;scroll-margin-top:calc(var(--md-scroll-margin) - var(--md-scroll-offset))}@media screen and (min-width:76.25em){.md-header--lifted~.md-container .md-typeset :target{--md-scroll-margin:6rem}}.md-typeset h1:target,.md-typeset h2:target,.md-typeset h3:target{--md-scroll-offset:0.2rem}.md-typeset h4:target{--md-scroll-offset:0.15rem}.md-typeset div.arithmatex{overflow:auto}@media screen and (max-width:44.9375em){.md-typeset div.arithmatex{margin:0 -.8rem}}.md-typeset div.arithmatex>*{margin-left:auto!important;margin-right:auto!important;padding:0 .8rem;touch-action:auto;width:-webkit-min-content;width:min-content}.md-typeset div.arithmatex>* mjx-container{margin:0!important}.md-typeset del.critic{background-color:var(--md-typeset-del-color)}.md-typeset del.critic,.md-typeset ins.critic{-webkit-box-decoration-break:clone;box-decoration-break:clone}.md-typeset ins.critic{background-color:var(--md-typeset-ins-color)}.md-typeset .critic.comment{-webkit-box-decoration-break:clone;box-decoration-break:clone;color:var(--md-code-hl-comment-color)}.md-typeset .critic.comment:before{content:"/* "}.md-typeset .critic.comment:after{content:" */"}.md-typeset .critic.block{box-shadow:none;display:block;margin:1em 0;overflow:auto;padding-left:.8rem;padding-right:.8rem}.md-typeset .critic.block>:first-child{margin-top:.5em}.md-typeset .critic.block>:last-child{margin-bottom:.5em}:root{--md-details-icon:url('data:image/svg+xml;charset=utf-8,')}.md-typeset details{display:flow-root;overflow:visible;padding-top:0}.md-typeset details[open]>summary:after{transform:rotate(90deg)}.md-typeset details:not([open]){box-shadow:none;padding-bottom:0}.md-typeset details:not([open])>summary{border-radius:.1rem}[dir=ltr] .md-typeset summary{padding-right:1.8rem}[dir=rtl] .md-typeset summary{padding-left:1.8rem}[dir=ltr] .md-typeset summary{border-top-left-radius:.1rem}[dir=ltr] .md-typeset summary,[dir=rtl] .md-typeset summary{border-top-right-radius:.1rem}[dir=rtl] .md-typeset summary{border-top-left-radius:.1rem}.md-typeset summary{cursor:pointer;display:block;min-height:1rem}.md-typeset summary.focus-visible{outline-color:var(--md-accent-fg-color);outline-offset:.2rem}.md-typeset summary:not(.focus-visible){-webkit-tap-highlight-color:transparent;outline:none}[dir=ltr] .md-typeset summary:after{right:.4rem}[dir=rtl] .md-typeset summary:after{left:.4rem}.md-typeset summary:after{background-color:currentcolor;content:"";height:1rem;-webkit-mask-image:var(--md-details-icon);mask-image:var(--md-details-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.625em;transform:rotate(0deg);transition:transform .25s;width:1rem}[dir=rtl] .md-typeset summary:after{transform:rotate(180deg)}.md-typeset summary::marker{display:none}.md-typeset summary::-webkit-details-marker{display:none}.md-typeset .emojione,.md-typeset .gemoji,.md-typeset .twemoji{display:inline-flex;height:1.125em;vertical-align:text-top}.md-typeset .emojione svg,.md-typeset .gemoji svg,.md-typeset .twemoji svg{fill:currentcolor;max-height:100%;width:1.125em}.highlight .o,.highlight .ow{color:var(--md-code-hl-operator-color)}.highlight .p{color:var(--md-code-hl-punctuation-color)}.highlight .cpf,.highlight .l,.highlight .s,.highlight .s1,.highlight .s2,.highlight .sb,.highlight .sc,.highlight .si,.highlight .ss{color:var(--md-code-hl-string-color)}.highlight .cp,.highlight .se,.highlight .sh,.highlight .sr,.highlight .sx{color:var(--md-code-hl-special-color)}.highlight .il,.highlight .m,.highlight .mb,.highlight .mf,.highlight .mh,.highlight .mi,.highlight .mo{color:var(--md-code-hl-number-color)}.highlight .k,.highlight .kd,.highlight .kn,.highlight .kp,.highlight .kr,.highlight .kt{color:var(--md-code-hl-keyword-color)}.highlight .kc,.highlight .n{color:var(--md-code-hl-name-color)}.highlight .bp,.highlight .nb,.highlight .no{color:var(--md-code-hl-constant-color)}.highlight .nc,.highlight .ne,.highlight .nf,.highlight .nn{color:var(--md-code-hl-function-color)}.highlight .nd,.highlight .ni,.highlight .nl,.highlight .nt{color:var(--md-code-hl-keyword-color)}.highlight .c,.highlight .c1,.highlight .ch,.highlight .cm,.highlight .cs,.highlight .sd{color:var(--md-code-hl-comment-color)}.highlight .na,.highlight .nv,.highlight .vc,.highlight .vg,.highlight .vi{color:var(--md-code-hl-variable-color)}.highlight .ge,.highlight .gh,.highlight .go,.highlight .gp,.highlight .gr,.highlight .gs,.highlight .gt,.highlight .gu{color:var(--md-code-hl-generic-color)}.highlight .gd,.highlight .gi{border-radius:.1rem;margin:0 -.125em;padding:0 .125em}.highlight .gd{background-color:var(--md-typeset-del-color)}.highlight .gi{background-color:var(--md-typeset-ins-color)}.highlight .hll{background-color:var(--md-code-hl-color--light);box-shadow:2px 0 0 0 var(--md-code-hl-color) inset;display:block;margin:0 -1.1764705882em;padding:0 1.1764705882em}.highlight span.filename{background-color:var(--md-code-bg-color);border-bottom:.05rem solid var(--md-default-fg-color--lightest);border-top-left-radius:.1rem;border-top-right-radius:.1rem;display:flow-root;font-size:.85em;font-weight:700;margin-top:1em;padding:.6617647059em 1.1764705882em;position:relative}.highlight span.filename+pre{margin-top:0}.highlight span.filename+pre>code{border-top-left-radius:0;border-top-right-radius:0}.highlight [data-linenos]:before{background-color:var(--md-code-bg-color);box-shadow:-.05rem 0 var(--md-default-fg-color--lightest) inset;color:var(--md-default-fg-color--light);content:attr(data-linenos);float:left;left:-1.1764705882em;margin-left:-1.1764705882em;margin-right:1.1764705882em;padding-left:1.1764705882em;position:sticky;-webkit-user-select:none;user-select:none;z-index:3}.highlight code a[id]{position:absolute;visibility:hidden}.highlight code[data-md-copying] .hll{display:contents}.highlight code[data-md-copying] .md-annotation{display:none}.highlighttable{display:flow-root}.highlighttable tbody,.highlighttable td{display:block;padding:0}.highlighttable tr{display:flex}.highlighttable pre{margin:0}.highlighttable th.filename{flex-grow:1;padding:0;text-align:left}.highlighttable th.filename span.filename{margin-top:0}.highlighttable .linenos{background-color:var(--md-code-bg-color);border-bottom-left-radius:.1rem;border-top-left-radius:.1rem;font-size:.85em;padding:.7720588235em 0 .7720588235em 1.1764705882em;-webkit-user-select:none;user-select:none}.highlighttable .linenodiv{box-shadow:-.05rem 0 var(--md-default-fg-color--lightest) inset;padding-right:.5882352941em}.highlighttable .linenodiv pre{color:var(--md-default-fg-color--light);text-align:right}.highlighttable .code{flex:1;min-width:0}.linenodiv a{color:inherit}.md-typeset .highlighttable{direction:ltr;margin:1em 0}.md-typeset .highlighttable>tbody>tr>.code>div>pre>code{border-bottom-left-radius:0;border-top-left-radius:0}.md-typeset .highlight+.result{border:.05rem solid var(--md-code-bg-color);border-bottom-left-radius:.1rem;border-bottom-right-radius:.1rem;border-top-width:.1rem;margin-top:-1.125em;overflow:visible;padding:0 1em}.md-typeset .highlight+.result:after{clear:both;content:"";display:block}@media screen and (max-width:44.9375em){.md-content__inner>.highlight{margin:1em -.8rem}.md-content__inner>.highlight>.filename,.md-content__inner>.highlight>.highlighttable>tbody>tr>.code>div>pre>code,.md-content__inner>.highlight>.highlighttable>tbody>tr>.filename span.filename,.md-content__inner>.highlight>.highlighttable>tbody>tr>.linenos,.md-content__inner>.highlight>pre>code{border-radius:0}.md-content__inner>.highlight+.result{border-left-width:0;border-radius:0;border-right-width:0;margin-left:-.8rem;margin-right:-.8rem}}.md-typeset .keys kbd:after,.md-typeset .keys kbd:before{-moz-osx-font-smoothing:initial;-webkit-font-smoothing:initial;color:inherit;margin:0;position:relative}.md-typeset .keys span{color:var(--md-default-fg-color--light);padding:0 .2em}.md-typeset .keys .key-alt:before,.md-typeset .keys .key-left-alt:before,.md-typeset .keys .key-right-alt:before{content:"⎇";padding-right:.4em}.md-typeset .keys .key-command:before,.md-typeset .keys .key-left-command:before,.md-typeset .keys .key-right-command:before{content:"⌘";padding-right:.4em}.md-typeset .keys .key-control:before,.md-typeset .keys .key-left-control:before,.md-typeset .keys .key-right-control:before{content:"⌃";padding-right:.4em}.md-typeset .keys .key-left-meta:before,.md-typeset .keys .key-meta:before,.md-typeset .keys .key-right-meta:before{content:"◆";padding-right:.4em}.md-typeset .keys .key-left-option:before,.md-typeset .keys .key-option:before,.md-typeset .keys .key-right-option:before{content:"⌥";padding-right:.4em}.md-typeset .keys .key-left-shift:before,.md-typeset .keys .key-right-shift:before,.md-typeset .keys .key-shift:before{content:"⇧";padding-right:.4em}.md-typeset .keys .key-left-super:before,.md-typeset .keys .key-right-super:before,.md-typeset .keys .key-super:before{content:"❖";padding-right:.4em}.md-typeset .keys .key-left-windows:before,.md-typeset .keys .key-right-windows:before,.md-typeset .keys .key-windows:before{content:"⊞";padding-right:.4em}.md-typeset .keys .key-arrow-down:before{content:"↓";padding-right:.4em}.md-typeset .keys .key-arrow-left:before{content:"←";padding-right:.4em}.md-typeset .keys .key-arrow-right:before{content:"→";padding-right:.4em}.md-typeset .keys .key-arrow-up:before{content:"↑";padding-right:.4em}.md-typeset .keys .key-backspace:before{content:"⌫";padding-right:.4em}.md-typeset .keys .key-backtab:before{content:"⇤";padding-right:.4em}.md-typeset .keys .key-caps-lock:before{content:"⇪";padding-right:.4em}.md-typeset .keys .key-clear:before{content:"⌧";padding-right:.4em}.md-typeset .keys .key-context-menu:before{content:"☰";padding-right:.4em}.md-typeset .keys .key-delete:before{content:"⌦";padding-right:.4em}.md-typeset .keys .key-eject:before{content:"⏏";padding-right:.4em}.md-typeset .keys .key-end:before{content:"⤓";padding-right:.4em}.md-typeset .keys .key-escape:before{content:"⎋";padding-right:.4em}.md-typeset .keys .key-home:before{content:"⤒";padding-right:.4em}.md-typeset .keys .key-insert:before{content:"⎀";padding-right:.4em}.md-typeset .keys .key-page-down:before{content:"⇟";padding-right:.4em}.md-typeset .keys .key-page-up:before{content:"⇞";padding-right:.4em}.md-typeset .keys .key-print-screen:before{content:"⎙";padding-right:.4em}.md-typeset .keys .key-tab:after{content:"⇥";padding-left:.4em}.md-typeset .keys .key-num-enter:after{content:"⌤";padding-left:.4em}.md-typeset .keys .key-enter:after{content:"⏎";padding-left:.4em}:root{--md-tabbed-icon--prev:url('data:image/svg+xml;charset=utf-8,');--md-tabbed-icon--next:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .tabbed-set{border-radius:.1rem;display:flex;flex-flow:column wrap;margin:1em 0;position:relative}.md-typeset .tabbed-set>input{height:0;opacity:0;position:absolute;width:0}.md-typeset .tabbed-set>input:target{--md-scroll-offset:0.625em}.md-typeset .tabbed-labels{-ms-overflow-style:none;box-shadow:0 -.05rem var(--md-default-fg-color--lightest) inset;display:flex;max-width:100%;overflow:auto;scrollbar-width:none}@media print{.md-typeset .tabbed-labels{display:contents}}@media screen{.js .md-typeset .tabbed-labels{position:relative}.js .md-typeset .tabbed-labels:before{background:var(--md-accent-fg-color);bottom:0;content:"";display:block;height:2px;left:0;position:absolute;transform:translateX(var(--md-indicator-x));transition:width 225ms,transform .25s;transition-timing-function:cubic-bezier(.4,0,.2,1);width:var(--md-indicator-width)}}.md-typeset .tabbed-labels::-webkit-scrollbar{display:none}.md-typeset .tabbed-labels>label{border-bottom:.1rem solid #0000;border-radius:.1rem .1rem 0 0;color:var(--md-default-fg-color--light);cursor:pointer;flex-shrink:0;font-size:.64rem;font-weight:700;padding:.78125em 1.25em .625em;scroll-margin-inline-start:1rem;transition:background-color .25s,color .25s;white-space:nowrap;width:auto}@media print{.md-typeset .tabbed-labels>label:first-child{order:1}.md-typeset .tabbed-labels>label:nth-child(2){order:2}.md-typeset .tabbed-labels>label:nth-child(3){order:3}.md-typeset .tabbed-labels>label:nth-child(4){order:4}.md-typeset .tabbed-labels>label:nth-child(5){order:5}.md-typeset .tabbed-labels>label:nth-child(6){order:6}.md-typeset .tabbed-labels>label:nth-child(7){order:7}.md-typeset .tabbed-labels>label:nth-child(8){order:8}.md-typeset .tabbed-labels>label:nth-child(9){order:9}.md-typeset .tabbed-labels>label:nth-child(10){order:10}.md-typeset .tabbed-labels>label:nth-child(11){order:11}.md-typeset .tabbed-labels>label:nth-child(12){order:12}.md-typeset .tabbed-labels>label:nth-child(13){order:13}.md-typeset .tabbed-labels>label:nth-child(14){order:14}.md-typeset .tabbed-labels>label:nth-child(15){order:15}.md-typeset .tabbed-labels>label:nth-child(16){order:16}.md-typeset .tabbed-labels>label:nth-child(17){order:17}.md-typeset .tabbed-labels>label:nth-child(18){order:18}.md-typeset .tabbed-labels>label:nth-child(19){order:19}.md-typeset .tabbed-labels>label:nth-child(20){order:20}}.md-typeset .tabbed-labels>label:hover{color:var(--md-accent-fg-color)}.md-typeset .tabbed-content{width:100%}@media print{.md-typeset .tabbed-content{display:contents}}.md-typeset .tabbed-block{display:none}@media print{.md-typeset .tabbed-block{display:block}.md-typeset .tabbed-block:first-child{order:1}.md-typeset .tabbed-block:nth-child(2){order:2}.md-typeset .tabbed-block:nth-child(3){order:3}.md-typeset .tabbed-block:nth-child(4){order:4}.md-typeset .tabbed-block:nth-child(5){order:5}.md-typeset .tabbed-block:nth-child(6){order:6}.md-typeset .tabbed-block:nth-child(7){order:7}.md-typeset .tabbed-block:nth-child(8){order:8}.md-typeset .tabbed-block:nth-child(9){order:9}.md-typeset .tabbed-block:nth-child(10){order:10}.md-typeset .tabbed-block:nth-child(11){order:11}.md-typeset .tabbed-block:nth-child(12){order:12}.md-typeset .tabbed-block:nth-child(13){order:13}.md-typeset .tabbed-block:nth-child(14){order:14}.md-typeset .tabbed-block:nth-child(15){order:15}.md-typeset .tabbed-block:nth-child(16){order:16}.md-typeset .tabbed-block:nth-child(17){order:17}.md-typeset .tabbed-block:nth-child(18){order:18}.md-typeset .tabbed-block:nth-child(19){order:19}.md-typeset .tabbed-block:nth-child(20){order:20}}.md-typeset .tabbed-block>.highlight:first-child>pre,.md-typeset .tabbed-block>pre:first-child{margin:0}.md-typeset .tabbed-block>.highlight:first-child>pre>code,.md-typeset .tabbed-block>pre:first-child>code{border-top-left-radius:0;border-top-right-radius:0}.md-typeset .tabbed-block>.highlight:first-child>.filename{border-top-left-radius:0;border-top-right-radius:0;margin:0}.md-typeset .tabbed-block>.highlight:first-child>.highlighttable{margin:0}.md-typeset .tabbed-block>.highlight:first-child>.highlighttable>tbody>tr>.filename span.filename,.md-typeset .tabbed-block>.highlight:first-child>.highlighttable>tbody>tr>.linenos{border-top-left-radius:0;border-top-right-radius:0;margin:0}.md-typeset .tabbed-block>.highlight:first-child>.highlighttable>tbody>tr>.code>div>pre>code{border-top-left-radius:0;border-top-right-radius:0}.md-typeset .tabbed-block>.highlight:first-child+.result{margin-top:-.125em}.md-typeset .tabbed-block>.tabbed-set{margin:0}.md-typeset .tabbed-button{align-self:center;border-radius:100%;color:var(--md-default-fg-color--light);cursor:pointer;display:block;height:.9rem;margin-top:.1rem;pointer-events:auto;transition:background-color .25s;width:.9rem}.md-typeset .tabbed-button:hover{background-color:var(--md-accent-fg-color--transparent);color:var(--md-accent-fg-color)}.md-typeset .tabbed-button:after{background-color:currentcolor;content:"";display:block;height:100%;-webkit-mask-image:var(--md-tabbed-icon--prev);mask-image:var(--md-tabbed-icon--prev);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;transition:background-color .25s,transform .25s;width:100%}.md-typeset .tabbed-control{background:linear-gradient(to right,var(--md-default-bg-color) 60%,#0000);display:flex;height:1.9rem;justify-content:start;pointer-events:none;position:absolute;transition:opacity 125ms;width:1.2rem}[dir=rtl] .md-typeset .tabbed-control{transform:rotate(180deg)}.md-typeset .tabbed-control[hidden]{opacity:0}.md-typeset .tabbed-control--next{background:linear-gradient(to left,var(--md-default-bg-color) 60%,#0000);justify-content:end;right:0}.md-typeset .tabbed-control--next .tabbed-button:after{-webkit-mask-image:var(--md-tabbed-icon--next);mask-image:var(--md-tabbed-icon--next)}@media screen and (max-width:44.9375em){[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels{padding-left:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels{padding-right:.8rem}.md-content__inner>.tabbed-set .tabbed-labels{margin:0 -.8rem;max-width:100vw;scroll-padding-inline-start:.8rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels:after{padding-right:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels:after{padding-left:.8rem}.md-content__inner>.tabbed-set .tabbed-labels:after{content:""}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{padding-left:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{padding-right:.8rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{margin-left:-.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{margin-right:-.8rem}.md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--prev{width:2rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{padding-right:.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{padding-left:.8rem}[dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{margin-right:-.8rem}[dir=rtl] .md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{margin-left:-.8rem}.md-content__inner>.tabbed-set .tabbed-labels~.tabbed-control--next{width:2rem}}@media screen{.md-typeset .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9){color:var(--md-accent-fg-color)}.md-typeset .no-js .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.md-typeset .no-js .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.md-typeset .no-js .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.md-typeset .no-js .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.md-typeset .no-js .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.md-typeset .no-js .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.md-typeset .no-js .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.md-typeset .no-js .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.md-typeset .no-js .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.md-typeset .no-js .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.md-typeset .no-js .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.md-typeset .no-js .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.md-typeset .no-js .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.md-typeset .no-js .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.md-typeset .no-js .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.md-typeset .no-js .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.md-typeset .no-js .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.md-typeset .no-js .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.md-typeset .no-js .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.md-typeset .no-js .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9),.no-js .md-typeset .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child,.no-js .md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-labels>:nth-child(10),.no-js .md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-labels>:nth-child(11),.no-js .md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-labels>:nth-child(12),.no-js .md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-labels>:nth-child(13),.no-js .md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-labels>:nth-child(14),.no-js .md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-labels>:nth-child(15),.no-js .md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-labels>:nth-child(16),.no-js .md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-labels>:nth-child(17),.no-js .md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-labels>:nth-child(18),.no-js .md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-labels>:nth-child(19),.no-js .md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-labels>:nth-child(2),.no-js .md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-labels>:nth-child(20),.no-js .md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-labels>:nth-child(3),.no-js .md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-labels>:nth-child(4),.no-js .md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-labels>:nth-child(5),.no-js .md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-labels>:nth-child(6),.no-js .md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-labels>:nth-child(7),.no-js .md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-labels>:nth-child(8),.no-js .md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-labels>:nth-child(9){border-color:var(--md-accent-fg-color)}}.md-typeset .tabbed-set>input:first-child.focus-visible~.tabbed-labels>:first-child,.md-typeset .tabbed-set>input:nth-child(10).focus-visible~.tabbed-labels>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11).focus-visible~.tabbed-labels>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12).focus-visible~.tabbed-labels>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13).focus-visible~.tabbed-labels>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14).focus-visible~.tabbed-labels>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15).focus-visible~.tabbed-labels>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16).focus-visible~.tabbed-labels>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17).focus-visible~.tabbed-labels>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18).focus-visible~.tabbed-labels>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19).focus-visible~.tabbed-labels>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2).focus-visible~.tabbed-labels>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20).focus-visible~.tabbed-labels>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3).focus-visible~.tabbed-labels>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4).focus-visible~.tabbed-labels>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5).focus-visible~.tabbed-labels>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6).focus-visible~.tabbed-labels>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7).focus-visible~.tabbed-labels>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8).focus-visible~.tabbed-labels>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9).focus-visible~.tabbed-labels>:nth-child(9){background-color:var(--md-accent-fg-color--transparent)}.md-typeset .tabbed-set>input:first-child:checked~.tabbed-content>:first-child,.md-typeset .tabbed-set>input:nth-child(10):checked~.tabbed-content>:nth-child(10),.md-typeset .tabbed-set>input:nth-child(11):checked~.tabbed-content>:nth-child(11),.md-typeset .tabbed-set>input:nth-child(12):checked~.tabbed-content>:nth-child(12),.md-typeset .tabbed-set>input:nth-child(13):checked~.tabbed-content>:nth-child(13),.md-typeset .tabbed-set>input:nth-child(14):checked~.tabbed-content>:nth-child(14),.md-typeset .tabbed-set>input:nth-child(15):checked~.tabbed-content>:nth-child(15),.md-typeset .tabbed-set>input:nth-child(16):checked~.tabbed-content>:nth-child(16),.md-typeset .tabbed-set>input:nth-child(17):checked~.tabbed-content>:nth-child(17),.md-typeset .tabbed-set>input:nth-child(18):checked~.tabbed-content>:nth-child(18),.md-typeset .tabbed-set>input:nth-child(19):checked~.tabbed-content>:nth-child(19),.md-typeset .tabbed-set>input:nth-child(2):checked~.tabbed-content>:nth-child(2),.md-typeset .tabbed-set>input:nth-child(20):checked~.tabbed-content>:nth-child(20),.md-typeset .tabbed-set>input:nth-child(3):checked~.tabbed-content>:nth-child(3),.md-typeset .tabbed-set>input:nth-child(4):checked~.tabbed-content>:nth-child(4),.md-typeset .tabbed-set>input:nth-child(5):checked~.tabbed-content>:nth-child(5),.md-typeset .tabbed-set>input:nth-child(6):checked~.tabbed-content>:nth-child(6),.md-typeset .tabbed-set>input:nth-child(7):checked~.tabbed-content>:nth-child(7),.md-typeset .tabbed-set>input:nth-child(8):checked~.tabbed-content>:nth-child(8),.md-typeset .tabbed-set>input:nth-child(9):checked~.tabbed-content>:nth-child(9){display:block}:root{--md-tasklist-icon:url('data:image/svg+xml;charset=utf-8,');--md-tasklist-icon--checked:url('data:image/svg+xml;charset=utf-8,')}.md-typeset .task-list-item{list-style-type:none;position:relative}[dir=ltr] .md-typeset .task-list-item [type=checkbox]{left:-2em}[dir=rtl] .md-typeset .task-list-item [type=checkbox]{right:-2em}.md-typeset .task-list-item [type=checkbox]{position:absolute;top:.45em}.md-typeset .task-list-control [type=checkbox]{opacity:0;z-index:-1}[dir=ltr] .md-typeset .task-list-indicator:before{left:-1.5em}[dir=rtl] .md-typeset .task-list-indicator:before{right:-1.5em}.md-typeset .task-list-indicator:before{background-color:var(--md-default-fg-color--lightest);content:"";height:1.25em;-webkit-mask-image:var(--md-tasklist-icon);mask-image:var(--md-tasklist-icon);-webkit-mask-position:center;mask-position:center;-webkit-mask-repeat:no-repeat;mask-repeat:no-repeat;-webkit-mask-size:contain;mask-size:contain;position:absolute;top:.15em;width:1.25em}.md-typeset [type=checkbox]:checked+.task-list-indicator:before{background-color:#00e676;-webkit-mask-image:var(--md-tasklist-icon--checked);mask-image:var(--md-tasklist-icon--checked)}:root>*{--md-mermaid-font-family:var(--md-text-font-family),sans-serif;--md-mermaid-edge-color:var(--md-code-fg-color);--md-mermaid-node-bg-color:var(--md-accent-fg-color--transparent);--md-mermaid-node-fg-color:var(--md-accent-fg-color);--md-mermaid-label-bg-color:var(--md-default-bg-color);--md-mermaid-label-fg-color:var(--md-code-fg-color);--md-mermaid-sequence-actor-bg-color:var(--md-mermaid-label-bg-color);--md-mermaid-sequence-actor-fg-color:var(--md-mermaid-label-fg-color);--md-mermaid-sequence-actor-border-color:var(--md-mermaid-node-fg-color);--md-mermaid-sequence-actor-line-color:var(--md-default-fg-color--lighter);--md-mermaid-sequence-actorman-bg-color:var(--md-mermaid-label-bg-color);--md-mermaid-sequence-actorman-line-color:var(--md-mermaid-node-fg-color);--md-mermaid-sequence-box-bg-color:var(--md-mermaid-node-bg-color);--md-mermaid-sequence-box-fg-color:var(--md-mermaid-edge-color);--md-mermaid-sequence-label-bg-color:var(--md-mermaid-node-bg-color);--md-mermaid-sequence-label-fg-color:var(--md-mermaid-node-fg-color);--md-mermaid-sequence-loop-bg-color:var(--md-mermaid-node-bg-color);--md-mermaid-sequence-loop-fg-color:var(--md-mermaid-edge-color);--md-mermaid-sequence-loop-border-color:var(--md-mermaid-node-fg-color);--md-mermaid-sequence-message-fg-color:var(--md-mermaid-edge-color);--md-mermaid-sequence-message-line-color:var(--md-mermaid-edge-color);--md-mermaid-sequence-note-bg-color:var(--md-mermaid-label-bg-color);--md-mermaid-sequence-note-fg-color:var(--md-mermaid-edge-color);--md-mermaid-sequence-note-border-color:var(--md-mermaid-label-fg-color);--md-mermaid-sequence-number-bg-color:var(--md-mermaid-node-fg-color);--md-mermaid-sequence-number-fg-color:var(--md-accent-bg-color)}.mermaid{line-height:normal;margin:1em 0}@media screen and (min-width:45em){[dir=ltr] .md-typeset .inline{float:left}[dir=rtl] .md-typeset .inline{float:right}[dir=ltr] .md-typeset .inline{margin-right:.8rem}[dir=rtl] .md-typeset .inline{margin-left:.8rem}.md-typeset .inline{margin-bottom:.8rem;margin-top:0;width:11.7rem}[dir=ltr] .md-typeset .inline.end{float:right}[dir=rtl] .md-typeset .inline.end{float:left}[dir=ltr] .md-typeset .inline.end{margin-left:.8rem;margin-right:0}[dir=rtl] .md-typeset .inline.end{margin-left:0;margin-right:.8rem}} \ No newline at end of file diff --git a/develop/assets/stylesheets/main.30068a00.min.css.map b/develop/assets/stylesheets/main.30068a00.min.css.map new file mode 100644 index 00000000..23cd93fc --- /dev/null +++ b/develop/assets/stylesheets/main.30068a00.min.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["src/assets/stylesheets/main/components/_meta.scss","../../../src/assets/stylesheets/main.scss","src/assets/stylesheets/main/_resets.scss","src/assets/stylesheets/main/_colors.scss","src/assets/stylesheets/main/_icons.scss","src/assets/stylesheets/main/_typeset.scss","src/assets/stylesheets/utilities/_break.scss","src/assets/stylesheets/main/components/_author.scss","src/assets/stylesheets/main/components/_banner.scss","src/assets/stylesheets/main/components/_base.scss","src/assets/stylesheets/main/components/_clipboard.scss","src/assets/stylesheets/main/components/_consent.scss","src/assets/stylesheets/main/components/_content.scss","src/assets/stylesheets/main/components/_dialog.scss","src/assets/stylesheets/main/components/_feedback.scss","src/assets/stylesheets/main/components/_footer.scss","src/assets/stylesheets/main/components/_form.scss","src/assets/stylesheets/main/components/_header.scss","node_modules/material-design-color/material-color.scss","src/assets/stylesheets/main/components/_nav.scss","src/assets/stylesheets/main/components/_pagination.scss","src/assets/stylesheets/main/components/_post.scss","src/assets/stylesheets/main/components/_search.scss","src/assets/stylesheets/main/components/_select.scss","src/assets/stylesheets/main/components/_sidebar.scss","src/assets/stylesheets/main/components/_source.scss","src/assets/stylesheets/main/components/_status.scss","src/assets/stylesheets/main/components/_tabs.scss","src/assets/stylesheets/main/components/_tag.scss","src/assets/stylesheets/main/components/_tooltip.scss","src/assets/stylesheets/main/components/_top.scss","src/assets/stylesheets/main/components/_version.scss","src/assets/stylesheets/main/extensions/markdown/_admonition.scss","src/assets/stylesheets/main/extensions/markdown/_footnotes.scss","src/assets/stylesheets/main/extensions/markdown/_toc.scss","src/assets/stylesheets/main/extensions/pymdownx/_arithmatex.scss","src/assets/stylesheets/main/extensions/pymdownx/_critic.scss","src/assets/stylesheets/main/extensions/pymdownx/_details.scss","src/assets/stylesheets/main/extensions/pymdownx/_emoji.scss","src/assets/stylesheets/main/extensions/pymdownx/_highlight.scss","src/assets/stylesheets/main/extensions/pymdownx/_keys.scss","src/assets/stylesheets/main/extensions/pymdownx/_tabbed.scss","src/assets/stylesheets/main/extensions/pymdownx/_tasklist.scss","src/assets/stylesheets/main/integrations/_mermaid.scss","src/assets/stylesheets/main/_modifiers.scss"],"names":[],"mappings":"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C/BgpGN,C+B3oGE,4DACE,0B/B8oGJ,C+B3oGI,0EACE,wBAlBG,CAmBH,iDAAA,CAAA,yC/B6oGN,C+BzoGI,wEACE,a/B2oGN,C+BhqGE,4DACE,oB/BmqGJ,C+BhqGI,sFACE,gC/BkqGN,C+B7pGE,oEACE,0B/BgqGJ,C+B7pGI,kFACE,wBAlBG,CAmBH,qDAAA,CAAA,6C/B+pGN,C+B3pGI,gFACE,a/B6pGN,C+BlrGE,8DACE,oB/BqrGJ,C+BlrGI,wFACE,gC/BorGN,C+B/qGE,sEACE,0B/BkrGJ,C+B/qGI,oFACE,wBAlBG,CAmBH,sDAAA,CAAA,8C/BirGN,C+B7qGI,kFACE,a/B+qGN,C+BpsGE,4DACE,oB/BusGJ,C+BpsGI,sFACE,gC/BssGN,C+BjsGE,oEACE,0B/BosGJ,C+BjsGI,kFACE,wBAlBG,CAmBH,qDAAA,CAAA,6C/BmsGN,C+B/rGI,gFACE,a/BisGN,C+BttGE,4DACE,oB/BytGJ,C+BttGI,sFACE,gC/BwtGN,C+BntGE,oEACE,0B/BstGJ,C+BntGI,kFACE,wBAlBG,CAmBH,qDAAA,CAAA,6C/BqtGN,C+BjtGI,gFACE,a/BmtGN,C+BxuGE,0DACE,oB/B2uGJ,C+BxuGI,oFACE,gC/B0uGN,C+BruGE,kEACE,0B/BwuGJ,C+BruGI,gFACE,wBAlBG,CAmBH,oDAAA,CAAA,4C/BuuGN,C+BnuGI,8EACE,a/BquGN,C+B1vGE,oDACE,oB/B6vGJ,C+B1vGI,8EACE,gC/B4vGN,C+BvvGE,4DACE,0B/B0vGJ,C+BvvGI,0EACE,wBAlBG,CAmBH,iDAAA,CAAA,yC/ByvGN,C+BrvGI,wEACE,a/BuvGN,C+B5wGE,4DACE,oB/B+wGJ,C+B5wGI,sFACE,gC/B8wGN,C+BzwGE,oEACE,0B/B4wGJ,C+BzwGI,kFACE,wBAlBG,CAmBH,qDAAA,CAAA,6C/B2wGN,C+BvwGI,gFACE,a/BywGN,C+B9xGE,wDACE,oB/BiyGJ,C+B9xGI,kFACE,gC/BgyGN,C+B3xGE,gEACE,0B/B8xGJ,C+B3xGI,8EACE,wBAlBG,CAmBH,mDAAA,CAAA,2C/B6xGN,C+BzxGI,4EACE,a/B2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","file":"main.css"} \ No newline at end of file diff --git a/develop/dictionary.txt b/develop/dictionary.txt index d3d2eb25..58f6eeec 100644 --- a/develop/dictionary.txt +++ b/develop/dictionary.txt @@ -37,3 +37,4 @@ frontends misconfiguration misconfigurations backhaul +sublicense diff --git a/develop/index.html b/develop/index.html index dedf4eef..2dc41b9d 100644 --- a/develop/index.html +++ b/develop/index.html @@ -1,4 +1,4 @@ - ReactPy-Django
Skip to content

Add ReactPy to a Django Project

Overview

If you want to add some interactivity to your existing Django project, you don't have to rewrite it in ReactPy. Use ReactPy-Django to add ReactPy to your existing stack, and render interactive components anywhere.

Note

These docs assumes you have already created a Django project, which involves creating and installing at least one Django app.

If do not have a Django project, check out this 9 minute YouTube tutorial created by IDG TECHtalk.


Step 1: Install from PyPI

Run the following command to install reactpy-django in your Python environment.

pip install reactpy-django
+ Add ReactPy to a Django Project - ReactPy-Django       

Add ReactPy to a Django Project

Overview

If you want to add some interactivity to your existing Django project, you don't have to rewrite it in ReactPy. Use ReactPy-Django to add ReactPy to your existing stack, and render interactive components anywhere.

Note

These docs assumes you have already created a Django project, which involves creating and installing at least one Django app.

If do not have a Django project, check out this 9 minute YouTube tutorial created by IDG TECHtalk.


Step 1: Install from PyPI

Run the following command to install reactpy-django in your Python environment.

pip install reactpy-django
 

Step 2: Configure settings.py

Add "reactpy_django" to INSTALLED_APPS in your settings.py file.

1
 2
 3
@@ -100,4 +100,4 @@
     {% component "example_project.my_app.components.hello_world" recipient="World" %}
   </body>
 </html>
-

Last update: September 16, 2023
Authors: Mark Bakhit
\ No newline at end of file +

Last update: September 16, 2023
Authors: Mark Bakhit
\ No newline at end of file diff --git a/develop/learn/your-first-component/index.html b/develop/learn/your-first-component/index.html index 194d50d3..8fe3103b 100644 --- a/develop/learn/your-first-component/index.html +++ b/develop/learn/your-first-component/index.html @@ -1,4 +1,4 @@ - Your First Component - ReactPy-Django
Skip to content

Your First Component

Overview

Components are one of the core concepts of ReactPy. They are the foundation upon which you build user interfaces (UI), which makes them the perfect place to start your journey!

Note

If you have reached this point, you should have already installed ReactPy-Django through the previous steps.


Selecting a Django App

You will now need to pick at least one Django app to start using ReactPy-Django on.

For the following examples, we will assume the following:

  1. You have a Django app named my_app, which was created by Django's startapp command.
  2. You have placed my_app directly into your Django project folder (./example_project/my_app). This is common for small projects.
How do I organize my Django project for ReactPy?

ReactPy-Django has no project structure requirements. Organize everything as you wish, just like any Django project.

Defining a component

You will need a file to start creating ReactPy components.

We recommend creating a components.py file within your chosen Django app to start out. For this example, the file path will look like this: ./example_project/my_app/components.py.

Within this file, you can define your component functions using ReactPy's @component decorator.

1
+ Your First Component - ReactPy-Django       

Your First Component

Overview

Components are one of the core concepts of ReactPy. They are the foundation upon which you build user interfaces (UI), which makes them the perfect place to start your journey!

Note

If you have reached this point, you should have already installed ReactPy-Django through the previous steps.


Selecting a Django App

You will now need to pick at least one Django app to start using ReactPy-Django on.

For the following examples, we will assume the following:

  1. You have a Django app named my_app, which was created by Django's startapp command.
  2. You have placed my_app directly into your Django project folder (./example_project/my_app). This is common for small projects.
How do I organize my Django project for ReactPy?

ReactPy-Django has no project structure requirements. Organize everything as you wish, just like any Django project.

Defining a component

You will need a file to start creating ReactPy components.

We recommend creating a components.py file within your chosen Django app to start out. For this example, the file path will look like this: ./example_project/my_app/components.py.

Within this file, you can define your component functions using ReactPy's @component decorator.

1
 2
 3
 4
@@ -20,7 +20,7 @@
     {% component "example_project.my_app.components.hello_world" recipient="World" %}
   </body>
 </html>
-
Do not use context variables for the component path

The ReactPy component finder (reactpy_django.utils.RootComponentFinder) requires that your component path is a string.

Do not use Django template/context variables for the component path. Failure to follow this warning can result in unexpected behavior, such as components that will not render.

For example, do not do the following:

1
+
Do not use context variables for the component path

The ReactPy component finder requires that your component path is a string.

Do not use Django template/context variables for the component path. Failure to follow this warning can result in unexpected behavior, such as components that will not render.

For example, do not do the following:

1
 2
 3
 4
@@ -78,4 +78,4 @@
     path("example/", views.index),
 ]
 
Which urls.py do I add my views to?

For simple Django projects, you can easily add all of your views directly into the Django project's urls.py. However, as you start increase your project's complexity you might end up with way too much within one file.

Once you reach that point, we recommend creating an individual urls.py within each of your Django apps.

Then, within your Django project's urls.py you will use Django's include function to link it all together.

Viewing your component

To test your new Django view, run the following command to start up a development web server.

python manage.py runserver
-

Now you can navigate to your Django project URL that contains a ReactPy component, such as http://127.0.0.1:8000/example/ (from the previous step).

If you copy-pasted our example component, you will now see your component display "Hello World".

Do not use manage.py runserver for production

This command is only intended for development purposes. For production deployments make sure to read Django's documentation.

Learn more

Congratulations! If you followed the previous steps, you have now created a "Hello World" component using ReactPy-Django!

Deep Dive

The docs you are reading only covers our Django integration. To learn more, check out one of the following links:

Additionally, the vast majority of tutorials/guides you find for ReactJS can be applied to ReactPy.


Last update: September 16, 2023
Authors: Mark Bakhit
\ No newline at end of file +

Now you can navigate to your Django project URL that contains a ReactPy component, such as http://127.0.0.1:8000/example/ (from the previous step).

If you copy-pasted our example component, you will now see your component display "Hello World".

Do not use manage.py runserver for production

This command is only intended for development purposes. For production deployments make sure to read Django's documentation.

Learn more

Congratulations! If you followed the previous steps, you have now created a "Hello World" component using ReactPy-Django!

Deep Dive

The docs you are reading only covers our Django integration. To learn more, check out one of the following links:

Additionally, the vast majority of tutorials/guides you find for ReactJS can be applied to ReactPy.


Last update: September 16, 2023
Authors: Mark Bakhit
\ No newline at end of file diff --git a/develop/reference/components/index.html b/develop/reference/components/index.html index a07fe9d2..2d5fe70b 100644 --- a/develop/reference/components/index.html +++ b/develop/reference/components/index.html @@ -1,4 +1,4 @@ - Components - ReactPy-Django

Components

Overview

We supply some pre-designed that components can be used to help simplify development.


View To Component

Convert any Django view into a ReactPy component by using this decorator. Compatible with Function Based Views and Class Based Views. Views can be sync or async.

 1
+ Components - ReactPy-Django       

Components

Overview

We supply some pre-designed that components can be used to help simplify development.


View To Component

Convert any Django view into a ReactPy component by using this decorator. Compatible with Function Based Views and Class Based Views. Views can be sync or async.

 1
  2
  3
  4
@@ -319,7 +319,7 @@
         django_css("css/buttons.css"),
         html.button("My Button!"),
     )
-
See Interface

Parameters

Name Type Description Default
static_path str The path to the static file. This path is identical to what you would use on a static template tag. N/A
key Key | None A key to uniquely identify this component which is unique amongst a component's immediate siblings None

Returns

Type Description
Component A ReactPy component.
Should I put django_css at the top of my HTML?

Yes, if the stylesheet contains styling for your component.

Can I load static CSS using html.link instead?

While you can load stylesheets with html.link, keep in mind that loading this way does not ensure load order. Thus, your stylesheet will be loaded after your component is displayed. This would likely cause unintended visual behavior, so use this at your own discretion.

Here's an example on what you should avoid doing for Django static files:

 1
+
See Interface

Parameters

Name Type Description Default
static_path str The path to the static file. This path is identical to what you would use on Django's {% static %} template tag. N/A
key Key | None A key to uniquely identify this component which is unique amongst a component's immediate siblings None

Returns

Type Description
Component A ReactPy component.
Can I load static CSS using html.link instead?

While you can load stylesheets with html.link, keep in mind that loading this way does not ensure load order. Thus, your stylesheet will be loaded after your component is displayed. This would likely cause unintended visual behavior, so use this at your own discretion.

Here's an example on what you should avoid doing for Django static files:

 1
  2
  3
  4
@@ -338,7 +338,7 @@
         html.link({"rel": "stylesheet", "href": static("css/buttons.css")}),
         html.button("My Button!"),
     )
-
How do I load external CSS?

django_css can only be used with local static files.

For external CSS, substitute django_css with html.link.

 1
+
How do I load external CSS?

django_css can only be used with local static files.

For external CSS, you should use html.link.

 1
  2
  3
  4
@@ -359,7 +359,7 @@
         ),
         html.button("My Button!"),
     )
-
Why not load my CSS in <head>?

Traditionally, stylesheets are loaded in your <head> using the {% load static %} template tag.

To help improve webpage load times, you can use the django_css component to defer loading your stylesheet until it is needed.

Django JS

Allows you to defer loading JavaScript until a component begins rendering. This JavaScript must be stored within Django's static files.

 1
+
Why not load my CSS in <head>?

Traditionally, stylesheets are loaded in your <head> using Django's {% static %} template tag.

However, to help improve webpage load times you can use this django_css component to defer loading your stylesheet until it is needed.

Django JS

Allows you to defer loading JavaScript until a component begins rendering. This JavaScript must be stored within Django's static files.

Pitfall

Be mindful of load order! If your JavaScript relies on the component existing on the page, you must place django_js at the bottom of your component.

 1
  2
  3
  4
@@ -378,7 +378,7 @@
         html.button("My Button!"),
         django_js("js/scripts.js"),
     )
-
See Interface

Parameters

Name Type Description Default
static_path str The path to the static file. This path is identical to what you would use on a static template tag. N/A
key Key | None A key to uniquely identify this component which is unique amongst a component's immediate siblings None

Returns

Type Description
Component A ReactPy component.
Should I put django_js at the bottom of my HTML?

Yes, if your scripts are reliant on the contents of the component.

Can I load static JavaScript using html.script instead?

While you can load JavaScript with html.script, keep in mind that loading this way does not ensure load order. Thus, your JavaScript will likely be loaded at an arbitrary time after your component is displayed.

Here's an example on what you should avoid doing for Django static files:

 1
+
See Interface

Parameters

Name Type Description Default
static_path str The path to the static file. This path is identical to what you would use on Django's {% static %} template tag. N/A
key Key | None A key to uniquely identify this component which is unique amongst a component's immediate siblings None

Returns

Type Description
Component A ReactPy component.
Can I load static JavaScript using html.script instead?

While you can load JavaScript with html.script, keep in mind that loading this way does not ensure load order. Thus, your JavaScript will likely be loaded at an arbitrary time after your component is displayed.

Here's an example on what you should avoid doing for Django static files:

 1
  2
  3
  4
@@ -397,7 +397,7 @@
         html.script({"src": static("js/scripts.js")}),
         html.button("My Button!"),
     )
-
How do I load external JS?

django_js can only be used with local static files.

For external JavaScript, substitute django_js with html.script.

1
+
How do I load external JS?

django_js can only be used with local static files.

For external JavaScript, you should use html.script.

1
 2
 3
 4
@@ -414,4 +414,4 @@
         html.script({"src": "https://example.com/external-scripts.js"}),
         html.button("My Button!"),
     )
-
Why not load my JS in <head>?

Traditionally, JavaScript is loaded in your <head> using the {% load static %} template tag.

To help improve webpage load times, you can use the django_js component to defer loading your JavaScript until it is needed.


Last update: September 7, 2023
Authors: Mark Bakhit
\ No newline at end of file +
Why not load my JS in <head>?

Traditionally, JavaScript is loaded in your <head> using Django's {% static %} template tag.

However, to help improve webpage load times you can use this django_js component to defer loading your JavaScript until it is needed.


Last update: September 21, 2023
Authors: Mark Bakhit
\ No newline at end of file diff --git a/develop/reference/decorators/index.html b/develop/reference/decorators/index.html index e5fce61b..0f6822dd 100644 --- a/develop/reference/decorators/index.html +++ b/develop/reference/decorators/index.html @@ -1,4 +1,4 @@ - Decorators - ReactPy-Django

Decorators

Overview

Decorator functions can be used within your components.py to help simplify development.


Auth Required

You can limit access to a component to users with a specific auth_attribute by using this decorator (with or without parentheses).

By default, this decorator checks if the user is logged in and not deactivated (is_active).

This decorator is commonly used to selectively render a component only if a user is_staff or is_superuser.

1
+ Decorators - ReactPy-Django       

Decorators

Overview

Decorator functions can be used within your components.py to help simplify development.


Auth Required

You can limit component access to users with a specific auth_attribute by using this decorator (with or without parentheses).

By default, this decorator checks if the user is logged in and not deactivated (is_active).

This decorator is commonly used to selectively render a component only if a user is_staff or is_superuser.

1
 2
 3
 4
@@ -96,4 +96,4 @@
 @auth_required(auth_attribute="is_really_cool")
 def my_component():
     return html.div("I am logged in!")
-

Last update: September 7, 2023
Authors: Mark Bakhit
\ No newline at end of file +

Last update: September 21, 2023
Authors: Mark Bakhit
\ No newline at end of file diff --git a/develop/reference/hooks/index.html b/develop/reference/hooks/index.html index 29034ea4..6185ed1e 100644 --- a/develop/reference/hooks/index.html +++ b/develop/reference/hooks/index.html @@ -1,4 +1,4 @@ - Hooks - ReactPy-Django

Hooks

Overview

Prefabricated hooks can be used within your components.py to help simplify development.

Note

Looking for standard React hooks?

This package only contains Django specific hooks. Standard hooks can be found within reactive-python/reactpy.


Use Query

This hook is used read data from the Django ORM.

The query function you provide must return either a Model or QuerySet.

 1
+ Hooks - ReactPy-Django       

Hooks

Overview

Prefabricated hooks can be used within your components.py to help simplify development.

Note

Looking for standard React hooks?

This package only contains Django specific hooks. Standard hooks can be found within reactive-python/reactpy.


Use Query

This hook is used to execute functions in the background and return the result, typically to read data the Django ORM.

The default postprocessor expects your query function to return a Django Model or QuerySet. The postprocessor needs to be changed to execute other types of queries. Query functions can be sync or async.

 1
  2
  3
  4
@@ -18,13 +18,15 @@
 18
 19
 20
-21
from example.models import TodoItem
+21
+22
from channels.db import database_sync_to_async
+from example.models import TodoItem
 from reactpy import component, html
 from reactpy_django.hooks import use_query
 
 
-def get_items():
-    return TodoItem.objects.all()
+async def get_items():
+    return await database_sync_to_async(TodoItem.objects.all)()
 
 
 @component
@@ -81,7 +83,7 @@
     )
 
     return str(query.data)
-
Why does get_items in the example return TodoItem.objects.all()?

This was a technical design decision to based on Apollo's useQuery hook, but ultimately helps avoid Django's SynchronousOnlyOperation exceptions.

The use_query hook ensures the provided Model or QuerySet executes all deferred/lazy queries safely prior to reaching your components.

How can I use QueryOptions to customize fetching behavior?

thread_sensitive

Whether to run your synchronous query function in thread-sensitive mode. Thread-sensitive mode is turned on by default due to Django ORM limitations. See Django's sync_to_async docs docs for more information.

This setting only applies to sync query functions, and will be ignored for async functions.

 1
+
How can I customize this hook's behavior?

This hook accepts a options: QueryOptions parameter that can be used to customize behavior.

Below are the settings that can be modified via these QueryOptions.


thread_sensitive

Whether to run your synchronous query function in thread-sensitive mode. Thread-sensitive mode is turned on by default due to Django ORM limitations. See Django's sync_to_async docs docs for more information.

This setting only applies to sync query functions, and will be ignored for async functions.

 1
  2
  3
  4
@@ -122,7 +124,7 @@
         return None
 
     return str(query.data)
-

postprocessor

By default, automatic recursive fetching of ManyToMany or ForeignKey fields is enabled within the default QueryOptions.postprocessor. This is needed to prevent SynchronousOnlyOperation exceptions when accessing these fields within your ReactPy components.

However, if you...

  1. Want to use this hook to defer IO intensive tasks to be computed in the background
  2. Want to to utilize use_query with a different ORM

... then you can either set a custom postprocessor, or disable all postprocessing behavior by modifying the QueryOptions.postprocessor parameter. In the example below, we will set the postprocessor to None to disable postprocessing behavior.

 1
+

postprocessor

By default, automatic recursive fetching of ManyToMany or ForeignKey fields is enabled within the django_query_postprocessor. This is needed to prevent SynchronousOnlyOperation exceptions when accessing these fields within your ReactPy components.

However, if you...

  1. Want to use this hook to defer IO intensive tasks to be computed in the background
  2. Want to to utilize use_query with a different ORM

... then you can either set a custom postprocessor, or disable all postprocessing behavior by modifying the QueryOptions.postprocessor parameter. In the example below, we will set the postprocessor to None to disable postprocessing behavior.

 1
  2
  3
  4
@@ -224,7 +226,7 @@
         return None
 
     return str(query.data)
-

postprocessor_kwargs

By default, automatic recursive fetching of ManyToMany or ForeignKey fields is enabled within the default QueryOptions.postprocessor. This is needed to prevent SynchronousOnlyOperation exceptions when accessing these fields within your ReactPy components.

However, if you have deep nested trees of relational data, this may not be a desirable behavior. In these scenarios, you may prefer to manually fetch these relational fields using a second use_query hook.

You can disable the prefetching behavior of the default postprocessor (located at reactpy_django.utils.django_query_postprocessor) via the QueryOptions.postprocessor_kwargs parameter.

 1
+

postprocessor_kwargs

By default, automatic recursive fetching of ManyToMany or ForeignKey fields is enabled within the django_query_postprocessor. This is needed to prevent SynchronousOnlyOperation exceptions when accessing these fields within your ReactPy components.

However, if you have deep nested trees of relational data, this may not be a desirable behavior. In these scenarios, you may prefer to manually fetch these relational fields using a second use_query hook.

You can disable the prefetching behavior of the default postprocessor (located at reactpy_django.utils.django_query_postprocessor) via the QueryOptions.postprocessor_kwargs parameter.

 1
  2
  3
  4
@@ -285,7 +287,7 @@
     # By disabling `many_to_many` and `many_to_one`, accessing these fields will now
     # generate a `SynchronousOnlyOperation` exception
     return f"{query.data.many_to_many_field} {query.data.foriegn_key_field_set}"
-

Note: In Django's ORM design, the field name to access foreign keys is postfixed with _set by default.

Can I define async query functions?

Async functions are supported by use_query. You can use them in the same way as a sync query function.

However, be mindful of Django async ORM restrictions.

 1
+

Note: In Django's ORM design, the field name to access foreign keys is postfixed with _set by default.

Can I make ORM calls without hooks?

Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a SynchronousOnlyOperation exception.

These SynchronousOnlyOperation exceptions may be removed in a future version of Django. However, it is best practice to always perform IO operations (such as ORM queries) via hooks to prevent performance issues.

Can I make a failed query try again?

Yes, a use_mutation can be re-performed by calling reset() on your use_mutation instance.

For example, take a look at reset_event below.

 1
  2
  3
  4
@@ -306,29 +308,58 @@
 19
 20
 21
-22
from channels.db import database_sync_to_async
-from example.models import TodoItem
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
from example.models import TodoItem
 from reactpy import component, html
-from reactpy_django.hooks import use_query
+from reactpy_django.hooks import use_mutation
 
 
-async def get_items():
-    return await database_sync_to_async(TodoItem.objects.all)()
+def add_item(text: str):
+    TodoItem(text=text).save()
 
 
 @component
 def todo_list():
-    item_query = use_query(get_items)
+    item_mutation = use_mutation(add_item)
 
-    if item_query.loading:
-        rendered_items = html.h2("Loading...")
-    elif item_query.error or not item_query.data:
-        rendered_items = html.h2("Error when loading!")
+    def reset_event(event):
+        item_mutation.reset()
+
+    def submit_event(event):
+        if event["key"] == "Enter":
+            item_mutation.execute(text=event["target"]["value"])
+
+    if item_mutation.loading:
+        mutation_status = html.h2("Adding...")
+    elif item_mutation.error:
+        mutation_status = html.button({"onClick": reset_event}, "Error: Try again!")
     else:
-        rendered_items = html.ul([html.li(item, key=item) for item in item_query.data])
+        mutation_status = html.h2("Mutation done.")
 
-    return html.div("Rendered items: ", rendered_items)
-
Can I make ORM calls without hooks?

Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a SynchronousOnlyOperation exception.

These SynchronousOnlyOperation exceptions may be resolved in a future version of Django containing an asynchronous ORM. However, it is best practice to always perform ORM calls in the background via hooks.

Use Mutation

This hook is used to create, update, or delete Django ORM objects.

The mutation function you provide should have no return value.

 1
+    return html.div(
+        html.label("Add an item:"),
+        html.input({"type": "text", "onKeyDown": submit_event}),
+        mutation_status,
+    )
+
1
+2
+3
+4
+5
from django.db.models import CharField, Model
+
+
+class TodoItem(Model):
+    text: CharField = CharField(max_length=255)
+
Why does the example query function return TodoItem.objects.all()?

This design decision was based on Apollo's useQuery hook, but ultimately helps avoid Django's SynchronousOnlyOperation exceptions.

With the Model or QuerySet your function returns, this hook uses the default postprocessor to ensure that all deferred or lazy fields are executed.

Use Mutation

This hook is used to modify data in the background, typically to create/update/delete data from the Django ORM.

Mutation functions can return False to prevent executing your refetch function. All other returns are ignored. Mutation functions can be sync or async.

 1
  2
  3
  4
@@ -361,8 +392,8 @@
 from reactpy_django.hooks import use_mutation
 
 
-def add_item(text: str):
-    TodoItem(text=text).save()
+async def add_item(text: str):
+    await TodoItem(text=text).asave()
 
 
 @component
@@ -394,7 +425,7 @@
 
 class TodoItem(Model):
     text: CharField = CharField(max_length=255)
-
See Interface

Parameters

Name Type Description Default
mutate Callable[_Params, bool | None] A callable that performs Django ORM create, update, or delete functionality. If this function returns False, then your refetch function will not be used. N/A
refetch Callable[..., Any] | Sequence[Callable[..., Any]] | None A query function (used by the use_query hook) or a sequence of query functions that will be called if the mutation succeeds. This is useful for refetching data after a mutation has been performed. None

Returns

Type Description
Mutation[_Params] An object containing loading/error states, a reset callable that will set loading/error states to defaults, and a execute callable that will run the query.
How can I provide arguments to my mutation function?

*args and **kwargs can be provided to your mutation function via #!python mutation.execute` parameters.

 1
+
See Interface

Parameters

Name Type Description Default
mutate Callable[_Params, bool | None] A callable that performs Django ORM create, update, or delete functionality. If this function returns False, then your refetch function will not be used. N/A
refetch Callable[..., Any] | Sequence[Callable[..., Any]] | None A query function (the function you provide to your use_query hook) or a sequence of query functions that need a refetch if the mutation succeeds. This is useful for refreshing data after a mutation has been performed. None

Returns

Type Description
Mutation[_Params] An object containing loading/error states, a reset callable that will set loading/error states to defaults, and a execute callable that will run the query.
How can I provide arguments to my mutation function?

*args and **kwargs can be provided to your mutation function via #!python mutation.execute` parameters.

 1
  2
  3
  4
@@ -423,7 +454,7 @@
     mutation.execute(123, other_value=True)
 
     ...
-
Can use_mutation trigger a refetch of use_query?

Yes, use_mutation can queue a refetch of a use_query via the refetch=... argument.

The example below is a merge of the use_query and use_mutation examples above with the addition of a use_mutation(refetch=...) argument.

Please note that any use_query hooks that use get_items will be refetched upon a successful mutation.

 1
+
How can I customize this hook's behavior?

This hook accepts a options: MutationOptions parameter that can be used to customize behavior.

Below are the settings that can be modified via these MutationOptions.


thread_sensitive

Whether to run your synchronous mutation function in thread-sensitive mode. Thread-sensitive mode is turned on by default due to Django ORM limitations. See Django's sync_to_async docs docs for more information.

This setting only applies to sync query functions, and will be ignored for async functions.

 1
  2
  3
  4
@@ -454,25 +485,72 @@
 29
 30
 31
-32
-33
-34
-35
-36
-37
-38
-39
-40
-41
-42
-43
-44
from example.models import TodoItem
-from reactpy import component, html
-from reactpy_django.hooks import use_mutation, use_query
+32
from reactpy import component, html
+from reactpy_django.hooks import use_mutation
+from reactpy_django.types import MutationOptions
 
 
-def get_items():
-    return TodoItem.objects.all()
+def execute_thread_safe_mutation():
+    """This is an example mutation function that does some thread-safe operation."""
+    pass
+
+
+@component
+def my_component():
+    item_mutation = use_mutation(
+        MutationOptions(thread_sensitive=False),
+        execute_thread_safe_mutation,
+    )
+
+    def submit_event(event):
+        if event["key"] == "Enter":
+            item_mutation.execute(text=event["target"]["value"])
+
+    if item_mutation.loading or item_mutation.error:
+        mutation_status = html.h2("Doing something...")
+    elif item_mutation.error:
+        mutation_status = html.h2("Error!")
+    else:
+        mutation_status = html.h2("Done.")
+
+    return html.div(
+        html.input({"type": "text", "onKeyDown": submit_event}),
+        mutation_status,
+    )
+
Can I make ORM calls without hooks?

Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a SynchronousOnlyOperation exception.

These SynchronousOnlyOperation exceptions may be removed in a future version of Django. However, it is best practice to always perform IO operations (such as ORM queries) via hooks to prevent performance issues.

Can I make a failed mutation try again?

Yes, a use_mutation can be re-performed by calling reset() on your use_mutation instance.

For example, take a look at reset_event below.

 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
from example.models import TodoItem
+from reactpy import component, html
+from reactpy_django.hooks import use_mutation
 
 
 def add_item(text: str):
@@ -481,26 +559,19 @@
 
 @component
 def todo_list():
-    item_query = use_query(get_items)
-    item_mutation = use_mutation(add_item, refetch=get_items)
+    item_mutation = use_mutation(add_item)
+
+    def reset_event(event):
+        item_mutation.reset()
 
     def submit_event(event):
         if event["key"] == "Enter":
             item_mutation.execute(text=event["target"]["value"])
 
-    # Handle all possible query states
-    if item_query.loading:
-        rendered_items = html.h2("Loading...")
-    elif item_query.error or not item_query.data:
-        rendered_items = html.h2("Error when loading!")
-    else:
-        rendered_items = html.ul(html.li(item, key=item) for item in item_query.data)
-
-    # Handle all possible mutation states
     if item_mutation.loading:
         mutation_status = html.h2("Adding...")
     elif item_mutation.error:
-        mutation_status = html.h2("Error when adding!")
+        mutation_status = html.button({"onClick": reset_event}, "Error: Try again!")
     else:
         mutation_status = html.h2("Mutation done.")
 
@@ -508,7 +579,6 @@
         html.label("Add an item:"),
         html.input({"type": "text", "onKeyDown": submit_event}),
         mutation_status,
-        rendered_items,
     )
 
1
 2
@@ -519,7 +589,7 @@
 
 class TodoItem(Model):
     text: CharField = CharField(max_length=255)
-
Can I make a failed use_mutation try again?

Yes, a use_mutation can be re-performed by calling reset() on your use_mutation instance.

For example, take a look at reset_event below.

 1
+
Can use_mutation trigger a refetch of use_query?

Yes, use_mutation can queue a refetch of a use_query via the refetch=... argument.

The example below is a merge of the use_query and use_mutation examples above with the addition of a use_mutation(refetch=...) argument.

Please note that refetch will cause all use_query hooks that use get_items in the current component tree will be refetched.

 1
  2
  3
  4
@@ -550,9 +620,25 @@
 29
 30
 31
-32
from example.models import TodoItem
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
from example.models import TodoItem
 from reactpy import component, html
-from reactpy_django.hooks import use_mutation
+from reactpy_django.hooks import use_mutation, use_query
+
+
+def get_items():
+    return TodoItem.objects.all()
 
 
 def add_item(text: str):
@@ -561,19 +647,26 @@
 
 @component
 def todo_list():
-    item_mutation = use_mutation(add_item)
-
-    def reset_event(event):
-        item_mutation.reset()
+    item_query = use_query(get_items)
+    item_mutation = use_mutation(add_item, refetch=get_items)
 
     def submit_event(event):
         if event["key"] == "Enter":
             item_mutation.execute(text=event["target"]["value"])
 
+    # Handle all possible query states
+    if item_query.loading:
+        rendered_items = html.h2("Loading...")
+    elif item_query.error or not item_query.data:
+        rendered_items = html.h2("Error when loading!")
+    else:
+        rendered_items = html.ul(html.li(item, key=item) for item in item_query.data)
+
+    # Handle all possible mutation states
     if item_mutation.loading:
         mutation_status = html.h2("Adding...")
     elif item_mutation.error:
-        mutation_status = html.button({"onClick": reset_event}, "Error: Try again!")
+        mutation_status = html.h2("Error when adding!")
     else:
         mutation_status = html.h2("Mutation done.")
 
@@ -581,6 +674,7 @@
         html.label("Add an item:"),
         html.input({"type": "text", "onKeyDown": submit_event}),
         mutation_status,
+        rendered_items,
     )
 
1
 2
@@ -591,7 +685,7 @@
 
 class TodoItem(Model):
     text: CharField = CharField(max_length=255)
-
Can I make ORM calls without hooks?

Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a SynchronousOnlyOperation exception.

These SynchronousOnlyOperation exceptions may be resolved in a future version of Django containing an asynchronous ORM. However, it is best practice to always perform ORM calls in the background via hooks.

Use Connection

This hook is used to fetch the Django Channels WebSocket.

1
+

Use Connection

This hook is used to fetch the active connection, which is either a Django WebSocket or a HTTP Request.

1
 2
 3
 4
@@ -606,7 +700,7 @@
 def my_component():
     my_connection = use_connection()
     return html.div(str(my_connection))
-
See Interface

Parameters

None

Returns

Type Description
Connection The component's WebSocket.

Use Scope

This is a shortcut that returns the WebSocket's scope.

1
+
See Interface

Parameters

None

Returns

Type Description
Connection The component's WebSocket or HttpRequest.

Use Scope

This is a shortcut that returns the WebSocket or HTTP scope.

1
 2
 3
 4
@@ -621,7 +715,7 @@
 def my_component():
     my_scope = use_scope()
     return html.div(str(my_scope))
-
See Interface

Parameters

None

Returns

Type Description
MutableMapping[str, Any] The WebSocket's scope.

Use Location

This is a shortcut that returns the WebSocket's path.

You can expect this hook to provide strings such as /reactpy/my_path.

1
+
See Interface

Parameters

None

Returns

Type Description
MutableMapping[str, Any] The WebSocket's scope.

Use Location

This is a shortcut that returns the client's URL path.

You can expect this hook to provide strings such as /reactpy/my_path.

1
 2
 3
 4
@@ -636,7 +730,7 @@
 def my_component():
     my_location = use_location()
     return html.div(str(my_location))
-
See Interface

Parameters

None

Returns

Type Description
Location An object containing the current URL's pathname and search query.
This hook's behavior will be changed in a future update

This hook will be updated to return the browser's currently active HTTP path. This change will come in alongside ReactPy URL routing support.

Check out reactive-python/reactpy-django#147 for more information.

Use Origin

This is a shortcut that returns the WebSocket's origin.

You can expect this hook to provide strings such as http://example.com.

1
+
See Interface

Parameters

None

Returns

Type Description
Location An object containing the current URL's pathname and search query.
This hook's behavior will be changed in a future update

This hook will be updated to return the browser's currently active HTTP path. This change will come in alongside ReactPy URL routing support.

Check out reactive-python/reactpy-django#147 for more information.

Use Origin

This is a shortcut that returns the client's origin.

You can expect this hook to provide strings such as http://example.com.

1
 2
 3
 4
@@ -651,4 +745,4 @@
 def my_component():
     my_origin = use_origin()
     return html.div(my_origin or "No origin")
-
See Interface

Parameters

None

Returns

Type Description
str | None A string containing the browser's current origin, obtained from WebSocket headers (if available).

Last update: September 16, 2023
Authors: Mark Bakhit
\ No newline at end of file +
See Interface

Parameters

None

Returns

Type Description
str | None A string containing the browser's current origin, obtained from WebSocket or HTTP headers (if available).

Last update: September 21, 2023
Authors: Mark Bakhit
\ No newline at end of file diff --git a/develop/reference/settings/index.html b/develop/reference/settings/index.html index 39456f5b..2daab02e 100644 --- a/develop/reference/settings/index.html +++ b/develop/reference/settings/index.html @@ -1,5 +1,5 @@ - Settings - ReactPy-Django

Settings

Overview

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

The default configuration of ReactPy is suitable for the vast majority of use cases.

You should only consider changing settings when the necessity arises.


General Settings


REACTPY_URL_PREFIX

Default: "reactpy/"

Example Value(s): "rp/", "render/reactpy/"

The prefix used for all ReactPy WebSocket and HTTP URLs.


REACTPY_DEFAULT_QUERY_POSTPROCESSOR

Default: "reactpy_django.utils.django_query_postprocessor"

Example Value(s): "example_project.postprocessor", None

Dotted path to the default reactpy_django.hooks.use_query postprocessor function.

Postprocessor functions can be async or sync. Here is an example of a sync postprocessor function:

def postprocessor(data):
+ Settings - ReactPy-Django       

Settings

Overview

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

The default configuration of ReactPy is suitable for the vast majority of use cases.

You should only consider changing settings when the necessity arises.


General Settings


REACTPY_URL_PREFIX

Default: "reactpy/"

Example Value(s): "rp/", "render/reactpy/"

The prefix used for all ReactPy WebSocket and HTTP URLs.


REACTPY_DEFAULT_QUERY_POSTPROCESSOR

Default: "reactpy_django.utils.django_query_postprocessor"

Example Value(s): "example_project.postprocessor", None

Dotted path to the global default reactpy_django.hooks.use_query postprocessor function.

Postprocessor functions can be async or sync. Here is an example of a sync postprocessor function:

def postprocessor(data):
     del data["foo"]
     return data
 

Set REACTPY_DEFAULT_QUERY_POSTPROCESSOR to None to disable the default postprocessor.


REACTPY_AUTH_BACKEND

Default: "django.contrib.auth.backends.ModelBackend"

Example Value(s): "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 AuthMiddlewareStack and...
  2. You are using Django's AUTHENTICATION_BACKENDS setting and...
  3. Your Django user model does not define a backend attribute.

Performance Settings


REACTPY_DATABASE

Default: "default"

Example Value(s): "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:

DATABASE_ROUTERS = ["reactpy_django.database.Router", ...]
-

REACTPY_CACHE

Default: "default"

Example Value(s): "my-reactpy-cache"

Cache used by ReactPy, typically for file operations.

We recommend configuring redis, python-diskcache, or LocMemCache.


REACTPY_BACKHAUL_THREAD

Default: False

Example Value(s): 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 and uvicorn.


REACTPY_DEFAULT_HOSTS

Default: None

Example Value(s): ["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 host argument in your template tag to manually override this default.


REACTPY_PRERENDER

Default: False

Example Value(s): 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 connection related hooks use HTTP.
  3. 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 prerender argument in your template tag to manually override this default.


Stability Settings


REACTPY_RECONNECT_INTERVAL

Default: 750

Example Value(s): 100, 2500, 6000

Milliseconds between client reconnection attempts.


REACTPY_RECONNECT_BACKOFF_MULTIPLIER

Default: 1.25

Example Value(s): 1, 1.5, 3

On each reconnection attempt, the 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 1.


REACTPY_RECONNECT_MAX_INTERVAL

Default: 60000

Example Value(s): 10000, 25000, 900000

Maximum milliseconds between client reconnection attempts.

This allows setting an upper bound on how high REACTPY_RECONNECT_BACKOFF_MULTIPLIER can increase the time between reconnection attempts.


REACTPY_RECONNECT_MAX_RETRIES

Default: 150

Example Value(s): 0, 5, 300

Maximum number of reconnection attempts before the client gives up.


REACTPY_SESSION_MAX_AGE

Default: 259200

Example Value(s): 0, 60, 96000

Maximum seconds to store ReactPy component sessions.

ReactPy sessions include data such as *args and **kwargs passed into your {% component %} template tag.

Use 0 to not store any session data.


Last update: September 16, 2023
Authors: Mark Bakhit
\ No newline at end of file +

REACTPY_CACHE

Default: "default"

Example Value(s): "my-reactpy-cache"

Cache used by ReactPy, typically for file operations.

We recommend configuring redis, python-diskcache, or LocMemCache.


REACTPY_BACKHAUL_THREAD

Default: False

Example Value(s): 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 and uvicorn.


REACTPY_DEFAULT_HOSTS

Default: None

Example Value(s): ["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 host argument in your template tag to manually override this default.


REACTPY_PRERENDER

Default: False

Example Value(s): 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 connection related hooks use HTTP.
  3. 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 prerender argument in your template tag to manually override this default.


Stability Settings


REACTPY_RECONNECT_INTERVAL

Default: 750

Example Value(s): 100, 2500, 6000

Milliseconds between client reconnection attempts.


REACTPY_RECONNECT_BACKOFF_MULTIPLIER

Default: 1.25

Example Value(s): 1, 1.5, 3

On each reconnection attempt, the 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 1.


REACTPY_RECONNECT_MAX_INTERVAL

Default: 60000

Example Value(s): 10000, 25000, 900000

Maximum milliseconds between client reconnection attempts.

This allows setting an upper bound on how high REACTPY_RECONNECT_BACKOFF_MULTIPLIER can increase the time between reconnection attempts.


REACTPY_RECONNECT_MAX_RETRIES

Default: 150

Example Value(s): 0, 5, 300

Maximum number of reconnection attempts before the client gives up.


REACTPY_SESSION_MAX_AGE

Default: 259200

Example Value(s): 0, 60, 96000

Maximum seconds to store ReactPy component sessions.

ReactPy sessions include data such as *args and **kwargs passed into your {% component %} template tag.

Use 0 to not store any session data.


Last update: September 21, 2023
Authors: Mark Bakhit
\ No newline at end of file diff --git a/develop/reference/template-tag/index.html b/develop/reference/template-tag/index.html index 2ae3416f..f3c74dd2 100644 --- a/develop/reference/template-tag/index.html +++ b/develop/reference/template-tag/index.html @@ -1,4 +1,4 @@ - Template Tag - ReactPy-Django

Template Tag

Overview

Django template tags can be used within your HTML templates to provide ReactPy features.


Component

This template tag can be used to insert any number of ReactPy components onto your page.

1
+ Template Tag - ReactPy-Django       

Template Tag

Overview

Django template tags can be used within your HTML templates to provide ReactPy features.


Component

This template tag can be used to insert any number of ReactPy components onto your page.

1
 2
 3
 4
@@ -11,7 +11,7 @@
     {% component "example_project.my_app.components.hello_world" recipient="World" %}
   </body>
 </html>
-
See Interface

Parameters

Name Type Description Default
dotted_path str The dotted path to the component to render. N/A
*args Any The positional arguments to provide to the component. N/A
class str | None The HTML class to apply to the top-level component div. None
key Any Force the component's root node to use a specific key value. Using key within a template tag is effectively useless. None
host 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
None
prerender str If "True", the component will pre-rendered, which enables SEO compatibility and reduces perceived latency. "False"
**kwargs Any The keyword arguments to provide to the component. N/A

Returns

Type Description
Component A ReactPy component.
Do not use context variables for the component path

The ReactPy component finder (reactpy_django.utils.RootComponentFinder) requires that your component path is a string.

Do not use Django template/context variables for the component path. Failure to follow this warning can result in unexpected behavior, such as components that will not render.

For example, do not do the following:

1
+
See Interface

Parameters

Name Type Description Default
dotted_path str The dotted path to the component to render. N/A
*args Any The positional arguments to provide to the component. N/A
class str | None The HTML class to apply to the top-level component div. None
key Any Force the component's root node to use a specific key value. Using key within a template tag is effectively useless. None
host 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
None
prerender str If "True", the component will pre-rendered, which enables SEO compatibility and reduces perceived latency. "False"
**kwargs Any The keyword arguments to provide to the component. N/A

Returns

Type Description
Component A ReactPy component.
Do not use context variables for the component path

The ReactPy component finder requires that your component path is a string.

Do not use Django template/context variables for the component path. Failure to follow this warning can result in unexpected behavior, such as components that will not render.

For example, do not do the following:

1
 2
 3
 4
@@ -36,7 +36,7 @@
 3
...
 {% component "example_project.my_app.components.do_something" host="127.0.0.1:8001" %}
 ...
-

This configuration most commonly involves you deploying multiple instances of your project. But, you can also create dedicated Django project(s) that only render specific ReactPy components if you wish.

Here's a couple of things to keep in mind:

  1. If your host address are completely separate ( origin1.com != origin2.com ) you will need to configure CORS headers on your main application during deployment.
  2. You will not need to register ReactPy HTTP or WebSocket paths on any applications that do not perform any component rendering.
  3. Your component will only be able to access your template tag's *args/**kwargs if your applications share a common database.
Can I use multiple components on one page?

You can add as many components to a webpage as needed by using the template tag multiple times. Retrofitting legacy sites to use ReactPy will typically involve many components on one page.

1
+

This configuration most commonly involves you deploying multiple instances of your project. But, you can also create dedicated Django project(s) that only render specific ReactPy components if you wish.

Here's a couple of things to keep in mind:

  1. If your host address are completely separate ( origin1.com != origin2.com ) you will need to configure CORS headers on your main application during deployment.
  2. You will not need to register ReactPy WebSocket or HTTP paths on any applications that do not perform any component rendering.
  3. Your component will only be able to access your template tag's *args/**kwargs if your applications share a common database.
Can I use multiple components on one page?

You can add as many components to a webpage as needed by using the template tag multiple times. Retrofitting legacy sites to use ReactPy will typically involve many components on one page.

1
 2
 3
 4
@@ -65,4 +65,4 @@
 @component
 def frog_greeter(number, name, species=""):
     return f"Hello #{number}, {name} the {species}!"
-

Last update: September 16, 2023
Authors: Mark Bakhit
\ No newline at end of file +

Last update: September 21, 2023
Authors: Mark Bakhit
\ No newline at end of file diff --git a/develop/reference/utils/index.html b/develop/reference/utils/index.html index a99fd0ef..e1d11d8c 100644 --- a/develop/reference/utils/index.html +++ b/develop/reference/utils/index.html @@ -1,4 +1,4 @@ - Utilities - ReactPy-Django

Utilities

Overview

Utility functions provide various miscellaneous functionality. These are typically not used, but are available for advanced use cases.


Django Query Postprocessor

This is the default postprocessor for the use_query hook.

This postprocessor is designed to avoid Django's SynchronousOnlyException by recursively fetching all fields within a Model or QuerySet to prevent lazy execution.

 1
+ Utilities - ReactPy-Django       

Utilities

Overview

Utility functions provide various miscellaneous functionality. These are typically not used, but are available for advanced use cases.


Django Query Postprocessor

This is the default postprocessor for the use_query hook.

This postprocessor is designed to avoid Django's SynchronousOnlyException by recursively fetching all fields within a Model or QuerySet to prevent lazy execution.

 1
  2
  3
  4
@@ -67,4 +67,4 @@
     def ready(self):
         # Add components to the ReactPy component registry when Django is ready
         register_component("example_project.my_app.components.hello_world")
-
Only use this within MyAppConfig.ready()

You should always call register_component within a Django MyAppConfig.ready() method. This ensures you will retain multiprocessing compatibility, such as with ASGI web server workers.

Do I need to use this?

You typically will not need to use this function.

For security reasons, ReactPy does not allow non-registered components to be root components. However, all components contained within Django templates are automatically considered root components.

This is typically only needed when you have a dedicated Django application as a rendering server that doesn't have templates, such as when modifying the template tag host argument. On this dedicated rendering server, you would need to manually register your components.


Last update: September 16, 2023
Authors: Mark Bakhit
\ No newline at end of file +
Only use this within MyAppConfig.ready()

You should always call register_component within a Django MyAppConfig.ready() method. This ensures you will retain multiprocessing compatibility, such as with ASGI web server workers.

Do I need to use this?

You typically will not need to use this function.

For security reasons, ReactPy requires all root components to be registered. However, all components contained within Django templates are automatically registered.

This function is needed when you have configured your host to a dedicated Django rendering application that doesn't have templates.


Last update: September 21, 2023
Authors: Mark Bakhit
\ No newline at end of file diff --git a/develop/search/search_index.json b/develop/search/search_index.json index e1579b2a..ee95f7be 100644 --- a/develop/search/search_index.json +++ b/develop/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"about/changelog/","title":"Changelog","text":"

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

"},{"location":"about/changelog/#unreleased","title":"Unreleased","text":""},{"location":"about/changelog/#added","title":"Added","text":"
  • ReactPy components can now use SEO compatible rendering!
    • settings.py:REACTPY_PRERENDER can be set to True to enable this behavior by default
    • Or, you can enable it on individual components via the template tag: {% component \"...\" prerender=\"True\" %}
"},{"location":"about/changelog/#changed","title":"Changed","text":"
  • Renamed undocumented utility function reactpy_django.utils.ComponentPreloader to reactpy_django.utils.RootComponentFinder.
"},{"location":"about/changelog/#351-2023-09-07","title":"3.5.1 - 2023-09-07","text":""},{"location":"about/changelog/#added_1","title":"Added","text":"
  • Warning W018 (Suspicious position of 'reactpy_django' in INSTALLED_APPS) has been added.
"},{"location":"about/changelog/#changed_1","title":"Changed","text":"
  • The default postprocessor can now disabled by setting REACTPY_DEFAULT_QUERY_POSTPROCESSOR to None.
  • Massive overhaul of docs styling.
"},{"location":"about/changelog/#350-2023-08-26","title":"3.5.0 - 2023-08-26","text":""},{"location":"about/changelog/#added_2","title":"Added","text":"
  • More customization for reconnection behavior through new settings!
    • REACTPY_RECONNECT_INTERVAL
    • REACTPY_RECONNECT_MAX_INTERVAL
    • REACTPY_RECONNECT_MAX_RETRIES
    • REACTPY_RECONNECT_BACKOFF_MULTIPLIER
  • ReactPy-Django docs are now version controlled via mike!
"},{"location":"about/changelog/#changed_2","title":"Changed","text":"
  • Bumped the minimum ReactPy version to 1.0.2.
  • Prettier WebSocket URLs for components that do not have sessions.
  • Template tag will now only validate args/kwargs if settings.py:DEBUG is enabled.
  • Bumped the minimum @reactpy/client version to 0.3.1
  • Bumped the minimum Django version to 4.2.
  • Use TypeScript instead of JavaScript for this repository.
    • Note: ReactPy-Django will continue bumping minimum Django requirements to versions that increase async support. This \"latest-only\" trend will continue until Django has all async features that ReactPy benefits from. After this point, ReactPy-Django will begin supporting all maintained Django versions.
"},{"location":"about/changelog/#removed","title":"Removed","text":"
  • settings.py:REACTPY_RECONNECT_MAX is removed. See the docs for the new REACTPY_RECONNECT_* settings.
"},{"location":"about/changelog/#340-2023-08-18","title":"3.4.0 - 2023-08-18","text":""},{"location":"about/changelog/#added_3","title":"Added","text":"
  • Distributed Computing: ReactPy components can now optionally be rendered by a completely separate server!
    • REACTPY_DEFAULT_HOSTS setting can round-robin a list of ReactPy rendering hosts.
    • host argument has been added to the component template tag to force components to render on a specific host.
  • reactpy_django.utils.register_component function can manually register root components.
    • Useful if you have dedicated ReactPy rendering application(s) that do not use HTML templates.
"},{"location":"about/changelog/#changed_3","title":"Changed","text":"
  • ReactPy will now provide a warning if your HTTP URLs are not on the same prefix as your WebSockets.
  • Cleaner logging output for auto-detected ReactPy root components.
"},{"location":"about/changelog/#deprecated","title":"Deprecated","text":"
  • reactpy_django.REACTPY_WEBSOCKET_PATH is deprecated. The identical replacement is REACTPY_WEBSOCKET_ROUTE.
  • settings.py:REACTPY_WEBSOCKET_URL is deprecated. The similar replacement is REACTPY_URL_PREFIX.
"},{"location":"about/changelog/#removed_1","title":"Removed","text":"
  • Warning W007 (REACTPY_WEBSOCKET_URL doesn't end with a slash) has been removed. ReactPy now automatically handles slashes.
  • Warning W008 (REACTPY_WEBSOCKET_URL doesn't start with an alphanumeric character) has been removed. ReactPy now automatically handles this scenario.
  • Error E009 (channels is not in settings.py:INSTALLED_APPS) has been removed. Newer versions of channels do not require installation via INSTALLED_APPS to receive an ASGI web server.
"},{"location":"about/changelog/#332-2023-08-13","title":"3.3.2 - 2023-08-13","text":""},{"location":"about/changelog/#added_4","title":"Added","text":"
  • ReactPy WebSocket will now decode messages via orjson resulting in an ~6% overall performance improvement.
  • Built-in asyncio event loops are now patched via nest_asyncio, resulting in an ~10% overall performance improvement. This has no performance impact if you are running your web server with uvloop.
"},{"location":"about/changelog/#fixed","title":"Fixed","text":"
  • Fix bug where REACTPY_WEBSOCKET_URL always generates a warning if unset.
  • Fixed bug on Windows where assert f is self._write_fut would be raised by uvicorn when REACTPY_BACKHAUL_THREAD = True.
  • Fixed bug on Windows where rendering behavior would be jittery with daphne when REACTPY_BACKHAUL_THREAD = True.
"},{"location":"about/changelog/#331-2023-08-08","title":"3.3.1 - 2023-08-08","text":""},{"location":"about/changelog/#added_5","title":"Added","text":"
  • Additional system checks for ReactPy misconfigurations.
"},{"location":"about/changelog/#changed_4","title":"Changed","text":"
  • REACTPY_BACKHAUL_THREAD now defaults to False.
"},{"location":"about/changelog/#330-2023-08-05","title":"3.3.0 - 2023-08-05","text":""},{"location":"about/changelog/#added_6","title":"Added","text":"
  • Added system checks for a variety of common ReactPy misconfigurations.
  • REACTPY_BACKHAUL_THREAD setting to enable/disable threading behavior.
"},{"location":"about/changelog/#changed_5","title":"Changed","text":"
  • If using settings.py:REACTPY_DATABASE, reactpy_django.database.Router must now be registered in settings.py:DATABASE_ROUTERS.
  • By default, ReactPy will now use a backhaul thread to increase performance.
  • Minimum Python version required is now 3.9
  • A thread-safe cache is no longer required.
"},{"location":"about/changelog/#321-2023-06-29","title":"3.2.1 - 2023-06-29","text":""},{"location":"about/changelog/#added_7","title":"Added","text":"
  • Template tag exception details are now rendered on the webpage when settings.py:DEBUG is enabled.
"},{"location":"about/changelog/#fixed_1","title":"Fixed","text":"
  • Prevent exceptions within the component template tag from causing the whole template to fail to render.
"},{"location":"about/changelog/#320-2023-06-08","title":"3.2.0 - 2023-06-08","text":""},{"location":"about/changelog/#added_8","title":"Added","text":"
  • Added warning if poor system/cache/database performance is detected while in DEBUG mode.
  • Added REACTPY_AUTH_BACKEND setting to allow for custom authentication backends.
"},{"location":"about/changelog/#changed_6","title":"Changed","text":"
  • Using SessionMiddlewareStack is now optional.
  • Using AuthMiddlewareStack is now optional.
"},{"location":"about/changelog/#310-2023-05-06","title":"3.1.0 - 2023-05-06","text":""},{"location":"about/changelog/#added_9","title":"Added","text":"
  • use_query now supports async functions.
  • use_mutation now supports async functions.
  • reactpy_django.types.QueryOptions.thread_sensitive option to customize how sync queries are executed.
  • reactpy_django.hooks.use_mutation now accepts reactpy_django.types.MutationOptions option to customize how mutations are executed.
"},{"location":"about/changelog/#changed_7","title":"Changed","text":"
  • The mutate argument on reactpy_django.hooks.use_mutation has been renamed to mutation.
"},{"location":"about/changelog/#fixed_2","title":"Fixed","text":"
  • Fix bug where ReactPy utilizes Django's default cache timeout, which can prematurely expire the component cache.
"},{"location":"about/changelog/#301-2023-04-06","title":"3.0.1 - 2023-04-06","text":""},{"location":"about/changelog/#changed_8","title":"Changed","text":"
  • django-reactpy database entries are no longer cleaned during Django application startup. Instead, it will occur on webpage loads if REACTPY_RECONNECT_MAX seconds has elapsed since the last cleaning.
"},{"location":"about/changelog/#300-reactpy-2023-03-30","title":"3.0.0-reactpy - 2023-03-30","text":""},{"location":"about/changelog/#changed_9","title":"Changed","text":"
  • django-idom has been renamed to reactpy-django! Please note that all references to the word idom in your code should be changed to reactpy. See the docs for more details.
"},{"location":"about/changelog/#300-2023-03-08","title":"3.0.0 - 2023-03-08","text":"Note

This is Django-IDOM's biggest update yet!

To upgrade from previous version you will need to...

  1. Install django-idom >= 3.0.0
  2. Run idom rewrite-keys <DIR> and idom rewrite-camel-case-props <DIR> to update your idom.html.* calls to the new syntax
  3. Run python manage.py migrate to create the new Django-IDOM database entries
"},{"location":"about/changelog/#added_10","title":"Added","text":"
  • The idom client will automatically configure itself to debug mode depending on settings.py:DEBUG.
  • use_connection hook for returning the browser's active Connection.
  • IDOM_CACHE is now configurable within settings.py to whatever cache name you wish.
"},{"location":"about/changelog/#changed_10","title":"Changed","text":"
  • It is now mandatory to run manage.py migrate after installing IDOM.
  • Bumped the minimum IDOM version to 1.0.0. Due to IDOM 1.0.0, idom.html.*...
    • HTML properties can now be snake_case. For example className now becomes class_name.
    • key=... is now declared within the props dict (rather than as a kwarg).
  • The component template tag now supports both positional and keyword arguments.
  • The component template tag now supports non-serializable arguments.
  • IDOM_WS_MAX_RECONNECT_TIMEOUT setting has been renamed to IDOM_RECONNECT_MAX.
"},{"location":"about/changelog/#removed_2","title":"Removed","text":"
  • django_idom.hooks.use_websocket has been removed. The similar replacement is django_idom.hooks.use_connection.
  • django_idom.types.IdomWebsocket has been removed. The similar replacement is django_idom.types.Connection.
  • settings.py:CACHE['idom'] is no longer used by default. The name of the cache back-end must now be specified with the IDOM_CACHE setting.
"},{"location":"about/changelog/#fixed_3","title":"Fixed","text":"
  • view_to_component will now retain the contents of a <head> tag when rendering.
  • React client is now set to production rather than development.
  • use_query will now utilize field.related_name when postprocessing many-to-one relationships.
"},{"location":"about/changelog/#security","title":"Security","text":"
  • Fixed a potential method of component template tag argument spoofing.
  • Exception information will no longer be displayed on the page, based on the value of settings.py:DEBUG.
"},{"location":"about/changelog/#221-2023-01-09","title":"2.2.1 - 2023-01-09","text":""},{"location":"about/changelog/#fixed_4","title":"Fixed","text":"
  • Fixed bug where use_query would not recursively fetch many-to-one relationships.
  • IDOM preloader will now print out the exception stack when failing to import a module.
"},{"location":"about/changelog/#220-2022-12-28","title":"2.2.0 - 2022-12-28","text":""},{"location":"about/changelog/#added_11","title":"Added","text":"
  • Add options: QueryOptions parameter to use_query to allow for configuration of this hook.
"},{"location":"about/changelog/#changed_11","title":"Changed","text":"
  • By default, use_query will recursively prefetch all many-to-many or many-to-one relationships to prevent SynchronousOnlyOperation exceptions.
"},{"location":"about/changelog/#removed_3","title":"Removed","text":"
  • django_idom.hooks._fetch_lazy_fields has been deleted. The equivalent replacement is django_idom.utils.django_query_postprocessor.
"},{"location":"about/changelog/#210-2022-11-01","title":"2.1.0 - 2022-11-01","text":""},{"location":"about/changelog/#changed_12","title":"Changed","text":"
  • Minimum channels version is now 4.0.0.
"},{"location":"about/changelog/#fixed_5","title":"Fixed","text":"
  • Change type hint on view_to_component callable to have request argument be optional.
  • Change type hint on view_to_component to represent it as a decorator with parenthesis (such as @view_to_component(compatibility=True))
"},{"location":"about/changelog/#security_1","title":"Security","text":"
  • Add note to docs about potential information exposure via view_to_component when using compatibility=True.
"},{"location":"about/changelog/#201-2022-10-18","title":"2.0.1 - 2022-10-18","text":""},{"location":"about/changelog/#fixed_6","title":"Fixed","text":"
  • Ability to use key=... parameter on all prefabricated components.
"},{"location":"about/changelog/#200-2022-10-17","title":"2.0.0 - 2022-10-17","text":""},{"location":"about/changelog/#added_12","title":"Added","text":"
  • use_origin hook for returning the browser's location.origin.
"},{"location":"about/changelog/#changed_13","title":"Changed","text":"
  • view_to_component now returns a Callable, instead of directly returning a Component. Check the docs for new usage info.
  • use_mutation and use_query will now log any query failures.
"},{"location":"about/changelog/#fixed_7","title":"Fixed","text":"
  • Allow use_mutation to have refetch=None, as the docs suggest is possible.
  • use_query will now prefetch all fields to prevent SynchronousOnlyOperation exceptions.
  • view_to_component, django_css, and django_js type hints will now display like normal functions.
  • IDOM preloader no longer attempts to parse commented out IDOM components.
  • Tests are now fully functional on Windows
"},{"location":"about/changelog/#120-2022-09-19","title":"1.2.0 - 2022-09-19","text":""},{"location":"about/changelog/#added_13","title":"Added","text":"
  • auth_required decorator to prevent your components from rendering to unauthenticated users.
  • use_query hook for fetching database values.
  • use_mutation hook for modifying database values.
  • view_to_component utility to convert legacy Django views to IDOM components.
"},{"location":"about/changelog/#changed_14","title":"Changed","text":"
  • Bumped the minimum IDOM version to 0.40.2
  • Testing suite now uses playwright instead of selenium
"},{"location":"about/changelog/#fixed_8","title":"Fixed","text":"
  • IDOM preloader is no longer sensitive to whitespace within template tags.
"},{"location":"about/changelog/#110-2022-07-01","title":"1.1.0 - 2022-07-01","text":""},{"location":"about/changelog/#added_14","title":"Added","text":"
  • django_css and django_js components to defer loading CSS & JS files until needed.
"},{"location":"about/changelog/#changed_15","title":"Changed","text":"
  • Bumped the minimum IDOM version to 0.39.0
"},{"location":"about/changelog/#100-2022-05-22","title":"1.0.0 - 2022-05-22","text":""},{"location":"about/changelog/#added_15","title":"Added","text":"
  • Django specific hooks! use_websocket, use_scope, and use_location are now available within the django_idom.hooks module.
  • Documentation has been placed into a formal docs webpage.
  • Logging for when a component fails to import, or if no components were found within Django.
"},{"location":"about/changelog/#changed_16","title":"Changed","text":"
  • idom_component template tag has been renamed to component
  • Bumped the minimum IDOM version to 0.38.0
"},{"location":"about/changelog/#removed_4","title":"Removed","text":"
  • websocket parameter for components has been removed. Functionally, it is replaced with django_idom.hooks.use_websocket.
"},{"location":"about/changelog/#005-2022-04-04","title":"0.0.5 - 2022-04-04","text":""},{"location":"about/changelog/#changed_17","title":"Changed","text":"
  • Bumped the minimum IDOM version to 0.37.2
"},{"location":"about/changelog/#fixed_9","title":"Fixed","text":"
  • ModuleNotFoundError: No module named idom.core.proto caused by IDOM 0.37.2
"},{"location":"about/changelog/#004-2022-03-05","title":"0.0.4 - 2022-03-05","text":""},{"location":"about/changelog/#changed_18","title":"Changed","text":"
  • Bumped the minimum IDOM version to 0.37.1
"},{"location":"about/changelog/#003-2022-02-19","title":"0.0.3 - 2022-02-19","text":""},{"location":"about/changelog/#changed_19","title":"Changed","text":"
  • Bumped the minimum IDOM version to 0.36.3
"},{"location":"about/changelog/#002-2022-01-30","title":"0.0.2 - 2022-01-30","text":""},{"location":"about/changelog/#added_16","title":"Added","text":"
  • Ability to declare the HTML class of the top-level component div
  • name = ... parameter to IDOM HTTP paths for use with django.urls.reverse()
  • Cache versioning to automatically invalidate old web module files from the cache back-end
  • Automatic pre-population of the IDOM component registry
  • Type hinting for IdomWebsocket
"},{"location":"about/changelog/#changed_20","title":"Changed","text":"
  • Fetching web modules from disk and/or cache is now fully async
  • Static files are now contained within a django_idom/ parent folder
  • Upgraded IDOM to version 0.36.0
  • Minimum Django version required is now 4.0
  • Minimum Python version required is now 3.8
"},{"location":"about/changelog/#removed_5","title":"Removed","text":"
  • IDOM_WEB_MODULES_PATH has been replaced with Django include(...)
  • IDOM_WS_MAX_RECONNECT_DELAY has been renamed to IDOM_WS_MAX_RECONNECT_TIMEOUT
  • idom_web_modules cache back-end has been renamed to idom
"},{"location":"about/changelog/#fixed_10","title":"Fixed","text":"
  • Increase test timeout values to prevent false positives
  • Windows compatibility for building Django-IDOM
"},{"location":"about/changelog/#security_2","title":"Security","text":"
  • Fixed potential directory traversal attack on the IDOM web modules URL
"},{"location":"about/changelog/#001-2021-08-18","title":"0.0.1 - 2021-08-18","text":""},{"location":"about/changelog/#added_17","title":"Added","text":"
  • Support for IDOM within the Django
"},{"location":"about/code/","title":"Code","text":""},{"location":"about/code/#overview","title":"Overview","text":"

You will need to set up a Python environment to develop ReactPy-Django.

Note

Looking to contribute features that are not Django specific?

Everything within the reactpy-django repository must be specific to Django integration. Check out the ReactPy Core documentation to contribute general features such as components, hooks, and events.

"},{"location":"about/code/#creating-an-environment","title":"Creating an environment","text":"

If you plan to make code changes to this repository, you will need to install the following dependencies first:

  • Python 3.9+
  • Git
  • NPM for installing and managing Javascript

Once done, you should clone this repository:

git clone https://github.com/reactive-python/reactpy-django.git\ncd reactpy-django\n

Then, by running the command below you can:

  • Install an editable version of the Python code
  • Download, build, and install Javascript dependencies
pip install -e . -r requirements.txt --verbose --upgrade\n

Pitfall

Some of our development dependencies require a C++ compiler, which is not installed by default on Windows.

If you receive errors related to this during installation, follow the instructions in your console errors.

Finally, to verify that everything is working properly, you can manually run the test web server.

cd tests\npython manage.py runserver\n

Navigate to http://127.0.0.1:8000 to see if the tests are rendering correctly.

"},{"location":"about/code/#creating-a-pull-request","title":"Creating a pull request","text":"

Now, you can create/modify the ReactPy-Django source code, and Pull Request (PR) your changes to our GitHub repository.

To learn how to create GitHub PRs, click here.

"},{"location":"about/code/#running-the-full-test-suite","title":"Running the full test suite","text":"

Note

This repository uses Nox to run tests. For a full test of available scripts run nox -l.

By running the command below you can run the full test suite:

nox -s test\n

Or, if you want to run the tests in the background:

nox -s test -- --headless\n
"},{"location":"about/code/#running-django-tests","title":"Running Django tests","text":"

If you want to only run our Django tests in your current environment, you can use the following command:

cd tests\npython manage.py test\n
"},{"location":"about/code/#running-django-test-web-server","title":"Running Django test web server","text":"

If you want to manually run the Django test application, you can use the following command:

cd tests\npython manage.py runserver\n
"},{"location":"about/docs/","title":"Docs","text":""},{"location":"about/docs/#overview","title":"Overview","text":"

You will need to set up a Python environment to create, test, and preview docs changes.

"},{"location":"about/docs/#modifying-docs","title":"Modifying Docs","text":"

If you plan to make changes to this documentation, you will need to install the following dependencies first:

  • Python 3.9+
  • Git

Once done, you should clone this repository:

git clone https://github.com/reactive-python/reactpy-django.git\ncd reactpy-django\n

Then, by running the command below you can:

  • Install an editable version of the documentation
  • Self-host a test server for the documentation
pip install -r requirements.txt --upgrade\n

Finally, to verify that everything is working properly, you can manually run the docs preview web server.

mkdocs serve\n

Navigate to http://127.0.0.1:8000 to view a preview of the documentation.

"},{"location":"about/docs/#github-pull-request","title":"GitHub Pull Request","text":"

Now, you can create/modify the ReactPy-Django source code, and Pull Request (PR) your changes to our GitHub repository.

To learn how to create GitHub PRs, click here.

"},{"location":"learn/add-reactpy-to-a-django-project/","title":"Add ReactPy to a Django Project","text":""},{"location":"learn/add-reactpy-to-a-django-project/#overview","title":"Overview","text":"

If you want to add some interactivity to your existing Django project, you don't have to rewrite it in ReactPy. Use ReactPy-Django to add ReactPy to your existing stack, and render interactive components anywhere.

Note

These docs assumes you have already created a Django project, which involves creating and installing at least one Django app.

If do not have a Django project, check out this 9 minute YouTube tutorial created by IDG TECHtalk.

"},{"location":"learn/add-reactpy-to-a-django-project/#step-1-install-from-pypi","title":"Step 1: Install from PyPI","text":"

Run the following command to install reactpy-django in your Python environment.

pip install reactpy-django\n
"},{"location":"learn/add-reactpy-to-a-django-project/#step-2-configure-settingspy","title":"Step 2: Configure settings.py","text":"

Add \"reactpy_django\" to INSTALLED_APPS in your settings.py file.

settings.py
INSTALLED_APPS = [\n    ...,\n    \"reactpy_django\",\n]\n
Enable ASGI and Django Channels (Required)

ReactPy-Django requires Django ASGI and Django Channels WebSockets.

If you have not enabled ASGI on your Django project yet, here is a summary of the django and channels installation docs:

  1. Install channels[daphne]
  2. Add \"daphne\" to INSTALLED_APPS.

    INSTALLED_APPS = [\n    \"daphne\",\n    ...,\n]\n
  3. Set your ASGI_APPLICATION variable.

    ASGI_APPLICATION = \"example_project.asgi.application\"\n
Configure ReactPy settings (Optional)

ReactPy's has additional configuration available to fit a variety of use cases.

See the ReactPy settings documentation to learn more.

"},{"location":"learn/add-reactpy-to-a-django-project/#step-3-configure-urlspy","title":"Step 3: Configure urls.py","text":"

Add ReactPy HTTP paths to your urlpatterns in your urls.py file.

urls.py
from django.urls import include, path\n\nurlpatterns = [\n    ...,\n    path(\"reactpy/\", include(\"reactpy_django.http.urls\")),\n]\n
"},{"location":"learn/add-reactpy-to-a-django-project/#step-4-configure-asgipy","title":"Step 4: Configure asgi.py","text":"

Register ReactPy's WebSocket using REACTPY_WEBSOCKET_ROUTE in your asgi.py file.

asgi.py
import os\n\nfrom django.core.asgi import get_asgi_application\n\n# Ensure DJANGO_SETTINGS_MODULE is set properly based on your project name!\nos.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"example_project.settings\")\n\n# Fetch ASGI application before importing dependencies that require ORM models.\ndjango_asgi_app = get_asgi_application()\n\n\nfrom channels.routing import ProtocolTypeRouter, URLRouter  # noqa: E402\nfrom reactpy_django import REACTPY_WEBSOCKET_ROUTE  # noqa: E402\n\napplication = ProtocolTypeRouter(\n    {\n        \"http\": django_asgi_app,\n        \"websocket\": URLRouter([REACTPY_WEBSOCKET_ROUTE]),\n    }\n)\n
Add AuthMiddlewareStack and SessionMiddlewareStack (Optional)

There are many situations where you need to access the Django User or Session objects within ReactPy components. For example, if you want to:

  1. Access the User that is currently logged in
  2. Login or logout the current User
  3. Access Django's Session object

In these situations will need to ensure you are using AuthMiddlewareStack and/or SessionMiddlewareStack.

from channels.auth import AuthMiddlewareStack  # noqa: E402\nfrom channels.sessions import SessionMiddlewareStack  # noqa: E402\n\napplication = ProtocolTypeRouter(\n    {\n        \"http\": django_asgi_app,\n        \"websocket\": SessionMiddlewareStack(\n            AuthMiddlewareStack(\n                URLRouter(\n                    [REACTPY_WEBSOCKET_ROUTE],\n                )\n            )\n        ),\n    }\n)\n
Where is my asgi.py?

If you do not have an asgi.py, follow the channels installation guide.

"},{"location":"learn/add-reactpy-to-a-django-project/#step-5-run-database-migrations","title":"Step 5: Run database migrations","text":"

Run Django's migrate command to initialize ReactPy-Django's database table.

python manage.py migrate\n
"},{"location":"learn/add-reactpy-to-a-django-project/#step-6-check-your-configuration","title":"Step 6: Check your configuration","text":"

Run Django's check command to verify if ReactPy was set up correctly.

python manage.py check\n
"},{"location":"learn/add-reactpy-to-a-django-project/#step-7-create-your-first-component","title":"Step 7: Create your first component","text":"

The next step will show you how to create your first ReactPy component.

Prefer a quick summary? Read the At a Glance section below.

At a Glance: Your First Component

my_app/components.py

You will need a file to define your ReactPy components. We recommend creating a components.py file within your chosen Django app to start out. Within this file, we will create a simple hello_world component.

from reactpy import component, html\n\n@component\ndef hello_world(recipient: str):\n    return html.h1(f\"Hello {recipient}!\")\n

my_app/templates/my-template.html

In your Django app's HTML template, you can now embed your ReactPy component using the component template tag. Within this tag, you will need to type in the dotted path to the component.

Additionally, you can pass in args and kwargs into your component function. After reading the code below, pay attention to how the function definition for hello_world (from the previous example) accepts a recipient argument.

{% load reactpy %}\n<!DOCTYPE html>\n<html>\n  <body>\n{% component \"example_project.my_app.components.hello_world\" recipient=\"World\" %}\n  </body>\n</html>\n
"},{"location":"learn/your-first-component/","title":"Your First Component","text":""},{"location":"learn/your-first-component/#overview","title":"Overview","text":"

Components are one of the core concepts of ReactPy. They are the foundation upon which you build user interfaces (UI), which makes them the perfect place to start your journey!

Note

If you have reached this point, you should have already installed ReactPy-Django through the previous steps.

"},{"location":"learn/your-first-component/#selecting-a-django-app","title":"Selecting a Django App","text":"

You will now need to pick at least one Django app to start using ReactPy-Django on.

For the following examples, we will assume the following:

  1. You have a Django app named my_app, which was created by Django's startapp command.
  2. You have placed my_app directly into your Django project folder (./example_project/my_app). This is common for small projects.
How do I organize my Django project for ReactPy?

ReactPy-Django has no project structure requirements. Organize everything as you wish, just like any Django project.

"},{"location":"learn/your-first-component/#defining-a-component","title":"Defining a component","text":"

You will need a file to start creating ReactPy components.

We recommend creating a components.py file within your chosen Django app to start out. For this example, the file path will look like this: ./example_project/my_app/components.py.

Within this file, you can define your component functions using ReactPy's @component decorator.

components.py
from reactpy import component, html\n\n@component\ndef hello_world(recipient: str):\n    return html.h1(f\"Hello {recipient}!\")\n
What should I name my ReactPy files and functions?

You have full freedom in naming/placement of your files and functions.

We recommend creating a components.py for small Django apps. If your app has a lot of components, you should consider breaking them apart into individual modules such as components/navbar.py.

Ultimately, components are referenced by Python dotted path in my-template.html (see next step). This path must be valid to Python's importlib.

What does the decorator actually do?

While not all components need to be decorated, there are a few features this decorator adds to your components.

  1. The ability to be used as a root component.
    • The decorator is required for any component that you want to reference in your Django templates (see next step).
  2. The ability to use hooks.
    • The decorator is required on any component where hooks are defined.
  3. Scoped failures.
    • If a decorated component generates an exception, then only that one component will fail to render.
"},{"location":"learn/your-first-component/#embedding-in-a-template","title":"Embedding in a template","text":"

In your Django app's HTML template, you can now embed your ReactPy component using the {% component %} template tag. Within this tag, you will need to type in the dotted path to the component.

Additionally, you can pass in args and kwargs into your component function. After reading the code below, pay attention to how the function definition for hello_world (from the previous step) accepts a recipient argument.

my-template.html
{% load reactpy %}\n<!DOCTYPE html>\n<html>\n  <body>\n{% component \"example_project.my_app.components.hello_world\" recipient=\"World\" %}\n  </body>\n</html>\n
Do not use context variables for the component path

The ReactPy component finder (reactpy_django.utils.RootComponentFinder) requires that your component path is a string.

Do not use Django template/context variables for the component path. Failure to follow this warning can result in unexpected behavior, such as components that will not render.

For example, do not do the following:

my-template.htmlviews.py
<!-- This is good -->\n{% component \"example_project.my_app.components.hello_world\" recipient=\"World\" %}\n\n<!-- This is bad -->\n{% component my_variable recipient=\"World\" %}\n
from django.shortcuts import render\n\n\ndef example_view(request):\n    context_vars = {\"my_variable\": \"example_project.my_app.components.hello_world\"}\n    return render(request, \"my-template.html\", context_vars)\n
Can I use multiple components on one page?

You can add as many components to a webpage as needed by using the template tag multiple times. Retrofitting legacy sites to use ReactPy will typically involve many components on one page.

my-template.html
{% load reactpy %}\n<!DOCTYPE html>\n<html>\n    <body>\n        <h1>{% component \"example_project.my_app.components.my_title\" %}</h1>\n        <p>{% component \"example_project.my_app_2.components.goodbye_world\" class=\"bold small-font\" %}</p>\n{% component \"example_project.my_app_3.components.simple_button\" %}\n    </body>\n</html>\n

Please note that components separated like this will not be able to interact with each other, except through database queries.

Additionally, in scenarios where you are trying to create a Single Page Application (SPA) within Django, you will only have one component within your <body> tag.

Where is my templates folder?

If you do not have a ./templates/ folder in your Django app, you can simply create one! Keep in mind, templates within this folder will not be detected by Django unless you add the corresponding Django app to settings.py:INSTALLED_APPS.

"},{"location":"learn/your-first-component/#setting-up-a-django-view","title":"Setting up a Django view","text":"

Within your Django app's views.py file, you will need to create a view function to render the HTML template my-template.html (from the previous step).

views.py
from django.shortcuts import render\n\n\ndef index(request):\n    return render(request, \"my-template.html\")\n

We will add this new view into your urls.py and define what URL it should be accessible at.

urls.py
from django.urls import path\nfrom example import views\n\nurlpatterns = [\n    path(\"example/\", views.index),\n]\n
Which urls.py do I add my views to?

For simple Django projects, you can easily add all of your views directly into the Django project's urls.py. However, as you start increase your project's complexity you might end up with way too much within one file.

Once you reach that point, we recommend creating an individual urls.py within each of your Django apps.

Then, within your Django project's urls.py you will use Django's include function to link it all together.

"},{"location":"learn/your-first-component/#viewing-your-component","title":"Viewing your component","text":"

To test your new Django view, run the following command to start up a development web server.

python manage.py runserver\n

Now you can navigate to your Django project URL that contains a ReactPy component, such as http://127.0.0.1:8000/example/ (from the previous step).

If you copy-pasted our example component, you will now see your component display \"Hello World\".

Do not use manage.py runserver for production

This command is only intended for development purposes. For production deployments make sure to read Django's documentation.

"},{"location":"learn/your-first-component/#learn-more","title":"Learn more","text":"

Congratulations! If you followed the previous steps, you have now created a \"Hello World\" component using ReactPy-Django!

Deep Dive

The docs you are reading only covers our Django integration. To learn more, check out one of the following links:

  • ReactPy-Django Feature Reference
  • ReactPy Core Documentation
  • Ask Questions on Discord

Additionally, the vast majority of tutorials/guides you find for ReactJS can be applied to ReactPy.

"},{"location":"reference/components/","title":"Components","text":""},{"location":"reference/components/#overview","title":"Overview","text":"

We supply some pre-designed that components can be used to help simplify development.

"},{"location":"reference/components/#view-to-component","title":"View To Component","text":"

Convert any Django view into a ReactPy component by using this decorator. Compatible with Function Based Views and Class Based Views. Views can be sync or async.

components.py
from django.http import HttpResponse\nfrom reactpy import component, html\nfrom reactpy_django.components import view_to_component\n\n\n@view_to_component\ndef hello_world_view(request):\n    return HttpResponse(\"Hello World!\")\n\n\n@component\ndef my_component():\n    return html.div(\n        hello_world_view(),\n    )\n
See Interface

Parameters

Name Type Description Default view Callable | View The view function or class to convert. N/A compatibility bool If True, the component will be rendered in an iframe. When using compatibility mode tranforms, strict_parsing, request, args, and kwargs arguments will be ignored. False transforms Sequence[Callable[[VdomDict], Any]] A list of functions that transforms the newly generated VDOM. The functions will be called on each VDOM node. tuple strict_parsing bool If True, an exception will be generated if the HTML does not perfectly adhere to HTML5. True

Returns

Type Description _ViewComponentConstructor A function that takes request, *args, key, **kwargs and returns a ReactPy component. All parameters are directly provided to your view, besides key which is used by ReactPy. Potential information exposure when using compatibility = True

When using compatibility mode, ReactPy automatically exposes a URL to your view.

It is your responsibility to ensure privileged information is not leaked via this method.

You must implement a method to ensure only authorized users can access your view. This can be done via directly writing conditionals into your view, or by adding decorators such as user_passes_test to your views. For example...

Function Based ViewClass Based View
from django.contrib.auth.decorators import user_passes_test\nfrom reactpy_django.components import view_to_component\n\n\n@view_to_component(compatibility=True)\n@user_passes_test(lambda u: u.is_superuser)  # type: ignore[union-attr]\ndef example_view(request):\n    ...\n
from django.contrib.auth.decorators import user_passes_test\nfrom django.utils.decorators import method_decorator\nfrom django.views.generic import TemplateView\nfrom reactpy_django.components import view_to_component\n\n\n@view_to_component(compatibility=True)\n@method_decorator(user_passes_test(lambda u: u.is_superuser), name=\"dispatch\")  # type: ignore[union-attr]\nclass ExampleView(TemplateView):\n    ...\n
Existing limitations

There are currently several limitations of using view_to_component that may be resolved in a future version.

  • Requires manual intervention to change request methods beyond GET.
  • ReactPy events cannot conveniently be attached to converted view HTML.
  • Has no option to automatically intercept local anchor link (such as <a href='example/'></a>) click events.

Please note these limitations do not exist when using compatibility mode.

How do I use this for Class Based Views?

You can simply pass your Class Based View directly into view_to_component.

components.py
from django.http import HttpResponse\nfrom django.views import View\nfrom reactpy import component, html\nfrom reactpy_django.components import view_to_component\n\n\nclass HelloWorldView(View):\n    def get(self, request):\n        return HttpResponse(\"Hello World!\")\n\n\nvtc = view_to_component(HelloWorldView)\n\n\n@component\ndef my_component():\n    return html.div(\n        vtc(),\n    )\n
How do I transform views from external libraries?

In order to convert external views, you can utilize view_to_component as a function, rather than a decorator.

components.py
from example.views import example_view\nfrom reactpy import component, html\nfrom reactpy_django.components import view_to_component\n\nexample_vtc = view_to_component(example_view)\n\n\n@component\ndef my_component():\n    return html.div(\n        example_vtc(),\n    )\n
How do I provide request, args, and kwargs to a view?

Request

You can use the request parameter to provide the view a custom request object.

components.py
from django.http import HttpRequest, HttpResponse\nfrom reactpy import component, html\nfrom reactpy_django.components import view_to_component\n\nexample_request = HttpRequest()\nexample_request.method = \"PUT\"\n\n\n@view_to_component\ndef hello_world_view(request):\n    return HttpResponse(f\"Hello World! {request.method}\")\n\n\n@component\ndef my_component():\n    return html.div(\n        hello_world_view(\n            example_request,\n        ),\n    )\n

args and kwargs

You can use the args and kwargs parameters to provide positional and keyworded arguments to a view.

components.py
from django.http import HttpResponse\nfrom reactpy import component, html\nfrom reactpy_django.components import view_to_component\n\n\n@view_to_component\ndef hello_world_view(request, arg1, arg2, key1=None, key2=None):\n    return HttpResponse(f\"Hello World! {arg1} {arg2} {key1} {key2}\")\n\n\n@component\ndef my_component():\n    return html.div(\n        hello_world_view(\n            None,  # Your request object (optional)\n            \"value_1\",\n            \"value_2\",\n            key1=\"abc\",\n            key2=\"123\",\n        ),\n    )\n
How do I use strict_parsing, compatibility, and transforms?

strict_parsing

By default, an exception will be generated if your view's HTML does not perfectly adhere to HTML5.

However, there are some circumstances where you may not have control over the original HTML, so you may be unable to fix it. Or you may be relying on non-standard HTML tags such as <my-tag> Hello World </my-tag>.

In these scenarios, you may want to rely on best-fit parsing by setting the strict_parsing parameter to False.

components.py
from django.http import HttpResponse\nfrom reactpy import component, html\nfrom reactpy_django.components import view_to_component\n\n\n@view_to_component(strict_parsing=False)\ndef hello_world_view(request):\n    return HttpResponse(\"<my-tag> Hello World </my-tag>\")\n\n\n@component\ndef my_component():\n    return html.div(\n        hello_world_view(),\n    )\n

Note: Best-fit parsing is designed to be similar to how web browsers would handle non-standard or broken HTML.

compatibility

For views that rely on HTTP responses other than GET (such as PUT, POST, PATCH, etc), you should consider using compatibility mode to render your view within an iframe.

Any view can be rendered within compatibility mode. However, the transforms, strict_parsing, request, args, and kwargs arguments do not apply to compatibility mode.

components.py
from django.http import HttpResponse\nfrom reactpy import component, html\nfrom reactpy_django.components import view_to_component\n\n\n@view_to_component(compatibility=True)\ndef hello_world_view(request):\n    return HttpResponse(\"Hello World!\")\n\n\n@component\ndef my_component():\n    return html.div(\n        hello_world_view(),\n    )\n

Note: By default the compatibility iframe is unstyled, and thus won't look pretty until you add some CSS.

transforms

After your view has been turned into VDOM (python dictionaries), view_to_component will call your transforms functions on every VDOM node.

This allows you to modify your view prior to rendering.

For example, if you are trying to modify the text of a node with a certain id, you can create a transform like such:

components.py
from django.http import HttpResponse\nfrom reactpy import component, html\nfrom reactpy_django.components import view_to_component\n\n\ndef example_transform(vdom):\n    attributes = vdom.get(\"attributes\")\n    if attributes and attributes.get(\"id\") == \"hello-world\":\n        vdom[\"children\"][0] = \"Good Bye World!\"\n\n\n@view_to_component(transforms=[example_transform])\ndef hello_world_view(request):\n    return HttpResponse(\"<div id='hello-world'> Hello World! <div>\")\n\n\n@component\ndef my_component():\n    return html.div(\n        hello_world_view(),\n    )\n
"},{"location":"reference/components/#django-css","title":"Django CSS","text":"

Allows you to defer loading a CSS stylesheet until a component begins rendering. This stylesheet must be stored within Django's static files.

components.py
from reactpy import component, html\nfrom reactpy_django.components import django_css\n\n\n@component\ndef my_component():\n    return html.div(\n        django_css(\"css/buttons.css\"),\n        html.button(\"My Button!\"),\n    )\n
See Interface

Parameters

Name Type Description Default static_path str The path to the static file. This path is identical to what you would use on a static template tag. N/A key Key | None A key to uniquely identify this component which is unique amongst a component's immediate siblings None

Returns

Type Description Component A ReactPy component. Should I put django_css at the top of my HTML?

Yes, if the stylesheet contains styling for your component.

Can I load static CSS using html.link instead?

While you can load stylesheets with html.link, keep in mind that loading this way does not ensure load order. Thus, your stylesheet will be loaded after your component is displayed. This would likely cause unintended visual behavior, so use this at your own discretion.

Here's an example on what you should avoid doing for Django static files:

from django.templatetags.static import static\nfrom reactpy import component, html\n\n\n@component\ndef my_component():\n    return html.div(\n        html.link({\"rel\": \"stylesheet\", \"href\": static(\"css/buttons.css\")}),\n        html.button(\"My Button!\"),\n    )\n
How do I load external CSS?

django_css can only be used with local static files.

For external CSS, substitute django_css with html.link.

from reactpy import component, html\n\n\n@component\ndef my_component():\n    return html.div(\n        html.link(\n            {\"rel\": \"stylesheet\", \"href\": \"https://example.com/external-styles.css\"}\n        ),\n        html.button(\"My Button!\"),\n    )\n
Why not load my CSS in <head>?

Traditionally, stylesheets are loaded in your <head> using the {% load static %} template tag.

To help improve webpage load times, you can use the django_css component to defer loading your stylesheet until it is needed.

"},{"location":"reference/components/#django-js","title":"Django JS","text":"

Allows you to defer loading JavaScript until a component begins rendering. This JavaScript must be stored within Django's static files.

components.py
from reactpy import component, html\nfrom reactpy_django.components import django_js\n\n\n@component\ndef my_component():\n    return html.div(\n        html.button(\"My Button!\"),\n        django_js(\"js/scripts.js\"),\n    )\n
See Interface

Parameters

Name Type Description Default static_path str The path to the static file. This path is identical to what you would use on a static template tag. N/A key Key | None A key to uniquely identify this component which is unique amongst a component's immediate siblings None

Returns

Type Description Component A ReactPy component. Should I put django_js at the bottom of my HTML?

Yes, if your scripts are reliant on the contents of the component.

Can I load static JavaScript using html.script instead?

While you can load JavaScript with html.script, keep in mind that loading this way does not ensure load order. Thus, your JavaScript will likely be loaded at an arbitrary time after your component is displayed.

Here's an example on what you should avoid doing for Django static files:

from django.templatetags.static import static\nfrom reactpy import component, html\n\n\n@component\ndef my_component():\n    return html.div(\n        html.script({\"src\": static(\"js/scripts.js\")}),\n        html.button(\"My Button!\"),\n    )\n
How do I load external JS?

django_js can only be used with local static files.

For external JavaScript, substitute django_js with html.script.

from reactpy import component, html\n\n\n@component\ndef my_component():\n    return html.div(\n        html.script({\"src\": \"https://example.com/external-scripts.js\"}),\n        html.button(\"My Button!\"),\n    )\n
Why not load my JS in <head>?

Traditionally, JavaScript is loaded in your <head> using the {% load static %} template tag.

To help improve webpage load times, you can use the django_js component to defer loading your JavaScript until it is needed.

"},{"location":"reference/decorators/","title":"Decorators","text":""},{"location":"reference/decorators/#overview","title":"Overview","text":"

Decorator functions can be used within your components.py to help simplify development.

"},{"location":"reference/decorators/#auth-required","title":"Auth Required","text":"

You can limit access to a component to users with a specific auth_attribute by using this decorator (with or without parentheses).

By default, this decorator checks if the user is logged in and not deactivated (is_active).

This decorator is commonly used to selectively render a component only if a user is_staff or is_superuser.

components.py
from reactpy import component, html\nfrom reactpy_django.decorators import auth_required\n\n\n@component\n@auth_required\ndef my_component():\n    return html.div(\"I am logged in!\")\n
See Interface

Parameters

Name Type Description Default auth_attribute str The value to check within the user object. This is checked via getattr(scope[\"user\"], auth_attribute). \"is_active\" fallback ComponentType | VdomDict | None The component or reactpy.html snippet to render if the user is not authenticated. None

Returns

Type Description #!python Component` A ReactPy component. #!python VdomDict| A#!python reactpy.html` snippet. #!python None` No component render. How do I render a different component if authentication fails?

You can use a component with the fallback argument, as seen below.

components.py
from reactpy import component, html\nfrom reactpy_django.decorators import auth_required\n\n\n@component\ndef my_component_fallback():\n    return html.div(\"I am NOT logged in!\")\n\n\n@component\n@auth_required(fallback=my_component_fallback)\ndef my_component():\n    return html.div(\"I am logged in!\")\n
How do I render a simple reactpy.html snippet if authentication fails?

You can use a reactpy.html snippet with the fallback argument, as seen below.

components.py
from reactpy import component, html\nfrom reactpy_django.decorators import auth_required\n\n\n@component\n@auth_required(fallback=html.div(\"I am NOT logged in!\"))\ndef my_component():\n    return html.div(\"I am logged in!\")\n
How can I check if a user is_staff?

You can do this by setting auth_attribute=\"is_staff\", as seen blow.

components.py
from reactpy import component, html\nfrom reactpy_django.decorators import auth_required\n\n\n@component\n@auth_required(auth_attribute=\"is_staff\")\ndef my_component():\n    return html.div(\"I am logged in!\")\n
How can I check for a custom attribute?

You will need to be using a custom user model within your Django instance.

For example, if your user model has the field is_really_cool ...

models.py
from django.contrib.auth.models import AbstractBaseUser\n\n\nclass CustomUserModel(AbstractBaseUser):\n    @property\n    def is_really_cool(self):\n        return True\n

... then you would do the following within your decorator:

components.py
from reactpy import component, html\nfrom reactpy_django.decorators import auth_required\n\n\n@component\n@auth_required(auth_attribute=\"is_really_cool\")\ndef my_component():\n    return html.div(\"I am logged in!\")\n
"},{"location":"reference/hooks/","title":"Hooks","text":""},{"location":"reference/hooks/#overview","title":"Overview","text":"

Prefabricated hooks can be used within your components.py to help simplify development.

Note

Looking for standard React hooks?

This package only contains Django specific hooks. Standard hooks can be found within reactive-python/reactpy.

"},{"location":"reference/hooks/#use-query","title":"Use Query","text":"

This hook is used read data from the Django ORM.

The query function you provide must return either a Model or QuerySet.

components.pymodels.py
from example.models import TodoItem\nfrom reactpy import component, html\nfrom reactpy_django.hooks import use_query\n\n\ndef get_items():\n    return TodoItem.objects.all()\n\n\n@component\ndef todo_list():\n    item_query = use_query(get_items)\n\n    if item_query.loading:\n        rendered_items = html.h2(\"Loading...\")\n    elif item_query.error or not item_query.data:\n        rendered_items = html.h2(\"Error when loading!\")\n    else:\n        rendered_items = html.ul([html.li(item, key=item) for item in item_query.data])\n\n    return html.div(\"Rendered items: \", rendered_items)\n
from django.db.models import CharField, Model\n\n\nclass TodoItem(Model):\n    text: CharField = CharField(max_length=255)\n
See Interface

Parameters

Name Type Description Default options QueryOptions | None An optional QueryOptions object that can modify how the query is executed. None query Callable[_Params, _Result | None] A callable that returns a Django Model or QuerySet. N/A *args _Params.args Positional arguments to pass into query. N/A **kwargs _Params.kwargs Keyword arguments to pass into query. N/A

Returns

Type Description Query[_Result | None] An object containing loading/error states, your data (if the query has successfully executed), and a refetch callable that can be used to re-run the query. How can I provide arguments to my query function?

*args and **kwargs can be provided to your query function via use_query parameters.

components.py
from reactpy import component\nfrom reactpy_django.hooks import use_query\n\n\ndef example_query(value: int, other_value: bool = False):\n    ...\n\n\n@component\ndef my_component():\n    query = use_query(\n        example_query,\n        123,\n        other_value=True,\n    )\n\n    return str(query.data)\n
Why does get_items in the example return TodoItem.objects.all()?

This was a technical design decision to based on Apollo's useQuery hook, but ultimately helps avoid Django's SynchronousOnlyOperation exceptions.

The use_query hook ensures the provided Model or QuerySet executes all deferred/lazy queries safely prior to reaching your components.

How can I use QueryOptions to customize fetching behavior?

thread_sensitive

Whether to run your synchronous query function in thread-sensitive mode. Thread-sensitive mode is turned on by default due to Django ORM limitations. See Django's sync_to_async docs docs for more information.

This setting only applies to sync query functions, and will be ignored for async functions.

components.py
from reactpy import component\nfrom reactpy_django.hooks import use_query\nfrom reactpy_django.types import QueryOptions\n\n\ndef execute_thread_safe_operation():\n\"\"\"This is an example query function that does some thread-safe operation.\"\"\"\n    pass\n\n\n@component\ndef my_component():\n    query = use_query(\n        QueryOptions(thread_sensitive=False),\n        execute_thread_safe_operation,\n    )\n\n    if query.loading or query.error:\n        return None\n\n    return str(query.data)\n

postprocessor

By default, automatic recursive fetching of ManyToMany or ForeignKey fields is enabled within the default QueryOptions.postprocessor. This is needed to prevent SynchronousOnlyOperation exceptions when accessing these fields within your ReactPy components.

However, if you...

  1. Want to use this hook to defer IO intensive tasks to be computed in the background
  2. Want to to utilize use_query with a different ORM

... then you can either set a custom postprocessor, or disable all postprocessing behavior by modifying the QueryOptions.postprocessor parameter. In the example below, we will set the postprocessor to None to disable postprocessing behavior.

components.py
from reactpy import component\nfrom reactpy_django.hooks import use_query\nfrom reactpy_django.types import QueryOptions\n\n\ndef execute_io_intensive_operation():\n\"\"\"This is an example query function that does something IO intensive.\"\"\"\n    pass\n\n\n@component\ndef my_component():\n    query = use_query(\n        QueryOptions(postprocessor=None),\n        execute_io_intensive_operation,\n    )\n\n    if query.loading or query.error:\n        return None\n\n    return str(query.data)\n

If you wish to create a custom postprocessor, you will need to create a callable.

The first argument of postprocessor must be the query data. All proceeding arguments are optional postprocessor_kwargs (see below). This postprocessor must return the modified data.

components.py
from reactpy import component\nfrom reactpy_django.hooks import use_query\nfrom reactpy_django.types import QueryOptions\n\n\ndef my_postprocessor(data, example_kwarg=True):\n    if example_kwarg:\n        return data\n\n    return dict(data)\n\n\ndef execute_io_intensive_operation():\n\"\"\"This is an example query function that does something IO intensive.\"\"\"\n    pass\n\n\n@component\ndef my_component():\n    query = use_query(\n        QueryOptions(\n            postprocessor=my_postprocessor,\n            postprocessor_kwargs={\"example_kwarg\": False},\n        ),\n        execute_io_intensive_operation,\n    )\n\n    if query.loading or query.error:\n        return None\n\n    return str(query.data)\n

postprocessor_kwargs

By default, automatic recursive fetching of ManyToMany or ForeignKey fields is enabled within the default QueryOptions.postprocessor. This is needed to prevent SynchronousOnlyOperation exceptions when accessing these fields within your ReactPy components.

However, if you have deep nested trees of relational data, this may not be a desirable behavior. In these scenarios, you may prefer to manually fetch these relational fields using a second use_query hook.

You can disable the prefetching behavior of the default postprocessor (located at reactpy_django.utils.django_query_postprocessor) via the QueryOptions.postprocessor_kwargs parameter.

components.py
from example.models import TodoItem\nfrom reactpy import component\nfrom reactpy_django.hooks import use_query\nfrom reactpy_django.types import QueryOptions\n\n\ndef get_model_with_relationships():\n\"\"\"This is an example query function that gets `MyModel` which has a ManyToMany field, and\n    additionally other models that have formed a ForeignKey association to `MyModel`.\n\n    ManyToMany Field: `many_to_many_field`\n    ForeignKey Field: `foreign_key_field_set`\n    \"\"\"\n    return TodoItem.objects.get(id=1)\n\n\n@component\ndef my_component():\n    query = use_query(\n        QueryOptions(\n            postprocessor_kwargs={\"many_to_many\": False, \"many_to_one\": False}\n        ),\n        get_model_with_relationships,\n    )\n\n    if query.loading or query.error or not query.data:\n        return None\n\n    # By disabling `many_to_many` and `many_to_one`, accessing these fields will now\n    # generate a `SynchronousOnlyOperation` exception\n    return f\"{query.data.many_to_many_field} {query.data.foriegn_key_field_set}\"\n

Note: In Django's ORM design, the field name to access foreign keys is postfixed with _set by default.

Can I define async query functions?

Async functions are supported by use_query. You can use them in the same way as a sync query function.

However, be mindful of Django async ORM restrictions.

components.py
from channels.db import database_sync_to_async\nfrom example.models import TodoItem\nfrom reactpy import component, html\nfrom reactpy_django.hooks import use_query\n\n\nasync def get_items():\n    return await database_sync_to_async(TodoItem.objects.all)()\n\n\n@component\ndef todo_list():\n    item_query = use_query(get_items)\n\n    if item_query.loading:\n        rendered_items = html.h2(\"Loading...\")\n    elif item_query.error or not item_query.data:\n        rendered_items = html.h2(\"Error when loading!\")\n    else:\n        rendered_items = html.ul([html.li(item, key=item) for item in item_query.data])\n\n    return html.div(\"Rendered items: \", rendered_items)\n
Can I make ORM calls without hooks?

Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a SynchronousOnlyOperation exception.

These SynchronousOnlyOperation exceptions may be resolved in a future version of Django containing an asynchronous ORM. However, it is best practice to always perform ORM calls in the background via hooks.

"},{"location":"reference/hooks/#use-mutation","title":"Use Mutation","text":"

This hook is used to create, update, or delete Django ORM objects.

The mutation function you provide should have no return value.

components.pymodels.py
from example.models import TodoItem\nfrom reactpy import component, html\nfrom reactpy_django.hooks import use_mutation\n\n\ndef add_item(text: str):\n    TodoItem(text=text).save()\n\n\n@component\ndef todo_list():\n    item_mutation = use_mutation(add_item)\n\n    def submit_event(event):\n        if event[\"key\"] == \"Enter\":\n            item_mutation.execute(text=event[\"target\"][\"value\"])\n\n    if item_mutation.loading:\n        mutation_status = html.h2(\"Adding...\")\n    elif item_mutation.error:\n        mutation_status = html.h2(\"Error when adding!\")\n    else:\n        mutation_status = html.h2(\"Mutation done.\")\n\n    return html.div(\n        html.label(\"Add an item:\"),\n        html.input({\"type\": \"text\", \"onKeyDown\": submit_event}),\n        mutation_status,\n    )\n
from django.db.models import CharField, Model\n\n\nclass TodoItem(Model):\n    text: CharField = CharField(max_length=255)\n
See Interface

Parameters

Name Type Description Default mutate Callable[_Params, bool | None] A callable that performs Django ORM create, update, or delete functionality. If this function returns False, then your refetch function will not be used. N/A refetch Callable[..., Any] | Sequence[Callable[..., Any]] | None A query function (used by the use_query hook) or a sequence of query functions that will be called if the mutation succeeds. This is useful for refetching data after a mutation has been performed. None

Returns

Type Description Mutation[_Params] An object containing loading/error states, a reset callable that will set loading/error states to defaults, and a execute callable that will run the query. How can I provide arguments to my mutation function?

*args and **kwargs can be provided to your mutation function via #!python mutation.execute` parameters.

components.py
from reactpy import component\nfrom reactpy_django.hooks import use_mutation\n\n\ndef example_mutation(value: int, other_value: bool = False):\n    ...\n\n\n@component\ndef my_component():\n    mutation = use_mutation(example_mutation)\n\n    mutation.execute(123, other_value=True)\n\n    ...\n
Can use_mutation trigger a refetch of use_query?

Yes, use_mutation can queue a refetch of a use_query via the refetch=... argument.

The example below is a merge of the use_query and use_mutation examples above with the addition of a use_mutation(refetch=...) argument.

Please note that any use_query hooks that use get_items will be refetched upon a successful mutation.

components.pymodels.py
from example.models import TodoItem\nfrom reactpy import component, html\nfrom reactpy_django.hooks import use_mutation, use_query\n\n\ndef get_items():\n    return TodoItem.objects.all()\n\n\ndef add_item(text: str):\n    TodoItem(text=text).save()\n\n\n@component\ndef todo_list():\n    item_query = use_query(get_items)\n    item_mutation = use_mutation(add_item, refetch=get_items)\n\n    def submit_event(event):\n        if event[\"key\"] == \"Enter\":\n            item_mutation.execute(text=event[\"target\"][\"value\"])\n\n    # Handle all possible query states\n    if item_query.loading:\n        rendered_items = html.h2(\"Loading...\")\n    elif item_query.error or not item_query.data:\n        rendered_items = html.h2(\"Error when loading!\")\n    else:\n        rendered_items = html.ul(html.li(item, key=item) for item in item_query.data)\n\n    # Handle all possible mutation states\n    if item_mutation.loading:\n        mutation_status = html.h2(\"Adding...\")\n    elif item_mutation.error:\n        mutation_status = html.h2(\"Error when adding!\")\n    else:\n        mutation_status = html.h2(\"Mutation done.\")\n\n    return html.div(\n        html.label(\"Add an item:\"),\n        html.input({\"type\": \"text\", \"onKeyDown\": submit_event}),\n        mutation_status,\n        rendered_items,\n    )\n
from django.db.models import CharField, Model\n\n\nclass TodoItem(Model):\n    text: CharField = CharField(max_length=255)\n
Can I make a failed use_mutation try again?

Yes, a use_mutation can be re-performed by calling reset() on your use_mutation instance.

For example, take a look at reset_event below.

components.pymodels.py
from example.models import TodoItem\nfrom reactpy import component, html\nfrom reactpy_django.hooks import use_mutation\n\n\ndef add_item(text: str):\n    TodoItem(text=text).save()\n\n\n@component\ndef todo_list():\n    item_mutation = use_mutation(add_item)\n\n    def reset_event(event):\n        item_mutation.reset()\n\n    def submit_event(event):\n        if event[\"key\"] == \"Enter\":\n            item_mutation.execute(text=event[\"target\"][\"value\"])\n\n    if item_mutation.loading:\n        mutation_status = html.h2(\"Adding...\")\n    elif item_mutation.error:\n        mutation_status = html.button({\"onClick\": reset_event}, \"Error: Try again!\")\n    else:\n        mutation_status = html.h2(\"Mutation done.\")\n\n    return html.div(\n        html.label(\"Add an item:\"),\n        html.input({\"type\": \"text\", \"onKeyDown\": submit_event}),\n        mutation_status,\n    )\n
from django.db.models import CharField, Model\n\n\nclass TodoItem(Model):\n    text: CharField = CharField(max_length=255)\n
Can I make ORM calls without hooks?

Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a SynchronousOnlyOperation exception.

These SynchronousOnlyOperation exceptions may be resolved in a future version of Django containing an asynchronous ORM. However, it is best practice to always perform ORM calls in the background via hooks.

"},{"location":"reference/hooks/#use-connection","title":"Use Connection","text":"

This hook is used to fetch the Django Channels WebSocket.

components.py
from reactpy import component, html\nfrom reactpy_django.hooks import use_connection\n\n\n@component\ndef my_component():\n    my_connection = use_connection()\n    return html.div(str(my_connection))\n
See Interface

Parameters

None

Returns

Type Description Connection The component's WebSocket."},{"location":"reference/hooks/#use-scope","title":"Use Scope","text":"

This is a shortcut that returns the WebSocket's scope.

components.py
from reactpy import component, html\nfrom reactpy_django.hooks import use_scope\n\n\n@component\ndef my_component():\n    my_scope = use_scope()\n    return html.div(str(my_scope))\n
See Interface

Parameters

None

Returns

Type Description MutableMapping[str, Any] The WebSocket's scope."},{"location":"reference/hooks/#use-location","title":"Use Location","text":"

This is a shortcut that returns the WebSocket's path.

You can expect this hook to provide strings such as /reactpy/my_path.

components.py
from reactpy import component, html\nfrom reactpy_django.hooks import use_location\n\n\n@component\ndef my_component():\n    my_location = use_location()\n    return html.div(str(my_location))\n
See Interface

Parameters

None

Returns

Type Description Location An object containing the current URL's pathname and search query. This hook's behavior will be changed in a future update

This hook will be updated to return the browser's currently active HTTP path. This change will come in alongside ReactPy URL routing support.

Check out reactive-python/reactpy-django#147 for more information.

"},{"location":"reference/hooks/#use-origin","title":"Use Origin","text":"

This is a shortcut that returns the WebSocket's origin.

You can expect this hook to provide strings such as http://example.com.

components.py
from reactpy import component, html\nfrom reactpy_django.hooks import use_origin\n\n\n@component\ndef my_component():\n    my_origin = use_origin()\n    return html.div(my_origin or \"No origin\")\n
See Interface

Parameters

None

Returns

Type Description str | None A string containing the browser's current origin, obtained from WebSocket headers (if available)."},{"location":"reference/settings/","title":"Settings","text":""},{"location":"reference/settings/#overview","title":"Overview","text":"

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

The default configuration of ReactPy is suitable for the vast majority of use cases.

You should only consider changing settings when the necessity arises.

"},{"location":"reference/settings/#general-settings","title":"General Settings","text":""},{"location":"reference/settings/#reactpy_url_prefix","title":"REACTPY_URL_PREFIX","text":"

Default: \"reactpy/\"

Example Value(s): \"rp/\", \"render/reactpy/\"

The prefix used for all ReactPy WebSocket and HTTP URLs.

"},{"location":"reference/settings/#reactpy_default_query_postprocessor","title":"REACTPY_DEFAULT_QUERY_POSTPROCESSOR","text":"

Default: \"reactpy_django.utils.django_query_postprocessor\"

Example Value(s): \"example_project.postprocessor\", None

Dotted path to the default reactpy_django.hooks.use_query postprocessor function.

Postprocessor functions can be async or sync. Here is an example of a sync postprocessor function:

def postprocessor(data):\n    del data[\"foo\"]\n    return data\n

Set REACTPY_DEFAULT_QUERY_POSTPROCESSOR to None to disable the default postprocessor.

"},{"location":"reference/settings/#reactpy_auth_backend","title":"REACTPY_AUTH_BACKEND","text":"

Default: \"django.contrib.auth.backends.ModelBackend\"

Example Value(s): \"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 AuthMiddlewareStack and...
  2. You are using Django's AUTHENTICATION_BACKENDS setting and...
  3. Your Django user model does not define a backend attribute.
"},{"location":"reference/settings/#performance-settings","title":"Performance Settings","text":""},{"location":"reference/settings/#reactpy_database","title":"REACTPY_DATABASE","text":"

Default: \"default\"

Example Value(s): \"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:

DATABASE_ROUTERS = [\"reactpy_django.database.Router\", ...]\n
"},{"location":"reference/settings/#reactpy_cache","title":"REACTPY_CACHE","text":"

Default: \"default\"

Example Value(s): \"my-reactpy-cache\"

Cache used by ReactPy, typically for file operations.

We recommend configuring redis, python-diskcache, or LocMemCache.

"},{"location":"reference/settings/#reactpy_backhaul_thread","title":"REACTPY_BACKHAUL_THREAD","text":"

Default: False

Example Value(s): 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 and uvicorn.

"},{"location":"reference/settings/#reactpy_default_hosts","title":"REACTPY_DEFAULT_HOSTS","text":"

Default: None

Example Value(s): [\"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 host argument in your template tag to manually override this default.

"},{"location":"reference/settings/#reactpy_prerender","title":"REACTPY_PRERENDER","text":"

Default: False

Example Value(s): 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 connection related hooks use HTTP.
  3. 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 prerender argument in your template tag to manually override this default.

"},{"location":"reference/settings/#stability-settings","title":"Stability Settings","text":""},{"location":"reference/settings/#reactpy_reconnect_interval","title":"REACTPY_RECONNECT_INTERVAL","text":"

Default: 750

Example Value(s): 100, 2500, 6000

Milliseconds between client reconnection attempts.

"},{"location":"reference/settings/#reactpy_reconnect_backoff_multiplier","title":"REACTPY_RECONNECT_BACKOFF_MULTIPLIER","text":"

Default: 1.25

Example Value(s): 1, 1.5, 3

On each reconnection attempt, the 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 1.

"},{"location":"reference/settings/#reactpy_reconnect_max_interval","title":"REACTPY_RECONNECT_MAX_INTERVAL","text":"

Default: 60000

Example Value(s): 10000, 25000, 900000

Maximum milliseconds between client reconnection attempts.

This allows setting an upper bound on how high REACTPY_RECONNECT_BACKOFF_MULTIPLIER can increase the time between reconnection attempts.

"},{"location":"reference/settings/#reactpy_reconnect_max_retries","title":"REACTPY_RECONNECT_MAX_RETRIES","text":"

Default: 150

Example Value(s): 0, 5, 300

Maximum number of reconnection attempts before the client gives up.

"},{"location":"reference/settings/#reactpy_session_max_age","title":"REACTPY_SESSION_MAX_AGE","text":"

Default: 259200

Example Value(s): 0, 60, 96000

Maximum seconds to store ReactPy component sessions.

ReactPy sessions include data such as *args and **kwargs passed into your {% component %} template tag.

Use 0 to not store any session data.

"},{"location":"reference/template-tag/","title":"Template Tag","text":""},{"location":"reference/template-tag/#overview","title":"Overview","text":"

Django template tags can be used within your HTML templates to provide ReactPy features.

"},{"location":"reference/template-tag/#component","title":"Component","text":"

This template tag can be used to insert any number of ReactPy components onto your page.

my-template.html
{% load reactpy %}\n<!DOCTYPE html>\n<html>\n  <body>\n{% component \"example_project.my_app.components.hello_world\" recipient=\"World\" %}\n  </body>\n</html>\n
See Interface

Parameters

Name Type Description Default dotted_path str The dotted path to the component to render. N/A *args Any The positional arguments to provide to the component. N/A class str | None The HTML class to apply to the top-level component div. None key Any Force the component's root node to use a specific key value. Using key within a template tag is effectively useless. None host 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 None prerender str If \"True\", the component will pre-rendered, which enables SEO compatibility and reduces perceived latency. \"False\" **kwargs Any The keyword arguments to provide to the component. N/A

Returns

Type Description Component A ReactPy component. Do not use context variables for the component path

The ReactPy component finder (reactpy_django.utils.RootComponentFinder) requires that your component path is a string.

Do not use Django template/context variables for the component path. Failure to follow this warning can result in unexpected behavior, such as components that will not render.

For example, do not do the following:

my-template.htmlviews.py
<!-- This is good -->\n{% component \"example_project.my_app.components.hello_world\" recipient=\"World\" %}\n\n<!-- This is bad -->\n{% component my_variable recipient=\"World\" %}\n
from django.shortcuts import render\n\n\ndef example_view(request):\n    context_vars = {\"my_variable\": \"example_project.my_app.components.hello_world\"}\n    return render(request, \"my-template.html\", context_vars)\n
Can I render components on a different server (distributed computing)?

Yes! By using the host keyword argument, you can render components from a completely separate ASGI server.

my-template.html
...\n{% component \"example_project.my_app.components.do_something\" host=\"127.0.0.1:8001\" %}\n...\n

This configuration most commonly involves you deploying multiple instances of your project. But, you can also create dedicated Django project(s) that only render specific ReactPy components if you wish.

Here's a couple of things to keep in mind:

  1. If your host address are completely separate ( origin1.com != origin2.com ) you will need to configure CORS headers on your main application during deployment.
  2. You will not need to register ReactPy HTTP or WebSocket paths on any applications that do not perform any component rendering.
  3. Your component will only be able to access your template tag's *args/**kwargs if your applications share a common database.
Can I use multiple components on one page?

You can add as many components to a webpage as needed by using the template tag multiple times. Retrofitting legacy sites to use ReactPy will typically involve many components on one page.

my-template.html
{% load reactpy %}\n<!DOCTYPE html>\n<html>\n    <body>\n        <h1>{% component \"example_project.my_app.components.my_title\" %}</h1>\n        <p>{% component \"example_project.my_app_2.components.goodbye_world\" class=\"bold small-font\" %}</p>\n{% component \"example_project.my_app_3.components.simple_button\" %}\n    </body>\n</html>\n

Please note that components separated like this will not be able to interact with each other, except through database queries.

Additionally, in scenarios where you are trying to create a Single Page Application (SPA) within Django, you will only have one component within your <body> tag.

Can I use positional arguments instead of keyword arguments?

You can use any combination of *args/**kwargs in your template tag.

my-template.htmlcomponents.py
{% component \"example_project.my_app.components.frog_greeter\" 123 \"Mr. Froggles\" species=\"Grey Treefrog\" %}\n
from reactpy import component\n\n\n@component\ndef frog_greeter(number, name, species=\"\"):\n    return f\"Hello #{number}, {name} the {species}!\"\n
"},{"location":"reference/utils/","title":"Utilities","text":""},{"location":"reference/utils/#overview","title":"Overview","text":"

Utility functions provide various miscellaneous functionality. These are typically not used, but are available for advanced use cases.

"},{"location":"reference/utils/#django-query-postprocessor","title":"Django Query Postprocessor","text":"

This is the default postprocessor for the use_query hook.

This postprocessor is designed to avoid Django's SynchronousOnlyException by recursively fetching all fields within a Model or QuerySet to prevent lazy execution.

components.pymodels.py
from example.models import TodoItem\nfrom reactpy import component\nfrom reactpy_django.hooks import use_query\nfrom reactpy_django.types import QueryOptions\nfrom reactpy_django.utils import django_query_postprocessor\n\n\ndef get_items():\n    return TodoItem.objects.all()\n\n\n@component\ndef todo_list():\n    # These `QueryOptions` are functionally equivalent to ReactPy-Django's default values\n    item_query = use_query(\n        QueryOptions(\n            postprocessor=django_query_postprocessor,\n            postprocessor_kwargs={\"many_to_many\": True, \"many_to_one\": True},\n        ),\n        get_items,\n    )\n\n    return item_query.data\n
from django.db.models import CharField, Model\n\n\nclass TodoItem(Model):\n    text: CharField = CharField(max_length=255)\n
See Interface

Parameters

Name Type Description Default data QuerySet | Model The Model or QuerySet to recursively fetch fields from. N/A many_to_many bool Whether or not to recursively fetch ManyToManyField relationships. True many_to_one bool Whether or not to recursively fetch ForeignKey relationships. True

Returns

Type Description QuerySet | Model The Model or QuerySet with all fields fetched."},{"location":"reference/utils/#register-component","title":"Register Component","text":"

This function is used manually register a root component with ReactPy.

apps.py
from django.apps import AppConfig\nfrom reactpy_django.utils import register_component\n\n\nclass ExampleConfig(AppConfig):\n    def ready(self):\n        # Add components to the ReactPy component registry when Django is ready\n        register_component(\"example_project.my_app.components.hello_world\")\n
Only use this within MyAppConfig.ready()

You should always call register_component within a Django MyAppConfig.ready() method. This ensures you will retain multiprocessing compatibility, such as with ASGI web server workers.

Do I need to use this?

You typically will not need to use this function.

For security reasons, ReactPy does not allow non-registered components to be root components. However, all components contained within Django templates are automatically considered root components.

This is typically only needed when you have a dedicated Django application as a rendering server that doesn't have templates, such as when modifying the template tag host argument. On this dedicated rendering server, you would need to manually register your components.

"}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"about/changelog/","title":"Changelog","text":"

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

"},{"location":"about/changelog/#unreleased","title":"Unreleased","text":""},{"location":"about/changelog/#added","title":"Added","text":"
  • ReactPy components can now use SEO compatible rendering!
    • settings.py:REACTPY_PRERENDER can be set to True to enable this behavior by default
    • Or, you can enable it on individual components via the template tag: {% component \"...\" prerender=\"True\" %}
"},{"location":"about/changelog/#changed","title":"Changed","text":"
  • Renamed undocumented utility function reactpy_django.utils.ComponentPreloader to reactpy_django.utils.RootComponentFinder.
"},{"location":"about/changelog/#351-2023-09-07","title":"3.5.1 - 2023-09-07","text":""},{"location":"about/changelog/#added_1","title":"Added","text":"
  • Warning W018 (Suspicious position of 'reactpy_django' in INSTALLED_APPS) has been added.
"},{"location":"about/changelog/#changed_1","title":"Changed","text":"
  • The default postprocessor can now disabled by setting REACTPY_DEFAULT_QUERY_POSTPROCESSOR to None.
  • Massive overhaul of docs styling.
"},{"location":"about/changelog/#350-2023-08-26","title":"3.5.0 - 2023-08-26","text":""},{"location":"about/changelog/#added_2","title":"Added","text":"
  • More customization for reconnection behavior through new settings!
    • REACTPY_RECONNECT_INTERVAL
    • REACTPY_RECONNECT_MAX_INTERVAL
    • REACTPY_RECONNECT_MAX_RETRIES
    • REACTPY_RECONNECT_BACKOFF_MULTIPLIER
  • ReactPy-Django docs are now version controlled via mike!
"},{"location":"about/changelog/#changed_2","title":"Changed","text":"
  • Bumped the minimum ReactPy version to 1.0.2.
  • Prettier WebSocket URLs for components that do not have sessions.
  • Template tag will now only validate args/kwargs if settings.py:DEBUG is enabled.
  • Bumped the minimum @reactpy/client version to 0.3.1
  • Bumped the minimum Django version to 4.2.
  • Use TypeScript instead of JavaScript for this repository.
    • Note: ReactPy-Django will continue bumping minimum Django requirements to versions that increase async support. This \"latest-only\" trend will continue until Django has all async features that ReactPy benefits from. After this point, ReactPy-Django will begin supporting all maintained Django versions.
"},{"location":"about/changelog/#removed","title":"Removed","text":"
  • settings.py:REACTPY_RECONNECT_MAX is removed. See the docs for the new REACTPY_RECONNECT_* settings.
"},{"location":"about/changelog/#340-2023-08-18","title":"3.4.0 - 2023-08-18","text":""},{"location":"about/changelog/#added_3","title":"Added","text":"
  • Distributed Computing: ReactPy components can now optionally be rendered by a completely separate server!
    • REACTPY_DEFAULT_HOSTS setting can round-robin a list of ReactPy rendering hosts.
    • host argument has been added to the component template tag to force components to render on a specific host.
  • reactpy_django.utils.register_component function can manually register root components.
    • Useful if you have dedicated ReactPy rendering application(s) that do not use HTML templates.
"},{"location":"about/changelog/#changed_3","title":"Changed","text":"
  • ReactPy will now provide a warning if your HTTP URLs are not on the same prefix as your WebSockets.
  • Cleaner logging output for auto-detected ReactPy root components.
"},{"location":"about/changelog/#deprecated","title":"Deprecated","text":"
  • reactpy_django.REACTPY_WEBSOCKET_PATH is deprecated. The identical replacement is REACTPY_WEBSOCKET_ROUTE.
  • settings.py:REACTPY_WEBSOCKET_URL is deprecated. The similar replacement is REACTPY_URL_PREFIX.
"},{"location":"about/changelog/#removed_1","title":"Removed","text":"
  • Warning W007 (REACTPY_WEBSOCKET_URL doesn't end with a slash) has been removed. ReactPy now automatically handles slashes.
  • Warning W008 (REACTPY_WEBSOCKET_URL doesn't start with an alphanumeric character) has been removed. ReactPy now automatically handles this scenario.
  • Error E009 (channels is not in settings.py:INSTALLED_APPS) has been removed. Newer versions of channels do not require installation via INSTALLED_APPS to receive an ASGI web server.
"},{"location":"about/changelog/#332-2023-08-13","title":"3.3.2 - 2023-08-13","text":""},{"location":"about/changelog/#added_4","title":"Added","text":"
  • ReactPy WebSocket will now decode messages via orjson resulting in an ~6% overall performance improvement.
  • Built-in asyncio event loops are now patched via nest_asyncio, resulting in an ~10% overall performance improvement. This has no performance impact if you are running your web server with uvloop.
"},{"location":"about/changelog/#fixed","title":"Fixed","text":"
  • Fix bug where REACTPY_WEBSOCKET_URL always generates a warning if unset.
  • Fixed bug on Windows where assert f is self._write_fut would be raised by uvicorn when REACTPY_BACKHAUL_THREAD = True.
  • Fixed bug on Windows where rendering behavior would be jittery with daphne when REACTPY_BACKHAUL_THREAD = True.
"},{"location":"about/changelog/#331-2023-08-08","title":"3.3.1 - 2023-08-08","text":""},{"location":"about/changelog/#added_5","title":"Added","text":"
  • Additional system checks for ReactPy misconfigurations.
"},{"location":"about/changelog/#changed_4","title":"Changed","text":"
  • REACTPY_BACKHAUL_THREAD now defaults to False.
"},{"location":"about/changelog/#330-2023-08-05","title":"3.3.0 - 2023-08-05","text":""},{"location":"about/changelog/#added_6","title":"Added","text":"
  • Added system checks for a variety of common ReactPy misconfigurations.
  • REACTPY_BACKHAUL_THREAD setting to enable/disable threading behavior.
"},{"location":"about/changelog/#changed_5","title":"Changed","text":"
  • If using settings.py:REACTPY_DATABASE, reactpy_django.database.Router must now be registered in settings.py:DATABASE_ROUTERS.
  • By default, ReactPy will now use a backhaul thread to increase performance.
  • Minimum Python version required is now 3.9
  • A thread-safe cache is no longer required.
"},{"location":"about/changelog/#321-2023-06-29","title":"3.2.1 - 2023-06-29","text":""},{"location":"about/changelog/#added_7","title":"Added","text":"
  • Template tag exception details are now rendered on the webpage when settings.py:DEBUG is enabled.
"},{"location":"about/changelog/#fixed_1","title":"Fixed","text":"
  • Prevent exceptions within the component template tag from causing the whole template to fail to render.
"},{"location":"about/changelog/#320-2023-06-08","title":"3.2.0 - 2023-06-08","text":""},{"location":"about/changelog/#added_8","title":"Added","text":"
  • Added warning if poor system/cache/database performance is detected while in DEBUG mode.
  • Added REACTPY_AUTH_BACKEND setting to allow for custom authentication backends.
"},{"location":"about/changelog/#changed_6","title":"Changed","text":"
  • Using SessionMiddlewareStack is now optional.
  • Using AuthMiddlewareStack is now optional.
"},{"location":"about/changelog/#310-2023-05-06","title":"3.1.0 - 2023-05-06","text":""},{"location":"about/changelog/#added_9","title":"Added","text":"
  • use_query now supports async functions.
  • use_mutation now supports async functions.
  • reactpy_django.types.QueryOptions.thread_sensitive option to customize how sync queries are executed.
  • reactpy_django.hooks.use_mutation now accepts reactpy_django.types.MutationOptions option to customize how mutations are executed.
"},{"location":"about/changelog/#changed_7","title":"Changed","text":"
  • The mutate argument on reactpy_django.hooks.use_mutation has been renamed to mutation.
"},{"location":"about/changelog/#fixed_2","title":"Fixed","text":"
  • Fix bug where ReactPy utilizes Django's default cache timeout, which can prematurely expire the component cache.
"},{"location":"about/changelog/#301-2023-04-06","title":"3.0.1 - 2023-04-06","text":""},{"location":"about/changelog/#changed_8","title":"Changed","text":"
  • django-reactpy database entries are no longer cleaned during Django application startup. Instead, it will occur on webpage loads if REACTPY_RECONNECT_MAX seconds has elapsed since the last cleaning.
"},{"location":"about/changelog/#300-reactpy-2023-03-30","title":"3.0.0-reactpy - 2023-03-30","text":""},{"location":"about/changelog/#changed_9","title":"Changed","text":"
  • django-idom has been renamed to reactpy-django! Please note that all references to the word idom in your code should be changed to reactpy. See the docs for more details.
"},{"location":"about/changelog/#300-2023-03-08","title":"3.0.0 - 2023-03-08","text":"Note

This is Django-IDOM's biggest update yet!

To upgrade from previous version you will need to...

  1. Install django-idom >= 3.0.0
  2. Run idom rewrite-keys <DIR> and idom rewrite-camel-case-props <DIR> to update your idom.html.* calls to the new syntax
  3. Run python manage.py migrate to create the new Django-IDOM database entries
"},{"location":"about/changelog/#added_10","title":"Added","text":"
  • The idom client will automatically configure itself to debug mode depending on settings.py:DEBUG.
  • use_connection hook for returning the browser's active Connection.
  • IDOM_CACHE is now configurable within settings.py to whatever cache name you wish.
"},{"location":"about/changelog/#changed_10","title":"Changed","text":"
  • It is now mandatory to run manage.py migrate after installing IDOM.
  • Bumped the minimum IDOM version to 1.0.0. Due to IDOM 1.0.0, idom.html.*...
    • HTML properties can now be snake_case. For example className now becomes class_name.
    • key=... is now declared within the props dict (rather than as a kwarg).
  • The component template tag now supports both positional and keyword arguments.
  • The component template tag now supports non-serializable arguments.
  • IDOM_WS_MAX_RECONNECT_TIMEOUT setting has been renamed to IDOM_RECONNECT_MAX.
"},{"location":"about/changelog/#removed_2","title":"Removed","text":"
  • django_idom.hooks.use_websocket has been removed. The similar replacement is django_idom.hooks.use_connection.
  • django_idom.types.IdomWebsocket has been removed. The similar replacement is django_idom.types.Connection.
  • settings.py:CACHE['idom'] is no longer used by default. The name of the cache back-end must now be specified with the IDOM_CACHE setting.
"},{"location":"about/changelog/#fixed_3","title":"Fixed","text":"
  • view_to_component will now retain the contents of a <head> tag when rendering.
  • React client is now set to production rather than development.
  • use_query will now utilize field.related_name when postprocessing many-to-one relationships.
"},{"location":"about/changelog/#security","title":"Security","text":"
  • Fixed a potential method of component template tag argument spoofing.
  • Exception information will no longer be displayed on the page, based on the value of settings.py:DEBUG.
"},{"location":"about/changelog/#221-2023-01-09","title":"2.2.1 - 2023-01-09","text":""},{"location":"about/changelog/#fixed_4","title":"Fixed","text":"
  • Fixed bug where use_query would not recursively fetch many-to-one relationships.
  • IDOM preloader will now print out the exception stack when failing to import a module.
"},{"location":"about/changelog/#220-2022-12-28","title":"2.2.0 - 2022-12-28","text":""},{"location":"about/changelog/#added_11","title":"Added","text":"
  • Add options: QueryOptions parameter to use_query to allow for configuration of this hook.
"},{"location":"about/changelog/#changed_11","title":"Changed","text":"
  • By default, use_query will recursively prefetch all many-to-many or many-to-one relationships to prevent SynchronousOnlyOperation exceptions.
"},{"location":"about/changelog/#removed_3","title":"Removed","text":"
  • django_idom.hooks._fetch_lazy_fields has been deleted. The equivalent replacement is django_idom.utils.django_query_postprocessor.
"},{"location":"about/changelog/#210-2022-11-01","title":"2.1.0 - 2022-11-01","text":""},{"location":"about/changelog/#changed_12","title":"Changed","text":"
  • Minimum channels version is now 4.0.0.
"},{"location":"about/changelog/#fixed_5","title":"Fixed","text":"
  • Change type hint on view_to_component callable to have request argument be optional.
  • Change type hint on view_to_component to represent it as a decorator with parenthesis (such as @view_to_component(compatibility=True))
"},{"location":"about/changelog/#security_1","title":"Security","text":"
  • Add note to docs about potential information exposure via view_to_component when using compatibility=True.
"},{"location":"about/changelog/#201-2022-10-18","title":"2.0.1 - 2022-10-18","text":""},{"location":"about/changelog/#fixed_6","title":"Fixed","text":"
  • Ability to use key=... parameter on all prefabricated components.
"},{"location":"about/changelog/#200-2022-10-17","title":"2.0.0 - 2022-10-17","text":""},{"location":"about/changelog/#added_12","title":"Added","text":"
  • use_origin hook for returning the browser's location.origin.
"},{"location":"about/changelog/#changed_13","title":"Changed","text":"
  • view_to_component now returns a Callable, instead of directly returning a Component. Check the docs for new usage info.
  • use_mutation and use_query will now log any query failures.
"},{"location":"about/changelog/#fixed_7","title":"Fixed","text":"
  • Allow use_mutation to have refetch=None, as the docs suggest is possible.
  • use_query will now prefetch all fields to prevent SynchronousOnlyOperation exceptions.
  • view_to_component, django_css, and django_js type hints will now display like normal functions.
  • IDOM preloader no longer attempts to parse commented out IDOM components.
  • Tests are now fully functional on Windows
"},{"location":"about/changelog/#120-2022-09-19","title":"1.2.0 - 2022-09-19","text":""},{"location":"about/changelog/#added_13","title":"Added","text":"
  • auth_required decorator to prevent your components from rendering to unauthenticated users.
  • use_query hook for fetching database values.
  • use_mutation hook for modifying database values.
  • view_to_component utility to convert legacy Django views to IDOM components.
"},{"location":"about/changelog/#changed_14","title":"Changed","text":"
  • Bumped the minimum IDOM version to 0.40.2
  • Testing suite now uses playwright instead of selenium
"},{"location":"about/changelog/#fixed_8","title":"Fixed","text":"
  • IDOM preloader is no longer sensitive to whitespace within template tags.
"},{"location":"about/changelog/#110-2022-07-01","title":"1.1.0 - 2022-07-01","text":""},{"location":"about/changelog/#added_14","title":"Added","text":"
  • django_css and django_js components to defer loading CSS & JS files until needed.
"},{"location":"about/changelog/#changed_15","title":"Changed","text":"
  • Bumped the minimum IDOM version to 0.39.0
"},{"location":"about/changelog/#100-2022-05-22","title":"1.0.0 - 2022-05-22","text":""},{"location":"about/changelog/#added_15","title":"Added","text":"
  • Django specific hooks! use_websocket, use_scope, and use_location are now available within the django_idom.hooks module.
  • Documentation has been placed into a formal docs webpage.
  • Logging for when a component fails to import, or if no components were found within Django.
"},{"location":"about/changelog/#changed_16","title":"Changed","text":"
  • idom_component template tag has been renamed to component
  • Bumped the minimum IDOM version to 0.38.0
"},{"location":"about/changelog/#removed_4","title":"Removed","text":"
  • websocket parameter for components has been removed. Functionally, it is replaced with django_idom.hooks.use_websocket.
"},{"location":"about/changelog/#005-2022-04-04","title":"0.0.5 - 2022-04-04","text":""},{"location":"about/changelog/#changed_17","title":"Changed","text":"
  • Bumped the minimum IDOM version to 0.37.2
"},{"location":"about/changelog/#fixed_9","title":"Fixed","text":"
  • ModuleNotFoundError: No module named idom.core.proto caused by IDOM 0.37.2
"},{"location":"about/changelog/#004-2022-03-05","title":"0.0.4 - 2022-03-05","text":""},{"location":"about/changelog/#changed_18","title":"Changed","text":"
  • Bumped the minimum IDOM version to 0.37.1
"},{"location":"about/changelog/#003-2022-02-19","title":"0.0.3 - 2022-02-19","text":""},{"location":"about/changelog/#changed_19","title":"Changed","text":"
  • Bumped the minimum IDOM version to 0.36.3
"},{"location":"about/changelog/#002-2022-01-30","title":"0.0.2 - 2022-01-30","text":""},{"location":"about/changelog/#added_16","title":"Added","text":"
  • Ability to declare the HTML class of the top-level component div
  • name = ... parameter to IDOM HTTP paths for use with django.urls.reverse()
  • Cache versioning to automatically invalidate old web module files from the cache back-end
  • Automatic pre-population of the IDOM component registry
  • Type hinting for IdomWebsocket
"},{"location":"about/changelog/#changed_20","title":"Changed","text":"
  • Fetching web modules from disk and/or cache is now fully async
  • Static files are now contained within a django_idom/ parent folder
  • Upgraded IDOM to version 0.36.0
  • Minimum Django version required is now 4.0
  • Minimum Python version required is now 3.8
"},{"location":"about/changelog/#removed_5","title":"Removed","text":"
  • IDOM_WEB_MODULES_PATH has been replaced with Django include(...)
  • IDOM_WS_MAX_RECONNECT_DELAY has been renamed to IDOM_WS_MAX_RECONNECT_TIMEOUT
  • idom_web_modules cache back-end has been renamed to idom
"},{"location":"about/changelog/#fixed_10","title":"Fixed","text":"
  • Increase test timeout values to prevent false positives
  • Windows compatibility for building Django-IDOM
"},{"location":"about/changelog/#security_2","title":"Security","text":"
  • Fixed potential directory traversal attack on the IDOM web modules URL
"},{"location":"about/changelog/#001-2021-08-18","title":"0.0.1 - 2021-08-18","text":""},{"location":"about/changelog/#added_17","title":"Added","text":"
  • Support for IDOM within the Django
"},{"location":"about/code/","title":"Code","text":""},{"location":"about/code/#overview","title":"Overview","text":"

You will need to set up a Python environment to develop ReactPy-Django.

Note

Looking to contribute features that are not Django specific?

Everything within the reactpy-django repository must be specific to Django integration. Check out the ReactPy Core documentation to contribute general features such as components, hooks, and events.

"},{"location":"about/code/#creating-an-environment","title":"Creating an environment","text":"

If you plan to make code changes to this repository, you will need to install the following dependencies first:

  • Python 3.9+
  • Git
  • NPM for installing and managing Javascript

Once done, you should clone this repository:

git clone https://github.com/reactive-python/reactpy-django.git\ncd reactpy-django\n

Then, by running the command below you can:

  • Install an editable version of the Python code
  • Download, build, and install Javascript dependencies
pip install -e . -r requirements.txt --verbose --upgrade\n

Pitfall

Some of our development dependencies require a C++ compiler, which is not installed by default on Windows.

If you receive errors related to this during installation, follow the instructions in your console errors.

Finally, to verify that everything is working properly, you can manually run the test web server.

cd tests\npython manage.py runserver\n

Navigate to http://127.0.0.1:8000 to see if the tests are rendering correctly.

"},{"location":"about/code/#creating-a-pull-request","title":"Creating a pull request","text":"

Now, you can create/modify the ReactPy-Django source code, and Pull Request (PR) your changes to our GitHub repository.

To learn how to create GitHub PRs, click here.

"},{"location":"about/code/#running-the-full-test-suite","title":"Running the full test suite","text":"

Note

This repository uses Nox to run tests. For a full test of available scripts run nox -l.

By running the command below you can run the full test suite:

nox -s test\n

Or, if you want to run the tests in the background:

nox -s test -- --headless\n
"},{"location":"about/code/#running-django-tests","title":"Running Django tests","text":"

If you want to only run our Django tests in your current environment, you can use the following command:

cd tests\npython manage.py test\n
"},{"location":"about/code/#running-django-test-web-server","title":"Running Django test web server","text":"

If you want to manually run the Django test application, you can use the following command:

cd tests\npython manage.py runserver\n
"},{"location":"about/docs/","title":"Docs","text":""},{"location":"about/docs/#overview","title":"Overview","text":"

You will need to set up a Python environment to create, test, and preview docs changes.

"},{"location":"about/docs/#modifying-docs","title":"Modifying Docs","text":"

If you plan to make changes to this documentation, you will need to install the following dependencies first:

  • Python 3.9+
  • Git

Once done, you should clone this repository:

git clone https://github.com/reactive-python/reactpy-django.git\ncd reactpy-django\n

Then, by running the command below you can:

  • Install an editable version of the documentation
  • Self-host a test server for the documentation
pip install -r requirements.txt --upgrade\n

Finally, to verify that everything is working properly, you can manually run the docs preview web server.

mkdocs serve\n

Navigate to http://127.0.0.1:8000 to view a preview of the documentation.

"},{"location":"about/docs/#github-pull-request","title":"GitHub Pull Request","text":"

Now, you can create/modify the ReactPy-Django source code, and Pull Request (PR) your changes to our GitHub repository.

To learn how to create GitHub PRs, click here.

"},{"location":"about/license/","title":"License","text":""},{"location":"about/license/#the-mit-license-mit","title":"The MIT License (MIT)","text":""},{"location":"about/license/#copyright-c-reactive-python-and-affiliates","title":"Copyright (c) Reactive Python and affiliates.","text":"

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

"},{"location":"learn/add-reactpy-to-a-django-project/","title":"Add ReactPy to a Django Project","text":""},{"location":"learn/add-reactpy-to-a-django-project/#overview","title":"Overview","text":"

If you want to add some interactivity to your existing Django project, you don't have to rewrite it in ReactPy. Use ReactPy-Django to add ReactPy to your existing stack, and render interactive components anywhere.

Note

These docs assumes you have already created a Django project, which involves creating and installing at least one Django app.

If do not have a Django project, check out this 9 minute YouTube tutorial created by IDG TECHtalk.

"},{"location":"learn/add-reactpy-to-a-django-project/#step-1-install-from-pypi","title":"Step 1: Install from PyPI","text":"

Run the following command to install reactpy-django in your Python environment.

pip install reactpy-django\n
"},{"location":"learn/add-reactpy-to-a-django-project/#step-2-configure-settingspy","title":"Step 2: Configure settings.py","text":"

Add \"reactpy_django\" to INSTALLED_APPS in your settings.py file.

settings.py
INSTALLED_APPS = [\n    ...,\n    \"reactpy_django\",\n]\n
Enable ASGI and Django Channels (Required)

ReactPy-Django requires Django ASGI and Django Channels WebSockets.

If you have not enabled ASGI on your Django project yet, here is a summary of the django and channels installation docs:

  1. Install channels[daphne]
  2. Add \"daphne\" to INSTALLED_APPS.

    INSTALLED_APPS = [\n    \"daphne\",\n    ...,\n]\n
  3. Set your ASGI_APPLICATION variable.

    ASGI_APPLICATION = \"example_project.asgi.application\"\n
Configure ReactPy settings (Optional)

ReactPy's has additional configuration available to fit a variety of use cases.

See the ReactPy settings documentation to learn more.

"},{"location":"learn/add-reactpy-to-a-django-project/#step-3-configure-urlspy","title":"Step 3: Configure urls.py","text":"

Add ReactPy HTTP paths to your urlpatterns in your urls.py file.

urls.py
from django.urls import include, path\n\nurlpatterns = [\n    ...,\n    path(\"reactpy/\", include(\"reactpy_django.http.urls\")),\n]\n
"},{"location":"learn/add-reactpy-to-a-django-project/#step-4-configure-asgipy","title":"Step 4: Configure asgi.py","text":"

Register ReactPy's WebSocket using REACTPY_WEBSOCKET_ROUTE in your asgi.py file.

asgi.py
import os\n\nfrom django.core.asgi import get_asgi_application\n\n# Ensure DJANGO_SETTINGS_MODULE is set properly based on your project name!\nos.environ.setdefault(\"DJANGO_SETTINGS_MODULE\", \"example_project.settings\")\n\n# Fetch ASGI application before importing dependencies that require ORM models.\ndjango_asgi_app = get_asgi_application()\n\n\nfrom channels.routing import ProtocolTypeRouter, URLRouter  # noqa: E402\nfrom reactpy_django import REACTPY_WEBSOCKET_ROUTE  # noqa: E402\n\napplication = ProtocolTypeRouter(\n    {\n        \"http\": django_asgi_app,\n        \"websocket\": URLRouter([REACTPY_WEBSOCKET_ROUTE]),\n    }\n)\n
Add AuthMiddlewareStack and SessionMiddlewareStack (Optional)

There are many situations where you need to access the Django User or Session objects within ReactPy components. For example, if you want to:

  1. Access the User that is currently logged in
  2. Login or logout the current User
  3. Access Django's Session object

In these situations will need to ensure you are using AuthMiddlewareStack and/or SessionMiddlewareStack.

from channels.auth import AuthMiddlewareStack  # noqa: E402\nfrom channels.sessions import SessionMiddlewareStack  # noqa: E402\n\napplication = ProtocolTypeRouter(\n    {\n        \"http\": django_asgi_app,\n        \"websocket\": SessionMiddlewareStack(\n            AuthMiddlewareStack(\n                URLRouter(\n                    [REACTPY_WEBSOCKET_ROUTE],\n                )\n            )\n        ),\n    }\n)\n
Where is my asgi.py?

If you do not have an asgi.py, follow the channels installation guide.

"},{"location":"learn/add-reactpy-to-a-django-project/#step-5-run-database-migrations","title":"Step 5: Run database migrations","text":"

Run Django's migrate command to initialize ReactPy-Django's database table.

python manage.py migrate\n
"},{"location":"learn/add-reactpy-to-a-django-project/#step-6-check-your-configuration","title":"Step 6: Check your configuration","text":"

Run Django's check command to verify if ReactPy was set up correctly.

python manage.py check\n
"},{"location":"learn/add-reactpy-to-a-django-project/#step-7-create-your-first-component","title":"Step 7: Create your first component","text":"

The next step will show you how to create your first ReactPy component.

Prefer a quick summary? Read the At a Glance section below.

At a Glance: Your First Component

my_app/components.py

You will need a file to define your ReactPy components. We recommend creating a components.py file within your chosen Django app to start out. Within this file, we will create a simple hello_world component.

from reactpy import component, html\n\n@component\ndef hello_world(recipient: str):\n    return html.h1(f\"Hello {recipient}!\")\n

my_app/templates/my-template.html

In your Django app's HTML template, you can now embed your ReactPy component using the component template tag. Within this tag, you will need to type in the dotted path to the component.

Additionally, you can pass in args and kwargs into your component function. After reading the code below, pay attention to how the function definition for hello_world (from the previous example) accepts a recipient argument.

{% load reactpy %}\n<!DOCTYPE html>\n<html>\n  <body>\n{% component \"example_project.my_app.components.hello_world\" recipient=\"World\" %}\n  </body>\n</html>\n
"},{"location":"learn/your-first-component/","title":"Your First Component","text":""},{"location":"learn/your-first-component/#overview","title":"Overview","text":"

Components are one of the core concepts of ReactPy. They are the foundation upon which you build user interfaces (UI), which makes them the perfect place to start your journey!

Note

If you have reached this point, you should have already installed ReactPy-Django through the previous steps.

"},{"location":"learn/your-first-component/#selecting-a-django-app","title":"Selecting a Django App","text":"

You will now need to pick at least one Django app to start using ReactPy-Django on.

For the following examples, we will assume the following:

  1. You have a Django app named my_app, which was created by Django's startapp command.
  2. You have placed my_app directly into your Django project folder (./example_project/my_app). This is common for small projects.
How do I organize my Django project for ReactPy?

ReactPy-Django has no project structure requirements. Organize everything as you wish, just like any Django project.

"},{"location":"learn/your-first-component/#defining-a-component","title":"Defining a component","text":"

You will need a file to start creating ReactPy components.

We recommend creating a components.py file within your chosen Django app to start out. For this example, the file path will look like this: ./example_project/my_app/components.py.

Within this file, you can define your component functions using ReactPy's @component decorator.

components.py
from reactpy import component, html\n\n@component\ndef hello_world(recipient: str):\n    return html.h1(f\"Hello {recipient}!\")\n
What should I name my ReactPy files and functions?

You have full freedom in naming/placement of your files and functions.

We recommend creating a components.py for small Django apps. If your app has a lot of components, you should consider breaking them apart into individual modules such as components/navbar.py.

Ultimately, components are referenced by Python dotted path in my-template.html (see next step). This path must be valid to Python's importlib.

What does the decorator actually do?

While not all components need to be decorated, there are a few features this decorator adds to your components.

  1. The ability to be used as a root component.
    • The decorator is required for any component that you want to reference in your Django templates (see next step).
  2. The ability to use hooks.
    • The decorator is required on any component where hooks are defined.
  3. Scoped failures.
    • If a decorated component generates an exception, then only that one component will fail to render.
"},{"location":"learn/your-first-component/#embedding-in-a-template","title":"Embedding in a template","text":"

In your Django app's HTML template, you can now embed your ReactPy component using the {% component %} template tag. Within this tag, you will need to type in the dotted path to the component.

Additionally, you can pass in args and kwargs into your component function. After reading the code below, pay attention to how the function definition for hello_world (from the previous step) accepts a recipient argument.

my-template.html
{% load reactpy %}\n<!DOCTYPE html>\n<html>\n  <body>\n{% component \"example_project.my_app.components.hello_world\" recipient=\"World\" %}\n  </body>\n</html>\n
Do not use context variables for the component path

The ReactPy component finder requires that your component path is a string.

Do not use Django template/context variables for the component path. Failure to follow this warning can result in unexpected behavior, such as components that will not render.

For example, do not do the following:

my-template.htmlviews.py
<!-- This is good -->\n{% component \"example_project.my_app.components.hello_world\" recipient=\"World\" %}\n\n<!-- This is bad -->\n{% component my_variable recipient=\"World\" %}\n
from django.shortcuts import render\n\n\ndef example_view(request):\n    context_vars = {\"my_variable\": \"example_project.my_app.components.hello_world\"}\n    return render(request, \"my-template.html\", context_vars)\n
Can I use multiple components on one page?

You can add as many components to a webpage as needed by using the template tag multiple times. Retrofitting legacy sites to use ReactPy will typically involve many components on one page.

my-template.html
{% load reactpy %}\n<!DOCTYPE html>\n<html>\n    <body>\n        <h1>{% component \"example_project.my_app.components.my_title\" %}</h1>\n        <p>{% component \"example_project.my_app_2.components.goodbye_world\" class=\"bold small-font\" %}</p>\n{% component \"example_project.my_app_3.components.simple_button\" %}\n    </body>\n</html>\n

Please note that components separated like this will not be able to interact with each other, except through database queries.

Additionally, in scenarios where you are trying to create a Single Page Application (SPA) within Django, you will only have one component within your <body> tag.

Where is my templates folder?

If you do not have a ./templates/ folder in your Django app, you can simply create one! Keep in mind, templates within this folder will not be detected by Django unless you add the corresponding Django app to settings.py:INSTALLED_APPS.

"},{"location":"learn/your-first-component/#setting-up-a-django-view","title":"Setting up a Django view","text":"

Within your Django app's views.py file, you will need to create a view function to render the HTML template my-template.html (from the previous step).

views.py
from django.shortcuts import render\n\n\ndef index(request):\n    return render(request, \"my-template.html\")\n

We will add this new view into your urls.py and define what URL it should be accessible at.

urls.py
from django.urls import path\nfrom example import views\n\nurlpatterns = [\n    path(\"example/\", views.index),\n]\n
Which urls.py do I add my views to?

For simple Django projects, you can easily add all of your views directly into the Django project's urls.py. However, as you start increase your project's complexity you might end up with way too much within one file.

Once you reach that point, we recommend creating an individual urls.py within each of your Django apps.

Then, within your Django project's urls.py you will use Django's include function to link it all together.

"},{"location":"learn/your-first-component/#viewing-your-component","title":"Viewing your component","text":"

To test your new Django view, run the following command to start up a development web server.

python manage.py runserver\n

Now you can navigate to your Django project URL that contains a ReactPy component, such as http://127.0.0.1:8000/example/ (from the previous step).

If you copy-pasted our example component, you will now see your component display \"Hello World\".

Do not use manage.py runserver for production

This command is only intended for development purposes. For production deployments make sure to read Django's documentation.

"},{"location":"learn/your-first-component/#learn-more","title":"Learn more","text":"

Congratulations! If you followed the previous steps, you have now created a \"Hello World\" component using ReactPy-Django!

Deep Dive

The docs you are reading only covers our Django integration. To learn more, check out one of the following links:

  • ReactPy-Django Feature Reference
  • ReactPy Core Documentation
  • Ask Questions on Discord

Additionally, the vast majority of tutorials/guides you find for ReactJS can be applied to ReactPy.

"},{"location":"reference/components/","title":"Components","text":""},{"location":"reference/components/#overview","title":"Overview","text":"

We supply some pre-designed that components can be used to help simplify development.

"},{"location":"reference/components/#view-to-component","title":"View To Component","text":"

Convert any Django view into a ReactPy component by using this decorator. Compatible with Function Based Views and Class Based Views. Views can be sync or async.

components.py
from django.http import HttpResponse\nfrom reactpy import component, html\nfrom reactpy_django.components import view_to_component\n\n\n@view_to_component\ndef hello_world_view(request):\n    return HttpResponse(\"Hello World!\")\n\n\n@component\ndef my_component():\n    return html.div(\n        hello_world_view(),\n    )\n
See Interface

Parameters

Name Type Description Default view Callable | View The view function or class to convert. N/A compatibility bool If True, the component will be rendered in an iframe. When using compatibility mode tranforms, strict_parsing, request, args, and kwargs arguments will be ignored. False transforms Sequence[Callable[[VdomDict], Any]] A list of functions that transforms the newly generated VDOM. The functions will be called on each VDOM node. tuple strict_parsing bool If True, an exception will be generated if the HTML does not perfectly adhere to HTML5. True

Returns

Type Description _ViewComponentConstructor A function that takes request, *args, key, **kwargs and returns a ReactPy component. All parameters are directly provided to your view, besides key which is used by ReactPy. Potential information exposure when using compatibility = True

When using compatibility mode, ReactPy automatically exposes a URL to your view.

It is your responsibility to ensure privileged information is not leaked via this method.

You must implement a method to ensure only authorized users can access your view. This can be done via directly writing conditionals into your view, or by adding decorators such as user_passes_test to your views. For example...

Function Based ViewClass Based View
from django.contrib.auth.decorators import user_passes_test\nfrom reactpy_django.components import view_to_component\n\n\n@view_to_component(compatibility=True)\n@user_passes_test(lambda u: u.is_superuser)  # type: ignore[union-attr]\ndef example_view(request):\n    ...\n
from django.contrib.auth.decorators import user_passes_test\nfrom django.utils.decorators import method_decorator\nfrom django.views.generic import TemplateView\nfrom reactpy_django.components import view_to_component\n\n\n@view_to_component(compatibility=True)\n@method_decorator(user_passes_test(lambda u: u.is_superuser), name=\"dispatch\")  # type: ignore[union-attr]\nclass ExampleView(TemplateView):\n    ...\n
Existing limitations

There are currently several limitations of using view_to_component that may be resolved in a future version.

  • Requires manual intervention to change request methods beyond GET.
  • ReactPy events cannot conveniently be attached to converted view HTML.
  • Has no option to automatically intercept local anchor link (such as <a href='example/'></a>) click events.

Please note these limitations do not exist when using compatibility mode.

How do I use this for Class Based Views?

You can simply pass your Class Based View directly into view_to_component.

components.py
from django.http import HttpResponse\nfrom django.views import View\nfrom reactpy import component, html\nfrom reactpy_django.components import view_to_component\n\n\nclass HelloWorldView(View):\n    def get(self, request):\n        return HttpResponse(\"Hello World!\")\n\n\nvtc = view_to_component(HelloWorldView)\n\n\n@component\ndef my_component():\n    return html.div(\n        vtc(),\n    )\n
How do I transform views from external libraries?

In order to convert external views, you can utilize view_to_component as a function, rather than a decorator.

components.py
from example.views import example_view\nfrom reactpy import component, html\nfrom reactpy_django.components import view_to_component\n\nexample_vtc = view_to_component(example_view)\n\n\n@component\ndef my_component():\n    return html.div(\n        example_vtc(),\n    )\n
How do I provide request, args, and kwargs to a view?

Request

You can use the request parameter to provide the view a custom request object.

components.py
from django.http import HttpRequest, HttpResponse\nfrom reactpy import component, html\nfrom reactpy_django.components import view_to_component\n\nexample_request = HttpRequest()\nexample_request.method = \"PUT\"\n\n\n@view_to_component\ndef hello_world_view(request):\n    return HttpResponse(f\"Hello World! {request.method}\")\n\n\n@component\ndef my_component():\n    return html.div(\n        hello_world_view(\n            example_request,\n        ),\n    )\n

args and kwargs

You can use the args and kwargs parameters to provide positional and keyworded arguments to a view.

components.py
from django.http import HttpResponse\nfrom reactpy import component, html\nfrom reactpy_django.components import view_to_component\n\n\n@view_to_component\ndef hello_world_view(request, arg1, arg2, key1=None, key2=None):\n    return HttpResponse(f\"Hello World! {arg1} {arg2} {key1} {key2}\")\n\n\n@component\ndef my_component():\n    return html.div(\n        hello_world_view(\n            None,  # Your request object (optional)\n            \"value_1\",\n            \"value_2\",\n            key1=\"abc\",\n            key2=\"123\",\n        ),\n    )\n
How do I use strict_parsing, compatibility, and transforms?

strict_parsing

By default, an exception will be generated if your view's HTML does not perfectly adhere to HTML5.

However, there are some circumstances where you may not have control over the original HTML, so you may be unable to fix it. Or you may be relying on non-standard HTML tags such as <my-tag> Hello World </my-tag>.

In these scenarios, you may want to rely on best-fit parsing by setting the strict_parsing parameter to False.

components.py
from django.http import HttpResponse\nfrom reactpy import component, html\nfrom reactpy_django.components import view_to_component\n\n\n@view_to_component(strict_parsing=False)\ndef hello_world_view(request):\n    return HttpResponse(\"<my-tag> Hello World </my-tag>\")\n\n\n@component\ndef my_component():\n    return html.div(\n        hello_world_view(),\n    )\n

Note: Best-fit parsing is designed to be similar to how web browsers would handle non-standard or broken HTML.

compatibility

For views that rely on HTTP responses other than GET (such as PUT, POST, PATCH, etc), you should consider using compatibility mode to render your view within an iframe.

Any view can be rendered within compatibility mode. However, the transforms, strict_parsing, request, args, and kwargs arguments do not apply to compatibility mode.

components.py
from django.http import HttpResponse\nfrom reactpy import component, html\nfrom reactpy_django.components import view_to_component\n\n\n@view_to_component(compatibility=True)\ndef hello_world_view(request):\n    return HttpResponse(\"Hello World!\")\n\n\n@component\ndef my_component():\n    return html.div(\n        hello_world_view(),\n    )\n

Note: By default the compatibility iframe is unstyled, and thus won't look pretty until you add some CSS.

transforms

After your view has been turned into VDOM (python dictionaries), view_to_component will call your transforms functions on every VDOM node.

This allows you to modify your view prior to rendering.

For example, if you are trying to modify the text of a node with a certain id, you can create a transform like such:

components.py
from django.http import HttpResponse\nfrom reactpy import component, html\nfrom reactpy_django.components import view_to_component\n\n\ndef example_transform(vdom):\n    attributes = vdom.get(\"attributes\")\n    if attributes and attributes.get(\"id\") == \"hello-world\":\n        vdom[\"children\"][0] = \"Good Bye World!\"\n\n\n@view_to_component(transforms=[example_transform])\ndef hello_world_view(request):\n    return HttpResponse(\"<div id='hello-world'> Hello World! <div>\")\n\n\n@component\ndef my_component():\n    return html.div(\n        hello_world_view(),\n    )\n
"},{"location":"reference/components/#django-css","title":"Django CSS","text":"

Allows you to defer loading a CSS stylesheet until a component begins rendering. This stylesheet must be stored within Django's static files.

components.py
from reactpy import component, html\nfrom reactpy_django.components import django_css\n\n\n@component\ndef my_component():\n    return html.div(\n        django_css(\"css/buttons.css\"),\n        html.button(\"My Button!\"),\n    )\n
See Interface

Parameters

Name Type Description Default static_path str The path to the static file. This path is identical to what you would use on Django's {% static %} template tag. N/A key Key | None A key to uniquely identify this component which is unique amongst a component's immediate siblings None

Returns

Type Description Component A ReactPy component. Can I load static CSS using html.link instead?

While you can load stylesheets with html.link, keep in mind that loading this way does not ensure load order. Thus, your stylesheet will be loaded after your component is displayed. This would likely cause unintended visual behavior, so use this at your own discretion.

Here's an example on what you should avoid doing for Django static files:

from django.templatetags.static import static\nfrom reactpy import component, html\n\n\n@component\ndef my_component():\n    return html.div(\n        html.link({\"rel\": \"stylesheet\", \"href\": static(\"css/buttons.css\")}),\n        html.button(\"My Button!\"),\n    )\n
How do I load external CSS?

django_css can only be used with local static files.

For external CSS, you should use html.link.

from reactpy import component, html\n\n\n@component\ndef my_component():\n    return html.div(\n        html.link(\n            {\"rel\": \"stylesheet\", \"href\": \"https://example.com/external-styles.css\"}\n        ),\n        html.button(\"My Button!\"),\n    )\n
Why not load my CSS in <head>?

Traditionally, stylesheets are loaded in your <head> using Django's {% static %} template tag.

However, to help improve webpage load times you can use this django_css component to defer loading your stylesheet until it is needed.

"},{"location":"reference/components/#django-js","title":"Django JS","text":"

Allows you to defer loading JavaScript until a component begins rendering. This JavaScript must be stored within Django's static files.

Pitfall

Be mindful of load order! If your JavaScript relies on the component existing on the page, you must place django_js at the bottom of your component.

components.py
from reactpy import component, html\nfrom reactpy_django.components import django_js\n\n\n@component\ndef my_component():\n    return html.div(\n        html.button(\"My Button!\"),\n        django_js(\"js/scripts.js\"),\n    )\n
See Interface

Parameters

Name Type Description Default static_path str The path to the static file. This path is identical to what you would use on Django's {% static %} template tag. N/A key Key | None A key to uniquely identify this component which is unique amongst a component's immediate siblings None

Returns

Type Description Component A ReactPy component. Can I load static JavaScript using html.script instead?

While you can load JavaScript with html.script, keep in mind that loading this way does not ensure load order. Thus, your JavaScript will likely be loaded at an arbitrary time after your component is displayed.

Here's an example on what you should avoid doing for Django static files:

from django.templatetags.static import static\nfrom reactpy import component, html\n\n\n@component\ndef my_component():\n    return html.div(\n        html.script({\"src\": static(\"js/scripts.js\")}),\n        html.button(\"My Button!\"),\n    )\n
How do I load external JS?

django_js can only be used with local static files.

For external JavaScript, you should use html.script.

from reactpy import component, html\n\n\n@component\ndef my_component():\n    return html.div(\n        html.script({\"src\": \"https://example.com/external-scripts.js\"}),\n        html.button(\"My Button!\"),\n    )\n
Why not load my JS in <head>?

Traditionally, JavaScript is loaded in your <head> using Django's {% static %} template tag.

However, to help improve webpage load times you can use this django_js component to defer loading your JavaScript until it is needed.

"},{"location":"reference/decorators/","title":"Decorators","text":""},{"location":"reference/decorators/#overview","title":"Overview","text":"

Decorator functions can be used within your components.py to help simplify development.

"},{"location":"reference/decorators/#auth-required","title":"Auth Required","text":"

You can limit component access to users with a specific auth_attribute by using this decorator (with or without parentheses).

By default, this decorator checks if the user is logged in and not deactivated (is_active).

This decorator is commonly used to selectively render a component only if a user is_staff or is_superuser.

components.py
from reactpy import component, html\nfrom reactpy_django.decorators import auth_required\n\n\n@component\n@auth_required\ndef my_component():\n    return html.div(\"I am logged in!\")\n
See Interface

Parameters

Name Type Description Default auth_attribute str The value to check within the user object. This is checked via getattr(scope[\"user\"], auth_attribute). \"is_active\" fallback ComponentType | VdomDict | None The component or reactpy.html snippet to render if the user is not authenticated. None

Returns

Type Description #!python Component` A ReactPy component. #!python VdomDict| A#!python reactpy.html` snippet. #!python None` No component render. How do I render a different component if authentication fails?

You can use a component with the fallback argument, as seen below.

components.py
from reactpy import component, html\nfrom reactpy_django.decorators import auth_required\n\n\n@component\ndef my_component_fallback():\n    return html.div(\"I am NOT logged in!\")\n\n\n@component\n@auth_required(fallback=my_component_fallback)\ndef my_component():\n    return html.div(\"I am logged in!\")\n
How do I render a simple reactpy.html snippet if authentication fails?

You can use a reactpy.html snippet with the fallback argument, as seen below.

components.py
from reactpy import component, html\nfrom reactpy_django.decorators import auth_required\n\n\n@component\n@auth_required(fallback=html.div(\"I am NOT logged in!\"))\ndef my_component():\n    return html.div(\"I am logged in!\")\n
How can I check if a user is_staff?

You can do this by setting auth_attribute=\"is_staff\", as seen blow.

components.py
from reactpy import component, html\nfrom reactpy_django.decorators import auth_required\n\n\n@component\n@auth_required(auth_attribute=\"is_staff\")\ndef my_component():\n    return html.div(\"I am logged in!\")\n
How can I check for a custom attribute?

You will need to be using a custom user model within your Django instance.

For example, if your user model has the field is_really_cool ...

models.py
from django.contrib.auth.models import AbstractBaseUser\n\n\nclass CustomUserModel(AbstractBaseUser):\n    @property\n    def is_really_cool(self):\n        return True\n

... then you would do the following within your decorator:

components.py
from reactpy import component, html\nfrom reactpy_django.decorators import auth_required\n\n\n@component\n@auth_required(auth_attribute=\"is_really_cool\")\ndef my_component():\n    return html.div(\"I am logged in!\")\n
"},{"location":"reference/hooks/","title":"Hooks","text":""},{"location":"reference/hooks/#overview","title":"Overview","text":"

Prefabricated hooks can be used within your components.py to help simplify development.

Note

Looking for standard React hooks?

This package only contains Django specific hooks. Standard hooks can be found within reactive-python/reactpy.

"},{"location":"reference/hooks/#use-query","title":"Use Query","text":"

This hook is used to execute functions in the background and return the result, typically to read data the Django ORM.

The default postprocessor expects your query function to return a Django Model or QuerySet. The postprocessor needs to be changed to execute other types of queries. Query functions can be sync or async.

components.pymodels.py
from channels.db import database_sync_to_async\nfrom example.models import TodoItem\nfrom reactpy import component, html\nfrom reactpy_django.hooks import use_query\n\n\nasync def get_items():\n    return await database_sync_to_async(TodoItem.objects.all)()\n\n\n@component\ndef todo_list():\n    item_query = use_query(get_items)\n\n    if item_query.loading:\n        rendered_items = html.h2(\"Loading...\")\n    elif item_query.error or not item_query.data:\n        rendered_items = html.h2(\"Error when loading!\")\n    else:\n        rendered_items = html.ul([html.li(item, key=item) for item in item_query.data])\n\n    return html.div(\"Rendered items: \", rendered_items)\n
from django.db.models import CharField, Model\n\n\nclass TodoItem(Model):\n    text: CharField = CharField(max_length=255)\n
See Interface

Parameters

Name Type Description Default options QueryOptions | None An optional QueryOptions object that can modify how the query is executed. None query Callable[_Params, _Result | None] A callable that returns a Django Model or QuerySet. N/A *args _Params.args Positional arguments to pass into query. N/A **kwargs _Params.kwargs Keyword arguments to pass into query. N/A

Returns

Type Description Query[_Result | None] An object containing loading/error states, your data (if the query has successfully executed), and a refetch callable that can be used to re-run the query. How can I provide arguments to my query function?

*args and **kwargs can be provided to your query function via use_query parameters.

components.py
from reactpy import component\nfrom reactpy_django.hooks import use_query\n\n\ndef example_query(value: int, other_value: bool = False):\n    ...\n\n\n@component\ndef my_component():\n    query = use_query(\n        example_query,\n        123,\n        other_value=True,\n    )\n\n    return str(query.data)\n
How can I customize this hook's behavior?

This hook accepts a options: QueryOptions parameter that can be used to customize behavior.

Below are the settings that can be modified via these QueryOptions.

thread_sensitive

Whether to run your synchronous query function in thread-sensitive mode. Thread-sensitive mode is turned on by default due to Django ORM limitations. See Django's sync_to_async docs docs for more information.

This setting only applies to sync query functions, and will be ignored for async functions.

components.py
from reactpy import component\nfrom reactpy_django.hooks import use_query\nfrom reactpy_django.types import QueryOptions\n\n\ndef execute_thread_safe_operation():\n\"\"\"This is an example query function that does some thread-safe operation.\"\"\"\n    pass\n\n\n@component\ndef my_component():\n    query = use_query(\n        QueryOptions(thread_sensitive=False),\n        execute_thread_safe_operation,\n    )\n\n    if query.loading or query.error:\n        return None\n\n    return str(query.data)\n

postprocessor

By default, automatic recursive fetching of ManyToMany or ForeignKey fields is enabled within the django_query_postprocessor. This is needed to prevent SynchronousOnlyOperation exceptions when accessing these fields within your ReactPy components.

However, if you...

  1. Want to use this hook to defer IO intensive tasks to be computed in the background
  2. Want to to utilize use_query with a different ORM

... then you can either set a custom postprocessor, or disable all postprocessing behavior by modifying the QueryOptions.postprocessor parameter. In the example below, we will set the postprocessor to None to disable postprocessing behavior.

components.py
from reactpy import component\nfrom reactpy_django.hooks import use_query\nfrom reactpy_django.types import QueryOptions\n\n\ndef execute_io_intensive_operation():\n\"\"\"This is an example query function that does something IO intensive.\"\"\"\n    pass\n\n\n@component\ndef my_component():\n    query = use_query(\n        QueryOptions(postprocessor=None),\n        execute_io_intensive_operation,\n    )\n\n    if query.loading or query.error:\n        return None\n\n    return str(query.data)\n

If you wish to create a custom postprocessor, you will need to create a callable.

The first argument of postprocessor must be the query data. All proceeding arguments are optional postprocessor_kwargs (see below). This postprocessor must return the modified data.

components.py
from reactpy import component\nfrom reactpy_django.hooks import use_query\nfrom reactpy_django.types import QueryOptions\n\n\ndef my_postprocessor(data, example_kwarg=True):\n    if example_kwarg:\n        return data\n\n    return dict(data)\n\n\ndef execute_io_intensive_operation():\n\"\"\"This is an example query function that does something IO intensive.\"\"\"\n    pass\n\n\n@component\ndef my_component():\n    query = use_query(\n        QueryOptions(\n            postprocessor=my_postprocessor,\n            postprocessor_kwargs={\"example_kwarg\": False},\n        ),\n        execute_io_intensive_operation,\n    )\n\n    if query.loading or query.error:\n        return None\n\n    return str(query.data)\n

postprocessor_kwargs

By default, automatic recursive fetching of ManyToMany or ForeignKey fields is enabled within the django_query_postprocessor. This is needed to prevent SynchronousOnlyOperation exceptions when accessing these fields within your ReactPy components.

However, if you have deep nested trees of relational data, this may not be a desirable behavior. In these scenarios, you may prefer to manually fetch these relational fields using a second use_query hook.

You can disable the prefetching behavior of the default postprocessor (located at reactpy_django.utils.django_query_postprocessor) via the QueryOptions.postprocessor_kwargs parameter.

components.py
from example.models import TodoItem\nfrom reactpy import component\nfrom reactpy_django.hooks import use_query\nfrom reactpy_django.types import QueryOptions\n\n\ndef get_model_with_relationships():\n\"\"\"This is an example query function that gets `MyModel` which has a ManyToMany field, and\n    additionally other models that have formed a ForeignKey association to `MyModel`.\n\n    ManyToMany Field: `many_to_many_field`\n    ForeignKey Field: `foreign_key_field_set`\n    \"\"\"\n    return TodoItem.objects.get(id=1)\n\n\n@component\ndef my_component():\n    query = use_query(\n        QueryOptions(\n            postprocessor_kwargs={\"many_to_many\": False, \"many_to_one\": False}\n        ),\n        get_model_with_relationships,\n    )\n\n    if query.loading or query.error or not query.data:\n        return None\n\n    # By disabling `many_to_many` and `many_to_one`, accessing these fields will now\n    # generate a `SynchronousOnlyOperation` exception\n    return f\"{query.data.many_to_many_field} {query.data.foriegn_key_field_set}\"\n

Note: In Django's ORM design, the field name to access foreign keys is postfixed with _set by default.

Can I make ORM calls without hooks?

Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a SynchronousOnlyOperation exception.

These SynchronousOnlyOperation exceptions may be removed in a future version of Django. However, it is best practice to always perform IO operations (such as ORM queries) via hooks to prevent performance issues.

Can I make a failed query try again?

Yes, a use_mutation can be re-performed by calling reset() on your use_mutation instance.

For example, take a look at reset_event below.

components.pymodels.py
from example.models import TodoItem\nfrom reactpy import component, html\nfrom reactpy_django.hooks import use_mutation\n\n\ndef add_item(text: str):\n    TodoItem(text=text).save()\n\n\n@component\ndef todo_list():\n    item_mutation = use_mutation(add_item)\n\n    def reset_event(event):\n        item_mutation.reset()\n\n    def submit_event(event):\n        if event[\"key\"] == \"Enter\":\n            item_mutation.execute(text=event[\"target\"][\"value\"])\n\n    if item_mutation.loading:\n        mutation_status = html.h2(\"Adding...\")\n    elif item_mutation.error:\n        mutation_status = html.button({\"onClick\": reset_event}, \"Error: Try again!\")\n    else:\n        mutation_status = html.h2(\"Mutation done.\")\n\n    return html.div(\n        html.label(\"Add an item:\"),\n        html.input({\"type\": \"text\", \"onKeyDown\": submit_event}),\n        mutation_status,\n    )\n
from django.db.models import CharField, Model\n\n\nclass TodoItem(Model):\n    text: CharField = CharField(max_length=255)\n
Why does the example query function return TodoItem.objects.all()?

This design decision was based on Apollo's useQuery hook, but ultimately helps avoid Django's SynchronousOnlyOperation exceptions.

With the Model or QuerySet your function returns, this hook uses the default postprocessor to ensure that all deferred or lazy fields are executed.

"},{"location":"reference/hooks/#use-mutation","title":"Use Mutation","text":"

This hook is used to modify data in the background, typically to create/update/delete data from the Django ORM.

Mutation functions can return False to prevent executing your refetch function. All other returns are ignored. Mutation functions can be sync or async.

components.pymodels.py
from example.models import TodoItem\nfrom reactpy import component, html\nfrom reactpy_django.hooks import use_mutation\n\n\nasync def add_item(text: str):\n    await TodoItem(text=text).asave()\n\n\n@component\ndef todo_list():\n    item_mutation = use_mutation(add_item)\n\n    def submit_event(event):\n        if event[\"key\"] == \"Enter\":\n            item_mutation.execute(text=event[\"target\"][\"value\"])\n\n    if item_mutation.loading:\n        mutation_status = html.h2(\"Adding...\")\n    elif item_mutation.error:\n        mutation_status = html.h2(\"Error when adding!\")\n    else:\n        mutation_status = html.h2(\"Mutation done.\")\n\n    return html.div(\n        html.label(\"Add an item:\"),\n        html.input({\"type\": \"text\", \"onKeyDown\": submit_event}),\n        mutation_status,\n    )\n
from django.db.models import CharField, Model\n\n\nclass TodoItem(Model):\n    text: CharField = CharField(max_length=255)\n
See Interface

Parameters

Name Type Description Default mutate Callable[_Params, bool | None] A callable that performs Django ORM create, update, or delete functionality. If this function returns False, then your refetch function will not be used. N/A refetch Callable[..., Any] | Sequence[Callable[..., Any]] | None A query function (the function you provide to your use_query hook) or a sequence of query functions that need a refetch if the mutation succeeds. This is useful for refreshing data after a mutation has been performed. None

Returns

Type Description Mutation[_Params] An object containing loading/error states, a reset callable that will set loading/error states to defaults, and a execute callable that will run the query. How can I provide arguments to my mutation function?

*args and **kwargs can be provided to your mutation function via #!python mutation.execute` parameters.

components.py
from reactpy import component\nfrom reactpy_django.hooks import use_mutation\n\n\ndef example_mutation(value: int, other_value: bool = False):\n    ...\n\n\n@component\ndef my_component():\n    mutation = use_mutation(example_mutation)\n\n    mutation.execute(123, other_value=True)\n\n    ...\n
How can I customize this hook's behavior?

This hook accepts a options: MutationOptions parameter that can be used to customize behavior.

Below are the settings that can be modified via these MutationOptions.

thread_sensitive

Whether to run your synchronous mutation function in thread-sensitive mode. Thread-sensitive mode is turned on by default due to Django ORM limitations. See Django's sync_to_async docs docs for more information.

This setting only applies to sync query functions, and will be ignored for async functions.

components.py
from reactpy import component, html\nfrom reactpy_django.hooks import use_mutation\nfrom reactpy_django.types import MutationOptions\n\n\ndef execute_thread_safe_mutation():\n\"\"\"This is an example mutation function that does some thread-safe operation.\"\"\"\n    pass\n\n\n@component\ndef my_component():\n    item_mutation = use_mutation(\n        MutationOptions(thread_sensitive=False),\n        execute_thread_safe_mutation,\n    )\n\n    def submit_event(event):\n        if event[\"key\"] == \"Enter\":\n            item_mutation.execute(text=event[\"target\"][\"value\"])\n\n    if item_mutation.loading or item_mutation.error:\n        mutation_status = html.h2(\"Doing something...\")\n    elif item_mutation.error:\n        mutation_status = html.h2(\"Error!\")\n    else:\n        mutation_status = html.h2(\"Done.\")\n\n    return html.div(\n        html.input({\"type\": \"text\", \"onKeyDown\": submit_event}),\n        mutation_status,\n    )\n
Can I make ORM calls without hooks?

Due to Django's ORM design, database queries must be deferred using hooks. Otherwise, you will see a SynchronousOnlyOperation exception.

These SynchronousOnlyOperation exceptions may be removed in a future version of Django. However, it is best practice to always perform IO operations (such as ORM queries) via hooks to prevent performance issues.

Can I make a failed mutation try again?

Yes, a use_mutation can be re-performed by calling reset() on your use_mutation instance.

For example, take a look at reset_event below.

components.pymodels.py
from example.models import TodoItem\nfrom reactpy import component, html\nfrom reactpy_django.hooks import use_mutation\n\n\ndef add_item(text: str):\n    TodoItem(text=text).save()\n\n\n@component\ndef todo_list():\n    item_mutation = use_mutation(add_item)\n\n    def reset_event(event):\n        item_mutation.reset()\n\n    def submit_event(event):\n        if event[\"key\"] == \"Enter\":\n            item_mutation.execute(text=event[\"target\"][\"value\"])\n\n    if item_mutation.loading:\n        mutation_status = html.h2(\"Adding...\")\n    elif item_mutation.error:\n        mutation_status = html.button({\"onClick\": reset_event}, \"Error: Try again!\")\n    else:\n        mutation_status = html.h2(\"Mutation done.\")\n\n    return html.div(\n        html.label(\"Add an item:\"),\n        html.input({\"type\": \"text\", \"onKeyDown\": submit_event}),\n        mutation_status,\n    )\n
from django.db.models import CharField, Model\n\n\nclass TodoItem(Model):\n    text: CharField = CharField(max_length=255)\n
Can use_mutation trigger a refetch of use_query?

Yes, use_mutation can queue a refetch of a use_query via the refetch=... argument.

The example below is a merge of the use_query and use_mutation examples above with the addition of a use_mutation(refetch=...) argument.

Please note that refetch will cause all use_query hooks that use get_items in the current component tree will be refetched.

components.pymodels.py
from example.models import TodoItem\nfrom reactpy import component, html\nfrom reactpy_django.hooks import use_mutation, use_query\n\n\ndef get_items():\n    return TodoItem.objects.all()\n\n\ndef add_item(text: str):\n    TodoItem(text=text).save()\n\n\n@component\ndef todo_list():\n    item_query = use_query(get_items)\n    item_mutation = use_mutation(add_item, refetch=get_items)\n\n    def submit_event(event):\n        if event[\"key\"] == \"Enter\":\n            item_mutation.execute(text=event[\"target\"][\"value\"])\n\n    # Handle all possible query states\n    if item_query.loading:\n        rendered_items = html.h2(\"Loading...\")\n    elif item_query.error or not item_query.data:\n        rendered_items = html.h2(\"Error when loading!\")\n    else:\n        rendered_items = html.ul(html.li(item, key=item) for item in item_query.data)\n\n    # Handle all possible mutation states\n    if item_mutation.loading:\n        mutation_status = html.h2(\"Adding...\")\n    elif item_mutation.error:\n        mutation_status = html.h2(\"Error when adding!\")\n    else:\n        mutation_status = html.h2(\"Mutation done.\")\n\n    return html.div(\n        html.label(\"Add an item:\"),\n        html.input({\"type\": \"text\", \"onKeyDown\": submit_event}),\n        mutation_status,\n        rendered_items,\n    )\n
from django.db.models import CharField, Model\n\n\nclass TodoItem(Model):\n    text: CharField = CharField(max_length=255)\n
"},{"location":"reference/hooks/#use-connection","title":"Use Connection","text":"

This hook is used to fetch the active connection, which is either a Django WebSocket or a HTTP Request.

components.py
from reactpy import component, html\nfrom reactpy_django.hooks import use_connection\n\n\n@component\ndef my_component():\n    my_connection = use_connection()\n    return html.div(str(my_connection))\n
See Interface

Parameters

None

Returns

Type Description Connection The component's WebSocket or HttpRequest."},{"location":"reference/hooks/#use-scope","title":"Use Scope","text":"

This is a shortcut that returns the WebSocket or HTTP scope.

components.py
from reactpy import component, html\nfrom reactpy_django.hooks import use_scope\n\n\n@component\ndef my_component():\n    my_scope = use_scope()\n    return html.div(str(my_scope))\n
See Interface

Parameters

None

Returns

Type Description MutableMapping[str, Any] The WebSocket's scope."},{"location":"reference/hooks/#use-location","title":"Use Location","text":"

This is a shortcut that returns the client's URL path.

You can expect this hook to provide strings such as /reactpy/my_path.

components.py
from reactpy import component, html\nfrom reactpy_django.hooks import use_location\n\n\n@component\ndef my_component():\n    my_location = use_location()\n    return html.div(str(my_location))\n
See Interface

Parameters

None

Returns

Type Description Location An object containing the current URL's pathname and search query. This hook's behavior will be changed in a future update

This hook will be updated to return the browser's currently active HTTP path. This change will come in alongside ReactPy URL routing support.

Check out reactive-python/reactpy-django#147 for more information.

"},{"location":"reference/hooks/#use-origin","title":"Use Origin","text":"

This is a shortcut that returns the client's origin.

You can expect this hook to provide strings such as http://example.com.

components.py
from reactpy import component, html\nfrom reactpy_django.hooks import use_origin\n\n\n@component\ndef my_component():\n    my_origin = use_origin()\n    return html.div(my_origin or \"No origin\")\n
See Interface

Parameters

None

Returns

Type Description str | None A string containing the browser's current origin, obtained from WebSocket or HTTP headers (if available)."},{"location":"reference/settings/","title":"Settings","text":""},{"location":"reference/settings/#overview","title":"Overview","text":"

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

The default configuration of ReactPy is suitable for the vast majority of use cases.

You should only consider changing settings when the necessity arises.

"},{"location":"reference/settings/#general-settings","title":"General Settings","text":""},{"location":"reference/settings/#reactpy_url_prefix","title":"REACTPY_URL_PREFIX","text":"

Default: \"reactpy/\"

Example Value(s): \"rp/\", \"render/reactpy/\"

The prefix used for all ReactPy WebSocket and HTTP URLs.

"},{"location":"reference/settings/#reactpy_default_query_postprocessor","title":"REACTPY_DEFAULT_QUERY_POSTPROCESSOR","text":"

Default: \"reactpy_django.utils.django_query_postprocessor\"

Example Value(s): \"example_project.postprocessor\", None

Dotted path to the global default reactpy_django.hooks.use_query postprocessor function.

Postprocessor functions can be async or sync. Here is an example of a sync postprocessor function:

def postprocessor(data):\n    del data[\"foo\"]\n    return data\n

Set REACTPY_DEFAULT_QUERY_POSTPROCESSOR to None to disable the default postprocessor.

"},{"location":"reference/settings/#reactpy_auth_backend","title":"REACTPY_AUTH_BACKEND","text":"

Default: \"django.contrib.auth.backends.ModelBackend\"

Example Value(s): \"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 AuthMiddlewareStack and...
  2. You are using Django's AUTHENTICATION_BACKENDS setting and...
  3. Your Django user model does not define a backend attribute.
"},{"location":"reference/settings/#performance-settings","title":"Performance Settings","text":""},{"location":"reference/settings/#reactpy_database","title":"REACTPY_DATABASE","text":"

Default: \"default\"

Example Value(s): \"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:

DATABASE_ROUTERS = [\"reactpy_django.database.Router\", ...]\n
"},{"location":"reference/settings/#reactpy_cache","title":"REACTPY_CACHE","text":"

Default: \"default\"

Example Value(s): \"my-reactpy-cache\"

Cache used by ReactPy, typically for file operations.

We recommend configuring redis, python-diskcache, or LocMemCache.

"},{"location":"reference/settings/#reactpy_backhaul_thread","title":"REACTPY_BACKHAUL_THREAD","text":"

Default: False

Example Value(s): 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 and uvicorn.

"},{"location":"reference/settings/#reactpy_default_hosts","title":"REACTPY_DEFAULT_HOSTS","text":"

Default: None

Example Value(s): [\"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 host argument in your template tag to manually override this default.

"},{"location":"reference/settings/#reactpy_prerender","title":"REACTPY_PRERENDER","text":"

Default: False

Example Value(s): 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 connection related hooks use HTTP.
  3. 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 prerender argument in your template tag to manually override this default.

"},{"location":"reference/settings/#stability-settings","title":"Stability Settings","text":""},{"location":"reference/settings/#reactpy_reconnect_interval","title":"REACTPY_RECONNECT_INTERVAL","text":"

Default: 750

Example Value(s): 100, 2500, 6000

Milliseconds between client reconnection attempts.

"},{"location":"reference/settings/#reactpy_reconnect_backoff_multiplier","title":"REACTPY_RECONNECT_BACKOFF_MULTIPLIER","text":"

Default: 1.25

Example Value(s): 1, 1.5, 3

On each reconnection attempt, the 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 1.

"},{"location":"reference/settings/#reactpy_reconnect_max_interval","title":"REACTPY_RECONNECT_MAX_INTERVAL","text":"

Default: 60000

Example Value(s): 10000, 25000, 900000

Maximum milliseconds between client reconnection attempts.

This allows setting an upper bound on how high REACTPY_RECONNECT_BACKOFF_MULTIPLIER can increase the time between reconnection attempts.

"},{"location":"reference/settings/#reactpy_reconnect_max_retries","title":"REACTPY_RECONNECT_MAX_RETRIES","text":"

Default: 150

Example Value(s): 0, 5, 300

Maximum number of reconnection attempts before the client gives up.

"},{"location":"reference/settings/#reactpy_session_max_age","title":"REACTPY_SESSION_MAX_AGE","text":"

Default: 259200

Example Value(s): 0, 60, 96000

Maximum seconds to store ReactPy component sessions.

ReactPy sessions include data such as *args and **kwargs passed into your {% component %} template tag.

Use 0 to not store any session data.

"},{"location":"reference/template-tag/","title":"Template Tag","text":""},{"location":"reference/template-tag/#overview","title":"Overview","text":"

Django template tags can be used within your HTML templates to provide ReactPy features.

"},{"location":"reference/template-tag/#component","title":"Component","text":"

This template tag can be used to insert any number of ReactPy components onto your page.

my-template.html
{% load reactpy %}\n<!DOCTYPE html>\n<html>\n  <body>\n{% component \"example_project.my_app.components.hello_world\" recipient=\"World\" %}\n  </body>\n</html>\n
See Interface

Parameters

Name Type Description Default dotted_path str The dotted path to the component to render. N/A *args Any The positional arguments to provide to the component. N/A class str | None The HTML class to apply to the top-level component div. None key Any Force the component's root node to use a specific key value. Using key within a template tag is effectively useless. None host 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 None prerender str If \"True\", the component will pre-rendered, which enables SEO compatibility and reduces perceived latency. \"False\" **kwargs Any The keyword arguments to provide to the component. N/A

Returns

Type Description Component A ReactPy component. Do not use context variables for the component path

The ReactPy component finder requires that your component path is a string.

Do not use Django template/context variables for the component path. Failure to follow this warning can result in unexpected behavior, such as components that will not render.

For example, do not do the following:

my-template.htmlviews.py
<!-- This is good -->\n{% component \"example_project.my_app.components.hello_world\" recipient=\"World\" %}\n\n<!-- This is bad -->\n{% component my_variable recipient=\"World\" %}\n
from django.shortcuts import render\n\n\ndef example_view(request):\n    context_vars = {\"my_variable\": \"example_project.my_app.components.hello_world\"}\n    return render(request, \"my-template.html\", context_vars)\n
Can I render components on a different server (distributed computing)?

Yes! By using the host keyword argument, you can render components from a completely separate ASGI server.

my-template.html
...\n{% component \"example_project.my_app.components.do_something\" host=\"127.0.0.1:8001\" %}\n...\n

This configuration most commonly involves you deploying multiple instances of your project. But, you can also create dedicated Django project(s) that only render specific ReactPy components if you wish.

Here's a couple of things to keep in mind:

  1. If your host address are completely separate ( origin1.com != origin2.com ) you will need to configure CORS headers on your main application during deployment.
  2. You will not need to register ReactPy WebSocket or HTTP paths on any applications that do not perform any component rendering.
  3. Your component will only be able to access your template tag's *args/**kwargs if your applications share a common database.
Can I use multiple components on one page?

You can add as many components to a webpage as needed by using the template tag multiple times. Retrofitting legacy sites to use ReactPy will typically involve many components on one page.

my-template.html
{% load reactpy %}\n<!DOCTYPE html>\n<html>\n    <body>\n        <h1>{% component \"example_project.my_app.components.my_title\" %}</h1>\n        <p>{% component \"example_project.my_app_2.components.goodbye_world\" class=\"bold small-font\" %}</p>\n{% component \"example_project.my_app_3.components.simple_button\" %}\n    </body>\n</html>\n

Please note that components separated like this will not be able to interact with each other, except through database queries.

Additionally, in scenarios where you are trying to create a Single Page Application (SPA) within Django, you will only have one component within your <body> tag.

Can I use positional arguments instead of keyword arguments?

You can use any combination of *args/**kwargs in your template tag.

my-template.htmlcomponents.py
{% component \"example_project.my_app.components.frog_greeter\" 123 \"Mr. Froggles\" species=\"Grey Treefrog\" %}\n
from reactpy import component\n\n\n@component\ndef frog_greeter(number, name, species=\"\"):\n    return f\"Hello #{number}, {name} the {species}!\"\n
"},{"location":"reference/utils/","title":"Utilities","text":""},{"location":"reference/utils/#overview","title":"Overview","text":"

Utility functions provide various miscellaneous functionality. These are typically not used, but are available for advanced use cases.

"},{"location":"reference/utils/#django-query-postprocessor","title":"Django Query Postprocessor","text":"

This is the default postprocessor for the use_query hook.

This postprocessor is designed to avoid Django's SynchronousOnlyException by recursively fetching all fields within a Model or QuerySet to prevent lazy execution.

components.pymodels.py
from example.models import TodoItem\nfrom reactpy import component\nfrom reactpy_django.hooks import use_query\nfrom reactpy_django.types import QueryOptions\nfrom reactpy_django.utils import django_query_postprocessor\n\n\ndef get_items():\n    return TodoItem.objects.all()\n\n\n@component\ndef todo_list():\n    # These `QueryOptions` are functionally equivalent to ReactPy-Django's default values\n    item_query = use_query(\n        QueryOptions(\n            postprocessor=django_query_postprocessor,\n            postprocessor_kwargs={\"many_to_many\": True, \"many_to_one\": True},\n        ),\n        get_items,\n    )\n\n    return item_query.data\n
from django.db.models import CharField, Model\n\n\nclass TodoItem(Model):\n    text: CharField = CharField(max_length=255)\n
See Interface

Parameters

Name Type Description Default data QuerySet | Model The Model or QuerySet to recursively fetch fields from. N/A many_to_many bool Whether or not to recursively fetch ManyToManyField relationships. True many_to_one bool Whether or not to recursively fetch ForeignKey relationships. True

Returns

Type Description QuerySet | Model The Model or QuerySet with all fields fetched."},{"location":"reference/utils/#register-component","title":"Register Component","text":"

This function is used manually register a root component with ReactPy.

apps.py
from django.apps import AppConfig\nfrom reactpy_django.utils import register_component\n\n\nclass ExampleConfig(AppConfig):\n    def ready(self):\n        # Add components to the ReactPy component registry when Django is ready\n        register_component(\"example_project.my_app.components.hello_world\")\n
Only use this within MyAppConfig.ready()

You should always call register_component within a Django MyAppConfig.ready() method. This ensures you will retain multiprocessing compatibility, such as with ASGI web server workers.

Do I need to use this?

You typically will not need to use this function.

For security reasons, ReactPy requires all root components to be registered. However, all components contained within Django templates are automatically registered.

This function is needed when you have configured your host to a dedicated Django rendering application that doesn't have templates.

"}]} \ No newline at end of file diff --git a/develop/sitemap.xml b/develop/sitemap.xml index 9a1c7ecb..8d790b79 100644 --- a/develop/sitemap.xml +++ b/develop/sitemap.xml @@ -2,62 +2,67 @@ https://reactive-python.github.io/reactpy-django/develop/ - 2023-09-16 + 2023-09-21 daily https://reactive-python.github.io/reactpy-django/develop/about/changelog/ - 2023-09-16 + 2023-09-21 daily https://reactive-python.github.io/reactpy-django/develop/about/code/ - 2023-09-16 + 2023-09-21 daily https://reactive-python.github.io/reactpy-django/develop/about/docs/ - 2023-09-16 + 2023-09-21 + daily + + + https://reactive-python.github.io/reactpy-django/develop/about/license/ + 2023-09-21 daily https://reactive-python.github.io/reactpy-django/develop/learn/add-reactpy-to-a-django-project/ - 2023-09-16 + 2023-09-21 daily https://reactive-python.github.io/reactpy-django/develop/learn/your-first-component/ - 2023-09-16 + 2023-09-21 daily https://reactive-python.github.io/reactpy-django/develop/reference/components/ - 2023-09-16 + 2023-09-21 daily https://reactive-python.github.io/reactpy-django/develop/reference/decorators/ - 2023-09-16 + 2023-09-21 daily https://reactive-python.github.io/reactpy-django/develop/reference/hooks/ - 2023-09-16 + 2023-09-21 daily https://reactive-python.github.io/reactpy-django/develop/reference/settings/ - 2023-09-16 + 2023-09-21 daily https://reactive-python.github.io/reactpy-django/develop/reference/template-tag/ - 2023-09-16 + 2023-09-21 daily https://reactive-python.github.io/reactpy-django/develop/reference/utils/ - 2023-09-16 + 2023-09-21 daily \ No newline at end of file diff --git a/develop/sitemap.xml.gz b/develop/sitemap.xml.gz index 034429c1..5c0e4cbe 100644 Binary files a/develop/sitemap.xml.gz and b/develop/sitemap.xml.gz differ